@@ -4115,12 +4115,17 @@ class ExistentialTypeVisitor
4115
4115
ASTContext &Ctx;
4116
4116
bool checkStatements;
4117
4117
bool hitTopStmt;
4118
+
4119
+ unsigned exprCount = 0 ;
4120
+ llvm::SmallVector<TypeRepr *, 4 > reprStack;
4118
4121
4119
4122
public:
4120
4123
ExistentialTypeVisitor (ASTContext &ctx, bool checkStatements)
4121
4124
: Ctx(ctx), checkStatements(checkStatements), hitTopStmt(false ) { }
4122
4125
4123
4126
bool walkToTypeReprPre (TypeRepr *T) override {
4127
+ reprStack.push_back (T);
4128
+
4124
4129
if (T->isInvalid ())
4125
4130
return false ;
4126
4131
if (auto compound = dyn_cast<CompoundIdentTypeRepr>(T)) {
@@ -4141,6 +4146,11 @@ class ExistentialTypeVisitor
4141
4146
return true ;
4142
4147
}
4143
4148
4149
+ bool walkToTypeReprPost (TypeRepr *T) override {
4150
+ reprStack.pop_back ();
4151
+ return true ;
4152
+ }
4153
+
4144
4154
std::pair<bool , Stmt*> walkToStmtPre (Stmt *S) override {
4145
4155
if (checkStatements && !hitTopStmt) {
4146
4156
hitTopStmt = true ;
@@ -4154,22 +4164,96 @@ class ExistentialTypeVisitor
4154
4164
return !checkStatements;
4155
4165
}
4156
4166
4167
+ std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
4168
+ ++exprCount;
4169
+ return {true , E};
4170
+ }
4171
+
4172
+ Expr * walkToExprPost (Expr *E) override {
4173
+ --exprCount;
4174
+ return E;
4175
+ }
4176
+
4157
4177
void visitTypeRepr (TypeRepr *T) {
4158
4178
// Do nothing for all TypeReprs except the ones listed below.
4159
4179
}
4160
4180
4181
+ bool existentialNeedsParens (TypeRepr *parent) {
4182
+ switch (parent->getKind ()) {
4183
+ case TypeReprKind::Optional:
4184
+ case TypeReprKind::Protocol:
4185
+ return true ;
4186
+ case TypeReprKind::Metatype:
4187
+ case TypeReprKind::Attributed:
4188
+ case TypeReprKind::Error:
4189
+ case TypeReprKind::Function:
4190
+ case TypeReprKind::InOut:
4191
+ case TypeReprKind::Composition:
4192
+ case TypeReprKind::OpaqueReturn:
4193
+ case TypeReprKind::NamedOpaqueReturn:
4194
+ case TypeReprKind::Existential:
4195
+ case TypeReprKind::SimpleIdent:
4196
+ case TypeReprKind::GenericIdent:
4197
+ case TypeReprKind::CompoundIdent:
4198
+ case TypeReprKind::Dictionary:
4199
+ case TypeReprKind::ImplicitlyUnwrappedOptional:
4200
+ case TypeReprKind::Tuple:
4201
+ case TypeReprKind::Fixed:
4202
+ case TypeReprKind::Array:
4203
+ case TypeReprKind::SILBox:
4204
+ case TypeReprKind::Shared:
4205
+ case TypeReprKind::Owned:
4206
+ case TypeReprKind::Isolated:
4207
+ case TypeReprKind::Placeholder:
4208
+ case TypeReprKind::CompileTimeConst:
4209
+ return false ;
4210
+ }
4211
+ }
4212
+
4161
4213
void visitIdentTypeRepr (IdentTypeRepr *T) {
4162
4214
if (T->isInvalid ())
4163
4215
return ;
4164
4216
4217
+ // Compute the type repr to attach 'any' to.
4218
+ TypeRepr *replaceRepr = T;
4219
+ // Insert parens in expression context for '(any P).self'
4220
+ bool needsParens = (exprCount != 0 );
4221
+ if (reprStack.size () > 1 ) {
4222
+ auto parentIt = reprStack.end () - 2 ;
4223
+ needsParens = existentialNeedsParens (*parentIt);
4224
+
4225
+ // Expand to include parenthesis before checking if the parent needs
4226
+ // to be replaced.
4227
+ while (parentIt != reprStack.begin () &&
4228
+ (*parentIt)->getWithoutParens () != *parentIt)
4229
+ parentIt -= 1 ;
4230
+
4231
+ // For existential metatypes, 'any' is applied to the metatype.
4232
+ if ((*parentIt)->getKind () == TypeReprKind::Metatype) {
4233
+ replaceRepr = *parentIt;
4234
+ if (parentIt != reprStack.begin ())
4235
+ needsParens = existentialNeedsParens (*(parentIt - 1 ));
4236
+ }
4237
+ }
4238
+
4239
+ std::string fix;
4240
+ llvm::raw_string_ostream OS (fix);
4241
+ if (needsParens)
4242
+ OS << " (" ;
4243
+ ExistentialTypeRepr existential (SourceLoc (), replaceRepr);
4244
+ existential.print (OS);
4245
+ if (needsParens)
4246
+ OS << " )" ;
4247
+
4165
4248
auto comp = T->getComponentRange ().back ();
4166
4249
if (auto *proto = dyn_cast_or_null<ProtocolDecl>(comp->getBoundDecl ())) {
4167
4250
if (proto->existentialRequiresAny ()) {
4168
4251
Ctx.Diags .diagnose (comp->getNameLoc (),
4169
4252
diag::existential_requires_any,
4170
4253
proto->getDeclaredInterfaceType (),
4171
4254
/* isAlias=*/ false )
4172
- .limitBehavior (DiagnosticBehavior::Warning);
4255
+ .limitBehavior (DiagnosticBehavior::Warning)
4256
+ .fixItReplace (replaceRepr->getSourceRange (), fix);
4173
4257
}
4174
4258
} else if (auto *alias = dyn_cast_or_null<TypeAliasDecl>(comp->getBoundDecl ())) {
4175
4259
auto type = Type (alias->getDeclaredInterfaceType ()->getDesugaredType ());
@@ -4187,7 +4271,8 @@ class ExistentialTypeVisitor
4187
4271
diag::existential_requires_any,
4188
4272
alias->getDeclaredInterfaceType (),
4189
4273
/* isAlias=*/ true )
4190
- .limitBehavior (DiagnosticBehavior::Warning);
4274
+ .limitBehavior (DiagnosticBehavior::Warning)
4275
+ .fixItReplace (replaceRepr->getSourceRange (), fix);
4191
4276
}
4192
4277
}
4193
4278
}
0 commit comments