Skip to content

Commit 4b2f1db

Browse files
committed
Tweak Self: Sized restriction diagnostic output
1 parent d137b7a commit 4b2f1db

13 files changed

+68
-61
lines changed

src/librustc/traits/error_reporting/mod.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1046,11 +1046,22 @@ pub fn report_object_safety_error(
10461046

10471047
let mut reported_violations = FxHashSet::default();
10481048
for violation in violations {
1049+
if let ObjectSafetyViolation::SizedSelf(sp) = &violation {
1050+
if !sp.is_empty() {
1051+
// Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
1052+
// with a `Span`.
1053+
reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
1054+
}
1055+
}
10491056
if reported_violations.insert(violation.clone()) {
1050-
match violation.span() {
1051-
Some(span) => err.span_label(span, violation.error_msg()),
1052-
None => err.note(&violation.error_msg()),
1053-
};
1057+
let spans = violation.spans();
1058+
if spans.is_empty() {
1059+
err.note(&violation.error_msg());
1060+
} else {
1061+
for span in spans {
1062+
err.span_label(span, violation.error_msg());
1063+
}
1064+
}
10541065
}
10551066
}
10561067

src/librustc/traits/object_safety.rs

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@ use rustc_hir::def_id::DefId;
1818
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
1919
use rustc_span::symbol::Symbol;
2020
use rustc_span::{Span, DUMMY_SP};
21+
use smallvec::SmallVec;
2122
use syntax::ast;
2223

2324
use std::borrow::Cow;
2425
use std::iter::{self};
2526

26-
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
27+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
2728
pub enum ObjectSafetyViolation {
2829
/// `Self: Sized` declared on the trait.
29-
SizedSelf(Span),
30+
SizedSelf(SmallVec<[Span; 1]>),
3031

3132
/// Supertrait reference references `Self` an in illegal location
3233
/// (e.g., `trait Foo : Bar<Self>`).
@@ -75,18 +76,18 @@ impl ObjectSafetyViolation {
7576
}
7677
}
7778

78-
pub fn span(&self) -> Option<Span> {
79+
pub fn spans(&self) -> SmallVec<[Span; 1]> {
7980
// When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
8081
// diagnostics use a `note` instead of a `span_label`.
81-
match *self {
82+
match self {
83+
ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
8284
ObjectSafetyViolation::AssocConst(_, span)
83-
| ObjectSafetyViolation::SizedSelf(span)
8485
| ObjectSafetyViolation::Method(_, _, span)
85-
if span != DUMMY_SP =>
86+
if *span != DUMMY_SP =>
8687
{
87-
Some(span)
88+
vec![*span].into()
8889
}
89-
_ => None,
90+
_ => vec![].into(),
9091
}
9192
}
9293
}
@@ -189,10 +190,14 @@ fn object_safety_violations_for_trait(
189190
tcx.def_path_str(trait_def_id)
190191
),
191192
);
192-
match violation.span() {
193-
Some(span) => err.span_label(span, violation.error_msg()),
194-
None => err.note(&violation.error_msg()),
195-
};
193+
let spans = violation.spans();
194+
if spans.is_empty() {
195+
err.note(&violation.error_msg());
196+
} else {
197+
for span in spans {
198+
err.span_label(span, violation.error_msg());
199+
}
200+
}
196201
err.emit();
197202
false
198203
} else {
@@ -203,8 +208,9 @@ fn object_safety_violations_for_trait(
203208

204209
// Check the trait itself.
205210
if trait_has_sized_self(tcx, trait_def_id) {
206-
let span = get_sized_bound(tcx, trait_def_id);
207-
violations.push(ObjectSafetyViolation::SizedSelf(span));
211+
// We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
212+
let spans = get_sized_bounds(tcx, trait_def_id);
213+
violations.push(ObjectSafetyViolation::SizedSelf(spans));
208214
}
209215
if predicates_reference_self(tcx, trait_def_id, false) {
210216
violations.push(ObjectSafetyViolation::SupertraitSelf);
@@ -224,25 +230,26 @@ fn object_safety_violations_for_trait(
224230
violations
225231
}
226232

227-
fn get_sized_bound(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Span {
233+
fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
228234
tcx.hir()
229235
.get_if_local(trait_def_id)
230236
.and_then(|node| match node {
231-
hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., bounds, _), .. }) => bounds
232-
.iter()
233-
.filter_map(|b| match b {
234-
hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None)
235-
if Some(trait_ref.trait_ref.trait_def_id())
236-
== tcx.lang_items().sized_trait() =>
237-
{
238-
Some(trait_ref.span)
239-
}
240-
_ => None,
241-
})
242-
.next(),
237+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., bounds, _), .. }) => Some(
238+
bounds
239+
.iter()
240+
.filter_map(|b| match b {
241+
hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None)
242+
if trait_has_sized_self(tcx, trait_ref.trait_ref.trait_def_id()) =>
243+
{
244+
Some(trait_ref.span)
245+
}
246+
_ => None,
247+
})
248+
.collect::<SmallVec<[Span; 1]>>(),
249+
),
243250
_ => None,
244251
})
245-
.unwrap_or(DUMMY_SP)
252+
.unwrap_or_else(SmallVec::new)
246253
}
247254

