@@ -419,6 +419,89 @@ static LabeledStmt *findBreakOrContinueStmtTarget(
419
419
return nullptr ;
420
420
}
421
421
422
+ bool TypeChecker::typeCheckStmtConditionElement (StmtConditionElement &elt,
423
+ bool &isFalsable,
424
+ DeclContext *dc) {
425
+ auto &Context = dc->getASTContext ();
426
+ if (elt.getKind () == StmtConditionElement::CK_Availability) {
427
+ isFalsable = true ;
428
+
429
+ // Reject inlinable code using availability macros.
430
+ PoundAvailableInfo *info = elt.getAvailability ();
431
+ if (auto *decl = dc->getAsDecl ()) {
432
+ if (decl->getAttrs ().hasAttribute <InlinableAttr>() ||
433
+ decl->getAttrs ().hasAttribute <AlwaysEmitIntoClientAttr>())
434
+ for (auto queries : info->getQueries ())
435
+ if (auto availSpec =
436
+ dyn_cast<PlatformVersionConstraintAvailabilitySpec>(queries))
437
+ if (availSpec->getMacroLoc ().isValid ()) {
438
+ Context.Diags .diagnose (
439
+ availSpec->getMacroLoc (),
440
+ swift::diag::availability_macro_in_inlinable,
441
+ decl->getDescriptiveKind ());
442
+ break ;
443
+ }
444
+ }
445
+
446
+ return false ;
447
+ }
448
+
449
+ if (auto E = elt.getBooleanOrNull ()) {
450
+ assert (!E->getType () && " the bool condition is already type checked" );
451
+ bool hadError = TypeChecker::typeCheckCondition (E, dc);
452
+ elt.setBoolean (E);
453
+ isFalsable = true ;
454
+ return hadError;
455
+ }
456
+ assert (elt.getKind () != StmtConditionElement::CK_Boolean);
457
+
458
+ // This is cleanup goop run on the various paths where type checking of the
459
+ // pattern binding fails.
460
+ auto typeCheckPatternFailed = [&] {
461
+ elt.getPattern ()->setType (ErrorType::get (Context));
462
+ elt.getInitializer ()->setType (ErrorType::get (Context));
463
+
464
+ elt.getPattern ()->forEachVariable ([&](VarDecl *var) {
465
+ // Don't change the type of a variable that we've been able to
466
+ // compute a type for.
467
+ if (var->hasInterfaceType () && !var->isInvalid ())
468
+ return ;
469
+ var->setInvalid ();
470
+ });
471
+ };
472
+
473
+ // Resolve the pattern.
474
+ assert (!elt.getPattern ()->hasType () &&
475
+ " the pattern binding condition is already type checked" );
476
+ auto *pattern = TypeChecker::resolvePattern (elt.getPattern (), dc,
477
+ /* isStmtCondition*/ true );
478
+ if (!pattern) {
479
+ typeCheckPatternFailed ();
480
+ return true ;
481
+ }
482
+ elt.setPattern (pattern);
483
+
484
+ TypeChecker::diagnoseDuplicateBoundVars (pattern);
485
+
486
+ // Check the pattern, it allows unspecified types because the pattern can
487
+ // provide type information.
488
+ auto contextualPattern = ContextualPattern::forRawPattern (pattern, dc);
489
+ Type patternType = TypeChecker::typeCheckPattern (contextualPattern);
490
+ if (patternType->hasError ()) {
491
+ typeCheckPatternFailed ();
492
+ return true ;
493
+ }
494
+
495
+ // If the pattern didn't get a type, it's because we ran into some
496
+ // unknown types along the way. We'll need to check the initializer.
497
+ auto init = elt.getInitializer ();
498
+ bool hadError = TypeChecker::typeCheckBinding (pattern, init, dc, patternType);
499
+ elt.setPattern (pattern);
500
+ elt.setInitializer (init);
501
+ isFalsable |= pattern->isRefutablePattern ();
502
+ return hadError;
503
+ }
504
+
422
505
// / Type check the given 'if', 'while', or 'guard' statement condition.
423
506
// /
424
507
// / \param stmt The conditional statement to type-check, which will be modified
@@ -427,88 +510,12 @@ static LabeledStmt *findBreakOrContinueStmtTarget(
427
510
// / \returns true if an error occurred, false otherwise.
428
511
static bool typeCheckConditionForStatement (LabeledConditionalStmt *stmt,
429
512
DeclContext *dc) {
430
- auto &Context = dc->getASTContext ();
431
513
bool hadError = false ;
432
514
bool hadAnyFalsable = false ;
433
515
auto cond = stmt->getCond ();
434
516
for (auto &elt : cond) {
435
- if (elt.getKind () == StmtConditionElement::CK_Availability) {
436
- hadAnyFalsable = true ;
437
-
438
- // Reject inlinable code using availability macros.
439
- PoundAvailableInfo *info = elt.getAvailability ();
440
- if (auto *decl = dc->getAsDecl ()) {
441
- if (decl->getAttrs ().hasAttribute <InlinableAttr>() ||
442
- decl->getAttrs ().hasAttribute <AlwaysEmitIntoClientAttr>())
443
- for (auto queries : info->getQueries ())
444
- if (auto availSpec =
445
- dyn_cast<PlatformVersionConstraintAvailabilitySpec>(queries))
446
- if (availSpec->getMacroLoc ().isValid ()) {
447
- Context.Diags .diagnose (
448
- availSpec->getMacroLoc (),
449
- swift::diag::availability_macro_in_inlinable,
450
- decl->getDescriptiveKind ());
451
- break ;
452
- }
453
- }
454
-
455
- continue ;
456
- }
457
-
458
- if (auto E = elt.getBooleanOrNull ()) {
459
- assert (!E->getType () && " the bool condition is already type checked" );
460
- hadError |= TypeChecker::typeCheckCondition (E, dc);
461
- elt.setBoolean (E);
462
- hadAnyFalsable = true ;
463
- continue ;
464
- }
465
- assert (elt.getKind () != StmtConditionElement::CK_Boolean);
466
-
467
- // This is cleanup goop run on the various paths where type checking of the
468
- // pattern binding fails.
469
- auto typeCheckPatternFailed = [&] {
470
- hadError = true ;
471
- elt.getPattern ()->setType (ErrorType::get (Context));
472
- elt.getInitializer ()->setType (ErrorType::get (Context));
473
-
474
- elt.getPattern ()->forEachVariable ([&](VarDecl *var) {
475
- // Don't change the type of a variable that we've been able to
476
- // compute a type for.
477
- if (var->hasInterfaceType () && !var->isInvalid ())
478
- return ;
479
- var->setInvalid ();
480
- });
481
- };
482
-
483
- // Resolve the pattern.
484
- assert (!elt.getPattern ()->hasType () &&
485
- " the pattern binding condition is already type checked" );
486
- auto *pattern = TypeChecker::resolvePattern (elt.getPattern (), dc,
487
- /* isStmtCondition*/ true );
488
- if (!pattern) {
489
- typeCheckPatternFailed ();
490
- continue ;
491
- }
492
- elt.setPattern (pattern);
493
-
494
- TypeChecker::diagnoseDuplicateBoundVars (pattern);
495
-
496
- // Check the pattern, it allows unspecified types because the pattern can
497
- // provide type information.
498
- auto contextualPattern = ContextualPattern::forRawPattern (pattern, dc);
499
- Type patternType = TypeChecker::typeCheckPattern (contextualPattern);
500
- if (patternType->hasError ()) {
501
- typeCheckPatternFailed ();
502
- continue ;
503
- }
504
-
505
- // If the pattern didn't get a type, it's because we ran into some
506
- // unknown types along the way. We'll need to check the initializer.
507
- auto init = elt.getInitializer ();
508
- hadError |= TypeChecker::typeCheckBinding (pattern, init, dc, patternType);
509
- elt.setPattern (pattern);
510
- elt.setInitializer (init);
511
- hadAnyFalsable |= pattern->isRefutablePattern ();
517
+ hadError |=
518
+ TypeChecker::typeCheckStmtConditionElement (elt, hadAnyFalsable, dc);
512
519
}
513
520
514
521
// If the binding is not refutable, and there *is* an else, reject it as
0 commit comments