Auto merge of #56837 - arielb1:nonprincipal-trait-objects, r=nikomatsakis

Add support for trait-objects without a principal

The hard-error version of #56481 - should be merged after we do something about the `traitobject` crate.

Fixes #33140.
Fixes #57057.

r? @nikomatsakis
This commit is contained in:
bors 2019-01-05 03:36:31 +00:00
commit 2fba17fc97
56 changed files with 816 additions and 454 deletions

View File

@ -492,6 +492,7 @@ define_dep_nodes!( <'tcx>
[] AdtDefOfItem(DefId),
[] ImplTraitRef(DefId),
[] ImplPolarity(DefId),
[] Issue33140SelfTy(DefId),
[] FnSignature(DefId),
[] CoerceUnsizedInfo(DefId),

View File

@ -337,10 +337,6 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
self.infcx.tcx
}
fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.infcx.trait_object_mode()
}
fn tag(&self) -> &'static str {
"Generalizer"
}

View File

@ -29,10 +29,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.fields.infcx.trait_object_mode()
}
fn a_is_expected(&self) -> bool { self.a_is_expected }
fn relate_item_substs(&mut self,

View File

@ -5,7 +5,7 @@ use super::Subtype;
use traits::ObligationCause;
use ty::{self, Ty, TyCtxt};
use ty::relate::{self, Relate, RelateResult, TypeRelation};
use ty::relate::{Relate, RelateResult, TypeRelation};
/// "Greatest lower bound" (common subtype)
pub struct Glb<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
@ -26,10 +26,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Glb" }
fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.fields.infcx.trait_object_mode()
}
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
fn a_is_expected(&self) -> bool { self.a_is_expected }

View File

@ -5,7 +5,7 @@ use super::Subtype;
use traits::ObligationCause;
use ty::{self, Ty, TyCtxt};
use ty::relate::{self, Relate, RelateResult, TypeRelation};
use ty::relate::{Relate, RelateResult, TypeRelation};
/// "Least upper bound" (common supertype)
pub struct Lub<'combine, 'infcx: 'combine, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
@ -26,10 +26,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Lub" }
fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.fields.infcx.trait_object_mode()
}
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
fn a_is_expected(&self) -> bool { self.a_is_expected }

View File

@ -25,7 +25,7 @@ use syntax_pos::{self, Span};
use traits::{self, ObligationCause, PredicateObligations, TraitEngine};
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
use ty::fold::TypeFoldable;
use ty::relate::{RelateResult, TraitObjectMode};
use ty::relate::RelateResult;
use ty::subst::{Kind, Substs};
use ty::{self, GenericParamDefKind, Ty, TyCtxt, CtxtInterners};
use ty::{FloatVid, IntVid, TyVid};
@ -171,9 +171,6 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
// This flag is true while there is an active snapshot.
in_snapshot: Cell<bool>,
// The TraitObjectMode used here,
trait_object_mode: TraitObjectMode,
// A set of constraints that regionck must validate. Each
// constraint has the form `T:'a`, meaning "some type `T` must
// outlive the lifetime 'a". These constraints derive from
@ -465,7 +462,6 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
arena: SyncDroplessArena,
interners: Option<CtxtInterners<'tcx>>,
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
trait_object_mode: TraitObjectMode,
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
@ -475,7 +471,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
arena: SyncDroplessArena::default(),
interners: None,
fresh_tables: None,
trait_object_mode: TraitObjectMode::NoSquash,
}
}
}
@ -488,12 +483,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
self
}
pub fn with_trait_object_mode(mut self, mode: TraitObjectMode) -> Self {
debug!("with_trait_object_mode: setting mode to {:?}", mode);
self.trait_object_mode = mode;
self
}
/// Given a canonical value `C` as a starting point, create an
/// inference context that contains each of the bound values
/// within instantiated as a fresh variable. The `f` closure is
@ -520,7 +509,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
pub fn enter<R>(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R {
let InferCtxtBuilder {
global_tcx,
trait_object_mode,
ref arena,
ref mut interners,
ref fresh_tables,
@ -532,7 +520,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
f(InferCtxt {
tcx,
in_progress_tables,
trait_object_mode,
projection_cache: Default::default(),
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
int_unification_table: RefCell::new(ut::UnificationTable::new()),
@ -614,10 +601,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.in_snapshot.get()
}
pub fn trait_object_mode(&self) -> TraitObjectMode {
self.trait_object_mode
}
pub fn freshen<T: TypeFoldable<'tcx>>(&self, t: T) -> T {
t.fold_with(&mut self.freshener())
}

View File

@ -372,13 +372,6 @@ where
self.infcx.tcx
}
fn trait_object_mode(&self) -> relate::TraitObjectMode {
// squashing should only be done in coherence, not NLL
assert_eq!(self.infcx.trait_object_mode(),
relate::TraitObjectMode::NoSquash);
relate::TraitObjectMode::NoSquash
}
fn tag(&self) -> &'static str {
"nll::subtype"
}
@ -693,13 +686,6 @@ where
self.infcx.tcx
}
fn trait_object_mode(&self) -> relate::TraitObjectMode {
// squashing should only be done in coherence, not NLL
assert_eq!(self.infcx.trait_object_mode(),
relate::TraitObjectMode::NoSquash);
relate::TraitObjectMode::NoSquash
}
fn tag(&self) -> &'static str {
"nll::generalizer"
}

View File

@ -5,7 +5,7 @@ use traits::Obligation;
use ty::{self, Ty, TyCtxt};
use ty::TyVar;
use ty::fold::TypeFoldable;
use ty::relate::{self, Cause, Relate, RelateResult, TypeRelation};
use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use std::mem;
/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
@ -33,10 +33,6 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx>
for Sub<'combine, 'infcx, 'gcx, 'tcx>
{
fn tag(&self) -> &'static str { "Sub" }
fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.fields.infcx.trait_object_mode()
}
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx }
fn a_is_expected(&self) -> bool { self.a_is_expected }

View File

