Skip to content

Commit b156fbe

Browse files
authored
Merge pull request #12305 from graydon/clang-importees-have-no-associated-type-members
[AST] Avoid getMembers() calls in contexts that only need associated types.
2 parents dc273f7 + 51d759e commit b156fbe

File tree

5 files changed

+65
-78
lines changed

5 files changed

+65
-78
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3552,6 +3552,11 @@ class ProtocolDecl final : public NominalTypeDecl {
35523552
/// Retrieve the set of protocols inherited from this protocol.
35533553
llvm::TinyPtrVector<ProtocolDecl *> getInheritedProtocols() const;
35543554

3555+
/// Retrieve the set of AssociatedTypeDecl members of this protocol; this
3556+
/// saves loading the set of members in cases where there's no possibility of
3557+
/// a protocol having nested types (ObjC protocols).
3558+
llvm::TinyPtrVector<AssociatedTypeDecl *> getAssociatedTypeMembers() const;
3559+
35553560
/// Walk all of the protocols inherited by this protocol, transitively,
35563561
/// invoking the callback function for each protocol.
35573562
///

lib/AST/Decl.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3018,6 +3018,19 @@ ProtocolDecl::getInheritedProtocols() const {
30183018
return result;
30193019
}
30203020

3021+
llvm::TinyPtrVector<AssociatedTypeDecl *>
3022+
ProtocolDecl::getAssociatedTypeMembers() const {
3023+
llvm::TinyPtrVector<AssociatedTypeDecl *> result;
3024+
if (!isObjC()) {
3025+
for (auto member : getMembers()) {
3026+
if (auto ATD = dyn_cast<AssociatedTypeDecl>(member)) {
3027+
result.push_back(ATD);
3028+
}
3029+
}
3030+
}
3031+
return result;
3032+
}
3033+
30213034
bool ProtocolDecl::walkInheritedProtocols(
30223035
llvm::function_ref<TypeWalker::Action(ProtocolDecl *)> fn) const {
30233036
auto self = const_cast<ProtocolDecl *>(this);

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2196,19 +2196,6 @@ static void maybeAddSameTypeRequirementForNestedType(
21962196
GenericSignatureBuilder::UnresolvedHandlingKind::GenerateConstraints);
21972197
}
21982198

2199-
/// Walk the members of a protocol.
2200-
///
2201-
/// This is essentially just a call to \c proto->getMembers(), except that
2202-
/// for Objective-C-imported protocols we can simply return an empty declaration
2203-
/// range because the generic signature builder only cares about nested types (which
2204-
/// Objective-C protocols don't have).
2205-
static DeclRange getProtocolMembers(ProtocolDecl *proto) {
2206-
if (proto->hasClangNode())
2207-
return DeclRange(DeclIterator(), DeclIterator());
2208-
2209-
return proto->getMembers();
2210-
}
2211-
22122199
bool PotentialArchetype::addConformance(ProtocolDecl *proto,
22132200
const RequirementSource *source,
22142201
GenericSignatureBuilder &builder) {
@@ -3149,7 +3136,7 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
31493136
[&](ProtocolDecl *inheritedProto) -> TypeWalker::Action {
31503137
if (inheritedProto == proto) return TypeWalker::Action::Continue;
31513138

3152-
for (auto req : getProtocolMembers(inheritedProto)) {
3139+
for (auto req : inheritedProto->getMembers()) {
31533140
if (auto typeReq = dyn_cast<TypeDecl>(req))
31543141
inheritedTypeDecls[typeReq->getFullName()].push_back(typeReq);
31553142
}
@@ -3248,7 +3235,7 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
32483235
};
32493236

32503237
// Add requirements for each of the associated types.
3251-
for (auto Member : getProtocolMembers(proto)) {
3238+
for (auto Member : proto->getMembers()) {
32523239
if (auto assocTypeDecl = dyn_cast<AssociatedTypeDecl>(Member)) {
32533240
// Add requirements placed directly on this associated type.
32543241
Type assocType = DependentMemberType::get(concreteSelf, assocTypeDecl);
@@ -3477,9 +3464,7 @@ void GenericSignatureBuilder::updateSuperclass(
34773464
auto updateSuperclassConformances = [&] {
34783465
for (auto proto : T->getConformsTo()) {
34793466
if (auto superSource = resolveSuperConformance(T, proto)) {
3480-
for (auto req : getProtocolMembers(proto)) {
3481-
auto assocType = dyn_cast<AssociatedTypeDecl>(req);
3482-
if (!assocType) continue;
3467+
for (auto assocType : proto->getAssociatedTypeMembers()) {
34833468

34843469
const auto &nestedTypes = T->getNestedTypes();
34853470
auto nested = nestedTypes.find(assocType->getName());

lib/Sema/TypeCheckDecl.cpp

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,12 @@ void TypeChecker::validateWhereClauses(ProtocolDecl *protocol,
255255
options, resolver);
256256
}
257257

258-
for (auto member : protocol->getMembers()) {
259-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
260-
if (auto whereClause = assocType->getTrailingWhereClause()) {
261-
revertGenericRequirements(whereClause->getRequirements());
262-
validateRequirements(whereClause->getWhereLoc(),
263-
whereClause->getRequirements(),
264-
protocol, options, resolver);
265-
}
258+
for (auto assocType : protocol->getAssociatedTypeMembers()) {
259+
if (auto whereClause = assocType->getTrailingWhereClause()) {
260+
revertGenericRequirements(whereClause->getRequirements());
261+
validateRequirements(whereClause->getWhereLoc(),
262+
whereClause->getRequirements(),
263+
protocol, options, resolver);
266264
}
267265
}
268266
}
@@ -3251,10 +3249,7 @@ static void checkVarBehavior(VarDecl *decl, TypeChecker &TC) {
32513249
// First, satisfy any associated type requirements.
32523250
Substitution valueSub;
32533251
AssociatedTypeDecl *valueReqt = nullptr;
3254-
for (auto requirementDecl : behaviorProto->getMembers()) {
3255-
auto assocTy = dyn_cast<AssociatedTypeDecl>(requirementDecl);
3256-
if (!assocTy)
3257-
continue;
3252+
for (auto assocTy : behaviorProto->getAssociatedTypeMembers()) {
32583253

32593254
// Match a Value associated type requirement to the property type.
32603255
if (assocTy->getName() != TC.Context.Id_Value) {
@@ -7711,10 +7706,8 @@ void TypeChecker::validateDeclForNameLookup(ValueDecl *D) {
77117706
// Record inherited protocols.
77127707
resolveInheritedProtocols(proto);
77137708

7714-
for (auto member : proto->getMembers()) {
7715-
if (auto ATD = dyn_cast<AssociatedTypeDecl>(member)) {
7716-
validateDeclForNameLookup(ATD);
7717-
}
7709+
for (auto ATD : proto->getAssociatedTypeMembers()) {
7710+
validateDeclForNameLookup(ATD);
77187711
}
77197712

77207713
// Make sure the protocol is fully validated by the end of Sema.

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 35 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,12 +2371,10 @@ diagnoseMatch(ModuleDecl *module, NormalProtocolConformance *conformance,
23712371
// Form a string describing the associated type deductions.
23722372
// FIXME: Determine which associated types matter, and only print those.
23732373
llvm::SmallString<128> withAssocTypes;
2374-
for (auto member : conformance->getProtocol()->getMembers()) {
2375-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
2376-
if (conformance->usesDefaultDefinition(assocType)) {
2377-
Type witness = conformance->getTypeWitness(assocType, nullptr);
2378-
addAssocTypeDeductionString(withAssocTypes, assocType, witness);
2379-
}
2374+
for (auto assocType : conformance->getProtocol()->getAssociatedTypeMembers()) {
2375+
if (conformance->usesDefaultDefinition(assocType)) {
2376+
Type witness = conformance->getTypeWitness(assocType, nullptr);
2377+
addAssocTypeDeductionString(withAssocTypes, assocType, witness);
23802378
}
23812379
}
23822380
if (!withAssocTypes.empty())
@@ -4277,10 +4275,7 @@ void ConformanceChecker::resolveTypeWitnesses() {
42774275
Conformance->setState(ProtocolConformanceState::CheckingTypeWitnesses);
42784276
SWIFT_DEFER { Conformance->setState(initialState); };
42794277

4280-
for (auto member : Proto->getMembers()) {
4281-
auto assocType = dyn_cast<AssociatedTypeDecl>(member);
4282-
if (!assocType)
4283-
continue;
4278+
for (auto assocType : Proto->getAssociatedTypeMembers()) {
42844279

42854280
// If we already have a type witness, do nothing.
42864281
if (Conformance->hasTypeWitness(assocType))
@@ -4350,23 +4345,21 @@ void ConformanceChecker::resolveTypeWitnesses() {
43504345
TypeSubstitutionMap substitutions;
43514346
substitutions[Proto->mapTypeIntoContext(selfType)
43524347
->castTo<ArchetypeType>()] = Adoptee;
4353-
for (auto member : Proto->getMembers()) {
4354-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
4355-
auto archetype = Proto->mapTypeIntoContext(
4356-
assocType->getDeclaredInterfaceType())
4357-
->getAs<ArchetypeType>();
4358-
if (!archetype)
4359-
continue;
4360-
if (Conformance->hasTypeWitness(assocType)) {
4361-
substitutions[archetype] =
4362-
Conformance->getTypeWitness(assocType, nullptr);
4363-
} else {
4364-
auto known = typeWitnesses.begin(assocType);
4365-
if (known != typeWitnesses.end())
4366-
substitutions[archetype] = known->first;
4367-
else
4368-
substitutions[archetype] = ErrorType::get(archetype);
4369-
}
4348+
for (auto assocType : Proto->getAssociatedTypeMembers()) {
4349+
auto archetype = Proto->mapTypeIntoContext(
4350+
assocType->getDeclaredInterfaceType())
4351+
->getAs<ArchetypeType>();
4352+
if (!archetype)
4353+
continue;
4354+
if (Conformance->hasTypeWitness(assocType)) {
4355+
substitutions[archetype] =
4356+
Conformance->getTypeWitness(assocType, nullptr);
4357+
} else {
4358+
auto known = typeWitnesses.begin(assocType);
4359+
if (known != typeWitnesses.end())
4360+
substitutions[archetype] = known->first;
4361+
else
4362+
substitutions[archetype] = ErrorType::get(archetype);
43704363
}
43714364
}
43724365

@@ -4493,25 +4486,23 @@ void ConformanceChecker::resolveTypeWitnesses() {
44934486
// substitution of type witness bindings into other type witness bindings.
44944487
auto checkCurrentTypeWitnesses = [&]() -> bool {
44954488
// Fold the dependent member types within this type.
4496-
for (auto member : Proto->getMembers()) {
4497-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
4498-
if (Conformance->hasTypeWitness(assocType))
4499-
continue;
4489+
for (auto assocType : Proto->getAssociatedTypeMembers()) {
4490+
if (Conformance->hasTypeWitness(assocType))
4491+
continue;
45004492

4501-
// If the type binding does not have a type parameter, there's nothing
4502-
// to do.
4503-
auto known = typeWitnesses.begin(assocType);
4504-
assert(known != typeWitnesses.end());
4505-
if (!known->first->hasTypeParameter() &&
4506-
!known->first->hasDependentMember())
4507-
continue;
4493+
// If the type binding does not have a type parameter, there's nothing
4494+
// to do.
4495+
auto known = typeWitnesses.begin(assocType);
4496+
assert(known != typeWitnesses.end());
4497+
if (!known->first->hasTypeParameter() &&
4498+
!known->first->hasDependentMember())
4499+
continue;
45084500

4509-
Type replaced = known->first.transform(foldDependentMemberTypes);
4510-
if (replaced.isNull())
4511-
return true;
4512-
4513-
known->first = replaced;
4514-
}
4501+
Type replaced = known->first.transform(foldDependentMemberTypes);
4502+
if (replaced.isNull())
4503+
return true;
4504+
4505+
known->first = replaced;
45154506
}
45164507

45174508
// Check any same-type requirements in the protocol's requirement signature.

0 commit comments

Comments
 (0)