Skip to content

Commit b27817c

Browse files
committed
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.
1 parent 85641f7 commit b27817c

7 files changed

+101
-1
lines changed

compiler/rustc_hir_analysis/messages.ftl

+6
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ hir_analysis_invalid_receiver_ty_help =
249249
hir_analysis_invalid_receiver_ty_help_no_arbitrary_self_types =
250250
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`)
251251
252+
hir_analysis_invalid_receiver_ty_help_nonnull_note =
253+
`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`
254+
255+
hir_analysis_invalid_receiver_ty_help_weak_note =
256+
`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`
257+
252258
hir_analysis_invalid_receiver_ty_no_arbitrary_self_types = invalid `self` parameter type: `{$receiver_ty}`
253259
.note = type of `self` must be `Self` or a type that dereferences to it
254260

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use {rustc_ast as ast, rustc_hir as hir};
4444
use crate::autoderef::Autoderef;
4545
use crate::collect::CollectItemTypesVisitor;
4646
use crate::constrained_generic_params::{Parameter, identify_constrained_generic_params};
47+
use crate::errors::InvalidReceiverTyHint;
4748
use crate::{errors, fluent_generated as fluent};
4849

4950
pub(super) struct WfCheckingCtxt<'a, 'tcx> {
@@ -1749,7 +1750,18 @@ fn check_method_receiver<'tcx>(
17491750
{
17501751
match receiver_validity_err {
17511752
ReceiverValidityError::DoesNotDeref if arbitrary_self_types_level.is_some() => {
1752-
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
1753+
let hint = match receiver_ty
1754+
.builtin_deref(false)
1755+
.unwrap_or(receiver_ty)
1756+
.ty_adt_def()
1757+
.and_then(|adt_def| tcx.get_diagnostic_name(adt_def.did()))
1758+
{
1759+
Some(sym::RcWeak | sym::ArcWeak) => Some(InvalidReceiverTyHint::Weak),
1760+
Some(sym::NonNull) => Some(InvalidReceiverTyHint::NonNull),
1761+
_ => None,
1762+
};
1763+
1764+
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty, hint })
17531765
}
17541766
ReceiverValidityError::DoesNotDeref => {
17551767
tcx.dcx().emit_err(errors::InvalidReceiverTyNoArbitrarySelfTypes {

compiler/rustc_hir_analysis/src/errors.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1655,6 +1655,14 @@ pub(crate) struct NonConstRange {
16551655
pub span: Span,
16561656
}
16571657

1658+
#[derive(Subdiagnostic)]
1659+
pub(crate) enum InvalidReceiverTyHint {
1660+
#[note(hir_analysis_invalid_receiver_ty_help_weak_note)]
1661+
Weak,
1662+
#[note(hir_analysis_invalid_receiver_ty_help_nonnull_note)]
1663+
NonNull,
1664+
}
1665+
16581666
#[derive(Diagnostic)]
16591667
#[diag(hir_analysis_invalid_receiver_ty_no_arbitrary_self_types, code = E0307)]
16601668
#[note]
@@ -1673,6 +1681,8 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
16731681
#[primary_span]
16741682
pub span: Span,
16751683
pub receiver_ty: Ty<'tcx>,
1684+
#[subdiagnostic]
1685+
pub hint: Option<InvalidReceiverTyHint>,
16761686
}
16771687

16781688
#[derive(Diagnostic)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(arbitrary_self_types)]
2+
3+
struct A;
4+
5+
impl A {
6+
fn m(self: std::ptr::NonNull<Self>) {}
7+
//~^ ERROR: invalid `self` parameter type
8+
fn n(self: &std::ptr::NonNull<Self>) {}
9+
//~^ ERROR: invalid `self` parameter type
10+
}
11+
12+
fn main() {
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0307]: invalid `self` parameter type: `NonNull<A>`
2+
--> $DIR/arbitrary_self_types_nonnull.rs:6:16
3+
|
4+
LL | fn m(self: std::ptr::NonNull<Self>) {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: type of `self` must be `Self` or some type implementing `Receiver`
8+
= 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>`
9+
= 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`
10+
11+
error[E0307]: invalid `self` parameter type: `&NonNull<A>`
12+
--> $DIR/arbitrary_self_types_nonnull.rs:8:16
13+
|
14+
LL | fn n(self: &std::ptr::NonNull<Self>) {}
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^
16+
|
17+
= note: type of `self` must be `Self` or some type implementing `Receiver`
18+
= 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>`
19+
= 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`
20+
21+
error: aborting due to 2 previous errors
22+
23+
For more information about this error, try `rustc --explain E0307`.
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(arbitrary_self_types)]
2+
3+
struct A;
4+
5+
impl A {
6+
fn m(self: std::rc::Weak<Self>) {}
7+
//~^ ERROR: invalid `self` parameter type
8+
fn n(self: std::sync::Weak<Self>) {}
9+
//~^ ERROR: invalid `self` parameter type
10+
}
11+
12+
fn main() {
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0307]: invalid `self` parameter type: `std::rc::Weak<A>`
2+
--> $DIR/arbitrary_self_types_weak.rs:6:16
3+
|
4+
LL | fn m(self: std::rc::Weak<Self>) {}
5+
| ^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: type of `self` must be `Self` or some type implementing `Receiver`
8+
= 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>`
9+
= 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`
10+
11+
error[E0307]: invalid `self` parameter type: `std::sync::Weak<A>`
12+
--> $DIR/arbitrary_self_types_weak.rs:8:16
13+
|
14+
LL | fn n(self: std::sync::Weak<Self>) {}
15+
| ^^^^^^^^^^^^^^^^^^^^^
16+
|
17+
= note: type of `self` must be `Self` or some type implementing `Receiver`
18+
= 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>`
19+
= 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`
20+
21+
error: aborting due to 2 previous errors
22+
23+
For more information about this error, try `rustc --explain E0307`.

0 commit comments

Comments
 (0)