@@ -1561,73 +1561,70 @@ 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 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.
1567
1606
// ```
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
1571
1615
// };
1572
1616
// ```
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`.
1578
1621
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 (
1580
1623
base_expr,
1581
- fresh_base_ty,
1582
- |_| {
1583
- error_happened = true ;
1584
- } ,
1624
+ self . resolve_vars_if_possible ( fresh_base_ty) ,
1625
+ |_| { } ,
1585
1626
) ;
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
1631
1628
} else {
1632
1629
// Check the base_expr, regardless of a bad expected adt_ty, so we can get
1633
1630
// type errors on that expression, too.
0 commit comments