@@ -36,7 +36,8 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
36
36
use rustc_infer:: infer:: InferOk ;
37
37
use rustc_middle:: ty;
38
38
use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AllowTwoPhase } ;
39
- use rustc_middle:: ty:: error:: TypeError :: FieldMisMatch ;
39
+ use rustc_middle:: ty:: error:: TypeError :: { FieldMisMatch , Sorts } ;
40
+ use rustc_middle:: ty:: relate:: expected_found_bool;
40
41
use rustc_middle:: ty:: subst:: SubstsRef ;
41
42
use rustc_middle:: ty:: Ty ;
42
43
use rustc_middle:: ty:: TypeFoldable ;
@@ -1375,124 +1376,105 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1375
1376
}
1376
1377
1377
1378
if let Some ( base_expr) = base_expr {
1378
- let expected = if self . tcx . features ( ) . type_changing_struct_update {
1379
- NoExpectation
1380
- } else {
1381
- ExpectHasType ( adt_ty)
1382
- } ;
1383
- let mut ty = self . check_expr_with_expectation ( base_expr, expected) ;
1384
-
1385
- let expected_ty = expected. to_option ( & self ) . unwrap_or ( adt_ty) ;
1386
- // While we don't allow *arbitrary* coercions here, we *do* allow
1387
- // coercions from ! to `expected`.
1388
- if ty. is_never ( ) {
1389
- assert ! (
1390
- !self . typeck_results. borrow( ) . adjustments( ) . contains_key( base_expr. hir_id) ,
1391
- "expression with never type wound up being adjusted"
1392
- ) ;
1393
- let adj_ty = self . next_ty_var ( TypeVariableOrigin {
1394
- kind : TypeVariableOriginKind :: AdjustmentType ,
1395
- span : base_expr. span ,
1396
- } ) ;
1397
- self . apply_adjustments (
1398
- base_expr,
1399
- vec ! [ Adjustment { kind: Adjust :: NeverToAny , target: adj_ty } ] ,
1400
- ) ;
1401
- ty = adj_ty;
1402
- }
1403
- let cause = self . misc ( base_expr. span ) ;
1404
- let mut fru_tys = None ;
1405
- let mut err = None ;
1406
- let is_struct;
1407
-
1408
- if let ty:: Adt ( adt, substs) = expected_ty. kind ( ) {
1409
- match ty. kind ( ) {
1410
- ty:: Adt ( base_adt, base_subs) if adt == base_adt => {
1411
- if self . tcx . features ( ) . type_changing_struct_update {
1412
- let tys = variant
1413
- . fields
1414
- . iter ( )
1415
- . map ( |f| {
1416
- let fru_ty = self . normalize_associated_types_in (
1417
- expr_span,
1418
- self . field_ty ( base_expr. span , f, base_subs) ,
1419
- ) ;
1420
- let ident = self . tcx . adjust_ident ( f. ident , variant. def_id ) ;
1421
- if let Some ( _) = remaining_fields. remove ( & ident) {
1422
- let target_ty = self . field_ty ( base_expr. span , f, substs) ;
1423
- match self . at ( & cause, self . param_env ) . sup ( target_ty, fru_ty)
1424
- {
1425
- Ok ( InferOk { obligations, value : ( ) } ) => {
1426
- self . register_predicates ( obligations)
1427
- }
1428
- // FIXME: Need better diagnostics for `FieldMisMatch` error
1429
- Err ( _) => {
1430
- if err. is_none ( ) {
1431
- err = Some ( self . report_mismatched_types (
1379
+ // FIXME: We are currently creating two branches here in order to maintain
1380
+ // consistency. But they should be merged as much as possible.
1381
+ let fru_tys = if self . tcx . features ( ) . type_changing_struct_update {
1382
+ let base_ty = self . check_expr ( base_expr) ;
1383
+ match adt_ty. kind ( ) {
1384
+ ty:: Adt ( adt, substs) if adt. is_struct ( ) => {
1385
+ match base_ty. kind ( ) {
1386
+ ty:: Adt ( base_adt, base_subs) if adt == base_adt => {
1387
+ variant
1388
+ . fields
1389
+ . iter ( )
1390
+ . map ( |f| {
1391
+ let fru_ty = self . normalize_associated_types_in (
1392
+ expr_span,
1393
+ self . field_ty ( base_expr. span , f, base_subs) ,
1394
+ ) ;
1395
+ let ident = self . tcx . adjust_ident ( f. ident , variant. def_id ) ;
1396
+ if let Some ( _) = remaining_fields. remove ( & ident) {
1397
+ let target_ty =
1398
+ self . field_ty ( base_expr. span , f, substs) ;
1399
+ let cause = self . misc ( base_expr. span ) ;
1400
+ match self
1401
+ . at ( & cause, self . param_env )
1402
+ . sup ( target_ty, fru_ty)
1403
+ {
1404
+ Ok ( InferOk { obligations, value : ( ) } ) => {
1405
+ self . register_predicates ( obligations)
1406
+ }
1407
+ // FIXME: Need better diagnostics for `FieldMisMatch` error
1408
+ Err ( _) => self
1409
+ . report_mismatched_types (
1432
1410
& cause,
1433
1411
target_ty,
1434
1412
fru_ty,
1435
1413
FieldMisMatch (
1436
1414
variant. ident . name ,
1437
1415
ident. name ,
1438
1416
) ,
1439
- ) )
1440
- }
1417
+ )
1418
+ . emit ( ) ,
1441
1419
}
1442
1420
}
1443
- }
1444
- fru_ty
1445
- } )
1446
- . collect ( ) ;
1447
- fru_tys = Some ( tys) ;
1448
- } else {
1449
- err = self . demand_suptype_diag ( base_expr. span , expected_ty, ty) ;
1450
- if err. is_some ( ) && self . tcx . sess . is_nightly_build ( ) {
1451
- feature_err (
1452
- & self . tcx . sess . parse_sess ,
1453
- sym:: type_changing_struct_update,
1454
- base_expr. span ,
1455
- "type changing struct updating is experimental" ,
1456
- )
1457
- . emit ( ) ;
1421
+ fru_ty
1422
+ } )
1423
+ . collect ( )
1424
+ }
1425
+ _ => {
1426
+ return self
1427
+ . report_mismatched_types (
1428
+ & self . misc ( base_expr. span ) ,
1429
+ adt_ty,
1430
+ base_ty,
1431
+ Sorts ( expected_found_bool ( true , adt_ty, base_ty) ) ,
1432
+ )
1433
+ . emit ( ) ;
1458
1434
}
1459
1435
}
1460
1436
}
1461
1437
_ => {
1462
- err = self . demand_suptype_diag ( base_expr. span , expected_ty, ty) ;
1438
+ return self
1439
+ . tcx
1440
+ . sess
1441
+ . emit_err ( FunctionalRecordUpdateOnNonStruct { span : base_expr. span } ) ;
1463
1442
}
1464
1443
}
1465
- is_struct = adt. is_struct ( ) ;
1466
- if is_struct && fru_tys. is_none ( ) {
1467
- fru_tys = Some (
1468
- variant
1469
- . fields
1470
- . iter ( )
1471
- . map ( |f| {
1472
- self . normalize_associated_types_in (
1473
- expr_span,
1474
- f. ty ( self . tcx , substs) ,
1475
- )
1476
- } )
1477
- . collect ( ) ,
1478
- )
1479
- }
1480
1444
} else {
1481
- err = self . demand_suptype_diag ( base_expr. span , expected_ty, ty) ;
1482
- is_struct = false ;
1483
- }
1484
- if let Some ( mut err) = err {
1485
- let expr = base_expr. peel_drop_temps ( ) ;
1486
- self . suggest_deref_ref_or_into ( & mut err, expr, expected_ty, ty, None ) ;
1487
- err. emit ( ) ;
1488
- }
1489
- if let Some ( fru_tys) = fru_tys {
1490
- self . typeck_results . borrow_mut ( ) . fru_field_types_mut ( ) . insert ( expr_id, fru_tys) ;
1491
- }
1492
- if !is_struct {
1493
- let e = FunctionalRecordUpdateOnNonStruct { span : base_expr. span } ;
1494
- self . tcx . sess . emit_err ( e) ;
1495
- }
1445
+ self . check_expr_has_type_or_error ( base_expr, adt_ty, |_| {
1446
+ let base_ty = self . check_expr ( base_expr) ;
1447
+ let same_adt = match ( adt_ty. kind ( ) , base_ty. kind ( ) ) {
1448
+ ( ty:: Adt ( adt, _) , ty:: Adt ( base_adt, _) ) if adt == base_adt => true ,
1449
+ _ => false ,
1450
+ } ;
1451
+ if self . tcx . sess . is_nightly_build ( ) && same_adt {
1452
+ feature_err (
1453
+ & self . tcx . sess . parse_sess ,
1454
+ sym:: type_changing_struct_update,
1455
+ base_expr. span ,
1456
+ "type changing struct updating is experimental" ,
1457
+ )
1458
+ . emit ( ) ;
1459
+ }
1460
+ } ) ;
1461
+ match adt_ty. kind ( ) {
1462
+ ty:: Adt ( adt, substs) if adt. is_struct ( ) => variant
1463
+ . fields
1464
+ . iter ( )
1465
+ . map ( |f| {
1466
+ self . normalize_associated_types_in ( expr_span, f. ty ( self . tcx , substs) )
1467
+ } )
1468
+ . collect ( ) ,
1469
+ _ => {
1470
+ return self
1471
+ . tcx
1472
+ . sess
1473
+ . emit_err ( FunctionalRecordUpdateOnNonStruct { span : base_expr. span } ) ;
1474
+ }
1475
+ }
1476
+ } ;
1477
+ self . typeck_results . borrow_mut ( ) . fru_field_types_mut ( ) . insert ( expr_id, fru_tys) ;
1496
1478
} else if kind_name != "union" && !remaining_fields. is_empty ( ) {
1497
1479
let inaccessible_remaining_fields = remaining_fields. iter ( ) . any ( |( _, ( _, field) ) | {
1498
1480
!field. vis . is_accessible_from ( tcx. parent_module ( expr_id) . to_def_id ( ) , tcx)
0 commit comments