diff --git a/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs b/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs index f0d1f6e221572..d1835829e0726 100644 --- a/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs +++ b/compiler/rustc_codegen_cranelift/example/arbitrary_self_types_pointers_and_wrappers.rs @@ -3,7 +3,7 @@ #![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)] use std::marker::Unsize; -use std::ops::{CoerceUnsized, Deref, DispatchFromDyn}; +use std::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; struct Ptr(Box); @@ -14,6 +14,9 @@ impl Deref for Ptr { &*self.0 } } +impl Receiver for Ptr { + type Target = T; +} impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} impl + ?Sized, U: ?Sized> DispatchFromDyn> for Ptr {} @@ -27,6 +30,9 @@ impl Deref for Wrapper { &self.0 } } +impl Receiver for Wrapper { + type Target = T; +} impl, U> CoerceUnsized> for Wrapper {} impl, U> DispatchFromDyn> for Wrapper {} diff --git a/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs b/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs index c26606f0bdd5c..afae06b576aea 100644 --- a/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs +++ b/compiler/rustc_codegen_gcc/example/arbitrary_self_types_pointers_and_wrappers.rs @@ -4,10 +4,8 @@ #![feature(rustc_attrs)] #![allow(internal_features)] -use std::{ - ops::{Deref, CoerceUnsized, DispatchFromDyn}, - marker::Unsize, -}; +use std::marker::Unsize; +use std::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; struct Ptr(Box); @@ -18,6 +16,9 @@ impl Deref for Ptr { &*self.0 } } +impl Receiver for Ptr { + type Target = T; +} impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} impl + ?Sized, U: ?Sized> DispatchFromDyn> for Ptr {} @@ -31,11 +32,13 @@ impl Deref for Wrapper { &self.0 } } +impl Receiver for Wrapper { + type Target = T; +} impl, U> CoerceUnsized> for Wrapper {} impl, U> DispatchFromDyn> for Wrapper {} - trait Trait { fn ptr_wrapper(self: Ptr>) -> i32; fn wrapper_ptr(self: Wrapper>) -> i32; diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index 8079212fac551..cf033cf8b4b8c 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -2,6 +2,8 @@ use std::cmp::Ordering; use std::fmt::{self, Debug}; use std::hash::{Hash, Hasher}; use std::ops::Deref; +#[cfg(not(bootstrap))] +use std::ops::Receiver; use std::ptr; use crate::stable_hasher::{HashStable, StableHasher}; @@ -54,6 +56,11 @@ impl<'a, T> Deref for Interned<'a, T> { } } +#[cfg(not(bootstrap))] +impl<'a, T> Receiver for Interned<'a, T> { + type Target = T; +} + impl<'a, T> PartialEq for Interned<'a, T> { #[inline] fn eq(&self, other: &Self) -> bool { diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 41f6292e740bd..21334fffc81cb 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -13,6 +13,7 @@ #![cfg_attr(bootstrap, feature(array_windows))] #![deny(unsafe_op_in_unsafe_fn)] #![feature(allocator_api)] +#![feature(arbitrary_self_types)] #![feature(ascii_char)] #![feature(ascii_char_variants)] #![feature(assert_matches)] diff --git a/compiler/rustc_error_codes/src/error_codes/E0307.md b/compiler/rustc_error_codes/src/error_codes/E0307.md index b9c0493e8d6e6..e997c3f7e3b44 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0307.md +++ b/compiler/rustc_error_codes/src/error_codes/E0307.md @@ -67,8 +67,6 @@ impl Trait for Foo { The nightly feature [Arbitrary self types][AST] extends the accepted set of receiver types to also include any type that implements the `Receiver` trait and can follow its chain of `Target` types to `Self`. -There's a blanket implementation of `Receiver` for `T: Deref`, so any -type which dereferences to `Self` can be used. ``` #![feature(arbitrary_self_types)] @@ -76,13 +74,9 @@ type which dereferences to `Self` can be used. struct Foo; struct Bar; -// Because you can dereference `Bar` into `Foo`... -impl std::ops::Deref for Bar { +// Because you can set `Bar` as method receiver for `Foo`... +impl std::ops::Receiver for Bar { type Target = Foo; - - fn deref(&self) -> &Foo { - &Foo - } } impl Foo { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index ca2ce2f18812b..9f5a4c9b3e39b 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -353,6 +353,8 @@ declare_features! ( (unstable, arbitrary_self_types, "1.23.0", Some(44874)), /// Allows inherent and trait methods with arbitrary self types that are raw pointers. (unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)), + /// Enforce agreement between `Receiver::Target` and `Deref::Target` + (unstable, arbitrary_self_types_split_chains, "1.23.0", Some(44874)), /// Target features on arm. (unstable, arm_target_feature, "1.27.0", Some(150246)), /// Enables experimental inline assembly support for additional architectures. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 416a6b19edfc8..453f63d940727 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -149,6 +149,11 @@ hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like ` hir_analysis_cross_crate_traits_defined = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate .label = can't implement cross-crate trait for type in another crate +hir_analysis_deref_receiver_target_diverge = `Deref::Target` does not agree with `Receiver::Target` + .label = `Deref::Target` is `{$deref_ty}` but `Receiver::Target` is `{$recv_ty}` + .note = `#![feature(arbitrary_self_types_merge_chains)]` rejects this kind of divergence +hir_analysis_deref_receiver_target_diverge_feature = `Receiver::Target` diverging from `Deref::Target` is not supported, we look forward to your feedback + hir_analysis_dispatch_from_dyn_repr = structs implementing `DispatchFromDyn` may not have `#[repr(packed)]` or `#[repr(C)]` hir_analysis_dispatch_from_dyn_zst = the trait `DispatchFromDyn` may only be implemented for structs containing the field being coerced, ZST fields with 1 byte alignment that don't mention type/const generics, and nothing else @@ -259,7 +264,8 @@ hir_analysis_invalid_receiver_ty_help = consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types = - consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable hir_analysis_invalid_receiver_ty_help_nonnull_note = `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver` diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 1f06b1c94237d..1e992ab3dc207 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -1,3 +1,6 @@ +use std::cell::RefCell; + +use rustc_data_structures::unord::UnordMap; use rustc_hir::limit::Limit; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::PredicateObligations; @@ -26,6 +29,39 @@ struct AutoderefSnapshot<'tcx> { obligations: PredicateObligations<'tcx>, } +#[derive(Debug, Default)] +pub struct AutoderefCache<'tcx> { + next_deref: RefCell, (Ty<'tcx>, PredicateObligations<'tcx>)>>, + next_receiver: RefCell, (Ty<'tcx>, PredicateObligations<'tcx>)>>, +} + +impl<'tcx> AutoderefCache<'tcx> { + pub fn get( + &self, + use_receiver: bool, + ty: Ty<'tcx>, + ) -> Option<(Ty<'tcx>, PredicateObligations<'tcx>)> { + if use_receiver { + self.next_receiver.borrow().get(&ty).cloned() + } else { + self.next_deref.borrow().get(&ty).cloned() + } + } + pub fn cache( + &self, + use_receiver: bool, + ty: Ty<'tcx>, + next: Ty<'tcx>, + predicates: PredicateObligations<'tcx>, + ) { + if use_receiver { + self.next_receiver.borrow_mut().insert(ty, (next, predicates)); + } else { + self.next_deref.borrow_mut().insert(ty, (next, predicates)); + } + } +} + /// Recursively dereference a type, considering both built-in /// dereferences (`*`) and the `Deref` trait. /// Although called `Autoderef` it can be configured to use the @@ -36,6 +72,7 @@ pub struct Autoderef<'a, 'tcx> { span: Span, body_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, + cache: Option<&'a AutoderefCache<'tcx>>, // Current state: state: AutoderefSnapshot<'tcx>, @@ -80,16 +117,19 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { } // Otherwise, deref if type is derefable: - // NOTE: in the case of self.use_receiver_trait = true, you might think it would - // be better to skip this clause and use the Overloaded case only, since &T - // and &mut T implement Receiver. But built-in derefs apply equally to Receiver - // and Deref, and this has benefits for const and the emitted MIR. + // NOTE: in the case of self.use_receiver_trait = true, + // Autoderef works only with Receiver trait. + // Caller is expecting us to expand the Receiver chain only. let (kind, new_ty) = if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) { debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty)); // NOTE: we may still need to normalize the built-in deref in case // we have some type like `&::Assoc`, since users of // autoderef expect this type to have been structurally normalized. + // NOTE: even when we follow Receiver chain we still unwrap + // references and pointers here, but this is only symbolic and + // we are not going to really dereferences any references or pointers. + // That happens when autoderef is chasing the Deref chain. if self.infcx.next_trait_solver() && let ty::Alias(..) = ty.kind() { @@ -122,6 +162,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> { impl<'a, 'tcx> Autoderef<'a, 'tcx> { pub fn new( infcx: &'a InferCtxt<'tcx>, + cache: Option<&'a AutoderefCache<'tcx>>, param_env: ty::ParamEnv<'tcx>, body_def_id: LocalDefId, span: Span, @@ -129,6 +170,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { ) -> Self { Autoderef { infcx, + cache, span, body_id: body_def_id, param_env, @@ -145,13 +187,19 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self), ret)] fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option> { - debug!("overloaded_deref_ty({:?})", ty); let tcx = self.infcx.tcx; if ty.references_error() { return None; } + if let Some(cache) = &self.cache + && let Some((ty, obligations)) = cache.get(self.use_receiver_trait, self.state.cur_ty) + { + self.state.obligations.extend(obligations); + return Some(ty); + } // , or whatever the equivalent trait is that we've been asked to walk. let (trait_def_id, trait_target_def_id) = if self.use_receiver_trait { @@ -167,18 +215,23 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { self.param_env, ty::Binder::dummy(trait_ref), ); - // We detect whether the self type implements `Deref` before trying to + // We detect whether the self type implements `Deref`/`Receiver` before trying to // structurally normalize. We use `predicate_may_hold_opaque_types_jank` // to support not-yet-defined opaque types. It will succeed for `impl Deref` // but fail for `impl OtherTrait`. if !self.infcx.predicate_may_hold_opaque_types_jank(&obligation) { - debug!("overloaded_deref_ty: cannot match obligation"); + debug!("cannot match obligation"); return None; } let (normalized_ty, obligations) = self.structurally_normalize_ty(Ty::new_projection(tcx, trait_target_def_id, [ty]))?; - debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations); + debug!(?ty, ?normalized_ty, ?obligations); + if matches!(ty.kind(), ty::Adt(..)) + && let Some(cache) = &self.cache + { + cache.cache(self.use_receiver_trait, ty, normalized_ty, obligations.clone()); + } self.state.obligations.extend(obligations); Some(self.infcx.resolve_vars_if_possible(normalized_ty)) @@ -255,11 +308,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { /// Use `core::ops::Receiver` and `core::ops::Receiver::Target` as /// the trait and associated type to iterate, instead of /// `core::ops::Deref` and `core::ops::Deref::Target` - pub fn use_receiver_trait(mut self) -> Self { + pub fn follow_receiver_chain(mut self) -> Self { self.use_receiver_trait = true; self } - pub fn silence_errors(mut self) -> Self { self.silence_errors = true; self diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 725294dfd3771..88606f5cb1c16 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1770,7 +1770,9 @@ fn check_method_receiver<'tcx>( // Report error; would not have worked with `arbitrary_self_types[_pointers]`. { match receiver_validity_err { - ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => { + ReceiverValidityError::DoesNotReceive + if arbitrary_self_types_level.is_some() => + { let hint = match receiver_ty .builtin_deref(false) .unwrap_or(receiver_ty) @@ -1784,7 +1786,7 @@ fn check_method_receiver<'tcx>( tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty, hint }) } - ReceiverValidityError::DoesNotDeref => { + ReceiverValidityError::DoesNotReceive => { tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes { span, receiver_ty, @@ -1806,7 +1808,7 @@ fn check_method_receiver<'tcx>( enum ReceiverValidityError { /// The self type does not get to the receiver type by following the /// autoderef chain. - DoesNotDeref, + DoesNotReceive, /// A type was found which is a method type parameter, and that's not allowed. MethodGenericParamUsed, } @@ -1862,17 +1864,21 @@ fn receiver_is_valid<'tcx>( confirm_type_is_not_a_method_generic_param(receiver_ty, method_generics)?; - let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_def_id, span, receiver_ty); + let cache = Default::default(); + let mut autoderef = + Autoderef::new(infcx, Some(&cache), wfcx.param_env, wfcx.body_def_id, span, receiver_ty); // The `arbitrary_self_types` feature allows custom smart pointer - // types to be method receivers, as identified by following the Receiver + // types to be method receivers, as identified by following the Receiver // chain. if arbitrary_self_types_enabled.is_some() { - autoderef = autoderef.use_receiver_trait(); + // We are in the wf check, so we would like to deref the references in the type head. + // However, we do not want to walk `Deref` chain. + autoderef = autoderef.follow_receiver_chain(); } // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`. - if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) { + if matches!(arbitrary_self_types_enabled, Some(ArbitrarySelfTypesLevel::WithPointers)) { autoderef = autoderef.include_raw_pointers(); } @@ -1926,7 +1932,7 @@ fn receiver_is_valid<'tcx>( } debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty); - Err(ReceiverValidityError::DoesNotDeref) + Err(ReceiverValidityError::DoesNotReceive) } fn legacy_receiver_is_implemented<'tcx>( diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 61562cc1e4f30..cb61834011ee3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -16,13 +16,14 @@ use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeVisitableExt, TypingMode, suggest_constraining_type_params, }; +use rustc_session::parse::feature_err; use rustc_span::{DUMMY_SP, Span, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::misc::{ ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason, type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy, }; -use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt}; +use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCause, ObligationCtxt}; use tracing::debug; use crate::errors; @@ -48,6 +49,7 @@ pub(super) fn check_trait<'tcx>( lang_items.coerce_pointee_validated_trait(), visit_implementation_of_coerce_pointee_validity, )?; + checker.check(lang_items.receiver_trait(), visit_implementation_of_receiver)?; Ok(()) } @@ -755,3 +757,55 @@ fn visit_implementation_of_coerce_pointee_validity( } Ok(()) } + +fn visit_implementation_of_receiver(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { + let tcx = checker.tcx; + if tcx.features().arbitrary_self_types_split_chains() { + return Ok(()); + } + let impl_did = checker.impl_def_id; + let span = tcx.def_span(impl_did); + let deref_target_did = tcx.require_lang_item(LangItem::DerefTarget, span); + let receiver_target_did = tcx.require_lang_item(LangItem::ReceiverTarget, span); + let self_ty = tcx.impl_trait_ref(impl_did).instantiate_identity().self_ty(); + let param_env = tcx.param_env(impl_did); + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let ocx = ObligationCtxt::new(&infcx); + let cause = ObligationCause::misc(span, impl_did); + ocx.register_obligation(Obligation::new( + tcx, + cause.clone(), + param_env, + ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::Deref, span), [self_ty]), + )); + if !ocx.evaluate_obligations_error_on_ambiguity().is_empty() { + // We cannot enforce Deref::Target == Receiver::Target because we cannot find `impl Deref` + return Ok(()); + } + let infer::InferOk { value: deref_target_ty, .. } = infcx.at(&cause, param_env).normalize( + Ty::new_projection_from_args(tcx, deref_target_did, tcx.mk_args(&[self_ty.into()])), + ); + let infer::InferOk { value: receiver_target_ty, .. } = infcx.at(&cause, param_env).normalize( + Ty::new_projection_from_args(tcx, receiver_target_did, tcx.mk_args(&[self_ty.into()])), + ); + if let Err(_) = infcx.at(&cause, param_env).eq( + infer::DefineOpaqueTypes::No, + deref_target_ty, + receiver_target_ty, + ) { + feature_err( + tcx.sess, + sym::arbitrary_self_types_split_chains, + span, + crate::fluent_generated::hir_analysis_deref_receiver_target_diverge_feature, + ) + .emit(); + Err(tcx.dcx().emit_err(errors::DerefReceiverTargetDiverge { + span, + deref_ty: deref_target_ty, + recv_ty: receiver_target_ty, + })) + } else { + Ok(()) + } +} diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index b388396ac4fcd..19adf08a0d328 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1075,6 +1075,17 @@ pub(crate) struct CoercePointeeNoField { pub span: Span, } +#[derive(Diagnostic)] +#[diag(hir_analysis_deref_receiver_target_diverge)] +pub(crate) struct DerefReceiverTargetDiverge<'a> { + #[primary_span] + #[label] + #[note] + pub span: Span, + pub deref_ty: Ty<'a>, + pub recv_ty: Ty<'a>, +} + #[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)] #[help] diff --git a/compiler/rustc_hir_typeck/src/autoderef.rs b/compiler/rustc_hir_typeck/src/autoderef.rs index 4fe77278706ec..9e4dc040f36b0 100644 --- a/compiler/rustc_hir_typeck/src/autoderef.rs +++ b/compiler/rustc_hir_typeck/src/autoderef.rs @@ -15,7 +15,7 @@ use super::{FnCtxt, PlaceOp}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> { - Autoderef::new(self, self.param_env, self.body_id, span, base_ty) + Autoderef::new(self, None, self.param_env, self.body_id, span, base_ty) } pub(crate) fn try_overloaded_deref( diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index e81537008bb5e..a34a33a9acae6 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -1,3 +1,4 @@ +use std::marker::PhantomData; use std::ops::Deref; use rustc_hir as hir; @@ -350,18 +351,37 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // yield an object-type (e.g., `&Object` or `Box` // etc). - let mut autoderef = self.fcx.autoderef(self.span, self_ty); + let fcx = self.fcx; + let span = self.span; + let autoderef = fcx.autoderef(span, self_ty); // We don't need to gate this behind arbitrary self types // per se, but it does make things a bit more gated. - if self.tcx.features().arbitrary_self_types() - || self.tcx.features().arbitrary_self_types_pointers() - { - autoderef = autoderef.use_receiver_trait(); - } + let follow_receiver_chain = self.tcx.features().arbitrary_self_types() + || self.tcx.features().arbitrary_self_types_pointers(); autoderef .include_raw_pointers() + .flat_map(|(ty, derefs)| { + enum EitherIter { + A(A, PhantomData C>), + B(B), + } + impl, B: Iterator, C> Iterator for EitherIter { + type Item = C; + fn next(&mut self) -> Option { + match self { + EitherIter::A(a, _) => a.next(), + EitherIter::B(b) => b.next(), + } + } + } + if follow_receiver_chain { + EitherIter::A(fcx.autoderef(span, ty).follow_receiver_chain(), PhantomData) + } else { + EitherIter::B([(ty, derefs)].into_iter()) + } + }) .find_map(|(ty, _)| match ty.kind() { ty::Dynamic(data, ..) => Some(closure( self, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 1a25f6a582f22..5962b86e503ed 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -4,12 +4,16 @@ use std::cmp::max; use std::ops::Deref; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::indexmap::IndexSet; use rustc_data_structures::sso::SsoHashSet; +use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::Applicability; use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; use rustc_hir::{self as hir, ExprKind, HirId, Node, find_attr}; use rustc_hir_analysis::autoderef::{self, Autoderef}; +use rustc_index::bit_set::DenseBitSet; +use rustc_index::{IndexVec, indexvec}; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TyCtxtInferExt}; use rustc_infer::traits::{ObligationCauseCode, PredicateObligation, query}; @@ -49,6 +53,11 @@ use crate::FnCtxt; #[derive(Clone, Copy, Debug)] pub(crate) struct IsSuggestion(pub bool); +rustc_index::newtype_index! { + #[orderable] + struct CandidateIdx {} +} + pub(crate) struct ProbeContext<'a, 'tcx> { fcx: &'a FnCtxt<'a, 'tcx>, span: Span, @@ -61,9 +70,15 @@ pub(crate) struct ProbeContext<'a, 'tcx> { orig_steps_var_values: &'a OriginalQueryValues<'tcx>, steps: &'tcx [CandidateStep<'tcx>], - inherent_candidates: Vec>, + raw_inherent_candidates: IndexVec>, + did_to_inherent_candidates: UnordMap, + inherent_probe_candidates: Vec>, + inherent_probe_step_to_slot: Vec, + receiver_chain_next: Vec, + inherent_probe_start: Vec, + flattened_inherent_candidates: Vec>, + extension_candidates: Vec>, - impl_dups: FxHashSet, /// When probing for names, include names that are close to the /// requested name (by edit distance) @@ -86,6 +101,7 @@ pub(crate) struct ProbeContext<'a, 'tcx> { /// machinery, since we don't particularly care about, for example, similarly named /// candidates if we're *reporting* similarly named candidates. is_suggestion: IsSuggestion, + isolate_receiver_chain: bool, } impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> { @@ -364,7 +380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { scope, |probe_cx| { Ok(probe_cx - .inherent_candidates + .raw_inherent_candidates .into_iter() .chain(probe_cx.extension_candidates) .collect()) @@ -372,6 +388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } + #[instrument(level = "debug", skip(self, op))] pub(crate) fn probe_op( &'a self, span: Span, @@ -418,6 +435,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .make_query_response_ignoring_pending_obligations(var_values, self_ty), self_ty_is_opaque: false, autoderefs: 0, + receiver_depth: 0, from_unsafe_deref: false, unsize: false, reachable_via_deref: true, @@ -557,27 +575,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_args = self.fresh_args_for_item(trait_span, trait_def_id); let trait_ref = ty::TraitRef::new_from_args(self.tcx, trait_def_id, trait_args); - probe_cx.push_candidate( - Candidate { - item, - kind: CandidateKind::TraitCandidate(ty::Binder::dummy(trait_ref)), - import_ids: smallvec![], - }, - false, - ); + probe_cx.push_extension_candidate(Candidate { + item, + kind: CandidateKind::TraitCandidate(ty::Binder::dummy(trait_ref)), + import_ids: smallvec![], + }); } }; + probe_cx.flatten_candidates(); op(probe_cx) }) } } +#[instrument(level = "debug", skip(tcx))] pub(crate) fn method_autoderef_steps<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalMethodAutoderefStepsGoal<'tcx>, ) -> MethodAutoderefStepsResult<'tcx> { - debug!("method_autoderef_steps({:?})", goal); - let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal); let ParamEnvAnd { param_env, @@ -614,61 +629,79 @@ pub(crate) fn method_autoderef_steps<'tcx>( }; // If arbitrary self types is not enabled, we follow the chain of - // `Deref`. If arbitrary self types is enabled, we instead - // follow the chain of `Receiver`, but we also record whether - // such types are reachable by following the (potentially shorter) - // chain of `Deref`. We will use the first list when finding - // potentially relevant function implementations (e.g. relevant impl blocks) - // but the second list when determining types that the receiver may be - // converted to, in order to find out which of those methods might actually - // be callable. - let mut autoderef_via_deref = - Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty) - .include_raw_pointers() - .silence_errors(); + // `Deref` only. + // If arbitrary self types is enabled, we additionally + // follow the chain of `Receiver`. + // When the feature is enabled, we will use the first list when + // finding applicable method receiving value `self`, + // from which a second list chasing `Receiver` traits is followed + // when determining the type of `Self` and the `impl` block with + // such `Self` type. + let autoderef_cache = Default::default(); + let mut autoderef_via_deref = Autoderef::new( + infcx, + Some(&autoderef_cache), + param_env, + hir::def_id::CRATE_DEF_ID, + DUMMY_SP, + self_ty, + ) + .include_raw_pointers() + .silence_errors(); let mut reached_raw_pointer = false; let arbitrary_self_types_enabled = tcx.features().arbitrary_self_types() || tcx.features().arbitrary_self_types_pointers(); let (mut steps, reached_recursion_limit): (Vec<_>, bool) = if arbitrary_self_types_enabled { - let reachable_via_deref = - autoderef_via_deref.by_ref().map(|_| true).chain(std::iter::repeat(false)); - - let mut autoderef_via_receiver = - Autoderef::new(infcx, param_env, hir::def_id::CRATE_DEF_ID, DUMMY_SP, self_ty) - .include_raw_pointers() - .use_receiver_trait() - .silence_errors(); - let steps = autoderef_via_receiver - .by_ref() - .zip(reachable_via_deref) - .map(|((ty, d), reachable_via_deref)| { + let mut reached_recursion_limit = false; + let mut steps = vec![]; + + for (ty, autoderefs) in &mut autoderef_via_deref { + let mut recv_chain = Autoderef::new( + infcx, + Some(&autoderef_cache), + param_env, + hir::def_id::CRATE_DEF_ID, + DUMMY_SP, + ty, + ) + .follow_receiver_chain() + .silence_errors(); + if tcx.features().arbitrary_self_types_pointers() { + recv_chain = recv_chain.include_raw_pointers(); + } + steps.extend(recv_chain.by_ref().map(|(ty, receiver_depth)| { let step = CandidateStep { self_ty: infcx .make_query_response_ignoring_pending_obligations(inference_vars, ty), self_ty_is_opaque: self_ty_is_opaque(ty), - autoderefs: d, + autoderefs, + receiver_depth, from_unsafe_deref: reached_raw_pointer, unsize: false, - reachable_via_deref, + reachable_via_deref: receiver_depth == 0, }; - if ty.is_raw_ptr() { - // all the subsequent steps will be from_unsafe_deref - reached_raw_pointer = true; - } + step - }) - .collect(); - (steps, autoderef_via_receiver.reached_recursion_limit()) + })); + debug!(?steps, "finished walking receiver chain"); + if ty.is_raw_ptr() { + // all the subsequent steps will be from_unsafe_deref + reached_raw_pointer = true; + } + reached_recursion_limit |= recv_chain.reached_recursion_limit(); + } + (steps, reached_recursion_limit || autoderef_via_deref.reached_recursion_limit()) } else { let steps = autoderef_via_deref .by_ref() - .map(|(ty, d)| { + .map(|(ty, autoderefs)| { let step = CandidateStep { self_ty: infcx .make_query_response_ignoring_pending_obligations(inference_vars, ty), self_ty_is_opaque: self_ty_is_opaque(ty), - autoderefs: d, + autoderefs, + receiver_depth: 0, from_unsafe_deref: reached_raw_pointer, unsize: false, reachable_via_deref: true, @@ -701,6 +734,7 @@ pub(crate) fn method_autoderef_steps<'tcx>( ), self_ty_is_opaque: false, autoderefs, + receiver_depth: 0, // this could be from an unsafe deref if we had // a *mut/const [T; N] from_unsafe_deref: reached_raw_pointer, @@ -736,15 +770,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { scope_expr_id: HirId, is_suggestion: IsSuggestion, ) -> ProbeContext<'a, 'tcx> { - ProbeContext { + let mut this = ProbeContext { fcx, span, mode, method_name, return_type, - inherent_candidates: Vec::new(), + raw_inherent_candidates: indexvec![], + did_to_inherent_candidates: Default::default(), + inherent_probe_candidates: vec![], + inherent_probe_step_to_slot: vec![], + receiver_chain_next: vec![], + flattened_inherent_candidates: vec![], + inherent_probe_start: vec![], extension_candidates: Vec::new(), - impl_dups: FxHashSet::default(), orig_steps_var_values, steps, allow_similar_names: false, @@ -753,16 +792,60 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { static_candidates: RefCell::new(Vec::new()), scope_expr_id, is_suggestion, - } + isolate_receiver_chain: fcx.tcx.features().arbitrary_self_types() + || fcx.tcx.features().arbitrary_self_types_pointers(), + }; + this.reset(); + this } fn reset(&mut self) { - self.inherent_candidates.clear(); + self.raw_inherent_candidates.raw.clear(); + self.did_to_inherent_candidates.clear(); + self.inherent_probe_candidates.clear(); + self.inherent_probe_step_to_slot.clear(); + self.receiver_chain_next.clear(); + self.inherent_probe_start.clear(); + self.flattened_inherent_candidates.clear(); self.extension_candidates.clear(); - self.impl_dups.clear(); self.private_candidates.clear(); self.private_candidate.set(None); self.static_candidates.borrow_mut().clear(); + + let nr_steps = self.steps.len(); + let mut receiver_to_probe_step: UnordMap, usize> = Default::default(); + let mut last_receiver_chain_step = None; + self.receiver_chain_next.resize(nr_steps, nr_steps); + self.inherent_probe_candidates.reserve(nr_steps); + self.inherent_probe_step_to_slot.reserve(nr_steps); + self.inherent_probe_start + .reserve(self.steps.iter().filter(|s| s.reachable_via_deref).count()); + for (mut id, step) in self.steps.iter().enumerate() { + let mut fresh = true; + let context = step.self_ty.value.value; + debug!(?context, id); + if let Some(&prev_id) = receiver_to_probe_step.get(&context) { + id = prev_id; + self.inherent_probe_step_to_slot.push(nr_steps); + fresh = false; + } else { + receiver_to_probe_step.insert(context, id); + let slot = self.inherent_probe_candidates.len(); + self.inherent_probe_candidates.push(smallvec![]); + self.inherent_probe_step_to_slot.push(slot); + } + if step.reachable_via_deref { + self.inherent_probe_start.push(id); + self.flattened_inherent_candidates.push(smallvec![]); + if self.isolate_receiver_chain { + last_receiver_chain_step = None; + } + } + if let Some(last) = last_receiver_chain_step { + self.receiver_chain_next[last] = id; + } + last_receiver_chain_step = fresh.then_some(id); + } } /// When we're looking up a method by path (UFCS), we relate the receiver @@ -778,8 +861,39 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /////////////////////////////////////////////////////////////////////////// // CANDIDATE ASSEMBLY - fn push_candidate(&mut self, candidate: Candidate<'tcx>, is_inherent: bool) { - let is_accessible = if let Some(name) = self.method_name { + fn push_extension_candidate(&mut self, candidate: Candidate<'tcx>) { + if !self.is_candidate_visible(&candidate) { + self.private_candidates.push(candidate); + return; + } + + self.extension_candidates.push(candidate); + } + + fn push_inherent_candidate(&mut self, candidate: Candidate<'tcx>, context: usize) { + if !self.is_candidate_visible(&candidate) { + self.private_candidates.push(candidate); + return; + } + + debug!(?context, ?candidate, "push inherent"); + let id = if let InherentImplCandidate { .. } = candidate.kind { + let did = candidate.item.def_id; + if let Some(&id) = self.did_to_inherent_candidates.get(&did) { + id + } else { + let id = self.raw_inherent_candidates.push(candidate); + self.did_to_inherent_candidates.insert(did, id); + id + } + } else { + self.raw_inherent_candidates.push(candidate) + }; + self.inherent_probe_candidates[self.inherent_probe_step_to_slot[context]].push(id); + } + + fn is_candidate_visible(&self, candidate: &Candidate<'tcx>) -> bool { + if let Some(name) = self.method_name { let item = candidate.item; let hir_id = self.tcx.local_def_id_to_hir_id(self.body_id); let def_scope = @@ -787,68 +901,104 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { item.visibility(self.tcx).is_accessible_from(def_scope, self.tcx) } else { true - }; - if is_accessible { - if is_inherent { - self.inherent_candidates.push(candidate); - } else { - self.extension_candidates.push(candidate); + } + } + + fn flatten_candidates(&mut self) { + let nr_steps = self.steps.len(); + for (deref_step, &step) in self.inherent_probe_start.iter().enumerate() { + let mut step = step; + let mut visited = DenseBitSet::new_empty(nr_steps); + let mut all_candidates = IndexSet::new(); + while step < nr_steps && visited.insert(step) { + let Some(candidates) = + self.inherent_probe_candidates.get(self.inherent_probe_step_to_slot[step]) + else { + break; + }; + debug!(?step, ?candidates); + all_candidates.extend(candidates.iter().copied()); + step = self.receiver_chain_next[step]; } - } else { - self.private_candidates.push(candidate); + debug!(?deref_step, ?all_candidates); + self.flattened_inherent_candidates[deref_step] = all_candidates.into_iter().collect(); } } fn assemble_inherent_candidates(&mut self) { - for step in self.steps.iter() { - self.assemble_probe(&step.self_ty, step.autoderefs); + for (context, step) in self.steps.iter().enumerate() { + self.assemble_probe(&step.self_ty, step.receiver_depth, context); } } + fn generalized_ty(&self, ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) -> Ty<'tcx> { + // Subtle: we can't use `instantiate_query_response` here: using it will + // commit to all of the type equalities assumed by inference going through + // autoderef (see the `method-probe-no-guessing` test). + // + // However, in this code, it is OK if we end up with an object type that is + // "more general" than the object type that we are evaluating. For *every* + // object type `MY_OBJECT`, a function call that goes through a trait-ref + // of the form `::func` is a valid + // `ObjectCandidate`, and it should be discoverable "exactly" through one + // of the iterations in the autoderef loop, so there is no problem with it + // being discoverable in another one of these iterations. + // + // Using `instantiate_canonical` on our + // `Canonical>>` and then *throwing away* the + // `CanonicalVarValues` will exactly give us such a generalization - it + // will still match the original object type, but it won't pollute our + // type variables in any form, so just do that! + let (QueryResponse { value, .. }, _ignored_var_values) = + self.fcx.instantiate_canonical(self.span, ty); + value + } + #[instrument(level = "debug", skip(self))] fn assemble_probe( &mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, receiver_steps: usize, + context: usize, ) { let raw_self_ty = self_ty.value.value; + if self.inherent_probe_step_to_slot[context] >= self.inherent_probe_candidates.len() { + // This context has been explored. + return; + } match *raw_self_ty.kind() { ty::Dynamic(data, ..) if let Some(p) = data.principal() => { - // Subtle: we can't use `instantiate_query_response` here: using it will - // commit to all of the type equalities assumed by inference going through - // autoderef (see the `method-probe-no-guessing` test). - // - // However, in this code, it is OK if we end up with an object type that is - // "more general" than the object type that we are evaluating. For *every* - // object type `MY_OBJECT`, a function call that goes through a trait-ref - // of the form `::func` is a valid - // `ObjectCandidate`, and it should be discoverable "exactly" through one - // of the iterations in the autoderef loop, so there is no problem with it - // being discoverable in another one of these iterations. - // - // Using `instantiate_canonical` on our - // `Canonical>>` and then *throwing away* the - // `CanonicalVarValues` will exactly give us such a generalization - it - // will still match the original object type, but it won't pollute our - // type variables in any form, so just do that! - let (QueryResponse { value: generalized_self_ty, .. }, _ignored_var_values) = - self.fcx.instantiate_canonical(self.span, self_ty); - - self.assemble_inherent_candidates_from_object(generalized_self_ty); - self.assemble_inherent_impl_candidates_for_type(p.def_id(), receiver_steps); - self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps); + self.assemble_inherent_candidates_from_object(self_ty, context); + self.assemble_inherent_impl_candidates_for_type( + p.def_id(), + context, + receiver_steps, + ); + self.assemble_inherent_candidates_for_incoherent_ty( + raw_self_ty, + context, + receiver_steps, + ); } ty::Adt(def, _) => { let def_id = def.did(); - self.assemble_inherent_impl_candidates_for_type(def_id, receiver_steps); - self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps); + self.assemble_inherent_impl_candidates_for_type(def_id, context, receiver_steps); + self.assemble_inherent_candidates_for_incoherent_ty( + raw_self_ty, + context, + receiver_steps, + ); } ty::Foreign(did) => { - self.assemble_inherent_impl_candidates_for_type(did, receiver_steps); - self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps); + self.assemble_inherent_impl_candidates_for_type(did, context, receiver_steps); + self.assemble_inherent_candidates_for_incoherent_ty( + raw_self_ty, + context, + receiver_steps, + ); } ty::Param(_) => { - self.assemble_inherent_candidates_from_param(raw_self_ty); + self.assemble_inherent_candidates_from_param(raw_self_ty, context); } ty::Bool | ty::Char @@ -862,7 +1012,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::Ref(..) | ty::Never | ty::Tuple(..) => { - self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps) + self.assemble_inherent_candidates_for_incoherent_ty( + raw_self_ty, + context, + receiver_steps, + ); } _ => {} } @@ -870,50 +1024,63 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn assemble_inherent_candidates_for_incoherent_ty( &mut self, - self_ty: Ty<'tcx>, + receiver_ty: Ty<'tcx>, + context: usize, receiver_steps: usize, ) { - let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else { - bug!("unexpected incoherent type: {:?}", self_ty) + let Some(simp) = simplify_type(self.tcx, receiver_ty, TreatParams::InstantiateWithInfer) + else { + bug!("unexpected incoherent type: {:?}", receiver_ty) }; for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter() { - self.assemble_inherent_impl_probe(impl_def_id, receiver_steps); + self.assemble_inherent_impl_probe(impl_def_id, context, receiver_steps); } } - fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId, receiver_steps: usize) { + fn assemble_inherent_impl_candidates_for_type( + &mut self, + def_id: DefId, + context: usize, + receiver_steps: usize, + ) { let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter(); for &impl_def_id in impl_def_ids { - self.assemble_inherent_impl_probe(impl_def_id, receiver_steps); + self.assemble_inherent_impl_probe(impl_def_id, context, receiver_steps); } } #[instrument(level = "debug", skip(self))] - fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId, receiver_steps: usize) { - if !self.impl_dups.insert(impl_def_id) { - return; // already visited - } - + fn assemble_inherent_impl_probe( + &mut self, + impl_def_id: DefId, + context: usize, + receiver_steps: usize, + ) { for item in self.impl_or_trait_item(impl_def_id) { if !self.has_applicable_self(&item) { // No receiver declared. Not a candidate. self.record_static_candidate(CandidateSource::Impl(impl_def_id)); continue; } - self.push_candidate( + self.push_inherent_candidate( Candidate { item, kind: InherentImplCandidate { impl_def_id, receiver_steps }, import_ids: smallvec![], }, - true, + context, ); } } #[instrument(level = "debug", skip(self))] - fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) { - let principal = match self_ty.kind() { + fn assemble_inherent_candidates_from_object( + &mut self, + self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, + context: usize, + ) { + let generalized_self_ty = self.generalized_ty(self_ty); + let principal = match generalized_self_ty.kind() { ty::Dynamic(data, ..) => Some(data), _ => None, } @@ -922,7 +1089,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { span_bug!( self.span, "non-object {:?} in assemble_inherent_candidates_from_object", - self_ty + generalized_self_ty ) }); @@ -932,24 +1099,24 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // `Self` type anywhere other than the receiver. Here, we use a // instantiation that replaces `Self` with the object type itself. Hence, // a `&self` method will wind up with an argument type like `&dyn Trait`. - let trait_ref = principal.with_self_ty(self.tcx, self_ty); + let trait_ref = principal.with_self_ty(self.tcx, generalized_self_ty); self.assemble_candidates_for_bounds( traits::supertraits(self.tcx, trait_ref), |this, new_trait_ref, item| { - this.push_candidate( + this.push_inherent_candidate( Candidate { item, kind: ObjectCandidate(new_trait_ref), import_ids: smallvec![], }, - true, + context, ); }, ); } #[instrument(level = "debug", skip(self))] - fn assemble_inherent_candidates_from_param(&mut self, param_ty: Ty<'tcx>) { + fn assemble_inherent_candidates_from_param(&mut self, param_ty: Ty<'tcx>, context: usize) { debug_assert_matches!(param_ty.kind(), ty::Param(_)); let tcx = self.tcx; @@ -975,13 +1142,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }); self.assemble_candidates_for_bounds(bounds, |this, poly_trait_ref, item| { - this.push_candidate( + this.push_inherent_candidate( Candidate { item, kind: WhereClauseCandidate(poly_trait_ref), import_ids: smallvec![], }, - true, + context, ); }); } @@ -1050,7 +1217,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - #[instrument(level = "debug", skip(self))] fn assemble_extension_candidates_for_trait( &mut self, import_ids: &SmallVec<[LocalDefId; 1]>, @@ -1072,14 +1238,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { bound_trait_ref.def_id(), )); } else { - self.push_candidate( - Candidate { - item, - import_ids: import_ids.clone(), - kind: TraitCandidate(bound_trait_ref), - }, - false, - ); + self.push_extension_candidate(Candidate { + item, + import_ids: import_ids.clone(), + kind: TraitCandidate(bound_trait_ref), + }); } } } @@ -1095,14 +1258,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.record_static_candidate(CandidateSource::Trait(trait_def_id)); continue; } - self.push_candidate( - Candidate { - item, - import_ids: import_ids.clone(), - kind: TraitCandidate(ty::Binder::dummy(trait_ref)), - }, - false, - ); + self.push_extension_candidate(Candidate { + item, + import_ids: import_ids.clone(), + kind: TraitCandidate(ty::Binder::dummy(trait_ref)), + }); } } } @@ -1111,9 +1271,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, candidate_filter: impl Fn(&ty::AssocItem) -> bool, ) -> Vec { - let mut set = FxHashSet::default(); + let mut set = UnordSet::default(); let mut names: Vec<_> = self - .inherent_candidates + .raw_inherent_candidates .iter() .chain(&self.extension_candidates) .filter(|candidate| candidate_filter(&candidate.item)) @@ -1209,6 +1369,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { })) } + #[instrument(level = "debug", skip_all)] fn pick_core( &self, unsatisfied_predicates: &mut UnsatisfiedPredicates<'tcx>, @@ -1236,6 +1397,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }) } + #[instrument(level = "debug", skip(self))] fn pick_all_method<'b>( &self, pick_diag_hints: &mut PickDiagHints<'b, 'tcx>, @@ -1247,13 +1409,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // so we want to follow the `Deref` chain not the `Receiver` chain. Filter out // steps which can only be reached by following the (longer) `Receiver` chain. .filter(|step| step.reachable_via_deref) - .filter(|step| { - debug!("pick_all_method: step={:?}", step); + .enumerate() + .filter(|(_, step)| { + debug!(?step, ?step.from_unsafe_deref); // skip types that are from a type error or that would require dereferencing // a raw pointer !step.self_ty.value.references_error() && !step.from_unsafe_deref }) - .find_map(|step| { + .find_map(|(deref_depth, step)| { let InferOk { value: self_ty, obligations: instantiate_self_ty_obligations } = self .fcx .probe_instantiate_query_response( @@ -1268,34 +1431,38 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let by_value_pick = self.pick_by_value_method( step, self_ty, + deref_depth, &instantiate_self_ty_obligations, pick_diag_hints, ); // Check for shadowing of a by-reference method by a by-value method (see comments on check_for_shadowing) if let Some(by_value_pick) = by_value_pick { - if let Ok(by_value_pick) = by_value_pick.as_ref() { - if by_value_pick.kind == PickKind::InherentImplPick { - for mutbl in [hir::Mutability::Not, hir::Mutability::Mut] { - if let Err(e) = self.check_for_shadowed_autorefd_method( - by_value_pick, - step, - self_ty, - &instantiate_self_ty_obligations, - mutbl, - track_unstable_candidates, - ) { - return Some(Err(e)); - } + if let Ok(by_value_pick) = &by_value_pick + && matches!(by_value_pick.kind, PickKind::InherentImplPick) + { + for mutbl in [hir::Mutability::Not, hir::Mutability::Mut] { + if let Err(e) = self.check_for_shadowed_autorefd_method( + by_value_pick, + step, + self_ty, + deref_depth, + &instantiate_self_ty_obligations, + mutbl, + track_unstable_candidates, + ) { + return Some(Err(e)); } } } + return Some(by_value_pick); } let autoref_pick = self.pick_autorefd_method( step, self_ty, + deref_depth, &instantiate_self_ty_obligations, hir::Mutability::Not, pick_diag_hints, @@ -1303,21 +1470,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ); // Check for shadowing of a by-mut-ref method by a by-reference method (see comments on check_for_shadowing) if let Some(autoref_pick) = autoref_pick { - if let Ok(autoref_pick) = autoref_pick.as_ref() { + if let Ok(autoref_pick) = &autoref_pick + && matches!(autoref_pick.kind, PickKind::InherentImplPick) + { // Check we're not shadowing others - if autoref_pick.kind == PickKind::InherentImplPick { - if let Err(e) = self.check_for_shadowed_autorefd_method( - autoref_pick, - step, - self_ty, - &instantiate_self_ty_obligations, - hir::Mutability::Mut, - track_unstable_candidates, - ) { - return Some(Err(e)); - } + if let Err(e) = self.check_for_shadowed_autorefd_method( + autoref_pick, + step, + self_ty, + deref_depth, + &instantiate_self_ty_obligations, + hir::Mutability::Mut, + track_unstable_candidates, + ) { + return Some(Err(e)); } } + return Some(autoref_pick); } @@ -1347,6 +1516,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.pick_autorefd_method( step, self_ty, + deref_depth, &instantiate_self_ty_obligations, hir::Mutability::Mut, pick_diag_hints, @@ -1356,6 +1526,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.pick_const_ptr_method( step, self_ty, + deref_depth, &instantiate_self_ty_obligations, pick_diag_hints, ) @@ -1364,6 +1535,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.pick_reborrow_pin_method( step, self_ty, + deref_depth, &instantiate_self_ty_obligations, pick_diag_hints, ) @@ -1372,25 +1544,33 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } /// Check for cases where arbitrary self types allows shadowing - /// of methods that might be a compatibility break. Specifically, - /// we have something like: + /// of methods that might be a compatibility break. + /// + /// As an example, first we examine this code. /// ```ignore (illustrative) /// struct A; /// impl A { - /// fn foo(self: &NonNull) {} - /// // note this is by reference + /// fn foo(self: &NonNull) { + /// // ^ note that the receiver is a reference + /// } /// } /// ``` - /// then we've come along and added this method to `NonNull`: + /// Then we've come along and added this method to `NonNull`: /// ```ignore (illustrative) - /// fn foo(self) // note this is by value + /// impl A { + /// fn foo(self: A) // note this is by value + /// } /// ``` - /// Report an error in this case. + /// Here we report an error on the ground of shadowing `foo` in this case. + /// Shadowing happens when an inherent method candidate appears deeper in + /// the Receiver sub-chain that is rooted from the same `self` value. + #[instrument(level = "debug", skip(self))] fn check_for_shadowed_autorefd_method( &self, possible_shadower: &Pick<'tcx>, step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, + deref_depth: usize, instantiate_self_ty_obligations: &[PredicateObligation<'tcx>], mutbl: hir::Mutability, track_unstable_candidates: bool, @@ -1409,19 +1589,20 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // unstable_candidates in order to reflect the behavior of the // main search. let mut pick_diag_hints = PickDiagHints { - unstable_candidates: if track_unstable_candidates { Some(Vec::new()) } else { None }, - unsatisfied_predicates: &mut Vec::new(), + unstable_candidates: track_unstable_candidates.then(Vec::new), + unsatisfied_predicates: &mut vec![], }; // Set criteria for how we find methods possibly shadowed by 'possible_shadower' let pick_constraints = PickConstraintsForShadowed { // It's the same `self` type... autoderefs: possible_shadower.autoderefs, // ... but the method was found in an impl block determined - // by searching further along the Receiver chain than the other, + // by searching further along the Receiver sub-chain than the other, // showing that it's a smart pointer type causing the problem... receiver_steps: possible_shadower.receiver_steps, // ... and they don't end up pointing to the same item in the - // first place (could happen with things like blanket impls for T) + // first place. + // This could happen with things like blanket impls for T. def_id: possible_shadower.item.def_id, }; // A note on the autoderefs above. Within pick_by_value_method, an extra @@ -1441,13 +1622,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // ``` // then we've come along and added this method to `NonNull`: // ``` - // fn foo(&self) // note this is by single reference + // impl NonNull { + // .. + // fn foo(&self) { .. } // note this is by single reference + // } // ``` // and the call is: // ``` - // let bar = NonNull; - // let bar = &foo; - // bar.foo(); + // let a: NonNull = ..; + // let ref_a = &a; + // ref_a.foo(); // ``` // In these circumstances, the logic is wrong, and we wouldn't spot // the shadowing, because the autoderef-based maths wouldn't line up. @@ -1456,6 +1640,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let potentially_shadowed_pick = self.pick_autorefd_method( step, self_ty, + deref_depth, instantiate_self_ty_obligations, mutbl, &mut pick_diag_hints, @@ -1463,7 +1648,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ); // Look for actual pairs of shadower/shadowed which are // the sort of shadowing case we want to avoid. Specifically... - if let Some(Ok(possible_shadowed)) = potentially_shadowed_pick.as_ref() { + if let Some(Ok(possible_shadowed)) = &potentially_shadowed_pick { let sources = [possible_shadower, possible_shadowed] .into_iter() .map(|p| self.candidate_source_from_pick(p)) @@ -1483,6 +1668,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, + deref_depth: usize, instantiate_self_ty_obligations: &[PredicateObligation<'tcx>], pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, ) -> Option> { @@ -1490,7 +1676,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { return None; } - self.pick_method(self_ty, instantiate_self_ty_obligations, pick_diag_hints, None).map(|r| { + self.pick_method( + self_ty, + deref_depth, + instantiate_self_ty_obligations, + pick_diag_hints, + None, + ) + .map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; @@ -1527,6 +1720,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, + deref_depth: usize, instantiate_self_ty_obligations: &[PredicateObligation<'tcx>], mutbl: hir::Mutability, pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, @@ -1546,6 +1740,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let autoref_ty = Ty::new_ref(tcx, region, self_ty, mutbl); self.pick_method( autoref_ty, + deref_depth, instantiate_self_ty_obligations, pick_diag_hints, pick_constraints, @@ -1566,6 +1761,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, + deref_depth: usize, instantiate_self_ty_obligations: &[PredicateObligation<'tcx>], pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, ) -> Option> { @@ -1588,25 +1784,32 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let region = self.tcx.lifetimes.re_erased; let autopin_ty = Ty::new_pinned_ref(self.tcx, region, inner_ty, hir::Mutability::Not); - self.pick_method(autopin_ty, instantiate_self_ty_obligations, pick_diag_hints, None).map( - |r| { - r.map(|mut pick| { - pick.autoderefs = step.autoderefs; - pick.autoref_or_ptr_adjustment = - Some(AutorefOrPtrAdjustment::ReborrowPin(hir::Mutability::Not)); - pick - }) - }, + self.pick_method( + autopin_ty, + deref_depth, + instantiate_self_ty_obligations, + pick_diag_hints, + None, ) + .map(|r| { + r.map(|mut pick| { + pick.autoderefs = step.autoderefs; + pick.autoref_or_ptr_adjustment = + Some(AutorefOrPtrAdjustment::ReborrowPin(hir::Mutability::Not)); + pick + }) + }) } /// If `self_ty` is `*mut T` then this picks `*const T` methods. The reason why we have a /// special case for this is because going from `*mut T` to `*const T` with autoderefs and /// autorefs would require dereferencing the pointer, which is not safe. + #[instrument(level = "debug", skip(self, pick_diag_hints))] fn pick_const_ptr_method( &self, step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, + deref_depth: usize, instantiate_self_ty_obligations: &[PredicateObligation<'tcx>], pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, ) -> Option> { @@ -1620,44 +1823,57 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }; let const_ptr_ty = Ty::new_imm_ptr(self.tcx, ty); - self.pick_method(const_ptr_ty, instantiate_self_ty_obligations, pick_diag_hints, None).map( - |r| { - r.map(|mut pick| { - pick.autoderefs = step.autoderefs; - pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::ToConstPtr); - pick - }) - }, + self.pick_method( + const_ptr_ty, + deref_depth, + instantiate_self_ty_obligations, + pick_diag_hints, + None, ) + .map(|r| { + r.map(|mut pick| { + pick.autoderefs = step.autoderefs; + pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::ToConstPtr); + pick + }) + }) } + #[instrument(level = "debug", skip_all, fields(?self_ty))] fn pick_method( &self, self_ty: Ty<'tcx>, + deref_depth: usize, instantiate_self_ty_obligations: &[PredicateObligation<'tcx>], pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, pick_constraints: Option<&PickConstraintsForShadowed>, ) -> Option> { - debug!("pick_method(self_ty={})", self.ty_to_string(self_ty)); + debug!(%deref_depth, "searching inherent candidates"); + if let res @ Some(_) = self.consider_candidates( + self_ty, + instantiate_self_ty_obligations, + self.flattened_inherent_candidates[deref_depth] + .iter() + .map(|&id| &self.raw_inherent_candidates[id]), + pick_diag_hints, + pick_constraints, + ) { + return res; + } - for (kind, candidates) in - [("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)] - { - debug!("searching {} candidates", kind); - let res = self.consider_candidates( - self_ty, - instantiate_self_ty_obligations, - candidates, - pick_diag_hints, - pick_constraints, - ); - if let Some(pick) = res { - return Some(pick); - } + debug!("searching extension candidates"); + if let res @ Some(_) = self.consider_candidates( + self_ty, + instantiate_self_ty_obligations, + &self.extension_candidates, + pick_diag_hints, + pick_constraints, + ) { + return res; } - if self.private_candidate.get().is_none() { - if let Some(Ok(pick)) = self.consider_candidates( + if self.private_candidate.get().is_none() + && let Some(Ok(pick)) = self.consider_candidates( self_ty, instantiate_self_ty_obligations, &self.private_candidates, @@ -1666,27 +1882,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { unsatisfied_predicates: &mut vec![], }, None, - ) { - self.private_candidate.set(Some((pick.item.as_def_kind(), pick.item.def_id))); - } + ) + { + self.private_candidate.set(Some((pick.item.as_def_kind(), pick.item.def_id))); } None } - fn consider_candidates( - &self, + #[instrument(level = "debug", skip_all, ret)] + fn consider_candidates<'s>( + &'s self, self_ty: Ty<'tcx>, instantiate_self_ty_obligations: &[PredicateObligation<'tcx>], - candidates: &[Candidate<'tcx>], + candidates: impl IntoIterator>, pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, pick_constraints: Option<&PickConstraintsForShadowed>, ) -> Option> { let mut applicable_candidates: Vec<_> = candidates - .iter() + .into_iter() .filter(|candidate| { - pick_constraints - .map(|pick_constraints| pick_constraints.candidate_may_shadow(&candidate)) - .unwrap_or(true) + pick_constraints.map_or(true, |pick_constraints| { + pick_constraints.candidate_may_shadow(candidate) + }) }) .map(|probe| { ( @@ -1699,7 +1916,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ), ) }) - .filter(|&(_, status)| status != ProbeResult::NoMatch) + .filter(|&(_, status)| !matches!(status, ProbeResult::NoMatch)) .collect(); debug!("applicable_candidates: {:?}", applicable_candidates); @@ -2399,6 +2616,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { pcx.method_name = Some(method_name); pcx.assemble_inherent_candidates(); pcx.assemble_extension_candidates_for_all_traits(); + pcx.flatten_candidates(); pcx.pick_core(&mut Vec::new()).and_then(|pick| pick.ok()).map(|pick| pick.item) }) .collect(); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 08db16ba8ecbb..6147e5d01b0e2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1144,7 +1144,7 @@ rustc_queries! { } query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] { - desc { |tcx| "collecting all inherent impls for `{:?}`", key } + desc { |tcx| "collecting all incoherent impls for `{:?}`", key } } /// Unsafety-check this `LocalDefId`. diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 9f3bc0ec43e6a..636f11feb3319 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -172,6 +172,7 @@ pub struct CandidateStep<'tcx> { /// reachable via Deref when examining what the receiver type can /// be converted into by autodereffing. pub reachable_via_deref: bool, + pub receiver_depth: usize, } #[derive(Copy, Clone, Debug, HashStable)] diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7cbf2088efce5..a7218a2b6357f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2558,6 +2558,8 @@ mod ref_mut { use std::cell::{BorrowMutError, Cell, Ref, RefCell, RefMut}; use std::fmt; use std::ops::Deref; + #[cfg(not(bootstrap))] + use std::ops::Receiver; use crate::Resolver; @@ -2574,6 +2576,10 @@ mod ref_mut { self.p } } + #[cfg(not(bootstrap))] + impl<'a, T> Receiver for RefOrMut<'a, T> { + type Target = T; + } impl<'a, T> AsRef for RefOrMut<'a, T> { fn as_ref(&self) -> &T { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 72709753b1dff..3987160cf54fe 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -467,6 +467,7 @@ symbols! { arbitrary_enum_discriminant, arbitrary_self_types, arbitrary_self_types_pointers, + arbitrary_self_types_split_chains, areg, args, arith_offset, diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 60758551cc048..331f63ab0fd8e 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -196,7 +196,7 @@ use core::mem::MaybeUninit; use core::mem::{self, SizedTypeProperties}; use core::ops::{ AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref, DerefMut, - DerefPure, DispatchFromDyn, LegacyReceiver, + DerefPure, DispatchFromDyn, LegacyReceiver, Receiver, }; #[cfg(not(no_global_oom_handling))] use core::ops::{Residual, Try}; @@ -2197,6 +2197,10 @@ unsafe impl DerefPure for Box {} #[unstable(feature = "legacy_receiver_trait", issue = "none")] impl LegacyReceiver for Box {} +#[unstable(feature = "arbitrary_self_types", issue = "44874")] +impl Receiver for Box { + type Target = T; +} #[stable(feature = "boxed_closure_impls", since = "1.35.0")] impl + ?Sized, A: Allocator> FnOnce for Box { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index b659e904c8a0b..d49a5e4e73e4d 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -88,6 +88,8 @@ #![cfg_attr(not(no_global_oom_handling), feature(string_replace_in_place))] #![feature(alloc_layout_extra)] #![feature(allocator_api)] +#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] #![feature(array_into_iter_constructors)] #![feature(ascii_char)] #![feature(assert_matches)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 8a72748668ccb..f0dd3bd71954d 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -254,7 +254,9 @@ use core::iter; use core::marker::{PhantomData, Unsize}; use core::mem::{self, ManuallyDrop, align_of_val_raw}; use core::num::NonZeroUsize; -use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; +use core::ops::{ + CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver, Receiver, +}; #[cfg(not(no_global_oom_handling))] use core::ops::{Residual, Try}; use core::panic::{RefUnwindSafe, UnwindSafe}; @@ -2436,6 +2438,10 @@ unsafe impl DerefPure for UniqueRc {} #[unstable(feature = "legacy_receiver_trait", issue = "none")] impl LegacyReceiver for Rc {} +#[unstable(feature = "arbitrary_self_types", issue = "44874")] +impl Receiver for Rc { + type Target = T; +} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for Rc { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4180fe91cb558..c5b55e96c5de8 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -21,7 +21,9 @@ use core::iter; use core::marker::{PhantomData, Unsize}; use core::mem::{self, ManuallyDrop, align_of_val_raw}; use core::num::NonZeroUsize; -use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; +use core::ops::{ + CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver, Receiver, +}; #[cfg(not(no_global_oom_handling))] use core::ops::{Residual, Try}; use core::panic::{RefUnwindSafe, UnwindSafe}; @@ -2434,6 +2436,10 @@ unsafe impl DerefPure for Arc {} #[unstable(feature = "legacy_receiver_trait", issue = "none")] impl LegacyReceiver for Arc {} +#[unstable(feature = "arbitrary_self_types", issue = "44874")] +impl Receiver for Arc { + type Target = T; +} #[cfg(not(no_global_oom_handling))] impl Arc { diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 68f22767d6cf0..ffac356378bb5 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1193,7 +1193,7 @@ pub trait FnPtr: Copy + Clone { /// ``` /// #![feature(arbitrary_self_types, derive_coerce_pointee)] /// use std::marker::CoercePointee; -/// use std::ops::Deref; +/// use std::ops::{Deref, Receiver}; /// /// #[derive(CoercePointee)] /// #[repr(transparent)] @@ -1205,8 +1205,12 @@ pub trait FnPtr: Copy + Clone { /// &self.0 /// } /// } +/// impl Receiver for MySmartPointer { +/// type Target = T; +/// } /// -/// // You can always define this trait. (as long as you have #![feature(arbitrary_self_types)]) +/// // You can define this trait, +/// // given that you also enable `#![feature(arbitrary_self_types)]`. /// trait MyTrait { /// fn func(self: MySmartPointer); /// } diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs index 305861ea7b698..c79910b693cc5 100644 --- a/library/core/src/ops/deref.rs +++ b/library/core/src/ops/deref.rs @@ -303,9 +303,8 @@ unsafe impl DerefPure for &mut T {} /// Indicates that a struct can be used as a method receiver. /// That is, a type can use this type as a type of `self`, like this: -/// ```compile_fail -/// # // This is currently compile_fail because the compiler-side parts -/// # // of arbitrary_self_types are not implemented +/// ``` +/// #![feature(arbitrary_self_types)] /// use std::ops::Receiver; /// /// struct SmartPointer(T); @@ -374,14 +373,6 @@ pub trait Receiver: PointeeSized { type Target: ?Sized; } -#[unstable(feature = "arbitrary_self_types", issue = "44874")] -impl Receiver for P -where - P: Deref, -{ - type Target = T; -} - /// Indicates that a struct can be used as a method receiver, without the /// `arbitrary_self_types` feature. This is implemented by stdlib pointer types like `Box`, /// `Rc`, `&T`, and `Pin

