Skip to content

Commit

Permalink
Sema: Teach getReferencedAssociatedTypes() to look through typealiases
Browse files Browse the repository at this point in the history
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 <https://bugs.swift.org/browse/SR-3641>.
  • Loading branch information
slavapestov committed Jan 19, 2017
1 parent b861853 commit 0926773
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 8 deletions.
13 changes: 5 additions & 8 deletions lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -506,13 +506,10 @@ static SmallVector<TupleTypeElt, 4> decomposeIntoTupleElements(Type type) {
static AssociatedTypeDecl *
getReferencedAssocTypeOfProtocol(Type type, ProtocolDecl *proto) {
if (auto dependentMember = type->getAs<DependentMemberType>()) {
if (auto genericParam
= dependentMember->getBase()->getAs<GenericTypeParamType>()) {
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;
}
}
}
Expand Down Expand Up @@ -2158,7 +2155,7 @@ ConformanceChecker::getReferencedAssociatedTypes(ValueDecl *req) {
// signature.
auto &assocTypes = ReferencedAssociatedTypes[req];
llvm::SmallPtrSet<AssociatedTypeDecl *, 4> 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);
Expand Down
12 changes: 12 additions & 0 deletions test/decl/protocol/req/associated_type_inference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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]) { }
}

0 comments on commit 0926773

Please sign in to comment.