Skip to content

Commit 250fbf2

Browse files
committed
Sema: Reject 'any P' in inheritance clauses
1 parent 792d5e8 commit 250fbf2

File tree

5 files changed

+54
-26
lines changed

5 files changed

+54
-26
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2784,9 +2784,11 @@ WARNING(anyobject_class_inheritance_deprecated,Deprecation,
27842784
ERROR(multiple_inheritance,none,
27852785
"multiple inheritance from classes %0 and %1", (Type, Type))
27862786
ERROR(inheritance_from_non_protocol_or_class,none,
2787-
"inheritance from non-protocol, non-class type %0", (Type))
2787+
"inheritance from non-protocol, non-class type '%0'", (StringRef))
27882788
ERROR(inheritance_from_non_protocol,none,
2789-
"inheritance from non-protocol type %0", (Type))
2789+
"inheritance from non-protocol type '%0'", (StringRef))
2790+
ERROR(inheritance_from_anyobject,none,
2791+
"only protocols can inherit from 'AnyObject'", ())
27902792
ERROR(inheritance_from_parameterized_protocol,none,
27912793
"cannot inherit from protocol type with generic argument %0", (Type))
27922794
ERROR(superclass_not_first,none,

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,15 @@ static void checkInheritanceClause(
212212
inheritedAnyObject = { i, inherited.getSourceRange() };
213213
}
214214

215-
if (inheritedTy->isExistentialType()) {
215+
if (inheritedTy->is<ParameterizedProtocolType>()) {
216+
if (!isa<ProtocolDecl>(decl)) {
217+
decl->diagnose(diag::inheritance_from_parameterized_protocol,
218+
inheritedTy);
219+
}
220+
continue;
221+
}
222+
223+
if (inheritedTy->isConstraintType()) {
216224
auto layout = inheritedTy->getExistentialLayout();
217225

218226
// Subclass existentials are not allowed except on classes and
@@ -227,10 +235,7 @@ static void checkInheritanceClause(
227235
// AnyObject is not allowed except on protocols.
228236
if (layout.hasExplicitAnyObject &&
229237
!isa<ProtocolDecl>(decl)) {
230-
decl->diagnose(canHaveSuperclass
231-
? diag::inheritance_from_non_protocol_or_class
232-
: diag::inheritance_from_non_protocol,
233-
inheritedTy);
238+
decl->diagnose(diag::inheritance_from_anyobject);
234239
continue;
235240
}
236241

@@ -249,14 +254,6 @@ static void checkInheritanceClause(
249254
inheritedTy = layout.explicitSuperclass;
250255
}
251256

252-
if (inheritedTy->is<ParameterizedProtocolType>()) {
253-
if (!isa<ProtocolDecl>(decl)) {
254-
decl->diagnose(diag::inheritance_from_parameterized_protocol,
255-
inheritedTy);
256-
}
257-
continue;
258-
}
259-
260257
// If this is an enum inheritance clause, check for a raw type.
261258
if (isa<EnumDecl>(decl)) {
262259
// Check if we already had a raw type.
@@ -338,11 +335,19 @@ static void checkInheritanceClause(
338335
}
339336
}
340337

338+
// FIXME: The inherited type is printed directly here because
339+
// the current default is to not print `any` for existential
340+
// types, but this error message is super confusing without `any`
341+
// if the user wrote it explicitly.
342+
PrintOptions options;
343+
options.PrintExplicitAny = true;
344+
auto inheritedTyString = inheritedTy.getString(options);
345+
341346
// We can't inherit from a non-class, non-protocol type.
342347
decl->diagnose(canHaveSuperclass
343348
? diag::inheritance_from_non_protocol_or_class
344349
: diag::inheritance_from_non_protocol,
345-
inheritedTy);
350+
inheritedTyString);
346351
// FIXME: Note pointing to the declaration 'inheritedTy' references?
347352
}
348353
}

lib/Sema/TypeCheckRequestFunctions.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,8 @@ Type EnumRawTypeRequest::evaluate(Evaluator &evaluator,
142142
auto &inheritedType = *inheritedTypeResult;
143143
if (!inheritedType) continue;
144144

145-
// Skip existential types.
146-
if (inheritedType->isExistentialType()) continue;
145+
// Skip protocol conformances.
146+
if (inheritedType->isConstraintType()) continue;
147147

148148
// We found a raw type; return it.
149149
return inheritedType;

test/decl/protocol/conforms/placement.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,20 +105,20 @@ extension ExplicitSub1 : P1 { } // expected-error{{redundant conformance of 'Exp
105105
// ---------------------------------------------------------------------------
106106
// Suppression of synthesized conformances
107107
// ---------------------------------------------------------------------------
108-
class SynthesizedClass1 : AnyObject { } // expected-error{{inheritance from non-protocol, non-class type 'AnyObject'}}
108+
class SynthesizedClass1 : AnyObject { } // expected-error{{only protocols can inherit from 'AnyObject'}}
109109

110110
class SynthesizedClass2 { }
111-
extension SynthesizedClass2 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
111+
extension SynthesizedClass2 : AnyObject { } // expected-error{{only protocols can inherit from 'AnyObject'}}
112112

113113
class SynthesizedClass3 : AnyObjectRefinement { }
114114

115115
class SynthesizedClass4 { }
116116
extension SynthesizedClass4 : AnyObjectRefinement { }
117117

118-
class SynthesizedSubClass1 : SynthesizedClass1, AnyObject { } // expected-error{{inheritance from non-protocol, non-class type 'AnyObject'}}
118+
class SynthesizedSubClass1 : SynthesizedClass1, AnyObject { } // expected-error{{only protocols can inherit from 'AnyObject'}}
119119

120120
class SynthesizedSubClass2 : SynthesizedClass2 { }
121-
extension SynthesizedSubClass2 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
121+
extension SynthesizedSubClass2 : AnyObject { } // expected-error{{only protocols can inherit from 'AnyObject'}}
122122

123123
class SynthesizedSubClass3 : SynthesizedClass1, AnyObjectRefinement { }
124124

@@ -169,12 +169,12 @@ extension MFExplicitSub1 : P1 { } // expected-error{{redundant conformance of 'M
169169
// ---------------------------------------------------------------------------
170170
class MFSynthesizedClass1 { }
171171

172-
extension MFSynthesizedClass2 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
172+
extension MFSynthesizedClass2 : AnyObject { } // expected-error{{only protocols can inherit from 'AnyObject'}}
173173

174174
class MFSynthesizedClass4 { }
175175
extension MFSynthesizedClass4 : AnyObjectRefinement { }
176176

177-
extension MFSynthesizedSubClass2 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
177+
extension MFSynthesizedSubClass2 : AnyObject { } // expected-error{{only protocols can inherit from 'AnyObject'}}
178178

179179
extension MFSynthesizedSubClass3 : AnyObjectRefinement { }
180180

@@ -198,7 +198,7 @@ extension MMSuper1 : MMP1 { } // expected-warning{{conformance of 'MMSuper1' to
198198
extension MMSuper1 : MMP2a { } // expected-warning{{conformance of 'MMSuper1' to protocol 'MMP2a' was already stated in the type's module 'placement_module_A'}}
199199
extension MMSuper1 : MMP3b { } // okay
200200

201-
extension MMSub1 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
201+
extension MMSub1 : AnyObject { } // expected-error{{only protocols can inherit from 'AnyObject'}}
202202

203203
extension MMSub2 : MMP1 { } // expected-warning{{conformance of 'MMSub2' to protocol 'MMP1' was already stated in the type's module 'placement_module_A'}}
204204
extension MMSub2 : MMP2a { } // expected-warning{{conformance of 'MMSub2' to protocol 'MMP2a' was already stated in the type's module 'placement_module_A'}}
@@ -209,7 +209,7 @@ extension MMSub2 : MMAnyObjectRefinement { } // okay
209209
extension MMSub3 : MMP1 { } // expected-warning{{conformance of 'MMSub3' to protocol 'MMP1' was already stated in the type's module 'placement_module_A'}}
210210
extension MMSub3 : MMP2a { } // expected-warning{{conformance of 'MMSub3' to protocol 'MMP2a' was already stated in the type's module 'placement_module_A'}}
211211
extension MMSub3 : MMP3b { } // okay
212-
extension MMSub3 : AnyObject { } // expected-error{{inheritance from non-protocol type 'AnyObject'}}
212+
extension MMSub3 : AnyObject { } // expected-error{{only protocols can inherit from 'AnyObject'}}
213213

214214
extension MMSub4 : MMP1 { } // expected-warning{{conformance of 'MMSub4' to protocol 'MMP1' was already stated in the type's module 'placement_module_B'}}
215215
extension MMSub4 : MMP2a { } // expected-warning{{conformance of 'MMSub4' to protocol 'MMP2a' was already stated in the type's module 'placement_module_B'}}

test/type/explicit_existential.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,3 +257,24 @@ func testConstraintAlias(x: Constraint) {} // expected-warning{{'Constraint' (ak
257257

258258
typealias Existential = any Input
259259
func testExistentialAlias(x: Existential, y: any Constraint) {}
260+
261+
// Reject explicit existential types in inheritance clauses
262+
protocol Empty {}
263+
264+
struct S : any Empty {} // expected-error {{inheritance from non-protocol type 'any Empty'}}
265+
class C : any Empty {} // expected-error {{inheritance from non-protocol, non-class type 'any Empty'}}
266+
267+
// FIXME: Diagnostics are not great in the enum case because we confuse this with a raw type
268+
269+
enum E : any Empty { // expected-error {{raw type 'Empty' is not expressible by a string, integer, or floating-point literal}}
270+
// expected-error@-1 {{'E' declares raw type 'Empty', but does not conform to RawRepresentable and conformance could not be synthesized}}
271+
// expected-error@-2 {{RawRepresentable conformance cannot be synthesized because raw type 'Empty' is not Equatable}}
272+
case hack
273+
}
274+
275+
enum EE : Equatable, any Empty { // expected-error {{raw type 'Empty' is not expressible by a string, integer, or floating-point literal}}
276+
// expected-error@-1 {{'EE' declares raw type 'Empty', but does not conform to RawRepresentable and conformance could not be synthesized}}
277+
// expected-error@-2 {{RawRepresentable conformance cannot be synthesized because raw type 'Empty' is not Equatable}}
278+
// expected-error@-3 {{raw type 'Empty' must appear first in the enum inheritance clause}}
279+
case hack
280+
}

0 commit comments

Comments
 (0)