Skip to content

Commit 7566f98

Browse files
committed
Sema: Diagnose enum inheritance clause containing subclass existential
Also, tidy up the code a bit and stop emitting redundant diagnostics for associated types. Fixes <https://bugs.swift.org/browse/SR-10232>.
1 parent 691802c commit 7566f98

File tree

10 files changed

+59
-98
lines changed

10 files changed

+59
-98
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2268,14 +2268,10 @@ ERROR(duplicate_inheritance,none,
22682268
"duplicate inheritance from %0", (Type))
22692269
WARNING(duplicate_anyobject_class_inheritance,none,
22702270
"redundant inheritance from 'AnyObject' and Swift 3 'class' keyword", ())
2271-
ERROR(objc_protocol_with_superclass,none,
2272-
"protocol %0 is '@objc' and cannot have a superclass constraint", (Identifier))
2271+
ERROR(inheritance_from_protocol_with_superclass,none,
2272+
"inheritance from class-constrained protocol composition type %0", (Type))
22732273
ERROR(multiple_inheritance,none,
22742274
"multiple inheritance from classes %0 and %1", (Type, Type))
2275-
ERROR(non_class_inheritance,none,
2276-
"non-class type %0 cannot inherit from class %1", (Type, Type))
2277-
ERROR(extension_class_inheritance,none,
2278-
"extension of type %0 cannot inherit from class %1", (Type, Type))
22792275
ERROR(inheritance_from_non_protocol_or_class,none,
22802276
"inheritance from non-protocol, non-class type %0", (Type))
22812277
ERROR(inheritance_from_non_protocol,none,

lib/Sema/TypeCheckDecl.cpp

Lines changed: 43 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ static void validateAttributes(TypeChecker &TC, Decl *D);
215215
/// file.
216216
static void checkInheritanceClause(
217217
llvm::PointerUnion<TypeDecl *, ExtensionDecl *> declUnion) {
218-
TypeResolutionOptions options = None;
219218
DeclContext *DC;
220219
MutableArrayRef<TypeLoc> inheritedClause;
221220
ExtensionDecl *ext = nullptr;
@@ -224,7 +223,6 @@ static void checkInheritanceClause(
224223
if ((ext = declUnion.dyn_cast<ExtensionDecl *>())) {
225224
decl = ext;
226225
DC = ext;
227-
options |= TypeResolutionFlags::AllowUnavailableProtocol;
228226

229227
inheritedClause = ext->getInherited();
230228

@@ -243,14 +241,17 @@ static void checkInheritanceClause(
243241
decl = typeDecl;
244242
if (auto nominal = dyn_cast<NominalTypeDecl>(typeDecl)) {
245243
DC = nominal;
246-
options |= TypeResolutionFlags::AllowUnavailableProtocol;
247244
} else {
248245
DC = typeDecl->getDeclContext();
249246
}
250247

251248
inheritedClause = typeDecl->getInherited();
252249
}
253250

251+
bool canHaveSuperclass = (isa<ClassDecl>(decl) ||
252+
(isa<ProtocolDecl>(decl) &&
253+
!cast<ProtocolDecl>(decl)->isObjC()));
254+
254255
ASTContext &ctx = decl->getASTContext();
255256
auto &diags = ctx.Diags;
256257

@@ -259,13 +260,6 @@ static void checkInheritanceClause(
259260
if (ext)
260261
return ext->getSourceRange().End;
261262

262-
if (auto genericTypeDecl = dyn_cast<GenericTypeDecl>(typeDecl)) {
263-
if (auto genericParams = genericTypeDecl->getGenericParams())
264-
return genericParams->getSourceRange().End;
265-
266-
return genericTypeDecl->getNameLoc();
267-
}
268-
269263
return typeDecl->getNameLoc();
270264
};
271265

@@ -316,6 +310,12 @@ static void checkInheritanceClause(
316310
if (!inheritedTy || inheritedTy->hasError())
317311
continue;
318312

313+
// For generic parameters and associated types, the GSB checks constraints;
314+
// however, we still want to fire off the requests to produce diagnostics
315+
// in some circular validation cases.
316+
if (isa<AbstractTypeParamDecl>(decl))
317+
continue;
318+
319319
// Check whether we inherited from 'AnyObject' twice.
320320
// Other redundant-inheritance scenarios are checked below, the
321321
// GenericSignatureBuilder (for protocol inheritance) or the
@@ -351,41 +351,36 @@ static void checkInheritanceClause(
351351
if (inheritedTy->isExistentialType()) {
352352
auto layout = inheritedTy->getExistentialLayout();
353353

354-
// @objc protocols cannot have superclass constraints.
355-
if (layout.explicitSuperclass) {
356-
if (auto *protoDecl = dyn_cast<ProtocolDecl>(decl)) {
357-
if (protoDecl->isObjC()) {
358-
protoDecl->diagnose(diag::objc_protocol_with_superclass,
359-
protoDecl->getName());
360-
continue;
361-
}
362-
}
363-
}
354+
// Inheritance from protocol compositions that do not contain classes
355+
// or AnyObject is always OK.
356+
if (!layout.hasExplicitAnyObject &&
357+
!layout.explicitSuperclass)
358+
continue;
364359

365-
// Protocols, generic parameters and associated types can inherit
366-
// from subclass existentials, which are "exploded" into their
367-
// corresponding requirements.
368-
//
369-
// Extensions, structs and enums can only inherit from protocol
370-
// compositions that do not contain AnyObject or class members.
371-
if (isa<ProtocolDecl>(decl) ||
372-
isa<AbstractTypeParamDecl>(decl) ||
373-
(!layout.hasExplicitAnyObject &&
374-
!layout.explicitSuperclass)) {
360+
// Protocols can inherit from AnyObject.
361+
if (layout.hasExplicitAnyObject &&
362+
isa<ProtocolDecl>(decl))
375363
continue;
376-
}
377364

378-
// Classes can inherit from subclass existentials as long as they
379-
// do not contain an explicit AnyObject member.
380-
if (isa<ClassDecl>(decl) &&
381-
!layout.hasExplicitAnyObject) {
382-
// Superclass inheritance is handled below.
383-
inheritedTy = layout.explicitSuperclass;
384-
if (!inheritedTy)
365+
// Class-constrained protocol compositions are not allowed except in
366+
// special cases.
367+
if (layout.explicitSuperclass) {
368+
if (!canHaveSuperclass) {
369+
decl->diagnose(diag::inheritance_from_protocol_with_superclass,
370+
inheritedTy);
385371
continue;
372+
}
373+
374+
// Classes can inherit from protocol compositions that contain a
375+
// superclass, but not AnyObject.
376+
if (isa<ClassDecl>(decl) &&
377+
!layout.hasExplicitAnyObject) {
378+
// Superclass inheritance is handled below.
379+
inheritedTy = layout.explicitSuperclass;
380+
}
386381
}
387382
}
388-
383+
389384
// If this is an enum inheritance clause, check for a raw type.
390385
if (isa<EnumDecl>(decl)) {
391386
// Check if we already had a raw type.
@@ -445,29 +440,6 @@ static void checkInheritanceClause(
445440
continue;
446441
}
447442

448-
// @objc protocols cannot have superclass constraints.
449-
if (auto *protoDecl = dyn_cast<ProtocolDecl>(decl)) {
450-
if (protoDecl->isObjC()) {
451-
protoDecl->diagnose(diag::objc_protocol_with_superclass,
452-
protoDecl->getName());
453-
continue;
454-
}
455-
}
456-
457-
// If the declaration we're looking at doesn't allow a superclass,
458-
// complain.
459-
if (isa<StructDecl>(decl) || isa<ExtensionDecl>(decl)) {
460-
decl->diagnose(isa<ExtensionDecl>(decl)
461-
? diag::extension_class_inheritance
462-
: diag::non_class_inheritance,
463-
isa<ExtensionDecl>(decl)
464-
? cast<ExtensionDecl>(decl)->getDeclaredInterfaceType()
465-
: cast<TypeDecl>(decl)->getDeclaredInterfaceType(),
466-
inheritedTy)
467-
.highlight(inherited.getSourceRange());
468-
continue;
469-
}
470-
471443
// If this is not the first entry in the inheritance clause, complain.
472444
if (isa<ClassDecl>(decl) && i > 0) {
473445
auto removeRange = getRemovalRange(i);
@@ -480,21 +452,18 @@ static void checkInheritanceClause(
480452
// Fall through to record the superclass.
481453
}
482454

483-
// Record the superclass.
484-
superclassTy = inheritedTy;
485-
superclassRange = inherited.getSourceRange();
486-
continue;
455+
if (canHaveSuperclass) {
456+
// Record the superclass.
457+
superclassTy = inheritedTy;
458+
superclassRange = inherited.getSourceRange();
459+
continue;
460+
}
487461
}
488462

489-
// The GenericSignatureBuilder diagnoses problems with generic type
490-
// parameters.
491-
if (isa<GenericTypeParamDecl>(decl))
492-
continue;
493-
494463
// We can't inherit from a non-class, non-protocol type.
495-
decl->diagnose((isa<StructDecl>(decl) || isa<ExtensionDecl>(decl))
496-
? diag::inheritance_from_non_protocol
497-
: diag::inheritance_from_non_protocol_or_class,
464+
decl->diagnose(canHaveSuperclass
465+
? diag::inheritance_from_non_protocol_or_class
466+
: diag::inheritance_from_non_protocol,
498467
inheritedTy);
499468
// FIXME: Note pointing to the declaration 'inheritedTy' references?
500469
}

test/Constraints/generics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ protocol SR_7984_P {
672672
struct A<T: String> {} // expected-error {{type 'T' constrained to non-protocol, non-class type 'String'}}
673673
struct B<T> where T: String {} // expected-error {{type 'T' constrained to non-protocol, non-class type 'String'}}
674674
protocol C {
675-
associatedtype Foo: String // expected-error {{inheritance from non-protocol, non-class type 'String'}} expected-error {{type 'Self.Foo' constrained to non-protocol, non-class type 'String'}}
675+
associatedtype Foo: String // expected-error {{type 'Self.Foo' constrained to non-protocol, non-class type 'String'}}
676676
}
677677
protocol D {
678678
associatedtype Foo where Foo: String // expected-error {{type 'Self.Foo' constrained to non-protocol, non-class type 'String'}}

test/Generics/superclass_constraint.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,8 @@ func takeP5<T: P5>(_ t: T) {
105105

106106
protocol P7 {
107107
associatedtype Assoc: A, Other
108-
// FIXME: expected-error@-1{{multiple inheritance from classes 'A' and 'Other'}}
109-
// expected-note@-2{{superclass constraint 'Self.Assoc' : 'A' written here}}
110-
// expected-error@-3{{'Self.Assoc' cannot be a subclass of both 'Other' and 'A'}}
108+
// expected-note@-1{{superclass constraint 'Self.Assoc' : 'A' written here}}
109+
// expected-error@-2{{'Self.Assoc' cannot be a subclass of both 'Other' and 'A'}}
111110
}
112111

113112
// CHECK: superclassConformance4

test/NameBinding/scope_map_lookup.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ protocol P1 {
2525
// Protocols involving associated types.
2626
protocol AProtocol {
2727
associatedtype e : e
28-
// expected-error@-1 {{inheritance from non-protocol, non-class type 'Self.e'}}
29-
// expected-error@-2 {{type 'Self.e' constrained to non-protocol, non-class type 'Self.e'}}
28+
// expected-error@-1 {{type 'Self.e' constrained to non-protocol, non-class type 'Self.e'}}
3029
}
3130

3231
// Extensions.

test/Sema/circular_decl_checking.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,9 @@ func TopLevelGenericFunc2<T : TopLevelGenericFunc2>(x: T) -> T { return x} // ex
4343
var TopLevelVar: TopLevelVar? { return nil } // expected-error {{use of undeclared type 'TopLevelVar'}}
4444

4545

46-
// FIXME: The first error is redundant and isn't correct in what it states.
4746
protocol AProtocol {
4847
associatedtype e : e
4948
// expected-error@-1 {{type 'Self.e' constrained to non-protocol, non-class type 'Self.e'}}
50-
// expected-error@-2 {{inheritance from non-protocol, non-class type 'Self.e'}}
5149
}
5250

5351

test/decl/enum/enumtest.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,3 +436,9 @@ let _: NestedBazEnumGeneric.Baz<Int> = .none // ok
436436
let _: NestedBazEnumGeneric.Baz<Int> = .one // ok
437437
let _: NestedBazEnumGeneric.Baz<Int>? = .one // ok
438438
let _: NestedBazEnumGeneric.Baz<Int>?? = .one // ok
439+
440+
class C {}
441+
protocol P {}
442+
443+
enum E : C & P {}
444+
// expected-error@-1 {{inheritance from class-constrained protocol composition type 'C & P'}}

test/decl/inherit/inherit.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ class D3 : Any, A { } // expected-error{{superclass 'A' must appear first in the
3030
class D4 : P & P1, A { } // expected-error{{superclass 'A' must appear first in the inheritance clause}}{{18-21=}}{{12-12=A, }}
3131

3232
// Struct inheriting a class
33-
struct S : A { } // expected-error{{non-class type 'S' cannot inherit from class 'A'}}
33+
struct S : A { } // expected-error{{inheritance from non-protocol type 'A'}}
3434

3535
// Protocol inheriting a class
3636
protocol Q : A { }
3737

3838
// Extension inheriting a class
39-
extension C : A { } // expected-error{{extension of type 'C' cannot inherit from class 'A'}}
39+
extension C : A { } // expected-error{{inheritance from non-protocol type 'A'}}
4040

4141
// Keywords in inheritance clauses
4242
struct S2 : struct { } // expected-error{{expected type}}

test/decl/protocol/protocol_with_superclass_objc.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
class Base {}
44

55
@objc protocol Protocol1 : Base {}
6-
// expected-error@-1 {{protocol 'Protocol1' is '@objc' and cannot have a superclass constraint}}
6+
// expected-error@-1 {{inheritance from non-protocol type 'Base'}}
77

88
@objc protocol OtherProtocol {}
99

1010
typealias Composition = OtherProtocol & Base
1111

1212
@objc protocol Protocol2 : Composition {}
13-
// expected-error@-1 {{protocol 'Protocol2' is '@objc' and cannot have a superclass constraint}}
13+
// expected-error@-1 {{inheritance from class-constrained protocol composition type 'Composition' (aka 'Base & OtherProtocol')}}

test/decl/protocol/req/unsatisfiable.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,9 @@ protocol Base {
3737
associatedtype Assoc
3838
}
3939

40-
// FIXME: The first error is redundant and isn't correct in what it states.
41-
// FIXME: This used to /not/ error in Swift 3. It didn't impose any statically-
42-
// enforced requirements, but the compiler crashed if you used anything but the
43-
// same type.
4440
protocol Sub1: Base {
4541
associatedtype SubAssoc: Assoc
4642
// expected-error@-1 {{type 'Self.SubAssoc' constrained to non-protocol, non-class type 'Self.Assoc'}}
47-
// expected-error@-2 {{inheritance from non-protocol, non-class type 'Self.Assoc'}}
4843
}
4944

5045
// FIXME: This error is incorrect in what it states.
@@ -58,7 +53,6 @@ struct S {}
5853
protocol P4 {
5954
associatedtype X : S
6055
// expected-error@-1 {{type 'Self.X' constrained to non-protocol, non-class type 'S'}}
61-
// expected-error@-2 {{inheritance from non-protocol, non-class type 'S'}}
6256
}
6357

6458
protocol P5 {

0 commit comments

Comments
 (0)