Skip to content

Commit c85eae1

Browse files
Get rid of the second call to setType() in validateExtension().
This means that we no longer have the invariant that the extendedType always contains the generic parameters. So we need to fix the assertions/test cases for it.
1 parent 3952a0a commit c85eae1

File tree

10 files changed

+52
-49
lines changed

10 files changed

+52
-49
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5252
/// describe what change you made. The content of this comment isn't important;
5353
/// it just ensures a conflict if two people change the module format.
5454
/// Don't worry about adhering to the 80-column limit for this line.
55-
const uint16_t SWIFTMODULE_VERSION_MINOR = 511; // ctor failability change
55+
const uint16_t SWIFTMODULE_VERSION_MINOR = 512; // extended types may be left as unbound generic types
5656

5757
using DeclIDField = BCFixed<31>;
5858

lib/Sema/TypeCheckDecl.cpp

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4451,7 +4451,7 @@ static Type formExtensionInterfaceType(
44514451

44524452
/// Check the generic parameters of an extension, recursively handling all of
44534453
/// the parameter lists within the extension.
4454-
static std::pair<GenericEnvironment *, Type>
4454+
static GenericEnvironment *
44554455
checkExtensionGenericParams(TypeChecker &tc, ExtensionDecl *ext, Type type,
44564456
GenericParamList *genericParams) {
44574457
assert(!ext->getGenericEnvironment());
@@ -4489,7 +4489,7 @@ checkExtensionGenericParams(TypeChecker &tc, ExtensionDecl *ext, Type type,
44894489
(mustInferRequirements ||
44904490
!sameTypeReqs.empty()));
44914491

4492-
return { env, extInterfaceType };
4492+
return env;
44934493
}
44944494

44954495
static bool isNonGenericTypeAliasType(Type type) {
@@ -4500,7 +4500,7 @@ static bool isNonGenericTypeAliasType(Type type) {
45004500
return false;
45014501
}
45024502

4503-
static Type validateExtendedType(ExtensionDecl *ext, DiagnosticEngine &diags) {
4503+
static Type validateExtendedType(ExtensionDecl *ext) {
45044504
auto error = [&ext]() {
45054505
ext->setInvalid();
45064506
return ErrorType::get(ext->getASTContext());
@@ -4525,16 +4525,15 @@ static Type validateExtendedType(ExtensionDecl *ext, DiagnosticEngine &diags) {
45254525
if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
45264526
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
45274527
auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
4528-
if (extendedNominal) {
4529-
if (!isPassThroughTypealias(aliasDecl)) {
4530-
extendedType = extendedNominal->getDeclaredType();
4531-
ext->getExtendedTypeLoc().setType(extendedType);
4532-
}
4533-
return extendedType;
4534-
}
4528+
if (extendedNominal)
4529+
return isPassThroughTypealias(aliasDecl)
4530+
? extendedType
4531+
: extendedNominal->getDeclaredType();
45354532
}
45364533
}
45374534

4535+
auto &diags = ext->getASTContext().Diags;
4536+
45384537
// Cannot extend a metatype.
45394538
if (extendedType->is<AnyMetatypeType>()) {
45404539
diags.diagnose(ext->getLoc(), diag::extension_metatype, extendedType)
@@ -4570,7 +4569,7 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) {
45704569

45714570
DeclValidationRAII IBV(ext);
45724571

4573-
(void)validateExtendedType(ext, Diags);
4572+
auto extendedType = validateExtendedType(ext);
45744573

45754574
if (auto *nominal = ext->getExtendedNominal()) {
45764575
// If this extension was not already bound, it means it is either in an
@@ -4583,14 +4582,11 @@ void TypeChecker::validateExtension(ExtensionDecl *ext) {
45834582
// Validate the nominal type declaration being extended.
45844583
validateDecl(nominal);
45854584

4586-
if (auto *genericParams = ext->getGenericParams()) {
4587-
GenericEnvironment *env;
4588-
Type extendedType = ext->getExtendedType();
4589-
std::tie(env, extendedType) = checkExtensionGenericParams(
4590-
*this, ext, extendedType,
4591-
genericParams);
4585+
ext->getExtendedTypeLoc().setType(extendedType);
45924586

4593-
ext->getExtendedTypeLoc().setType(extendedType);
4587+
if (auto *genericParams = ext->getGenericParams()) {
4588+
GenericEnvironment *env =
4589+
checkExtensionGenericParams(*this, ext, extendedType, genericParams);
45944590
ext->setGenericEnvironment(env);
45954591
}
45964592
}

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ static void checkGenericParamList(TypeChecker &tc,
7676

7777
if (auto decl = owner.dc->getAsDecl()) {
7878
if (auto extDecl = dyn_cast<ExtensionDecl>(decl)) {
79-
auto extType = extDecl->getExtendedType();
79+
auto extType = extDecl->getDeclaredInterfaceType();
8080
auto extSelfType = extDecl->getSelfInterfaceType();
8181
auto reqLHSType = req.getFirstType();
8282
auto reqRHSType = req.getSecondType();

lib/Sema/TypeCheckType.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,11 +536,20 @@ Type TypeChecker::resolveTypeInContext(
536536
parentDC = parentDC->getParent()) {
537537
if (auto *ext = dyn_cast<ExtensionDecl>(parentDC)) {
538538
auto extendedType = ext->getExtendedType();
539+
if (auto *unboundGeneric = dyn_cast<UnboundGenericType>(extendedType.getPointer())) {
540+
if (auto *ugAliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getAnyGeneric())) {
541+
if (ugAliasDecl == aliasDecl)
542+
return resolution.mapTypeIntoContext(
543+
aliasDecl->getDeclaredInterfaceType());
544+
545+
extendedType = unboundGeneric->getParent();
546+
continue;
547+
}
548+
}
539549
if (auto *aliasType = dyn_cast<TypeAliasType>(extendedType.getPointer())) {
540-
if (aliasType->getDecl() == aliasDecl) {
550+
if (aliasType->getDecl() == aliasDecl)
541551
return resolution.mapTypeIntoContext(
542552
aliasDecl->getDeclaredInterfaceType());
543-
}
544553

545554
extendedType = aliasType->getParent();
546555
continue;

lib/Serialization/Deserialization.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3931,9 +3931,8 @@ class swift::DeclDeserializer {
39313931
MF.configureGenericEnvironment(extension, genericEnvID);
39323932

39333933
auto baseTy = MF.getType(baseID);
3934-
auto nominal = baseTy->getAnyNominal();
3935-
assert(!baseTy->hasUnboundGenericType());
39363934
extension->getExtendedTypeLoc().setType(baseTy);
3935+
auto nominal = extension->getExtendedNominal();
39373936

39383937
if (isImplicit)
39393938
extension->setImplicit();

lib/Serialization/Serialization.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2871,7 +2871,6 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
28712871

28722872
auto contextID = S.addDeclContextRef(extension->getDeclContext());
28732873
Type baseTy = extension->getExtendedType();
2874-
assert(!baseTy->hasUnboundGenericType());
28752874
assert(!baseTy->hasArchetype());
28762875

28772876
// FIXME: Use the canonical type here in order to minimize circularity

test/Frontend/debug-generic-signatures.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ struct NonRecur: P2 {
7373
// Conditional conformance.
7474

7575
struct Generic<T> {}
76-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Generic<T>
76+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Generic
7777
// CHECK-NEXT: (normal_conformance type=Generic<T> protocol=P1
7878
// CHECK-NEXT: (assoc_type req=A type=T)
7979
// CHECK-NEXT: (value req=f() witness=main.(file).Generic extension.f()@{{.*}})
@@ -86,7 +86,7 @@ extension Generic: P1 where T: P1 {
8686

8787
// Satisfying associated types with requirements with generic params
8888
class Super<T, U> {}
89-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Super<T, U>
89+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Super
9090
// CHECK-NEXT: (normal_conformance type=Super<T, U> protocol=P2
9191
// CHECK-NEXT: (assoc_type req=A type=T)
9292
// CHECK-NEXT: (assoc_type req=B type=T)

test/Generics/conditional_conformances.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ func takes_P2<X: P2>(_: X) {}
2121
func takes_P5<X: P5>(_: X) {}
2222

2323
struct Free<T> {}
24-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Free<T>
24+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Free
2525
// CHECK-NEXT: (normal_conformance type=Free<T> protocol=P2
2626
// CHECK-NEXT: conforms_to: T P1)
2727
extension Free: P2 where T: P1 {} // expected-note {{requirement from conditional conformance of 'Free<U>' to 'P2'}}
@@ -33,7 +33,7 @@ func free_bad<U>(_: U) {
3333
}
3434

3535
struct Constrained<T: P1> {}
36-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Constrained<T>
36+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Constrained
3737
// CHECK-NEXT: (normal_conformance type=Constrained<T> protocol=P2
3838
// CHECK-NEXT: conforms_to: T P3)
3939
extension Constrained: P2 where T: P3 {} // expected-note {{requirement from conditional conformance of 'Constrained<U>' to 'P2'}}
@@ -45,17 +45,17 @@ func constrained_bad<U: P1>(_: U) {
4545
}
4646

4747
struct RedundantSame<T: P1> {}
48-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSame<T>
48+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSame
4949
// CHECK-NEXT: (normal_conformance type=RedundantSame<T> protocol=P2)
5050
extension RedundantSame: P2 where T: P1 {}
5151

5252
struct RedundantSuper<T: P4> {}
53-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSuper<T>
53+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundantSuper
5454
// CHECK-NEXT: (normal_conformance type=RedundantSuper<T> protocol=P2)
5555
extension RedundantSuper: P2 where T: P1 {}
5656

5757
struct OverlappingSub<T: P1> {}
58-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=OverlappingSub<T>
58+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=OverlappingSub
5959
// CHECK-NEXT: (normal_conformance type=OverlappingSub<T> protocol=P2
6060
// CHECK-NEXT: conforms_to: T P4)
6161
extension OverlappingSub: P2 where T: P4 {} // expected-note {{requirement from conditional conformance of 'OverlappingSub<U>' to 'P2'}}
@@ -68,7 +68,7 @@ func overlapping_sub_bad<U: P1>(_: U) {
6868

6969

7070
struct SameType<T> {}
71-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=SameType<T>
71+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=SameType
7272
// CHECK-NEXT: (normal_conformance type=SameType<T> protocol=P2
7373
// CHECK-NEXT: same_type: T Int)
7474
extension SameType: P2 where T == Int {}
@@ -84,7 +84,7 @@ func same_type_bad<U>(_: U) {
8484

8585

8686
struct SameTypeGeneric<T, U> {}
87-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=SameTypeGeneric<T, U>
87+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=SameTypeGeneric
8888
// CHECK-NEXT: (normal_conformance type=SameTypeGeneric<T, U> protocol=P2
8989
// CHECK-NEXT: same_type: T U)
9090
extension SameTypeGeneric: P2 where T == U {}
@@ -108,7 +108,7 @@ func same_type_bad<U, V>(_: U, _: V) {
108108

109109

110110
struct Infer<T, U> {}
111-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Infer<T, U>
111+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=Infer
112112
// CHECK-NEXT: (normal_conformance type=Infer<T, U> protocol=P2
113113
// CHECK-NEXT: same_type: T Constrained<U>
114114
// CHECK-NEXT: conforms_to: U P1)
@@ -126,7 +126,7 @@ func infer_bad<U: P1, V>(_: U, _: V) {
126126
}
127127

128128
struct InferRedundant<T, U: P1> {}
129-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InferRedundant<T, U>
129+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InferRedundant
130130
// CHECK-NEXT: (normal_conformance type=InferRedundant<T, U> protocol=P2
131131
// CHECK-NEXT: same_type: T Constrained<U>)
132132
extension InferRedundant: P2 where T == Constrained<U> {}
@@ -146,7 +146,7 @@ class C2: C1 {}
146146
class C3: C2 {}
147147

148148
struct ClassFree<T> {}
149-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassFree<T>
149+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassFree
150150
// CHECK-NEXT: (normal_conformance type=ClassFree<T> protocol=P2
151151
// CHECK-NEXT: superclass: T C1)
152152
extension ClassFree: P2 where T: C1 {}
@@ -159,7 +159,7 @@ func class_free_bad<U>(_: U) {
159159
}
160160

161161
struct ClassMoreSpecific<T: C1> {}
162-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassMoreSpecific<T>
162+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassMoreSpecific
163163
// CHECK-NEXT: (normal_conformance type=ClassMoreSpecific<T> protocol=P2
164164
// CHECK-NEXT: superclass: T C3)
165165
extension ClassMoreSpecific: P2 where T: C3 {} // expected-note {{requirement from conditional conformance of 'ClassMoreSpecific<U>' to 'P2'}}
@@ -173,7 +173,7 @@ func class_more_specific_bad<U: C1>(_: U) {
173173

174174

175175
struct ClassLessSpecific<T: C3> {}
176-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassLessSpecific<T>
176+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=ClassLessSpecific
177177
// CHECK-NEXT: (normal_conformance type=ClassLessSpecific<T> protocol=P2)
178178
extension ClassLessSpecific: P2 where T: C1 {}
179179

@@ -195,11 +195,11 @@ func subclass_bad() {
195195
// Inheriting conformances:
196196

197197
struct InheritEqual<T> {}
198-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual<T>
198+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual
199199
// CHECK-NEXT: (normal_conformance type=InheritEqual<T> protocol=P2
200200
// CHECK-NEXT: conforms_to: T P1)
201201
extension InheritEqual: P2 where T: P1 {} // expected-note {{requirement from conditional conformance of 'InheritEqual<U>' to 'P2'}}
202-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual<T>
202+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritEqual
203203
// CHECK-NEXT: (normal_conformance type=InheritEqual<T> protocol=P5
204204
// CHECK-NEXT: (normal_conformance type=InheritEqual<T> protocol=P2
205205
// CHECK-NEXT: conforms_to: T P1)
@@ -223,11 +223,11 @@ extension InheritLess: P5 {} // expected-error{{type 'T' does not conform to pro
223223

224224

225225
struct InheritMore<T> {}
226-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore<T>
226+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore
227227
// CHECK-NEXT: (normal_conformance type=InheritMore<T> protocol=P2
228228
// CHECK-NEXT: conforms_to: T P1)
229229
extension InheritMore: P2 where T: P1 {} // expected-note {{requirement from conditional conformance of 'InheritMore<U>' to 'P2'}}
230-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore<T>
230+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=InheritMore
231231
// CHECK-NEXT: (normal_conformance type=InheritMore<T> protocol=P5
232232
// CHECK-NEXT: (normal_conformance type=InheritMore<T> protocol=P2
233233
// CHECK-NEXT: conforms_to: T P1)
@@ -310,12 +310,12 @@ extension TwoDisjointConformances: P2 where T == String {}
310310
// signature, meaning the stored conditional requirement is T: P1, which isn't
311311
// true in the original type's generic signature.
312312
struct RedundancyOrderDependenceGood<T: P1, U> {}
313-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceGood<T, U>
313+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceGood
314314
// CHECK-NEXT: (normal_conformance type=RedundancyOrderDependenceGood<T, U> protocol=P2
315315
// CHECK-NEXT: same_type: T U)
316316
extension RedundancyOrderDependenceGood: P2 where U: P1, T == U {}
317317
struct RedundancyOrderDependenceBad<T, U: P1> {}
318-
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceBad<T, U>
318+
// CHECK-LABEL: ExtensionDecl line={{.*}} base=RedundancyOrderDependenceBad
319319
// CHECK-NEXT: (normal_conformance type=RedundancyOrderDependenceBad<T, U> protocol=P2
320320
// CHECK-NEXT: conforms_to: T P1
321321
// CHECK-NEXT: same_type: T U)

test/Serialization/extension-of-typealias.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ extension Zahl {
2121

2222
public typealias List<T> = Array<T>
2323

24-
// CHECK-LABEL: extension Array {
24+
// CHECK-LABEL: extension List {
2525
extension List {
2626
// CHECK-NEXT: addedMember()
2727
public func addedMember() {}
2828
} // CHECK-NEXT: {{^}$}}
2929

30-
// CHECK-LABEL: extension Array where Element == Int {
30+
// CHECK-LABEL: extension List where Element == Int {
3131
extension List where Element == Int {
3232
// CHECK-NEXT: addedMemberInt()
3333
public func addedMemberInt() {}

validation-test/Serialization/rdar29694978.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extension MyNonGenericType {}
2222

2323
// CHECK-DAG: typealias MyGenericType<T> = GenericType<T>
2424
typealias MyGenericType<T: NSObject> = GenericType<T>
25-
// CHECK-DAG: extension GenericType where Element : NSObject
25+
// CHECK-DAG: extension MyGenericType where Element : NSObject
2626
extension MyGenericType {}
27-
// CHECK-DAG: extension GenericType where Element == NSObject
27+
// CHECK-DAG: extension MyGenericType where Element == NSObject
2828
extension MyGenericType where Element == NSObject {}

0 commit comments

Comments
 (0)