about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <ariel.byd@gmail.com>2019-01-03 23:46:46 +0200
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2019-01-04 01:50:35 +0200
commit0b511b7bd22bde3c647191de79ba5a019b183269 (patch)
tree55d717471c2a1f48a03b4d228c4b884e63145eac
parent7eb444e4f18d50e48868861010b3d87d741d1218 (diff)
implement a hack to make traitobject 0.1.0 compile
-rw-r--r--src/librustc/dep_graph/dep_node.rs1
-rw-r--r--src/librustc/traits/mod.rs2
-rw-r--r--src/librustc/traits/select.rs3
-rw-r--r--src/librustc/traits/specialize/mod.rs21
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs44
-rw-r--r--src/librustc/ty/mod.rs122
-rw-r--r--src/librustc/ty/query/mod.rs2
-rw-r--r--src/librustc/ty/query/plumbing.rs1
-rw-r--r--src/test/run-pass/issues/issue-33140.rs47
-rw-r--r--src/test/ui/issues/issue-33140-hack-boundaries.rs80
-rw-r--r--src/test/ui/issues/issue-33140-hack-boundaries.stderr67
-rw-r--r--src/test/ui/issues/issue-33140-traitobject-crate.rs101
-rw-r--r--src/test/ui/issues/issue-33140-traitobject-crate.stderr39
-rw-r--r--src/test/ui/issues/issue-33140.rs5
-rw-r--r--src/test/ui/issues/issue-33140.stderr33
15 files changed, 478 insertions, 90 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 070551c0b7b..3156f17e0c4 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -492,6 +492,7 @@ define_dep_nodes!( <'tcx>
     [] AdtDefOfItem(DefId),
     [] ImplTraitRef(DefId),
     [] ImplPolarity(DefId),
+    [] Issue33140SelfTy(DefId),
     [] FnSignature(DefId),
     [] CoerceUnsizedInfo(DefId),
 
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 1a9f1ada111..b42d742b7f8 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -56,6 +56,8 @@ pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
 pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError};
 pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
 pub use self::specialize::find_associated_item;
