@@ -2292,7 +2292,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
22922292 match method_fn_ty. sty {
22932293 ty:: TyFnDef ( def_id, .., ref fty) => {
22942294 // 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 (
22962296 sp,
22972297 expected,
22982298 fty. 0 . output ( ) ,
@@ -2645,14 +2645,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
26452645 TypeAndSubsts { substs : substs, ty : substd_ty }
26462646 }
26472647
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 > > {
26562656 let expected_args = expected_ret. only_has_type ( self ) . and_then ( |ret_ty| {
26572657 self . fudge_regions_if_ok ( & RegionVariableOrigin :: Coercion ( call_span) , || {
26582658 // Attempt to apply a subtyping relationship between the formal
@@ -2675,7 +2675,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
26752675 } ) . collect ( ) )
26762676 } ) . ok ( )
26772677 } ) . unwrap_or ( vec ! [ ] ) ;
2678- debug ! ( "expected_types_for_fn_args (formal={:?} -> {:?}, expected={:?} -> {:?})" ,
2678+ debug ! ( "expected_inputs_for_expected_output (formal={:?} -> {:?}, expected={:?} -> {:?})" ,
26792679 formal_args, formal_ret,
26802680 expected_args, expected_ret) ;
26812681 expected_args
@@ -3032,14 +3032,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
30323032
30333033 fn check_expr_struct_fields ( & self ,
30343034 adt_ty : Ty < ' tcx > ,
3035+ expected : Expectation < ' tcx > ,
30353036 expr_id : ast:: NodeId ,
30363037 span : Span ,
30373038 variant : & ' tcx ty:: VariantDef ,
30383039 ast_fields : & ' gcx [ hir:: Field ] ,
30393040 check_completeness : bool ) {
30403041 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+ }
30433051 _ => span_bug ! ( span, "non-ADT passed to check_expr_struct_fields" )
30443052 } ;
30453053
@@ -3054,10 +3062,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
30543062
30553063 // Typecheck each field.
30563064 for field in ast_fields {
3057- let expected_field_type;
3065+ let final_field_type;
3066+ let field_type_hint;
30583067
30593068 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) ;
30613071
30623072 seen_fields. insert ( field. name . node , field. span ) ;
30633073
@@ -3069,7 +3079,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
30693079 }
30703080 } else {
30713081 error_happened = true ;
3072- expected_field_type = tcx. types . err ;
3082+ final_field_type = tcx. types . err ;
3083+ field_type_hint = tcx. types . err ;
30733084 if let Some ( _) = variant. find_field_named ( field. name . node ) {
30743085 let mut err = struct_span_err ! ( self . tcx. sess,
30753086 field. name. span,
@@ -3091,7 +3102,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
30913102
30923103 // Make sure to give a type to the field even if there's
30933104 // 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) ;
30953107 }
30963108
30973109 // Make sure the programmer specified correct number of fields.
@@ -3201,6 +3213,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
32013213
32023214 fn check_expr_struct ( & self ,
32033215 expr : & hir:: Expr ,
3216+ expected : Expectation < ' tcx > ,
32043217 qpath : & hir:: QPath ,
32053218 fields : & ' gcx [ hir:: Field ] ,
32063219 base_expr : & ' gcx Option < P < hir:: Expr > > ) -> Ty < ' tcx >
@@ -3219,7 +3232,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
32193232 hir:: QPath :: TypeRelative ( ref qself, _) => qself. span
32203233 } ;
32213234
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,
32233236 base_expr. is_none ( ) ) ;
32243237 if let & Some ( ref base_expr) = base_expr {
32253238 self . check_expr_has_type ( base_expr, struct_ty) ;
@@ -3764,7 +3777,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
37643777 }
37653778 }
37663779 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)
37683781 }
37693782 hir:: ExprField ( ref base, ref field) => {
37703783 self . check_field ( expr, lvalue_pref, & base, field)
0 commit comments