Skip to content

Commit b90b564

Browse files
committed
ExistentialTypeSyntaxChecker: Look through inverses
1 parent 44e5286 commit b90b564

File tree

3 files changed

+36
-24
lines changed

3 files changed

+36
-24
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5982,26 +5982,6 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
59825982

59835983
reprStack.push_back(T);
59845984

5985-
// Suppressed conformance needs to be within any/some.
5986-
if (auto inverse = dyn_cast<InverseTypeRepr>(T)) {
5987-
if (isAnyOrSomeMissing()) {
5988-
// Find an enclosing protocol composition, if there is one, so we
5989-
// can insert 'any' before that.
5990-
SourceLoc anyLoc = inverse->getTildeLoc();
5991-
if (reprStack.size() > 1) {
5992-
if (auto *repr =
5993-
dyn_cast<CompositionTypeRepr>(*(reprStack.end() - 2))) {
5994-
anyLoc = repr->getStartLoc();
5995-
}
5996-
}
5997-
5998-
Ctx.Diags.diagnose(inverse->getTildeLoc(), diag::inverse_requires_any)
5999-
.highlight(inverse->getConstraint()->getSourceRange())
6000-
.fixItInsert(anyLoc, "any ");
6001-
}
6002-
return Action::SkipChildren();
6003-
}
6004-
60055985
auto *declRefTR = dyn_cast<DeclRefTypeRepr>(T);
60065986
if (!declRefTR) {
60075987
return Action::Continue();
@@ -6134,6 +6114,8 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
61346114
/// visited, assuming it is a constraint type demanding `any` or `some`, is
61356115
/// missing either keyword.
61366116
bool isAnyOrSomeMissing() const {
6117+
assert(isa<DeclRefTypeRepr>(reprStack.back()));
6118+
61376119
if (reprStack.size() < 2) {
61386120
return true;
61396121
}
@@ -6171,6 +6153,36 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
61716153
return;
61726154
}
61736155

6156+
// Backtrack the stack, looking just through parentheses and metatypes. If
6157+
// we find an inverse (which always requires `any`), diagnose it specially.
6158+
if (reprStack.size() > 1) {
6159+
auto it = reprStack.end() - 2;
6160+
while (it != reprStack.begin() &&
6161+
((*it)->isParenType() || isa<MetatypeTypeRepr>(*it))) {
6162+
--it;
6163+
continue;
6164+
}
6165+
6166+
if (auto inverse = dyn_cast<InverseTypeRepr>(*it)) {
6167+
if (isAnyOrSomeMissing()) {
6168+
// Find an enclosing protocol composition, if there is one, so we
6169+
// can insert 'any' before that.
6170+
SourceLoc anyLoc = inverse->getTildeLoc();
6171+
if (it != reprStack.begin()) {
6172+
if (auto *comp = dyn_cast<CompositionTypeRepr>(*(it - 1))) {
6173+
anyLoc = comp->getStartLoc();
6174+
}
6175+
}
6176+
6177+
Ctx.Diags.diagnose(inverse->getTildeLoc(), diag::inverse_requires_any)
6178+
.highlight(inverse->getConstraint()->getSourceRange())
6179+
.fixItInsert(anyLoc, "any ");
6180+
6181+
return;
6182+
}
6183+
}
6184+
}
6185+
61746186
auto *decl = T->getBoundDecl();
61756187
if (!decl) {
61766188
return;

test/type/explicit_existential.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ func testAnyFixIt() {
345345
// expected-error@+2 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{12-20=any HasAssoc}}
346346
// expected-error@+1 {{use of 'S.HasAssoc_Alias' (aka 'HasAssoc') as a type must be written 'any S.HasAssoc_Alias' (aka 'any HasAssoc')}}{{10-36=any G<HasAssoc>.HasAssoc_Alias}}
347347
let _: G<HasAssoc>.HasAssoc_Alias
348-
// FIXME: Generic argument not diagnosed.
348+
// expected-error@+2 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{13-21=any HasAssoc}}
349349
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{10-10=any }}
350350
let _: ~G<HasAssoc>.Copyable_Alias
351351
// FIXME: No fix-it + generic argument not diagnosed.
@@ -439,7 +439,7 @@ func testAnyFixIt() {
439439
let _: any HasAssocGeneric<~Copyable>
440440
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{16-24=any HasAssoc}}
441441
let _: any G<HasAssoc>.HasAssoc_Alias
442-
// FIXME: Generic argument not diagnosed.
442+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{17-25=any HasAssoc}}
443443
let _: any ~G<HasAssoc>.Copyable_Alias
444444
do {
445445
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{22-30=any HasAssoc}}

test/type/explicit_existential_swift6.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ func testAnyFixIt() {
377377
// expected-error@+2 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{12-20=any HasAssoc}}
378378
// expected-error@+1 {{use of 'S.HasAssoc_Alias' (aka 'HasAssoc') as a type must be written 'any S.HasAssoc_Alias' (aka 'any HasAssoc')}}{{10-36=any G<HasAssoc>.HasAssoc_Alias}}
379379
let _: G<HasAssoc>.HasAssoc_Alias
380-
// FIXME: Generic argument not diagnosed.
380+
// expected-error@+2 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{13-21=any HasAssoc}}
381381
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{10-10=any }}
382382
let _: ~G<HasAssoc>.Copyable_Alias
383383
// FIXME: No fix-it + generic argument not diagnosed.
@@ -471,7 +471,7 @@ func testAnyFixIt() {
471471
let _: any HasAssocGeneric<~Copyable>
472472
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{16-24=any HasAssoc}}
473473
let _: any G<HasAssoc>.HasAssoc_Alias
474-
// FIXME: Generic argument not diagnosed.
474+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{17-25=any HasAssoc}}
475475
let _: any ~G<HasAssoc>.Copyable_Alias
476476
do {
477477
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{22-30=any HasAssoc}}

0 commit comments

Comments
 (0)