1
Fork 0

Integrate projection bounds to ExistentialBounds but do not use them for anything.

This commit is contained in:
Niko Matsakis 2014-12-26 04:36:04 -05:00
parent 82787c2252
commit becbd81aaa
14 changed files with 240 additions and 108 deletions

View file

@ -200,9 +200,9 @@ pub fn parse_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum,
parse_bounds(&mut st, conv) parse_bounds(&mut st, conv)
} }
pub fn parse_existential_bounds_data(data: &[u8], crate_num: ast::CrateNum, pub fn parse_existential_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum,
pos: uint, tcx: &ty::ctxt, conv: conv_did) pos: uint, tcx: &ty::ctxt<'tcx>, conv: conv_did)
-> ty::ExistentialBounds { -> ty::ExistentialBounds<'tcx> {
let mut st = parse_state_from_data(data, crate_num, pos, tcx); let mut st = parse_state_from_data(data, crate_num, pos, tcx);
parse_existential_bounds(&mut st, conv) parse_existential_bounds(&mut st, conv)
} }
@ -744,10 +744,18 @@ fn parse_type_param_def<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did)
} }
} }
fn parse_existential_bounds(st: &mut PState, conv: conv_did) -> ty::ExistentialBounds { fn parse_existential_bounds<'a,'tcx>(st: &mut PState<'a,'tcx>,
let r = parse_region(st, |x,y| conv(x,y)); conv: conv_did)
let bb = parse_builtin_bounds(st, conv); -> ty::ExistentialBounds<'tcx>
return ty::ExistentialBounds { region_bound: r, builtin_bounds: bb }; {
let ty::ParamBounds { trait_bounds, mut region_bounds, builtin_bounds, projection_bounds } =
parse_bounds(st, conv);
assert_eq!(region_bounds.len(), 1);
assert_eq!(trait_bounds.len(), 0);
let region_bound = region_bounds.pop().unwrap();
return ty::ExistentialBounds { region_bound: region_bound,
builtin_bounds: builtin_bounds,
projection_bounds: projection_bounds };
} }
fn parse_builtin_bounds(st: &mut PState, _conv: conv_did) -> ty::BuiltinBounds { fn parse_builtin_bounds(st: &mut PState, _conv: conv_did) -> ty::BuiltinBounds {

View file

@ -392,9 +392,14 @@ pub fn enc_builtin_bounds(w: &mut SeekableMemWriter, _cx: &ctxt, bs: &ty::Builti
mywrite!(w, "."); mywrite!(w, ".");
} }
pub fn enc_existential_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ExistentialBounds) { pub fn enc_existential_bounds<'a,'tcx>(w: &mut SeekableMemWriter,
enc_region(w, cx, bs.region_bound); cx: &ctxt<'a,'tcx>,
enc_builtin_bounds(w, cx, &bs.builtin_bounds); bs: &ty::ExistentialBounds<'tcx>) {
let param_bounds = ty::ParamBounds { trait_bounds: vec!(),
region_bounds: vec!(bs.region_bound),
builtin_bounds: bs.builtin_bounds,
projection_bounds: bs.projection_bounds.clone() };
enc_bounds(w, cx, &param_bounds);
} }
pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,

View file

