Skip to content

Commit f8cdf38

Browse files
authored
Rollup merge of rust-lang#64110 - estebank:receiver-type, r=Centril
Refer to "`self` type" instead of "receiver type" Fix rust-lang#42603.
2 parents a537aa1 + e16ce80 commit f8cdf38

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+283
-150
lines changed

src/librustc/error_codes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Generally, `Self: Sized` is used to indicate that the trait should not be used
3939
as a trait object. If the trait comes from your own crate, consider removing
4040
this restriction.
4141
42-
### Method references the `Self` type in its arguments or return type
42+
### Method references the `Self` type in its parameters or return type
4343
4444
This happens when a trait has a method like the following:
4545

src/librustc/infer/error_reporting/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1627,7 +1627,7 @@ impl<'tcx> ObligationCause<'tcx> {
16271627
MainFunctionType => Error0580("main function has wrong type"),
16281628
StartFunctionType => Error0308("start function has wrong type"),
16291629
IntrinsicType => Error0308("intrinsic has wrong type"),
1630-
MethodReceiver => Error0308("mismatched method receiver"),
1630+
MethodReceiver => Error0308("mismatched `self` parameter type"),
16311631

16321632
// In the case where we have no more specific thing to
16331633
// say, also take a look at the error code, maybe we can

src/librustc/traits/error_reporting.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1384,7 +1384,10 @@ impl<'tcx> TyCtxt<'tcx> {
13841384
let mut reported_violations = FxHashSet::default();
13851385
for violation in violations {
13861386
if reported_violations.insert(violation.clone()) {
1387-
err.note(&violation.error_msg());
1387+
match violation.span() {
1388+
Some(span) => err.span_label(span, violation.error_msg()),
1389+
None => err.note(&violation.error_msg()),
1390+
};
13881391
}
13891392
}
13901393
Some(err)

src/librustc/traits/object_safety.rs

+44-28
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::borrow::Cow;
2020
use std::iter::{self};
2121
use syntax::ast::{self};
2222
use syntax::symbol::InternedString;
23-
use syntax_pos::Span;
23+
use syntax_pos::{Span, DUMMY_SP};
2424

2525
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
2626
pub enum ObjectSafetyViolation {
@@ -32,10 +32,10 @@ pub enum ObjectSafetyViolation {
3232
SupertraitSelf,
3333

3434
/// Method has something illegal.
35-
Method(ast::Name, MethodViolationCode),
35+
Method(ast::Name, MethodViolationCode, Span),
3636

3737
/// Associated const.
38-
AssocConst(ast::Name),
38+
AssocConst(ast::Name, Span),
3939
}
4040

4141
impl ObjectSafetyViolation {
@@ -46,22 +46,35 @@ impl ObjectSafetyViolation {
4646
ObjectSafetyViolation::SupertraitSelf =>
4747
"the trait cannot use `Self` as a type parameter \
4848
in the supertraits or where-clauses".into(),
49-
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) =>
50-
format!("method `{}` has no receiver", name).into(),
51-
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) =>
52-
format!("method `{}` references the `Self` type \
53-
in its arguments or return type", name).into(),
54-
ObjectSafetyViolation::Method(name,
55-
MethodViolationCode::WhereClauseReferencesSelf(_)) =>
56-
format!("method `{}` references the `Self` type in where clauses", name).into(),
57-
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
49+
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) =>
50+
format!("associated function `{}` has no `self` parameter", name).into(),
51+
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!(
52+
"method `{}` references the `Self` type in its parameters or return type",
53+
name,
54+
).into(),
55+
ObjectSafetyViolation::Method(
56+
name,
57+
MethodViolationCode::WhereClauseReferencesSelf,
58+
_,
59+
) => format!("method `{}` references the `Self` type in where clauses", name).into(),
60+
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) =>
5861
format!("method `{}` has generic type parameters", name).into(),
59-
ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) =>
60-
format!("method `{}`'s receiver cannot be dispatched on", name).into(),
61-
ObjectSafetyViolation::AssocConst(name) =>
62+
ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) =>
63+
format!("method `{}`'s `self` parameter cannot be dispatched on", name).into(),
64+
ObjectSafetyViolation::AssocConst(name, _) =>
6265
format!("the trait cannot contain associated consts like `{}`", name).into(),
6366
}
6467
}
68+
69+
pub fn span(&self) -> Option<Span> {
70+
// When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
71+
// diagnostics use a `note` instead of a `span_label`.
72+
match *self {
73+
ObjectSafetyViolation::AssocConst(_, span) |
74+
ObjectSafetyViolation::Method(_, _, span) if span != DUMMY_SP => Some(span),
75+
_ => None,
76+
}
77+
}
6578
}
6679