+pub use self::specialize::specialization_graph::FutureCompatOverlapError;
+pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind;
 pub use self::engine::{TraitEngine, TraitEngineExt};
 pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
 pub use self::util::{supertraits, supertrait_def_ids, transitive_bounds,
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 9ad974d8e08..6db6fe31fba 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2260,7 +2260,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
                         ImplCandidate(victim_def) => {
                             let tcx = self.tcx().global_tcx();
                             return tcx.specializes((other_def, victim_def))
-                                || tcx.impls_are_allowed_to_overlap(other_def, victim_def);
+                                || tcx.impls_are_allowed_to_overlap(
+                                    other_def, victim_def).is_some();
                         }
                         ParamCandidate(ref cand) => {
                             // Prefer the impl to a global where clause candidate.
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 5ab54b2c99d..e5ed16e7558 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -14,11 +14,10 @@ pub mod specialization_graph;
 use hir::def_id::DefId;
 use infer::{InferCtxt, InferOk};
 use lint;
-use traits::coherence;
+use traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
 use syntax_pos::DUMMY_SP;
-use traits::{self, ObligationCause, TraitEngine};
 use traits::select::IntercrateAmbiguityCause;
 use ty::{self, TyCtxt, TypeFoldable};
 use ty::subst::{Subst, Substs};
@@ -27,6 +26,7 @@ use super::{SelectionContext, FulfillmentContext};
 use super::util::impl_trait_ref_and_oblig;
 
 /// Information pertinent to an overlapping impl error.
+#[derive(Debug)]
 pub struct OverlapError {
     pub with_impl: DefId,
     pub trait_desc: String,
@@ -310,8 +310,9 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
             let insert_result = sg.insert(tcx, impl_def_id);
             // Report error if there was one.
             let (overlap, used_to_be_allowed) = match insert_result {
-                Err(overlap) => (Some(overlap), false),
-                Ok(opt_overlap) => (opt_overlap, true)
+                Err(overlap) => (Some(overlap), None),
+                Ok(Some(overlap)) => (Some(overlap.error), Some(overlap.kind)),
+                Ok(None) => (None, None)
             };
 
             if let Some(overlap) = overlap {
@@ -321,14 +322,20 @@ pub(super) fn specialization_graph_provider<'a, 'tcx>(
                         String::new(), |ty| {
                             format!(" for type `{}`", ty)
                         }),
-                    if used_to_be_allowed { " (E0119)" } else { "" }
+                    if used_to_be_allowed.is_some() { " (E0119)" } else { "" }
                 );
                 let impl_span = tcx.sess.source_map().def_span(
                     tcx.span_of_impl(impl_def_id).unwrap()
                 );
-                let mut err = if used_to_be_allowed {
+                let mut err = if let Some(kind) = used_to_be_allowed {
+                    let lint = match kind {
+                        FutureCompatOverlapErrorKind::Issue43355 =>
+                            lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
+                        FutureCompatOverlapErrorKind::Issue33140 =>
+                            lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
+                    };
                     tcx.struct_span_lint_node(
-                        lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
+                        lint,
                         tcx.hir().as_local_node_id(impl_def_id).unwrap(),
                         impl_span,
                         &msg)
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index c22adeb55a2..e5780a26a19 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -58,10 +58,22 @@ struct Children {
     blanket_impls: Vec<DefId>,
 }
 
+#[derive(Copy, Clone, Debug)]
+pub enum FutureCompatOverlapErrorKind {
+    Issue43355,
+    Issue33140,
+}
+
+#[derive(Debug)]
+pub struct FutureCompatOverlapError {
+    pub error: OverlapError,
+    pub kind: FutureCompatOverlapErrorKind
+}
+
 /// The result of attempting to insert an impl into a group of children.
 enum Inserted {
     /// The impl was inserted as a new child in this group of children.
-    BecameNewSibling(Option<OverlapError>),
+    BecameNewSibling(Option<FutureCompatOverlapError>),
 
     /// The impl should replace existing impls [X1, ..], because the impl specializes X1, X2, etc.
     ReplaceChildren(Vec<DefId>),
@@ -162,7 +174,19 @@ impl<'a, 'gcx, 'tcx> Children {
                 impl_def_id,
                 traits::IntercrateMode::Issue43355,
                 |overlap| {
-                    if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
+                    if let Some(overlap_kind) =
+                        tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling)
+                    {
+                        match overlap_kind {
+                            ty::ImplOverlapKind::Permitted => {}
+                            ty::ImplOverlapKind::Issue33140 => {
+                                last_lint = Some(FutureCompatOverlapError {
+                                    error: overlap_error(overlap),
+                                    kind: FutureCompatOverlapErrorKind::Issue33140
+                                });
+                            }
+                        }
+
                         return Ok((false, false));
                     }
 
@@ -190,13 +214,23 @@ impl<'a, 'gcx, 'tcx> Children {
 
                 replace_children.push(possible_sibling);
             } else {
-                if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
+                if let None = tcx.impls_are_allowed_to_overlap(
+                    impl_def_id, possible_sibling)
+                {
+                    // do future-compat checks for overlap. Have issue #33140
+                    // errors overwrite issue #43355 errors when both are present.
+
                     traits::overlapping_impls(
                         tcx,
                         possible_sibling,
                         impl_def_id,
                         traits::IntercrateMode::Fixed,
-                        |overlap| last_lint = Some(overlap_error(overlap)),
+                        |overlap| {
+                            last_lint = Some(FutureCompatOverlapError {
+                                error: overlap_error(overlap),
+                                kind: FutureCompatOverlapErrorKind::Issue43355
+                            });
+                        },
                         || (),
                     );
                 }
@@ -263,7 +297,7 @@ impl<'a, 'gcx, 'tcx> Graph {
     pub fn insert(&mut self,
                   tcx: TyCtxt<'a, 'gcx, 'tcx>,
                   impl_def_id: DefId)
-                  -> Result<Option<OverlapError>, OverlapError> {
+                  -> Result<Option<FutureCompatOverlapError>, OverlapError> {
         assert!(impl_def_id.is_local());
 
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index d40dd830e9f..aa3ff5e4a2d 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2637,6 +2637,45 @@ impl<'gcx> ::std::ops::Deref for Attributes<'gcx> {
     }
 }
 
+#[derive(Debug, PartialEq, Eq)]
+pub enum ImplOverlapKind {
+    /// These impls are always allowed to overlap.
+    Permitted,
+    /// These impls are allowed to overlap, but that raises
+    /// an issue #33140 future-compatibility warning.
+    ///
+    /// Some background: in Rust 1.0, the trait-object types `Send + Sync` (today's
+    /// `dyn Send + Sync`) and `Sync + Send` (now `dyn Sync + Send`) were different.
+    ///
+    /// The widely-used version 0.1.0 of the crate `traitobject` had accidentally relied
+    /// that difference, making what reduces to the following set of impls:
+    ///
+    /// ```
+    /// trait Trait {}
+    /// impl Trait for dyn Send + Sync {}
+    /// impl Trait for dyn Sync + Send {}
+    /// ```
+    ///
+    /// Obviously, once we made these types be identical, that code causes a coherence
+    /// error and a fairly big headache for us. However, luckily for us, the trait
+    /// `Trait` used in this case is basically a marker trait, and therefore having
+    /// overlapping impls for it is sound.
+    ///
+    /// To handle this, we basically regard the trait as a marker trait, with an additional
+    /// future-compatibility warning. To avoid accidentally "stabilizing" this feature,
+    /// it has the following restrictions:
+    ///
+    /// 1. The trait must indeed be a marker-like trait (i.e., no items), and must be
+    /// positive impls.
+    /// 2. The trait-ref of both impls must be equal.
+    /// 3. The trait-ref of both impls must be a trait object type consisting only of
+    /// marker traits.
+    /// 4. Neither of the impls can have any where-clauses.
+    ///
+    /// Once `traitobject` 0.1.0 is no longer an active concern, this hack can be removed.
+    Issue33140
+}
+
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
         self.typeck_tables_of(self.hir().body_owner_def_id(body))
@@ -2788,8 +2827,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     /// Returns `true` if the impls are the same polarity and the trait either
     /// has no items or is annotated #[marker] and prevents item overrides.
-    pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
-        if self.features().overlapping_marker_traits {
+    pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId)
+                                        -> Option<ImplOverlapKind>
+    {
+        let is_legit = if self.features().overlapping_marker_traits {
             let trait1_is_empty = self.impl_trait_ref(def_id1)
                 .map_or(false, |trait_ref| {
                     self.associated_item_def_ids(trait_ref.def_id).is_empty()
@@ -2811,6 +2852,29 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                 && is_marker_impl(def_id2)
         } else {
             false
+        };
+
+        if is_legit {
+            debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted)",
+                  def_id1, def_id2);
+            Some(ImplOverlapKind::Permitted)
+        } else {
+            if let Some(self_ty1) = self.issue33140_self_ty(def_id1) {
+                if let Some(self_ty2) = self.issue33140_self_ty(def_id2) {
+                    if self_ty1 == self_ty2 {
+                        debug!("impls_are_allowed_to_overlap({:?}, {:?}) - issue #33140 HACK",
+                               def_id1, def_id2);
+                        return Some(ImplOverlapKind::Issue33140);
+                    } else {
+                        debug!("impls_are_allowed_to_overlap({:?}, {:?}) - found {:?} != {:?}",
+                              def_id1, def_id2, self_ty1, self_ty2);
+                    }
+                }
+            }
+
+            debug!("impls_are_allowed_to_overlap({:?}, {:?}) = None",
+                  def_id1, def_id2);
+            None
         }
     }
 
@@ -3203,6 +3267,59 @@ fn instance_def_size_estimate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+/// If `def_id` is an issue 33140 hack impl, return its self type. Otherwise
+/// return None.
+///
+/// See ImplOverlapKind::Issue33140 for more details.
+fn issue33140_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                def_id: DefId)
+                                -> Option<Ty<'tcx>>
+{
+    debug!("issue33140_self_ty({:?})", def_id);
+
+    let trait_ref = tcx.impl_trait_ref(def_id).unwrap_or_else(|| {
+        bug!("issue33140_self_ty called on inherent impl {:?}", def_id)
+    });
+
+    debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref);
+
+    let is_marker_like =
+        tcx.impl_polarity(def_id) == hir::ImplPolarity::Positive &&
+        tcx.associated_item_def_ids(trait_ref.def_id).is_empty();
+
+    // Check whether these impls would be ok for a marker trait.
+    if !is_marker_like {
+        debug!("issue33140_self_ty - not marker-like!");
+        return None;
+    }
+
+    // impl must be `impl Trait for dyn Marker1 + Marker2 + ...`
+    if trait_ref.substs.len() != 1 {
+        debug!("issue33140_self_ty - impl has substs!");
+        return None;
+    }
+
+    let predicates = tcx.predicates_of(def_id);
+    if predicates.parent.is_some() || !predicates.predicates.is_empty() {
+        debug!("issue33140_self_ty - impl has predicates {:?}!", predicates);
+        return None;
+    }
+
+    let self_ty = trait_ref.self_ty();
+    let self_ty_matches = match self_ty.sty {
+        ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(),
+        _ => false
+    };
+
+    if self_ty_matches {
+        debug!("issue33140_self_ty - MATCHES!");
+        Some(self_ty)
+    } else {
+        debug!("issue33140_self_ty - non-matching self type");
+        None
+    }
+}
+
 pub fn provide(providers: &mut ty::query::Providers<'_>) {
     context::provide(providers);
     erase_regions::provide(providers);
@@ -3221,6 +3338,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
         crate_hash,
         trait_impls_of: trait_def::trait_impls_of_provider,
         instance_def_size_estimate,
+        issue33140_self_ty,
         ..*providers
     };
 }
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index 4d026b97233..99dd3569491 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -202,6 +202,8 @@ define_queries! { <'tcx>
 
         [] fn impl_trait_ref: ImplTraitRef(DefId) -> Option<ty::TraitRef<'tcx>>,
         [] fn impl_polarity: ImplPolarity(DefId) -> hir::ImplPolarity,
+
+        [] fn issue33140_self_ty: Issue33140SelfTy(DefId) -> Option<ty::Ty<'tcx>>,
     },
 
     TypeChecking {
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 6887f480f72..9a1ab559688 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -1275,6 +1275,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
         DepKind::AdtDefOfItem => { force!(adt_def, def_id!()); }
         DepKind::ImplTraitRef => { force!(impl_trait_ref, def_id!()); }
         DepKind::ImplPolarity => { force!(impl_polarity, def_id!()); }
+        DepKind::Issue33140SelfTy => { force!(issue33140_self_ty, def_id!()); }
         DepKind::FnSignature => { force!(fn_sig, def_id!()); }
         DepKind::CoerceUnsizedInfo => { force!(coerce_unsized_info, def_id!()); }
         DepKind::ItemVariances => { force!(variances_of, def_id!()); }
diff --git a/src/test/run-pass/issues/issue-33140.rs b/src/test/run-pass/issues/issue-33140.rs
deleted file mode 100644
index 4d91af2fb19..00000000000
--- a/src/test/run-pass/issues/issue-33140.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-#![allow(order_dependent_trait_objects)]
-
-trait Trait {
-    fn xyz() -> bool;
-}
-
-impl Trait for dyn Send + Sync {
-    fn xyz() -> bool { false }
-}
-
-impl Trait for dyn Sync + Send {
-    fn xyz() -> bool { true }
-}
-
-trait Trait2 {
-    fn uvw() -> bool;
-}
-
-impl Trait2 for dyn Send + Sync {
-    fn uvw() -> bool { false }
-}
-
-impl Trait2 for dyn Sync + Send + Sync {
-    fn uvw() -> bool { true }
-}
-
-struct Foo<T: ?Sized>(T);
-impl Foo<dyn Send + Sync> {
-    fn abc() -> bool {
-        false
-    }
-}
-
-impl Foo<dyn Sync + Send> {
-    fn abc() -> bool {
-        true
-    }
-}
-
-fn main() {
-    assert_eq!(<dyn Send+Sync>::xyz(), false);
-    assert_eq!(<dyn Sync+Send>::xyz(), true);
-    assert_eq!(<dyn Send+Sync>::uvw(), false);
-    assert_eq!(<dyn Sync+Send+Sync>::uvw(), true);
-    assert_eq!(<Foo<dyn Send+Sync>>::abc(), false);
-    assert_eq!(<Foo<dyn Sync+Send>>::abc(), true);
-}
diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.rs b/src/test/ui/issues/issue-33140-hack-boundaries.rs
new file mode 100644
index 00000000000..fbdef51c132
--- /dev/null
+++ b/src/test/ui/issues/issue-33140-hack-boundaries.rs
@@ -0,0 +1,80 @@
+#![feature(optin_builtin_traits)]
+#![allow(order_dependent_trait_objects)]
+
+// Check that the issue #33140 hack does not allow unintended things.
+
+// OK
+trait Trait0 {
+}
+
+impl Trait0 for dyn Send {}
+impl Trait0 for dyn Send {}
+
+// Problem 1: associated types
+trait Trait1 {
+    fn my_fn(&self) {}
+}
+
+impl Trait1 for dyn Send {}
+impl Trait1 for dyn Send {}
+//~^ ERROR E0119
+
+// Problem 2: negative impl
+trait Trait2 {
+}
+
+impl Trait2 for dyn Send {}
+impl !Trait2 for dyn Send {}
+//~^ ERROR E0119
+
+
+// Problem 3: type parameter
+trait Trait3<T: ?Sized> {
+}
+
+impl Trait3<dyn Sync> for dyn Send {}
+impl Trait3<dyn Sync> for dyn Send {}
+//~^ ERROR E0119
+
+// Problem 4a: not a trait object - generic
+trait Trait4a {
+}
+
+impl<T: ?Sized> Trait4a for T {}
+impl Trait4a for dyn Send {}
+//~^ ERROR E0119
+
+// Problem 4b: not a trait object - misc
+trait Trait4b {
+}
+
+impl Trait4b for () {}
+impl Trait4b for () {}
+//~^ ERROR E0119
+
+// Problem 4c: not a principal-less trait object
+trait Trait4c {
+}
+
+impl Trait4c for dyn Trait1 + Send {}
+impl Trait4c for dyn Trait1 + Send {}
+//~^ ERROR E0119
+
+// Problem 4d: lifetimes
+trait Trait4d {
+}
+
+impl<'a> Trait4d for dyn Send + 'a {}
+impl<'a> Trait4d for dyn Send + 'a {}
+//~^ ERROR E0119
+
+
+// Problem 5: where-clauses
+trait Trait5 {
+}
+
+impl Trait5 for dyn Send {}
+impl Trait5 for dyn Send where u32: Copy {}
+//~^ ERROR E0119
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-33140-hack-boundaries.stderr b/src/test/ui/issues/issue-33140-hack-boundaries.stderr
new file mode 100644
index 00000000000..95aaa55ba7c
--- /dev/null
+++ b/src/test/ui/issues/issue-33140-hack-boundaries.stderr
@@ -0,0 +1,67 @@
+error[E0119]: conflicting implementations of trait `Trait1` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:19:1
+   |
+LL | impl Trait1 for dyn Send {}
+   | ------------------------ first implementation here
+LL | impl Trait1 for dyn Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:27:1
+   |
+LL | impl Trait2 for dyn Send {}
+   | ------------------------ first implementation here
+LL | impl !Trait2 for dyn Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait3<(dyn std::marker::Sync + 'static)>` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:36:1
+   |
+LL | impl Trait3<dyn Sync> for dyn Send {}
+   | ---------------------------------- first implementation here
+LL | impl Trait3<dyn Sync> for dyn Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait4a` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:44:1
+   |
+LL | impl<T: ?Sized> Trait4a for T {}
+   | ----------------------------- first implementation here
+LL | impl Trait4a for dyn Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait4b` for type `()`:
+  --> $DIR/issue-33140-hack-boundaries.rs:52:1
+   |
+LL | impl Trait4b for () {}
+   | ------------------- first implementation here
+LL | impl Trait4b for () {}
+   | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
+
+error[E0119]: conflicting implementations of trait `Trait4c` for type `(dyn Trait1 + std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:60:1
+   |
+LL | impl Trait4c for dyn Trait1 + Send {}
+   | ---------------------------------- first implementation here
+LL | impl Trait4c for dyn Trait1 + Send {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn Trait1 + std::marker::Send + 'static)`
+
+error[E0119]: conflicting implementations of trait `Trait4d` for type `dyn std::marker::Send`:
+  --> $DIR/issue-33140-hack-boundaries.rs:68:1
+   |
+LL | impl<'a> Trait4d for dyn Send + 'a {}
+   | ---------------------------------- first implementation here
+LL | impl<'a> Trait4d for dyn Send + 'a {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `dyn std::marker::Send`
+
+error[E0119]: conflicting implementations of trait `Trait5` for type `(dyn std::marker::Send + 'static)`:
+  --> $DIR/issue-33140-hack-boundaries.rs:77:1
+   |
+LL | impl Trait5 for dyn Send {}
+   | ------------------------ first implementation here
+LL | impl Trait5 for dyn Send where u32: Copy {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/issues/issue-33140-traitobject-crate.rs b/src/test/ui/issues/issue-33140-traitobject-crate.rs
new file mode 100644
index 00000000000..2b644817df1
--- /dev/null
+++ b/src/test/ui/issues/issue-33140-traitobject-crate.rs
@@ -0,0 +1,101 @@
+// compile-pass
+
+#![warn(order_dependent_trait_objects)]
+
+// Check that traitobject 0.1.0 compiles
+
+//! # traitobject
+//!
+//! Unsafe helpers for working with raw TraitObjects.
+
+/// A trait implemented for all trait objects.
+///
+/// Implementations for all traits in std are provided.
+pub unsafe trait Trait {}
+
+unsafe impl Trait for ::std::any::Any + Send { }
+unsafe impl Trait for ::std::any::Any + Sync { }
+unsafe impl Trait for ::std::any::Any + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::Borrow<T> + Send { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::Borrow<T> + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::Borrow<T> + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::BorrowMut<T> + Send { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::BorrowMut<T> + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::borrow::BorrowMut<T> + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsMut<T> + Send { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsMut<T> + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsMut<T> + Send + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsRef<T> + Send { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsRef<T> + Sync { }
+unsafe impl<T: ?Sized> Trait for ::std::convert::AsRef<T> + Send + Sync { }
+unsafe impl Trait for ::std::error::Error + Send { }
+unsafe impl Trait for ::std::error::Error + Sync { }
+unsafe impl Trait for ::std::error::Error + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Binary + Send { }
+unsafe impl Trait for ::std::fmt::Binary + Sync { }
+unsafe impl Trait for ::std::fmt::Binary + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Debug + Send { }
+unsafe impl Trait for ::std::fmt::Debug + Sync { }
+unsafe impl Trait for ::std::fmt::Debug + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Display + Send { }
+unsafe impl Trait for ::std::fmt::Display + Sync { }
+unsafe impl Trait for ::std::fmt::Display + Send + Sync { }
+unsafe impl Trait for ::std::fmt::LowerExp + Send { }
+unsafe impl Trait for ::std::fmt::LowerExp + Sync { }
+unsafe impl Trait for ::std::fmt::LowerExp + Send + Sync { }
+unsafe impl Trait for ::std::fmt::LowerHex + Send { }
+unsafe impl Trait for ::std::fmt::LowerHex + Sync { }
+unsafe impl Trait for ::std::fmt::LowerHex + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Octal + Send { }
+unsafe impl Trait for ::std::fmt::Octal + Sync { }
+unsafe impl Trait for ::std::fmt::Octal + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Pointer + Send { }
+unsafe impl Trait for ::std::fmt::Pointer + Sync { }
+unsafe impl Trait for ::std::fmt::Pointer + Send + Sync { }
+unsafe impl Trait for ::std::fmt::UpperExp + Send { }
+unsafe impl Trait for ::std::fmt::UpperExp + Sync { }
+unsafe impl Trait for ::std::fmt::UpperExp + Send + Sync { }
+unsafe impl Trait for ::std::fmt::UpperHex + Send { }
+unsafe impl Trait for ::std::fmt::UpperHex + Sync { }
+unsafe impl Trait for ::std::fmt::UpperHex + Send + Sync { }
+unsafe impl Trait for ::std::fmt::Write + Send { }
+unsafe impl Trait for ::std::fmt::Write + Sync { }
+unsafe impl Trait for ::std::fmt::Write + Send + Sync { }
+unsafe impl Trait for ::std::hash::Hasher + Send { }
+unsafe impl Trait for ::std::hash::Hasher + Sync { }
+unsafe impl Trait for ::std::hash::Hasher + Send + Sync { }
+unsafe impl Trait for ::std::io::BufRead + Send { }
+unsafe impl Trait for ::std::io::BufRead + Sync { }
+unsafe impl Trait for ::std::io::BufRead + Send + Sync { }
+unsafe impl Trait for ::std::io::Read + Send { }
+unsafe impl Trait for ::std::io::Read + Sync { }
+unsafe impl Trait for ::std::io::Read + Send + Sync { }
+unsafe impl Trait for ::std::io::Seek + Send { }
+unsafe impl Trait for ::std::io::Seek + Sync { }
+unsafe impl Trait for ::std::io::Seek + Send + Sync { }
+unsafe impl Trait for ::std::io::Write + Send { }
+unsafe impl Trait for ::std::io::Write + Sync { }
+unsafe impl Trait for ::std::io::Write + Send + Sync { }
+unsafe impl<T, I> Trait for ::std::iter::IntoIterator<IntoIter=I, Item=T> { }
+unsafe impl<T> Trait for ::std::iter::Iterator<Item=T> + Send { }
+unsafe impl<T> Trait for ::std::iter::Iterator<Item=T> + Sync { }
+unsafe impl<T> Trait for ::std::iter::Iterator<Item=T> + Send + Sync { }
+unsafe impl Trait for ::std::marker::Send + Send { }
+unsafe impl Trait for ::std::marker::Send + Sync { }
+unsafe impl Trait for ::std::marker::Send + Send + Sync { }
+unsafe impl Trait for ::std::marker::Sync + Send { }
+unsafe impl Trait for ::std::marker::Sync + Sync { }
+unsafe impl Trait for ::std::marker::Sync + Send + Sync { }
+unsafe impl Trait for ::std::ops::Drop + Send { }
+unsafe impl Trait for ::std::ops::Drop + Sync { }
+unsafe impl Trait for ::std::ops::Drop + Send + Sync { }
+unsafe impl Trait for ::std::string::ToString + Send { }
+unsafe impl Trait for ::std::string::ToString + Sync { }
+unsafe impl Trait for ::std::string::ToString + Send + Sync { }
+fn assert_trait<T: Trait + ?Sized>() {}
+
+fn main() {
+    assert_trait::<dyn Send>();
+    assert_trait::<dyn Sync>();
+    assert_trait::<dyn Send + Sync>();
+}
diff --git a/src/test/ui/issues/issue-33140-traitobject-crate.stderr b/src/test/ui/issues/issue-33140-traitobject-crate.stderr
new file mode 100644
index 00000000000..28193b0eeb9
--- /dev/null
+++ b/src/test/ui/issues/issue-33140-traitobject-crate.stderr
@@ -0,0 +1,39 @@
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: (E0119)
+  --> $DIR/issue-33140-traitobject-crate.rs:85:1
+   |
+LL | unsafe impl Trait for ::std::marker::Send + Sync { }
+   | ------------------------------------------------ first implementation here
+LL | unsafe impl Trait for ::std::marker::Send + Send + Sync { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)`
+   |
+note: lint level defined here
+  --> $DIR/issue-33140-traitobject-crate.rs:3:9
+   |
+LL | #![warn(order_dependent_trait_objects)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: (E0119)
+  --> $DIR/issue-33140-traitobject-crate.rs:86:1
+   |
+LL | unsafe impl Trait for ::std::marker::Send + Send + Sync { }
+   | ------------------------------------------------------- first implementation here
+LL | unsafe impl Trait for ::std::marker::Sync + Send { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`: (E0119)
+  --> $DIR/issue-33140-traitobject-crate.rs:88:1
+   |
+LL | unsafe impl Trait for ::std::marker::Sync + Send { }
+   | ------------------------------------------------ first implementation here
+LL | unsafe impl Trait for ::std::marker::Sync + Sync { }
+LL | unsafe impl Trait for ::std::marker::Sync + Send + Sync { }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)`
+   |
+   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
diff --git a/src/test/ui/issues/issue-33140.rs b/src/test/ui/issues/issue-33140.rs
index 8d19248d5e0..930e24218ac 100644
--- a/src/test/ui/issues/issue-33140.rs
+++ b/src/test/ui/issues/issue-33140.rs
@@ -1,5 +1,3 @@
-#![deny(order_dependent_trait_objects)]
-
 trait Trait {
     fn xyz() -> bool;
 }
@@ -10,7 +8,6 @@ impl Trait for dyn Send + Sync {
 
 impl Trait for dyn Sync + Send {
 //~^ ERROR conflicting implementations
-//~| hard error
     fn xyz() -> bool { true }
 }
 
@@ -24,14 +21,12 @@ impl Trait2 for dyn Send + Sync {
 
 impl Trait2 for dyn Sync + Send + Sync {
 //~^ ERROR conflicting implementations
-//~| hard error
     fn uvw() -> bool { true }
 }
 
 struct Foo<T: ?Sized>(T);
 impl Foo<dyn Send + Sync> {
     fn abc() -> bool { //~ ERROR duplicate definitions with name `abc`
-                       //~| hard error
         false
     }
 }
diff --git a/src/test/ui/issues/issue-33140.stderr b/src/test/ui/issues/issue-33140.stderr
index 520921a7512..6e63828f5f7 100644
--- a/src/test/ui/issues/issue-33140.stderr
+++ b/src/test/ui/issues/issue-33140.stderr
@@ -1,37 +1,25 @@
-error: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
-  --> $DIR/issue-33140.rs:11:1
+error[E0119]: conflicting implementations of trait `Trait` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`:
+  --> $DIR/issue-33140.rs:9:1
    |
 LL | impl Trait for dyn Send + Sync {
    | ------------------------------ first implementation here
 ...
 LL | impl Trait for dyn Sync + Send {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
-   |
-note: lint level defined here
-  --> $DIR/issue-33140.rs:1:9
-   |
-LL | #![deny(order_dependent_trait_objects)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)`
 
-error: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
-  --> $DIR/issue-33140.rs:25:1
+error[E0119]: conflicting implementations of trait `Trait2` for type `(dyn std::marker::Sync + std::marker::Send + 'static)`:
+  --> $DIR/issue-33140.rs:22:1
    |
 LL | impl Trait2 for dyn Send + Sync {
    | ------------------------------- first implementation here
 ...
 LL | impl Trait2 for dyn Sync + Send + Sync {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
-   |
-   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Sync + std::marker::Send + 'static)`
 
-error: duplicate definitions with name `abc` (E0592)
-  --> $DIR/issue-33140.rs:33:5
+error[E0592]: duplicate definitions with name `abc`
+  --> $DIR/issue-33140.rs:29:5
    |
 LL | /     fn abc() -> bool { //~ ERROR duplicate definitions with name `abc`
-LL | |                        //~| hard error
 LL | |         false
 LL | |     }
    | |_____^ duplicate definitions for `abc`
@@ -40,9 +28,8 @@ LL | /     fn abc() -> bool {
 LL | |         true
 LL | |     }
    | |_____- other definition for `abc`
-   |
-   = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
 
 error: aborting due to 3 previous errors
 
+Some errors occurred: E0119, E0592.
+For more information about an error, try `rustc --explain E0119`.