@ -11,7 +11,6 @@ use traits::{self, Normalized, SelectionContext, Obligation, ObligationCause};
use traits::IntercrateMode;
use traits::select::IntercrateAmbiguityCause;
use ty::{self, Ty, TyCtxt};
use ty::relate::TraitObjectMode;
use ty::fold::TypeFoldable;
use ty::subst::Subst;
@ -55,7 +54,6 @@ pub fn overlapping_impls<'gcx, F1, F2, R>(
impl1_def_id: DefId,
impl2_def_id: DefId,
intercrate_mode: IntercrateMode,
trait_object_mode: TraitObjectMode,
on_overlap: F1,
no_overlap: F2,
) -> R
@ -66,14 +64,12 @@ where
debug!("overlapping_impls(\
impl1_def_id={:?}, \
impl2_def_id={:?},
intercrate_mode={:?},
trait_object_mode={:?})",
intercrate_mode={:?})",
impl1_def_id,
impl2_def_id,
intercrate_mode,
trait_object_mode);
intercrate_mode);
let overlaps = tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| {
let overlaps = tcx.infer_ctxt().enter(|infcx| {
let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
overlap(selcx, impl1_def_id, impl2_def_id).is_some()
});
@ -85,7 +81,7 @@ where
// In the case where we detect an error, run the check again, but
// this time tracking intercrate ambuiguity causes for better
// diagnostics. (These take time and can lead to false errors.)
tcx.infer_ctxt().with_trait_object_mode(trait_object_mode).enter(|infcx| {
tcx.infer_ctxt().enter(|infcx| {
let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
selcx.enable_tracking_intercrate_ambiguity_causes();
on_overlap(overlap(selcx, impl1_def_id, impl2_def_id).unwrap())
@ -510,7 +506,13 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
ty::Adt(def, _) => def_id_is_local(def.did, in_crate),
ty::Foreign(did) => def_id_is_local(did, in_crate),
ty::Dynamic(ref tt, ..) => def_id_is_local(tt.principal().def_id(), in_crate),
ty::Dynamic(ref tt, ..) => {
if let Some(principal) = tt.principal() {
def_id_is_local(principal.def_id(), in_crate)
} else {
false
}
}
ty::Error => true,

View File

@ -447,7 +447,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
{
let simp = fast_reject::simplify_type(self.tcx,
trait_ref.skip_binder().self_ty(),
true,);
true);
let all_impls = self.tcx.all_impls(trait_ref.def_id());
match simp {

View File

@ -33,7 +33,7 @@ use infer::{InferCtxt, InferOk, TypeFreshener};
use middle::lang_items;
use mir::interpret::GlobalId;
use ty::fast_reject;
use ty::relate::{TypeRelation, TraitObjectMode};
use ty::relate::TypeRelation;
use ty::subst::{Subst, Substs};
use ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
@ -1416,13 +1416,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
return false;
}
// Same idea as the above, but for alt trait object modes. These
// should only be used in intercrate mode - better safe than sorry.
if self.infcx.trait_object_mode() != TraitObjectMode::NoSquash {
bug!("using squashing TraitObjectMode outside of intercrate mode? param_env={:?}",
param_env);
}
// Otherwise, we can use the global cache.
true
}
@ -2016,7 +2009,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
return;
}
data.principal().with_self_ty(self.tcx(), self_ty)
if let Some(principal) = data.principal() {
principal.with_self_ty(self.tcx(), self_ty)
} else {
// Only auto-trait bounds exist.
return;
}
}
ty::Infer(ty::TyVar(_)) => {
debug!("assemble_candidates_from_object_ty: ambiguous");
@ -2108,7 +2106,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
//
// We always upcast when we can because of reason
// #2 (region bounds).
data_a.principal().def_id() == data_b.principal().def_id()
data_a.principal_def_id() == data_b.principal_def_id()
&& data_b.auto_traits()
// All of a's auto traits need to be in b's auto traits.
.all(|b| data_a.auto_traits().any(|a| a == b))
@ -2262,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.
@ -2919,7 +2918,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let self_ty = self.infcx
.shallow_resolve(*obligation.self_ty().skip_binder());
let poly_trait_ref = match self_ty.sty {
ty::Dynamic(ref data, ..) => data.principal().with_self_ty(self.tcx(), self_ty),
ty::Dynamic(ref data, ..) =>
data.principal().unwrap_or_else(|| {
span_bug!(obligation.cause.span, "object candidate with no principal")
}).with_self_ty(self.tcx(), self_ty),
_ => span_bug!(obligation.cause.span, "object candidate with non-object"),
};
@ -3222,8 +3224,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
(&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => {
// See assemble_candidates_for_unsizing for more info.
let existential_predicates = data_a.map_bound(|data_a| {
let iter = iter::once(ty::ExistentialPredicate::Trait(data_a.principal()))
.chain(
let iter =
data_a.principal().map(|x| ty::ExistentialPredicate::Trait(x))
.into_iter().chain(
data_a
.projection_bounds()
.map(|x| ty::ExistentialPredicate::Projection(x)),
@ -3260,7 +3263,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// T -> Trait.
(_, &ty::Dynamic(ref data, r)) => {
let mut object_dids = data.auto_traits()
.chain(iter::once(data.principal().def_id()));
.chain(data.principal_def_id());
if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
return Err(TraitNotObjectSafe(did));
}
@ -3571,8 +3574,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
previous: &ty::PolyTraitRef<'tcx>,
current: &ty::PolyTraitRef<'tcx>,
) -> bool {
let mut matcher = ty::_match::Match::new(
self.tcx(), self.infcx.trait_object_mode());
let mut matcher = ty::_match::Match::new(self.tcx());
matcher.relate(previous, current).is_ok()
}

View File

@ -14,8 +14,7 @@ pub mod specialization_graph;
use hir::def_id::DefId;
use infer::{InferCtxt, InferOk};
use lint;
use traits::{self, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine};
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;

View File

@ -7,7 +7,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
use traits;
use ty::{self, TyCtxt, TypeFoldable};
use ty::fast_reject::{self, SimplifiedType};
use ty::relate::TraitObjectMode;
use rustc_data_structures::sync::Lrc;
use syntax::ast::Ident;
use util::captures::Captures;
@ -174,9 +173,20 @@ impl<'a, 'gcx, 'tcx> Children {
possible_sibling,
impl_def_id,
traits::IntercrateMode::Issue43355,
TraitObjectMode::NoSquash,
|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));
}
@ -204,31 +214,17 @@ impl<'a, 'gcx, 'tcx> Children {
replace_children.push(possible_sibling);
} else {
if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
// do future-compat checks for overlap. Have issue #43355
// errors overwrite issue #33140 errors when both are present.
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,
TraitObjectMode::SquashAutoTraitsIssue33140,
|overlap| {
last_lint = Some(FutureCompatOverlapError {
error: overlap_error(overlap),
kind: FutureCompatOverlapErrorKind::Issue33140
});
},
|| (),
);
traits::overlapping_impls(
tcx,
possible_sibling,
impl_def_id,
traits::IntercrateMode::Fixed,
TraitObjectMode::NoSquash,
|overlap| {
last_lint = Some(FutureCompatOverlapError {
error: overlap_error(overlap),

View File

@ -19,24 +19,17 @@ use ty::relate::{self, Relate, TypeRelation, RelateResult};
/// important thing about the result is Ok/Err. Also, matching never
/// affects any type variables or unification state.
pub struct Match<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
trait_object_mode: relate::TraitObjectMode
tcx: TyCtxt<'a, 'gcx, 'tcx>
}
impl<'a, 'gcx, 'tcx> Match<'a, 'gcx, 'tcx> {
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
trait_object_mode: relate::TraitObjectMode)
-> Match<'a, 'gcx, 'tcx> {
Match { tcx, trait_object_mode }
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Match<'a, 'gcx, 'tcx> {
Match { tcx }
}
}
impl<'a, 'gcx, 'tcx> TypeRelation<'a, 'gcx, 'tcx> for Match<'a, 'gcx, 'tcx> {
fn tag(&self) -> &'static str { "Match" }
fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.trait_object_mode
}
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.tcx }
fn a_is_expected(&self) -> bool { true } // irrelevant

View File

@ -184,7 +184,11 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
ty::FnDef(..) => "fn item".into(),
ty::FnPtr(_) => "fn pointer".into(),
ty::Dynamic(ref inner, ..) => {
format!("trait {}", tcx.item_path_str(inner.principal().def_id())).into()
if let Some(principal) = inner.principal() {
format!("trait {}", tcx.item_path_str(principal.def_id())).into()
} else {
"trait".into()
}
}
ty::Closure(..) => "closure".into(),
ty::Generator(..) => "generator".into(),

View File

@ -71,11 +71,11 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
ty::Array(..) | ty::Slice(_) => Some(ArraySimplifiedType),
ty::RawPtr(_) => Some(PtrSimplifiedType),
ty::Dynamic(ref trait_info, ..) => {
let principal_def_id = trait_info.principal().def_id();
if tcx.trait_is_auto(principal_def_id) {
Some(MarkerTraitObjectSimplifiedType)
} else {
Some(TraitSimplifiedType(principal_def_id))
match trait_info.principal_def_id() {
Some(principal_def_id) if !tcx.trait_is_auto(principal_def_id) => {
Some(TraitSimplifiedType(principal_def_id))
}
_ => Some(MarkerTraitObjectSimplifiedType)
}
}
ty::Ref(_, ty, _) => {
@ -140,9 +140,9 @@ impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> {
ArraySimplifiedType => ArraySimplifiedType,
PtrSimplifiedType => PtrSimplifiedType,
NeverSimplifiedType => NeverSimplifiedType,
MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
TupleSimplifiedType(n) => TupleSimplifiedType(n),
TraitSimplifiedType(d) => TraitSimplifiedType(map(d)),
MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType,
ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)),
GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)),
GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n),

View File

@ -479,7 +479,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
match ty.sty {
ty::Adt(adt_def, _) => Some(adt_def.did),
ty::Dynamic(data, ..) => Some(data.principal().def_id()),
ty::Dynamic(data, ..) => data.principal_def_id(),
ty::Array(subty, _) |
ty::Slice(subty) => characteristic_def_id_of_type(subty),

View File

@ -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
};
}

