@@ -220,11 +220,6 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
220
220
std::pair<Type, ContextualTypePurpose>
221
221
validateContextualType (Type contextualType, ContextualTypePurpose CTP);
222
222
223
- // / Check the specified closure to see if it is a multi-statement closure with
224
- // / an uninferred type. If so, diagnose the problem with an error and return
225
- // / true.
226
- bool diagnoseAmbiguousMultiStatementClosure (ClosureExpr *closure);
227
-
228
223
// / Given a result of name lookup that had no viable results, diagnose the
229
224
// / unviable ones.
230
225
void diagnoseUnviableLookupResults (MemberLookupResult &lookupResults,
@@ -2694,138 +2689,6 @@ FailureDiagnosis::validateContextualType(Type contextualType,
2694
2689
return {contextualType, CTP};
2695
2690
}
2696
2691
2697
- // / Check the specified closure to see if it is a multi-statement closure with
2698
- // / an uninferred type. If so, diagnose the problem with an error and return
2699
- // / true.
2700
- bool FailureDiagnosis::
2701
- diagnoseAmbiguousMultiStatementClosure (ClosureExpr *closure) {
2702
- if (closure->hasSingleExpressionBody () ||
2703
- closure->hasExplicitResultType ())
2704
- return false ;
2705
-
2706
- auto closureType = CS.getType (closure)->getAs <AnyFunctionType>();
2707
- if (!closureType ||
2708
- !(closureType->getResult ()->hasUnresolvedType () ||
2709
- closureType->getResult ()->hasTypeVariable ()))
2710
- return false ;
2711
-
2712
- // Okay, we have a multi-statement closure expr that has no inferred result,
2713
- // type, in the context of a larger expression. The user probably expected
2714
- // the compiler to infer the result type of the closure from the body of the
2715
- // closure, which Swift doesn't do for multi-statement closures. Try to be
2716
- // helpful by digging into the body of the closure, looking for a return
2717
- // statement, and inferring the result type from it. If we can figure that
2718
- // out, we can produce a fixit hint.
2719
- class ReturnStmtFinder : public ASTWalker {
2720
- SmallVectorImpl<ReturnStmt*> &returnStmts;
2721
- public:
2722
- ReturnStmtFinder (SmallVectorImpl<ReturnStmt*> &returnStmts)
2723
- : returnStmts(returnStmts) {}
2724
-
2725
- // Walk through statements, so we find returns hiding in if/else blocks etc.
2726
- std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
2727
- // Keep track of any return statements we find.
2728
- if (auto RS = dyn_cast<ReturnStmt>(S))
2729
- returnStmts.push_back (RS);
2730
- return { true , S };
2731
- }
2732
-
2733
- // Don't walk into anything else, since they cannot contain statements
2734
- // that can return from the current closure.
2735
- std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
2736
- return { false , E };
2737
- }
2738
- std::pair<bool , Pattern*> walkToPatternPre (Pattern *P) override {
2739
- return { false , P };
2740
- }
2741
- bool walkToDeclPre (Decl *D) override { return false ; }
2742
- bool walkToTypeLocPre (TypeLoc &TL) override { return false ; }
2743
- bool walkToTypeReprPre (TypeRepr *T) override { return false ; }
2744
- bool walkToParameterListPre (ParameterList *PL) override { return false ; }
2745
- };
2746
-
2747
- SmallVector<ReturnStmt*, 4 > Returns;
2748
- closure->getBody ()->walk (ReturnStmtFinder (Returns));
2749
-
2750
- // If we found a return statement inside of the closure expression, then go
2751
- // ahead and type check the body to see if we can determine a type.
2752
- for (auto RS : Returns) {
2753
- llvm::SaveAndRestore<DeclContext *> SavedDC (CS.DC , closure);
2754
-
2755
- // Otherwise, we're ok to type check the subexpr.
2756
- Type resultType;
2757
- if (RS->hasResult ()) {
2758
- auto resultExpr = RS->getResult ();
2759
- ConcreteDeclRef decl = nullptr ;
2760
-
2761
- // If return expression uses closure parameters, which have/are
2762
- // type variables, such means that we won't be able to
2763
- // type-check result correctly and, unfortunately,
2764
- // we are going to leak type variables from the parent
2765
- // constraint system through declaration types.
2766
- bool hasUnresolvedParams = false ;
2767
- resultExpr->forEachChildExpr ([&](Expr *childExpr) -> Expr *{
2768
- if (auto DRE = dyn_cast<DeclRefExpr>(childExpr)) {
2769
- if (auto param = dyn_cast<ParamDecl>(DRE->getDecl ())) {
2770
- auto paramType =
2771
- param->hasInterfaceType () ? param->getType () : Type ();
2772
- if (!paramType || paramType->hasTypeVariable ()) {
2773
- hasUnresolvedParams = true ;
2774
- return nullptr ;
2775
- }
2776
- }
2777
- }
2778
- return childExpr;
2779
- });
2780
-
2781
- if (hasUnresolvedParams)
2782
- continue ;
2783
-
2784
- ConstraintSystem::preCheckExpression (resultExpr, CS.DC , &CS);
2785
-
2786
- // Obtain type of the result expression without applying solutions,
2787
- // because otherwise this might result in leaking of type variables,
2788
- // since we are not resetting result statement and if expression is
2789
- // successfully type-checked its type cleanup is going to be disabled
2790
- // (we are allowing unresolved types), and as a side-effect it might
2791
- // also be transformed e.g. OverloadedDeclRefExpr -> DeclRefExpr.
2792
- auto type = TypeChecker::getTypeOfExpressionWithoutApplying (
2793
- resultExpr, CS.DC , decl, FreeTypeVariableBinding::UnresolvedType);
2794
- if (type)
2795
- resultType = type->getRValueType ();
2796
- }
2797
-
2798
- // If we found a type, presuppose it was the intended result and insert a
2799
- // fixit hint.
2800
- if (resultType && !isUnresolvedOrTypeVarType (resultType)) {
2801
- // If there is a location for an 'in' token, then the argument list was
2802
- // specified somehow but no return type was. Insert a "-> ReturnType "
2803
- // before the in token.
2804
- if (closure->getInLoc ().isValid ()) {
2805
- diagnose (closure->getLoc (), diag::cannot_infer_closure_result_type)
2806
- .fixItInsert (closure->getInLoc (), diag::insert_closure_return_type,
2807
- resultType, /* argListSpecified*/ false );
2808
- return true ;
2809
- }
2810
-
2811
- // Otherwise, the closure must take zero arguments. We know this
2812
- // because the if one or more argument is specified, a multi-statement
2813
- // closure *must* name them, or explicitly ignore them with "_ in".
2814
- //
2815
- // As such, we insert " () -> ReturnType in " right after the '{' that
2816
- // starts the closure body.
2817
- diagnose (closure->getLoc (), diag::cannot_infer_closure_result_type)
2818
- .fixItInsertAfter (closure->getBody ()->getLBraceLoc (),
2819
- diag::insert_closure_return_type, resultType,
2820
- /* argListSpecified*/ true );
2821
- return true ;
2822
- }
2823
- }
2824
-
2825
- diagnose (closure->getLoc (), diag::cannot_infer_closure_result_type);
2826
- return true ;
2827
- }
2828
-
2829
2692
// / Emit an ambiguity diagnostic about the specified expression.
2830
2693
void FailureDiagnosis::diagnoseAmbiguity (Expr *E) {
2831
2694
if (auto *assignment = dyn_cast<AssignExpr>(E)) {
@@ -2855,11 +2718,6 @@ void FailureDiagnosis::diagnoseAmbiguity(Expr *E) {
2855
2718
// Unresolved/Anonymous ClosureExprs are common enough that we should give
2856
2719
// them tailored diagnostics.
2857
2720
if (auto CE = dyn_cast<ClosureExpr>(E->getValueProvidingExpr ())) {
2858
- // If this is a multi-statement closure with no explicit result type, emit
2859
- // a note to clue the developer in.
2860
- if (diagnoseAmbiguousMultiStatementClosure (CE))
2861
- return ;
2862
-
2863
2721
diagnose (E->getLoc (), diag::cannot_infer_closure_type)
2864
2722
.highlight (E->getSourceRange ());
2865
2723
return ;
@@ -2901,22 +2759,6 @@ void FailureDiagnosis::diagnoseAmbiguity(Expr *E) {
2901
2759
return ;
2902
2760
}
2903
2761
2904
- // A very common cause of this diagnostic is a situation where a closure expr
2905
- // has no inferred type, due to being a multiline closure. Check to see if
2906
- // this is the case and (if so), speculatively diagnose that as the problem.
2907
- bool didDiagnose = false ;
2908
- E->forEachChildExpr ([&](Expr *subExpr) -> Expr*{
2909
- auto closure = dyn_cast<ClosureExpr>(subExpr);
2910
- if (!didDiagnose && closure)
2911
- didDiagnose = diagnoseAmbiguousMultiStatementClosure (closure);
2912
-
2913
- return subExpr;
2914
- });
2915
-
2916
- if (didDiagnose) return ;
2917
-
2918
-
2919
-
2920
2762
// Attempt to re-type-check the entire expression, allowing ambiguity, but
2921
2763
// ignoring a contextual type.
2922
2764
if (expr == E) {
0 commit comments