248255
fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_only: bool) -> bool {

src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ LL | trait NonObjectSafe1: Sized {}
66
...
77
LL | fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) {
88
| ^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe1` cannot be made into an object
9-
|
10-
= note: the trait cannot require that `Self : Sized`
119

1210
error[E0038]: the trait `NonObjectSafe2` cannot be made into an object
1311
--> $DIR/feature-gate-object_safe_for_dispatch.rs:22:36
@@ -44,8 +42,6 @@ LL | trait NonObjectSafe1: Sized {}
4442
...
4543
LL | impl Trait for dyn NonObjectSafe1 {}
4644
| ^^^^^ the trait `NonObjectSafe1` cannot be made into an object
47-
|
48-
= note: the trait cannot require that `Self : Sized`
4945

5046
error: aborting due to 5 previous errors
5147

src/test/ui/issues/issue-20692.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
trait Array: Sized {}
1+
trait Array: Sized + Copy {}
22

33
fn f<T: Array>(x: &T) {
44
let _ = x

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
error[E0038]: the trait `Array` cannot be made into an object
22
--> $DIR/issue-20692.rs:7:5
33
|
4-
LL | trait Array: Sized {}
5-
| ----- the trait cannot require that `Self : Sized`
4+
LL | trait Array: Sized + Copy {}
5+
| ----- ---- the trait cannot require that `Self : Sized`
6+
| |
7+
| the trait cannot require that `Self : Sized`
68
...
79
LL | &dyn Array;
810
| ^^^^^^^^^^ the trait `Array` cannot be made into an object
9-
|
10-
= note: the trait cannot require that `Self : Sized`
1111

1212
error[E0038]: the trait `Array` cannot be made into an object
1313
--> $DIR/issue-20692.rs:4:13
1414
|
15-
LL | trait Array: Sized {}
16-
| ----- the trait cannot require that `Self : Sized`
15+
LL | trait Array: Sized + Copy {}
16+
| ----- ---- the trait cannot require that `Self : Sized`
17+
| |
18+
| the trait cannot require that `Self : Sized`
1719
...
1820
LL | let _ = x
1921
| ^ the trait `Array` cannot be made into an object
2022
|
21-
= note: the trait cannot require that `Self : Sized`
2223
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Array>` for `&T`
2324
= note: required by cast to type `&dyn Array`
2425

src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,21 @@ LL | take_param(&x);
1212
error[E0038]: the trait `Foo` cannot be made into an object
1313
--> $DIR/kindck-inherited-copy-bound.rs:28:19
1414
|
15+
LL | trait Foo : Copy {
16+
| ---- the trait cannot require that `Self : Sized`
17+
...
1518
LL | let z = &x as &dyn Foo;
1619
| ^^^^^^^^ the trait `Foo` cannot be made into an object
17-
|
18-
= note: the trait cannot require that `Self : Sized`
1920

2021
error[E0038]: the trait `Foo` cannot be made into an object
2122
--> $DIR/kindck-inherited-copy-bound.rs:28:13
2223
|
24+
LL | trait Foo : Copy {
25+
| ---- the trait cannot require that `Self : Sized`
26+
...
2327
LL | let z = &x as &dyn Foo;
2428
| ^^ the trait `Foo` cannot be made into an object
2529
|
26-
= note: the trait cannot require that `Self : Sized`
2730
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<{integer}>`
2831
= note: required by cast to type `&dyn Foo`
2932

src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ LL | take_param(&x);
1212
error[E0038]: the trait `Foo` cannot be made into an object
1313
--> $DIR/kindck-inherited-copy-bound.rs:28:13
1414
|
15+
LL | trait Foo : Copy {
16+
| ---- the trait cannot require that `Self : Sized`
17+
...
1518
LL | let z = &x as &dyn Foo;
1619
| ^^ the trait `Foo` cannot be made into an object
1720
|
18-
= note: the trait cannot require that `Self : Sized`
1921
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<i32>`
2022
= note: required by cast to type `&dyn Foo`
2123

src/test/ui/object-safety/object-safety-sized.curr.stderr

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ LL | trait Bar : Sized {
66
...
77
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
88
| ^^^^^^^^ the trait `Bar` cannot be made into an object
9-
|
10-
= note: the trait cannot require that `Self : Sized`
119

1210
error: aborting due to previous error
1311

src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ LL | trait Bar : Sized {
77
LL | t
88
| ^ the trait `Bar` cannot be made into an object
99
|
10-
= note: the trait cannot require that `Self : Sized`
1110
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
1211
= note: required by cast to type `&dyn Bar`
1312

src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ LL | trait A: Sized {
1818
| ----- the trait cannot require that `Self : Sized`
1919
LL | fn f(a: A) -> A;
2020
| ^ the trait `A` cannot be made into an object
21-
|
22-
= note: the trait cannot require that `Self : Sized`
2321

2422
error: associated item referring to unboxed trait object for its own trait
2523
--> $DIR/object-unsafe-trait-should-use-self.rs:8:13

0 commit comments

Comments
 (0)