Skip to content

Commit 4ef1904

Browse files
committed
AST: Don't allow declarations to shadow generic parameters
Associated type inference can synthesize type aliases with the same name as a generic parameter. This is all fine since the underlying type of the alias is the generic parameter type, however it might have been synthesized in a constrained extension, resulting in bogus diagnostics that depend on the order in which declarations are type checked, which can vary between WMO and non-WMO, different batch mode settings, etc. Instead, let's just check the generic parameter list first. Fixes <rdar://problem/22587551>, <rdar://problem/44777661>.
1 parent 7c6a6bd commit 4ef1904

File tree

5 files changed

+68
-33
lines changed

5 files changed

+68
-33
lines changed

lib/AST/NameLookup.cpp

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -999,8 +999,6 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
999999

10001000
// Look in the generic parameters after checking our local declaration.
10011001
GenericParams = AFD->getGenericParams();
1002-
} else if (auto *SD = dyn_cast<SubscriptDecl>(DC)) {
1003-
GenericParams = SD->getGenericParams();
10041002
} else if (auto *ACE = dyn_cast<AbstractClosureExpr>(DC)) {
10051003
// Look for local variables; normally, the parser resolves these
10061004
// for us, but it can't do the right thing inside local types.
@@ -1042,12 +1040,14 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
10421040
continue;
10431041
} else {
10441042
assert(isa<TopLevelCodeDecl>(DC) || isa<Initializer>(DC) ||
1045-
isa<TypeAliasDecl>(DC));
1043+
isa<TypeAliasDecl>(DC) || isa<SubscriptDecl>(DC));
10461044
if (!isCascadingUse.hasValue())
10471045
isCascadingUse = DC->isCascadingContextForLookup(false);
10481046
}
10491047

1050-
// Check the generic parameters for something with the given name.
1048+
// If we're inside a function context, we've already moved to
1049+
// the parent DC, so we have to check the function's generic
1050+
// parameters first.
10511051
if (GenericParams) {
10521052
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
10531053
localVal.checkGenericParams(GenericParams);
@@ -1056,6 +1056,30 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
10561056
return;
10571057
}
10581058

1059+
// Check the generic parameters of our context.
1060+
GenericParamList *dcGenericParams = nullptr;
1061+
if (auto nominal = dyn_cast<NominalTypeDecl>(DC))
1062+
dcGenericParams = nominal->getGenericParams();
1063+
else if (auto ext = dyn_cast<ExtensionDecl>(DC))
1064+
dcGenericParams = ext->getGenericParams();
1065+
else if (auto subscript = dyn_cast<SubscriptDecl>(DC))
1066+
dcGenericParams = subscript->getGenericParams();
1067+
1068+
while (dcGenericParams) {
1069+
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
1070+
localVal.checkGenericParams(dcGenericParams);
1071+
1072+
if (shouldReturnBasedOnResults())
1073+
return;
1074+
1075+
// Extensions of nested types have multiple levels of
1076+
// generic parameters, so we have to visit them explicitly.
1077+
if (!isa<ExtensionDecl>(DC))
1078+
break;
1079+
1080+
dcGenericParams = dcGenericParams->getOuterParameters();
1081+
}
1082+
10591083
if (BaseDC && !lookupDecls.empty()) {
10601084
NLOptions options = baseNLOptions;
10611085
if (isCascadingUse.getValue())
@@ -1071,12 +1095,9 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
10711095
// Classify this declaration.
10721096
FoundAny = true;
10731097

1074-
// Types are local or metatype members.
1098+
// Types are formally members of the metatype.
10751099
if (auto TD = dyn_cast<TypeDecl>(Result)) {
1076-
if (isa<GenericTypeParamDecl>(TD))
1077-
Results.push_back(LookupResultEntry(Result));
1078-
else
1079-
Results.push_back(LookupResultEntry(MetaBaseDC, Result));
1100+
Results.push_back(LookupResultEntry(MetaBaseDC, Result));
10801101
continue;
10811102
}
10821103

@@ -1108,29 +1129,6 @@ UnqualifiedLookup::UnqualifiedLookup(DeclName Name, DeclContext *DC,
11081129
}
11091130
}
11101131

1111-
// Check the generic parameters if our context is a generic type or
1112-
// extension thereof.
1113-
GenericParamList *dcGenericParams = nullptr;
1114-
if (auto nominal = dyn_cast<NominalTypeDecl>(DC))
1115-
dcGenericParams = nominal->getGenericParams();
1116-
else if (auto ext = dyn_cast<ExtensionDecl>(DC))
1117-
dcGenericParams = ext->getGenericParams();
1118-
else if (auto subscript = dyn_cast<SubscriptDecl>(DC))
1119-
dcGenericParams = subscript->getGenericParams();
1120-
1121-
while (dcGenericParams) {
1122-
namelookup::FindLocalVal localVal(SM, Loc, Consumer);
1123-
localVal.checkGenericParams(dcGenericParams);
1124-
1125-
if (shouldReturnBasedOnResults())
1126-
return;
1127-
1128-
if (!isa<ExtensionDecl>(DC))
1129-
break;
1130-
1131-
dcGenericParams = dcGenericParams->getOuterParameters();
1132-
}
1133-
11341132
DC = DC->getParentForLookup();
11351133
}
11361134