@ -842,7 +842,8 @@ trait rbml_writer_helpers<'tcx> {
type_scheme: ty::TypeScheme<'tcx>); type_scheme: ty::TypeScheme<'tcx>);
fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
substs: &subst::Substs<'tcx>); substs: &subst::Substs<'tcx>);
fn emit_existential_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::ExistentialBounds); 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_builtin_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::BuiltinBounds);
fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, fn emit_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
adj: &ty::AutoAdjustment<'tcx>); adj: &ty::AutoAdjustment<'tcx>);
@ -982,7 +983,8 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
}); });
} }
fn emit_existential_bounds(&mut self, ecx: &e::EncodeContext, bounds: &ty::ExistentialBounds) { 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(this.writer, self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this.writer,
&ecx.ty_str_ctxt(), &ecx.ty_str_ctxt(),
bounds))); bounds)));
@ -1372,7 +1374,7 @@ trait rbml_decoder_decoder_helpers<'tcx> {
fn read_type_scheme<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) fn read_type_scheme<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::TypeScheme<'tcx>; -> ty::TypeScheme<'tcx>;
fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::ExistentialBounds; -> ty::ExistentialBounds<'tcx>;
fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> subst::Substs<'tcx>; -> subst::Substs<'tcx>;
fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>) fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
@ -1626,7 +1628,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
} }
fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>) fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-> ty::ExistentialBounds -> ty::ExistentialBounds<'tcx>
{ {
self.read_opaque(|this, doc| { self.read_opaque(|this, doc| {
Ok(tydecode::parse_existential_bounds_data(doc.data, Ok(tydecode::parse_existential_bounds_data(doc.data,

View file

@ -351,11 +351,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
(&ty::ty_trait(..), &ty::ty_trait(..)) => { (&ty::ty_trait(..), &ty::ty_trait(..)) => {
None None
} }
(_, &ty::ty_trait(box ty::TyTrait { ref principal, bounds })) => { (_, &ty::ty_trait(box ty::TyTrait { ref principal, ref bounds })) => {
// FIXME what is the purpose of `ty`? // FIXME what is the purpose of `ty`?
let ty = ty::mk_trait(tcx, principal.clone(), bounds); let ty = ty::mk_trait(tcx, principal.clone(), bounds.clone());
Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: (*principal).clone(), Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: principal.clone(),
bounds: bounds }, bounds: bounds.clone() },
ty_a))) ty_a)))
} }
(&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b)) (&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
@ -458,10 +458,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
match a.sty { match a.sty {
ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty.sty { ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty.sty {
ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => { ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
debug!("mutbl={} b_mutbl={}", mutbl, b_mutbl); debug!("mutbl={} b_mutbl={}", mutbl, b_mutbl);
// FIXME what is purpose of this type `tr`? let tr = ty::mk_trait(tcx, principal.clone(), bounds.clone());
let tr = ty::mk_trait(tcx, principal.clone(), bounds);
try!(self.subtype(mk_ty(tr), b)); try!(self.subtype(mk_ty(tr), b));
Ok(Some(AdjustDerefRef(AutoDerefRef { Ok(Some(AdjustDerefRef(AutoDerefRef {
autoderefs: 1, autoderefs: 1,

View file

@ -222,7 +222,7 @@ pub trait Combine<'tcx> {
}; };
let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety)); let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety));
let onceness = try!(self.oncenesses(a.onceness, b.onceness)); let onceness = try!(self.oncenesses(a.onceness, b.onceness));
let bounds = try!(self.existential_bounds(a.bounds, b.bounds)); let bounds = try!(self.existential_bounds(&a.bounds, &b.bounds));
let sig = try!(self.binders(&a.sig, &b.sig)); let sig = try!(self.binders(&a.sig, &b.sig));
let abi = try!(self.abi(a.abi, b.abi)); let abi = try!(self.abi(a.abi, b.abi));
Ok(ty::ClosureTy { Ok(ty::ClosureTy {
@ -289,15 +289,61 @@ pub trait Combine<'tcx> {
fn oncenesses(&self, a: Onceness, b: Onceness) -> cres<'tcx, Onceness>; fn oncenesses(&self, a: Onceness, b: Onceness) -> cres<'tcx, Onceness>;
fn projection_tys(&self,
a: &ty::ProjectionTy<'tcx>,
b: &ty::ProjectionTy<'tcx>)
-> cres<'tcx, ty::ProjectionTy<'tcx>>
{
if a.item_name != b.item_name {
Err(ty::terr_projection_name_mismatched(
expected_found(self, a.item_name, b.item_name)))
} else {
let trait_ref = try!(self.trait_refs(&*a.trait_ref, &*b.trait_ref));
Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name })
}
}
fn projection_predicates(&self,
a: &ty::ProjectionPredicate<'tcx>,
b: &ty::ProjectionPredicate<'tcx>)
-> cres<'tcx, ty::ProjectionPredicate<'tcx>>
{
let projection_ty = try!(self.projection_tys(&a.projection_ty, &b.projection_ty));
let ty = try!(self.tys(a.ty, b.ty));
Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty })
}
fn projection_bounds(&self,
a: &Vec<ty::PolyProjectionPredicate<'tcx>>,
b: &Vec<ty::PolyProjectionPredicate<'tcx>>)
-> cres<'tcx, Vec<ty::PolyProjectionPredicate<'tcx>>>
{
// To be compatible, `a` and `b` must be for precisely the
// same set of traits and item names. We always require that
// projection bounds lists are sorted by trait-def-id and item-name,
// so we can just iterate through the lists pairwise, so long as they are the
// same length.
if a.len() != b.len() {
Err(ty::terr_projection_bounds_length(expected_found(self, a.len(), b.len())))
} else {
a.iter()
.zip(b.iter())
.map(|(a, b)| self.binders(a, b))
.collect()
}
}
fn existential_bounds(&self, fn existential_bounds(&self,
a: ty::ExistentialBounds, a: &ty::ExistentialBounds<'tcx>,
b: ty::ExistentialBounds) b: &ty::ExistentialBounds<'tcx>)
-> cres<'tcx, ty::ExistentialBounds> -> cres<'tcx, ty::ExistentialBounds<'tcx>>
{ {
let r = try!(self.contraregions(a.region_bound, b.region_bound)); let r = try!(self.contraregions(a.region_bound, b.region_bound));
let nb = try!(self.builtin_bounds(a.builtin_bounds, b.builtin_bounds)); let nb = try!(self.builtin_bounds(a.builtin_bounds, b.builtin_bounds));
let pb = try!(self.projection_bounds(&a.projection_bounds, &b.projection_bounds));
Ok(ty::ExistentialBounds { region_bound: r, Ok(ty::ExistentialBounds { region_bound: r,
builtin_bounds: nb }) builtin_bounds: nb,
projection_bounds: pb })
} }
fn builtin_bounds(&self, fn builtin_bounds(&self,
@ -381,6 +427,16 @@ impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> {
} }
} }
impl<'tcx> Combineable<'tcx> for ty::ProjectionPredicate<'tcx> {
fn combine<C:Combine<'tcx>>(combiner: &C,
a: &ty::ProjectionPredicate<'tcx>,
b: &ty::ProjectionPredicate<'tcx>)
-> cres<'tcx, ty::ProjectionPredicate<'tcx>>
{
combiner.projection_predicates(a, b)
}
}
impl<'tcx> Combineable<'tcx> for ty::FnSig<'tcx> { impl<'tcx> Combineable<'tcx> for ty::FnSig<'tcx> {
fn combine<C:Combine<'tcx>>(combiner: &C, fn combine<C:Combine<'tcx>>(combiner: &C,
a: &ty::FnSig<'tcx>, a: &ty::FnSig<'tcx>,
@ -496,7 +552,7 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
&ty::ty_trait(ref b_)) => { &ty::ty_trait(ref b_)) => {
debug!("Trying to match traits {} and {}", a, b); debug!("Trying to match traits {} and {}", a, b);
let principal = try!(this.binders(&a_.principal, &b_.principal)); let principal = try!(this.binders(&a_.principal, &b_.principal));
let bounds = try!(this.existential_bounds(a_.bounds, b_.bounds)); let bounds = try!(this.existential_bounds(&a_.bounds, &b_.bounds));
Ok(ty::mk_trait(tcx, principal, bounds)) Ok(ty::mk_trait(tcx, principal, bounds))
} }
@ -595,12 +651,8 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
} }
(&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => { (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
if a_data.item_name == b_data.item_name { let projection_ty = try!(this.projection_tys(a_data, b_data));
let trait_ref = try!(this.trait_refs(&*a_data.trait_ref, &*b_data.trait_ref)); Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
Ok(ty::mk_projection(tcx, Rc::new(trait_ref), a_data.item_name))
} else {
Err(ty::terr_sorts(expected_found(this, a, b)))
}
} }
_ => Err(ty::terr_sorts(expected_found(this, a, b))) _ => Err(ty::terr_sorts(expected_found(this, a, b)))

View file

@ -396,14 +396,14 @@ pub fn type_of_adjust<'tcx>(cx: &ctxt<'tcx>, adj: &AutoAdjustment<'tcx>) -> Opti
fn type_of_autoref<'tcx>(cx: &ctxt<'tcx>, autoref: &AutoRef<'tcx>) -> Option<Ty<'tcx>> { fn type_of_autoref<'tcx>(cx: &ctxt<'tcx>, autoref: &AutoRef<'tcx>) -> Option<Ty<'tcx>> {
match autoref { match autoref {
&AutoUnsize(ref k) => match k { &AutoUnsize(ref k) => match k {
&UnsizeVtable(TyTrait { ref principal, bounds }, _) => { &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
Some(mk_trait(cx, (*principal).clone(), bounds)) Some(mk_trait(cx, principal.clone(), bounds.clone()))
} }
_ => None _ => None
}, },
&AutoUnsizeUniq(ref k) => match k { &AutoUnsizeUniq(ref k) => match k {
&UnsizeVtable(TyTrait { ref principal, bounds }, _) => { &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
Some(mk_uniq(cx, mk_trait(cx, (*principal).clone(), bounds))) Some(mk_uniq(cx, mk_trait(cx, principal.clone(), bounds.clone())))
} }
_ => None _ => None
}, },
@ -1040,7 +1040,7 @@ pub struct ClosureTy<'tcx> {
pub unsafety: ast::Unsafety, pub unsafety: ast::Unsafety,
pub onceness: ast::Onceness, pub onceness: ast::Onceness,
pub store: TraitStore, pub store: TraitStore,
pub bounds: ExistentialBounds, pub bounds: ExistentialBounds<'tcx>,
pub sig: PolyFnSig<'tcx>, pub sig: PolyFnSig<'tcx>,
pub abi: abi::Abi, pub abi: abi::Abi,
} }
@ -1376,7 +1376,7 @@ pub enum sty<'tcx> {
#[deriving(Clone, PartialEq, Eq, Hash, Show)] #[deriving(Clone, PartialEq, Eq, Hash, Show)]
pub struct TyTrait<'tcx> { pub struct TyTrait<'tcx> {
pub principal: ty::PolyTraitRef<'tcx>, pub principal: ty::PolyTraitRef<'tcx>,
pub bounds: ExistentialBounds pub bounds: ExistentialBounds<'tcx>,
} }
impl<'tcx> TyTrait<'tcx> { impl<'tcx> TyTrait<'tcx> {
@ -1510,7 +1510,9 @@ pub enum type_err<'tcx> {
terr_builtin_bounds(expected_found<BuiltinBounds>), terr_builtin_bounds(expected_found<BuiltinBounds>),
terr_variadic_mismatch(expected_found<bool>), terr_variadic_mismatch(expected_found<bool>),
terr_cyclic_ty, terr_cyclic_ty,
terr_convergence_mismatch(expected_found<bool>) terr_convergence_mismatch(expected_found<bool>),
terr_projection_name_mismatched(expected_found<ast::Name>),
terr_projection_bounds_length(expected_found<uint>),
} }
/// Bounds suitable for a named type parameter like `A` in `fn foo<A>` /// Bounds suitable for a named type parameter like `A` in `fn foo<A>`
@ -1528,10 +1530,11 @@ pub struct ParamBounds<'tcx> {
/// major difference between this case and `ParamBounds` is that /// major difference between this case and `ParamBounds` is that
/// general purpose trait bounds are omitted and there must be /// general purpose trait bounds are omitted and there must be
/// *exactly one* region. /// *exactly one* region.
#[deriving(Copy, PartialEq, Eq, Hash, Clone, Show)] #[deriving(PartialEq, Eq, Hash, Clone, Show)]
pub struct ExistentialBounds { pub struct ExistentialBounds<'tcx> {
pub region_bound: ty::Region, pub region_bound: ty::Region,
pub builtin_bounds: BuiltinBounds pub builtin_bounds: BuiltinBounds,
pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>,
} }
pub type BuiltinBounds = EnumSet<BuiltinBound>; pub type BuiltinBounds = EnumSet<BuiltinBound>;
@ -1559,9 +1562,10 @@ pub fn all_builtin_bounds() -> BuiltinBounds {
} }
/// An existential bound that does not implement any traits. /// An existential bound that does not implement any traits.
pub fn region_existential_bound(r: ty::Region) -> ExistentialBounds { pub fn region_existential_bound<'tcx>(r: ty::Region) -> ExistentialBounds<'tcx> {
ty::ExistentialBounds { region_bound: r, ty::ExistentialBounds { region_bound: r,
builtin_bounds: empty_builtin_bounds() } builtin_bounds: empty_builtin_bounds(),
projection_bounds: Vec::new() }
} }
impl CLike for BuiltinBound { impl CLike for BuiltinBound {
@ -1820,12 +1824,24 @@ pub struct ProjectionPredicate<'tcx> {
pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>; pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
impl<'tcx> PolyProjectionPredicate<'tcx> {
pub fn sort_key(&self) -> (ast::DefId, ast::Name) {
self.0.projection_ty.sort_key()
}
}
#[deriving(Clone, PartialEq, Eq, Hash, Show)] #[deriving(Clone, PartialEq, Eq, Hash, Show)]
pub struct ProjectionTy<'tcx> { pub struct ProjectionTy<'tcx> {
pub trait_ref: Rc<ty::TraitRef<'tcx>>, pub trait_ref: Rc<ty::TraitRef<'tcx>>,
pub item_name: ast::Name, pub item_name: ast::Name,
} }
impl<'tcx> ProjectionTy<'tcx> {
pub fn sort_key(&self) -> (ast::DefId, ast::Name) {
(self.trait_ref.def_id, self.item_name)
}
}
pub trait ToPolyTraitRef<'tcx> { pub trait ToPolyTraitRef<'tcx> {
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
} }
@ -2675,8 +2691,11 @@ pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>, pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
principal: ty::PolyTraitRef<'tcx>, principal: ty::PolyTraitRef<'tcx>,
bounds: ExistentialBounds) bounds: ExistentialBounds<'tcx>)
-> Ty<'tcx> { -> Ty<'tcx>
{
assert!(bound_list_is_sorted(bounds.projection_bounds.as_slice()));
let inner = box TyTrait { let inner = box TyTrait {
principal: principal, principal: principal,
bounds: bounds bounds: bounds
@ -2684,6 +2703,16 @@ pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
mk_t(cx, ty_trait(inner)) mk_t(cx, ty_trait(inner))
} }
fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
bounds.len() == 0 ||
bounds[1..].iter().enumerate().all(
|(index, bound)| bounds[index].sort_key() <= bound.sort_key())
}
pub fn sort_bounds_list(bounds: &mut [ty::PolyProjectionPredicate]) {
bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()))
}
pub fn mk_projection<'tcx>(cx: &ctxt<'tcx>, pub fn mk_projection<'tcx>(cx: &ctxt<'tcx>,
trait_ref: Rc<ty::TraitRef<'tcx>>, trait_ref: Rc<ty::TraitRef<'tcx>>,
item_name: ast::Name) item_name: ast::Name)
@ -3226,7 +3255,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
} }
} }
ty_trait(box TyTrait { bounds, .. }) => { ty_trait(box TyTrait { ref bounds, .. }) => {
object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
} }
@ -3391,7 +3420,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
fn closure_contents(cty: &ClosureTy) -> TypeContents { fn closure_contents(cty: &ClosureTy) -> TypeContents {
// Closure contents are just like trait contents, but with potentially // Closure contents are just like trait contents, but with potentially
// even more stuff. // even more stuff.
let st = object_contents(cty.bounds); let st = object_contents(&cty.bounds);
let st = match cty.store { let st = match cty.store {
UniqTraitStore => { UniqTraitStore => {
@ -3405,7 +3434,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
st st
} }
fn object_contents(bounds: ExistentialBounds) -> TypeContents { fn object_contents(bounds: &ExistentialBounds) -> TypeContents {
// These are the type contents of the (opaque) interior. We // These are the type contents of the (opaque) interior. We
// make no assumptions (other than that it cannot have an // make no assumptions (other than that it cannot have an
// in-scope type parameter within, which makes no sense). // in-scope type parameter within, which makes no sense).
@ -4205,6 +4234,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
let bounds = ty::ExistentialBounds { let bounds = ty::ExistentialBounds {
region_bound: ReStatic, region_bound: ReStatic,
builtin_bounds: all_builtin_bounds(), builtin_bounds: all_builtin_bounds(),
projection_bounds: vec!(),
}; };
ty::mk_closure( ty::mk_closure(
@ -4339,8 +4369,8 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
format!("UnsizeStruct with bad sty: {}", format!("UnsizeStruct with bad sty: {}",
ty_to_string(cx, ty))[]) ty_to_string(cx, ty))[])
}, },
&UnsizeVtable(TyTrait { ref principal, bounds }, _) => { &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
mk_trait(cx, (*principal).clone(), bounds) mk_trait(cx, principal.clone(), bounds.clone())
} }
} }
} }
@ -4760,6 +4790,16 @@ pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String {
if values.expected { "converging" } else { "diverging" }, if values.expected { "converging" } else { "diverging" },
if values.found { "converging" } else { "diverging" }) if values.found { "converging" } else { "diverging" })
} }
terr_projection_name_mismatched(ref values) => {
format!("expected {}, found {}",
token::get_name(values.expected),
token::get_name(values.found))
}
terr_projection_bounds_length(ref values) => {
format!("expected {} associated type bindings, found {}",
values.expected,
values.found)
}
} }
} }

