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;
use std::fmt::Show;
use std::fmt;
use std::hash::{Hash, sip, Writer};
-use std::gc::Gc;
use std::iter::AdditiveIterator;
use std::mem;
use std::ops;
#[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>>>,
- pub map: ast_map::Map,
+ /// 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>,
pub tcache: type_cache,
/// 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>,
/// These two caches are used by const_eval when decoding external statics
/// and variants that are found.
- pub extern_const_statics: RefCell<DefIdMap<Option<Gc<ast::Expr>>>>,
- pub extern_const_variants: RefCell<DefIdMap<Option<Gc<ast::Expr>>>>,
+ pub extern_const_statics: RefCell<DefIdMap<ast::NodeId>>,
+ 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 {
terr_float_mismatch(expected_found<ast::FloatTy>),
terr_traits(expected_found<ast::DefId>),
terr_builtin_bounds(expected_found<BuiltinBounds>),
- terr_variadic_mismatch(expected_found<bool>)
+ terr_variadic_mismatch(expected_found<bool>),
+ terr_cyclic_ty,
}
/// Bounds suitable for a named type parameter like `A` in `fn foo<A>`
/// 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 enum InferTy {
TyVar(TyVid),
IntVar(IntVid),
- FloatVar(FloatVid)
+ FloatVar(FloatVid),
+ SkolemizedTy(uint),
+
+ // FIXME -- once integral fallback is impl'd, we should remove
+ // this type. It's only needed to prevent spurious errors for
+ // integers whose type winds up never being constrained.
+ SkolemizedIntTy(uint),
}
#[deriving(Clone, Encodable, Decodable, Eq, Hash, Show)]
TyVar(ref v) => v.fmt(f),
IntVar(ref v) => v.fmt(f),
FloatVar(ref v) => v.fmt(f),
+ SkolemizedTy(v) => write!(f, "SkolemizedTy({})", v),
+ SkolemizedIntTy(v) => write!(f, "SkolemizedIntTy({})", v),
}
}
}
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>,
}
}
}
+impl TraitRef {
+ pub fn self_ty(&self) -> ty::t {
+ self.substs.self_ty().unwrap()
+ }
+}
+
/// When type checking, we use the `ParameterEnvironment` to track
/// details about the type/lifetime parameters that are in scope.
/// It primarily stores the bounds information.
/// 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
/// may specify stronger requirements). This field indicates the
/// region of the callee.
pub implicit_region_bound: ty::Region,
+
+ /// Obligations that the caller must satisfy. This is basically
+ /// the set of bounds on the in-scope type parameters, translated
+ /// into Obligations.
+ ///
+ /// Note: This effectively *duplicates* the `bounds` array for
+ /// now.
+ pub caller_obligations: VecPerParamSpace<traits::Obligation>,
}
impl ParameterEnvironment {
let method_generics = &method_ty.generics;
construct_parameter_environment(
cx,
+ method.span,
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)) => {
let method_generics = &method_ty.generics;
construct_parameter_environment(
cx,
+ method.span,
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)) => {
let fn_pty = ty::lookup_item_type(cx, fn_def_id);
construct_parameter_environment(cx,
+ item.span,
&fn_pty.generics,
body.id)
}
ast::ItemStatic(..) => {
let def_id = ast_util::local_def(id);
let pty = ty::lookup_item_type(cx, def_id);
- construct_parameter_environment(cx, &pty.generics, id)
+ construct_parameter_environment(cx, item.span,
+ &pty.generics, id)
}
_ => {
cx.sess.span_bug(item.span,
/// As `Polytype` but for a trait ref.
pub struct TraitDef {
+ /// Generic type definitions. Note that `Self` is listed in here
+ /// as having a single bound, the trait itself (e.g., in the trait
+ /// `Eq`, there is a single bound `Self : Eq`). This is so that
+ /// default methods get to assume that the `Self` parameters
+ /// implements the trait.
pub generics: Generics,
+
+ /// The "supertrait" bounds.
pub bounds: ParamBounds,
pub trait_ref: Rc<ty::TraitRef>,
}
pub type node_type_table = RefCell<HashMap<uint,t>>;
/// Records information about each unboxed closure.
+#[deriving(Clone)]
pub struct UnboxedClosure {
/// The type of the unboxed closure.
pub closure_type: ClosureTy,
pub kind: UnboxedClosureKind,
}
-#[deriving(PartialEq, Eq)]
+#[deriving(Clone, PartialEq, Eq)]
pub enum UnboxedClosureKind {
FnUnboxedClosureKind,
FnMutUnboxedClosureKind,
type_arena: &'tcx TypedArena<t_box_>,
dm: resolve::DefMap,
named_region_map: resolve_lifetime::NamedRegionMap,
- map: ast_map::Map,
+ map: ast_map::Map<'tcx>,
freevars: freevars::freevar_map,
capture_modes: freevars::CaptureModeMap,
region_maps: middle::region::RegionMaps,
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()),
}
}
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
flags |= sflags(substs);
}
- &ty_trait(box ty::TyTrait { ref substs, ref bounds, .. }) => {
+ &ty_trait(box TyTrait { ref substs, ref bounds, .. }) => {
flags |= sflags(substs);
flags |= flags_for_bounds(bounds);
}
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 {
}
// Scalar and unique types are sendable, and durable
+ ty_infer(ty::SkolemizedIntTy(_)) |
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_bare_fn(_) | ty::ty_char => {
TC::None
}
}
- ty_trait(box ty::TyTrait { bounds, .. }) => {
+ ty_trait(box TyTrait { bounds, .. }) => {
object_contents(cx, bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
}
}
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
}
}
}
}
+pub fn type_is_skolemized(ty: t) -> bool {
+ match get(ty).sty {
+ ty_infer(SkolemizedTy(_)) => true,
+ ty_infer(SkolemizedIntTy(_)) => true,
+ _ => false
+ }
+}
+
pub fn type_is_uint(ty: t) -> bool {
match get(ty).sty {
ty_infer(IntVar(_)) | ty_uint(ast::TyU) => true,
pub fn unsized_part_of_type(cx: &ctxt, ty: t) -> t {
match get(ty).sty {
ty_str | ty_trait(..) | ty_vec(..) => ty,
- ty_struct(_, ref substs) => {
- // Exactly one of the type parameters must be unsized.
- for tp in substs.types.get_slice(subst::TypeSpace).iter() {
- if !type_is_sized(cx, *tp) {
- return unsized_part_of_type(cx, *tp);
- }
- }
- fail!("Unsized struct type with no unsized type params? {}", ty_to_string(cx, ty));
+ ty_struct(def_id, ref substs) => {
+ let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter()
+ .map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect();
+ // Exactly one of the fields must be unsized.
+ assert!(unsized_fields.len() == 1)
+
+ unsized_part_of_type(cx, unsized_fields[0])
}
_ => {
assert!(type_is_sized(cx, ty),
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 => {
RvalueDpsExpr
}
- ast::ExprLit(lit) if lit_is_str(lit) => {
+ ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
RvalueDpsExpr
}
RvalueDatumExpr
}
- ast::ExprBox(place, _) => {
+ ast::ExprBox(ref place, _) => {
// Special case `Box<T>`/`Gc<T>` for now:
let definition = match tcx.def_map.borrow().find(&place.id) {
Some(&def) => 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(),
ty_infer(TyVar(_)) => "inferred type".to_string(),
ty_infer(IntVar(_)) => "integral variable".to_string(),
ty_infer(FloatVar(_)) => "floating-point variable".to_string(),
+ ty_infer(SkolemizedTy(_)) => "skolemized type".to_string(),
+ ty_infer(SkolemizedIntTy(_)) => "skolemized integral type".to_string(),
ty_param(ref p) => {
if p.space == subst::SelfSpace {
"Self".to_string()
}
match *err {
+ terr_cyclic_ty => "cyclic type of infinite size".to_string(),
terr_mismatch => "types differ".to_string(),
terr_fn_style_mismatch(values) => {
format!("expected {} fn, found {} fn",
Some(ast_map::NodeItem(item)) => {
match item.node {
ItemTrait(_, _, _, ref ms) => {
- let (_, p) = ast_util::split_trait_methods(ms.as_slice());
+ 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()
+ }).collect()
}
_ => {
cx.sess.bug(format!("provided_trait_methods: `{}` is \
})
}
+/// 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",
expr, since check_enum_variants also updates the enum_var_cache
*/
match cx.map.get(id.node) {
- ast_map::NodeItem(item) => {
+ ast_map::NodeItem(ref item) => {
match item.node {
ast::ItemEnum(ref enum_definition, _) => {
let mut last_discriminant: Option<Disr> = None;
- Rc::new(enum_definition.variants.iter().map(|&variant| {
+ Rc::new(enum_definition.variants.iter().map(|variant| {
let mut discriminant = match last_discriminant {
Some(val) => val + 1,
};
last_discriminant = Some(discriminant);
- Rc::new(VariantInfo::from_ast_variant(cx, &*variant,
+ Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
discriminant))
}).collect())
}
|| 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
});
struct TypeNormalizer<'a, 'tcx: 'a>(&'a ctxt<'tcx>);
impl<'a, 'tcx> TypeFolder<'tcx> for TypeNormalizer<'a, 'tcx> {
- fn tcx<'a>(&'a self) -> &'a ctxt<'tcx> { let TypeNormalizer(c) = *self; c }
+ fn tcx(&self) -> &ctxt<'tcx> { let TypeNormalizer(c) = *self; c }
fn fold_ty(&mut self, t: ty::t) -> ty::t {
match self.tcx().normalized_cache.borrow().find_copy(&t) {
pub fn each_bound_trait_and_supertraits(tcx: &ctxt,
bounds: &[Rc<TraitRef>],
f: |Rc<TraitRef>| -> bool)
- -> bool {
- for bound_trait_ref in bounds.iter() {
- let mut supertrait_set = HashMap::new();
- let mut trait_refs = Vec::new();
- let mut i = 0;
-
- // Seed the worklist with the trait from the bound
- supertrait_set.insert(bound_trait_ref.def_id, ());
- trait_refs.push(bound_trait_ref.clone());
-
- // Add the given trait ty to the hash map
- while i < trait_refs.len() {
- debug!("each_bound_trait_and_supertraits(i={:?}, trait_ref={})",
- i, trait_refs.get(i).repr(tcx));
-
- if !f(trait_refs.get(i).clone()) {
- return false;
- }
-
- // Add supertraits to supertrait_set
- let trait_ref = trait_refs.get(i).clone();
- let trait_def = lookup_trait_def(tcx, trait_ref.def_id);
- for supertrait_ref in trait_def.bounds.trait_bounds.iter() {
- let supertrait_ref = supertrait_ref.subst(tcx, &trait_ref.substs);
- debug!("each_bound_trait_and_supertraits(supertrait_ref={})",
- supertrait_ref.repr(tcx));
-
- let d_id = supertrait_ref.def_id;
- if !supertrait_set.contains_key(&d_id) {
- // FIXME(#5527) Could have same trait multiple times
- supertrait_set.insert(d_id, ());
- trait_refs.push(supertrait_ref.clone());
- }
- }
-
- i += 1;
+ -> bool
+{
+ for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
+ if !f(bound_trait_ref) {
+ return false;
}
}
return 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);
}
}
+pub fn empty_parameter_environment() -> ParameterEnvironment {
+ /*!
+ * Construct a parameter environment suitable for static contexts
+ * or other contexts where there are no free type/lifetime
+ * parameters in scope.
+ */
+
+ ty::ParameterEnvironment { free_substs: Substs::empty(),
+ bounds: VecPerParamSpace::empty(),
+ caller_obligations: VecPerParamSpace::empty(),
+ implicit_region_bound: ty::ReEmpty }
+}
+
pub fn construct_parameter_environment(
tcx: &ctxt,
+ span: Span,
generics: &ty::Generics,
free_id: ast::NodeId)
-> ParameterEnvironment
free_substs.repr(tcx),
bounds.repr(tcx));
+ let obligations = traits::obligations_for_generics(tcx, traits::ObligationCause::misc(span),
+ generics, &free_substs);
+
return ty::ParameterEnvironment {
free_substs: free_substs,
bounds: bounds,
implicit_region_bound: ty::ReScope(free_id),
+ caller_obligations: obligations,
};
fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
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",