Skip to content

Commit cb82a46

Browse files
committed
[NFC] Stash Syntactic Information in EnumIsCaseExpr
After the TypeLocs were removed here, the TypeRepr from the IsExpr was the only thing providing access to syntactic information from the parent IsExpr. In order to support this, it was possible to construct a bizarre ConditionalCheckedCastExpr that contained both semantic and syntactic information. This doesn't comport with the rest of the casting nodes, which force you to pick one or the other. Since we're rewriting an IsExpr into a EnumIsCaseExpr, let's just stash the syntactic information there. This unblocks a bit of cleanup.
1 parent e9c3157 commit cb82a46

File tree

4 files changed

+38
-39
lines changed

4 files changed

+38
-39
lines changed

include/swift/AST/Expr.h

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4704,7 +4704,7 @@ class ForcedCheckedCastExpr final : public CheckedCastExpr {
47044704

47054705
/// Represents an explicit conditional checked cast, which converts
47064706
/// from a type to some subtype and produces an Optional value, which will be
4707-
/// .Some(x) if the cast succeeds, or .None if the cast fails.
4707+
/// .some(x) if the cast succeeds, or .none if the cast fails.
47084708
/// Spelled 'a as? T' and produces a value of type 'T?'.
47094709
class ConditionalCheckedCastExpr final : public CheckedCastExpr {
47104710
SourceLoc QuestionLoc;
@@ -4722,9 +4722,6 @@ class ConditionalCheckedCastExpr final : public CheckedCastExpr {
47224722
static ConditionalCheckedCastExpr *createImplicit(ASTContext &ctx, Expr *sub,
47234723
Type castTy);
47244724

4725-
static ConditionalCheckedCastExpr *
4726-
createImplicit(ASTContext &ctx, Expr *sub, TypeRepr *tyRepr, Type castTy);
4727-
47284725
/// Retrieve the location of the '?' that follows 'as'.
47294726
SourceLoc getQuestionLoc() const { return QuestionLoc; }
47304727

@@ -4911,20 +4908,21 @@ class IfExpr : public Expr {
49114908
/// a particular case.
49124909
class EnumIsCaseExpr : public Expr {
49134910
Expr *SubExpr;
4911+
TypeRepr *CaseRepr;
49144912
EnumElementDecl *Element;
49154913

49164914
public:
4917-
EnumIsCaseExpr(Expr *SubExpr, EnumElementDecl *Element)
4918-
: Expr(ExprKind::EnumIsCase, /*implicit*/ true),
4919-
SubExpr(SubExpr), Element(Element)
4920-
{}
4921-
4915+
EnumIsCaseExpr(Expr *SubExpr, TypeRepr *CaseRepr, EnumElementDecl *Element)
4916+
: Expr(ExprKind::EnumIsCase, /*implicit*/ true), SubExpr(SubExpr),
4917+
CaseRepr(CaseRepr), Element(Element) {}
4918+
49224919
Expr *getSubExpr() const { return SubExpr; }
49234920
void setSubExpr(Expr *e) { SubExpr = e; }
4924-
4921+
4922+
TypeRepr *getCaseTypeRepr() const { return CaseRepr; }
4923+
49254924
EnumElementDecl *getEnumElement() const { return Element; }
4926-
void setEnumElement(EnumElementDecl *elt) { Element = elt; }
4927-
4925+
49284926
SourceLoc getLoc() const { return SubExpr->getLoc(); }
49294927
SourceLoc getStartLoc() const { return SubExpr->getStartLoc(); }
49304928
SourceLoc getEndLoc() const { return SubExpr->getEndLoc(); }

lib/AST/ASTWalker.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,11 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
951951
return nullptr;
952952
E->setSubExpr(Sub);
953953
}
954-
954+
955+
if (auto *typerepr = E->getCaseTypeRepr())
956+
if (doIt(typerepr))
957+
return nullptr;
958+
955959
return E;
956960
}
957961

lib/AST/Expr.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,17 +1808,6 @@ ConditionalCheckedCastExpr::createImplicit(ASTContext &ctx, Expr *sub,
18081808
return expr;
18091809
}
18101810

1811-
ConditionalCheckedCastExpr *
1812-
ConditionalCheckedCastExpr::createImplicit(ASTContext &ctx, Expr *sub,
1813-
TypeRepr *tyRepr, Type castTy) {
1814-
auto *const expr = new (ctx) ConditionalCheckedCastExpr(
1815-
sub, SourceLoc(), SourceLoc(), new (ctx) TypeExpr(tyRepr));
1816-
expr->setType(OptionalType::get(castTy));
1817-
expr->setImplicit();
1818-
expr->setCastType(castTy);
1819-
return expr;
1820-
}
1821-
18221811
IsExpr *IsExpr::create(ASTContext &ctx, SourceLoc isLoc, TypeRepr *tyRepr) {
18231812
return new (ctx) IsExpr(nullptr, isLoc, new (ctx) TypeExpr(tyRepr));
18241813
}

lib/Sema/CSApply.cpp

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3574,12 +3574,14 @@ namespace {
35743574
castKind == CheckedCastKind::ArrayDowncast ||
35753575
castKind == CheckedCastKind::DictionaryDowncast ||
35763576
castKind == CheckedCastKind::SetDowncast) {
3577-
auto *const cast = ConditionalCheckedCastExpr::createImplicit(
3578-
ctx, sub, castTypeRepr, toType);
3577+
auto *const cast =
3578+
ConditionalCheckedCastExpr::createImplicit(ctx, sub, toType);
3579+
cast->setType(OptionalType::get(toType));
3580+
cast->setCastType(toType);
35793581
cs.setType(cast, cast->getType());
35803582

35813583
// Type-check this conditional case.
3582-
Expr *result = handleConditionalCheckedCastExpr(cast, true);
3584+
Expr *result = handleConditionalCheckedCastExpr(cast, castTypeRepr);
35833585
if (!result)
35843586
return nullptr;
35853587

@@ -3588,7 +3590,8 @@ namespace {
35883590

35893591
// Match the optional value against its `Some` case.
35903592
auto *someDecl = ctx.getOptionalSomeDecl();
3591-
auto isSomeExpr = new (ctx) EnumIsCaseExpr(result, someDecl);
3593+
auto isSomeExpr =
3594+
new (ctx) EnumIsCaseExpr(result, castTypeRepr, someDecl);
35923595
auto boolDecl = ctx.getBoolDecl();
35933596

35943597
if (!boolDecl) {
@@ -4010,40 +4013,45 @@ namespace {
40104013
}
40114014

40124015
Expr *visitConditionalCheckedCastExpr(ConditionalCheckedCastExpr *expr) {
4016+
// Simplify and update the type we're casting to.
4017+
auto *const castTypeRepr = expr->getCastTypeRepr();
4018+
const auto toType = simplifyType(cs.getType(castTypeRepr));
4019+
expr->setCastType(toType);
4020+
cs.setType(castTypeRepr, toType);
4021+
40134022
// If we need to insert a force-unwrap for coercions of the form
40144023
// 'as! T!', do so now.
40154024
if (hasForcedOptionalResult(expr)) {
4016-
auto *coerced = handleConditionalCheckedCastExpr(expr);
4025+
auto *coerced = handleConditionalCheckedCastExpr(expr, castTypeRepr);
40174026
if (!coerced)
40184027
return nullptr;
40194028

40204029
return coerceImplicitlyUnwrappedOptionalToValue(
40214030
coerced, cs.getType(coerced)->getOptionalObjectType());
40224031
}
40234032

4024-
return handleConditionalCheckedCastExpr(expr);
4033+
return handleConditionalCheckedCastExpr(expr, castTypeRepr);
40254034
}
40264035

40274036
Expr *handleConditionalCheckedCastExpr(ConditionalCheckedCastExpr *expr,
4028-
bool isInsideIsExpr = false) {
4037+
TypeRepr *castTypeRepr) {
4038+
assert(castTypeRepr &&
4039+
"cast requires TypeRepr; implicit casts are superfluous");
4040+
40294041
// The subexpression is always an rvalue.
40304042
auto &ctx = cs.getASTContext();
40314043
auto sub = cs.coerceToRValue(expr->getSubExpr());
40324044
expr->setSubExpr(sub);
40334045

40344046
// Simplify and update the type we're casting to.
4035-
auto *const castTypeRepr = expr->getCastTypeRepr();
4036-
40374047
const auto fromType = cs.getType(sub);
4038-
const auto toType = simplifyType(cs.getType(castTypeRepr));
4039-
expr->setCastType(toType);
4040-
cs.setType(castTypeRepr, toType);
4048+
const auto toType = expr->getCastType();
40414049

40424050
bool isSubExprLiteral = isa<LiteralExpr>(sub);
40434051
auto castContextKind =
4044-
(SuppressDiagnostics || isInsideIsExpr || isSubExprLiteral)
4045-
? CheckedCastContextKind::None
4046-
: CheckedCastContextKind::ConditionalCast;
4052+
(SuppressDiagnostics || expr->isImplicit() || isSubExprLiteral)
4053+
? CheckedCastContextKind::None
4054+
: CheckedCastContextKind::ConditionalCast;
40474055

40484056
auto castKind = TypeChecker::typeCheckCheckedCast(
40494057
fromType, toType, castContextKind, cs.DC, expr->getLoc(), sub,

0 commit comments

Comments
 (0)