From 0926773c698d7d78f33f3d9cc5e86c528e5c1e7b Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 18 Jan 2017 21:40:24 -0800 Subject: [PATCH] Sema: Teach getReferencedAssociatedTypes() to look through typealiases Now that NameAliasTypes desugar to interface types, it is possible to have a protocol requirement type contain a NameAliasType which contains an associated type: protocol P { associatedtype Element typealias Elements = [Element] func process(elements: Elements) } In Swift 3, the typealias would be desugared at name lookup time in this case, but this is no longer the case, as a result associated type inference stopped working in this example. Fixes . --- lib/Sema/TypeCheckProtocol.cpp | 13 +++++-------- .../protocol/req/associated_type_inference.swift | 12 ++++++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index af8dd68dbe7b4..168c105c89a20 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -506,13 +506,10 @@ static SmallVector decomposeIntoTupleElements(Type type) { static AssociatedTypeDecl * getReferencedAssocTypeOfProtocol(Type type, ProtocolDecl *proto) { if (auto dependentMember = type->getAs()) { - if (auto genericParam - = dependentMember->getBase()->getAs()) { - if (genericParam->getDepth() == 0 && genericParam->getIndex() == 0) { - if (auto assocType = dependentMember->getAssocType()) { - if (assocType->getDeclContext() == proto) - return assocType; - } + if (auto assocType = dependentMember->getAssocType()) { + if (dependentMember->getBase()->isEqual(proto->getSelfInterfaceType()) && + assocType->getProtocol() == proto) { + return assocType; } } } @@ -2158,7 +2155,7 @@ ConformanceChecker::getReferencedAssociatedTypes(ValueDecl *req) { // signature. auto &assocTypes = ReferencedAssociatedTypes[req]; llvm::SmallPtrSet knownAssocTypes; - req->getInterfaceType().visit([&](Type type) { + req->getInterfaceType()->getCanonicalType().visit([&](Type type) { if (auto assocType = getReferencedAssocTypeOfProtocol(type, Proto)) { if (knownAssocTypes.insert(assocType).second) { assocTypes.push_back(assocType); diff --git a/test/decl/protocol/req/associated_type_inference.swift b/test/decl/protocol/req/associated_type_inference.swift index ceb1eea132cf2..16f7323a7cb6a 100644 --- a/test/decl/protocol/req/associated_type_inference.swift +++ b/test/decl/protocol/req/associated_type_inference.swift @@ -343,3 +343,15 @@ extension Cookie { struct Thumbprint : Cookie {} // expected-error@-1 {{type 'Thumbprint' does not conform to protocol 'Cookie'}} + +// Looking through typealiases +protocol Vector { + associatedtype Element + typealias Elements = [Element] + + func process(elements: Elements) +} + +struct Int8Vector : Vector { + func process(elements: [Int8]) { } +}