On object safety violation, point at source when possible

This commit is contained in:
Esteban Küber 2019-09-02 20:22:22 -07:00
parent 3ea932ab0e
commit c1e5e5c567
26 changed files with 129 additions and 84 deletions

View File

@ -1384,7 +1384,10 @@ impl<'tcx> TyCtxt<'tcx> {
let mut reported_violations = FxHashSet::default();
for violation in violations {
if reported_violations.insert(violation.clone()) {
err.note(&violation.error_msg());
match violation.span() {
Some(span) => err.span_label(span, violation.error_msg()),
None => err.note(&violation.error_msg()),
};
}
}
Some(err)

View File

@ -32,10 +32,10 @@ pub enum ObjectSafetyViolation {
SupertraitSelf,
/// Method has something illegal.
Method(ast::Name, MethodViolationCode),
Method(ast::Name, MethodViolationCode, Span),
/// Associated const.
AssocConst(ast::Name),
AssocConst(ast::Name, Span),
}
impl ObjectSafetyViolation {
@ -46,24 +46,33 @@ impl ObjectSafetyViolation {
ObjectSafetyViolation::SupertraitSelf =>
"the trait cannot use `Self` as a type parameter \
in the supertraits or where-clauses".into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) =>
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) =>
format!("associated function `{}` has no `self` parameter", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => format!(
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!(
"method `{}` references the `Self` type in its arguments or return type",
name,
).into(),
ObjectSafetyViolation::Method(
name,
MethodViolationCode::WhereClauseReferencesSelf(_),
MethodViolationCode::WhereClauseReferencesSelf,
_,
) => format!("method `{}` references the `Self` type in where clauses", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) =>
format!("method `{}` has generic type parameters", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) =>
ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) =>
format!("method `{}`'s receiver cannot be dispatched on", name).into(),
ObjectSafetyViolation::AssocConst(name) =>
ObjectSafetyViolation::AssocConst(name, _) =>
format!("the trait cannot contain associated consts like `{}`", name).into(),
}
}
pub fn span(&self) -> Option<Span> {
match self {
ObjectSafetyViolation::AssocConst(_, span) |
ObjectSafetyViolation::Method(_, _, span) => Some(*span),
_ => None,
}
}
}
/// Reasons a method might not be object-safe.
@ -76,7 +85,7 @@ pub enum MethodViolationCode {
ReferencesSelf,
/// e.g., `fn foo(&self) where Self: Clone`
WhereClauseReferencesSelf(Span),
WhereClauseReferencesSelf,
/// e.g., `fn foo<A>()`
Generic,
@ -90,9 +99,10 @@ impl<'tcx> TyCtxt<'tcx> {
/// astconv -- currently, `Self` in supertraits. This is needed
/// because `object_safety_violations` can't be used during
/// type collection.
pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
-> Vec<ObjectSafetyViolation>
{
pub fn astconv_object_safety_violations(
self,
trait_def_id: DefId,
) -> Vec<ObjectSafetyViolation> {
debug_assert!(self.generics_of(trait_def_id).has_self);
let violations = traits::supertrait_def_ids(self, trait_def_id)
.filter(|&def_id| self.predicates_reference_self(def_id, true))
@ -130,7 +140,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
match self.virtual_call_violation_for_method(trait_def_id, method) {
None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true,
Some(_) => false,
}
}
@ -140,12 +150,15 @@ impl<'tcx> TyCtxt<'tcx> {
let mut violations: Vec<_> = self.associated_items(trait_def_id)
.filter(|item| item.kind == ty::AssocKind::Method)
.filter_map(|item|
self.object_safety_violation_for_method(trait_def_id, &item)
.map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
self.object_safety_violation_for_method(trait_def_id, &item).map(|code| {
ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span)
})
).filter(|violation| {
if let ObjectSafetyViolation::Method(_,
MethodViolationCode::WhereClauseReferencesSelf(span)) = violation
{
if let ObjectSafetyViolation::Method(
_,
MethodViolationCode::WhereClauseReferencesSelf,
span,
) = violation {
// Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
// It's also hard to get a use site span, so we use the method definition span.
self.lint_node_note(
@ -171,7 +184,7 @@ impl<'tcx> TyCtxt<'tcx> {
violations.extend(self.associated_items(trait_def_id)
.filter(|item| item.kind == ty::AssocKind::Const)
.map(|item| ObjectSafetyViolation::AssocConst(item.ident.name)));
.map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)));
debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
trait_def_id,
@ -327,8 +340,7 @@ impl<'tcx> TyCtxt<'tcx> {
.visit_tys_shallow(|t| {
self.contains_illegal_self_type_reference(trait_def_id, t)
}) {
let span = self.def_span(method.def_id);
return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
return Some(MethodViolationCode::WhereClauseReferencesSelf);
}
let receiver_ty = self.liberate_late_bound_regions(

View File

@ -1,10 +1,11 @@
error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/associated-const-in-trait.rs:9:6
|
LL | const N: usize;
| - the trait cannot contain associated consts like `N`
...
LL | impl dyn Trait {
| ^^^^^^^^^ the trait `Trait` cannot be made into an object
|
= note: the trait cannot contain associated consts like `N`
error: aborting due to previous error

View File

@ -1,10 +1,10 @@
error[E0038]: the trait `NotObjectSafe` cannot be made into an object
--> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6
|
LL | trait NotObjectSafe { fn eq(&self, other: Self); }
| -- method `eq` references the `Self` type in its arguments or return type
LL | impl NotObjectSafe for dyn NotObjectSafe { }
| ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
|
= note: method `eq` references the `Self` type in its arguments or return type
error: aborting due to previous error

View File

@ -1,10 +1,10 @@
error[E0038]: the trait `NotObjectSafe` cannot be made into an object
--> $DIR/coherence-impl-trait-for-trait-object-safe.rs:11:6
|
LL | trait NotObjectSafe { fn eq(&self, other: Self); }
| -- method `eq` references the `Self` type in its arguments or return type
LL | impl NotObjectSafe for dyn NotObjectSafe { }
| ^^^^^^^^^^^^^ the trait `NotObjectSafe` cannot be made into an object
|
= note: method `eq` references the `Self` type in its arguments or return type
error: aborting due to previous error

View File

@ -61,8 +61,9 @@ 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: associated function `xxx` has no `self` parameter
...
LL | fn xxx() { ### }
| --- associated function `xxx` has no `self` parameter
error: aborting due to 9 previous errors

View File

@ -1,14 +1,13 @@
// compile-flags: -Z teach
trait SomeTrait {
fn foo();
fn foo(); //~ associated function `foo` has no `self` parameter
}
fn main() {
let trait_obj: &dyn SomeTrait = SomeTrait;
//~^ ERROR expected value, found trait `SomeTrait`
//~| ERROR E0038
//~| associated function `foo` has no `self` parameter
let &invalid = trait_obj;
//~^ ERROR E0033

View File

@ -7,13 +7,14 @@ LL | let trait_obj: &dyn SomeTrait = SomeTrait;
error[E0038]: the trait `SomeTrait` cannot be made into an object
--> $DIR/E0033-teach.rs:8:20
|
LL | fn foo();
| --- associated function `foo` has no `self` parameter
...
LL | let trait_obj: &dyn SomeTrait = SomeTrait;
| ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
|
= note: associated function `foo` has no `self` parameter
error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
--> $DIR/E0033-teach.rs:13:9
--> $DIR/E0033-teach.rs:12:9
|
LL | let &invalid = trait_obj;
| ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced

View File

@ -1,12 +1,11 @@
trait SomeTrait {
fn foo();
fn foo(); //~ associated function `foo` has no `self` parameter
}
fn main() {
let trait_obj: &dyn SomeTrait = SomeTrait;
//~^ ERROR expected value, found trait `SomeTrait`
//~| ERROR E0038
//~| associated function `foo` has no `self` parameter
let &invalid = trait_obj;
//~^ ERROR E0033

View File

@ -7,13 +7,14 @@ LL | let trait_obj: &dyn SomeTrait = SomeTrait;
error[E0038]: the trait `SomeTrait` cannot be made into an object
--> $DIR/E0033.rs:6:20
|
LL | fn foo();
| --- associated function `foo` has no `self` parameter
...
LL | let trait_obj: &dyn SomeTrait = SomeTrait;
| ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
|
= note: associated function `foo` has no `self` parameter
error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
--> $DIR/E0033.rs:11:9
--> $DIR/E0033.rs:10:9
|
LL | let &invalid = trait_obj;
| ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced

View File

@ -1,10 +1,11 @@
error[E0038]: the trait `Trait` cannot be made into an object
--> $DIR/E0038.rs:5:1
|
LL | fn foo(&self) -> Self;
| --- method `foo` references the `Self` type in its arguments or return type
...
LL | fn call_foo(x: Box<dyn Trait>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
= note: method `foo` references the `Self` type in its arguments or return type
error: aborting due to previous error

View File

@ -1,10 +1,11 @@
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/issue-18959.rs:11:1
|
LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
| --- method `foo` has generic type parameters
...
LL | fn foo(b: &dyn Bar) {
| ^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `foo` has generic type parameters
error: aborting due to previous error

View File

@ -1,10 +1,11 @@
error[E0038]: the trait `Qiz` cannot be made into an object
--> $DIR/issue-19380.rs:11:3
|
LL | fn qiz();
| --- associated function `qiz` has no `self` parameter
...
LL | foos: &'static [&'static (dyn Qiz + 'static)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object
|
= note: associated function `qiz` has no `self` parameter
error: aborting due to previous error

View File

@ -1,18 +1,21 @@
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/issue-19538.rs:17:15
|
LL | fn foo<T>(&self, val: T);
| --- method `foo` has generic type parameters
...
LL | let test: &mut dyn Bar = &mut thing;
| ^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `foo` has generic type parameters
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/issue-19538.rs:17:30
|
LL | fn foo<T>(&self, val: T);
| --- method `foo` has generic type parameters
...
LL | let test: &mut dyn Bar = &mut thing;
| ^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `foo` has generic type parameters
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
error: aborting due to 2 previous errors

View File

@ -1,8 +1,8 @@
error: the trait `X` cannot be made into an object
--> $DIR/issue-50781.rs:6:5
--> $DIR/issue-50781.rs:6:8
|
LL | fn foo(&self) where Self: Trait;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^
|
note: lint level defined here
--> $DIR/issue-50781.rs:1:9

View File

@ -1,10 +1,11 @@
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-associated-consts.rs:9:1
|
LL | const X: usize;
| - the trait cannot contain associated consts like `X`
...
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: the trait cannot contain associated consts like `X`
error: aborting due to previous error

View File

@ -1,18 +1,20 @@
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-generics.rs:14:1
|
LL | fn bar<T>(&self, t: T);
| --- method `bar` has generic type parameters
...
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `bar` has generic type parameters
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-generics.rs:19:1
|
LL | fn bar<T>(&self, t: T);
| --- method `bar` has generic type parameters
...
LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `bar` has generic type parameters
error: aborting due to 2 previous errors

View File

@ -1,18 +1,20 @@
error[E0038]: the trait `Bar` cannot be made into an object
--> $DIR/object-safety-mentions-Self.rs:17:1
|
LL | fn bar(&self, x: &Self);
| --- method `bar` references the `Self` type in its arguments or return type
...
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
|
= note: method `bar` references the `Self` type in its arguments or return type
error[E0038]: the trait `Baz` cannot be made into an object
--> $DIR/object-safety-mentions-Self.rs:22:1
|
LL | fn bar(&self) -> Self;
| --- method `bar` references the `Self` type in its arguments or return type
...
LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object
|
= note: method `bar` references the `Self` type in its arguments or return type
error: aborting due to 2 previous errors

View File

@ -1,10 +1,11 @@
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/object-safety-no-static.rs:8:1
|
LL | fn foo();
| --- associated function `foo` has no `self` parameter
...
LL | fn foo_implicit<T:Foo+'static>(b: Box<T>) -> Box<dyn Foo + 'static> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: associated function `foo` has no `self` parameter
error: aborting due to previous error

View File

@ -3,8 +3,6 @@ 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: associated function `bar` has no `self` parameter
error: aborting due to previous error

View File

@ -1,18 +1,21 @@
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/arbitrary-self-types-not-object-safe.rs:31:32
|
LL | fn foo(self: &Rc<Self>) -> usize;
| --- method `foo`'s receiver cannot be dispatched on
...
LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
| ^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: method `foo`'s receiver cannot be dispatched on
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/arbitrary-self-types-not-object-safe.rs:31:13
|
LL | fn foo(self: &Rc<Self>) -> usize;
| --- method `foo`'s receiver cannot be dispatched on
...
LL | let x = Rc::new(5usize) as Rc<dyn Foo>;
| ^^^^^^^^^^^^^^^ the trait `Foo` cannot be made into an object
|
= note: method `foo`'s receiver cannot be dispatched on
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::rc::Rc<dyn Foo>>` for `std::rc::Rc<usize>`
error: aborting due to 2 previous errors

View File

@ -103,12 +103,17 @@ LL | C::A;
error[E0038]: the trait `assoc_const::C` cannot be made into an object
--> $DIR/trait-item-privacy.rs:101:5
|
LL | const A: u8 = 0;
| - the trait cannot contain associated consts like `A`
...
LL | const B: u8 = 0;
| - the trait cannot contain associated consts like `B`
...
LL | const C: u8 = 0;
| - the trait cannot contain associated consts like `C`
...
LL | C::A;
| ^^^^ the trait `assoc_const::C` cannot be made into an object
|
= note: the trait cannot contain associated consts like `C`
= note: the trait cannot contain associated consts like `B`
= note: the trait cannot contain associated consts like `A`
error[E0223]: ambiguous associated type
--> $DIR/trait-item-privacy.rs:115:12

View File

@ -1,19 +1,22 @@
error[E0038]: the trait `Tr` cannot be made into an object
--> $DIR/trait-object-safety.rs:15:22
|
LL | fn foo();
| --- associated function `foo` has no `self` parameter
...
LL | let _: &dyn Tr = &St;
| ^^^ the trait `Tr` cannot be made into an object
|
= note: associated function `foo` has no `self` parameter
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Tr>` for `&St`
error[E0038]: the trait `Tr` cannot be made into an object
--> $DIR/trait-object-safety.rs:15:12
|
LL | fn foo();
| --- associated function `foo` has no `self` parameter
...
LL | let _: &dyn Tr = &St;
| ^^^^^^^ the trait `Tr` cannot be made into an object
|
= note: associated function `foo` has no `self` parameter
error: aborting due to 2 previous errors

View File

@ -13,20 +13,25 @@ LL | 10.blah::<i32, i32>();
error[E0038]: the trait `bar` cannot be made into an object
--> $DIR/trait-test-2.rs:11:16
|
LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
| --- ---- method `blah` has generic type parameters
| |
| method `dup` references the `Self` type in its arguments or return type
...
LL | (box 10 as Box<dyn bar>).dup();
| ^^^^^^^^^^^^ the trait `bar` cannot be made into an object
|
= note: method `dup` references the `Self` type in its arguments or return type
= note: method `blah` has generic type parameters
error[E0038]: the trait `bar` cannot be made into an object
--> $DIR/trait-test-2.rs:11:6
|
LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
| --- ---- method `blah` has generic type parameters
| |
| method `dup` references the `Self` type in its arguments or return type
...
LL | (box 10 as Box<dyn bar>).dup();
| ^^^^^^ the trait `bar` cannot be made into an object
|
= note: method `dup` references the `Self` type in its arguments or return type
= note: method `blah` has generic type parameters
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn bar>>` for `std::boxed::Box<{integer}>`
error: aborting due to 4 previous errors

View File

@ -13,10 +13,11 @@ LL | let y = x as dyn MyAdd<i32>;
error[E0038]: the trait `MyAdd` cannot be made into an object
--> $DIR/type-parameter-defaults-referencing-Self-ppaux.rs:14:18
|
LL | trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
| --- method `add` references the `Self` type in its arguments or return type
...
LL | let y = x as dyn MyAdd<i32>;
| ^^^^^^^^^^^^^^ the trait `MyAdd` cannot be made into an object
|
= note: method `add` references the `Self` type in its arguments or return type
error: aborting due to 2 previous errors

View File

@ -1,10 +1,11 @@
error[E0038]: the trait `A` cannot be made into an object
--> $DIR/wf-object-safe.rs:9:13
|
LL | fn foo(&self, _x: &Self);
| --- method `foo` references the `Self` type in its arguments or return type
...
LL | let _x: &dyn A;
| ^^^^^^ the trait `A` cannot be made into an object
|
= note: method `foo` references the `Self` type in its arguments or return type
error: aborting due to previous error