@@ -39,6 +39,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
3939use rustc_trait_selection:: traits:: {
4040 self , FulfillmentError , ObligationCause , ObligationCauseCode , ObligationCtxt , WellFormedLoc ,
4141} ;
42+ use rustc_type_ir:: solve:: NoSolution ;
4243use rustc_type_ir:: TypeFlags ;
4344
4445use std:: cell:: LazyCell ;
@@ -1712,13 +1713,12 @@ fn receiver_is_valid<'tcx>(
17121713 let cause =
17131714 ObligationCause :: new ( span, wfcx. body_def_id , traits:: ObligationCauseCode :: MethodReceiver ) ;
17141715
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+ } ) {
17221722 return true ;
17231723 }
17241724
@@ -1729,58 +1729,51 @@ fn receiver_is_valid<'tcx>(
17291729 autoderef = autoderef. include_raw_pointers ( ) ;
17301730 }
17311731
1732- // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
1733- autoderef. next ( ) ;
1734-
17351732 let receiver_trait_def_id = tcx. require_lang_item ( LangItem :: Receiver , Some ( span) ) ;
17361733
17371734 // 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+ ) ;
17471740
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+ }
17541751
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.
17551762 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- }
17691763 }
1770- } else {
1771- debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" , receiver_ty, self_ty) ;
1772- return false ;
1773- }
1774- }
17751764
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+ }
17811773 }
17821774
1783- true
1775+ debug ! ( "receiver_is_valid: type `{:?}` does not deref to `{:?}`" , receiver_ty, self_ty) ;
1776+ false
17841777}
17851778
17861779fn receiver_is_implemented < ' tcx > (
0 commit comments