From 1c9242f83fdea3e4c7a452d1453370ee81a900af Mon Sep 17 00:00:00 2001 From: =?utf8?q?Esteban=20K=C3=BCber?= Date: Sun, 19 Jan 2020 14:53:37 -0800 Subject: [PATCH] Point at `Sized` bound --- src/librustc/traits/object_safety.rs | 40 +++++++++++++++---- ...ature-gate-object_safe_for_dispatch.stderr | 6 +++ src/test/ui/issues/issue-20692.stderr | 6 +++ src/test/ui/issues/issue-50781.stderr | 3 +- .../object-safety-sized.curr.stderr | 3 ++ ...fety-sized.object_safe_for_dispatch.stderr | 3 ++ .../wf/wf-convert-unsafe-trait-obj-box.stderr | 9 +++++ .../ui/wf/wf-convert-unsafe-trait-obj.stderr | 9 +++++ .../ui/wf/wf-unsafe-trait-obj-match.stderr | 6 +++ 9 files changed, 76 insertions(+), 9 deletions(-) diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 15f81bb3f47..bca0ecb1e79 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -26,7 +26,7 @@ #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum ObjectSafetyViolation { /// `Self: Sized` declared on the trait. - SizedSelf, + SizedSelf(Span), /// Supertrait reference references `Self` an in illegal location /// (e.g., `trait Foo : Bar`). @@ -42,7 +42,7 @@ pub enum ObjectSafetyViolation { impl ObjectSafetyViolation { pub fn error_msg(&self) -> Cow<'static, str> { match *self { - ObjectSafetyViolation::SizedSelf => { + ObjectSafetyViolation::SizedSelf(_) => { "the trait cannot require that `Self : Sized`".into() } ObjectSafetyViolation::SupertraitSelf => { @@ -80,6 +80,7 @@ pub fn span(&self) -> Option { // diagnostics use a `note` instead of a `span_label`. match *self { ObjectSafetyViolation::AssocConst(_, span) + | ObjectSafetyViolation::SizedSelf(span) | ObjectSafetyViolation::Method(_, _, span) if span != DUMMY_SP => { @@ -179,7 +180,7 @@ fn object_safety_violations_for_trait( { // 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. - tcx.struct_span_lint_hir( + let mut err = tcx.struct_span_lint_hir( WHERE_CLAUSES_OBJECT_SAFETY, hir::CRATE_HIR_ID, *span, @@ -187,9 +188,12 @@ fn object_safety_violations_for_trait( "the trait `{}` cannot be made into an object", tcx.def_path_str(trait_def_id) ), - ) - .note(&violation.error_msg()) - .emit(); + ); + match violation.span() { + Some(span) => err.span_label(span, violation.error_msg()), + None => err.note(&violation.error_msg()), + }; + err.emit(); false } else { true @@ -199,7 +203,8 @@ fn object_safety_violations_for_trait( // Check the trait itself. if trait_has_sized_self(tcx, trait_def_id) { - violations.push(ObjectSafetyViolation::SizedSelf); + let span = get_sized_bound(tcx, trait_def_id); + violations.push(ObjectSafetyViolation::SizedSelf(span)); } if predicates_reference_self(tcx, trait_def_id, false) { violations.push(ObjectSafetyViolation::SupertraitSelf); @@ -219,6 +224,27 @@ fn object_safety_violations_for_trait( violations } +fn get_sized_bound(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Span { + 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(), + _ => None, + }) + .unwrap_or(DUMMY_SP) +} + fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_only: bool) -> bool { let trait_ref = ty::Binder::dummy(ty::TraitRef::identity(tcx, trait_def_id)); let predicates = if supertraits_only { diff --git a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr index a2409621db3..de362e1cef0 100644 --- a/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr +++ b/src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr @@ -1,6 +1,9 @@ error[E0038]: the trait `NonObjectSafe1` cannot be made into an object --> $DIR/feature-gate-object_safe_for_dispatch.rs:18:38 | +LL | trait NonObjectSafe1: Sized {} + | ----- the trait cannot require that `Self : Sized` +... LL | fn takes_non_object_safe_ref(obj: &dyn NonObjectSafe1) { | ^^^^^^^^^^^^^^^^^^^ the trait `NonObjectSafe1` cannot be made into an object | @@ -36,6 +39,9 @@ LL | fn return_non_object_safe_rc() -> std::rc::Rc { error[E0038]: the trait `NonObjectSafe1` cannot be made into an object --> $DIR/feature-gate-object_safe_for_dispatch.rs:38:6 | +LL | trait NonObjectSafe1: Sized {} + | ----- the trait cannot require that `Self : Sized` +... LL | impl Trait for dyn NonObjectSafe1 {} | ^^^^^ the trait `NonObjectSafe1` cannot be made into an object | diff --git a/src/test/ui/issues/issue-20692.stderr b/src/test/ui/issues/issue-20692.stderr index 06c83f65be2..4757742a707 100644 --- a/src/test/ui/issues/issue-20692.stderr +++ b/src/test/ui/issues/issue-20692.stderr @@ -1,6 +1,9 @@ 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 | &dyn Array; | ^^^^^^^^^^ the trait `Array` cannot be made into an object | @@ -9,6 +12,9 @@ LL | &dyn Array; 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 | let _ = x | ^ the trait `Array` cannot be made into an object | diff --git a/src/test/ui/issues/issue-50781.stderr b/src/test/ui/issues/issue-50781.stderr index cb6ca24c712..c161e9efd12 100644 --- a/src/test/ui/issues/issue-50781.stderr +++ b/src/test/ui/issues/issue-50781.stderr @@ -2,7 +2,7 @@ error: the trait `X` cannot be made into an object --> $DIR/issue-50781.rs:6:8 | LL | fn foo(&self) where Self: Trait; - | ^^^ + | ^^^ method `foo` references the `Self` type in where clauses | note: the lint level is defined here --> $DIR/issue-50781.rs:1:9 @@ -11,7 +11,6 @@ LL | #![deny(where_clauses_object_safety)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #51443 - = note: method `foo` references the `Self` type in where clauses error: aborting due to previous error diff --git a/src/test/ui/object-safety/object-safety-sized.curr.stderr b/src/test/ui/object-safety/object-safety-sized.curr.stderr index 0f284fc8507..be0a2519a46 100644 --- a/src/test/ui/object-safety/object-safety-sized.curr.stderr +++ b/src/test/ui/object-safety/object-safety-sized.curr.stderr @@ -1,6 +1,9 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-sized.rs:12:30 | +LL | trait Bar : Sized { + | ----- the trait cannot require that `Self : Sized` +... LL | fn make_bar(t: &T) -> &dyn Bar { | ^^^^^^^^ the trait `Bar` cannot be made into an object | diff --git a/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr index 3d88dfc40ed..c20ddee54c0 100644 --- a/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr +++ b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr @@ -1,6 +1,9 @@ error[E0038]: the trait `Bar` cannot be made into an object --> $DIR/object-safety-sized.rs:14:5 | +LL | trait Bar : Sized { + | ----- the trait cannot require that `Self : Sized` +... LL | t | ^ the trait `Bar` cannot be made into an object | diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr index 0b63aef2bce..4c033cfcd89 100644 --- a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr +++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr @@ -1,6 +1,9 @@ error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/wf-convert-unsafe-trait-obj-box.rs:16:33 | +LL | trait Trait: Sized {} + | ----- the trait cannot require that `Self : Sized` +... LL | let t_box: Box = Box::new(S); | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object | @@ -11,6 +14,9 @@ LL | let t_box: Box = Box::new(S); error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/wf-convert-unsafe-trait-obj-box.rs:17:15 | +LL | trait Trait: Sized {} + | ----- the trait cannot require that `Self : Sized` +... LL | takes_box(Box::new(S)); | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object | @@ -21,6 +27,9 @@ LL | takes_box(Box::new(S)); error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/wf-convert-unsafe-trait-obj-box.rs:15:5 | +LL | trait Trait: Sized {} + | ----- the trait cannot require that `Self : Sized` +... LL | Box::new(S) as Box; | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object | diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr index 7aeefd731fb..ba3792c362e 100644 --- a/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr +++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr @@ -1,6 +1,9 @@ error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/wf-convert-unsafe-trait-obj.rs:16:25 | +LL | trait Trait: Sized {} + | ----- the trait cannot require that `Self : Sized` +... LL | let t: &dyn Trait = &S; | ^^ the trait `Trait` cannot be made into an object | @@ -11,6 +14,9 @@ LL | let t: &dyn Trait = &S; error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/wf-convert-unsafe-trait-obj.rs:17:17 | +LL | trait Trait: Sized {} + | ----- the trait cannot require that `Self : Sized` +... LL | takes_trait(&S); | ^^ the trait `Trait` cannot be made into an object | @@ -21,6 +27,9 @@ LL | takes_trait(&S); error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/wf-convert-unsafe-trait-obj.rs:15:5 | +LL | trait Trait: Sized {} + | ----- the trait cannot require that `Self : Sized` +... LL | &S as &dyn Trait; | ^^ the trait `Trait` cannot be made into an object | diff --git a/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr index 594fad41385..a0082578d4d 100644 --- a/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr +++ b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr @@ -15,6 +15,9 @@ LL | | } error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/wf-unsafe-trait-obj-match.rs:26:21 | +LL | trait Trait: Sized {} + | ----- the trait cannot require that `Self : Sized` +... LL | Some(()) => &S, | ^^ the trait `Trait` cannot be made into an object | @@ -25,6 +28,9 @@ LL | Some(()) => &S, error[E0038]: the trait `Trait` cannot be made into an object --> $DIR/wf-unsafe-trait-obj-match.rs:25:25 | +LL | trait Trait: Sized {} + | ----- the trait cannot require that `Self : Sized` +... LL | let t: &dyn Trait = match opt() { | ^^^^^^^^^^^ the trait `Trait` cannot be made into an object | -- 2.44.0