Skip to content

Commit c0ae9b9

Browse files
committed
Move out-of-place ThenStmt checking to constraint generation
1 parent 6ee44f0 commit c0ae9b9

File tree

7 files changed

+69
-21
lines changed

7 files changed

+69
-21
lines changed

include/swift/Sema/CSFix.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,9 @@ enum class FixKind : uint8_t {
458458
/// Ignore an attempt to specialize non-generic type.
459459
AllowConcreteTypeSpecialization,
460460

461+
/// Ignore an out-of-place \c then statement.
462+
IgnoreOutOfPlaceThenStmt,
463+
461464
/// Ignore situations when provided number of generic arguments didn't match
462465
/// expected number of parameters.
463466
IgnoreGenericSpecializationArityMismatch,
@@ -3684,6 +3687,29 @@ class AllowConcreteTypeSpecialization final : public ConstraintFix {
36843687
}
36853688
};
36863689

3690+
class IgnoreOutOfPlaceThenStmt final : public ConstraintFix {
3691+
IgnoreOutOfPlaceThenStmt(ConstraintSystem &cs, ConstraintLocator *locator)
3692+
: ConstraintFix(cs, FixKind::IgnoreOutOfPlaceThenStmt, locator) {}
3693+
3694+
public:
3695+
std::string getName() const override {
3696+
return "ignore out-of-place ThenStmt";
3697+
}
3698+
3699+
bool diagnose(const Solution &solution, bool asNote = false) const override;
3700+
3701+
bool diagnoseForAmbiguity(CommonFixesArray commonFixes) const override {
3702+
return diagnose(*commonFixes.front().first);
3703+
}
3704+
3705+
static IgnoreOutOfPlaceThenStmt *create(ConstraintSystem &cs,
3706+
ConstraintLocator *locator);
3707+
3708+
static bool classof(const ConstraintFix *fix) {
3709+
return fix->getKind() == FixKind::IgnoreOutOfPlaceThenStmt;
3710+
}
3711+
};
3712+
36873713
class IgnoreGenericSpecializationArityMismatch final : public ConstraintFix {
36883714
ValueDecl *D;
36893715
unsigned NumParams;

lib/Sema/CSDiagnostics.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9158,6 +9158,11 @@ bool ConcreteTypeSpecialization::diagnoseAsError() {
91589158
return true;
91599159
}
91609160

9161+
bool OutOfPlaceThenStmtFailure::diagnoseAsError() {
9162+
emitDiagnostic(diag::out_of_place_then_stmt);
9163+
return true;
9164+
}
9165+
91619166
bool InvalidTypeSpecializationArity::diagnoseAsError() {
91629167
emitDiagnostic(diag::type_parameter_count_mismatch, D->getBaseIdentifier(),
91639168
NumParams, NumArgs, NumArgs < NumParams, HasParameterPack);

lib/Sema/CSDiagnostics.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3073,6 +3073,16 @@ class ConcreteTypeSpecialization final : public FailureDiagnostic {
30733073
bool diagnoseAsError() override;
30743074
};
30753075

3076+
/// Diagnose an out-of-place ThenStmt.
3077+
class OutOfPlaceThenStmtFailure final : public FailureDiagnostic {
3078+
public:
3079+
OutOfPlaceThenStmtFailure(const Solution &solution,
3080+
ConstraintLocator *locator)
3081+
: FailureDiagnostic(solution, locator) {}
3082+
3083+
bool diagnoseAsError() override;
3084+
};
3085+
30763086
/// Diagnose attempts to specialize with invalid number of generic arguments:
30773087
///
30783088
/// \code

lib/Sema/CSFix.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2843,6 +2843,18 @@ AllowConcreteTypeSpecialization::create(ConstraintSystem &cs, Type concreteTy,
28432843
AllowConcreteTypeSpecialization(cs, concreteTy, locator);
28442844
}
28452845

2846+
bool IgnoreOutOfPlaceThenStmt::diagnose(const Solution &solution,
2847+
bool asNote) const {
2848+
OutOfPlaceThenStmtFailure failure(solution, getLocator());
2849+
return failure.diagnose(asNote);
2850+
}
2851+
2852+
IgnoreOutOfPlaceThenStmt *
2853+
IgnoreOutOfPlaceThenStmt::create(ConstraintSystem &cs,
2854+
ConstraintLocator *locator) {
2855+
return new (cs.getAllocator()) IgnoreOutOfPlaceThenStmt(cs, locator);
2856+
}
2857+
28462858
bool IgnoreGenericSpecializationArityMismatch::diagnose(
28472859
const Solution &solution, bool asNote) const {
28482860
InvalidTypeSpecializationArity failure(solution, D, NumParams, NumArgs,

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15291,6 +15291,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1529115291
case FixKind::DestructureTupleToMatchPackExpansionParameter:
1529215292
case FixKind::AllowValueExpansionWithoutPackReferences:
1529315293
case FixKind::IgnoreInvalidPatternInExpr:
15294+
case FixKind::IgnoreOutOfPlaceThenStmt:
1529415295
case FixKind::IgnoreMissingEachKeyword:
1529515296
llvm_unreachable("handled elsewhere");
1529615297
}

lib/Sema/CSSyntacticElement.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,11 +1255,21 @@ class SyntacticElementConstraintGenerator
12551255
auto *resultExpr = thenStmt->getResult();
12561256
auto contextInfo = cs.getContextualTypeInfo(resultExpr);
12571257

1258+
// First check to make sure the ThenStmt is in a valid position.
1259+
SmallVector<ThenStmt *, 4> validThenStmts;
1260+
if (auto SVE = context.getAsSingleValueStmtExpr())
1261+
(void)SVE.get()->getThenStmts(validThenStmts);
1262+
1263+
if (!llvm::is_contained(validThenStmts, thenStmt)) {
1264+
auto *thenLoc = cs.getConstraintLocator(thenStmt);
1265+
(void)cs.recordFix(IgnoreOutOfPlaceThenStmt::create(cs, thenLoc));
1266+
}
1267+
12581268
// For an if/switch expression, if the contextual type for the branch is
12591269
// still a type variable, we can drop it. This avoids needlessly
12601270
// propagating the type of the branch to subsequent branches, instead
12611271
// we'll let the join handle the conversion.
1262-
if (contextInfo && isExpr<SingleValueStmtExpr>(locator->getAnchor())) {
1272+
if (contextInfo) {
12631273
auto contextualFixedTy =
12641274
cs.getFixedTypeRecursive(contextInfo->getType(), /*wantRValue*/ true);
12651275
if (contextualFixedTy->isTypeVariableOrMember())
@@ -2176,29 +2186,22 @@ class SyntacticElementSolutionApplication
21762186
}
21772187

21782188
ASTNode visitThenStmt(ThenStmt *thenStmt) {
2179-
// Note we're defensive here over whether we're in a SingleValueStmtExpr,
2180-
// as we don't diagnose out-of-place ThenStmts until MiscDiagnostics. If we
2181-
// have an out-of-place ThenStmt, just rewrite the expr without a contextual
2182-
// type.
21832189
auto SVE = context.getAsSingleValueStmtExpr();
2184-
auto ty = SVE ? solution.getResolvedType(SVE.get()) : Type();
2190+
assert(SVE && "Should have diagnosed an out-of-place ThenStmt");
2191+
auto ty = solution.getResolvedType(SVE.get());
21852192

21862193
// We need to fixup the conversion type to the full result type,
21872194
// not the branch result type. This is necessary as there may be
21882195
// an additional conversion required for the branch.
21892196
auto target = solution.getTargetFor(thenStmt->getResult());
2190-
if (ty)
2191-
target->setExprConversionType(ty);
2197+
target->setExprConversionType(ty);
21922198

21932199
auto *resultExpr = thenStmt->getResult();
21942200
if (auto newResultTarget = rewriteTarget(*target))
21952201
resultExpr = newResultTarget->getAsExpr();
21962202

21972203
thenStmt->setResult(resultExpr);
21982204

2199-
if (!SVE)
2200-
return thenStmt;
2201-
22022205
// If the expression was typed as Void, its branches are effectively
22032206
// discarded, so treat them as ignored expressions.
22042207
if (ty->lookThroughAllOptionalTypes()->isVoid()) {

lib/Sema/MiscDiagnostics.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3846,7 +3846,6 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
38463846
ASTContext &Ctx;
38473847
DiagnosticEngine &Diags;
38483848
llvm::DenseSet<SingleValueStmtExpr *> ValidSingleValueStmtExprs;
3849-
llvm::DenseSet<ThenStmt *> ValidThenStmts;
38503849

38513850
public:
38523851
SingleValueStmtUsageChecker(
@@ -3919,11 +3918,6 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
39193918
SVE->getStmt()->getKind());
39203919
}
39213920

3922-
// Mark the valid 'then' statements.
3923-
SmallVector<ThenStmt *, 4> scratch;
3924-
for (auto *thenStmt : SVE->getThenStmts(scratch))
3925-
ValidThenStmts.insert(thenStmt);
3926-
39273921
// Diagnose invalid SingleValueStmtExprs. This should only happen for
39283922
// expressions in positions that we didn't support before
39293923
// (e.g assignment or *explicit* return).
@@ -4008,11 +4002,8 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
40084002
if (auto *TS = dyn_cast<ThrowStmt>(S))
40094003
markValidSingleValueStmt(TS->getSubExpr());
40104004

4011-
if (auto *TS = dyn_cast<ThenStmt>(S)) {
4005+
if (auto *TS = dyn_cast<ThenStmt>(S))
40124006
markValidSingleValueStmt(TS->getResult());
4013-
if (!ValidThenStmts.contains(TS))
4014-
Diags.diagnose(TS->getThenLoc(), diag::out_of_place_then_stmt);
4015-
}
40164007

40174008
return Action::Continue(S);
40184009
}

0 commit comments

Comments
 (0)