@@ -29,6 +29,7 @@ use rustc_session::parse::feature_err;
2929use rustc_span:: symbol:: { sym, Ident } ;
3030use rustc_span:: { Span , DUMMY_SP } ;
3131use rustc_target:: spec:: abi:: Abi ;
32+ use rustc_trait_selection:: infer:: InferCtxtExt ;
3233use rustc_trait_selection:: regions:: InferCtxtRegionExt ;
3334use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
3435use rustc_trait_selection:: traits:: misc:: {
@@ -39,7 +40,6 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
3940use rustc_trait_selection:: traits:: {
4041 self , FulfillmentError , ObligationCause , ObligationCauseCode , ObligationCtxt , WellFormedLoc ,
4142} ;
42- use rustc_type_ir:: solve:: NoSolution ;
4343use rustc_type_ir:: TypeFlags ;
4444
4545use std:: cell:: LazyCell ;
@@ -1713,12 +1713,13 @@ fn receiver_is_valid<'tcx>(
17131713 let cause =
17141714 ObligationCause :: new ( span, wfcx. body_def_id , traits:: ObligationCauseCode :: MethodReceiver ) ;
17151715
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+ }
17221723 return true ;
17231724 }
17241725
@@ -1729,51 +1730,58 @@ fn receiver_is_valid<'tcx>(
17291730 autoderef = autoderef. include_raw_pointers ( ) ;
17301731 }
17311732
1733+ // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
1734+ autoderef. next ( ) ;
1735+
17321736 let receiver_trait_def_id = tcx. require_lang_item ( LangItem :: Receiver , Some ( span) ) ;
17331737
17341738 // 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+ ) ;
17401745
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+ }
17511755
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.
17621756 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+ }
17631770 }
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 ;
17721774 }
17731775 }
17741776
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
17771785}
17781786
17791787fn receiver_is_implemented < ' tcx > (
0 commit comments