Skip to content

Commit cdfe5a0

Browse files
committed
TypeCheckType: Tidy up and rename ExistentialTypeVisitor
1 parent 14d38e7 commit cdfe5a0

File tree

1 file changed

+78
-60
lines changed

1 file changed

+78
-60
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 78 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5772,9 +5772,12 @@ Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module,
57725772

57735773
namespace {
57745774

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 {
57785781
ASTContext &Ctx;
57795782
bool checkStatements;
57805783
bool hitTopStmt;
@@ -5783,22 +5786,21 @@ class ExistentialTypeVisitor
57835786
llvm::SmallVector<TypeRepr *, 4> reprStack;
57845787

57855788
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) {}
57885791

57895792
MacroWalking getMacroWalkingBehavior() const override {
57905793
return MacroWalking::ArgumentsAndExpansion;
57915794
}
57925795

57935796
PreWalkAction walkToTypeReprPre(TypeRepr *T) override {
5794-
reprStack.push_back(T);
5795-
57965797
if (T->isInvalid())
57975798
return Action::SkipNode();
5799+
57985800
if (auto memberTR = dyn_cast<MemberTypeRepr>(T)) {
57995801
// Only visit the last component to check, because nested typealiases in
58005802
// existentials are okay.
5801-
visit(memberTR->getLastComponent());
5803+
memberTR->getLastComponent()->walk(*this);
58025804
return Action::SkipNode();
58035805
}
58045806
// Arbitrary protocol constraints are OK on opaque types.
@@ -5809,11 +5811,20 @@ class ExistentialTypeVisitor
58095811
if (isa<ExistentialTypeRepr>(T))
58105812
return Action::SkipNode();
58115813

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+
58135823
return Action::Continue();
58145824
}
58155825

58165826
PostWalkAction walkToTypeReprPost(TypeRepr *T) override {
5827+
assert(reprStack.back() == T);
58175828
reprStack.pop_back();
58185829
return Action::Continue();
58195830
}
@@ -5841,11 +5852,8 @@ class ExistentialTypeVisitor
58415852
return Action::Continue(E);
58425853
}
58435854

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 {
58495857
switch (parent->getKind()) {
58505858
case TypeReprKind::Optional:
58515859
case TypeReprKind::Protocol:
@@ -5883,16 +5891,9 @@ class ExistentialTypeVisitor
58835891
}
58845892
}
58855893

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 {
58955895
TypeRepr *replaceRepr = T;
5896+
58965897
// Insert parens in expression context for '(any P).self'
58975898
bool needsParens = (exprCount != 0);
58985899
if (reprStack.size() > 1) {
@@ -5913,26 +5914,42 @@ class ExistentialTypeVisitor
59135914
}
59145915
}
59155916

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());
59245933

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)) {
59265944
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);
59335951
}
5934-
} else if (auto *alias =
5935-
dyn_cast_or_null<TypeAliasDecl>(T->getBoundDecl())) {
5952+
} else if (auto *alias = dyn_cast<TypeAliasDecl>(decl)) {
59365953
auto type = Type(alias->getDeclaredInterfaceType()->getDesugaredType());
59375954

59385955
// If this is a type alias to a constraint type, the type
@@ -5944,18 +5961,19 @@ class ExistentialTypeVisitor
59445961
if (!protoDecl->existentialRequiresAny())
59455962
continue;
59465963

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);
59535970
}
59545971
}
59555972
}
59565973
}
59575974

5958-
void visitRequirements(ArrayRef<RequirementRepr> reqts) {
5975+
public:
5976+
void checkRequirements(ArrayRef<RequirementRepr> reqts) {
59595977
for (auto reqt : reqts) {
59605978
if (reqt.getKind() == RequirementReprKind::SameType) {
59615979
if (auto *repr = reqt.getFirstTypeRepr())
@@ -6003,18 +6021,18 @@ void TypeChecker::checkExistentialTypes(Decl *decl) {
60036021
checkExistentialTypes(ctx, macroDecl->getGenericParams());
60046022
checkExistentialTypes(ctx, macroDecl->getTrailingWhereClause());
60056023
} 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);
60086026
for (auto *genArg : macroExpansionDecl->getGenericArgs())
6009-
genArg->walk(visitor);
6027+
genArg->walk(checker);
60106028
}
60116029

60126030
if (isa<TypeDecl>(decl) || isa<ExtensionDecl>(decl) ||
60136031
isa<MacroExpansionDecl>(decl))
60146032
return;
60156033

6016-
ExistentialTypeVisitor visitor(ctx, /*checkStatements=*/false);
6017-
decl->walk(visitor);
6034+
ExistentialTypeSyntaxChecker checker(ctx, /*checkStatements=*/false);
6035+
decl->walk(checker);
60186036
}
60196037

60206038
void TypeChecker::checkExistentialTypes(ASTContext &ctx, Stmt *stmt,
@@ -6027,8 +6045,8 @@ void TypeChecker::checkExistentialTypes(ASTContext &ctx, Stmt *stmt,
60276045
if (sourceFile && sourceFile->Kind == SourceFileKind::Interface)
60286046
return;
60296047

6030-
ExistentialTypeVisitor visitor(ctx, /*checkStatements=*/true);
6031-
stmt->walk(visitor);
6048+
ExistentialTypeSyntaxChecker checker(ctx, /*checkStatements=*/true);
6049+
stmt->walk(checker);
60326050
}
60336051

60346052
void TypeChecker::checkExistentialTypes(ASTContext &ctx,
@@ -6040,26 +6058,26 @@ void TypeChecker::checkExistentialTypes(ASTContext &ctx,
60406058
if (typeAlias->getUnderlyingType()->isConstraintType())
60416059
return;
60426060

6043-
ExistentialTypeVisitor visitor(ctx, /*checkStatements=*/true);
6044-
typeAlias->getUnderlyingTypeRepr()->walk(visitor);
6061+
ExistentialTypeSyntaxChecker checker(ctx, /*checkStatements=*/true);
6062+
typeAlias->getUnderlyingTypeRepr()->walk(checker);
60456063
}
60466064

60476065
void TypeChecker::checkExistentialTypes(
60486066
ASTContext &ctx, TrailingWhereClause *whereClause) {
60496067
if (whereClause == nullptr)
60506068
return;
60516069

6052-
ExistentialTypeVisitor visitor(ctx, /*checkStatements=*/false);
6053-
visitor.visitRequirements(whereClause->getRequirements());
6070+
ExistentialTypeSyntaxChecker checker(ctx, /*checkStatements=*/false);
6071+
checker.checkRequirements(whereClause->getRequirements());
60546072
}
60556073

60566074
void TypeChecker::checkExistentialTypes(
60576075
ASTContext &ctx, GenericParamList *genericParams) {
60586076
if (genericParams == nullptr)
60596077
return;
60606078

6061-
ExistentialTypeVisitor visitor(ctx, /*checkStatements=*/false);
6062-
visitor.visitRequirements(genericParams->getRequirements());
6079+
ExistentialTypeSyntaxChecker checker(ctx, /*checkStatements=*/false);
6080+
checker.checkRequirements(genericParams->getRequirements());
60636081
}
60646082

60656083
Type CustomAttrTypeRequest::evaluate(Evaluator &eval, CustomAttr *attr,

0 commit comments

Comments
 (0)