@@ -41,8 +41,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
4141use rustc_infer:: infer:: InferOk ;
4242use rustc_middle:: middle:: stability;
4343use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AllowTwoPhase } ;
44- use rustc_middle:: ty:: error:: ExpectedFound ;
45- use rustc_middle:: ty:: error:: TypeError :: { FieldMisMatch , Sorts } ;
44+ use rustc_middle:: ty:: error:: TypeError :: FieldMisMatch ;
4645use rustc_middle:: ty:: subst:: SubstsRef ;
4746use rustc_middle:: ty:: { self , AdtKind , DefIdTree , Ty , TypeFoldable } ;
4847use rustc_session:: parse:: feature_err;
@@ -65,7 +64,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
6564 & self ,
6665 expr : & ' tcx hir:: Expr < ' tcx > ,
6766 expected : Ty < ' tcx > ,
68- extend_err : impl Fn ( & mut Diagnostic ) ,
67+ extend_err : impl FnMut ( & mut Diagnostic ) ,
6968 ) -> Ty < ' tcx > {
7069 self . check_expr_meets_expectation_or_error ( expr, ExpectHasType ( expected) , extend_err)
7170 }
@@ -74,7 +73,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7473 & self ,
7574 expr : & ' tcx hir:: Expr < ' tcx > ,
7675 expected : Expectation < ' tcx > ,
77- extend_err : impl Fn ( & mut Diagnostic ) ,
76+ mut extend_err : impl FnMut ( & mut Diagnostic ) ,
7877 ) -> Ty < ' tcx > {
7978 let expected_ty = expected. to_option ( & self ) . unwrap_or ( self . tcx . types . bool ) ;
8079 let mut ty = self . check_expr_with_expectation ( expr, expected) ;
@@ -1480,10 +1479,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14801479 // re-link the regions that EIfEO can erase.
14811480 self . demand_eqtype ( span, adt_ty_hint, adt_ty) ;
14821481
1483- let ( substs, adt_kind, kind_name) = match adt_ty. kind ( ) {
1484- ty:: Adt ( adt, substs) => ( substs, adt. adt_kind ( ) , adt. variant_descr ( ) ) ,
1485- _ => span_bug ! ( span, "non-ADT passed to check_expr_struct_fields" ) ,
1482+ let ty:: Adt ( adt, substs) = adt_ty. kind ( ) else {
1483+ span_bug ! ( span, "non-ADT passed to check_expr_struct_fields" ) ;
14861484 } ;
1485+ let adt_kind = adt. adt_kind ( ) ;
14871486
14881487 let mut remaining_fields = variant
14891488 . fields
@@ -1521,7 +1520,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15211520 } ) ;
15221521 } else {
15231522 self . report_unknown_field (
1524- adt_ty, variant, field, ast_fields, kind_name, expr_span,
1523+ adt_ty,
1524+ variant,
1525+ field,
1526+ ast_fields,
1527+ adt. variant_descr ( ) ,
1528+ expr_span,
15251529 ) ;
15261530 }
15271531
@@ -1534,7 +1538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15341538 }
15351539
15361540 // Make sure the programmer specified correct number of fields.
1537- if kind_name == "union" {
1541+ if adt_kind == AdtKind :: Union {
15381542 if ast_fields. len ( ) != 1 {
15391543 struct_span_err ! (
15401544 tcx. sess,
@@ -1557,67 +1561,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15571561 // FIXME: We are currently creating two branches here in order to maintain
15581562 // consistency. But they should be merged as much as possible.
15591563 let fru_tys = if self . tcx . features ( ) . type_changing_struct_update {
1560- let base_ty = self . check_expr ( base_expr) ;
1561- match adt_ty. kind ( ) {
1562- ty:: Adt ( adt, substs) if adt. is_struct ( ) => {
1563- match base_ty. kind ( ) {
1564- ty:: Adt ( base_adt, base_subs) if adt == base_adt => {
1565- variant
1566- . fields
1567- . iter ( )
1568- . map ( |f| {
1569- let fru_ty = self . normalize_associated_types_in (
1570- expr_span,
1571- self . field_ty ( base_expr. span , f, base_subs) ,
1572- ) ;
1573- let ident = self
1574- . tcx
1575- . adjust_ident ( f. ident ( self . tcx ) , variant. def_id ) ;
1576- if let Some ( _) = remaining_fields. remove ( & ident) {
1577- let target_ty =
1578- self . field_ty ( base_expr. span , f, substs) ;
1579- let cause = self . misc ( base_expr. span ) ;
1580- match self
1581- . at ( & cause, self . param_env )
1582- . sup ( target_ty, fru_ty)
1583- {
1584- Ok ( InferOk { obligations, value : ( ) } ) => {
1585- self . register_predicates ( obligations)
1586- }
1587- // FIXME: Need better diagnostics for `FieldMisMatch` error
1588- Err ( _) => {
1589- self . report_mismatched_types (
1590- & cause,
1591- target_ty,
1592- fru_ty,
1593- FieldMisMatch ( variant. name , ident. name ) ,
1594- )
1595- . emit ( ) ;
1596- }
1597- }
1564+ if let ty:: Adt ( adt, substs) = adt_ty. kind ( ) && adt. is_struct ( ) {
1565+ // Make an ADT with fresh inference substitutions. This
1566+ // will allow us to guide inference along so that, e.g.
1567+ // ```
1568+ // let x = MyStruct<'a, B, const C: usize> {
1569+ // f: 1,
1570+ // ..Default::default()
1571+ // };
1572+ // ```
1573+ // will have the default base expression constrained to
1574+ // `MyStruct<'_, _, _>`, as opposed to just `_`... This
1575+ // will allow us to then do a subtyping relation on all
1576+ // of the `remaining_fields` below, per the RFC.
1577+ let fresh_substs = self . fresh_substs_for_item ( base_expr. span , adt. did ( ) ) ;
1578+ let fresh_base_ty = self . tcx . mk_adt ( * adt, fresh_substs) ;
1579+ let base_ty = self . check_expr_has_type_or_error (
1580+ base_expr,
1581+ fresh_base_ty,
1582+ |_| {
1583+ error_happened = true ;
1584+ } ,
1585+ ) ;
1586+ let base_ty = self . shallow_resolve ( base_ty) ;
1587+ if let ty:: Adt ( base_adt, base_substs) = base_ty. kind ( ) && adt == base_adt {
1588+ variant
1589+ . fields
1590+ . iter ( )
1591+ . map ( |f| {
1592+ let fru_ty = self . normalize_associated_types_in (
1593+ expr_span,
1594+ self . field_ty ( base_expr. span , f, base_substs) ,
1595+ ) ;
1596+ let ident = self
1597+ . tcx
1598+ . adjust_ident ( f. ident ( self . tcx ) , variant. def_id ) ;
1599+ if let Some ( _) = remaining_fields. remove ( & ident) {
1600+ let target_ty =
1601+ self . field_ty ( base_expr. span , f, substs) ;
1602+ let cause = self . misc ( base_expr. span ) ;
1603+ match self
1604+ . at ( & cause, self . param_env )
1605+ . sup ( target_ty, fru_ty)
1606+ {
1607+ Ok ( InferOk { obligations, value : ( ) } ) => {
1608+ self . register_predicates ( obligations)
15981609 }
1599- fru_ty
1600- } )
1601- . collect ( )
1602- }
1603- _ => {
1604- self . report_mismatched_types (
1605- & self . misc ( base_expr. span ) ,
1606- adt_ty,
1607- base_ty,
1608- Sorts ( ExpectedFound :: new ( true , adt_ty, base_ty) ) ,
1609- )
1610- . emit ( ) ;
1611- return ;
1612- }
1610+ // FIXME: Need better diagnostics for `FieldMisMatch` error
1611+ Err ( _) => {
1612+ self . report_mismatched_types (
1613+ & cause,
1614+ target_ty,
1615+ fru_ty,
1616+ FieldMisMatch ( variant. name , ident. name ) ,
1617+ )
1618+ . emit ( ) ;
1619+ }
1620+ }
1621+ }
1622+ self . resolve_vars_if_possible ( fru_ty)
1623+ } )
1624+ . collect ( )
1625+ } else {
1626+ if !error_happened && !base_ty. references_error ( ) {
1627+ span_bug ! ( base_expr. span, "expected an error to have been reported in `check_expr_has_type_or_error`" ) ;
16131628 }
1614- }
1615- _ => {
1616- self . tcx
1617- . sess
1618- . emit_err ( FunctionalRecordUpdateOnNonStruct { span : base_expr. span } ) ;
16191629 return ;
16201630 }
1631+ } else {
1632+ // Check the base_expr, regardless of a bad expected adt_ty, so we can get
1633+ // type errors on that expression, too.
1634+ self . check_expr ( base_expr) ;
1635+ self . tcx
1636+ . sess
1637+ . emit_err ( FunctionalRecordUpdateOnNonStruct { span : base_expr. span } ) ;
1638+ return ;
16211639 }
16221640 } else {
16231641 self . check_expr_has_type_or_error ( base_expr, adt_ty, |_| {
@@ -1653,7 +1671,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16531671 }
16541672 } ;
16551673 self . typeck_results . borrow_mut ( ) . fru_field_types_mut ( ) . insert ( expr_id, fru_tys) ;
1656- } else if kind_name != "union" && !remaining_fields. is_empty ( ) {
1674+ } else if adt_kind != AdtKind :: Union && !remaining_fields. is_empty ( ) {
16571675 let inaccessible_remaining_fields = remaining_fields. iter ( ) . any ( |( _, ( _, field) ) | {
16581676 !field. vis . is_accessible_from ( tcx. parent_module ( expr_id) . to_def_id ( ) , tcx)
16591677 } ) ;
0 commit comments