Skip to content

Commit 922b206

Browse files
committed
Revert "[NFC, Typechecker] Remove UnsupportedProtocolVisitor and checkUnsupportedProtocolType()"
This reverts commit 15f88e9.
1 parent bbbb131 commit 922b206

File tree

4 files changed

+144
-0
lines changed

4 files changed

+144
-0
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3361,6 +3361,8 @@ static void checkSwitch(ASTContext &ctx, const SwitchStmt *stmt) {
33613361
// We want to warn about "case .Foo, .Bar where 1 != 100:" since the where
33623362
// clause only applies to the second case, and this is surprising.
33633363
for (auto cs : stmt->getCases()) {
3364+
TypeChecker::checkUnsupportedProtocolType(ctx, cs);
3365+
33643366
// The case statement can have multiple case items, each can have a where.
33653367
// If we find a "where", and there is a preceding item without a where, and
33663368
// if they are on the same source line, then warn.
@@ -4839,6 +4841,8 @@ void swift::performSyntacticExprDiagnostics(const Expr *E,
48394841
void swift::performStmtDiagnostics(const Stmt *S, DeclContext *DC) {
48404842
auto &ctx = DC->getASTContext();
48414843

4844+
TypeChecker::checkUnsupportedProtocolType(ctx, const_cast<Stmt *>(S));
4845+
48424846
if (auto switchStmt = dyn_cast<SwitchStmt>(S))
48434847
checkSwitch(ctx, switchStmt);
48444848

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,8 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
16961696

16971697
DeclVisitor<DeclChecker>::visit(decl);
16981698

1699+
TypeChecker::checkUnsupportedProtocolType(decl);
1700+
16991701
if (auto VD = dyn_cast<ValueDecl>(decl)) {
17001702
auto &Context = getASTContext();
17011703
TypeChecker::checkForForbiddenPrefix(Context, VD->getBaseName());

lib/Sema/TypeCheckType.cpp

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3943,6 +3943,128 @@ Type TypeChecker::substMemberTypeWithBase(ModuleDecl *module,
39433943
return resultType;
39443944
}
39453945

3946+
namespace {
3947+
3948+
class UnsupportedProtocolVisitor
3949+
: public TypeReprVisitor<UnsupportedProtocolVisitor>, public ASTWalker
3950+
{
3951+
ASTContext &Ctx;
3952+
bool checkStatements;
3953+
bool hitTopStmt;
3954+
3955+
public:
3956+
UnsupportedProtocolVisitor(ASTContext &ctx, bool checkStatements)
3957+
: Ctx(ctx), checkStatements(checkStatements), hitTopStmt(false) { }
3958+
3959+
bool walkToTypeReprPre(TypeRepr *T) override {
3960+
if (T->isInvalid())
3961+
return false;
3962+
if (auto compound = dyn_cast<CompoundIdentTypeRepr>(T)) {
3963+
// Only visit the last component to check, because nested typealiases in
3964+
// existentials are okay.
3965+
visit(compound->getComponentRange().back());
3966+
return false;
3967+
}
3968+
// Arbitrary protocol constraints are OK on opaque types.
3969+
if (isa<OpaqueReturnTypeRepr>(T))
3970+
return false;
3971+
3972+
visit(T);
3973+
return true;
3974+
}
3975+
3976+
std::pair<bool, Stmt*> walkToStmtPre(Stmt *S) override {
3977+
if (checkStatements && !hitTopStmt) {
3978+
hitTopStmt = true;
3979+
return { true, S };
3980+
}
3981+
3982+
return { false, S };
3983+
}
3984+
3985+
bool walkToDeclPre(Decl *D) override {
3986+
return !checkStatements;
3987+
}
3988+
3989+
void visitTypeRepr(TypeRepr *T) {
3990+
// Do nothing for all TypeReprs except the ones listed below.
3991+
}
3992+
3993+
void visitIdentTypeRepr(IdentTypeRepr *T) {
3994+
return;
3995+
}
3996+
3997+
void visitRequirements(ArrayRef<RequirementRepr> reqts) {
3998+
for (auto reqt : reqts) {
3999+
if (reqt.getKind() == RequirementReprKind::SameType) {
4000+
if (auto *repr = reqt.getFirstTypeRepr())
4001+
repr->walk(*this);
4002+
if (auto *repr = reqt.getSecondTypeRepr())
4003+
repr->walk(*this);
4004+
}
4005+
}
4006+
}
4007+
};
4008+
4009+
} // end anonymous namespace
4010+
4011+
void TypeChecker::checkUnsupportedProtocolType(Decl *decl) {
4012+
if (!decl || decl->isInvalid())
4013+
return;
4014+
4015+
auto &ctx = decl->getASTContext();
4016+
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(decl)) {
4017+
checkUnsupportedProtocolType(ctx, protocolDecl->getTrailingWhereClause());
4018+
} else if (auto *genericDecl = dyn_cast<GenericTypeDecl>(decl)) {
4019+
checkUnsupportedProtocolType(ctx, genericDecl->getGenericParams());
4020+
checkUnsupportedProtocolType(ctx, genericDecl->getTrailingWhereClause());
4021+
} else if (auto *assocType = dyn_cast<AssociatedTypeDecl>(decl)) {
4022+
checkUnsupportedProtocolType(ctx, assocType->getTrailingWhereClause());
4023+
} else if (auto *extDecl = dyn_cast<ExtensionDecl>(decl)) {
4024+
checkUnsupportedProtocolType(ctx, extDecl->getTrailingWhereClause());
4025+
} else if (auto *subscriptDecl = dyn_cast<SubscriptDecl>(decl)) {
4026+
checkUnsupportedProtocolType(ctx, subscriptDecl->getGenericParams());
4027+
checkUnsupportedProtocolType(ctx, subscriptDecl->getTrailingWhereClause());
4028+
} else if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(decl)) {
4029+
if (!isa<AccessorDecl>(funcDecl)) {
4030+
checkUnsupportedProtocolType(ctx, funcDecl->getGenericParams());
4031+
checkUnsupportedProtocolType(ctx, funcDecl->getTrailingWhereClause());
4032+
}
4033+
}
4034+
4035+
if (isa<TypeDecl>(decl) || isa<ExtensionDecl>(decl))
4036+
return;
4037+
4038+
UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/false);
4039+
decl->walk(visitor);
4040+
}
4041+
4042+
void TypeChecker::checkUnsupportedProtocolType(ASTContext &ctx, Stmt *stmt) {
4043+
if (!stmt)
4044+
return;
4045+
4046+
UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/true);
4047+
stmt->walk(visitor);
4048+
}
4049+
4050+
void TypeChecker::checkUnsupportedProtocolType(
4051+
ASTContext &ctx, TrailingWhereClause *whereClause) {
4052+
if (whereClause == nullptr)
4053+
return;
4054+
4055+
UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/false);
4056+
visitor.visitRequirements(whereClause->getRequirements());
4057+
}
4058+
4059+
void TypeChecker::checkUnsupportedProtocolType(
4060+
ASTContext &ctx, GenericParamList *genericParams) {
4061+
if (genericParams == nullptr)
4062+
return;
4063+
4064+
UnsupportedProtocolVisitor visitor(ctx, /*checkStatements=*/false);
4065+
visitor.visitRequirements(genericParams->getRequirements());
4066+
}
4067+
39464068
Type CustomAttrTypeRequest::evaluate(Evaluator &eval, CustomAttr *attr,
39474069
DeclContext *dc,
39484070
CustomAttrTypeKind typeKind) const {

lib/Sema/TypeChecker.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,22 @@ Type getOptionalType(SourceLoc loc, Type elementType);
245245
Expr *resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *Context,
246246
bool replaceInvalidRefsWithErrors);
247247

248+
/// Check for unsupported protocol types in the given declaration.
249+
void checkUnsupportedProtocolType(Decl *decl);
250+
251+
/// Check for unsupported protocol types in the given statement.
252+
void checkUnsupportedProtocolType(ASTContext &ctx, Stmt *stmt);
253+
254+
/// Check for unsupported protocol types in the given generic requirement
255+
/// list.
256+
void checkUnsupportedProtocolType(ASTContext &ctx,
257+
TrailingWhereClause *whereClause);
258+
259+
/// Check for unsupported protocol types in the given generic requirement
260+
/// list.
261+
void checkUnsupportedProtocolType(ASTContext &ctx,
262+
GenericParamList *genericParams);
263+
248264
/// Substitute the given base type into the type of the given nested type,
249265
/// producing the effective type that the nested type will have.
250266
///

0 commit comments

Comments
 (0)