Skip to content

Commit c1e5e5c

Browse files
committed
On object safety violation, point at source when possible
1 parent 3ea932a commit c1e5e5c

26 files changed

+129
-84
lines changed

src/librustc/traits/error_reporting.rs

Lines changed: 4 additions & 1 deletion
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

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -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,24 +46,33 @@ 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) =>
49+
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod, _) =>
5050
format!("associated function `{}` has no `self` parameter", name).into(),
51-
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) => format!(
51+
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf, _) => format!(
5252
"method `{}` references the `Self` type in its arguments or return type",
5353
name,
5454
).into(),
5555
ObjectSafetyViolation::Method(
5656
name,
57-
MethodViolationCode::WhereClauseReferencesSelf(_),
57+
MethodViolationCode::WhereClauseReferencesSelf,
58+
_,
5859
) => format!("method `{}` references the `Self` type in where clauses", name).into(),
59-
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
60+
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) =>
6061
format!("method `{}` has generic type parameters", name).into(),
61-
ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver) =>
62+
ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) =>
6263
format!("method `{}`'s receiver cannot be dispatched on", name).into(),
63-
ObjectSafetyViolation::AssocConst(name) =>
64+
ObjectSafetyViolation::AssocConst(name, _) =>
6465
format!("the trait cannot contain associated consts like `{}`", name).into(),
6566
}
6667
}
68+
69+
pub fn span(&self) -> Option<Span> {
70+
match self {
71+
ObjectSafetyViolation::AssocConst(_, span) |
72+
ObjectSafetyViolation::Method(_, _, span) => Some(*span),
73+
_ => None,
74+
}
75+
}
6776
}
6877

