Skip to content

Commit c70514a

Browse files
authored
Merge pull request #42277 from hborla/optional-any-fixit
[Type Resolution] Emit a tailored diagnostic for the incorrect `any P?` syntax.
2 parents d51401c + aac3071 commit c70514a

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4746,6 +4746,9 @@ ERROR(unchecked_not_existential,none,
47464746
ERROR(any_not_existential,none,
47474747
"'any' has no effect on %select{concrete type|type parameter}0 %1",
47484748
(bool, Type))
4749+
ERROR(incorrect_optional_any,none,
4750+
"optional 'any' type must be written %0",
4751+
(Type))
47494752
ERROR(existential_requires_any,none,
47504753
"use of %select{protocol |}2%0 as a type must be written %1",
47514754
(Type, Type, bool))

lib/Sema/TypeCheckType.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3955,9 +3955,24 @@ TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr,
39553955
if (constraintType->hasError())
39563956
return ErrorType::get(getASTContext());
39573957

3958-
auto anyStart = repr->getAnyLoc();
3959-
auto anyEnd = Lexer::getLocForEndOfToken(getASTContext().SourceMgr, anyStart);
39603958
if (!constraintType->isExistentialType()) {
3959+
// Emit a tailored diagnostic for the incorrect optional
3960+
// syntax 'any P?' with a fix-it to add parenthesis.
3961+
auto wrapped = constraintType->getOptionalObjectType();
3962+
if (wrapped && (wrapped->is<ExistentialType>() ||
3963+
wrapped->is<ExistentialMetatypeType>())) {
3964+
std::string fix;
3965+
llvm::raw_string_ostream OS(fix);
3966+
constraintType->print(OS, PrintOptions::forDiagnosticArguments());
3967+
diagnose(repr->getLoc(), diag::incorrect_optional_any,
3968+
constraintType)
3969+
.fixItReplace(repr->getSourceRange(), fix);
3970+
return constraintType;
3971+
}
3972+
3973+
auto anyStart = repr->getAnyLoc();
3974+
auto anyEnd = Lexer::getLocForEndOfToken(getASTContext().SourceMgr,
3975+
anyStart);
39613976
diagnose(repr->getLoc(), diag::any_not_existential,
39623977
constraintType->isTypeParameter(),
39633978
constraintType)

test/type/explicit_existential.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,4 +308,9 @@ func testAnyFixIt() {
308308
let _: HasAssoc.Type? = ConformingType.self
309309
// expected-warning@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-18=(any HasAssoc)}}
310310
let _: HasAssoc.Protocol? = (any HasAssoc).self
311+
312+
// expected-error@+1 {{optional 'any' type must be written '(any HasAssoc)?'}}{{10-23=(any HasAssoc)?}}
313+
let _: any HasAssoc? = nil
314+
// expected-error@+1 {{optional 'any' type must be written '(any HasAssoc.Type)?'}}{{10-28=(any HasAssoc.Type)?}}
315+
let _: any HasAssoc.Type? = nil
311316
}

0 commit comments

Comments
 (0)