Skip to content

Commit 5f585a1

Browse files
committed
[Sema] Generalize checking of conditional nested typealiases to all types.
One can have arbitrary types defined in a constrained extension, not just typealiases, e.g. struct Foo<T> {} extension Foo where T == Int { struct X {} } A mention of `Foo<String>.X` should be flagged, since String != Int. Previously this worked (in expressions) only if `X` was a typealias, and with this patch the above example is flagged too. Part of https://bugs.swift.org/browse/SR-5440 and https://bugs.swift.org/browse/SR-7976 and rdar://problem/41063870.
1 parent f65000a commit 5f585a1

File tree

2 files changed

+253
-14
lines changed

2 files changed

+253
-14
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -481,36 +481,74 @@ Type ConstraintSystem::openUnboundGenericType(UnboundGenericType *unbound,
481481
/*unsatisfiedDependency*/nullptr);
482482
}
483483

484-
Type ConstraintSystem::openUnboundGenericType(
485-
Type type,
486-
ConstraintLocatorBuilder locator) {
487-
assert(!type->hasTypeParameter());
484+
static void checkNestedTypeConstraints(ConstraintSystem &cs, Type type,
485+
ConstraintLocatorBuilder locator) {
486+
// If this is a type defined inside of constrainted extension, let's add all
487+
// of the generic requirements to the constraint system to make sure that it's
488+
// something we can use.
489+
GenericTypeDecl *decl = nullptr;
490+
Type parentTy;
491+
SubstitutionMap subMap;
488492

489-
// If this is a generic typealias defined inside of constrainted extension,
490-
// let's add all of the generic requirements to the constraint system to
491-
// make sure that it's something we can use.
492493
if (auto *NAT = dyn_cast<NameAliasType>(type.getPointer())) {
493-
auto *decl = NAT->getDecl();
494-
auto *extension = dyn_cast<ExtensionDecl>(decl->getDeclContext());
495-
auto parentTy = NAT->getParent();
496-
494+
decl = NAT->getDecl();
495+
parentTy = NAT->getParent();
496+
subMap = NAT->getSubstitutionMap();
497+
} else if (auto *AGT = type->getAs<AnyGenericType>()) {
498+
decl = AGT->getDecl();
499+
parentTy = AGT->getParent();
500+
// the context substitution map is fine here, since we can't be adding more
501+
// info than that, unlike a typealias
502+
}
503+
504+
// If this decl is generic, the constraints are handled when the generic
505+
// parameters are applied, so we don't have to handle them here (which makes
506+
// getting the right substitution maps easier).
507+
if (decl && !decl->isGeneric()) {
508+
auto extension = dyn_cast<ExtensionDecl>(decl->getDeclContext());
497509
if (parentTy && extension && extension->isConstrainedExtension()) {
498-
auto subMap = NAT->getSubstitutionMap();
499510
auto contextSubMap = parentTy->getContextSubstitutionMap(
500511
extension->getParentModule(),
501512
extension->getAsNominalTypeOrNominalTypeExtensionContext());
513+
if (!subMap) {
514+
// The substitution map wasn't set above, meaning we should grab the map
515+
// for the extension itself.
516+
subMap = parentTy->getContextSubstitutionMap(
517+
extension->getParentModule(), extension);
518+
}
502519

503-
if (auto *signature = NAT->getGenericSignature()) {
504-
openGenericRequirements(
520+
if (auto *signature = decl->getGenericSignature()) {
521+
cs.openGenericRequirements(
505522
extension, signature, /*skipProtocolSelfConstraint*/ true, locator,
506523
[&](Type type) {
524+
// Why do we look in two substitution maps? We have to use the
525+
// context substitution map to find types, because we need to
526+
// avoid thinking about them when handling the constraints, or all
527+
// the requirements in the signature become tautologies (if the
528+
// extension has 'T == Int', subMap will map T -> Int, so the
529+
// requirement becomes Int == Int no matter what the actual types
530+
// are here). However, we need the conformances for the extension
531+
// because the requirements might look like `T: P, T.U: Q`, where
532+
// U is an associated type of protocol P.
507533
return type.subst(QuerySubstitutionMap{contextSubMap},
508534
LookUpConformanceInSubstitutionMap(subMap),
509535
SubstFlags::UseErrorType);
510536
});
511537
}
512538
}
539+
540+
// And now make sure sure the parent is okay, for things like X<T>.Y.Z.
541+
if (parentTy) {
542+
checkNestedTypeConstraints(cs, parentTy, locator);
543+
}
513544
}
545+
}
546+
547+
Type ConstraintSystem::openUnboundGenericType(
548+
Type type, ConstraintLocatorBuilder locator) {
549+
assert(!type->hasTypeParameter());
550+
551+
checkNestedTypeConstraints(*this, type, locator);
514552

515553
if (!type->hasUnboundGenericType())
516554
return type;
Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol P {}
4+
struct X: P {}
5+
struct Y {}
6+
7+
protocol AssociatedType {
8+
associatedtype T
9+
}
10+
struct Z1: AssociatedType {
11+
typealias T = X
12+
}
13+
struct Z2: AssociatedType {
14+
typealias T = Y
15+
}
16+
17+
struct SameType<T> {}
18+
extension SameType where T == X {
19+
typealias TypeAlias1 = T
20+
typealias TypeAlias2 = Y
21+
typealias TypeAlias3<U> = (T, U) // expected-note {{requirement specified as 'T' == 'X' [with T = Y]}}
22+
23+
struct Decl1 {}
24+
enum Decl2 {}
25+
class Decl3 {}
26+
struct Decl4<U> {} // expected-note 17 {{requirement specified as 'T' == 'X' [with T = Y]}}
27+
enum Decl5<U: P> {} // expected-note {{requirement specified as 'T' == 'X' [with T = Y]}}
28+
}
29+
30+
let _ = SameType<X>.TypeAlias1.self
31+
let _ = SameType<X>.TypeAlias2.self
32+
let _ = SameType<X>.TypeAlias3<X>.self
33+
let _ = SameType<X>.Decl1.self
34+
let _ = SameType<X>.Decl2.self
35+
let _ = SameType<X>.Decl3.self
36+
let _ = SameType<X>.Decl4<X>.self
37+
let _ = SameType<X>.Decl5<X>.self
38+
39+
let _ = SameType<Y>.TypeAlias1.self // expected-error {{'SameType<Y>.TypeAlias1.Type' (aka 'X.Type') requires the types 'Y' and 'X' be equivalent}}
40+
let _ = SameType<Y>.TypeAlias2.self // expected-error {{'SameType<Y>.TypeAlias2.Type' (aka 'Y.Type') requires the types 'Y' and 'X' be equivalent}}
41+
let _ = SameType<Y>.TypeAlias3<X>.self // expected-error {{'SameType<Y>.TypeAlias3' requires the types 'Y' and 'X' be equivalent}}
42+
let _ = SameType<Y>.Decl1.self // expected-error {{'SameType<Y>.Decl1.Type' requires the types 'Y' and 'X' be equivalent}}
43+
let _ = SameType<Y>.Decl2.self // expected-error {{'SameType<Y>.Decl2.Type' requires the types 'Y' and 'X' be equivalent}}
44+
let _ = SameType<Y>.Decl3.self // expected-error {{'SameType<Y>.Decl3.Type' requires the types 'Y' and 'X' be equivalent}}
45+
let _ = SameType<Y>.Decl4<X>.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
46+
let _ = SameType<Y>.Decl5<X>.self // expected-error {{'SameType<Y>.Decl5' requires the types 'Y' and 'X' be equivalent}}
47+
48+
struct Conforms<T> {}
49+
extension Conforms where T: P {
50+
typealias TypeAlias1 = T
51+
typealias TypeAlias2 = Y
52+
typealias TypeAlias3<U> = (T, U)
53+
54+
struct Decl1 {}
55+
enum Decl2 {}
56+
class Decl3 {}
57+
struct Decl4<U> {}
58+
enum Decl5<U: P> {}
59+
}
60+
61+
let _ = Conforms<X>.TypeAlias1.self
62+
let _ = Conforms<X>.TypeAlias2.self
63+
let _ = Conforms<X>.TypeAlias3<X>.self
64+
let _ = Conforms<X>.Decl1.self
65+
let _ = Conforms<X>.Decl2.self
66+
let _ = Conforms<X>.Decl3.self
67+
let _ = Conforms<X>.Decl4<X>.self
68+
let _ = Conforms<X>.Decl5<X>.self
69+
70+
let _ = Conforms<Y>.TypeAlias1.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
71+
let _ = Conforms<Y>.TypeAlias2.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
72+
let _ = Conforms<Y>.TypeAlias3<X>.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
73+
let _ = Conforms<Y>.Decl1.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
74+
let _ = Conforms<Y>.Decl2.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
75+
let _ = Conforms<Y>.Decl3.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
76+
let _ = Conforms<Y>.Decl4<X>.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
77+
let _ = Conforms<Y>.Decl5<X>.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
78+
79+
// Now, even more nesting!
80+
81+
extension SameType.Decl1 {
82+
typealias TypeAlias1 = T
83+
typealias TypeAlias2 = Y
84+
typealias TypeAlias3<U> = (T, U) // expected-note {{requirement specified as 'T' == 'X' [with T = Y]}}
85+
86+
struct Decl1 {}
87+
enum Decl2 {}
88+
class Decl3 {}
89+
struct Decl4<U> {} // expected-note {{requirement specified as 'T' == 'X' [with T = Y]}}
90+
enum Decl5<U: P> {} // expected-note {{requirement specified as 'T' == 'X' [with T = Y]}}
91+
}
92+
93+
let _ = SameType<X>.Decl1.TypeAlias1.self
94+
let _ = SameType<X>.Decl1.TypeAlias2.self
95+
let _ = SameType<X>.Decl1.TypeAlias3<X>.self
96+
let _ = SameType<X>.Decl1.Decl1.self
97+
let _ = SameType<X>.Decl1.Decl2.self
98+
let _ = SameType<X>.Decl1.Decl3.self
99+
let _ = SameType<X>.Decl1.Decl4<X>.self
100+
let _ = SameType<X>.Decl1.Decl5<X>.self
101+
102+
let _ = SameType<Y>.Decl1.TypeAlias1.self // expected-error {{'SameType<Y>.Decl1.TypeAlias1.Type' (aka 'X.Type') requires the types 'Y' and 'X' be equivalent}}
103+
let _ = SameType<Y>.Decl1.TypeAlias2.self // expected-error {{'SameType<Y>.Decl1.TypeAlias2.Type' (aka 'Y.Type') requires the types 'Y' and 'X' be equivalent}}
104+
let _ = SameType<Y>.Decl1.TypeAlias3<X>.self // expected-error {{'SameType<Y>.Decl1.TypeAlias3' requires the types 'Y' and 'X' be equivalent}}
105+
let _ = SameType<Y>.Decl1.Decl1.self // expected-error {{'SameType<Y>.Decl1.Decl1.Type' requires the types 'Y' and 'X' be equivalent}}
106+
let _ = SameType<Y>.Decl1.Decl2.self // expected-error {{'SameType<Y>.Decl1.Decl2.Type' requires the types 'Y' and 'X' be equivalent}}
107+
let _ = SameType<Y>.Decl1.Decl3.self // expected-error {{'SameType<Y>.Decl1.Decl3.Type' requires the types 'Y' and 'X' be equivalent}}
108+
let _ = SameType<Y>.Decl1.Decl4<X>.self // expected-error {{'SameType<Y>.Decl1.Decl4' requires the types 'Y' and 'X' be equivalent}}
109+
let _ = SameType<Y>.Decl1.Decl5<X>.self // expected-error {{'SameType<Y>.Decl1.Decl5' requires the types 'Y' and 'X' be equivalent}}
110+
111+
extension SameType.Decl4 where U == X {
112+
typealias TypeAlias1 = T
113+
typealias TypeAlias2 = Y
114+
typealias TypeAlias3<V> = (T, U, V) // expected-note {{requirement specified as 'U' == 'X' [with U = Y]}}
115+
116+
struct Decl1 {}
117+
enum Decl2 {}
118+
class Decl3 {}
119+
struct Decl4<V> {} // expected-note {{requirement specified as 'U' == 'X' [with U = Y]}}
120+
enum Decl5<V: P> {} // expected-note {{requirement specified as 'U' == 'X' [with U = Y]}}
121+
}
122+
123+
// All the combinations
124+
125+
let _ = SameType<X>.Decl4<X>.TypeAlias1.self
126+
let _ = SameType<X>.Decl4<X>.TypeAlias2.self
127+
let _ = SameType<X>.Decl4<X>.TypeAlias3<X>.self
128+
let _ = SameType<X>.Decl4<X>.Decl1.self
129+
let _ = SameType<X>.Decl4<X>.Decl2.self
130+
let _ = SameType<X>.Decl4<X>.Decl3.self
131+
let _ = SameType<X>.Decl4<X>.Decl4<X>.self
132+
let _ = SameType<X>.Decl4<X>.Decl5<X>.self
133+
134+
let _ = SameType<X>.Decl4<Y>.TypeAlias1.self // expected-error {{'SameType<X>.Decl4<Y>.TypeAlias1.Type' (aka 'X.Type') requires the types 'Y' and 'X' be equivalent}}
135+
let _ = SameType<X>.Decl4<Y>.TypeAlias2.self // expected-error {{'SameType<X>.Decl4<Y>.TypeAlias2.Type' (aka 'Y.Type') requires the types 'Y' and 'X' be equivalent}}
136+
let _ = SameType<X>.Decl4<Y>.TypeAlias3<X>.self // expected-error {{'SameType<X>.Decl4<Y>.TypeAlias3' requires the types 'Y' and 'X' be equivalent}}
137+
let _ = SameType<X>.Decl4<Y>.Decl1.self // expected-error {{'SameType<X>.Decl4<Y>.Decl1.Type' requires the types 'Y' and 'X' be equivalent}}
138+
let _ = SameType<X>.Decl4<Y>.Decl2.self // expected-error {{'SameType<X>.Decl4<Y>.Decl2.Type' requires the types 'Y' and 'X' be equivalent}}
139+
let _ = SameType<X>.Decl4<Y>.Decl3.self // expected-error {{'SameType<X>.Decl4<Y>.Decl3.Type' requires the types 'Y' and 'X' be equivalent}}
140+
let _ = SameType<X>.Decl4<Y>.Decl4<X>.self // expected-error {{'SameType<X>.Decl4<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
141+
let _ = SameType<X>.Decl4<Y>.Decl5<X>.self // expected-error {{'SameType<X>.Decl4<Y>.Decl5' requires the types 'Y' and 'X' be equivalent}}
142+
143+
let _ = SameType<Y>.Decl4<X>.TypeAlias1.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
144+
let _ = SameType<Y>.Decl4<X>.TypeAlias2.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
145+
let _ = SameType<Y>.Decl4<X>.TypeAlias3<X>.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
146+
let _ = SameType<Y>.Decl4<X>.Decl1.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
147+
let _ = SameType<Y>.Decl4<X>.Decl2.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
148+
let _ = SameType<Y>.Decl4<X>.Decl3.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
149+
let _ = SameType<Y>.Decl4<X>.Decl4<X>.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
150+
let _ = SameType<Y>.Decl4<X>.Decl5<X>.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
151+
152+
let _ = SameType<Y>.Decl4<Y>.TypeAlias1.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
153+
let _ = SameType<Y>.Decl4<Y>.TypeAlias2.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
154+
let _ = SameType<Y>.Decl4<Y>.TypeAlias3<X>.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
155+
let _ = SameType<Y>.Decl4<Y>.Decl1.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
156+
let _ = SameType<Y>.Decl4<Y>.Decl2.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
157+
let _ = SameType<Y>.Decl4<Y>.Decl3.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
158+
let _ = SameType<Y>.Decl4<Y>.Decl4<X>.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
159+
let _ = SameType<Y>.Decl4<Y>.Decl5<X>.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
160+
161+
// Finally, extra complicated:
162+
extension Conforms.Decl4 where U: AssociatedType, U.T: P {
163+
typealias TypeAlias1 = T
164+
typealias TypeAlias2 = Y
165+
typealias TypeAlias3<V> = (T, U, V)
166+
167+
struct Decl1 {}
168+
enum Decl2 {}
169+
class Decl3 {}
170+
struct Decl4<V> {}
171+
enum Decl5<V: P> {}
172+
}
173+
174+
let _ = Conforms<X>.Decl4<Z1>.TypeAlias1.self
175+
let _ = Conforms<X>.Decl4<Z1>.TypeAlias2.self
176+
let _ = Conforms<X>.Decl4<Z1>.TypeAlias3<X>.self
177+
let _ = Conforms<X>.Decl4<Z1>.Decl1.self
178+
let _ = Conforms<X>.Decl4<Z1>.Decl2.self
179+
let _ = Conforms<X>.Decl4<Z1>.Decl3.self
180+
let _ = Conforms<X>.Decl4<Z1>.Decl4<X>.self
181+
let _ = Conforms<X>.Decl4<Z1>.Decl5<X>.self
182+
183+
// Two different forms of badness, corresponding to the two requirements:
184+
185+
let _ = Conforms<X>.Decl4<Y>.TypeAlias1.self // expected-error {{type 'Y' does not conform to protocol 'AssociatedType'}}
186+
let _ = Conforms<X>.Decl4<Y>.TypeAlias2.self // expected-error {{type 'Y' does not conform to protocol 'AssociatedType'}}
187+
let _ = Conforms<X>.Decl4<Y>.TypeAlias3<X>.self // expected-error {{type 'Y' does not conform to protocol 'AssociatedType'}}
188+
let _ = Conforms<X>.Decl4<Y>.Decl1.self // expected-error {{type 'Y' does not conform to protocol 'AssociatedType'}}
189+
let _ = Conforms<X>.Decl4<Y>.Decl2.self // expected-error {{type 'Y' does not conform to protocol 'AssociatedType'}}
190+
let _ = Conforms<X>.Decl4<Y>.Decl3.self // expected-error {{type 'Y' does not conform to protocol 'AssociatedType'}}
191+
let _ = Conforms<X>.Decl4<Y>.Decl4<X>.self // expected-error {{type 'Y' does not conform to protocol 'AssociatedType'}}
192+
let _ = Conforms<X>.Decl4<Y>.Decl5<X>.self // expected-error {{type 'Y' does not conform to protocol 'AssociatedType'}}
193+
194+
let _ = Conforms<X>.Decl4<Z2>.TypeAlias1.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}}
195+
let _ = Conforms<X>.Decl4<Z2>.TypeAlias2.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}}
196+
let _ = Conforms<X>.Decl4<Z2>.TypeAlias3<X>.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}}
197+
let _ = Conforms<X>.Decl4<Z2>.Decl1.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}}
198+
let _ = Conforms<X>.Decl4<Z2>.Decl2.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}}
199+
let _ = Conforms<X>.Decl4<Z2>.Decl3.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}}
200+
let _ = Conforms<X>.Decl4<Z2>.Decl4<X>.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}}
201+
let _ = Conforms<X>.Decl4<Z2>.Decl5<X>.self // expected-error {{type 'Z2.T' (aka 'Y') does not conform to protocol 'P'}}

0 commit comments

Comments
 (0)