@@ -29,7 +29,6 @@ use rustc_session::parse::feature_err;
29
29
use rustc_span:: symbol:: { sym, Ident } ;
30
30
use rustc_span:: { Span , DUMMY_SP } ;
31
31
use rustc_target:: spec:: abi:: Abi ;
32
- use rustc_trait_selection:: infer:: InferCtxtExt ;
33
32
use rustc_trait_selection:: regions:: InferCtxtRegionExt ;
34
33
use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
35
34
use rustc_trait_selection:: traits:: misc:: {
@@ -40,6 +39,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
40
39
use rustc_trait_selection:: traits:: {
41
40
self , FulfillmentError , ObligationCause , ObligationCauseCode , ObligationCtxt , WellFormedLoc ,
42
41
} ;
42
+ use rustc_type_ir:: solve:: NoSolution ;
43
43
use rustc_type_ir:: TypeFlags ;
44
44
45
45
use std:: cell:: LazyCell ;
@@ -1713,13 +1713,12 @@ fn receiver_is_valid<'tcx>(
1713
1713
let cause =
1714
1714
ObligationCause :: new ( span, wfcx. body_def_id , traits:: ObligationCauseCode :: MethodReceiver ) ;
1715
1715
1716
- let can_eq_self = |ty| infcx. can_eq ( wfcx. param_env , self_ty, ty) ;
1717
-
1718
- // `self: Self` is always valid.
1719
- if can_eq_self ( receiver_ty) {
1720
- if let Err ( err) = wfcx. eq ( & cause, wfcx. param_env , self_ty, receiver_ty) {
1721
- infcx. err_ctxt ( ) . report_mismatched_types ( & cause, self_ty, receiver_ty, err) . emit ( ) ;
1722
- }
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
+ } ) {
1723
1722
return true ;
1724
1723
}
1725
1724
@@ -1730,58 +1729,51 @@ fn receiver_is_valid<'tcx>(
1730
1729
autoderef = autoderef. include_raw_pointers ( ) ;
1731
1730
}
1732
1731
1733
- // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
1734
- autoderef. next ( ) ;
1735
-
1736
1732
let receiver_trait_def_id = tcx. require_lang_item ( LangItem :: Receiver , Some ( span) ) ;
1737
1733
1738
1734
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
1739
- loop {
1740
- if let Some ( ( potential_self_ty, _) ) = autoderef. next ( ) {
1741
- debug ! (
1742
- "receiver_is_valid: potential self type `{:?}` to match `{:?}`" ,
1743
- potential_self_ty, self_ty
1744
- ) ;
1745
-
1746
- if can_eq_self ( potential_self_ty) {
1747
- 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
+ ) ;
1748
1740
1749
- if let Err ( err) = wfcx. eq ( & cause, wfcx. param_env , self_ty, potential_self_ty) {
1750
- infcx
1751
- . err_ctxt ( )
1752
- . report_mismatched_types ( & cause, self_ty, potential_self_ty, err)
1753
- . emit ( ) ;
1754
- }
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
+ }
1755
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.
1756
1762
break ;
1757
- } else {
1758
- // Without `feature(arbitrary_self_types)`, we require that each step in the
1759
- // deref chain implement `receiver`
1760
- if !arbitrary_self_types_enabled
1761
- && !receiver_is_implemented (
1762
- wfcx,
1763
- receiver_trait_def_id,
1764
- cause. clone ( ) ,
1765
- potential_self_ty,
1766
- )
1767
- {
1768
- return false ;
1769
- }
1770
1763
}
1771
- } else {
1772
- debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" , receiver_ty, self_ty) ;
1773
- return false ;
1774
- }
1775
- }
1776
1764
1777
- // Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
1778
- if !arbitrary_self_types_enabled
1779
- && !receiver_is_implemented ( wfcx, receiver_trait_def_id, cause. clone ( ) , receiver_ty)
1780
- {
1781
- 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
+ }
1782
1773
}
1783
1774
1784
- true
1775
+ debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" , receiver_ty, self_ty) ;
1776
+ false
1785
1777
}
1786
1778
1787
1779
fn receiver_is_implemented < ' tcx > (
0 commit comments