test/NameBinding/name_lookup.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,3 +601,11 @@ func test3() {
601601
_ = b
602602
}
603603
}
604+
605+
// rdar://problem/22587551
606+
class ShadowingGenericParameter<T> {
607+
typealias T = Int
608+
func foo (t : T) {}
609+
}
610+
611+
_ = ShadowingGenericParameter<String>().foo(t: "hi")

test/Sema/circular_decl_checking.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ class X {
6666

6767
// <rdar://problem/17144076> recursive typealias causes a segfault in the type checker
6868
struct SomeStruct<A> {
69-
typealias A = A // expected-error {{type alias 'A' references itself}}
69+
typealias A = A // this is OK now -- the underlying type is the generic parameter 'A'
70+
typealias B = B // expected-error {{type alias 'B' references itself}}
7071
// expected-note@-1 {{type declared here}}
7172
}
7273

test/api-digester/Outputs/stability-stdlib-source.swift.expected

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,31 @@ Func AnyRandomAccessCollection.formIndex(_:offsetBy:limitedBy:) has parameter 0
2222
Func AnyRandomAccessCollection.formIndex(after:) has parameter 0 changing from Default to InOut
2323
Func AnyRandomAccessCollection.formIndex(before:) has parameter 0 changing from Default to InOut
2424
Func Array.append(_:) has parameter 0 changing from Default to Owned
25+
Func Array.append(_:) has parameter 0 type change from Array<Element>.Element to Element
2526
Func Array.insert(_:at:) has parameter 0 changing from Default to Owned
27+
Func Array.insert(_:at:) has parameter 0 type change from Array<Element>.Element to Element
2628
Func ArraySlice.append(_:) has parameter 0 changing from Default to Owned
29+
Func ArraySlice.append(_:) has parameter 0 type change from ArraySlice<Element>.Element to Element
2730
Func ArraySlice.insert(_:at:) has parameter 0 changing from Default to Owned
31+
Func ArraySlice.insert(_:at:) has parameter 0 type change from ArraySlice<Element>.Element to Element
2832
Func ContiguousArray.append(_:) has parameter 0 changing from Default to Owned
33+
Func ContiguousArray.append(_:) has parameter 0 type change from ContiguousArray<Element>.Element to Element
2934
Func ContiguousArray.insert(_:at:) has parameter 0 changing from Default to Owned
35+
Func ContiguousArray.insert(_:at:) has parameter 0 type change from ContiguousArray<Element>.Element to Element
3036
Func DefaultIndices.formIndex(after:) has parameter 0 changing from Default to InOut
3137
Func DefaultIndices.formIndex(before:) has parameter 0 changing from Default to InOut
3238
Func Dictionary.updateValue(_:forKey:) has parameter 0 changing from Default to Owned
39+
Func Dictionary.updateValue(_:forKey:) has parameter 0 type change from Dictionary<Key, Value>.Value to Value
3340
Func LazyFilterCollection.formIndex(_:offsetBy:) has parameter 0 changing from Default to InOut
3441
Func LazyFilterCollection.formIndex(_:offsetBy:limitedBy:) has parameter 0 changing from Default to InOut
3542
Func LazyFilterCollection.formIndex(after:) has parameter 0 changing from Default to InOut
3643
Func LazyFilterCollection.formIndex(before:) has parameter 0 changing from Default to InOut
3744
Func LazyMapCollection.formIndex(after:) has parameter 0 changing from Default to InOut
3845
Func LazyMapCollection.formIndex(before:) has parameter 0 changing from Default to InOut
3946
Func Set.insert(_:) has parameter 0 changing from Default to Owned
47+
Func Set.insert(_:) has parameter 0 type change from Set<Element>.Element to Element
4048
Func Set.update(with:) has parameter 0 changing from Default to Owned
49+
Func Set.update(with:) has parameter 0 type change from Set<Element>.Element to Element
4150
Func Slice.formIndex(after:) has parameter 0 changing from Default to InOut
4251
Func Slice.formIndex(before:) has parameter 0 changing from Default to InOut
4352
Func String.UTF16View.Indices.formIndex(after:) has parameter 0 changing from Default to InOut

test/decl/protocol/req/associated_type_inference.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,3 +508,22 @@ protocol P20 {
508508
struct S19 : P20 { // expected-error{{type 'S19' does not conform to protocol 'P20'}}
509509
typealias TT = Int?
510510
}
511+
512+
// rdar://problem/44777661
513+
struct S30<T> where T : P30 {}
514+
515+
protocol P30 {
516+
static func bar()
517+
}
518+
519+
protocol P31 {
520+
associatedtype T : P30
521+
}
522+
523+
extension S30 : P31 where T : P31 {}
524+
525+
extension S30 {
526+
func foo() {
527+
T.bar()
528+
}
529+
}

0 commit comments

Comments
 (0)