@@ -4115,12 +4115,17 @@ class ExistentialTypeVisitor
41154115 ASTContext &Ctx;
41164116 bool checkStatements;
41174117 bool hitTopStmt;
4118+
4119+ unsigned exprCount = 0 ;
4120+ llvm::SmallVector<TypeRepr *, 4 > reprStack;
41184121
41194122public:
41204123 ExistentialTypeVisitor (ASTContext &ctx, bool checkStatements)
41214124 : Ctx(ctx), checkStatements(checkStatements), hitTopStmt(false ) { }
41224125
41234126 bool walkToTypeReprPre (TypeRepr *T) override {
4127+ reprStack.push_back (T);
4128+
41244129 if (T->isInvalid ())
41254130 return false ;
41264131 if (auto compound = dyn_cast<CompoundIdentTypeRepr>(T)) {
@@ -4141,6 +4146,11 @@ class ExistentialTypeVisitor
41414146 return true ;
41424147 }
41434148
4149+ bool walkToTypeReprPost (TypeRepr *T) override {
4150+ reprStack.pop_back ();
4151+ return true ;
4152+ }
4153+
41444154 std::pair<bool , Stmt*> walkToStmtPre (Stmt *S) override {
41454155 if (checkStatements && !hitTopStmt) {
41464156 hitTopStmt = true ;
@@ -4154,22 +4164,96 @@ class ExistentialTypeVisitor
41544164 return !checkStatements;
41554165 }
41564166
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+
41574177 void visitTypeRepr (TypeRepr *T) {
41584178 // Do nothing for all TypeReprs except the ones listed below.
41594179 }
41604180
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+
41614213 void visitIdentTypeRepr (IdentTypeRepr *T) {
41624214 if (T->isInvalid ())
41634215 return ;
41644216
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+
41654248 auto comp = T->getComponentRange ().back ();
41664249 if (auto *proto = dyn_cast_or_null<ProtocolDecl>(comp->getBoundDecl ())) {
41674250 if (proto->existentialRequiresAny ()) {
41684251 Ctx.Diags .diagnose (comp->getNameLoc (),
41694252 diag::existential_requires_any,
41704253 proto->getDeclaredInterfaceType (),
41714254 /* isAlias=*/ false )
4172- .limitBehavior (DiagnosticBehavior::Warning);
4255+ .limitBehavior (DiagnosticBehavior::Warning)
4256+ .fixItReplace (replaceRepr->getSourceRange (), fix);
41734257 }
41744258 } else if (auto *alias = dyn_cast_or_null<TypeAliasDecl>(comp->getBoundDecl ())) {
41754259 auto type = Type (alias->getDeclaredInterfaceType ()->getDesugaredType ());
@@ -4187,7 +4271,8 @@ class ExistentialTypeVisitor
41874271 diag::existential_requires_any,
41884272 alias->getDeclaredInterfaceType (),
41894273 /* isAlias=*/ true )
4190- .limitBehavior (DiagnosticBehavior::Warning);
4274+ .limitBehavior (DiagnosticBehavior::Warning)
4275+ .fixItReplace (replaceRepr->getSourceRange (), fix);
41914276 }
41924277 }
41934278 }
0 commit comments