diff --git a/compiler/rustc_error_codes/src/error_codes/E0307.md b/compiler/rustc_error_codes/src/error_codes/E0307.md index 0d29d56ea1a75..b9c0493e8d6e6 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0307.md +++ b/compiler/rustc_error_codes/src/error_codes/E0307.md @@ -65,8 +65,10 @@ impl Trait for Foo { ``` The nightly feature [Arbitrary self types][AST] extends the accepted -set of receiver types to also include any type that can dereference to -`Self`: +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)] diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 32498d9c5ab5b..25feb95d5dfeb 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -241,10 +241,10 @@ hir_analysis_invalid_generic_receiver_ty_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`) hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty}` - .note = type of `self` must be `Self` or a type that dereferences to it + .note = type of `self` must be `Self` or some type implementing `Receiver` hir_analysis_invalid_receiver_ty_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`) + consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` hir_analysis_invalid_union_field = field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 5a66c31a0cc31..d8e9227a87c86 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -18,7 +18,6 @@ pub enum AutoderefKind { /// A type which must dispatch to a `Deref` implementation. Overloaded, } - struct AutoderefSnapshot<'tcx> { at_start: bool, reached_recursion_limit: bool, @@ -27,6 +26,10 @@ struct AutoderefSnapshot<'tcx> { obligations: PredicateObligations<'tcx>, } +/// Recursively dereference a type, considering both built-in +/// dereferences (`*`) and the `Deref` trait. +/// Although called `Autoderef` it can be configured to use the +/// `Receiver` trait instead of the `Deref` trait. pub struct Autoderef<'a, 'tcx> { // Meta infos: infcx: &'a InferCtxt<'tcx>, @@ -39,6 +42,7 @@ pub struct Autoderef<'a, 'tcx> { // Configurations: include_raw_pointers: bool, + use_receiver_trait: bool, silence_errors: bool, } @@ -69,6 +73,10 @@ 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. 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)); @@ -111,7 +119,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { body_def_id: LocalDefId, span: Span, base_ty: Ty<'tcx>, - ) -> Autoderef<'a, 'tcx> { + ) -> Self { Autoderef { infcx, span, @@ -125,6 +133,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { reached_recursion_limit: false, }, include_raw_pointers: false, + use_receiver_trait: false, silence_errors: false, } } @@ -137,8 +146,13 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { return None; } - // - let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [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 { + (tcx.lang_items().receiver_trait()?, tcx.lang_items().receiver_target()?) + } else { + (tcx.lang_items().deref_trait()?, tcx.lang_items().deref_target()?) + }; + let trait_ref = ty::TraitRef::new(tcx, trait_def_id, [ty]); let cause = traits::ObligationCause::misc(self.span, self.body_id); let obligation = traits::Obligation::new( tcx, @@ -151,11 +165,8 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { return None; } - let (normalized_ty, obligations) = self.structurally_normalize(Ty::new_projection( - tcx, - tcx.lang_items().deref_target()?, - [ty], - ))?; + let (normalized_ty, obligations) = + self.structurally_normalize(Ty::new_projection(tcx, trait_target_def_id, [ty]))?; debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations); self.state.obligations.extend(obligations); @@ -234,6 +245,14 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { self } + /// 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 { + 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 c9773972d9a24..57264d0bd2afc 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1821,13 +1821,18 @@ fn receiver_is_valid<'tcx>( let mut autoderef = Autoderef::new(infcx, 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 + // chain. + if arbitrary_self_types_enabled.is_some() { + autoderef = autoderef.use_receiver_trait(); + } + // The `arbitrary_self_types_pointers` feature allows raw pointer receivers like `self: *const Self`. if arbitrary_self_types_enabled == Some(ArbitrarySelfTypesLevel::WithPointers) { autoderef = autoderef.include_raw_pointers(); } - let receiver_trait_def_id = tcx.require_lang_item(LangItem::LegacyReceiver, Some(span)); - // Keep dereferencing `receiver_ty` until we get to `self_ty`. while let Some((potential_self_ty, _)) = autoderef.next() { debug!( @@ -1849,11 +1854,13 @@ fn receiver_is_valid<'tcx>( } // Without `feature(arbitrary_self_types)`, we require that each step in the - // deref chain implement `receiver`. + // deref chain implement `LegacyReceiver`. if arbitrary_self_types_enabled.is_none() { - if !receiver_is_implemented( + let legacy_receiver_trait_def_id = + tcx.require_lang_item(LangItem::LegacyReceiver, Some(span)); + if !legacy_receiver_is_implemented( wfcx, - receiver_trait_def_id, + legacy_receiver_trait_def_id, cause.clone(), potential_self_ty, ) { @@ -1866,7 +1873,7 @@ fn receiver_is_valid<'tcx>( cause.clone(), wfcx.param_env, potential_self_ty, - receiver_trait_def_id, + legacy_receiver_trait_def_id, ); } } @@ -1875,14 +1882,14 @@ fn receiver_is_valid<'tcx>( Err(ReceiverValidityError::DoesNotDeref) } -fn receiver_is_implemented<'tcx>( +fn legacy_receiver_is_implemented<'tcx>( wfcx: &WfCheckingCtxt<'_, 'tcx>, - receiver_trait_def_id: DefId, + legacy_receiver_trait_def_id: DefId, cause: ObligationCause<'tcx>, receiver_ty: Ty<'tcx>, ) -> bool { let tcx = wfcx.tcx(); - let trait_ref = ty::TraitRef::new(tcx, receiver_trait_def_id, [receiver_ty]); + let trait_ref = ty::TraitRef::new(tcx, legacy_receiver_trait_def_id, [receiver_ty]); let obligation = Obligation::new(tcx, cause, wfcx.param_env, trait_ref); @@ -1890,7 +1897,7 @@ fn receiver_is_implemented<'tcx>( true } else { debug!( - "receiver_is_implemented: type `{:?}` does not implement `Receiver` trait", + "receiver_is_implemented: type `{:?}` does not implement `LegacyReceiver` trait", receiver_ty ); false diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 3399a9fe88078..d0272651c0809 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -917,7 +917,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [candidate] => format!( "the method of the same name on {} `{}`", match candidate.kind { - probe::CandidateKind::InherentImplCandidate(_) => "the inherent impl for", + probe::CandidateKind::InherentImplCandidate { .. } => "the inherent impl for", _ => "trait", }, self.tcx.def_path_str(candidate.item.container_id(self.tcx)) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 039c117c09995..3b377076545da 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -79,12 +79,6 @@ pub(crate) struct ProbeContext<'a, 'tcx> { /// used for error reporting static_candidates: RefCell>, - /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used - /// for error reporting - unsatisfied_predicates: RefCell< - Vec<(ty::Predicate<'tcx>, Option>, Option>)>, - >, - scope_expr_id: HirId, /// Is this probe being done for a diagnostic? This will skip some error reporting @@ -109,7 +103,7 @@ pub(crate) struct Candidate<'tcx> { #[derive(Debug, Clone)] pub(crate) enum CandidateKind<'tcx> { - InherentImplCandidate(DefId), + InherentImplCandidate { impl_def_id: DefId, receiver_steps: usize }, ObjectCandidate(ty::PolyTraitRef<'tcx>), TraitCandidate(ty::PolyTraitRef<'tcx>), WhereClauseCandidate(ty::PolyTraitRef<'tcx>), @@ -162,6 +156,52 @@ impl AutorefOrPtrAdjustment { } } +/// Extra information required only for error reporting. +#[derive(Debug)] +struct PickDiagHints<'a, 'tcx> { + /// Unstable candidates alongside the stable ones. + unstable_candidates: Option, Symbol)>>, + + /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used + /// for error reporting + unsatisfied_predicates: &'a mut Vec<( + ty::Predicate<'tcx>, + Option>, + Option>, + )>, +} + +/// Criteria to apply when searching for a given Pick. This is used during +/// the search for potentially shadowed methods to ensure we don't search +/// more candidates than strictly necessary. +#[derive(Debug)] +struct PickConstraintsForShadowed { + autoderefs: usize, + receiver_steps: Option, + def_id: DefId, +} + +impl PickConstraintsForShadowed { + fn may_shadow_based_on_autoderefs(&self, autoderefs: usize) -> bool { + autoderefs == self.autoderefs + } + + fn candidate_may_shadow(&self, candidate: &Candidate<'_>) -> bool { + // An item never shadows itself + candidate.item.def_id != self.def_id + // and we're only concerned about inherent impls doing the shadowing. + // Shadowing can only occur if the shadowed is further along + // the Receiver dereferencing chain than the shadowed. + && match candidate.kind { + CandidateKind::InherentImplCandidate { receiver_steps, .. } => match self.receiver_steps { + Some(shadowed_receiver_steps) => receiver_steps > shadowed_receiver_steps, + _ => false + }, + _ => false + } + } +} + #[derive(Debug, Clone)] pub(crate) struct Pick<'tcx> { pub item: ty::AssocItem, @@ -181,6 +221,11 @@ pub(crate) struct Pick<'tcx> { /// Unstable candidates alongside the stable ones. unstable_candidates: Vec<(Candidate<'tcx>, Symbol)>, + + /// Number of jumps along the `Receiver::Target` chain we followed + /// to identify this method. Used only for deshadowing errors. + /// Only applies for inherent impls. + pub receiver_steps: Option, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -366,6 +411,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { autoderefs: 0, from_unsafe_deref: false, unsize: false, + reachable_via_deref: true, }]), opt_bad_ty: None, reached_recursion_limit: false, @@ -516,47 +562,93 @@ fn method_autoderef_steps<'tcx>( let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal); let ParamEnvAnd { param_env, value: self_ty } = goal; - let mut autoderef = + // 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(); - let mut reached_raw_pointer = false; - let mut steps: Vec<_> = autoderef - .by_ref() - .map(|(ty, d)| { - let step = CandidateStep { - self_ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, ty), - autoderefs: d, - from_unsafe_deref: reached_raw_pointer, - unsize: false, - }; - if let ty::RawPtr(_, _) = ty.kind() { - // all the subsequent steps will be from_unsafe_deref - reached_raw_pointer = true; - } - step - }) - .collect(); - let final_ty = autoderef.final_ty(true); + 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 step = CandidateStep { + self_ty: infcx + .make_query_response_ignoring_pending_obligations(inference_vars, ty), + autoderefs: d, + from_unsafe_deref: reached_raw_pointer, + unsize: false, + reachable_via_deref, + }; + if ty.is_unsafe_ptr() { + // all the subsequent steps will be from_unsafe_deref + reached_raw_pointer = true; + } + step + }) + .collect(); + (steps, autoderef_via_receiver.reached_recursion_limit()) + } else { + let steps = autoderef_via_deref + .by_ref() + .map(|(ty, d)| { + let step = CandidateStep { + self_ty: infcx + .make_query_response_ignoring_pending_obligations(inference_vars, ty), + autoderefs: d, + from_unsafe_deref: reached_raw_pointer, + unsize: false, + reachable_via_deref: true, + }; + if ty.is_unsafe_ptr() { + // all the subsequent steps will be from_unsafe_deref + reached_raw_pointer = true; + } + step + }) + .collect(); + (steps, autoderef_via_deref.reached_recursion_limit()) + }; + let final_ty = autoderef_via_deref.final_ty(true); let opt_bad_ty = match final_ty.kind() { ty::Infer(ty::TyVar(_)) | ty::Error(_) => Some(MethodAutoderefBadTy { reached_raw_pointer, ty: infcx.make_query_response_ignoring_pending_obligations(inference_vars, final_ty), }), ty::Array(elem_ty, _) => { - let dereferences = steps.len() - 1; - + let autoderefs = steps.iter().filter(|s| s.reachable_via_deref).count() - 1; steps.push(CandidateStep { self_ty: infcx.make_query_response_ignoring_pending_obligations( inference_vars, Ty::new_slice(infcx.tcx, *elem_ty), ), - autoderefs: dereferences, + autoderefs, // this could be from an unsafe deref if we had // a *mut/const [T; N] from_unsafe_deref: reached_raw_pointer, unsize: true, + reachable_via_deref: true, // this is always the final type from + // autoderef_via_deref }); None @@ -569,7 +661,7 @@ fn method_autoderef_steps<'tcx>( MethodAutoderefStepsResult { steps: tcx.arena.alloc_from_iter(steps), opt_bad_ty: opt_bad_ty.map(|ty| &*tcx.arena.alloc(ty)), - reached_recursion_limit: autoderef.reached_recursion_limit(), + reached_recursion_limit, } } @@ -600,7 +692,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { private_candidates: Vec::new(), private_candidate: Cell::new(None), static_candidates: RefCell::new(Vec::new()), - unsatisfied_predicates: RefCell::new(Vec::new()), scope_expr_id, is_suggestion, } @@ -613,7 +704,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.private_candidates.clear(); self.private_candidate.set(None); self.static_candidates.borrow_mut().clear(); - self.unsatisfied_predicates.borrow_mut().clear(); } /// When we're looking up a method by path (UFCS), we relate the receiver @@ -652,12 +742,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn assemble_inherent_candidates(&mut self) { for step in self.steps.iter() { - self.assemble_probe(&step.self_ty); + self.assemble_probe(&step.self_ty, step.autoderefs); } } #[instrument(level = "debug", skip(self))] - fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) { + fn assemble_probe( + &mut self, + self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>, + receiver_steps: usize, + ) { let raw_self_ty = self_ty.value.value; match *raw_self_ty.kind() { ty::Dynamic(data, ..) if let Some(p) = data.principal() => { @@ -682,22 +776,31 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.fcx.instantiate_canonical(self.span, self_ty); self.assemble_inherent_candidates_from_object(generalized_self_ty); - self.assemble_inherent_impl_candidates_for_type(p.def_id()); + self.assemble_inherent_impl_candidates_for_type(p.def_id(), receiver_steps); if self.tcx.has_attr(p.def_id(), sym::rustc_has_incoherent_inherent_impls) { - self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty); + self.assemble_inherent_candidates_for_incoherent_ty( + raw_self_ty, + receiver_steps, + ); } } ty::Adt(def, _) => { let def_id = def.did(); - self.assemble_inherent_impl_candidates_for_type(def_id); + self.assemble_inherent_impl_candidates_for_type(def_id, receiver_steps); if self.tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls) { - self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty); + self.assemble_inherent_candidates_for_incoherent_ty( + raw_self_ty, + receiver_steps, + ); } } ty::Foreign(did) => { - self.assemble_inherent_impl_candidates_for_type(did); + self.assemble_inherent_impl_candidates_for_type(did, receiver_steps); if self.tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) { - self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty); + self.assemble_inherent_candidates_for_incoherent_ty( + raw_self_ty, + receiver_steps, + ); } } ty::Param(p) => { @@ -714,29 +817,35 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { | ty::RawPtr(_, _) | ty::Ref(..) | ty::Never - | ty::Tuple(..) => self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty), + | ty::Tuple(..) => { + self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps) + } _ => {} } } - fn assemble_inherent_candidates_for_incoherent_ty(&mut self, self_ty: Ty<'tcx>) { + fn assemble_inherent_candidates_for_incoherent_ty( + &mut self, + self_ty: Ty<'tcx>, + receiver_steps: usize, + ) { let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else { bug!("unexpected incoherent type: {:?}", self_ty) }; for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter() { - self.assemble_inherent_impl_probe(impl_def_id); + self.assemble_inherent_impl_probe(impl_def_id, receiver_steps); } } - fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) { + fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId, receiver_steps: usize) { let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter(); for &impl_def_id in impl_def_ids { - self.assemble_inherent_impl_probe(impl_def_id); + self.assemble_inherent_impl_probe(impl_def_id, receiver_steps); } } #[instrument(level = "debug", skip(self))] - fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) { + fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId, receiver_steps: usize) { if !self.impl_dups.insert(impl_def_id) { return; // already visited } @@ -750,7 +859,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.push_candidate( Candidate { item, - kind: InherentImplCandidate(impl_def_id), + kind: InherentImplCandidate { impl_def_id, receiver_steps }, import_ids: smallvec![], }, true, @@ -989,7 +1098,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn pick(mut self) -> PickResult<'tcx> { assert!(self.method_name.is_some()); - if let Some(r) = self.pick_core() { + let mut unsatisfied_predicates = Vec::new(); + + if let Some(r) = self.pick_core(&mut unsatisfied_predicates) { return r; } @@ -1009,7 +1120,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let static_candidates = std::mem::take(self.static_candidates.get_mut()); let private_candidate = self.private_candidate.take(); - let unsatisfied_predicates = std::mem::take(self.unsatisfied_predicates.get_mut()); // things failed, so lets look at all traits, for diagnostic purposes now: self.reset(); @@ -1019,7 +1129,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.assemble_extension_candidates_for_all_traits(); - let out_of_scope_traits = match self.pick_core() { + let out_of_scope_traits = match self.pick_core(&mut Vec::new()) { Some(Ok(p)) => vec![p.item.container_id(self.tcx)], Some(Err(MethodError::Ambiguity(v))) => v .into_iter() @@ -1054,17 +1164,48 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { })) } - fn pick_core(&self) -> Option> { + fn pick_core( + &self, + unsatisfied_predicates: &mut Vec<( + ty::Predicate<'tcx>, + Option>, + Option>, + )>, + ) -> Option> { // Pick stable methods only first, and consider unstable candidates if not found. - self.pick_all_method(Some(&mut vec![])).or_else(|| self.pick_all_method(None)) + self.pick_all_method(&mut PickDiagHints { + // This first cycle, maintain a list of unstable candidates which + // we encounter. This will end up in the Pick for diagnostics. + unstable_candidates: Some(Vec::new()), + // Contribute to the list of unsatisfied predicates which may + // also be used for diagnostics. + unsatisfied_predicates, + }) + .or_else(|| { + self.pick_all_method(&mut PickDiagHints { + // On the second search, don't provide a special list of unstable + // candidates. This indicates to the picking code that it should + // in fact include such unstable candidates in the actual + // search. + unstable_candidates: None, + // And there's no need to duplicate ourselves in the + // unsatisifed predicates list. Provide a throwaway list. + unsatisfied_predicates: &mut Vec::new(), + }) + }) } - fn pick_all_method( + fn pick_all_method<'b>( &self, - mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, + pick_diag_hints: &mut PickDiagHints<'b, 'tcx>, ) -> Option> { + let track_unstable_candidates = pick_diag_hints.unstable_candidates.is_some(); self.steps .iter() + // At this point we're considering the types to which the receiver can be converted, + // so we want to follow the `Deref` chain not the `Receiver` chain. Filter out + // steps which can only be reached by following the (longer) `Receiver` chain. + .filter(|step| step.reachable_via_deref) .filter(|step| { debug!("pick_all_method: step={:?}", step); // skip types that are from a type error or that would require dereferencing @@ -1082,40 +1223,188 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .unwrap_or_else(|_| { span_bug!(self.span, "{:?} was applicable but now isn't?", step.self_ty) }); - self.pick_by_value_method(step, self_ty, unstable_candidates.as_deref_mut()) - .or_else(|| { - self.pick_autorefd_method( - step, - self_ty, - hir::Mutability::Not, - unstable_candidates.as_deref_mut(), - ) - .or_else(|| { - self.pick_autorefd_method( + + let by_value_pick = self.pick_by_value_method(step, self_ty, pick_diag_hints); + + // Check for shadowing of a by-reference method by a by-value method (see comments on check_for_shadowing) + if let Some(by_value_pick) = by_value_pick { + if let Ok(by_value_pick) = by_value_pick.as_ref() { + if by_value_pick.kind == PickKind::InherentImplPick { + if let Err(e) = self.check_for_shadowed_autorefd_method( + by_value_pick, step, self_ty, - hir::Mutability::Mut, - unstable_candidates.as_deref_mut(), - ) - }) - .or_else(|| { - self.pick_const_ptr_method( + hir::Mutability::Not, + track_unstable_candidates, + ) { + return Some(Err(e)); + } + if let Err(e) = self.check_for_shadowed_autorefd_method( + by_value_pick, step, self_ty, - unstable_candidates.as_deref_mut(), - ) - }) - .or_else(|| { - self.pick_reborrow_pin_method( + hir::Mutability::Mut, + track_unstable_candidates, + ) { + return Some(Err(e)); + } + } + } + return Some(by_value_pick); + } + + let autoref_pick = self.pick_autorefd_method( + step, + self_ty, + hir::Mutability::Not, + pick_diag_hints, + None, + ); + // 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() { + // 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, - unstable_candidates.as_deref_mut(), - ) - }) - }) + hir::Mutability::Mut, + track_unstable_candidates, + ) { + return Some(Err(e)); + } + } + } + return Some(autoref_pick); + } + + // Note that no shadowing errors are produced from here on, + // as we consider const ptr methods. + // We allow new methods that take *mut T to shadow + // methods which took *const T, so there is no entry in + // this list for the results of `pick_const_ptr_method`. + // The reason is that the standard pointer cast method + // (on a mutable pointer) always already shadows the + // cast method (on a const pointer). So, if we added + // `pick_const_ptr_method` to this method, the anti- + // shadowing algorithm would always complain about + // the conflict between *const::cast and *mut::cast. + // In practice therefore this does constrain us: + // we cannot add new + // self: *mut Self + // methods to types such as NonNull or anything else + // which implements Receiver, because this might in future + // shadow existing methods taking + // self: *const NonNull + // in the pointee. In practice, methods taking raw pointers + // are rare, and it seems that it should be easily possible + // to avoid such compatibility breaks. + // We also don't check for reborrowed pin methods which + // may be shadowed; these also seem unlikely to occur. + self.pick_autorefd_method( + step, + self_ty, + hir::Mutability::Mut, + pick_diag_hints, + None, + ) + .or_else(|| self.pick_const_ptr_method(step, self_ty, pick_diag_hints)) + .or_else(|| self.pick_reborrow_pin_method(step, self_ty, pick_diag_hints)) }) } + /// Check for cases where arbitrary self types allows shadowing + /// of methods that might be a compatibility break. Specifically, + /// we have something like: + /// ```ignore (illustrative) + /// struct A; + /// impl A { + /// fn foo(self: &NonNull) {} + /// // note this is by reference + /// } + /// ``` + /// then we've come along and added this method to `NonNull`: + /// ```ignore (illustrative) + /// fn foo(self) // note this is by value + /// ``` + /// Report an error in this case. + fn check_for_shadowed_autorefd_method( + &self, + possible_shadower: &Pick<'tcx>, + step: &CandidateStep<'tcx>, + self_ty: Ty<'tcx>, + mutbl: hir::Mutability, + track_unstable_candidates: bool, + ) -> Result<(), MethodError<'tcx>> { + // We don't want to remember any of the diagnostic hints from this + // shadow search, but we do need to provide Some/None for the + // 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(), + }; + // 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, + // 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) + def_id: possible_shadower.item.def_id, + }; + // A note on the autoderefs above. Within pick_by_value_method, an extra + // autoderef may be applied in order to reborrow a reference with + // a different lifetime. That seems as though it would break the + // logic of these constraints, since the number of autoderefs could + // no longer be used to identify the fundamental type of the receiver. + // However, this extra autoderef is applied only to by-value calls + // where the receiver is already a reference. So this situation would + // only occur in cases where the shadowing looks like this: + // ``` + // struct A; + // impl A { + // fn foo(self: &&NonNull) {} + // // note this is by DOUBLE reference + // } + // ``` + // then we've come along and added this method to `NonNull`: + // ``` + // fn foo(&self) // note this is by single reference + // ``` + // and the call is: + // ``` + // let bar = NonNull; + // let bar = &foo; + // bar.foo(); + // ``` + // In these circumstances, the logic is wrong, and we wouldn't spot + // the shadowing, because the autoderef-based maths wouldn't line up. + // This is a niche case and we can live without generating an error + // in the case of such shadowing. + let potentially_shadowed_pick = self.pick_autorefd_method( + step, + self_ty, + mutbl, + &mut pick_diag_hints, + Some(&pick_constraints), + ); + // 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() { + let sources = [possible_shadower, possible_shadowed] + .into_iter() + .map(|p| self.candidate_source_from_pick(p)) + .collect(); + return Err(MethodError::Ambiguity(sources)); + } + Ok(()) + } + /// For each type `T` in the step list, this attempts to find a method where /// the (transformed) self type is exactly `T`. We do however do one /// transformation on the adjustment: if we are passing a region pointer in, @@ -1126,13 +1415,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, - unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, + pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, ) -> Option> { if step.unsize { return None; } - self.pick_method(self_ty, unstable_candidates).map(|r| { + self.pick_method(self_ty, pick_diag_hints, None).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; @@ -1170,15 +1459,22 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, mutbl: hir::Mutability, - unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, + pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, + pick_constraints: Option<&PickConstraintsForShadowed>, ) -> Option> { let tcx = self.tcx; + if let Some(pick_constraints) = pick_constraints { + if !pick_constraints.may_shadow_based_on_autoderefs(step.autoderefs) { + return None; + } + } + // In general, during probing we erase regions. let region = tcx.lifetimes.re_erased; let autoref_ty = Ty::new_ref(tcx, region, self_ty, mutbl); - self.pick_method(autoref_ty, unstable_candidates).map(|r| { + self.pick_method(autoref_ty, pick_diag_hints, pick_constraints).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; pick.autoref_or_ptr_adjustment = @@ -1189,12 +1485,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } /// Looks for applicable methods if we reborrow a `Pin<&mut T>` as a `Pin<&T>`. - #[instrument(level = "debug", skip(self, step, unstable_candidates))] + #[instrument(level = "debug", skip(self, step, pick_diag_hints))] fn pick_reborrow_pin_method( &self, step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, - unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, + pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, ) -> Option> { if !self.tcx.features().pin_ergonomics() { return None; @@ -1215,7 +1511,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let region = self.tcx.lifetimes.re_erased; let autopin_ty = Ty::new_pinned_ref(self.tcx, region, inner_ty, hir::Mutability::Not); - self.pick_method(autopin_ty, unstable_candidates).map(|r| { + self.pick_method(autopin_ty, pick_diag_hints, None).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; pick.autoref_or_ptr_adjustment = @@ -1232,7 +1528,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, step: &CandidateStep<'tcx>, self_ty: Ty<'tcx>, - unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, + pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, ) -> Option> { // Don't convert an unsized reference to ptr if step.unsize { @@ -1244,7 +1540,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }; let const_ptr_ty = Ty::new_imm_ptr(self.tcx, ty); - self.pick_method(const_ptr_ty, unstable_candidates).map(|r| { + self.pick_method(const_ptr_ty, pick_diag_hints, None).map(|r| { r.map(|mut pick| { pick.autoderefs = step.autoderefs; pick.autoref_or_ptr_adjustment = Some(AutorefOrPtrAdjustment::ToConstPtr); @@ -1256,40 +1552,35 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn pick_method( &self, self_ty: Ty<'tcx>, - mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, + pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, + pick_constraints: Option<&PickConstraintsForShadowed>, ) -> Option> { debug!("pick_method(self_ty={})", self.ty_to_string(self_ty)); - let mut possibly_unsatisfied_predicates = Vec::new(); - for (kind, candidates) in [("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)] { debug!("searching {} candidates", kind); - let res = self.consider_candidates( - self_ty, - candidates, - &mut possibly_unsatisfied_predicates, - unstable_candidates.as_deref_mut(), - ); + let res = + self.consider_candidates(self_ty, candidates, pick_diag_hints, pick_constraints); if let Some(pick) = res { return Some(pick); } } if self.private_candidate.get().is_none() { - if let Some(Ok(pick)) = - self.consider_candidates(self_ty, &self.private_candidates, &mut vec![], None) - { + if let Some(Ok(pick)) = self.consider_candidates( + self_ty, + &self.private_candidates, + &mut PickDiagHints { + unstable_candidates: None, + unsatisfied_predicates: &mut vec![], + }, + None, + ) { self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id))); } } - - // `pick_method` may be called twice for the same self_ty if no stable methods - // match. Only extend once. - if unstable_candidates.is_some() { - self.unsatisfied_predicates.borrow_mut().extend(possibly_unsatisfied_predicates); - } None } @@ -1297,17 +1588,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, candidates: &[Candidate<'tcx>], - possibly_unsatisfied_predicates: &mut Vec<( - ty::Predicate<'tcx>, - Option>, - Option>, - )>, - mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>, + pick_diag_hints: &mut PickDiagHints<'_, 'tcx>, + pick_constraints: Option<&PickConstraintsForShadowed>, ) -> Option> { let mut applicable_candidates: Vec<_> = candidates .iter() + .filter(|candidate| { + pick_constraints + .map(|pick_constraints| pick_constraints.candidate_may_shadow(&candidate)) + .unwrap_or(true) + }) .map(|probe| { - (probe, self.consider_probe(self_ty, probe, possibly_unsatisfied_predicates)) + ( + probe, + self.consider_probe( + self_ty, + probe, + &mut pick_diag_hints.unsatisfied_predicates, + ), + ) }) .filter(|&(_, status)| status != ProbeResult::NoMatch) .collect(); @@ -1322,7 +1621,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - if let Some(uc) = &mut unstable_candidates { + if let Some(uc) = &mut pick_diag_hints.unstable_candidates { applicable_candidates.retain(|&(candidate, _)| { if let stability::EvalResult::Deny { feature, .. } = self.tcx.eval_stability(candidate.item.def_id, None, self.span, None) @@ -1340,10 +1639,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } applicable_candidates.pop().map(|(probe, status)| match status { - ProbeResult::Match => { - Ok(probe - .to_unadjusted_pick(self_ty, unstable_candidates.cloned().unwrap_or_default())) - } + ProbeResult::Match => Ok(probe.to_unadjusted_pick( + self_ty, + pick_diag_hints.unstable_candidates.clone().unwrap_or_default(), + )), ProbeResult::NoMatch | ProbeResult::BadReturnType => Err(MethodError::BadReturnType), }) } @@ -1372,6 +1671,7 @@ impl<'tcx> Pick<'tcx> { autoref_or_ptr_adjustment: _, self_ty, unstable_candidates: _, + receiver_steps: _, } = *self; self_ty != other.self_ty || def_id != other.item.def_id } @@ -1447,7 +1747,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { /// so do not use to make a decision that may lead to a successful compilation. fn candidate_source(&self, candidate: &Candidate<'tcx>, self_ty: Ty<'tcx>) -> CandidateSource { match candidate.kind { - InherentImplCandidate(_) => { + InherentImplCandidate { .. } => { CandidateSource::Impl(candidate.item.container_id(self.tcx)) } ObjectCandidate(_) | WhereClauseCandidate(_) => { @@ -1477,6 +1777,15 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + fn candidate_source_from_pick(&self, pick: &Pick<'tcx>) -> CandidateSource { + match pick.kind { + InherentImplPick => CandidateSource::Impl(pick.item.container_id(self.tcx)), + ObjectPick | WhereClausePick(_) | TraitPick => { + CandidateSource::Trait(pick.item.container_id(self.tcx)) + } + } + } + #[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)] fn consider_probe( &self, @@ -1501,7 +1810,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let (mut xform_self_ty, mut xform_ret_ty); match probe.kind { - InherentImplCandidate(impl_def_id) => { + InherentImplCandidate { impl_def_id, .. } => { let impl_args = self.fresh_args_for_item(self.span, impl_def_id); let impl_ty = self.tcx.type_of(impl_def_id).instantiate(self.tcx, impl_args); (xform_self_ty, xform_ret_ty) = @@ -1693,7 +2002,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // We don't normalize the other candidates for perf/backwards-compat reasons... // but `self.return_type` is only set on the diagnostic-path, so we // should be okay doing it here. - if !matches!(probe.kind, InherentImplCandidate(_)) { + if !matches!(probe.kind, InherentImplCandidate { .. }) { xform_ret_ty = ocx.normalize(&cause, self.param_env, xform_ret_ty); } @@ -1771,6 +2080,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { autoref_or_ptr_adjustment: None, self_ty, unstable_candidates: vec![], + receiver_steps: None, }) } @@ -1808,7 +2118,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { pcx.method_name = Some(method_name); pcx.assemble_inherent_candidates(); pcx.assemble_extension_candidates_for_all_traits(); - pcx.pick_core().and_then(|pick| pick.ok()).map(|pick| pick.item) + pcx.pick_core(&mut Vec::new()).and_then(|pick| pick.ok()).map(|pick| pick.item) }) .collect(); @@ -2042,7 +2352,7 @@ impl<'tcx> Candidate<'tcx> { Pick { item: self.item, kind: match self.kind { - InherentImplCandidate(_) => InherentImplPick, + InherentImplCandidate { .. } => InherentImplPick, ObjectCandidate(_) => ObjectPick, TraitCandidate(_) => TraitPick, WhereClauseCandidate(trait_ref) => { @@ -2064,6 +2374,10 @@ impl<'tcx> Candidate<'tcx> { autoref_or_ptr_adjustment: None, self_ty, unstable_candidates, + receiver_steps: match self.kind { + InherentImplCandidate { receiver_steps, .. } => Some(receiver_steps), + _ => None, + }, } } } diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index eeed5118592bc..f049da95f29ae 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -149,11 +149,21 @@ pub struct CandidateStep<'tcx> { /// `foo.by_raw_ptr()` will work and `foo.by_ref()` won't. pub from_unsafe_deref: bool, pub unsize: bool, + /// We will generate CandidateSteps which are reachable via a chain + /// of following `Receiver`. The first 'n' of those will be reachable + /// by following a chain of 'Deref' instead (since there's a blanket + /// implementation of Receiver for Deref). + /// We use the entire set of steps when identifying method candidates + /// (e.g. identifying relevant `impl` blocks) but only those that are + /// reachable via Deref when examining what the receiver type can + /// be converted into by autodereffing. + pub reachable_via_deref: bool, } #[derive(Copy, Clone, Debug, HashStable)] pub struct MethodAutoderefStepsResult<'tcx> { - /// The valid autoderef steps that could be found. + /// The valid autoderef steps that could be found by following a chain + /// of `Receiver` or `Deref` trait implementations. pub steps: &'tcx [CandidateStep<'tcx>], /// If Some(T), a type autoderef reported an error on. pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>, diff --git a/tests/ui/async-await/inference_var_self_argument.stderr b/tests/ui/async-await/inference_var_self_argument.stderr index 7b7b3dbc757f1..a33c5f7b07dca 100644 --- a/tests/ui/async-await/inference_var_self_argument.stderr +++ b/tests/ui/async-await/inference_var_self_argument.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&dyn Foo` 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`) + = 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[E0038]: the trait `Foo` cannot be made into an object --> $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..f4db949a5f430 100644 --- a/tests/ui/async-await/issue-66312.stderr +++ b/tests/ui/async-await/issue-66312.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `T` 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`) + = 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[E0308]: mismatched types --> $DIR/issue-66312.rs:9:8 diff --git a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr index 3bb93cf2ea0b1..0c5b8a4d3b685 100644 --- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types-pointers.stderr @@ -7,7 +7,7 @@ LL | fn foo(self: *const Self) {} = note: see issue #44874 for more information = help: add `#![feature(arbitrary_self_types_pointers)]` 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error[E0658]: `*mut Bar` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:12:18 @@ -18,7 +18,7 @@ LL | fn bar(self: *mut Self) {} = note: see issue #44874 for more information = help: add `#![feature(arbitrary_self_types_pointers)]` 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature --> $DIR/feature-gate-arbitrary-self-types-pointers.rs:2:18 @@ -29,7 +29,7 @@ LL | fn foo(self: *const Self); = note: see issue #44874 for more information = help: add `#![feature(arbitrary_self_types_pointers)]` 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error: aborting due to 3 previous errors 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 7f0e02c91f8f8..3ffba533d63fc 100644 --- a/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr +++ b/tests/ui/feature-gates/feature-gate-arbitrary-self-types.stderr @@ -7,7 +7,7 @@ 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` 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 @@ -18,7 +18,7 @@ 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` 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 @@ -29,7 +29,7 @@ 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error: aborting due to 3 previous errors diff --git a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr index 856e059533139..3eb87adb33adc 100644 --- a/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr +++ b/tests/ui/feature-gates/feature-gate-arbitrary_self_types-raw-pointer.stderr @@ -7,7 +7,7 @@ LL | fn foo(self: *const Self) {} = note: see issue #44874 for more information = help: add `#![feature(arbitrary_self_types_pointers)]` 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error[E0658]: `*const ()` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:14:18 @@ -18,7 +18,7 @@ LL | fn bar(self: *const Self) {} = note: see issue #44874 for more information = help: add `#![feature(arbitrary_self_types_pointers)]` 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature --> $DIR/feature-gate-arbitrary_self_types-raw-pointer.rs:9:18 @@ -29,7 +29,7 @@ LL | fn bar(self: *const Self); = note: see issue #44874 for more information = help: add `#![feature(arbitrary_self_types_pointers)]` 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error: aborting due to 3 previous errors 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..eb9e51a04c394 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 @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Cell<&Self>` 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`) + = 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 diff --git a/tests/ui/issues/issue-56806.stderr b/tests/ui/issues/issue-56806.stderr index ec50d863758db..4b0a59fe12def 100644 --- a/tests/ui/issues/issue-56806.stderr +++ b/tests/ui/issues/issue-56806.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Box<(dyn Trait + 'static)>` 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`) + = 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 diff --git a/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr b/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr index 3babf63347c35..46804642af88e 100644 --- a/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr +++ b/tests/ui/lifetimes/could-not-resolve-issue-121503.stderr @@ -7,7 +7,7 @@ LL | async fn box_ref_Struct(self: Box) -> &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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error: aborting due to 1 previous error diff --git a/tests/ui/methods/call_method_unknown_referent.rs b/tests/ui/methods/call_method_unknown_referent.rs new file mode 100644 index 0000000000000..b01e2d80f7f80 --- /dev/null +++ b/tests/ui/methods/call_method_unknown_referent.rs @@ -0,0 +1,48 @@ +//@ edition: 2018 + +#![feature(arbitrary_self_types)] + +// tests that the referent type of a reference must be known to call methods on it + +struct SmartPtr(T); + +impl core::ops::Receiver for SmartPtr { + type Target = T; +} + +impl SmartPtr { + fn foo(&self) {} +} + +fn main() { + let val = 1_u32; + let ptr = &val; + let _a: i32 = (ptr as &_).read(); + //~^ ERROR type annotations needed + + // Same again, but with a smart pointer type + let val2 = 1_u32; + let rc = std::rc::Rc::new(val2); + let _b = (rc as std::rc::Rc<_>).read(); + //~^ ERROR type annotations needed + + // Same again, but with a smart pointer type + let ptr = SmartPtr(val); + + // We can call unambiguous outer-type methods on this + (ptr as SmartPtr<_>).foo(); + // ... but we can't follow the Receiver chain to the inner type + // because we end up with _. + + // Because SmartPtr implements Receiver, it's arguable which of the + // following two diagnostics we'd want in this case: + // (a) "type annotations needed" (because the inner type is _) + // (b) "no method named `read` found for struct `SmartPtr`" + // (ignoring the fact that there might have been methods on the + // inner type, had it not been _) + // At present we produce error type (b), which is necessary because + // our resolution logic needs to be able to call methods such as foo() + // on the outer type even if the inner type is ambiguous. + let _c = (ptr as SmartPtr<_>).read(); + //~^ ERROR no method named `read` found for struct `SmartPtr` +} diff --git a/tests/ui/methods/call_method_unknown_referent.stderr b/tests/ui/methods/call_method_unknown_referent.stderr new file mode 100644 index 0000000000000..748b02b52b577 --- /dev/null +++ b/tests/ui/methods/call_method_unknown_referent.stderr @@ -0,0 +1,29 @@ +error[E0282]: type annotations needed + --> $DIR/call_method_unknown_referent.rs:20:31 + | +LL | let _a: i32 = (ptr as &_).read(); + | ^^^^ cannot infer type + +error[E0282]: type annotations needed + --> $DIR/call_method_unknown_referent.rs:26:37 + | +LL | let _b = (rc as std::rc::Rc<_>).read(); + | ^^^^ cannot infer type + +error[E0599]: no method named `read` found for struct `SmartPtr` in the current scope + --> $DIR/call_method_unknown_referent.rs:46:35 + | +LL | struct SmartPtr(T); + | ------------------ method `read` not found for this struct +... +LL | let _c = (ptr as SmartPtr<_>).read(); + | ^^^^ method not found in `SmartPtr<_>` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `read`, perhaps you need to implement it: + candidate #1: `std::io::Read` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0282, E0599. +For more information about an error, try `rustc --explain E0282`. diff --git a/tests/ui/methods/call_method_unknown_referent2.rs b/tests/ui/methods/call_method_unknown_referent2.rs new file mode 100644 index 0000000000000..b1615bd8d4414 --- /dev/null +++ b/tests/ui/methods/call_method_unknown_referent2.rs @@ -0,0 +1,24 @@ +//@ edition: 2018 +//@ run-pass + +#![feature(arbitrary_self_types)] + +// tests that the referent type of a reference must be known to call methods on it + +struct SmartPtr(T); + +impl core::ops::Receiver for SmartPtr { + type Target = T; +} + +impl SmartPtr { + fn foo(&self) -> usize { 3 } +} + +fn main() { + let val = 1_u32; + let ptr = SmartPtr(val); + // Ensure calls to outer methods work even if inner methods can't be + // resolved due to the type variable + assert_eq!((ptr as SmartPtr<_>).foo(), 3); +} 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 new file mode 100644 index 0000000000000..495d261c549ca --- /dev/null +++ b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.rs @@ -0,0 +1,64 @@ +#![feature(arbitrary_self_types)] + +use std::ops::{Receiver, Deref}; + +struct SmartPtr<'a, T: ?Sized>(&'a T); + +impl<'a, T: ?Sized> Deref for SmartPtr<'a, T> { + type Target = T; + fn deref(&self) -> &Self::Target { + self.0 + } +} + +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> { +} + +struct Foo(u32); +impl Foo { + fn a>(self: R) -> u32 { + //~^ ERROR invalid generic `self` parameter type: `R` + 2 + } + fn b>(self: R) -> u32 { + //~^ ERROR invalid generic `self` parameter type: `R` + self.0 + } + 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` + self.0 + } +} + +fn main() { + let foo = Foo(1); + assert_eq!((&foo).a::<&Foo>(), 2); + assert_eq!((&foo).b::<&Foo>(), 1); + assert_eq!((&foo).a(), 2); + assert_eq!((&foo).b(), 1); + assert_eq!((&foo).c(), 3); + assert_eq!((&foo).d(), 1); + assert_eq!(foo.a::<&Foo>(), 2); + //~^ ERROR mismatched types + assert_eq!(foo.b::<&Foo>(), 1); + //~^ ERROR mismatched types + let smart_ptr = SmartPtr(&foo); + assert_eq!(smart_ptr.a(), 2); + assert_eq!(smart_ptr.b(), 1); + assert_eq!(smart_ptr.c(), 3); + assert_eq!(smart_ptr.d(), 1); + assert_eq!(smart_ptr.a::<&Foo>(), 2); + //~^ ERROR mismatched types + assert_eq!(smart_ptr.b::<&Foo>(), 1); + //~^ ERROR mismatched types +} 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 new file mode 100644 index 0000000000000..9af2a08f3712d --- /dev/null +++ b/tests/ui/self/arbitrary-self-from-method-substs-with-receiver.stderr @@ -0,0 +1,70 @@ +error[E0801]: invalid generic `self` parameter type: `R` + --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:25:42 + | +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 + | +LL | fn b>(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 + | +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 + | +LL | fn d(self: impl Deref) -> 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 + | +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 + | +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 + | +LL | assert_eq!(smart_ptr.a::<&Foo>(), 2); + | ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>` + | + = note: expected reference `&Foo` + found struct `SmartPtr<'_, Foo, >` + +error[E0308]: mismatched types + --> $DIR/arbitrary-self-from-method-substs-with-receiver.rs:62:16 + | +LL | assert_eq!(smart_ptr.b::<&Foo>(), 1); + | ^^^^^^^^^ expected `&Foo`, found `SmartPtr<'_, Foo>` + | + = note: expected reference `&Foo` + found struct `SmartPtr<'_, Foo, >` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0308, E0801. +For more information about an error, try `rustc --explain E0308`. 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 5dc3a0b023472..7cf9c9a3afd4d 100644 --- a/tests/ui/self/arbitrary-self-from-method-substs.default.stderr +++ b/tests/ui/self/arbitrary-self-from-method-substs.default.stderr @@ -61,7 +61,7 @@ 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` 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 @@ -72,7 +72,7 @@ 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`, `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`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error[E0271]: type mismatch resolving `::Receiver == Foo` --> $DIR/arbitrary-self-from-method-substs.rs:92:9 diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr index c75165d9f8e27..0469aca27dc81 100644 --- a/tests/ui/self/arbitrary-self-opaque.stderr +++ b/tests/ui/self/arbitrary-self-opaque.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar` 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`) + = 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: item does not constrain `Bar::{opaque#0}`, but has it in its signature --> $DIR/arbitrary-self-opaque.rs:7:8 diff --git a/tests/ui/self/arbitrary_self_types_by_value_reborrow.rs b/tests/ui/self/arbitrary_self_types_by_value_reborrow.rs new file mode 100644 index 0000000000000..de4db1b9afec7 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_by_value_reborrow.rs @@ -0,0 +1,69 @@ +//@ run-pass + +#![feature(arbitrary_self_types)] +#![allow(dead_code)] + +// With arbitrary self types v2, we show an error if there are +// multiple contenders for a method call in an inner and outer type. +// The goal is to avoid any possibility of confusion by a new +// 'shadowing' method calling a 'shadowed' method. +// However, there are niche circumstances where this +// algorithm doesn't quite work, due to reborrows to get a different +// lifetime. The test below explicitly tests those circumstances to ensure +// the behavior is as expected, even if it's not 100% desirable. They're +// very niche circumstances. + +#[derive(Debug, PartialEq)] +enum Callee { + INNER, + OUTER +} + +struct MyNonNull(T); + +impl std::ops::Receiver for MyNonNull { + type Target = T; +} + +struct A; +impl A { + fn foo(self: MyNonNull) -> Callee { + Callee::INNER + } + + fn bar(self: &MyNonNull) -> Callee { + Callee::INNER + } + + fn baz(self: &&MyNonNull) -> Callee { + // note this is by DOUBLE reference + Callee::INNER + } +} + +impl MyNonNull { + fn foo(&self) -> Callee{ + Callee::OUTER + } + + fn bar(&self) -> Callee{ + Callee::OUTER + } + + fn baz(&self) -> Callee{ + Callee::OUTER + } +} + +fn main() { + // The normal deshadowing case. Does not compile. + // assert_eq!(MyNonNull(A).foo(), Callee::INNER); + + // Similarly, does not compile. + //assert_eq!(MyNonNull(A).bar(), Callee::INNER); + + // The double-reference case. + // We call the newly-added outer type method. + // Not ideal but very niche so we accept it. + assert_eq!(MyNonNull(A).baz(), Callee::OUTER); +} diff --git a/tests/ui/self/arbitrary_self_types_generic_over_receiver.rs b/tests/ui/self/arbitrary_self_types_generic_over_receiver.rs new file mode 100644 index 0000000000000..8ccda9368addf --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_generic_over_receiver.rs @@ -0,0 +1,23 @@ +#![feature(arbitrary_self_types)] + +use std::ops::{Receiver, Deref}; + +struct Foo(u32); +impl Foo { + fn a(self: impl Receiver) -> u32 { + //~^ ERROR invalid generic `self` parameter type: `impl Receiver` + 3 + } + fn b(self: impl Deref) -> u32 { + //~^ ERROR invalid generic `self` parameter type: `impl Deref` + self.0 + } +} + +fn main() { + let foo = Foo(1); + foo.a(); + //~^ ERROR the trait bound + foo.b(); + //~^ ERROR the trait bound +} diff --git a/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr new file mode 100644 index 0000000000000..2da3925341e2f --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr @@ -0,0 +1,59 @@ +error[E0801]: invalid generic `self` parameter type: `impl Receiver` + --> $DIR/arbitrary_self_types_generic_over_receiver.rs:7:16 + | +LL | fn a(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_types_generic_over_receiver.rs:11:16 + | +LL | fn b(self: impl Deref) -> 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[E0277]: the trait bound `Foo: std::ops::Receiver` is not satisfied + --> $DIR/arbitrary_self_types_generic_over_receiver.rs:19:9 + | +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 + | +LL | fn a(self: impl Receiver) -> u32 { + | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::a` +help: consider borrowing here + | +LL | &foo.a(); + | + +LL | &mut foo.a(); + | ++++ + +error[E0277]: the trait bound `Foo: Deref` is not satisfied + --> $DIR/arbitrary_self_types_generic_over_receiver.rs:21:9 + | +LL | foo.b(); + | ^ the trait `Deref` is not implemented for `Foo` + | +note: required by a bound in `Foo::b` + --> $DIR/arbitrary_self_types_generic_over_receiver.rs:11:21 + | +LL | fn b(self: impl Deref) -> u32 { + | ^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::b` +help: consider borrowing here + | +LL | &foo.b(); + | + +LL | &mut foo.b(); + | ++++ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0277, E0801. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/self/arbitrary_self_types_generic_receiver.rs b/tests/ui/self/arbitrary_self_types_generic_receiver.rs new file mode 100644 index 0000000000000..0739fb778b605 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_generic_receiver.rs @@ -0,0 +1,50 @@ +#![feature(arbitrary_self_types)] + +struct PtrA(T); + +impl core::ops::Receiver for PtrA { + type Target = T; +} + +struct PtrB(T); + +trait SomePtr: core::ops::Receiver::SomeTarget> { + type SomeTarget; +} + +impl SomePtr for PtrB { + type SomeTarget = T; +} + +impl core::ops::Receiver for PtrB { + type Target = T; +} + +struct Content; + +impl Content { + fn a>(self: &R) {} + //~^ ERROR invalid generic + fn b>(self: &mut R) {} + //~^ ERROR invalid generic + fn c>(self: R) {} + //~^ ERROR invalid generic + fn d>(self: R) {} + //~^ ERROR invalid generic + fn e(self: impl SomePtr) {} + //~^ ERROR invalid generic +} + +fn main() { + PtrA(Content).a(); + PtrA(Content).b(); + PtrA(Content).c(); + std::rc::Rc::new(Content).a(); + std::rc::Rc::new(Content).b(); + std::rc::Rc::new(Content).c(); + PtrB(Content).a(); + PtrB(Content).b(); + PtrB(Content).c(); + PtrB(Content).d(); + PtrB(Content).e(); +} diff --git a/tests/ui/self/arbitrary_self_types_generic_receiver.stderr b/tests/ui/self/arbitrary_self_types_generic_receiver.stderr new file mode 100644 index 0000000000000..788c55ea2f1c3 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_generic_receiver.stderr @@ -0,0 +1,48 @@ +error[E0801]: invalid generic `self` parameter type: `&R` + --> $DIR/arbitrary_self_types_generic_receiver.rs:26:53 + | +LL | fn a>(self: &R) {} + | ^^ + | + = 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_types_generic_receiver.rs:28:53 + | +LL | fn b>(self: &mut R) {} + | ^^^^^^ + | + = 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_types_generic_receiver.rs:30:53 + | +LL | fn c>(self: R) {} + | ^ + | + = 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_types_generic_receiver.rs:32:45 + | +LL | fn d>(self: R) {} + | ^ + | + = 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 SomePtr` + --> $DIR/arbitrary_self_types_generic_receiver.rs:34:16 + | +LL | fn e(self: impl SomePtr) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = 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: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0801`. diff --git a/tests/ui/self/arbitrary_self_types_lifetime_elision.rs b/tests/ui/self/arbitrary_self_types_lifetime_elision.rs new file mode 100644 index 0000000000000..fd645c1013b64 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_lifetime_elision.rs @@ -0,0 +1,27 @@ +//@ run-pass + +#![feature(arbitrary_self_types)] + +#[derive(Clone)] +struct SmartPtr<'a, T: ?Sized>(&'a T); + +impl<'a, T: ?Sized> std::ops::Receiver for SmartPtr<'a, T> { + type Target = T; +} + +#[derive(Clone)] +struct MyType; + +impl MyType { + fn m(self: SmartPtr) {} + fn n(self: SmartPtr<'_, Self>) {} + fn o<'a>(self: SmartPtr<'a, Self>) {} +} + +fn main() { + let a = MyType; + let ptr = SmartPtr(&a); + ptr.clone().m(); + ptr.clone().n(); + ptr.o(); +} diff --git a/tests/ui/self/arbitrary_self_types_no_generics.rs b/tests/ui/self/arbitrary_self_types_no_generics.rs new file mode 100644 index 0000000000000..8a6f57418829e --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_no_generics.rs @@ -0,0 +1,32 @@ +//@ run-pass + +#![feature(arbitrary_self_types)] + +pub struct A; + +impl A { + pub fn f(self: B) -> i32 { 1 } +} + +pub struct B(A); + +impl core::ops::Receiver for B { + type Target = A; +} + +struct C; + +struct D; + +impl C { + fn weird(self: D) -> i32 { 3 } +} + +impl core::ops::Receiver for D { + type Target = C; +} + +fn main() { + assert_eq!(B(A).f(), 1); + assert_eq!(D.weird(), 3); +} diff --git a/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs new file mode 100644 index 0000000000000..26e48f69d23ea --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.rs @@ -0,0 +1,38 @@ +#![feature(arbitrary_self_types)] + +use std::rc::Rc; + +struct Foo; + +struct CppRef(T); + +impl std::ops::Receiver for CppRef { + type Target = T; +} + +impl Foo{ + fn frobnicate_self(self) {} + fn frobnicate_ref(&self) {} + fn frobnicate_cpp_ref(self: CppRef) {} +} + +fn main() { + let foo_rc = Rc::new(Foo); + + // this compiles fine, and desugars to `Foo::frobnicate_ref(&*foo_rc)` + foo_rc.frobnicate_ref(); + + let foo_cpp_ref = CppRef(Foo); + + // should not compile because it would desugar to `Foo::frobnicate_ref(&*foo_cpp_ref)` + // and you can't deref a CppRef + foo_cpp_ref.frobnicate_ref(); + //~^ ERROR no method named + + foo_cpp_ref.frobnicate_self(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)` + //~^ ERROR no method named + + // should compile, because we're not dereffing the CppRef + // desugars to `Foo::frobnicate_cpp_ref(foo_cpp_ref)` + foo_cpp_ref.frobnicate_cpp_ref(); +} diff --git a/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr new file mode 100644 index 0000000000000..4c0ab88493e94 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr @@ -0,0 +1,39 @@ +error[E0599]: no method named `frobnicate_ref` found for struct `CppRef` in the current scope + --> $DIR/arbitrary_self_types_not_allow_call_with_no_deref.rs:29:17 + | +LL | struct CppRef(T); + | ---------------- method `frobnicate_ref` not found for this struct +... +LL | foo_cpp_ref.frobnicate_ref(); + | ^^^^^^^^^^^^^^ + | +help: one of the expressions' fields has a method of the same name + | +LL | foo_cpp_ref.0.frobnicate_ref(); + | ++ +help: there is a method `frobnicate_cpp_ref` with a similar name + | +LL | foo_cpp_ref.frobnicate_cpp_ref(); + | ~~~~~~~~~~~~~~~~~~ + +error[E0599]: no method named `frobnicate_self` found for struct `CppRef` in the current scope + --> $DIR/arbitrary_self_types_not_allow_call_with_no_deref.rs:32:17 + | +LL | struct CppRef(T); + | ---------------- method `frobnicate_self` not found for this struct +... +LL | foo_cpp_ref.frobnicate_self(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)` + | ^^^^^^^^^^^^^^^ + | +help: one of the expressions' fields has a method of the same name + | +LL | foo_cpp_ref.0.frobnicate_self(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)` + | ++ +help: there is a method `frobnicate_cpp_ref` with a similar name + | +LL | foo_cpp_ref.frobnicate_cpp_ref(); // would desugar to `Foo::frobnicate_self(*foo_cpp_ref)` + | ~~~~~~~~~~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/self/arbitrary_self_types_recursive_receiver.rs b/tests/ui/self/arbitrary_self_types_recursive_receiver.rs new file mode 100644 index 0000000000000..f3e7f96d7c4de --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_recursive_receiver.rs @@ -0,0 +1,32 @@ +//@ run-pass +#![feature(arbitrary_self_types)] + +struct MyNonNull(*const T); + +impl std::ops::Receiver for MyNonNull { + type Target = T; +} + +#[allow(dead_code)] +impl MyNonNull { + fn foo(&self) -> *const U { + self.cast::().bar() + } + fn cast(&self) -> MyNonNull { + MyNonNull(self.0 as *const U) + } + fn bar(&self) -> *const T { + self.0 + } +} + +#[repr(transparent)] +struct Foo(usize); +#[repr(transparent)] +struct Bar(usize); + +fn main() { + let a = Foo(3); + let ptr = MyNonNull(&a); + let _bar_ptr: *const Bar = ptr.foo(); +} diff --git a/tests/ui/self/arbitrary_self_types_shadowing_val_constptr.rs b/tests/ui/self/arbitrary_self_types_shadowing_val_constptr.rs new file mode 100644 index 0000000000000..2b718cb0454ce --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_shadowing_val_constptr.rs @@ -0,0 +1,33 @@ +//@ run-pass + +#![feature(arbitrary_self_types)] +#![feature(arbitrary_self_types_pointers)] + +pub struct A; + +impl A { + pub fn f(self: *const MyNonNull) -> i32 { 1 } +} + +pub struct MyNonNull(T); + +impl core::ops::Receiver for MyNonNull { + type Target = T; +} + +impl MyNonNull { + // Imagine this a NEW method in B shadowing an EXISTING + // method in A. + pub fn f(self: *mut Self) -> i32 { + 2 + } +} + +fn main() { + let mut b = MyNonNull(A); + let b = &mut b; + let b = b as *mut MyNonNull; + // We actually allow the shadowing in the case of const vs mut raw + // pointer receivers. + assert_eq!(b.f(), 2); +} diff --git a/tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs b/tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs new file mode 100644 index 0000000000000..cebf0ea7cba93 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_struct_receiver_trait.rs @@ -0,0 +1,31 @@ +//@ run-pass +#![feature(arbitrary_self_types)] + +use std::ops::Receiver; + +struct SmartPtr(T); + +impl Receiver for SmartPtr { + type Target = T; +} + +struct Foo { + x: i32, + y: i32, +} + +impl Foo { + fn x(self: &SmartPtr) -> i32 { + self.0.x + } + + fn y(self: SmartPtr) -> i32 { + self.0.y + } +} + +fn main() { + let foo = SmartPtr(Foo {x: 3, y: 4}); + assert_eq!(3, foo.x()); + assert_eq!(4, foo.y()); +} diff --git a/tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs b/tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs new file mode 100644 index 0000000000000..9c0402da0befe --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_trait_receiver_trait.rs @@ -0,0 +1,25 @@ +//@ run-pass +#![feature(arbitrary_self_types)] +#![allow(unused_allocation)] + +struct SmartPtr(T); + +impl std::ops::Receiver for SmartPtr { + type Target = T; +} + +trait Trait { + fn trait_method<'a>(self: &'a Box>) -> &'a [i32]; +} + +impl Trait for Vec { + fn trait_method<'a>(self: &'a Box>) -> &'a [i32] { + &(**self).0 + } +} + +fn main() { + let v = vec![1, 2, 3]; + + assert_eq!(&[1, 2, 3], Box::new(SmartPtr(v)).trait_method()); +} diff --git a/tests/ui/self/arbitrary_self_types_unshadowing.rs b/tests/ui/self/arbitrary_self_types_unshadowing.rs new file mode 100644 index 0000000000000..cd195654cc195 --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_unshadowing.rs @@ -0,0 +1,55 @@ +#![feature(arbitrary_self_types)] + +pub struct A; + +// The receiver of the potentially shadowed method +// precisely matches that of the shadower +impl A { + pub fn f(self: Wrapper) -> i32 { 1 } + pub fn g(self: &Wrapper) -> i32 { 2 } + pub fn h(self: &mut Wrapper) -> i32 { 3 } +} + +// The receiver of the potentially shadowed method is a reference +pub struct B; + +impl B { + pub fn f(self: &Wrapper) -> i32 { 9 } +} + +// The receiver of the potentially shadowed method is a mut reference + +pub struct C; + +impl C { + pub fn f(self: &mut Wrapper) -> i32 { 10 } + pub fn g(self: &mut Wrapper) -> i32 { 11 } +} + +pub struct Wrapper(T); + +impl core::ops::Receiver for Wrapper { + type Target = T; +} + +impl Wrapper { + pub fn f(self) -> i32 { 5 } + pub fn g(&self) -> i32 { 6 } + pub fn h(&mut self) -> i32 { 7 } +} + +fn main() { + assert_eq!(Wrapper(A).f(), 1); + //~^ ERROR: multiple applicable items in scope + assert_eq!(Wrapper(A).g(), 2); + //~^ ERROR: multiple applicable items in scope + assert_eq!(Wrapper(A).h(), 3); + //~^ ERROR: multiple applicable items in scope + let a = Wrapper(A); + assert_eq!(Wrapper(B).f(), 9); + //~^ ERROR: multiple applicable items in scope + assert_eq!(Wrapper(C).f(), 10); + //~^ ERROR: multiple applicable items in scope + assert_eq!(Wrapper(C).g(), 11); + //~^ ERROR: multiple applicable items in scope +} diff --git a/tests/ui/self/arbitrary_self_types_unshadowing.stderr b/tests/ui/self/arbitrary_self_types_unshadowing.stderr new file mode 100644 index 0000000000000..3a126c495c94d --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_unshadowing.stderr @@ -0,0 +1,105 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing.rs:42:27 + | +LL | assert_eq!(Wrapper(A).f(), 1); + | ^ multiple `f` found + | +note: candidate #1 is defined in an impl for the type `A` + --> $DIR/arbitrary_self_types_unshadowing.rs:8:5 + | +LL | pub fn f(self: Wrapper) -> i32 { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing.rs:36:5 + | +LL | pub fn f(self) -> i32 { 5 } + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing.rs:44:27 + | +LL | assert_eq!(Wrapper(A).g(), 2); + | ^ multiple `g` found + | +note: candidate #1 is defined in an impl for the type `A` + --> $DIR/arbitrary_self_types_unshadowing.rs:9:5 + | +LL | pub fn g(self: &Wrapper) -> i32 { 2 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing.rs:37:5 + | +LL | pub fn g(&self) -> i32 { 6 } + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing.rs:46:27 + | +LL | assert_eq!(Wrapper(A).h(), 3); + | ^ multiple `h` found + | +note: candidate #1 is defined in an impl for the type `A` + --> $DIR/arbitrary_self_types_unshadowing.rs:10:5 + | +LL | pub fn h(self: &mut Wrapper) -> i32 { 3 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing.rs:38:5 + | +LL | pub fn h(&mut self) -> i32 { 7 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing.rs:49:27 + | +LL | assert_eq!(Wrapper(B).f(), 9); + | ^ multiple `f` found + | +note: candidate #1 is defined in an impl for the type `B` + --> $DIR/arbitrary_self_types_unshadowing.rs:17:5 + | +LL | pub fn f(self: &Wrapper) -> i32 { 9 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing.rs:36:5 + | +LL | pub fn f(self) -> i32 { 5 } + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing.rs:51:27 + | +LL | assert_eq!(Wrapper(C).f(), 10); + | ^ multiple `f` found + | +note: candidate #1 is defined in an impl for the type `C` + --> $DIR/arbitrary_self_types_unshadowing.rs:25:5 + | +LL | pub fn f(self: &mut Wrapper) -> i32 { 10 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing.rs:36:5 + | +LL | pub fn f(self) -> i32 { 5 } + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing.rs:53:27 + | +LL | assert_eq!(Wrapper(C).g(), 11); + | ^ multiple `g` found + | +note: candidate #1 is defined in an impl for the type `C` + --> $DIR/arbitrary_self_types_unshadowing.rs:26:5 + | +LL | pub fn g(self: &mut Wrapper) -> i32 { 11 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing.rs:37:5 + | +LL | pub fn g(&self) -> i32 { 6 } + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.rs b/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.rs new file mode 100644 index 0000000000000..62553c2622a7e --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.rs @@ -0,0 +1,61 @@ +#![feature(arbitrary_self_types_pointers)] +#![feature(arbitrary_self_types)] + +pub struct A; + +// The receiver of the potentially shadowed method +// precisely matches that of the shadower +impl A { + pub fn f(self: Wrapper) -> i32 { 1 } + pub fn g(self: &Wrapper) -> i32 { 2 } + pub fn h(self: &mut Wrapper) -> i32 { 3 } + pub fn i(self: *const Wrapper) -> i32 { 4 } +} + +// The receiver of the potentially shadowed method is a reference +pub struct B; + +impl B { + pub fn f(self: &Wrapper) -> i32 { 9 } +} + +// The receiver of the potentially shadowed method is a mut reference + +pub struct C; + +impl C { + pub fn f(self: &mut Wrapper) -> i32 { 10 } + pub fn g(self: &mut Wrapper) -> i32 { 11 } +} + +pub struct Wrapper(T); + +impl core::ops::Receiver for Wrapper { + type Target = T; +} + +impl Wrapper { + pub fn f(self) -> i32 { 5 } + pub fn g(&self) -> i32 { 6 } + pub fn h(&mut self) -> i32 { 7 } + pub fn i(self: *const Self) -> i32 { 8 } +} + +fn main() { + assert_eq!(Wrapper(A).f(), 1); + //~^ ERROR: multiple applicable items in scope + assert_eq!(Wrapper(A).g(), 2); + //~^ ERROR: multiple applicable items in scope + assert_eq!(Wrapper(A).h(), 3); + //~^ ERROR: multiple applicable items in scope + let a = Wrapper(A); + let a_ptr = &a as *const Wrapper; + assert_eq!(a_ptr.i(), 4); + //~^ ERROR: multiple applicable items in scope + assert_eq!(Wrapper(B).f(), 9); + //~^ ERROR: multiple applicable items in scope + assert_eq!(Wrapper(C).f(), 10); + //~^ ERROR: multiple applicable items in scope + assert_eq!(Wrapper(C).g(), 11); + //~^ ERROR: multiple applicable items in scope +} diff --git a/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.stderr b/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.stderr new file mode 100644 index 0000000000000..6d453aed0f06d --- /dev/null +++ b/tests/ui/self/arbitrary_self_types_unshadowing_ptrs.stderr @@ -0,0 +1,122 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:45:27 + | +LL | assert_eq!(Wrapper(A).f(), 1); + | ^ multiple `f` found + | +note: candidate #1 is defined in an impl for the type `A` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:9:5 + | +LL | pub fn f(self: Wrapper) -> i32 { 1 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:38:5 + | +LL | pub fn f(self) -> i32 { 5 } + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:47:27 + | +LL | assert_eq!(Wrapper(A).g(), 2); + | ^ multiple `g` found + | +note: candidate #1 is defined in an impl for the type `A` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:10:5 + | +LL | pub fn g(self: &Wrapper) -> i32 { 2 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:39:5 + | +LL | pub fn g(&self) -> i32 { 6 } + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:49:27 + | +LL | assert_eq!(Wrapper(A).h(), 3); + | ^ multiple `h` found + | +note: candidate #1 is defined in an impl for the type `A` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:11:5 + | +LL | pub fn h(self: &mut Wrapper) -> i32 { 3 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:40:5 + | +LL | pub fn h(&mut self) -> i32 { 7 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:53:22 + | +LL | assert_eq!(a_ptr.i(), 4); + | ^ multiple `i` found + | +note: candidate #1 is defined in an impl for the type `A` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:12:5 + | +LL | pub fn i(self: *const Wrapper) -> i32 { 4 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:41:5 + | +LL | pub fn i(self: *const Self) -> i32 { 8 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:55:27 + | +LL | assert_eq!(Wrapper(B).f(), 9); + | ^ multiple `f` found + | +note: candidate #1 is defined in an impl for the type `B` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:19:5 + | +LL | pub fn f(self: &Wrapper) -> i32 { 9 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:38:5 + | +LL | pub fn f(self) -> i32 { 5 } + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:57:27 + | +LL | assert_eq!(Wrapper(C).f(), 10); + | ^ multiple `f` found + | +note: candidate #1 is defined in an impl for the type `C` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:27:5 + | +LL | pub fn f(self: &mut Wrapper) -> i32 { 10 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:38:5 + | +LL | pub fn f(self) -> i32 { 5 } + | ^^^^^^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:59:27 + | +LL | assert_eq!(Wrapper(C).g(), 11); + | ^ multiple `g` found + | +note: candidate #1 is defined in an impl for the type `C` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:28:5 + | +LL | pub fn g(self: &mut Wrapper) -> i32 { 11 } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Wrapper` + --> $DIR/arbitrary_self_types_unshadowing_ptrs.rs:39:5 + | +LL | pub fn g(&self) -> i32 { 6 } + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/self/conflicting_inner.rs b/tests/ui/self/conflicting_inner.rs new file mode 100644 index 0000000000000..1a7037dce7393 --- /dev/null +++ b/tests/ui/self/conflicting_inner.rs @@ -0,0 +1,38 @@ +//@ run-pass +//@ revisions: default feature +#![cfg_attr(feature, feature(arbitrary_self_types))] + +// This test aims to be like the IndexVec within rustc, and conflicts +// over its into_iter(). + +#[allow(dead_code)] +trait Foo { + fn foo(self) -> usize; +} + +struct IndexVec(T); + +impl std::ops::Deref for IndexVec { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a, T> Foo for &'a IndexVec { + fn foo(self) -> usize { + 2 + } +} + +impl IndexVec { + fn foo(self) -> usize { + 1 + } +} + +fn main() { + let ivec = IndexVec(0usize); + assert_eq!(ivec.foo(), 1); +} diff --git a/tests/ui/self/conflicting_inner2.rs b/tests/ui/self/conflicting_inner2.rs new file mode 100644 index 0000000000000..e6a6b5ef793e3 --- /dev/null +++ b/tests/ui/self/conflicting_inner2.rs @@ -0,0 +1,63 @@ +//@ run-pass +//@ revisions: default feature +#![cfg_attr(feature, feature(arbitrary_self_types))] + +use std::pin::Pin; +use std::ops::DerefMut; +use std::marker::Unpin; + +struct TryChunks; + +impl TryChunks { + #[allow(dead_code)] + fn take(self: std::pin::Pin<&mut Self>) -> usize { + 1 + } +} + +#[allow(dead_code)] +trait Stream { + fn poll_next(self: std::pin::Pin<&mut Self>); +} + +#[allow(dead_code)] +trait StreamExt: Stream { + #[allow(dead_code)] + fn take(self) -> usize where Self: Sized + { + 2 + } +} + +impl StreamExt for T where T: Stream {} + +impl Stream for TryChunks { + fn poll_next(self: std::pin::Pin<&mut Self>) { + assert_eq!(self.take(), 1); + } +} + +#[allow(dead_code)] +impl Stream for &mut S { + #[allow(dead_code)] + fn poll_next(mut self: Pin<&mut Self>) { + S::poll_next(Pin::new(&mut **self)) + } +} + +#[allow(dead_code)] +impl

