@@ -29,7 +29,6 @@ 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 ;
3332use rustc_trait_selection:: regions:: InferCtxtRegionExt ;
3433use rustc_trait_selection:: traits:: error_reporting:: TypeErrCtxtExt ;
3534use rustc_trait_selection:: traits:: misc:: {
@@ -40,6 +39,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
4039use rustc_trait_selection:: traits:: {
4140 self , FulfillmentError , ObligationCause , ObligationCauseCode , ObligationCtxt , WellFormedLoc ,
4241} ;
42+ use rustc_type_ir:: solve:: NoSolution ;
4343use rustc_type_ir:: TypeFlags ;
4444
4545use std:: cell:: LazyCell ;
@@ -1713,13 +1713,12 @@ fn receiver_is_valid<'tcx>(
17131713 let cause =
17141714 ObligationCause :: new ( span, wfcx. body_def_id , traits:: ObligationCauseCode :: MethodReceiver ) ;
17151715
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+ } ) {
17231722 return true ;
17241723 }
17251724
@@ -1730,58 +1729,51 @@ fn receiver_is_valid<'tcx>(
17301729 autoderef = autoderef. include_raw_pointers ( ) ;
17311730 }
17321731
1733- // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
1734- autoderef. next ( ) ;
1735-
17361732 let receiver_trait_def_id = tcx. require_lang_item ( LangItem :: Receiver , Some ( span) ) ;
17371733
17381734 // 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+ ) ;
17481740
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+ }
17551751
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.
17561762 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- }
17701763 }
1771- } else {
1772- debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" , receiver_ty, self_ty) ;
1773- return false ;
1774- }
1775- }
17761764
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+ }
17821773 }
17831774
1784- true
1775+ debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" , receiver_ty, self_ty) ;
1776+ false
17851777}
17861778
17871779fn receiver_is_implemented < ' tcx > (
0 commit comments