@@ -1421,14 +1421,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14211421 ///
14221422 /// This is used when checking the constructor in struct literals.
14231423 fn instantiate_struct_literal_ty ( & self ,
1424- did : ast :: DefId ,
1424+ struct_ty : ty :: TypeScheme < ' tcx > ,
14251425 path : & ast:: Path )
14261426 -> TypeAndSubsts < ' tcx >
14271427 {
1428- let tcx = self . tcx ( ) ;
1429-
1430- let ty:: TypeScheme { generics, ty : decl_ty } =
1431- tcx. lookup_item_type ( did) ;
1428+ let ty:: TypeScheme { generics, ty : decl_ty } = struct_ty;
14321429
14331430 let substs = astconv:: ast_path_substs_for_ty ( self , self ,
14341431 path. span ,
@@ -3168,6 +3165,18 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
31683165 }
31693166 }
31703167
3168+ fn report_exprstruct_on_nondict < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
3169+ id : ast:: NodeId ,
3170+ fields : & ' tcx [ ast:: Field ] ,
3171+ base_expr : & ' tcx Option < P < ast:: Expr > > ,
3172+ path : & ast:: Path )
3173+ {
3174+ span_err ! ( fcx. tcx( ) . sess, path. span, E0071 ,
3175+ "`{}` does not name a structure" ,
3176+ pprust:: path_to_string( path) ) ;
3177+ check_struct_fields_on_error ( fcx, id, fields, base_expr)
3178+ }
3179+
31713180 type ExprCheckerWithTy = fn ( & FnCtxt , & ast:: Expr , Ty ) ;
31723181
31733182 let tcx = fcx. ccx . tcx ;
@@ -3618,7 +3627,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
36183627 ast:: ExprStruct ( ref path, ref fields, ref base_expr) => {
36193628 // Resolve the path.
36203629 let def = lookup_full_def ( tcx, path. span , id) ;
3621- let struct_id = match def {
3630+
3631+ let struct_ty = match def {
36223632 def:: DefVariant ( enum_id, variant_id, true ) => {
36233633 if let & Some ( ref base_expr) = base_expr {
36243634 span_err ! ( tcx. sess, base_expr. span, E0436 ,
@@ -3627,54 +3637,38 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
36273637 }
36283638 check_struct_enum_variant ( fcx, id, expr. span , enum_id,
36293639 variant_id, & fields[ ..] ) ;
3630- enum_id
3640+ Some ( tcx . lookup_item_type ( enum_id) )
36313641 }
3632- def:: DefTrait ( def_id) => {
3633- span_err ! ( tcx. sess, path. span, E0159 ,
3634- "use of trait `{}` as a struct constructor" ,
3635- pprust:: path_to_string( path) ) ;
3636- check_struct_fields_on_error ( fcx,
3637- id,
3638- & fields[ ..] ,
3639- base_expr) ;
3640- def_id
3641- } ,
3642- def => {
3642+ def:: DefTy ( did, _) | def:: DefStruct ( did) => {
36433643 // Verify that this was actually a struct.
3644- let typ = fcx. ccx . tcx . lookup_item_type ( def. def_id ( ) ) ;
3645- match typ. ty . sty {
3646- ty:: TyStruct ( struct_def, _) => {
3647- check_struct_constructor ( fcx,
3648- id,
3649- expr. span ,
3650- struct_def,
3651- & fields[ ..] ,
3652- base_expr. as_ref ( ) . map ( |e| & * * e) ) ;
3653- }
3654- _ => {
3655- span_err ! ( tcx. sess, path. span, E0071 ,
3656- "`{}` does not name a structure" ,
3657- pprust:: path_to_string( path) ) ;
3658- check_struct_fields_on_error ( fcx,
3659- id,
3660- & fields[ ..] ,
3661- base_expr) ;
3662- }
3644+ let typ = tcx. lookup_item_type ( did) ;
3645+ if let ty:: TyStruct ( struct_def, _) = typ. ty . sty {
3646+ check_struct_constructor ( fcx,
3647+ id,
3648+ expr. span ,
3649+ struct_def,
3650+ & fields,
3651+ base_expr. as_ref ( ) . map ( |e| & * * e) ) ;
3652+ } else {
3653+ report_exprstruct_on_nondict ( fcx, id, & fields, base_expr, path) ;
36633654 }
3664-
3665- def. def_id ( )
3655+ Some ( typ)
3656+ }
3657+ _ => {
3658+ report_exprstruct_on_nondict ( fcx, id, & fields, base_expr, path) ;
3659+ None
36663660 }
36673661 } ;
36683662
36693663 // Turn the path into a type and verify that that type unifies with
36703664 // the resulting structure type. This is needed to handle type
36713665 // parameters correctly.
3672- let actual_structure_type = fcx . expr_ty ( & * expr ) ;
3673- if !actual_structure_type . references_error ( ) {
3674- let type_and_substs = fcx. instantiate_struct_literal_ty ( struct_id , path) ;
3666+ if let Some ( struct_ty ) = struct_ty {
3667+ let expr_ty = fcx . expr_ty ( & expr ) ;
3668+ let type_and_substs = fcx. instantiate_struct_literal_ty ( struct_ty , path) ;
36753669 match fcx. mk_subty ( false ,
36763670 infer:: Misc ( path. span ) ,
3677- actual_structure_type ,
3671+ expr_ty ,
36783672 type_and_substs. ty ) {
36793673 Ok ( ( ) ) => { }
36803674 Err ( type_error) => {
@@ -3685,8 +3679,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
36853679 fcx. infcx( )
36863680 . ty_to_string( type_and_substs. ty) ,
36873681 fcx. infcx( )
3688- . ty_to_string(
3689- actual_structure_type) ,
3682+ . ty_to_string( expr_ty) ,
36903683 type_error) ;
36913684 tcx. note_and_explain_type_err ( & type_error, path. span ) ;
36923685 }
0 commit comments