Skip to content

Commit 4bef7bf

Browse files
Merge pull request #41506 from LucianoPAlmeida/SR-15843-generic-ambiguity
[Sema] Attempt diagnose generic arg ambiguity if all solutions produce generic arg mismatch
2 parents ddc2065 + 034c4bd commit 4bef7bf

File tree

2 files changed

+35
-24
lines changed

2 files changed

+35
-24
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3697,7 +3697,8 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
36973697
solution.Fixes, [](const ConstraintFix *fix) -> bool {
36983698
return fix->getKind() == FixKind::AllowArgumentTypeMismatch ||
36993699
fix->getKind() == FixKind::AllowFunctionTypeMismatch ||
3700-
fix->getKind() == FixKind::AllowTupleTypeMismatch;
3700+
fix->getKind() == FixKind::AllowTupleTypeMismatch ||
3701+
fix->getKind() == FixKind::GenericArgumentsMismatch;
37013702
});
37023703
});
37033704

@@ -3711,24 +3712,27 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
37113712
genericParams;
37123713
// Consider only representative type variables shared across
37133714
// all of the solutions.
3714-
for (auto *typeVar : cs.getTypeVariables()) {
3715-
if (auto *GP = typeVar->getImpl().getGenericParameter()) {
3716-
auto *locator = typeVar->getImpl().getLocator();
3717-
auto *repr = cs.getRepresentative(typeVar);
3718-
// If representative is another generic parameter let's
3719-
// use its generic parameter type instead of originator's,
3720-
// but it's possible that generic parameter is equated to
3721-
// some other type e.g.
3722-
//
3723-
// func foo<T>(_: T) -> T {}
3724-
//
3725-
// In this case when reference to function `foo` is "opened"
3726-
// type variable representing `T` would be equated to
3727-
// type variable representing a result type of the reference.
3728-
if (auto *reprGP = repr->getImpl().getGenericParameter())
3729-
GP = reprGP;
3715+
for (auto &solution : solutions) {
3716+
for (auto &typeBinding : solution.typeBindings) {
3717+
auto *typeVar = typeBinding.first;
3718+
if (auto *GP = typeVar->getImpl().getGenericParameter()) {
3719+
auto *locator = typeVar->getImpl().getLocator();
3720+
auto *repr = cs.getRepresentative(typeVar);
3721+
// If representative is another generic parameter let's
3722+
// use its generic parameter type instead of originator's,
3723+
// but it's possible that generic parameter is equated to
3724+
// some other type e.g.
3725+
//
3726+
// func foo<T>(_: T) -> T {}
3727+
//
3728+
// In this case when reference to function `foo` is "opened"
3729+
// type variable representing `T` would be equated to
3730+
// type variable representing a result type of the reference.
3731+
if (auto *reprGP = repr->getImpl().getGenericParameter())
3732+
GP = reprGP;
37303733

3731-
genericParams[repr] = {GP, getLoc(locator->getAnchor())};
3734+
genericParams[repr] = {GP, getLoc(locator->getAnchor())};
3735+
}
37323736
}
37333737
}
37343738

@@ -3743,6 +3747,14 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
37433747
llvm::SmallSetVector<Type, 4> arguments;
37443748
for (const auto &solution : solutions) {
37453749
auto type = solution.typeBindings.lookup(typeVar);
3750+
// Type variables gathered from a solution's type binding context may not
3751+
// exist in another given solution because each solution could have a
3752+
// different set of overload choices picked, which implies that some of
3753+
// the generic parameters, and type variables that represent them, would
3754+
// be unique to that solution.
3755+
if (!type)
3756+
continue;
3757+
37463758
// Contextual opaque result type is uniquely identified by
37473759
// declaration it's associated with, so we have to compare
37483760
// declarations instead of using pointer equality on such types.

test/Constraints/casts_swift6.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,11 @@ func test_compatibility_coercions(_ arr: [Int], _ optArr: [Int]?, _ dict: [Strin
2727
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
2828

2929
// Make sure we error on the following in Swift 6 mode.
30-
31-
// FIXME: Bad diagnostics (SR-15843)
32-
_ = id(arr) as [String] // expected-error {{type of expression is ambiguous without more context}}
33-
_ = (arr ?? []) as [String] // expected-error {{type of expression is ambiguous without more context}}
34-
_ = (arr ?? [] ?? []) as [String] // expected-error {{type of expression is ambiguous without more context}}
35-
_ = (optArr ?? []) as [String] // expected-error {{type of expression is ambiguous without more context}}
30+
_ = id(arr) as [String] // expected-error {{conflicting arguments to generic parameter 'T' ('[Int]' vs. '[String]')}}
31+
_ = (arr ?? []) as [String] // expected-error {{conflicting arguments to generic parameter 'T' ('[String]' vs. '[Int]')}}
32+
_ = (arr ?? [] ?? []) as [String] // expected-error {{conflicting arguments to generic parameter 'T' ('[String]' vs. '[Int]')}}
33+
// expected-error@-1{{conflicting arguments to generic parameter 'T' ('[String]' vs. '[Int]')}}
34+
_ = (optArr ?? []) as [String] // expected-error {{conflicting arguments to generic parameter 'T' ('[Int]' vs. '[String]'}}
3635

3736
_ = (arr ?? []) as [String]? // expected-error {{'[Int]' is not convertible to '[String]?'}}
3837
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}}

0 commit comments

Comments
 (0)