`. @@ -399,6 +390,14 @@ pub trait LegacyReceiver: PointeeSized { #[unstable(feature = "legacy_receiver_trait", issue = "none")] impl LegacyReceiver for &T {} +#[unstable(feature = "arbitrary_self_types", issue = "44874")] +impl Receiver for &T { + type Target = T; +} #[unstable(feature = "legacy_receiver_trait", issue = "none")] impl LegacyReceiver for &mut T {} +#[unstable(feature = "arbitrary_self_types", issue = "44874")] +impl Receiver for &mut T { + type Target = T; +} diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 74ecb5ee4946f..cacd37ac5a6f4 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -921,7 +921,9 @@ #![stable(feature = "pin", since = "1.33.0")] use crate::hash::{Hash, Hasher}; -use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver}; +use crate::ops::{ + CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver, Receiver, +}; #[allow(unused_imports)] use crate::{ cell::{RefCell, UnsafeCell}, @@ -1782,6 +1784,10 @@ unsafe impl DerefPure for Pin {} #[unstable(feature = "legacy_receiver_trait", issue = "none")] impl LegacyReceiver for Pin {} +#[unstable(feature = "arbitrary_self_types", issue = "44874")] +impl Receiver for Pin { + type Target = Ptr; +} #[stable(feature = "pin", since = "1.33.0")] impl fmt::Debug for Pin { diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index f86933029341e..be097dca1d43d 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -4,6 +4,8 @@ use std::fs::{File, Metadata}; use std::io::{ErrorKind, IsTerminal, Seek, SeekFrom, Write}; use std::marker::CoercePointee; use std::ops::Deref; +#[cfg(not(bootstrap))] +use std::ops::Receiver; use std::rc::{Rc, Weak}; use std::{fs, io}; @@ -43,6 +45,10 @@ impl Deref for FileDescriptionRef { &self.0.inner } } +#[cfg(not(bootstrap))] +impl Receiver for FileDescriptionRef { + type Target = T; +} impl FileDescriptionRef { pub fn id(&self) -> FdId { diff --git a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs index d993e5ad68ccc..564cea3168199 100644 --- a/src/tools/miri/tests/pass/dyn-arbitrary-self.rs +++ b/src/tools/miri/tests/pass/dyn-arbitrary-self.rs @@ -1,6 +1,12 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(arbitrary_self_types_pointers, unsize, coerce_unsized, dispatch_from_dyn)] +#![feature( + arbitrary_self_types, + arbitrary_self_types_pointers, + unsize, + coerce_unsized, + dispatch_from_dyn +)] #![feature(rustc_attrs)] fn pin_box_dyn() { @@ -63,7 +69,7 @@ fn stdlib_pointers() { fn pointers_and_wrappers() { use std::marker::Unsize; - use std::ops::{CoerceUnsized, Deref, DispatchFromDyn}; + use std::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; struct Ptr(Box); @@ -74,6 +80,9 @@ fn pointers_and_wrappers() { &*self.0 } } + impl Receiver for Ptr { + type Target = T; + } impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} impl + ?Sized, U: ?Sized> DispatchFromDyn> for Ptr {} @@ -87,6 +96,9 @@ fn pointers_and_wrappers() { &self.0 } } + impl Receiver for Wrapper { + type Target = T; + } impl, U> CoerceUnsized> for Wrapper {} impl, U> DispatchFromDyn> for Wrapper {} diff --git a/tests/crashes/138564.rs b/tests/crashes/138564.rs index b10f75f8cdd0c..460917260be0e 100644 --- a/tests/crashes/138564.rs +++ b/tests/crashes/138564.rs @@ -3,7 +3,7 @@ #![feature(unsize, dispatch_from_dyn, arbitrary_self_types)] use std::marker::Unsize; -use std::ops::{Deref, DispatchFromDyn}; +use std::ops::{Deref, DispatchFromDyn, Receiver}; #[repr(align(16))] pub struct MyPointer(*const T); @@ -15,7 +15,9 @@ impl Deref for MyPointer { unimplemented!() } } - +impl Receiver for MyPointer { + type Target = T; +} pub trait Trait { fn foo(self: MyPointer) {} } diff --git a/tests/ui/abi/invalid-self-parameter-type-56806.stderr b/tests/ui/abi/invalid-self-parameter-type-56806.stderr index ac249b8f10880..5d4d147614b8e 100644 --- a/tests/ui/abi/invalid-self-parameter-type-56806.stderr +++ b/tests/ui/abi/invalid-self-parameter-type-56806.stderr @@ -5,7 +5,8 @@ LL | fn dyn_instead_of_self(self: Box); | ^^^^^^^^^^^^^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error: aborting due to 1 previous error diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr index c4240a095e685..8382ddab50a96 100644 --- a/tests/ui/async-await/inference_var_self_argument.stderr +++ b/tests/ui/async-await/inference_var_self_argument.stderr @@ -5,7 +5,8 @@ LL | async fn foo(self: &dyn Foo) { | ^^^^^^^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/inference_var_self_argument.rs:5:33 diff --git a/tests/ui/async-await/issue-66312.stderr b/tests/ui/async-await/issue-66312.stderr index c95ae1147df36..3f889516fea8a 100644 --- a/tests/ui/async-await/issue-66312.stderr +++ b/tests/ui/async-await/issue-66312.stderr @@ -5,7 +5,8 @@ LL | fn is_some(self: T); | ^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error[E0308]: mismatched types --> $DIR/issue-66312.rs:9:8 diff --git a/tests/ui/deriving/deriving-coerce-pointee.rs b/tests/ui/deriving/deriving-coerce-pointee.rs index 26762e4d0face..0297119813a69 100644 --- a/tests/ui/deriving/deriving-coerce-pointee.rs +++ b/tests/ui/deriving/deriving-coerce-pointee.rs @@ -2,6 +2,7 @@ #![feature(derive_coerce_pointee, arbitrary_self_types)] use std::marker::CoercePointee; +use std::ops::{Deref, Receiver}; #[derive(CoercePointee)] #[repr(transparent)] @@ -16,13 +17,17 @@ impl Clone for MyPointer<'_, T> { } } -impl<'a, T: ?Sized> core::ops::Deref for MyPointer<'a, T> { +impl<'a, T: ?Sized> Deref for MyPointer<'a, T> { type Target = T; fn deref(&self) -> &'a T { self.ptr } } +impl<'a, T: ?Sized> Receiver for MyPointer<'a, T> { + type Target = T; +} + struct MyValue(u32); impl MyValue { fn through_pointer(self: MyPointer<'_, Self>) -> u32 { diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.rs b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.rs index 47ca7e3497578..f57316de5be67 100644 --- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.rs +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.rs @@ -1,6 +1,4 @@ -use std::{ - ops::Deref, -}; +use std::ops::Deref; struct Ptr(Box); @@ -13,17 +11,17 @@ impl Deref for Ptr { } trait Foo { - fn foo(self: Ptr); //~ ERROR `Ptr` cannot be used as the type of `self` without + fn foo(self: Ptr); //~ ERROR invalid `self` parameter type: `Ptr` } struct Bar; impl Foo for Bar { - fn foo(self: Ptr) {} //~ ERROR `Ptr` cannot be used as the type of `self` without + fn foo(self: Ptr) {} //~ ERROR invalid `self` parameter type: `Ptr` } impl Bar { - fn bar(self: Box>) {} //~ ERROR `Box>` cannot be used as the + fn bar(self: Box>) {} //~ ERROR invalid `self` parameter type: `Box>` } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr index 3ffba533d63fc..bdbc0d0ff12d6 100644 --- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr @@ -1,36 +1,33 @@ -error[E0658]: `Ptr` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/feature-gate-arbitrary-self-types.rs:22:18 +error[E0307]: invalid `self` parameter type: `Ptr` + --> $DIR/feature-gate-arbitrary-self-types.rs:20:18 | LL | fn foo(self: Ptr) {} | ^^^^^^^^^ | - = note: see issue #44874 for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable -error[E0658]: `Box>` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/feature-gate-arbitrary-self-types.rs:26:18 +error[E0307]: invalid `self` parameter type: `Box>` + --> $DIR/feature-gate-arbitrary-self-types.rs:24:18 | LL | fn bar(self: Box>) {} | ^^^^^^^^^^^^^^ | - = note: see issue #44874 for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable -error[E0658]: `Ptr` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/feature-gate-arbitrary-self-types.rs:16:18 +error[E0307]: invalid `self` parameter type: `Ptr` + --> $DIR/feature-gate-arbitrary-self-types.rs:14:18 | LL | fn foo(self: Ptr); | ^^^^^^^^^ | - = note: see issue #44874 for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0307`. diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr index 2150effc3b74d..029ac8fc9cec7 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-cell.stderr @@ -5,7 +5,8 @@ LL | fn cell(self: Cell<&Self>); | ^^^^^^^^^^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs index 8d7ccea9e6477..663a3eef535fa 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.rs @@ -2,10 +2,8 @@ #![feature(arbitrary_self_types, unsize, coerce_unsized)] -use std::{ - marker::Unsize, - ops::{CoerceUnsized, Deref}, -}; +use std::marker::Unsize; +use std::ops::{CoerceUnsized, Deref, Receiver}; struct Ptr(Box); @@ -16,6 +14,9 @@ impl Deref for Ptr { &*self.0 } } +impl Receiver for Ptr { + type Target = T; +} impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} // Because this impl is missing the coercion below fails. diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr index c70ab65aa9056..8b99d64efe683 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Trait` is not dyn compatible - --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:33 + --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:33:33 | LL | fn ptr(self: Ptr); | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` @@ -9,7 +9,7 @@ LL | Ptr(Box::new(4)) as Ptr; | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18 + --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:26:18 | LL | trait Trait { | ----- this trait is not dyn compatible... diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs index 6ceec11930833..358668dacf178 100644 --- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs +++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.rs @@ -10,7 +10,7 @@ use std::marker::PhantomData; mod internal { - use std::ops::{CoerceUnsized, Deref, DispatchFromDyn}; + use std::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; use std::marker::{PhantomData, Unsize}; pub struct Smaht(pub Box, pub PhantomData); @@ -22,6 +22,9 @@ mod internal { &self.0 } } + impl Receiver for Smaht { + type Target = T; + } impl, U: ?Sized, MISC> CoerceUnsized> for Smaht {} @@ -52,6 +55,9 @@ mod internal { type Target = (); fn deref(&self) -> &() { &() } } + impl Receiver for dyn Foo { + type Target = (); + } impl Foo for () {} } diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr index aeecb82e9d910..a8707bcc24e68 100644 --- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr +++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:88:24 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:94:24 | LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` @@ -7,7 +7,7 @@ LL | let _seetype: () = z; | expected due to this error[E0308]: mismatched types - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:105:24 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:111:24 | LL | let _seetype: () = z; | -- ^ expected `()`, found `u64` @@ -15,18 +15,18 @@ LL | let _seetype: () = z; | expected due to this error[E0034]: multiple applicable items in scope - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:123:15 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:129:15 | LL | let z = x.foo(); | ^^^ multiple `foo` found | note: candidate #1 is defined in an impl of the trait `NuisanceFoo` for the type `T` - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:73:9 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:79:9 | LL | fn foo(self) {} | ^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `X` for the type `T` - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:46:9 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:49:9 | LL | fn foo(self: Smaht) -> u64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL + let z = X::foo(x); | error[E0308]: mismatched types - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:140:24 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:146:24 | LL | let _seetype: () = z; | -- ^ expected `()`, found `u8` @@ -50,7 +50,7 @@ LL | let _seetype: () = z; | expected due to this error[E0308]: mismatched types - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:158:24 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:164:24 | LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` @@ -58,7 +58,7 @@ LL | let _seetype: () = z; | expected due to this error[E0308]: mismatched types - --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:175:24 + --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:181:24 | LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` diff --git a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs index 495d261c549ca..a3308ae1bd0fa 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs +++ b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs @@ -1,6 +1,6 @@ #![feature(arbitrary_self_types)] -use std::ops::{Receiver, Deref}; +use std::ops::{Deref, Receiver}; struct SmartPtr<'a, T: ?Sized>(&'a T); @@ -11,31 +11,34 @@ impl<'a, T: ?Sized> Deref for SmartPtr<'a, T> { } } +impl<'a, T: ?Sized> Receiver for SmartPtr<'a, T> { + type Target = T; +} + impl<'a, T: ?Sized> Clone for SmartPtr<'a, T> { fn clone(&self) -> Self { Self(self.0) } } -impl<'a, T: ?Sized> Copy for SmartPtr<'a, T> { -} +impl<'a, T: ?Sized> Copy for SmartPtr<'a, T> {} struct Foo(u32); impl Foo { - fn a>(self: R) -> u32 { + fn a>(self: R) -> u32 { //~^ ERROR invalid generic `self` parameter type: `R` 2 } - fn b>(self: R) -> u32 { + fn b + Receiver>(self: R) -> u32 { //~^ ERROR invalid generic `self` parameter type: `R` self.0 } - fn c(self: impl Receiver) -> u32 { + fn c(self: impl Receiver) -> u32 { //~^ ERROR invalid generic `self` parameter type: `impl Receiver` 3 } - fn d(self: impl Deref) -> u32 { - //~^ ERROR invalid generic `self` parameter type: `impl Deref` + fn d(self: impl Deref + Receiver) -> u32 { + //~^ ERROR invalid generic `self` parameter type: `impl Deref + Receiver` self.0 } } diff --git a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr index bafa290a3cfd0..14af53ed8b268 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr @@ -1,53 +1,53 @@ error[E0801]: invalid generic `self` parameter type: `R` - --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:25:42 + --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:28:44 | -LL | fn a>(self: R) -> u32 { - | ^ +LL | fn a>(self: R) -> u32 { + | ^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `R` - --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:29:39 + --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:32:67 | -LL | fn b>(self: R) -> u32 { - | ^ +LL | fn b + Receiver>(self: R) -> u32 { + | ^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `impl Receiver` - --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:33:16 + --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:36:16 | -LL | fn c(self: impl Receiver) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn c(self: impl Receiver) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0801]: invalid generic `self` parameter type: `impl Deref` - --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:37:16 +error[E0801]: invalid generic `self` parameter type: `impl Deref + Receiver` + --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:40:16 | -LL | fn d(self: impl Deref) -> u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn d(self: impl Deref + Receiver) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0308]: mismatched types - --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:51:16 + --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:54:16 | LL | assert_eq!(foo.a::<&Foo>(), 2); | ^^^ expected `&Foo`, found `Foo` error[E0308]: mismatched types - --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:53:16 + --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:56:16 | LL | assert_eq!(foo.b::<&Foo>(), 1); | ^^^ expected `&Foo`, found `Foo` error[E0308]: mismatched types - --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:60:16 + --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:63:16 | LL | assert_eq!(smart_ptr.a::<&Foo>(), 2); | ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>` @@ -56,7 +56,7 @@ LL | assert_eq!(smart_ptr.a::<&Foo>(), 2); found struct `SmartPtr<'_, Foo>` error[E0308]: mismatched types - --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:62:16 + --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:65:16 | LL | assert_eq!(smart_ptr.b::<&Foo>(), 1); | ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>` diff --git a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr index 7cf9c9a3afd4d..70dbaf13a6fad 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr @@ -1,87 +1,85 @@ error[E0801]: invalid generic `self` parameter type: `R` - --> $DIR/arbitrary-self-from-method-substs.rs:9:43 + --> $DIR/arbitrary-self-from-method-substs.rs:12:43 | -LL | fn get>(self: R) -> u32 { +LL | fn get>(self: R) -> u32 | ^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `&R` - --> $DIR/arbitrary-self-from-method-substs.rs:13:44 + --> $DIR/arbitrary-self-from-method-substs.rs:20:44 | -LL | fn get1>(self: &R) -> u32 { +LL | fn get1>(self: &R) -> u32 | ^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `&mut R` - --> $DIR/arbitrary-self-from-method-substs.rs:17:44 + --> $DIR/arbitrary-self-from-method-substs.rs:28:44 | -LL | fn get2>(self: &mut R) -> u32 { +LL | fn get2>(self: &mut R) -> u32 | ^^^^^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `Rc` - --> $DIR/arbitrary-self-from-method-substs.rs:21:44 + --> $DIR/arbitrary-self-from-method-substs.rs:36:44 | -LL | fn get3>(self: std::rc::Rc) -> u32 { +LL | fn get3>(self: std::rc::Rc) -> u32 | ^^^^^^^^^^^^^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `&Rc` - --> $DIR/arbitrary-self-from-method-substs.rs:25:44 + --> $DIR/arbitrary-self-from-method-substs.rs:44:44 | -LL | fn get4>(self: &std::rc::Rc) -> u32 { +LL | fn get4>(self: &std::rc::Rc) -> u32 | ^^^^^^^^^^^^^^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `Rc<&R>` - --> $DIR/arbitrary-self-from-method-substs.rs:29:44 + --> $DIR/arbitrary-self-from-method-substs.rs:52:44 | -LL | fn get5>(self: std::rc::Rc<&R>) -> u32 { +LL | fn get5>(self: std::rc::Rc<&R>) -> u32 | ^^^^^^^^^^^^^^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) -error[E0658]: `::Receiver` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/arbitrary-self-from-method-substs.rs:33:37 +error[E0307]: invalid `self` parameter type: `::Receiver` + --> $DIR/arbitrary-self-from-method-substs.rs:63:37 | LL | fn get6(self: FR::Receiver, other: FR) -> u32 { | ^^^^^^^^^^^^ | - = note: see issue #44874 for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable -error[E0658]: `R` cannot be used as the type of `self` without the `arbitrary_self_types` feature - --> $DIR/arbitrary-self-from-method-substs.rs:61:18 +error[E0307]: invalid `self` parameter type: `R` + --> $DIR/arbitrary-self-from-method-substs.rs:102:18 | LL | fn get(self: R) {} | ^ | - = note: see issue #44874 for more information - = help: add `#![feature(arbitrary_self_types)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` + = note: type of `self` must be `Self` or a type that dereferences to it + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error[E0271]: type mismatch resolving `::Receiver == Foo` - --> $DIR/arbitrary-self-from-method-substs.rs:92:9 + --> $DIR/arbitrary-self-from-method-substs.rs:136:9 | LL | foo.get6(Silly); | ^^^^ type mismatch resolving `::Receiver == Foo` | note: expected this to be `Foo` - --> $DIR/arbitrary-self-from-method-substs.rs:71:21 + --> $DIR/arbitrary-self-from-method-substs.rs:115:21 | LL | type Receiver = std::rc::Rc; | ^^^^^^^^^^^^^^^^ @@ -89,13 +87,13 @@ LL | type Receiver = std::rc::Rc; found struct `Rc` error[E0271]: type mismatch resolving `::Receiver == &Foo` - --> $DIR/arbitrary-self-from-method-substs.rs:96:9 + --> $DIR/arbitrary-self-from-method-substs.rs:140:9 | LL | foo.get6(Silly); | ^^^^ type mismatch resolving `::Receiver == &Foo` | note: expected this to be `&Foo` - --> $DIR/arbitrary-self-from-method-substs.rs:71:21 + --> $DIR/arbitrary-self-from-method-substs.rs:115:21 | LL | type Receiver = std::rc::Rc; | ^^^^^^^^^^^^^^^^ @@ -103,7 +101,7 @@ LL | type Receiver = std::rc::Rc; found struct `Rc` error[E0599]: the method `get` exists for struct `Rc>`, but its trait bounds were not satisfied - --> $DIR/arbitrary-self-from-method-substs.rs:100:7 + --> $DIR/arbitrary-self-from-method-substs.rs:144:7 | LL | struct Bar(std::marker::PhantomData); | ------------- doesn't satisfy `Bar<_>: Deref` @@ -118,12 +116,12 @@ note: the following trait bounds were not satisfied: `<&mut Rc> as Deref>::Target = Bar<&mut Rc>>` `> as Deref>::Target = Bar>>` `Bar<_>: Deref` - --> $DIR/arbitrary-self-from-method-substs.rs:60:9 + --> $DIR/arbitrary-self-from-method-substs.rs:97:9 | -LL | impl> Bar { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ - | | | - | | unsatisfied trait bound introduced here +LL | impl> Bar + | ^^^^^^^^^^^^^^^^^^^^ ------ + | | | + | | unsatisfied trait bound introduced here | unsatisfied trait bound introduced here note: the trait `Deref` must be implemented --> $SRC_DIR/core/src/ops/deref.rs:LL:COL @@ -132,7 +130,7 @@ note: the trait `Deref` must be implemented candidate #1: `SliceIndex` error[E0599]: the method `get` exists for reference `&Rc>`, but its trait bounds were not satisfied - --> $DIR/arbitrary-self-from-method-substs.rs:108:7 + --> $DIR/arbitrary-self-from-method-substs.rs:152:7 | LL | struct Bar(std::marker::PhantomData); | ------------- doesn't satisfy `Bar<_>: Deref` @@ -149,12 +147,12 @@ note: the following trait bounds were not satisfied: `<&mut Rc> as Deref>::Target = Bar<&mut Rc>>` `> as Deref>::Target = Bar>>` `Bar<_>: Deref` - --> $DIR/arbitrary-self-from-method-substs.rs:60:9 + --> $DIR/arbitrary-self-from-method-substs.rs:97:9 | -LL | impl> Bar { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ - | | | - | | unsatisfied trait bound introduced here +LL | impl> Bar + | ^^^^^^^^^^^^^^^^^^^^ ------ + | | | + | | unsatisfied trait bound introduced here | unsatisfied trait bound introduced here note: the trait `Deref` must be implemented --> $SRC_DIR/core/src/ops/deref.rs:LL:COL @@ -164,5 +162,5 @@ note: the trait `Deref` must be implemented error: aborting due to 12 previous errors -Some errors have detailed explanations: E0271, E0599, E0658, E0801. +Some errors have detailed explanations: E0271, E0307, E0599, E0801. For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr index f67918a2577ac..217a7ee310a77 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.feature.stderr @@ -1,65 +1,65 @@ error[E0801]: invalid generic `self` parameter type: `R` - --> $DIR/arbitrary-self-from-method-substs.rs:9:43 + --> $DIR/arbitrary-self-from-method-substs.rs:12:43 | -LL | fn get>(self: R) -> u32 { +LL | fn get>(self: R) -> u32 | ^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `&R` - --> $DIR/arbitrary-self-from-method-substs.rs:13:44 + --> $DIR/arbitrary-self-from-method-substs.rs:20:44 | -LL | fn get1>(self: &R) -> u32 { +LL | fn get1>(self: &R) -> u32 | ^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `&mut R` - --> $DIR/arbitrary-self-from-method-substs.rs:17:44 + --> $DIR/arbitrary-self-from-method-substs.rs:28:44 | -LL | fn get2>(self: &mut R) -> u32 { +LL | fn get2>(self: &mut R) -> u32 | ^^^^^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `Rc` - --> $DIR/arbitrary-self-from-method-substs.rs:21:44 + --> $DIR/arbitrary-self-from-method-substs.rs:36:44 | -LL | fn get3>(self: std::rc::Rc) -> u32 { +LL | fn get3>(self: std::rc::Rc) -> u32 | ^^^^^^^^^^^^^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `&Rc` - --> $DIR/arbitrary-self-from-method-substs.rs:25:44 + --> $DIR/arbitrary-self-from-method-substs.rs:44:44 | -LL | fn get4>(self: &std::rc::Rc) -> u32 { +LL | fn get4>(self: &std::rc::Rc) -> u32 | ^^^^^^^^^^^^^^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0801]: invalid generic `self` parameter type: `Rc<&R>` - --> $DIR/arbitrary-self-from-method-substs.rs:29:44 + --> $DIR/arbitrary-self-from-method-substs.rs:52:44 | -LL | fn get5>(self: std::rc::Rc<&R>) -> u32 { +LL | fn get5>(self: std::rc::Rc<&R>) -> u32 | ^^^^^^^^^^^^^^^ | = note: type of `self` must not be a method generic parameter type = help: use a concrete type such as `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) error[E0308]: mismatched types - --> $DIR/arbitrary-self-from-method-substs.rs:76:5 + --> $DIR/arbitrary-self-from-method-substs.rs:120:5 | LL | foo.get::<&Foo>(); | ^^^ expected `&Foo`, found `Foo` error[E0308]: mismatched types - --> $DIR/arbitrary-self-from-method-substs.rs:78:5 + --> $DIR/arbitrary-self-from-method-substs.rs:122:5 | LL | foo.get::>(); | ^^^ expected `Rc`, found `Foo` @@ -68,7 +68,7 @@ LL | foo.get::>(); found struct `Foo` error[E0308]: mismatched types - --> $DIR/arbitrary-self-from-method-substs.rs:84:5 + --> $DIR/arbitrary-self-from-method-substs.rs:128:5 | LL | smart_ptr.get::>(); | ^^^^^^^^^ expected `SmartPtr2<'_, Foo>`, found `SmartPtr<'_, Foo>` @@ -77,7 +77,7 @@ LL | smart_ptr.get::>(); found struct `SmartPtr<'_, Foo>` error[E0308]: mismatched types - --> $DIR/arbitrary-self-from-method-substs.rs:86:5 + --> $DIR/arbitrary-self-from-method-substs.rs:130:5 | LL | smart_ptr.get::<&Foo>(); | ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>` @@ -86,13 +86,13 @@ LL | smart_ptr.get::<&Foo>(); found struct `SmartPtr<'_, Foo>` error[E0271]: type mismatch resolving `::Receiver == Foo` - --> $DIR/arbitrary-self-from-method-substs.rs:92:9 + --> $DIR/arbitrary-self-from-method-substs.rs:136:9 | LL | foo.get6(Silly); | ^^^^ type mismatch resolving `::Receiver == Foo` | note: expected this to be `Foo` - --> $DIR/arbitrary-self-from-method-substs.rs:71:21 + --> $DIR/arbitrary-self-from-method-substs.rs:115:21 | LL | type Receiver = std::rc::Rc; | ^^^^^^^^^^^^^^^^ @@ -100,13 +100,13 @@ LL | type Receiver = std::rc::Rc; found struct `Rc` error[E0271]: type mismatch resolving `::Receiver == &Foo` - --> $DIR/arbitrary-self-from-method-substs.rs:96:9 + --> $DIR/arbitrary-self-from-method-substs.rs:140:9 | LL | foo.get6(Silly); | ^^^^ type mismatch resolving `::Receiver == &Foo` | note: expected this to be `&Foo` - --> $DIR/arbitrary-self-from-method-substs.rs:71:21 + --> $DIR/arbitrary-self-from-method-substs.rs:115:21 | LL | type Receiver = std::rc::Rc; | ^^^^^^^^^^^^^^^^ @@ -114,60 +114,86 @@ LL | type Receiver = std::rc::Rc; found struct `Rc` error[E0599]: the method `get` exists for struct `Rc>`, but its trait bounds were not satisfied - --> $DIR/arbitrary-self-from-method-substs.rs:100:7 + --> $DIR/arbitrary-self-from-method-substs.rs:144:7 | LL | struct Bar(std::marker::PhantomData); - | ------------- doesn't satisfy `Bar<_>: Deref` + | ------------- doesn't satisfy `Bar<_>: Deref` or `Bar<_>: std::ops::Receiver` ... LL | t.get(); | ^^^ method cannot be called on `Rc>` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: `<&Bar<_> as Deref>::Target = Bar<&Bar<_>>` + `<&Bar<_> as std::ops::Receiver>::Target = Bar<&Bar<_>>` `<&Rc> as Deref>::Target = Bar<&Rc>>` + `<&Rc> as std::ops::Receiver>::Target = Bar<&Rc>>` `<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>` + `<&mut Bar<_> as std::ops::Receiver>::Target = Bar<&mut Bar<_>>` `<&mut Rc> as Deref>::Target = Bar<&mut Rc>>` + `<&mut Rc> as std::ops::Receiver>::Target = Bar<&mut Rc>>` `> as Deref>::Target = Bar>>` + `> as std::ops::Receiver>::Target = Bar>>` `Bar<_>: Deref` - --> $DIR/arbitrary-self-from-method-substs.rs:60:9 + `Bar<_>: std::ops::Receiver` + --> $DIR/arbitrary-self-from-method-substs.rs:97:9 | -LL | impl> Bar { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ - | | | - | | unsatisfied trait bound introduced here +LL | impl> Bar + | ^^^^^^^^^^^^^^^^^^^^ ------ + | | | + | | unsatisfied trait bound introduced here | unsatisfied trait bound introduced here -note: the trait `Deref` must be implemented +... +LL | R: Receiver, + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here +note: the traits `Deref` and `std::ops::Receiver` must be implemented --> $SRC_DIR/core/src/ops/deref.rs:LL:COL = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `get`, perhaps you need to implement it: candidate #1: `SliceIndex` error[E0599]: the method `get` exists for reference `&Rc>`, but its trait bounds were not satisfied - --> $DIR/arbitrary-self-from-method-substs.rs:108:7 + --> $DIR/arbitrary-self-from-method-substs.rs:152:7 | LL | struct Bar(std::marker::PhantomData); - | ------------- doesn't satisfy `Bar<_>: Deref` + | ------------- doesn't satisfy `Bar<_>: Deref` or `Bar<_>: std::ops::Receiver` ... LL | t.get(); | ^^^ method cannot be called on `&Rc>` due to unsatisfied trait bounds | note: the following trait bounds were not satisfied: `<&&Rc> as Deref>::Target = Bar<&&Rc>>` + `<&&Rc> as std::ops::Receiver>::Target = Bar<&&Rc>>` `<&Bar<_> as Deref>::Target = Bar<&Bar<_>>` + `<&Bar<_> as std::ops::Receiver>::Target = Bar<&Bar<_>>` `<&Rc> as Deref>::Target = Bar<&Rc>>` + `<&Rc> as std::ops::Receiver>::Target = Bar<&Rc>>` `<&mut &Rc> as Deref>::Target = Bar<&mut &Rc>>` + `<&mut &Rc> as std::ops::Receiver>::Target = Bar<&mut &Rc>>` `<&mut Bar<_> as Deref>::Target = Bar<&mut Bar<_>>` + `<&mut Bar<_> as std::ops::Receiver>::Target = Bar<&mut Bar<_>>` `<&mut Rc> as Deref>::Target = Bar<&mut Rc>>` + `<&mut Rc> as std::ops::Receiver>::Target = Bar<&mut Rc>>` `> as Deref>::Target = Bar>>` + `> as std::ops::Receiver>::Target = Bar>>` `Bar<_>: Deref` - --> $DIR/arbitrary-self-from-method-substs.rs:60:9 + `Bar<_>: std::ops::Receiver` + --> $DIR/arbitrary-self-from-method-substs.rs:97:9 | -LL | impl> Bar { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ - | | | - | | unsatisfied trait bound introduced here +LL | impl> Bar + | ^^^^^^^^^^^^^^^^^^^^ ------ + | | | + | | unsatisfied trait bound introduced here | unsatisfied trait bound introduced here -note: the trait `Deref` must be implemented +... +LL | R: Receiver, + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here +note: the traits `Deref` and `std::ops::Receiver` must be implemented --> $SRC_DIR/core/src/ops/deref.rs:LL:COL = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `get`, perhaps you need to implement it: diff --git a/tests/ui/self/arbitrary-self-from-method-substs.rs b/tests/ui/self/arbitrary-self-from-method-substs.rs index f2d6585961517..ff2f03dd8ff0c 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.rs +++ b/tests/ui/self/arbitrary-self-from-method-substs.rs @@ -1,42 +1,71 @@ //@ revisions: default feature +#![feature(where_clause_attrs)] #![cfg_attr(feature, feature(arbitrary_self_types))] -use std::ops::Deref; use std::marker::PhantomData; +use std::ops::Deref; +#[cfg(feature)] +use std::ops::Receiver; struct Foo(u32); impl Foo { - fn get>(self: R) -> u32 { - //~^ ERROR: invalid generic `self` parameter type + fn get>(self: R) -> u32 + //~^ ERROR: invalid generic `self` parameter type + where + #[cfg(feature)] + R: Receiver, + { self.0 } - fn get1>(self: &R) -> u32 { - //~^ ERROR: invalid generic `self` parameter type + fn get1>(self: &R) -> u32 + //~^ ERROR: invalid generic `self` parameter type + where + #[cfg(feature)] + R: Receiver, + { self.0 } - fn get2>(self: &mut R) -> u32 { - //~^ ERROR: invalid generic `self` parameter type + fn get2>(self: &mut R) -> u32 + //~^ ERROR: invalid generic `self` parameter type + where + #[cfg(feature)] + R: Receiver, + { self.0 } - fn get3>(self: std::rc::Rc) -> u32 { - //~^ ERROR: invalid generic `self` parameter type + fn get3>(self: std::rc::Rc) -> u32 + //~^ ERROR: invalid generic `self` parameter type + where + #[cfg(feature)] + R: Receiver, + { self.0 } - fn get4>(self: &std::rc::Rc) -> u32 { - //~^ ERROR: invalid generic `self` parameter type + fn get4>(self: &std::rc::Rc) -> u32 + //~^ ERROR: invalid generic `self` parameter type + where + #[cfg(feature)] + R: Receiver, + { self.0 } - fn get5>(self: std::rc::Rc<&R>) -> u32 { - //~^ ERROR: invalid generic `self` parameter type + fn get5>(self: std::rc::Rc<&R>) -> u32 + //~^ ERROR: invalid generic `self` parameter type + where + #[cfg(feature)] + R: Receiver, + { self.0 } +} + +impl Foo { fn get6(self: FR::Receiver, other: FR) -> u32 { - //[default]~^ ERROR: `::Receiver` cannot be used as the type of `self` + //[default]~^ ERROR: invalid `self` parameter type: `::Receiver` 42 } } - struct SmartPtr<'a, T: ?Sized>(&'a T); impl<'a, T: ?Sized> Deref for SmartPtr<'a, T> { @@ -45,6 +74,10 @@ impl<'a, T: ?Sized> Deref for SmartPtr<'a, T> { unimplemented!() } } +#[cfg(feature)] +impl<'a, T: ?Sized> Receiver for SmartPtr<'a, T> { + type Target = T; +} struct SmartPtr2<'a, T: ?Sized>(&'a T); @@ -54,16 +87,27 @@ impl<'a, T: ?Sized> Deref for SmartPtr2<'a, T> { unimplemented!() } } +#[cfg(feature)] +impl<'a, T: ?Sized> Receiver for SmartPtr2<'a, T> { + type Target = T; +} struct Bar(std::marker::PhantomData); -impl> Bar { +impl> Bar +where + #[cfg(feature)] + R: Receiver, +{ fn get(self: R) {} - //[default]~^ ERROR: `R` cannot be used as the type of `self` + //[default]~^ ERROR: invalid `self` parameter type: `R` } trait FindReceiver { + #[cfg(not(feature))] type Receiver: Deref; + #[cfg(feature)] + type Receiver: Deref + Receiver; } struct Silly; diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr index 36ae3d6fd02bb..ef96f08e26b42 100644 --- a/tests/ui/self/arbitrary-self-opaque.stderr +++ b/tests/ui/self/arbitrary-self-opaque.stderr @@ -5,7 +5,8 @@ LL | fn foo(self: Bar) {} | ^^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error: item does not constrain `Bar::{opaque#0}` --> $DIR/arbitrary-self-opaque.rs:8:8 diff --git a/tests/ui/self/arbitrary-self-types-merge-chains.rs b/tests/ui/self/arbitrary-self-types-merge-chains.rs new file mode 100644 index 0000000000000..c619ce07b454f --- /dev/null +++ b/tests/ui/self/arbitrary-self-types-merge-chains.rs @@ -0,0 +1,59 @@ +// gate-test-arbitrary_self_types_split_chains + +#![feature(arbitrary_self_types)] + +use std::marker::PhantomData; +use std::ops::{Deref, Receiver}; + +struct A; +impl Deref for A { + type Target = u8; + fn deref(&self) -> &u8 { + &0 + } +} +impl Receiver for A { + //~^ ERROR `Deref::Target` does not agree with `Receiver::Target` + //~| ERROR `Receiver::Target` diverging from `Deref::Target` is not supported + type Target = u32; +} + +struct B<'a, T>(&'a T); +impl<'a, T> Deref for B<'a, T> { + type Target = T; + fn deref(&self) -> &T { + &*self.0 + } +} +impl<'a, T> Receiver for B<'a, T> { + //~^ ERROR `Deref::Target` does not agree with `Receiver::Target` + //~| ERROR `Receiver::Target` diverging from `Deref::Target` is not supported + type Target = Box; +} + +struct C<'a, T>(&'a T); +impl<'a, T> Deref for C<'a, T> { + type Target = Self; + fn deref(&self) -> &Self { + self + } +} +impl<'b, T> Receiver for C<'b, T> { + type Target = Self; // OK +} + +struct D(PhantomData T>); +trait Trait { + type Output; +} +impl> Deref for D { + type Target = T::Output; + fn deref(&self) -> &T { + unimplemented!() + } +} +impl Receiver for D { + type Target = T; // OK +} + +fn main() {} diff --git a/tests/ui/self/arbitrary-self-types-merge-chains.stderr b/tests/ui/self/arbitrary-self-types-merge-chains.stderr new file mode 100644 index 0000000000000..ea8bf36f309c0 --- /dev/null +++ b/tests/ui/self/arbitrary-self-types-merge-chains.stderr @@ -0,0 +1,47 @@ +error[E0658]: `Receiver::Target` diverging from `Deref::Target` is not supported, we look forward to your feedback + --> $DIR/arbitrary-self-types-merge-chains.rs:15:1 + | +LL | impl Receiver for A { + | ^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types_split_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: `Deref::Target` does not agree with `Receiver::Target` + --> $DIR/arbitrary-self-types-merge-chains.rs:15:1 + | +LL | impl Receiver for A { + | ^^^^^^^^^^^^^^^^^^^ `Deref::Target` is `u8` but `Receiver::Target` is `u32` + | +note: `#![feature(arbitrary_self_types_merge_chains)]` rejects this kind of divergence + --> $DIR/arbitrary-self-types-merge-chains.rs:15:1 + | +LL | impl Receiver for A { + | ^^^^^^^^^^^^^^^^^^^ + +error[E0658]: `Receiver::Target` diverging from `Deref::Target` is not supported, we look forward to your feedback + --> $DIR/arbitrary-self-types-merge-chains.rs:28:1 + | +LL | impl<'a, T> Receiver for B<'a, T> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #44874 for more information + = help: add `#![feature(arbitrary_self_types_split_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: `Deref::Target` does not agree with `Receiver::Target` + --> $DIR/arbitrary-self-types-merge-chains.rs:28:1 + | +LL | impl<'a, T> Receiver for B<'a, T> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Deref::Target` is `T` but `Receiver::Target` is `Box` + | +note: `#![feature(arbitrary_self_types_merge_chains)]` rejects this kind of divergence + --> $DIR/arbitrary-self-types-merge-chains.rs:28:1 + | +LL | impl<'a, T> Receiver for B<'a, T> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/self/arbitrary-self-types-split-chains.rs b/tests/ui/self/arbitrary-self-types-split-chains.rs new file mode 100644 index 0000000000000..a9b4fd69f6904 --- /dev/null +++ b/tests/ui/self/arbitrary-self-types-split-chains.rs @@ -0,0 +1,30 @@ +//@ check-pass + +#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_split_chains)] + +use std::ops::{Deref, Receiver}; + +struct A; +impl Deref for A { + type Target = u8; + fn deref(&self) -> &u8 { + &0 + } +} +impl Receiver for A { + type Target = u32; +} + +struct B<'a, T>(&'a T); +impl<'a, T> Deref for B<'a, T> { + type Target = T; + fn deref(&self) -> &T { + &*self.0 + } +} +impl<'a, T> Receiver for B<'a, T> { + type Target = Box; +} + +fn main() {} diff --git a/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr index 7a3d8b43c2e3a..75188787ece67 100644 --- a/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr +++ b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr @@ -22,7 +22,6 @@ error[E0277]: the trait bound `Foo: std::ops::Receiver` is not satisfied LL | foo.a(); | ^ the trait `std::ops::Receiver` is not implemented for `Foo` | - = note: required for `Foo` to implement `std::ops::Receiver` note: required by a bound in `Foo::a` --> $DIR/arbitrary_self_types_generic_over_receiver.rs:7:21 | diff --git a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs index 4dc170c3a65a1..95377ff73d8a3 100644 --- a/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs +++ b/tests/ui/self/arbitrary_self_types_pointers_and_wrappers.rs @@ -2,11 +2,9 @@ #![feature(arbitrary_self_types, unsize, coerce_unsized, dispatch_from_dyn)] #![feature(rustc_attrs)] -use std::{ - cell::Cell, - ops::{Deref, CoerceUnsized, DispatchFromDyn}, - marker::Unsize, -}; +use std::cell::Cell; +use std::marker::Unsize; +use std::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; struct Ptr(Box); @@ -17,11 +15,13 @@ impl Deref for Ptr { &*self.0 } } +impl Receiver for Ptr { + type Target = T; +} impl + ?Sized, U: ?Sized> CoerceUnsized> for Ptr {} impl + ?Sized, U: ?Sized> DispatchFromDyn> for Ptr {} - struct CellPtr<'a, T: ?Sized>(Cell<&'a T>); impl<'a, T: ?Sized> Deref for CellPtr<'a, T> { @@ -31,6 +31,9 @@ impl<'a, T: ?Sized> Deref for CellPtr<'a, T> { self.0.get() } } +impl<'a, T: ?Sized> Receiver for CellPtr<'a, T> { + type Target = T; +} impl<'a, T: Unsize + ?Sized, U: ?Sized> CoerceUnsized> for CellPtr<'a, T> {} impl<'a, T: Unsize + ?Sized, U: ?Sized> DispatchFromDyn> for CellPtr<'a, T> {} @@ -44,11 +47,12 @@ impl Deref for Wrapper { &self.0 } } - +impl Receiver for Wrapper { + type Target = T; +} impl, U> CoerceUnsized> for Wrapper {} impl, U> DispatchFromDyn> for Wrapper {} - trait Trait { fn ptr_wrapper(self: Ptr>) -> i32; fn wrapper_ptr(self: Wrapper>) -> i32; diff --git a/tests/ui/self/arbitrary_self_types_silly.rs b/tests/ui/self/arbitrary_self_types_silly.rs index 94726bd69cc57..d77698bd77488 100644 --- a/tests/ui/self/arbitrary_self_types_silly.rs +++ b/tests/ui/self/arbitrary_self_types_silly.rs @@ -12,8 +12,14 @@ impl std::ops::Deref for Bar { } } +impl std::ops::Receiver for Bar { + type Target = Foo; +} + impl Foo { - fn bar(self: Bar) -> i32 { 3 } + fn bar(self: Bar) -> i32 { + 3 + } } fn main() { diff --git a/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr index 237bbc5671515..eb66875b3a95d 100644 --- a/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr +++ b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr @@ -23,7 +23,8 @@ LL | fn method(self: &W) {} | ^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:14:5 diff --git a/tests/ui/self/dispatch-from-dyn-layout-3.rs b/tests/ui/self/dispatch-from-dyn-layout-3.rs index 6878a4f4ac271..340806574b2fe 100644 --- a/tests/ui/self/dispatch-from-dyn-layout-3.rs +++ b/tests/ui/self/dispatch-from-dyn-layout-3.rs @@ -6,10 +6,9 @@ #![feature(dispatch_from_dyn)] #![feature(arbitrary_self_types)] -use std::ops::Deref; -use std::ops::DispatchFromDyn; +use std::ops::{Deref, DispatchFromDyn, Receiver}; -trait Trait> +trait Trait + Receiver> where for<'a> &'a T: DispatchFromDyn<&'a T>, { diff --git a/tests/ui/self/dispatch-from-dyn-layout.rs b/tests/ui/self/dispatch-from-dyn-layout.rs index 468dc89a73e61..1b6d0c86ed97e 100644 --- a/tests/ui/self/dispatch-from-dyn-layout.rs +++ b/tests/ui/self/dispatch-from-dyn-layout.rs @@ -6,9 +6,9 @@ #![feature(arbitrary_self_types, dispatch_from_dyn)] -use std::ops::{Deref, DispatchFromDyn}; +use std::ops::{Deref, DispatchFromDyn, Receiver}; -trait Trait + DispatchFromDyn> { +trait Trait + Receiver + DispatchFromDyn> { fn foo(self: T) -> dyn Trait; } diff --git a/tests/ui/self/dispatch-from-dyn-zst-transmute.rs b/tests/ui/self/dispatch-from-dyn-zst-transmute.rs index 967958ab48695..637ec5362fe90 100644 --- a/tests/ui/self/dispatch-from-dyn-zst-transmute.rs +++ b/tests/ui/self/dispatch-from-dyn-zst-transmute.rs @@ -2,10 +2,8 @@ #![feature(unsize)] #![feature(dispatch_from_dyn)] -use std::marker::PhantomData; -use std::marker::Unsize; -use std::ops::DispatchFromDyn; -use std::ops::Deref; +use std::marker::{PhantomData, Unsize}; +use std::ops::{Deref, DispatchFromDyn, Receiver}; struct IsSendToken(PhantomData T>); @@ -18,7 +16,9 @@ impl<'a, T, U> DispatchFromDyn> for Foo<'a, T> //~^ ERROR implementing `DispatchFromDyn` does not allow multiple fields to be coerced where T: Unsize + ?Sized, - U: ?Sized {} + U: ?Sized, +{ +} trait Bar { fn f(self: Foo<'_, Self>); @@ -30,5 +30,8 @@ impl Deref for Foo<'_, U> { self.ptr } } +impl Receiver for Foo<'_, U> { + type Target = U; +} fn main() {} diff --git a/tests/ui/self/dispatch-from-dyn-zst-transmute.stderr b/tests/ui/self/dispatch-from-dyn-zst-transmute.stderr index cc8be45e99d8a..9b35c11d1f03c 100644 --- a/tests/ui/self/dispatch-from-dyn-zst-transmute.stderr +++ b/tests/ui/self/dispatch-from-dyn-zst-transmute.stderr @@ -1,15 +1,15 @@ error[E0375]: implementing `DispatchFromDyn` does not allow multiple fields to be coerced - --> $DIR/dispatch-from-dyn-zst-transmute.rs:17:1 + --> $DIR/dispatch-from-dyn-zst-transmute.rs:15:1 | LL | / impl<'a, T, U> DispatchFromDyn> for Foo<'a, T> LL | | LL | | where LL | | T: Unsize + ?Sized, -LL | | U: ?Sized {} - | |_____________^ +LL | | U: ?Sized, + | |______________^ | note: the trait `DispatchFromDyn` may only be implemented when a single field is being coerced - --> $DIR/dispatch-from-dyn-zst-transmute.rs:13:5 + --> $DIR/dispatch-from-dyn-zst-transmute.rs:11:5 | LL | token: IsSendToken, | ^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs b/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs index 55c070eb03682..84b6577c4845e 100644 --- a/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs +++ b/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs @@ -3,8 +3,8 @@ #![feature(derive_coerce_pointee)] #![feature(arbitrary_self_types)] -use std::ops::Deref; use std::marker::CoercePointee; +use std::ops::{Deref, Receiver}; use std::sync::Arc; trait MyTrait {} @@ -19,6 +19,9 @@ impl> Deref for MyArc { &self.0 } } +impl> Receiver for MyArc { + type Target = T; +} trait Mirror { type Assoc; diff --git a/tests/ui/self/dyn-dispatch-requires-supertrait.rs b/tests/ui/self/dyn-dispatch-requires-supertrait.rs index f2661c406fef0..f1beb838839d1 100644 --- a/tests/ui/self/dyn-dispatch-requires-supertrait.rs +++ b/tests/ui/self/dyn-dispatch-requires-supertrait.rs @@ -3,8 +3,8 @@ #![feature(derive_coerce_pointee)] #![feature(arbitrary_self_types)] -use std::ops::Deref; use std::marker::CoercePointee; +use std::ops::{Deref, Receiver}; use std::sync::Arc; trait MyTrait {} @@ -15,7 +15,7 @@ struct MyArc where T: MyTrait + ?Sized, { - inner: Arc + inner: Arc, } impl Deref for MyArc { @@ -24,6 +24,9 @@ impl Deref for MyArc { &self.inner } } +impl Receiver for MyArc { + type Target = T; +} // Proving that `MyArc` is dyn-dispatchable requires proving `MyArc` implements // `DispatchFromDyn>`. The `DispatchFromDyn` impl that is generated from the diff --git a/tests/ui/self/elision/multiple-ref-self-async.rs b/tests/ui/self/elision/multiple-ref-self-async.rs index f63b455901ee0..cb3940c326f81 100644 --- a/tests/ui/self/elision/multiple-ref-self-async.rs +++ b/tests/ui/self/elision/multiple-ref-self-async.rs @@ -4,18 +4,22 @@ #![allow(non_snake_case)] use std::marker::PhantomData; -use std::ops::Deref; +use std::ops::{Deref, Receiver}; use std::pin::Pin; -struct Struct { } +struct Struct {} struct Wrap(T, PhantomData

); impl Deref for Wrap { type Target = T; - fn deref(&self) -> &T { &self.0 } + fn deref(&self) -> &T { + &self.0 + } +} +impl Receiver for Wrap { + type Target = T; } - impl Struct { // Test using multiple `&Self`: @@ -45,4 +49,4 @@ impl Struct { } } -fn main() { } +fn main() {} diff --git a/tests/ui/self/elision/multiple-ref-self-async.stderr b/tests/ui/self/elision/multiple-ref-self-async.stderr index e2abc7c1e7852..56cf60ab6e791 100644 --- a/tests/ui/self/elision/multiple-ref-self-async.stderr +++ b/tests/ui/self/elision/multiple-ref-self-async.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/multiple-ref-self-async.rs:22:74 + --> $DIR/multiple-ref-self-async.rs:26:74 | LL | async fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 { | ------------------ --- ^ expected named lifetime parameter @@ -11,7 +11,7 @@ LL | async fn wrap_ref_Self_ref_Self<'a>(self: Wrap<&'a Self, &'a Self>, f: | ++++ ++ ++ ++ ++ error[E0106]: missing lifetime specifier - --> $DIR/multiple-ref-self-async.rs:27:84 + --> $DIR/multiple-ref-self-async.rs:31:84 | LL | async fn box_wrap_ref_Self_ref_Self(self: Box>, f: &u32) -> &u32 { | ----------------------- ---- ^ expected named lifetime parameter @@ -23,7 +23,7 @@ LL | async fn box_wrap_ref_Self_ref_Self<'a>(self: Box $DIR/multiple-ref-self-async.rs:32:84 + --> $DIR/multiple-ref-self-async.rs:36:84 | LL | async fn pin_wrap_ref_Self_ref_Self(self: Pin>, f: &u32) -> &u32 { | ----------------------- ---- ^ expected named lifetime parameter @@ -35,7 +35,7 @@ LL | async fn pin_wrap_ref_Self_ref_Self<'a>(self: Pin $DIR/multiple-ref-self-async.rs:37:93 + --> $DIR/multiple-ref-self-async.rs:41:93 | LL | async fn box_box_wrap_ref_Self_ref_Self(self: Box>>, f: &u32) -> &u32 { | ---------------------------- ---- ^ expected named lifetime parameter @@ -47,7 +47,7 @@ LL | async fn box_box_wrap_ref_Self_ref_Self<'a>(self: Box $DIR/multiple-ref-self-async.rs:42:93 + --> $DIR/multiple-ref-self-async.rs:46:93 | LL | async fn box_pin_wrap_ref_Self_ref_Self(self: Box>>, f: &u32) -> &u32 { | ---------------------------- ---- ^ expected named lifetime parameter diff --git a/tests/ui/self/elision/multiple-ref-self.rs b/tests/ui/self/elision/multiple-ref-self.rs index dd9b138051d0b..dc8487e36c7ba 100644 --- a/tests/ui/self/elision/multiple-ref-self.rs +++ b/tests/ui/self/elision/multiple-ref-self.rs @@ -2,16 +2,21 @@ #![allow(non_snake_case)] use std::marker::PhantomData; -use std::ops::Deref; +use std::ops::{Deref, Receiver}; use std::pin::Pin; -struct Struct { } +struct Struct {} struct Wrap(T, PhantomData

); impl Deref for Wrap { type Target = T; - fn deref(&self) -> &T { &self.0 } + fn deref(&self) -> &T { + &self.0 + } +} +impl Receiver for Wrap { + type Target = T; } impl Struct { @@ -43,4 +48,4 @@ impl Struct { } } -fn main() { } +fn main() {} diff --git a/tests/ui/self/elision/multiple-ref-self.stderr b/tests/ui/self/elision/multiple-ref-self.stderr index 24d74d352e482..9fcf1da9337c8 100644 --- a/tests/ui/self/elision/multiple-ref-self.stderr +++ b/tests/ui/self/elision/multiple-ref-self.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/multiple-ref-self.rs:20:68 + --> $DIR/multiple-ref-self.rs:25:68 | LL | fn wrap_ref_Self_ref_Self(self: Wrap<&Self, &Self>, f: &u8) -> &u8 { | ------------------ --- ^ expected named lifetime parameter @@ -11,7 +11,7 @@ LL | fn wrap_ref_Self_ref_Self<'a>(self: Wrap<&'a Self, &'a Self>, f: &'a u8 | ++++ ++ ++ ++ ++ error[E0106]: missing lifetime specifier - --> $DIR/multiple-ref-self.rs:25:78 + --> $DIR/multiple-ref-self.rs:30:78 | LL | fn box_wrap_ref_Self_ref_Self(self: Box>, f: &u32) -> &u32 { | ----------------------- ---- ^ expected named lifetime parameter @@ -23,7 +23,7 @@ LL | fn box_wrap_ref_Self_ref_Self<'a>(self: Box>, | ++++ ++ ++ ++ ++ error[E0106]: missing lifetime specifier - --> $DIR/multiple-ref-self.rs:30:78 + --> $DIR/multiple-ref-self.rs:35:78 | LL | fn pin_wrap_ref_Self_ref_Self(self: Pin>, f: &u32) -> &u32 { | ----------------------- ---- ^ expected named lifetime parameter @@ -35,7 +35,7 @@ LL | fn pin_wrap_ref_Self_ref_Self<'a>(self: Pin>, | ++++ ++ ++ ++ ++ error[E0106]: missing lifetime specifier - --> $DIR/multiple-ref-self.rs:35:87 + --> $DIR/multiple-ref-self.rs:40:87 | LL | fn box_box_wrap_ref_Self_ref_Self(self: Box>>, f: &u32) -> &u32 { | ---------------------------- ---- ^ expected named lifetime parameter @@ -47,7 +47,7 @@ LL | fn box_box_wrap_ref_Self_ref_Self<'a>(self: Box $DIR/multiple-ref-self.rs:40:87 + --> $DIR/multiple-ref-self.rs:45:87 | LL | fn box_pin_wrap_ref_Self_ref_Self(self: Box>>, f: &u32) -> &u32 { | ---------------------------- ---- ^ expected named lifetime parameter diff --git a/tests/ui/self/elision/ref-self-async.rs b/tests/ui/self/elision/ref-self-async.rs index 1f3e670d3d1df..a0b5d75716ebd 100644 --- a/tests/ui/self/elision/ref-self-async.rs +++ b/tests/ui/self/elision/ref-self-async.rs @@ -4,16 +4,21 @@ #![feature(arbitrary_self_types)] use std::marker::PhantomData; -use std::ops::Deref; +use std::ops::{Deref, Receiver}; use std::pin::Pin; -struct Struct { } +struct Struct {} struct Wrap(T, PhantomData

); impl Deref for Wrap { type Target = T; - fn deref(&self) -> &T { &self.0 } + fn deref(&self) -> &T { + &self.0 + } +} +impl Receiver for Wrap { + type Target = T; } impl Struct { @@ -57,4 +62,4 @@ impl Struct { } } -fn main() { } +fn main() {} diff --git a/tests/ui/self/elision/ref-self-async.stderr b/tests/ui/self/elision/ref-self-async.stderr index a75ece5f2c768..6a782c2ee8c39 100644 --- a/tests/ui/self/elision/ref-self-async.stderr +++ b/tests/ui/self/elision/ref-self-async.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/ref-self-async.rs:23:9 + --> $DIR/ref-self-async.rs:28:9 | LL | async fn ref_self(&self, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -14,7 +14,7 @@ LL | async fn ref_self<'a>(&self, f: &'a u32) -> &'a u32 { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self-async.rs:30:9 + --> $DIR/ref-self-async.rs:35:9 | LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -29,7 +29,7 @@ LL | async fn ref_Self<'a>(self: &Self, f: &'a u32) -> &'a u32 { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self-async.rs:35:9 + --> $DIR/ref-self-async.rs:40:9 | LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -44,7 +44,7 @@ LL | async fn box_ref_Self<'a>(self: Box<&Self>, f: &'a u32) -> &'a u32 { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self-async.rs:40:9 + --> $DIR/ref-self-async.rs:45:9 | LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -59,7 +59,7 @@ LL | async fn pin_ref_Self<'a>(self: Pin<&Self>, f: &'a u32) -> &'a u32 { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self-async.rs:45:9 + --> $DIR/ref-self-async.rs:50:9 | LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -74,7 +74,7 @@ LL | async fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &'a | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self-async.rs:50:9 + --> $DIR/ref-self-async.rs:55:9 | LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -89,7 +89,7 @@ LL | async fn box_pin_ref_Self<'a>(self: Box>, f: &'a u32) -> &'a | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self-async.rs:55:9 + --> $DIR/ref-self-async.rs:60:9 | LL | async fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { | - - let's call the lifetime of this reference `'1` diff --git a/tests/ui/self/elision/ref-self-multi.rs b/tests/ui/self/elision/ref-self-multi.rs index ed431a9c852dd..b750541ca325a 100644 --- a/tests/ui/self/elision/ref-self-multi.rs +++ b/tests/ui/self/elision/ref-self-multi.rs @@ -3,15 +3,20 @@ #![allow(unused)] use std::marker::PhantomData; -use std::ops::Deref; +use std::ops::{Deref, Receiver}; -struct Struct { } +struct Struct {} struct Wrap(T, PhantomData

); impl Deref for Wrap { type Target = T; - fn deref(&self) -> &T { &self.0 } + fn deref(&self) -> &T { + &self.0 + } +} +impl Receiver for Wrap { + type Target = T; } impl Struct { @@ -26,4 +31,4 @@ impl Struct { } } -fn main() { } +fn main() {} diff --git a/tests/ui/self/elision/ref-self-multi.stderr b/tests/ui/self/elision/ref-self-multi.stderr index 7e0451aa0d5c3..976f539bea06a 100644 --- a/tests/ui/self/elision/ref-self-multi.stderr +++ b/tests/ui/self/elision/ref-self-multi.stderr @@ -1,5 +1,5 @@ error[E0106]: missing lifetime specifier - --> $DIR/ref-self-multi.rs:18:56 + --> $DIR/ref-self-multi.rs:23:56 | LL | fn ref_box_ref_Self(self: &Box<&Self>, f: &u32) -> &u32 { | ----------- ---- ^ expected named lifetime parameter @@ -11,7 +11,7 @@ LL | fn ref_box_ref_Self<'a>(self: &'a Box<&'a Self>, f: &'a u32) -> &'a u32 | ++++ ++ ++ ++ ++ error[E0106]: missing lifetime specifier - --> $DIR/ref-self-multi.rs:23:63 + --> $DIR/ref-self-multi.rs:28:63 | LL | fn ref_wrap_ref_Self(self: &Wrap<&Self, u32>, f: &u32) -> &u32 { | ----------------- ---- ^ expected named lifetime parameter diff --git a/tests/ui/self/elision/ref-self.fixed b/tests/ui/self/elision/ref-self.fixed index 784ccb9efe2f6..64a23c9c5f56f 100644 --- a/tests/ui/self/elision/ref-self.fixed +++ b/tests/ui/self/elision/ref-self.fixed @@ -5,7 +5,7 @@ #![allow(non_snake_case, dead_code)] use std::marker::PhantomData; -use std::ops::Deref; +use std::ops::{Deref, Receiver}; use std::pin::Pin; struct Struct {} @@ -18,6 +18,9 @@ impl Deref for Wrap { &self.0 } } +impl Receiver for Wrap { + type Target = T; +} impl Struct { // Test using `&self` sugar: diff --git a/tests/ui/self/elision/ref-self.rs b/tests/ui/self/elision/ref-self.rs index dbe441879cc5d..df3bbca6d19f8 100644 --- a/tests/ui/self/elision/ref-self.rs +++ b/tests/ui/self/elision/ref-self.rs @@ -5,7 +5,7 @@ #![allow(non_snake_case, dead_code)] use std::marker::PhantomData; -use std::ops::Deref; +use std::ops::{Deref, Receiver}; use std::pin::Pin; struct Struct {} @@ -18,6 +18,9 @@ impl Deref for Wrap { &self.0 } } +impl Receiver for Wrap { + type Target = T; +} impl Struct { // Test using `&self` sugar: diff --git a/tests/ui/self/elision/ref-self.stderr b/tests/ui/self/elision/ref-self.stderr index 64e7bfc1bb06c..525ff061f32dc 100644 --- a/tests/ui/self/elision/ref-self.stderr +++ b/tests/ui/self/elision/ref-self.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/ref-self.rs:26:9 + --> $DIR/ref-self.rs:29:9 | LL | fn ref_self(&self, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -14,7 +14,7 @@ LL | fn ref_self<'a>(&self, f: &'a u32) -> &'a u32 { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self.rs:33:9 + --> $DIR/ref-self.rs:36:9 | LL | fn ref_Self(self: &Self, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -29,7 +29,7 @@ LL | fn ref_Self<'a>(self: &Self, f: &'a u32) -> &'a u32 { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self.rs:38:9 + --> $DIR/ref-self.rs:41:9 | LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -44,7 +44,7 @@ LL | fn box_ref_Self<'a>(self: Box<&Self>, f: &'a u32) -> &'a u32 { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self.rs:43:9 + --> $DIR/ref-self.rs:46:9 | LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -59,7 +59,7 @@ LL | fn pin_ref_Self<'a>(self: Pin<&Self>, f: &'a u32) -> &'a u32 { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self.rs:48:9 + --> $DIR/ref-self.rs:51:9 | LL | fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -74,7 +74,7 @@ LL | fn box_box_ref_Self<'a>(self: Box>, f: &'a u32) -> &'a u32 { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self.rs:53:9 + --> $DIR/ref-self.rs:56:9 | LL | fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` @@ -89,7 +89,7 @@ LL | fn box_pin_ref_Self<'a>(self: Box>, f: &'a u32) -> &'a u32 { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self.rs:58:9 + --> $DIR/ref-self.rs:61:9 | LL | fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { | - - let's call the lifetime of this reference `'1` @@ -104,7 +104,7 @@ LL | fn wrap_ref_Self_Self<'a>(self: Wrap<&Self, Self>, f: &'a u8) -> &'a u8 | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/ref-self.rs:63:9 + --> $DIR/ref-self.rs:66:9 | LL | fn ref_box_Self(self: &Box, f: &u32) -> &u32 { | - - let's call the lifetime of this reference `'1` diff --git a/tests/ui/self/invalid-self-dyn-receiver.rs b/tests/ui/self/invalid-self-dyn-receiver.rs index a989b331b5e0b..f1867bda2167f 100644 --- a/tests/ui/self/invalid-self-dyn-receiver.rs +++ b/tests/ui/self/invalid-self-dyn-receiver.rs @@ -4,17 +4,18 @@ #![feature(arbitrary_self_types)] -use std::ops::Deref; +use std::ops::{Deref, Receiver}; -trait Foo: Deref { - fn method(self: &dyn Bar) {} - //~^ ERROR invalid `self` parameter type: `&dyn Bar` +trait Foo: Deref + Receiver { + fn method(self: &dyn Bar) {} + //~^ ERROR invalid `self` parameter type: `&dyn Bar` } trait Bar {} fn test(x: &dyn Foo) { - x.method(); + x.method(); + //~^ ERROR type annotations needed } fn main() {} diff --git a/tests/ui/self/invalid-self-dyn-receiver.stderr b/tests/ui/self/invalid-self-dyn-receiver.stderr index f77f5686ad282..0fed908037e04 100644 --- a/tests/ui/self/invalid-self-dyn-receiver.stderr +++ b/tests/ui/self/invalid-self-dyn-receiver.stderr @@ -1,12 +1,26 @@ error[E0307]: invalid `self` parameter type: `&dyn Bar` - --> $DIR/invalid-self-dyn-receiver.rs:10:22 + --> $DIR/invalid-self-dyn-receiver.rs:10:21 | -LL | fn method(self: &dyn Bar) {} - | ^^^^^^^^ +LL | fn method(self: &dyn Bar) {} + | ^^^^^^^^ | = note: type of `self` must be `Self` or some type implementing `Receiver` = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` -error: aborting due to 1 previous error +error[E0283]: type annotations needed + --> $DIR/invalid-self-dyn-receiver.rs:17:7 + | +LL | x.method(); + | ^^^^^^ + | + = note: cannot satisfy `_: Foo` +help: try using a fully qualified path to specify the expected types + | +LL - x.method(); +LL + <_ as Foo>::method(x); + | + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0307`. +Some errors have detailed explanations: E0283, E0307. +For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr index c57a100bbe227..4c524cfcb0a7b 100644 --- a/tests/ui/span/issue-27522.stderr +++ b/tests/ui/span/issue-27522.stderr @@ -5,7 +5,8 @@ LL | fn handler(self: &SomeType); | ^^^^^^^^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr index c275cdccaa8c1..b113a771c704a 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr @@ -35,7 +35,8 @@ LL | fn bar(self: ()) {} | ^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error: aborting due to 2 previous errors diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 6744281dc34e2..ac78408557027 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -69,7 +69,8 @@ LL | fn foo(self: Smaht); | ^^^^^^^^^^^^^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error: aborting due to 7 previous errors diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr index 7b5f7cd9f7033..f024fc52f3d43 100644 --- a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -24,7 +24,8 @@ LL | fn foo(self: isize, x: isize) -> isize { | ^^^^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error[E0307]: invalid `self` parameter type: `Bar` --> $DIR/ufcs-explicit-self-bad.rs:19:18 @@ -33,7 +34,8 @@ LL | fn foo(self: Bar, x: isize) -> isize { | ^^^^^^^^^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error[E0307]: invalid `self` parameter type: `&Bar` --> $DIR/ufcs-explicit-self-bad.rs:23:18 @@ -42,7 +44,8 @@ LL | fn bar(self: &Bar, x: isize) -> isize { | ^^^^^^^^^^^ | = note: type of `self` must be `Self` or a type that dereferences to it - = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`) + = help: consider changing to `self`, `&self`, `&mut self`, `self: Box`, `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one of the previous types except `Self`); + alternatively, consider implement `Receiver` trait on the type of `self`, where applicable error[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:37:21