@@ -39,6 +39,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
39
39
use rustc_trait_selection:: traits:: {
40
40
self , FulfillmentError , ObligationCause , ObligationCauseCode , ObligationCtxt , WellFormedLoc ,
41
41
} ;
42
+ use rustc_type_ir:: solve:: NoSolution ;
42
43
use rustc_type_ir:: TypeFlags ;
43
44
44
45
use std:: cell:: LazyCell ;
@@ -1712,13 +1713,12 @@ fn receiver_is_valid<'tcx>(
1712
1713
let cause =
1713
1714
ObligationCause :: new ( span, wfcx. body_def_id , traits:: ObligationCauseCode :: MethodReceiver ) ;
1714
1715
1715
- let can_eq_self = |ty| infcx. can_eq ( wfcx. param_env , self_ty, ty) ;
1716
-
1717
- // `self: Self` is always valid.
1718
- if can_eq_self ( receiver_ty) {
1719
- if let Err ( err) = wfcx. eq ( & cause, wfcx. param_env , self_ty, receiver_ty) {
1720
- infcx. err_ctxt ( ) . report_mismatched_types ( & cause, self_ty, receiver_ty, err) . emit ( ) ;
1721
- }
1716
+ // Special case `receiver == self_ty`, which doesn't necessarily require the `Receiver` lang item.
1717
+ if let Ok ( ( ) ) = wfcx. infcx . commit_if_ok ( |_| {
1718
+ let ocx = ObligationCtxt :: new ( wfcx. infcx ) ;
1719
+ ocx. eq ( & cause, wfcx. param_env , self_ty, receiver_ty) ?;
1720
+ if ocx. select_all_or_error ( ) . is_empty ( ) { Ok ( ( ) ) } else { Err ( NoSolution ) }
1721
+ } ) {
1722
1722
return true ;
1723
1723
}
1724
1724
@@ -1729,58 +1729,51 @@ fn receiver_is_valid<'tcx>(
1729
1729
autoderef = autoderef. include_raw_pointers ( ) ;
1730
1730
}
1731
1731
1732
- // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
1733
- autoderef. next ( ) ;
1734
-
1735
1732
let receiver_trait_def_id = tcx. require_lang_item ( LangItem :: Receiver , Some ( span) ) ;
1736
1733
1737
1734
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
1738
- loop {
1739
- if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
1740
- debug ! (
1741
- "receiver_is_valid: potential self type `{:?}` to match `{:?}`" ,
1742
- potential_self_ty, self_ty
1743
- ) ;
1744
-
1745
- if can_eq_self ( potential_self_ty) {
1746
- wfcx. register_obligations ( autoderef. into_obligations ( ) ) ;
1735
+ while let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
1736
+ debug ! (
1737
+ "receiver_is_valid: potential self type `{:?}` to match `{:?}`" ,
1738
+ potential_self_ty, self_ty
1739
+ ) ;
1747
1740
1748
- if let Err ( err) = wfcx. eq ( & cause, wfcx. param_env , self_ty, potential_self_ty) {
1749
- infcx
1750
- . err_ctxt ( )
1751
- . report_mismatched_types ( & cause, self_ty, potential_self_ty, err)
1752
- . emit ( ) ;
1753
- }
1741
+ // Check if the self type unifies. If it does, then commit the result
1742
+ // since it may have region side-effects.
1743
+ if let Ok ( ( ) ) = wfcx. infcx . commit_if_ok ( |_| {
1744
+ let ocx = ObligationCtxt :: new ( wfcx. infcx ) ;
1745
+ ocx. eq ( & cause, wfcx. param_env , self_ty, potential_self_ty) ?;
1746
+ if ocx. select_all_or_error ( ) . is_empty ( ) { Ok ( ( ) ) } else { Err ( NoSolution ) }
1747
+ } ) {
1748
+ wfcx. register_obligations ( autoderef. into_obligations ( ) ) ;
1749
+ return true ;
1750
+ }
1754
1751
1752
+ // Without `feature(arbitrary_self_types)`, we require that each step in the
1753
+ // deref chain implement `receiver`.
1754
+ if !arbitrary_self_types_enabled {
1755
+ if !receiver_is_implemented (
1756
+ wfcx,
1757
+ receiver_trait_def_id,
1758
+ cause. clone ( ) ,
1759
+ potential_self_ty,
1760
+ ) {
1761
+ // We cannot proceed.
1755
1762
break ;
1756
- } else {
1757
- // Without `feature(arbitrary_self_types)`, we require that each step in the
1758
- // deref chain implement `receiver`
1759
- if !arbitrary_self_types_enabled
1760
- && !receiver_is_implemented (
1761
- wfcx,
1762
- receiver_trait_def_id,
1763
- cause. clone ( ) ,
1764
- potential_self_ty,
1765
- )
1766
- {
1767
- return false ;
1768
- }
1769
1763
}
1770
- } else {
1771
- debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" , receiver_ty, self_ty) ;
1772
- return false ;
1773
- }
1774
- }
1775
1764
1776
- // Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
1777
- if !arbitrary_self_types_enabled
1778
- && !receiver_is_implemented ( wfcx, receiver_trait_def_id, cause. clone ( ) , receiver_ty)
1779
- {
1780
- return false ;
1765
+ // Register the bound, in case it has any region side-effects.
1766
+ wfcx. register_bound (
1767
+ cause. clone ( ) ,
1768
+ wfcx. param_env ,
1769
+ potential_self_ty,
1770
+ receiver_trait_def_id,
1771
+ ) ;
1772
+ }
1781
1773
}
1782
1774
1783
- true
1775
+ debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" , receiver_ty, self_ty) ;
1776
+ false
1784
1777
}
1785
1778
1786
1779
fn receiver_is_implemented < ' tcx > (
0 commit comments