@@ -1561,73 +1561,70 @@ 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 some fresh substitutions for our ADT type.
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+ Err ( _) => {
1588+ // This should never happen, since we're just subtyping the
1589+ // remaining_fields, but it's fine to emit this, I guess.
1590+ self . report_mismatched_types (
1591+ & cause,
1592+ target_ty,
1593+ fru_ty,
1594+ FieldMisMatch ( variant. name , ident. name ) ,
1595+ )
1596+ . emit ( ) ;
1597+ }
1598+ }
1599+ }
1600+ self . resolve_vars_if_possible ( fru_ty)
1601+ } )
1602+ . collect ( ) ;
1603+ // The use of fresh substs that we have subtyped against
1604+ // our base ADT type's fields allows us to guide inference
1605+ // along so that, e.g.
15671606 // ```
1568- // let x = MyStruct<'a, B, const C: usize> {
1569- // f: 1,
1570- // ..Default::default()
1607+ // MyStruct<'a, F1, F2, const C: usize> {
1608+ // f: F1,
1609+ // // Other fields that reference `'a`, `F2`, and `C`
1610+ // }
1611+ //
1612+ // let x = MyStruct {
1613+ // f: 1usize,
1614+ // ..other_struct
15711615 // };
15721616 // ```
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 ( ) ) ;
1617+ // will have the `other_struct` expression constrained to
1618+ // `MyStruct<'a, _, F2, C>`, as opposed to just `_`...
1619+ // This is important to allow coercions to happen in
1620+ // `other_struct` itself. See `coerce-in-base-expr.rs`.
15781621 let fresh_base_ty = self . tcx . mk_adt ( * adt, fresh_substs) ;
1579- let base_ty = self . check_expr_has_type_or_error (
1622+ self . check_expr_has_type_or_error (
15801623 base_expr,
1581- fresh_base_ty,
1582- |_| {
1583- error_happened = true ;
1584- } ,
1624+ self . resolve_vars_if_possible ( fresh_base_ty) ,
1625+ |_| { } ,
15851626 ) ;
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 ( )
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`" ) ;
1628- }
1629- return ;
1630- }
1627+ fru_tys
16311628 } else {
16321629 // Check the base_expr, regardless of a bad expected adt_ty, so we can get
16331630 // type errors on that expression, too.
0 commit comments