@@ -1421,14 +1421,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1421
1421
///
1422
1422
/// This is used when checking the constructor in struct literals.
1423
1423
fn instantiate_struct_literal_ty ( & self ,
1424
- did : ast :: DefId ,
1424
+ struct_ty : ty :: TypeScheme < ' tcx > ,
1425
1425
path : & ast:: Path )
1426
1426
-> TypeAndSubsts < ' tcx >
1427
1427
{
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;
1432
1429
1433
1430
let substs = astconv:: ast_path_substs_for_ty ( self , self ,
1434
1431
path. span ,
@@ -3168,6 +3165,18 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3168
3165
}
3169
3166
}
3170
3167
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
+
3171
3180
type ExprCheckerWithTy = fn ( & FnCtxt , & ast:: Expr , Ty ) ;
3172
3181
3173
3182
let tcx = fcx. ccx . tcx ;
@@ -3618,7 +3627,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3618
3627
ast:: ExprStruct ( ref path, ref fields, ref base_expr) => {
3619
3628
// Resolve the path.
3620
3629
let def = lookup_full_def ( tcx, path. span , id) ;
3621
- let struct_id = match def {
3630
+
3631
+ let struct_ty = match def {
3622
3632
def:: DefVariant ( enum_id, variant_id, true ) => {
3623
3633
if let & Some ( ref base_expr) = base_expr {
3624
3634
span_err ! ( tcx. sess, base_expr. span, E0436 ,
@@ -3627,54 +3637,38 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3627
3637
}
3628
3638
check_struct_enum_variant ( fcx, id, expr. span , enum_id,
3629
3639
variant_id, & fields[ ..] ) ;
3630
- enum_id
3640
+ Some ( tcx . lookup_item_type ( enum_id) )
3631
3641
}
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) => {
3643
3643
// 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) ;
3663
3654
}
3664
-
3665
- def. def_id ( )
3655
+ Some ( typ)
3656
+ }
3657
+ _ => {
3658
+ report_exprstruct_on_nondict ( fcx, id, & fields, base_expr, path) ;
3659
+ None
3666
3660
}
3667
3661
} ;
3668
3662
3669
3663
// Turn the path into a type and verify that that type unifies with
3670
3664
// the resulting structure type. This is needed to handle type
3671
3665
// 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) ;
3675
3669
match fcx. mk_subty ( false ,
3676
3670
infer:: Misc ( path. span ) ,
3677
- actual_structure_type ,
3671
+ expr_ty ,
3678
3672
type_and_substs. ty ) {
3679
3673
Ok ( ( ) ) => { }
3680
3674
Err ( type_error) => {
@@ -3685,8 +3679,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3685
3679
fcx. infcx( )
3686
3680
. ty_to_string( type_and_substs. ty) ,
3687
3681
fcx. infcx( )
3688
- . ty_to_string(
3689
- actual_structure_type) ,
3682
+ . ty_to_string( expr_ty) ,
3690
3683
type_error) ;
3691
3684
tcx. note_and_explain_type_err ( & type_error, path. span ) ;
3692
3685
}
0 commit comments