Skip to content

Commit 0153cff

Browse files
authored
Merge pull request swiftlang#33268 from rintaro/sema-condforstmt-localize
[NFC][Sema] Move typeCheckConditionForStatement() to TypeCheckStmt.cpp
2 parents 50a6666 + 00573dd commit 0153cff

File tree

3 files changed

+100
-103
lines changed

3 files changed

+100
-103
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 0 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,97 +2358,6 @@ bool TypeChecker::typeCheckCondition(Expr *&expr, DeclContext *dc) {
23582358
return !resultTy;
23592359
}
23602360

2361-
bool TypeChecker::typeCheckConditionForStatement(LabeledConditionalStmt *stmt,
2362-
DeclContext *dc) {
2363-
auto &Context = dc->getASTContext();
2364-
bool hadError = false;
2365-
bool hadAnyFalsable = false;
2366-
auto cond = stmt->getCond();
2367-
for (auto &elt : cond) {
2368-
if (elt.getKind() == StmtConditionElement::CK_Availability) {
2369-
hadAnyFalsable = true;
2370-
continue;
2371-
}
2372-
2373-
if (auto E = elt.getBooleanOrNull()) {
2374-
assert(!E->getType() && "the bool condition is already type checked");
2375-
hadError |= typeCheckCondition(E, dc);
2376-
elt.setBoolean(E);
2377-
hadAnyFalsable = true;
2378-
continue;
2379-
}
2380-
assert(elt.getKind() != StmtConditionElement::CK_Boolean);
2381-
2382-
// This is cleanup goop run on the various paths where type checking of the
2383-
// pattern binding fails.
2384-
auto typeCheckPatternFailed = [&] {
2385-
hadError = true;
2386-
elt.getPattern()->setType(ErrorType::get(Context));
2387-
elt.getInitializer()->setType(ErrorType::get(Context));
2388-
2389-
elt.getPattern()->forEachVariable([&](VarDecl *var) {
2390-
// Don't change the type of a variable that we've been able to
2391-
// compute a type for.
2392-
if (var->hasInterfaceType() && !var->isInvalid())
2393-
return;
2394-
var->setInvalid();
2395-
});
2396-
};
2397-
2398-
// Resolve the pattern.
2399-
assert(!elt.getPattern()->hasType() &&
2400-
"the pattern binding condition is already type checked");
2401-
auto *pattern = TypeChecker::resolvePattern(elt.getPattern(), dc,
2402-
/*isStmtCondition*/ true);
2403-
if (!pattern) {
2404-
typeCheckPatternFailed();
2405-
continue;
2406-
}
2407-
elt.setPattern(pattern);
2408-
2409-
// Check the pattern, it allows unspecified types because the pattern can
2410-
// provide type information.
2411-
auto contextualPattern = ContextualPattern::forRawPattern(pattern, dc);
2412-
Type patternType = TypeChecker::typeCheckPattern(contextualPattern);
2413-
if (patternType->hasError()) {
2414-
typeCheckPatternFailed();
2415-
continue;
2416-
}
2417-
2418-
// If the pattern didn't get a type, it's because we ran into some
2419-
// unknown types along the way. We'll need to check the initializer.
2420-
auto init = elt.getInitializer();
2421-
hadError |= TypeChecker::typeCheckBinding(pattern, init, dc, patternType);
2422-
elt.setPattern(pattern);
2423-
elt.setInitializer(init);
2424-
hadAnyFalsable |= pattern->isRefutablePattern();
2425-
}
2426-
2427-
// If the binding is not refutable, and there *is* an else, reject it as
2428-
// unreachable.
2429-
if (!hadAnyFalsable && !hadError) {
2430-
auto &diags = dc->getASTContext().Diags;
2431-
Diag<> msg = diag::invalid_diagnostic;
2432-
switch (stmt->getKind()) {
2433-
case StmtKind::If:
2434-
msg = diag::if_always_true;
2435-
break;
2436-
case StmtKind::While:
2437-
msg = diag::while_always_true;
2438-
break;
2439-
case StmtKind::Guard:
2440-
msg = diag::guard_always_succeeds;
2441-
break;
2442-
default:
2443-
llvm_unreachable("unknown LabeledConditionalStmt kind");
2444-
}
2445-
diags.diagnose(cond[0].getStartLoc(), msg);
2446-
}
2447-
2448-
stmt->setCond(cond);
2449-
return false;
2450-
}
2451-
24522361
/// Find the '~=` operator that can compare an expression inside a pattern to a
24532362
/// value of a given type.
24542363
bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC,

lib/Sema/TypeCheckStmt.cpp

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,103 @@ static LabeledStmt *findBreakOrContinueStmtTarget(
446446
return nullptr;
447447
}
448448

