+
+ /// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
+ pub fn qpath_def(&self, qpath: &hir::QPath, id: hir::HirId) -> Def {
+ match *qpath {
+ hir::QPath::Resolved(_, ref path) => path.def,
+ hir::QPath::TypeRelative(..) => {
+ validate_hir_id_for_typeck_tables(self.local_id_root, id, false);
+ self.type_dependent_defs.get(&id.local_id).cloned().unwrap_or(Def::Err)
+ }
+ }
+ }
+
+ pub fn type_dependent_defs(&self) -> LocalTableInContext<Def> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.type_dependent_defs
+ }
+ }
+
+ pub fn type_dependent_defs_mut(&mut self) -> LocalTableInContextMut<Def> {
+ LocalTableInContextMut {
+ local_id_root: self.local_id_root,
+ data: &mut self.type_dependent_defs
+ }
+ }
+
+ pub fn field_indices(&self) -> LocalTableInContext<usize> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.field_indices
+ }
+ }
+
+ pub fn field_indices_mut(&mut self) -> LocalTableInContextMut<usize> {
+ LocalTableInContextMut {
+ local_id_root: self.local_id_root,
+ data: &mut self.field_indices
+ }
+ }
+
+ pub fn user_provided_tys(&self) -> LocalTableInContext<CanonicalTy<'tcx>> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.user_provided_tys
+ }
+ }
+
+ pub fn user_provided_tys_mut(&mut self) -> LocalTableInContextMut<CanonicalTy<'tcx>> {
+ LocalTableInContextMut {
+ local_id_root: self.local_id_root,
+ data: &mut self.user_provided_tys
+ }
+ }
+
+ pub fn node_types(&self) -> LocalTableInContext<Ty<'tcx>> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.node_types
+ }
+ }
+
+ pub fn node_types_mut(&mut self) -> LocalTableInContextMut<Ty<'tcx>> {
+ 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,
+ None => {
+ bug!("node_id_to_type: no type for node `{}`",
+ tls::with(|tcx| {
+ let id = tcx.hir.definitions().find_node_for_hir_id(id);
+ tcx.hir.node_to_string(id)
+ }))
+ }
+ }
+ }
+
+ pub fn node_id_to_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
+ validate_hir_id_for_typeck_tables(self.local_id_root, id, false);
+ 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> {
+ validate_hir_id_for_typeck_tables(self.local_id_root, id, false);
+ 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, false);
+ 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> {
+ self.node_id_to_type(pat.hir_id)
+ }
+
+ pub fn pat_ty_opt(&self, pat: &hir::Pat) -> Option<Ty<'tcx>> {
+ self.node_id_to_type_opt(pat.hir_id)
+ }
+
+ // Returns the type of an expression as a monotype.
+ //
+ // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
+ // some cases, we insert `Adjustment` annotations such as auto-deref or
+ // auto-ref. The type returned by this function does not consider such
+ // adjustments. See `expr_ty_adjusted()` instead.
+ //
+ // NB (2): This type doesn't provide type parameter substitutions; e.g. if you
+ // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize"
+ // instead of "fn(ty) -> T with T = isize".
+ pub fn expr_ty(&self, expr: &hir::Expr) -> Ty<'tcx> {
+ self.node_id_to_type(expr.hir_id)
+ }
+
+ pub fn expr_ty_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> {
+ self.node_id_to_type_opt(expr.hir_id)
+ }
+
+ pub fn adjustments(&self) -> LocalTableInContext<Vec<ty::adjustment::Adjustment<'tcx>>> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.adjustments
+ }
+ }
+
+ pub fn adjustments_mut(&mut self)
+ -> LocalTableInContextMut<Vec<ty::adjustment::Adjustment<'tcx>>> {
+ LocalTableInContextMut {
+ local_id_root: self.local_id_root,
+ data: &mut self.adjustments
+ }
+ }
+
+ pub fn expr_adjustments(&self, expr: &hir::Expr)
+ -> &[ty::adjustment::Adjustment<'tcx>] {
+ validate_hir_id_for_typeck_tables(self.local_id_root, expr.hir_id, false);
+ self.adjustments.get(&expr.hir_id.local_id).map_or(&[], |a| &a[..])
+ }
+
+ /// Returns the type of `expr`, considering any `Adjustment`
+ /// entry recorded for that expression.
+ pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> Ty<'tcx> {
+ self.expr_adjustments(expr)
+ .last()
+ .map_or_else(|| self.expr_ty(expr), |adj| adj.target)
+ }
+
+ pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> {
+ self.expr_adjustments(expr)
+ .last()
+ .map(|adj| adj.target)
+ .or_else(|| self.expr_ty_opt(expr))
+ }
+
+ pub fn is_method_call(&self, expr: &hir::Expr) -> bool {
+ // Only paths and method calls/overloaded operators have
+ // entries in type_dependent_defs, ignore the former here.
+ if let hir::ExprPath(_) = expr.node {
+ return false;
+ }
+
+ match self.type_dependent_defs().get(expr.hir_id) {
+ Some(&Def::Method(_)) => true,
+ _ => false
+ }
+ }
+
+ pub fn pat_binding_modes(&self) -> LocalTableInContext<BindingMode> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.pat_binding_modes
+ }
+ }
+
+ pub fn pat_binding_modes_mut(&mut self)
+ -> LocalTableInContextMut<BindingMode> {
+ LocalTableInContextMut {
+ local_id_root: self.local_id_root,
+ data: &mut self.pat_binding_modes
+ }
+ }
+
+ pub fn pat_adjustments(&self) -> LocalTableInContext<Vec<Ty<'tcx>>> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.pat_adjustments,
+ }
+ }
+
+ pub fn pat_adjustments_mut(&mut self)
+ -> LocalTableInContextMut<Vec<Ty<'tcx>>> {
+ LocalTableInContextMut {
+ local_id_root: self.local_id_root,
+ data: &mut self.pat_adjustments,
+ }
+ }
+
+ pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> ty::UpvarCapture<'tcx> {
+ self.upvar_capture_map[&upvar_id]
+ }
+
+ pub fn closure_kind_origins(&self) -> LocalTableInContext<(Span, ast::Name)> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.closure_kind_origins
+ }
+ }
+
+ pub fn closure_kind_origins_mut(&mut self) -> LocalTableInContextMut<(Span, ast::Name)> {
+ LocalTableInContextMut {
+ local_id_root: self.local_id_root,
+ data: &mut self.closure_kind_origins
+ }
+ }
+
+ pub fn liberated_fn_sigs(&self) -> LocalTableInContext<ty::FnSig<'tcx>> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.liberated_fn_sigs
+ }
+ }
+
+ pub fn liberated_fn_sigs_mut(&mut self) -> LocalTableInContextMut<ty::FnSig<'tcx>> {
+ LocalTableInContextMut {
+ local_id_root: self.local_id_root,
+ data: &mut self.liberated_fn_sigs
+ }
+ }
+
+ pub fn fru_field_types(&self) -> LocalTableInContext<Vec<Ty<'tcx>>> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.fru_field_types
+ }
+ }
+
+ pub fn fru_field_types_mut(&mut self) -> LocalTableInContextMut<Vec<Ty<'tcx>>> {
+ LocalTableInContextMut {
+ local_id_root: self.local_id_root,
+ data: &mut self.fru_field_types
+ }
+ }
+
+ pub fn cast_kinds(&self) -> LocalTableInContext<ty::cast::CastKind> {
+ LocalTableInContext {
+ local_id_root: self.local_id_root,
+ data: &self.cast_kinds
+ }
+ }
+
+ pub fn cast_kinds_mut(&mut self) -> LocalTableInContextMut<ty::cast::CastKind> {
+ LocalTableInContextMut {
+ local_id_root: self.local_id_root,
+ data: &mut self.cast_kinds
+ }
+ }
+}
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>) {
+ let ty::TypeckTables {
+ local_id_root,
+ ref type_dependent_defs,
+ ref field_indices,
+ ref user_provided_tys,
+ ref node_types,
+ ref node_substs,
+ ref adjustments,
+ ref pat_binding_modes,
+ ref pat_adjustments,
+ ref upvar_capture_map,
+ ref closure_kind_origins,
+ 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| {
+ type_dependent_defs.hash_stable(hcx, hasher);
+ field_indices.hash_stable(hcx, hasher);
+ user_provided_tys.hash_stable(hcx, hasher);
+ node_types.hash_stable(hcx, hasher);
+ node_substs.hash_stable(hcx, hasher);
+ adjustments.hash_stable(hcx, hasher);
+ pat_binding_modes.hash_stable(hcx, hasher);
+ pat_adjustments.hash_stable(hcx, hasher);
+ hash_stable_hashmap(hcx, hasher, upvar_capture_map, |up_var_id, hcx| {
+ let ty::UpvarId {
+ var_id,
+ closure_expr_id
+ } = *up_var_id;
+
+ let local_id_root =
+ local_id_root.expect("trying to hash invalid TypeckTables");
+
+ let var_owner_def_id = DefId {
+ krate: local_id_root.krate,
+ index: var_id.owner,
+ };
+ let closure_def_id = DefId {
+ krate: local_id_root.krate,
+ index: closure_expr_id.to_def_id().index,
+ };
+ (hcx.def_path_hash(var_owner_def_id),
+ var_id.local_id,
+ hcx.def_path_hash(closure_def_id))
+ });
+
+ closure_kind_origins.hash_stable(hcx, hasher);
+ liberated_fn_sigs.hash_stable(hcx, hasher);
+ fru_field_types.hash_stable(hcx, hasher);
+ cast_kinds.hash_stable(hcx, hasher);
+ used_trait_imports.hash_stable(hcx, hasher);
+ tainted_by_errors.hash_stable(hcx, hasher);
+ free_region_map.hash_stable(hcx, hasher);
+ })
+ }