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_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 a313b91ef9bda..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 @@ -263,7 +267,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_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_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/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/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-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 + 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