rollup merge of #18506 : nikomatsakis/assoc-type-bounds
This commit is contained in:
commit
eb793616dc
25 changed files with 519 additions and 433 deletions
|
@ -79,7 +79,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
|
||||||
e::IIForeignRef(i) => i.id,
|
e::IIForeignRef(i) => i.id,
|
||||||
e::IITraitItemRef(_, &ast::ProvidedMethod(ref m)) => m.id,
|
e::IITraitItemRef(_, &ast::ProvidedMethod(ref m)) => m.id,
|
||||||
e::IITraitItemRef(_, &ast::RequiredMethod(ref m)) => m.id,
|
e::IITraitItemRef(_, &ast::RequiredMethod(ref m)) => m.id,
|
||||||
e::IITraitItemRef(_, &ast::TypeTraitItem(ref ti)) => ti.id,
|
e::IITraitItemRef(_, &ast::TypeTraitItem(ref ti)) => ti.ty_param.id,
|
||||||
e::IIImplItemRef(_, &ast::MethodImplItem(ref m)) => m.id,
|
e::IIImplItemRef(_, &ast::MethodImplItem(ref m)) => m.id,
|
||||||
e::IIImplItemRef(_, &ast::TypeImplItem(ref ti)) => ti.id,
|
e::IIImplItemRef(_, &ast::TypeImplItem(ref ti)) => ti.id,
|
||||||
};
|
};
|
||||||
|
@ -154,7 +154,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
|
||||||
match *ti {
|
match *ti {
|
||||||
ast::ProvidedMethod(ref m) => m.pe_ident(),
|
ast::ProvidedMethod(ref m) => m.pe_ident(),
|
||||||
ast::RequiredMethod(ref ty_m) => ty_m.ident,
|
ast::RequiredMethod(ref ty_m) => ty_m.ident,
|
||||||
ast::TypeTraitItem(ref ti) => ti.ident,
|
ast::TypeTraitItem(ref ti) => ti.ty_param.ident,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ast::IIImplItem(_, ref m) => {
|
ast::IIImplItem(_, ref m) => {
|
||||||
|
@ -709,8 +709,9 @@ impl<'a> vtable_decoder_helpers for reader::Decoder<'a> {
|
||||||
{
|
{
|
||||||
let types = self.read_to_vec(|this| Ok(f(this))).unwrap();
|
let types = self.read_to_vec(|this| Ok(f(this))).unwrap();
|
||||||
let selfs = self.read_to_vec(|this| Ok(f(this))).unwrap();
|
let selfs = self.read_to_vec(|this| Ok(f(this))).unwrap();
|
||||||
|
let assocs = self.read_to_vec(|this| Ok(f(this))).unwrap();
|
||||||
let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
|
let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
|
||||||
VecPerParamSpace::new(types, selfs, fns)
|
VecPerParamSpace::new(types, selfs, assocs, fns)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_vtable_res_with_key(&mut self,
|
fn read_vtable_res_with_key(&mut self,
|
||||||
|
|
|
@ -296,8 +296,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
|
||||||
self.exported_items.insert(m.id);
|
self.exported_items.insert(m.id);
|
||||||
}
|
}
|
||||||
ast::TypeTraitItem(ref t) => {
|
ast::TypeTraitItem(ref t) => {
|
||||||
debug!("typedef {}", t.id);
|
debug!("typedef {}", t.ty_param.id);
|
||||||
self.exported_items.insert(t.id);
|
self.exported_items.insert(t.ty_param.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1564,19 +1564,19 @@ impl<'a> Resolver<'a> {
|
||||||
}
|
}
|
||||||
ast::TypeTraitItem(ref associated_type) => {
|
ast::TypeTraitItem(ref associated_type) => {
|
||||||
let def = DefAssociatedTy(local_def(
|
let def = DefAssociatedTy(local_def(
|
||||||
associated_type.id));
|
associated_type.ty_param.id));
|
||||||
|
|
||||||
let name_bindings =
|
let name_bindings =
|
||||||
self.add_child(associated_type.ident.name,
|
self.add_child(associated_type.ty_param.ident.name,
|
||||||
module_parent.clone(),
|
module_parent.clone(),
|
||||||
ForbidDuplicateTypesAndValues,
|
ForbidDuplicateTypesAndValues,
|
||||||
associated_type.span);
|
associated_type.ty_param.span);
|
||||||
// NB: not IMPORTABLE
|
// NB: not IMPORTABLE
|
||||||
name_bindings.define_type(def,
|
name_bindings.define_type(def,
|
||||||
associated_type.span,
|
associated_type.ty_param.span,
|
||||||
PUBLIC);
|
PUBLIC);
|
||||||
|
|
||||||
(associated_type.ident.name, TypeTraitItemKind)
|
(associated_type.ty_param.ident.name, TypeTraitItemKind)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4223,7 +4223,7 @@ impl<'a> Resolver<'a> {
|
||||||
impl_items.as_slice());
|
impl_items.as_slice());
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemTrait(ref generics, ref unbound, ref bounds, ref methods) => {
|
ItemTrait(ref generics, ref unbound, ref bounds, ref trait_items) => {
|
||||||
// Create a new rib for the self type.
|
// Create a new rib for the self type.
|
||||||
let mut self_type_rib = Rib::new(ItemRibKind);
|
let mut self_type_rib = Rib::new(ItemRibKind);
|
||||||
|
|
||||||
|
@ -4251,13 +4251,13 @@ impl<'a> Resolver<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
for method in (*methods).iter() {
|
for trait_item in (*trait_items).iter() {
|
||||||
// Create a new rib for the method-specific type
|
// Create a new rib for the trait_item-specific type
|
||||||
// parameters.
|
// parameters.
|
||||||
//
|
//
|
||||||
// FIXME #4951: Do we need a node ID here?
|
// FIXME #4951: Do we need a node ID here?
|
||||||
|
|
||||||
match *method {
|
match *trait_item {
|
||||||
ast::RequiredMethod(ref ty_m) => {
|
ast::RequiredMethod(ref ty_m) => {
|
||||||
this.with_type_parameter_rib
|
this.with_type_parameter_rib
|
||||||
(HasTypeParameters(&ty_m.generics,
|
(HasTypeParameters(&ty_m.generics,
|
||||||
|
@ -4292,8 +4292,9 @@ impl<'a> Resolver<'a> {
|
||||||
ProvidedMethod(m.id)),
|
ProvidedMethod(m.id)),
|
||||||
&**m)
|
&**m)
|
||||||
}
|
}
|
||||||
ast::TypeTraitItem(_) => {
|
ast::TypeTraitItem(ref data) => {
|
||||||
visit::walk_trait_item(this, method);
|
this.resolve_type_parameter(&data.ty_param);
|
||||||
|
visit::walk_trait_item(this, trait_item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4482,6 +4483,12 @@ impl<'a> Resolver<'a> {
|
||||||
fn resolve_type_parameters(&mut self,
|
fn resolve_type_parameters(&mut self,
|
||||||
type_parameters: &OwnedSlice<TyParam>) {
|
type_parameters: &OwnedSlice<TyParam>) {
|
||||||
for type_parameter in type_parameters.iter() {
|
for type_parameter in type_parameters.iter() {
|
||||||
|
self.resolve_type_parameter(type_parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_type_parameter(&mut self,
|
||||||
|
type_parameter: &TyParam) {
|
||||||
for bound in type_parameter.bounds.iter() {
|
for bound in type_parameter.bounds.iter() {
|
||||||
self.resolve_type_parameter_bound(type_parameter.id, bound,
|
self.resolve_type_parameter_bound(type_parameter.id, bound,
|
||||||
TraitBoundingTypeParameter);
|
TraitBoundingTypeParameter);
|
||||||
|
@ -4497,7 +4504,6 @@ impl<'a> Resolver<'a> {
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_type_parameter_bounds(&mut self,
|
fn resolve_type_parameter_bounds(&mut self,
|
||||||
id: NodeId,
|
id: NodeId,
|
||||||
|
|
|
@ -86,7 +86,7 @@ impl<'v> Visitor<'v> for Annotator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeTraitItem(ref typedef) => (typedef.id, &typedef.attrs),
|
TypeTraitItem(ref typedef) => (typedef.ty_param.id, &typedef.attrs),
|
||||||
};
|
};
|
||||||
self.annotate(id, attrs, |v| visit::walk_trait_item(v, t));
|
self.annotate(id, attrs, |v| visit::walk_trait_item(v, t));
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,17 +56,18 @@ impl Substs {
|
||||||
r: Vec<ty::Region>)
|
r: Vec<ty::Region>)
|
||||||
-> Substs
|
-> Substs
|
||||||
{
|
{
|
||||||
Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()),
|
Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new(), Vec::new()),
|
||||||
VecPerParamSpace::new(r, Vec::new(), Vec::new()))
|
VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_trait(t: Vec<ty::t>,
|
pub fn new_trait(t: Vec<ty::t>,
|
||||||
r: Vec<ty::Region>,
|
r: Vec<ty::Region>,
|
||||||
|
a: Vec<ty::t>,
|
||||||
s: ty::t)
|
s: ty::t)
|
||||||
-> Substs
|
-> Substs
|
||||||
{
|
{
|
||||||
Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()),
|
Substs::new(VecPerParamSpace::new(t, vec!(s), a, Vec::new()),
|
||||||
VecPerParamSpace::new(r, Vec::new(), Vec::new()))
|
VecPerParamSpace::new(r, Vec::new(), Vec::new(), Vec::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn erased(t: VecPerParamSpace<ty::t>) -> Substs
|
pub fn erased(t: VecPerParamSpace<ty::t>) -> Substs
|
||||||
|
@ -172,19 +173,21 @@ impl RegionSubsts {
|
||||||
pub enum ParamSpace {
|
pub enum ParamSpace {
|
||||||
TypeSpace, // Type parameters attached to a type definition, trait, or impl
|
TypeSpace, // Type parameters attached to a type definition, trait, or impl
|
||||||
SelfSpace, // Self parameter on a trait
|
SelfSpace, // Self parameter on a trait
|
||||||
|
AssocSpace, // Assoc types defined in a trait/impl
|
||||||
FnSpace, // Type parameters attached to a method or fn
|
FnSpace, // Type parameters attached to a method or fn
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParamSpace {
|
impl ParamSpace {
|
||||||
pub fn all() -> [ParamSpace, ..3] {
|
pub fn all() -> [ParamSpace, ..4] {
|
||||||
[TypeSpace, SelfSpace, FnSpace]
|
[TypeSpace, SelfSpace, AssocSpace, FnSpace]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_uint(self) -> uint {
|
pub fn to_uint(self) -> uint {
|
||||||
match self {
|
match self {
|
||||||
TypeSpace => 0,
|
TypeSpace => 0,
|
||||||
SelfSpace => 1,
|
SelfSpace => 1,
|
||||||
FnSpace => 2,
|
AssocSpace => 2,
|
||||||
|
FnSpace => 3,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +195,8 @@ impl ParamSpace {
|
||||||
match u {
|
match u {
|
||||||
0 => TypeSpace,
|
0 => TypeSpace,
|
||||||
1 => SelfSpace,
|
1 => SelfSpace,
|
||||||
2 => FnSpace,
|
2 => AssocSpace,
|
||||||
|
3 => FnSpace,
|
||||||
_ => panic!("Invalid ParamSpace: {}", u)
|
_ => panic!("Invalid ParamSpace: {}", u)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,14 +216,27 @@ pub struct VecPerParamSpace<T> {
|
||||||
// Here is how the representation corresponds to the abstraction
|
// Here is how the representation corresponds to the abstraction
|
||||||
// i.e. the "abstraction function" AF:
|
// i.e. the "abstraction function" AF:
|
||||||
//
|
//
|
||||||
// AF(self) = (self.content.slice_to(self.type_limit),
|
// AF(self) = (self.content[..self.type_limit],
|
||||||
// self.content.slice(self.type_limit, self.self_limit),
|
// self.content[self.type_limit..self.self_limit],
|
||||||
// self.content.slice_from(self.self_limit))
|
// self.content[self.self_limit..self.assoc_limit],
|
||||||
|
// self.content[self.assoc_limit..])
|
||||||
type_limit: uint,
|
type_limit: uint,
|
||||||
self_limit: uint,
|
self_limit: uint,
|
||||||
|
assoc_limit: uint,
|
||||||
content: Vec<T>,
|
content: Vec<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The `split` function converts one `VecPerParamSpace` into this
|
||||||
|
* `SeparateVecsPerParamSpace` structure.
|
||||||
|
*/
|
||||||
|
pub struct SeparateVecsPerParamSpace<T> {
|
||||||
|
pub types: Vec<T>,
|
||||||
|
pub selfs: Vec<T>,
|
||||||
|
pub assocs: Vec<T>,
|
||||||
|
pub fns: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<T:fmt::Show> fmt::Show for VecPerParamSpace<T> {
|
impl<T:fmt::Show> fmt::Show for VecPerParamSpace<T> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
try!(write!(fmt, "VecPerParamSpace {{"));
|
try!(write!(fmt, "VecPerParamSpace {{"));
|
||||||
|
@ -236,7 +253,8 @@ impl<T> VecPerParamSpace<T> {
|
||||||
match space {
|
match space {
|
||||||
TypeSpace => (0, self.type_limit),
|
TypeSpace => (0, self.type_limit),
|
||||||
SelfSpace => (self.type_limit, self.self_limit),
|
SelfSpace => (self.type_limit, self.self_limit),
|
||||||
FnSpace => (self.self_limit, self.content.len()),
|
AssocSpace => (self.self_limit, self.assoc_limit),
|
||||||
|
FnSpace => (self.assoc_limit, self.content.len()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,6 +262,7 @@ impl<T> VecPerParamSpace<T> {
|
||||||
VecPerParamSpace {
|
VecPerParamSpace {
|
||||||
type_limit: 0,
|
type_limit: 0,
|
||||||
self_limit: 0,
|
self_limit: 0,
|
||||||
|
assoc_limit: 0,
|
||||||
content: Vec::new()
|
content: Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,26 +273,33 @@ impl<T> VecPerParamSpace<T> {
|
||||||
|
|
||||||
/// `t` is the type space.
|
/// `t` is the type space.
|
||||||
/// `s` is the self space.
|
/// `s` is the self space.
|
||||||
|
/// `a` is the assoc space.
|
||||||
/// `f` is the fn space.
|
/// `f` is the fn space.
|
||||||
pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
|
pub fn new(t: Vec<T>, s: Vec<T>, a: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
|
||||||
let type_limit = t.len();
|
let type_limit = t.len();
|
||||||
let self_limit = t.len() + s.len();
|
let self_limit = type_limit + s.len();
|
||||||
|
let assoc_limit = self_limit + a.len();
|
||||||
|
|
||||||
let mut content = t;
|
let mut content = t;
|
||||||
content.extend(s.into_iter());
|
content.extend(s.into_iter());
|
||||||
|
content.extend(a.into_iter());
|
||||||
content.extend(f.into_iter());
|
content.extend(f.into_iter());
|
||||||
|
|
||||||
VecPerParamSpace {
|
VecPerParamSpace {
|
||||||
type_limit: type_limit,
|
type_limit: type_limit,
|
||||||
self_limit: self_limit,
|
self_limit: self_limit,
|
||||||
|
assoc_limit: assoc_limit,
|
||||||
content: content,
|
content: content,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_internal(content: Vec<T>, type_limit: uint, self_limit: uint)
|
fn new_internal(content: Vec<T>, type_limit: uint, self_limit: uint, assoc_limit: uint)
|
||||||
-> VecPerParamSpace<T>
|
-> VecPerParamSpace<T>
|
||||||
{
|
{
|
||||||
VecPerParamSpace {
|
VecPerParamSpace {
|
||||||
type_limit: type_limit,
|
type_limit: type_limit,
|
||||||
self_limit: self_limit,
|
self_limit: self_limit,
|
||||||
|
assoc_limit: assoc_limit,
|
||||||
content: content,
|
content: content,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,8 +311,9 @@ impl<T> VecPerParamSpace<T> {
|
||||||
pub fn push(&mut self, space: ParamSpace, value: T) {
|
pub fn push(&mut self, space: ParamSpace, value: T) {
|
||||||
let (_, limit) = self.limits(space);
|
let (_, limit) = self.limits(space);
|
||||||
match space {
|
match space {
|
||||||
TypeSpace => { self.type_limit += 1; self.self_limit += 1; }
|
TypeSpace => { self.type_limit += 1; self.self_limit += 1; self.assoc_limit += 1; }
|
||||||
SelfSpace => { self.self_limit += 1; }
|
SelfSpace => { self.self_limit += 1; self.assoc_limit += 1; }
|
||||||
|
AssocSpace => { self.assoc_limit += 1; }
|
||||||
FnSpace => { }
|
FnSpace => { }
|
||||||
}
|
}
|
||||||
self.content.insert(limit, value);
|
self.content.insert(limit, value);
|
||||||
|
@ -298,8 +325,9 @@ impl<T> VecPerParamSpace<T> {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
match space {
|
match space {
|
||||||
TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; }
|
TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; self.assoc_limit -= 1; }
|
||||||
SelfSpace => { self.self_limit -= 1; }
|
SelfSpace => { self.self_limit -= 1; self.assoc_limit -= 1; }
|
||||||
|
AssocSpace => { self.assoc_limit -= 1; }
|
||||||
FnSpace => {}
|
FnSpace => {}
|
||||||
}
|
}
|
||||||
self.content.remove(limit - 1)
|
self.content.remove(limit - 1)
|
||||||
|
@ -386,35 +414,35 @@ impl<T> VecPerParamSpace<T> {
|
||||||
let result = self.iter().map(pred).collect();
|
let result = self.iter().map(pred).collect();
|
||||||
VecPerParamSpace::new_internal(result,
|
VecPerParamSpace::new_internal(result,
|
||||||
self.type_limit,
|
self.type_limit,
|
||||||
self.self_limit)
|
self.self_limit,
|
||||||
|
self.assoc_limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn map_move<U>(self, pred: |T| -> U) -> VecPerParamSpace<U> {
|
pub fn map_move<U>(self, pred: |T| -> U) -> VecPerParamSpace<U> {
|
||||||
let (t, s, f) = self.split();
|
let SeparateVecsPerParamSpace {
|
||||||
|
types: t,
|
||||||
|
selfs: s,
|
||||||
|
assocs: a,
|
||||||
|
fns: f
|
||||||
|
} = self.split();
|
||||||
|
|
||||||
VecPerParamSpace::new(t.into_iter().map(|p| pred(p)).collect(),
|
VecPerParamSpace::new(t.into_iter().map(|p| pred(p)).collect(),
|
||||||
s.into_iter().map(|p| pred(p)).collect(),
|
s.into_iter().map(|p| pred(p)).collect(),
|
||||||
|
a.into_iter().map(|p| pred(p)).collect(),
|
||||||
f.into_iter().map(|p| pred(p)).collect())
|
f.into_iter().map(|p| pred(p)).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split(self) -> (Vec<T>, Vec<T>, Vec<T>) {
|
pub fn split(self) -> SeparateVecsPerParamSpace<T> {
|
||||||
// FIXME (#15418): this does two traversals when in principle
|
let VecPerParamSpace { type_limit, self_limit, assoc_limit, content } = self;
|
||||||
// one would suffice. i.e. change to use `move_iter`.
|
|
||||||
let VecPerParamSpace { type_limit, self_limit, content } = self;
|
|
||||||
let mut i = 0;
|
|
||||||
let (prefix, fn_vec) = content.partition(|_| {
|
|
||||||
let on_left = i < self_limit;
|
|
||||||
i += 1;
|
|
||||||
on_left
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut i = 0;
|
let mut content_iter = content.into_iter();
|
||||||
let (type_vec, self_vec) = prefix.partition(|_| {
|
|
||||||
let on_left = i < type_limit;
|
|
||||||
i += 1;
|
|
||||||
on_left
|
|
||||||
});
|
|
||||||
|
|
||||||
(type_vec, self_vec, fn_vec)
|
SeparateVecsPerParamSpace {
|
||||||
|
types: content_iter.by_ref().take(type_limit).collect(),
|
||||||
|
selfs: content_iter.by_ref().take(self_limit - type_limit).collect(),
|
||||||
|
assocs: content_iter.by_ref().take(assoc_limit - self_limit).collect(),
|
||||||
|
fns: content_iter.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
|
pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
|
||||||
|
@ -560,12 +588,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
||||||
this.tcx().sess.span_bug(
|
this.tcx().sess.span_bug(
|
||||||
span,
|
span,
|
||||||
format!("Type parameter `{}` ({}/{}/{}) out of range \
|
format!("Type parameter `{}` ({}/{}/{}) out of range \
|
||||||
when substituting (root type={})",
|
when substituting (root type={}) substs={}",
|
||||||
p.repr(this.tcx()),
|
p.repr(this.tcx()),
|
||||||
source_ty.repr(this.tcx()),
|
source_ty.repr(this.tcx()),
|
||||||
space,
|
space,
|
||||||
index,
|
index,
|
||||||
this.root_ty.repr(this.tcx())).as_slice());
|
this.root_ty.repr(this.tcx()),
|
||||||
|
this.substs.repr(this.tcx())).as_slice());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1618,7 +1618,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
Ok(o) => o,
|
Ok(o) => o,
|
||||||
Err(ErrorReported) => Vec::new()
|
Err(ErrorReported) => Vec::new()
|
||||||
};
|
};
|
||||||
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
|
let obligations = VecPerParamSpace::new(obligations, Vec::new(),
|
||||||
|
Vec::new(), Vec::new());
|
||||||
VtableBuiltinData { nested: obligations }
|
VtableBuiltinData { nested: obligations }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1693,6 +1694,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
vec![arguments_tuple.subst(self.tcx(), substs),
|
vec![arguments_tuple.subst(self.tcx(), substs),
|
||||||
new_signature.output.unwrap().subst(self.tcx(), substs)],
|
new_signature.output.unwrap().subst(self.tcx(), substs)],
|
||||||
vec![],
|
vec![],
|
||||||
|
vec![],
|
||||||
obligation.self_ty())
|
obligation.self_ty())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,12 @@ pub fn trans_static_method_callee(bcx: Block,
|
||||||
// type parameters that belong to the trait but also some that
|
// type parameters that belong to the trait but also some that
|
||||||
// belong to the method:
|
// belong to the method:
|
||||||
let rcvr_substs = node_id_substs(bcx, ExprId(expr_id));
|
let rcvr_substs = node_id_substs(bcx, ExprId(expr_id));
|
||||||
let (rcvr_type, rcvr_self, rcvr_method) = rcvr_substs.types.split();
|
let subst::SeparateVecsPerParamSpace {
|
||||||
|
types: rcvr_type,
|
||||||
|
selfs: rcvr_self,
|
||||||
|
assocs: rcvr_assoc,
|
||||||
|
fns: rcvr_method
|
||||||
|
} = rcvr_substs.types.split();
|
||||||
|
|
||||||
// Lookup the precise impl being called. To do that, we need to
|
// Lookup the precise impl being called. To do that, we need to
|
||||||
// create a trait reference identifying the self type and other
|
// create a trait reference identifying the self type and other
|
||||||
|
@ -232,6 +237,7 @@ pub fn trans_static_method_callee(bcx: Block,
|
||||||
let trait_substs =
|
let trait_substs =
|
||||||
Substs::erased(VecPerParamSpace::new(rcvr_type,
|
Substs::erased(VecPerParamSpace::new(rcvr_type,
|
||||||
rcvr_self,
|
rcvr_self,
|
||||||
|
rcvr_assoc,
|
||||||
Vec::new()));
|
Vec::new()));
|
||||||
debug!("trait_substs={}", trait_substs.repr(bcx.tcx()));
|
debug!("trait_substs={}", trait_substs.repr(bcx.tcx()));
|
||||||
let trait_ref = Rc::new(ty::TraitRef { def_id: trait_id,
|
let trait_ref = Rc::new(ty::TraitRef { def_id: trait_id,
|
||||||
|
@ -265,10 +271,16 @@ pub fn trans_static_method_callee(bcx: Block,
|
||||||
// that with the `rcvr_method` from before, which tells us
|
// that with the `rcvr_method` from before, which tells us
|
||||||
// the type parameters from the *method*, to yield
|
// the type parameters from the *method*, to yield
|
||||||
// `callee_substs=[[T=int],[],[U=String]]`.
|
// `callee_substs=[[T=int],[],[U=String]]`.
|
||||||
let (impl_type, impl_self, _) = impl_substs.types.split();
|
let subst::SeparateVecsPerParamSpace {
|
||||||
|
types: impl_type,
|
||||||
|
selfs: impl_self,
|
||||||
|
assocs: impl_assoc,
|
||||||
|
fns: _
|
||||||
|
} = impl_substs.types.split();
|
||||||
let callee_substs =
|
let callee_substs =
|
||||||
Substs::erased(VecPerParamSpace::new(impl_type,
|
Substs::erased(VecPerParamSpace::new(impl_type,
|
||||||
impl_self,
|
impl_self,
|
||||||
|
impl_assoc,
|
||||||
rcvr_method));
|
rcvr_method));
|
||||||
|
|
||||||
let mth_id = method_with_name(ccx, impl_did, mname);
|
let mth_id = method_with_name(ccx, impl_did, mname);
|
||||||
|
@ -397,12 +409,17 @@ fn combine_impl_and_methods_tps(bcx: Block,
|
||||||
|
|
||||||
// Break apart the type parameters from the node and type
|
// Break apart the type parameters from the node and type
|
||||||
// parameters from the receiver.
|
// parameters from the receiver.
|
||||||
let (_, _, node_method) = node_substs.types.split();
|
let node_method = node_substs.types.split().fns;
|
||||||
let (rcvr_type, rcvr_self, rcvr_method) = rcvr_substs.types.clone().split();
|
let subst::SeparateVecsPerParamSpace {
|
||||||
|
types: rcvr_type,
|
||||||
|
selfs: rcvr_self,
|
||||||
|
assocs: rcvr_assoc,
|
||||||
|
fns: rcvr_method
|
||||||
|
} = rcvr_substs.types.clone().split();
|
||||||
assert!(rcvr_method.is_empty());
|
assert!(rcvr_method.is_empty());
|
||||||
subst::Substs {
|
subst::Substs {
|
||||||
regions: subst::ErasedRegions,
|
regions: subst::ErasedRegions,
|
||||||
types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, node_method)
|
types: subst::VecPerParamSpace::new(rcvr_type, rcvr_self, rcvr_assoc, node_method)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -573,10 +573,6 @@ pub struct ctxt<'tcx> {
|
||||||
/// Maps def IDs to true if and only if they're associated types.
|
/// Maps def IDs to true if and only if they're associated types.
|
||||||
pub associated_types: RefCell<DefIdMap<bool>>,
|
pub associated_types: RefCell<DefIdMap<bool>>,
|
||||||
|
|
||||||
/// Maps def IDs of traits to information about their associated types.
|
|
||||||
pub trait_associated_types:
|
|
||||||
RefCell<DefIdMap<Rc<Vec<AssociatedTypeInfo>>>>,
|
|
||||||
|
|
||||||
/// Caches the results of trait selection. This cache is used
|
/// Caches the results of trait selection. This cache is used
|
||||||
/// for things that do not have to do with the parameters in scope.
|
/// for things that do not have to do with the parameters in scope.
|
||||||
pub selection_cache: traits::SelectionCache,
|
pub selection_cache: traits::SelectionCache,
|
||||||
|
@ -1564,7 +1560,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
||||||
stability: RefCell::new(stability),
|
stability: RefCell::new(stability),
|
||||||
capture_modes: capture_modes,
|
capture_modes: capture_modes,
|
||||||
associated_types: RefCell::new(DefIdMap::new()),
|
associated_types: RefCell::new(DefIdMap::new()),
|
||||||
trait_associated_types: RefCell::new(DefIdMap::new()),
|
|
||||||
selection_cache: traits::SelectionCache::new(),
|
selection_cache: traits::SelectionCache::new(),
|
||||||
repr_hint_cache: RefCell::new(DefIdMap::new()),
|
repr_hint_cache: RefCell::new(DefIdMap::new()),
|
||||||
}
|
}
|
||||||
|
@ -1994,6 +1989,16 @@ impl ItemSubsts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ParamBounds {
|
||||||
|
pub fn empty() -> ParamBounds {
|
||||||
|
ParamBounds {
|
||||||
|
builtin_bounds: empty_builtin_bounds(),
|
||||||
|
trait_bounds: Vec::new(),
|
||||||
|
region_bounds: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Type utilities
|
// Type utilities
|
||||||
|
|
||||||
pub fn type_is_nil(ty: t) -> bool {
|
pub fn type_is_nil(ty: t) -> bool {
|
||||||
|
@ -4155,18 +4160,6 @@ impl Ord for AssociatedTypeInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the associated types belonging to the given trait, in parameter
|
|
||||||
/// order.
|
|
||||||
pub fn associated_types_for_trait(cx: &ctxt, trait_id: ast::DefId)
|
|
||||||
-> Rc<Vec<AssociatedTypeInfo>> {
|
|
||||||
cx.trait_associated_types
|
|
||||||
.borrow()
|
|
||||||
.find(&trait_id)
|
|
||||||
.expect("associated_types_for_trait(): trait not found, try calling \
|
|
||||||
ensure_associated_types()")
|
|
||||||
.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
|
pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
|
||||||
-> Rc<Vec<ImplOrTraitItemId>> {
|
-> Rc<Vec<ImplOrTraitItemId>> {
|
||||||
lookup_locally_or_in_crate_store("trait_item_def_ids",
|
lookup_locally_or_in_crate_store("trait_item_def_ids",
|
||||||
|
|
|
@ -54,7 +54,7 @@ use middle::def;
|
||||||
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
|
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
|
||||||
use middle::lang_items::{FnOnceTraitLangItem};
|
use middle::lang_items::{FnOnceTraitLangItem};
|
||||||
use middle::resolve_lifetime as rl;
|
use middle::resolve_lifetime as rl;
|
||||||
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
|
use middle::subst::{FnSpace, TypeSpace, AssocSpace, SelfSpace, Subst, Substs};
|
||||||
use middle::subst::{VecPerParamSpace};
|
use middle::subst::{VecPerParamSpace};
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
use middle::typeck::lookup_def_tcx;
|
use middle::typeck::lookup_def_tcx;
|
||||||
|
@ -215,7 +215,8 @@ fn ast_path_substs<'tcx,AC,RS>(
|
||||||
associated_ty: Option<ty::t>,
|
associated_ty: Option<ty::t>,
|
||||||
path: &ast::Path)
|
path: &ast::Path)
|
||||||
-> Substs
|
-> Substs
|
||||||
where AC: AstConv<'tcx>, RS: RegionScope {
|
where AC: AstConv<'tcx>, RS: RegionScope
|
||||||
|
{
|
||||||
/*!
|
/*!
|
||||||
* Given a path `path` that refers to an item `I` with the
|
* Given a path `path` that refers to an item `I` with the
|
||||||
* declared generics `decl_generics`, returns an appropriate
|
* declared generics `decl_generics`, returns an appropriate
|
||||||
|
@ -338,16 +339,20 @@ fn ast_path_substs<'tcx,AC,RS>(
|
||||||
substs.types.push(TypeSpace, default);
|
substs.types.push(TypeSpace, default);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// This is an associated type.
|
tcx.sess.span_bug(path.span,
|
||||||
|
"extra parameter without default");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for param in decl_generics.types.get_slice(AssocSpace).iter() {
|
||||||
substs.types.push(
|
substs.types.push(
|
||||||
TypeSpace,
|
AssocSpace,
|
||||||
this.associated_type_binding(path.span,
|
this.associated_type_binding(path.span,
|
||||||
associated_ty,
|
associated_ty,
|
||||||
decl_def_id,
|
decl_def_id,
|
||||||
param.def_id))
|
param.def_id))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
substs
|
substs
|
||||||
}
|
}
|
||||||
|
@ -628,9 +633,13 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
a_seq_ty: &ast::Ty,
|
a_seq_ty: &ast::Ty,
|
||||||
ptr_ty: PointerTy,
|
ptr_ty: PointerTy,
|
||||||
constr: |ty::t| -> ty::t)
|
constr: |ty::t| -> ty::t)
|
||||||
-> ty::t {
|
-> ty::t
|
||||||
|
{
|
||||||
let tcx = this.tcx();
|
let tcx = this.tcx();
|
||||||
debug!("mk_pointer(ptr_ty={})", ptr_ty);
|
|
||||||
|
debug!("mk_pointer(ptr_ty={}, a_seq_ty={})",
|
||||||
|
ptr_ty,
|
||||||
|
a_seq_ty.repr(tcx));
|
||||||
|
|
||||||
match a_seq_ty.node {
|
match a_seq_ty.node {
|
||||||
ast::TyVec(ref ty) => {
|
ast::TyVec(ref ty) => {
|
||||||
|
@ -730,7 +739,13 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
|
||||||
trait_type_id: ast::DefId,
|
trait_type_id: ast::DefId,
|
||||||
span: Span)
|
span: Span)
|
||||||
-> ty::t
|
-> ty::t
|
||||||
where AC: AstConv<'tcx>, RS: RegionScope {
|
where AC: AstConv<'tcx>, RS: RegionScope
|
||||||
|
{
|
||||||
|
debug!("associated_ty_to_ty(trait_path={}, for_ast_type={}, trait_type_id={})",
|
||||||
|
trait_path.repr(this.tcx()),
|
||||||
|
for_ast_type.repr(this.tcx()),
|
||||||
|
trait_type_id.repr(this.tcx()));
|
||||||
|
|
||||||
// Find the trait that this associated type belongs to.
|
// Find the trait that this associated type belongs to.
|
||||||
let trait_did = match ty::impl_or_trait_item(this.tcx(),
|
let trait_did = match ty::impl_or_trait_item(this.tcx(),
|
||||||
trait_type_id).container() {
|
trait_type_id).container() {
|
||||||
|
@ -757,9 +772,16 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
|
||||||
None,
|
None,
|
||||||
Some(for_type),
|
Some(for_type),
|
||||||
trait_path);
|
trait_path);
|
||||||
|
|
||||||
|
debug!("associated_ty_to_ty(trait_ref={})",
|
||||||
|
trait_ref.repr(this.tcx()));
|
||||||
|
|
||||||
let trait_def = this.get_trait_def(trait_did);
|
let trait_def = this.get_trait_def(trait_did);
|
||||||
for type_parameter in trait_def.generics.types.iter() {
|
for type_parameter in trait_def.generics.types.iter() {
|
||||||
if type_parameter.def_id == trait_type_id {
|
if type_parameter.def_id == trait_type_id {
|
||||||
|
debug!("associated_ty_to_ty(type_parameter={} substs={})",
|
||||||
|
type_parameter.repr(this.tcx()),
|
||||||
|
trait_ref.substs.repr(this.tcx()));
|
||||||
return *trait_ref.substs.types.get(type_parameter.space,
|
return *trait_ref.substs.types.get(type_parameter.space,
|
||||||
type_parameter.index)
|
type_parameter.index)
|
||||||
}
|
}
|
||||||
|
@ -772,7 +794,10 @@ fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
|
||||||
// Parses the programmer's textual representation of a type into our
|
// Parses the programmer's textual representation of a type into our
|
||||||
// internal notion of a type.
|
// internal notion of a type.
|
||||||
pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||||
this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t {
|
this: &AC, rscope: &RS, ast_ty: &ast::Ty) -> ty::t
|
||||||
|
{
|
||||||
|
debug!("ast_ty_to_ty(ast_ty={})",
|
||||||
|
ast_ty.repr(this.tcx()));
|
||||||
|
|
||||||
let tcx = this.tcx();
|
let tcx = this.tcx();
|
||||||
|
|
||||||
|
|
|
@ -298,13 +298,19 @@ fn collect_trait_methods(ccx: &CrateCtxt,
|
||||||
&*m.pe_fn_decl())
|
&*m.pe_fn_decl())
|
||||||
}
|
}
|
||||||
ast::TypeTraitItem(ref at) => {
|
ast::TypeTraitItem(ref at) => {
|
||||||
tcx.sess.span_bug(at.span,
|
tcx.sess.span_bug(at.ty_param.span,
|
||||||
"there shouldn't \
|
"there shouldn't \
|
||||||
be a type trait \
|
be a type trait \
|
||||||
item here")
|
item here")
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
debug!("ty_method_of_trait_method yielded {} \
|
||||||
|
for method {} of trait {}",
|
||||||
|
ty_method.repr(ccx.tcx),
|
||||||
|
trait_item.repr(ccx.tcx),
|
||||||
|
local_def(trait_id).repr(ccx.tcx));
|
||||||
|
|
||||||
make_method_ty(ccx, &*ty_method);
|
make_method_ty(ccx, &*ty_method);
|
||||||
|
|
||||||
tcx.impl_or_trait_items
|
tcx.impl_or_trait_items
|
||||||
|
@ -315,9 +321,9 @@ fn collect_trait_methods(ccx: &CrateCtxt,
|
||||||
ast::TypeTraitItem(ref ast_associated_type) => {
|
ast::TypeTraitItem(ref ast_associated_type) => {
|
||||||
let trait_did = local_def(trait_id);
|
let trait_did = local_def(trait_id);
|
||||||
let associated_type = ty::AssociatedType {
|
let associated_type = ty::AssociatedType {
|
||||||
name: ast_associated_type.ident.name,
|
name: ast_associated_type.ty_param.ident.name,
|
||||||
vis: ast::Public,
|
vis: ast::Public,
|
||||||
def_id: local_def(ast_associated_type.id),
|
def_id: local_def(ast_associated_type.ty_param.id),
|
||||||
container: TraitContainer(trait_did),
|
container: TraitContainer(trait_did),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -345,7 +351,7 @@ fn collect_trait_methods(ccx: &CrateCtxt,
|
||||||
method.id))
|
method.id))
|
||||||
}
|
}
|
||||||
ast::TypeTraitItem(ref typedef) => {
|
ast::TypeTraitItem(ref typedef) => {
|
||||||
ty::TypeTraitItemId(local_def(typedef.id))
|
ty::TypeTraitItemId(local_def(typedef.ty_param.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).collect());
|
}).collect());
|
||||||
|
@ -460,35 +466,35 @@ fn convert_associated_type(ccx: &CrateCtxt,
|
||||||
// associated type.
|
// associated type.
|
||||||
let type_parameter_def = trait_def.generics
|
let type_parameter_def = trait_def.generics
|
||||||
.types
|
.types
|
||||||
.get_slice(subst::TypeSpace)
|
.get_slice(subst::AssocSpace)
|
||||||
.iter()
|
.iter()
|
||||||
.find(|def| {
|
.find(|def| {
|
||||||
def.def_id == local_def(associated_type.id)
|
def.def_id == local_def(associated_type.ty_param.id)
|
||||||
});
|
});
|
||||||
let type_parameter_def = match type_parameter_def {
|
let type_parameter_def = match type_parameter_def {
|
||||||
Some(type_parameter_def) => type_parameter_def,
|
Some(type_parameter_def) => type_parameter_def,
|
||||||
None => {
|
None => {
|
||||||
ccx.tcx().sess.span_bug(associated_type.span,
|
ccx.tcx().sess.span_bug(associated_type.ty_param.span,
|
||||||
"`convert_associated_type()` didn't find \
|
"`convert_associated_type()` didn't find \
|
||||||
a type parameter ID corresponding to \
|
a type parameter ID corresponding to \
|
||||||
this type")
|
this type")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let param_type = ty::mk_param(ccx.tcx,
|
let param_type = ty::mk_param(ccx.tcx,
|
||||||
subst::TypeSpace,
|
type_parameter_def.space,
|
||||||
type_parameter_def.index,
|
type_parameter_def.index,
|
||||||
local_def(associated_type.id));
|
local_def(associated_type.ty_param.id));
|
||||||
ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.id),
|
ccx.tcx.tcache.borrow_mut().insert(local_def(associated_type.ty_param.id),
|
||||||
Polytype {
|
Polytype {
|
||||||
generics: ty::Generics::empty(),
|
generics: ty::Generics::empty(),
|
||||||
ty: param_type,
|
ty: param_type,
|
||||||
});
|
});
|
||||||
write_ty_to_tcx(ccx.tcx, associated_type.id, param_type);
|
write_ty_to_tcx(ccx.tcx, associated_type.ty_param.id, param_type);
|
||||||
|
|
||||||
let associated_type = Rc::new(ty::AssociatedType {
|
let associated_type = Rc::new(ty::AssociatedType {
|
||||||
name: associated_type.ident.name,
|
name: associated_type.ty_param.ident.name,
|
||||||
vis: ast::Public,
|
vis: ast::Public,
|
||||||
def_id: local_def(associated_type.id),
|
def_id: local_def(associated_type.ty_param.id),
|
||||||
container: TraitContainer(trait_def.trait_ref.def_id),
|
container: TraitContainer(trait_def.trait_ref.def_id),
|
||||||
});
|
});
|
||||||
ccx.tcx
|
ccx.tcx
|
||||||
|
@ -780,25 +786,18 @@ impl<'a,'tcx> AstConv<'tcx> for ImplCtxt<'a,'tcx> {
|
||||||
ty: Option<ty::t>,
|
ty: Option<ty::t>,
|
||||||
trait_id: ast::DefId,
|
trait_id: ast::DefId,
|
||||||
associated_type_id: ast::DefId)
|
associated_type_id: ast::DefId)
|
||||||
-> ty::t {
|
-> ty::t
|
||||||
ensure_associated_types(self, trait_id);
|
{
|
||||||
let associated_type_ids = ty::associated_types_for_trait(self.ccx.tcx,
|
let trait_def = ty::lookup_trait_def(self.tcx(), trait_id);
|
||||||
trait_id);
|
|
||||||
match self.opt_trait_ref_id {
|
match self.opt_trait_ref_id {
|
||||||
Some(trait_ref_id) if trait_ref_id == trait_id => {
|
Some(trait_ref_id) if trait_ref_id == trait_id => {
|
||||||
// It's an associated type on the trait that we're
|
// It's an associated type on the trait that we're
|
||||||
// implementing.
|
// implementing.
|
||||||
let associated_type_id =
|
assert!(trait_def.generics.types
|
||||||
associated_type_ids.iter()
|
.get_slice(subst::AssocSpace)
|
||||||
.find(|id| {
|
.iter()
|
||||||
id.def_id == associated_type_id
|
.any(|type_param_def| type_param_def.def_id == associated_type_id));
|
||||||
})
|
let associated_type = ty::impl_or_trait_item(self.ccx.tcx, associated_type_id);
|
||||||
.expect("associated_type_binding(): \
|
|
||||||
expected associated type ID \
|
|
||||||
in trait");
|
|
||||||
let associated_type =
|
|
||||||
ty::impl_or_trait_item(self.ccx.tcx,
|
|
||||||
associated_type_id.def_id);
|
|
||||||
for impl_item in self.impl_items.iter() {
|
for impl_item in self.impl_items.iter() {
|
||||||
match *impl_item {
|
match *impl_item {
|
||||||
ast::MethodImplItem(_) => {}
|
ast::MethodImplItem(_) => {}
|
||||||
|
@ -978,9 +977,9 @@ impl<'a,'tcx> AstConv<'tcx> for TraitMethodCtxt<'a,'tcx> {
|
||||||
match *item {
|
match *item {
|
||||||
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
|
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
|
||||||
ast::TypeTraitItem(ref item) => {
|
ast::TypeTraitItem(ref item) => {
|
||||||
if local_def(item.id) == associated_type_id {
|
if local_def(item.ty_param.id) == associated_type_id {
|
||||||
return ty::mk_param(self.tcx(),
|
return ty::mk_param(self.tcx(),
|
||||||
subst::TypeSpace,
|
subst::AssocSpace,
|
||||||
index,
|
index,
|
||||||
associated_type_id)
|
associated_type_id)
|
||||||
}
|
}
|
||||||
|
@ -1451,7 +1450,8 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||||
trait_id: ast::NodeId,
|
trait_id: ast::NodeId,
|
||||||
generics: &ast::Generics,
|
generics: &ast::Generics,
|
||||||
items: &[ast::TraitItem])
|
items: &[ast::TraitItem])
|
||||||
-> subst::Substs {
|
-> subst::Substs
|
||||||
|
{
|
||||||
// Creates a no-op substitution for the trait's type parameters.
|
// Creates a no-op substitution for the trait's type parameters.
|
||||||
let regions =
|
let regions =
|
||||||
generics.lifetimes
|
generics.lifetimes
|
||||||
|
@ -1464,7 +1464,7 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Start with the generics in the type parameters...
|
// Start with the generics in the type parameters...
|
||||||
let mut types: Vec<_> =
|
let types: Vec<_> =
|
||||||
generics.ty_params
|
generics.ty_params
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
@ -1472,24 +1472,27 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::Item) -> Rc<ty::TraitDef> {
|
||||||
i, local_def(def.id)))
|
i, local_def(def.id)))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// ...and add generics synthesized from the associated types.
|
// ...and also create generics synthesized from the associated types.
|
||||||
for item in items.iter() {
|
let assoc_types: Vec<_> =
|
||||||
match *item {
|
items.iter()
|
||||||
|
.flat_map(|item| match *item {
|
||||||
ast::TypeTraitItem(ref trait_item) => {
|
ast::TypeTraitItem(ref trait_item) => {
|
||||||
let index = types.len();
|
let index = types.len();
|
||||||
types.push(ty::mk_param(ccx.tcx,
|
Some(ty::mk_param(ccx.tcx,
|
||||||
subst::TypeSpace,
|
subst::AssocSpace,
|
||||||
index,
|
index,
|
||||||
local_def(trait_item.id)))
|
local_def(trait_item.ty_param.id))).into_iter()
|
||||||
}
|
|
||||||
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
|
|
||||||
}
|
}
|
||||||
|
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {
|
||||||
|
None.into_iter()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let self_ty =
|
let self_ty =
|
||||||
ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id));
|
ty::mk_param(ccx.tcx, subst::SelfSpace, 0, local_def(trait_id));
|
||||||
|
|
||||||
subst::Substs::new_trait(types, regions, self_ty)
|
subst::Substs::new_trait(types, regions, assoc_types, self_ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1630,11 +1633,11 @@ fn ty_of_trait_item(ccx: &CrateCtxt, trait_item: &ast::TraitItem)
|
||||||
"ty_of_trait_item() on provided method")
|
"ty_of_trait_item() on provided method")
|
||||||
}
|
}
|
||||||
ast::TypeTraitItem(ref associated_type) => {
|
ast::TypeTraitItem(ref associated_type) => {
|
||||||
let parent = ccx.tcx.map.get_parent(associated_type.id);
|
let parent = ccx.tcx.map.get_parent(associated_type.ty_param.id);
|
||||||
let trait_def = match ccx.tcx.map.get(parent) {
|
let trait_def = match ccx.tcx.map.get(parent) {
|
||||||
ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
|
ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
|
||||||
_ => {
|
_ => {
|
||||||
ccx.tcx.sess.span_bug(associated_type.span,
|
ccx.tcx.sess.span_bug(associated_type.ty_param.span,
|
||||||
"associated type's parent wasn't \
|
"associated type's parent wasn't \
|
||||||
an item?!")
|
an item?!")
|
||||||
}
|
}
|
||||||
|
@ -1661,38 +1664,33 @@ fn ty_generics_for_type(ccx: &CrateCtxt,
|
||||||
fn ty_generics_for_trait(ccx: &CrateCtxt,
|
fn ty_generics_for_trait(ccx: &CrateCtxt,
|
||||||
trait_id: ast::NodeId,
|
trait_id: ast::NodeId,
|
||||||
substs: &subst::Substs,
|
substs: &subst::Substs,
|
||||||
generics: &ast::Generics,
|
ast_generics: &ast::Generics,
|
||||||
items: &[ast::TraitItem])
|
items: &[ast::TraitItem])
|
||||||
-> ty::Generics {
|
-> ty::Generics {
|
||||||
let mut generics =
|
let mut generics =
|
||||||
ty_generics(ccx,
|
ty_generics(ccx,
|
||||||
subst::TypeSpace,
|
subst::TypeSpace,
|
||||||
generics.lifetimes.as_slice(),
|
ast_generics.lifetimes.as_slice(),
|
||||||
generics.ty_params.as_slice(),
|
ast_generics.ty_params.as_slice(),
|
||||||
ty::Generics::empty(),
|
ty::Generics::empty(),
|
||||||
&generics.where_clause,
|
&ast_generics.where_clause,
|
||||||
DontCreateTypeParametersForAssociatedTypes);
|
DontCreateTypeParametersForAssociatedTypes);
|
||||||
|
|
||||||
// Add in type parameters for any associated types.
|
// Add in type parameters for any associated types.
|
||||||
for item in items.iter() {
|
for item in items.iter() {
|
||||||
match *item {
|
match *item {
|
||||||
ast::TypeTraitItem(ref associated_type) => {
|
ast::TypeTraitItem(ref associated_type) => {
|
||||||
let def = ty::TypeParameterDef {
|
let def =
|
||||||
space: subst::TypeSpace,
|
get_or_create_type_parameter_def(
|
||||||
index: generics.types.len(subst::TypeSpace),
|
ccx,
|
||||||
name: associated_type.ident.name,
|
subst::AssocSpace,
|
||||||
def_id: local_def(associated_type.id),
|
&associated_type.ty_param,
|
||||||
bounds: ty::ParamBounds {
|
generics.types.len(subst::TypeSpace),
|
||||||
builtin_bounds: ty::empty_builtin_bounds(),
|
&ast_generics.where_clause,
|
||||||
trait_bounds: Vec::new(),
|
Some(local_def(trait_id)));
|
||||||
region_bounds: Vec::new(),
|
ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.ty_param.id,
|
||||||
},
|
|
||||||
associated_with: Some(local_def(trait_id)),
|
|
||||||
default: None,
|
|
||||||
};
|
|
||||||
ccx.tcx.ty_param_defs.borrow_mut().insert(associated_type.id,
|
|
||||||
def.clone());
|
def.clone());
|
||||||
generics.types.push(subst::TypeSpace, def);
|
generics.types.push(subst::AssocSpace, def);
|
||||||
}
|
}
|
||||||
ast::ProvidedMethod(_) | ast::RequiredMethod(_) => {}
|
ast::ProvidedMethod(_) | ast::RequiredMethod(_) => {}
|
||||||
}
|
}
|
||||||
|
@ -1791,86 +1789,17 @@ enum CreateTypeParametersForAssociatedTypesFlag {
|
||||||
CreateTypeParametersForAssociatedTypes,
|
CreateTypeParametersForAssociatedTypes,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ensure_associated_types<'tcx,AC>(this: &AC, trait_id: ast::DefId)
|
|
||||||
where AC: AstConv<'tcx> {
|
|
||||||
if this.tcx().trait_associated_types.borrow().contains_key(&trait_id) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if trait_id.krate == ast::LOCAL_CRATE {
|
|
||||||
match this.tcx().map.find(trait_id.node) {
|
|
||||||
Some(ast_map::NodeItem(item)) => {
|
|
||||||
match item.node {
|
|
||||||
ast::ItemTrait(_, _, _, ref trait_items) => {
|
|
||||||
let mut result = Vec::new();
|
|
||||||
let mut index = 0;
|
|
||||||
for trait_item in trait_items.iter() {
|
|
||||||
match *trait_item {
|
|
||||||
ast::RequiredMethod(_) |
|
|
||||||
ast::ProvidedMethod(_) => {}
|
|
||||||
ast::TypeTraitItem(ref associated_type) => {
|
|
||||||
let info = ty::AssociatedTypeInfo {
|
|
||||||
def_id: local_def(associated_type.id),
|
|
||||||
index: index,
|
|
||||||
name: associated_type.ident.name,
|
|
||||||
};
|
|
||||||
result.push(info);
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.tcx()
|
|
||||||
.trait_associated_types
|
|
||||||
.borrow_mut()
|
|
||||||
.insert(trait_id, Rc::new(result));
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
this.tcx().sess.bug("ensure_associated_types() \
|
|
||||||
called on non-trait")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
this.tcx().sess.bug("ensure_associated_types() called on \
|
|
||||||
non-trait")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cross-crate case.
|
|
||||||
let mut result = Vec::new();
|
|
||||||
let mut index = 0;
|
|
||||||
let trait_items = ty::trait_items(this.tcx(), trait_id);
|
|
||||||
for trait_item in trait_items.iter() {
|
|
||||||
match *trait_item {
|
|
||||||
ty::MethodTraitItem(_) => {}
|
|
||||||
ty::TypeTraitItem(ref associated_type) => {
|
|
||||||
let info = ty::AssociatedTypeInfo {
|
|
||||||
def_id: associated_type.def_id,
|
|
||||||
index: index,
|
|
||||||
name: associated_type.name
|
|
||||||
};
|
|
||||||
result.push(info);
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.tcx().trait_associated_types.borrow_mut().insert(trait_id,
|
|
||||||
Rc::new(result));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ty_generics<'tcx,AC>(this: &AC,
|
fn ty_generics<'tcx,AC>(this: &AC,
|
||||||
space: subst::ParamSpace,
|
space: subst::ParamSpace,
|
||||||
lifetime_defs: &[ast::LifetimeDef],
|
lifetime_defs: &[ast::LifetimeDef],
|
||||||
types: &[ast::TyParam],
|
types: &[ast::TyParam],
|
||||||
base_generics: ty::Generics,
|
base_generics: ty::Generics,
|
||||||
where_clause: &ast::WhereClause,
|
where_clause: &ast::WhereClause,
|
||||||
create_type_parameters_for_associated_types:
|
create_type_parameters_for_associated_types_flag:
|
||||||
CreateTypeParametersForAssociatedTypesFlag)
|
CreateTypeParametersForAssociatedTypesFlag)
|
||||||
-> ty::Generics
|
-> ty::Generics
|
||||||
where AC: AstConv<'tcx> {
|
where AC: AstConv<'tcx>
|
||||||
|
{
|
||||||
let mut result = base_generics;
|
let mut result = base_generics;
|
||||||
|
|
||||||
for (i, l) in lifetime_defs.iter().enumerate() {
|
for (i, l) in lifetime_defs.iter().enumerate() {
|
||||||
|
@ -1891,62 +1820,11 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||||
// First, create the virtual type parameters for associated types if
|
// First, create the virtual type parameters for associated types if
|
||||||
// necessary.
|
// necessary.
|
||||||
let mut associated_types_generics = ty::Generics::empty();
|
let mut associated_types_generics = ty::Generics::empty();
|
||||||
match create_type_parameters_for_associated_types {
|
match create_type_parameters_for_associated_types_flag {
|
||||||
DontCreateTypeParametersForAssociatedTypes => {}
|
DontCreateTypeParametersForAssociatedTypes => {}
|
||||||
CreateTypeParametersForAssociatedTypes => {
|
CreateTypeParametersForAssociatedTypes => {
|
||||||
let mut index = 0;
|
create_type_parameters_for_associated_types(this, space, types,
|
||||||
for param in types.iter() {
|
&mut associated_types_generics);
|
||||||
for bound in param.bounds.iter() {
|
|
||||||
match *bound {
|
|
||||||
ast::TraitTyParamBound(ref trait_bound) => {
|
|
||||||
match lookup_def_tcx(this.tcx(),
|
|
||||||
trait_bound.path.span,
|
|
||||||
trait_bound.ref_id) {
|
|
||||||
def::DefTrait(trait_did) => {
|
|
||||||
ensure_associated_types(this, trait_did);
|
|
||||||
let associated_types =
|
|
||||||
ty::associated_types_for_trait(
|
|
||||||
this.tcx(),
|
|
||||||
trait_did);
|
|
||||||
for associated_type_info in
|
|
||||||
associated_types.iter() {
|
|
||||||
let associated_type_trait_item =
|
|
||||||
ty::impl_or_trait_item(
|
|
||||||
this.tcx(),
|
|
||||||
associated_type_info.def_id);
|
|
||||||
let def = ty::TypeParameterDef {
|
|
||||||
name: associated_type_trait_item.name(),
|
|
||||||
def_id: associated_type_info.def_id,
|
|
||||||
space: space,
|
|
||||||
index: types.len() + index,
|
|
||||||
bounds: ty::ParamBounds {
|
|
||||||
builtin_bounds:
|
|
||||||
ty::empty_builtin_bounds(),
|
|
||||||
trait_bounds: Vec::new(),
|
|
||||||
region_bounds: Vec::new(),
|
|
||||||
},
|
|
||||||
associated_with: {
|
|
||||||
Some(local_def(param.id))
|
|
||||||
},
|
|
||||||
default: None,
|
|
||||||
};
|
|
||||||
associated_types_generics.types
|
|
||||||
.push(space,
|
|
||||||
def);
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
this.tcx().sess.span_bug(trait_bound.path
|
|
||||||
.span,
|
|
||||||
"not a trait?!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1960,7 +1838,8 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||||
space,
|
space,
|
||||||
param,
|
param,
|
||||||
i,
|
i,
|
||||||
where_clause);
|
where_clause,
|
||||||
|
None);
|
||||||
debug!("ty_generics: def for type param: {}, {}",
|
debug!("ty_generics: def for type param: {}, {}",
|
||||||
def.repr(this.tcx()),
|
def.repr(this.tcx()),
|
||||||
space);
|
space);
|
||||||
|
@ -1981,14 +1860,93 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
fn get_or_create_type_parameter_def<'tcx,AC>(
|
fn create_type_parameters_for_associated_types<'tcx,AC>(
|
||||||
this: &AC,
|
this: &AC,
|
||||||
|
space: subst::ParamSpace,
|
||||||
|
types: &[ast::TyParam],
|
||||||
|
associated_types_generics: &mut ty::Generics)
|
||||||
|
where AC: AstConv<'tcx>
|
||||||
|
{
|
||||||
|
// The idea here is roughly as follows. We start with
|
||||||
|
// an item that is paramerized by various type parameters
|
||||||
|
// with bounds:
|
||||||
|
//
|
||||||
|
// fn foo<T:Iterator>(t: T) { ... }
|
||||||
|
//
|
||||||
|
// The traits in those bounds declare associated types:
|
||||||
|
//
|
||||||
|
// trait Iterator { type Elem; ... }
|
||||||
|
//
|
||||||
|
// And we rewrite the original function so that every associated
|
||||||
|
// type is bound to some fresh type parameter:
|
||||||
|
//
|
||||||
|
// fn foo<A,T:Iterator<Elem=A>>(t: T) { ... }
|
||||||
|
|
||||||
|
// Number of synthetic type parameters created thus far
|
||||||
|
let mut index = 0;
|
||||||
|
|
||||||
|
// Iterate over the each type parameter `T` (from the example)
|
||||||
|
for param in types.iter() {
|
||||||
|
// Iterate over the bound `Iterator`
|
||||||
|
for bound in param.bounds.iter() {
|
||||||
|
// In the above example, `ast_trait_ref` is `Iterator`.
|
||||||
|
let ast_trait_ref = match *bound {
|
||||||
|
ast::TraitTyParamBound(ref r) => r,
|
||||||
|
ast::UnboxedFnTyParamBound(..) => { continue; }
|
||||||
|
ast::RegionTyParamBound(..) => { continue; }
|
||||||
|
};
|
||||||
|
|
||||||
|
let trait_def_id =
|
||||||
|
match lookup_def_tcx(this.tcx(),
|
||||||
|
ast_trait_ref.path.span,
|
||||||
|
ast_trait_ref.ref_id) {
|
||||||
|
def::DefTrait(trait_def_id) => trait_def_id,
|
||||||
|
_ => {
|
||||||
|
this.tcx().sess.span_bug(ast_trait_ref.path.span,
|
||||||
|
"not a trait?!")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// trait_def_id is def-id of `Iterator`
|
||||||
|
let trait_def = ty::lookup_trait_def(this.tcx(), trait_def_id);
|
||||||
|
let associated_type_defs = trait_def.generics.types.get_slice(subst::AssocSpace);
|
||||||
|
|
||||||
|
// Iterate over each associated type `Elem`
|
||||||
|
for associated_type_def in associated_type_defs.iter() {
|
||||||
|
// Create the fresh type parameter `A`
|
||||||
|
let def = ty::TypeParameterDef {
|
||||||
|
name: associated_type_def.name,
|
||||||
|
def_id: associated_type_def.def_id,
|
||||||
|
space: space,
|
||||||
|
index: types.len() + index,
|
||||||
|
bounds: ty::ParamBounds {
|
||||||
|
builtin_bounds: associated_type_def.bounds.builtin_bounds,
|
||||||
|
|
||||||
|
// FIXME(#18178) -- we should add the other bounds, but
|
||||||
|
// that requires subst and more logic
|
||||||
|
trait_bounds: Vec::new(),
|
||||||
|
region_bounds: Vec::new(),
|
||||||
|
},
|
||||||
|
associated_with: Some(local_def(param.id)),
|
||||||
|
default: None,
|
||||||
|
};
|
||||||
|
associated_types_generics.types.push(space, def);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
|
||||||
space: subst::ParamSpace,
|
space: subst::ParamSpace,
|
||||||
param: &ast::TyParam,
|
param: &ast::TyParam,
|
||||||
index: uint,
|
index: uint,
|
||||||
where_clause: &ast::WhereClause)
|
where_clause: &ast::WhereClause,
|
||||||
|
associated_with: Option<ast::DefId>)
|
||||||
-> ty::TypeParameterDef
|
-> ty::TypeParameterDef
|
||||||
where AC: AstConv<'tcx> {
|
where AC: AstConv<'tcx>
|
||||||
|
{
|
||||||
match this.tcx().ty_param_defs.borrow().find(¶m.id) {
|
match this.tcx().ty_param_defs.borrow().find(¶m.id) {
|
||||||
Some(d) => { return (*d).clone(); }
|
Some(d) => { return (*d).clone(); }
|
||||||
None => { }
|
None => { }
|
||||||
|
@ -2028,7 +1986,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||||
index: index,
|
index: index,
|
||||||
name: param.ident.name,
|
name: param.ident.name,
|
||||||
def_id: local_def(param.id),
|
def_id: local_def(param.id),
|
||||||
associated_with: None,
|
associated_with: associated_with,
|
||||||
bounds: bounds,
|
bounds: bounds,
|
||||||
default: default
|
default: default
|
||||||
};
|
};
|
||||||
|
@ -2037,7 +1995,6 @@ fn ty_generics<'tcx,AC>(this: &AC,
|
||||||
|
|
||||||
def
|
def
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_bounds<'tcx,AC>(this: &AC,
|
fn compute_bounds<'tcx,AC>(this: &AC,
|
||||||
name_of_bounded_thing: ast::Name,
|
name_of_bounded_thing: ast::Name,
|
||||||
|
|
|
@ -774,10 +774,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
assert!(generics.regions.len(subst::FnSpace) == 0);
|
assert!(generics.regions.len(subst::FnSpace) == 0);
|
||||||
|
|
||||||
let type_parameter_count = generics.types.len(subst::TypeSpace);
|
let type_parameter_count = generics.types.len(subst::TypeSpace);
|
||||||
|
let type_parameters = self.next_ty_vars(type_parameter_count);
|
||||||
|
|
||||||
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
|
let region_param_defs = generics.regions.get_slice(subst::TypeSpace);
|
||||||
let regions = self.region_vars_for_defs(span, region_param_defs);
|
let regions = self.region_vars_for_defs(span, region_param_defs);
|
||||||
let type_parameters = self.next_ty_vars(type_parameter_count);
|
|
||||||
subst::Substs::new_trait(type_parameters, regions, self_ty)
|
let assoc_type_parameter_count = generics.types.len(subst::AssocSpace);
|
||||||
|
let assoc_type_parameters = self.next_ty_vars(assoc_type_parameter_count);
|
||||||
|
|
||||||
|
subst::Substs::new_trait(type_parameters, regions, assoc_type_parameters, self_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fresh_bound_region(&self, binder_id: ast::NodeId) -> ty::Region {
|
pub fn fresh_bound_region(&self, binder_id: ast::NodeId) -> ty::Region {
|
||||||
|
|
|
@ -425,7 +425,13 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String {
|
||||||
}
|
}
|
||||||
ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty),
|
ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty),
|
||||||
ty_err => "[type error]".to_string(),
|
ty_err => "[type error]".to_string(),
|
||||||
ty_param(ref param_ty) => param_ty.repr(cx),
|
ty_param(ref param_ty) => {
|
||||||
|
if cx.sess.verbose() {
|
||||||
|
param_ty.repr(cx)
|
||||||
|
} else {
|
||||||
|
param_ty.user_string(cx)
|
||||||
|
}
|
||||||
|
}
|
||||||
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
|
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
|
||||||
let base = ty::item_path_str(cx, did);
|
let base = ty::item_path_str(cx, did);
|
||||||
let generics = ty::lookup_item_type(cx, did).generics;
|
let generics = ty::lookup_item_type(cx, did).generics;
|
||||||
|
@ -481,6 +487,17 @@ pub fn parameterized(cx: &ctxt,
|
||||||
generics: &ty::Generics)
|
generics: &ty::Generics)
|
||||||
-> String
|
-> String
|
||||||
{
|
{
|
||||||
|
if cx.sess.verbose() {
|
||||||
|
if substs.is_noop() {
|
||||||
|
return format!("{}", base);
|
||||||
|
} else {
|
||||||
|
return format!("{}<{},{}>",
|
||||||
|
base,
|
||||||
|
substs.regions.repr(cx),
|
||||||
|
substs.types.repr(cx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut strs = Vec::new();
|
let mut strs = Vec::new();
|
||||||
|
|
||||||
match substs.regions {
|
match substs.regions {
|
||||||
|
@ -505,7 +522,7 @@ pub fn parameterized(cx: &ctxt,
|
||||||
let tps = substs.types.get_slice(subst::TypeSpace);
|
let tps = substs.types.get_slice(subst::TypeSpace);
|
||||||
let ty_params = generics.types.get_slice(subst::TypeSpace);
|
let ty_params = generics.types.get_slice(subst::TypeSpace);
|
||||||
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
|
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
|
||||||
let num_defaults = if has_defaults && !cx.sess.verbose() {
|
let num_defaults = if has_defaults {
|
||||||
ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
|
ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
|
||||||
match def.default {
|
match def.default {
|
||||||
Some(default) => default.subst(cx, substs) == actual,
|
Some(default) => default.subst(cx, substs) == actual,
|
||||||
|
@ -520,18 +537,6 @@ pub fn parameterized(cx: &ctxt,
|
||||||
strs.push(ty_to_string(cx, *t))
|
strs.push(ty_to_string(cx, *t))
|
||||||
}
|
}
|
||||||
|
|
||||||
if cx.sess.verbose() {
|
|
||||||
for t in substs.types.get_slice(subst::SelfSpace).iter() {
|
|
||||||
strs.push(format!("self {}", t.repr(cx)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// generally there shouldn't be any substs in the fn param
|
|
||||||
// space, but in verbose mode, print them out.
|
|
||||||
for t in substs.types.get_slice(subst::FnSpace).iter() {
|
|
||||||
strs.push(format!("fn {}", t.repr(cx)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if strs.len() > 0u {
|
if strs.len() > 0u {
|
||||||
format!("{}<{}>", base, strs.connect(", "))
|
format!("{}<{}>", base, strs.connect(", "))
|
||||||
} else {
|
} else {
|
||||||
|
@ -668,9 +673,10 @@ impl Repr for subst::Substs {
|
||||||
|
|
||||||
impl<T:Repr> Repr for subst::VecPerParamSpace<T> {
|
impl<T:Repr> Repr for subst::VecPerParamSpace<T> {
|
||||||
fn repr(&self, tcx: &ctxt) -> String {
|
fn repr(&self, tcx: &ctxt) -> String {
|
||||||
format!("[{};{};{}]",
|
format!("[{};{};{};{}]",
|
||||||
self.get_slice(subst::TypeSpace).repr(tcx),
|
self.get_slice(subst::TypeSpace).repr(tcx),
|
||||||
self.get_slice(subst::SelfSpace).repr(tcx),
|
self.get_slice(subst::SelfSpace).repr(tcx),
|
||||||
|
self.get_slice(subst::AssocSpace).repr(tcx),
|
||||||
self.get_slice(subst::FnSpace).repr(tcx))
|
self.get_slice(subst::FnSpace).repr(tcx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -726,7 +732,7 @@ impl Repr for ty::TraitRef {
|
||||||
fn repr(&self, tcx: &ctxt) -> String {
|
fn repr(&self, tcx: &ctxt) -> String {
|
||||||
let base = ty::item_path_str(tcx, self.def_id);
|
let base = ty::item_path_str(tcx, self.def_id);
|
||||||
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
|
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
|
||||||
format!("<{} as {}>",
|
format!("<{} : {}>",
|
||||||
self.substs.self_ty().repr(tcx),
|
self.substs.self_ty().repr(tcx),
|
||||||
parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics))
|
parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics))
|
||||||
}
|
}
|
||||||
|
@ -741,6 +747,19 @@ impl Repr for ty::TraitDef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Repr for ast::TraitItem {
|
||||||
|
fn repr(&self, _tcx: &ctxt) -> String {
|
||||||
|
match *self {
|
||||||
|
ast::RequiredMethod(ref data) => format!("RequiredMethod({}, id={})",
|
||||||
|
data.ident, data.id),
|
||||||
|
ast::ProvidedMethod(ref data) => format!("ProvidedMethod(id={})",
|
||||||
|
data.id),
|
||||||
|
ast::TypeTraitItem(ref data) => format!("TypeTraitItem({}, id={})",
|
||||||
|
data.ty_param.ident, data.ty_param.id),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Repr for ast::Expr {
|
impl Repr for ast::Expr {
|
||||||
fn repr(&self, _tcx: &ctxt) -> String {
|
fn repr(&self, _tcx: &ctxt) -> String {
|
||||||
format!("expr({}: {})", self.id, pprust::expr_to_string(self))
|
format!("expr({}: {})", self.id, pprust::expr_to_string(self))
|
||||||
|
@ -759,6 +778,12 @@ impl UserString for ast::Path {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Repr for ast::Ty {
|
||||||
|
fn repr(&self, _tcx: &ctxt) -> String {
|
||||||
|
format!("type({})", pprust::ty_to_string(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Repr for ast::Item {
|
impl Repr for ast::Item {
|
||||||
fn repr(&self, tcx: &ctxt) -> String {
|
fn repr(&self, tcx: &ctxt) -> String {
|
||||||
format!("item({})", tcx.map.node_to_string(self.id))
|
format!("item({})", tcx.map.node_to_string(self.id))
|
||||||
|
@ -1262,7 +1287,8 @@ impl UserString for ParamTy {
|
||||||
|
|
||||||
impl Repr for ParamTy {
|
impl Repr for ParamTy {
|
||||||
fn repr(&self, tcx: &ctxt) -> String {
|
fn repr(&self, tcx: &ctxt) -> String {
|
||||||
self.user_string(tcx)
|
let ident = self.user_string(tcx);
|
||||||
|
format!("{}/{}.{}", ident, self.space, self.idx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2203,12 +2203,12 @@ impl Clean<Stability> for attr::Stability {
|
||||||
impl Clean<Item> for ast::AssociatedType {
|
impl Clean<Item> for ast::AssociatedType {
|
||||||
fn clean(&self, cx: &DocContext) -> Item {
|
fn clean(&self, cx: &DocContext) -> Item {
|
||||||
Item {
|
Item {
|
||||||
source: self.span.clean(cx),
|
source: self.ty_param.span.clean(cx),
|
||||||
name: Some(self.ident.clean(cx)),
|
name: Some(self.ty_param.ident.clean(cx)),
|
||||||
attrs: self.attrs.clean(cx),
|
attrs: self.attrs.clean(cx),
|
||||||
inner: AssociatedTypeItem,
|
inner: AssociatedTypeItem,
|
||||||
visibility: None,
|
visibility: None,
|
||||||
def_id: ast_util::local_def(self.id),
|
def_id: ast_util::local_def(self.ty_param.id),
|
||||||
stability: None,
|
stability: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -861,10 +861,8 @@ pub enum ImplItem {
|
||||||
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||||
pub struct AssociatedType {
|
pub struct AssociatedType {
|
||||||
pub id: NodeId,
|
|
||||||
pub span: Span,
|
|
||||||
pub ident: Ident,
|
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
|
pub ty_param: TyParam,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||||
|
|
|
@ -405,7 +405,9 @@ impl<'ast> Map<'ast> {
|
||||||
MethMac(_) => panic!("no path elem for {}", node),
|
MethMac(_) => panic!("no path elem for {}", node),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeTraitItem(ref m) => PathName(m.ident.name),
|
TypeTraitItem(ref m) => {
|
||||||
|
PathName(m.ty_param.ident.name)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
NodeVariant(v) => PathName(v.node.name.name),
|
NodeVariant(v) => PathName(v.node.name.name),
|
||||||
_ => panic!("no path elem for {}", node)
|
_ => panic!("no path elem for {}", node)
|
||||||
|
@ -510,7 +512,7 @@ impl<'ast> Map<'ast> {
|
||||||
match *trait_method {
|
match *trait_method {
|
||||||
RequiredMethod(ref type_method) => type_method.span,
|
RequiredMethod(ref type_method) => type_method.span,
|
||||||
ProvidedMethod(ref method) => method.span,
|
ProvidedMethod(ref method) => method.span,
|
||||||
TypeTraitItem(ref typedef) => typedef.span,
|
TypeTraitItem(ref typedef) => typedef.ty_param.span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(NodeImplItem(ref impl_item)) => {
|
Some(NodeImplItem(ref impl_item)) => {
|
||||||
|
@ -650,7 +652,7 @@ impl Named for TraitItem {
|
||||||
match *self {
|
match *self {
|
||||||
RequiredMethod(ref tm) => tm.ident.name,
|
RequiredMethod(ref tm) => tm.ident.name,
|
||||||
ProvidedMethod(ref m) => m.name(),
|
ProvidedMethod(ref m) => m.name(),
|
||||||
TypeTraitItem(ref at) => at.ident.name,
|
TypeTraitItem(ref at) => at.ty_param.ident.name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -783,7 +785,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||||
self.insert(m.id, NodeTraitItem(tm));
|
self.insert(m.id, NodeTraitItem(tm));
|
||||||
}
|
}
|
||||||
TypeTraitItem(ref typ) => {
|
TypeTraitItem(ref typ) => {
|
||||||
self.insert(typ.id, NodeTraitItem(tm));
|
self.insert(typ.ty_param.id, NodeTraitItem(tm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -976,7 +978,7 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
|
||||||
let trait_item_id = match *trait_item {
|
let trait_item_id = match *trait_item {
|
||||||
ProvidedMethod(ref m) => m.id,
|
ProvidedMethod(ref m) => m.id,
|
||||||
RequiredMethod(ref m) => m.id,
|
RequiredMethod(ref m) => m.id,
|
||||||
TypeTraitItem(ref ty) => ty.id,
|
TypeTraitItem(ref ty) => ty.ty_param.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
collector.insert(trait_item_id, NodeTraitItem(trait_item));
|
collector.insert(trait_item_id, NodeTraitItem(trait_item));
|
||||||
|
@ -1080,7 +1082,7 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String {
|
||||||
}
|
}
|
||||||
TypeTraitItem(ref t) => {
|
TypeTraitItem(ref t) => {
|
||||||
format!("type item {} in {} (id={})",
|
format!("type item {} in {} (id={})",
|
||||||
token::get_ident(t.ident),
|
token::get_ident(t.ty_param.ident),
|
||||||
map.path_to_string(id),
|
map.path_to_string(id),
|
||||||
id)
|
id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -524,7 +524,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
|
||||||
match *tm {
|
match *tm {
|
||||||
ast::RequiredMethod(ref m) => self.operation.visit_id(m.id),
|
ast::RequiredMethod(ref m) => self.operation.visit_id(m.id),
|
||||||
ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id),
|
ast::ProvidedMethod(ref m) => self.operation.visit_id(m.id),
|
||||||
ast::TypeTraitItem(ref typ) => self.operation.visit_id(typ.id),
|
ast::TypeTraitItem(ref typ) => self.operation.visit_id(typ.ty_param.id),
|
||||||
}
|
}
|
||||||
visit::walk_trait_item(self, tm);
|
visit::walk_trait_item(self, tm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,7 +260,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
|
||||||
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
|
ast::RequiredMethod(_) | ast::ProvidedMethod(_) => {}
|
||||||
ast::TypeTraitItem(ref ti) => {
|
ast::TypeTraitItem(ref ti) => {
|
||||||
self.gate_feature("associated_types",
|
self.gate_feature("associated_types",
|
||||||
ti.span,
|
ti.ty_param.span,
|
||||||
"associated types are experimental")
|
"associated types are experimental")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -793,19 +793,16 @@ pub fn noop_fold_typedef<T>(t: Typedef, folder: &mut T)
|
||||||
|
|
||||||
pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T)
|
pub fn noop_fold_associated_type<T>(at: AssociatedType, folder: &mut T)
|
||||||
-> AssociatedType
|
-> AssociatedType
|
||||||
where T: Folder {
|
where T: Folder
|
||||||
let new_id = folder.new_id(at.id);
|
{
|
||||||
let new_span = folder.new_span(at.span);
|
|
||||||
let new_ident = folder.fold_ident(at.ident);
|
|
||||||
let new_attrs = at.attrs
|
let new_attrs = at.attrs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|attr| folder.fold_attribute((*attr).clone()))
|
.map(|attr| folder.fold_attribute((*attr).clone()))
|
||||||
.collect();
|
.collect();
|
||||||
|
let new_param = folder.fold_ty_param(at.ty_param);
|
||||||
ast::AssociatedType {
|
ast::AssociatedType {
|
||||||
ident: new_ident,
|
|
||||||
attrs: new_attrs,
|
attrs: new_attrs,
|
||||||
id: new_id,
|
ty_param: new_param,
|
||||||
span: new_span,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1229,16 +1229,13 @@ impl<'a> Parser<'a> {
|
||||||
/// Parses `type Foo;` in a trait declaration only. The `type` keyword has
|
/// Parses `type Foo;` in a trait declaration only. The `type` keyword has
|
||||||
/// already been parsed.
|
/// already been parsed.
|
||||||
fn parse_associated_type(&mut self, attrs: Vec<Attribute>)
|
fn parse_associated_type(&mut self, attrs: Vec<Attribute>)
|
||||||
-> AssociatedType {
|
-> AssociatedType
|
||||||
let lo = self.span.lo;
|
{
|
||||||
let ident = self.parse_ident();
|
let ty_param = self.parse_ty_param();
|
||||||
let hi = self.span.hi;
|
|
||||||
self.expect(&token::Semi);
|
self.expect(&token::Semi);
|
||||||
AssociatedType {
|
AssociatedType {
|
||||||
id: ast::DUMMY_NODE_ID,
|
|
||||||
span: mk_sp(lo, hi),
|
|
||||||
ident: ident,
|
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
|
ty_param: ty_param,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -815,9 +815,11 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_associated_type(&mut self, typedef: &ast::AssociatedType)
|
fn print_associated_type(&mut self, typedef: &ast::AssociatedType)
|
||||||
-> IoResult<()> {
|
-> IoResult<()>
|
||||||
|
{
|
||||||
|
try!(self.print_outer_attributes(typedef.attrs[]));
|
||||||
try!(self.word_space("type"));
|
try!(self.word_space("type"));
|
||||||
try!(self.print_ident(typedef.ident));
|
try!(self.print_ty_param(&typedef.ty_param));
|
||||||
word(&mut self.s, ";")
|
word(&mut self.s, ";")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2431,23 +2433,7 @@ impl<'a> State<'a> {
|
||||||
} else {
|
} else {
|
||||||
let idx = idx - generics.lifetimes.len();
|
let idx = idx - generics.lifetimes.len();
|
||||||
let param = generics.ty_params.get(idx);
|
let param = generics.ty_params.get(idx);
|
||||||
match param.unbound {
|
s.print_ty_param(param)
|
||||||
Some(TraitTyParamBound(ref tref)) => {
|
|
||||||
try!(s.print_trait_ref(tref));
|
|
||||||
try!(s.word_space("?"));
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
try!(s.print_ident(param.ident));
|
|
||||||
try!(s.print_bounds(":", ¶m.bounds));
|
|
||||||
match param.default {
|
|
||||||
Some(ref default) => {
|
|
||||||
try!(space(&mut s.s));
|
|
||||||
try!(s.word_space("="));
|
|
||||||
s.print_type(&**default)
|
|
||||||
}
|
|
||||||
_ => Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -2455,6 +2441,26 @@ impl<'a> State<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> {
|
||||||
|
match param.unbound {
|
||||||
|
Some(TraitTyParamBound(ref tref)) => {
|
||||||
|
try!(self.print_trait_ref(tref));
|
||||||
|
try!(self.word_space("?"));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
try!(self.print_ident(param.ident));
|
||||||
|
try!(self.print_bounds(":", ¶m.bounds));
|
||||||
|
match param.default {
|
||||||
|
Some(ref default) => {
|
||||||
|
try!(space(&mut self.s));
|
||||||
|
try!(self.word_space("="));
|
||||||
|
self.print_type(&**default)
|
||||||
|
}
|
||||||
|
_ => Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print_where_clause(&mut self, generics: &ast::Generics)
|
pub fn print_where_clause(&mut self, generics: &ast::Generics)
|
||||||
-> IoResult<()> {
|
-> IoResult<()> {
|
||||||
if generics.where_clause.predicates.len() == 0 {
|
if generics.where_clause.predicates.len() == 0 {
|
||||||
|
|
|
@ -596,7 +596,8 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_method: &'v Tr
|
||||||
RequiredMethod(ref method_type) => visitor.visit_ty_method(method_type),
|
RequiredMethod(ref method_type) => visitor.visit_ty_method(method_type),
|
||||||
ProvidedMethod(ref method) => walk_method_helper(visitor, &**method),
|
ProvidedMethod(ref method) => walk_method_helper(visitor, &**method),
|
||||||
TypeTraitItem(ref associated_type) => {
|
TypeTraitItem(ref associated_type) => {
|
||||||
visitor.visit_ident(associated_type.span, associated_type.ident)
|
visitor.visit_ident(associated_type.ty_param.span,
|
||||||
|
associated_type.ty_param.ident)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
24
src/test/compile-fail/associated-types-unsized.rs
Normal file
24
src/test/compile-fail/associated-types-unsized.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#![feature(associated_types)]
|
||||||
|
|
||||||
|
trait Get {
|
||||||
|
type Sized? Value;
|
||||||
|
fn get(&self) -> <Self as Get>::Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo<T:Get>(t: T) {
|
||||||
|
let x = t.get(); //~ ERROR the trait `core::kinds::Sized` is not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
// Regions that just appear in normal spots are contravariant:
|
// Regions that just appear in normal spots are contravariant:
|
||||||
|
|
||||||
#[rustc_variance]
|
#[rustc_variance]
|
||||||
struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]]
|
struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[];[]]
|
||||||
x: &'a int,
|
x: &'a int,
|
||||||
y: &'b [int],
|
y: &'b [int],
|
||||||
c: &'c str
|
c: &'c str
|
||||||
|
@ -23,7 +23,7 @@ struct Test2<'a, 'b, 'c> { //~ ERROR regions=[[-, -, -];[];[]]
|
||||||
// Those same annotations in function arguments become covariant:
|
// Those same annotations in function arguments become covariant:
|
||||||
|
|
||||||
#[rustc_variance]
|
#[rustc_variance]
|
||||||
struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]]
|
struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[];[]]
|
||||||
x: extern "Rust" fn(&'a int),
|
x: extern "Rust" fn(&'a int),
|
||||||
y: extern "Rust" fn(&'b [int]),
|
y: extern "Rust" fn(&'b [int]),
|
||||||
c: extern "Rust" fn(&'c str),
|
c: extern "Rust" fn(&'c str),
|
||||||
|
@ -32,7 +32,7 @@ struct Test3<'a, 'b, 'c> { //~ ERROR regions=[[+, +, +];[];[]]
|
||||||
// Mutability induces invariance:
|
// Mutability induces invariance:
|
||||||
|
|
||||||
#[rustc_variance]
|
#[rustc_variance]
|
||||||
struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]]
|
struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[];[]]
|
||||||
x: &'a mut &'b int,
|
x: &'a mut &'b int,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ struct Test4<'a, 'b:'a> { //~ ERROR regions=[[-, o];[];[]]
|
||||||
// contravariant context:
|
// contravariant context:
|
||||||
|
|
||||||
#[rustc_variance]
|
#[rustc_variance]
|
||||||
struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[]]
|
struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[];[]]
|
||||||
x: extern "Rust" fn(&'a mut &'b int),
|
x: extern "Rust" fn(&'a mut &'b int),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,21 +50,21 @@ struct Test5<'a, 'b> { //~ ERROR regions=[[+, o];[];[]]
|
||||||
// argument list occurs in an invariant context.
|
// argument list occurs in an invariant context.
|
||||||
|
|
||||||
#[rustc_variance]
|
#[rustc_variance]
|
||||||
struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[]]
|
struct Test6<'a, 'b> { //~ ERROR regions=[[-, o];[];[];[]]
|
||||||
x: &'a mut extern "Rust" fn(&'b int),
|
x: &'a mut extern "Rust" fn(&'b int),
|
||||||
}
|
}
|
||||||
|
|
||||||
// No uses at all is bivariant:
|
// No uses at all is bivariant:
|
||||||
|
|
||||||
#[rustc_variance]
|
#[rustc_variance]
|
||||||
struct Test7<'a> { //~ ERROR regions=[[*];[];[]]
|
struct Test7<'a> { //~ ERROR regions=[[*];[];[];[]]
|
||||||
x: int
|
x: int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try enums too.
|
// Try enums too.
|
||||||
|
|
||||||
#[rustc_variance]
|
#[rustc_variance]
|
||||||
enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]]
|
enum Test8<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[];[]]
|
||||||
Test8A(extern "Rust" fn(&'a int)),
|
Test8A(extern "Rust" fn(&'a int)),
|
||||||
Test8B(&'b [int]),
|
Test8B(&'b [int]),
|
||||||
Test8C(&'b mut &'c str),
|
Test8C(&'b mut &'c str),
|
||||||
|
|
|
@ -13,29 +13,29 @@
|
||||||
// Try enums too.
|
// Try enums too.
|
||||||
|
|
||||||
#[rustc_variance]
|
#[rustc_variance]
|
||||||
enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]]
|
enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[];[]]
|
||||||
Test8A(extern "Rust" fn(&'a int)),
|
Test8A(extern "Rust" fn(&'a int)),
|
||||||
Test8B(&'b [int]),
|
Test8B(&'b [int]),
|
||||||
Test8C(&'b mut &'c str),
|
Test8C(&'b mut &'c str),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_variance]
|
#[rustc_variance]
|
||||||
struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[]]
|
struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[];[]]
|
||||||
f: Base<'z, 'y, 'x, 'w>
|
f: Base<'z, 'y, 'x, 'w>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_variance] // Combine - and + to yield o
|
#[rustc_variance] // Combine - and + to yield o
|
||||||
struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[]]
|
struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[];[]]
|
||||||
f: Base<'a, 'a, 'b, 'c>
|
f: Base<'a, 'a, 'b, 'c>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
|
#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
|
||||||
struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[]]
|
struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[];[]]
|
||||||
f: Base<'a, 'b, 'a, 'c>
|
f: Base<'a, 'b, 'a, 'c>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here)
|
#[rustc_variance] // Combine + and * to yield + (just pay attention to 'a here)
|
||||||
struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[]]
|
struct Derived4<'a, 'b, 'c:'b> { //~ ERROR regions=[[+, -, o];[];[];[]]
|
||||||
f: Base<'a, 'b, 'c, 'a>
|
f: Base<'a, 'b, 'c, 'a>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ use std::mem;
|
||||||
trait T { fn foo(); }
|
trait T { fn foo(); }
|
||||||
|
|
||||||
#[rustc_variance]
|
#[rustc_variance]
|
||||||
struct TOption<'a> { //~ ERROR regions=[[-];[];[]]
|
struct TOption<'a> { //~ ERROR regions=[[-];[];[];[]]
|
||||||
v: Option<Box<T + 'a>>,
|
v: Option<Box<T + 'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue