Skip to content

Commit f51d5b6

Browse files
committed
[Conformance checking] Allow generic parameter when inferring type witnesses.
As part of type witness inference, allow us to infer a generic parameter as the type witness for an associated type, when the associated type has the same name as the generic parameter. We likely want the more-general rule that generic parameters are always visible as members of their enclosing type, but I'll tackle that separately. This works around an order dependency that affected the source compatibility suite.
1 parent 1763a2c commit f51d5b6

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,8 +1022,6 @@ matchWitness(TypeChecker &tc,
10221022
std::get<1>(types))) {
10231023
return *result;
10241024
}
1025-
1026-
// FIXME: Consider default arguments here?
10271025
}
10281026

10291027
// If the witness is 'throws', the requirement must be.
@@ -4276,7 +4274,6 @@ void ConformanceChecker::resolveTypeWitnesses() {
42764274
SWIFT_DEFER { Conformance->setState(initialState); };
42774275

42784276
for (auto assocType : Proto->getAssociatedTypeMembers()) {
4279-
42804277
// If we already have a type witness, do nothing.
42814278
if (Conformance->hasTypeWitness(assocType))
42824279
continue;
@@ -4599,6 +4596,24 @@ void ConformanceChecker::resolveTypeWitnesses() {
45994596
continue;
46004597
}
46014598

4599+
// If there is a generic parameter of the named type, use that.
4600+
if (auto gpList = DC->getGenericParamsOfContext()) {
4601+
GenericTypeParamDecl *foundGP = nullptr;
4602+
for (auto gp : *gpList) {
4603+
if (gp->getName() == assocType->getName()) {
4604+
foundGP = gp;
4605+
break;
4606+
}
4607+
}
4608+
4609+
if (foundGP) {
4610+
auto gpType = DC->mapTypeIntoContext(
4611+
foundGP->getDeclaredInterfaceType());
4612+
typeWitnesses.insert(assocType, {gpType, reqDepth});
4613+
continue;
4614+
}
4615+
}
4616+
46024617
// The solution is incomplete.
46034618
recordMissing();
46044619
return;

test/decl/protocol/req/associated_type_inference.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,9 @@ public protocol Thenable {
195195
func then(_ success: (_: T) -> T) -> Self
196196
}
197197

198-
public class CorePromise<T> : Thenable { // expected-error{{type 'CorePromise<T>' does not conform to protocol 'Thenable'}}
199-
public func then(_ success: @escaping (_ t: T, _: CorePromise<T>) -> T) -> Self {
200-
return self.then() { (t: T) -> T in
198+
public class CorePromise<U> : Thenable { // expected-error{{type 'CorePromise<U>' does not conform to protocol 'Thenable'}}
199+
public func then(_ success: @escaping (_ t: U, _: CorePromise<U>) -> U) -> Self {
200+
return self.then() { (t: U) -> U in // expected-error{{contextual closure type '(U, CorePromise<U>) -> U' expects 2 arguments, but 1 was used in closure body}}
201201
return success(t: t, self)
202202
}
203203
}
@@ -390,3 +390,13 @@ protocol P13 {
390390
struct S13 : P13 { // expected-error{{type 'S13' does not conform to protocol 'P13'}}
391391
func foo(arg: inout Int) {}
392392
}
393+
394+
// "Infer" associated type from generic parameter.
395+
protocol P14 {
396+
associatedtype Value
397+
}
398+
399+
struct P14a<Value>: P14 { }
400+
401+
struct P14b<Value> { }
402+
extension P14b: P14 { }

0 commit comments

Comments
 (0)