6978
/// Reasons a method might not be object-safe.
@@ -76,7 +85,7 @@ pub enum MethodViolationCode {
7685
ReferencesSelf,
7786

7887
/// e.g., `fn foo(&self) where Self: Clone`
79-
WhereClauseReferencesSelf(Span),
88+
WhereClauseReferencesSelf,
8089

8190
/// e.g., `fn foo<A>()`
8291
Generic,
@@ -90,9 +99,10 @@ impl<'tcx> TyCtxt<'tcx> {
9099
/// astconv -- currently, `Self` in supertraits. This is needed
91100
/// because `object_safety_violations` can't be used during
92101
/// type collection.
93-
pub fn astconv_object_safety_violations(self, trait_def_id: DefId)
94-
-> Vec<ObjectSafetyViolation>
95-
{
102+
pub fn astconv_object_safety_violations(
103+
self,
104+
trait_def_id: DefId,
105+
) -> Vec<ObjectSafetyViolation> {
96106
debug_assert!(self.generics_of(trait_def_id).has_self);
97107
let violations = traits::supertrait_def_ids(self, trait_def_id)
98108
.filter(|&def_id| self.predicates_reference_self(def_id, true))
@@ -130,7 +140,7 @@ impl<'tcx> TyCtxt<'tcx> {
130140
}
131141

132142
match self.virtual_call_violation_for_method(trait_def_id, method) {
133-
None | Some(MethodViolationCode::WhereClauseReferencesSelf(_)) => true,
143+
None | Some(MethodViolationCode::WhereClauseReferencesSelf) => true,
134144
Some(_) => false,
135145
}
136146
}
@@ -140,12 +150,15 @@ impl<'tcx> TyCtxt<'tcx> {
140150
let mut violations: Vec<_> = self.associated_items(trait_def_id)
141151
.filter(|item| item.kind == ty::AssocKind::Method)
142152
.filter_map(|item|
143-
self.object_safety_violation_for_method(trait_def_id, &item)
144-
.map(|code| ObjectSafetyViolation::Method(item.ident.name, code))
153+
self.object_safety_violation_for_method(trait_def_id, &item).map(|code| {
154+
ObjectSafetyViolation::Method(item.ident.name, code, item.ident.span)
155+
})
145156
).filter(|violation| {
146-
if let ObjectSafetyViolation::Method(_,
147-
MethodViolationCode::WhereClauseReferencesSelf(span)) = violation
148-
{
157+
if let ObjectSafetyViolation::Method(
158+
_,
159+
MethodViolationCode::WhereClauseReferencesSelf,
160+
span,
161+
) = violation {
149162
// Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
150163
// It's also hard to get a use site span, so we use the method definition span.
151164
self.lint_node_note(
@@ -171,7 +184,7 @@ impl<'tcx> TyCtxt<'tcx> {
171184

172185
violations.extend(self.associated_items(trait_def_id)
173186
.filter(|item| item.kind == ty::AssocKind::Const)
174-
.map(|item| ObjectSafetyViolation::AssocConst(item.ident.name)));
187+
.map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)));
175188

176189
debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
177190
trait_def_id,
@@ -327,8 +340,7 @@ impl<'tcx> TyCtxt<'tcx> {
327340
.visit_tys_shallow(|t| {
328341
self.contains_illegal_self_type_reference(trait_def_id, t)
329342
}) {
330-
let span = self.def_span(method.def_id);
331-
return Some(MethodViolationCode::WhereClauseReferencesSelf(span));
343+
return Some(MethodViolationCode::WhereClauseReferencesSelf);
332344
}
333345

334346
let receiver_ty = self.liberate_late_bound_regions(

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

Lines changed: 3 additions & 2 deletions
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

Lines changed: 2 additions & 2 deletions
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 arguments 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

Lines changed: 2 additions & 2 deletions
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 arguments 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

Lines changed: 3 additions & 2 deletions
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: associated function `xxx` has no `self` parameter
64+
...
65+
LL | fn xxx() { ### }
66+
| --- associated function `xxx` has no `self` parameter
6667

6768
error: aborting due to 9 previous errors
6869

src/test/ui/error-codes/E0033-teach.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
// compile-flags: -Z teach
22

33
trait SomeTrait {
4-
fn foo();
4+
fn foo(); //~ associated function `foo` has no `self` parameter
55
}
66

77
fn main() {
88
let trait_obj: &dyn SomeTrait = SomeTrait;
99
//~^ ERROR expected value, found trait `SomeTrait`
1010
//~| ERROR E0038
11-
//~| associated function `foo` has no `self` parameter
1211

1312
let &invalid = trait_obj;
1413
//~^ ERROR E0033

src/test/ui/error-codes/E0033-teach.stderr

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ LL | let trait_obj: &dyn SomeTrait = SomeTrait;
77
error[E0038]: the trait `SomeTrait` cannot be made into an object
88
--> $DIR/E0033-teach.rs:8:20
99
|
10+
LL | fn foo();
11+
| --- associated function `foo` has no `self` parameter
12+
...
1013
LL | let trait_obj: &dyn SomeTrait = SomeTrait;
1114
| ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
12-
|
13-
= note: associated function `foo` has no `self` parameter
1415

1516
error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
16-
--> $DIR/E0033-teach.rs:13:9
17+
--> $DIR/E0033-teach.rs:12:9
1718
|
1819
LL | let &invalid = trait_obj;
1920
| ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced

src/test/ui/error-codes/E0033.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
trait SomeTrait {
2-
fn foo();
2+
fn foo(); //~ associated function `foo` has no `self` parameter
33
}
44

55
fn main() {
66
let trait_obj: &dyn SomeTrait = SomeTrait;
77
//~^ ERROR expected value, found trait `SomeTrait`
88
//~| ERROR E0038
9-
//~| associated function `foo` has no `self` parameter
109

1110
let &invalid = trait_obj;
1211
//~^ ERROR E0033

src/test/ui/error-codes/E0033.stderr

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ LL | let trait_obj: &dyn SomeTrait = SomeTrait;
77
error[E0038]: the trait `SomeTrait` cannot be made into an object
88
--> $DIR/E0033.rs:6:20
99
|
10+
LL | fn foo();
11+
| --- associated function `foo` has no `self` parameter
12+
...
1013
LL | let trait_obj: &dyn SomeTrait = SomeTrait;
1114
| ^^^^^^^^^^^^^^ the trait `SomeTrait` cannot be made into an object
12-
|
13-
= note: associated function `foo` has no `self` parameter
1415

1516
error[E0033]: type `&dyn SomeTrait` cannot be dereferenced
16-
--> $DIR/E0033.rs:11:9
17+
--> $DIR/E0033.rs:10:9
1718
|
1819
LL | let &invalid = trait_obj;
1920
| ^^^^^^^^ type `&dyn SomeTrait` cannot be dereferenced

src/test/ui/error-codes/E0038.stderr

Lines changed: 3 additions & 2 deletions
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/E0038.rs:5:1
33
|
4+
LL | fn foo(&self) -> Self;
5+
| --- method `foo` references the `Self` type in its arguments or return type
6+
...
47
LL | fn call_foo(x: Box<dyn Trait>) {
58
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` cannot be made into an object
6-
|
7-
= note: method `foo` references the `Self` type in its arguments or return type
89

910
error: aborting due to previous error
1011

src/test/ui/issues/issue-18959.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
error[E0038]: the trait `Bar` cannot be made into an object
22
--> $DIR/issue-18959.rs:11:1
33
|
4+
LL | pub trait Foo { fn foo<T>(&self, ext_thing: &T); }
5+
| --- method `foo` has generic type parameters
6+
...
47
LL | fn foo(b: &dyn Bar) {
58
| ^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
6-
|
7-
= note: method `foo` has generic type parameters
89

910
error: aborting due to previous error
1011

src/test/ui/issues/issue-19380.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
error[E0038]: the trait `Qiz` cannot be made into an object
22
--> $DIR/issue-19380.rs:11:3
33
|
4+
LL | fn qiz();
5+
| --- associated function `qiz` has no `self` parameter
6+
...
47
LL | foos: &'static [&'static (dyn Qiz + 'static)]
58
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Qiz` cannot be made into an object
6-
|
7-
= note: associated function `qiz` has no `self` parameter
89

910
error: aborting due to previous error
1011

src/test/ui/issues/issue-19538.stderr

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
error[E0038]: the trait `Bar` cannot be made into an object
22
--> $DIR/issue-19538.rs:17:15
33
|
4+
LL | fn foo<T>(&self, val: T);
5+
| --- method `foo` has generic type parameters
6+
...
47
LL | let test: &mut dyn Bar = &mut thing;
58
| ^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
6-
|
7-
= note: method `foo` has generic type parameters
89

910
error[E0038]: the trait `Bar` cannot be made into an object
1011
--> $DIR/issue-19538.rs:17:30
1112
|
13+
LL | fn foo<T>(&self, val: T);
14+
| --- method `foo` has generic type parameters
15+
...
1216
LL | let test: &mut dyn Bar = &mut thing;
1317
| ^^^^^^^^^^ the trait `Bar` cannot be made into an object
1418
|
15-
= note: method `foo` has generic type parameters
1619
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
1720

1821
error: aborting due to 2 previous errors

src/test/ui/issues/issue-50781.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: the trait `X` cannot be made into an object
2-
--> $DIR/issue-50781.rs:6:5
2+
--> $DIR/issue-50781.rs:6:8
33
|
44
LL | fn foo(&self) where Self: Trait;
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^
66
|
77
note: lint level defined here
88
--> $DIR/issue-50781.rs:1:9

src/test/ui/object-safety/object-safety-associated-consts.stderr

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
error[E0038]: the trait `Bar` cannot be made into an object
22
--> $DIR/object-safety-associated-consts.rs:9:1
33
|
4+
LL | const X: usize;
5+
| - the trait cannot contain associated consts like `X`
6+
...
47
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
58
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
6-
|
7-
= note: the trait cannot contain associated consts like `X`
89

910
error: aborting due to previous error
1011

src/test/ui/object-safety/object-safety-generics.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
error[E0038]: the trait `Bar` cannot be made into an object
22
--> $DIR/object-safety-generics.rs:14:1
33
|
4+
LL | fn bar<T>(&self, t: T);
5+
| --- method `bar` has generic type parameters
6+
...
47
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
58
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
6-
|
7-
= note: method `bar` has generic type parameters
89

910
error[E0038]: the trait `Bar` cannot be made into an object
1011
--> $DIR/object-safety-generics.rs:19:1
1112
|
13+
LL | fn bar<T>(&self, t: T);
14+
| --- method `bar` has generic type parameters
15+
...
1216
LL | fn make_bar_explicit<T:Bar>(t: &T) -> &dyn Bar {
1317
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
14-
|
15-
= note: method `bar` has generic type parameters
1618

1719
error: aborting due to 2 previous errors
1820

src/test/ui/object-safety/object-safety-mentions-Self.stderr

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
error[E0038]: the trait `Bar` cannot be made into an object
22
--> $DIR/object-safety-mentions-Self.rs:17:1
33
|
4+
LL | fn bar(&self, x: &Self);
5+
| --- method `bar` references the `Self` type in its arguments or return type
6+
...
47
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
58
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` cannot be made into an object
6-
|
7-
= note: method `bar` references the `Self` type in its arguments or return type
89

910
error[E0038]: the trait `Baz` cannot be made into an object
1011
--> $DIR/object-safety-mentions-Self.rs:22:1
1112
|
13+
LL | fn bar(&self) -> Self;
14+
| --- method `bar` references the `Self` type in its arguments or return type
15+
...
1216
LL | fn make_baz<T:Baz>(t: &T) -> &dyn Baz {
1317
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Baz` cannot be made into an object
14-
|
15-
= note: method `bar` references the `Self` type in its arguments or return type
1618

1719
error: aborting due to 2 previous errors
1820

0 commit comments

Comments
 (0)