@@ -5772,9 +5772,12 @@ Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module,
5772
5772
5773
5773
namespace {
5774
5774
5775
- class ExistentialTypeVisitor
5776
- : public TypeReprVisitor<ExistentialTypeVisitor>, public ASTWalker
5777
- {
5775
+ // / Usually, existential types, existential metatypes, and singleton
5776
+ // / metatypes of existential must be written using `any` syntax. For example,
5777
+ // / `any P`, `any P.Type`, and `(any P).Type` respectively. This walker
5778
+ // / traverses an AST in search for occurrences of these types and checks their
5779
+ // / written syntax.
5780
+ class ExistentialTypeSyntaxChecker : public ASTWalker {
5778
5781
ASTContext &Ctx;
5779
5782
bool checkStatements;
5780
5783
bool hitTopStmt;
@@ -5783,22 +5786,21 @@ class ExistentialTypeVisitor
5783
5786
llvm::SmallVector<TypeRepr *, 4 > reprStack;
5784
5787
5785
5788
public:
5786
- ExistentialTypeVisitor (ASTContext &ctx, bool checkStatements)
5787
- : Ctx(ctx), checkStatements(checkStatements), hitTopStmt(false ) { }
5789
+ ExistentialTypeSyntaxChecker (ASTContext &ctx, bool checkStatements)
5790
+ : Ctx(ctx), checkStatements(checkStatements), hitTopStmt(false ) {}
5788
5791
5789
5792
MacroWalking getMacroWalkingBehavior () const override {
5790
5793
return MacroWalking::ArgumentsAndExpansion;
5791
5794
}
5792
5795
5793
5796
PreWalkAction walkToTypeReprPre (TypeRepr *T) override {
5794
- reprStack.push_back (T);
5795
-
5796
5797
if (T->isInvalid ())
5797
5798
return Action::SkipNode ();
5799
+
5798
5800
if (auto memberTR = dyn_cast<MemberTypeRepr>(T)) {
5799
5801
// Only visit the last component to check, because nested typealiases in
5800
5802
// existentials are okay.
5801
- visit ( memberTR->getLastComponent ());
5803
+ memberTR->getLastComponent ()-> walk (* this );
5802
5804
return Action::SkipNode ();
5803
5805
}
5804
5806
// Arbitrary protocol constraints are OK on opaque types.
@@ -5809,11 +5811,20 @@ class ExistentialTypeVisitor
5809
5811
if (isa<ExistentialTypeRepr>(T))
5810
5812
return Action::SkipNode ();
5811
5813
5812
- visit (T);
5814
+ reprStack.push_back (T);
5815
+
5816
+ auto *declRefTR = dyn_cast<DeclRefTypeRepr>(T);
5817
+ if (!declRefTR) {
5818
+ return Action::Continue ();
5819
+ }
5820
+
5821
+ checkDeclRefTypeRepr (declRefTR);
5822
+
5813
5823
return Action::Continue ();
5814
5824
}
5815
5825
5816
5826
PostWalkAction walkToTypeReprPost (TypeRepr *T) override {
5827
+ assert (reprStack.back () == T);
5817
5828
reprStack.pop_back ();
5818
5829
return Action::Continue ();
5819
5830
}
@@ -5841,11 +5852,8 @@ class ExistentialTypeVisitor
5841
5852
return Action::Continue (E);
5842
5853
}
5843
5854
5844
- void visitTypeRepr (TypeRepr *T) {
5845
- // Do nothing for all TypeReprs except the ones listed below.
5846
- }
5847
-
5848
- bool existentialNeedsParens (TypeRepr *parent) {
5855
+ private:
5856
+ bool existentialNeedsParens (TypeRepr *parent) const {
5849
5857
switch (parent->getKind ()) {
5850
5858
case TypeReprKind::Optional:
5851
5859
case TypeReprKind::Protocol:
@@ -5883,16 +5891,9 @@ class ExistentialTypeVisitor
5883
5891
}
5884
5892
}
5885
5893
5886
- void visitIdentTypeRepr (IdentTypeRepr *T) {
5887
- if (T->isInvalid ())
5888
- return ;
5889
-
5890
- if (Ctx.LangOpts .hasFeature (Feature::ImplicitSome)) {
5891
- return ;
5892
- }
5893
-
5894
- // Compute the type repr to attach 'any' to.
5894
+ void emitInsertAnyFixit (InFlightDiagnostic &diag, DeclRefTypeRepr *T) const {
5895
5895
TypeRepr *replaceRepr = T;
5896
+
5896
5897
// Insert parens in expression context for '(any P).self'
5897
5898
bool needsParens = (exprCount != 0 );
5898
5899
if (reprStack.size () > 1 ) {
@@ -5913,26 +5914,42 @@ class ExistentialTypeVisitor
5913
5914
}
5914
5915
}
5915
5916
5916
- std::string fix;
5917
- llvm::raw_string_ostream OS (fix);
5918
- if (needsParens)
5919
- OS << " (" ;
5920
- ExistentialTypeRepr existential (SourceLoc (), replaceRepr);
5921
- existential.print (OS);
5922
- if (needsParens)
5923
- OS << " )" ;
5917
+ llvm::SmallString<64 > fix;
5918
+ {
5919
+ llvm::raw_svector_ostream OS (fix);
5920
+ if (needsParens)
5921
+ OS << " (" ;
5922
+ ExistentialTypeRepr existential (SourceLoc (), replaceRepr);
5923
+ existential.print (OS);
5924
+ if (needsParens)
5925
+ OS << " )" ;
5926
+ }
5927
+
5928
+ diag.fixItReplace (replaceRepr->getSourceRange (), fix);
5929
+ }
5930
+
5931
+ void checkDeclRefTypeRepr (DeclRefTypeRepr *T) const {
5932
+ assert (!T->isInvalid ());
5924
5933
5925
- if (auto *proto = dyn_cast_or_null<ProtocolDecl>(T->getBoundDecl ())) {
5934
+ if (Ctx.LangOpts .hasFeature (Feature::ImplicitSome)) {
5935
+ return ;
5936
+ }
5937
+
5938
+ auto *decl = T->getBoundDecl ();
5939
+ if (!decl) {
5940
+ return ;
5941
+ }
5942
+
5943
+ if (auto *proto = dyn_cast<ProtocolDecl>(decl)) {
5926
5944
if (proto->existentialRequiresAny ()) {
5927
- Ctx. Diags . diagnose (T-> getNameLoc (),
5928
- diag::existential_requires_any,
5929
- proto->getDeclaredInterfaceType (),
5930
- proto->getDeclaredExistentialType (),
5931
- /* isAlias=*/ false )
5932
- . fixItReplace (replaceRepr-> getSourceRange (), fix );
5945
+ auto diag =
5946
+ Ctx. Diags . diagnose (T-> getNameLoc (), diag::existential_requires_any,
5947
+ proto->getDeclaredInterfaceType (),
5948
+ proto->getDeclaredExistentialType (),
5949
+ /* isAlias=*/ false );
5950
+ emitInsertAnyFixit (diag, T );
5933
5951
}
5934
- } else if (auto *alias =
5935
- dyn_cast_or_null<TypeAliasDecl>(T->getBoundDecl ())) {
5952
+ } else if (auto *alias = dyn_cast<TypeAliasDecl>(decl)) {
5936
5953
auto type = Type (alias->getDeclaredInterfaceType ()->getDesugaredType ());
5937
5954
5938
5955
// If this is a type alias to a constraint type, the type
@@ -5944,18 +5961,19 @@ class ExistentialTypeVisitor
5944
5961
if (!protoDecl->existentialRequiresAny ())
5945
5962
continue ;
5946
5963
5947
- Ctx.Diags .diagnose (T-> getNameLoc (),
5948
- diag::existential_requires_any,
5949
- alias->getDeclaredInterfaceType (),
5950
- ExistentialType::get (alias->getDeclaredInterfaceType ()),
5951
- /* isAlias=*/ true )
5952
- . fixItReplace (replaceRepr-> getSourceRange (), fix );
5964
+ auto diag = Ctx.Diags .diagnose (
5965
+ T-> getNameLoc (), diag::existential_requires_any,
5966
+ alias->getDeclaredInterfaceType (),
5967
+ ExistentialType::get (alias->getDeclaredInterfaceType ()),
5968
+ /* isAlias=*/ true );
5969
+ emitInsertAnyFixit (diag, T );
5953
5970
}
5954
5971
}
5955
5972
}
5956
5973
}
5957
5974
5958
- void visitRequirements (ArrayRef<RequirementRepr> reqts) {
5975
+ public:
5976
+ void checkRequirements (ArrayRef<RequirementRepr> reqts) {
5959
5977
for (auto reqt : reqts) {
5960
5978
if (reqt.getKind () == RequirementReprKind::SameType) {
5961
5979
if (auto *repr = reqt.getFirstTypeRepr ())
@@ -6003,18 +6021,18 @@ void TypeChecker::checkExistentialTypes(Decl *decl) {
6003
6021
checkExistentialTypes (ctx, macroDecl->getGenericParams ());
6004
6022
checkExistentialTypes (ctx, macroDecl->getTrailingWhereClause ());
6005
6023
} else if (auto *macroExpansionDecl = dyn_cast<MacroExpansionDecl>(decl)) {
6006
- ExistentialTypeVisitor visitor (ctx, /* checkStatements=*/ false );
6007
- macroExpansionDecl->getArgs ()->walk (visitor );
6024
+ ExistentialTypeSyntaxChecker checker (ctx, /* checkStatements=*/ false );
6025
+ macroExpansionDecl->getArgs ()->walk (checker );
6008
6026
for (auto *genArg : macroExpansionDecl->getGenericArgs ())
6009
- genArg->walk (visitor );
6027
+ genArg->walk (checker );
6010
6028
}
6011
6029
6012
6030
if (isa<TypeDecl>(decl) || isa<ExtensionDecl>(decl) ||
6013
6031
isa<MacroExpansionDecl>(decl))
6014
6032
return ;
6015
6033
6016
- ExistentialTypeVisitor visitor (ctx, /* checkStatements=*/ false );
6017
- decl->walk (visitor );
6034
+ ExistentialTypeSyntaxChecker checker (ctx, /* checkStatements=*/ false );
6035
+ decl->walk (checker );
6018
6036
}
6019
6037
6020
6038
void TypeChecker::checkExistentialTypes (ASTContext &ctx, Stmt *stmt,
@@ -6027,8 +6045,8 @@ void TypeChecker::checkExistentialTypes(ASTContext &ctx, Stmt *stmt,
6027
6045
if (sourceFile && sourceFile->Kind == SourceFileKind::Interface)
6028
6046
return ;
6029
6047
6030
- ExistentialTypeVisitor visitor (ctx, /* checkStatements=*/ true );
6031
- stmt->walk (visitor );
6048
+ ExistentialTypeSyntaxChecker checker (ctx, /* checkStatements=*/ true );
6049
+ stmt->walk (checker );
6032
6050
}
6033
6051
6034
6052
void TypeChecker::checkExistentialTypes (ASTContext &ctx,
@@ -6040,26 +6058,26 @@ void TypeChecker::checkExistentialTypes(ASTContext &ctx,
6040
6058
if (typeAlias->getUnderlyingType ()->isConstraintType ())
6041
6059
return ;
6042
6060
6043
- ExistentialTypeVisitor visitor (ctx, /* checkStatements=*/ true );
6044
- typeAlias->getUnderlyingTypeRepr ()->walk (visitor );
6061
+ ExistentialTypeSyntaxChecker checker (ctx, /* checkStatements=*/ true );
6062
+ typeAlias->getUnderlyingTypeRepr ()->walk (checker );
6045
6063
}
6046
6064
6047
6065
void TypeChecker::checkExistentialTypes (
6048
6066
ASTContext &ctx, TrailingWhereClause *whereClause) {
6049
6067
if (whereClause == nullptr )
6050
6068
return ;
6051
6069
6052
- ExistentialTypeVisitor visitor (ctx, /* checkStatements=*/ false );
6053
- visitor. visitRequirements (whereClause->getRequirements ());
6070
+ ExistentialTypeSyntaxChecker checker (ctx, /* checkStatements=*/ false );
6071
+ checker. checkRequirements (whereClause->getRequirements ());
6054
6072
}
6055
6073
6056
6074
void TypeChecker::checkExistentialTypes (
6057
6075
ASTContext &ctx, GenericParamList *genericParams) {
6058
6076
if (genericParams == nullptr )
6059
6077
return ;
6060
6078
6061
- ExistentialTypeVisitor visitor (ctx, /* checkStatements=*/ false );
6062
- visitor. visitRequirements (genericParams->getRequirements ());
6079
+ ExistentialTypeSyntaxChecker checker (ctx, /* checkStatements=*/ false );
6080
+ checker. checkRequirements (genericParams->getRequirements ());
6063
6081
}
6064
6082
6065
6083
Type CustomAttrTypeRequest::evaluate (Evaluator &eval, CustomAttr *attr,
0 commit comments