@@ -2292,7 +2292,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2292
2292
match method_fn_ty. sty {
2293
2293
ty:: TyFnDef ( def_id, .., ref fty) => {
2294
2294
// HACK(eddyb) ignore self in the definition (see above).
2295
- let expected_arg_tys = self . expected_types_for_fn_args (
2295
+ let expected_arg_tys = self . expected_inputs_for_expected_output (
2296
2296
sp,
2297
2297
expected,
2298
2298
fty. 0 . output ( ) ,
@@ -2645,14 +2645,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2645
2645
TypeAndSubsts { substs : substs, ty : substd_ty }
2646
2646
}
2647
2647
2648
- /// Unifies the return type with the expected type early, for more coercions
2649
- /// and forward type information on the argument expressions.
2650
- fn expected_types_for_fn_args ( & self ,
2651
- call_span : Span ,
2652
- expected_ret : Expectation < ' tcx > ,
2653
- formal_ret : Ty < ' tcx > ,
2654
- formal_args : & [ Ty < ' tcx > ] )
2655
- -> Vec < Ty < ' tcx > > {
2648
+ /// Unifies the output type with the expected type early, for more coercions
2649
+ /// and forward type information on the input expressions.
2650
+ fn expected_inputs_for_expected_output ( & self ,
2651
+ call_span : Span ,
2652
+ expected_ret : Expectation < ' tcx > ,
2653
+ formal_ret : Ty < ' tcx > ,
2654
+ formal_args : & [ Ty < ' tcx > ] )
2655
+ -> Vec < Ty < ' tcx > > {
2656
2656
let expected_args = expected_ret. only_has_type ( self ) . and_then ( |ret_ty| {
2657
2657
self . fudge_regions_if_ok ( & RegionVariableOrigin :: Coercion ( call_span) , || {
2658
2658
// Attempt to apply a subtyping relationship between the formal
@@ -2675,7 +2675,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
2675
2675
} ) . collect ( ) )
2676
2676
} ) . ok ( )
2677
2677
} ) . unwrap_or ( vec ! [ ] ) ;
2678
- debug ! ( "expected_types_for_fn_args (formal={:?} -> {:?}, expected={:?} -> {:?})" ,
2678
+ debug ! ( "expected_inputs_for_expected_output (formal={:?} -> {:?}, expected={:?} -> {:?})" ,
2679
2679
formal_args, formal_ret,
2680
2680
expected_args, expected_ret) ;
2681
2681
expected_args
@@ -3032,14 +3032,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3032
3032
3033
3033
fn check_expr_struct_fields ( & self ,
3034
3034
adt_ty : Ty < ' tcx > ,
3035
+ expected : Expectation < ' tcx > ,
3035
3036
expr_id : ast:: NodeId ,
3036
3037
span : Span ,
3037
3038
variant : & ' tcx ty:: VariantDef ,
3038
3039
ast_fields : & ' gcx [ hir:: Field ] ,
3039
3040
check_completeness : bool ) {
3040
3041
let tcx = self . tcx ;
3041
- let ( substs, adt_kind, kind_name) = match adt_ty. sty {
3042
- ty:: TyAdt ( adt, substs) => ( substs, adt. adt_kind ( ) , adt. variant_descr ( ) ) ,
3042
+
3043
+ let adt_ty_hint =
3044
+ self . expected_inputs_for_expected_output ( span, expected, adt_ty, & [ adt_ty] )
3045
+ . get ( 0 ) . cloned ( ) . unwrap_or ( adt_ty) ;
3046
+
3047
+ let ( substs, hint_substs, adt_kind, kind_name) = match ( & adt_ty. sty , & adt_ty_hint. sty ) {
3048
+ ( & ty:: TyAdt ( adt, substs) , & ty:: TyAdt ( _, hint_substs) ) => {
3049
+ ( substs, hint_substs, adt. adt_kind ( ) , adt. variant_descr ( ) )
3050
+ }
3043
3051
_ => span_bug ! ( span, "non-ADT passed to check_expr_struct_fields" )
3044
3052
} ;
3045
3053
@@ -3054,10 +3062,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3054
3062
3055
3063
// Typecheck each field.
3056
3064
for field in ast_fields {
3057
- let expected_field_type;
3065
+ let final_field_type;
3066
+ let field_type_hint;
3058
3067
3059
3068
if let Some ( v_field) = remaining_fields. remove ( & field. name . node ) {
3060
- expected_field_type = self . field_ty ( field. span , v_field, substs) ;
3069
+ final_field_type = self . field_ty ( field. span , v_field, substs) ;
3070
+ field_type_hint = self . field_ty ( field. span , v_field, hint_substs) ;
3061
3071
3062
3072
seen_fields. insert ( field. name . node , field. span ) ;
3063
3073
@@ -3069,7 +3079,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3069
3079
}
3070
3080
} else {
3071
3081
error_happened = true ;
3072
- expected_field_type = tcx. types . err ;
3082
+ final_field_type = tcx. types . err ;
3083
+ field_type_hint = tcx. types . err ;
3073
3084
if let Some ( _) = variant. find_field_named ( field. name . node ) {
3074
3085
let mut err = struct_span_err ! ( self . tcx. sess,
3075
3086
field. name. span,
@@ -3091,7 +3102,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3091
3102
3092
3103
// Make sure to give a type to the field even if there's
3093
3104
// an error, so we can continue typechecking
3094
- self . check_expr_coercable_to_type ( & field. expr , expected_field_type) ;
3105
+ let ty = self . check_expr_with_hint ( & field. expr , field_type_hint) ;
3106
+ self . demand_coerce ( & field. expr , ty, final_field_type) ;
3095
3107
}
3096
3108
3097
3109
// Make sure the programmer specified correct number of fields.
@@ -3201,6 +3213,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3201
3213
3202
3214
fn check_expr_struct ( & self ,
3203
3215
expr : & hir:: Expr ,
3216
+ expected : Expectation < ' tcx > ,
3204
3217
qpath : & hir:: QPath ,
3205
3218
fields : & ' gcx [ hir:: Field ] ,
3206
3219
base_expr : & ' gcx Option < P < hir:: Expr > > ) -> Ty < ' tcx >
@@ -3219,7 +3232,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3219
3232
hir:: QPath :: TypeRelative ( ref qself, _) => qself. span
3220
3233
} ;
3221
3234
3222
- self . check_expr_struct_fields ( struct_ty, expr. id , path_span, variant, fields,
3235
+ self . check_expr_struct_fields ( struct_ty, expected , expr. id , path_span, variant, fields,
3223
3236
base_expr. is_none ( ) ) ;
3224
3237
if let & Some ( ref base_expr) = base_expr {
3225
3238
self . check_expr_has_type ( base_expr, struct_ty) ;
@@ -3764,7 +3777,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3764
3777
}
3765
3778
}
3766
3779
hir:: ExprStruct ( ref qpath, ref fields, ref base_expr) => {
3767
- self . check_expr_struct ( expr, qpath, fields, base_expr)
3780
+ self . check_expr_struct ( expr, expected , qpath, fields, base_expr)
3768
3781
}
3769
3782
hir:: ExprField ( ref base, ref field) => {
3770
3783
self . check_field ( expr, lvalue_pref, & base, field)
0 commit comments