about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/traits/error_reporting/mod.rs19
-rw-r--r--src/librustc/traits/object_safety.rs63
-rw-r--r--src/test/ui/feature-gates/feature-gate-object_safe_for_dispatch.stderr4
-rw-r--r--src/test/ui/issues/issue-20692.rs2
-rw-r--r--src/test/ui/issues/issue-20692.stderr15
-rw-r--r--src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr9
-rw-r--r--src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr4
-rw-r--r--src/test/ui/object-safety/object-safety-sized.curr.stderr2
-rw-r--r--src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr1
-rw-r--r--src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr2
-rw-r--r--src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr3
-rw-r--r--src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr3
-rw-r--r--src/test/ui/wf/wf-unsafe-trait-obj-match.stderr2
13 files changed, 68 insertions, 61 deletions
diff --git a/src/librustc/traits/error_reporting/mod.rs b/src/librustc/traits/error_reporting/mod.rs
index 28084c9d4ac..f15fa779534 100644
--- a/src/librustc/traits/error_reporting/mod.rs
+++ b/src/librustc/traits/error_reporting/mod.rs
@@ -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());
+                }
+            }
         }
     }
 
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index bca0ecb1e79..8ceefb0abf0 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -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 {
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 de362e1cef0..237c22d3bf0 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
@@ -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
 
diff --git a/src/test/ui/issues/issue-20692.rs b/src/test/ui/issues/issue-20692.rs
index 2a05bba7b16..1cb2d8c7302 100644
--- a/src/test/ui/issues/issue-20692.rs
+++ b/src/test/ui/issues/issue-20692.rs
@@ -1,4 +1,4 @@
-trait Array: Sized {}
+trait Array: Sized + Copy {}
 
 fn f<T: Array>(x: &T) {
     let _ = x
diff --git a/src/test/ui/issues/issue-20692.stderr b/src/test/ui/issues/issue-20692.stderr
index 4757742a707..62efdfb2e91 100644
--- a/src/test/ui/issues/issue-20692.stderr
+++ b/src/test/ui/issues/issue-20692.stderr
@@ -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`
 
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
index da1a7a7520e..a0ecca3020e 100644
--- a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
@@ -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`
 
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
index f272f829ba6..5694150ed7c 100644
--- a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
@@ -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`
 
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 be0a2519a46..473c8f8e6fa 100644
--- a/src/test/ui/object-safety/object-safety-sized.curr.stderr
+++ b/src/test/ui/object-safety/object-safety-sized.curr.stderr
@@ -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
 
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 c20ddee54c0..217e2aa00da 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
@@ -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`
 
diff --git a/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr b/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr
index f1c1a6bb972..91fa144032f 100644
--- a/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr
+++ b/src/test/ui/suggestions/object-unsafe-trait-should-use-self.stderr
@@ -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
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 4c033cfcd89..461ad97f2f0 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
@@ -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>`
 
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 ba3792c362e..6fc57369b4e 100644
--- a/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr
+++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr
@@ -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`
 
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 a0082578d4d..36c60aefa6b 100644
--- a/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr
+++ b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr
@@ -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`