Skip to content

Commit 8acd573

Browse files
committed
Sema: Fix two problems in the solver's witness type matching logic
If we have an inner generic parameter of the requirement on the LHS, it can't match anything other than an inner generic parameter on the RHS. If we have the protocol Self type on the LHS, it can only match something with the same nominal on the RHS. This should be an exact match but ideally we would also recursively solve dependnet member types, etc. Skip this all for now.
1 parent bfdafe6 commit 8acd573

File tree

4 files changed

+75
-1
lines changed

4 files changed

+75
-1
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2035,9 +2035,26 @@ AssociatedTypeInference::getPotentialTypeWitnessesByMatchingTypes(ValueDecl *req
20352035
return true;
20362036
}
20372037

2038-
/// FIXME: Recheck the type of Self against the second type?
20392038
bool mismatch(GenericTypeParamType *selfParamType,
20402039
TypeBase *secondType, Type sugaredFirstType) {
2040+
if (selfParamType->isEqual(Conformance->getProtocol()->getSelfInterfaceType())) {
2041+
// A DynamicSelfType always matches the Self parameter.
2042+
if (secondType->is<DynamicSelfType>())
2043+
return true;
2044+
2045+
// Otherwise, 'Self' should at least have a matching nominal type.
2046+
if (secondType->getAnyNominal() == Conformance->getType()->getAnyNominal())
2047+
return true;
2048+
2049+
return false;
2050+
}
2051+
2052+
// Any other generic parameter type is an inner generic parameter type
2053+
// of the requirement. If we're matching it with something that is not a
2054+
// generic parameter type, we cannot hope to succeed.
2055+
if (!secondType->is<GenericTypeParamType>())
2056+
return false;
2057+
20412058
return true;
20422059
}
20432060
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol P {
4+
associatedtype A
5+
6+
func f(_: A) -> Self
7+
}
8+
9+
class C1: P {
10+
func f(_: Int) -> Self {}
11+
}
12+
13+
class Base {
14+
func f(_: String) -> Self {}
15+
}
16+
17+
class Derived: Base, P {}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-typecheck-verify-swift -disable-experimental-associated-type-inference
2+
// RUN: %target-typecheck-verify-swift -enable-experimental-associated-type-inference
3+
4+
// We can't infer anything from 'Self', but we must still validate the
5+
// binding.
6+
7+
protocol P1 {
8+
associatedtype A
9+
10+
func f(_: Self, _: A)
11+
}
12+
13+
struct S1: P1 {
14+
// Don't consider this f(); A := Float is not a candidate type witness.
15+
func f(_: Int, _: Float) {}
16+
17+
func f(_: S1, _: String) {}
18+
}
19+
20+
let x: String.Type = S1.A.self
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-typecheck-verify-swift -disable-experimental-associated-type-inference
2+
// RUN: %target-typecheck-verify-swift -enable-experimental-associated-type-inference
3+
4+
// An inner generic parameter of the protocol requirement should not
5+
// match against a concrete type in the witness.
6+
7+
protocol P2 {
8+
associatedtype A
9+
func f<T>(_: T, _: A)
10+
}
11+
12+
struct S2<A>: P2 {
13+
// These are not candiate witnesses for the requirement.
14+
func f(_: Float, _: Array<A>) {}
15+
func f(_: String, _: Array<A>) {}
16+
17+
func f<T>(_: T, _: A) {}
18+
}
19+
20+
let x: Int.Type = S2<Int>.A.self

0 commit comments

Comments
 (0)