implement a hack to make traitobject 0.1.0 compile
This commit is contained in:
parent
7eb444e4f1
commit
0b511b7bd2
15 changed files with 478 additions and 90 deletions
|
|
@ -492,6 +492,7 @@ define_dep_nodes!( <'tcx>
|
|||
[] AdtDefOfItem(DefId),
|
||||
[] ImplTraitRef(DefId),
|
||||
[] ImplPolarity(DefId),
|
||||
[] Issue33140SelfTy(DefId),
|
||||
[] FnSignature(DefId),
|
||||
[] CoerceUnsizedInfo(DefId),
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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!()); }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
80
src/test/ui/issues/issue-33140-hack-boundaries.rs
Normal file
80
src/test/ui/issues/issue-33140-hack-boundaries.rs
Normal file
|
|
@ -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() {}
|
||||
67
src/test/ui/issues/issue-33140-hack-boundaries.stderr
Normal file
67
src/test/ui/issues/issue-33140-hack-boundaries.stderr
Normal file
|
|
@ -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`.
|
||||
101
src/test/ui/issues/issue-33140-traitobject-crate.rs
Normal file
101
src/test/ui/issues/issue-33140-traitobject-crate.rs
Normal file
|
|
@ -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>();
|
||||
}
|
||||
39
src/test/ui/issues/issue-33140-traitobject-crate.stderr
Normal file
39
src/test/ui/issues/issue-33140-traitobject-crate.stderr
Normal file
|
|
@ -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>
|
||||
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue