Skip to content

Commit 77f53a5

Browse files
authored
Merge pull request #72713 from karwa/nested-circles
Fix name lookup in nested protocol inheritance clauses
2 parents 2507583 + 6164ee5 commit 77f53a5

File tree

2 files changed

+95
-28
lines changed

2 files changed

+95
-28
lines changed

lib/AST/NameLookup.cpp

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,8 @@ static DirectlyReferencedTypeDecls
10871087
directReferencesForTypeRepr(Evaluator &evaluator, ASTContext &ctx,
10881088
TypeRepr *typeRepr, DeclContext *dc,
10891089
bool allowUsableFromInline,
1090-
bool rhsOfSelfRequirement);
1090+
bool rhsOfSelfRequirement,
1091+
bool allowProtocolMembers);
10911092

10921093
/// Retrieve the set of type declarations that are directly referenced from
10931094
/// the given type.
@@ -1148,7 +1149,8 @@ SelfBounds SelfBoundsFromWhereClauseRequest::evaluate(
11481149
rhsDecls = directReferencesForTypeRepr(evaluator, ctx, typeRepr,
11491150
const_cast<DeclContext *>(dc),
11501151
/*allowUsableFromInline=*/false,
1151-
/*rhsOfSelfRequirement=*/true);
1152+
/*rhsOfSelfRequirement=*/true,
1153+
/*allowProtocolMembers=*/true);
11521154
}
11531155

11541156
SmallVector<ModuleDecl *, 2> modulesFound;
@@ -1212,7 +1214,8 @@ TypeDeclsFromWhereClauseRequest::evaluate(Evaluator &evaluator,
12121214
auto resolve = [&](TypeRepr *typeRepr) {
12131215
auto decls = directReferencesForTypeRepr(evaluator, ctx, typeRepr, ext,
12141216
/*allowUsableFromInline=*/false,
1215-
/*rhsOfSelfRequirement=*/false);
1217+
/*rhsOfSelfRequirement=*/false,
1218+
/*allowProtocolMembers=*/true);
12161219
result.first.insert(result.first.end(),
12171220
decls.first.begin(),
12181221
decls.first.end());
@@ -2882,10 +2885,11 @@ directReferencesForUnqualifiedTypeLookup(DeclNameRef name,
28822885
SourceLoc loc, DeclContext *dc,
28832886
LookupOuterResults lookupOuter,
28842887
bool allowUsableFromInline,
2885-
bool rhsOfSelfRequirement) {
2886-
UnqualifiedLookupOptions options =
2887-
UnqualifiedLookupFlags::TypeLookup |
2888-
UnqualifiedLookupFlags::AllowProtocolMembers;
2888+
bool rhsOfSelfRequirement,
2889+
bool allowProtocolMembers) {
2890+
UnqualifiedLookupOptions options = UnqualifiedLookupFlags::TypeLookup;
2891+
if (allowProtocolMembers)
2892+
options |= UnqualifiedLookupFlags::AllowProtocolMembers;
28892893
if (lookupOuter == LookupOuterResults::Included)
28902894
options |= UnqualifiedLookupFlags::IncludeOuterResults;
28912895

@@ -2999,11 +3003,12 @@ static DirectlyReferencedTypeDecls
29993003
directReferencesForDeclRefTypeRepr(Evaluator &evaluator, ASTContext &ctx,
30003004
DeclRefTypeRepr *repr, DeclContext *dc,
30013005
bool allowUsableFromInline,
3002-
bool rhsOfSelfRequirement) {
3006+
bool rhsOfSelfRequirement,
3007+
bool allowProtocolMembers) {
30033008
if (auto *qualIdentTR = dyn_cast<QualifiedIdentTypeRepr>(repr)) {
30043009
auto result = directReferencesForTypeRepr(
30053010
evaluator, ctx, qualIdentTR->getBase(), dc,
3006-
allowUsableFromInline, rhsOfSelfRequirement);
3011+
allowUsableFromInline, rhsOfSelfRequirement, allowProtocolMembers);
30073012

30083013
// For a qualified identifier, perform qualified name lookup.
30093014
result.first = directReferencesForQualifiedTypeLookup(
@@ -3016,14 +3021,15 @@ directReferencesForDeclRefTypeRepr(Evaluator &evaluator, ASTContext &ctx,
30163021
// For an unqualified identifier, perform unqualified name lookup.
30173022
return directReferencesForUnqualifiedTypeLookup(
30183023
repr->getNameRef(), repr->getLoc(), dc, LookupOuterResults::Excluded,
3019-
allowUsableFromInline, rhsOfSelfRequirement);
3024+
allowUsableFromInline, rhsOfSelfRequirement, allowProtocolMembers);
30203025
}
30213026

30223027
static DirectlyReferencedTypeDecls
30233028
directReferencesForTypeRepr(Evaluator &evaluator,
30243029
ASTContext &ctx, TypeRepr *typeRepr,
30253030
DeclContext *dc, bool allowUsableFromInline,
3026-
bool rhsOfSelfRequirement) {
3031+
bool rhsOfSelfRequirement,
3032+
bool allowProtocolMembers) {
30273033
DirectlyReferencedTypeDecls result;
30283034

30293035
switch (typeRepr->getKind()) {
@@ -3036,7 +3042,8 @@ directReferencesForTypeRepr(Evaluator &evaluator,
30363042
return directReferencesForTypeRepr(evaluator, ctx,
30373043
attributed->getTypeRepr(), dc,
30383044
allowUsableFromInline,
3039-
rhsOfSelfRequirement);
3045+
rhsOfSelfRequirement,
3046+
allowProtocolMembers);
30403047
}
30413048

30423049
case TypeReprKind::Composition: {
@@ -3045,7 +3052,8 @@ directReferencesForTypeRepr(Evaluator &evaluator,
30453052
auto componentResult =
30463053
directReferencesForTypeRepr(evaluator, ctx, component, dc,
30473054
allowUsableFromInline,
3048-
rhsOfSelfRequirement);
3055+
rhsOfSelfRequirement,
3056+
allowProtocolMembers);
30493057
result.first.insert(result.first.end(),
30503058
componentResult.first.begin(),
30513059
componentResult.first.end());
@@ -3061,7 +3069,8 @@ directReferencesForTypeRepr(Evaluator &evaluator,
30613069
return directReferencesForDeclRefTypeRepr(evaluator, ctx,
30623070
cast<DeclRefTypeRepr>(typeRepr),
30633071
dc, allowUsableFromInline,
3064-
rhsOfSelfRequirement);
3072+
rhsOfSelfRequirement,
3073+
allowProtocolMembers);
30653074

30663075
case TypeReprKind::Dictionary:
30673076
result.first.push_back(ctx.getDictionaryDecl());
@@ -3073,7 +3082,8 @@ directReferencesForTypeRepr(Evaluator &evaluator,
30733082
result = directReferencesForTypeRepr(evaluator, ctx,
30743083
tupleRepr->getElementType(0), dc,
30753084
allowUsableFromInline,
3076-
rhsOfSelfRequirement);
3085+
rhsOfSelfRequirement,
3086+
allowProtocolMembers);
30773087
} else {
30783088
result.first.push_back(ctx.getBuiltinTupleDecl());
30793089
}
@@ -3085,23 +3095,26 @@ directReferencesForTypeRepr(Evaluator &evaluator,
30853095
return directReferencesForTypeRepr(evaluator, ctx,
30863096
packExpansionRepr->getElementType(), dc,
30873097
allowUsableFromInline,
3088-
rhsOfSelfRequirement);
3098+
rhsOfSelfRequirement,
3099+
allowProtocolMembers);
30893100
}
30903101

30913102
case TypeReprKind::PackExpansion: {
30923103
auto packExpansionRepr = cast<PackExpansionTypeRepr>(typeRepr);
30933104
return directReferencesForTypeRepr(evaluator, ctx,
30943105
packExpansionRepr->getPatternType(), dc,
30953106
allowUsableFromInline,
3096-
rhsOfSelfRequirement);
3107+
rhsOfSelfRequirement,
3108+
allowProtocolMembers);
30973109
}
30983110

30993111
case TypeReprKind::PackElement: {
31003112
auto packReferenceRepr = cast<PackElementTypeRepr>(typeRepr);
31013113
return directReferencesForTypeRepr(evaluator, ctx,
31023114
packReferenceRepr->getPackType(), dc,
31033115
allowUsableFromInline,
3104-
rhsOfSelfRequirement);
3116+
rhsOfSelfRequirement,
3117+
allowProtocolMembers);
31053118
}
31063119

31073120
case TypeReprKind::Inverse: {
@@ -3111,7 +3124,8 @@ directReferencesForTypeRepr(Evaluator &evaluator,
31113124
auto innerResult = directReferencesForTypeRepr(evaluator, ctx,
31123125
inverseRepr->getConstraint(), dc,
31133126
allowUsableFromInline,
3114-
rhsOfSelfRequirement);
3127+
rhsOfSelfRequirement,
3128+
allowProtocolMembers);
31153129
if (innerResult.first.size() == 1) {
31163130
if (auto *proto = dyn_cast<ProtocolDecl>(innerResult.first[0])) {
31173131
if (auto ip = proto->getInvertibleProtocolKind()) {
@@ -3221,10 +3235,16 @@ DirectlyReferencedTypeDecls InheritedDeclsReferencedRequest::evaluate(
32213235
else
32223236
dc = (DeclContext *)decl.get<const ExtensionDecl *>();
32233237

3238+
// If looking at a protocol's inheritance list,
3239+
// do not look at protocol members to avoid circularity.
3240+
// Protocols cannot inherit from any protocol members anyway.
3241+
bool allowProtocolMembers = (dc->getSelfProtocolDecl() == nullptr);
3242+
32243243
return directReferencesForTypeRepr(evaluator, dc->getASTContext(), typeRepr,
32253244
const_cast<DeclContext *>(dc),
32263245
/*allowUsableFromInline=*/false,
3227-
/*rhsOfSelfRequirement=*/false);
3246+
/*rhsOfSelfRequirement=*/false,
3247+
allowProtocolMembers);
32283248
}
32293249

32303250
// Fall back to semantic types.
@@ -3245,7 +3265,8 @@ DirectlyReferencedTypeDecls UnderlyingTypeDeclsReferencedRequest::evaluate(
32453265
return directReferencesForTypeRepr(evaluator, typealias->getASTContext(),
32463266
typeRepr, typealias,
32473267
/*allowUsableFromInline=*/false,
3248-
/*rhsOfSelfRequirement=*/false);
3268+
/*rhsOfSelfRequirement=*/false,
3269+
/*allowProtocolMembers=*/true);
32493270
}
32503271

32513272
// Fall back to semantic types.
@@ -3404,7 +3425,8 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator,
34043425
DirectlyReferencedTypeDecls referenced =
34053426
directReferencesForTypeRepr(evaluator, ctx, typeRepr, ext->getParent(),
34063427
ext->isInSpecializeExtensionContext(),
3407-
/*rhsOfSelfRequirement=*/false);
3428+
/*rhsOfSelfRequirement=*/false,
3429+
/*allowProtocolMembers=*/true);
34083430

34093431
// Resolve those type declarations to nominal type declarations.
34103432
SmallVector<ModuleDecl *, 2> modulesFound;
@@ -3454,7 +3476,8 @@ bool TypeRepr::isProtocolOrProtocolComposition(DeclContext *dc) {
34543476
auto &ctx = dc->getASTContext();
34553477
auto references = directReferencesForTypeRepr(ctx.evaluator, ctx, this, dc,
34563478
/*allowUsableFromInline=*/false,
3457-
/*rhsOfSelfRequirement=*/false);
3479+
/*rhsOfSelfRequirement=*/false,
3480+
/*allowProtocolMembers=*/true);
34583481
return declsAreProtocols(references.first);
34593482
}
34603483

@@ -3489,7 +3512,8 @@ createTupleExtensionGenericParams(ASTContext &ctx,
34893512
extendedTypeRepr,
34903513
ext->getParent(),
34913514
/*allowUsableFromInline=*/false,
3492-
/*rhsOfSelfRequirement=*/false);
3515+
/*rhsOfSelfRequirement=*/false,
3516+
/*allowProtocolMembers=*/true);
34933517
assert(referenced.second.empty() && "Implement me");
34943518
if (referenced.first.size() != 1 || !isa<TypeAliasDecl>(referenced.first[0]))
34953519
return nullptr;
@@ -3764,7 +3788,8 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
37643788
decls = directReferencesForTypeRepr(
37653789
evaluator, ctx, typeRepr, dc,
37663790
/*allowUsableFromInline=*/false,
3767-
/*rhsOfSelfRequirement=*/false);
3791+
/*rhsOfSelfRequirement=*/false,
3792+
/*allowProtocolMembers=*/true);
37683793
} else if (Type type = attr->getType()) {
37693794
decls = directReferencesForType(type);
37703795
}
@@ -3795,7 +3820,8 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
37953820
decls = directReferencesForUnqualifiedTypeLookup(
37963821
name, loc, dc, LookupOuterResults::Included,
37973822
/*allowUsableFromInline=*/false,
3798-
/*rhsOfSelfRequirement=*/false);
3823+
/*rhsOfSelfRequirement=*/false,
3824+
/*allowProtocolMembers*/true);
37993825
nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls.first,
38003826
ResolveToNominalOptions(),
38013827
modulesFound, anyObject);
@@ -4033,7 +4059,8 @@ ProtocolDecl *ImplementsAttrProtocolRequest::evaluate(
40334059
DirectlyReferencedTypeDecls referenced =
40344060
directReferencesForTypeRepr(evaluator, ctx, typeRepr, dc,
40354061
/*allowUsableFromInline=*/false,
4036-
/*rhsOfSelfRequirement=*/false);
4062+
/*rhsOfSelfRequirement=*/false,
4063+
/*allowProtocolMembers=*/true);
40374064

40384065
// Resolve those type declarations to nominal type declarations.
40394066
SmallVector<ModuleDecl *, 2> modulesFound;

test/decl/nested/protocol.swift

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,46 @@ class OuterClass {
4444
protocol InnerProtocol : OuterClass { }
4545
}
4646

47+
// Name lookup circularity tests.
48+
49+
protocol SomeBaseProtocol {}
50+
51+
struct ConformanceOnDecl: ConformanceOnDecl.P {
52+
protocol P: SomeBaseProtocol {}
53+
}
54+
struct ConformanceOnDecl_2: ConformanceOnDecl_2.P {
55+
protocol P where Self: SomeBaseProtocol {}
56+
}
57+
struct ConformanceOnDecl_3: Self.P {
58+
protocol P: SomeBaseProtocol {}
59+
}
60+
struct ConformanceOnDecl_4: ConformanceOnDecl_4.Q {
61+
protocol P: SomeBaseProtocol {}
62+
protocol Q: P {}
63+
}
64+
65+
66+
struct ConformanceInExtension {
67+
protocol P: SomeBaseProtocol {}
68+
}
69+
extension ConformanceInExtension: ConformanceInExtension.P {}
70+
71+
struct ConformanceInExtension_2 {
72+
protocol P where Self: SomeBaseProtocol {}
73+
}
74+
extension ConformanceInExtension_2: ConformanceInExtension_2.P {}
75+
76+
struct ConformanceInExtension_3 {
77+
protocol P: SomeBaseProtocol {}
78+
}
79+
extension ConformanceInExtension_3: Self.P {}
80+
81+
struct ConformanceInExtension_4 {
82+
protocol P: SomeBaseProtocol {}
83+
protocol Q: P {}
84+
}
85+
extension ConformanceInExtension_4: ConformanceInExtension_4.Q {}
86+
4787
// Protocols can be nested in actors.
4888

4989
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
@@ -315,4 +355,4 @@ struct Outer {
315355
typealias B = Int
316356
}
317357
}
318-
}
358+
}

0 commit comments

Comments
 (0)