Skip to content

Commit

Permalink
Refactor TyTrait to contain a interned ExistentialPredicate slice.
Browse files Browse the repository at this point in the history
Renames TyTrait to TyDynamic.
  • Loading branch information
Mark-Simulacrum committed Nov 29, 2016
1 parent 64e97d9 commit bb35d50
Show file tree
Hide file tree
Showing 59 changed files with 614 additions and 515 deletions.
2 changes: 1 addition & 1 deletion mk/crates.mk
Expand Up @@ -140,7 +140,7 @@ DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \
rustc_const_eval rustc_errors
rustc_const_eval rustc_errors rustc_data_structures

DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts test \
rustc_lint rustc_const_eval syntax_pos rustc_data_structures
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/infer/freshen.rs
Expand Up @@ -165,7 +165,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> {
ty::TyRef(..) |
ty::TyFnDef(..) |
ty::TyFnPtr(_) |
ty::TyTrait(..) |
ty::TyDynamic(..) |
ty::TyClosure(..) |
ty::TyNever |
ty::TyTuple(..) |
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/coherence.rs
Expand Up @@ -227,7 +227,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
match ty.sty {
ty::TyBox(..) | ty::TyRef(..) => true,
ty::TyAdt(def, _) => def.is_fundamental(),
ty::TyTrait(ref data) => {
ty::TyDynamic(ref data, ..) => {
data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental"))
}
_ => false
Expand Down Expand Up @@ -270,7 +270,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
krate == Some(LOCAL_CRATE)
}

ty::TyTrait(ref tt) => {
ty::TyDynamic(ref tt, ..) => {
tt.principal().map_or(false, |p| p.def_id().is_local())
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/error_reporting.rs
Expand Up @@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5),
ty::TyArray(..) | ty::TySlice(..) => Some(6),
ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7),
ty::TyTrait(..) => Some(8),
ty::TyDynamic(..) => Some(8),
ty::TyClosure(..) => Some(9),
ty::TyTuple(..) => Some(10),
ty::TyProjection(..) => Some(11),
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/traits/fulfill.rs
Expand Up @@ -231,10 +231,10 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
}

pub fn register_bound(&mut self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>,
def_id: DefId,
cause: ObligationCause<'tcx>)
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>,
def_id: DefId,
cause: ObligationCause<'tcx>)
{
let trait_ref = ty::TraitRef {
def_id: def_id,
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/traits/mod.rs
Expand Up @@ -366,10 +366,10 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
/// conservative towards *no impl*, which is the opposite of the
/// `evaluate` methods).
pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
ty: Ty<'tcx>,
def_id: DefId,
span: Span)
-> bool
ty: Ty<'tcx>,
def_id: DefId,
span: Span)
-> bool
{
debug!("type_known_to_meet_bound(ty={:?}, bound={:?})",
ty,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/traits/project.rs
Expand Up @@ -1123,15 +1123,15 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
debug!("confirm_object_candidate(object_ty={:?})",
object_ty);
let data = match object_ty.sty {
ty::TyTrait(ref data) => data,
ty::TyDynamic(ref data, ..) => data,
_ => {
span_bug!(
obligation.cause.span,
"confirm_object_candidate called with non-object: {:?}",
object_ty)
}
};
let env_predicates = data.projection_bounds.iter().map(|p| {
let env_predicates = data.projection_bounds().map(|p| {
p.with_self_ty(selcx.tcx(), object_ty).to_predicate()
}).collect();
let env_predicate = {
Expand Down
144 changes: 64 additions & 80 deletions src/librustc/traits/select.rs
Expand Up @@ -50,7 +50,6 @@ use std::fmt;
use std::marker::PhantomData;
use std::mem;
use std::rc::Rc;
use std::iter;
use syntax::abi::Abi;
use hir;
use util::nodemap::FxHashMap;
Expand Down Expand Up @@ -1094,38 +1093,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// and applicable impls. There is a certain set of precedence rules here.

let def_id = obligation.predicate.def_id();
match obligation.predicate.def_id() {
_ if self.tcx().lang_items.copy_trait() == Some(def_id) => {
debug!("obligation self ty is {:?}",
obligation.predicate.0.self_ty());

// User-defined copy impls are permitted, but only for
// structs and enums.
self.assemble_candidates_from_impls(obligation, &mut candidates)?;

// For other types, we'll use the builtin rules.
let copy_conditions = self.copy_conditions(obligation);
self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?;
}
_ if self.tcx().lang_items.sized_trait() == Some(def_id) => {
// Sized is never implementable by end-users, it is
// always automatically computed.
let sized_conditions = self.sized_conditions(obligation);
self.assemble_builtin_bound_candidates(sized_conditions,
&mut candidates)?;
}

_ if self.tcx().lang_items.unsize_trait() == Some(def_id) => {
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
}

// For non-builtins and Send/Sync
_ => {
self.assemble_closure_candidates(obligation, &mut candidates)?;
self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
self.assemble_candidates_from_impls(obligation, &mut candidates)?;
self.assemble_candidates_from_object_ty(obligation, &mut candidates);
}
if self.tcx().lang_items.copy_trait() == Some(def_id) {
debug!("obligation self ty is {:?}",
obligation.predicate.0.self_ty());

// User-defined copy impls are permitted, but only for
// structs and enums.
self.assemble_candidates_from_impls(obligation, &mut candidates)?;

// For other types, we'll use the builtin rules.
let copy_conditions = self.copy_conditions(obligation);
self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?;
} else if self.tcx().lang_items.sized_trait() == Some(def_id) {
// Sized is never implementable by end-users, it is
// always automatically computed.
let sized_conditions = self.sized_conditions(obligation);
self.assemble_builtin_bound_candidates(sized_conditions,
&mut candidates)?;
} else if self.tcx().lang_items.unsize_trait() == Some(def_id) {
self.assemble_candidates_for_unsizing(obligation, &mut candidates);
} else {
self.assemble_closure_candidates(obligation, &mut candidates)?;
self.assemble_fn_pointer_candidates(obligation, &mut candidates)?;
self.assemble_candidates_from_impls(obligation, &mut candidates)?;
self.assemble_candidates_from_object_ty(obligation, &mut candidates);
}

self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
Expand Down Expand Up @@ -1446,7 +1437,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {

if self.tcx().trait_has_default_impl(def_id) {
match self_ty.sty {
ty::TyTrait(..) => {
ty::TyDynamic(..) => {
// For object types, we don't know what the closed
// over types are. For most traits, this means we
// conservatively say nothing; a candidate may be
Expand Down Expand Up @@ -1516,7 +1507,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// any LBR.
let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty());
let poly_trait_ref = match self_ty.sty {
ty::TyTrait(ref data) => {
ty::TyDynamic(ref data, ..) => {
if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
debug!("assemble_candidates_from_object_ty: matched builtin bound, \
pushing candidate");
Expand All @@ -1525,7 +1516,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}

match data.principal() {
Some(ref p) => p.with_self_ty(this.tcx(), self_ty),
Some(p) => p.with_self_ty(this.tcx(), self_ty),
None => return,
}
}
Expand Down Expand Up @@ -1598,7 +1589,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {

let may_apply = match (&source.sty, &target.sty) {
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
(&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => {
(&ty::TyDynamic(ref data_a, ..), &ty::TyDynamic(ref data_b, ..)) => {
// Upcasts permit two things:
//
// 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
Expand All @@ -1611,7 +1602,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// We always upcast when we can because of reason
// #2 (region bounds).
match (data_a.principal(), data_b.principal()) {
(Some(ref a), Some(ref b)) => a.def_id() == b.def_id() &&
(Some(a), Some(b)) => a.def_id() == b.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)),
Expand All @@ -1620,7 +1611,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
}

// T -> Trait.
(_, &ty::TyTrait(_)) => true,
(_, &ty::TyDynamic(..)) => true,

// Ambiguous handling is below T -> Trait, because inference
// variables can still implement Unsize<Trait> and nested
Expand Down Expand Up @@ -1772,7 +1763,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
Where(ty::Binder(Vec::new()))
}

ty::TyStr | ty::TySlice(_) | ty::TyTrait(..) => Never,
ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) => Never,

ty::TyTuple(tys) => {
Where(ty::Binder(tys.last().into_iter().cloned().collect()))
Expand Down Expand Up @@ -1818,7 +1809,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
Where(ty::Binder(Vec::new()))
}

ty::TyBox(_) | ty::TyTrait(..) | ty::TyStr | ty::TySlice(..) |
ty::TyBox(_) | ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) |
ty::TyClosure(..) |
ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
Never
Expand Down Expand Up @@ -1883,7 +1874,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
Vec::new()
}

ty::TyTrait(..) |
ty::TyDynamic(..) |
ty::TyParam(..) |
ty::TyProjection(..) |
ty::TyAnon(..) |
Expand Down Expand Up @@ -2169,11 +2160,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// OK to skip binder, it is reintroduced below
let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
match self_ty.sty {
ty::TyTrait(ref data) => {
ty::TyDynamic(ref data, ..) => {
// OK to skip the binder, it is reintroduced below
let principal = data.principal().unwrap();
let input_types = principal.input_types();
let assoc_types = data.projection_bounds.iter()
let assoc_types = data.projection_bounds()
.map(|pb| pb.skip_binder().ty);
let all_types: Vec<_> = input_types.chain(assoc_types)
.collect();
Expand Down Expand Up @@ -2305,7 +2296,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
// case that results. -nmatsakis
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
let poly_trait_ref = match self_ty.sty {
ty::TyTrait(ref data) => {
ty::TyDynamic(ref data, ..) => {
data.principal().unwrap().with_self_ty(self.tcx(), self_ty)
}
_ => {
Expand Down Expand Up @@ -2474,14 +2465,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let mut nested = vec![];
match (&source.sty, &target.sty) {
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
(&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => {
(&ty::TyDynamic(ref data_a, r_a), &ty::TyDynamic(ref data_b, r_b)) => {
// See assemble_candidates_for_unsizing for more info.
let new_trait = tcx.mk_trait(ty::TraitObject::new(
data_a.principal(),
data_b.region_bound,
data_b.auto_traits().collect(),
data_a.projection_bounds.clone(),
));
// Binders reintroduced below in call to mk_existential_predicates.
let principal = data_a.skip_binder().principal();
let iter = principal.into_iter().map(ty::ExistentialPredicate::Trait)
.chain(data_a.skip_binder().projection_bounds()
.map(|x| ty::ExistentialPredicate::Projection(x)))
.chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
let new_trait = tcx.mk_dynamic(
ty::Binder(tcx.mk_existential_predicates(iter)), r_b);
let InferOk { obligations, .. } =
self.infcx.sub_types(false, &obligation.cause, new_trait, target)
.map_err(|_| Unimplemented)?;
Expand All @@ -2491,17 +2484,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
let cause = ObligationCause::new(obligation.cause.span,
obligation.cause.body_id,
ObjectCastObligation(target));
let outlives = ty::OutlivesPredicate(data_a.region_bound,
data_b.region_bound);
let outlives = ty::OutlivesPredicate(r_a, r_b);
nested.push(Obligation::with_depth(cause,
obligation.recursion_depth + 1,
ty::Binder(outlives).to_predicate()));
}

// T -> Trait.
(_, &ty::TyTrait(ref data)) => {
(_, &ty::TyDynamic(ref data, r)) => {
let mut object_dids =
data.auto_traits().chain(data.principal().map(|ref p| p.def_id()));
data.auto_traits().chain(data.principal().map(|p| p.def_id()));
if let Some(did) = object_dids.find(|did| {
!tcx.is_object_safe(*did)
}) {
Expand All @@ -2517,35 +2509,27 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
predicate));
};

// Create the obligation for casting from T to Trait.
push(data.principal().unwrap().with_self_ty(tcx, source).to_predicate());

// We can only make objects from sized types.
let trait_refs = data.auto_traits()
.chain(iter::once(
tcx.lang_items.require(lang_items::SizedTraitLangItem)
.unwrap_or_else(|msg| tcx.sess.fatal(&msg[..]))))
.map(|did| ty::TraitRef {
def_id: did,
substs: tcx.mk_substs_trait(source, &[]),
});

// Create additional obligations for all the various builtin
// bounds attached to the object cast. (In other words, if the
// object type is Foo+Send, this would create an obligation
// for the Send check.)
for tr in trait_refs {
push(tr.to_predicate());
// Create obligations:
// - Casting T to Trait
// - For all the various builtin bounds attached to the object cast. (In other
// words, if the object type is Foo+Send, this would create an obligation for the
// Send check.)
// - Projection predicates
for predicate in data.iter() {
push(predicate.with_self_ty(tcx, source));
}

// Create obligations for the projection predicates.
for bound in &data.projection_bounds {
push(bound.with_self_ty(tcx, source).to_predicate());
}
// We can only make objects from sized types.
let tr = ty::TraitRef {
def_id: tcx.lang_items.require(lang_items::SizedTraitLangItem)
.unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])),
substs: tcx.mk_substs_trait(source, &[]),
};
push(tr.to_predicate());

// If the type is `Foo+'a`, ensures that the type
// being cast to `Foo+'a` outlives `'a`:
let outlives = ty::OutlivesPredicate(source, data.region_bound);
let outlives = ty::OutlivesPredicate(source, r);
push(ty::Binder(outlives).to_predicate());
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/contents.rs
Expand Up @@ -195,7 +195,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
tc_ty(tcx, typ, cache).owned_pointer()
}

ty::TyTrait(_) => {
ty::TyDynamic(..) => {
TC::All - TC::InteriorParam
}

Expand Down

0 comments on commit bb35d50

Please sign in to comment.