@@ -16,6 +16,7 @@ use crate::util::common::ErrorReported;
1616
1717use errors:: Applicability ;
1818use syntax:: ast;
19+ use syntax:: ptr:: P ;
1920use syntax:: symbol:: sym;
2021use rustc:: hir;
2122use rustc:: hir:: { ExprKind , QPath } ;
@@ -844,4 +845,64 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
844845 tuple
845846 }
846847 }
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+ }
847908}
0 commit comments