@@ -1561,71 +1561,73 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15611561 // FIXME: We are currently creating two branches here in order to maintain
15621562 // consistency. But they should be merged as much as possible.
15631563 let fru_tys = if self . tcx . features ( ) . type_changing_struct_update {
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.
1564+ if adt. is_struct ( ) {
1565+ // Make an ADT with fresh inference substitutions.
1566+ let fresh_substs = self . fresh_substs_for_item ( base_expr. span , adt. did ( ) ) ;
1567+ // We do subtyping on the FRU fields first, so we can
1568+ // learn exactly what types we expect the base expr
1569+ // needs constrained to be compatible with the struct
1570+ // type we expect from the expectation value.
1571+ let fru_tys = variant
1572+ . fields
1573+ . iter ( )
1574+ . map ( |f| {
1575+ let fru_ty = self . normalize_associated_types_in (
1576+ expr_span,
1577+ self . field_ty ( base_expr. span , f, fresh_substs) ,
1578+ ) ;
1579+ let ident = self . tcx . adjust_ident ( f. ident ( self . tcx ) , variant. def_id ) ;
1580+ if let Some ( _) = remaining_fields. remove ( & ident) {
1581+ let target_ty = self . field_ty ( base_expr. span , f, substs) ;
1582+ let cause = self . misc ( base_expr. span ) ;
1583+ match self . at ( & cause, self . param_env ) . sup ( target_ty, fru_ty) {
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+ }
1598+ }
1599+ self . resolve_vars_if_possible ( fru_ty)
1600+ } )
1601+ . collect ( ) ;
1602+ // The use of fresh substs that we have subtyped against
1603+ // our existing ADT type allows us to guide inference along
1604+ // so that, e.g.
15671605 // ```
1568- // let x = MyStruct<'a, B, const C: usize> {
1569- // f: 1,
1570- // ..Default::default()
1606+ // MyStruct<'a, F1, F2, const C: usize> {
1607+ // f: F1,
1608+ // // Other fields that reference `'a`, `F2`, and `C`
1609+ // }
1610+ //
1611+ // let x = MyStruct {
1612+ // f: 1usize,
1613+ // ..other_struct
15711614 // };
15721615 // ```
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 ( ) ) ;
1616+ // will have the `other_struct` expression constrained to
1617+ // `MyStruct<'a, _, F2, C>`, as opposed to just `_`...
1618+ // This is important to allow coercions to happen in
1619+ // `other_struct` itself. See `coerce-in-base-expr.rs`.
15781620 let fresh_base_ty = self . tcx . mk_adt ( * adt, fresh_substs) ;
15791621 let base_ty = self . check_expr_has_type_or_error (
15801622 base_expr,
1581- fresh_base_ty,
1623+ self . resolve_vars_if_possible ( fresh_base_ty) ,
15821624 |_| {
15831625 error_happened = true ;
15841626 } ,
15851627 ) ;
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)
1609- }
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 ( )
1628+ if !error_happened && !base_ty. references_error ( ) {
1629+ fru_tys
16251630 } 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`" ) ;
1628- }
16291631 return ;
16301632 }
16311633 } else {
0 commit comments