Skip to content

Commit d47bba6

Browse files
committed
Improve diagnostics when attempting to extend existential type
1 parent f7c9cec commit d47bba6

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
@@ -1972,10 +1972,12 @@ NOTE(objc_generic_extension_using_type_parameter_here,none,
19721972
"generic parameter used here", ())
19731973
NOTE(objc_generic_extension_using_type_parameter_try_objc,none,
19741974
"add '@objc' to allow uses of 'self' within the function body", ())
1975+
ERROR(unsupported_existential_extension,none,
1976+
"extension of existential type %0 is not supported", (Type))
19751977
ERROR(invalid_nominal_extension,none,
19761978
"extension of type %0 must be declared as an extension of %1",
19771979
(Type, Type))
1978-
NOTE(invalid_nominal_extension_rewrite,none,
1980+
NOTE(invalid_extension_rewrite,none,
19791981
"did you mean to extend %0 instead?", (Type))
19801982
ERROR(synthesized_nominal_extension,none,
19811983
"cannot extend synthesized type %0", (Type))

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3084,21 +3084,31 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
30843084
const bool wasAlreadyInvalid = ED->isInvalid();
30853085
ED->setInvalid();
30863086
if (!extType->hasError() && extType->getAnyNominal()) {
3087+
auto canExtType = extType->getCanonicalType();
3088+
if (auto existential = canExtType->getAs<ExistentialType>()) {
3089+
ED->diagnose(diag::unsupported_existential_extension, extType)
3090+
.highlight(ED->getExtendedTypeRepr()->getSourceRange());
3091+
ED->diagnose(diag::invalid_extension_rewrite,
3092+
existential->getConstraintType())
3093+
.fixItReplace(ED->getExtendedTypeRepr()->getSourceRange(),
3094+
existential->getConstraintType()->getString());
3095+
return;
3096+
}
3097+
30873098
// If we've got here, then we have some kind of extension of a prima
3088-
// fascie non-nominal type. This can come up when we're projecting
3099+
// facie non-nominal type. This can come up when we're projecting
30893100
// typealiases out of bound generic types.
30903101
//
30913102
// struct Array<T> { typealias Indices = Range<Int> }
30923103
// extension Array.Indices.Bound {}
30933104
//
30943105
// Offer to rewrite it to the underlying nominal type.
3095-
auto canExtType = extType->getCanonicalType();
30963106
if (canExtType.getPointer() != extType.getPointer()) {
30973107
ED->diagnose(diag::invalid_nominal_extension, extType, canExtType)
3098-
.highlight(ED->getExtendedTypeRepr()->getSourceRange());
3099-
ED->diagnose(diag::invalid_nominal_extension_rewrite, canExtType)
3100-
.fixItReplace(ED->getExtendedTypeRepr()->getSourceRange(),
3101-
canExtType->getString());
3108+
.highlight(ED->getExtendedTypeRepr()->getSourceRange());
3109+
ED->diagnose(diag::invalid_extension_rewrite, canExtType)
3110+
.fixItReplace(ED->getExtendedTypeRepr()->getSourceRange(),
3111+
canExtType->getString());
31023112
return;
31033113
}
31043114
}

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)