Skip to content

Commit fce8738

Browse files
committed
[ConstraintSystem] Replace dependent member types with holes when the base type
doesn't conform to the associatedtype's protocol (only in diagnostic mode). This allows the solver to find solutions for more cases involving requirement failures for dependent member types without special cases across the solver that check for dependent member types with no type variables.
1 parent b58ea4b commit fce8738

File tree

5 files changed

+43
-25
lines changed

5 files changed

+43
-25
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3560,14 +3560,6 @@ bool ConstraintSystem::repairFailures(
35603560
if (lhs->hasHole() || rhs->hasHole())
35613561
return true;
35623562

3563-
// If dependent members are present here it's because the base doesn't
3564-
// conform to the associated type's protocol. We can only get here if we
3565-
// already applied a fix for the conformance failure.
3566-
if (lhs->hasDependentMember() || rhs->hasDependentMember()) {
3567-
increaseScore(SK_Fix);
3568-
return true;
3569-
}
3570-
35713563
// If requirement is something like `T == [Int]` let's let
35723564
// type matcher a chance to match generic parameters before
35733565
// recording a fix, because then we'll know exactly how many
@@ -4202,15 +4194,6 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
42024194
llvm_unreachable("type variables should have already been handled by now");
42034195

42044196
case TypeKind::DependentMember: {
4205-
// If one of the dependent member types has no type variables, the
4206-
// dependent member can't be simplified because the base doesn't conform
4207-
// to the associated type's protocol. We can only get here if we already
4208-
// applied a fix for the conformance failure.
4209-
if (!desugar1->hasTypeVariable() || !desugar2->hasTypeVariable()) {
4210-
increaseScore(SK_Fix);
4211-
return getTypeMatchSuccess();
4212-
}
4213-
42144197
// Nothing we can solve yet, since we need to wait until
42154198
// type variables will get resolved.
42164199
return formUnsolvedResult();

lib/Sema/ConstraintSystem.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2454,8 +2454,17 @@ Type ConstraintSystem::simplifyTypeImpl(Type type,
24542454
auto *proto = assocType->getProtocol();
24552455
auto conformance = DC->getParentModule()->lookupConformance(
24562456
lookupBaseType, proto);
2457-
if (!conformance)
2457+
if (!conformance) {
2458+
// If the base type doesn't conform to the associatedtype's protocol,
2459+
// there will be a missing conformance fix applied in diagnostic mode,
2460+
// so the concrete dependent member type is considered a "hole" in
2461+
// order to continue solving.
2462+
if (shouldAttemptFixes() &&
2463+
getPhase() == ConstraintSystemPhase::Solving)
2464+
return getASTContext().TheUnresolvedType;
2465+
24582466
return DependentMemberType::get(lookupBaseType, assocType);
2467+
}
24592468

24602469
auto subs = SubstitutionMap::getProtocolSubstitutions(
24612470
proto, lookupBaseType, conformance);
@@ -2895,22 +2904,24 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
28952904
static bool
28962905
diagnoseAmbiguityWithEphemeralPointers(ConstraintSystem &cs,
28972906
ArrayRef<Solution> solutions) {
2898-
bool allSolutionsHaveFixes = true;
2907+
unsigned numSolutionsWithFixes = 0;
28992908
for (const auto &solution : solutions) {
29002909
if (solution.Fixes.empty()) {
2901-
allSolutionsHaveFixes = false;
29022910
continue;
29032911
}
29042912

29052913
if (!llvm::all_of(solution.Fixes, [](const ConstraintFix *fix) {
29062914
return fix->getKind() == FixKind::TreatEphemeralAsNonEphemeral;
29072915
}))
29082916
return false;
2917+
2918+
numSolutionsWithFixes += 1;
29092919
}
29102920

2911-
// If all solutions have fixes for ephemeral pointers, let's
2921+
// If all or no solutions have fixes for ephemeral pointers, let's
29122922
// let `diagnoseAmbiguityWithFixes` diagnose the problem.
2913-
if (allSolutionsHaveFixes)
2923+
if (numSolutionsWithFixes == 0 ||
2924+
numSolutionsWithFixes == solutions.size())
29142925
return false;
29152926

29162927
// If only some of the solutions have ephemeral pointer fixes
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol P {
4+
associatedtype V
5+
}
6+
7+
struct Person {
8+
var name: String = ""
9+
}
10+
11+
struct Row : P {
12+
typealias V = String
13+
init(_: V) {}
14+
}
15+
16+
func foo<C: Collection, R: P>(_ collection: C, _: (C.Element.V) -> R) where C.Element: P { }
17+
// expected-note@-1 {{where 'C.Element' = 'Person'}}
18+
19+
func bar(_ arr: [Person]) {
20+
foo(arr) { person in // expected-error {{global function 'foo' requires that 'Person' conform to 'P'}}
21+
Row(person.name)
22+
}
23+
}
24+

test/Generics/deduction.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,12 @@ genericInheritsA(C_GI())
243243
//===----------------------------------------------------------------------===//
244244
// Deduction for member operators
245245
//===----------------------------------------------------------------------===//
246-
protocol Addable { // expected-note {{where 'Self' = 'U'}}
246+
protocol Addable {
247247
static func +(x: Self, y: Self) -> Self
248248
}
249249
func addAddables<T : Addable, U>(_ x: T, y: T, u: U) -> T {
250-
u + u // expected-error{{referencing operator function '+' on 'Addable' requires that 'U' conform to 'Addable'}}
250+
// FIXME(diagnostics): This should report the "no exact matches" diagnostic.
251+
u + u // expected-error{{referencing operator function '+' on 'RangeReplaceableCollection' requires that 'U' conform to 'RangeReplaceableCollection'}}
251252
return x+y
252253
}
253254

validation-test/compiler_crashers_2_fixed/0119-rdar33613329.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,3 @@ var x = X()
4444
x ~> \X.y ≈> { a in a += 1; return 3 }
4545
// expected-error@-1 {{referencing operator function '~>' on 'P' requires that 'M<WritableKeyPath<X, Int>, R>' conform to 'P'}}
4646
// expected-error@-2 {{unable to infer complex closure return type; add explicit type to disambiguate}}
47-
// expected-error@-3 {{cannot convert value of type 'X' to expected argument type 'M<WritableKeyPath<X, Int>, R>.A'}}

0 commit comments

Comments
 (0)