From 1f54df1101cabc4663906a5b8b6ca99bab6267a3 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 10 Aug 2017 16:10:04 +0200 Subject: [PATCH] Encapsulate sub-table access in TypeckTables and validate keys on each access. --- src/librustc/ich/impls_ty.rs | 68 +--- src/librustc/infer/mod.rs | 11 +- src/librustc/middle/dead.rs | 6 +- src/librustc/middle/effect.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 8 +- src/librustc/middle/mem_categorization.rs | 14 +- src/librustc/middle/reachable.rs | 2 +- src/librustc/traits/error_reporting.rs | 3 +- src/librustc/ty/context.rs | 355 +++++++++++++++++--- src/librustc_borrowck/borrowck/mod.rs | 8 +- src/librustc_const_eval/check_match.rs | 15 +- src/librustc_const_eval/pattern.rs | 4 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_lint/unused.rs | 3 +- src/librustc_mir/build/mod.rs | 3 +- src/librustc_mir/hair/cx/expr.rs | 11 +- src/librustc_passes/consts.rs | 6 +- src/librustc_privacy/lib.rs | 8 +- src/librustc_save_analysis/lib.rs | 4 +- src/librustc_typeck/check/_match.rs | 10 +- src/librustc_typeck/check/cast.rs | 9 +- src/librustc_typeck/check/closure.rs | 5 +- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 10 +- src/librustc_typeck/check/method/probe.rs | 4 +- src/librustc_typeck/check/mod.rs | 54 +-- src/librustc_typeck/check/op.rs | 10 +- src/librustc_typeck/check/regionck.rs | 23 +- src/librustc_typeck/check/upvar.rs | 12 +- src/librustc_typeck/check/writeback.rs | 103 +++--- src/librustc_typeck/collect.rs | 4 +- 31 files changed, 463 insertions(+), 316 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 279e62c6311..45b2a4a1e96 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -11,8 +11,7 @@ //! This module contains `HashStable` implementations for various data types //! from rustc::ty in no particular order. -use hir::def_id::DefId; -use ich::{self, StableHashingContext, NodeIdHashingMode}; +use ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use std::hash as std_hash; @@ -612,71 +611,6 @@ impl_stable_hash_for!(struct ty::ExistentialProjection<'tcx> { ty }); - -impl<'a, 'gcx, 'tcx> HashStable> -for ty::TypeckTables<'gcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, - hasher: &mut StableHasher) { - let ty::TypeckTables { - local_id_root, - ref type_dependent_defs, - ref node_types, - ref node_substs, - ref adjustments, - ref pat_binding_modes, - ref upvar_capture_map, - ref closure_tys, - ref closure_kinds, - ref liberated_fn_sigs, - ref fru_field_types, - - ref cast_kinds, - - ref used_trait_imports, - tainted_by_errors, - ref free_region_map, - } = *self; - - hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - ich::hash_stable_itemlocalmap(hcx, hasher, type_dependent_defs); - ich::hash_stable_itemlocalmap(hcx, hasher, node_types); - ich::hash_stable_itemlocalmap(hcx, hasher, node_substs); - ich::hash_stable_itemlocalmap(hcx, hasher, adjustments); - ich::hash_stable_itemlocalmap(hcx, hasher, pat_binding_modes); - ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| { - let ty::UpvarId { - var_id, - closure_expr_id - } = *up_var_id; - - let var_def_id = DefId { - krate: local_id_root.krate, - index: var_id, - }; - let closure_def_id = DefId { - krate: local_id_root.krate, - index: closure_expr_id, - }; - (hcx.def_path_hash(var_def_id), hcx.def_path_hash(closure_def_id)) - }); - - ich::hash_stable_itemlocalmap(hcx, hasher, closure_tys); - ich::hash_stable_itemlocalmap(hcx, hasher, closure_kinds); - ich::hash_stable_itemlocalmap(hcx, hasher, liberated_fn_sigs); - ich::hash_stable_itemlocalmap(hcx, hasher, fru_field_types); - ich::hash_stable_itemlocalmap(hcx, hasher, cast_kinds); - - ich::hash_stable_hashset(hcx, hasher, used_trait_imports, |hcx, def_id| { - hcx.def_path_hash(*def_id) - }); - - tainted_by_errors.hash_stable(hcx, hasher); - free_region_map.hash_stable(hcx, hasher); - }) - } -} - impl_stable_hash_for!(enum ty::fast_reject::SimplifiedType { BoolSimplifiedType, CharSimplifiedType, diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 727b0af2f54..1a8d570bde0 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1331,11 +1331,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { if let Some(tables) = self.in_progress_tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { - let tables = tables.borrow(); let hir_id = self.tcx.hir.node_to_hir_id(id); - tables.validate_hir_id(hir_id); - return tables.closure_kinds - .get(&hir_id.local_id) + return tables.borrow() + .closure_kinds() + .get(hir_id) .cloned() .map(|(kind, _)| kind); } @@ -1355,10 +1354,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn fn_sig(&self, def_id: DefId) -> ty::PolyFnSig<'tcx> { if let Some(tables) = self.in_progress_tables { if let Some(id) = self.tcx.hir.as_local_node_id(def_id) { - let tables = tables.borrow(); let hir_id = self.tcx.hir.node_to_hir_id(id); - tables.validate_hir_id(hir_id); - if let Some(&ty) = tables.closure_tys.get(&hir_id.local_id) { + if let Some(&ty) = tables.borrow().closure_tys().get(hir_id) { return ty; } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 0cca5690c01..0081555095b 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -94,8 +94,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } } - fn lookup_and_handle_method(&mut self, id: hir::ItemLocalId) { - self.check_def_id(self.tables.type_dependent_defs[&id].def_id()); + fn lookup_and_handle_method(&mut self, id: hir::HirId) { + self.check_def_id(self.tables.type_dependent_defs()[id].def_id()); } fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) { @@ -241,7 +241,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { self.handle_definition(def); } hir::ExprMethodCall(..) => { - self.lookup_and_handle_method(expr.hir_id.local_id); + self.lookup_and_handle_method(expr.hir_id); } hir::ExprField(ref lhs, ref name) => { self.handle_field_access(&lhs, name.node); diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index e8ecf9c21cd..6b7280cf0ac 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -166,7 +166,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprMethodCall(..) => { - let def_id = self.tables.type_dependent_defs[&expr.hir_id.local_id].def_id(); + let def_id = self.tables.type_dependent_defs()[expr.hir_id].def_id(); let sig = self.tcx.fn_sig(def_id); debug!("effect: method call case, signature is {:?}", sig); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 73800fe7f08..324f9a6e906 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -537,7 +537,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } ty::TyError => { } _ => { - let def_id = self.mc.tables.type_dependent_defs[&call.hir_id.local_id].def_id(); + let def_id = self.mc.tables.type_dependent_defs()[call.hir_id].def_id(); match OverloadedCallType::from_method_id(self.tcx(), def_id) { FnMutOverloadedCall => { let call_scope_r = self.tcx().node_scope_region(call.id); @@ -797,8 +797,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { pat); return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| { if let PatKind::Binding(..) = pat.node { - self.mc.tables.validate_hir_id(pat.hir_id); - let bm = *self.mc.tables.pat_binding_modes.get(&pat.hir_id.local_id) + let bm = *self.mc.tables.pat_binding_modes().get(pat.hir_id) .expect("missing binding mode"); match bm { ty::BindByReference(..) => @@ -824,8 +823,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(_, def_id, ..) = pat.node { debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode); - mc.tables.validate_hir_id(pat.hir_id); - let bm = *mc.tables.pat_binding_modes.get(&pat.hir_id.local_id) + let bm = *mc.tables.pat_binding_modes().get(pat.hir_id) .expect("missing binding mode"); // pat_ty: the type of the binding being produced. diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 08231a9ba1b..1f3f9fce854 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -334,10 +334,8 @@ impl MutabilityCategory { let ret = match tcx.hir.get(id) { hir_map::NodeLocal(p) => match p.node { PatKind::Binding(..) => { - - tables.validate_hir_id(p.hir_id); - let bm = *tables.pat_binding_modes - .get(&p.hir_id.local_id) + let bm = *tables.pat_binding_modes() + .get(p.hir_id) .expect("missing binding mode"); if bm == ty::BindByValue(hir::MutMutable) { McDeclared @@ -485,10 +483,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // fundamental fix to this conflated use of the node id. let ret_ty = match pat.node { PatKind::Binding(..) => { - self.tables.validate_hir_id(pat.hir_id); let bm = *self.tables - .pat_binding_modes - .get(&pat.hir_id.local_id) + .pat_binding_modes() + .get(pat.hir_id) .expect("missing binding mode"); if let ty::BindByReference(_) = bm { @@ -698,7 +695,6 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { -> McResult> { let fn_hir_id = self.tcx.hir.node_to_hir_id(fn_node_id); - self.tables.validate_hir_id(fn_hir_id); // An upvar can have up to 3 components. We translate first to a // `Categorization::Upvar`, which is itself a fiction -- it represents the reference to the @@ -723,7 +719,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // FnMut | copied -> &'env mut | upvar -> &'env mut -> &'up bk // FnOnce | copied | upvar -> &'up bk - let kind = match self.tables.closure_kinds.get(&fn_hir_id.local_id) { + let kind = match self.tables.closure_kinds().get(fn_hir_id) { Some(&(kind, _)) => kind, None => span_bug!(span, "missing closure kind") }; diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 98f82a51267..bd9a413ca61 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { Some(self.tables.qpath_def(qpath, expr.hir_id)) } hir::ExprMethodCall(..) => { - Some(self.tables.type_dependent_defs[&expr.hir_id.local_id]) + Some(self.tables.type_dependent_defs()[expr.hir_id]) } _ => None }; diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 8c4054254d0..c5b0f11b823 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -684,8 +684,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some(tables) = self.in_progress_tables { let tables = tables.borrow(); let closure_hir_id = self.tcx.hir.node_to_hir_id(node_id); - tables.validate_hir_id(closure_hir_id); - match tables.closure_kinds.get(&closure_hir_id.local_id) { + match tables.closure_kinds().get(closure_hir_id) { Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => { err.span_note(span, &format!( "closure is `FnOnce` because it moves the \ diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 77964f6845b..ac851f182a0 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -20,6 +20,7 @@ use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::map as hir_map; use hir::map::DefPathHash; use lint::{self, Lint}; +use ich::{self, StableHashingContext, NodeIdHashingMode}; use middle::free_region::FreeRegionMap; use middle::lang_items; use middle::resolve_lifetime; @@ -45,19 +46,22 @@ use ty::BindingMode; use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap}; use util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::accumulate_vec::AccumulateVec; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, + StableHasherResult}; use arena::{TypedArena, DroplessArena}; use rustc_data_structures::indexed_vec::IndexVec; use std::borrow::Borrow; use std::cell::{Cell, RefCell}; use std::cmp::Ordering; +use std::collections::hash_map::{self, Entry}; use std::hash::{Hash, Hasher}; use std::mem; use std::ops::Deref; use std::iter; use std::rc::Rc; use syntax::abi; -use syntax::ast::{self, Name}; +use syntax::ast::{self, Name, NodeId}; use syntax::attr; use syntax::codemap::MultiSpan; use syntax::symbol::{Symbol, keywords}; @@ -207,6 +211,91 @@ pub struct CommonTypes<'tcx> { pub re_erased: Region<'tcx>, } +pub struct LocalTableInContext<'a, V: 'a> { + local_id_root: DefId, + data: &'a ItemLocalMap +} + +/// Validate that the given HirId (respectively its `local_id` part) can be +/// safely used as a key in the tables of a TypeckTable. For that to be +/// the case, the HirId must have the same `owner` as all the other IDs in +/// this table (signified by `local_id_root`). Otherwise the HirId +/// would be in a different frame of reference and using its `local_id` +/// would result in lookup errors, or worse, in silently wrong data being +/// stored/returned. +fn validate_hir_id_for_typeck_tables(table_id_root: DefId, hir_id: hir::HirId) { + #[cfg(debug_assertions)] + { + if table_id_root.is_local() { + if hir_id.owner != table_id_root.index { + ty::tls::with(|tcx| { + let node_id = tcx.hir + .definitions() + .find_node_for_hir_id(hir_id); + + bug!("node {} with HirId::owner {:?} cannot be placed in \ + TypeckTables with local_id_root {:?}", + tcx.hir.node_to_string(node_id), + DefId::local(hir_id.owner), + table_id_root) + }); + } + } + } +} + +impl<'a, V> LocalTableInContext<'a, V> { + pub fn contains_key(&self, id: hir::HirId) -> bool { + validate_hir_id_for_typeck_tables(self.local_id_root, id); + self.data.contains_key(&id.local_id) + } + + pub fn get(&self, id: hir::HirId) -> Option<&V> { + validate_hir_id_for_typeck_tables(self.local_id_root, id); + self.data.get(&id.local_id) + } + + pub fn iter(&self) -> hash_map::Iter { + self.data.iter() + } +} + +impl<'a, V> ::std::ops::Index for LocalTableInContext<'a, V> { + type Output = V; + + fn index(&self, key: hir::HirId) -> &V { + self.get(key).expect("LocalTableInContext: key not found") + } +} + +pub struct LocalTableInContextMut<'a, V: 'a> { + local_id_root: DefId, + data: &'a mut ItemLocalMap +} + +impl<'a, V> LocalTableInContextMut<'a, V> { + + pub fn get_mut(&mut self, id: hir::HirId) -> Option<&mut V> { + validate_hir_id_for_typeck_tables(self.local_id_root, id); + self.data.get_mut(&id.local_id) + } + + pub fn entry(&mut self, id: hir::HirId) -> Entry { + validate_hir_id_for_typeck_tables(self.local_id_root, id); + self.data.entry(id.local_id) + } + + pub fn insert(&mut self, id: hir::HirId, val: V) -> Option { + validate_hir_id_for_typeck_tables(self.local_id_root, id); + self.data.insert(id.local_id, val) + } + + pub fn remove(&mut self, id: hir::HirId) -> Option { + validate_hir_id_for_typeck_tables(self.local_id_root, id); + self.data.remove(&id.local_id) + } +} + #[derive(RustcEncodable, RustcDecodable)] pub struct TypeckTables<'tcx> { /// The HirId::owner all ItemLocalIds in this table are relative to. @@ -214,50 +303,50 @@ pub struct TypeckTables<'tcx> { /// Resolved definitions for `::X` associated paths and /// method calls, including those of overloaded operators. - pub type_dependent_defs: ItemLocalMap, + type_dependent_defs: ItemLocalMap, /// Stores the types for various nodes in the AST. Note that this table /// is not guaranteed to be populated until after typeck. See /// typeck::check::fn_ctxt for details. - pub node_types: ItemLocalMap>, + node_types: ItemLocalMap>, /// Stores the type parameters which were substituted to obtain the type /// of this node. This only applies to nodes that refer to entities /// parameterized by type parameters, such as generic fns, types, or /// other items. - pub node_substs: ItemLocalMap<&'tcx Substs<'tcx>>, + node_substs: ItemLocalMap<&'tcx Substs<'tcx>>, - pub adjustments: ItemLocalMap>>, + adjustments: ItemLocalMap>>, // Stores the actual binding mode for all instances of hir::BindingAnnotation. - pub pat_binding_modes: ItemLocalMap, + pat_binding_modes: ItemLocalMap, /// Borrows pub upvar_capture_map: ty::UpvarCaptureMap<'tcx>, /// Records the type of each closure. - pub closure_tys: ItemLocalMap>, + closure_tys: ItemLocalMap>, /// Records the kind of each closure and the span and name of the variable /// that caused the closure to be this kind. - pub closure_kinds: ItemLocalMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, + closure_kinds: ItemLocalMap<(ty::ClosureKind, Option<(Span, ast::Name)>)>, /// For each fn, records the "liberated" types of its arguments /// and return type. Liberated means that all bound regions /// (including late-bound regions) are replaced with free /// equivalents. This table is not used in trans (since regions /// are erased there) and hence is not serialized to metadata. - pub liberated_fn_sigs: ItemLocalMap>, + liberated_fn_sigs: ItemLocalMap>, /// For each FRU expression, record the normalized types of the fields /// of the struct - this is needed because it is non-trivial to /// normalize while preserving regions. This table is used only in /// MIR construction and hence is not serialized to metadata. - pub fru_field_types: ItemLocalMap>>, + fru_field_types: ItemLocalMap>>, /// Maps a cast expression to its kind. This is keyed on the /// *from* expression of the cast, not the cast itself. - pub cast_kinds: ItemLocalMap, + cast_kinds: ItemLocalMap, /// Set of trait imports actually used in the method resolution. /// This is used for warning unused imports. @@ -288,7 +377,6 @@ impl<'tcx> TypeckTables<'tcx> { liberated_fn_sigs: ItemLocalMap(), fru_field_types: ItemLocalMap(), cast_kinds: ItemLocalMap(), - lints: lint::LintTable::new(), used_trait_imports: DefIdSet(), tainted_by_errors: false, free_region_map: FreeRegionMap::new(), @@ -300,12 +388,40 @@ impl<'tcx> TypeckTables<'tcx> { match *qpath { hir::QPath::Resolved(_, ref path) => path.def, hir::QPath::TypeRelative(..) => { - self.validate_hir_id(id); + validate_hir_id_for_typeck_tables(self.local_id_root, id); self.type_dependent_defs.get(&id.local_id).cloned().unwrap_or(Def::Err) } } } + pub fn type_dependent_defs(&self) -> LocalTableInContext { + LocalTableInContext { + local_id_root: self.local_id_root, + data: &self.type_dependent_defs + } + } + + pub fn type_dependent_defs_mut(&mut self) -> LocalTableInContextMut { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.type_dependent_defs + } + } + + pub fn node_types(&self) -> LocalTableInContext> { + LocalTableInContext { + local_id_root: self.local_id_root, + data: &self.node_types + } + } + + pub fn node_types_mut(&mut self) -> LocalTableInContextMut> { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.node_types + } + } + pub fn node_id_to_type(&self, id: hir::HirId) -> Ty<'tcx> { match self.node_id_to_type_opt(id) { Some(ty) => ty, @@ -320,15 +436,27 @@ impl<'tcx> TypeckTables<'tcx> { } pub fn node_id_to_type_opt(&self, id: hir::HirId) -> Option> { - self.validate_hir_id(id); + validate_hir_id_for_typeck_tables(self.local_id_root, id); self.node_types.get(&id.local_id).cloned() } + pub fn node_substs_mut(&mut self) -> LocalTableInContextMut<&'tcx Substs<'tcx>> { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.node_substs + } + } + pub fn node_substs(&self, id: hir::HirId) -> &'tcx Substs<'tcx> { - self.validate_hir_id(id); + validate_hir_id_for_typeck_tables(self.local_id_root, id); self.node_substs.get(&id.local_id).cloned().unwrap_or(Substs::empty()) } + pub fn node_substs_opt(&self, id: hir::HirId) -> Option<&'tcx Substs<'tcx>> { + validate_hir_id_for_typeck_tables(self.local_id_root, id); + self.node_substs.get(&id.local_id).cloned() + } + // Returns the type of a pattern as a monotype. Like @expr_ty, this function // doesn't provide type parameter substitutions. pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> { @@ -357,9 +485,24 @@ impl<'tcx> TypeckTables<'tcx> { self.node_id_to_type_opt(expr.hir_id) } + pub fn adjustments(&self) -> LocalTableInContext>> { + LocalTableInContext { + local_id_root: self.local_id_root, + data: &self.adjustments + } + } + + pub fn adjustments_mut(&mut self) + -> LocalTableInContextMut>> { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.adjustments + } + } + pub fn expr_adjustments(&self, expr: &hir::Expr) -> &[ty::adjustment::Adjustment<'tcx>] { - self.validate_hir_id(expr.hir_id); + validate_hir_id_for_typeck_tables(self.local_id_root, expr.hir_id); self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..]) } @@ -385,48 +528,166 @@ impl<'tcx> TypeckTables<'tcx> { return false; } - self.validate_hir_id(expr.hir_id); - match self.type_dependent_defs.get(&expr.hir_id.local_id) { + match self.type_dependent_defs().get(expr.hir_id) { Some(&Def::Method(_)) => true, _ => false } } + pub fn pat_binding_modes(&self) -> LocalTableInContext { + LocalTableInContext { + local_id_root: self.local_id_root, + data: &self.pat_binding_modes + } + } + + pub fn pat_binding_modes_mut(&mut self) + -> LocalTableInContextMut { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.pat_binding_modes + } + } + pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> { self.upvar_capture_map[&upvar_id] } - /// Validate that the given HirId (respectively its `local_id` part) can be - /// safely used as a key in the tables of this TypeckTable. For that to be - /// the case, the HirId must have the same `owner` as all the other IDs in - /// this table (signified by the `local_id_root` field). Otherwise the HirId - /// would be in a different frame of reference and using its `local_id` - /// would result in lookup errors, or worse, in silently wrong data being - /// stored/returned. - /// - /// Therefore it is advised to call this method anytime before using a given - /// HirId::local_id as a key. - #[inline] - pub fn validate_hir_id(&self, hir_id: hir::HirId) { - #[cfg(debug_assertions)] - { - if self.local_id_root.is_local() { - if hir_id.owner != self.local_id_root.index { - ty::tls::with(|tcx| { - let node_id = tcx.hir - .definitions() - .find_node_for_hir_id(hir_id); - - bug!("node {} with HirId::owner {:?} cannot be placed in \ - TypeckTables with local_id_root {:?}", - tcx.hir.node_to_string(node_id), - DefId::local(hir_id.owner), - self.local_id_root) - }); - } - } + pub fn closure_tys(&self) -> LocalTableInContext> { + LocalTableInContext { + local_id_root: self.local_id_root, + data: &self.closure_tys } } + + pub fn closure_tys_mut(&mut self) + -> LocalTableInContextMut> { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.closure_tys + } + } + + pub fn closure_kinds(&self) -> LocalTableInContext<(ty::ClosureKind, + Option<(Span, ast::Name)>)> { + LocalTableInContext { + local_id_root: self.local_id_root, + data: &self.closure_kinds + } + } + + pub fn closure_kinds_mut(&mut self) + -> LocalTableInContextMut<(ty::ClosureKind, Option<(Span, ast::Name)>)> { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.closure_kinds + } + } + + pub fn liberated_fn_sigs(&self) -> LocalTableInContext> { + LocalTableInContext { + local_id_root: self.local_id_root, + data: &self.liberated_fn_sigs + } + } + + pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut> { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.liberated_fn_sigs + } + } + + pub fn fru_field_types(&self) -> LocalTableInContext>> { + LocalTableInContext { + local_id_root: self.local_id_root, + data: &self.fru_field_types + } + } + + pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut>> { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.fru_field_types + } + } + + pub fn cast_kinds(&self) -> LocalTableInContext { + LocalTableInContext { + local_id_root: self.local_id_root, + data: &self.cast_kinds + } + } + + pub fn cast_kinds_mut(&mut self) -> LocalTableInContextMut { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.cast_kinds + } + } +} + +impl<'a, 'gcx, 'tcx> HashStable> for TypeckTables<'gcx> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>, + hasher: &mut StableHasher) { + let ty::TypeckTables { + local_id_root, + ref type_dependent_defs, + ref node_types, + ref node_substs, + ref adjustments, + ref pat_binding_modes, + ref upvar_capture_map, + ref closure_tys, + ref closure_kinds, + ref liberated_fn_sigs, + ref fru_field_types, + + ref cast_kinds, + + ref used_trait_imports, + tainted_by_errors, + ref free_region_map, + } = *self; + + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + ich::hash_stable_itemlocalmap(hcx, hasher, type_dependent_defs); + ich::hash_stable_itemlocalmap(hcx, hasher, node_types); + ich::hash_stable_itemlocalmap(hcx, hasher, node_substs); + ich::hash_stable_itemlocalmap(hcx, hasher, adjustments); + ich::hash_stable_itemlocalmap(hcx, hasher, pat_binding_modes); + ich::hash_stable_hashmap(hcx, hasher, upvar_capture_map, |hcx, up_var_id| { + let ty::UpvarId { + var_id, + closure_expr_id + } = *up_var_id; + + let var_def_id = DefId { + krate: local_id_root.krate, + index: var_id, + }; + let closure_def_id = DefId { + krate: local_id_root.krate, + index: closure_expr_id, + }; + (hcx.def_path_hash(var_def_id), hcx.def_path_hash(closure_def_id)) + }); + + ich::hash_stable_itemlocalmap(hcx, hasher, closure_tys); + ich::hash_stable_itemlocalmap(hcx, hasher, closure_kinds); + ich::hash_stable_itemlocalmap(hcx, hasher, liberated_fn_sigs); + ich::hash_stable_itemlocalmap(hcx, hasher, fru_field_types); + ich::hash_stable_itemlocalmap(hcx, hasher, cast_kinds); + + ich::hash_stable_hashset(hcx, hasher, used_trait_imports, |hcx, def_id| { + hcx.def_path_hash(*def_id) + }); + + tainted_by_errors.hash_stable(hcx, hasher); + free_region_map.hash_stable(hcx, hasher); + }) + } } impl<'tcx> CommonTypes<'tcx> { diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 07981cc67fc..412af05f5bd 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -600,9 +600,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { ty::TypeVariants::TyClosure(id, _) => { let node_id = self.tcx.hir.as_local_node_id(id).unwrap(); let hir_id = self.tcx.hir.node_to_hir_id(node_id); - self.tables.validate_hir_id(hir_id); if let Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) = - self.tables.closure_kinds.get(&hir_id.local_id) + self.tables.closure_kinds().get(hir_id) { err.span_note(span, &format!( "closure cannot be invoked more than once because \ @@ -904,10 +903,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { match pat.node { hir::PatKind::Binding(..) => { - self.tables.validate_hir_id(pat.hir_id); *self.tables - .pat_binding_modes - .get(&pat.hir_id.local_id) + .pat_binding_modes() + .get(pat.hir_id) .expect("missing binding mode") } _ => bug!("local is not a binding: {:?}", pat) diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index a990670f08b..ea7deef4724 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -269,10 +269,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) { pat.walk(|p| { if let PatKind::Binding(_, _, name, None) = p.node { - cx.tables.validate_hir_id(p.hir_id); let bm = *cx.tables - .pat_binding_modes - .get(&p.hir_id.local_id) + .pat_binding_modes() + .get(p.hir_id) .expect("missing binding mode"); if bm != ty::BindByValue(hir::MutImmutable) { @@ -464,10 +463,9 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, for pat in pats { pat.each_binding(|_, id, span, _path| { let hir_id = cx.tcx.hir.node_to_hir_id(id); - cx.tables.validate_hir_id(hir_id); let bm = *cx.tables - .pat_binding_modes - .get(&hir_id.local_id) + .pat_binding_modes() + .get(hir_id) .expect("missing binding mode"); if let ty::BindByReference(..) = bm { by_ref_span = Some(span); @@ -501,10 +499,9 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, for pat in pats { pat.walk(|p| { if let PatKind::Binding(_, _, _, ref sub) = p.node { - cx.tables.validate_hir_id(p.hir_id); let bm = *cx.tables - .pat_binding_modes - .get(&p.hir_id.local_id) + .pat_binding_modes() + .get(p.hir_id) .expect("missing binding mode"); match bm { ty::BindByValue(..) => { diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 924193786c1..d151e817040 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -381,8 +381,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::TyRef(r, _) => Some(r), _ => None, }; - let bm = *self.tables.pat_binding_modes.get(&pat.hir_id.local_id) - .expect("missing binding mode"); + let bm = *self.tables.pat_binding_modes().get(pat.hir_id) + .expect("missing binding mode"); let (mutability, mode) = match bm { ty::BindByValue(hir::MutMutable) => (Mutability::Mut, BindingMode::ByValue), diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 56c0fa7b2ad..cef35be59cd 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -935,7 +935,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { // Check for method calls and overloaded operators. if cx.tables.is_method_call(expr) { let hir_id = cx.tcx.hir.definitions().node_to_hir_id(id); - let def_id = cx.tables.type_dependent_defs[&hir_id.local_id].def_id(); + let def_id = cx.tables.type_dependent_defs()[hir_id].def_id(); let substs = cx.tables.node_substs(hir_id); if method_call_refers_to_method(cx, method, def_id, substs, id) { return true; diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index f8f91e6c29d..65973d99c54 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -46,8 +46,7 @@ impl UnusedMut { for p in pats { p.each_binding(|_, id, span, path1| { let hir_id = cx.tcx.hir.node_to_hir_id(id); - cx.tables.validate_hir_id(hir_id); - let bm = match cx.tables.pat_binding_modes.get(&hir_id.local_id) { + let bm = match cx.tables.pat_binding_modes().get(hir_id) { Some(&bm) => bm, None => span_bug!(span, "missing binding mode"), }; diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index d029e2f10e8..14392ae70e4 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -91,8 +91,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) let fn_hir_id = tcx.hir.node_to_hir_id(id); - cx.tables().validate_hir_id(fn_hir_id); - let fn_sig = cx.tables().liberated_fn_sigs[&fn_hir_id.local_id].clone(); + let fn_sig = cx.tables().liberated_fn_sigs()[fn_hir_id].clone(); let ty = tcx.type_of(tcx.hir.local_def_id(id)); let mut abi = fn_sig.abi; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 11da73187b3..5b3e4b1ddc3 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -387,11 +387,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, substs: substs, fields: field_refs, base: base.as_ref().map(|base| { - cx.tables().validate_hir_id(expr.hir_id); FruInfo { base: base.to_ref(), field_types: cx.tables() - .fru_field_types[&expr.hir_id.local_id] + .fru_field_types()[expr.hir_id] .clone(), } }), @@ -551,10 +550,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprCast(ref source, _) => { // Check to see if this cast is a "coercion cast", where the cast is actually done // using a coercion (or is a no-op). - cx.tables().validate_hir_id(source.hir_id); if let Some(&TyCastKind::CoercionCast) = cx.tables() - .cast_kinds - .get(&source.hir_id.local_id) { + .cast_kinds() + .get(source.hir_id) { // Convert the lexpr to a vexpr. ExprKind::Use { source: source.to_ref() } } else { @@ -586,8 +584,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, -> Expr<'tcx> { let temp_lifetime = cx.region_maps.temporary_scope(expr.id); let (def_id, substs) = custom_callee.unwrap_or_else(|| { - cx.tables().validate_hir_id(expr.hir_id); - (cx.tables().type_dependent_defs[&expr.hir_id.local_id].def_id(), + (cx.tables().type_dependent_defs()[expr.hir_id].def_id(), cx.tables().node_substs(expr.hir_id)) }); Expr { diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 4a2925175c2..a390448f43a 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -320,8 +320,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } hir::ExprCast(ref from, _) => { debug!("Checking const cast(id={})", from.id); - v.tables.validate_hir_id(from.hir_id); - match v.tables.cast_kinds.get(&from.hir_id.local_id) { + match v.tables.cast_kinds().get(from.hir_id) { None => span_bug!(e.span, "no kind for cast"), Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => { v.promotable = false; @@ -388,8 +387,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprMethodCall(..) => { - v.tables.validate_hir_id(e.hir_id); - let def_id = v.tables.type_dependent_defs[&e.hir_id.local_id].def_id(); + let def_id = v.tables.type_dependent_defs()[e.hir_id].def_id(); match v.tcx.associated_item(def_id).container { ty::ImplContainer(_) => v.handle_const_fn_call(def_id, node_ty), ty::TraitContainer(_) => v.promotable = false diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 1c5e528d887..6f8c6a5ed3b 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -649,7 +649,7 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { if self.tables.node_substs(id).visit_with(self) { return true; } - if let Some(adjustments) = self.tables.adjustments.get(&id.local_id) { + if let Some(adjustments) = self.tables.adjustments().get(id) { for adjustment in adjustments { if adjustment.target.visit_with(self) { return true; @@ -748,8 +748,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } hir::ExprMethodCall(_, span, _) => { // Method calls have to be checked specially. - self.tables.validate_hir_id(expr.hir_id); - let def_id = self.tables.type_dependent_defs[&expr.hir_id.local_id].def_id(); + let def_id = self.tables.type_dependent_defs()[expr.hir_id].def_id(); self.span = span; if self.tcx.type_of(def_id).visit_with(self) { return; @@ -766,8 +765,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // we have to check it additionally. if let hir::QPath::TypeRelative(..) = *qpath { let hir_id = self.tcx.hir.node_to_hir_id(id); - self.tables.validate_hir_id(hir_id); - if let Some(def) = self.tables.type_dependent_defs.get(&hir_id.local_id).cloned() { + if let Some(def) = self.tables.type_dependent_defs().get(hir_id).cloned() { if let Some(assoc_item) = self.tcx.opt_associated_item(def.def_id()) { if let ty::ImplContainer(impl_def_id) = assoc_item.container { if self.tcx.type_of(impl_def_id).visit_with(self) { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index d46d8624a12..8baea0fd83d 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -550,8 +550,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } ast::ExprKind::MethodCall(..) => { - let local_id = self.tcx.hir.definitions().node_to_hir_id(expr.id).local_id; - let method_id = self.tables.type_dependent_defs[&local_id].def_id(); + let expr_hir_id = self.tcx.hir.definitions().node_to_hir_id(expr.id); + let method_id = self.tables.type_dependent_defs()[expr_hir_id].def_id(); let (def_id, decl_id) = match self.tcx.associated_item(method_id).container { ty::ImplContainer(_) => (Some(method_id), None), ty::TraitContainer(_) => (None, Some(method_id)), diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 3a616dadc42..b49b9377e8c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -118,11 +118,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // identical to what could be scraped from the HIR, but this will change with // default binding modes (#42640). let bm = ty::BindingMode::convert(ba); - { - let mut inh_tables = self.inh.tables.borrow_mut(); - inh_tables.validate_hir_id(pat.hir_id); - inh_tables.pat_binding_modes.insert(pat.hir_id.local_id, bm); - } + self.inh + .tables + .borrow_mut() + .pat_binding_modes_mut() + .insert(pat.hir_id, bm); let typ = self.local_ty(pat.span, pat.id); match bm { ty::BindByReference(mutbl) => { diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 2be427eee1b..b18b11f3d90 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -330,16 +330,13 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { } else if self.try_coercion_cast(fcx) { self.trivial_cast_lint(fcx); debug!(" -> CoercionCast"); - let mut tables = fcx.tables.borrow_mut(); - tables.validate_hir_id(self.expr.hir_id); - tables.cast_kinds.insert(self.expr.hir_id.local_id, CastKind::CoercionCast); + fcx.tables.borrow_mut().cast_kinds_mut().insert(self.expr.hir_id, + CastKind::CoercionCast); } else { match self.do_check(fcx) { Ok(k) => { debug!(" -> {:?}", k); - let mut tables = fcx.tables.borrow_mut(); - tables.validate_hir_id(self.expr.hir_id); - tables.cast_kinds.insert(self.expr.hir_id.local_id, k); + fcx.tables.borrow_mut().cast_kinds_mut().insert(self.expr.hir_id, k); } Err(e) => self.report_cast_error(fcx, e), }; diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 8bf58d866ef..61795a7e623 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -104,11 +104,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { { let mut tables = self.tables.borrow_mut(); - tables.validate_hir_id(expr.hir_id); - tables.closure_tys.insert(expr.hir_id.local_id, sig); + tables.closure_tys_mut().insert(expr.hir_id, sig); match opt_kind { Some(kind) => { - tables.closure_kinds.insert(expr.hir_id.local_id, (kind, None)); + tables.closure_kinds_mut().insert(expr.hir_id, (kind, None)); } None => {} } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 428938eae82..53f3d811fae 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -844,7 +844,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // First try to coerce the new expression to the type of the previous ones, // but only if the new expression has no coercion already applied to it. let mut first_error = None; - if !self.tables.borrow().adjustments.contains_key(&new.hir_id.local_id) { + if !self.tables.borrow().adjustments().contains_key(new.hir_id) { let result = self.commit_if_ok(|_| coerce.coerce(new_ty, prev_ty)); match result { Ok(ok) => { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 0294dab17d5..355e6cdbbe0 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -451,8 +451,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // tables borrowed during (`deref_mut`) method resolution. let previous_adjustments = self.tables .borrow_mut() - .adjustments - .remove(&expr.hir_id.local_id); + .adjustments_mut() + .remove(expr.hir_id); if let Some(mut adjustments) = previous_adjustments { let pref = LvaluePreference::PreferMutLvalue; for adjustment in &mut adjustments { @@ -469,7 +469,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { } source = adjustment.target; } - self.tables.borrow_mut().adjustments.insert(expr.hir_id.local_id, adjustments); + self.tables.borrow_mut().adjustments_mut().insert(expr.hir_id, adjustments); } match expr.node { @@ -529,8 +529,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let base_expr_ty = self.node_ty(base_expr.hir_id); if let Some(adjustments) = self.tables .borrow_mut() - .adjustments - .get_mut(&base_expr.hir_id.local_id) { + .adjustments_mut() + .get_mut(base_expr.hir_id) { let mut source = base_expr_ty; for adjustment in &mut adjustments[..] { if let Adjust::Borrow(AutoBorrow::Ref(..)) = adjustment.kind { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index fc8f4f32440..5de4a35bdc7 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -829,9 +829,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { }; let closure_kind = { - let tables = self.tables.borrow(); - tables.validate_hir_id(closure_id); - match tables.closure_kinds.get(&closure_id.local_id) { + match self.tables.borrow().closure_kinds().get(closure_id) { Some(&(k, _)) => k, None => { return Err(MethodError::ClosureAmbiguity(trait_def_id)); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 60930d8184a..483b5bb1020 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -744,7 +744,7 @@ fn closure_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, -> ty::ClosureKind { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let hir_id = tcx.hir.node_to_hir_id(node_id); - tcx.typeck_tables_of(def_id).closure_kinds[&hir_id.local_id].0 + tcx.typeck_tables_of(def_id).closure_kinds()[hir_id].0 } fn adt_destructor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -1028,12 +1028,8 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, fcx.write_ty(arg.hir_id, arg_ty); } - { - let mut inh_tables = inherited.tables.borrow_mut(); - let fn_hir_id = fcx.tcx.hir.node_to_hir_id(fn_id); - inh_tables.validate_hir_id(fn_hir_id); - inh_tables.liberated_fn_sigs.insert(fn_hir_id.local_id, fn_sig); - } + let fn_hir_id = fcx.tcx.hir.node_to_hir_id(fn_id); + inherited.tables.borrow_mut().liberated_fn_sigs_mut().insert(fn_hir_id, fn_sig); fcx.check_return_expr(&body.value); @@ -1816,11 +1812,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn write_ty(&self, id: hir::HirId, ty: Ty<'tcx>) { debug!("write_ty({:?}, {:?}) in fcx {}", id, self.resolve_type_vars_if_possible(&ty), self.tag()); - { - let mut tables = self.tables.borrow_mut(); - tables.validate_hir_id(id); - tables.node_types.insert(id.local_id, ty); - } + self.tables.borrow_mut().node_types_mut().insert(id, ty); if ty.references_error() { self.has_errors.set(true); @@ -1833,11 +1825,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { - { - let mut tables = self.tables.borrow_mut(); - tables.validate_hir_id(hir_id); - tables.type_dependent_defs.insert(hir_id.local_id, Def::Method(method.def_id)); - } + self.tables + .borrow_mut() + .type_dependent_defs_mut() + .insert(hir_id, Def::Method(method.def_id)); self.write_substs(hir_id, method.substs); } @@ -1848,9 +1839,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { substs, self.tag()); - let mut tables = self.tables.borrow_mut(); - tables.validate_hir_id(node_id); - tables.node_substs.insert(node_id.local_id, substs); + self.tables.borrow_mut().node_substs_mut().insert(node_id, substs); } } @@ -1861,9 +1850,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return; } - let mut tables = self.tables.borrow_mut(); - tables.validate_hir_id(expr.hir_id); - match tables.adjustments.entry(expr.hir_id.local_id) { + match self.tables.borrow_mut().adjustments_mut().entry(expr.hir_id) { Entry::Vacant(entry) => { entry.insert(adj); }, Entry::Occupied(mut entry) => { debug!(" - composing on top of {:?}", entry.get()); @@ -2017,9 +2004,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> { - let tables = self.tables.borrow(); - tables.validate_hir_id(id); - match tables.node_types.get(&id.local_id) { + match self.tables.borrow().node_types().get(id) { Some(&t) => t, None if self.err_count_since_creation() != 0 => self.tcx.types.err, None => { @@ -2682,7 +2667,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // While we don't allow *arbitrary* coercions here, we *do* allow // coercions from ! to `expected`. if ty.is_never() { - assert!(!self.tables.borrow().adjustments.contains_key(&expr.hir_id.local_id), + assert!(!self.tables.borrow().adjustments().contains_key(expr.hir_id), "expression with never type wound up being adjusted"); let adj_ty = self.next_diverging_ty_var( TypeVariableOrigin::AdjustmentType(expr.span)); @@ -3408,9 +3393,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs)) }).collect(); - let mut tables = self.tables.borrow_mut(); - tables.validate_hir_id(expr.hir_id); - tables.fru_field_types.insert(expr.hir_id.local_id, fru_field_types); + self.tables + .borrow_mut() + .fru_field_types_mut() + .insert(expr.hir_id, fru_field_types); } _ => { span_err!(self.tcx.sess, base_expr.span, E0436, @@ -4043,9 +4029,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Write back the new resolution. let hir_id = self.tcx.hir.node_to_hir_id(node_id); - let mut tables = self.tables.borrow_mut(); - tables.validate_hir_id(hir_id); - tables.type_dependent_defs.insert(hir_id.local_id, def); + self.tables.borrow_mut().type_dependent_defs_mut().insert(hir_id, def); (def, ty) } @@ -4087,9 +4071,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Write back the new resolution. let hir_id = self.tcx.hir.node_to_hir_id(node_id); - let mut tables = self.tables.borrow_mut(); - tables.validate_hir_id(hir_id); - tables.type_dependent_defs.insert(hir_id.local_id, def); + self.tables.borrow_mut().type_dependent_defs_mut().insert(hir_id, def); (def, Some(ty), slice::ref_slice(&**item_segment)) } diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index f2104b8dbae..a4e1fdaf39e 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -210,10 +210,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // some cases applied on the RHS, on top of which we need // to autoref, which is not allowed by apply_adjustments. // self.apply_adjustments(rhs_expr, vec![autoref]); - let mut tables = self.tables.borrow_mut(); - tables.validate_hir_id(rhs_expr.hir_id); - tables.adjustments.entry(rhs_expr.hir_id.local_id) - .or_insert(vec![]).push(autoref); + self.tables + .borrow_mut() + .adjustments_mut() + .entry(rhs_expr.hir_id) + .or_insert(vec![]) + .push(autoref); } } self.write_method_call(expr.hir_id, method); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index c9c8f3363ce..b187075a36d 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -309,10 +309,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let old_call_site_scope = self.set_call_site_scope(Some(call_site)); let fn_sig = { - let tables = self.tables.borrow(); let fn_hir_id = self.tcx.hir.node_to_hir_id(id); - tables.validate_hir_id(fn_hir_id); - match tables.liberated_fn_sigs.get(&fn_hir_id.local_id) { + match self.tables.borrow().liberated_fn_sigs().get(fn_hir_id) { Some(f) => f.clone(), None => { bug!("No fn-sig entry for id={}", id); @@ -1121,14 +1119,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // report errors later on in the writeback phase. let ty0 = self.resolve_node_type(hir_id); - let ty = { - let tables = self.tables.borrow(); - tables.validate_hir_id(hir_id); - tables.adjustments - .get(&hir_id.local_id) - .and_then(|adj| adj.last()) - .map_or(ty0, |adj| adj.target) - }; + let ty = self.tables + .borrow() + .adjustments() + .get(hir_id) + .and_then(|adj| adj.last()) + .map_or(ty0, |adj| adj.target); let ty = self.resolve_type(ty); debug!("constrain_regions_in_type_of_node(\ ty={}, ty0={}, id={:?}, minimum_lifetime={:?})", @@ -1207,9 +1203,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { match sub_pat.node { // `ref x` pattern PatKind::Binding(..) => { - mc.tables.validate_hir_id(sub_pat.hir_id); - let bm = *mc.tables.pat_binding_modes.get(&sub_pat.hir_id.local_id) - .expect("missing binding mode"); + let bm = *mc.tables.pat_binding_modes().get(sub_pat.hir_id) + .expect("missing binding mode"); if let ty::BindByReference(mutbl) = bm { self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id, mutbl, sub_cmt); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 111f224c3d1..6db5c5b1cb0 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -103,8 +103,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let infer_kind = match self.tables .borrow_mut() - .closure_kinds - .entry(closure_hir_id.local_id) { + .closure_kinds_mut() + .entry(closure_hir_id) { Entry::Occupied(_) => false, Entry::Vacant(entry) => { debug!("check_closure: adding closure {:?} as Fn", closure_node_id); @@ -162,8 +162,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .remove(&closure_def_id.index) { self.tables .borrow_mut() - .closure_kinds - .insert(closure_hir_id.local_id, kind); + .closure_kinds_mut() + .insert(closure_hir_id, kind); } } self.tables.borrow_mut().upvar_capture_map.extend( @@ -482,9 +482,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { let closure_kind = self.adjust_closure_kinds.get(&closure_id).cloned() .or_else(|| { let closure_id = self.fcx.tcx.hir.def_index_to_hir_id(closure_id); - let fcx_tables = self.fcx.tables.borrow(); - fcx_tables.validate_hir_id(closure_id); - fcx_tables.closure_kinds.get(&closure_id.local_id).cloned() + self.fcx.tables.borrow().closure_kinds().get(closure_id).cloned() }); if let Some((existing_kind, _)) = closure_kind { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 515bbe49c39..0e7083b72f5 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -93,8 +93,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'gcx>) { debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty); assert!(!ty.needs_infer()); - self.tables.validate_hir_id(hir_id); - self.tables.node_types.insert(hir_id.local_id, ty); + self.tables.node_types_mut().insert(hir_id, ty); } // Hacky hack: During type-checking, we treat *all* operators @@ -110,9 +109,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { if inner_ty.is_scalar() { let mut tables = self.fcx.tables.borrow_mut(); - tables.validate_hir_id(e.hir_id); - tables.type_dependent_defs.remove(&e.hir_id.local_id); - tables.node_substs.remove(&e.hir_id.local_id); + tables.type_dependent_defs_mut().remove(e.hir_id); + tables.node_substs_mut().remove(e.hir_id); } } hir::ExprBinary(ref op, ref lhs, ref rhs) | @@ -125,19 +123,19 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { if lhs_ty.is_scalar() && rhs_ty.is_scalar() { let mut tables = self.fcx.tables.borrow_mut(); - tables.validate_hir_id(e.hir_id); - tables.type_dependent_defs.remove(&e.hir_id.local_id); - tables.node_substs.remove(&e.hir_id.local_id); + tables.type_dependent_defs_mut().remove(e.hir_id); + tables.node_substs_mut().remove(e.hir_id); match e.node { hir::ExprBinary(..) => { if !op.node.is_by_value() { - tables.adjustments.get_mut(&lhs.hir_id.local_id).map(|a| a.pop()); - tables.adjustments.get_mut(&rhs.hir_id.local_id).map(|a| a.pop()); + let mut adjustments = tables.adjustments_mut(); + adjustments.get_mut(lhs.hir_id).map(|a| a.pop()); + adjustments.get_mut(rhs.hir_id).map(|a| a.pop()); } }, hir::ExprAssignOp(..) => { - tables.adjustments.get_mut(&lhs.hir_id.local_id).map(|a| a.pop()); + tables.adjustments_mut().get_mut(lhs.hir_id).map(|a| a.pop()); }, _ => {}, } @@ -186,14 +184,13 @@ impl<'cx, 'gcx, 'tcx> Visitor<'gcx> for WritebackCx<'cx, 'gcx, 'tcx> { fn visit_pat(&mut self, p: &'gcx hir::Pat) { match p.node { hir::PatKind::Binding(..) => { - let bm = { - let fcx_tables = self.fcx.tables.borrow(); - fcx_tables.validate_hir_id(p.hir_id); - *fcx_tables.pat_binding_modes.get(&p.hir_id.local_id) - .expect("missing binding mode") - }; - self.tables.validate_hir_id(p.hir_id); - self.tables.pat_binding_modes.insert(p.hir_id.local_id, bm); + let bm = *self.fcx + .tables + .borrow() + .pat_binding_modes() + .get(p.hir_id) + .expect("missing binding mode"); + self.tables.pat_binding_modes_mut().insert(p.hir_id, bm); } _ => {} }; @@ -233,23 +230,36 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { let fcx_tables = self.fcx.tables.borrow(); debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); - for (&id, closure_ty) in fcx_tables.closure_tys.iter() { + for (&id, closure_ty) in fcx_tables.closure_tys().iter() { let hir_id = hir::HirId { owner: fcx_tables.local_id_root.index, local_id: id, }; let closure_ty = self.resolve(closure_ty, &hir_id); - self.tables.closure_tys.insert(id, closure_ty); + self.tables.closure_tys_mut().insert(hir_id, closure_ty); } - for (&id, &closure_kind) in fcx_tables.closure_kinds.iter() { - self.tables.closure_kinds.insert(id, closure_kind); + for (&id, &closure_kind) in fcx_tables.closure_kinds().iter() { + let hir_id = hir::HirId { + owner: fcx_tables.local_id_root.index, + local_id: id, + }; + self.tables.closure_kinds_mut().insert(hir_id, closure_kind); } } fn visit_cast_types(&mut self) { - self.tables.cast_kinds.extend( - self.fcx.tables.borrow().cast_kinds.iter().map(|(&key, &value)| (key, value))); + let fcx_tables = self.fcx.tables.borrow(); + let fcx_cast_kinds = fcx_tables.cast_kinds(); + let mut self_cast_kinds = self.tables.cast_kinds_mut(); + + for (&local_id, &cast_kind) in fcx_cast_kinds.iter() { + let hir_id = hir::HirId { + owner: fcx_tables.local_id_root.index, + local_id, + }; + self_cast_kinds.insert(hir_id, cast_kind); + } } fn visit_free_region_map(&mut self) { @@ -293,20 +303,18 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { }); let hir_id = self.tcx().hir.node_to_hir_id(node_id); - self.tables.validate_hir_id(hir_id); - self.tables.node_types.insert(hir_id.local_id, outside_ty); + self.tables.node_types_mut().insert(hir_id, outside_ty); } } fn visit_node_id(&mut self, span: Span, hir_id: hir::HirId) { - { - let mut fcx_tables = self.fcx.tables.borrow_mut(); - fcx_tables.validate_hir_id(hir_id); - // Export associated path extensions and method resultions. - if let Some(def) = fcx_tables.type_dependent_defs.remove(&hir_id.local_id) { - self.tables.validate_hir_id(hir_id); - self.tables.type_dependent_defs.insert(hir_id.local_id, def); - } + // Export associated path extensions and method resultions. + if let Some(def) = self.fcx + .tables + .borrow_mut() + .type_dependent_defs_mut() + .remove(hir_id) { + self.tables.type_dependent_defs_mut().insert(hir_id, def); } // Resolve any borrowings for the node with id `node_id` @@ -319,20 +327,20 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { debug!("Node {:?} has type {:?}", hir_id, n_ty); // Resolve any substitutions - if let Some(&substs) = self.fcx.tables.borrow().node_substs.get(&hir_id.local_id) { + if let Some(substs) = self.fcx.tables.borrow().node_substs_opt(hir_id) { let substs = self.resolve(&substs, &span); debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs); assert!(!substs.needs_infer()); - self.tables.node_substs.insert(hir_id.local_id, substs); + self.tables.node_substs_mut().insert(hir_id, substs); } } fn visit_adjustments(&mut self, span: Span, hir_id: hir::HirId) { - let adjustment = { - let mut fcx_tables = self.fcx.tables.borrow_mut(); - fcx_tables.validate_hir_id(hir_id); - fcx_tables.adjustments.remove(&hir_id.local_id) - }; + let adjustment = self.fcx + .tables + .borrow_mut() + .adjustments_mut() + .remove(hir_id); match adjustment { None => { debug!("No adjustments for node {:?}", hir_id); @@ -341,8 +349,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { Some(adjustment) => { let resolved_adjustment = self.resolve(&adjustment, &span); debug!("Adjustments for node {:?}: {:?}", hir_id, resolved_adjustment); - self.tables.validate_hir_id(hir_id); - self.tables.adjustments.insert(hir_id.local_id, resolved_adjustment); + self.tables.adjustments_mut().insert(hir_id, resolved_adjustment); } } } @@ -351,13 +358,13 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { let fcx_tables = self.fcx.tables.borrow(); debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); - for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs.iter() { + for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() { let hir_id = hir::HirId { owner: fcx_tables.local_id_root.index, local_id, }; let fn_sig = self.resolve(fn_sig, &hir_id); - self.tables.liberated_fn_sigs.insert(local_id, fn_sig.clone()); + self.tables.liberated_fn_sigs_mut().insert(hir_id, fn_sig.clone()); } } @@ -365,13 +372,13 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { let fcx_tables = self.fcx.tables.borrow(); debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); - for (&local_id, ftys) in fcx_tables.fru_field_types.iter() { + for (&local_id, ftys) in fcx_tables.fru_field_types().iter() { let hir_id = hir::HirId { owner: fcx_tables.local_id_root.index, local_id, }; let ftys = self.resolve(ftys, &hir_id); - self.tables.fru_field_types.insert(local_id, ftys); + self.tables.fru_field_types_mut().insert(hir_id, ftys); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 30188a7cbdc..91b41eb33a1 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1240,9 +1240,7 @@ fn fn_sig<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } NodeExpr(&hir::Expr { node: hir::ExprClosure(..), hir_id, .. }) => { - let tables = tcx.typeck_tables_of(def_id); - tables.validate_hir_id(hir_id); - tables.closure_tys[&hir_id.local_id] + tcx.typeck_tables_of(def_id).closure_tys()[hir_id] } x => {