Skip to content

Commit c838853

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 061c77c commit c838853

File tree

7 files changed

+103
-3
lines changed

7 files changed

+103
-3
lines changed

compiler/rustc_hir_analysis/messages.ftl

Lines changed: 4 additions & 0 deletions
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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,6 +1676,16 @@ fn check_method_receiver<'tcx>(
16761676
};
16771677
let generics = tcx.generics_of(method.def_id);
16781678

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

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

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,8 @@ pub(crate) struct InvalidReceiverTy<'tcx> {
16211621
#[primary_span]
16221622
pub span: Span,
16231623
pub receiver_ty: Ty<'tcx>,
1624+
#[note(hir_analysis_invalid_receiver_ty_help_pointer_note)]
1625+
pub raw_pointer: bool,
16241626
}
16251627

16261628
#[derive(Diagnostic)]
Lines changed: 19 additions & 0 deletions
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+
}
Lines changed: 25 additions & 0 deletions
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`.
Lines changed: 24 additions & 0 deletions
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+
}
Lines changed: 12 additions & 0 deletions
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)