@@ -5980,33 +5980,28 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
5980
5980
if (T->isInvalid ())
5981
5981
return Action::SkipNode ();
5982
5982
5983
- // Arbitrary protocol constraints are OK on opaque types.
5984
- if (isa<OpaqueReturnTypeRepr>(T))
5985
- return Action::SkipNode ();
5986
-
5987
- // Arbitrary protocol constraints are okay for 'any' types.
5988
- if (isa<ExistentialTypeRepr>(T))
5989
- return Action::SkipNode ();
5983
+ reprStack.push_back (T);
5990
5984
5991
5985
// Suppressed conformance needs to be within any/some.
5992
5986
if (auto inverse = dyn_cast<InverseTypeRepr>(T)) {
5993
- // Find an enclosing protocol composition, if there is one, so we
5994
- // can insert 'any' before that.
5995
- SourceLoc anyLoc = inverse->getTildeLoc ();
5996
- if (!reprStack.empty ()) {
5997
- if (isa<CompositionTypeRepr>(reprStack.back ())) {
5998
- anyLoc = reprStack.back ()->getStartLoc ();
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
+ }
5999
5996
}
6000
- }
6001
5997
6002
- Ctx.Diags .diagnose (inverse->getTildeLoc (), diag::inverse_requires_any)
6003
- .highlight (inverse->getConstraint ()->getSourceRange ())
6004
- .fixItInsert (anyLoc, " any " );
6005
- return Action::SkipNode ();
5998
+ Ctx.Diags .diagnose (inverse->getTildeLoc (), diag::inverse_requires_any)
5999
+ .highlight (inverse->getConstraint ()->getSourceRange ())
6000
+ .fixItInsert (anyLoc, " any " );
6001
+ }
6002
+ return Action::SkipChildren ();
6006
6003
}
6007
6004
6008
- reprStack.push_back (T);
6009
-
6010
6005
auto *declRefTR = dyn_cast<DeclRefTypeRepr>(T);
6011
6006
if (!declRefTR) {
6012
6007
return Action::Continue ();
@@ -6135,6 +6130,40 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
6135
6130
diag.fixItReplace (replaceRepr->getSourceRange (), fix);
6136
6131
}
6137
6132
6133
+ // / Returns a Boolean value indicating whether the type representation being
6134
+ // / visited, assuming it is a constraint type demanding `any` or `some`, is
6135
+ // / missing either keyword.
6136
+ bool isAnyOrSomeMissing () const {
6137
+ if (reprStack.size () < 2 ) {
6138
+ return true ;
6139
+ }
6140
+
6141
+ auto it = reprStack.end () - 1 ;
6142
+ while (true ) {
6143
+ --it;
6144
+ if (it == reprStack.begin ()) {
6145
+ break ;
6146
+ }
6147
+
6148
+ // Look through parens, inverses, metatypes, and compositions.
6149
+ if ((*it)->isParenType () || isa<InverseTypeRepr>(*it) ||
6150
+ isa<CompositionTypeRepr>(*it) || isa<MetatypeTypeRepr>(*it)) {
6151
+ continue ;
6152
+ }
6153
+
6154
+ // Look through '?' and '!' too; `any P?` et al. is diagnosed in the
6155
+ // type resolver.
6156
+ if (isa<OptionalTypeRepr>(*it) ||
6157
+ isa<ImplicitlyUnwrappedOptionalTypeRepr>(*it)) {
6158
+ continue ;
6159
+ }
6160
+
6161
+ break ;
6162
+ }
6163
+
6164
+ return !(isa<OpaqueReturnTypeRepr>(*it) || isa<ExistentialTypeRepr>(*it));
6165
+ }
6166
+
6138
6167
void checkDeclRefTypeRepr (DeclRefTypeRepr *T) const {
6139
6168
assert (!T->isInvalid ());
6140
6169
@@ -6148,7 +6177,7 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
6148
6177
}
6149
6178
6150
6179
if (auto *proto = dyn_cast<ProtocolDecl>(decl)) {
6151
- if (proto->existentialRequiresAny ()) {
6180
+ if (proto->existentialRequiresAny () && isAnyOrSomeMissing () ) {
6152
6181
auto diag =
6153
6182
Ctx.Diags .diagnose (T->getNameLoc (), diag::existential_requires_any,
6154
6183
proto->getDeclaredInterfaceType (),
@@ -6178,7 +6207,7 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
6178
6207
if (auto *PCT = type->getAs <ProtocolCompositionType>())
6179
6208
diagnose |= !PCT->getInverses ().empty ();
6180
6209
6181
- if (diagnose) {
6210
+ if (diagnose && isAnyOrSomeMissing () ) {
6182
6211
auto diag = Ctx.Diags .diagnose (
6183
6212
T->getNameLoc (), diag::existential_requires_any,
6184
6213
alias->getDeclaredInterfaceType (),
0 commit comments