Skip to content

Commit 4b2ad13

Browse files
committed
Arbitrary self types v2: new diagnostics (part)
Part-implement new diagnostics specified in the RFC, and leave TODOs for the rest.
1 parent 4bc339f commit 4b2ad13

7 files changed

+103
-3
lines changed

compiler/rustc_hir_analysis/messages.ftl

+4
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ hir_analysis_invalid_receiver_ty = invalid `self` parameter type: `{$receiver_ty
246246
hir_analysis_invalid_receiver_ty_help =
247247
consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
248248
249+
hir_analysis_invalid_receiver_ty_help_pointer_note =
250+
Raw pointers do not implement Receiver. Consider wrapping your pointer in
251+
a newtype wrapper for which you implement Receiver
252+
249253
hir_analysis_invalid_union_field =
250254
field must implement `Copy` or be wrapped in `ManuallyDrop<...>` to be used in a union
251255
.note = union fields must not have drop side-effects, which is currently enforced via either `Copy` or `ManuallyDrop<...>`

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -1677,6 +1677,16 @@ fn check_method_receiver<'tcx>(
16771677
};
16781678
let generics = tcx.generics_of(method.def_id);
16791679

1680+
// yet to do: determine whether self_ty is Sized. If not (most commonly
1681+
// if it's a trait) determine whether receiver_ty::Target is Sized.
1682+
// If so, arrange to emit the extra help in _HELP_FOR_SIZED_SELF_TYPE.
1683+
// Then adjust tests/ui/self/arbitrary_self_types_sizedness_trait.rs
1684+
// to match.
1685+
// yet to do: determine whether self_ty is NonNull or Weak, and use
1686+
// _HELP_FOR_NONNULL and _HELP_FOR_WEAK as appropriate. No tests yet
1687+
// exist for this.
1688+
let raw_pointer = is_raw_pointer(receiver_ty);
1689+
16801690
let receiver_validity =
16811691
receiver_is_valid(wfcx, span, receiver_ty, self_ty, arbitrary_self_types_level, generics);
16821692
if let Err(receiver_validity_err) = receiver_validity {
@@ -1735,9 +1745,9 @@ fn check_method_receiver<'tcx>(
17351745
// Report error; would not have worked with `arbitrary_self_types[_pointers]`.
17361746
{
17371747
match receiver_validity_err {
1738-
ReceiverValidityError::DoesNotDeref => {
1739-
tcx.dcx().emit_err(errors::InvalidReceiverTy { span, receiver_ty })
1740-
}
1748+
ReceiverValidityError::DoesNotDeref => tcx
1749+
.dcx()
1750+
.emit_err(errors::InvalidReceiverTy { span, receiver_ty, raw_pointer }),
17411751
ReceiverValidityError::MethodGenericParamUsed => {
17421752
tcx.dcx().emit_err(errors::InvalidGenericReceiverTy { span, receiver_ty })
17431753
}
@@ -1773,6 +1783,10 @@ fn confirm_type_is_not_a_method_generic_param(
17731783
Ok(())
17741784
}
17751785

1786+
fn is_raw_pointer<'tcx>(ty: Ty<'tcx>) -> bool {
1787+
matches!(ty.kind(), ty::RawPtr(..))
1788+
}
1789+
17761790
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
17771791
/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
17781792
/// through a `*const/mut T` raw pointer if `arbitrary_self_types_pointers` is also enabled.

compiler/rustc_hir_analysis/src/errors.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1653,6 +1653,8 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
16531653
#[primary_span]
16541654
pub span: Span,
16551655
pub receiver_ty: Ty<'tcx>,
1656+
#[note(hir_analysis_invalid_receiver_ty_help_pointer_note)]
1657+
pub raw_pointer: bool,
16561658
}
16571659

16581660
#[derive(Diagnostic)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#![feature(arbitrary_self_types)]
2+
3+
struct A;
4+
5+
impl A {
6+
fn m(self: *const Self) {}
7+
//~^ ERROR: `*const A` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
8+
}
9+
10+
trait B {
11+
fn bm(self: *const Self) {}
12+
//~^ ERROR: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
13+
}
14+
15+
fn main() {
16+
let a = A;
17+
let ptr = &a as *const A;
18+
ptr.m();
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0658]: `*const A` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
2+
--> $DIR/arbitrary_self_types_pointer.rs:6:16
3+
|
4+
LL | fn m(self: *const Self) {}
5+
| ^^^^^^^^^^^
6+
|
7+
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
8+
= help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
9+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
10+
= 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>`
11+
12+
error[E0658]: `*const Self` cannot be used as the type of `self` without the `arbitrary_self_types_pointers` feature
13+
--> $DIR/arbitrary_self_types_pointer.rs:11:17
14+
|
15+
LL | fn bm(self: *const Self) {}
16+
| ^^^^^^^^^^^
17+
|
18+
= note: see issue #44874 <https://github.com/rust-lang/rust/issues/44874> for more information
19+
= help: add `#![feature(arbitrary_self_types_pointers)]` to the crate attributes to enable
20+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
21+
= 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>`
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![feature(arbitrary_self_types)]
2+
3+
struct SmartPtr<'a, T: ?Sized>(&'a T);
4+
5+
impl<T> std::ops::Receiver for SmartPtr<'_, T> {
6+
type Target = T;
7+
}
8+
9+
struct A;
10+
11+
trait B {
12+
fn m(self: SmartPtr<Self>) {}
13+
//~^ ERROR: invalid `self` parameter type
14+
}
15+
16+
impl B for A {
17+
fn m(self: SmartPtr<Self>) {}
18+
}
19+
20+
fn main() {
21+
let a = A;
22+
let a = SmartPtr(&A);
23+
a.m();
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0307]: invalid `self` parameter type: `SmartPtr<'_, Self>`
2+
--> $DIR/arbitrary_self_types_sizedness_trait.rs:12:16
3+
|
4+
LL | fn m(self: SmartPtr<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+
10+
error: aborting due to 1 previous error
11+
12+
For more information about this error, try `rustc --explain E0307`.

0 commit comments

Comments
 (0)