6780
/// Reasons a method might not be object-safe.
@@ -74,7 +87,7 @@ pub enum MethodViolationCode {
7487
ReferencesSelf,
7588

7689
/// e.g., `fn foo(&self) where Self: Clone`
77-
WhereClauseReferencesSelf(Span),
90+
WhereClauseReferencesSelf,
7891

7992
/// e.g., `fn foo<A>()`
8093
Generic,
@@ -88,9 +101,10 @@ impl<'tcx> TyCtxt<'tcx> {
88101
/// astconv -- currently, `Self` in supertraits. This is needed
89102
/// because `object_safety_violations` can't be used during
90103
/// type collection.
91-
pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
92-
-> Vec<ObjectSafetyViolation>
93-
{
104+
pub fn astconv_object_safety_violations(
105+
self,
106+
trait_def_id: DefId,
107+
) -> Vec<ObjectSafetyViolation> {
94108
debug_assert!(self.generics_of(trait_def_id).has_self);
95109
let violations = traits::supertrait_def_ids(self, trait_def_id)
96110
.filter(|&def_id| self.predicates_reference_self(def_id, true))
@@ -128,7 +142,7 @@ impl<'tcx> TyCtxt<'tcx> {
128142
}
129143

130144
match self.virtual_call_violation_for_method(trait_def_id, method) {
131-
None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
145+
None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true,
132146
Some(_) => false,
133147
}
134148
}
@@ -138,12 +152,15 @@ impl<'tcx> TyCtxt<'tcx> {
138152
let mut violations: Vec<_> = self.associated_items(trait_def_id)
139153
.filter(|item| item.kind == ty::AssocKind::Method)
140154
.filter_map(|item|
141-
self.object_safety_violation_for_method(trait_def_id, &item)
142-
.map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
155+
self.object_safety_violation_for_method(trait_def_id, &item).map(|code| {
156+
ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span)
157+
})
143158
).filter(|violation| {
144-
if let ObjectSafetyViolation::Method(_,
145-
MethodViolationCode::WhereClauseReferencesSelf(span)) = violation
146-
{
159+
if let ObjectSafetyViolation::Method(
160+
_,
161+
MethodViolationCode::WhereClauseReferencesSelf,
162+
span,
163+
) = violation {
147164
// Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
148165
// It's also hard to get a use site span, so we use the method definition span.
149166
self.lint_node_note(
@@ -169,7 +186,7 @@ impl<'tcx> TyCtxt<'tcx> {
169186

170187
violations.extend(self.associated_items(trait_def_id)
171188
.filter(|item| item.kind == ty::AssocKind::Const)
172-
.map(|item| ObjectSafetyViolation::AssocConst(item.ident.name)));
189+
.map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)));
173190

174191
debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
175192
trait_def_id,
@@ -325,8 +342,7 @@ impl<'tcx> TyCtxt<'tcx> {
325342
.visit_tys_shallow(|t| {
326343
self.contains_illegal_self_type_reference(trait_def_id, t)
327344
}) {
328-
let span = self.def_span(method.def_id);
329-
return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
345+
return Some(MethodViolationCode::WhereClauseReferencesSelf);
330346
}
331347

332348
let receiver_ty = self.liberate_late_bound_regions(

src/librustc_typeck/check/wfcheck.rs

+18-18
Original file line numberDiff line numberDiff line change
@@ -762,19 +762,19 @@ fn check_opaque_types<'fcx, 'tcx>(
762762
substituted_predicates
763763
}
764764

765+
const HELP_FOR_SELF_TYPE: &str =
766+
"consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
767+
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
768+
of the previous types except `Self`)";
769+
765770
fn check_method_receiver<'fcx, 'tcx>(
766771
fcx: &FnCtxt<'fcx, 'tcx>,
767772
method_sig: &hir::MethodSig,
768773
method: &ty::AssocItem,
769774
self_ty: Ty<'tcx>,
770775
) {
771-
const HELP_FOR_SELF_TYPE: &str =
772-
"consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, \
773-
`self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one \
774-
of the previous types except `Self`)";
775776
// Check that the method has a valid receiver type, given the type `Self`.
776-
debug!("check_method_receiver({:?}, self_ty={:?})",
777-
method, self_ty);
777+
debug!("check_method_receiver({:?}, self_ty={:?})", method, self_ty);
778778

779779
if !method.method_has_self_argument {
780780
return;
@@ -805,12 +805,7 @@ fn check_method_receiver<'fcx, 'tcx>(
805805
if fcx.tcx.features().arbitrary_self_types {
806806
if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
807807
// Report error; `arbitrary_self_types` was enabled.
808-
fcx.tcx.sess.diagnostic().mut_span_err(
809-
span, &format!("invalid method receiver type: {:?}", receiver_ty)
810-
).note("type of `self` must be `Self` or a type that dereferences to it")
811-
.help(HELP_FOR_SELF_TYPE)
812-
.code(DiagnosticId::Error("E0307".into()))
813-
.emit();
808+
e0307(fcx, span, receiver_ty);
814809
}
815810
} else {
816811
if !receiver_is_valid(fcx, span, receiver_ty, self_ty, false) {
@@ -830,17 +825,22 @@ fn check_method_receiver<'fcx, 'tcx>(
830825
.emit();
831826
} else {
832827
// Report error; would not have worked with `arbitrary_self_types`.
833-
fcx.tcx.sess.diagnostic().mut_span_err(
834-
span, &format!("invalid method receiver type: {:?}", receiver_ty)
835-
).note("type must be `Self` or a type that dereferences to it")
836-
.help(HELP_FOR_SELF_TYPE)
837-
.code(DiagnosticId::Error("E0307".into()))
838-
.emit();
828+
e0307(fcx, span, receiver_ty);
839829
}
840830
}
841831
}
842832
}
843833

834+
fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) {
835+
fcx.tcx.sess.diagnostic().mut_span_err(
836+
span,
837+
&format!("invalid `self` parameter type: {:?}", receiver_ty)
838+
).note("type of `self` must be `Self` or a type that dereferences to it")
839+
.help(HELP_FOR_SELF_TYPE)
840+
.code(DiagnosticId::Error("E0307".into()))
841+
.emit();
842+
}
843+
844844
/// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If
845845
/// `arbitrary_self_types` is enabled, `receiver_ty` must transitively deref to `self_ty`, possibly
846846
/// through a `*const/mut T` raw pointer. If the feature is not enabled, the requirements are more

src/librustc_typeck/error_codes.rs

+82-2
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ match string {
212212
E0033: r##"
213213
This error indicates that a pointer to a trait type cannot be implicitly
214214
dereferenced by a pattern. Every trait defines a type, but because the
215-
size of trait implementors isn't fixed, this type has no compile-time size.
215+
size of trait implementers isn't fixed, this type has no compile-time size.
216216
Therefore, all accesses to trait types must be through pointers. If you
217217
encounter this error you should try to avoid dereferencing the pointer.
218218
@@ -2425,6 +2425,87 @@ struct Bar<S, T> { x: Foo<S, T> }
24252425
```
24262426
"##,
24272427

2428+
E0307: r##"
2429+
This error indicates that the `self` parameter in a method has an invalid
2430+
"reciever type".
2431+
2432+
Methods take a special first parameter, of which there are three variants:
2433+
`self`, `&self`, and `&mut self`. These are syntactic sugar for
2434+
`self: Self`, `self: &Self`, and `self: &mut Self` respectively.
2435+
2436+
```
2437+
# struct Foo;
2438+
trait Trait {
2439+
fn foo(&self);
2440+
// ^^^^^ `self` here is a reference to the receiver object
2441+
}
2442+
2443+
impl Trait for Foo {
2444+
fn foo(&self) {}
2445+
// ^^^^^ the receiver type is `&Foo`
2446+
}
2447+
```
2448+
2449+
The type `Self` acts as an alias to the type of the current trait
2450+
implementer, or "receiver type". Besides the already mentioned `Self`,
2451+
`&Self` and `&mut Self` valid receiver types, the following are also valid:
2452+
`self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, and `self: Pin<P>`
2453+
(where P is one of the previous types except `Self`). Note that `Self` can
2454+
also be the underlying implementing type, like `Foo` in the following
2455+
example:
2456+
2457+
```
2458+
# struct Foo;
2459+
# trait Trait {
2460+
# fn foo(&self);
2461+
# }
2462+
impl Trait for Foo {
2463+
fn foo(self: &Foo) {}
2464+
}
2465+
```
2466+
2467+
E0307 will be emitted by the compiler when using an invalid reciver type,
2468+
like in the following example:
2469+
2470+
```compile_fail,E0307
2471+
# struct Foo;
2472+
# struct Bar;
2473+
# trait Trait {
2474+
# fn foo(&self);
2475+
# }
2476+
impl Trait for Foo {
2477+
fn foo(self: &Bar) {}
2478+
}
2479+
```
2480+
2481+
The nightly feature [Arbintrary self types][AST] extends the accepted
2482+
set of receiver types to also include any type that can dereference to
2483+
`Self`:
2484+
2485+
```
2486+
#![feature(arbitrary_self_types)]
2487+
2488+
struct Foo;
2489+
struct Bar;
2490+
2491+
// Because you can dereference `Bar` into `Foo`...
2492+
impl std::ops::Deref for Bar {
2493+
type Target = Foo;
2494+
2495+
fn deref(&self) -> &Foo {
2496+
&Foo
2497+
}
2498+
}
2499+
2500+
impl Foo {
2501+
fn foo(self: Bar) {}
2502+
// ^^^^^^^^^ ...it can be used as the receiver type
2503+
}
2504+
```
2505+
2506+
[AST]: https://doc.rust-lang.org/unstable-book/language-features/arbitrary-self-types.html
2507+
"##,
2508+
24282509
E0321: r##"
24292510
A cross-crate opt-out trait was implemented on something which wasn't a struct
24302511
or enum type. Erroneous code example:
@@ -4851,7 +4932,6 @@ register_diagnostics! {
48514932
// E0247,
48524933
// E0248, // value used as a type, now reported earlier during resolution as E0412
48534934
// E0249,
4854-
E0307, // invalid method `self` type
48554935
// E0319, // trait impls for defaulted traits allowed just for structs/enums
48564936
// E0372, // coherence not object safe
48574937
E0377, // the trait `CoerceUnsized` may only be implemented for a coercion

src/test/ui/associated-const/associated-const-in-trait.stderr

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
error[E0038]: the trait `Trait` cannot be made into an object
22
--> $DIR/associated-const-in-trait.rs:9:6
33
|
4+
LL | const N: usize;
5+
| - the trait cannot contain associated consts like `N`
6+
...
47
LL | impl dyn Trait {
58
| ^^^^^^^^^ the trait `Trait` cannot be made into an object
6-
|
7-
= note: the trait cannot contain associated consts like `N`
89

910
error: aborting due to previous error
1011

src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.old.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
error[E0038]: the trait `NotObjectSafe` cannot be made into an object
22
--> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6
33
|
4+
LL | trait NotObjectSafe { fn eq(&self, other: Self); }
5+
| -- method `eq` references the `Self` type in its parameters or return type
46
LL | impl NotObjectSafe for dyn NotObjectSafe { }
57
| ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
6-
|
7-
= note: method `eq` references the `Self` type in its arguments or return type
88

99
error: aborting due to previous error
1010

src/test/ui/coherence/coherence-impl-trait-for-trait-object-safe.re.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
error[E0038]: the trait `NotObjectSafe` cannot be made into an object
22
--> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6
33
|
4+
LL | trait NotObjectSafe { fn eq(&self, other: Self); }
5+
| -- method `eq` references the `Self` type in its parameters or return type
46
LL | impl NotObjectSafe for dyn NotObjectSafe { }
57
| ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
6-
|
7-
= note: method `eq` references the `Self` type in its arguments or return type
88

99
error: aborting due to previous error
1010

src/test/ui/did_you_mean/issue-40006.stderr

+3-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ error[E0038]: the trait `X` cannot be made into an object
6161
|
6262
LL | impl dyn X {
6363
| ^^^^^ the trait `X` cannot be made into an object
64-
|
65-
= note: method `xxx` has no receiver
64+
...
65+
LL | fn xxx() { ### }
66+
| --- associated function `xxx` has no `self` parameter
6667

6768
error: aborting due to 9 previous errors
6869

0 commit comments

Comments
 (0)