@@ -2559,7 +2559,8 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2559
2559
iterator_expr,
2560
2560
& [ ] ,
2561
2561
AutorefArgs :: No ,
2562
- DontTupleArguments ) ;
2562
+ DontTupleArguments ,
2563
+ NoExpectation ) ;
2563
2564
2564
2565
match method {
2565
2566
Some ( method) => {
@@ -2601,7 +2602,8 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2601
2602
callee_expr : & ast:: Expr ,
2602
2603
args_no_rcvr : & [ P < ast:: Expr > ] ,
2603
2604
autoref_args : AutorefArgs ,
2604
- tuple_arguments : TupleArgumentsFlag )
2605
+ tuple_arguments : TupleArgumentsFlag ,
2606
+ expected : Expectation < ' tcx > )
2605
2607
-> ty:: FnOutput < ' tcx > {
2606
2608
if ty:: type_is_error ( method_fn_ty) {
2607
2609
let err_inputs = err_args ( fcx. tcx ( ) , args_no_rcvr. len ( ) ) ;
@@ -2614,6 +2616,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2614
2616
check_argument_types ( fcx,
2615
2617
sp,
2616
2618
& err_inputs[ ] ,
2619
+ & [ ] ,
2617
2620
args_no_rcvr,
2618
2621
autoref_args,
2619
2622
false ,
@@ -2623,9 +2626,15 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2623
2626
match method_fn_ty. sty {
2624
2627
ty:: ty_bare_fn( _, ref fty) => {
2625
2628
// HACK(eddyb) ignore self in the definition (see above).
2629
+ let expected_arg_tys = expected_types_for_fn_args ( fcx,
2630
+ sp,
2631
+ expected,
2632
+ fty. sig . 0 . output ,
2633
+ & fty. sig . 0 . inputs [ 1 ..] ) ;
2626
2634
check_argument_types ( fcx,
2627
2635
sp,
2628
2636
& fty. sig . 0 . inputs [ 1 ..] ,
2637
+ & expected_arg_tys[ ] ,
2629
2638
args_no_rcvr,
2630
2639
autoref_args,
2631
2640
fty. sig . 0 . variadic ,
@@ -2645,6 +2654,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2645
2654
fn check_argument_types < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
2646
2655
sp : Span ,
2647
2656
fn_inputs : & [ Ty < ' tcx > ] ,
2657
+ expected_arg_tys : & [ Ty < ' tcx > ] ,
2648
2658
args : & [ P < ast:: Expr > ] ,
2649
2659
autoref_args : AutorefArgs ,
2650
2660
variadic : bool ,
@@ -2659,6 +2669,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2659
2669
1
2660
2670
} ;
2661
2671
2672
+ let mut expected_arg_tys = expected_arg_tys;
2662
2673
let expected_arg_count = fn_inputs. len ( ) ;
2663
2674
let formal_tys = if tuple_arguments == TupleArguments {
2664
2675
let tuple_type = structurally_resolved_type ( fcx, sp, fn_inputs[ 0 ] ) ;
@@ -2671,23 +2682,32 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2671
2682
if arg_types. len( ) == 1 { "" } else { "s" } ,
2672
2683
args. len( ) ,
2673
2684
if args. len( ) == 1 { " was" } else { "s were" } ) ;
2685
+ expected_arg_tys = & [ ] [ ] ;
2674
2686
err_args ( fcx. tcx ( ) , args. len ( ) )
2675
2687
} else {
2688
+ expected_arg_tys = match expected_arg_tys. get ( 0 ) {
2689
+ Some ( & ty) => match ty. sty {
2690
+ ty:: ty_tup( ref tys) => & * * tys,
2691
+ _ => & [ ]
2692
+ } ,
2693
+ None => & [ ]
2694
+ } ;
2676
2695
( * arg_types) . clone ( )
2677
2696
}
2678
2697
}
2679
2698
_ => {
2680
2699
span_err ! ( tcx. sess, sp, E0059 ,
2681
2700
"cannot use call notation; the first type parameter \
2682
2701
for the function trait is neither a tuple nor unit") ;
2702
+ expected_arg_tys = & [ ] [ ] ;
2683
2703
err_args ( fcx. tcx ( ) , args. len ( ) )
2684
2704
}
2685
2705
}
2686
2706
} else if expected_arg_count == supplied_arg_count {
2687
- fn_inputs. iter ( ) . map ( |a| * a ) . collect ( )
2707
+ fn_inputs. to_vec ( )
2688
2708
} else if variadic {
2689
2709
if supplied_arg_count >= expected_arg_count {
2690
- fn_inputs. iter ( ) . map ( |a| * a ) . collect ( )
2710
+ fn_inputs. to_vec ( )
2691
2711
} else {
2692
2712
span_err ! ( tcx. sess, sp, E0060 ,
2693
2713
"this function takes at least {} parameter{} \
@@ -2696,6 +2716,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2696
2716
if expected_arg_count == 1 { "" } else { "s" } ,
2697
2717
supplied_arg_count,
2698
2718
if supplied_arg_count == 1 { " was" } else { "s were" } ) ;
2719
+ expected_arg_tys = & [ ] [ ] ;
2699
2720
err_args ( fcx. tcx ( ) , supplied_arg_count)
2700
2721
}
2701
2722
} else {
@@ -2705,6 +2726,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2705
2726
if expected_arg_count == 1 { "" } else { "s" } ,
2706
2727
supplied_arg_count,
2707
2728
if supplied_arg_count == 1 { " was" } else { "s were" } ) ;
2729
+ expected_arg_tys = & [ ] [ ] ;
2708
2730
err_args ( fcx. tcx ( ) , supplied_arg_count)
2709
2731
} ;
2710
2732
@@ -2768,7 +2790,25 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
2768
2790
AutorefArgs :: No => { }
2769
2791
}
2770
2792
2771
- check_expr_coercable_to_type ( fcx, & * * arg, formal_ty) ;
2793
+ // The special-cased logic below has three functions:
2794
+ // 1. Provide as good of an expected type as possible.
2795
+ let expected = expected_arg_tys. get ( i) . map ( |& ty| {
2796
+ Expectation :: rvalue_hint ( ty)
2797
+ } ) ;
2798
+
2799
+ check_expr_with_unifier ( fcx, & * * arg,
2800
+ expected. unwrap_or ( ExpectHasType ( formal_ty) ) ,
2801
+ NoPreference , || {
2802
+ // 2. Coerce to the most detailed type that could be coerced
2803
+ // to, which is `expected_ty` if `rvalue_hint` returns an
2804
+ // `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
2805
+ let coerce_ty = expected. and_then ( |e| e. only_has_type ( fcx) ) ;
2806
+ demand:: coerce ( fcx, arg. span , coerce_ty. unwrap_or ( formal_ty) , & * * arg) ;
2807
+
2808
+ // 3. Relate the expected type and the formal one,
2809
+ // if the expected type was used for the coercion.
2810
+ coerce_ty. map ( |ty| demand:: suptype ( fcx, arg. span , formal_ty, ty) ) ;
2811
+ } ) ;
2772
2812
}
2773
2813
}
2774
2814
}
@@ -3008,6 +3048,45 @@ enum TupleArgumentsFlag {
3008
3048
TupleArguments ,
3009
3049
}
3010
3050
3051
+ /// Unifies the return type with the expected type early, for more coercions
3052
+ /// and forward type information on the argument expressions.
3053
+ fn expected_types_for_fn_args < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
3054
+ call_span : Span ,
3055
+ expected_ret : Expectation < ' tcx > ,
3056
+ formal_ret : ty:: FnOutput < ' tcx > ,
3057
+ formal_args : & [ Ty < ' tcx > ] )
3058
+ -> Vec < Ty < ' tcx > > {
3059
+ let expected_args = expected_ret. only_has_type ( fcx) . and_then ( |ret_ty| {
3060
+ if let ty:: FnConverging ( formal_ret_ty) = formal_ret {
3061
+ fcx. infcx ( ) . commit_regions_if_ok ( || {
3062
+ // Attempt to apply a subtyping relationship between the formal
3063
+ // return type (likely containing type variables if the function
3064
+ // is polymorphic) and the expected return type.
3065
+ // No argument expectations are produced if unification fails.
3066
+ let origin = infer:: Misc ( call_span) ;
3067
+ let ures = fcx. infcx ( ) . sub_types ( false , origin, formal_ret_ty, ret_ty) ;
3068
+ // FIXME(#15760) can't use try! here, FromError doesn't default
3069
+ // to identity so the resulting type is not constrained.
3070
+ if let Err ( e) = ures {
3071
+ return Err ( e) ;
3072
+ }
3073
+
3074
+ // Record all the argument types, with the substitutions
3075
+ // produced from the above subtyping unification.
3076
+ Ok ( formal_args. iter ( ) . map ( |ty| {
3077
+ fcx. infcx ( ) . resolve_type_vars_if_possible ( ty)
3078
+ } ) . collect ( ) )
3079
+ } ) . ok ( )
3080
+ } else {
3081
+ None
3082
+ }
3083
+ } ) . unwrap_or ( vec ! [ ] ) ;
3084
+ debug ! ( "expected_types_for_fn_args(formal={} -> {}, expected={} -> {})" ,
3085
+ formal_args. repr( fcx. tcx( ) ) , formal_ret. repr( fcx. tcx( ) ) ,
3086
+ expected_args. repr( fcx. tcx( ) ) , expected_ret. repr( fcx. tcx( ) ) ) ;
3087
+ expected_args
3088
+ }
3089
+
3011
3090
/// Invariant:
3012
3091
/// If an expression has any sub-expressions that result in a type error,
3013
3092
/// inspecting that expression's type with `ty::type_is_error` will return
@@ -3029,12 +3108,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3029
3108
expr. repr( fcx. tcx( ) ) , expected. repr( fcx. tcx( ) ) ) ;
3030
3109
3031
3110
// Checks a method call.
3032
- fn check_method_call ( fcx : & FnCtxt ,
3033
- expr : & ast:: Expr ,
3034
- method_name : ast:: SpannedIdent ,
3035
- args : & [ P < ast:: Expr > ] ,
3036
- tps : & [ P < ast:: Ty > ] ,
3037
- lvalue_pref : LvaluePreference ) {
3111
+ fn check_method_call < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
3112
+ expr : & ast:: Expr ,
3113
+ method_name : ast:: SpannedIdent ,
3114
+ args : & [ P < ast:: Expr > ] ,
3115
+ tps : & [ P < ast:: Ty > ] ,
3116
+ expected : Expectation < ' tcx > ,
3117
+ lvalue_pref : LvaluePreference ) {
3038
3118
let rcvr = & * args[ 0 ] ;
3039
3119
check_expr_with_lvalue_pref ( fcx, & * rcvr, lvalue_pref) ;
3040
3120
@@ -3071,7 +3151,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3071
3151
expr,
3072
3152
& args[ 1 ..] ,
3073
3153
AutorefArgs :: No ,
3074
- DontTupleArguments ) ;
3154
+ DontTupleArguments ,
3155
+ expected) ;
3075
3156
3076
3157
write_call ( fcx, expr, ret_ty) ;
3077
3158
}
@@ -3182,7 +3263,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3182
3263
op_ex,
3183
3264
args,
3184
3265
autoref_args,
3185
- DontTupleArguments ) {
3266
+ DontTupleArguments ,
3267
+ NoExpectation ) {
3186
3268
ty:: FnConverging ( result_type) => result_type,
3187
3269
ty:: FnDiverging => fcx. tcx ( ) . types . err
3188
3270
}
@@ -3198,7 +3280,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3198
3280
op_ex,
3199
3281
args,
3200
3282
autoref_args,
3201
- DontTupleArguments ) ;
3283
+ DontTupleArguments ,
3284
+ NoExpectation ) ;
3202
3285
fcx. tcx ( ) . types . err
3203
3286
}
3204
3287
}
@@ -4045,10 +4128,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
4045
4128
fcx. write_ty ( id, fcx. node_ty ( b. id ) ) ;
4046
4129
}
4047
4130
ast:: ExprCall ( ref callee, ref args) => {
4048
- callee:: check_call ( fcx, expr, & * * callee, & args[ ] ) ;
4131
+ callee:: check_call ( fcx, expr, & * * callee, & args[ ] , expected ) ;
4049
4132
}
4050
4133
ast:: ExprMethodCall ( ident, ref tps, ref args) => {
4051
- check_method_call ( fcx, expr, ident, & args[ ] , & tps[ ] , lvalue_pref) ;
4134
+ check_method_call ( fcx, expr, ident, & args[ ] , & tps[ ] , expected , lvalue_pref) ;
4052
4135
let arg_tys = args. iter ( ) . map ( |a| fcx. expr_ty ( & * * a) ) ;
4053
4136
let args_err = arg_tys. fold ( false ,
4054
4137
|rest_err, a| {
0 commit comments