Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for trait-objects without a principal #56837

Merged
merged 12 commits into from
Jan 5, 2019
1 change: 1 addition & 0 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
@@ -492,6 +492,7 @@ define_dep_nodes!( <'tcx>
[] AdtDefOfItem(DefId),
[] ImplTraitRef(DefId),
[] ImplPolarity(DefId),
[] Issue33140SelfTy(DefId),
[] FnSignature(DefId),
[] CoerceUnsizedInfo(DefId),

4 changes: 0 additions & 4 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
@@ -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"
}
4 changes: 0 additions & 4 deletions src/librustc/infer/equate.rs
Original file line number Diff line number Diff line change
@@ -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,
6 changes: 1 addition & 5 deletions src/librustc/infer/glb.rs
Original file line number Diff line number Diff line change
@@ -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 }
6 changes: 1 addition & 5 deletions src/librustc/infer/lub.rs
Original file line number Diff line number Diff line change
@@ -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 }
19 changes: 1 addition & 18 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
@@ -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())
}
14 changes: 0 additions & 14 deletions src/librustc/infer/nll_relate/mod.rs
Original file line number Diff line number Diff line change
@@ -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"
}
6 changes: 1 addition & 5 deletions src/librustc/infer/sub.rs
Original file line number Diff line number Diff line change
@@ -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 }

20 changes: 11 additions & 9 deletions src/librustc/traits/coherence.rs
Original file line number Diff line number Diff line change
@@ -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())
@@ -485,7 +481,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,

2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
@@ -449,7 +449,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 {
36 changes: 19 additions & 17 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
@@ -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()
}

3 changes: 1 addition & 2 deletions src/librustc/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Loading