Skip to content

Commit 0ca8393

Browse files
committed
Improve diagnostics when attempting to extend existential type
1 parent 34d9624 commit 0ca8393

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1933,10 +1933,12 @@ NOTE(objc_generic_extension_using_type_parameter_here,none,
19331933
"generic parameter used here", ())
19341934
NOTE(objc_generic_extension_using_type_parameter_try_objc,none,
19351935
"add '@objc' to allow uses of 'self' within the function body", ())
1936+
ERROR(unsupported_existential_extension,none,
1937+
"extension of existential type %0 is not supported", (Type))
19361938
ERROR(invalid_nominal_extension,none,
19371939
"extension of type %0 must be declared as an extension of %1",
19381940
(Type, Type))
1939-
NOTE(invalid_nominal_extension_rewrite,none,
1941+
NOTE(invalid_extension_rewrite,none,
19401942
"did you mean to extend %0 instead?", (Type))
19411943
ERROR(synthesized_nominal_extension,none,
19421944
"cannot extend synthesized type %0", (Type))

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3042,21 +3042,31 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
30423042
const bool wasAlreadyInvalid = ED->isInvalid();
30433043
ED->setInvalid();
30443044
if (!extType->hasError() && extType->getAnyNominal()) {
3045+
auto canExtType = extType->getCanonicalType();
3046+
if (auto existential = canExtType->getAs<ExistentialType>()) {
3047+
ED->diagnose(diag::unsupported_existential_extension, extType)
3048+
.highlight(ED->getExtendedTypeRepr()->getSourceRange());
3049+
ED->diagnose(diag::invalid_extension_rewrite,
3050+
existential->getConstraintType())
3051+
.fixItReplace(ED->getExtendedTypeRepr()->getSourceRange(),
3052+
canExtType->getString());
3053+
return;
3054+
}
3055+
30453056
// If we've got here, then we have some kind of extension of a prima
3046-
// fascie non-nominal type. This can come up when we're projecting
3057+
// facie non-nominal type. This can come up when we're projecting
30473058
// typealiases out of bound generic types.
30483059
//
30493060
// struct Array<T> { typealias Indices = Range<Int> }
30503061
// extension Array.Indices.Bound {}
30513062
//
30523063
// Offer to rewrite it to the underlying nominal type.
3053-
auto canExtType = extType->getCanonicalType();
30543064
if (canExtType.getPointer() != extType.getPointer()) {
30553065
ED->diagnose(diag::invalid_nominal_extension, extType, canExtType)
3056-
.highlight(ED->getExtendedTypeRepr()->getSourceRange());
3057-
ED->diagnose(diag::invalid_nominal_extension_rewrite, canExtType)
3058-
.fixItReplace(ED->getExtendedTypeRepr()->getSourceRange(),
3059-
canExtType->getString());
3066+
.highlight(ED->getExtendedTypeRepr()->getSourceRange());
3067+
ED->diagnose(diag::invalid_extension_rewrite, canExtType)
3068+
.fixItReplace(ED->getExtendedTypeRepr()->getSourceRange(),
3069+
canExtType->getString());
30603070
return;
30613071
}
30623072
}

test/decl/ext/extensions.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ extension Tree.LimbContent.Contents {
349349

350350
extension Tree.BoughPayload.Contents {
351351
// expected-error@-1 {{extension of type 'Tree.BoughPayload.Contents' (aka 'Nest<Int>') must be declared as an extension of 'Nest<Int>'}}
352-
// expected-note@-2 {{did you mean to extend 'Nest<Int>' instead?}}
352+
// expected-note@-2 {{did you mean to extend 'Nest<Int>' instead?}} {{11-37=Nest<Int>}}
353353
}
354354

355355
// SR-10466 Check 'where' clause when referencing type defined inside extension
@@ -366,3 +366,25 @@ protocol Rdar66943328 {
366366
}
367367
extension Rdar66943328 where Assoc == Int // expected-error {{expected '{' in extension}}
368368
#endif
369+
370+
// Reject extension of existential type
371+
372+
protocol P4 {}
373+
374+
extension any P4 {
375+
// expected-error@-1 {{extension of existential type 'any P4' is not supported}}
376+
// expected-note@-2 {{did you mean to extend 'P4' instead?}}
377+
}
378+
379+
typealias A4 = P4
380+
381+
extension any A4 {
382+
// expected-error@-1 {{extension of existential type 'any A4' (aka 'any P4') is not supported}}
383+
// expected-note@-2 {{did you mean to extend 'P4' instead?}} {{11-17=P4}}
384+
}
385+
386+
typealias B4 = any P4
387+
extension B4 {
388+
// expected-error@-1 {{extension of existential type 'B4' (aka 'any P4') is not supported}}
389+
// expected-note@-2 {{did you mean to extend 'P4' instead?}} {{11-13=P4}}
390+
}

0 commit comments

Comments
 (0)