Skip to content

Commit e5e9827

Browse files
Merge pull request #60680 from cbjeukendrup/diag_unsupported_existential_extension
Improve diagnostics when trying to extend existential type
2 parents f2c8a70 + d47bba6 commit e5e9827

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
@@ -2035,10 +2035,12 @@ NOTE(objc_generic_extension_using_type_parameter_here,none,
20352035
"generic parameter used here", ())
20362036
NOTE(objc_generic_extension_using_type_parameter_try_objc,none,
20372037
"add '@objc' to allow uses of 'self' within the function body", ())
2038+
ERROR(unsupported_existential_extension,none,
2039+
"extension of existential type %0 is not supported", (Type))
20382040
ERROR(invalid_nominal_extension,none,
20392041
"extension of type %0 must be declared as an extension of %1",
20402042
(Type, Type))
2041-
NOTE(invalid_nominal_extension_rewrite,none,
2043+
NOTE(invalid_extension_rewrite,none,
20422044
"did you mean to extend %0 instead?", (Type))
20432045
ERROR(synthesized_nominal_extension,none,
20442046
"cannot extend synthesized type %0", (Type))

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3189,21 +3189,31 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
31893189
const bool wasAlreadyInvalid = ED->isInvalid();
31903190
ED->setInvalid();
31913191
if (!extType->hasError() && extType->getAnyNominal()) {
3192+
auto canExtType = extType->getCanonicalType();
3193+
if (auto existential = canExtType->getAs<ExistentialType>()) {
3194+
ED->diagnose(diag::unsupported_existential_extension, extType)
3195+
.highlight(ED->getExtendedTypeRepr()->getSourceRange());
3196+
ED->diagnose(diag::invalid_extension_rewrite,
3197+
existential->getConstraintType())
3198+
.fixItReplace(ED->getExtendedTypeRepr()->getSourceRange(),
3199+
existential->getConstraintType()->getString());
3200+
return;
3201+
}
3202+
31923203
// If we've got here, then we have some kind of extension of a prima
3193-
// fascie non-nominal type. This can come up when we're projecting
3204+
// facie non-nominal type. This can come up when we're projecting
31943205
// typealiases out of bound generic types.
31953206
//
31963207
// struct Array<T> { typealias Indices = Range<Int> }
31973208
// extension Array.Indices.Bound {}
31983209
//
31993210
// Offer to rewrite it to the underlying nominal type.
3200-
auto canExtType = extType->getCanonicalType();
32013211
if (canExtType.getPointer() != extType.getPointer()) {
32023212
ED->diagnose(diag::invalid_nominal_extension, extType, canExtType)
3203-
.highlight(ED->getExtendedTypeRepr()->getSourceRange());
3204-
ED->diagnose(diag::invalid_nominal_extension_rewrite, canExtType)
3205-
.fixItReplace(ED->getExtendedTypeRepr()->getSourceRange(),
3206-
canExtType->getString());
3213+
.highlight(ED->getExtendedTypeRepr()->getSourceRange());
3214+
ED->diagnose(diag::invalid_extension_rewrite, canExtType)
3215+
.fixItReplace(ED->getExtendedTypeRepr()->getSourceRange(),
3216+
canExtType->getString());
32073217
return;
32083218
}
32093219
}

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
// https://github.com/apple/swift/issues/52866
@@ -367,3 +367,25 @@ protocol Rdar66943328 {
367367
}
368368
extension Rdar66943328 where Assoc == Int // expected-error {{expected '{' in extension}}
369369
#endif
370+
371+
// Reject extension of existential type
372+
373+
protocol P4 {}
374+
375+
extension any P4 {
376+
// expected-error@-1 {{extension of existential type 'any P4' is not supported}}
377+
// expected-note@-2 {{did you mean to extend 'P4' instead?}} {{11-17=P4}}
378+
}
379+
380+
typealias A4 = P4
381+
382+
extension any A4 {
383+
// expected-error@-1 {{extension of existential type 'any A4' (aka 'any P4') is not supported}}
384+
// expected-note@-2 {{did you mean to extend 'P4' instead?}} {{11-17=P4}}
385+
}
386+
387+
typealias B4 = any P4
388+
extension B4 {
389+
// expected-error@-1 {{extension of existential type 'B4' (aka 'any P4') is not supported}}
390+
// expected-note@-2 {{did you mean to extend 'P4' instead?}} {{11-13=P4}}
391+
}

0 commit comments

Comments
 (0)