@@ -29,6 +29,7 @@ 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 ;
32
33
use rustc_trait_selection:: regions:: InferCtxtRegionExt ;
33
34
use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
34
35
use rustc_trait_selection:: traits:: misc:: {
@@ -39,7 +40,6 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
39
40
use rustc_trait_selection:: traits:: {
40
41
self , FulfillmentError , ObligationCause , ObligationCauseCode , ObligationCtxt , WellFormedLoc ,
41
42
} ;
42
- use rustc_type_ir:: solve:: NoSolution ;
43
43
use rustc_type_ir:: TypeFlags ;
44
44
45
45
use std:: cell:: LazyCell ;
@@ -1713,12 +1713,13 @@ fn receiver_is_valid<'tcx>(
1713
1713
let cause =
1714
1714
ObligationCause :: new ( span, wfcx. body_def_id , traits:: ObligationCauseCode :: MethodReceiver ) ;
1715
1715
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
- } ) {
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
+ }
1722
1723
return true ;
1723
1724
}
1724
1725
@@ -1729,51 +1730,58 @@ fn receiver_is_valid<'tcx>(
1729
1730
autoderef = autoderef. include_raw_pointers ( ) ;
1730
1731
}
1731
1732
1733
+ // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
1734
+ autoderef. next ( ) ;
1735
+
1732
1736
let receiver_trait_def_id = tcx. require_lang_item ( LangItem :: Receiver , Some ( span) ) ;
1733
1737
1734
1738
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
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
- ) ;
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
+ ) ;
1740
1745
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
- }
1746
+ if can_eq_self ( potential_self_ty) {
1747
+ wfcx. register_obligations ( autoderef. into_obligations ( ) ) ;
1748
+
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
+ }
1751
1755
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.
1762
1756
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
+ }
1763
1770
}
1764
-
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
- ) ;
1771
+ } else {
1772
+ debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" , receiver_ty, self_ty) ;
1773
+ return false ;
1772
1774
}
1773
1775
}
1774
1776
1775
- debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" , receiver_ty, self_ty) ;
1776
- false
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 ;
1782
+ }
1783
+
1784
+ true
1777
1785
}
1778
1786
1779
1787
fn receiver_is_implemented < ' tcx > (
0 commit comments