Use more appropriate spans on object unsafe traits and provide structured suggestions when possible

This commit is contained in:
Esteban Küber 2020-01-31 18:48:35 -08:00
parent 413bfa4b98
commit a52ec87a17
22 changed files with 178 additions and 62 deletions

View File

@ -1073,9 +1073,15 @@ pub fn report_object_safety_error(
err.span_label(span, &msg); err.span_label(span, &msg);
} }
} }
if let (Some(_), Some(note)) = (trait_span, violation.solution()) { match (trait_span, violation.solution()) {
(Some(_), Some((note, None))) => {
err.help(&note);
}
(Some(_), Some((note, Some((sugg, span))))) => {
err.span_suggestion(span, &note, sugg, Applicability::MachineApplicable);
}
// Only provide the help if its a local trait, otherwise it's not actionable. // Only provide the help if its a local trait, otherwise it's not actionable.
err.help(&note); _ => {}
} }
} }
} }

View File

@ -13,6 +13,7 @@ use super::elaborate_predicates;
use crate::traits::{self, Obligation, ObligationCause}; use crate::traits::{self, Obligation, ObligationCause};
use crate::ty::subst::{InternalSubsts, Subst}; use crate::ty::subst::{InternalSubsts, Subst};
use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
@ -48,14 +49,20 @@ impl ObjectSafetyViolation {
"it cannot use `Self` as a type parameter in the supertraits or `where`-clauses" "it cannot use `Self` as a type parameter in the supertraits or `where`-clauses"
.into() .into()
} }
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) => { ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => {
format!("associated function `{}` has no `self` parameter", name).into() format!("associated function `{}` has no `self` parameter", name).into()
} }
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!( ObjectSafetyViolation::Method(
"method `{}` references the `Self` type in its parameters or return type",
name, name,
) MethodViolationCode::ReferencesSelfInput(_),
.into(), DUMMY_SP,
) => format!("method `{}` references the `Self` type in its parameters", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfInput(_), _) => {
format!("method `{}` references the `Self` type in this parameter", name).into()
}
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfOutput, _) => {
format!("method `{}` references the `Self` type in its return type", name).into()
}
ObjectSafetyViolation::Method( ObjectSafetyViolation::Method(
name, name,
MethodViolationCode::WhereClauseReferencesSelf, MethodViolationCode::WhereClauseReferencesSelf,
@ -78,23 +85,31 @@ impl ObjectSafetyViolation {
} }
} }
pub fn solution(&self) -> Option<String> { pub fn solution(&self) -> Option<(String, Option<(String, Span)>)> {
Some(match *self { Some(match *self {
ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf => { ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf => {
return None; return None;
} }
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) => format!( ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(sugg), _) => (
"consider turning `{}` into a method by giving it a `&self` argument or \ format!(
constraining it with `where Self: Sized`", "consider turning `{}` into a method by giving it a `&self` argument or \
name constraining it so it does not apply to trait objects",
name
),
sugg.map(|(sugg, sp)| (sugg.to_string(), sp)),
), ),
ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => { ObjectSafetyViolation::Method(
name,
MethodViolationCode::UndispatchableReceiver,
span,
) => (
format!("consider changing method `{}`'s `self` parameter to be `&self`", name) format!("consider changing method `{}`'s `self` parameter to be `&self`", name)
.into() .into(),
} Some(("&Self".to_string(), span)),
),
ObjectSafetyViolation::AssocConst(name, _) ObjectSafetyViolation::AssocConst(name, _)
| ObjectSafetyViolation::Method(name, ..) => { | ObjectSafetyViolation::Method(name, ..) => {
format!("consider moving `{}` to another trait", name) (format!("consider moving `{}` to another trait", name), None)
} }
}) })
} }
@ -119,10 +134,13 @@ impl ObjectSafetyViolation {
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum MethodViolationCode { pub enum MethodViolationCode {
/// e.g., `fn foo()` /// e.g., `fn foo()`
StaticMethod, StaticMethod(Option<(&'static str, Span)>),
/// e.g., `fn foo(&self, x: Self)` or `fn foo(&self) -> Self` /// e.g., `fn foo(&self, x: Self)`
ReferencesSelf, ReferencesSelfInput(usize),
/// e.g., `fn foo(&self) -> Self`
ReferencesSelfOutput,
/// e.g., `fn foo(&self) where Self: Clone` /// e.g., `fn foo(&self) where Self: Clone`
WhereClauseReferencesSelf, WhereClauseReferencesSelf,
@ -193,7 +211,7 @@ fn object_safety_violations_for_trait(
.filter(|item| item.kind == ty::AssocKind::Method) .filter(|item| item.kind == ty::AssocKind::Method)
.filter_map(|item| { .filter_map(|item| {
object_safety_violation_for_method(tcx, trait_def_id, &item) object_safety_violation_for_method(tcx, trait_def_id, &item)
.map(|code| ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span)) .map(|(code, span)| ObjectSafetyViolation::Method(item.ident.name, code, span))
}) })
.filter(|violation| { .filter(|violation| {
if let ObjectSafetyViolation::Method( if let ObjectSafetyViolation::Method(
@ -224,9 +242,15 @@ fn object_safety_violations_for_trait(
) )
}; };
err.span_label(*span, &msg); err.span_label(*span, &msg);
if let (Some(_), Some(note)) = (node, violation.solution()) { match (node, violation.solution()) {
(Some(_), Some((note, None))) => {
err.help(&note);
}
(Some(_), Some((note, Some((sugg, span))))) => {
err.span_suggestion(span, &note, sugg, Applicability::MachineApplicable);
}
// Only provide the help if its a local trait, otherwise it's not actionable. // Only provide the help if its a local trait, otherwise it's not actionable.
err.help(&note); _ => {}
} }
err.emit(); err.emit();
false false
@ -398,7 +422,7 @@ fn object_safety_violation_for_method(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
trait_def_id: DefId, trait_def_id: DefId,
method: &ty::AssocItem, method: &ty::AssocItem,
) -> Option<MethodViolationCode> { ) -> Option<(MethodViolationCode, Span)> {
debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method); debug!("object_safety_violation_for_method({:?}, {:?})", trait_def_id, method);
// Any method that has a `Self : Sized` requisite is otherwise // Any method that has a `Self : Sized` requisite is otherwise
// exempt from the regulations. // exempt from the regulations.
@ -406,7 +430,26 @@ fn object_safety_violation_for_method(
return None; return None;
} }
virtual_call_violation_for_method(tcx, trait_def_id, method) let violation = virtual_call_violation_for_method(tcx, trait_def_id, method);
// Get an accurate span depending on the violation.
violation.map(|v| {
let node = tcx.hir().get_if_local(method.def_id);
let span = match (v, node) {
(MethodViolationCode::ReferencesSelfInput(arg), Some(node)) => node
.fn_decl()
.and_then(|decl| decl.inputs.get(arg + 1))
.map_or(method.ident.span, |arg| arg.span),
(MethodViolationCode::UndispatchableReceiver, Some(node)) => node
.fn_decl()
.and_then(|decl| decl.inputs.get(0))
.map_or(method.ident.span, |arg| arg.span),
(MethodViolationCode::ReferencesSelfOutput, Some(node)) => {
node.fn_decl().map_or(method.ident.span, |decl| decl.output.span())
}
_ => method.ident.span,
};
(v, span)
})
} }
/// Returns `Some(_)` if this method cannot be called on a trait /// Returns `Some(_)` if this method cannot be called on a trait
@ -420,18 +463,26 @@ fn virtual_call_violation_for_method<'tcx>(
) -> Option<MethodViolationCode> { ) -> Option<MethodViolationCode> {
// The method's first parameter must be named `self` // The method's first parameter must be named `self`
if !method.method_has_self_argument { if !method.method_has_self_argument {
return Some(MethodViolationCode::StaticMethod); // We'll attempt to provide a structured suggestion for `Self: Sized`.
let sugg =
tcx.hir().get_if_local(method.def_id).as_ref().and_then(|node| node.generics()).map(
|generics| match generics.where_clause.predicates {
[] => (" where Self: Sized", generics.where_clause.span),
[.., pred] => (", Self: Sized", pred.span().shrink_to_hi()),
},
);
return Some(MethodViolationCode::StaticMethod(sugg));
} }
let sig = tcx.fn_sig(method.def_id); let sig = tcx.fn_sig(method.def_id);
for input_ty in &sig.skip_binder().inputs()[1..] { for (i, input_ty) in sig.skip_binder().inputs()[1..].iter().enumerate() {
if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) { if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
return Some(MethodViolationCode::ReferencesSelf); return Some(MethodViolationCode::ReferencesSelfInput(i));
} }
} }
if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output().skip_binder()) { if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output().skip_binder()) {
return Some(MethodViolationCode::ReferencesSelf); return Some(MethodViolationCode::ReferencesSelfOutput);
} }
// We can't monomorphize things like `fn foo<A>(...)`. // We can't monomorphize things like `fn foo<A>(...)`.

View File

@ -2631,4 +2631,25 @@ impl Node<'_> {
_ => None, _ => None,
} }
} }
pub fn fn_decl(&self) -> Option<&FnDecl<'_>> {
match self {
Node::TraitItem(TraitItem { kind: TraitItemKind::Method(fn_sig, _), .. })
| Node::ImplItem(ImplItem { kind: ImplItemKind::Method(fn_sig, _), .. })
| Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl),
Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
Some(fn_decl)
}
_ => None,
}
}
pub fn generics(&self) -> Option<&Generics<'_>> {
match self {
Node::TraitItem(TraitItem { generics, .. })
| Node::ImplItem(ImplItem { generics, .. })
| Node::Item(Item { kind: ItemKind::Fn(_, generics, _), .. }) => Some(generics),
_ => None,
}
}
} }

