Skip to content

Commit 8955625

Browse files
committed
ExistentialTypeSyntaxChecker: Fix any fix-it for higher-order metatypes
1 parent b90b564 commit 8955625

File tree

3 files changed

+48
-23
lines changed

3 files changed

+48
-23
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6074,40 +6074,53 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
60746074
}
60756075

60766076
void emitInsertAnyFixit(InFlightDiagnostic &diag, DeclRefTypeRepr *T) const {
6077-
TypeRepr *replaceRepr = T;
6077+
TypeRepr *replacementT = T;
60786078

60796079
// Insert parens in expression context for '(any P).self'
60806080
bool needsParens = (exprCount != 0);
6081+
6082+
// Compute the replacement node (the node to which to apply `any`).
60816083
if (reprStack.size() > 1) {
6082-
auto parentIt = reprStack.end() - 2;
6083-
needsParens = anySyntaxNeedsParens(*parentIt);
6084-
6085-
// Expand to include parenthesis before checking if the parent needs
6086-
// to be replaced.
6087-
while (parentIt != reprStack.begin() &&
6088-
(*parentIt)->getWithoutParens() != *parentIt)
6089-
parentIt -= 1;
6090-
6091-
// For existential metatypes, 'any' is applied to the metatype.
6092-
if ((*parentIt)->getKind() == TypeReprKind::Metatype) {
6093-
replaceRepr = *parentIt;
6094-
if (parentIt != reprStack.begin())
6095-
needsParens = anySyntaxNeedsParens(*(parentIt - 1));
6084+
auto it = reprStack.end() - 1;
6085+
auto replacementIt = it;
6086+
6087+
// Backtrack the stack and expand the replacement range to any parent
6088+
// `.Type` metatypes, skipping only parentheses.
6089+
do {
6090+
--it;
6091+
if ((*it)->isParenType()) {
6092+
continue;
6093+
}
6094+
6095+
if (isa<MetatypeTypeRepr>(*it)) {
6096+
replacementIt = it;
6097+
continue;
6098+
}
6099+
6100+
break;
6101+
} while (it != reprStack.begin());
6102+
6103+
// Whether parentheses are necessary is determined by the immediate parent
6104+
// of the replacement node.
6105+
if (replacementIt != reprStack.begin()) {
6106+
needsParens = anySyntaxNeedsParens(*(replacementIt - 1));
60966107
}
6108+
6109+
replacementT = *replacementIt;
60976110
}
60986111

60996112
llvm::SmallString<64> fix;
61006113
{
61016114
llvm::raw_svector_ostream OS(fix);
61026115
if (needsParens)
61036116
OS << "(";
6104-
ExistentialTypeRepr existential(SourceLoc(), replaceRepr);
6117+
ExistentialTypeRepr existential(SourceLoc(), replacementT);
61056118
existential.print(OS);
61066119
if (needsParens)
61076120
OS << ")";
61086121
}
61096122

6110-
diag.fixItReplace(replaceRepr->getSourceRange(), fix);
6123+
diag.fixItReplace(replacementT->getSourceRange(), fix);
61116124
}
61126125

61136126
/// Returns a Boolean value indicating whether the type representation being

test/type/explicit_existential.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,8 @@ func testAnyFixIt() {
358358
let _: HasAssoc.Type
359359
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{10-10=any }}
360360
let _: ~Copyable.Type
361+
// expected-error@+1 {{type 'any Copyable.Type' cannot be suppressed}}
362+
let _: ~(Copyable.Type)
361363
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-25=any (HasAssoc).Type}}
362364
let _: (HasAssoc).Type
363365
// FIXME: Fix-it produces singleton, not existential, metatype type?
@@ -368,13 +370,18 @@ func testAnyFixIt() {
368370
// FIXME: Fix-it produces singleton, not existential, metatype type?
369371
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{12-12=any }}
370372
let _: ((~Copyable)).Type
371-
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-23=any HasAssoc.Type}}
373+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-28=any HasAssoc.Type.Type}}
372374
let _: HasAssoc.Type.Type
373375
// expected-error@+1 {{type 'any Copyable.Type.Type' cannot be suppressed}}
374376
let _: ~Copyable.Type.Type
375377
// FIXME: Fix-it produces singleton, not existential, metatype type?
376378
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{11-11=any }}
377379
let _: (~Copyable).Type.Type
380+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-30=any (HasAssoc.Type).Type}}
381+
let _: (HasAssoc.Type).Type
382+
// FIXME: Fix-it produces singleton, not existential, metatype type?
383+
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{11-11=any }}
384+
let _: (~Copyable.Type).Type
378385
// expected-error@+2 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-18=(any HasAssoc)}}
379386
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{30-38=(any HasAssoc)}}
380387
let _: HasAssoc.Protocol = HasAssoc.self
@@ -405,8 +412,7 @@ func testAnyFixIt() {
405412
// FIXME: Incorrect fix-it.
406413
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{11-11=any }}
407414
let _: (~Copyable).Type.Protocol
408-
// FIXME: Incorrect fix-it.
409-
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-23=any HasAssoc.Type}}
415+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-28=(any HasAssoc.Type.Type)}}
410416
let _: HasAssoc.Type.Type.Protocol
411417
// FIXME: Incorrect fix-it.
412418
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{11-11=any }}

test/type/explicit_existential_swift6.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ func testAnyFixIt() {
390390
let _: HasAssoc.Type
391391
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{10-10=any }}
392392
let _: ~Copyable.Type
393+
// expected-error@+1 {{type 'any Copyable.Type' cannot be suppressed}}
394+
let _: ~(Copyable.Type)
393395
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-25=any (HasAssoc).Type}}
394396
let _: (HasAssoc).Type
395397
// FIXME: Fix-it produces singleton, not existential, metatype type?
@@ -400,13 +402,18 @@ func testAnyFixIt() {
400402
// FIXME: Fix-it produces singleton, not existential, metatype type?
401403
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{12-12=any }}
402404
let _: ((~Copyable)).Type
403-
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-23=any HasAssoc.Type}}
405+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-28=any HasAssoc.Type.Type}}
404406
let _: HasAssoc.Type.Type
405407
// expected-error@+1 {{type 'any Copyable.Type.Type' cannot be suppressed}}
406408
let _: ~Copyable.Type.Type
407409
// FIXME: Fix-it produces singleton, not existential, metatype type?
408410
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{11-11=any }}
409411
let _: (~Copyable).Type.Type
412+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-30=any (HasAssoc.Type).Type}}
413+
let _: (HasAssoc.Type).Type
414+
// FIXME: Fix-it produces singleton, not existential, metatype type?
415+
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{11-11=any }}
416+
let _: (~Copyable.Type).Type
410417
// expected-error@+2 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-18=(any HasAssoc)}}
411418
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{30-38=(any HasAssoc)}}
412419
let _: HasAssoc.Protocol = HasAssoc.self
@@ -437,8 +444,7 @@ func testAnyFixIt() {
437444
// FIXME: Incorrect fix-it.
438445
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{11-11=any }}
439446
let _: (~Copyable).Type.Protocol
440-
// FIXME: Incorrect fix-it.
441-
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-23=any HasAssoc.Type}}
447+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-28=(any HasAssoc.Type.Type)}}
442448
let _: HasAssoc.Type.Type.Protocol
443449
// FIXME: Incorrect fix-it.
444450
// expected-error@+1 {{constraint that suppresses conformance requires 'any'}}{{11-11=any }}

0 commit comments

Comments
 (0)