// except according to those terms.
pub use self::Variance::*;
-pub use self::DtorKind::*;
-pub use self::ImplOrTraitItemContainer::*;
+pub use self::AssociatedItemContainer::*;
pub use self::BorrowKind::*;
-pub use self::ImplOrTraitItem::*;
pub use self::IntVarValue::*;
pub use self::LvaluePreference::*;
pub use self::fold::TypeFoldable;
use dep_graph::{self, DepNode};
-use hir::map as ast_map;
+use hir::{map as hir_map, FreevarMap, TraitMap};
use middle;
-use hir::def::{Def, CtorKind, PathResolution, ExportMap};
-use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
+use hir::def::{Def, CtorKind, ExportMap};
+use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
+use middle::const_val::ConstVal;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
+use middle::resolve_lifetime::ObjectLifetimeDefault;
use mir::Mir;
use traits;
use ty;
use ty::subst::{Subst, Substs};
+use ty::util::IntTypeExt;
use ty::walk::TypeWalker;
use util::common::MemoizationMap;
-use util::nodemap::NodeSet;
-use util::nodemap::FnvHashMap;
+use util::nodemap::{NodeSet, FxHashMap};
use serialize::{self, Encodable, Encoder};
use std::borrow::Cow;
use std::cell::{Cell, RefCell, Ref};
+use std::collections::BTreeMap;
use std::hash::{Hash, Hasher};
-use std::iter;
use std::ops::Deref;
use std::rc::Rc;
use std::slice;
use std::mem;
use syntax::ast::{self, Name, NodeId};
use syntax::attr;
-use syntax::parse::token::{self, InternedString};
+use syntax::symbol::{Symbol, InternedString};
use syntax_pos::{DUMMY_SP, Span};
-
use rustc_const_math::ConstInt;
+use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter;
+
use hir;
-use hir::intravisit::Visitor;
+use hir::itemlikevisit::ItemLikeVisitor;
pub use self::sty::{Binder, DebruijnIndex};
-pub use self::sty::{BuiltinBound, BuiltinBounds};
-pub use self::sty::{BareFnTy, FnSig, PolyFnSig};
-pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitObject};
+pub use self::sty::{FnSig, PolyFnSig};
+pub use self::sty::{InferTy, ParamTy, ProjectionTy, ExistentialPredicate};
pub use self::sty::{ClosureSubsts, TypeAndMut};
pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef};
pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
pub use self::sty::Region::*;
pub use self::sty::TypeVariants::*;
-pub use self::sty::BuiltinBound::Send as BoundSend;
-pub use self::sty::BuiltinBound::Sized as BoundSized;
-pub use self::sty::BuiltinBound::Copy as BoundCopy;
-pub use self::sty::BuiltinBound::Sync as BoundSync;
-
pub use self::contents::TypeContents;
-pub use self::context::{TyCtxt, tls};
-pub use self::context::{CtxtArenas, Lift, Tables};
+pub use self::context::{TyCtxt, GlobalArenas, tls};
+pub use self::context::{Lift, TypeckTables};
pub use self::trait_def::{TraitDef, TraitFlags};
+pub use self::maps::queries;
+
pub mod adjustment;
pub mod cast;
pub mod error;
pub mod fast_reject;
pub mod fold;
+pub mod inhabitedness;
pub mod item_path;
pub mod layout;
pub mod _match;
mod contents;
mod context;
mod flags;
-mod ivar;
mod structural_impls;
mod sty;
-pub type Disr = ConstInt;
-
// Data types
/// The complete set of all analyses described in this module. This is
/// produced by the driver and fed to trans and later passes.
#[derive(Clone)]
-pub struct CrateAnalysis<'a> {
+pub struct CrateAnalysis {
pub export_map: ExportMap,
pub access_levels: middle::privacy::AccessLevels,
pub reachable: NodeSet,
- pub name: &'a str,
+ pub name: String,
pub glob_map: Option<hir::GlobMap>,
}
-#[derive(Copy, Clone)]
-pub enum DtorKind {
- NoDtor,
- TraitDtor
-}
-
-impl DtorKind {
- pub fn is_present(&self) -> bool {
- match *self {
- TraitDtor => true,
- _ => false
- }
- }
+#[derive(Clone)]
+pub struct Resolutions {
+ pub freevars: FreevarMap,
+ pub trait_map: TraitMap,
+ pub maybe_unused_trait_imports: NodeSet,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub enum ImplOrTraitItemContainer {
+pub enum AssociatedItemContainer {
TraitContainer(DefId),
ImplContainer(DefId),
}
-impl ImplOrTraitItemContainer {
+impl AssociatedItemContainer {
pub fn id(&self) -> DefId {
match *self {
TraitContainer(id) => id,
let header = ImplHeader {
impl_def_id: impl_def_id,
- self_ty: tcx.lookup_item_type(impl_def_id).ty,
+ self_ty: tcx.item_type(impl_def_id),
trait_ref: tcx.impl_trait_ref(impl_def_id),
- predicates: tcx.lookup_predicates(impl_def_id).predicates
+ predicates: tcx.item_predicates(impl_def_id).predicates
}.subst(tcx, impl_substs);
let traits::Normalized { value: mut header, obligations } =
}
}
-#[derive(Clone)]
-pub enum ImplOrTraitItem<'tcx> {
- ConstTraitItem(Rc<AssociatedConst<'tcx>>),
- MethodTraitItem(Rc<Method<'tcx>>),
- TypeTraitItem(Rc<AssociatedType<'tcx>>),
-}
-
-impl<'tcx> ImplOrTraitItem<'tcx> {
- pub fn def(&self) -> Def {
- match *self {
- ConstTraitItem(ref associated_const) => Def::AssociatedConst(associated_const.def_id),
- MethodTraitItem(ref method) => Def::Method(method.def_id),
- TypeTraitItem(ref ty) => Def::AssociatedTy(ty.def_id),
- }
- }
-
- pub fn def_id(&self) -> DefId {
- match *self {
- ConstTraitItem(ref associated_const) => associated_const.def_id,
- MethodTraitItem(ref method) => method.def_id,
- TypeTraitItem(ref associated_type) => associated_type.def_id,
- }
- }
+#[derive(Copy, Clone, Debug)]
+pub struct AssociatedItem {
+ pub def_id: DefId,
+ pub name: Name,
+ pub kind: AssociatedKind,
+ pub vis: Visibility,
+ pub defaultness: hir::Defaultness,
+ pub container: AssociatedItemContainer,
- pub fn name(&self) -> Name {
- match *self {
- ConstTraitItem(ref associated_const) => associated_const.name,
- MethodTraitItem(ref method) => method.name,
- TypeTraitItem(ref associated_type) => associated_type.name,
- }
- }
+ /// Whether this is a method with an explicit self
+ /// as its first argument, allowing method calls.
+ pub method_has_self_argument: bool,
+}
- pub fn vis(&self) -> Visibility {
- match *self {
- ConstTraitItem(ref associated_const) => associated_const.vis,
- MethodTraitItem(ref method) => method.vis,
- TypeTraitItem(ref associated_type) => associated_type.vis,
- }
- }
+#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
+pub enum AssociatedKind {
+ Const,
+ Method,
+ Type
+}
- pub fn container(&self) -> ImplOrTraitItemContainer {
- match *self {
- ConstTraitItem(ref associated_const) => associated_const.container,
- MethodTraitItem(ref method) => method.container,
- TypeTraitItem(ref associated_type) => associated_type.container,
+impl AssociatedItem {
+ pub fn def(&self) -> Def {
+ match self.kind {
+ AssociatedKind::Const => Def::AssociatedConst(self.def_id),
+ AssociatedKind::Method => Def::Method(self.def_id),
+ AssociatedKind::Type => Def::AssociatedTy(self.def_id),
}
}
- pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> {
- match *self {
- MethodTraitItem(ref m) => Some((*m).clone()),
- _ => None,
+ /// Tests whether the associated item admits a non-trivial implementation
+ /// for !
+ pub fn relevant_for_never<'tcx>(&self) -> bool {
+ match self.kind {
+ AssociatedKind::Const => true,
+ AssociatedKind::Type => true,
+ // FIXME(canndrew): Be more thorough here, check if any argument is uninhabited.
+ AssociatedKind::Method => !self.method_has_self_argument,
}
}
}
/// Visible everywhere (including in other crates).
Public,
/// Visible only in the given crate-local module.
- Restricted(NodeId),
+ Restricted(DefId),
/// Not visible anywhere in the local crate. This is the visibility of private external items.
- PrivateExternal,
+ Invisible,
}
-pub trait NodeIdTree {
- fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool;
-}
+pub trait DefIdTree: Copy {
+ fn parent(self, id: DefId) -> Option<DefId>;
+
+ fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
+ if descendant.krate != ancestor.krate {
+ return false;
+ }
-impl<'a> NodeIdTree for ast_map::Map<'a> {
- fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool {
- let mut node_ancestor = node;
- while node_ancestor != ancestor {
- let node_ancestor_parent = self.get_module_parent(node_ancestor);
- if node_ancestor_parent == node_ancestor {
- return false;
+ while descendant != ancestor {
+ match self.parent(descendant) {
+ Some(parent) => descendant = parent,
+ None => return false,
}
- node_ancestor = node_ancestor_parent;
}
true
}
}
+impl<'a, 'gcx, 'tcx> DefIdTree for TyCtxt<'a, 'gcx, 'tcx> {
+ fn parent(self, id: DefId) -> Option<DefId> {
+ self.def_key(id).parent.map(|index| DefId { index: index, ..id })
+ }
+}
+
impl Visibility {
pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self {
match *visibility {
hir::Public => Visibility::Public,
- hir::Visibility::Crate => Visibility::Restricted(ast::CRATE_NODE_ID),
- hir::Visibility::Restricted { id, .. } => match tcx.expect_def(id) {
+ hir::Visibility::Crate => Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)),
+ hir::Visibility::Restricted { ref path, .. } => match path.def {
// If there is no resolution, `resolve` will have already reported an error, so
// assume that the visibility is public to avoid reporting more privacy errors.
Def::Err => Visibility::Public,
- def => Visibility::Restricted(tcx.map.as_local_node_id(def.def_id()).unwrap()),
+ def => Visibility::Restricted(def.def_id()),
},
- hir::Inherited => Visibility::Restricted(tcx.map.get_module_parent(id)),
+ hir::Inherited => {
+ Visibility::Restricted(tcx.hir.local_def_id(tcx.hir.get_module_parent(id)))
+ }
}
}
/// Returns true if an item with this visibility is accessible from the given block.
- pub fn is_accessible_from<T: NodeIdTree>(self, block: NodeId, tree: &T) -> bool {
+ pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool {
let restriction = match self {
// Public items are visible everywhere.
Visibility::Public => return true,
// Private items from other crates are visible nowhere.
- Visibility::PrivateExternal => return false,
+ Visibility::Invisible => return false,
// Restricted items are visible in an arbitrary local module.
+ Visibility::Restricted(other) if other.krate != module.krate => return false,
Visibility::Restricted(module) => module,
};
- tree.is_descendant_of(block, restriction)
+ tree.is_descendant_of(module, restriction)
}
/// Returns true if this visibility is at least as accessible as the given visibility
- pub fn is_at_least<T: NodeIdTree>(self, vis: Visibility, tree: &T) -> bool {
+ pub fn is_at_least<T: DefIdTree>(self, vis: Visibility, tree: T) -> bool {
let vis_restriction = match vis {
Visibility::Public => return self == Visibility::Public,
- Visibility::PrivateExternal => return true,
+ Visibility::Invisible => return true,
Visibility::Restricted(module) => module,
};
}
}
-#[derive(Clone, Debug)]
-pub struct Method<'tcx> {
- pub name: Name,
- pub generics: &'tcx Generics<'tcx>,
- pub predicates: GenericPredicates<'tcx>,
- pub fty: &'tcx BareFnTy<'tcx>,
- pub explicit_self: ExplicitSelfCategory<'tcx>,
- pub vis: Visibility,
- pub defaultness: hir::Defaultness,
- pub has_body: bool,
- pub def_id: DefId,
- pub container: ImplOrTraitItemContainer,
-}
-
-impl<'tcx> Method<'tcx> {
- pub fn container_id(&self) -> DefId {
- match self.container {
- TraitContainer(id) => id,
- ImplContainer(id) => id,
- }
- }
-}
-
-impl<'tcx> PartialEq for Method<'tcx> {
- #[inline]
- fn eq(&self, other: &Self) -> bool { self.def_id == other.def_id }
-}
-
-impl<'tcx> Eq for Method<'tcx> {}
-
-impl<'tcx> Hash for Method<'tcx> {
- #[inline]
- fn hash<H: Hasher>(&self, s: &mut H) {
- self.def_id.hash(s)
- }
-}
-
-#[derive(Clone, Copy, Debug)]
-pub struct AssociatedConst<'tcx> {
- pub name: Name,
- pub ty: Ty<'tcx>,
- pub vis: Visibility,
- pub defaultness: hir::Defaultness,
- pub def_id: DefId,
- pub container: ImplOrTraitItemContainer,
- pub has_value: bool
-}
-
-#[derive(Clone, Copy, Debug)]
-pub struct AssociatedType<'tcx> {
- pub name: Name,
- pub ty: Option<Ty<'tcx>>,
- pub vis: Visibility,
- pub defaultness: hir::Defaultness,
- pub def_id: DefId,
- pub container: ImplOrTraitItemContainer,
-}
-
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)]
pub enum Variance {
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
/// needed to add to the side tables. Thus to disambiguate
/// we also keep track of whether there's an adjustment in
/// our key.
-#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
pub struct MethodCall {
pub expr_id: NodeId,
pub autoderef: u32
// maps from an expression id that corresponds to a method call to the details
// of the method to be invoked
-pub type MethodMap<'tcx> = FnvHashMap<MethodCall, MethodCallee<'tcx>>;
+pub type MethodMap<'tcx> = FxHashMap<MethodCall, MethodCallee<'tcx>>;
// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
/// Upvars do not get their own node-id. Instead, we use the pair of
/// the original var id (that is, the root variable that is referenced
/// by the upvar) and the id of the closure expression.
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub struct UpvarId {
pub var_id: NodeId,
pub closure_expr_id: NodeId,
/// Data must be immutable but not aliasable. This kind of borrow
/// cannot currently be expressed by the user and is used only in
- /// implicit closure bindings. It is needed when you the closure
+ /// implicit closure bindings. It is needed when the closure
/// is borrowing or mutating a mutable referent, e.g.:
///
/// let x: &mut isize = ...;
pub region: &'tcx ty::Region,
}
-pub type UpvarCaptureMap<'tcx> = FnvHashMap<UpvarId, UpvarCapture<'tcx>>;
+pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
#[derive(Copy, Clone)]
pub struct ClosureUpvar<'tcx> {
UintType(ast::UintTy),
}
-/// Default region to use for the bound of objects that are
-/// supplied as the value for this type parameter. This is derived
-/// from `T:'a` annotations appearing in the type definition. If
-/// this is `None`, then the default is inherited from the
-/// surrounding context. See RFC #599 for details.
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
-pub enum ObjectLifetimeDefault<'tcx> {
- /// Require an explicit annotation. Occurs when multiple
- /// `T:'a` constraints are found.
- Ambiguous,
-
- /// Use the base default, typically 'static, but in a fn body it is a fresh variable
- BaseDefault,
-
- /// Use the given region as the default.
- Specific(&'tcx Region),
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub struct TypeParameterDef<'tcx> {
+pub struct TypeParameterDef {
pub name: Name,
pub def_id: DefId,
pub index: u32,
- pub default_def_id: DefId, // for use in error reporing about defaults
- pub default: Option<Ty<'tcx>>,
- pub object_lifetime_default: ObjectLifetimeDefault<'tcx>,
+ pub has_default: bool,
+ pub object_lifetime_default: ObjectLifetimeDefault,
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
/// on generic parameter `T`, asserts data behind the parameter
pub pure_wrt_drop: bool,
}
-#[derive(Clone, RustcEncodable, RustcDecodable)]
-pub struct RegionParameterDef<'tcx> {
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
+pub struct RegionParameterDef {
pub name: Name,
pub def_id: DefId,
pub index: u32,
- pub bounds: Vec<&'tcx ty::Region>,
+ pub issue_32330: Option<ty::Issue32330>,
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
/// on generic parameter `'a`, asserts data of lifetime `'a`
pub pure_wrt_drop: bool,
}
-impl<'tcx> RegionParameterDef<'tcx> {
- pub fn to_early_bound_region(&self) -> ty::Region {
- ty::ReEarlyBound(self.to_early_bound_region_data())
- }
-
+impl RegionParameterDef {
pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
ty::EarlyBoundRegion {
index: self.index,
}
pub fn to_bound_region(&self) -> ty::BoundRegion {
- // this is an early bound region, so unaffected by #32330
- ty::BoundRegion::BrNamed(self.def_id, self.name, Issue32330::WontChange)
+ ty::BoundRegion::BrNamed(self.def_id, self.name)
}
}
/// Information about the formal type/lifetime parameters associated
/// with an item or method. Analogous to hir::Generics.
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub struct Generics<'tcx> {
+pub struct Generics {
pub parent: Option<DefId>,
pub parent_regions: u32,
pub parent_types: u32,
- pub regions: Vec<RegionParameterDef<'tcx>>,
- pub types: Vec<TypeParameterDef<'tcx>>,
+ pub regions: Vec<RegionParameterDef>,
+ pub types: Vec<TypeParameterDef>,
+
+ /// Reverse map to each `TypeParameterDef`'s `index` field, from
+ /// `def_id.index` (`def_id.krate` is the same as the item's).
+ pub type_param_to_index: BTreeMap<DefIndex, u32>,
+
pub has_self: bool,
}
-impl<'tcx> Generics<'tcx> {
+impl Generics {
pub fn parent_count(&self) -> usize {
self.parent_regions as usize + self.parent_types as usize
}
self.parent_count() + self.own_count()
}
- pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef<'tcx> {
+ pub fn region_param(&self, param: &EarlyBoundRegion) -> &RegionParameterDef {
+ assert_eq!(self.parent_count(), 0);
&self.regions[param.index as usize - self.has_self as usize]
}
- pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef<'tcx> {
+ pub fn type_param(&self, param: &ParamTy) -> &TypeParameterDef {
+ assert_eq!(self.parent_count(), 0);
&self.types[param.idx as usize - self.has_self as usize - self.regions.len()]
}
}
/// Bounds on generics.
-#[derive(Clone)]
+#[derive(Clone, Default)]
pub struct GenericPredicates<'tcx> {
pub parent: Option<DefId>,
pub predicates: Vec<Predicate<'tcx>>,
instantiated: &mut InstantiatedPredicates<'tcx>,
substs: &Substs<'tcx>) {
if let Some(def_id) = self.parent {
- tcx.lookup_predicates(def_id).instantiate_into(tcx, instantiated, substs);
+ tcx.item_predicates(def_id).instantiate_into(tcx, instantiated, substs);
}
instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs)))
}
/// Creates the dep-node for selecting/evaluating this trait reference.
fn dep_node(&self) -> DepNode<DefId> {
- // Ideally, the dep-node would just have all the input types
- // in it. But they are limited to including def-ids. So as an
- // approximation we include the def-ids for all nominal types
- // found somewhere. This means that we will e.g. conflate the
- // dep-nodes for `u32: SomeTrait` and `u64: SomeTrait`, but we
- // would have distinct dep-nodes for `Vec<u32>: SomeTrait`,
- // `Rc<u32>: SomeTrait`, and `(Vec<u32>, Rc<u32>): SomeTrait`.
- // Note that it's always sound to conflate dep-nodes, it just
- // leads to more recompilation.
- let def_ids: Vec<_> =
+ // Extact the trait-def and first def-id from inputs. See the
+ // docs for `DepNode::TraitSelect` for more information.
+ let trait_def_id = self.def_id();
+ let input_def_id =
self.input_types()
.flat_map(|t| t.walk())
.filter_map(|t| match t.sty {
- ty::TyAdt(adt_def, _) =>
- Some(adt_def.did),
- _ =>
- None
+ ty::TyAdt(adt_def, _) => Some(adt_def.did),
+ _ => None
})
- .chain(iter::once(self.def_id()))
- .collect();
- DepNode::TraitSelect(def_ids)
+ .next()
+ .unwrap_or(trait_def_id);
+ DepNode::TraitSelect {
+ trait_def_id: trait_def_id,
+ input_def_id: input_def_id
+ }
}
pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
}
}
-impl<'tcx> TraitRef<'tcx> {
- pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> {
- TraitRef { def_id: def_id, substs: substs }
- }
-
- pub fn self_ty(&self) -> Ty<'tcx> {
- self.substs.type_at(0)
- }
-
- pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
- // Select only the "input types" from a trait-reference. For
- // now this is all the types that appear in the
- // trait-reference, but it should eventually exclude
- // associated types.
- self.substs.types()
- }
-}
-
/// 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.
pub free_id_outlive: CodeExtent,
/// A cache for `moves_by_default`.
- pub is_copy_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
+ pub is_copy_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
/// A cache for `type_is_sized`
- pub is_sized_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
+ pub is_sized_cache: RefCell<FxHashMap<Ty<'tcx>, bool>>,
}
impl<'a, 'tcx> ParameterEnvironment<'tcx> {
implicit_region_bound: self.implicit_region_bound,
caller_bounds: caller_bounds,
free_id_outlive: self.free_id_outlive,
- is_copy_cache: RefCell::new(FnvHashMap()),
- is_sized_cache: RefCell::new(FnvHashMap()),
+ is_copy_cache: RefCell::new(FxHashMap()),
+ is_sized_cache: RefCell::new(FxHashMap()),
}
}
/// Construct a parameter environment given an item, impl item, or trait item
pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId)
-> ParameterEnvironment<'tcx> {
- match tcx.map.find(id) {
- Some(ast_map::NodeImplItem(ref impl_item)) => {
+ match tcx.hir.find(id) {
+ Some(hir_map::NodeImplItem(ref impl_item)) => {
match impl_item.node {
hir::ImplItemKind::Type(_) | hir::ImplItemKind::Const(..) => {
// associated types don't have their own entry (for some reason),
// so for now just grab environment for the impl
- let impl_id = tcx.map.get_parent(id);
- let impl_def_id = tcx.map.local_def_id(impl_id);
+ let impl_id = tcx.hir.get_parent(id);
+ let impl_def_id = tcx.hir.local_def_id(impl_id);
tcx.construct_parameter_environment(impl_item.span,
impl_def_id,
tcx.region_maps.item_extent(id))
}
hir::ImplItemKind::Method(_, ref body) => {
- let method_def_id = tcx.map.local_def_id(id);
- match tcx.impl_or_trait_item(method_def_id) {
- MethodTraitItem(ref method_ty) => {
- tcx.construct_parameter_environment(
- impl_item.span,
- method_ty.def_id,
- tcx.region_maps.call_site_extent(id, body.id))
- }
- _ => {
- bug!("ParameterEnvironment::for_item(): \
- got non-method item from impl method?!")
- }
- }
+ tcx.construct_parameter_environment(
+ impl_item.span,
+ tcx.hir.local_def_id(id),
+ tcx.region_maps.call_site_extent(id, body.node_id))
}
}
}
- Some(ast_map::NodeTraitItem(trait_item)) => {
+ Some(hir_map::NodeTraitItem(trait_item)) => {
match trait_item.node {
- hir::TypeTraitItem(..) | hir::ConstTraitItem(..) => {
+ hir::TraitItemKind::Type(..) | hir::TraitItemKind::Const(..) => {
// associated types don't have their own entry (for some reason),
// so for now just grab environment for the trait
- let trait_id = tcx.map.get_parent(id);
- let trait_def_id = tcx.map.local_def_id(trait_id);
+ let trait_id = tcx.hir.get_parent(id);
+ let trait_def_id = tcx.hir.local_def_id(trait_id);
tcx.construct_parameter_environment(trait_item.span,
trait_def_id,
tcx.region_maps.item_extent(id))
}
- hir::MethodTraitItem(_, ref body) => {
+ hir::TraitItemKind::Method(_, ref body) => {
// Use call-site for extent (unless this is a
// trait method with no default; then fallback
// to the method id).
- let method_def_id = tcx.map.local_def_id(id);
- match tcx.impl_or_trait_item(method_def_id) {
- MethodTraitItem(ref method_ty) => {
- let extent = if let Some(ref body) = *body {
- // default impl: use call_site extent as free_id_outlive bound.
- tcx.region_maps.call_site_extent(id, body.id)
- } else {
- // no default impl: use item extent as free_id_outlive bound.
- tcx.region_maps.item_extent(id)
- };
- tcx.construct_parameter_environment(
- trait_item.span,
- method_ty.def_id,
- extent)
- }
- _ => {
- bug!("ParameterEnvironment::for_item(): \
- got non-method item from provided \
- method?!")
- }
- }
+ let extent = if let hir::TraitMethod::Provided(body_id) = *body {
+ // default impl: use call_site extent as free_id_outlive bound.
+ tcx.region_maps.call_site_extent(id, body_id.node_id)
+ } else {
+ // no default impl: use item extent as free_id_outlive bound.
+ tcx.region_maps.item_extent(id)
+ };
+ tcx.construct_parameter_environment(
+ trait_item.span,
+ tcx.hir.local_def_id(id),
+ extent)
}
}
}
- Some(ast_map::NodeItem(item)) => {
+ Some(hir_map::NodeItem(item)) => {
match item.node {
- hir::ItemFn(.., ref body) => {
+ hir::ItemFn(.., body_id) => {
// We assume this is a function.
- let fn_def_id = tcx.map.local_def_id(id);
+ let fn_def_id = tcx.hir.local_def_id(id);
tcx.construct_parameter_environment(
item.span,
fn_def_id,
- tcx.region_maps.call_site_extent(id, body.id))
+ tcx.region_maps.call_site_extent(id, body_id.node_id))
}
hir::ItemEnum(..) |
hir::ItemStruct(..) |
hir::ItemImpl(..) |
hir::ItemConst(..) |
hir::ItemStatic(..) => {
- let def_id = tcx.map.local_def_id(id);
+ let def_id = tcx.hir.local_def_id(id);
tcx.construct_parameter_environment(item.span,
def_id,
tcx.region_maps.item_extent(id))
}
hir::ItemTrait(..) => {
- let def_id = tcx.map.local_def_id(id);
+ let def_id = tcx.hir.local_def_id(id);
tcx.construct_parameter_environment(item.span,
def_id,
tcx.region_maps.item_extent(id))
}
}
}
- Some(ast_map::NodeExpr(expr)) => {
+ Some(hir_map::NodeExpr(expr)) => {
// This is a convenience to allow closures to work.
- if let hir::ExprClosure(..) = expr.node {
- ParameterEnvironment::for_item(tcx, tcx.map.get_parent(id))
+ if let hir::ExprClosure(.., body, _) = expr.node {
+ let def_id = tcx.hir.local_def_id(id);
+ let base_def_id = tcx.closure_base_def_id(def_id);
+ tcx.construct_parameter_environment(
+ expr.span,
+ base_def_id,
+ tcx.region_maps.call_site_extent(id, body.node_id))
} else {
tcx.empty_parameter_environment()
}
}
- Some(ast_map::NodeForeignItem(item)) => {
- let def_id = tcx.map.local_def_id(id);
+ Some(hir_map::NodeForeignItem(item)) => {
+ let def_id = tcx.hir.local_def_id(id);
tcx.construct_parameter_environment(item.span,
def_id,
ROOT_CODE_EXTENT)
_ => {
bug!("ParameterEnvironment::from_item(): \
`{}` is not an item",
- tcx.map.node_to_string(id))
+ tcx.hir.node_to_string(id))
}
}
}
}
-/// A "type scheme", in ML terminology, is a type combined with some
-/// set of generic types that the type is, well, generic over. In Rust
-/// terms, it is the "type" of a fn item or struct -- this type will
-/// include various generic parameters that must be substituted when
-/// the item/struct is referenced. That is called converting the type
-/// scheme to a monotype.
-///
-/// - `generics`: the set of type parameters and their bounds
-/// - `ty`: the base types, which may reference the parameters defined
-/// in `generics`
-///
-/// Note that TypeSchemes are also sometimes called "polytypes" (and
-/// in fact this struct used to carry that name, so you may find some
-/// stray references in a comment or something). We try to reserve the
-/// "poly" prefix to refer to higher-ranked things, as in
-/// `PolyTraitRef`.
-///
-/// Note that each item also comes with predicates, see
-/// `lookup_predicates`.
-#[derive(Clone, Debug)]
-pub struct TypeScheme<'tcx> {
- pub generics: &'tcx Generics<'tcx>,
- pub ty: Ty<'tcx>,
+#[derive(Copy, Clone, Debug)]
+pub struct Destructor {
+ /// The def-id of the destructor method
+ pub did: DefId,
+ /// Invoking the destructor of a dtorck type during usual cleanup
+ /// (e.g. the glue emitted for stack unwinding) requires all
+ /// lifetimes in the type-structure of `adt` to strictly outlive
+ /// the adt value itself.
+ ///
+ /// If `adt` is not dtorck, then the adt's destructor can be
+ /// invoked even when there are lifetimes in the type-structure of
+ /// `adt` that do not strictly outlive the adt value itself.
+ /// (This allows programs to make cyclic structures without
+ /// resorting to unsafe means; see RFCs 769 and 1238).
+ pub is_dtorck: bool,
}
bitflags! {
flags AdtFlags: u32 {
const NO_ADT_FLAGS = 0,
const IS_ENUM = 1 << 0,
- const IS_DTORCK = 1 << 1, // is this a dtorck type?
- const IS_DTORCK_VALID = 1 << 2,
- const IS_PHANTOM_DATA = 1 << 3,
- const IS_SIMD = 1 << 4,
- const IS_FUNDAMENTAL = 1 << 5,
- const IS_UNION = 1 << 6,
+ const IS_PHANTOM_DATA = 1 << 1,
+ const IS_FUNDAMENTAL = 1 << 2,
+ const IS_UNION = 1 << 3,
+ const IS_BOX = 1 << 4,
}
}
-pub type AdtDef<'tcx> = &'tcx AdtDefData<'tcx, 'static>;
-pub type VariantDef<'tcx> = &'tcx VariantDefData<'tcx, 'static>;
-pub type FieldDef<'tcx> = &'tcx FieldDefData<'tcx, 'static>;
-
-// See comment on AdtDefData for explanation
-pub type AdtDefMaster<'tcx> = &'tcx AdtDefData<'tcx, 'tcx>;
-pub type VariantDefMaster<'tcx> = &'tcx VariantDefData<'tcx, 'tcx>;
-pub type FieldDefMaster<'tcx> = &'tcx FieldDefData<'tcx, 'tcx>;
-
-pub struct VariantDefData<'tcx, 'container: 'tcx> {
+#[derive(Debug)]
+pub struct VariantDef {
/// The variant's DefId. If this is a tuple-like struct,
/// this is the DefId of the struct's ctor.
pub did: DefId,
pub name: Name, // struct's name if this is a struct
- pub disr_val: Disr,
- pub fields: Vec<FieldDefData<'tcx, 'container>>,
+ pub discr: VariantDiscr,
+ pub fields: Vec<FieldDef>,
pub ctor_kind: CtorKind,
}
-pub struct FieldDefData<'tcx, 'container: 'tcx> {
- /// The field's DefId. NOTE: the fields of tuple-like enum variants
- /// are not real items, and don't have entries in tcache etc.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
+pub enum VariantDiscr {
+ /// Explicit value for this variant, i.e. `X = 123`.
+ /// The `DefId` corresponds to the embedded constant.
+ Explicit(DefId),
+
+ /// The previous variant's discriminant plus one.
+ /// For efficiency reasons, the distance from the
+ /// last `Explicit` discriminant is being stored,
+ /// or `0` for the first variant, if it has none.
+ Relative(usize),
+}
+
+#[derive(Debug)]
+pub struct FieldDef {
pub did: DefId,
pub name: Name,
pub vis: Visibility,
- /// TyIVar is used here to allow for variance (see the doc at
- /// AdtDefData).
- ///
- /// Note: direct accesses to `ty` must also add dep edges.
- ty: ivar::TyIVar<'tcx, 'container>
}
/// The definition of an abstract data type - a struct or enum.
///
/// These are all interned (by intern_adt_def) into the adt_defs
/// table.
-///
-/// Because of the possibility of nested tcx-s, this type
-/// needs 2 lifetimes: the traditional variant lifetime ('tcx)
-/// bounding the lifetime of the inner types is of course necessary.
-/// However, it is not sufficient - types from a child tcx must
-/// not be leaked into the master tcx by being stored in an AdtDefData.
-///
-/// The 'container lifetime ensures that by outliving the container
-/// tcx and preventing shorter-lived types from being inserted. When
-/// write access is not needed, the 'container lifetime can be
-/// erased to 'static, which can be done by the AdtDef wrapper.
-pub struct AdtDefData<'tcx, 'container: 'tcx> {
+pub struct AdtDef {
pub did: DefId,
- pub variants: Vec<VariantDefData<'tcx, 'container>>,
- destructor: Cell<Option<DefId>>,
- flags: Cell<AdtFlags>,
- sized_constraint: ivar::TyIVar<'tcx, 'container>,
+ pub variants: Vec<VariantDef>,
+ flags: AdtFlags,
+ pub repr: ReprOptions,
}
-impl<'tcx, 'container> PartialEq for AdtDefData<'tcx, 'container> {
- // AdtDefData are always interned and this is part of TyS equality
+impl PartialEq for AdtDef {
+ // AdtDef are always interned and this is part of TyS equality
#[inline]
fn eq(&self, other: &Self) -> bool { self as *const _ == other as *const _ }
}
-impl<'tcx, 'container> Eq for AdtDefData<'tcx, 'container> {}
+impl Eq for AdtDef {}
-impl<'tcx, 'container> Hash for AdtDefData<'tcx, 'container> {
+impl Hash for AdtDef {
#[inline]
fn hash<H: Hasher>(&self, s: &mut H) {
- (self as *const AdtDefData).hash(s)
+ (self as *const AdtDef).hash(s)
}
}
-impl<'tcx> serialize::UseSpecializedEncodable for AdtDef<'tcx> {
+impl<'tcx> serialize::UseSpecializedEncodable for &'tcx AdtDef {
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
self.did.encode(s)
}
}
-impl<'tcx> serialize::UseSpecializedDecodable for AdtDef<'tcx> {}
+impl<'tcx> serialize::UseSpecializedDecodable for &'tcx AdtDef {}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum AdtKind { Struct, Union, Enum }
-impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
- fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+/// Represents the repr options provided by the user,
+#[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)]
+pub struct ReprOptions {
+ pub c: bool,
+ pub packed: bool,
+ pub simd: bool,
+ pub int: Option<attr::IntType>,
+}
+
+impl ReprOptions {
+ pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions {
+ let mut ret = ReprOptions::default();
+
+ for attr in tcx.get_attrs(did).iter() {
+ for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) {
+ match r {
+ attr::ReprExtern => ret.c = true,
+ attr::ReprPacked => ret.packed = true,
+ attr::ReprSimd => ret.simd = true,
+ attr::ReprInt(i) => ret.int = Some(i),
+ }
+ }
+ }
+
+ // FIXME(eddyb) This is deprecated and should be removed.
+ if tcx.has_attr(did, "simd") {
+ ret.simd = true;
+ }
+
+ ret
+ }
+
+ pub fn discr_type(&self) -> attr::IntType {
+ self.int.unwrap_or(attr::SignedInt(ast::IntTy::Is))
+ }
+
+ /// Returns true if this `#[repr()]` should inhabit "smart enum
+ /// layout" optimizations, such as representing `Foo<&T>` as a
+ /// single pointer.
+ pub fn inhibit_enum_layout_opt(&self) -> bool {
+ self.c || self.int.is_some()
+ }
+}
+
+impl<'a, 'gcx, 'tcx> AdtDef {
+ fn new(tcx: TyCtxt,
did: DefId,
kind: AdtKind,
- variants: Vec<VariantDefData<'gcx, 'container>>) -> Self {
+ variants: Vec<VariantDef>,
+ repr: ReprOptions) -> Self {
let mut flags = AdtFlags::NO_ADT_FLAGS;
let attrs = tcx.get_attrs(did);
if attr::contains_name(&attrs, "fundamental") {
flags = flags | AdtFlags::IS_FUNDAMENTAL;
}
- if tcx.lookup_simd(did) {
- flags = flags | AdtFlags::IS_SIMD;
- }
if Some(did) == tcx.lang_items.phantom_data() {
flags = flags | AdtFlags::IS_PHANTOM_DATA;
}
+ if Some(did) == tcx.lang_items.owned_box() {
+ flags = flags | AdtFlags::IS_BOX;
+ }
match kind {
AdtKind::Enum => flags = flags | AdtFlags::IS_ENUM,
AdtKind::Union => flags = flags | AdtFlags::IS_UNION,
AdtKind::Struct => {}
}
- AdtDefData {
+ AdtDef {
did: did,
variants: variants,
- flags: Cell::new(flags),
- destructor: Cell::new(None),
- sized_constraint: ivar::TyIVar::new(),
+ flags: flags,
+ repr: repr,
}
}
- fn calculate_dtorck(&'gcx self, tcx: TyCtxt) {
- if tcx.is_adt_dtorck(self) {
- self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK);
- }
- self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK_VALID)
- }
-
#[inline]
pub fn is_struct(&self) -> bool {
!self.is_union() && !self.is_enum()
#[inline]
pub fn is_union(&self) -> bool {
- self.flags.get().intersects(AdtFlags::IS_UNION)
+ self.flags.intersects(AdtFlags::IS_UNION)
}
#[inline]
pub fn is_enum(&self) -> bool {
- self.flags.get().intersects(AdtFlags::IS_ENUM)
+ self.flags.intersects(AdtFlags::IS_ENUM)
}
/// Returns the kind of the ADT - Struct or Enum.
/// alive; Otherwise, only the contents are required to be.
#[inline]
pub fn is_dtorck(&'gcx self, tcx: TyCtxt) -> bool {
- if !self.flags.get().intersects(AdtFlags::IS_DTORCK_VALID) {
- self.calculate_dtorck(tcx)
- }
- self.flags.get().intersects(AdtFlags::IS_DTORCK)
+ self.destructor(tcx).map_or(false, |d| d.is_dtorck)
}
/// Returns whether this type is #[fundamental] for the purposes
/// of coherence checking.
#[inline]
pub fn is_fundamental(&self) -> bool {
- self.flags.get().intersects(AdtFlags::IS_FUNDAMENTAL)
+ self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
}
+ /// Returns true if this is PhantomData<T>.
#[inline]
- pub fn is_simd(&self) -> bool {
- self.flags.get().intersects(AdtFlags::IS_SIMD)
+ pub fn is_phantom_data(&self) -> bool {
+ self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
}
- /// Returns true if this is PhantomData<T>.
+ /// Returns true if this is Box<T>.
#[inline]
- pub fn is_phantom_data(&self) -> bool {
- self.flags.get().intersects(AdtFlags::IS_PHANTOM_DATA)
+ pub fn is_box(&self) -> bool {
+ self.flags.intersects(AdtFlags::IS_BOX)
}
/// Returns whether this type has a destructor.
- pub fn has_dtor(&self) -> bool {
- self.dtor_kind().is_present()
+ pub fn has_dtor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
+ self.destructor(tcx).is_some()
}
/// Asserts this is a struct and returns the struct's unique
/// variant.
- pub fn struct_variant(&self) -> &VariantDefData<'gcx, 'container> {
+ pub fn struct_variant(&self) -> &VariantDef {
assert!(!self.is_enum());
&self.variants[0]
}
- #[inline]
- pub fn type_scheme(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> TypeScheme<'gcx> {
- tcx.lookup_item_type(self.did)
- }
-
#[inline]
pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> GenericPredicates<'gcx> {
- tcx.lookup_predicates(self.did)
+ tcx.item_predicates(self.did)
}
/// Returns an iterator over all fields contained
/// by this ADT.
#[inline]
- pub fn all_fields(&self) ->
- iter::FlatMap<
- slice::Iter<VariantDefData<'gcx, 'container>>,
- slice::Iter<FieldDefData<'gcx, 'container>>,
- for<'s> fn(&'s VariantDefData<'gcx, 'container>)
- -> slice::Iter<'s, FieldDefData<'gcx, 'container>>
- > {
- self.variants.iter().flat_map(VariantDefData::fields_iter)
- }
-
- #[inline]
- pub fn is_empty(&self) -> bool {
- self.variants.is_empty()
+ pub fn all_fields<'s>(&'s self) -> impl Iterator<Item = &'s FieldDef> {
+ self.variants.iter().flat_map(|v| v.fields.iter())
}
#[inline]
self.variants.iter().all(|v| v.fields.is_empty())
}
- pub fn variant_with_id(&self, vid: DefId) -> &VariantDefData<'gcx, 'container> {
+ pub fn variant_with_id(&self, vid: DefId) -> &VariantDef {
self.variants
.iter()
.find(|v| v.did == vid)
.expect("variant_index_with_id: unknown variant")
}
- pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'gcx, 'container> {
+ pub fn variant_of_def(&self, def: Def) -> &VariantDef {
match def {
Def::Variant(vid) | Def::VariantCtor(vid, ..) => self.variant_with_id(vid),
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
}
}
- pub fn destructor(&self) -> Option<DefId> {
- self.destructor.get()
- }
+ pub fn discriminants(&'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>)
+ -> impl Iterator<Item=ConstInt> + 'a {
+ let repr_type = self.repr.discr_type();
+ let initial = repr_type.initial_discriminant(tcx.global_tcx());
+ let mut prev_discr = None::<ConstInt>;
+ self.variants.iter().map(move |v| {
+ let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr());
+ if let VariantDiscr::Explicit(expr_did) = v.discr {
+ match tcx.maps.monomorphic_const_eval.borrow()[&expr_did] {
+ Ok(ConstVal::Integral(v)) => {
+ discr = v;
+ }
+ _ => {}
+ }
+ }
+ prev_discr = Some(discr);
- pub fn set_destructor(&self, dtor: DefId) {
- self.destructor.set(Some(dtor));
+ discr
+ })
}
- pub fn dtor_kind(&self) -> DtorKind {
- match self.destructor.get() {
- Some(_) => TraitDtor,
- None => NoDtor,
- }
+ pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Destructor> {
+ queries::adt_destructor::get(tcx, DUMMY_SP, self.did)
}
-}
-impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'tcx, 'container> {
/// Returns a simpler type such that `Self: Sized` if and only
/// if that type is Sized, or `TyErr` if this type is recursive.
///
/// Due to normalization being eager, this applies even if
/// the associated type is behind a pointer, e.g. issue #31299.
pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
- match self.sized_constraint.get(DepNode::SizedConstraint(self.did)) {
- None => {
- let global_tcx = tcx.global_tcx();
- let this = global_tcx.lookup_adt_def_master(self.did);
- this.calculate_sized_constraint_inner(global_tcx, &mut Vec::new());
- self.sized_constraint(tcx)
- }
- Some(ty) => ty
- }
+ self.calculate_sized_constraint_inner(tcx.global_tcx(), &mut Vec::new())
}
-}
-impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
/// Calculates the Sized-constraint.
///
/// As the Sized-constraint of enums can be a *set* of types,
/// such.
/// - a TyError, if a type contained itself. The representability
/// check should catch this case.
- fn calculate_sized_constraint_inner(&'tcx self,
+ fn calculate_sized_constraint_inner(&self,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
- stack: &mut Vec<AdtDefMaster<'tcx>>)
+ stack: &mut Vec<DefId>)
+ -> Ty<'tcx>
{
- let dep_node = || DepNode::SizedConstraint(self.did);
+ if let Some(ty) = tcx.maps.adt_sized_constraint.borrow().get(&self.did) {
+ return ty;
+ }
// Follow the memoization pattern: push the computation of
// DepNode::SizedConstraint as our current task.
- let _task = tcx.dep_graph.in_task(dep_node());
- if self.sized_constraint.untracked_get().is_some() {
- // ---------------
- // can skip the dep-graph read since we just pushed the task
- return;
- }
+ let _task = tcx.dep_graph.in_task(DepNode::SizedConstraint(self.did));
- if stack.contains(&self) {
+ if stack.contains(&self.did) {
debug!("calculate_sized_constraint: {:?} is recursive", self);
// This should be reported as an error by `check_representable`.
//
// Consider the type as Sized in the meanwhile to avoid
// further errors.
- self.sized_constraint.fulfill(dep_node(), tcx.types.err);
- return;
+ tcx.maps.adt_sized_constraint.borrow_mut().insert(self.did, tcx.types.err);
+ return tcx.types.err;
}
- stack.push(self);
+ stack.push(self.did);
let tys : Vec<_> =
self.variants.iter().flat_map(|v| {
v.fields.last()
}).flat_map(|f| {
- self.sized_constraint_for_ty(tcx, stack, f.unsubst_ty())
+ let ty = tcx.item_type(f.did);
+ self.sized_constraint_for_ty(tcx, stack, ty)
}).collect();
let self_ = stack.pop().unwrap();
- assert_eq!(self_, self);
+ assert_eq!(self_, self.did);
let ty = match tys.len() {
_ if tys.references_error() => tcx.types.err,
0 => tcx.types.bool,
1 => tys[0],
- _ => tcx.intern_tup(&tys[..])
+ _ => tcx.intern_tup(&tys[..], false)
};
- match self.sized_constraint.get(dep_node()) {
+ let old = tcx.maps.adt_sized_constraint.borrow().get(&self.did).cloned();
+ match old {
Some(old_ty) => {
debug!("calculate_sized_constraint: {:?} recurred", self);
- assert_eq!(old_ty, tcx.types.err)
+ assert_eq!(old_ty, tcx.types.err);
+ old_ty
}
None => {
debug!("calculate_sized_constraint: {:?} => {:?}", self, ty);
- self.sized_constraint.fulfill(dep_node(), ty)
+ tcx.maps.adt_sized_constraint.borrow_mut().insert(self.did, ty);
+ ty
}
}
}
- fn sized_constraint_for_ty(
- &'tcx self,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- stack: &mut Vec<AdtDefMaster<'tcx>>,
- ty: Ty<'tcx>
- ) -> Vec<Ty<'tcx>> {
+ fn sized_constraint_for_ty(&self,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ stack: &mut Vec<DefId>,
+ ty: Ty<'tcx>)
+ -> Vec<Ty<'tcx>> {
let result = match ty.sty {
TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
- TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
+ TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) |
TyArray(..) | TyClosure(..) | TyNever => {
vec![]
}
- TyStr | TyTrait(..) | TySlice(_) | TyError => {
+ TyStr | TyDynamic(..) | TySlice(_) | TyError => {
// these are never sized - return the target type
vec![ty]
}
- TyTuple(ref tys) => {
+ TyTuple(ref tys, _) => {
match tys.last() {
None => vec![],
Some(ty) => self.sized_constraint_for_ty(tcx, stack, ty)
TyAdt(adt, substs) => {
// recursive case
- let adt = tcx.lookup_adt_def_master(adt.did);
- adt.calculate_sized_constraint_inner(tcx, stack);
let adt_ty =
- adt.sized_constraint
- .unwrap(DepNode::SizedConstraint(adt.did))
- .subst(tcx, substs);
+ adt.calculate_sized_constraint_inner(tcx, stack)
+ .subst(tcx, substs);
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
ty, adt_ty);
- if let ty::TyTuple(ref tys) = adt_ty.sty {
+ if let ty::TyTuple(ref tys, _) = adt_ty.sty {
tys.iter().flat_map(|ty| {
self.sized_constraint_for_ty(tcx, stack, ty)
}).collect()
def_id: sized_trait,
substs: tcx.mk_substs_trait(ty, &[])
}).to_predicate();
- let predicates = tcx.lookup_predicates(self.did).predicates;
+ let predicates = tcx.item_predicates(self.did).predicates;
if predicates.into_iter().any(|p| p == sized_predicate) {
vec![]
} else {
}
}
-impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
- #[inline]
- fn fields_iter(&self) -> slice::Iter<FieldDefData<'tcx, 'container>> {
- self.fields.iter()
- }
-
+impl<'a, 'gcx, 'tcx> VariantDef {
#[inline]
pub fn find_field_named(&self,
name: ast::Name)
- -> Option<&FieldDefData<'tcx, 'container>> {
+ -> Option<&FieldDef> {
self.fields.iter().find(|f| f.name == name)
}
}
#[inline]
- pub fn field_named(&self, name: ast::Name) -> &FieldDefData<'tcx, 'container> {
+ pub fn field_named(&self, name: ast::Name) -> &FieldDef {
self.find_field_named(name).unwrap()
}
}
-impl<'a, 'gcx, 'tcx, 'container> FieldDefData<'tcx, 'container> {
- pub fn new(did: DefId,
- name: Name,
- vis: Visibility) -> Self {
- FieldDefData {
- did: did,
- name: name,
- vis: vis,
- ty: ivar::TyIVar::new()
- }
- }
-
+impl<'a, 'gcx, 'tcx> FieldDef {
pub fn ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> {
- self.unsubst_ty().subst(tcx, subst)
- }
-
- pub fn unsubst_ty(&self) -> Ty<'tcx> {
- self.ty.unwrap(DepNode::FieldTy(self.did))
- }
-
- pub fn fulfill_ty(&self, ty: Ty<'container>) {
- self.ty.fulfill(DepNode::FieldTy(self.did), ty);
+ tcx.item_type(self.did).subst(tcx, subst)
}
}
impl<'a, 'tcx> ClosureKind {
pub fn trait_did(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefId {
- let result = match *self {
- ClosureKind::Fn => tcx.lang_items.require(FnTraitLangItem),
+ match *self {
+ ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem),
ClosureKind::FnMut => {
- tcx.lang_items.require(FnMutTraitLangItem)
+ tcx.require_lang_item(FnMutTraitLangItem)
}
ClosureKind::FnOnce => {
- tcx.lang_items.require(FnOnceTraitLangItem)
+ tcx.require_lang_item(FnOnceTraitLangItem)
}
- };
- match result {
- Ok(trait_did) => trait_did,
- Err(err) => tcx.sess.fatal(&err[..]),
}
}
/// Iterator that walks the immediate children of `self`. Hence
/// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
/// (but not `i32`, like `walk`).
- pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> {
+ pub fn walk_shallow(&'tcx self) -> AccIntoIter<walk::TypeWalkerArray<'tcx>> {
walk::walk_shallow(self)
}
}
}
-/// Helper for looking things up in the various maps that are populated during
-/// typeck::collect (e.g., `tcx.impl_or_trait_items`, `tcx.tcache`, etc). All of
-/// these share the pattern that if the id is local, it should have been loaded
-/// into the map by the `typeck::collect` phase. If the def-id is external,
-/// then we have to go consult the crate loading code (and cache the result for
-/// the future).
-fn lookup_locally_or_in_crate_store<M, F>(descr: &str,
- def_id: DefId,
- map: &M,
- load_external: F)
- -> M::Value where
- M: MemoizationMap<Key=DefId>,
- F: FnOnce() -> M::Value,
-{
- map.memoize(def_id, || {
- if def_id.is_local() {
- bug!("No def'n found for {:?} in tcx.{}", def_id, descr);
- }
- load_external()
- })
-}
-
impl BorrowKind {
pub fn from_mutbl(m: hir::Mutability) -> BorrowKind {
match m {
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
- pub fn tables(self) -> Ref<'a, Tables<'gcx>> {
- self.tables.borrow()
+ pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
+ self.item_tables(self.hir.body_owner_def_id(body))
+ }
+
+ pub fn item_tables(self, def_id: DefId) -> &'gcx TypeckTables<'gcx> {
+ queries::typeck_tables::get(self, DUMMY_SP, def_id)
}
pub fn expr_span(self, id: NodeId) -> Span {
- match self.map.find(id) {
- Some(ast_map::NodeExpr(e)) => {
+ match self.hir.find(id) {
+ Some(hir_map::NodeExpr(e)) => {
e.span
}
Some(f) => {
}
pub fn local_var_name_str(self, id: NodeId) -> InternedString {
- match self.map.find(id) {
- Some(ast_map::NodeLocal(pat)) => {
+ match self.hir.find(id) {
+ Some(hir_map::NodeLocal(pat)) => {
match pat.node {
- hir::PatKind::Binding(_, ref path1, _) => path1.node.as_str(),
+ hir::PatKind::Binding(_, _, ref path1, _) => path1.node.as_str(),
_ => {
bug!("Variable id {} maps to {:?}, not local", id, pat);
},
pub fn expr_is_lval(self, expr: &hir::Expr) -> bool {
match expr.node {
- hir::ExprPath(..) => {
- // This function can be used during type checking when not all paths are
- // fully resolved. Partially resolved paths in expressions can only legally
- // refer to associated items which are always rvalues.
- match self.expect_resolution(expr.id).base_def {
+ hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
+ match path.def {
Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
_ => false,
}
true
}
+ // Partially qualified paths in expressions can only legally
+ // refer to associated items which are always rvalues.
+ hir::ExprPath(hir::QPath::TypeRelative(..)) |
+
hir::ExprCall(..) |
hir::ExprMethodCall(..) |
hir::ExprStruct(..) |
}
}
- pub fn provided_trait_methods(self, id: DefId) -> Vec<Rc<Method<'gcx>>> {
- self.impl_or_trait_items(id).iter().filter_map(|&def_id| {
- match self.impl_or_trait_item(def_id) {
- MethodTraitItem(ref m) if m.has_body => Some(m.clone()),
- _ => None
- }
- }).collect()
+ pub fn provided_trait_methods(self, id: DefId) -> Vec<AssociatedItem> {
+ self.associated_items(id)
+ .filter(|item| item.kind == AssociatedKind::Method && item.defaultness.has_value())
+ .collect()
}
pub fn trait_impl_polarity(self, id: DefId) -> hir::ImplPolarity {
- if let Some(id) = self.map.as_local_node_id(id) {
- match self.map.expect_item(id).node {
+ if let Some(id) = self.hir.as_local_node_id(id) {
+ match self.hir.expect_item(id).node {
hir::ItemImpl(_, polarity, ..) => polarity,
ref item => bug!("trait_impl_polarity: {:?} not an impl", item)
}
}
}
+ pub fn trait_relevant_for_never(self, did: DefId) -> bool {
+ self.associated_items(did).any(|item| {
+ item.relevant_for_never()
+ })
+ }
+
pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized {
- self.custom_coerce_unsized_kinds.memoize(did, || {
- let (kind, src) = if did.krate != LOCAL_CRATE {
- (self.sess.cstore.custom_coerce_unsized_kind(did), "external")
- } else {
- (None, "local")
- };
+ queries::custom_coerce_unsized_kind::get(self, DUMMY_SP, did)
+ }
+
+ pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
+ if !def_id.is_local() {
+ return queries::associated_item::get(self, DUMMY_SP, def_id);
+ }
+
+ self.maps.associated_item.memoize(def_id, || {
+ // When the user asks for a given associated item, we
+ // always go ahead and convert all the associated items in
+ // the container. Note that we are also careful only to
+ // ever register a read on the *container* of the assoc
+ // item, not the assoc item itself. This prevents changes
+ // in the details of an item (for example, the type to
+ // which an associated type is bound) from contaminating
+ // those tasks that just need to scan the names of items
+ // and so forth.
+
+ let id = self.hir.as_local_node_id(def_id).unwrap();
+ let parent_id = self.hir.get_parent(id);
+ let parent_def_id = self.hir.local_def_id(parent_id);
+ let parent_item = self.hir.expect_item(parent_id);
+ match parent_item.node {
+ hir::ItemImpl(.., ref impl_trait_ref, _, ref impl_item_refs) => {
+ for impl_item_ref in impl_item_refs {
+ let assoc_item =
+ self.associated_item_from_impl_item_ref(parent_def_id,
+ impl_trait_ref.is_some(),
+ impl_item_ref);
+ self.maps.associated_item.borrow_mut()
+ .insert(assoc_item.def_id, assoc_item);
+ }
+ }
+
+ hir::ItemTrait(.., ref trait_item_refs) => {
+ for trait_item_ref in trait_item_refs {
+ let assoc_item =
+ self.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref);
+ self.maps.associated_item.borrow_mut()
+ .insert(assoc_item.def_id, assoc_item);
+ }
+ }
- match kind {
- Some(kind) => kind,
- None => {
- bug!("custom_coerce_unsized_kind: \
- {} impl `{}` is missing its kind",
- src, self.item_path_str(did));
+ ref r => {
+ panic!("unexpected container of associated items: {:?}", r)
}
}
+
+ // memoize wants us to return something, so return
+ // the one we generated for this def-id
+ *self.maps.associated_item.borrow().get(&def_id).unwrap()
})
}
- pub fn impl_or_trait_item(self, id: DefId) -> ImplOrTraitItem<'gcx> {
- lookup_locally_or_in_crate_store(
- "impl_or_trait_items", id, &self.impl_or_trait_items,
- || self.sess.cstore.impl_or_trait_item(self.global_tcx(), id)
- .expect("missing ImplOrTraitItem in metadata"))
- }
+ fn associated_item_from_trait_item_ref(self,
+ parent_def_id: DefId,
+ trait_item_ref: &hir::TraitItemRef)
+ -> AssociatedItem {
+ let def_id = self.hir.local_def_id(trait_item_ref.id.node_id);
+ let (kind, has_self) = match trait_item_ref.kind {
+ hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false),
+ hir::AssociatedItemKind::Method { has_self } => {
+ (ty::AssociatedKind::Method, has_self)
+ }
+ hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false),
+ };
- pub fn impl_or_trait_items(self, id: DefId) -> Rc<Vec<DefId>> {
- lookup_locally_or_in_crate_store(
- "impl_or_trait_items", id, &self.impl_or_trait_item_def_ids,
- || Rc::new(self.sess.cstore.impl_or_trait_items(id)))
- }
+ AssociatedItem {
+ name: trait_item_ref.name,
+ kind: kind,
+ vis: Visibility::from_hir(&hir::Inherited, trait_item_ref.id.node_id, self),
+ defaultness: trait_item_ref.defaultness,
+ def_id: def_id,
+ container: TraitContainer(parent_def_id),
+ method_has_self_argument: has_self
+ }
+ }
+
+ fn associated_item_from_impl_item_ref(self,
+ parent_def_id: DefId,
+ from_trait_impl: bool,
+ impl_item_ref: &hir::ImplItemRef)
+ -> AssociatedItem {
+ let def_id = self.hir.local_def_id(impl_item_ref.id.node_id);
+ let (kind, has_self) = match impl_item_ref.kind {
+ hir::AssociatedItemKind::Const => (ty::AssociatedKind::Const, false),
+ hir::AssociatedItemKind::Method { has_self } => {
+ (ty::AssociatedKind::Method, has_self)
+ }
+ hir::AssociatedItemKind::Type => (ty::AssociatedKind::Type, false),
+ };
- /// Returns the trait-ref corresponding to a given impl, or None if it is
- /// an inherent impl.
- pub fn impl_trait_ref(self, id: DefId) -> Option<TraitRef<'gcx>> {
- lookup_locally_or_in_crate_store(
- "impl_trait_refs", id, &self.impl_trait_refs,
- || self.sess.cstore.impl_trait_ref(self.global_tcx(), id))
+ // Trait impl items are always public.
+ let public = hir::Public;
+ let vis = if from_trait_impl { &public } else { &impl_item_ref.vis };
+
+ ty::AssociatedItem {
+ name: impl_item_ref.name,
+ kind: kind,
+ vis: ty::Visibility::from_hir(vis, impl_item_ref.id.node_id, self),
+ defaultness: impl_item_ref.defaultness,
+ def_id: def_id,
+ container: ImplContainer(parent_def_id),
+ method_has_self_argument: has_self
+ }
}
- /// Returns a path resolution for node id if it exists, panics otherwise.
- pub fn expect_resolution(self, id: NodeId) -> PathResolution {
- *self.def_map.borrow().get(&id).expect("no def-map entry for node id")
+ pub fn associated_item_def_ids(self, def_id: DefId) -> Rc<Vec<DefId>> {
+ if !def_id.is_local() {
+ return queries::associated_item_def_ids::get(self, DUMMY_SP, def_id);
+ }
+
+ self.maps.associated_item_def_ids.memoize(def_id, || {
+ let id = self.hir.as_local_node_id(def_id).unwrap();
+ let item = self.hir.expect_item(id);
+ let vec: Vec<_> = match item.node {
+ hir::ItemTrait(.., ref trait_item_refs) => {
+ trait_item_refs.iter()
+ .map(|trait_item_ref| trait_item_ref.id)
+ .map(|id| self.hir.local_def_id(id.node_id))
+ .collect()
+ }
+ hir::ItemImpl(.., ref impl_item_refs) => {
+ impl_item_refs.iter()
+ .map(|impl_item_ref| impl_item_ref.id)
+ .map(|id| self.hir.local_def_id(id.node_id))
+ .collect()
+ }
+ _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait")
+ };
+ Rc::new(vec)
+ })
}
- /// Returns a fully resolved definition for node id if it exists, panics otherwise.
- pub fn expect_def(self, id: NodeId) -> Def {
- self.expect_resolution(id).full_def()
+ #[inline] // FIXME(#35870) Avoid closures being unexported due to impl Trait.
+ pub fn associated_items(self, def_id: DefId)
+ -> impl Iterator<Item = ty::AssociatedItem> + 'a {
+ let def_ids = self.associated_item_def_ids(def_id);
+ (0..def_ids.len()).map(move |i| self.associated_item(def_ids[i]))
}
- /// Returns a fully resolved definition for node id if it exists, or none if no
- /// definition exists, panics on partial resolutions to catch errors.
- pub fn expect_def_or_none(self, id: NodeId) -> Option<Def> {
- self.def_map.borrow().get(&id).map(|resolution| resolution.full_def())
+ /// Returns the trait-ref corresponding to a given impl, or None if it is
+ /// an inherent impl.
+ pub fn impl_trait_ref(self, id: DefId) -> Option<TraitRef<'gcx>> {
+ queries::impl_trait_ref::get(self, DUMMY_SP, id)
}
// Returns `ty::VariantDef` if `def` refers to a struct,
// or variant or their constructors, panics otherwise.
- pub fn expect_variant_def(self, def: Def) -> VariantDef<'tcx> {
+ pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef {
match def {
Def::Variant(did) | Def::VariantCtor(did, ..) => {
let enum_did = self.parent_def_id(did).unwrap();
}
}
- pub fn def_key(self, id: DefId) -> ast_map::DefKey {
+ pub fn def_key(self, id: DefId) -> hir_map::DefKey {
if id.is_local() {
- self.map.def_key(id)
+ self.hir.def_key(id)
} else {
self.sess.cstore.def_key(id)
}
/// Convert a `DefId` into its fully expanded `DefPath` (every
/// `DefId` is really just an interned def-path).
///
- /// Note that if `id` is not local to this crate -- or is
- /// inlined into this crate -- the result will be a non-local
- /// `DefPath`.
- ///
- /// This function is only safe to use when you are sure that the
- /// full def-path is accessible. Examples that are known to be
- /// safe are local def-ids or items; see `opt_def_path` for more
- /// details.
- pub fn def_path(self, id: DefId) -> ast_map::DefPath {
- self.opt_def_path(id).unwrap_or_else(|| {
- bug!("could not load def-path for {:?}", id)
- })
+ /// Note that if `id` is not local to this crate, the result will
+ // be a non-local `DefPath`.
+ pub fn def_path(self, id: DefId) -> hir_map::DefPath {
+ if id.is_local() {
+ self.hir.def_path(id)
+ } else {
+ self.sess.cstore.def_path(id)
+ }
}
- /// Convert a `DefId` into its fully expanded `DefPath` (every
- /// `DefId` is really just an interned def-path).
- ///
- /// When going across crates, we do not save the full info for
- /// every cross-crate def-id, and hence we may not always be able
- /// to create a def-path. Therefore, this returns
- /// `Option<DefPath>` to cover that possibility. It will always
- /// return `Some` for local def-ids, however, as well as for
- /// items. The problems arise with "minor" def-ids like those
- /// associated with a pattern, `impl Trait`, or other internal
- /// detail to a fn.
- ///
- /// Note that if `id` is not local to this crate -- or is
- /// inlined into this crate -- the result will be a non-local
- /// `DefPath`.
- pub fn opt_def_path(self, id: DefId) -> Option<ast_map::DefPath> {
- if id.is_local() {
- Some(self.map.def_path(id))
+ pub fn def_span(self, def_id: DefId) -> Span {
+ if let Some(id) = self.hir.as_local_node_id(def_id) {
+ self.hir.span(id)
} else {
- self.sess.cstore.relative_def_path(id)
+ self.sess.cstore.def_span(&self.sess, def_id)
}
}
+ pub fn vis_is_accessible_from(self, vis: Visibility, block: NodeId) -> bool {
+ vis.is_accessible_from(self.hir.local_def_id(self.hir.get_module_parent(block)), self)
+ }
+
pub fn item_name(self, id: DefId) -> ast::Name {
- if let Some(id) = self.map.as_local_node_id(id) {
- self.map.name(id)
+ if let Some(id) = self.hir.as_local_node_id(id) {
+ self.hir.name(id)
} else if id.index == CRATE_DEF_INDEX {
- token::intern(&self.sess.cstore.original_crate_name(id.krate))
+ self.sess.cstore.original_crate_name(id.krate)
} else {
let def_key = self.sess.cstore.def_key(id);
// The name of a StructCtor is that of its struct parent.
- if let ast_map::DefPathData::StructCtor = def_key.disambiguated_data.data {
+ if let hir_map::DefPathData::StructCtor = def_key.disambiguated_data.data {
self.item_name(DefId {
krate: id.krate,
index: def_key.parent.unwrap()
}
}
- // Register a given item type
- pub fn register_item_type(self, did: DefId, scheme: TypeScheme<'gcx>) {
- self.tcache.borrow_mut().insert(did, scheme.ty);
- self.generics.borrow_mut().insert(did, scheme.generics);
- }
-
// If the given item is in an external crate, looks up its type and adds it to
// the type cache. Returns the type parameters and type.
- pub fn lookup_item_type(self, did: DefId) -> TypeScheme<'gcx> {
- let ty = lookup_locally_or_in_crate_store(
- "tcache", did, &self.tcache,
- || self.sess.cstore.item_type(self.global_tcx(), did));
-
- TypeScheme {
- ty: ty,
- generics: self.lookup_generics(did)
- }
- }
-
- pub fn opt_lookup_item_type(self, did: DefId) -> Option<TypeScheme<'gcx>> {
- if did.krate != LOCAL_CRATE {
- return Some(self.lookup_item_type(did));
- }
-
- if let Some(ty) = self.tcache.borrow().get(&did).cloned() {
- Some(TypeScheme {
- ty: ty,
- generics: self.lookup_generics(did)
- })
- } else {
- None
- }
+ pub fn item_type(self, did: DefId) -> Ty<'gcx> {
+ queries::ty::get(self, DUMMY_SP, did)
}
/// Given the did of a trait, returns its canonical trait ref.
- pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef<'gcx> {
- lookup_locally_or_in_crate_store(
- "trait_defs", did, &self.trait_defs,
- || self.alloc_trait_def(self.sess.cstore.trait_def(self.global_tcx(), did))
- )
- }
-
- /// Given the did of an ADT, return a master reference to its
- /// definition. Unless you are planning on fulfilling the ADT's fields,
- /// use lookup_adt_def instead.
- pub fn lookup_adt_def_master(self, did: DefId) -> AdtDefMaster<'gcx> {
- lookup_locally_or_in_crate_store(
- "adt_defs", did, &self.adt_defs,
- || self.sess.cstore.adt_def(self.global_tcx(), did)
- )
+ pub fn lookup_trait_def(self, did: DefId) -> &'gcx TraitDef {
+ queries::trait_def::get(self, DUMMY_SP, did)
}
/// Given the did of an ADT, return a reference to its definition.
- pub fn lookup_adt_def(self, did: DefId) -> AdtDef<'gcx> {
- // when reverse-variance goes away, a transmute::<AdtDefMaster,AdtDef>
- // would be needed here.
- self.lookup_adt_def_master(did)
+ pub fn lookup_adt_def(self, did: DefId) -> &'gcx AdtDef {
+ queries::adt_def::get(self, DUMMY_SP, did)
}
/// Given the did of an item, returns its generics.
- pub fn lookup_generics(self, did: DefId) -> &'gcx Generics<'gcx> {
- lookup_locally_or_in_crate_store(
- "generics", did, &self.generics,
- || self.alloc_generics(self.sess.cstore.item_generics(self.global_tcx(), did)))
+ pub fn item_generics(self, did: DefId) -> &'gcx Generics {
+ queries::generics::get(self, DUMMY_SP, did)
}
/// Given the did of an item, returns its full set of predicates.
- pub fn lookup_predicates(self, did: DefId) -> GenericPredicates<'gcx> {
- lookup_locally_or_in_crate_store(
- "predicates", did, &self.predicates,
- || self.sess.cstore.item_predicates(self.global_tcx(), did))
+ pub fn item_predicates(self, did: DefId) -> GenericPredicates<'gcx> {
+ queries::predicates::get(self, DUMMY_SP, did)
}
/// Given the did of a trait, returns its superpredicates.
- pub fn lookup_super_predicates(self, did: DefId) -> GenericPredicates<'gcx> {
- lookup_locally_or_in_crate_store(
- "super_predicates", did, &self.super_predicates,
- || self.sess.cstore.item_super_predicates(self.global_tcx(), did))
+ pub fn item_super_predicates(self, did: DefId) -> GenericPredicates<'gcx> {
+ queries::super_predicates::get(self, DUMMY_SP, did)
}
/// Given the did of an item, returns its MIR, borrowed immutably.
pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> {
- lookup_locally_or_in_crate_store("mir_map", did, &self.mir_map, || {
- let mir = self.sess.cstore.get_item_mir(self.global_tcx(), did);
- let mir = self.alloc_mir(mir);
+ queries::mir::get(self, DUMMY_SP, did).borrow()
+ }
+
+ /// Given the DefId of an item, returns its MIR, borrowed immutably.
+ /// Returns None if there is no MIR for the DefId
+ pub fn maybe_item_mir(self, did: DefId) -> Option<Ref<'gcx, Mir<'gcx>>> {
+ if did.is_local() && !self.maps.mir.borrow().contains_key(&did) {
+ return None;
+ }
- // Perma-borrow MIR from extern crates to prevent mutation.
- mem::forget(mir.borrow());
+ if !did.is_local() && !self.sess.cstore.is_item_mir_available(did) {
+ return None;
+ }
- mir
- }).borrow()
+ Some(self.item_mir(did))
}
/// If `type_needs_drop` returns true, then `ty` is definitely
/// Get the attributes of a definition.
pub fn get_attrs(self, did: DefId) -> Cow<'gcx, [ast::Attribute]> {
- if let Some(id) = self.map.as_local_node_id(did) {
- Cow::Borrowed(self.map.attrs(id))
+ if let Some(id) = self.hir.as_local_node_id(did) {
+ Cow::Borrowed(self.hir.attrs(id))
} else {
Cow::Owned(self.sess.cstore.item_attrs(did))
}
self.get_attrs(did).iter().any(|item| item.check_name(attr))
}
- /// Determine whether an item is annotated with `#[repr(packed)]`
- pub fn lookup_packed(self, did: DefId) -> bool {
- self.lookup_repr_hints(did).contains(&attr::ReprPacked)
- }
-
- /// Determine whether an item is annotated with `#[simd]`
- pub fn lookup_simd(self, did: DefId) -> bool {
- self.has_attr(did, "simd")
- || self.lookup_repr_hints(did).contains(&attr::ReprSimd)
- }
-
pub fn item_variances(self, item_id: DefId) -> Rc<Vec<ty::Variance>> {
- lookup_locally_or_in_crate_store(
- "item_variance_map", item_id, &self.item_variance_map,
- || Rc::new(self.sess.cstore.item_variances(item_id)))
+ queries::variances::get(self, DUMMY_SP, item_id)
}
pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool {
- self.populate_implementations_for_trait_if_necessary(trait_def_id);
-
let def = self.lookup_trait_def(trait_def_id);
def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL)
}
- /// Records a trait-to-implementation mapping.
- pub fn record_trait_has_default_impl(self, trait_def_id: DefId) {
- let def = self.lookup_trait_def(trait_def_id);
- def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL)
- }
-
- /// Load primitive inherent implementations if necessary
- pub fn populate_implementations_for_primitive_if_necessary(self,
- primitive_def_id: DefId) {
- if primitive_def_id.is_local() {
- return
- }
-
- // The primitive is not local, hence we are reading this out
- // of metadata.
- let _ignore = self.dep_graph.in_ignore();
-
- if self.populated_external_primitive_impls.borrow().contains(&primitive_def_id) {
- return
- }
-
- debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}",
- primitive_def_id);
-
- let impl_items = self.sess.cstore.impl_or_trait_items(primitive_def_id);
-
- // Store the implementation info.
- self.impl_or_trait_item_def_ids.borrow_mut().insert(primitive_def_id, Rc::new(impl_items));
- self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id);
- }
-
/// Populates the type context with all the inherent implementations for
/// the given type if necessary.
pub fn populate_inherent_implementations_for_type_if_necessary(self,
+ span: Span,
type_id: DefId) {
if type_id.is_local() {
+ // Make sure coherence of inherent impls ran already.
+ ty::queries::coherent_inherent_impls::force(self, span, LOCAL_CRATE);
return
}
type_id);
let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id);
- for &impl_def_id in &inherent_impls {
- // Store the implementation info.
- let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id);
- self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items));
- }
- self.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
+ self.maps.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
self.populated_external_types.borrow_mut().insert(type_id);
}
let _ignore = self.dep_graph.in_ignore();
let def = self.lookup_trait_def(trait_id);
- if def.flags.get().intersects(TraitFlags::IMPLS_VALID) {
+ if def.flags.get().intersects(TraitFlags::HAS_REMOTE_IMPLS) {
return;
}
debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def);
- if self.sess.cstore.is_defaulted_trait(trait_id) {
- self.record_trait_has_default_impl(trait_id);
- }
-
for impl_def_id in self.sess.cstore.implementations_of_trait(Some(trait_id)) {
- let impl_items = self.sess.cstore.impl_or_trait_items(impl_def_id);
let trait_ref = self.impl_trait_ref(impl_def_id).unwrap();
// Record the trait->implementation mapping.
let parent = self.sess.cstore.impl_parent(impl_def_id).unwrap_or(trait_id);
def.record_remote_impl(self, impl_def_id, trait_ref, parent);
-
- // For any methods that use a default implementation, add them to
- // the map. This is a bit unfortunate.
- for &impl_item_def_id in &impl_items {
- // load impl items eagerly for convenience
- // FIXME: we may want to load these lazily
- self.impl_or_trait_item(impl_item_def_id);
- }
-
- // Store the implementation info.
- self.impl_or_trait_item_def_ids.borrow_mut().insert(impl_def_id, Rc::new(impl_items));
}
- def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID);
+ def.flags.set(def.flags.get() | TraitFlags::HAS_REMOTE_IMPLS);
}
pub fn closure_kind(self, def_id: DefId) -> ty::ClosureKind {
- // If this is a local def-id, it should be inserted into the
- // tables by typeck; else, it will be retreived from
- // the external crate metadata.
- if let Some(&kind) = self.tables.borrow().closure_kinds.get(&def_id) {
- return kind;
- }
-
- let kind = self.sess.cstore.closure_kind(def_id);
- self.tables.borrow_mut().closure_kinds.insert(def_id, kind);
- kind
+ queries::closure_kind::get(self, DUMMY_SP, def_id)
}
- pub fn closure_type(self,
- def_id: DefId,
- substs: ClosureSubsts<'tcx>)
- -> ty::ClosureTy<'tcx>
- {
- // If this is a local def-id, it should be inserted into the
- // tables by typeck; else, it will be retreived from
- // the external crate metadata.
- if let Some(ty) = self.tables.borrow().closure_tys.get(&def_id) {
- return ty.subst(self, substs.func_substs);
- }
-
- let ty = self.sess.cstore.closure_ty(self.global_tcx(), def_id);
- self.tables.borrow_mut().closure_tys.insert(def_id, ty.clone());
- ty.subst(self, substs.func_substs)
+ pub fn closure_type(self, def_id: DefId) -> ty::PolyFnSig<'tcx> {
+ queries::closure_type::get(self, DUMMY_SP, def_id)
}
/// Given the def_id of an impl, return the def_id of the trait it implements.
/// If the given def ID describes a method belonging to an impl, return the
/// ID of the impl that the method belongs to. Otherwise, return `None`.
pub fn impl_of_method(self, def_id: DefId) -> Option<DefId> {
- if def_id.krate != LOCAL_CRATE {
- return self.sess.cstore.impl_or_trait_item(self.global_tcx(), def_id)
- .and_then(|item| {
- match item.container() {
- TraitContainer(_) => None,
- ImplContainer(def_id) => Some(def_id),
- }
- });
- }
- match self.impl_or_trait_items.borrow().get(&def_id).cloned() {
+ let item = if def_id.krate != LOCAL_CRATE {
+ if let Some(Def::Method(_)) = self.sess.cstore.describe_def(def_id) {
+ Some(self.associated_item(def_id))
+ } else {
+ None
+ }
+ } else {
+ self.maps.associated_item.borrow().get(&def_id).cloned()
+ };
+
+ match item {
Some(trait_item) => {
- match trait_item.container() {
+ match trait_item.container {
TraitContainer(_) => None,
ImplContainer(def_id) => Some(def_id),
}
if def_id.krate != LOCAL_CRATE {
return self.sess.cstore.trait_of_item(def_id);
}
- match self.impl_or_trait_items.borrow().get(&def_id) {
- Some(impl_or_trait_item) => {
- match impl_or_trait_item.container() {
+ match self.maps.associated_item.borrow().get(&def_id) {
+ Some(associated_item) => {
+ match associated_item.container {
TraitContainer(def_id) => Some(def_id),
ImplContainer(_) => None
}
}
}
- /// If the given def ID describes an item belonging to a trait, (either a
- /// default method or an implementation of a trait method), return the ID of
- /// the method inside trait definition (this means that if the given def ID
- /// is already that of the original trait method, then the return value is
- /// the same).
- /// Otherwise, return `None`.
- pub fn trait_item_of_item(self, def_id: DefId) -> Option<DefId> {
- let impl_or_trait_item = match self.impl_or_trait_items.borrow().get(&def_id) {
- Some(m) => m.clone(),
- None => return None,
- };
- match impl_or_trait_item.container() {
- TraitContainer(_) => Some(impl_or_trait_item.def_id()),
- ImplContainer(def_id) => {
- self.trait_id_of_impl(def_id).and_then(|trait_did| {
- let name = impl_or_trait_item.name();
- self.trait_items(trait_did).iter()
- .find(|item| item.name() == name)
- .map(|item| item.def_id())
- })
- }
- }
- }
-
/// Construct a parameter environment suitable for static contexts or other contexts where there
/// are no free type/lifetime parameters in scope.
pub fn empty_parameter_environment(self) -> ParameterEnvironment<'tcx> {
caller_bounds: Vec::new(),
implicit_region_bound: self.mk_region(ty::ReEmpty),
free_id_outlive: free_id_outlive,
- is_copy_cache: RefCell::new(FnvHashMap()),
- is_sized_cache: RefCell::new(FnvHashMap()),
+ is_copy_cache: RefCell::new(FxHashMap()),
+ is_sized_cache: RefCell::new(FxHashMap()),
}
}
//
let tcx = self.global_tcx();
- let generic_predicates = tcx.lookup_predicates(def_id);
+ let generic_predicates = tcx.item_predicates(def_id);
let bounds = generic_predicates.instantiate(tcx, free_substs);
let bounds = tcx.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds));
let predicates = bounds.predicates;
implicit_region_bound: tcx.mk_region(ty::ReScope(free_id_outlive)),
caller_bounds: predicates,
free_id_outlive: free_id_outlive,
- is_copy_cache: RefCell::new(FnvHashMap()),
- is_sized_cache: RefCell::new(FnvHashMap()),
+ is_copy_cache: RefCell::new(FxHashMap()),
+ is_sized_cache: RefCell::new(FxHashMap()),
};
let cause = traits::ObligationCause::misc(span, free_id_outlive.node_id(&self.region_maps));
self.mk_region(ty::ReScope(self.region_maps.node_extent(id)))
}
- pub fn visit_all_items_in_krate<V,F>(self,
- dep_node_fn: F,
- visitor: &mut V)
- where F: FnMut(DefId) -> DepNode<DefId>, V: Visitor<'gcx>
+ pub fn visit_all_item_likes_in_krate<V,F>(self,
+ dep_node_fn: F,
+ visitor: &mut V)
+ where F: FnMut(DefId) -> DepNode<DefId>, V: ItemLikeVisitor<'gcx>
{
- dep_graph::visit_all_items_in_krate(self.global_tcx(), dep_node_fn, visitor);
+ dep_graph::visit_all_item_likes_in_krate(self.global_tcx(), dep_node_fn, visitor);
+ }
+
+ /// Invokes `callback` for each body in the krate. This will
+ /// create a read edge from `DepNode::Krate` to the current task;
+ /// it is meant to be run in the context of some global task like
+ /// `BorrowckCrate`. The callback would then create a task like
+ /// `BorrowckBody(DefId)` to process each individual item.
+ pub fn visit_all_bodies_in_krate<C>(self, callback: C)
+ where C: Fn(/* body_owner */ DefId, /* body id */ hir::BodyId),
+ {
+ dep_graph::visit_all_bodies_in_krate(self.global_tcx(), callback)
}
/// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
/// with the name of the crate containing the impl.
- pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, InternedString> {
+ pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
if impl_did.is_local() {
- let node_id = self.map.as_local_node_id(impl_did).unwrap();
- Ok(self.map.span(node_id))
+ let node_id = self.hir.as_local_node_id(impl_did).unwrap();
+ Ok(self.hir.span(node_id))
} else {
Err(self.sess.cstore.crate_name(impl_did.krate))
}
}
}
-/// The category of explicit self.
-#[derive(Clone, Copy, Eq, PartialEq, Debug, RustcEncodable, RustcDecodable)]
-pub enum ExplicitSelfCategory<'tcx> {
- Static,
- ByValue,
- ByReference(&'tcx Region, hir::Mutability),
- ByBox,
-}
-
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn with_freevars<T, F>(self, fid: NodeId, f: F) -> T where
F: FnOnce(&[hir::Freevar]) -> T,