@@ -1561,71 +1561,73 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1561
1561
// FIXME: We are currently creating two branches here in order to maintain
1562
1562
// consistency. But they should be merged as much as possible.
1563
1563
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.
1567
1605
// ```
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
1571
1614
// };
1572
1615
// ```
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`.
1578
1620
let fresh_base_ty = self . tcx . mk_adt ( * adt, fresh_substs) ;
1579
1621
let base_ty = self . check_expr_has_type_or_error (
1580
1622
base_expr,
1581
- fresh_base_ty,
1623
+ self . resolve_vars_if_possible ( fresh_base_ty) ,
1582
1624
|_| {
1583
1625
error_happened = true ;
1584
1626
} ,
1585
1627
) ;
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
1625
1630
} 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
1631
return ;
1630
1632
}
1631
1633
} else {
0 commit comments