View file

@ -121,8 +121,8 @@ pub trait TypeFolder<'tcx> {
super_fold_trait_store(self, s) super_fold_trait_store(self, s)
} }
fn fold_existential_bounds(&mut self, s: ty::ExistentialBounds) fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
-> ty::ExistentialBounds { -> ty::ExistentialBounds<'tcx> {
super_fold_existential_bounds(self, s) super_fold_existential_bounds(self, s)
} }
@ -349,9 +349,9 @@ impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
} }
} }
impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds { impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds { fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds<'tcx> {
folder.fold_existential_bounds(*self) folder.fold_existential_bounds(self)
} }
} }
@ -449,7 +449,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::UnsizeKind<'tcx> {
match *self { match *self {
ty::UnsizeLength(len) => ty::UnsizeLength(len), ty::UnsizeLength(len) => ty::UnsizeLength(len),
ty::UnsizeStruct(box ref k, n) => ty::UnsizeStruct(box k.fold_with(folder), n), ty::UnsizeStruct(box ref k, n) => ty::UnsizeStruct(box k.fold_with(folder), n),
ty::UnsizeVtable(ty::TyTrait{ref principal, bounds}, self_ty) => { ty::UnsizeVtable(ty::TyTrait{ref principal, ref bounds}, self_ty) => {
ty::UnsizeVtable( ty::UnsizeVtable(
ty::TyTrait { ty::TyTrait {
principal: principal.fold_with(folder), principal: principal.fold_with(folder),
@ -565,9 +565,9 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
let substs = substs.fold_with(this); let substs = substs.fold_with(this);
ty::ty_enum(tid, this.tcx().mk_substs(substs)) ty::ty_enum(tid, this.tcx().mk_substs(substs))
} }
ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => { ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
ty::ty_trait(box ty::TyTrait { ty::ty_trait(box ty::TyTrait {
principal: (*principal).fold_with(this), principal: principal.fold_with(this),
bounds: bounds.fold_with(this), bounds: bounds.fold_with(this),
}) })
} }
@ -693,12 +693,15 @@ pub fn super_fold_trait_store<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
} }
} }
pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(this: &mut T, pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
bounds: ty::ExistentialBounds) this: &mut T,
-> ty::ExistentialBounds { bounds: &ty::ExistentialBounds<'tcx>)
-> ty::ExistentialBounds<'tcx>
{
ty::ExistentialBounds { ty::ExistentialBounds {
region_bound: bounds.region_bound.fold_with(this), region_bound: bounds.region_bound.fold_with(this),
builtin_bounds: bounds.builtin_bounds, builtin_bounds: bounds.builtin_bounds,
projection_bounds: bounds.projection_bounds.fold_with(this),
} }
} }

View file

@ -739,8 +739,8 @@ impl<'tcx> Repr<'tcx> for ty::BuiltinBounds {
} }
} }
impl<'tcx> Repr<'tcx> for ty::ExistentialBounds { impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
fn repr(&self, tcx: &ctxt) -> String { fn repr(&self, tcx: &ctxt<'tcx>) -> String {
self.user_string(tcx) self.user_string(tcx)
} }
} }
@ -1142,8 +1142,8 @@ impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> {
} }
} }
impl<'tcx> UserString<'tcx> for ty::ExistentialBounds { impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> {
fn user_string(&self, tcx: &ctxt) -> String { fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
if self.builtin_bounds.contains(&ty::BoundSend) && if self.builtin_bounds.contains(&ty::BoundSend) &&
self.region_bound == ty::ReStatic self.region_bound == ty::ReStatic
{ // Region bound is implied by builtin bounds: { // Region bound is implied by builtin bounds:

View file

@ -810,11 +810,13 @@ pub fn ast_ty_to_builtin_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
} }
} }
type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC, fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
rscope: &RS, rscope: &RS,
ty: &ast::Ty, ty: &ast::Ty,
bounds: &[ast::TyParamBound]) bounds: &[ast::TyParamBound])
-> Result<ty::PolyTraitRef<'tcx>, ErrorReported> -> Result<TraitAndProjections<'tcx>, ErrorReported>
where AC : AstConv<'tcx>, RS : RegionScope where AC : AstConv<'tcx>, RS : RegionScope
{ {
/*! /*!
@ -832,14 +834,17 @@ fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
ast::TyPath(ref path, id) => { ast::TyPath(ref path, id) => {
match this.tcx().def_map.borrow().get(&id) { match this.tcx().def_map.borrow().get(&id) {
Some(&def::DefTrait(trait_def_id)) => { Some(&def::DefTrait(trait_def_id)) => {
// TODO do something with this let mut projection_bounds = Vec::new();
let mut projections = Vec::new(); let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
Ok(ty::Binder(ast_path_to_trait_ref(this, rscope,
rscope, trait_def_id,
trait_def_id, None,
None, path,
path, Some(&mut projection_bounds)));
Some(&mut projections)))) let projection_bounds = projection_bounds.into_iter()
.map(ty::Binder)
.collect();
Ok((trait_ref, projection_bounds))
} }
_ => { _ => {
span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait"); span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait");
@ -882,6 +887,7 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
rscope: &RS, rscope: &RS,
span: Span, span: Span,
trait_ref: ty::PolyTraitRef<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>,
projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
bounds: &[ast::TyParamBound]) bounds: &[ast::TyParamBound])
-> Ty<'tcx> -> Ty<'tcx>
where AC : AstConv<'tcx>, RS : RegionScope where AC : AstConv<'tcx>, RS : RegionScope
@ -890,6 +896,7 @@ fn trait_ref_to_object_type<'tcx,AC,RS>(this: &AC,
rscope, rscope,
span, span,
Some(trait_ref.clone()), Some(trait_ref.clone()),
projection_bounds,
bounds); bounds);
let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds); let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
@ -1019,9 +1026,9 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
} }
ast::TyObjectSum(ref ty, ref bounds) => { ast::TyObjectSum(ref ty, ref bounds) => {
match ast_ty_to_trait_ref(this, rscope, &**ty, bounds[]) { match ast_ty_to_trait_ref(this, rscope, &**ty, bounds[]) {
Ok(trait_ref) => { Ok((trait_ref, projection_bounds)) => {
trait_ref_to_object_type(this, rscope, ast_ty.span, trait_ref_to_object_type(this, rscope, ast_ty.span,
trait_ref, bounds[]) trait_ref, projection_bounds, bounds[])
} }
Err(ErrorReported) => { Err(ErrorReported) => {
this.tcx().types.err this.tcx().types.err
@ -1062,13 +1069,15 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
rscope, rscope,
ast_ty.span, ast_ty.span,
None, None,
Vec::new(),
f.bounds.as_slice()); f.bounds.as_slice());
let region_bound = bounds.region_bound;
let fn_decl = ty_of_closure(this, let fn_decl = ty_of_closure(this,
f.unsafety, f.unsafety,
f.onceness, f.onceness,
bounds, bounds,
ty::RegionTraitStore( ty::RegionTraitStore(
bounds.region_bound, region_bound,
ast::MutMutable), ast::MutMutable),
&*f.decl, &*f.decl,
abi::Rust, abi::Rust,
@ -1092,15 +1101,19 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
def::DefTrait(trait_def_id) => { def::DefTrait(trait_def_id) => {
// N.B. this case overlaps somewhat with // N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details // TyObjectSum, see that fn for details
let mut projections = Vec::new(); // TODO let mut projection_bounds = Vec::new();
let trait_ref = ast_path_to_trait_ref(this, let trait_ref = ast_path_to_trait_ref(this,
rscope, rscope,
trait_def_id, trait_def_id,
None, None,
path, path,
Some(&mut projections)); Some(&mut projection_bounds));
let trait_ref = ty::Binder(trait_ref); let trait_ref = ty::Binder(trait_ref);
trait_ref_to_object_type(this, rscope, path.span, trait_ref, &[]) let projection_bounds = projection_bounds.into_iter()
.map(ty::Binder)
.collect();
trait_ref_to_object_type(this, rscope, path.span,
trait_ref, projection_bounds, &[])
} }
def::DefTy(did, _) | def::DefStruct(did) => { def::DefTy(did, _) | def::DefStruct(did) => {
ast_path_to_ty(this, rscope, did, path).ty ast_path_to_ty(this, rscope, did, path).ty
@ -1437,7 +1450,7 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>(
this: &AC, this: &AC,
unsafety: ast::Unsafety, unsafety: ast::Unsafety,
onceness: ast::Onceness, onceness: ast::Onceness,
bounds: ty::ExistentialBounds, bounds: ty::ExistentialBounds<'tcx>,
store: ty::TraitStore, store: ty::TraitStore,
decl: &ast::FnDecl, decl: &ast::FnDecl,
abi: abi::Abi, abi: abi::Abi,
@ -1500,14 +1513,15 @@ pub fn conv_existential_bounds<'tcx, AC: AstConv<'tcx>, RS:RegionScope>(
rscope: &RS, rscope: &RS,
span: Span, span: Span,
principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
ast_bounds: &[ast::TyParamBound]) ast_bounds: &[ast::TyParamBound])
-> ty::ExistentialBounds -> ty::ExistentialBounds<'tcx>
{ {
let partitioned_bounds = let partitioned_bounds =
partition_bounds(this.tcx(), span, ast_bounds); partition_bounds(this.tcx(), span, ast_bounds);
conv_existential_bounds_from_partitioned_bounds( conv_existential_bounds_from_partitioned_bounds(
this, rscope, span, principal_trait_ref, partitioned_bounds) this, rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds)
} }
fn conv_ty_poly_trait_ref<'tcx, AC, RS>( fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
@ -1520,14 +1534,14 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
{ {
let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]); let mut partitioned_bounds = partition_bounds(this.tcx(), span, ast_bounds[]);
let mut projections = Vec::new(); let mut projection_bounds = Vec::new();
let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) { let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
Some(trait_bound) => { Some(trait_bound) => {
let ptr = instantiate_poly_trait_ref(this, let ptr = instantiate_poly_trait_ref(this,
rscope, rscope,
trait_bound, trait_bound,
None, None,
&mut projections); &mut projection_bounds);
Some(ptr) Some(ptr)
} }
None => { None => {
@ -1538,13 +1552,12 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
} }
}; };
// TODO use projections somewhere
let bounds = let bounds =
conv_existential_bounds_from_partitioned_bounds(this, conv_existential_bounds_from_partitioned_bounds(this,
rscope, rscope,
span, span,
main_trait_bound.clone(), main_trait_bound.clone(),
projection_bounds,
partitioned_bounds); partitioned_bounds);
match main_trait_bound { match main_trait_bound {
@ -1558,8 +1571,9 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
rscope: &RS, rscope: &RS,
span: Span, span: Span,
principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
mut projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>, // Empty for boxed closures
partitioned_bounds: PartitionedBounds) partitioned_bounds: PartitionedBounds)
-> ty::ExistentialBounds -> ty::ExistentialBounds<'tcx>
where AC: AstConv<'tcx>, RS:RegionScope where AC: AstConv<'tcx>, RS:RegionScope
{ {
let PartitionedBounds { builtin_bounds, let PartitionedBounds { builtin_bounds,
@ -1582,9 +1596,12 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx, AC, RS>(
principal_trait_ref, principal_trait_ref,
builtin_bounds); builtin_bounds);
ty::sort_bounds_list(projection_bounds.as_mut_slice());
ty::ExistentialBounds { ty::ExistentialBounds {
region_bound: region_bound, region_bound: region_bound,
builtin_bounds: builtin_bounds, builtin_bounds: builtin_bounds,
projection_bounds: projection_bounds,
} }
} }

View file

@ -15,7 +15,6 @@ use middle::ty::{mod, HasProjectionTypes, Ty};
use middle::ty_fold::{mod, TypeFoldable, TypeFolder}; use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
use syntax::ast; use syntax::ast;
use syntax::codemap::Span; use syntax::codemap::Span;
use std::rc::Rc;
pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
fulfillment_cx: &mut FulfillmentContext<'tcx>, fulfillment_cx: &mut FulfillmentContext<'tcx>,

View file

@ -289,7 +289,7 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
(&ty::UniqTraitStore, _) => ast::Once, (&ty::UniqTraitStore, _) => ast::Once,
(&ty::RegionTraitStore(..), _) => ast::Many, (&ty::RegionTraitStore(..), _) => ast::Many,
}; };
(Some(sig), onceness, cenv.bounds) (Some(sig), onceness, cenv.bounds.clone())
} }
_ => { _ => {
// Not an error! Means we're inferring the closure type // Not an error! Means we're inferring the closure type

View file

@ -768,7 +768,7 @@ fn constrain_cast(rcx: &mut Rcx,
} }
/*From:*/ (_, /*From:*/ (_,
/*To: */ &ty::ty_trait(box ty::TyTrait { bounds, .. })) => { /*To: */ &ty::ty_trait(box ty::TyTrait { ref bounds, .. })) => {
// When T is existentially quantified as a trait // When T is existentially quantified as a trait
// `Foo+'to`, it must outlive the region bound `'to`. // `Foo+'to`, it must outlive the region bound `'to`.
type_must_outlive(rcx, infer::RelateObjectBound(cast_expr.span), type_must_outlive(rcx, infer::RelateObjectBound(cast_expr.span),
@ -851,7 +851,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
} }
match function_type.sty { match function_type.sty {
ty::ty_closure(box ty::ClosureTy {bounds, ..}) => { ty::ty_closure(box ty::ClosureTy {ref bounds, ..}) => {
ty::with_freevars(tcx, expr.id, |freevars| { ty::with_freevars(tcx, expr.id, |freevars| {
ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars); ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
}) })
@ -859,7 +859,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
ty::ty_unboxed_closure(_, region, _) => { ty::ty_unboxed_closure(_, region, _) => {
ty::with_freevars(tcx, expr.id, |freevars| { ty::with_freevars(tcx, expr.id, |freevars| {
let bounds = ty::region_existential_bound(*region); let bounds = ty::region_existential_bound(*region);
ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars); ensure_free_variable_types_outlive_closure_bound(rcx, &bounds, expr, freevars);
}) })
} }
_ => {} _ => {}
@ -870,7 +870,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
/// over values outliving the object's lifetime bound. /// over values outliving the object's lifetime bound.
fn ensure_free_variable_types_outlive_closure_bound( fn ensure_free_variable_types_outlive_closure_bound(
rcx: &mut Rcx, rcx: &mut Rcx,
bounds: ty::ExistentialBounds, bounds: &ty::ExistentialBounds,
expr: &ast::Expr, expr: &ast::Expr,
freevars: &[ty::Freevar]) freevars: &[ty::Freevar])
{ {

View file

@ -244,7 +244,7 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let object_trait_ty = let object_trait_ty =
ty::mk_trait(fcx.tcx(), ty::mk_trait(fcx.tcx(),
object_trait.principal.clone(), object_trait.principal.clone(),
object_trait.bounds); object_trait.bounds.clone());
debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}", debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
referent_ty.repr(fcx.tcx()), referent_ty.repr(fcx.tcx()),

View file

@ -500,13 +500,14 @@ impl Clean<TyParamBound> for ast::TyParamBound {
} }
} }
impl Clean<Vec<TyParamBound>> for ty::ExistentialBounds { impl<'tcx> Clean<Vec<TyParamBound>> for ty::ExistentialBounds<'tcx> {
fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> { fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
let mut vec = vec![]; let mut vec = vec![];
self.region_bound.clean(cx).map(|b| vec.push(RegionBound(b))); self.region_bound.clean(cx).map(|b| vec.push(RegionBound(b)));
for bb in self.builtin_bounds.iter() { for bb in self.builtin_bounds.iter() {
vec.push(bb.clean(cx)); vec.push(bb.clean(cx));
} }
// TODO projection bounds
vec vec
} }
} }
@ -1441,18 +1442,11 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
} }
} }
ty::ty_struct(did, substs) | ty::ty_struct(did, substs) |
ty::ty_enum(did, substs) | ty::ty_enum(did, substs) => {
ty::ty_trait(box ty::TyTrait {
principal: ty::Binder(ty::TraitRef { def_id: did, substs }),
.. }) =>
{
let fqn = csearch::get_item_path(cx.tcx(), did); let fqn = csearch::get_item_path(cx.tcx(), did);
let fqn: Vec<String> = fqn.into_iter().map(|i| { let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
i.to_string()
}).collect();
let kind = match self.sty { let kind = match self.sty {
ty::ty_struct(..) => TypeStruct, ty::ty_struct(..) => TypeStruct,
ty::ty_trait(..) => TypeTrait,
_ => TypeEnum, _ => TypeEnum,
}; };
let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(), let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
@ -1464,11 +1458,24 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
did: did, did: did,
} }
} }
ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
let did = principal.def_id();
let fqn = csearch::get_item_path(cx.tcx(), did);
let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
Some(did), principal.substs());
cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, TypeTrait));
ResolvedPath {
path: path,
typarams: Some(bounds.clean(cx)),
did: did,
}
}
ty::ty_tup(ref t) => Tuple(t.clean(cx)), ty::ty_tup(ref t) => Tuple(t.clean(cx)),
ty::ty_projection(ref data) => { ty::ty_projection(ref data) => {
let trait_ref = match data.trait_ref.clean(cx) { let trait_ref = match data.trait_ref.clean(cx) {
TyParamBound::TraitBound(t) => t, TyParamBound::TraitBound(t) => t.trait_,
TyParamBound::RegionBound(_) => panic!("cleaning a trait got a region??"), TyParamBound::RegionBound(_) => panic!("cleaning a trait got a region??"),
}; };
Type::QPath { Type::QPath {