From 7c93ba82ca78361154f8f9af47cb60eaf12295bc Mon Sep 17 00:00:00 2001 From: Xiangfei Ding Date: Tue, 2 Sep 2025 10:44:21 +0200 Subject: [PATCH 1/2] arbitrary_self_types: split the Autoderef chain Receiver chain has been an extension of Deref chain, but the consequence has been questioned as this would admit method signatures that are deemed dubious. It is also debatable that Receiver trait which determines applicable `Self` type should have anything to do with dereference operation in general. This patch separate the two traits and isolate their use in the language. This means that in method probing, we will chase down a Deref chain for an applicable type for the variable `self`, from which we additionally chase down a Receiver chain for an applicable `Self` type from a list of methods that accepts one of these possible types of `self`. This patch includes rewording of diagnostics. --- ...itrary_self_types_pointers_and_wrappers.rs | 8 +- ...itrary_self_types_pointers_and_wrappers.rs | 13 +- .../src/error_codes/E0307.md | 10 +- compiler/rustc_hir_analysis/messages.ftl | 3 +- compiler/rustc_hir_analysis/src/autoderef.rs | 72 +++++- .../rustc_hir_analysis/src/check/wfcheck.rs | 22 +- compiler/rustc_hir_typeck/src/autoderef.rs | 2 +- .../rustc_hir_typeck/src/method/confirm.rs | 32 ++- compiler/rustc_hir_typeck/src/method/probe.rs | 213 ++++++++++-------- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/traits/query.rs | 1 + compiler/rustc_resolve/src/lib.rs | 6 + library/alloc/src/boxed.rs | 6 +- library/alloc/src/lib.rs | 2 + library/alloc/src/rc.rs | 8 +- library/alloc/src/sync.rs | 8 +- library/core/src/marker.rs | 8 +- library/core/src/ops/deref.rs | 21 +- library/core/src/pin.rs | 8 +- src/tools/miri/src/shims/files.rs | 6 + .../miri/tests/pass/dyn-arbitrary-self.rs | 16 +- tests/crashes/138564.rs | 6 +- .../invalid-self-parameter-type-56806.stderr | 3 +- .../inference_var_self_argument.stderr | 3 +- tests/ui/async-await/issue-66312.stderr | 3 +- tests/ui/deriving/deriving-coerce-pointee.rs | 7 +- .../feature-gate-arbitrary-self-types.rs | 10 +- .../feature-gate-arbitrary-self-types.stderr | 35 ++- ...feature-gate-dispatch-from-dyn-cell.stderr | 3 +- ...ure-gate-dispatch-from-dyn-missing-impl.rs | 9 +- ...gate-dispatch-from-dyn-missing-impl.stderr | 4 +- ...-same-trait-object-with-separate-params.rs | 8 +- ...e-trait-object-with-separate-params.stderr | 16 +- ...y-self-from-method-substs-with-receiver.rs | 19 +- ...lf-from-method-substs-with-receiver.stderr | 34 +-- ...ary-self-from-method-substs.default.stderr | 80 ++++--- ...ary-self-from-method-substs.feature.stderr | 98 +++++--- .../self/arbitrary-self-from-method-substs.rs | 78 +++++-- tests/ui/self/arbitrary-self-opaque.stderr | 3 +- ...ry_self_types_generic_over_receiver.stderr | 1 - ...itrary_self_types_pointers_and_wrappers.rs | 20 +- tests/ui/self/arbitrary_self_types_silly.rs | 8 +- ...yn-incompatible-that-does-not-deref.stderr | 3 +- tests/ui/self/dispatch-from-dyn-layout-3.rs | 5 +- tests/ui/self/dispatch-from-dyn-layout.rs | 4 +- .../self/dispatch-from-dyn-zst-transmute.rs | 13 +- .../dispatch-from-dyn-zst-transmute.stderr | 8 +- .../dyn-dispatch-requires-supertrait-norm.rs | 5 +- .../self/dyn-dispatch-requires-supertrait.rs | 7 +- .../self/elision/multiple-ref-self-async.rs | 14 +- .../elision/multiple-ref-self-async.stderr | 10 +- tests/ui/self/elision/multiple-ref-self.rs | 13 +- .../ui/self/elision/multiple-ref-self.stderr | 10 +- tests/ui/self/elision/ref-self-async.rs | 13 +- tests/ui/self/elision/ref-self-async.stderr | 14 +- tests/ui/self/elision/ref-self-multi.rs | 13 +- tests/ui/self/elision/ref-self-multi.stderr | 4 +- tests/ui/self/elision/ref-self.fixed | 5 +- tests/ui/self/elision/ref-self.rs | 5 +- tests/ui/self/elision/ref-self.stderr | 16 +- tests/ui/self/invalid-self-dyn-receiver.rs | 11 +- .../ui/self/invalid-self-dyn-receiver.stderr | 24 +- tests/ui/span/issue-27522.stderr | 3 +- ...atible-trait-should-use-where-sized.stderr | 3 +- tests/ui/traits/issue-78372.stderr | 3 +- tests/ui/ufcs/ufcs-explicit-self-bad.stderr | 9 +- 66 files changed, 724 insertions(+), 406 deletions(-) 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_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_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index a313b91ef9bda..ce286a1adc6a9 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -263,7 +263,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 f3d6398b20853..7a99f38cf6ef9 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1720,7 +1720,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) @@ -1734,7 +1736,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, @@ -1756,7 +1758,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, } @@ -1812,17 +1814,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(); } @@ -1876,7 +1882,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_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 f7a0a55d5880d..c36a9273ff14a 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 a8457134031c9..8c9242cd5af37 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -372,6 +372,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) } + #[instrument(level = "debug", skip(self, op))] pub(crate) fn probe_op( &'a self, span: Span, @@ -418,6 +419,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, @@ -572,12 +574,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } +#[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 +615,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 +720,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, @@ -801,7 +821,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn assemble_inherent_candidates(&mut self) { for step in self.steps.iter() { - self.assemble_probe(&step.self_ty, step.autoderefs); + self.assemble_probe(&step.self_ty, step.receiver_depth); } } @@ -1236,6 +1256,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>, @@ -1248,7 +1269,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // 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); + 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 @@ -1274,22 +1295,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // 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, + &instantiate_self_ty_obligations, + mutbl, + track_unstable_candidates, + ) { + return Some(Err(e)); } } } + return Some(by_value_pick); } @@ -1303,21 +1325,22 @@ 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, + &instantiate_self_ty_obligations, + hir::Mutability::Mut, + track_unstable_candidates, + ) { + return Some(Err(e)); } } + return Some(autoref_pick); } @@ -1372,20 +1395,26 @@ 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. fn check_for_shadowed_autorefd_method( &self, possible_shadower: &Pick<'tcx>, @@ -1409,19 +1438,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 +1471,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. @@ -1463,7 +1496,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)) @@ -1603,6 +1636,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// 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>, @@ -1631,6 +1665,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ) } + #[instrument(level = "debug", skip_all)] fn pick_method( &self, self_ty: Ty<'tcx>, @@ -1656,8 +1691,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - 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,9 +1701,9 @@ 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 } @@ -1684,9 +1719,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let mut applicable_candidates: Vec<_> = candidates .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 +1734,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ), ) }) - .filter(|&(_, status)| status != ProbeResult::NoMatch) + .filter(|&(_, status)| !matches!(status, ProbeResult::NoMatch)) .collect(); debug!("applicable_candidates: {:?}", applicable_candidates); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e6bbdc87d9958..7e33601159f0e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1131,7 +1131,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 c5cd7c54e4e86..e360215613bf7 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 9f68b93520d29..868d0df03ff55 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2543,6 +2543,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; @@ -2559,6 +2561,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/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7ad1679b1c822..82e5eb51406d2 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -197,7 +197,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}; @@ -2076,6 +2076,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 786f88c29ef46..65fa3c8c5f6d8 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(array_windows)] #![feature(ascii_char)] diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index a24ea6e526c4b..3df3a661a3f58 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}; @@ -2350,6 +2352,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 13b5cf23e72d8..dc1f551d0586c 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}; @@ -2333,6 +2335,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 5fd0611a18434..5023e85eb6234 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1192,7 +1192,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)] @@ -1204,8 +1204,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 81c2dabf0d1d8..6564130c74fee 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 8c29cb040b55a..833a56a9101ff 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 1fccc32470ff6..600c567189f9f 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:5 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_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 a1c772f58e1f1..4fe3d6f01ad00 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 From 2304ec914852946e4ea6846ea55dfd44b1b1da43 Mon Sep 17 00:00:00 2001 From: Xiangfei Ding Date: Wed, 5 Nov 2025 15:36:59 +0000 Subject: [PATCH 2/2] enable experimentation with merged chains --- compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_hir_analysis/messages.ftl | 4 ++ .../src/coherence/builtin.rs | 48 ++++++++++++++- compiler/rustc_hir_analysis/src/errors.rs | 11 ++++ compiler/rustc_span/src/symbol.rs | 1 + .../self/arbitrary-self-types-merge-chains.rs | 58 +++++++++++++++++++ .../arbitrary-self-types-merge-chains.stderr | 26 +++++++++ 7 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 tests/ui/self/arbitrary-self-types-merge-chains.rs create mode 100644 tests/ui/self/arbitrary-self-types-merge-chains.stderr diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8397cd294e0a9..bca8af4cf62ba 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -380,6 +380,8 @@ declare_features! ( (unstable, alloc_error_handler, "1.29.0", Some(51540)), /// Allows inherent and trait methods with arbitrary self types. (unstable, arbitrary_self_types, "1.23.0", Some(44874)), + /// Enforce agreement between `Receiver::Target` and `Deref::Target` + (unstable, arbitrary_self_types_merge_chains, "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)), /// Allows #[cfg(...)] on inline assembly templates and operands. diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index ce286a1adc6a9..37bb324d3c225 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -149,6 +149,10 @@ 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_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 diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 61562cc1e4f30..c35c7e435b5c9 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -22,7 +22,7 @@ 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 +48,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 +756,48 @@ 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_merge_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, + ) { + 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 dbad98fd79528..6a604c1777df6 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1156,6 +1156,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_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 38718bad9e57e..14ea6d09afc6a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -463,6 +463,7 @@ symbols! { apx_target_feature, arbitrary_enum_discriminant, arbitrary_self_types, + arbitrary_self_types_merge_chains, arbitrary_self_types_pointers, areg, args, 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..5ce181aa2bbff --- /dev/null +++ b/tests/ui/self/arbitrary-self-types-merge-chains.rs @@ -0,0 +1,58 @@ +// gate-test-arbitrary_self_types_merge_chains + +#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_merge_chains)] + +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` + 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` + 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..7b3ae813f0603 --- /dev/null +++ b/tests/ui/self/arbitrary-self-types-merge-chains.stderr @@ -0,0 +1,26 @@ +error: `Deref::Target` does not agree with `Receiver::Target` + --> $DIR/arbitrary-self-types-merge-chains.rs:16: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:16:1 + | +LL | impl Receiver for A { + | ^^^^^^^^^^^^^^^^^^^ + +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 2 previous errors +