@@ -2045,7 +2045,7 @@ namespace {
2045
2045
}
2046
2046
}
2047
2047
2048
- auto extInfo = closureEffects (closure);
2048
+ auto extInfo = CS. closureEffects (closure);
2049
2049
2050
2050
// Closure expressions always have function type. In cases where a
2051
2051
// parameter or return type is omitted, a fresh type variable is used to
@@ -2501,214 +2501,6 @@ namespace {
2501
2501
return CS.getType (expr->getClosureBody ());
2502
2502
}
2503
2503
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
-
2712
2504
Type visitClosureExpr (ClosureExpr *closure) {
2713
2505
auto *locator = CS.getConstraintLocator (closure);
2714
2506
auto closureType = CS.createTypeVariable (locator, TVO_CanBindToNoEscape);
0 commit comments