1
Fork 0

Arbitrary self types v2: Weak, NonNull hints

Various types can be used as method receivers, such as Rc<>, Box<> and
Arc<>. The arbitrary self types v2 work allows further types to be made
method receivers by implementing the Receiver trait.

With that in mind, it may come as a surprise to people when certain
common types do not implement Receiver and thus cannot be used as a
method receiver.

The RFC for arbitrary self types v2 therefore proposes emitting specific
lint hints for these cases:
* NonNull
* Weak
* Raw pointers

The code already emits a hint for this third case, in that it advises
folks that the `arbitrary_self_types_pointers` feature may meet their
need. This PR adds diagnostic hints for the Weak and NonNull cases.
This commit is contained in:
Adrian Taylor 2024-12-02 15:02:59 +00:00
parent 85641f729f
commit b27817c8c6
7 changed files with 101 additions and 1 deletions

View file

@ -249,6 +249,12 @@ hir_analysis_invalid_receiver_ty_help =
hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types =
consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
hir_analysis_invalid_receiver_ty_help_nonnull_note =
`NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
hir_analysis_invalid_receiver_ty_help_weak_note =
`Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}`
.note = type of `self` must be `Self` or a type that dereferences to it

View file

@ -44,6 +44,7 @@ use {rustc_ast as ast, rustc_hir as hir};
use crate::autoderef::Autoderef;
use crate::collect::CollectItemTypesVisitor;
use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};
use crate::errors::InvalidReceiverTyHint;
use crate::{errors, fluent_generated as fluent};
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
@ -1749,7 +1750,18 @@ fn check_method_receiver<'tcx>(
{
match receiver_validity_err {
ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
let hint = match receiver_ty
.builtin_deref(false)
.unwrap_or(receiver_ty)
.ty_adt_def()
.and_then(|adt_def| tcx.get_diagnostic_name(adt_def.did()))
{
Some(sym::RcWeak | sym::ArcWeak) => Some(InvalidReceiverTyHint::Weak),
Some(sym::NonNull) => Some(InvalidReceiverTyHint::NonNull),
_ => None,
};
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty, hint })
}
ReceiverValidityError::DoesNotDeref => {
tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes {

View file

@ -1655,6 +1655,14 @@ pub(crate) struct NonConstRange {
pub span: Span,
}
#[derive(Subdiagnostic)]
pub(crate) enum InvalidReceiverTyHint {
#[note(hir_analysis_invalid_receiver_ty_help_weak_note)]
Weak,
#[note(hir_analysis_invalid_receiver_ty_help_nonnull_note)]
NonNull,
}
#[derive(Diagnostic)]
#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)]
#[note]
@ -1673,6 +1681,8 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
#[primary_span]
pub span: Span,
pub receiver_ty: Ty<'tcx>,
#[subdiagnostic]
pub hint: Option<InvalidReceiverTyHint>,
}
#[derive(Diagnostic)]

View file

@ -0,0 +1,13 @@
#![feature(arbitrary_self_types)]
struct A;
impl A {
fn m(self: std::ptr::NonNull<Self>) {}
//~^ ERROR: invalid `self` parameter type
fn n(self: &std::ptr::NonNull<Self>) {}
//~^ ERROR: invalid `self` parameter type
}
fn main() {
}

View file

@ -0,0 +1,23 @@
error[E0307]: invalid `self` parameter type: `NonNull<A>`
--> $DIR/arbitrary_self_types_nonnull.rs:6:16
|
LL | fn m(self: std::ptr::NonNull<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>`, `self: Rc<Self>`, or `self: Arc<Self>`
= note: `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
error[E0307]: invalid `self` parameter type: `&NonNull<A>`
--> $DIR/arbitrary_self_types_nonnull.rs:8:16
|
LL | fn n(self: &std::ptr::NonNull<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>`, `self: Rc<Self>`, or `self: Arc<Self>`
= note: `NonNull` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `NonNull` in a newtype wrapper for which you implement `Receiver`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0307`.

View file

@ -0,0 +1,13 @@
#![feature(arbitrary_self_types)]
struct A;
impl A {
fn m(self: std::rc::Weak<Self>) {}
//~^ ERROR: invalid `self` parameter type
fn n(self: std::sync::Weak<Self>) {}
//~^ ERROR: invalid `self` parameter type
}
fn main() {
}

View file

@ -0,0 +1,23 @@
error[E0307]: invalid `self` parameter type: `std::rc::Weak<A>`
--> $DIR/arbitrary_self_types_weak.rs:6:16
|
LL | fn m(self: std::rc::Weak<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>`, `self: Rc<Self>`, or `self: Arc<Self>`
= note: `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
error[E0307]: invalid `self` parameter type: `std::sync::Weak<A>`
--> $DIR/arbitrary_self_types_weak.rs:8:16
|
LL | fn n(self: std::sync::Weak<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>`, `self: Rc<Self>`, or `self: Arc<Self>`
= note: `Weak` does not implement `Receiver` because it has methods that may shadow the referent; consider wrapping your `Weak` in a newtype wrapper for which you implement `Receiver`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0307`.