Skip to content

Commit 40122df

Browse files
committed
[Sema] Add support for folding placeholders into TypeExprs
Move markAcceptableDiscardExprs into PreCheckExpr so that we can perform this analysis before we convert expressions like `_? = <value>` into `_ = <value>` since `_?` is now an expression with meaning, and we only want to perform this transformation when `_?` is on the LHS of an assignment
1 parent a5d0153 commit 40122df

File tree

2 files changed

+38
-33
lines changed

2 files changed

+38
-33
lines changed

lib/Sema/CSGen.cpp

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -792,9 +792,6 @@ namespace {
792792
= { nullptr, nullptr };
793793
unsigned currentEditorPlaceholderVariable = 0;
794794

795-
/// Keep track of acceptable DiscardAssignmentExpr's.
796-
llvm::SmallPtrSet<DiscardAssignmentExpr*, 2> CorrectDiscardAssignmentExprs;
797-
798795
/// A map from each UnresolvedMemberExpr to the respective (implicit) base
799796
/// found during our walk.
800797
llvm::MapVector<UnresolvedMemberExpr *, Type> UnresolvedBaseTypes;
@@ -2850,13 +2847,6 @@ namespace {
28502847
}
28512848

28522849
Type visitDiscardAssignmentExpr(DiscardAssignmentExpr *expr) {
2853-
/// Diagnose a '_' that isn't on the immediate LHS of an assignment.
2854-
if (!CorrectDiscardAssignmentExprs.count(expr)) {
2855-
auto &DE = CS.getASTContext().Diags;
2856-
DE.diagnose(expr->getLoc(), diag::discard_expr_outside_of_assignment);
2857-
return Type();
2858-
}
2859-
28602850
auto locator = CS.getConstraintLocator(expr);
28612851
auto typeVar = CS.createTypeVariable(locator, TVO_CanBindToNoEscape);
28622852
return LValueType::get(typeVar);
@@ -2894,25 +2884,6 @@ namespace {
28942884
}
28952885
}
28962886

2897-
/// Scout out the specified destination of an AssignExpr to recursively
2898-
/// identify DiscardAssignmentExpr in legal places. We can only allow them
2899-
/// in simple pattern-like expressions, so we reject anything complex here.
2900-
void markAcceptableDiscardExprs(Expr *E) {
2901-
if (!E) return;
2902-
2903-
if (auto *PE = dyn_cast<ParenExpr>(E))
2904-
return markAcceptableDiscardExprs(PE->getSubExpr());
2905-
if (auto *TE = dyn_cast<TupleExpr>(E)) {
2906-
for (auto &elt : TE->getElements())
2907-
markAcceptableDiscardExprs(elt);
2908-
return;
2909-
}
2910-
if (auto *DAE = dyn_cast<DiscardAssignmentExpr>(E))
2911-
CorrectDiscardAssignmentExprs.insert(DAE);
2912-
2913-
// Otherwise, we can't support this.
2914-
}
2915-
29162887
Type visitAssignExpr(AssignExpr *expr) {
29172888
// Handle invalid code.
29182889
if (!expr->getDest() || !expr->getSrc())
@@ -3498,9 +3469,6 @@ namespace {
34983469
return { false, expr };
34993470
}
35003471

3501-
if (auto *assignment = dyn_cast<AssignExpr>(expr))
3502-
CG.markAcceptableDiscardExprs(assignment->getDest());
3503-
35043472
return { true, expr };
35053473
}
35063474

lib/Sema/PreCheckExpr.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,9 @@ namespace {
811811
/// The expressions that are direct arguments of call expressions.
812812
llvm::SmallPtrSet<Expr *, 4> CallArgs;
813813

814+
/// Keep track of acceptable DiscardAssignmentExpr's.
815+
llvm::SmallPtrSet<DiscardAssignmentExpr*, 2> CorrectDiscardAssignmentExprs;
816+
814817
/// Simplify expressions which are type sugar productions that got parsed
815818
/// as expressions due to the parser not knowing which identifiers are
816819
/// type names.
@@ -935,6 +938,27 @@ namespace {
935938
StrangeInterpolationRewriter(getASTContext()));
936939
}
937940

941+
/// Scout out the specified destination of an AssignExpr to recursively
942+
/// identify DiscardAssignmentExpr in legal places. We can only allow them
943+
/// in simple pattern-like expressions, so we reject anything complex here.
944+
void markAcceptableDiscardExprs(Expr *E) {
945+
if (!E) return;
946+
947+
if (auto *PE = dyn_cast<ParenExpr>(E))
948+
return markAcceptableDiscardExprs(PE->getSubExpr());
949+
if (auto *TE = dyn_cast<TupleExpr>(E)) {
950+
for (auto &elt : TE->getElements())
951+
markAcceptableDiscardExprs(elt);
952+
return;
953+
}
954+
if (auto *BOE = dyn_cast<BindOptionalExpr>(E))
955+
return markAcceptableDiscardExprs(BOE->getSubExpr());
956+
if (auto *DAE = dyn_cast<DiscardAssignmentExpr>(E))
957+
CorrectDiscardAssignmentExprs.insert(DAE);
958+
959+
// Otherwise, we can't support this.
960+
}
961+
938962
public:
939963
PreCheckExpression(DeclContext *dc, Expr *parent,
940964
bool replaceInvalidRefsWithErrors)
@@ -1118,6 +1142,9 @@ namespace {
11181142
if (auto *ISLE = dyn_cast<InterpolatedStringLiteralExpr>(expr))
11191143
correctInterpolationIfStrange(ISLE);
11201144

1145+
if (auto *assignment = dyn_cast<AssignExpr>(expr))
1146+
markAcceptableDiscardExprs(assignment->getDest());
1147+
11211148
return finish(true, expr);
11221149
}
11231150

@@ -1244,7 +1271,8 @@ namespace {
12441271
// generating any of the unnecessary constraints.
12451272
if (auto BOE = dyn_cast<BindOptionalExpr>(expr)) {
12461273
if (auto DAE = dyn_cast<DiscardAssignmentExpr>(BOE->getSubExpr()))
1247-
return DAE;
1274+
if (CorrectDiscardAssignmentExprs.count(DAE))
1275+
return DAE;
12481276
}
12491277

12501278
// If this is a sugared type that needs to be folded into a single
@@ -1425,6 +1453,13 @@ TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) {
14251453
return simplifyNestedTypeExpr(UDE);
14261454
}
14271455

1456+
// Fold '_' into a placeholder type.
1457+
if (auto *DAE = dyn_cast<DiscardAssignmentExpr>(E)) {
1458+
auto *placeholderRepr =
1459+
new (getASTContext()) PlaceholderTypeRepr(DAE->getLoc());
1460+
return new (getASTContext()) TypeExpr(placeholderRepr);
1461+
}
1462+
14281463
// Fold T? into an optional type when T is a TypeExpr.
14291464
if (isa<OptionalEvaluationExpr>(E) || isa<BindOptionalExpr>(E)) {
14301465
TypeExpr *TyExpr;
@@ -1630,6 +1665,8 @@ TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) {
16301665
return nullptr;
16311666
if (auto *TyE = dyn_cast<TypeExpr>(E))
16321667
return TyE->getTypeRepr();
1668+
if (auto *DAE = dyn_cast<DiscardAssignmentExpr>(E))
1669+
return new (getASTContext()) PlaceholderTypeRepr(DAE->getLoc());
16331670
if (auto *TE = dyn_cast<TupleExpr>(E))
16341671
if (TE->getNumElements() == 0)
16351672
return TupleTypeRepr::createEmpty(ctx, TE->getSourceRange());

0 commit comments

Comments
 (0)