@@ -2045,7 +2045,7 @@ namespace {
20452045 }
20462046 }
20472047
2048- auto extInfo = closureEffects (closure);
2048+ auto extInfo = CS. closureEffects (closure);
20492049
20502050 // Closure expressions always have function type. In cases where a
20512051 // parameter or return type is omitted, a fresh type variable is used to
@@ -2501,214 +2501,6 @@ namespace {
25012501 return CS.getType (expr->getClosureBody ());
25022502 }
25032503
2504- // / Walk a closure AST to determine its effects.
2505- // /
2506- // / \returns a function's extended info describing the effects, as
2507- // / determined syntactically.
2508- FunctionType::ExtInfo closureEffects (ClosureExpr *expr) {
2509- // A walker that looks for 'try' and 'throw' expressions
2510- // that aren't nested within closures, nested declarations,
2511- // or exhaustive catches.
2512- class FindInnerThrows : public ASTWalker {
2513- ConstraintSystem &CS;
2514- DeclContext *DC;
2515- bool FoundThrow = false ;
2516-
2517- std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
2518- // If we've found a 'try', record it and terminate the traversal.
2519- if (isa<TryExpr>(expr)) {
2520- FoundThrow = true ;
2521- return { false , nullptr };
2522- }
2523-
2524- // Don't walk into a 'try!' or 'try?'.
2525- if (isa<ForceTryExpr>(expr) || isa<OptionalTryExpr>(expr)) {
2526- return { false , expr };
2527- }
2528-
2529- // Do not recurse into other closures.
2530- if (isa<ClosureExpr>(expr))
2531- return { false , expr };
2532-
2533- return { true , expr };
2534- }
2535-
2536- bool walkToDeclPre (Decl *decl) override {
2537- // Do not walk into function or type declarations.
2538- if (!isa<PatternBindingDecl>(decl))
2539- return false ;
2540-
2541- return true ;
2542- }
2543-
2544- bool isSyntacticallyExhaustive (DoCatchStmt *stmt) {
2545- for (auto catchClause : stmt->getCatches ()) {
2546- for (auto &LabelItem : catchClause->getMutableCaseLabelItems ()) {
2547- if (isSyntacticallyExhaustive (catchClause->getStartLoc (),
2548- LabelItem))
2549- return true ;
2550- }
2551- }
2552-
2553- return false ;
2554- }
2555-
2556- bool isSyntacticallyExhaustive (SourceLoc CatchLoc,
2557- CaseLabelItem &LabelItem) {
2558- // If it's obviously non-exhaustive, great.
2559- if (LabelItem.getGuardExpr ())
2560- return false ;
2561-
2562- // If we can show that it's exhaustive without full
2563- // type-checking, great.
2564- if (LabelItem.isSyntacticallyExhaustive ())
2565- return true ;
2566-
2567- // Okay, resolve the pattern.
2568- Pattern *pattern = LabelItem.getPattern ();
2569- if (!LabelItem.isPatternResolved ()) {
2570- pattern = TypeChecker::resolvePattern (pattern, CS.DC ,
2571- /* isStmtCondition*/ false );
2572- if (!pattern) return false ;
2573-
2574- // Save that aside while we explore the type.
2575- LabelItem.setPattern (pattern, /* resolved=*/ true );
2576- }
2577-
2578- // Require the pattern to have a particular shape: a number
2579- // of is-patterns applied to an irrefutable pattern.
2580- pattern = pattern->getSemanticsProvidingPattern ();
2581- while (auto isp = dyn_cast<IsPattern>(pattern)) {
2582- const Type castType = TypeResolution::forContextual (
2583- CS.DC , TypeResolverContext::InExpression,
2584- /* unboundTyOpener*/ nullptr )
2585- .resolveType (isp->getCastTypeRepr ());
2586- if (castType->hasError ()) {
2587- return false ;
2588- }
2589-
2590- if (!isp->hasSubPattern ()) {
2591- pattern = nullptr ;
2592- break ;
2593- } else {
2594- pattern = isp->getSubPattern ()->getSemanticsProvidingPattern ();
2595- }
2596- }
2597- if (pattern && pattern->isRefutablePattern ()) {
2598- return false ;
2599- }
2600-
2601- // Okay, now it should be safe to coerce the pattern.
2602- // Pull the top-level pattern back out.
2603- pattern = LabelItem.getPattern ();
2604- Type exnType = CS.getASTContext ().getErrorDecl ()->getDeclaredInterfaceType ();
2605-
2606- if (!exnType)
2607- return false ;
2608- auto contextualPattern =
2609- ContextualPattern::forRawPattern (pattern, DC);
2610- pattern = TypeChecker::coercePatternToType (
2611- contextualPattern, exnType, TypeResolverContext::InExpression);
2612- if (!pattern)
2613- return false ;
2614-
2615- LabelItem.setPattern (pattern, /* resolved=*/ true );
2616- return LabelItem.isSyntacticallyExhaustive ();
2617- }
2618-
2619- std::pair<bool , Stmt *> walkToStmtPre (Stmt *stmt) override {
2620- // If we've found a 'throw', record it and terminate the traversal.
2621- if (isa<ThrowStmt>(stmt)) {
2622- FoundThrow = true ;
2623- return { false , nullptr };
2624- }
2625-
2626- // Handle do/catch differently.
2627- if (auto doCatch = dyn_cast<DoCatchStmt>(stmt)) {
2628- // Only walk into the 'do' clause of a do/catch statement
2629- // if the catch isn't syntactically exhaustive.
2630- if (!isSyntacticallyExhaustive (doCatch)) {
2631- if (!doCatch->getBody ()->walk (*this ))
2632- return { false , nullptr };
2633- }
2634-
2635- // Walk into all the catch clauses.
2636- for (auto catchClause : doCatch->getCatches ()) {
2637- if (!catchClause->walk (*this ))
2638- return { false , nullptr };
2639- }
2640-
2641- // We've already walked all the children we care about.
2642- return { false , stmt };
2643- }
2644-
2645- return { true , stmt };
2646- }
2647-
2648- public:
2649- FindInnerThrows (ConstraintSystem &cs, DeclContext *dc)
2650- : CS(cs), DC(dc) {}
2651-
2652- bool foundThrow () { return FoundThrow; }
2653- };
2654-
2655- // A walker that looks for 'async' and 'await' expressions
2656- // that aren't nested within closures or nested declarations.
2657- class FindInnerAsync : public ASTWalker {
2658- bool FoundAsync = false ;
2659-
2660- std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
2661- // If we've found an 'await', record it and terminate the traversal.
2662- if (isa<AwaitExpr>(expr)) {
2663- FoundAsync = true ;
2664- return { false , nullptr };
2665- }
2666-
2667- // Do not recurse into other closures.
2668- if (isa<ClosureExpr>(expr))
2669- return { false , expr };
2670-
2671- return { true , expr };
2672- }
2673-
2674- bool walkToDeclPre (Decl *decl) override {
2675- // Do not walk into function or type declarations.
2676- if (!isa<PatternBindingDecl>(decl))
2677- return false ;
2678-
2679- return true ;
2680- }
2681-
2682- public:
2683- bool foundAsync () { return FoundAsync; }
2684- };
2685-
2686- // If either 'throws' or 'async' was explicitly specified, use that
2687- // set of effects.
2688- bool throws = expr->getThrowsLoc ().isValid ();
2689- bool async = expr->getAsyncLoc ().isValid ();
2690- if (throws || async) {
2691- return ASTExtInfoBuilder ()
2692- .withThrows (throws)
2693- .withAsync (async)
2694- .build ();
2695- }
2696-
2697- // Scan the body to determine the effects.
2698- auto body = expr->getBody ();
2699- if (!body)
2700- return FunctionType::ExtInfo ();
2701-
2702- auto throwFinder = FindInnerThrows (CS, expr);
2703- body->walk (throwFinder);
2704- auto asyncFinder = FindInnerAsync ();
2705- body->walk (asyncFinder);
2706- return ASTExtInfoBuilder ()
2707- .withThrows (throwFinder.foundThrow ())
2708- .withAsync (asyncFinder.foundAsync ())
2709- .build ();
2710- }
2711-
27122504 Type visitClosureExpr (ClosureExpr *closure) {
27132505 auto *locator = CS.getConstraintLocator (closure);
27142506 auto closureType = CS.createTypeVariable (locator, TVO_CanBindToNoEscape);
0 commit comments