@@ -23,7 +23,7 @@ use crate::type_error_struct;
2323
2424use crate :: errors:: { AddressOfTemporaryTaken , ReturnStmtOutsideOfFnBody , StructExprNonExhaustive } ;
2525use rustc_ast as ast;
26- use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
26+ use rustc_data_structures:: fx:: FxHashMap ;
2727use rustc_data_structures:: stack:: ensure_sufficient_stack;
2828use rustc_errors:: ErrorReported ;
2929use rustc_errors:: { pluralize, struct_span_err, Applicability , DiagnosticBuilder , DiagnosticId } ;
@@ -1264,109 +1264,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12641264 . emit_err ( StructExprNonExhaustive { span : expr. span , what : adt. variant_descr ( ) } ) ;
12651265 }
12661266
1267- let ( error_happened , mut remaining_fields ) = self . check_expr_struct_fields (
1267+ self . check_expr_struct_fields (
12681268 adt_ty,
12691269 expected,
12701270 expr. hir_id ,
12711271 qpath. span ( ) ,
12721272 variant,
12731273 fields,
1274- base_expr. is_none ( ) ,
1274+ base_expr,
12751275 expr. span ,
12761276 ) ;
1277- if let Some ( base_expr) = base_expr {
1278- // If check_expr_struct_fields hit an error, do not attempt to populate
1279- // the fields with the base_expr. This could cause us to hit errors later
1280- // when certain fields are assumed to exist that in fact do not.
1281- if !error_happened {
1282- // FIXME: We are currently creating two branches here in order to maintain
1283- // consistency. But they should be merged as much as possible.
1284- if self . tcx . features ( ) . type_changing_struct_update {
1285- let base_ty = self . check_expr ( base_expr) ;
1286- match ( adt_ty. kind ( ) , base_ty. kind ( ) ) {
1287- ( ty:: Adt ( adt, substs) , ty:: Adt ( base_adt, base_subs) ) if adt == base_adt => {
1288- if !adt. is_struct ( ) {
1289- self . tcx . sess . emit_err ( FunctionalRecordUpdateOnNonStruct {
1290- span : base_expr. span ,
1291- } ) ;
1292- } ;
1293- let fru_field_types = variant
1294- . fields
1295- . iter ( )
1296- . map ( |f| {
1297- let fru_ty = self . normalize_associated_types_in (
1298- expr. span ,
1299- self . field_ty ( base_expr. span , f, base_subs) ,
1300- ) ;
1301- let ident = self . tcx . adjust_ident ( f. ident , variant. def_id ) ;
1302- if remaining_fields. remove ( & ident) {
1303- let target_ty = self . field_ty ( base_expr. span , f, substs) ;
1304- let cause = self . misc ( base_expr. span ) ;
1305- match self . at ( & cause, self . param_env ) . sup ( target_ty, fru_ty)
1306- {
1307- Ok ( InferOk { obligations, value : ( ) } ) => {
1308- self . register_predicates ( obligations)
1309- }
1310- // FIXME: Needs better diagnostics here
1311- Err ( _) => self
1312- . report_mismatched_types (
1313- & cause,
1314- target_ty,
1315- fru_ty,
1316- FieldMisMatch ( variant. ident . name , ident. name ) ,
1317- )
1318- . emit ( ) ,
1319- }
1320- }
1321- fru_ty
1322- } )
1323- . collect ( ) ;
1324-
1325- self . typeck_results
1326- . borrow_mut ( )
1327- . fru_field_types_mut ( )
1328- . insert ( expr. hir_id , fru_field_types) ;
1329- }
1330- _ => {
1331- self . report_mismatched_types (
1332- & self . misc ( base_expr. span ) ,
1333- adt_ty,
1334- base_ty,
1335- Mismatch ,
1336- )
1337- . emit ( ) ;
1338- }
1339- }
1340- } else {
1341- self . check_expr_has_type_or_error ( base_expr, adt_ty, |_| { } ) ;
1342- match adt_ty. kind ( ) {
1343- ty:: Adt ( adt, substs) if adt. is_struct ( ) => {
1344- let fru_field_types = adt
1345- . non_enum_variant ( )
1346- . fields
1347- . iter ( )
1348- . map ( |f| {
1349- self . normalize_associated_types_in (
1350- expr. span ,
1351- f. ty ( self . tcx , substs) ,
1352- )
1353- } )
1354- . collect ( ) ;
1355-
1356- self . typeck_results
1357- . borrow_mut ( )
1358- . fru_field_types_mut ( )
1359- . insert ( expr. hir_id , fru_field_types) ;
1360- }
1361- _ => {
1362- self . tcx . sess . emit_err ( FunctionalRecordUpdateOnNonStruct {
1363- span : base_expr. span ,
1364- } ) ;
1365- }
1366- }
1367- } ;
1368- }
1369- }
1277+
13701278 self . require_type_is_sized ( adt_ty, expr. span , traits:: StructInitializerSized ) ;
13711279 adt_ty
13721280 }
@@ -1379,9 +1287,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13791287 span : Span ,
13801288 variant : & ' tcx ty:: VariantDef ,
13811289 ast_fields : & ' tcx [ hir:: ExprField < ' tcx > ] ,
1382- check_completeness : bool ,
1290+ base_expr : & ' tcx Option < & ' tcx hir :: Expr < ' tcx > > ,
13831291 expr_span : Span ,
1384- ) -> ( bool , FxHashSet < Ident > ) {
1292+ ) {
13851293 let tcx = self . tcx ;
13861294
13871295 let adt_ty_hint = self
@@ -1456,19 +1364,99 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14561364 )
14571365 . emit ( ) ;
14581366 }
1459- } else if check_completeness && !error_happened && !remaining_fields. is_empty ( ) {
1367+ }
1368+
1369+ // If check_expr_struct_fields hit an error, do not attempt to populate
1370+ // the fields with the base_expr. This could cause us to hit errors later
1371+ // when certain fields are assumed to exist that in fact do not.
1372+ if error_happened {
1373+ return ;
1374+ }
1375+
1376+ if let Some ( base_expr) = base_expr {
1377+ // FIXME: We are currently creating two branches here in order to maintain
1378+ // consistency. But they should be merged as much as possible.
1379+ let fru_tys = if self . tcx . features ( ) . type_changing_struct_update {
1380+ let base_ty = self . check_expr ( base_expr) ;
1381+ match ( adt_ty. kind ( ) , base_ty. kind ( ) ) {
1382+ ( ty:: Adt ( adt, substs) , ty:: Adt ( base_adt, base_subs) ) if adt == base_adt => {
1383+ if !adt. is_struct ( ) {
1384+ self . tcx . sess . emit_err ( FunctionalRecordUpdateOnNonStruct {
1385+ span : base_expr. span ,
1386+ } ) ;
1387+ } ;
1388+ variant
1389+ . fields
1390+ . iter ( )
1391+ . map ( |f| {
1392+ let fru_ty = self . normalize_associated_types_in (
1393+ expr_span,
1394+ self . field_ty ( base_expr. span , f, base_subs) ,
1395+ ) ;
1396+ let ident = self . tcx . adjust_ident ( f. ident , variant. def_id ) ;
1397+ if let Some ( _) = remaining_fields. remove ( & ident) {
1398+ let target_ty = self . field_ty ( base_expr. span , f, substs) ;
1399+ let cause = self . misc ( base_expr. span ) ;
1400+ match self . at ( & cause, self . param_env ) . sup ( target_ty, fru_ty) {
1401+ Ok ( InferOk { obligations, value : ( ) } ) => {
1402+ self . register_predicates ( obligations)
1403+ }
1404+ // FIXME: Need better diagnostics for `FieldMisMatch` error
1405+ Err ( _) => self
1406+ . report_mismatched_types (
1407+ & cause,
1408+ target_ty,
1409+ fru_ty,
1410+ FieldMisMatch ( variant. ident . name , ident. name ) ,
1411+ )
1412+ . emit ( ) ,
1413+ }
1414+ }
1415+ fru_ty
1416+ } )
1417+ . collect ( )
1418+ }
1419+ _ => {
1420+ return self
1421+ . report_mismatched_types (
1422+ & self . misc ( base_expr. span ) ,
1423+ adt_ty,
1424+ base_ty,
1425+ Mismatch ,
1426+ )
1427+ . emit ( ) ;
1428+ }
1429+ }
1430+ } else {
1431+ self . check_expr_has_type_or_error ( base_expr, adt_ty, |_| { } ) ;
1432+ match adt_ty. kind ( ) {
1433+ ty:: Adt ( adt, substs) if adt. is_struct ( ) => variant
1434+ . fields
1435+ . iter ( )
1436+ . map ( |f| {
1437+ self . normalize_associated_types_in ( expr_span, f. ty ( self . tcx , substs) )
1438+ } )
1439+ . collect ( ) ,
1440+ _ => {
1441+ return self
1442+ . tcx
1443+ . sess
1444+ . emit_err ( FunctionalRecordUpdateOnNonStruct { span : base_expr. span } ) ;
1445+ }
1446+ }
1447+ } ;
1448+ self . typeck_results . borrow_mut ( ) . fru_field_types_mut ( ) . insert ( expr_id, fru_tys) ;
1449+ } else if kind_name != "union" && !remaining_fields. is_empty ( ) {
14601450 let inaccessible_remaining_fields = remaining_fields. iter ( ) . any ( |( _, ( _, field) ) | {
14611451 !field. vis . is_accessible_from ( tcx. parent_module ( expr_id) . to_def_id ( ) , tcx)
14621452 } ) ;
14631453
14641454 if inaccessible_remaining_fields {
14651455 self . report_inaccessible_fields ( adt_ty, span) ;
14661456 } else {
1467- self . report_missing_fields ( adt_ty, span, remaining_fields. clone ( ) ) ;
1457+ self . report_missing_fields ( adt_ty, span, remaining_fields) ;
14681458 }
14691459 }
1470-
1471- ( error_happened, remaining_fields. iter ( ) . map ( |( ident, _) | ident. clone ( ) ) . collect ( ) )
14721460 }
14731461
14741462 fn check_struct_fields_on_error (
0 commit comments