#[deriving(Clone)]
pub enum ImplOrTraitItem {
MethodTraitItem(Rc<Method>),
+ TypeTraitItem(Rc<AssociatedType>),
}
impl ImplOrTraitItem {
fn id(&self) -> ImplOrTraitItemId {
match *self {
MethodTraitItem(ref method) => MethodTraitItemId(method.def_id),
+ TypeTraitItem(ref associated_type) => {
+ TypeTraitItemId(associated_type.def_id)
+ }
}
}
pub fn def_id(&self) -> ast::DefId {
match *self {
MethodTraitItem(ref method) => method.def_id,
+ TypeTraitItem(ref associated_type) => associated_type.def_id,
}
}
pub fn ident(&self) -> ast::Ident {
match *self {
MethodTraitItem(ref method) => method.ident,
+ TypeTraitItem(ref associated_type) => associated_type.ident,
}
}
pub fn container(&self) -> ImplOrTraitItemContainer {
match *self {
MethodTraitItem(ref method) => method.container,
+ TypeTraitItem(ref associated_type) => associated_type.container,
}
}
}
#[deriving(Clone)]
pub enum ImplOrTraitItemId {
MethodTraitItemId(ast::DefId),
+ TypeTraitItemId(ast::DefId),
}
impl ImplOrTraitItemId {
pub fn def_id(&self) -> ast::DefId {
match *self {
MethodTraitItemId(def_id) => def_id,
+ TypeTraitItemId(def_id) => def_id,
}
}
}
}
}
+#[deriving(Clone)]
+pub struct AssociatedType {
+ pub ident: ast::Ident,
+ pub vis: ast::Visibility,
+ pub def_id: ast::DefId,
+ pub container: ImplOrTraitItemContainer,
+}
+
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
pub struct mt {
pub ty: t,
/// Maps closures to their capture clauses.
pub capture_modes: RefCell<CaptureModeMap>,
+
+ /// Maps def IDs to true if and only if they're associated types.
+ 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>>>>,
}
pub enum tbox_flag {
/// as well as the existential type parameter in an object type.
#[deriving(PartialEq, Eq, Hash, Clone, Show)]
pub struct ParamBounds {
- pub opt_region_bound: Option<ty::Region>,
+ pub region_bounds: Vec<ty::Region>,
pub builtin_bounds: BuiltinBounds,
pub trait_bounds: Vec<Rc<TraitRef>>
}
/// Bounds suitable for an existentially quantified type parameter
/// such as those that appear in object types or closure types. The
/// major difference between this case and `ParamBounds` is that
-/// general purpose trait bounds are omitted.
+/// general purpose trait bounds are omitted and there must be
+/// *exactly one* region.
#[deriving(PartialEq, Eq, Hash, Clone, Show)]
pub struct ExistentialBounds {
pub region_bound: ty::Region,
pub def_id: ast::DefId,
pub space: subst::ParamSpace,
pub index: uint,
+ pub associated_with: Option<ast::DefId>,
pub bounds: ParamBounds,
pub default: Option<ty::t>,
}
/// the "outer" view of a type or method to the "inner" view.
/// In general, this means converting from bound parameters to
/// free parameters. Since we currently represent bound/free type
- /// parameters in the same way, this only has an affect on regions.
+ /// parameters in the same way, this only has an effect on regions.
pub free_substs: Substs,
/// Bounds on the various type parameters
method_generics,
method.pe_body().id)
}
+ TypeTraitItem(_) => {
+ cx.sess
+ .bug("ParameterEnvironment::from_item(): \
+ can't create a parameter environment \
+ for type trait items")
+ }
}
}
+ ast::TypeImplItem(_) => {
+ cx.sess.bug("ParameterEnvironment::from_item(): \
+ can't create a parameter environment \
+ for type impl items")
+ }
}
}
Some(ast_map::NodeTraitItem(trait_method)) => {
method_generics,
method.pe_body().id)
}
+ TypeTraitItem(_) => {
+ cx.sess
+ .bug("ParameterEnvironment::from_item(): \
+ can't create a parameter environment \
+ for type trait items")
+ }
}
}
+ ast::TypeTraitItem(_) => {
+ cx.sess.bug("ParameterEnvironment::from_item(): \
+ can't create a parameter environment \
+ for type trait items")
+ }
}
}
Some(ast_map::NodeItem(item)) => {
transmute_restrictions: RefCell::new(Vec::new()),
stability: RefCell::new(stability),
capture_modes: RefCell::new(capture_modes),
+ associated_types: RefCell::new(DefIdMap::new()),
+ trait_associated_types: RefCell::new(DefIdMap::new()),
}
}
pub fn to_ty(self, tcx: &ty::ctxt) -> ty::t {
ty::mk_param(tcx, self.space, self.idx, self.def_id)
}
+
+ pub fn is_self(&self) -> bool {
+ self.space == subst::SelfSpace && self.idx == 0
+ }
}
impl ItemSubsts {
}) => {
match ty::trait_item(typer.tcx(), trait_ref.def_id, n_mth) {
ty::MethodTraitItem(method) => method.generics.types.clone(),
+ ty::TypeTraitItem(_) => {
+ typer.tcx().sess.bug("method_call_type_param_defs() \
+ called on associated type")
+ }
}
}
}
// DefArg's, particularly those of immediate type, ought to
// considered rvalues.
def::DefStatic(..) |
- def::DefBinding(..) |
def::DefUpvar(..) |
- def::DefArg(..) |
def::DefLocal(..) => LvalueExpr,
def => {
Some(ast_map::NodeItem(item)) => {
match item.node {
ItemTrait(_, _, _, ref ms) => {
- ms.iter().filter_map(|m| match *m {
- ast::RequiredMethod(_) => None,
- ast::ProvidedMethod(ref m) => {
- match impl_or_trait_item(cx,
- ast_util::local_def(m.id)) {
- MethodTraitItem(m) => Some(m),
+ let (_, p) =
+ ast_util::split_trait_methods(ms.as_slice());
+ p.iter()
+ .map(|m| {
+ match impl_or_trait_item(
+ cx,
+ ast_util::local_def(m.id)) {
+ MethodTraitItem(m) => m,
+ TypeTraitItem(_) => {
+ cx.sess.bug("provided_trait_methods(): \
+ split_trait_methods() put \
+ associated types in the \
+ provided method bucket?!")
}
}
}).collect()
})
}
+/// Returns true if the given ID refers to an associated type and false if it
+/// refers to anything else.
+pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
+ let result = match cx.associated_types.borrow_mut().find(&id) {
+ Some(result) => return *result,
+ None if id.krate == ast::LOCAL_CRATE => {
+ match cx.impl_or_trait_items.borrow().find(&id) {
+ Some(ref item) => {
+ match **item {
+ TypeTraitItem(_) => true,
+ MethodTraitItem(_) => false,
+ }
+ }
+ None => false,
+ }
+ }
+ None => {
+ csearch::is_associated_type(&cx.sess.cstore, id)
+ }
+ };
+
+ cx.associated_types.borrow_mut().insert(id, result);
+ result
+}
+
+/// Returns the parameter index that the given associated type corresponds to.
+pub fn associated_type_parameter_index(cx: &ctxt,
+ trait_def: &TraitDef,
+ associated_type_id: ast::DefId)
+ -> uint {
+ for type_parameter_def in trait_def.generics.types.iter() {
+ if type_parameter_def.def_id == associated_type_id {
+ return type_parameter_def.index
+ }
+ }
+ cx.sess.bug("couldn't find associated type parameter index")
+}
+
+#[deriving(PartialEq, Eq)]
+pub struct AssociatedTypeInfo {
+ pub def_id: ast::DefId,
+ pub index: uint,
+ pub ident: ast::Ident,
+}
+
+impl PartialOrd for AssociatedTypeInfo {
+ fn partial_cmp(&self, other: &AssociatedTypeInfo) -> Option<Ordering> {
+ Some(self.index.cmp(&other.index))
+ }
+}
+
+impl Ord for AssociatedTypeInfo {
+ fn cmp(&self, other: &AssociatedTypeInfo) -> Ordering {
+ self.index.cmp(&other.index)
+ }
+}
+
+/// 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)
-> Rc<Vec<ImplOrTraitItemId>> {
lookup_locally_or_in_crate_store("trait_item_def_ids",
trait_bounds,
|trait_ref| {
let bounds = ty::bounds_for_trait_ref(tcx, &*trait_ref);
- push_region_bounds(bounds.opt_region_bound.as_slice(),
+ push_region_bounds(bounds.region_bounds.as_slice(),
bounds.builtin_bounds,
&mut all_bounds);
debug!("from {}: bounds={} all_bounds={}",
.insert(method_def_id, source);
}
}
+ TypeTraitItem(_) => {}
}
}
.insert(method_def_id, source);
}
}
+ TypeTraitItem(_) => {}
}
}
Some(m) => m.clone(),
None => return None,
};
- let name = match impl_item {
- MethodTraitItem(method) => method.ident.name,
- };
+ let name = impl_item.ident().name;
match trait_of_item(tcx, def_id) {
Some(trait_did) => {
let trait_items = ty::trait_items(tcx, trait_did);
space: subst::ParamSpace,
defs: &[TypeParameterDef]) {
for (i, def) in defs.iter().enumerate() {
+ debug!("construct_parameter_environment(): push_types_from_defs: \
+ space={} def={} index={}",
+ space,
+ def.repr(tcx),
+ i);
let ty = ty::mk_param(tcx, space, i, def.def_id);
types.push(space, ty);
}