mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 14:31:55 +00:00
Tweak Self: Sized
restriction diagnostic output
This commit is contained in:
parent
d137b7ac11
commit
4b2f1db6e4
@ -1046,11 +1046,22 @@ pub fn report_object_safety_error(
|
||||
|
||||
let mut reported_violations = FxHashSet::default();
|
||||
for violation in violations {
|
||||
if let ObjectSafetyViolation::SizedSelf(sp) = &violation {
|
||||
if !sp.is_empty() {
|
||||
// Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations
|
||||
// with a `Span`.
|
||||
reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into()));
|
||||
}
|
||||
}
|
||||
if reported_violations.insert(violation.clone()) {
|
||||
match violation.span() {
|
||||
Some(span) => err.span_label(span, violation.error_msg()),
|
||||
None => err.note(&violation.error_msg()),
|
||||
};
|
||||
let spans = violation.spans();
|
||||
if spans.is_empty() {
|
||||
err.note(&violation.error_msg());
|
||||
} else {
|
||||
for span in spans {
|
||||
err.span_label(span, violation.error_msg());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,15 +18,16 @@ use rustc_hir::def_id::DefId;
|
||||
use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use smallvec::SmallVec;
|
||||
use syntax::ast;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::iter::{self};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum ObjectSafetyViolation {
|
||||
/// `Self: Sized` declared on the trait.
|
||||
SizedSelf(Span),
|
||||
SizedSelf(SmallVec<[Span; 1]>),
|
||||
|
||||
/// Supertrait reference references `Self` an in illegal location
|
||||
/// (e.g., `trait Foo : Bar<Self>`).
|
||||
@ -75,18 +76,18 @@ impl ObjectSafetyViolation {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Option<Span> {
|
||||
pub fn spans(&self) -> SmallVec<[Span; 1]> {
|
||||
// When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
|
||||
// diagnostics use a `note` instead of a `span_label`.
|
||||
match *self {
|
||||
match self {
|
||||
ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
|
||||
ObjectSafetyViolation::AssocConst(_, span)
|
||||
| ObjectSafetyViolation::SizedSelf(span)
|
||||
| ObjectSafetyViolation::Method(_, _, span)
|
||||
if span != DUMMY_SP =>
|
||||
if *span != DUMMY_SP =>
|
||||
{
|
||||
Some(span)
|
||||
vec![*span].into()
|
||||
}
|
||||
_ => None,
|
||||
_ => vec![].into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -189,10 +190,14 @@ fn object_safety_violations_for_trait(
|
||||
tcx.def_path_str(trait_def_id)
|
||||
),
|
||||
);
|
||||
match violation.span() {
|
||||
Some(span) => err.span_label(span, violation.error_msg()),
|
||||
None => err.note(&violation.error_msg()),
|
||||
};
|
||||
let spans = violation.spans();
|
||||
if spans.is_empty() {
|
||||
err.note(&violation.error_msg());
|
||||
} else {
|
||||
for span in spans {
|
||||
err.span_label(span, violation.error_msg());
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
false
|
||||
} else {
|
||||
@ -203,8 +208,9 @@ fn object_safety_violations_for_trait(
|
||||
|
||||
// Check the trait itself.
|
||||
if trait_has_sized_self(tcx, trait_def_id) {
|
||||
let span = get_sized_bound(tcx, trait_def_id);
|
||||
violations.push(ObjectSafetyViolation::SizedSelf(span));
|
||||
// We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
|
||||
let spans = get_sized_bounds(tcx, trait_def_id);
|
||||
violations.push(ObjectSafetyViolation::SizedSelf(spans));
|
||||
}
|
||||
if predicates_reference_self(tcx, trait_def_id, false) {
|
||||
violations.push(ObjectSafetyViolation::SupertraitSelf);
|
||||
@ -224,25 +230,26 @@ fn object_safety_violations_for_trait(
|
||||
violations
|
||||
}
|
||||
|
||||
fn get_sized_bound(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Span {
|
||||
fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
|
||||
tcx.hir()
|
||||
.get_if_local(trait_def_id)
|
||||
.and_then(|node| match node {
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., bounds, _), .. }) => bounds
|
||||
.iter()
|
||||
.filter_map(|b| match b {
|
||||
hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None)
|
||||
if Some(trait_ref.trait_ref.trait_def_id())
|
||||
== tcx.lang_items().sized_trait() =>
|
||||
{
|
||||
Some(trait_ref.span)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.next(),
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., bounds, _), .. }) => Some(
|
||||
bounds
|
||||
.iter()
|
||||
.filter_map(|b| match b {
|
||||
hir::GenericBound::Trait(trait_ref, hir::TraitBoundModifier::None)
|
||||
if trait_has_sized_self(tcx, trait_ref.trait_ref.trait_def_id()) =>
|
||||
{
|
||||
Some(trait_ref.span)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect::<SmallVec<[Span; 1]>>(),
|
||||
),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or(DUMMY_SP)
|
||||
.unwrap_or_else(SmallVec::new)
|
||||
}
|
||||
|
||||
fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_only: bool) -> bool {
|
||||
|
@ -6,8 +6,6 @@ LL | trait NonObjectSafe1: Sized {}
|
||||
...
|
||||
LL | fn takes_non_object_safe_ref<T>(obj: &dyn NonObjectSafe1) {
|
||||
| ^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe1` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
|
||||
error[E0038]: the trait `NonObjectSafe2` cannot be made into an object
|
||||
--> $DIR/feature-gate-object_safe_for_dispatch.rs:22:36
|
||||
@ -44,8 +42,6 @@ LL | trait NonObjectSafe1: Sized {}
|
||||
...
|
||||
LL | impl Trait for dyn NonObjectSafe1 {}
|
||||
| ^^^^^ the trait `NonObjectSafe1` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
trait Array: Sized {}
|
||||
trait Array: Sized + Copy {}
|
||||
|
||||
fn f<T: Array>(x: &T) {
|
||||
let _ = x
|
||||
|
@ -1,24 +1,25 @@
|
||||
error[E0038]: the trait `Array` cannot be made into an object
|
||||
--> $DIR/issue-20692.rs:7:5
|
||||
|
|
||||
LL | trait Array: Sized {}
|
||||
| ----- the trait cannot require that `Self : Sized`
|
||||
LL | trait Array: Sized + Copy {}
|
||||
| ----- ---- the trait cannot require that `Self : Sized`
|
||||
| |
|
||||
| the trait cannot require that `Self : Sized`
|
||||
...
|
||||
LL | &dyn Array;
|
||||
| ^^^^^^^^^^ the trait `Array` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
|
||||
error[E0038]: the trait `Array` cannot be made into an object
|
||||
--> $DIR/issue-20692.rs:4:13
|
||||
|
|
||||
LL | trait Array: Sized {}
|
||||
| ----- the trait cannot require that `Self : Sized`
|
||||
LL | trait Array: Sized + Copy {}
|
||||
| ----- ---- the trait cannot require that `Self : Sized`
|
||||
| |
|
||||
| the trait cannot require that `Self : Sized`
|
||||
...
|
||||
LL | let _ = x
|
||||
| ^ the trait `Array` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Array>` for `&T`
|
||||
= note: required by cast to type `&dyn Array`
|
||||
|
||||
|
@ -12,18 +12,21 @@ LL | take_param(&x);
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:28:19
|
||||
|
|
||||
LL | trait Foo : Copy {
|
||||
| ---- the trait cannot require that `Self : Sized`
|
||||
...
|
||||
LL | let z = &x as &dyn Foo;
|
||||
| ^^^^^^^^ the trait `Foo` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:28:13
|
||||
|
|
||||
LL | trait Foo : Copy {
|
||||
| ---- the trait cannot require that `Self : Sized`
|
||||
...
|
||||
LL | let z = &x as &dyn Foo;
|
||||
| ^^ the trait `Foo` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<{integer}>`
|
||||
= note: required by cast to type `&dyn Foo`
|
||||
|
||||
|
@ -12,10 +12,12 @@ LL | take_param(&x);
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/kindck-inherited-copy-bound.rs:28:13
|
||||
|
|
||||
LL | trait Foo : Copy {
|
||||
| ---- the trait cannot require that `Self : Sized`
|
||||
...
|
||||
LL | let z = &x as &dyn Foo;
|
||||
| ^^ the trait `Foo` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Foo>` for `&std::boxed::Box<i32>`
|
||||
= note: required by cast to type `&dyn Foo`
|
||||
|
||||
|
@ -6,8 +6,6 @@ LL | trait Bar : Sized {
|
||||
...
|
||||
LL | fn make_bar<T:Bar>(t: &T) -> &dyn Bar {
|
||||
| ^^^^^^^^ the trait `Bar` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -7,7 +7,6 @@ LL | trait Bar : Sized {
|
||||
LL | t
|
||||
| ^ the trait `Bar` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Bar>` for `&T`
|
||||
= note: required by cast to type `&dyn Bar`
|
||||
|
||||
|
@ -18,8 +18,6 @@ LL | trait A: Sized {
|
||||
| ----- the trait cannot require that `Self : Sized`
|
||||
LL | fn f(a: A) -> A;
|
||||
| ^ the trait `A` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
|
||||
error: associated item referring to unboxed trait object for its own trait
|
||||
--> $DIR/object-unsafe-trait-should-use-self.rs:8:13
|
||||
|
@ -7,7 +7,6 @@ LL | trait Trait: Sized {}
|
||||
LL | let t_box: Box<dyn Trait> = Box::new(S);
|
||||
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Trait>>` for `std::boxed::Box<S>`
|
||||
= note: required by cast to type `std::boxed::Box<dyn Trait>`
|
||||
|
||||
@ -20,7 +19,6 @@ LL | trait Trait: Sized {}
|
||||
LL | takes_box(Box::new(S));
|
||||
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Trait>>` for `std::boxed::Box<S>`
|
||||
= note: required by cast to type `std::boxed::Box<(dyn Trait + 'static)>`
|
||||
|
||||
@ -33,7 +31,6 @@ LL | trait Trait: Sized {}
|
||||
LL | Box::new(S) as Box<dyn Trait>;
|
||||
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<std::boxed::Box<dyn Trait>>` for `std::boxed::Box<S>`
|
||||
= note: required by cast to type `std::boxed::Box<dyn Trait>`
|
||||
|
||||
|
@ -7,7 +7,6 @@ LL | trait Trait: Sized {}
|
||||
LL | let t: &dyn Trait = &S;
|
||||
| ^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
|
||||
= note: required by cast to type `&dyn Trait`
|
||||
|
||||
@ -20,7 +19,6 @@ LL | trait Trait: Sized {}
|
||||
LL | takes_trait(&S);
|
||||
| ^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
|
||||
= note: required by cast to type `&dyn Trait`
|
||||
|
||||
@ -33,7 +31,6 @@ LL | trait Trait: Sized {}
|
||||
LL | &S as &dyn Trait;
|
||||
| ^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
|
||||
= note: required by cast to type `&dyn Trait`
|
||||
|
||||
|
@ -21,7 +21,6 @@ LL | trait Trait: Sized {}
|
||||
LL | Some(()) => &S,
|
||||
| ^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&S`
|
||||
= note: required by cast to type `&dyn Trait`
|
||||
|
||||
@ -34,7 +33,6 @@ LL | trait Trait: Sized {}
|
||||
LL | let t: &dyn Trait = match opt() {
|
||||
| ^^^^^^^^^^^ the trait `Trait` cannot be made into an object
|
||||
|
|
||||
= note: the trait cannot require that `Self : Sized`
|
||||
= note: required because of the requirements on the impl of `std::ops::CoerceUnsized<&dyn Trait>` for `&R`
|
||||
= note: required by cast to type `&dyn Trait`
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user