@@ -419,6 +419,89 @@ static LabeledStmt *findBreakOrContinueStmtTarget(
419419 return nullptr ;
420420}
421421
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+
422505// / Type check the given 'if', 'while', or 'guard' statement condition.
423506// /
424507// / \param stmt The conditional statement to type-check, which will be modified
@@ -427,88 +510,12 @@ static LabeledStmt *findBreakOrContinueStmtTarget(
427510// / \returns true if an error occurred, false otherwise.
428511static bool typeCheckConditionForStatement (LabeledConditionalStmt *stmt,
429512 DeclContext *dc) {
430- auto &Context = dc->getASTContext ();
431513 bool hadError = false ;
432514 bool hadAnyFalsable = false ;
433515 auto cond = stmt->getCond ();
434516 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);
512519 }
513520
514521 // If the binding is not refutable, and there *is* an else, reject it as
0 commit comments