@@ -16,6 +16,7 @@ use crate::util::common::ErrorReported;
16
16
17
17
use errors:: Applicability ;
18
18
use syntax:: ast;
19
+ use syntax:: ptr:: P ;
19
20
use syntax:: symbol:: sym;
20
21
use rustc:: hir;
21
22
use rustc:: hir:: { ExprKind , QPath } ;
@@ -844,4 +845,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
844
845
tuple
845
846
}
846
847
}
848
+
849
+ fn check_expr_struct (
850
+ & self ,
851
+ expr : & hir:: Expr ,
852
+ expected : Expectation < ' tcx > ,
853
+ qpath : & QPath ,
854
+ fields : & ' tcx [ hir:: Field ] ,
855
+ base_expr : & ' tcx Option < P < hir:: Expr > > ,
856
+ ) -> Ty < ' tcx > {
857
+ // Find the relevant variant
858
+ let ( variant, adt_ty) =
859
+ if let Some ( variant_ty) = self . check_struct_path ( qpath, expr. hir_id ) {
860
+ variant_ty
861
+ } else {
862
+ self . check_struct_fields_on_error ( fields, base_expr) ;
863
+ return self . tcx . types . err ;
864
+ } ;
865
+
866
+ let path_span = match * qpath {
867
+ QPath :: Resolved ( _, ref path) => path. span ,
868
+ QPath :: TypeRelative ( ref qself, _) => qself. span
869
+ } ;
870
+
871
+ // Prohibit struct expressions when non-exhaustive flag is set.
872
+ let adt = adt_ty. ty_adt_def ( ) . expect ( "`check_struct_path` returned non-ADT type" ) ;
873
+ if !adt. did . is_local ( ) && variant. is_field_list_non_exhaustive ( ) {
874
+ span_err ! ( self . tcx. sess, expr. span, E0639 ,
875
+ "cannot create non-exhaustive {} using struct expression" ,
876
+ adt. variant_descr( ) ) ;
877
+ }
878
+
879
+ let error_happened = self . check_expr_struct_fields ( adt_ty, expected, expr. hir_id , path_span,
880
+ variant, fields, base_expr. is_none ( ) ) ;
881
+ if let & Some ( ref base_expr) = base_expr {
882
+ // If check_expr_struct_fields hit an error, do not attempt to populate
883
+ // the fields with the base_expr. This could cause us to hit errors later
884
+ // when certain fields are assumed to exist that in fact do not.
885
+ if !error_happened {
886
+ self . check_expr_has_type_or_error ( base_expr, adt_ty) ;
887
+ match adt_ty. sty {
888
+ ty:: Adt ( adt, substs) if adt. is_struct ( ) => {
889
+ let fru_field_types = adt. non_enum_variant ( ) . fields . iter ( ) . map ( |f| {
890
+ self . normalize_associated_types_in ( expr. span , & f. ty ( self . tcx , substs) )
891
+ } ) . collect ( ) ;
892
+
893
+ self . tables
894
+ . borrow_mut ( )
895
+ . fru_field_types_mut ( )
896
+ . insert ( expr. hir_id , fru_field_types) ;
897
+ }
898
+ _ => {
899
+ span_err ! ( self . tcx. sess, base_expr. span, E0436 ,
900
+ "functional record update syntax requires a struct" ) ;
901
+ }
902
+ }
903
+ }
904
+ }
905
+ self . require_type_is_sized ( adt_ty, expr. span , traits:: StructInitializerSized ) ;
906
+ adt_ty
907
+ }
847
908
}
0 commit comments