mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
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:
commit
2fba17fc97
@ -492,6 +492,7 @@ define_dep_nodes!( <'tcx>
|
||||
[] AdtDefOfItem(DefId),
|
||||
[] ImplTraitRef(DefId),
|
||||
[] ImplPolarity(DefId),
|
||||
[] Issue33140SelfTy(DefId),
|
||||
[] FnSignature(DefId),
|
||||
[] CoerceUnsizedInfo(DefId),
|
||||
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 }
|
||||
|
@ -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 }
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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!()); }
|
||||
|
@ -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)?)),
|
||||
|
@ -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())
|
||||
|
@ -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(),
|
||||
|
@ -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(())
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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(): {:?}",
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
})
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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(..) |
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
}
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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`)?
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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) => {
|
||||
|
@ -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(
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
}
|
41
src/test/run-pass/traits/principal-less-trait-objects.rs
Normal file
41
src/test/run-pass/traits/principal-less-trait-objects.rs
Normal 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);
|
||||
}
|
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::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>
|
||||
|
@ -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::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`.
|
||||
|
7
src/test/ui/issues/issue-57162.rs
Normal file
7
src/test/ui/issues/issue-57162.rs
Normal file
@ -0,0 +1,7 @@
|
||||
// compile-pass
|
||||
|
||||
trait Foo {}
|
||||
impl Foo for dyn Send {}
|
||||
|
||||
impl<T: Sync + Sync> Foo for T {}
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user