@@ -3061,14 +3061,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3061
3061
3062
3062
fn check_expr_struct_fields ( & self ,
3063
3063
adt_ty : Ty < ' tcx > ,
3064
+ expected : Expectation < ' tcx > ,
3064
3065
expr_id : ast:: NodeId ,
3065
3066
span : Span ,
3066
3067
variant : & ' tcx ty:: VariantDef ,
3067
3068
ast_fields : & ' gcx [ hir:: Field ] ,
3068
3069
check_completeness : bool ) {
3069
3070
let tcx = self . tcx ;
3070
- let ( substs, adt_kind, kind_name) = match adt_ty. sty {
3071
- ty:: TyAdt ( adt, substs) => ( substs, adt. adt_kind ( ) , adt. variant_descr ( ) ) ,
3071
+
3072
+ let adt_ty_hint =
3073
+ self . expected_inputs_for_expected_output ( span, expected, adt_ty, & [ adt_ty] )
3074
+ . get ( 0 ) . cloned ( ) . unwrap_or ( adt_ty) ;
3075
+
3076
+ let ( substs, hint_substs, adt_kind, kind_name) = match ( & adt_ty. sty , & adt_ty_hint. sty ) {
3077
+ ( & ty:: TyAdt ( adt, substs) , & ty:: TyAdt ( _, hint_substs) ) => {
3078
+ ( substs, hint_substs, adt. adt_kind ( ) , adt. variant_descr ( ) )
3079
+ }
3072
3080
_ => span_bug ! ( span, "non-ADT passed to check_expr_struct_fields" )
3073
3081
} ;
3074
3082
@@ -3083,10 +3091,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3083
3091
3084
3092
// Typecheck each field.
3085
3093
for field in ast_fields {
3086
- let expected_field_type;
3094
+ let final_field_type;
3095
+ let field_type_hint;
3087
3096
3088
3097
if let Some ( v_field) = remaining_fields. remove ( & field. name . node ) {
3089
- expected_field_type = self . field_ty ( field. span , v_field, substs) ;
3098
+ final_field_type = self . field_ty ( field. span , v_field, substs) ;
3099
+ field_type_hint = self . field_ty ( field. span , v_field, hint_substs) ;
3090
3100
3091
3101
seen_fields. insert ( field. name . node , field. span ) ;
3092
3102
@@ -3098,7 +3108,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3098
3108
}
3099
3109
} else {
3100
3110
error_happened = true ;
3101
- expected_field_type = tcx. types . err ;
3111
+ final_field_type = tcx. types . err ;
3112
+ field_type_hint = tcx. types . err ;
3102
3113
if let Some ( _) = variant. find_field_named ( field. name . node ) {
3103
3114
let mut err = struct_span_err ! ( self . tcx. sess,
3104
3115
field. name. span,
@@ -3120,7 +3131,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3120
3131
3121
3132
// Make sure to give a type to the field even if there's
3122
3133
// an error, so we can continue typechecking
3123
- self . check_expr_coercable_to_type ( & field. expr , expected_field_type) ;
3134
+ let ty = self . check_expr_with_hint ( & field. expr , field_type_hint) ;
3135
+ self . demand_coerce ( & field. expr , ty, final_field_type) ;
3124
3136
}
3125
3137
3126
3138
// Make sure the programmer specified correct number of fields.
@@ -3230,6 +3242,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3230
3242
3231
3243
fn check_expr_struct ( & self ,
3232
3244
expr : & hir:: Expr ,
3245
+ expected : Expectation < ' tcx > ,
3233
3246
qpath : & hir:: QPath ,
3234
3247
fields : & ' gcx [ hir:: Field ] ,
3235
3248
base_expr : & ' gcx Option < P < hir:: Expr > > ) -> Ty < ' tcx >
@@ -3248,7 +3261,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3248
3261
hir:: QPath :: TypeRelative ( ref qself, _) => qself. span
3249
3262
} ;
3250
3263
3251
- self . check_expr_struct_fields ( struct_ty, expr. id , path_span, variant, fields,
3264
+ self . check_expr_struct_fields ( struct_ty, expected , expr. id , path_span, variant, fields,
3252
3265
base_expr. is_none ( ) ) ;
3253
3266
if let & Some ( ref base_expr) = base_expr {
3254
3267
self . check_expr_has_type ( base_expr, struct_ty) ;
@@ -3793,7 +3806,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
3793
3806
}
3794
3807
}
3795
3808
hir:: ExprStruct ( ref qpath, ref fields, ref base_expr) => {
3796
- self . check_expr_struct ( expr, qpath, fields, base_expr)
3809
+ self . check_expr_struct ( expr, expected , qpath, fields, base_expr)
3797
3810
}
3798
3811
hir:: ExprField ( ref base, ref field) => {
3799
3812
self . check_field ( expr, lvalue_pref, & base, field)
0 commit comments