use middle::stability;
use middle::subst::{Subst, Substs, VecPerParamSpace};
use middle::subst;
+use middle::traits;
use middle::ty;
use middle::typeck;
use middle::ty_fold;
#[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,
// An unsize coercion applied to the tail field of a struct.
// The uint is the index of the type parameter which is unsized.
UnsizeStruct(Box<UnsizeKind>, uint),
- UnsizeVtable(ty::ExistentialBounds,
- ast::DefId, /* Trait ID */
- subst::Substs /* Trait substitutions */)
+ UnsizeVtable(TyTrait, /* the self type of the trait */ ty::t)
}
#[deriving(Clone)]
fn type_of_autoref(cx: &ctxt, autoref: &AutoRef) -> Option<t> {
match autoref {
&AutoUnsize(ref k) => match k {
- &UnsizeVtable(bounds, def_id, ref substs) => {
+ &UnsizeVtable(TyTrait { def_id, substs: ref substs, bounds }, _) => {
Some(mk_trait(cx, def_id, substs.clone(), bounds))
}
_ => None
},
&AutoUnsizeUniq(ref k) => match k {
- &UnsizeVtable(bounds, def_id, ref substs) => {
+ &UnsizeVtable(TyTrait { def_id, substs: ref substs, bounds }, _) => {
Some(mk_uniq(cx, mk_trait(cx, def_id, substs.clone(), bounds)))
}
_ => None
pub trait_refs: RefCell<NodeMap<Rc<TraitRef>>>,
pub trait_defs: RefCell<DefIdMap<Rc<TraitDef>>>,
+ /// Maps from node-id of a trait object cast (like `foo as
+ /// Box<Trait>`) to the trait reference.
+ pub object_cast_map: typeck::ObjectCastMap,
+
pub map: ast_map::Map<'tcx>,
pub intrinsic_defs: RefCell<DefIdMap<t>>,
pub freevars: RefCell<freevars::freevar_map>,
/// Maps a DefId of a type to a list of its inherent impls.
/// Contains implementations of methods that are inherent to a type.
/// Methods in these implementations don't need to be exported.
- pub inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
+ pub inherent_impls: RefCell<DefIdMap<Rc<Vec<ast::DefId>>>>,
/// Maps a DefId of an impl to a list of its items.
/// Note that this contains all of the impls that we know about,
/// about.
pub used_mut_nodes: RefCell<NodeSet>,
- /// vtable resolution information for impl declarations
- pub impl_vtables: typeck::impl_vtable_map,
-
/// The set of external nominal types whose implementations have been read.
/// This is used for lazy resolution of methods.
pub populated_external_types: RefCell<DefIdSet>,
pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>,
pub method_map: typeck::MethodMap,
- pub vtable_map: typeck::vtable_map,
pub dependency_formats: RefCell<dependency_format::Dependencies>,
/// 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)) => {
item_substs: RefCell::new(NodeMap::new()),
trait_refs: RefCell::new(NodeMap::new()),
trait_defs: RefCell::new(DefIdMap::new()),
+ object_cast_map: RefCell::new(NodeMap::new()),
map: map,
intrinsic_defs: RefCell::new(DefIdMap::new()),
freevars: RefCell::new(freevars),
impl_items: RefCell::new(DefIdMap::new()),
used_unsafe: RefCell::new(NodeSet::new()),
used_mut_nodes: RefCell::new(NodeSet::new()),
- impl_vtables: RefCell::new(DefIdMap::new()),
populated_external_types: RefCell::new(DefIdSet::new()),
populated_external_traits: RefCell::new(DefIdSet::new()),
upvar_borrow_map: RefCell::new(HashMap::new()),
extern_const_statics: RefCell::new(DefIdMap::new()),
extern_const_variants: RefCell::new(DefIdMap::new()),
method_map: RefCell::new(FnvHashMap::new()),
- vtable_map: RefCell::new(FnvHashMap::new()),
dependency_formats: RefCell::new(HashMap::new()),
unboxed_closures: RefCell::new(DefIdMap::new()),
node_lint_levels: RefCell::new(HashMap::new()),
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 {
}
pub fn type_is_trait(ty: t) -> bool {
+ type_trait_info(ty).is_some()
+}
+
+pub fn type_trait_info(ty: t) -> Option<&'static TyTrait> {
match get(ty).sty {
ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) | ty_ptr(mt { ty, ..}) => match get(ty).sty {
- ty_trait(..) => true,
- _ => false
+ ty_trait(ref t) => Some(&**t),
+ _ => None
},
- ty_trait(..) => true,
- _ => false
+ ty_trait(ref t) => Some(&**t),
+ _ => None
}
}
format!("UnsizeStruct with bad sty: {}",
ty_to_string(cx, ty)).as_slice())
},
- &UnsizeVtable(bounds, def_id, ref substs) => {
+ &UnsizeVtable(TyTrait { def_id, substs: ref substs, bounds }, _) => {
mk_trait(cx, def_id, substs.clone(), bounds)
}
}
}
pub fn method_call_type_param_defs<'tcx, T>(typer: &T,
- origin: typeck::MethodOrigin)
+ origin: &typeck::MethodOrigin)
-> VecPerParamSpace<TypeParameterDef>
where T: mc::Typer<'tcx> {
- match origin {
+ match *origin {
typeck::MethodStatic(did) => {
ty::lookup_item_type(typer.tcx(), did).generics.types.clone()
}
lookup_trait_def(typer.tcx(), def_id).generics.types.clone()
}
typeck::MethodParam(typeck::MethodParam{
- trait_id: trt_id,
+ trait_ref: ref trait_ref,
method_num: n_mth,
..
}) |
typeck::MethodObject(typeck::MethodObject{
- trait_id: trt_id,
+ trait_ref: ref trait_ref,
method_num: n_mth,
..
}) => {
- match ty::trait_item(typer.tcx(), trt_id, n_mth) {
+ 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 => {
ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
ty_box(_) => "Gc-ptr".to_string(),
ty_uniq(_) => "box".to_string(),
- ty_vec(_, _) => "vector".to_string(),
+ ty_vec(_, Some(_)) => "array".to_string(),
+ ty_vec(_, None) => "unsized array".to_string(),
ty_ptr(_) => "*-ptr".to_string(),
ty_rptr(_, _) => "&-ptr".to_string(),
ty_bare_fn(_) => "extern fn".to_string(),
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",
|| csearch::get_type(cx, did))
}
-pub fn lookup_impl_vtables(cx: &ctxt,
- did: ast::DefId)
- -> typeck::vtable_res {
- lookup_locally_or_in_crate_store(
- "impl_vtables", did, &mut *cx.impl_vtables.borrow_mut(),
- || csearch::get_impl_vtables(cx, did) )
-}
-
/// Given the did of a trait, returns its canonical trait ref.
pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> Rc<ty::TraitDef> {
let mut trait_defs = cx.trait_defs.borrow_mut();
let mut acc = Vec::new();
ty::each_attr(tcx, did, |meta| {
- acc.extend(attr::find_repr_attrs(tcx.sess.diagnostic(), meta).move_iter());
+ acc.extend(attr::find_repr_attrs(tcx.sess.diagnostic(), meta).into_iter());
true
});
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={}",
return
}
+ let mut inherent_impls = Vec::new();
csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
|impl_def_id| {
let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
.insert(method_def_id, source);
}
}
+ TypeTraitItem(_) => {}
}
}
// If this is an inherent implementation, record it.
if associated_traits.is_none() {
- match tcx.inherent_impls.borrow().find(&type_id) {
- Some(implementation_list) => {
- implementation_list.borrow_mut().push(impl_def_id);
- return;
- }
- None => {}
- }
- tcx.inherent_impls.borrow_mut().insert(type_id,
- Rc::new(RefCell::new(vec!(impl_def_id))));
+ inherent_impls.push(impl_def_id);
}
});
+ tcx.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls));
tcx.populated_external_types.borrow_mut().insert(type_id);
}
.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);
}
}
}
- ty_trait(box ty::TyTrait { def_id: d, bounds, .. }) => {
+ ty_trait(box TyTrait { def_id: d, bounds, .. }) => {
byte!(17);
did(&mut state, d);
hash!(bounds);
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);
}
}
}
+ pub fn to_mutbl_lossy(self) -> ast::Mutability {
+ /*!
+ * Returns a mutability `m` such that an `&m T` pointer could
+ * be used to obtain this borrow kind. Because borrow kinds
+ * are richer than mutabilities, we sometimes have to pick a
+ * mutability that is stronger than necessary so that it at
+ * least *would permit* the borrow in question.
+ */
+
+ match self {
+ MutBorrow => ast::MutMutable,
+ ImmBorrow => ast::MutImmutable,
+
+ // We have no type correponding to a unique imm borrow, so
+ // use `&mut`. It gives all the capabilities of an `&uniq`
+ // and hence is a safe "over approximation".
+ UniqueImmBorrow => ast::MutMutable,
+ }
+ }
+
pub fn to_user_str(&self) -> &'static str {
match *self {
MutBorrow => "mutable",