Skip to content

Commit

Permalink
Unrolled build for rust-lang#134264
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#134264 - adetaylor:weak-and-nonnull, r=compiler-errors

Arbitrary self types v2: Weak & NonNull diagnostics

This builds on top of rust-lang#134262 which is more urgent to review and merge first. I'll likely rebase this PR once that lands.

This is the first part of the diagnostic enhancements planned for Arbitrary Self Types v2.

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.

Tracking issue rust-lang#44874

r? `@wesleywiser`
  • Loading branch information
rust-timer authored Dec 15, 2024
2 parents b57d93d + b27817c commit ca78422
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 1 deletion.
6 changes: 6 additions & 0 deletions compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 13 additions & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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> {
Expand Down Expand Up @@ -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 {
Expand Down
10 changes: 10 additions & 0 deletions compiler/rustc_hir_analysis/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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)]
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/self/arbitrary_self_types_nonnull.rs
Original file line number Diff line number Diff line change
@@ -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() {
}
23 changes: 23 additions & 0 deletions tests/ui/self/arbitrary_self_types_nonnull.stderr
Original file line number Diff line number Diff line change
@@ -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`.
13 changes: 13 additions & 0 deletions tests/ui/self/arbitrary_self_types_weak.rs
Original file line number Diff line number Diff line change
@@ -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() {
}
23 changes: 23 additions & 0 deletions tests/ui/self/arbitrary_self_types_weak.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit ca78422

Please sign in to comment.