Skip to content

Commit d88507b

Browse files
committed
TypeCheckType: Do not error about missing existential any until Swift 7
1 parent 4531c1d commit d88507b

File tree

11 files changed

+150
-168
lines changed

11 files changed

+150
-168
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 26 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -904,11 +904,15 @@ static Type applyGenericArguments(Type type,
904904
auto parameterized =
905905
ParameterizedProtocolType::get(ctx, protoType, argTys);
906906

907+
// FIXME: Can this not be done in ExistentialTypeSyntaxChecker?
907908
if (resolution.getOptions().isConstraintImplicitExistential() &&
908909
!ctx.LangOpts.hasFeature(Feature::ImplicitSome)) {
909-
diags.diagnose(loc, diag::existential_requires_any, parameterized,
910-
ExistentialType::get(parameterized),
911-
/*isAlias=*/isa<TypeAliasType>(type.getPointer()));
910+
diags
911+
.diagnose(loc, diag::existential_requires_any, parameterized,
912+
ExistentialType::get(parameterized),
913+
/*isAlias=*/isa<TypeAliasType>(type.getPointer()))
914+
.warnUntilSwiftVersion(7);
915+
912916
return ErrorType::get(ctx);
913917
}
914918

@@ -6159,16 +6163,13 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
61596163
ASTContext &Ctx;
61606164
const bool checkStatements;
61616165
bool hitTopStmt;
6162-
const bool downgradeErrorsToWarnings;
61636166

61646167
unsigned exprCount = 0;
61656168
llvm::SmallVector<TypeRepr *, 4> reprStack;
61666169

61676170
public:
6168-
ExistentialTypeSyntaxChecker(ASTContext &ctx, bool checkStatements,
6169-
bool downgradeErrorsToWarnings = false)
6170-
: Ctx(ctx), checkStatements(checkStatements), hitTopStmt(false),
6171-
downgradeErrorsToWarnings(downgradeErrorsToWarnings) {}
6171+
ExistentialTypeSyntaxChecker(ASTContext &ctx, bool checkStatements)
6172+
: Ctx(ctx), checkStatements(checkStatements), hitTopStmt(false) {}
61726173

61736174
MacroWalking getMacroWalkingBehavior() const override {
61746175
return MacroWalking::ArgumentsAndExpansion;
@@ -6366,42 +6367,39 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
63666367
/// \param constraintTy The constraint type that is missing the keyword.
63676368
/// \param isInverted Whether the constraint type is an object of an `~`
63686369
/// inversion.
6369-
static DiagnosticBehavior getDiagnosticBehaviorForMissingAnyOrSomeKeyword(
6370-
Type constraintTy, bool isInverted, ASTContext &ctx) {
6370+
static bool shouldDiagnoseMissingAnyOrSomeKeyword(Type constraintTy,
6371+
bool isInverted,
6372+
ASTContext &ctx) {
63716373
// `Any` and `AnyObject` are always exempt from `any` syntax.
63726374
if (constraintTy->isAny() || constraintTy->isAnyObject()) {
6373-
return DiagnosticBehavior::Ignore;
6375+
return false;
63746376
}
63756377

6376-
// If the type is inverted, a missing `any` or `some` is an error.
6378+
// If the type is inverted, a missing `any` or `some` is always diagnosed.
63776379
if (isInverted) {
6378-
return DiagnosticBehavior::Error;
6380+
return true;
63796381
}
63806382

63816383
// If one of the protocols is inverted, a missing `any` or `some` is
6382-
// an error.
6384+
// always diagnosed.
63836385
if (auto *PCT = constraintTy->getAs<ProtocolCompositionType>()) {
63846386
if (!PCT->getInverses().empty()) {
6385-
return DiagnosticBehavior::Error;
6387+
return true;
63866388
}
63876389
}
63886390

63896391
// If one of the protocols has "Self or associated type" requirements,
6390-
// a missing `any` or `some` is an error.
6392+
// a missing `any` or `some` is always diagnosed.
63916393
auto layout = constraintTy->getExistentialLayout();
63926394
for (auto *protoDecl : layout.getProtocols()) {
63936395
if (protoDecl->hasSelfOrAssociatedTypeRequirements()) {
6394-
return DiagnosticBehavior::Error;
6396+
return true;
63956397
}
63966398
}
63976399

6398-
if (ctx.LangOpts.hasFeature(Feature::ExistentialAny)) {
6399-
// For anything else, a missing `any` or `some` is a warning if this
6400-
// feature is enabled.
6401-
return DiagnosticBehavior::Warning;
6402-
}
6403-
6404-
return DiagnosticBehavior::Ignore;
6400+
// For anything else, a missing `any` or `some` is diagnosed if this
6401+
// feature is enabled.
6402+
return ctx.LangOpts.hasFeature(Feature::ExistentialAny);
64056403
}
64066404

64076405
void checkDeclRefTypeRepr(DeclRefTypeRepr *T) const {
@@ -6452,20 +6450,11 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
64526450
return dyn_cast<InverseTypeRepr>(*it);
64536451
}();
64546452

6455-
DiagnosticBehavior behavior =
6456-
this->getDiagnosticBehaviorForMissingAnyOrSomeKeyword(
6457-
type, /*isInverted=*/outerInversion, this->Ctx);
6458-
6459-
if (behavior == DiagnosticBehavior::Ignore) {
6453+
if (!shouldDiagnoseMissingAnyOrSomeKeyword(
6454+
type, /*isInverted=*/outerInversion, this->Ctx)) {
64606455
return;
64616456
}
64626457

6463-
// If we were asked to downgrade errors, respect it.
6464-
if (behavior == DiagnosticBehavior::Error &&
6465-
this->downgradeErrorsToWarnings) {
6466-
behavior = DiagnosticBehavior::Warning;
6467-
}
6468-
64696458
std::optional<InFlightDiagnostic> diag;
64706459
if (outerInversion) {
64716460
diag.emplace(Ctx.Diags.diagnose(outerInversion->getTildeLoc(),
@@ -6477,7 +6466,7 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
64776466
/*isAlias=*/isa<TypeAliasDecl>(decl)));
64786467
}
64796468

6480-
diag->limitBehaviorUntilSwiftVersion(behavior, 7);
6469+
diag->warnUntilSwiftVersion(7);
64816470
emitInsertAnyFixit(*diag, T);
64826471
}
64836472

@@ -6554,14 +6543,7 @@ void TypeChecker::checkExistentialTypes(ASTContext &ctx, Stmt *stmt,
65546543
if (sourceFile && sourceFile->Kind == SourceFileKind::Interface)
65556544
return;
65566545

6557-
// Previously we missed this diagnostic on 'catch' statements, downgrade
6558-
// to a warning until Swift 7.
6559-
auto downgradeErrorsToWarnings = false;
6560-
if (auto *CS = dyn_cast<CaseStmt>(stmt))
6561-
downgradeErrorsToWarnings = CS->getParentKind() == CaseParentKind::DoCatch;
6562-
6563-
ExistentialTypeSyntaxChecker checker(ctx, /*checkStatements=*/true,
6564-
downgradeErrorsToWarnings);
6546+
ExistentialTypeSyntaxChecker checker(ctx, /*checkStatements=*/true);
65656547
stmt->walk(checker);
65666548
}
65676549

test/Generics/inverse_generics.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,8 +471,8 @@ func checkExistentials() {
471471

472472
typealias NotCopyable = ~Copyable
473473
typealias EmptyComposition = ~Copyable & ~Escapable
474-
func test(_ t: borrowing NotCopyable) {} // expected-error {{use of 'NotCopyable' (aka '~Copyable') as a type must be written 'any NotCopyable'}}
475-
func test(_ t: borrowing EmptyComposition) {} // expected-error {{use of 'EmptyComposition' (aka '~Copyable & ~Escapable') as a type must be written 'any EmptyComposition' (aka 'any ~Copyable & ~Escapable')}}
474+
func test(_ t: borrowing NotCopyable) {} // expected-warning {{use of 'NotCopyable' (aka '~Copyable') as a type must be written 'any NotCopyable'}}
475+
func test(_ t: borrowing EmptyComposition) {} // expected-warning {{use of 'EmptyComposition' (aka '~Copyable & ~Escapable') as a type must be written 'any EmptyComposition' (aka 'any ~Copyable & ~Escapable')}}
476476

477477
typealias Copy = Copyable
478478
func test(_ z1: Copy, _ z2: Copyable) {}

test/Macros/macros_diagnostics.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,8 @@ struct MyStruct<T: MyProto> {
196196

197197
struct SomeType {
198198
#genericUnary<Equatable>(0 as Hashable)
199-
// expected-error@-1{{use of protocol 'Equatable' as a type must be written 'any Equatable'}}
200-
// expected-error@-2{{use of protocol 'Hashable' as a type must be written 'any Hashable'}}
199+
// expected-warning@-1{{use of protocol 'Equatable' as a type must be written 'any Equatable'}}
200+
// expected-warning@-2{{use of protocol 'Hashable' as a type must be written 'any Hashable'}}
201201
// expected-error@-3{{external macro implementation type}}
202202
}
203203

test/Macros/top_level_freestanding.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func testGlobalVariable() {
112112

113113
// expected-note @+1 2 {{in expansion of macro 'anonymousTypes' here}}
114114
#anonymousTypes { () -> String in
115-
// expected-error @+1 {{use of protocol 'Equatable' as a type must be written 'any Equatable'}}
115+
// expected-warning @+1 {{use of protocol 'Equatable' as a type must be written 'any Equatable'}}
116116
_ = 0 as Equatable
117117
return "foo"
118118
}

test/decl/nested/protocol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ extension OuterProtocol {
237237

238238
struct ConformsToOuterProtocol : OuterProtocol {
239239
typealias Hen = Int
240-
func f() { let _ = InnerProtocol.self } // expected-error {{use of protocol 'InnerProtocol' as a type must be written 'any InnerProtocol'}}
240+
func f() { let _ = InnerProtocol.self } // expected-warning {{use of protocol 'InnerProtocol' as a type must be written 'any InnerProtocol'}}
241241
}
242242

243243
extension OuterProtocol {

test/decl/protocol/existential_member_access/generic_fixit.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ protocol P {
1212
protocol Q {}
1313

1414
do {
15-
func test(p: P) { // expected-error {{use of protocol 'P' as a type must be written 'any P'}}
15+
func test(p: P) { // expected-warning {{use of protocol 'P' as a type must be written 'any P'}}
1616
p.method(false) // expected-error {{member 'method' cannot be used on value of type 'any P'; consider using a generic constraint instead}} {{-1:16--1:17=some P}} {{none}}
1717
}
1818
}
1919
do {
20-
func test(p: ((P))) { // expected-error {{use of protocol 'P' as a type must be written 'any P'}}
20+
func test(p: ((P))) { // expected-warning {{use of protocol 'P' as a type must be written 'any P'}}
2121
p.method(false) // expected-error {{member 'method' cannot be used on value of type 'any P'; consider using a generic constraint instead}} {{-1:18--1:19=some P}} {{none}}
2222
}
2323
}
@@ -57,12 +57,12 @@ do {
5757
}
5858
}
5959
do {
60-
func test(p: P.Type) { // expected-error {{use of protocol 'P' as a type must be written 'any P'}}
60+
func test(p: P.Type) { // expected-warning {{use of protocol 'P' as a type must be written 'any P'}}
6161
p.staticMethod(false) // expected-error {{member 'staticMethod' cannot be used on value of type 'any P.Type'; consider using a generic constraint instead}} {{-1:16--1:17=(some P)}} {{none}}
6262
}
6363
}
6464
do {
65-
func test(p: (P).Type) { // expected-error {{use of protocol 'P' as a type must be written 'any P'}}
65+
func test(p: (P).Type) { // expected-warning {{use of protocol 'P' as a type must be written 'any P'}}
6666
p.staticMethod(false) // expected-error {{member 'staticMethod' cannot be used on value of type 'any P.Type'; consider using a generic constraint instead}} {{-1:17--1:18=some P}} {{none}}
6767
}
6868
}
@@ -78,12 +78,12 @@ do {
7878
}
7979

8080
do {
81-
func test(p: P & Q) { // expected-error {{use of protocol 'P' as a type must be written 'any P'}}
81+
func test(p: P & Q) { // expected-warning {{use of protocol 'P' as a type must be written 'any P'}}
8282
p.method(false) // expected-error {{member 'method' cannot be used on value of type 'any P & Q'; consider using a generic constraint instead}} {{-1:16--1:21=some P & Q}} {{none}}
8383
}
8484
}
8585
do {
86-
func test(p: ((P & Q))) { // expected-error {{use of protocol 'P' as a type must be written 'any P'}}
86+
func test(p: ((P & Q))) { // expected-warning {{use of protocol 'P' as a type must be written 'any P'}}
8787
p.method(false) // expected-error {{member 'method' cannot be used on value of type 'any P & Q'; consider using a generic constraint instead}} {{-1:18--1:23=some P & Q}} {{none}}
8888
}
8989
}
@@ -123,12 +123,12 @@ do {
123123
}
124124
}
125125
do {
126-
func test(p: (P & Q).Type) { // expected-error {{use of protocol 'P' as a type must be written 'any P'}}
126+
func test(p: (P & Q).Type) { // expected-warning {{use of protocol 'P' as a type must be written 'any P'}}
127127
p.staticMethod(false) // expected-error {{member 'staticMethod' cannot be used on value of type 'any (P & Q).Type'; consider using a generic constraint instead}} {{-1:17--1:22=some P & Q}} {{none}}
128128
}
129129
}
130130
do {
131-
func test(p: ((P & Q)).Type) { // expected-error {{use of protocol 'P' as a type must be written 'any P'}}
131+
func test(p: ((P & Q)).Type) { // expected-warning {{use of protocol 'P' as a type must be written 'any P'}}
132132
p.staticMethod(false) // expected-error {{member 'staticMethod' cannot be used on value of type 'any (P & Q).Type'; consider using a generic constraint instead}} {{-1:18--1:23=some P & Q}} {{none}}
133133
}
134134
}

test/decl/protocol/protocols.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ func i<T : C3>(_ x : T?) -> Bool {
475475
// expected-warning@-1 {{checking a value with optional type 'T?' against type 'any P1' succeeds whenever the value is non-nil; did you mean to use '!= nil'?}}
476476
}
477477
func j(_ x : C1) -> Bool {
478-
return x is P1 // expected-error {{use of protocol 'P1' as a type must be written 'any P1'}}
478+
return x is P1 // expected-warning {{use of protocol 'P1' as a type must be written 'any P1'}}
479479
}
480480
func k(_ x : C1?) -> Bool {
481481
return x is any P1

test/decl/protocol/recursive_requirement.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %target-typecheck-verify-swift
2-
// RUN: not %target-swift-frontend -typecheck %s -debug-generic-signatures 2>&1 | %FileCheck %s
2+
// RUN: %target-swift-frontend -typecheck %s -debug-generic-signatures 2>&1 | %FileCheck %s
33

44
// -----
55

@@ -95,7 +95,7 @@ protocol AsExistentialB {
9595
}
9696

9797
protocol AsExistentialAssocTypeA {
98-
var delegate : AsExistentialAssocTypeB? { get } // expected-error {{use of protocol 'AsExistentialAssocTypeB' as a type must be written 'any AsExistentialAssocTypeB'}}
98+
var delegate : (any AsExistentialAssocTypeB)? { get }
9999
}
100100
protocol AsExistentialAssocTypeB {
101101
func aMethod(_ object : AsExistentialAssocTypeA)
@@ -107,7 +107,7 @@ protocol AsExistentialAssocTypeAgainA {
107107
associatedtype Bar
108108
}
109109
protocol AsExistentialAssocTypeAgainB {
110-
func aMethod(_ object : AsExistentialAssocTypeAgainA) // expected-error {{use of protocol 'AsExistentialAssocTypeAgainA' as a type must be written 'any AsExistentialAssocTypeAgainA'}}
110+
func aMethod(_ object : any AsExistentialAssocTypeAgainA)
111111
}
112112

113113
// https://github.com/apple/swift/issues/43164

0 commit comments

Comments
 (0)