@@ -41,8 +41,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
41
41
use rustc_infer:: infer:: InferOk ;
42
42
use rustc_middle:: middle:: stability;
43
43
use 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 ;
46
45
use rustc_middle:: ty:: subst:: SubstsRef ;
47
46
use rustc_middle:: ty:: { self , AdtKind , DefIdTree , Ty , TypeFoldable } ;
48
47
use rustc_session:: parse:: feature_err;
@@ -65,7 +64,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
65
64
& self ,
66
65
expr : & ' tcx hir:: Expr < ' tcx > ,
67
66
expected : Ty < ' tcx > ,
68
- extend_err : impl Fn ( & mut Diagnostic ) ,
67
+ extend_err : impl FnMut ( & mut Diagnostic ) ,
69
68
) -> Ty < ' tcx > {
70
69
self . check_expr_meets_expectation_or_error ( expr, ExpectHasType ( expected) , extend_err)
71
70
}
@@ -74,7 +73,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
74
73
& self ,
75
74
expr : & ' tcx hir:: Expr < ' tcx > ,
76
75
expected : Expectation < ' tcx > ,
77
- extend_err : impl Fn ( & mut Diagnostic ) ,
76
+ mut extend_err : impl FnMut ( & mut Diagnostic ) ,
78
77
) -> Ty < ' tcx > {
79
78
let expected_ty = expected. to_option ( & self ) . unwrap_or ( self . tcx . types . bool ) ;
80
79
let mut ty = self . check_expr_with_expectation ( expr, expected) ;
@@ -1480,10 +1479,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1480
1479
// re-link the regions that EIfEO can erase.
1481
1480
self . demand_eqtype ( span, adt_ty_hint, adt_ty) ;
1482
1481
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" ) ;
1486
1484
} ;
1485
+ let adt_kind = adt. adt_kind ( ) ;
1487
1486
1488
1487
let mut remaining_fields = variant
1489
1488
. fields
@@ -1521,7 +1520,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1521
1520
} ) ;
1522
1521
} else {
1523
1522
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,
1525
1529
) ;
1526
1530
}
1527
1531
@@ -1534,7 +1538,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1534
1538
}
1535
1539
1536
1540
// Make sure the programmer specified correct number of fields.
1537
- if kind_name == "union" {
1541
+ if adt_kind == AdtKind :: Union {
1538
1542
if ast_fields. len ( ) != 1 {
1539
1543
struct_span_err ! (
1540
1544
tcx. sess,
@@ -1557,67 +1561,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1557
1561
// FIXME: We are currently creating two branches here in order to maintain
1558
1562
// consistency. But they should be merged as much as possible.
1559
1563
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)
1598
1609
}
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`" ) ;
1613
1628
}
1614
- }
1615
- _ => {
1616
- self . tcx
1617
- . sess
1618
- . emit_err ( FunctionalRecordUpdateOnNonStruct { span : base_expr. span } ) ;
1619
1629
return ;
1620
1630
}
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 ;
1621
1639
}
1622
1640
} else {
1623
1641
self . check_expr_has_type_or_error ( base_expr, adt_ty, |_| {
@@ -1653,7 +1671,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1653
1671
}
1654
1672
} ;
1655
1673
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 ( ) {
1657
1675
let inaccessible_remaining_fields = remaining_fields. iter ( ) . any ( |( _, ( _, field) ) | {
1658
1676
!field. vis . is_accessible_from ( tcx. parent_module ( expr_id) . to_def_id ( ) , tcx)
1659
1677
} ) ;
0 commit comments