Stream for Pin

+where + P: DerefMut + Unpin, + P::Target: Stream, +{ + #[allow(dead_code)] + fn poll_next(self: Pin<&mut Self>) { + self.get_mut().as_mut().poll_next() + } +} + +fn main() { + let mut item = Box::pin(TryChunks); + item.as_mut().poll_next(); +} diff --git a/tests/ui/span/issue-27522.stderr b/tests/ui/span/issue-27522.stderr index c57a100bbe227..04904b0ddc1c5 100644 --- a/tests/ui/span/issue-27522.stderr +++ b/tests/ui/span/issue-27522.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `&SomeType` 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`) + = 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 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 beafd7c2ab00f..eb9f9196a7234 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 @@ -32,8 +32,8 @@ error[E0307]: invalid `self` parameter type: `()` 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`) + = 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 2 previous errors diff --git a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs index aaa61e21155f4..e606d896e93d0 100644 --- a/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs +++ b/tests/ui/traits/const-traits/effects/auxiliary/minicore.rs @@ -110,6 +110,16 @@ impl LegacyReceiver for &T {} impl LegacyReceiver for &mut T {} +#[lang = "receiver"] +pub trait Receiver { + #[lang = "receiver_target"] + type Target: ?Sized; +} + +impl Receiver for T { + type Target = ::Target; +} + #[lang = "destruct"] #[const_trait] pub trait Destruct {} diff --git a/tests/ui/traits/issue-78372.stderr b/tests/ui/traits/issue-78372.stderr index 86234d15a5d4b..1c58915111f2c 100644 --- a/tests/ui/traits/issue-78372.stderr +++ b/tests/ui/traits/issue-78372.stderr @@ -61,8 +61,8 @@ error[E0307]: invalid `self` parameter type: `Smaht` 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`) + = 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[E0378]: the trait `DispatchFromDyn` may only be implemented for a coercion between structures --> $DIR/issue-78372.rs:3:1 diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr index 09efd7a9e7e2d..c6aa0e811f36c 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar` LL | fn bar(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`) + = 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[E0307]: invalid `self` parameter type: `&Bar` --> $DIR/method_resolution3.rs:20:18 @@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar` LL | fn baz(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`) + = 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 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr index 09efd7a9e7e2d..c6aa0e811f36c 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar` LL | fn bar(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`) + = 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[E0307]: invalid `self` parameter type: `&Bar` --> $DIR/method_resolution3.rs:20:18 @@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar` LL | fn baz(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`) + = 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 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr index 8ffdb21f2517b..e4c4d121733b6 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar` 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`) + = 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[E0307]: invalid `self` parameter type: `&Bar` --> $DIR/method_resolution4.rs:31:20 @@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar` LL | fn foomp(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`) + = 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 2 previous errors diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr index 8ffdb21f2517b..e4c4d121733b6 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr @@ -4,8 +4,8 @@ error[E0307]: invalid `self` parameter type: `Bar` 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`) + = 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[E0307]: invalid `self` parameter type: `&Bar` --> $DIR/method_resolution4.rs:31:20 @@ -13,8 +13,8 @@ error[E0307]: invalid `self` parameter type: `&Bar` LL | fn foomp(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`) + = 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 2 previous errors diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr index 2a8c4edbdb5f3..36bdc714e050b 100644 --- a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -22,8 +22,8 @@ error[E0307]: invalid `self` parameter type: `isize` 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`) + = 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[E0307]: invalid `self` parameter type: `Bar` --> $DIR/ufcs-explicit-self-bad.rs:19:18 @@ -31,8 +31,8 @@ error[E0307]: invalid `self` parameter type: `Bar` 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`) + = 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[E0307]: invalid `self` parameter type: `&Bar` --> $DIR/ufcs-explicit-self-bad.rs:23:18 @@ -40,8 +40,8 @@ error[E0307]: invalid `self` parameter type: `&Bar` 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`) + = 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[E0308]: mismatched `self` parameter type --> $DIR/ufcs-explicit-self-bad.rs:37:21