Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refer to "self type" instead of "receiver type" #64110

Merged
merged 7 commits into from
Sep 5, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1627,7 +1627,7 @@ impl<'tcx> ObligationCause<'tcx> {
MainFunctionType => Error0580("main function has wrong type"),
StartFunctionType => Error0308("start function has wrong type"),
IntrinsicType => Error0308("intrinsic has wrong type"),
MethodReceiver => Error0308("mismatched method receiver"),
MethodReceiver => Error0308("mismatched `self` parameter type"),

// In the case where we have no more specific thing to
// say, also take a look at the error code, maybe we can
Expand Down
16 changes: 9 additions & 7 deletions src/librustc/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ impl ObjectSafetyViolation {
"the trait cannot use `Self` as a type parameter \
in the supertraits or where-clauses".into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) =>
format!("method `{}` has no receiver", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) =>
format!("method `{}` references the `Self` type \
in its arguments or return type", name).into(),
ObjectSafetyViolation::Method(name,
MethodViolationCode::WhereClauseReferencesSelf(_)) =>
format!("method `{}` references the `Self` type in where clauses", name).into(),
format!("associated function `{}` has no `self` parameter", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => format!(
"method `{}` references the `Self` type in its arguments or return type",
Centril marked this conversation as resolved.
Show resolved Hide resolved
name,
).into(),
ObjectSafetyViolation::Method(
name,
MethodViolationCode::WhereClauseReferencesSelf(_),
) => format!("method `{}` references the `Self` type in where clauses", name).into(),
Centril marked this conversation as resolved.
Show resolved Hide resolved
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
format!("method `{}` has generic type parameters", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) =>
Expand Down
36 changes: 18 additions & 18 deletions src/librustc_typeck/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,19 +762,19 @@ fn check_opaque_types<'fcx, 'tcx>(
substituted_predicates
}

const HELP_FOR_SELF_TYPE: &str =
"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`)";

fn check_method_receiver<'fcx, 'tcx>(
fcx: &FnCtxt<'fcx, 'tcx>,
method_sig: &hir::MethodSig,
method: &ty::AssocItem,
self_ty: Ty<'tcx>,
) {
const HELP_FOR_SELF_TYPE: &str =
"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`)";
// Check that the method has a valid receiver type, given the type `Self`.
debug!("check_method_receiver({:?}, self_ty={:?})",
method, self_ty);
debug!("check_method_receiver({:?}, self_ty={:?})", method, self_ty);

if !method.method_has_self_argument {
return;
Expand Down Expand Up @@ -805,12 +805,7 @@ fn check_method_receiver<'fcx, 'tcx>(
if fcx.tcx.features().arbitrary_self_types {
if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
// Report error; `arbitrary_self_types` was enabled.
fcx.tcx.sess.diagnostic().mut_span_err(
span, &format!("invalid method receiver type: {:?}", receiver_ty)
).note("type of `self` must be `Self` or a type that dereferences to it")
.help(HELP_FOR_SELF_TYPE)
.code(DiagnosticId::Error("E0307".into()))
.emit();
e0307(fcx, span, receiver_ty);
}
} else {
if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) {
Expand All @@ -830,17 +825,22 @@ fn check_method_receiver<'fcx, 'tcx>(
.emit();
} else {
// Report error; would not have worked with `arbitrary_self_types`.
fcx.tcx.sess.diagnostic().mut_span_err(
span, &format!("invalid method receiver type: {:?}", receiver_ty)
).note("type must be `Self` or a type that dereferences to it")
.help(HELP_FOR_SELF_TYPE)
.code(DiagnosticId::Error("E0307".into()))
.emit();
e0307(fcx, span, receiver_ty);
}
}
}
}

fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) {
fcx.tcx.sess.diagnostic().mut_span_err(
span,
&format!("invalid `self` parameter type: {:?}", receiver_ty)
).note("type of `self` must be `Self` or a type that dereferences to it")
.help(HELP_FOR_SELF_TYPE)
.code(DiagnosticId::Error("E0307".into()))
.emit();
}

/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
/// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more
Expand Down
78 changes: 77 additions & 1 deletion src/librustc_typeck/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2425,6 +2425,83 @@ struct Bar<S, T> { x: Foo<S, T> }
```
"##,

E0307: r##"
This error indicates that the `self` parameter in a method has an invalid
"reciever type".

Methods take a special first parameter, of which there are three variants:
`self`, `&self`, and `&mut self`. The type `Self` acts as an alias to the
estebank marked this conversation as resolved.
Show resolved Hide resolved
type of the current trait implementor, or "receiver type". Besides the
estebank marked this conversation as resolved.
Show resolved Hide resolved
already mentioned `Self`, `&Self` and `&mut Self` valid receiver types, the
estebank marked this conversation as resolved.
Show resolved Hide resolved
following are also valid, if less common: `self: Box<Self>`,
estebank marked this conversation as resolved.
Show resolved Hide resolved
`self: Rc<Self>`, `self: Arc<Self>`, and `self: Pin<P>` (where P is one of
the previous types except `Self`).

```
# struct Foo;
trait Trait {
fn foo(&self);
// ^^^^^ this let's you refer to the type that implements this trait
estebank marked this conversation as resolved.
Show resolved Hide resolved
}
impl Trait for Foo {
// ^^^ this is the "receiver type"
estebank marked this conversation as resolved.
Show resolved Hide resolved
fn foo(&self) {}
// ^^^^^ this is of type `Foo`
}
```

The above is equivalent to:

```
# struct Foo;
# trait Trait {
# fn foo(&self);
# }
impl Trait for Foo {
fn foo(&self: &Foo) {}
estebank marked this conversation as resolved.
Show resolved Hide resolved
}
```

When using an invalid reciver type, like in the following example,

```compile_fail,E0307
# struct Foo;
# struct Bar;
# trait Trait {
# fn foo(&self);
# }
impl Trait for Struct {
fn foo(&self: &Bar) {}
}
```
estebank marked this conversation as resolved.
Show resolved Hide resolved

The nightly feature [Arbintrary self types][AST] extends the accepted
receiver type to also include any type that can dereference to `Self`:
estebank marked this conversation as resolved.
Show resolved Hide resolved

```
#![feature(arbitrary_self_types)]

struct Foo;
struct Bar;

// Because you can dereference `Bar` into `Foo`...
impl std::ops::Deref for Bar {
type Target = Foo;

fn deref(&self) -> &Foo {
&Foo
}
}

impl Foo {
fn foo(self: Bar) {}
// ^^^^^^^^^ ...it can be used as the receiver type
}
```

[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html
"##,

E0321: r##"
A cross-crate opt-out trait was implemented on something which wasn't a struct
or enum type. Erroneous code example:
Expand Down Expand Up @@ -4851,7 +4928,6 @@ register_diagnostics! {
// E0247,
// E0248, // value used as a type, now reported earlier during resolution as E0412
// E0249,
E0307, // invalid method `self` type
// E0319, // trait impls for defaulted traits allowed just for structs/enums
// E0372, // coherence not object safe
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/did_you_mean/issue-40006.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ error[E0038]: the trait `X` cannot be made into an object
LL | impl dyn X {
| ^^^^^ the trait `X` cannot be made into an object
|
= note: method `xxx` has no receiver
= note: associated function `xxx` has no `self` parameter

error: aborting due to 9 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0033-teach.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn main() {
let trait_obj: &dyn SomeTrait = SomeTrait;
//~^ ERROR expected value, found trait `SomeTrait`
//~| ERROR E0038
//~| method `foo` has no receiver
//~| associated function `foo` has no `self` parameter

let &invalid = trait_obj;
//~^ ERROR E0033
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0033-teach.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ error[E0038]: the trait `SomeTrait` cannot be made into an object
LL | let trait_obj: &dyn SomeTrait = SomeTrait;
| ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
|
= note: method `foo` has no receiver
= note: associated function `foo` has no `self` parameter

error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
--> $DIR/E0033-teach.rs:13:9
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0033.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ fn main() {
let trait_obj: &dyn SomeTrait = SomeTrait;
//~^ ERROR expected value, found trait `SomeTrait`
//~| ERROR E0038
//~| method `foo` has no receiver
//~| associated function `foo` has no `self` parameter

let &invalid = trait_obj;
//~^ ERROR E0033
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0033.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ error[E0038]: the trait `SomeTrait` cannot be made into an object
LL | let trait_obj: &dyn SomeTrait = SomeTrait;
| ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
|
= note: method `foo` has no receiver
= note: associated function `foo` has no `self` parameter

error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
--> $DIR/E0033.rs:11:9
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/explicit/explicit-self-lifetime-mismatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ struct Foo<'a,'b> {
impl<'a,'b> Foo<'a,'b> {
fn bar(self:
Foo<'b,'a>
//~^ ERROR mismatched method receiver
//~^ ERROR mismatched `self` parameter type
//~| expected type `Foo<'a, 'b>`
//~| found type `Foo<'b, 'a>`
//~| lifetime mismatch
//~| ERROR mismatched method receiver
//~| ERROR mismatched `self` parameter type
//~| expected type `Foo<'a, 'b>`
//~| found type `Foo<'b, 'a>`
//~| lifetime mismatch
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0308]: mismatched method receiver
error[E0308]: mismatched `self` parameter type
--> $DIR/explicit-self-lifetime-mismatch.rs:8:12
|
LL | Foo<'b,'a>
Expand All @@ -17,7 +17,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at
LL | impl<'a,'b> Foo<'a,'b> {
| ^^

error[E0308]: mismatched method receiver
error[E0308]: mismatched `self` parameter type
--> $DIR/explicit-self-lifetime-mismatch.rs:8:12
|
LL | Foo<'b,'a>
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-17740.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ struct Foo<'a> {

impl <'a> Foo<'a>{
fn bar(self: &mut Foo) {
//~^ mismatched method receiver
//~^ mismatched `self` parameter type
//~| expected type `Foo<'a>`
//~| found type `Foo<'_>`
//~| lifetime mismatch
//~| mismatched method receiver
//~| mismatched `self` parameter type
//~| expected type `Foo<'a>`
//~| found type `Foo<'_>`
//~| lifetime mismatch
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-17740.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0308]: mismatched method receiver
error[E0308]: mismatched `self` parameter type
--> $DIR/issue-17740.rs:6:18
|
LL | fn bar(self: &mut Foo) {
Expand All @@ -23,7 +23,7 @@ note: ...does not necessarily outlive the lifetime 'a as defined on the impl at
LL | impl <'a> Foo<'a>{
| ^^

error[E0308]: mismatched method receiver
error[E0308]: mismatched `self` parameter type
--> $DIR/issue-17740.rs:6:18
|
LL | fn bar(self: &mut Foo) {
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-17905-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ impl Pair<
isize
> {
fn say(self: &Pair<&str, isize>) {
//~^ ERROR mismatched method receiver
//~| ERROR mismatched method receiver
//~^ ERROR mismatched `self` parameter type
//~| ERROR mismatched `self` parameter type
println!("{:?}", self);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/issues/issue-17905-2.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0308]: mismatched method receiver
error[E0308]: mismatched `self` parameter type
--> $DIR/issue-17905-2.rs:8:18
|
LL | fn say(self: &Pair<&str, isize>) {
Expand All @@ -21,7 +21,7 @@ note: ...does not necessarily outlive the lifetime '_ as defined on the impl at
LL | &str,
| ^

error[E0308]: mismatched method receiver
error[E0308]: mismatched `self` parameter type
--> $DIR/issue-17905-2.rs:8:18
|
LL | fn say(self: &Pair<&str, isize>) {
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-19380.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0038]: the trait `Qiz` cannot be made into an object
LL | foos: &'static [&'static (dyn Qiz + 'static)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object
|
= note: method `qiz` has no receiver
= note: associated function `qiz` has no `self` parameter

error: aborting due to previous error

Expand Down
5 changes: 2 additions & 3 deletions src/test/ui/issues/issue-56806.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
pub trait Trait {
fn dyn_instead_of_self(self: Box<dyn Trait>);
//~^ ERROR invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)>
//~^ ERROR invalid `self` parameter type
}

pub fn main() {
}
pub fn main() {}
5 changes: 3 additions & 2 deletions src/test/ui/issues/issue-56806.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
error[E0307]: invalid method receiver type: std::boxed::Box<(dyn Trait + 'static)>
error[E0307]: invalid `self` parameter type: std::boxed::Box<(dyn Trait + 'static)>
--> $DIR/issue-56806.rs:2:34
|
LL | fn dyn_instead_of_self(self: Box<dyn Trait>);
| ^^^^^^^^^^^^^^
|
= note: type must be `Self` or a type that dereferences to it
= note: type of `self` must be `Self` or a type that dereferences to it
= help: 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`)

error: aborting due to previous error

For more information about this error, try `rustc --explain E0307`.
2 changes: 1 addition & 1 deletion src/test/ui/object-safety/object-safety-no-static.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0038]: the trait `Foo` cannot be made into an object
LL | fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<dyn Foo + 'static> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: method `foo` has no receiver
= note: associated function `foo` has no `self` parameter

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/resolve/issue-3907-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0038]: the trait `issue_3907::Foo` cannot be made into an object
LL | fn bar(_x: Foo) {}
| ^^^^^^^^^^^^^^^ the trait `issue_3907::Foo` cannot be made into an object
|
= note: method `bar` has no receiver
= note: associated function `bar` has no `self` parameter

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/span/issue-27522.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
struct SomeType {}

trait Foo {
fn handler(self: &SomeType); //~ ERROR invalid method receiver type
fn handler(self: &SomeType); //~ ERROR invalid `self` parameter type
}

fn main() {}
5 changes: 3 additions & 2 deletions src/test/ui/span/issue-27522.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
error[E0307]: invalid method receiver type: &SomeType
error[E0307]: invalid `self` parameter type: &SomeType
--> $DIR/issue-27522.rs:6:22
|
LL | fn handler(self: &SomeType);
| ^^^^^^^^^
|
= note: type must be `Self` or a type that dereferences to it
= note: type of `self` must be `Self` or a type that dereferences to it
= help: 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`)

error: aborting due to previous error

For more information about this error, try `rustc --explain E0307`.
Loading