449+
/// Type check the given 'if', 'while', or 'guard' statement condition.
450+
///
451+
/// \param stmt The conditional statement to type-check, which will be modified
452+
/// in place.
453+
///
454+
/// \returns true if an error occurred, false otherwise.
455+
static bool typeCheckConditionForStatement(LabeledConditionalStmt *stmt,
456+
DeclContext *dc) {
457+
auto &Context = dc->getASTContext();
458+
bool hadError = false;
459+
bool hadAnyFalsable = false;
460+
auto cond = stmt->getCond();
461+
for (auto &elt : cond) {
462+
if (elt.getKind() == StmtConditionElement::CK_Availability) {
463+
hadAnyFalsable = true;
464+
continue;
465+
}
466+
467+
if (auto E = elt.getBooleanOrNull()) {
468+
assert(!E->getType() && "the bool condition is already type checked");
469+
hadError |= TypeChecker::typeCheckCondition(E, dc);
470+
elt.setBoolean(E);
471+
hadAnyFalsable = true;
472+
continue;
473+
}
474+
assert(elt.getKind() != StmtConditionElement::CK_Boolean);
475+
476+
// This is cleanup goop run on the various paths where type checking of the
477+
// pattern binding fails.
478+
auto typeCheckPatternFailed = [&] {
479+
hadError = true;
480+
elt.getPattern()->setType(ErrorType::get(Context));
481+
elt.getInitializer()->setType(ErrorType::get(Context));
482+
483+
elt.getPattern()->forEachVariable([&](VarDecl *var) {
484+
// Don't change the type of a variable that we've been able to
485+
// compute a type for.
486+
if (var->hasInterfaceType() && !var->isInvalid())
487+
return;
488+
var->setInvalid();
489+
});
490+
};
491+
492+
// Resolve the pattern.
493+
assert(!elt.getPattern()->hasType() &&
494+
"the pattern binding condition is already type checked");
495+
auto *pattern = TypeChecker::resolvePattern(elt.getPattern(), dc,
496+
/*isStmtCondition*/ true);
497+
if (!pattern) {
498+
typeCheckPatternFailed();
499+
continue;
500+
}
501+
elt.setPattern(pattern);
502+
503+
// Check the pattern, it allows unspecified types because the pattern can
504+
// provide type information.
505+
auto contextualPattern = ContextualPattern::forRawPattern(pattern, dc);
506+
Type patternType = TypeChecker::typeCheckPattern(contextualPattern);
507+
if (patternType->hasError()) {
508+
typeCheckPatternFailed();
509+
continue;
510+
}
511+
512+
// If the pattern didn't get a type, it's because we ran into some
513+
// unknown types along the way. We'll need to check the initializer.
514+
auto init = elt.getInitializer();
515+
hadError |= TypeChecker::typeCheckBinding(pattern, init, dc, patternType);
516+
elt.setPattern(pattern);
517+
elt.setInitializer(init);
518+
hadAnyFalsable |= pattern->isRefutablePattern();
519+
}
520+
521+
// If the binding is not refutable, and there *is* an else, reject it as
522+
// unreachable.
523+
if (!hadAnyFalsable && !hadError) {
524+
auto &diags = dc->getASTContext().Diags;
525+
Diag<> msg = diag::invalid_diagnostic;
526+
switch (stmt->getKind()) {
527+
case StmtKind::If:
528+
msg = diag::if_always_true;
529+
break;
530+
case StmtKind::While:
531+
msg = diag::while_always_true;
532+
break;
533+
case StmtKind::Guard:
534+
msg = diag::guard_always_succeeds;
535+
break;
536+
default:
537+
llvm_unreachable("unknown LabeledConditionalStmt kind");
538+
}
539+
diags.diagnose(cond[0].getStartLoc(), msg);
540+
}
541+
542+
stmt->setCond(cond);
543+
return false;
544+
}
545+
449546
namespace {
450547
class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
451548
public:
@@ -785,7 +882,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
785882
}
786883

787884
Stmt *visitIfStmt(IfStmt *IS) {
788-
TypeChecker::typeCheckConditionForStatement(IS, DC);
885+
typeCheckConditionForStatement(IS, DC);
789886

790887
AddLabeledStmt ifNest(*this, IS);
791888

@@ -802,7 +899,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
802899
}
803900

804901
Stmt *visitGuardStmt(GuardStmt *GS) {
805-
TypeChecker::typeCheckConditionForStatement(GS, DC);
902+
typeCheckConditionForStatement(GS, DC);
806903

807904
Stmt *S = GS->getBody();
808905
typeCheckStmt(S);
@@ -819,7 +916,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
819916
}
820917

821918
Stmt *visitWhileStmt(WhileStmt *WS) {
822-
TypeChecker::typeCheckConditionForStatement(WS, DC);
919+
typeCheckConditionForStatement(WS, DC);
823920

824921
AddLabeledStmt loopNest(*this, WS);
825922
Stmt *S = WS->getBody();

lib/Sema/TypeChecker.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -691,15 +691,6 @@ void checkSwitchExhaustiveness(const SwitchStmt *stmt, const DeclContext *DC,
691691
/// \returns true if an error occurred, false otherwise.
692692
bool typeCheckCondition(Expr *&expr, DeclContext *dc);
693693

694-
/// Type check the given 'if', 'while', or 'guard' statement condition.
695-
///
696-
/// \param stmt The conditional statement to type-check, which will be modified
697-
/// in place.
698-
///
699-
/// \returns true if an error occurred, false otherwise.
700-
bool typeCheckConditionForStatement(LabeledConditionalStmt *stmt,
701-
DeclContext *dc);
702-
703694
/// Determine the semantics of a checked cast operation.
704695
///
705696
/// \param fromType The source type of the cast.

0 commit comments

Comments
 (0)