提交 4b25f085 编写于 作者: E Eduard Burtescu

rustc: move trait objects from TraitRef to ExistentialTraitRef.

上级 5ef6af09
......@@ -1248,9 +1248,7 @@ pub fn fresh_substs_for_generics(&self,
generics: &ty::Generics<'tcx>)
-> &'tcx subst::Substs<'tcx>
{
let type_defs = generics.types.as_full_slice();
let region_defs = generics.regions.as_full_slice();
let substs = Substs::from_param_defs(region_defs, type_defs, |def| {
let substs = Substs::from_generics(generics, |def, _| {
self.region_var_for_def(span, def)
}, |def, substs| {
self.type_var_for_def(span, def, substs)
......@@ -1271,9 +1269,7 @@ pub fn fresh_substs_for_trait(&self,
assert!(generics.types.len(subst::SelfSpace) == 1);
assert!(generics.types.len(subst::FnSpace) == 0);
let type_defs = generics.types.as_full_slice();
let region_defs = generics.regions.as_full_slice();
let substs = Substs::from_param_defs(region_defs, type_defs, |def| {
let substs = Substs::from_generics(generics, |def, _| {
self.region_var_for_def(span, def)
}, |def, substs| {
if def.space == subst::SelfSpace {
......
......@@ -231,7 +231,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool {
ty::TyEnum(def, _) | ty::TyStruct(def, _) =>
def.is_fundamental(),
ty::TyTrait(ref data) =>
tcx.has_attr(data.principal_def_id(), "fundamental"),
tcx.has_attr(data.principal.def_id(), "fundamental"),
_ =>
false
}
......@@ -275,7 +275,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)->
}
ty::TyTrait(ref tt) => {
tt.principal_def_id().is_local()
tt.principal.def_id().is_local()
}
ty::TyError => {
......
......@@ -1133,10 +1133,9 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>(
object_ty)
}
};
let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), object_ty);
let env_predicates = projection_bounds.iter()
.map(|p| p.to_predicate())
.collect();
let env_predicates = data.projection_bounds.iter().map(|p| {
p.with_self_ty(selcx.tcx(), object_ty).to_predicate()
}).collect();
let env_predicate = {
let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
......
......@@ -1528,7 +1528,7 @@ fn assemble_candidates_from_object_ty(&mut self,
ty::TyTrait(ref data) => {
match this.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) {
Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => {
if data.bounds.builtin_bounds.contains(&bound) {
if data.builtin_bounds.contains(&bound) {
debug!("assemble_candidates_from_object_ty: matched builtin bound, \
pushing candidate");
candidates.vec.push(BuiltinObjectCandidate);
......@@ -1538,7 +1538,7 @@ fn assemble_candidates_from_object_ty(&mut self,
_ => {}
}
data.principal_trait_ref_with_self_ty(this.tcx(), self_ty)
data.principal.with_self_ty(this.tcx(), self_ty)
}
ty::TyInfer(ty::TyVar(_)) => {
debug!("assemble_candidates_from_object_ty: ambiguous");
......@@ -1622,7 +1622,7 @@ fn assemble_candidates_for_unsizing(&mut self,
// We always upcast when we can because of reason
// #2 (region bounds).
data_a.principal.def_id() == data_a.principal.def_id() &&
data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds)
data_a.builtin_bounds.is_superset(&data_b.builtin_bounds)
}
// T -> Trait.
......@@ -2179,10 +2179,9 @@ fn confirm_default_impl_object_candidate(&mut self,
match self_ty.sty {
ty::TyTrait(ref data) => {
// OK to skip the binder, it is reintroduced below
let input_types = data.principal.skip_binder().substs.types.get_slice(TypeSpace);
let assoc_types = data.bounds.projection_bounds
.iter()
.map(|pb| pb.skip_binder().ty);
let input_types = data.principal.skip_binder().input_types();
let assoc_types = data.projection_bounds.iter()
.map(|pb| pb.skip_binder().ty);
let all_types: Vec<_> = input_types.iter().cloned()
.chain(assoc_types)
.collect();
......@@ -2315,7 +2314,7 @@ fn confirm_object_candidate(&mut self,
let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
let poly_trait_ref = match self_ty.sty {
ty::TyTrait(ref data) => {
data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
data.principal.with_self_ty(self.tcx(), self_ty)
}
_ => {
span_bug!(obligation.cause.span,
......@@ -2487,13 +2486,12 @@ fn confirm_builtin_unsize_candidate(&mut self,
// Trait+Kx+'a -> Trait+Ky+'b (upcasts).
(&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => {
// See assemble_candidates_for_unsizing for more info.
let bounds = ty::ExistentialBounds {
region_bound: data_b.bounds.region_bound,
builtin_bounds: data_b.bounds.builtin_bounds,
projection_bounds: data_a.bounds.projection_bounds.clone(),
};
let new_trait = tcx.mk_trait(data_a.principal.clone(), bounds);
let new_trait = tcx.mk_trait(ty::TraitObject {
principal: data_a.principal,
region_bound: data_b.region_bound,
builtin_bounds: data_b.builtin_bounds,
projection_bounds: data_a.projection_bounds.clone(),
});
let origin = TypeOrigin::Misc(obligation.cause.span);
let InferOk { obligations, .. } =
self.infcx.sub_types(false, origin, new_trait, target)
......@@ -2504,8 +2502,8 @@ fn confirm_builtin_unsize_candidate(&mut self,
let cause = ObligationCause::new(obligation.cause.span,
obligation.cause.body_id,
ObjectCastObligation(target));
let outlives = ty::OutlivesPredicate(data_a.bounds.region_bound,
data_b.bounds.region_bound);
let outlives = ty::OutlivesPredicate(data_a.region_bound,
data_b.region_bound);
nested.push(Obligation::with_depth(cause,
obligation.recursion_depth + 1,
ty::Binder(outlives).to_predicate()));
......@@ -2513,12 +2511,12 @@ fn confirm_builtin_unsize_candidate(&mut self,
// T -> Trait.
(_, &ty::TyTrait(ref data)) => {
let mut object_dids = Some(data.principal_def_id()).into_iter();
let mut object_dids = Some(data.principal.def_id()).into_iter();
// FIXME(#33243)
// data.bounds.builtin_bounds.iter().flat_map(|bound| {
// data.builtin_bounds.iter().flat_map(|bound| {
// tcx.lang_items.from_builtin_kind(bound).ok()
// })
// .chain(Some(data.principal_def_id()));
// .chain(Some(data.principal.def_id()));
if let Some(did) = object_dids.find(|did| {
!tcx.is_object_safe(*did)
}) {
......@@ -2535,10 +2533,10 @@ fn confirm_builtin_unsize_candidate(&mut self,
};
// Create the obligation for casting from T to Trait.
push(data.principal_trait_ref_with_self_ty(tcx, source).to_predicate());
push(data.principal.with_self_ty(tcx, source).to_predicate());
// We can only make objects from sized types.
let mut builtin_bounds = data.bounds.builtin_bounds;
let mut builtin_bounds = data.builtin_bounds;
builtin_bounds.insert(ty::BoundSized);
// Create additional obligations for all the various builtin
......@@ -2554,14 +2552,13 @@ fn confirm_builtin_unsize_candidate(&mut self,
}
// Create obligations for the projection predicates.
for bound in data.projection_bounds_with_self_ty(tcx, source) {
push(bound.to_predicate());
for bound in &data.projection_bounds {
push(bound.with_self_ty(tcx, source).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.bounds.region_bound);
let outlives = ty::OutlivesPredicate(source, data.region_bound);
push(ty::Binder(outlives).to_predicate());
}
......
......@@ -27,9 +27,9 @@
use traits;
use ty::{self, TraitRef, Ty, TypeAndMut};
use ty::{TyS, TypeVariants};
use ty::{AdtDef, ClosureSubsts, ExistentialBounds, Region};
use ty::{AdtDef, ClosureSubsts, Region};
use hir::FreevarMap;
use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitTy};
use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject};
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
use ty::TypeVariants::*;
use ty::layout::{Layout, TargetDataLayout};
......@@ -1150,12 +1150,6 @@ fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
region: mk_region(Region, keep_local) -> Region
);
fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
bounds.is_empty() ||
bounds[1..].iter().enumerate().all(
|(index, bound)| bounds[index].sort_key() <= bound.sort_key())
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// Create an unsafe fn ty based on a safe fn ty.
pub fn safe_to_unsafe_fn_ty(self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
......@@ -1288,18 +1282,9 @@ pub fn mk_fn_ptr(self, fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
self.mk_ty(TyFnPtr(fty))
}
pub fn mk_trait(self,
principal: ty::PolyTraitRef<'tcx>,
bounds: ExistentialBounds<'tcx>)
-> Ty<'tcx>
{
assert!(bound_list_is_sorted(&bounds.projection_bounds));
let inner = box TraitTy {
principal: principal,
bounds: bounds
};
self.mk_ty(TyTrait(inner))
pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> {
obj.projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));
self.mk_ty(TyTrait(box obj))
}
pub fn mk_projection(self,
......
......@@ -243,7 +243,7 @@ fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
ty::TyFnDef(..) => format!("fn item"),
ty::TyFnPtr(_) => "fn pointer".to_string(),
ty::TyTrait(ref inner) => {
format!("trait {}", tcx.item_path_str(inner.principal_def_id()))
format!("trait {}", tcx.item_path_str(inner.principal.def_id()))
}
ty::TyStruct(def, _) => {
format!("struct `{}`", tcx.item_path_str(def.did))
......
......@@ -61,7 +61,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
ty::TyArray(..) | ty::TySlice(_) => Some(VecSimplifiedType),
ty::TyRawPtr(_) => Some(PtrSimplifiedType),
ty::TyTrait(ref trait_info) => {
Some(TraitSimplifiedType(trait_info.principal_def_id()))
Some(TraitSimplifiedType(trait_info.principal.def_id()))
}
ty::TyStruct(def, _) => {
Some(StructSimplifiedType(def.did))
......
......@@ -116,17 +116,16 @@ fn add_sty(&mut self, st: &ty::TypeVariants) {
self.add_substs(substs);
}
&ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
&ty::TyTrait(ref obj) => {
let mut computation = FlagComputation::new();
computation.add_substs(principal.0.substs);
for projection_bound in &bounds.projection_bounds {
computation.add_substs(obj.principal.skip_binder().substs);
for projection_bound in &obj.projection_bounds {
let mut proj_computation = FlagComputation::new();
proj_computation.add_projection_predicate(&projection_bound.0);
proj_computation.add_existential_projection(&projection_bound.0);
self.add_bound_computation(&proj_computation);
}
self.add_bound_computation(&computation);
self.add_bounds(bounds);
self.add_region(obj.region_bound);
}
&ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => {
......@@ -199,9 +198,9 @@ fn add_region(&mut self, r: ty::Region) {
}
}
fn add_projection_predicate(&mut self, projection_predicate: &ty::ProjectionPredicate) {
self.add_projection_ty(&projection_predicate.projection_ty);
self.add_ty(projection_predicate.ty);
fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) {
self.add_substs(projection.trait_ref.substs);
self.add_ty(projection.ty);
}
fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) {
......@@ -214,8 +213,4 @@ fn add_substs(&mut self, substs: &subst::Substs) {
self.add_region(r);
}
}
fn add_bounds(&mut self, bounds: &ty::ExistentialBounds) {
self.add_region(bounds.region_bound);
}
}
......@@ -140,10 +140,6 @@ fn fold_mt(&mut self, t: &ty::TypeAndMut<'tcx>) -> ty::TypeAndMut<'tcx> {
t.super_fold_with(self)
}
fn fold_trait_ref(&mut self, t: &ty::TraitRef<'tcx>) -> ty::TraitRef<'tcx> {
t.super_fold_with(self)
}
fn fold_impl_header(&mut self, imp: &ty::ImplHeader<'tcx>) -> ty::ImplHeader<'tcx> {
imp.super_fold_with(self)
}
......@@ -177,11 +173,6 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
r.super_fold_with(self)
}
fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
-> ty::ExistentialBounds<'tcx> {
s.super_fold_with(self)
}
fn fold_autoref(&mut self, ar: &adjustment::AutoRef<'tcx>)
-> adjustment::AutoRef<'tcx> {
ar.super_fold_with(self)
......
......@@ -322,7 +322,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> {
ty::TyStruct(adt_def, _) |
ty::TyEnum(adt_def, _) => Some(adt_def.did),
ty::TyTrait(ref data) => Some(data.principal_def_id()),
ty::TyTrait(ref data) => Some(data.principal.def_id()),
ty::TyArray(subty, _) |
ty::TySlice(subty) |
......
......@@ -54,11 +54,13 @@
use hir::intravisit::Visitor;
pub use self::sty::{Binder, DebruijnIndex};
pub use self::sty::{BuiltinBound, BuiltinBounds, ExistentialBounds};
pub use self::sty::{BuiltinBound, BuiltinBounds};
pub use self::sty::{BareFnTy, FnSig, PolyFnSig};
pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitTy};
pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitObject};
pub use self::sty::{ClosureSubsts, TypeAndMut};
pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
pub use self::sty::{ExistentialProjection, PolyExistentialProjection};
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
pub use self::sty::Issue32330;
pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid};
......
......@@ -326,24 +326,33 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
}
}
impl<'tcx> Relate<'tcx> for ty::ProjectionPredicate<'tcx> {
impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &ty::ProjectionPredicate<'tcx>,
b: &ty::ProjectionPredicate<'tcx>)
-> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>>
a: &ty::ExistentialProjection<'tcx>,
b: &ty::ExistentialProjection<'tcx>)
-> RelateResult<'tcx, ty::ExistentialProjection<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
let projection_ty = relation.relate(&a.projection_ty, &b.projection_ty)?;
let ty = relation.relate(&a.ty, &b.ty)?;
Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty })
if a.item_name != b.item_name {
Err(TypeError::ProjectionNameMismatched(
expected_found(relation, &a.item_name, &b.item_name)))
} else {
let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?;
let ty = relation.relate(&a.ty, &b.ty)?;
Ok(ty::ExistentialProjection {
trait_ref: trait_ref,
item_name: a.item_name,
ty: ty
})
}
}
}
impl<'tcx> Relate<'tcx> for Vec<ty::PolyProjectionPredicate<'tcx>> {
impl<'tcx> Relate<'tcx> for Vec<ty::PolyExistentialProjection<'tcx>> {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &Vec<ty::PolyProjectionPredicate<'tcx>>,
b: &Vec<ty::PolyProjectionPredicate<'tcx>>)
-> RelateResult<'tcx, Vec<ty::PolyProjectionPredicate<'tcx>>>
a: &Vec<ty::PolyExistentialProjection<'tcx>>,
b: &Vec<ty::PolyExistentialProjection<'tcx>>)
-> RelateResult<'tcx, Vec<ty::PolyExistentialProjection<'tcx>>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
// To be compatible, `a` and `b` must be for precisely the
......@@ -361,27 +370,6 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
}
}
impl<'tcx> Relate<'tcx> for ty::ExistentialBounds<'tcx> {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &ty::ExistentialBounds<'tcx>,
b: &ty::ExistentialBounds<'tcx>)
-> RelateResult<'tcx, ty::ExistentialBounds<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
let r =
relation.with_cause(
Cause::ExistentialRegionBound,
|relation| relation.relate_with_variance(ty::Contravariant,
&a.region_bound,
&b.region_bound))?;
let nb = relation.relate(&a.builtin_bounds, &b.builtin_bounds)?;
let pb = relation.relate(&a.projection_bounds, &b.projection_bounds)?;
Ok(ty::ExistentialBounds { region_bound: r,
builtin_bounds: nb,
projection_bounds: pb })
}
}
impl<'tcx> Relate<'tcx> for ty::BuiltinBounds {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &ty::BuiltinBounds,
......@@ -416,6 +404,23 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
}
}
impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &ty::ExistentialTraitRef<'tcx>,
b: &ty::ExistentialTraitRef<'tcx>)
-> RelateResult<'tcx, ty::ExistentialTraitRef<'tcx>>
where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
{
// Different traits cannot be related
if a.def_id != b.def_id {
Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id)))
} else {
let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?;
Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs })
}
}
}
impl<'tcx> Relate<'tcx> for Ty<'tcx> {
fn relate<'a, 'gcx, R>(relation: &mut R,
a: &Ty<'tcx>,
......@@ -478,11 +483,23 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
Ok(tcx.mk_enum(a_def, substs))
}
(&ty::TyTrait(ref a_), &ty::TyTrait(ref b_)) =>
(&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) =>
{
let principal = relation.relate(&a_.principal, &b_.principal)?;
let bounds = relation.relate(&a_.bounds, &b_.bounds)?;
Ok(tcx.mk_trait(principal, bounds))
let principal = relation.relate(&a_obj.principal, &b_obj.principal)?;
let r =
relation.with_cause(
Cause::ExistentialRegionBound,
|relation| relation.relate_with_variance(ty::Contravariant,
&a_obj.region_bound,
&b_obj.region_bound))?;
let nb = relation.relate(&a_obj.builtin_bounds, &b_obj.builtin_bounds)?;
let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?;
Ok(tcx.mk_trait(ty::TraitObject {
principal: principal,
region_bound: r,
builtin_bounds: nb,
projection_bounds: pb
}))
}
(&ty::TyStruct(a_def, a_substs), &ty::TyStruct(b_def, b_substs))
......
......@@ -10,7 +10,7 @@
use infer::type_variable;
use ty::subst::{self, VecPerParamSpace};
use ty::{self, Lift, TraitRef, Ty, TyCtxt};
use ty::{self, Lift, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use std::rc::Rc;
......@@ -80,10 +80,20 @@ fn lift_to_tcx(&self, _: TyCtxt) -> Option<ty::Region> {
}
}
impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> {
type Lifted = TraitRef<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<TraitRef<'tcx>> {
tcx.lift(&self.substs).map(|substs| TraitRef {
impl<'a, 'tcx> Lift<'tcx> for ty::TraitRef<'a> {
type Lifted = ty::TraitRef<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
tcx.lift(&self.substs).map(|substs| ty::TraitRef {
def_id: self.def_id,
substs: substs
})
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialTraitRef<'a> {
type Lifted = ty::ExistentialTraitRef<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
tcx.lift(&self.substs).map(|substs| ty::ExistentialTraitRef {
def_id: self.def_id,
substs: substs
})
......@@ -141,6 +151,19 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialProjection<'a> {
type Lifted = ty::ExistentialProjection<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
tcx.lift(&(self.trait_ref, self.ty)).map(|(trait_ref, ty)| {
ty::ExistentialProjection {
trait_ref: trait_ref,
item_name: self.item_name,
ty: ty
}
})
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> {
type Lifted = ty::Predicate<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
......@@ -437,16 +460,20 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::TraitTy<'tcx> {
impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::TraitTy {
ty::TraitObject {
principal: self.principal.fold_with(folder),
bounds: self.bounds.fold_with(folder),
region_bound: self.region_bound.fold_with(folder),
builtin_bounds: self.builtin_bounds,
projection_bounds: self.projection_bounds.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.principal.visit_with(visitor) || self.bounds.visit_with(visitor)
self.principal.visit_with(visitor) ||
self.region_bound.visit_with(visitor) ||
self.projection_bounds.visit_with(visitor)
}
}
......@@ -599,8 +626,17 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
}
}
fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
folder.fold_trait_ref(self)
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.substs.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialTraitRef<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ExistentialTraitRef {
def_id: self.def_id,
substs: self.substs.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
......@@ -741,24 +777,6 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ExistentialBounds {
region_bound: self.region_bound.fold_with(folder),
builtin_bounds: self.builtin_bounds,
projection_bounds: self.projection_bounds.fold_with(folder),
}
}
fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
folder.fold_existential_bounds(self)
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.region_bound.visit_with(visitor) || self.projection_bounds.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::TypeParameterDef {
......@@ -893,6 +911,20 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialProjection<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ExistentialProjection {
trait_ref: self.trait_ref.fold_with(folder),
item_name: self.item_name,
ty: self.ty.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.trait_ref.visit_with(visitor) || self.ty.visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ProjectionTy {
......
......@@ -152,7 +152,7 @@ pub enum TypeVariants<'tcx> {
TyFnPtr(&'tcx BareFnTy<'tcx>),
/// A trait, defined with `trait`.
TyTrait(Box<TraitTy<'tcx>>),
TyTrait(Box<TraitObject<'tcx>>),
/// The anonymous type of a closure. Used to represent the type of
/// `|a| a`.
......@@ -291,57 +291,11 @@ fn decode<D: Decoder>(d: &mut D) -> Result<ClosureSubsts<'tcx>, D::Error> {
}
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct TraitTy<'tcx> {
pub principal: ty::PolyTraitRef<'tcx>,
pub bounds: ExistentialBounds<'tcx>,
}
impl<'a, 'gcx, 'tcx> TraitTy<'tcx> {
pub fn principal_def_id(&self) -> DefId {
self.principal.0.def_id
}
/// Object types don't have a self-type specified. Therefore, when
/// we convert the principal trait-ref into a normal trait-ref,
/// you must give *some* self-type. A common choice is `mk_err()`
/// or some skolemized type.
pub fn principal_trait_ref_with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
self_ty: Ty<'tcx>)
-> ty::PolyTraitRef<'tcx>
{
// otherwise the escaping regions would be captured by the binder
assert!(!self_ty.has_escaping_regions());
ty::Binder(TraitRef {
def_id: self.principal.0.def_id,
substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)),
})
}
pub fn projection_bounds_with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
self_ty: Ty<'tcx>)
-> Vec<ty::PolyProjectionPredicate<'tcx>>
{
// otherwise the escaping regions would be captured by the binders
assert!(!self_ty.has_escaping_regions());
self.bounds.projection_bounds.iter()
.map(|in_poly_projection_predicate| {
let in_projection_ty = &in_poly_projection_predicate.0.projection_ty;
let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty));
let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id,
substs);
let projection_ty = ty::ProjectionTy {
trait_ref: trait_ref,
item_name: in_projection_ty.item_name
};
ty::Binder(ty::ProjectionPredicate {
projection_ty: projection_ty,
ty: in_poly_projection_predicate.0.ty
})
})
.collect()
}
pub struct TraitObject<'tcx> {
pub principal: PolyExistentialTraitRef<'tcx>,
pub region_bound: ty::Region,
pub builtin_bounds: BuiltinBounds,
pub projection_bounds: Vec<PolyExistentialProjection<'tcx>>,
}
/// A complete reference to a trait. These take numerous guises in syntax,
......@@ -392,6 +346,70 @@ pub fn to_poly_trait_predicate(&self) -> ty::PolyTraitPredicate<'tcx> {
}
}
/// An existential reference to a trait, where `Self` is erased.
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
///
/// exists T. T: Trait<'a, 'b, X, Y>
///
/// The substitutions don't include the erased `Self`, only trait
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct ExistentialTraitRef<'tcx> {
pub def_id: DefId,
pub substs: &'tcx Substs<'tcx>,
}
impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> {
pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>,
trait_ref: ty::TraitRef<'tcx>)
-> ty::ExistentialTraitRef<'tcx> {
let mut substs = trait_ref.substs.clone();
substs.types.pop(subst::SelfSpace);
ty::ExistentialTraitRef {
def_id: trait_ref.def_id,
substs: tcx.mk_substs(substs)
}
}
pub fn input_types(&self) -> &[Ty<'tcx>] {
// Select only the "input types" from a trait-reference. For
// now this is all the types that appear in the
// trait-reference, but it should eventually exclude
// associated types.
self.substs.types.as_full_slice()
}
}
pub type PolyExistentialTraitRef<'tcx> = Binder<ExistentialTraitRef<'tcx>>;
impl<'a, 'gcx, 'tcx> PolyExistentialTraitRef<'tcx> {
pub fn def_id(&self) -> DefId {
self.0.def_id
}
pub fn input_types(&self) -> &[Ty<'tcx>] {
// FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<>
self.0.input_types()
}
/// Object types don't have a self-type specified. Therefore, when
/// we convert the principal trait-ref into a normal trait-ref,
/// you must give *some* self-type. A common choice is `mk_err()`
/// or some skolemized type.
pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
self_ty: Ty<'tcx>)
-> ty::PolyTraitRef<'tcx>
{
// otherwise the escaping regions would be captured by the binder
assert!(!self_ty.has_escaping_regions());
self.map_bound(|trait_ref| TraitRef {
def_id: trait_ref.def_id,
substs: tcx.mk_substs(trait_ref.substs.with_self_ty(self_ty)),
})
}
}
/// Binder is a binder for higher-ranked lifetimes. It is part of the
/// compiler's representation for things like `for<'a> Fn(&'a isize)`
/// (which would be represented by the type `PolyTraitRef ==
......@@ -730,27 +748,40 @@ pub enum InferTy {
FreshFloatTy(u32)
}
/// Bounds suitable for an existentially quantified type parameter
/// such as those that appear in object types or closure types.
#[derive(PartialEq, Eq, Hash, Clone)]
pub struct ExistentialBounds<'tcx> {
pub region_bound: ty::Region,
pub builtin_bounds: BuiltinBounds,
pub projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct ExistentialProjection<'tcx> {
pub trait_ref: ExistentialTraitRef<'tcx>,
pub item_name: Name,
pub ty: Ty<'tcx>
}
impl<'tcx> ExistentialBounds<'tcx> {
pub fn new(region_bound: ty::Region,
builtin_bounds: BuiltinBounds,
projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>)
-> Self {
let mut projection_bounds = projection_bounds;
projection_bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()));
ExistentialBounds {
region_bound: region_bound,
builtin_bounds: builtin_bounds,
projection_bounds: projection_bounds
}
pub type PolyExistentialProjection<'tcx> = Binder<ExistentialProjection<'tcx>>;
impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> {
pub fn item_name(&self) -> Name {
self.0.item_name // safe to skip the binder to access a name
}
pub fn sort_key(&self) -> (DefId, Name) {
(self.0.trait_ref.def_id, self.0.item_name)
}
pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
self_ty: Ty<'tcx>)
-> ty::PolyProjectionPredicate<'tcx>
{
// otherwise the escaping regions would be captured by the binders
assert!(!self_ty.has_escaping_regions());
let trait_ref = self.map_bound(|proj| proj.trait_ref);
self.map_bound(|proj| ty::ProjectionPredicate {
projection_ty: ty::ProjectionTy {
trait_ref: trait_ref.with_self_ty(tcx, self_ty).0,
item_name: proj.item_name
},
ty: proj.ty
})
}
}
......@@ -1185,7 +1216,7 @@ pub fn is_fn(&self) -> bool {
pub fn ty_to_def_id(&self) -> Option<DefId> {
match self.sty {
TyTrait(ref tt) => Some(tt.principal_def_id()),
TyTrait(ref tt) => Some(tt.principal.def_id()),
TyStruct(def, _) |
TyEnum(def, _) => Some(def.did),
TyClosure(id, _) => Some(id),
......@@ -1209,9 +1240,8 @@ pub fn regions(&self) -> Vec<ty::Region> {
vec![*region]
}
TyTrait(ref obj) => {
let mut v = vec![obj.bounds.region_bound];
v.extend_from_slice(obj.principal.skip_binder()
.substs.regions.as_full_slice());
let mut v = vec![obj.region_bound];
v.extend_from_slice(obj.principal.skip_binder().substs.regions.as_full_slice());
v
}
TyEnum(_, substs) |
......
......@@ -451,21 +451,21 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
// to sort them again by the name, in string form.
// Hash the whole principal trait ref.
self.def_id(data.principal_def_id());
self.def_id(data.principal.def_id());
data.principal.visit_with(self);
// Hash region and builtin bounds.
data.bounds.region_bound.visit_with(self);
self.hash(data.bounds.builtin_bounds);
data.region_bound.visit_with(self);
self.hash(data.builtin_bounds);
// Only projection bounds are left, sort and hash them.
let mut projection_bounds: Vec<_> = data.bounds.projection_bounds
let mut projection_bounds: Vec<_> = data.projection_bounds
.iter()
.map(|b| (b.item_name().as_str(), b))
.collect();
projection_bounds.sort_by_key(|&(ref name, _)| name.clone());
for (name, bound) in projection_bounds {
self.def_id(bound.0.projection_ty.trait_ref.def_id);
self.def_id(bound.0.trait_ref.def_id);
self.hash(name);
bound.visit_with(self);
}
......
......@@ -81,9 +81,9 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
ty::TyProjection(ref data) => {
push_reversed(stack, data.trait_ref.substs.types.as_full_slice());
}
ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
push_reversed(stack, principal.substs().types.as_full_slice());
push_reversed(stack, &bounds.projection_bounds.iter().map(|pred| {
ty::TyTrait(ref obj) => {
push_reversed(stack, obj.principal.input_types());
push_reversed(stack, &obj.projection_bounds.iter().map(|pred| {
pred.0.ty
}).collect::<Vec<_>>());
}
......
......@@ -406,13 +406,13 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
// FIXME(#33243): remove RFC1592
self.out.push(traits::Obligation::new(
cause.clone(),
ty::Predicate::ObjectSafe(data.principal_def_id())
ty::Predicate::ObjectSafe(data.principal.def_id())
));
let component_traits =
data.bounds.builtin_bounds.iter().flat_map(|bound| {
data.builtin_bounds.iter().flat_map(|bound| {
tcx.lang_items.from_builtin_kind(bound).ok()
});
// .chain(Some(data.principal_def_id()));
// .chain(Some(data.principal.def_id()));
self.out.extend(
component_traits.map(|did| { traits::Obligation::new(
cause.clone(),
......@@ -476,7 +476,7 @@ fn nominal_obligations(&mut self,
.collect()
}
fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitTy<'tcx>) {
fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitObject<'tcx>) {
// Imagine a type like this:
//
// trait Foo { }
......@@ -512,10 +512,10 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitTy<'tcx>) {
if !data.has_escaping_regions() {
let implicit_bounds =
object_region_bounds(self.infcx.tcx,
&data.principal,
data.bounds.builtin_bounds);
data.principal,
data.builtin_bounds);
let explicit_bound = data.bounds.region_bound;
let explicit_bound = data.region_bound;
for implicit_bound in implicit_bounds {
let cause = self.cause(traits::ReferenceOutlivesReferent(ty));
......@@ -534,7 +534,7 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitTy<'tcx>) {
/// `ty::required_region_bounds`, see that for more information.
pub fn object_region_bounds<'a, 'gcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
principal: &ty::PolyTraitRef<'tcx>,
principal: ty::PolyExistentialTraitRef<'tcx>,
others: ty::BuiltinBounds)
-> Vec<ty::Region>
{
......@@ -543,13 +543,8 @@ pub fn object_region_bounds<'a, 'gcx, 'tcx>(
// a skolemized type.
let open_ty = tcx.mk_infer(ty::FreshTy(0));
// Note that we preserve the overall binding levels here.
assert!(!open_ty.has_escaping_regions());
let substs = tcx.mk_substs(principal.0.substs.with_self_ty(open_ty));
let trait_refs = vec!(ty::Binder(ty::TraitRef::new(principal.0.def_id, substs)));
let mut predicates = others.to_predicates(tcx, open_ty);
predicates.extend(trait_refs.iter().map(|t| t.to_predicate()));
predicates.push(principal.with_self_ty(tcx, open_ty).to_predicate());
tcx.required_region_bounds(open_ty, predicates)
}
......@@ -288,7 +288,8 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter,
/// projection bounds, so we just stuff them altogether. But in
/// reality we should eventually sort things out better.
#[derive(Clone, Debug)]
struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, Vec<ty::ProjectionPredicate<'tcx>>);
struct TraitAndProjections<'tcx>(ty::ExistentialTraitRef<'tcx>,
Vec<ty::ProjectionPredicate<'tcx>>);
impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
......@@ -311,24 +312,24 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl<'tcx> fmt::Display for ty::TraitTy<'tcx> {
impl<'tcx> fmt::Display for ty::TraitObject<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let bounds = &self.bounds;
// Generate the main trait ref, including associated types.
ty::tls::with(|tcx| {
let principal = tcx.lift(&self.principal.0)
.expect("could not lift TraitRef for printing");
let projections = tcx.lift(&bounds.projection_bounds[..])
.expect("could not lift projections for printing");
let projections = projections.into_iter().map(|p| p.0).collect();
let projections = self.projection_bounds.iter().map(|p| {
let projection = tcx.lift(p)
.expect("could not lift projection for printing");
projection.with_self_ty(tcx, tcx.types.err).0
}).collect();
let tap = ty::Binder(TraitAndProjections(principal, projections));
in_binder(f, tcx, &ty::Binder(""), Some(tap))
})?;
// Builtin bounds.
for bound in &bounds.builtin_bounds {
for bound in &self.builtin_bounds {
write!(f, " + {:?}", bound)?;
}
......@@ -337,7 +338,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// use thread-local data of some kind? There are also
// advantages to just showing the region, since it makes
// people aware that it's there.
let bound = bounds.region_bound.to_string();
let bound = self.region_bound.to_string();
if !bound.is_empty() {
write!(f, " + {}", bound)?;
}
......@@ -397,10 +398,13 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// when printing out the debug representation, we don't need
// to enumerate the `for<...>` etc because the debruijn index
// tells you everything you need to know.
match self.substs.self_ty() {
None => write!(f, "{}", *self),
Some(self_ty) => write!(f, "<{:?} as {}>", self_ty, *self)
}
write!(f, "<{:?} as {}>", self.self_ty(), *self)
}
}
impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", *self)
}
}
......@@ -448,11 +452,38 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl<'tcx> fmt::Debug for ty::TraitTy<'tcx> {
impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "TraitTy({:?},{:?})",
self.principal,
self.bounds)
let mut empty = true;
let mut maybe_continue = |f: &mut fmt::Formatter| {
if empty {
empty = false;
Ok(())
} else {
write!(f, " + ")
}
};
maybe_continue(f)?;
write!(f, "{:?}", self.principal)?;
let region_str = format!("{:?}", self.region_bound);
if !region_str.is_empty() {
maybe_continue(f)?;
write!(f, "{}", region_str)?;
}
for bound in &self.builtin_bounds {
maybe_continue(f)?;
write!(f, "{:?}", bound)?;
}
for projection_bound in &self.projection_bounds {
maybe_continue(f)?;
write!(f, "{:?}", projection_bound)?;
}
Ok(())
}
}
......@@ -668,38 +699,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl<'tcx> fmt::Debug for ty::ExistentialBounds<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut empty = true;
let mut maybe_continue = |f: &mut fmt::Formatter| {
if empty {
empty = false;
Ok(())
} else {
write!(f, " + ")
}
};
let region_str = format!("{:?}", self.region_bound);
if !region_str.is_empty() {
maybe_continue(f)?;
write!(f, "{}", region_str)?;
}
for bound in &self.builtin_bounds {
maybe_continue(f)?;
write!(f, "{:?}", bound)?;
}
for projection_bound in &self.projection_bounds {
maybe_continue(f)?;
write!(f, "{:?}", projection_bound)?;
}
Ok(())
}
}
impl fmt::Display for ty::BuiltinBounds {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut bounds = self.iter();
......@@ -819,6 +818,13 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl<'tcx> fmt::Display for ty::ExistentialTraitRef<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
parameterized(f, self.substs, self.def_id, Ns::Type, &[],
|tcx| Some(tcx.lookup_trait_def(self.def_id).generics.clone()))
}
}
impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
......
......@@ -524,16 +524,8 @@ pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) {
trait rbml_writer_helpers<'tcx> {
fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region);
fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>);
fn emit_tys<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, tys: &[Ty<'tcx>]);
fn emit_predicate<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
predicate: &ty::Predicate<'tcx>);
fn emit_trait_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
ty: &ty::TraitRef<'tcx>);
fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
substs: &subst::Substs<'tcx>);
fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
bounds: &ty::ExistentialBounds<'tcx>);
fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds);
fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture);
fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
adj: &adjustment::AutoAdjustment<'tcx>);
......@@ -556,39 +548,6 @@ fn emit_ty<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, ty: Ty<'tcx>) {
ty)));
}
fn emit_tys<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>, tys: &[Ty<'tcx>]) {
self.emit_from_vec(tys, |this, ty| Ok(this.emit_ty(ecx, *ty)));
}
fn emit_trait_ref<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
trait_ref: &ty::TraitRef<'tcx>) {
self.emit_opaque(|this| Ok(tyencode::enc_trait_ref(&mut this.cursor,
&ecx.ty_str_ctxt(),
*trait_ref)));
}
fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
predicate: &ty::Predicate<'tcx>) {
self.emit_opaque(|this| {
Ok(tyencode::enc_predicate(&mut this.cursor,
&ecx.ty_str_ctxt(),
predicate))
});
}
fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
bounds: &ty::ExistentialBounds<'tcx>) {
self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(&mut this.cursor,
&ecx.ty_str_ctxt(),
bounds)));
}
fn emit_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds) {
self.emit_opaque(|this| Ok(tyencode::enc_builtin_bounds(&mut this.cursor,
&ecx.ty_str_ctxt(),
bounds)));
}
fn emit_upvar_capture(&mut self, ecx: &e::EncodeContext, capture: &ty::UpvarCapture) {
use rustc_serialize::Encoder;
......@@ -879,8 +838,6 @@ fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::PolyTraitRef<'tcx>;
fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::Predicate<'tcx>;
fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::ExistentialBounds<'tcx>;
fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> subst::Substs<'tcx>;
fn read_upvar_capture(&mut self, dcx: &DecodeContext)
......@@ -988,12 +945,6 @@ fn read_predicate<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
self.read_ty_encoded(dcx, |decoder| decoder.parse_predicate())
}
fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-> ty::ExistentialBounds<'tcx>
{
self.read_ty_encoded(dcx, |decoder| decoder.parse_existential_bounds())
}
fn read_substs<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-> subst::Substs<'tcx> {
self.read_opaque(|_, doc| {
......
......@@ -307,6 +307,12 @@ pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
ty::TraitRef {def_id: def, substs: substs}
}
pub fn parse_existential_trait_ref(&mut self) -> ty::ExistentialTraitRef<'tcx> {
let def = self.parse_def();
let substs = self.tcx.mk_substs(self.parse_substs());
ty::ExistentialTraitRef {def_id: def, substs: substs}
}
pub fn parse_ty(&mut self) -> Ty<'tcx> {
let tcx = self.tcx;
match self.next() {
......@@ -340,10 +346,30 @@ pub fn parse_ty(&mut self) -> Ty<'tcx> {
}
'x' => {
assert_eq!(self.next(), '[');
let trait_ref = ty::Binder(self.parse_trait_ref());
let bounds = self.parse_existential_bounds();
let trait_ref = ty::Binder(self.parse_existential_trait_ref());
let builtin_bounds = self.parse_builtin_bounds();
let region_bound = self.parse_region();
let mut projection_bounds = Vec::new();
loop {
match self.next() {
'P' => {
let bound = self.parse_existential_projection();
projection_bounds.push(ty::Binder(bound));
}
'.' => { break; }
c => {
bug!("parse_bounds: bad bounds ('{}')", c)
}
}
}
assert_eq!(self.next(), ']');
return tcx.mk_trait(trait_ref, bounds);
return tcx.mk_trait(ty::TraitObject {
principal: trait_ref,
region_bound: region_bound,
builtin_bounds: builtin_bounds,
projection_bounds: projection_bounds
});
}
'p' => {
assert_eq!(self.next(), '[');
......@@ -588,6 +614,14 @@ fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'tcx> {
}
}
fn parse_existential_projection(&mut self) -> ty::ExistentialProjection<'tcx> {
ty::ExistentialProjection {
trait_ref: self.parse_existential_trait_ref(),
item_name: token::intern(&self.parse_str('|')),
ty: self.parse_ty(),
}
}
pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
let name = self.parse_name(':');
let def_id = self.parse_def();
......@@ -649,27 +683,6 @@ fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault {
}
}
pub fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> {
let builtin_bounds = self.parse_builtin_bounds();
let region_bound = self.parse_region();
let mut projection_bounds = Vec::new();
loop {
match self.next() {
'P' => {
projection_bounds.push(ty::Binder(self.parse_projection_predicate()));
}
'.' => { break; }
c => {
bug!("parse_bounds: bad bounds ('{}')", c)
}
}
}
ty::ExistentialBounds::new(
region_bound, builtin_bounds, projection_bounds)
}
fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds {
let mut builtin_bounds = ty::BuiltinBounds::empty();
loop {
......
......@@ -104,11 +104,26 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
enc_substs(w, cx, substs);
write!(w, "]");
}
ty::TyTrait(box ty::TraitTy { ref principal,
ref bounds }) => {
ty::TyTrait(ref obj) => {
write!(w, "x[");
enc_trait_ref(w, cx, principal.0);
enc_existential_bounds(w, cx, bounds);
enc_existential_trait_ref(w, cx, obj.principal.0);
enc_builtin_bounds(w, cx, &obj.builtin_bounds);
enc_region(w, cx, obj.region_bound);
// Encode projection_bounds in a stable order
let mut projection_bounds: Vec<_> = obj.projection_bounds
.iter()
.map(|b| (b.item_name().as_str(), b))
.collect();
projection_bounds.sort_by_key(|&(ref name, _)| name.clone());
for tp in projection_bounds.iter().map(|&(_, tp)| tp) {
write!(w, "P");
enc_existential_projection(w, cx, &tp.0);
}
write!(w, ".");
write!(w, "]");
}
ty::TyTuple(ts) => {
......@@ -344,6 +359,12 @@ pub fn enc_trait_ref<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
enc_substs(w, cx, s.substs);
}
fn enc_existential_trait_ref<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
s: ty::ExistentialTraitRef<'tcx>) {
write!(w, "{}|", (cx.ds)(cx.tcx, s.def_id));
enc_substs(w, cx, s.substs);
}
fn enc_unsafety(w: &mut Cursor<Vec<u8>>, p: hir::Unsafety) {
match p {
hir::Unsafety::Normal => write!(w, "n"),
......@@ -386,7 +407,7 @@ fn enc_fn_sig<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
enc_ty(w, cx, fsig.0.output);
}
pub fn enc_builtin_bounds(w: &mut Cursor<Vec<u8>>, _cx: &ctxt, bs: &ty::BuiltinBounds) {
fn enc_builtin_bounds(w: &mut Cursor<Vec<u8>>, _cx: &ctxt, bs: &ty::BuiltinBounds) {
for bound in bs {
match bound {
ty::BoundSend => write!(w, "S"),
......@@ -399,28 +420,6 @@ pub fn enc_builtin_bounds(w: &mut Cursor<Vec<u8>>, _cx: &ctxt, bs: &ty::BuiltinB
write!(w, ".");
}
pub fn enc_existential_bounds<'a,'tcx>(w: &mut Cursor<Vec<u8>>,
cx: &ctxt<'a,'tcx>,
bs: &ty::ExistentialBounds<'tcx>) {
enc_builtin_bounds(w, cx, &bs.builtin_bounds);
enc_region(w, cx, bs.region_bound);
// Encode projection_bounds in a stable order
let mut projection_bounds: Vec<_> = bs.projection_bounds
.iter()
.map(|b| (b.item_name().as_str(), b))
.collect();
projection_bounds.sort_by_key(|&(ref name, _)| name.clone());
for tp in projection_bounds.iter().map(|&(_, tp)| tp) {
write!(w, "P");
enc_projection_predicate(w, cx, &tp.0);
}
write!(w, ".");
}
pub fn enc_type_param_def<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>,
v: &ty::TypeParameterDef<'tcx>) {
write!(w, "{}:{}|{}|{}|{}|",
......@@ -489,7 +488,9 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
}
ty::Predicate::Projection(ty::Binder(ref data)) => {
write!(w, "p");
enc_projection_predicate(w, cx, data);
enc_trait_ref(w, cx, data.projection_ty.trait_ref);
write!(w, "{}|", data.projection_ty.item_name);
enc_ty(w, cx, data.ty);
}
ty::Predicate::WellFormed(data) => {
write!(w, "w");
......@@ -509,10 +510,10 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
}
}
fn enc_projection_predicate<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
cx: &ctxt<'a, 'tcx>,
data: &ty::ProjectionPredicate<'tcx>) {
enc_trait_ref(w, cx, data.projection_ty.trait_ref);
write!(w, "{}|", data.projection_ty.item_name);
fn enc_existential_projection<'a, 'tcx>(w: &mut Cursor<Vec<u8>>,
cx: &ctxt<'a, 'tcx>,
data: &ty::ExistentialProjection<'tcx>) {
enc_existential_trait_ref(w, cx, data.trait_ref);
write!(w, "{}|", data.item_name);
enc_ty(w, cx, data.ty);
}
......@@ -562,14 +562,9 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
// change to the vtable.
old_info.expect("unsized_info: missing old info for trait upcast")
}
(_, &ty::TyTrait(box ty::TraitTy { ref principal, .. })) => {
// Note that we preserve binding levels here:
let substs = principal.0.substs.with_self_ty(source).erase_regions();
let substs = ccx.tcx().mk_substs(substs);
let trait_ref = ty::Binder(ty::TraitRef {
def_id: principal.def_id(),
substs: substs,
});
(_, &ty::TyTrait(ref data)) => {
let trait_ref = data.principal.with_self_ty(ccx.tcx(), source);
let trait_ref = ccx.tcx().erase_regions(&trait_ref);
consts::ptrcast(meth::get_vtable(ccx, trait_ref),
Type::vtable_ptr(ccx))
}
......
......@@ -1055,8 +1055,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a,
assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst());
if let ty::TyTrait(ref trait_ty) = trait_ty.sty {
let poly_trait_ref = trait_ty.principal_trait_ref_with_self_ty(scx.tcx(),
impl_ty);
let poly_trait_ref = trait_ty.principal.with_self_ty(scx.tcx(), impl_ty);
// Walk all methods of the trait, including those of its supertraits
for trait_ref in traits::supertraits(scx.tcx(), poly_trait_ref) {
......
......@@ -627,7 +627,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// But it does not describe the trait's methods.
let def_id = match trait_type.sty {
ty::TyTrait(ref data) => data.principal_def_id(),
ty::TyTrait(ref data) => data.principal.def_id(),
_ => {
bug!("debuginfo: Unexpected trait-object type in \
trait_pointer_metadata(): {:?}",
......
......@@ -476,10 +476,10 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
output.push(']');
},
ty::TyTrait(ref trait_data) => {
push_item_name(tcx, trait_data.principal.skip_binder().def_id, output);
push_item_name(tcx, trait_data.principal.def_id(), output);
push_type_params(tcx,
&trait_data.principal.skip_binder().substs.types,
&trait_data.bounds.projection_bounds,
&trait_data.projection_bounds,
output);
},
ty::TyFnDef(_, _, &ty::BareFnTy{ unsafety, abi, ref sig } ) |
......@@ -562,7 +562,7 @@ fn push_item_name(tcx: TyCtxt,
fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
types: &'tcx subst::VecPerParamSpace<Ty<'tcx>>,
projections: &[ty::PolyProjectionPredicate<'tcx>],
projections: &[ty::PolyExistentialProjection<'tcx>],
output: &mut String) {
if types.is_empty() && projections.is_empty() {
return;
......@@ -577,7 +577,7 @@ fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
for projection in projections {
let projection = projection.skip_binder();
let name = &projection.projection_ty.item_name.as_str();
let name = &projection.item_name.as_str();
output.push_str(name);
output.push_str("=");
push_unique_type_name(tcx, projection.ty, output);
......
此差异已折叠。
......@@ -78,7 +78,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
fn unsize_kind(&self, t: Ty<'tcx>) -> Option<UnsizeKind<'tcx>> {
match t.sty {
ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal_def_id())),
ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal.def_id())),
ty::TyStruct(def, substs) => {
// FIXME(arielb1): do some kind of normalization
match def.struct_variant().fields.last() {
......
......@@ -102,12 +102,11 @@ fn deduce_expectations_from_expected_type(&self, expected_ty: Ty<'tcx>)
match expected_ty.sty {
ty::TyTrait(ref object_type) => {
let proj_bounds = object_type.projection_bounds_with_self_ty(self.tcx,
self.tcx.types.err);
let sig = proj_bounds.iter()
.filter_map(|pb| self.deduce_sig_from_projection(pb))
.next();
let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal_def_id());
let sig = object_type.projection_bounds.iter().filter_map(|pb| {
let pb = pb.with_self_ty(self.tcx, self.tcx.types.err);
self.deduce_sig_from_projection(&pb)
}).next();
let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal.def_id());
(sig, kind)
}
ty::TyInfer(ty::TyVar(vid)) => {
......
......@@ -210,7 +210,7 @@ fn fresh_receiver_substs(&mut self,
probe::ObjectPick => {
let trait_def_id = pick.item.container().id();
self.extract_trait_ref(self_ty, |this, object_ty, data| {
self.extract_existential_trait_ref(self_ty, |this, object_ty, principal| {
// The object data has no entry for the Self
// Type. For the purposes of this method call, we
// substitute the object type itself. This
......@@ -222,9 +222,9 @@ fn fresh_receiver_substs(&mut self,
// been ruled out when we deemed the trait to be
// "object safe".
let original_poly_trait_ref =
data.principal_trait_ref_with_self_ty(this.tcx, object_ty);
principal.with_self_ty(this.tcx, object_ty);
let upcast_poly_trait_ref =
this.upcast(original_poly_trait_ref.clone(), trait_def_id);
this.upcast(original_poly_trait_ref, trait_def_id);
let upcast_trait_ref =
this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
......@@ -276,8 +276,12 @@ fn fresh_receiver_substs(&mut self,
}
}
fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where
F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>, Ty<'tcx>, &ty::TraitTy<'tcx>) -> R,
fn extract_existential_trait_ref<R, F>(&mut self,
self_ty: Ty<'tcx>,
mut closure: F) -> R
where F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>,
Ty<'tcx>,
ty::PolyExistentialTraitRef<'tcx>) -> R,
{
// If we specified that this is an object method, then the
// self-type ought to be something that can be dereferenced to
......@@ -288,7 +292,7 @@ fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R wh
self.fcx.autoderef(self.span, self_ty)
.filter_map(|(ty, _)| {
match ty.sty {
ty::TyTrait(ref data) => Some(closure(self, ty, &data)),
ty::TyTrait(ref data) => Some(closure(self, ty, data.principal)),
_ => None,
}
})
......@@ -331,9 +335,7 @@ fn instantiate_method_substs(&mut self,
// parameters from the type and those from the method.
//
// FIXME -- permit users to manually specify lifetimes
let type_defs = method.generics.types.as_full_slice();
let region_defs = method.generics.regions.as_full_slice();
subst::Substs::from_param_defs(region_defs, type_defs, |def| {
subst::Substs::from_generics(&method.generics, |def, _| {
if def.space != subst::FnSpace {
substs.region_for_def(def)
} else {
......
......@@ -189,9 +189,7 @@ pub fn lookup_method_in_trait_adjusted(&self,
assert!(trait_def.generics.regions.is_empty());
// Construct a trait-reference `self_ty : Trait<input_tys>`
let type_defs = trait_def.generics.types.as_full_slice();
let region_defs = trait_def.generics.regions.as_full_slice();
let substs = subst::Substs::from_param_defs(region_defs, type_defs, |def| {
let substs = subst::Substs::from_generics(&trait_def.generics, |def, _| {
self.region_var_for_def(span, def)
}, |def, substs| {
if def.space == subst::SelfSpace {
......
......@@ -290,8 +290,8 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
match self_ty.sty {
ty::TyTrait(box ref data) => {
self.assemble_inherent_candidates_from_object(self_ty, data);
self.assemble_inherent_impl_candidates_for_type(data.principal_def_id());
self.assemble_inherent_candidates_from_object(self_ty, data.principal);
self.assemble_inherent_impl_candidates_for_type(data.principal.def_id());
}
ty::TyEnum(def, _) |
ty::TyStruct(def, _) => {
......@@ -445,7 +445,7 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
fn assemble_inherent_candidates_from_object(&mut self,
self_ty: Ty<'tcx>,
data: &ty::TraitTy<'tcx>) {
principal: ty::PolyExistentialTraitRef<'tcx>) {
debug!("assemble_inherent_candidates_from_object(self_ty={:?})",
self_ty);
......@@ -456,7 +456,7 @@ fn assemble_inherent_candidates_from_object(&mut self,
// a substitution that replaces `Self` with the object type
// itself. Hence, a `&self` method will wind up with an
// argument type like `&Trait`.
let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx, self_ty);
let trait_ref = principal.with_self_ty(self.tcx, self_ty);
self.elaborate_bounds(&[trait_ref], |this, new_trait_ref, item| {
let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
......@@ -1227,15 +1227,16 @@ fn xform_method_self_ty(&self,
return impl_ty;
}
let placeholder;
let mut substs = substs;
if
!method.generics.types.is_empty_in(subst::FnSpace) ||
!method.generics.regions.is_empty_in(subst::FnSpace)
{
let type_defs = method.generics.types.as_full_slice();
let region_defs = method.generics.regions.as_full_slice();
placeholder = subst::Substs::from_param_defs(region_defs, type_defs, |def| {
// Erase any late-bound regions from the method and substitute
// in the values from the substitution.
let xform_self_ty = method.fty.sig.input(0);
let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty);
if method.generics.types.is_empty_in(subst::FnSpace) &&
method.generics.regions.is_empty_in(subst::FnSpace) {
xform_self_ty.subst(self.tcx, substs)
} else {
let substs = subst::Substs::from_generics(&method.generics, |def, _| {
if def.space != subst::FnSpace {
substs.region_for_def(def)
} else {
......@@ -1250,16 +1251,8 @@ fn xform_method_self_ty(&self,
self.type_var_for_def(self.span, def, cur_substs)
}
});
substs = &placeholder;
xform_self_ty.subst(self.tcx, &substs)
}
// Erase any late-bound regions from the method and substitute
// in the values from the substitution.
let xform_self_ty = method.fty.sig.input(0);
let xform_self_ty = self.erase_late_bound_regions(&xform_self_ty);
let xform_self_ty = xform_self_ty.subst(self.tcx, substs);
xform_self_ty
}
/// Get the type of an impl and generate substitutions with placeholders.
......
......@@ -358,7 +358,7 @@ fn is_local(ty: Ty) -> bool {
match ty.sty {
ty::TyEnum(def, _) | ty::TyStruct(def, _) => def.did.is_local(),
ty::TyTrait(ref tr) => tr.principal_def_id().is_local(),
ty::TyTrait(ref tr) => tr.principal.def_id().is_local(),
ty::TyParam(_) => true,
......
......@@ -824,11 +824,11 @@ fn walk_cast(&mut self,
}
/*From:*/ (_,
/*To: */ &ty::TyTrait(box ty::TraitTy { ref bounds, .. })) => {
/*To: */ &ty::TyTrait(ref obj)) => {
// When T is existentially quantified as a trait
// `Foo+'to`, it must outlive the region bound `'to`.
self.type_must_outlive(infer::RelateObjectBound(cast_expr.span),
from_ty, bounds.region_bound);
from_ty, obj.region_bound);
}
/*From:*/ (&ty::TyBox(from_referent_ty),
......
......@@ -75,7 +75,7 @@ fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
}
TyTrait(ref t) => {
Some(t.principal_def_id())
Some(t.principal.def_id())
}
TyBox(_) => {
......
......@@ -80,7 +80,7 @@ fn check_item(&self, item: &hir::Item) {
self.check_def_id(item, def.did);
}
ty::TyTrait(ref data) => {
self.check_def_id(item, data.principal_def_id());
self.check_def_id(item, data.principal.def_id());
}
ty::TyBox(..) => {
match self.tcx.lang_items.require_owned_box() {
......
......@@ -168,14 +168,14 @@ fn visit_item(&mut self, item: &'v hir::Item) {
// This is something like impl Trait1 for Trait2. Illegal
// if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
if !self.tcx.is_object_safe(data.principal_def_id()) {
if !self.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(self.tcx, data.principal_def_id());
traits::supertrait_def_ids(self.tcx, data.principal.def_id());
if supertrait_def_ids.any(|d| d == trait_def_id) {
span_err!(self.tcx.sess, item.span, E0371,
"the object type `{}` automatically \
......
......@@ -722,7 +722,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
AstConv::instantiate_mono_trait_ref(&ccx.icx(&()),
&ExplicitRscope,
ast_trait_ref,
None);
tcx.mk_self_type());
tcx.record_trait_has_default_impl(trait_ref.def_id);
......@@ -752,7 +752,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
AstConv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
&ExplicitRscope,
ast_trait_ref,
Some(selfty))
selfty)
});
tcx.impl_trait_refs.borrow_mut().insert(def_id, trait_ref);
......@@ -1815,10 +1815,12 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
let mut projections = Vec::new();
let trait_ref =
conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)),
ty,
poly_trait_ref,
&mut projections);
AstConv::instantiate_poly_trait_ref(&ccx.icx(&(base_predicates,
ast_generics)),
&ExplicitRscope,
poly_trait_ref,
ty,
&mut projections);
result.predicates.push(trait_ref.to_predicate());
......@@ -2069,7 +2071,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
astconv.instantiate_poly_trait_ref(&rscope,
bound,
Some(param_ty),
param_ty,
&mut projection_bounds)
}).collect();
......@@ -2100,7 +2102,10 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
match *bound {
hir::TraitTyParamBound(ref tr, hir::TraitBoundModifier::None) => {
let mut projections = Vec::new();
let pred = conv_poly_trait_ref(astconv, param_ty, tr, &mut projections);
let pred = astconv.instantiate_poly_trait_ref(&ExplicitRscope,
tr,
param_ty,
&mut projections);
projections.into_iter()
.map(|p| p.to_predicate())
.chain(Some(pred.to_predicate()))
......@@ -2117,19 +2122,6 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
}
}
fn conv_poly_trait_ref<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
param_ty: Ty<'tcx>,
trait_ref: &hir::PolyTraitRef,
projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
AstConv::instantiate_poly_trait_ref(astconv,
&ExplicitRscope,
trait_ref,
Some(param_ty),
projections)
}
fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
ccx: &CrateCtxt<'a, 'tcx>,
id: DefId,
......
......@@ -396,19 +396,16 @@ fn add_constraints_from_ty(&mut self,
ty::TyTrait(ref data) => {
let poly_trait_ref =
data.principal_trait_ref_with_self_ty(self.tcx(),
self.tcx().types.err);
data.principal.with_self_ty(self.tcx(), self.tcx().types.err);
// The type `Foo<T+'a>` is contravariant w/r/t `'a`:
let contra = self.contravariant(variance);
self.add_constraints_from_region(generics, data.bounds.region_bound, contra);
self.add_constraints_from_region(generics, data.region_bound, contra);
// Ignore the SelfSpace, it is erased.
self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance);
let projections = data.projection_bounds_with_self_ty(self.tcx(),
self.tcx().types.err);
for projection in &projections {
for projection in &data.projection_bounds {
self.add_constraints_from_ty(generics, projection.0.ty, self.invariant);
}
}
......
......@@ -630,26 +630,6 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
}
}
impl<'tcx> Clean<(Vec<TyParamBound>, Vec<TypeBinding>)> for ty::ExistentialBounds<'tcx> {
fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Vec<TypeBinding>) {
let mut tp_bounds = vec![];
self.region_bound.clean(cx).map(|b| tp_bounds.push(RegionBound(b)));
for bb in &self.builtin_bounds {
tp_bounds.push(bb.clean(cx));
}
let mut bindings = vec![];
for &ty::Binder(ref pb) in &self.projection_bounds {
bindings.push(TypeBinding {
name: pb.projection_ty.item_name.clean(cx),
ty: pb.ty.clean(cx)
});
}
(tp_bounds, bindings)
}
}
fn external_path_params(cx: &DocContext, trait_did: Option<DefId>,
bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
let lifetimes = substs.regions.get_slice(subst::TypeSpace)
......@@ -1848,12 +1828,26 @@ fn clean(&self, cx: &DocContext) -> Type {
is_generic: false,
}
}
ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => {
let did = principal.def_id();
ty::TyTrait(ref obj) => {
let did = obj.principal.def_id();
inline::record_extern_fqn(cx, did, TypeTrait);
let (typarams, bindings) = bounds.clean(cx);
let mut typarams = vec![];
obj.region_bound.clean(cx).map(|b| typarams.push(RegionBound(b)));
for bb in &obj.builtin_bounds {
typarams.push(bb.clean(cx));
}
let mut bindings = vec![];
for &ty::Binder(ref pb) in &obj.projection_bounds {
bindings.push(TypeBinding {
name: pb.item_name.clean(cx),
ty: pb.ty.clean(cx)
});
}
let path = external_path(cx, &cx.tcx().item_name(did).as_str(),
Some(did), bindings, principal.substs());
Some(did), bindings, obj.principal.0.substs);
ResolvedPath {
path: path,
typarams: Some(typarams),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册