View File

@ -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 {

View File

@ -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!()); }

View File

@ -24,20 +24,9 @@ pub enum Cause {
ExistentialRegionBound, // relating an existential region bound
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum TraitObjectMode {
NoSquash,
/// A temporary mode to treat `Send + Sync = Sync + Send`, should be
/// used only in coherence.
SquashAutoTraitsIssue33140
}
pub trait TypeRelation<'a, 'gcx: 'a+'tcx, 'tcx: 'a> : Sized {
fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx>;
/// Return the trait object mode to be used.
fn trait_object_mode(&self) -> TraitObjectMode;
/// Returns a static string we can use for printouts.
fn tag(&self) -> &'static str;
@ -591,44 +580,14 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::ExistentialPredicate<'tcx>> {
a: &Self,
b: &Self)
-> RelateResult<'tcx, Self>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
use ty::ExistentialPredicate::*;
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a {
let tcx = relation.tcx();
let (a_buf, b_buf);
let (a_norm, b_norm): (&[_], &[_]) = match relation.trait_object_mode() {
TraitObjectMode::NoSquash => {
(a, b)
}
TraitObjectMode::SquashAutoTraitsIssue33140 => {
// Treat auto-trait "principal" components as equal
// to the non-principal components, to make
// `dyn Send+Sync = dyn Sync+Send`.
let normalize = |d: &[ty::ExistentialPredicate<'tcx>]| {
let mut result: Vec<_> = d.iter().map(|pi| match pi {
Trait(ref a) if tcx.trait_is_auto(a.def_id) => {
AutoTrait(a.def_id)
},
other => *other
}).collect();
result.sort_by(|a, b| a.stable_cmp(tcx, b));
result.dedup();
result
};
a_buf = normalize(a);
b_buf = normalize(b);
(&a_buf, &b_buf)
}
};
if a_norm.len() != b_norm.len() {
if a.len() != b.len() {
return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b)));
}
let v = a_norm.iter().zip(b_norm.iter()).map(|(ep_a, ep_b)| {
let tcx = relation.tcx();
let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| {
use ty::ExistentialPredicate::*;
match (*ep_a, *ep_b) {
(Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)),

View File

@ -569,13 +569,42 @@ impl<'a, 'gcx, 'tcx> Binder<ExistentialPredicate<'tcx>> {
impl<'tcx> serialize::UseSpecializedDecodable for &'tcx List<ExistentialPredicate<'tcx>> {}
impl<'tcx> List<ExistentialPredicate<'tcx>> {
pub fn principal(&self) -> ExistentialTraitRef<'tcx> {
/// Returns the "principal def id" of this set of existential predicates.
///
/// A Rust trait object type consists (in addition to a lifetime bound)
/// of a set of trait bounds, which are separated into any number
/// of auto-trait bounds, and at most 1 non-auto-trait bound. The
/// non-auto-trait bound is called the "principal" of the trait
/// object.
///
/// Only the principal can have methods or type parameters (because
/// auto traits can have neither of them). This is important, because
/// it means the auto traits can be treated as an unordered set (methods
/// would force an order for the vtable, while relating traits with
/// type parameters without knowing the order to relate them in is
/// a rather non-trivial task).
///
/// For example, in the trait object `dyn fmt::Debug + Sync`, the
/// principal bound is `Some(fmt::Debug)`, while the auto-trait bounds
/// are the set `{Sync}`.
///
/// It is also possible to have a "trivial" trait object that
/// consists only of auto traits, with no principal - for example,
/// `dyn Send + Sync`. In that case, the set of auto-trait bounds
/// is `{Send, Sync}`, while there is no principal. These trait objects
/// have a "trivial" vtable consisting of just the size, alignment,
/// and destructor.
pub fn principal(&self) -> Option<ExistentialTraitRef<'tcx>> {
match self[0] {
ExistentialPredicate::Trait(tr) => tr,
other => bug!("first predicate is {:?}", other),
ExistentialPredicate::Trait(tr) => Some(tr),
_ => None
}
}
pub fn principal_def_id(&self) -> Option<DefId> {
self.principal().map(|d| d.def_id)
}
#[inline]
pub fn projection_bounds<'a>(&'a self) ->
impl Iterator<Item=ExistentialProjection<'tcx>> + 'a {
@ -599,8 +628,12 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
}
impl<'tcx> Binder<&'tcx List<ExistentialPredicate<'tcx>>> {
pub fn principal(&self) -> PolyExistentialTraitRef<'tcx> {
Binder::bind(self.skip_binder().principal())
pub fn principal(&self) -> Option<ty::Binder<ExistentialTraitRef<'tcx>>> {
self.skip_binder().principal().map(Binder::bind)
}
pub fn principal_def_id(&self) -> Option<DefId> {
self.skip_binder().principal_def_id()
}
#[inline]
@ -1917,7 +1950,9 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
Dynamic(ref obj, region) => {
out.push(region);
out.extend(obj.principal().skip_binder().substs.regions());
if let Some(principal) = obj.principal() {
out.extend(principal.skip_binder().substs.regions());
}
}
Adt(_, substs) | Opaque(_, substs) => {
out.extend(substs.regions())

View File

@ -381,7 +381,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
let cause = self.cause(traits::MiscObligation);
let component_traits =
data.auto_traits().chain(once(data.principal().def_id()));
data.auto_traits().chain(data.principal_def_id());
self.out.extend(
component_traits.map(|did| traits::Obligation::new(
cause.clone(),

View File

@ -711,21 +711,43 @@ define_print! {
ty::tls::with(|tcx| {
// Use a type that can't appear in defaults of type parameters.
let dummy_self = tcx.mk_infer(ty::FreshTy(0));
let mut first = true;
let principal = tcx
.lift(&self.principal())
.expect("could not lift TraitRef for printing")
.with_self_ty(tcx, dummy_self);
let projections = self.projection_bounds().map(|p| {
tcx.lift(&p)
.expect("could not lift projection for printing")
.with_self_ty(tcx, dummy_self)
}).collect::<Vec<_>>();
cx.parameterized(f, principal.substs, principal.def_id, &projections)?;
if let Some(principal) = self.principal() {
let principal = tcx
.lift(&principal)
.expect("could not lift TraitRef for printing")
.with_self_ty(tcx, dummy_self);
let projections = self.projection_bounds().map(|p| {
tcx.lift(&p)
.expect("could not lift projection for printing")
.with_self_ty(tcx, dummy_self)
}).collect::<Vec<_>>();
cx.parameterized(f, principal.substs, principal.def_id, &projections)?;
first = false;
}
// Builtin bounds.
for did in self.auto_traits() {
write!(f, " + {}", tcx.item_path_str(did))?;
let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
tcx.item_path_str(did)
}).collect();
// The auto traits come ordered by `DefPathHash`. While
// `DefPathHash` is *stable* in the sense that it depends on
// neither the host nor the phase of the moon, it depends
// "pseudorandomly" on the compiler version and the target.
//
// To avoid that causing instabilities in compiletest
// output, sort the auto-traits alphabetically.
auto_traits.sort();
for auto_trait in auto_traits {
if !first {
write!(f, " + ")?;
}
first = false;
write!(f, "{}", auto_trait)?;
}
Ok(())

View File

@ -50,7 +50,8 @@ pub struct CodegenCx<'ll, 'tcx: 'll> {
/// Cache instances of monomorphic and polymorphic items
pub instances: RefCell<FxHashMap<Instance<'tcx>, &'ll Value>>,
/// Cache generated vtables
pub vtables: RefCell<FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), &'ll Value>>,
pub vtables: RefCell<FxHashMap<
(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>,
/// Cache of constant strings,
pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, &'ll Value>>,
@ -311,7 +312,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
fn vtables(&self) -> &RefCell<FxHashMap<(Ty<'tcx>,
ty::PolyExistentialTraitRef<'tcx>), &'ll Value>>
Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>
{
&self.vtables
}

View File

@ -429,7 +429,8 @@ fn trait_pointer_metadata(
// But it does not describe the trait's methods.
let containing_scope = match trait_type.sty {
ty::Dynamic(ref data, ..) => Some(get_namespace_for_item(cx, data.principal().def_id())),
ty::Dynamic(ref data, ..) =>
data.principal_def_id().map(|did| get_namespace_for_item(cx, did)),
_ => {
bug!("debuginfo: Unexpected trait-object type in \
trait_pointer_metadata(): {:?}",

View File

@ -107,12 +107,16 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
}
},
ty::Dynamic(ref trait_data, ..) => {
let principal = cx.tcx.normalize_erasing_late_bound_regions(
ty::ParamEnv::reveal_all(),
&trait_data.principal(),
);
push_item_name(cx, principal.def_id, false, output);
push_type_params(cx, principal.substs, output);
if let Some(principal) = trait_data.principal() {
let principal = cx.tcx.normalize_erasing_late_bound_regions(
ty::ParamEnv::reveal_all(),
&principal,
);
push_item_name(cx, principal.def_id, false, output);
push_type_params(cx, principal.substs, output);
} else {
output.push_str("dyn '_");
}
},
ty::FnDef(..) | ty::FnPtr(_) => {
let sig = t.fn_sig(cx.tcx);

View File

@ -69,7 +69,7 @@ impl<'a, 'tcx: 'a> VirtualIndex {
pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
cx: &Cx,
ty: Ty<'tcx>,
trait_ref: ty::PolyExistentialTraitRef<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> Cx::Value {
let tcx = cx.tcx();
@ -83,8 +83,15 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
// Not in the cache. Build it.
let nullptr = cx.const_null(cx.type_i8p());
let methods = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
let methods = methods.iter().cloned().map(|opt_mth| {
let methods_root;
let methods = if let Some(trait_ref) = trait_ref {
methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, ty));
methods_root.iter()
} else {
(&[]).iter()
};
let methods = methods.cloned().map(|opt_mth| {
opt_mth.map_or(nullptr, |(def_id, substs)| {
callee::resolve_and_get_fn_for_vtable(cx, def_id, substs)
})

View File

@ -11,7 +11,7 @@ use std::sync::Arc;
pub trait MiscMethods<'tcx>: BackendTypes {
fn vtables(
&self,
) -> &RefCell<FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), Self::Value>>;
) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>;
fn check_overflow(&self) -> bool;
fn instances(&self) -> &RefCell<FxHashMap<Instance<'tcx>, Self::Value>>;
fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value;

View File

@ -42,7 +42,7 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>>,
/// A cache for deduplicating vtables
pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyExistentialTraitRef<'tcx>), AllocId>,
pub(super) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>,
}
/// A stack frame.

View File

@ -1,3 +1,4 @@
use rustc_data_structures::sync::Lrc;
use rustc::ty::{self, Ty};
use rustc::ty::layout::{Size, Align, LayoutOf};
use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
@ -14,7 +15,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
pub fn get_vtable(
&mut self,
ty: Ty<'tcx>,
poly_trait_ref: ty::PolyExistentialTraitRef<'tcx>,
poly_trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
trace!("get_vtable(trait_ref={:?})", poly_trait_ref);
@ -24,10 +25,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
return Ok(Pointer::from(vtable).with_default_tag());
}
let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
let trait_ref = self.tcx.erase_regions(&trait_ref);
let methods = if let Some(poly_trait_ref) = poly_trait_ref {
let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
let trait_ref = self.tcx.erase_regions(&trait_ref);
let methods = self.tcx.vtable_methods(trait_ref);
self.tcx.vtable_methods(trait_ref)
} else {
Lrc::new(Vec::new())
};
let layout = self.layout_of(ty)?;
assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");

View File

@ -894,20 +894,23 @@ fn create_mono_items_for_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
!impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars());
if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty {
let poly_trait_ref = trait_ty.principal().with_self_ty(tcx, impl_ty);
assert!(!poly_trait_ref.has_escaping_bound_vars());
if let Some(principal) = trait_ty.principal() {
let poly_trait_ref = principal.with_self_ty(tcx, impl_ty);
assert!(!poly_trait_ref.has_escaping_bound_vars());
// Walk all methods of the trait, including those of its supertraits
let methods = tcx.vtable_methods(poly_trait_ref);
let methods = methods.iter().cloned().filter_map(|method| method)
.map(|(def_id, substs)| ty::Instance::resolve_for_vtable(
// Walk all methods of the trait, including those of its supertraits
let methods = tcx.vtable_methods(poly_trait_ref);
let methods = methods.iter().cloned().filter_map(|method| method)
.map(|(def_id, substs)| ty::Instance::resolve_for_vtable(
tcx,
ty::ParamEnv::reveal_all(),
def_id,
substs).unwrap())
.filter(|&instance| should_monomorphize_locally(tcx, &instance))
.map(|instance| create_fn_mono_item(instance));
output.extend(methods);
.filter(|&instance| should_monomorphize_locally(tcx, &instance))
.map(|instance| create_fn_mono_item(instance));
output.extend(methods);
}
// Also add the destructor
visit_drop_use(tcx, impl_ty, false, output);
}

View File

@ -304,13 +304,16 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
output.push(']');
},
ty::Dynamic(ref trait_data, ..) => {
let principal = trait_data.principal();
self.push_def_path(principal.def_id(), output);
self.push_type_params(
principal.skip_binder().substs,
trait_data.projection_bounds(),
output,
);
if let Some(principal) = trait_data.principal() {
self.push_def_path(principal.def_id(), output);
self.push_type_params(
principal.skip_binder().substs,
trait_data.projection_bounds(),
output,
);
} else {
output.push_str("dyn '_");
}
},
ty::Foreign(did) => self.push_def_path(did, output),
ty::FnDef(..) |

View File

@ -17,7 +17,7 @@ use rustc::traits::{
};
use rustc::ty::{self, Ty};
use rustc::ty::subst::Kind;
use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
use syntax_pos::DUMMY_SP;
use super::{ChalkInferenceContext, ChalkArenas, ChalkExClause, ConstrainedSubst};
@ -157,10 +157,6 @@ impl TypeRelation<'cx, 'gcx, 'tcx> for AnswerSubstitutor<'cx, 'gcx, 'tcx> {
self.infcx.tcx
}
fn trait_object_mode(&self) -> relate::TraitObjectMode {
self.infcx.trait_object_mode()
}
fn tag(&self) -> &'static str {
"chalk_context::answer_substitutor"
}

View File

@ -1138,13 +1138,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
auto_traits.dedup();
// Calling `skip_binder` is okay, because the predicates are re-bound.
let principal = if tcx.trait_is_auto(existential_principal.def_id()) {
ty::ExistentialPredicate::AutoTrait(existential_principal.def_id())
} else {
ty::ExistentialPredicate::Trait(*existential_principal.skip_binder())
};
let mut v =
iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
iter::once(principal)
.chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait))
.chain(existential_projections
.map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder())))
.collect::<SmallVec<[_; 8]>>();
v.sort_by(|a, b| a.stable_cmp(tcx, b));
v.dedup();
let existential_predicates = ty::Binder::bind(tcx.mk_existential_predicates(v.into_iter()));
// Use explicitly-specified region bound.

View File

@ -63,7 +63,7 @@ enum PointerKind<'tcx> {
/// No metadata attached, ie pointer to sized type or foreign type
Thin,
/// A trait object
Vtable(DefId),
Vtable(Option<DefId>),
/// Slice
Length,
/// The unsize info of this projection
@ -95,7 +95,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Ok(match t.sty {
ty::Slice(_) | ty::Str => Some(PointerKind::Length),
ty::Dynamic(ref tty, ..) =>
Some(PointerKind::Vtable(tty.principal().def_id())),
Some(PointerKind::Vtable(tty.principal_def_id())),
ty::Adt(def, substs) if def.is_struct() => {
match def.non_enum_variant().fields.last() {
None => Some(PointerKind::Thin),

View File

@ -190,7 +190,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.deduce_sig_from_projection(None, &pb)
})
.next();
let kind = self.tcx.lang_items().fn_trait_kind(object_type.principal().def_id());
let kind = object_type.principal_def_id().and_then(|did| {
self.tcx.lang_items().fn_trait_kind(did)
});
(sig, kind)
}
ty::Infer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid),

View File

@ -280,7 +280,11 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
.include_raw_pointers()
.filter_map(|(ty, _)|
match ty.sty {
ty::Dynamic(ref data, ..) => Some(closure(self, ty, data.principal())),
ty::Dynamic(ref data, ..) => {
Some(closure(self, ty, data.principal().unwrap_or_else(|| {
span_bug!(self.span, "calling trait method on empty object?")
})))
},
_ => None,
}
)

View File

@ -505,17 +505,18 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
match self_ty.value.value.sty {
ty::Dynamic(ref data, ..) => {
let p = data.principal();
self.fcx.probe(|_| {
let InferOk { value: self_ty, obligations: _ } =
self.fcx.probe_instantiate_query_response(
self.span, &self.orig_steps_var_values, self_ty)
.unwrap_or_else(|_| {
span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty)
});
self.assemble_inherent_candidates_from_object(self_ty);
});
self.assemble_inherent_impl_candidates_for_type(p.def_id());
if let Some(p) = data.principal() {
self.fcx.probe(|_| {
let InferOk { value: self_ty, obligations: _ } =
self.fcx.probe_instantiate_query_response(
self.span, &self.orig_steps_var_values, self_ty)
.unwrap_or_else(|_| {
span_bug!(self.span, "{:?} was applicable but now isn't?", self_ty)
});
self.assemble_inherent_candidates_from_object(self_ty);
});
self.assemble_inherent_impl_candidates_for_type(p.def_id());
}
}
ty::Adt(def, _) => {
self.assemble_inherent_impl_candidates_for_type(def.did);
@ -680,10 +681,12 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
self_ty);
let principal = match self_ty.sty {
ty::Dynamic(ref data, ..) => data.principal(),
_ => span_bug!(self.span, "non-object {:?} in assemble_inherent_candidates_from_object",
self_ty)
};
ty::Dynamic(ref data, ..) => Some(data),
_ => None
}.and_then(|data| data.principal()).unwrap_or_else(|| {
span_bug!(self.span, "non-object {:?} in assemble_inherent_candidates_from_object",
self_ty)
});
// It is illegal to invoke a method on a trait instance that
// refers to the `Self` type. An error will be reported by

View File

@ -651,7 +651,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
ty::Adt(def, _) => def.did.is_local(),
ty::Foreign(did) => did.is_local(),
ty::Dynamic(ref tr, ..) => tr.principal().def_id().is_local(),
ty::Dynamic(ref tr, ..) =>
tr.principal().map(|d| d.def_id().is_local()).unwrap_or(false),
ty::Param(_) => true,

View File

@ -95,8 +95,8 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
ty::Foreign(did) => {
self.check_def_id(item, did);
}
ty::Dynamic(ref data, ..) => {
self.check_def_id(item, data.principal().def_id());
ty::Dynamic(ref data, ..) if data.principal_def_id().is_some() => {
self.check_def_id(item, data.principal_def_id().unwrap());
}
ty::Char => {
self.check_primitive_impl(def_id,

View File

@ -2,9 +2,8 @@ use namespace::Namespace;
use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::hir;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::traits::{self, IntercrateMode, FutureCompatOverlapErrorKind};
use rustc::traits::{self, IntercrateMode};
use rustc::ty::TyCtxt;
use rustc::ty::relate::TraitObjectMode;
use lint;
@ -20,11 +19,9 @@ struct InherentOverlapChecker<'a, 'tcx: 'a> {
}
impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
fn check_for_common_items_in_impls(
&self, impl1: DefId, impl2: DefId,
overlap: traits::OverlapResult,
used_to_be_allowed: Option<FutureCompatOverlapErrorKind>)
{
fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId,
overlap: traits::OverlapResult,
used_to_be_allowed: bool) {
let name_and_namespace = |def_id| {
let item = self.tcx.associated_item(def_id);
@ -40,28 +37,19 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
for &item2 in &impl_items2[..] {
if (name, namespace) == name_and_namespace(item2) {
let node_id = self.tcx.hir().as_local_node_id(impl1);
let mut err = match used_to_be_allowed {
Some(kind) if node_id.is_some() => {
let lint = match kind {
FutureCompatOverlapErrorKind::Issue43355 =>
lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
FutureCompatOverlapErrorKind::Issue33140 =>
lint::builtin::ORDER_DEPENDENT_TRAIT_OBJECTS,
};
self.tcx.struct_span_lint_node(
lint,
node_id.unwrap(),
self.tcx.span_of_impl(item1).unwrap(),
&format!("duplicate definitions with name `{}` (E0592)", name)
)
}
_ => {
struct_span_err!(self.tcx.sess,
self.tcx.span_of_impl(item1).unwrap(),
E0592,
"duplicate definitions with name `{}`",
name)
}
let mut err = if used_to_be_allowed && node_id.is_some() {
self.tcx.struct_span_lint_node(
lint::builtin::INCOHERENT_FUNDAMENTAL_IMPLS,
node_id.unwrap(),
self.tcx.span_of_impl(item1).unwrap(),
&format!("duplicate definitions with name `{}` (E0592)", name)
)
} else {
struct_span_err!(self.tcx.sess,
self.tcx.span_of_impl(item1).unwrap(),
E0592,
"duplicate definitions with name `{}`",
name)
};
err.span_label(self.tcx.span_of_impl(item1).unwrap(),
@ -88,73 +76,38 @@ impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
for (i, &impl1_def_id) in impls.iter().enumerate() {
for &impl2_def_id in &impls[(i + 1)..] {
// First, check if the impl was forbidden under the
// old rules. In that case, just have an error.
let used_to_be_allowed = traits::overlapping_impls(
self.tcx,
impl1_def_id,
impl2_def_id,
IntercrateMode::Issue43355,
TraitObjectMode::NoSquash,
|overlap| {
self.check_for_common_items_in_impls(
impl1_def_id,
impl2_def_id,
overlap,
None,
false,
);
false
},
|| true,
);
if !used_to_be_allowed {
continue;
if used_to_be_allowed {
traits::overlapping_impls(
self.tcx,
impl1_def_id,
impl2_def_id,
IntercrateMode::Fixed,
|overlap| self.check_for_common_items_in_impls(
impl1_def_id,
impl2_def_id,
overlap,
true,
),
|| (),
);
}
// Then, check if the impl was forbidden under only
// #43355. In that case, emit an #43355 error.
let used_to_be_allowed = traits::overlapping_impls(
self.tcx,
impl1_def_id,
impl2_def_id,
IntercrateMode::Fixed,
TraitObjectMode::NoSquash,
|overlap| {
self.check_for_common_items_in_impls(
impl1_def_id,
impl2_def_id,
overlap,
Some(FutureCompatOverlapErrorKind::Issue43355),
);
false
},
|| true,
);
if !used_to_be_allowed {
continue;
}
// Then, check if the impl was forbidden under
// #33140. In that case, emit a #33140 error.
traits::overlapping_impls(
self.tcx,
impl1_def_id,
impl2_def_id,
IntercrateMode::Fixed,
TraitObjectMode::SquashAutoTraitsIssue33140,
|overlap| {
self.check_for_common_items_in_impls(
impl1_def_id,
impl2_def_id,
overlap,
Some(FutureCompatOverlapErrorKind::Issue33140),
);
false
},
|| true,
);
}
}
}

View File

@ -171,25 +171,28 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI
// This is something like impl Trait1 for Trait2. Illegal
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
if !tcx.is_object_safe(data.principal().def_id()) {
// This is an error, but it will be reported by wfcheck. Ignore it here.
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
} else {
let mut supertrait_def_ids =
traits::supertrait_def_ids(tcx, data.principal().def_id());
if supertrait_def_ids.any(|d| d == trait_def_id) {
let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
struct_span_err!(tcx.sess,
sp,
E0371,
"the object type `{}` automatically implements the trait `{}`",
trait_ref.self_ty(),
tcx.item_path_str(trait_def_id))
.span_label(sp, format!("`{}` automatically implements trait `{}`",
trait_ref.self_ty(),
tcx.item_path_str(trait_def_id)))
.emit();
if let Some(principal_def_id) = data.principal_def_id() {
if !tcx.is_object_safe(principal_def_id) {
// This is an error, but it will be reported by wfcheck. Ignore it here.
// This is tested by `coherence-impl-trait-for-trait-object-safe.rs`.
} else {
let mut supertrait_def_ids =
traits::supertrait_def_ids(tcx, principal_def_id);
if supertrait_def_ids.any(|d| d == trait_def_id) {
let sp = tcx.sess.source_map().def_span(tcx.span_of_impl(impl_def_id).unwrap());
struct_span_err!(tcx.sess,
sp,
E0371,
"the object type `{}` automatically implements the trait `{}`",
trait_ref.self_ty(),
tcx.item_path_str(trait_def_id))
.span_label(sp, format!("`{}` automatically implements trait `{}`",
trait_ref.self_ty(),
tcx.item_path_str(trait_def_id)))
.emit();
}
}
}
// FIXME: also check auto-trait def-ids? (e.g. `impl Sync for Foo+Sync`)?
}
}

View File

@ -1618,6 +1618,7 @@ fn predicates_defined_on<'a, 'tcx>(
.predicates
.extend(inferred_outlives.iter().map(|&p| (p, span)));
}
debug!("predicates_defined_on({:?}) = {:?}", def_id, result);
result
}
@ -1645,6 +1646,7 @@ fn predicates_of<'a, 'tcx>(
.predicates
.push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span));
}
debug!("predicates_of(def_id={:?}) = {:?}", def_id, result);
result
}
@ -1972,10 +1974,12 @@ fn explicit_predicates_of<'a, 'tcx>(
);
}
Lrc::new(ty::GenericPredicates {
let result = Lrc::new(ty::GenericPredicates {
parent: generics.parent,
predicates,
})
});
debug!("explicit_predicates_of(def_id={:?}) = {:?}", def_id, result);
result
}
pub enum SizedByDefault {

View File

@ -194,27 +194,28 @@ fn insert_required_predicates_to_be_wf<'tcx>(
debug!("Dynamic");
debug!("field_ty = {}", &field_ty);
debug!("ty in field = {}", &ty);
let ex_trait_ref = obj.principal();
// Here, we are passing the type `usize` as a
// placeholder value with the function
// `with_self_ty`, since there is no concrete type
// `Self` for a `dyn Trait` at this
// stage. Therefore when checking explicit
// predicates in `check_explicit_predicates` we
// need to ignore checking the explicit_map for
// Self type.
let substs = ex_trait_ref
.with_self_ty(tcx, tcx.types.usize)
.skip_binder()
.substs;
check_explicit_predicates(
tcx,
&ex_trait_ref.skip_binder().def_id,
substs,
required_predicates,
explicit_map,
IgnoreSelfTy(true),
);
if let Some(ex_trait_ref) = obj.principal() {
// Here, we are passing the type `usize` as a
// placeholder value with the function
// `with_self_ty`, since there is no concrete type
// `Self` for a `dyn Trait` at this
// stage. Therefore when checking explicit
// predicates in `check_explicit_predicates` we
// need to ignore checking the explicit_map for
// Self type.
let substs = ex_trait_ref
.with_self_ty(tcx, tcx.types.usize)
.skip_binder()
.substs;
check_explicit_predicates(
tcx,
&ex_trait_ref.skip_binder().def_id,
substs,
required_predicates,
explicit_map,
IgnoreSelfTy(true),
);
}
}
ty::Projection(obj) => {

View File

@ -301,11 +301,12 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
let contra = self.contravariant(variance);
self.add_constraints_from_region(current, r, contra);
let poly_trait_ref = data
.principal()
.with_self_ty(self.tcx(), self.tcx().types.err);
self.add_constraints_from_trait_ref(
current, *poly_trait_ref.skip_binder(), variance);
if let Some(poly_trait_ref) = data.principal() {
let poly_trait_ref =
poly_trait_ref.with_self_ty(self.tcx(), self.tcx().types.err);
self.add_constraints_from_trait_ref(
current, *poly_trait_ref.skip_binder(), variance);
}
for projection in data.projection_bounds() {
self.add_constraints_from_ty(

View File

@ -2642,13 +2642,24 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
}
}
ty::Dynamic(ref obj, ref reg) => {
let principal = obj.principal();
let did = principal.def_id();
// HACK: pick the first `did` as the `did` of the trait object. Someone
// might want to implement "native" support for marker-trait-only
// trait objects.
let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits());
let did = dids.next().unwrap_or_else(|| {
panic!("found trait object `{:?}` with no traits?", self)
});
let substs = match obj.principal() {
Some(principal) => principal.skip_binder().substs,
// marker traits have no substs.
_ => cx.tcx.intern_substs(&[])
};
inline::record_extern_fqn(cx, did, TypeKind::Trait);
let mut typarams = vec![];
reg.clean(cx).map(|b| typarams.push(GenericBound::Outlives(b)));
for did in obj.auto_traits() {
for did in dids {
let empty = cx.tcx.intern_substs(&[]);
let path = external_path(cx, &cx.tcx.item_name(did).as_str(),
Some(did), false, vec![], empty);
@ -2674,7 +2685,7 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
}
let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did),
false, bindings, principal.skip_binder().substs);
false, bindings, substs);
ResolvedPath {
path,
typarams: Some(typarams),

View File

@ -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);
}

View File

@ -0,0 +1,41 @@
// Check that trait-objects without a principal codegen properly.
use std::sync::atomic::{AtomicUsize, Ordering};
use std::mem;
// Array is to make sure the size is not exactly pointer-size, so
// we can be sure we are measuring the right size in the
// `size_of_val` test.
struct SetOnDrop<'a>(&'a AtomicUsize, [u8; 64]);
impl<'a> Drop for SetOnDrop<'a> {
fn drop(&mut self) {
self.0.store(self.0.load(Ordering::Relaxed)+1, Ordering::Relaxed);
}
}
trait TypeEq<V: ?Sized> {}
impl<T: ?Sized> TypeEq<T> for T {}
fn assert_types_eq<U: ?Sized, V: ?Sized>() where U: TypeEq<V> {}
fn main() {
// Check that different ways of writing the same type are equal.
assert_types_eq::<dyn Sync, dyn Sync + Sync>();
assert_types_eq::<dyn Sync + Send, dyn Send + Sync>();
assert_types_eq::<dyn Sync + Send + Sync, dyn Send + Sync>();
// Check that codegen works.
//
// Using `AtomicUsize` here because `Cell<u32>` is not `Sync`, and
// so can't be made into a `Box<dyn Sync>`.
let c = AtomicUsize::new(0);
{
let d: Box<dyn Sync> = Box::new(SetOnDrop(&c, [0; 64]));
assert_eq!(mem::size_of_val(&*d),
mem::size_of::<SetOnDrop>());
assert_eq!(mem::align_of_val(&*d),
mem::align_of::<SetOnDrop>());
assert_eq!(c.load(Ordering::Relaxed), 0);
}
assert_eq!(c.load(Ordering::Relaxed), 1);
}

View 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() {}

View 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`.

View 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>();
}

View File

@ -0,0 +1,39 @@
warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + '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::Send + std::marker::Sync + '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::Send + std::marker::Sync + '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::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>
warning: conflicting implementations of trait `Trait` for type `(dyn std::marker::Send + std::marker::Sync + '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::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>

View File

@ -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
}
}

View File

@ -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::Send + std::marker::Sync + '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>
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::Send + std::marker::Sync + '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>
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`.

View File

@ -0,0 +1,7 @@
// compile-pass
trait Foo {}
impl Foo for dyn Send {}
impl<T: Sync + Sync> Foo for T {}
fn main() {}