Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -4709,6 +4709,9 @@ ERROR(unchecked_not_inheritance_clause,none,
ERROR(unchecked_not_existential,none,
"'unchecked' attribute cannot apply to non-protocol type %0", (Type))

ERROR(redundant_any_in_existential,none,
"redundant 'any' has no effect on existential type %0",
(Type))
ERROR(any_not_existential,none,
"'any' has no effect on %select{concrete type|type parameter}0 %1",
(bool, Type))
Expand Down
18 changes: 11 additions & 7 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3987,7 +3987,7 @@ TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr,
if (constraintType->hasError())
return ErrorType::get(getASTContext());

if (!constraintType->isExistentialType()) {
if (!constraintType->isConstraintType()) {
// Emit a tailored diagnostic for the incorrect optional
// syntax 'any P?' with a fix-it to add parenthesis.
auto wrapped = constraintType->getOptionalObjectType();
Expand All @@ -4001,14 +4001,18 @@ TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr,
.fixItReplace(repr->getSourceRange(), fix);
return constraintType;
}

// Diagnose redundant `any` on an already existential type e.g. any (any P)
// with a fix-it to remove first any.
if (constraintType->is<ExistentialType>()) {
diagnose(repr->getLoc(), diag::redundant_any_in_existential, constraintType)
.fixItRemove(repr->getAnyLoc());
return constraintType;
}

auto anyStart = repr->getAnyLoc();
auto anyEnd = Lexer::getLocForEndOfToken(getASTContext().SourceMgr,
anyStart);
diagnose(repr->getLoc(), diag::any_not_existential,
constraintType->isTypeParameter(),
constraintType)
.fixItRemove({anyStart, anyEnd});
constraintType->isTypeParameter(), constraintType)
.fixItRemove(repr->getAnyLoc());
return constraintType;
}

Expand Down
12 changes: 12 additions & 0 deletions test/type/explicit_existential.swift
Original file line number Diff line number Diff line change
Expand Up @@ -329,3 +329,15 @@ func testEnumAssociatedValue() {
case c3((P) -> Void)
}
}

// https://github.com/apple/swift/issues/58920
typealias Iterator = any IteratorProtocol
var example: any Iterator = 5 // expected-error{{redundant 'any' has no effect on existential type 'Iterator' (aka 'IteratorProtocol')}} {{14-18=}}
// expected-error@-1{{value of type 'Int' does not conform to specified type 'IteratorProtocol'}}
var example1: any (any IteratorProtocol) = 5 // expected-error{{redundant 'any' has no effect on existential type 'any IteratorProtocol'}} {{15-19=}}
// expected-error@-1{{value of type 'Int' does not conform to specified type 'IteratorProtocol'}}

protocol PP {}
struct A : PP {}
let _: any PP = A() // Ok
let _: any (any PP) = A() // expected-error{{redundant 'any' has no effect on existential type 'any PP'}} {{8-12=}}