View File

@ -172,7 +172,7 @@ impl<'a> Parser<'a> {
/// ``` /// ```
pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> { pub(super) fn parse_where_clause(&mut self) -> PResult<'a, WhereClause> {
let mut where_clause = let mut where_clause =
WhereClause { predicates: Vec::new(), span: self.prev_span.to(self.prev_span) }; WhereClause { predicates: Vec::new(), span: self.prev_span.shrink_to_hi() };
if !self.eat_keyword(kw::Where) { if !self.eat_keyword(kw::Where) {
return Ok(where_clause); return Ok(where_clause);

View File

@ -2,7 +2,7 @@ error[E0038]: the trait `NotObjectSafe` cannot be made into an object
--> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:6 --> $DIR/coherence-impl-trait-for-trait-object-safe.rs:7:6
| |
LL | trait NotObjectSafe { fn eq(&self, other: Self); } LL | trait NotObjectSafe { fn eq(&self, other: Self); }
| ------------- -- ...because method `eq` references the `Self` type in its parameters or return type | ------------- ---- ...because method `eq` references the `Self` type in this parameter
| | | |
| this trait cannot be made into an object... | this trait cannot be made into an object...
LL | impl NotObjectSafe for dyn NotObjectSafe { } LL | impl NotObjectSafe for dyn NotObjectSafe { }

View File

@ -15,7 +15,10 @@ LL | fn foo();
LL | let trait_obj: &dyn SomeTrait = SomeTrait; LL | let trait_obj: &dyn SomeTrait = SomeTrait;
| ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
| |
= help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn foo() where Self: Sized;
| ^^^^^^^^^^^^^^^^^
error[E0033]: type `&dyn SomeTrait` cannot be dereferenced error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
--> $DIR/E0033-teach.rs:12:9 --> $DIR/E0033-teach.rs:12:9

View File

@ -15,7 +15,10 @@ LL | fn foo();
LL | let trait_obj: &dyn SomeTrait = SomeTrait; LL | let trait_obj: &dyn SomeTrait = SomeTrait;
| ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object | ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
| |
= help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn foo() where Self: Sized;
| ^^^^^^^^^^^^^^^^^
error[E0033]: type `&dyn SomeTrait` cannot be dereferenced error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
--> $DIR/E0033.rs:10:9 --> $DIR/E0033.rs:10:9

View File

@ -4,7 +4,7 @@ error[E0038]: the trait `Trait` cannot be made into an object
LL | trait Trait { LL | trait Trait {
| ----- this trait cannot be made into an object... | ----- this trait cannot be made into an object...
LL | fn foo(&self) -> Self; LL | fn foo(&self) -> Self;
| --- ...because method `foo` references the `Self` type in its parameters or return type | ---- ...because method `foo` references the `Self` type in its return type
... ...
LL | fn call_foo(x: Box<dyn Trait>) { LL | fn call_foo(x: Box<dyn Trait>) {
| ^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object | ^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object

View File

@ -20,7 +20,10 @@ LL | fn static_fn() {}
LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 { LL | fn return_non_object_safe_ref() -> &'static dyn NonObjectSafe2 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe2` cannot be made into an object | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe2` cannot be made into an object
| |
= help: consider turning `static_fn` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` help: consider turning `static_fn` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn static_fn() where Self: Sized {}
| ^^^^^^^^^^^^^^^^^
error[E0038]: the trait `NonObjectSafe3` cannot be made into an object error[E0038]: the trait `NonObjectSafe3` cannot be made into an object
--> $DIR/feature-gate-object_safe_for_dispatch.rs:27:35 --> $DIR/feature-gate-object_safe_for_dispatch.rs:27:35
@ -41,7 +44,7 @@ error[E0038]: the trait `NonObjectSafe4` cannot be made into an object
LL | trait NonObjectSafe4 { LL | trait NonObjectSafe4 {
| -------------- this trait cannot be made into an object... | -------------- this trait cannot be made into an object...
LL | fn foo(&self, &Self); LL | fn foo(&self, &Self);
| --- ...because method `foo` references the `Self` type in its parameters or return type | ----- ...because method `foo` references the `Self` type in this parameter
... ...
LL | fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> { LL | fn return_non_object_safe_rc() -> std::rc::Rc<dyn NonObjectSafe4> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe4` cannot be made into an object | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe4` cannot be made into an object

View File

@ -9,7 +9,10 @@ LL | fn foo() -> Self;
LL | fn car() -> dyn NotObjectSafe { LL | fn car() -> dyn NotObjectSafe {
| ^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object | ^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
| |
= help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn foo() -> Self where Self: Sized;
| ^^^^^^^^^^^^^^^^^
error[E0038]: the trait `NotObjectSafe` cannot be made into an object error[E0038]: the trait `NotObjectSafe` cannot be made into an object
--> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:28:13 --> $DIR/object-unsafe-trait-in-return-position-dyn-trait.rs:28:13
@ -22,7 +25,10 @@ LL | fn foo() -> Self;
LL | fn cat() -> Box<dyn NotObjectSafe> { LL | fn cat() -> Box<dyn NotObjectSafe> {
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object | ^^^^^^^^^^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
| |
= help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn foo() -> Self where Self: Sized;
| ^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -9,7 +9,10 @@ LL | fn qiz();
LL | foos: &'static [&'static (dyn Qiz + 'static)] LL | foos: &'static [&'static (dyn Qiz + 'static)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object
| |
= help: consider turning `qiz` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` help: consider turning `qiz` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn qiz() where Self: Sized;
| ^^^^^^^^^^^^^^^^^
error: aborting due to previous error error: aborting due to previous error

View File

@ -4,7 +4,7 @@ error[E0038]: the trait `Bar` cannot be made into an object
LL | trait Bar { LL | trait Bar {
| --- this trait cannot be made into an object... | --- this trait cannot be made into an object...
LL | fn bar(&self, x: &Self); LL | fn bar(&self, x: &Self);
| --- ...because method `bar` references the `Self` type in its parameters or return type | ----- ...because method `bar` references the `Self` type in this parameter
... ...
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar { LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
| ^^^^^^^^ the trait `Bar` cannot be made into an object | ^^^^^^^^ the trait `Bar` cannot be made into an object
@ -17,7 +17,7 @@ error[E0038]: the trait `Baz` cannot be made into an object
LL | trait Baz { LL | trait Baz {
| --- this trait cannot be made into an object... | --- this trait cannot be made into an object...
LL | fn baz(&self) -> Self; LL | fn baz(&self) -> Self;
| --- ...because method `baz` references the `Self` type in its parameters or return type | ---- ...because method `baz` references the `Self` type in its return type
... ...
LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz { LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
| ^^^^^^^^ the trait `Baz` cannot be made into an object | ^^^^^^^^ the trait `Baz` cannot be made into an object

View File

@ -4,7 +4,7 @@ error[E0038]: the trait `Bar` cannot be made into an object
LL | trait Bar { LL | trait Bar {
| --- this trait cannot be made into an object... | --- this trait cannot be made into an object...
LL | fn bar(&self, x: &Self); LL | fn bar(&self, x: &Self);
| --- ...because method `bar` references the `Self` type in its parameters or return type | ----- ...because method `bar` references the `Self` type in this parameter
... ...
LL | t LL | t
| ^ the trait `Bar` cannot be made into an object | ^ the trait `Bar` cannot be made into an object
@ -19,7 +19,7 @@ error[E0038]: the trait `Baz` cannot be made into an object
LL | trait Baz { LL | trait Baz {
| --- this trait cannot be made into an object... | --- this trait cannot be made into an object...
LL | fn baz(&self) -> Self; LL | fn baz(&self) -> Self;
| --- ...because method `baz` references the `Self` type in its parameters or return type | ---- ...because method `baz` references the `Self` type in its return type
... ...
LL | t LL | t
| ^ the trait `Baz` cannot be made into an object | ^ the trait `Baz` cannot be made into an object

View File

@ -9,7 +9,10 @@ LL | fn foo() {}
LL | fn diverges() -> Box<dyn Foo> { LL | fn diverges() -> Box<dyn Foo> {
| ^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | ^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
| |
= help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn foo() where Self: Sized {}
| ^^^^^^^^^^^^^^^^^
error: aborting due to previous error error: aborting due to previous error

View File

@ -9,9 +9,12 @@ LL | fn foo() {}
LL | let b: Box<dyn Foo> = Box::new(Bar); LL | let b: Box<dyn Foo> = Box::new(Bar);
| ^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | ^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
| |
= help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized`
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<Bar>` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Foo>>` for `std::boxed::Box<Bar>`
= note: required by cast to type `std::boxed::Box<dyn Foo>` = note: required by cast to type `std::boxed::Box<dyn Foo>`
help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn foo() where Self: Sized {}
| ^^^^^^^^^^^^^^^^^
error: aborting due to previous error error: aborting due to previous error

View File

@ -4,12 +4,13 @@ error[E0038]: the trait `Foo` cannot be made into an object
LL | trait Foo { LL | trait Foo {
| --- this trait cannot be made into an object... | --- this trait cannot be made into an object...
LL | fn foo(self: &Rc<Self>) -> usize; LL | fn foo(self: &Rc<Self>) -> usize;
| --- ...because method `foo`'s `self` parameter cannot be dispatched on | ---------
| |
| ...because method `foo`'s `self` parameter cannot be dispatched on
| help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self`
... ...
LL | let x = Rc::new(5usize) as Rc<dyn Foo>; LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
| ^^^^^^^^^^^ the trait `Foo` cannot be made into an object | ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= help: consider changing method `foo`'s `self` parameter to be `&self`
error[E0038]: the trait `Foo` cannot be made into an object error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/arbitrary-self-types-not-object-safe.rs:33:13 --> $DIR/arbitrary-self-types-not-object-safe.rs:33:13
@ -17,12 +18,14 @@ error[E0038]: the trait `Foo` cannot be made into an object
LL | trait Foo { LL | trait Foo {
| --- this trait cannot be made into an object... | --- this trait cannot be made into an object...
LL | fn foo(self: &Rc<Self>) -> usize; LL | fn foo(self: &Rc<Self>) -> usize;
| --- ...because method `foo`'s `self` parameter cannot be dispatched on | ---------
| |
| ...because method `foo`'s `self` parameter cannot be dispatched on
| help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self`
... ...
LL | let x = Rc::new(5usize) as Rc<dyn Foo>; LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
| ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
| |
= help: consider changing method `foo`'s `self` parameter to be `&self`
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
= note: required by cast to type `std::rc::Rc<dyn Foo>` = note: required by cast to type `std::rc::Rc<dyn Foo>`

View File

@ -4,12 +4,14 @@ error[E0038]: the trait `Foo` cannot be made into an object
LL | trait Foo { LL | trait Foo {
| --- this trait cannot be made into an object... | --- this trait cannot be made into an object...
LL | fn foo(self: &Rc<Self>) -> usize; LL | fn foo(self: &Rc<Self>) -> usize;
| --- ...because method `foo`'s `self` parameter cannot be dispatched on | ---------
| |
| ...because method `foo`'s `self` parameter cannot be dispatched on
| help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self`
... ...
LL | let x = Rc::new(5usize) as Rc<dyn Foo>; LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
| ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object | ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
| |
= help: consider changing method `foo`'s `self` parameter to be `&self`
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
= note: required by cast to type `std::rc::Rc<dyn Foo>` = note: required by cast to type `std::rc::Rc<dyn Foo>`

View File

@ -44,7 +44,10 @@ LL | fn f(a: B) -> B;
| | | |
| ...because associated function `f` has no `self` parameter | ...because associated function `f` has no `self` parameter
| |
= help: consider turning `f` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` help: consider turning `f` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn f(a: B) -> B where Self: Sized;
| ^^^^^^^^^^^^^^^^^
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View File

@ -9,9 +9,12 @@ LL | fn foo();
LL | let _: &dyn Tr = &St; LL | let _: &dyn Tr = &St;
| ^^^ the trait `Tr` cannot be made into an object | ^^^ the trait `Tr` cannot be made into an object
| |
= help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized`
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St` = note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St`
= note: required by cast to type `&dyn Tr` = note: required by cast to type `&dyn Tr`
help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn foo() where Self: Sized;
| ^^^^^^^^^^^^^^^^^
error[E0038]: the trait `Tr` cannot be made into an object error[E0038]: the trait `Tr` cannot be made into an object
--> $DIR/trait-object-safety.rs:15:12 --> $DIR/trait-object-safety.rs:15:12
@ -24,7 +27,10 @@ LL | fn foo();
LL | let _: &dyn Tr = &St; LL | let _: &dyn Tr = &St;
| ^^^^^^^ the trait `Tr` cannot be made into an object | ^^^^^^^ the trait `Tr` cannot be made into an object
| |
= help: consider turning `foo` into a method by giving it a `&self` argument or constraining it with `where Self: Sized` help: consider turning `foo` into a method by giving it a `&self` argument or constraining it so it does not apply to trait objects
|
LL | fn foo() where Self: Sized;
| ^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -14,9 +14,9 @@ error[E0038]: the trait `bar` cannot be made into an object
--> $DIR/trait-test-2.rs:11:16 --> $DIR/trait-test-2.rs:11:16
| |
LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
| --- --- ---- ...because method `blah` has generic type parameters | --- ---- ---- ...because method `blah` has generic type parameters
| | | | | |
| | ...because method `dup` references the `Self` type in its parameters or return type | | ...because method `dup` references the `Self` type in its return type
| this trait cannot be made into an object... | this trait cannot be made into an object...
... ...
LL | (box 10 as Box<dyn bar>).dup(); LL | (box 10 as Box<dyn bar>).dup();
@ -29,9 +29,9 @@ error[E0038]: the trait `bar` cannot be made into an object
--> $DIR/trait-test-2.rs:11:6 --> $DIR/trait-test-2.rs:11:6
| |
LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); } LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
| --- --- ---- ...because method `blah` has generic type parameters | --- ---- ---- ...because method `blah` has generic type parameters
| | | | | |
| | ...because method `dup` references the `Self` type in its parameters or return type | | ...because method `dup` references the `Self` type in its return type
| this trait cannot be made into an object... | this trait cannot be made into an object...
... ...
LL | (box 10 as Box<dyn bar>).dup(); LL | (box 10 as Box<dyn bar>).dup();

View File

@ -14,7 +14,7 @@ error[E0038]: the trait `MyAdd` cannot be made into an object
--> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18 --> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18
| |
LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; } LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
| ----- --- ...because method `add` references the `Self` type in its parameters or return type | ----- ---- ...because method `add` references the `Self` type in its return type
| | | |
| this trait cannot be made into an object... | this trait cannot be made into an object...
... ...

View File

@ -4,7 +4,7 @@ error[E0038]: the trait `A` cannot be made into an object
LL | trait A { LL | trait A {
| - this trait cannot be made into an object... | - this trait cannot be made into an object...
LL | fn foo(&self, _x: &Self); LL | fn foo(&self, _x: &Self);
| --- ...because method `foo` references the `Self` type in its parameters or return type | ----- ...because method `foo` references the `Self` type in this parameter
... ...
LL | let _x: &dyn A; LL | let _x: &dyn A;
| ^^^^^^ the trait `A` cannot be made into an object | ^^^^^^ the trait `A` cannot be made into an object