Skip to content

Commit aac3071

Browse files
committed
[Type Resolution] Emit a tailored diagnostic for the incorrect 'any P?' syntax.
1 parent e790680 commit aac3071

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
@@ -4755,6 +4755,9 @@ ERROR(unchecked_not_existential,none,
47554755
ERROR(any_not_existential,none,
47564756
"'any' has no effect on %select{concrete type|type parameter}0 %1",
47574757
(bool, Type))
4758+
ERROR(incorrect_optional_any,none,
4759+
"optional 'any' type must be written %0",
4760+
(Type))
47584761
ERROR(existential_requires_any,none,
47594762
"use of %select{protocol |}2%0 as a type must be written %1",
47604763
(Type, Type, bool))

lib/Sema/TypeCheckType.cpp

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

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