@@ -36,7 +36,8 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
3636use rustc_infer:: infer:: InferOk ;
3737use rustc_middle:: ty;
3838use 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;
4041use rustc_middle:: ty:: subst:: SubstsRef ;
4142use rustc_middle:: ty:: Ty ;
4243use rustc_middle:: ty:: TypeFoldable ;
@@ -1375,124 +1376,105 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13751376 }
13761377
13771378 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 (
14321410 & cause,
14331411 target_ty,
14341412 fru_ty,
14351413 FieldMisMatch (
14361414 variant. ident . name ,
14371415 ident. name ,
14381416 ) ,
1439- ) )
1440- }
1417+ )
1418+ . emit ( ) ,
14411419 }
14421420 }
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 ( ) ;
14581434 }
14591435 }
14601436 }
14611437 _ => {
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 } ) ;
14631442 }
14641443 }
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- }
14801444 } 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) ;
14961478 } else if kind_name != "union" && !remaining_fields. is_empty ( ) {
14971479 let inaccessible_remaining_fields = remaining_fields. iter ( ) . any ( |( _, ( _, field) ) | {
14981480 !field. vis . is_accessible_from ( tcx. parent_module ( expr_id) . to_def_id ( ) , tcx)
0 commit comments