parse_bounds(&mut st, conv)
}
-pub fn parse_existential_bounds_data(data: &[u8], crate_num: ast::CrateNum,
- pos: uint, tcx: &ty::ctxt, conv: conv_did)
- -> ty::ExistentialBounds {
+pub fn parse_existential_bounds_data<'tcx>(data: &[u8], crate_num: ast::CrateNum,
+ pos: uint, tcx: &ty::ctxt<'tcx>, conv: conv_did)
+ -> ty::ExistentialBounds<'tcx> {
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
parse_existential_bounds(&mut st, conv)
}
}
}
-fn parse_existential_bounds(st: &mut PState, conv: conv_did) -> ty::ExistentialBounds {
- let r = parse_region(st, |x,y| conv(x,y));
- let bb = parse_builtin_bounds(st, conv);
- return ty::ExistentialBounds { region_bound: r, builtin_bounds: bb };
+fn parse_existential_bounds<'a,'tcx>(st: &mut PState<'a,'tcx>,
+ conv: conv_did)
+ -> ty::ExistentialBounds<'tcx>
+{
+ 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 {
mywrite!(w, ".");
}
-pub fn enc_existential_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ExistentialBounds) {
- enc_region(w, cx, bs.region_bound);
- enc_builtin_bounds(w, cx, &bs.builtin_bounds);
+pub fn enc_existential_bounds<'a,'tcx>(w: &mut SeekableMemWriter,
+ cx: &ctxt<'a,'tcx>,
+ 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, ¶m_bounds);
}
pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
type_scheme: ty::TypeScheme<'tcx>);
fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, '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_auto_adjustment<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
adj: &ty::AutoAdjustment<'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>) {
self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this.writer,
&ecx.ty_str_ctxt(),
bounds)));
fn read_type_scheme<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::TypeScheme<'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>)
-> subst::Substs<'tcx>;
fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
}
fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
- -> ty::ExistentialBounds
+ -> ty::ExistentialBounds<'tcx>
{
self.read_opaque(|this, doc| {
Ok(tydecode::parse_existential_bounds_data(doc.data,
(&ty::ty_trait(..), &ty::ty_trait(..)) => {
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`?
- let ty = ty::mk_trait(tcx, principal.clone(), bounds);
- Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: (*principal).clone(),
- bounds: bounds },
+ let ty = ty::mk_trait(tcx, principal.clone(), bounds.clone());
+ Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: principal.clone(),
+ bounds: bounds.clone() },
ty_a)))
}
(&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
match a.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);
- // FIXME what is purpose of this type `tr`?
- let tr = ty::mk_trait(tcx, principal.clone(), bounds);
+ let tr = ty::mk_trait(tcx, principal.clone(), bounds.clone());
try!(self.subtype(mk_ty(tr), b));
Ok(Some(AdjustDerefRef(AutoDerefRef {
autoderefs: 1,
};
let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety));
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 abi = try!(self.abi(a.abi, b.abi));
Ok(ty::ClosureTy {
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,
- a: ty::ExistentialBounds,
- b: ty::ExistentialBounds)
- -> cres<'tcx, ty::ExistentialBounds>
+ a: &ty::ExistentialBounds<'tcx>,
+ b: &ty::ExistentialBounds<'tcx>)
+ -> cres<'tcx, ty::ExistentialBounds<'tcx>>
{
let r = try!(self.contraregions(a.region_bound, b.region_bound));
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,
- builtin_bounds: nb })
+ builtin_bounds: nb,
+ projection_bounds: pb })
}
fn builtin_bounds(&self,
}
}
+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> {
fn combine<C:Combine<'tcx>>(combiner: &C,
a: &ty::FnSig<'tcx>,
&ty::ty_trait(ref b_)) => {
debug!("Trying to match traits {} and {}", a, b);
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))
}
}
(&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
- if a_data.item_name == b_data.item_name {
- let trait_ref = try!(this.trait_refs(&*a_data.trait_ref, &*b_data.trait_ref));
- Ok(ty::mk_projection(tcx, Rc::new(trait_ref), a_data.item_name))
- } else {
- Err(ty::terr_sorts(expected_found(this, a, b)))
- }
+ let projection_ty = try!(this.projection_tys(a_data, b_data));
+ Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
}
_ => Err(ty::terr_sorts(expected_found(this, a, b)))
fn type_of_autoref<'tcx>(cx: &ctxt<'tcx>, autoref: &AutoRef<'tcx>) -> Option<Ty<'tcx>> {
match autoref {
&AutoUnsize(ref k) => match k {
- &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
- Some(mk_trait(cx, (*principal).clone(), bounds))
+ &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
+ Some(mk_trait(cx, principal.clone(), bounds.clone()))
}
_ => None
},
&AutoUnsizeUniq(ref k) => match k {
- &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
- Some(mk_uniq(cx, mk_trait(cx, (*principal).clone(), bounds)))
+ &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
+ Some(mk_uniq(cx, mk_trait(cx, principal.clone(), bounds.clone())))
}
_ => None
},
pub unsafety: ast::Unsafety,
pub onceness: ast::Onceness,
pub store: TraitStore,
- pub bounds: ExistentialBounds,
+ pub bounds: ExistentialBounds<'tcx>,
pub sig: PolyFnSig<'tcx>,
pub abi: abi::Abi,
}
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
pub struct TyTrait<'tcx> {
pub principal: ty::PolyTraitRef<'tcx>,
- pub bounds: ExistentialBounds
+ pub bounds: ExistentialBounds<'tcx>,
}
impl<'tcx> TyTrait<'tcx> {
terr_builtin_bounds(expected_found<BuiltinBounds>),
terr_variadic_mismatch(expected_found<bool>),
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>`
/// major difference between this case and `ParamBounds` is that
/// general purpose trait bounds are omitted and there must be
/// *exactly one* region.
-#[deriving(Copy, PartialEq, Eq, Hash, Clone, Show)]
-pub struct ExistentialBounds {
+#[deriving(PartialEq, Eq, Hash, Clone, Show)]
+pub struct ExistentialBounds<'tcx> {
pub region_bound: ty::Region,
- pub builtin_bounds: BuiltinBounds
+ pub builtin_bounds: BuiltinBounds,
+ pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>,
}
pub type BuiltinBounds = EnumSet<BuiltinBound>;
}
/// 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,
- builtin_bounds: empty_builtin_bounds() }
+ builtin_bounds: empty_builtin_bounds(),
+ projection_bounds: Vec::new() }
}
impl CLike for BuiltinBound {
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)]
pub struct ProjectionTy<'tcx> {
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
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> {
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
}
pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
principal: ty::PolyTraitRef<'tcx>,
- bounds: ExistentialBounds)
- -> Ty<'tcx> {
+ bounds: ExistentialBounds<'tcx>)
+ -> Ty<'tcx>
+{
+ assert!(bound_list_is_sorted(bounds.projection_bounds.as_slice()));
+
let inner = box TyTrait {
principal: principal,
bounds: bounds
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>,
trait_ref: Rc<ty::TraitRef<'tcx>>,
item_name: ast::Name)
}
}
- ty_trait(box TyTrait { bounds, .. }) => {
+ ty_trait(box TyTrait { ref bounds, .. }) => {
object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
}
fn closure_contents(cty: &ClosureTy) -> TypeContents {
// Closure contents are just like trait contents, but with potentially
// even more stuff.
- let st = object_contents(cty.bounds);
+ let st = object_contents(&cty.bounds);
let st = match cty.store {
UniqTraitStore => {
st
}
- fn object_contents(bounds: ExistentialBounds) -> TypeContents {
+ fn object_contents(bounds: &ExistentialBounds) -> TypeContents {
// These are the type contents of the (opaque) interior. We
// make no assumptions (other than that it cannot have an
// in-scope type parameter within, which makes no sense).
let bounds = ty::ExistentialBounds {
region_bound: ReStatic,
builtin_bounds: all_builtin_bounds(),
+ projection_bounds: vec!(),
};
ty::mk_closure(
format!("UnsizeStruct with bad sty: {}",
ty_to_string(cx, ty))[])
},
- &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
- mk_trait(cx, (*principal).clone(), bounds)
+ &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
+ mk_trait(cx, principal.clone(), bounds.clone())
}
}
}
if values.expected { "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)
+ }
}
}
super_fold_trait_store(self, s)
}
- fn fold_existential_bounds(&mut self, s: ty::ExistentialBounds)
- -> ty::ExistentialBounds {
+ fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
+ -> ty::ExistentialBounds<'tcx> {
super_fold_existential_bounds(self, s)
}
}
}
-impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds {
- fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds {
- folder.fold_existential_bounds(*self)
+impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
+ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds<'tcx> {
+ folder.fold_existential_bounds(self)
}
}
match *self {
ty::UnsizeLength(len) => ty::UnsizeLength(len),
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::TyTrait {
principal: principal.fold_with(folder),
let substs = substs.fold_with(this);
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 {
- principal: (*principal).fold_with(this),
+ principal: principal.fold_with(this),
bounds: bounds.fold_with(this),
})
}
}
}
-pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
- bounds: ty::ExistentialBounds)
- -> ty::ExistentialBounds {
+pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
+ this: &mut T,
+ bounds: &ty::ExistentialBounds<'tcx>)
+ -> ty::ExistentialBounds<'tcx>
+{
ty::ExistentialBounds {
region_bound: bounds.region_bound.fold_with(this),
builtin_bounds: bounds.builtin_bounds,
+ projection_bounds: bounds.projection_bounds.fold_with(this),
}
}
}
}
-impl<'tcx> Repr<'tcx> for ty::ExistentialBounds {
- fn repr(&self, tcx: &ctxt) -> String {
+impl<'tcx> Repr<'tcx> for ty::ExistentialBounds<'tcx> {
+ fn repr(&self, tcx: &ctxt<'tcx>) -> String {
self.user_string(tcx)
}
}
}
}
-impl<'tcx> UserString<'tcx> for ty::ExistentialBounds {
- fn user_string(&self, tcx: &ctxt) -> String {
+impl<'tcx> UserString<'tcx> for ty::ExistentialBounds<'tcx> {
+ fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
if self.builtin_bounds.contains(&ty::BoundSend) &&
self.region_bound == ty::ReStatic
{ // Region bound is implied by builtin bounds:
}
}
+type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
+
fn ast_ty_to_trait_ref<'tcx,AC,RS>(this: &AC,
rscope: &RS,
ty: &ast::Ty,
bounds: &[ast::TyParamBound])
- -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
+ -> Result<TraitAndProjections<'tcx>, ErrorReported>
where AC : AstConv<'tcx>, RS : RegionScope
{
/*!
ast::TyPath(ref path, id) => {
match this.tcx().def_map.borrow().get(&id) {
Some(&def::DefTrait(trait_def_id)) => {
- // TODO do something with this
- let mut projections = Vec::new();
- Ok(ty::Binder(ast_path_to_trait_ref(this,
- rscope,
- trait_def_id,
- None,
- path,
- Some(&mut projections))))
+ let mut projection_bounds = Vec::new();
+ let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
+ rscope,
+ trait_def_id,
+ None,
+ path,
+ Some(&mut projection_bounds)));
+ 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");
rscope: &RS,
span: Span,
trait_ref: ty::PolyTraitRef<'tcx>,
+ projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
bounds: &[ast::TyParamBound])
-> Ty<'tcx>
where AC : AstConv<'tcx>, RS : RegionScope
rscope,
span,
Some(trait_ref.clone()),
+ projection_bounds,
bounds);
let result = ty::mk_trait(this.tcx(), trait_ref, existential_bounds);
}
ast::TyObjectSum(ref ty, ref 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, bounds[])
+ trait_ref, projection_bounds, bounds[])
}
Err(ErrorReported) => {
this.tcx().types.err
rscope,
ast_ty.span,
None,
+ Vec::new(),
f.bounds.as_slice());
+ let region_bound = bounds.region_bound;
let fn_decl = ty_of_closure(this,
f.unsafety,
f.onceness,
bounds,
ty::RegionTraitStore(
- bounds.region_bound,
+ region_bound,
ast::MutMutable),
&*f.decl,
abi::Rust,
def::DefTrait(trait_def_id) => {
// N.B. this case overlaps somewhat with
// 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,
rscope,
trait_def_id,
None,
path,
- Some(&mut projections));
+ Some(&mut projection_bounds));
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) => {
ast_path_to_ty(this, rscope, did, path).ty
this: &AC,
unsafety: ast::Unsafety,
onceness: ast::Onceness,
- bounds: ty::ExistentialBounds,
+ bounds: ty::ExistentialBounds<'tcx>,
store: ty::TraitStore,
decl: &ast::FnDecl,
abi: abi::Abi,
rscope: &RS,
span: Span,
principal_trait_ref: Option<ty::PolyTraitRef<'tcx>>, // None for boxed closures
+ projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
ast_bounds: &[ast::TyParamBound])
- -> ty::ExistentialBounds
+ -> ty::ExistentialBounds<'tcx>
{
let partitioned_bounds =
partition_bounds(this.tcx(), span, ast_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>(
{
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) {
Some(trait_bound) => {
let ptr = instantiate_poly_trait_ref(this,
rscope,
trait_bound,
None,
- &mut projections);
+ &mut projection_bounds);
Some(ptr)
}
None => {
}
};
- // TODO use projections somewhere
-
let bounds =
conv_existential_bounds_from_partitioned_bounds(this,
rscope,
span,
main_trait_bound.clone(),
+ projection_bounds,
partitioned_bounds);
match main_trait_bound {
rscope: &RS,
span: Span,
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)
- -> ty::ExistentialBounds
+ -> ty::ExistentialBounds<'tcx>
where AC: AstConv<'tcx>, RS:RegionScope
{
let PartitionedBounds { builtin_bounds,
principal_trait_ref,
builtin_bounds);
+ ty::sort_bounds_list(projection_bounds.as_mut_slice());
+
ty::ExistentialBounds {
region_bound: region_bound,
builtin_bounds: builtin_bounds,
+ projection_bounds: projection_bounds,
}
}
use middle::ty_fold::{mod, TypeFoldable, TypeFolder};
use syntax::ast;
use syntax::codemap::Span;
-use std::rc::Rc;
pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
fulfillment_cx: &mut FulfillmentContext<'tcx>,
(&ty::UniqTraitStore, _) => ast::Once,
(&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
}
/*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
// `Foo+'to`, it must outlive the region bound `'to`.
type_must_outlive(rcx, infer::RelateObjectBound(cast_expr.span),
}
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| {
ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
})
ty::ty_unboxed_closure(_, region, _) => {
ty::with_freevars(tcx, expr.id, |freevars| {
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);
})
}
_ => {}
/// over values outliving the object's lifetime bound.
fn ensure_free_variable_types_outlive_closure_bound(
rcx: &mut Rcx,
- bounds: ty::ExistentialBounds,
+ bounds: &ty::ExistentialBounds,
expr: &ast::Expr,
freevars: &[ty::Freevar])
{
let object_trait_ty =
ty::mk_trait(fcx.tcx(),
object_trait.principal.clone(),
- object_trait.bounds);
+ object_trait.bounds.clone());
debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
referent_ty.repr(fcx.tcx()),
}
}
-impl Clean<Vec<TyParamBound>> for ty::ExistentialBounds {
+impl<'tcx> Clean<Vec<TyParamBound>> for ty::ExistentialBounds<'tcx> {
fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
let mut vec = vec![];
self.region_bound.clean(cx).map(|b| vec.push(RegionBound(b)));
for bb in self.builtin_bounds.iter() {
vec.push(bb.clean(cx));
}
+ // TODO projection bounds
vec
}
}
}
}
ty::ty_struct(did, substs) |
- ty::ty_enum(did, substs) |
- ty::ty_trait(box ty::TyTrait {
- principal: ty::Binder(ty::TraitRef { def_id: did, substs }),
- .. }) =>
- {
+ ty::ty_enum(did, substs) => {
let fqn = csearch::get_item_path(cx.tcx(), did);
- let fqn: Vec<String> = fqn.into_iter().map(|i| {
- i.to_string()
- }).collect();
+ let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
let kind = match self.sty {
ty::ty_struct(..) => TypeStruct,
- ty::ty_trait(..) => TypeTrait,
_ => TypeEnum,
};
let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
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_projection(ref data) => {
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??"),
};
Type::QPath {