Skip to content

Commit

Permalink
Collect inherited associated type conformances.
Browse files Browse the repository at this point in the history
When we're determining which protocols an associated type conforms to,
look for same-named associated types in inherited protocols and add
their conformances to the set of protocols to which this associated
type conforms. Coupled with an embarrassing fix to the
protocol-minimization code, this should eliminate the dreaded SILGen
assertion about the number of conformances not matching the number of
protocols when generating witness table entries for associated type
witnesses. Fixes rdar://problem/21599502.

Swift SVN r29976
  • Loading branch information
DougGregor committed Jul 8, 2015
1 parent facf122 commit cef669a
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
4 changes: 3 additions & 1 deletion lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -879,8 +879,10 @@ static void addMinimumProtocols(Type T,
}

if (Visited.insert(Proto->getDecl()).second) {
Stack.push_back(Proto->getDecl());
for (auto Inherited : Proto->getDecl()->getInheritedProtocols(nullptr))
addProtocols(Inherited->getDeclaredType(), Stack);
addMinimumProtocols(Inherited->getDeclaredType(), Protocols, Known,
Visited, Stack, ZappedAny);
}
return;
}
Expand Down
30 changes: 30 additions & 0 deletions lib/Sema/TypeCheckDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,28 @@ void TypeChecker::checkInheritanceClause(Decl *decl,
inherited.setInvalidType(Context);
}

// For an associated type, find associated types with the same name
// in inherited protocols and add their conformances.
if (auto assocType = dyn_cast<AssociatedTypeDecl>(decl)) {
auto proto = cast<ProtocolDecl>(assocType->getDeclContext());
for (auto inheritedProto : proto->getInheritedProtocols(this)) {
SmallVector<ValueDecl *, 4> lookupResults;
unsigned subOptions
= NL_QualifiedDefault & ~(NL_RemoveNonVisible | NL_RemoveOverridden);
inheritedProto->lookupQualified(inheritedProto->getDeclaredType(),
assocType->getName(), subOptions, this,
lookupResults);

for (auto member : lookupResults) {
if (auto inheritedAssoc = dyn_cast<AssociatedTypeDecl>(member)) {
validateDecl(inheritedAssoc);
auto conforming = inheritedAssoc->getConformingProtocols(this);
allProtocols.insert(conforming.begin(), conforming.end());
}
}
}
}

// Record the protocols to which this declaration conforms along with the
// superclass.
auto allProtocolsCopy = Context.AllocateCopy(allProtocols);
Expand Down Expand Up @@ -5912,6 +5934,14 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) {
.getAsArchetype();
if (!archetype)
return;

#ifndef NDEBUG
auto conformingProtocols = assocType->getConformingProtocols(this);
SmallVector<ProtocolDecl *, 4> protocols(conformingProtocols.begin(),
conformingProtocols.end());
ProtocolType::canonicalizeProtocols(protocols);
assert(llvm::makeArrayRef(protocols) == archetype->getConformsTo());
#endif
assocType->setArchetype(archetype);
}
}
Expand Down
29 changes: 29 additions & 0 deletions test/SILGen/witnesses_canonical.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,32 @@ public protocol CT : ST, _CDT {

// CHECK: sil_witness_table <T where T : _CDT> _S<T>: CT module witnesses_canonical {
// associated_type_protocol (_SS: _CDT): _S<_S<T>>: specialize <T = _S<T>> (<T where T : _CDT> _S<T>: _CDT module witnesses_canonical)

// rdar://problem/21599502 -- make sure we get requirements on
// associated types from protocols we inherit.
public protocol P1 { }
public protocol P2 { }

public protocol Q1 {
typealias Assoc : P1
}

public protocol Q2 {
typealias Assoc : P2
}

public protocol Q3 : Q1, Q2 {
typealias Assoc
}

struct XP : P1, P2 { }

struct XQ3 : Q3 {
typealias Assoc = XP
}

// CHECK: sil_witness_table XQ3: Q3 module witnesses_canonical {
// CHECK: associated_type Assoc: XP
// CHECK: associated_type_protocol (Assoc: P1): XP: P1 module witnesses_canonical
// CHECK: associated_type_protocol (Assoc: P2): XP: P2 module witnesses_canonical
// CHECK: }

0 comments on commit cef669a

Please sign in to comment.