From 1f874ded52acaecd47b39e90e93d7d7a31c90dae Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 8 Jun 2017 23:57:01 +0300 Subject: [PATCH] rustc: do not depend on infcx.tables in MemCategorizationContext. --- src/librustc/infer/mod.rs | 143 ++---------------- src/librustc/middle/expr_use_visitor.rs | 41 +++-- src/librustc/middle/mem_categorization.rs | 94 +++++++----- src/librustc/traits/error_reporting.rs | 14 +- src/librustc_borrowck/borrowck/check_loans.rs | 5 +- .../borrowck/gather_loans/mod.rs | 10 +- src/librustc_const_eval/check_match.rs | 5 +- src/librustc_mir/build/mod.rs | 2 +- src/librustc_mir/hair/cx/mod.rs | 6 +- src/librustc_passes/consts.rs | 5 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/check/regionck.rs | 53 +++---- src/librustc_typeck/check/upvar.rs | 6 +- 13 files changed, 146 insertions(+), 240 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 6e9d028aa64..3e2d26aa518 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -19,11 +19,8 @@ pub use self::region_inference::{GenericKind, VerifyBound}; use hir::def_id::DefId; -use hir; use middle::free_region::{FreeRegionMap, RegionRelations}; use middle::region::RegionMaps; -use middle::mem_categorization as mc; -use middle::mem_categorization::McResult; use middle::lang_items; use mir::tcx::LvalueTy; use ty::subst::{Kind, Subst, Substs}; @@ -36,7 +33,6 @@ use rustc_data_structures::unify::{self, UnificationTable}; use std::cell::{Cell, RefCell, Ref, RefMut}; use std::fmt; -use std::ops::Deref; use syntax::ast; use errors::DiagnosticBuilder; use syntax_pos::{self, Span, DUMMY_SP}; @@ -80,55 +76,23 @@ pub struct InferOk<'tcx, T> { /// `InProgress` (during typeck) or `Interned` (result of typeck). /// Only the `InProgress` version supports `borrow_mut`. #[derive(Copy, Clone)] -pub enum InferTables<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - Interned(&'a ty::TypeckTables<'gcx>), +pub enum InferTables<'a, 'tcx: 'a> { InProgress(&'a RefCell>), Missing } -pub enum InferTablesRef<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - Interned(&'a ty::TypeckTables<'gcx>), - InProgress(Ref<'a, ty::TypeckTables<'tcx>>) -} - -impl<'a, 'gcx, 'tcx> Deref for InferTablesRef<'a, 'gcx, 'tcx> { - type Target = ty::TypeckTables<'tcx>; - fn deref(&self) -> &Self::Target { - match *self { - InferTablesRef::Interned(tables) => tables, - InferTablesRef::InProgress(ref tables) => tables - } - } -} - -impl<'a, 'gcx, 'tcx> InferTables<'a, 'gcx, 'tcx> { - pub fn borrow(self) -> InferTablesRef<'a, 'gcx, 'tcx> { +impl<'a, 'tcx> InferTables<'a, 'tcx> { + pub fn borrow(self) -> Ref<'a, ty::TypeckTables<'tcx>> { match self { - InferTables::Interned(tables) => InferTablesRef::Interned(tables), - InferTables::InProgress(tables) => InferTablesRef::InProgress(tables.borrow()), + InferTables::InProgress(tables) => tables.borrow(), InferTables::Missing => { bug!("InferTables: infcx.tables.borrow() with no tables") } } } - pub fn expect_interned(self) -> &'a ty::TypeckTables<'gcx> { - match self { - InferTables::Interned(tables) => tables, - InferTables::InProgress(_) => { - bug!("InferTables: infcx.tables.expect_interned() during type-checking"); - } - InferTables::Missing => { - bug!("InferTables: infcx.tables.expect_interned() with no tables") - } - } - } - pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> { match self { - InferTables::Interned(_) => { - bug!("InferTables: infcx.tables.borrow_mut() outside of type-checking"); - } InferTables::InProgress(tables) => tables.borrow_mut(), InferTables::Missing => { bug!("InferTables: infcx.tables.borrow_mut() with no tables") @@ -140,7 +104,7 @@ pub fn borrow_mut(self) -> RefMut<'a, ty::TypeckTables<'tcx>> { pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - pub tables: InferTables<'a, 'gcx, 'tcx>, + pub tables: InferTables<'a, 'tcx>, // Cache for projections. This cache is snapshotted along with the // infcx. @@ -397,41 +361,18 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } pub trait InferEnv<'a, 'tcx> { - fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>); + fn fresh_tables(self) -> Option>; } impl<'a, 'tcx> InferEnv<'a, 'tcx> for () { - fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - (None, None) - } -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for &'a ty::TypeckTables<'tcx> { - fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - (Some(self), None) + fn fresh_tables(self) -> Option> { + None } } impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> { - fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - (None, Some(self)) - } -} - -impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId { - fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> (Option<&'a ty::TypeckTables<'tcx>>, - Option>) { - let def_id = tcx.hir.body_owner_def_id(self); - (Some(tcx.typeck_tables_of(def_id)), None) + fn fresh_tables(self) -> Option> { + Some(self) } } @@ -442,29 +383,24 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { global_tcx: TyCtxt<'a, 'gcx, 'gcx>, arena: DroplessArena, fresh_tables: Option>>, - tables: Option<&'a ty::TypeckTables<'gcx>>, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { pub fn infer_ctxt>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { - let (tables, fresh_tables) = env.to_parts(self); InferCtxtBuilder { global_tcx: self, arena: DroplessArena::new(), - fresh_tables: fresh_tables.map(RefCell::new), - tables: tables, + fresh_tables: env.fresh_tables().map(RefCell::new), } } /// Fake InferCtxt with the global tcx. Used by pre-MIR borrowck /// for MemCategorizationContext/ExprUseVisitor. /// If any inference functionality is used, ICEs will occur. - pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId) - -> InferCtxt<'a, 'gcx, 'gcx> { - let (tables, _) = body.to_parts(self); + pub fn borrowck_fake_infer_ctxt(self) -> InferCtxt<'a, 'gcx, 'gcx> { InferCtxt { tcx: self, - tables: InferTables::Interned(tables.unwrap()), + tables: InferTables::Missing, type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(UnificationTable::new()), float_unification_table: RefCell::new(UnificationTable::new()), @@ -488,11 +424,9 @@ pub fn enter(&'tcx mut self, f: F) -> R global_tcx, ref arena, ref fresh_tables, - tables, } = *self; - let tables = tables.map(InferTables::Interned).unwrap_or_else(|| { - fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress) - }); + let tables = fresh_tables.as_ref() + .map_or(InferTables::Missing, InferTables::InProgress); global_tcx.enter_local(arena, |tcx| f(InferCtxt { tcx: tcx, tables: tables, @@ -1190,28 +1124,6 @@ pub fn set_tainted_by_errors(&self) { self.tainted_by_errors_flag.set(true) } - pub fn node_type(&self, id: ast::NodeId) -> Ty<'tcx> { - match self.tables.borrow().node_types.get(&id) { - Some(&t) => t, - // FIXME - None if self.is_tainted_by_errors() => - self.tcx.types.err, - None => { - bug!("no type for node {}: {} in fcx", - id, self.tcx.hir.node_to_string(id)); - } - } - } - - pub fn expr_ty(&self, ex: &hir::Expr) -> Ty<'tcx> { - match self.tables.borrow().node_types.get(&ex.id) { - Some(&t) => t, - None => { - bug!("no type for expr in fcx"); - } - } - } - pub fn resolve_regions_and_report_errors(&self, region_context: DefId, region_map: &RegionMaps, @@ -1310,21 +1222,6 @@ pub fn resolve_type_and_region_vars_if_possible(&self, value: &T) -> T value.fold_with(&mut r) } - /// Resolves all type variables in `t` and then, if any were left - /// unresolved, substitutes an error type. This is used after the - /// main checking when doing a second pass before writeback. The - /// justification is that writeback will produce an error for - /// these unconstrained type variables. - fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult> { - let ty = self.resolve_type_vars_if_possible(t); - if ty.references_error() || ty.is_ty_var() { - debug!("resolve_type_vars_or_error: error from {:?}", ty); - Err(()) - } else { - Ok(ty) - } - } - pub fn fully_resolve>(&self, value: &T) -> FixupResult { /*! * Attempts to resolve all type/region variables in @@ -1484,16 +1381,6 @@ pub fn verify_generic_bound(&self, self.region_vars.verify_generic_bound(origin, kind, a, bound); } - pub fn node_ty(&self, id: ast::NodeId) -> McResult> { - let ty = self.node_type(id); - self.resolve_type_vars_or_error(&ty) - } - - pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { - let ty = self.tables.borrow().expr_ty_adjusted(expr); - self.resolve_type_vars_or_error(&ty) - } - pub fn type_moves_by_default(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>, diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 4075d28a396..b24b2a616b0 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -235,17 +235,14 @@ fn from_method_id(tcx: TyCtxt, method_id: DefId) -> OverloadedCallType { /////////////////////////////////////////////////////////////////////////// // The ExprUseVisitor type // -// This is the code that actually walks the tree. Like -// mem_categorization, it requires a TYPER, which is a type that -// supplies types from the tree. After type checking is complete, you -// can just use the tcx as the typer. +// This is the code that actually walks the tree. pub struct ExprUseVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>, delegate: &'a mut Delegate<'tcx>, param_env: ty::ParamEnv<'tcx>, } -// If the TYPER results in an error, it's because the type check +// If the MC results in an error, it's because the type check // failed (or will fail, when the error is uncovered and reported // during writeback). In this case, we just ignore this part of the // code. @@ -266,13 +263,14 @@ macro_rules! return_if_err { impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { pub fn new(delegate: &'a mut (Delegate<'tcx>+'a), - region_maps: &'a RegionMaps, infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>) + param_env: ty::ParamEnv<'tcx>, + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) -> Self { ExprUseVisitor { - mc: mc::MemCategorizationContext::new(infcx, region_maps), + mc: mc::MemCategorizationContext::new(infcx, region_maps, tables), delegate, param_env, } @@ -282,7 +280,7 @@ pub fn consume_body(&mut self, body: &hir::Body) { debug!("consume_body(body={:?})", body); for arg in &body.arguments { - let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id)); + let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.id)); let fn_body_scope_r = self.tcx().node_scope_region(body.value.id); let arg_cmt = self.mc.cat_rvalue( @@ -427,7 +425,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) { hir::ExprAddrOf(m, ref base) => { // &base // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: - let expr_ty = return_if_err!(self.mc.infcx.node_ty(expr.id)); + let expr_ty = return_if_err!(self.mc.expr_ty(expr)); if let ty::TyRef(r, _) = expr_ty.sty { let bk = ty::BorrowKind::from_mutbl(m); self.borrow_expr(&base, r, bk, AddrOf); @@ -491,7 +489,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) { } hir::ExprAssignOp(_, ref lhs, ref rhs) => { - if self.mc.infcx.tables.borrow().is_method_call(expr) { + if self.mc.tables.is_method_call(expr) { self.consume_expr(lhs); } else { self.mutate_expr(expr, &lhs, MutateMode::WriteAndRead); @@ -514,7 +512,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) { } fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) { - let callee_ty = return_if_err!(self.mc.infcx.expr_ty_adjusted(callee)); + let callee_ty = return_if_err!(self.mc.expr_ty_adjusted(callee)); debug!("walk_callee: callee={:?} callee_ty={:?}", callee, callee_ty); match callee_ty.sty { @@ -523,7 +521,7 @@ fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) { } ty::TyError => { } _ => { - let def_id = self.mc.infcx.tables.borrow().type_dependent_defs[&call.id].def_id(); + let def_id = self.mc.tables.type_dependent_defs[&call.id].def_id(); match OverloadedCallType::from_method_id(self.tcx(), def_id) { FnMutOverloadedCall => { let call_scope_r = self.tcx().node_scope_region(call.id); @@ -664,8 +662,7 @@ fn contains_field_named(field: &ty::FieldDef, // consumed or borrowed as part of the automatic adjustment // process. fn walk_adjustment(&mut self, expr: &hir::Expr) { - let tables = self.mc.infcx.tables.borrow(); - let adjustments = tables.expr_adjustments(expr); + let adjustments = self.mc.tables.expr_adjustments(expr); let mut cmt = return_if_err!(self.mc.cat_expr_unadjusted(expr)); for adjustment in adjustments { debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); @@ -782,7 +779,7 @@ fn determine_pat_move_mode(&mut self, mode: &mut TrackMatchMode) { debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr, pat); - return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| { + return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| { match pat.node { PatKind::Binding(hir::BindByRef(..), ..) => mode.lub(BorrowingMatch), @@ -806,12 +803,12 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat let tcx = self.tcx(); let infcx = self.mc.infcx; let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self; - return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| { + return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(bmode, def_id, ..) = pat.node { debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode); // pat_ty: the type of the binding being produced. - let pat_ty = return_if_err!(infcx.node_ty(pat.id)); + let pat_ty = return_if_err!(mc.node_ty(pat.id)); // Each match binding is effectively an assignment to the // binding being produced. @@ -841,14 +838,14 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat // the interior nodes (enum variants and structs), as opposed // to the above loop's visit of than the bindings that form // the leaves of the pattern tree structure. - return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| { + return_if_err!(mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| { let qpath = match pat.node { PatKind::Path(ref qpath) | PatKind::TupleStruct(ref qpath, ..) | PatKind::Struct(ref qpath, ..) => qpath, _ => return }; - let def = infcx.tables.borrow().qpath_def(qpath, pat.id); + let def = mc.tables.qpath_def(qpath, pat.id); match def { Def::Variant(variant_did) | Def::VariantCtor(variant_did, ..) => { @@ -882,7 +879,7 @@ fn walk_captures(&mut self, closure_expr: &hir::Expr, fn_decl_span: Span) { let id_var = self.tcx().hir.as_local_node_id(def_id).unwrap(); let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id }; - let upvar_capture = self.mc.infcx.tables.borrow().upvar_capture(upvar_id); + let upvar_capture = self.mc.tables.upvar_capture(upvar_id); let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, fn_decl_span, freevar.def)); @@ -915,7 +912,7 @@ fn cat_captured_var(&mut self, // Create the cmt for the variable being borrowed, from the // caller's perspective let var_id = self.tcx().hir.as_local_node_id(upvar_def.def_id()).unwrap(); - let var_ty = self.mc.infcx.node_ty(var_id)?; + let var_ty = self.mc.node_ty(var_id)?; self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def) } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index ddbc7f91097..66de8bc5803 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -76,6 +76,7 @@ use hir::def::{Def, CtorKind}; use ty::adjustment; use ty::{self, Ty, TyCtxt}; +use ty::fold::TypeFoldable; use hir::{MutImmutable, MutMutable, PatKind}; use hir::pat_util::EnumerateAndAdjustIterator; @@ -283,6 +284,7 @@ fn span(&self) -> Span { self.span } pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, pub region_maps: &'a RegionMaps, + pub tables: &'a ty::TypeckTables<'tcx>, } pub type McResult = Result; @@ -386,35 +388,63 @@ pub fn to_user_str(&self) -> &'static str { impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { /// Context should be the `DefId` we use to fetch region-maps. pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - region_maps: &'a RegionMaps) + region_maps: &'a RegionMaps, + tables: &'a ty::TypeckTables<'tcx>) -> MemCategorizationContext<'a, 'gcx, 'tcx> { - MemCategorizationContext { infcx, region_maps } + MemCategorizationContext { infcx, region_maps, tables } } fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { self.infcx.tcx } - fn expr_ty(&self, expr: &hir::Expr) -> McResult> { - match self.infcx.node_ty(expr.id) { - Ok(t) => Ok(t), - Err(()) => { - debug!("expr_ty({:?}) yielded Err", expr); - Err(()) + fn resolve_type_vars_if_possible(&self, value: &T) -> T + where T: TypeFoldable<'tcx> + { + self.infcx.resolve_type_vars_if_possible(value) + } + + fn is_tainted_by_errors(&self) -> bool { + self.infcx.is_tainted_by_errors() + } + + fn resolve_type_vars_or_error(&self, + id: ast::NodeId, + ty: Option>) + -> McResult> { + match ty { + Some(ty) => { + let ty = self.resolve_type_vars_if_possible(&ty); + if ty.references_error() || ty.is_ty_var() { + debug!("resolve_type_vars_or_error: error from {:?}", ty); + Err(()) + } else { + Ok(ty) + } + } + // FIXME + None if self.is_tainted_by_errors() => Err(()), + None => { + bug!("no type for node {}: {} in mem_categorization", + id, self.tcx().hir.node_to_string(id)); } } } - fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { - self.infcx.expr_ty_adjusted(expr) + pub fn node_ty(&self, id: ast::NodeId) -> McResult> { + self.resolve_type_vars_or_error(id, self.tables.node_id_to_type_opt(id)) + } + + pub fn expr_ty(&self, expr: &hir::Expr) -> McResult> { + self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_opt(expr)) } - fn node_ty(&self, id: ast::NodeId) -> McResult> { - self.infcx.node_ty(id) + pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { + self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_adjusted_opt(expr)) } fn pat_ty(&self, pat: &hir::Pat) -> McResult> { - let base_ty = self.infcx.node_ty(pat.id)?; + let base_ty = self.node_ty(pat.id)?; // FIXME (Issue #18207): This code detects whether we are // looking at a `ref x`, and if so, figures out what the type // *being borrowed* is. But ideally we would put in a more @@ -454,7 +484,7 @@ fn helper<'a, 'gcx, 'tcx>(mc: &MemCategorizationContext<'a, 'gcx, 'tcx>, } } - helper(self, expr, self.infcx.tables.borrow().expr_adjustments(expr)) + helper(self, expr, self.tables.expr_adjustments(expr)) } pub fn cat_expr_adjusted(&self, expr: &hir::Expr, @@ -471,7 +501,7 @@ fn cat_expr_adjusted_with(&self, expr: &hir::Expr, where F: FnOnce() -> McResult> { debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr); - let target = self.infcx.resolve_type_vars_if_possible(&adjustment.target); + let target = self.resolve_type_vars_if_possible(&adjustment.target); match adjustment.kind { adjustment::Adjust::Deref(overloaded) => { // Equivalent to *expr or something similar. @@ -506,7 +536,7 @@ pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { let expr_ty = self.expr_ty(expr)?; match expr.node { hir::ExprUnary(hir::UnDeref, ref e_base) => { - if self.infcx.tables.borrow().is_method_call(expr) { + if self.tables.is_method_call(expr) { self.cat_overloaded_lvalue(expr, e_base, false) } else { let base_cmt = self.cat_expr(&e_base)?; @@ -529,7 +559,7 @@ pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { } hir::ExprIndex(ref base, _) => { - if self.infcx.tables.borrow().is_method_call(expr) { + if self.tables.is_method_call(expr) { // If this is an index implemented by a method call, then it // will include an implicit deref of the result. // The call to index() returns a `&T` value, which @@ -543,7 +573,7 @@ pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { } hir::ExprPath(ref qpath) => { - let def = self.infcx.tables.borrow().qpath_def(qpath, expr.id); + let def = self.tables.qpath_def(qpath, expr.id); self.cat_def(expr.id, expr.span, expr_ty, def) } @@ -595,15 +625,7 @@ pub fn cat_def(&self, Def::Upvar(def_id, _, fn_node_id) => { let var_id = self.tcx().hir.as_local_node_id(def_id).unwrap(); - let closure_id = self.tcx().hir.local_def_id(fn_node_id); - match self.infcx.closure_kind(closure_id) { - Some(kind) => { - self.cat_upvar(id, span, var_id, fn_node_id, kind) - } - None => { - span_bug!(span, "No closure kind for {:?}", closure_id); - } - } + self.cat_upvar(id, span, var_id, fn_node_id) } Def::Local(def_id) => { @@ -628,8 +650,7 @@ fn cat_upvar(&self, id: ast::NodeId, span: Span, var_id: ast::NodeId, - fn_node_id: ast::NodeId, - kind: ty::ClosureKind) + fn_node_id: ast::NodeId) -> McResult> { // An upvar can have up to 3 components. We translate first to a @@ -655,6 +676,11 @@ fn cat_upvar(&self, // FnMut | copied -> &'env mut | upvar -> &'env mut -> &'up bk // FnOnce | copied | upvar -> &'up bk + let kind = match self.tables.closure_kinds.get(&fn_node_id) { + Some(&(kind, _)) => kind, + None => span_bug!(span, "missing closure kind") + }; + let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: fn_node_id }; let var_ty = self.node_ty(var_id)?; @@ -694,7 +720,7 @@ fn cat_upvar(&self, // for that. let upvar_id = ty::UpvarId { var_id: var_id, closure_expr_id: fn_node_id }; - let upvar_capture = self.infcx.tables.borrow().upvar_capture(upvar_id); + let upvar_capture = self.tables.upvar_capture(upvar_id); let cmt_result = match upvar_capture { ty::UpvarCapture::ByValue => { cmt_result @@ -1000,14 +1026,14 @@ pub fn cat_downcast(&self, } pub fn cat_pattern(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()> - where F: FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat), + where F: FnMut(cmt<'tcx>, &hir::Pat), { self.cat_pattern_(cmt, pat, &mut op) } // FIXME(#19596) This is a workaround, but there should be a better way to do this fn cat_pattern_(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResult<()> - where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat) + where F : FnMut(cmt<'tcx>, &hir::Pat) { // Here, `cmt` is the categorization for the value being // matched and pat is the pattern it is being matched against. @@ -1056,7 +1082,7 @@ fn cat_pattern_(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResul debug!("cat_pattern: {:?} cmt={:?}", pat, cmt); - op(self, cmt.clone(), pat); + op(cmt.clone(), pat); // Note: This goes up here (rather than within the PatKind::TupleStruct arm // alone) because PatKind::Struct can also refer to variants. @@ -1087,7 +1113,7 @@ fn cat_pattern_(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResul match pat.node { PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => { - let def = self.infcx.tables.borrow().qpath_def(qpath, pat.id); + let def = self.tables.qpath_def(qpath, pat.id); let expected_len = match def { Def::VariantCtor(def_id, CtorKind::Fn) => { let enum_def = self.tcx().parent_def_id(def_id).unwrap(); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c8e99c0354a..74bfd977148 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -29,7 +29,7 @@ use hir::intravisit::{Visitor, NestedVisitorMap}; use hir::map::NodeExpr; use hir::def_id::DefId; -use infer::{self, InferCtxt, InferTables, InferTablesRef}; +use infer::{self, InferCtxt, InferTables}; use infer::type_variable::TypeVariableOrigin; use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; @@ -652,18 +652,10 @@ pub fn report_selection_error(&self, obligation.cause.span, format!("the requirement to implement `{}` derives from here", kind)); - let infer_tables = match self.tables { - InferTables::Interned(tables) => - Some(InferTablesRef::Interned(tables)), - InferTables::InProgress(tables) => - Some(InferTablesRef::InProgress(tables.borrow())), - InferTables::Missing => None, - }; - // Additional context information explaining why the closure only implements // a particular trait. - if let Some(tables) = infer_tables { - match tables.closure_kinds.get(&node_id) { + if let InferTables::InProgress(tables) = self.tables { + match tables.borrow().closure_kinds.get(&node_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_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 122a37ee32a..a47ec35d265 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -192,7 +192,6 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, debug!("check_loans(body id={})", body.value.id); let def_id = bccx.tcx.hir.body_owner_def_id(body.id()); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body.id()); let param_env = bccx.tcx.param_env(def_id); let mut clcx = CheckLoanCtxt { bccx: bccx, @@ -201,7 +200,9 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, all_loans: all_loans, param_env, }; - euv::ExprUseVisitor::new(&mut clcx, &bccx.region_maps, &infcx, param_env).consume_body(body); + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(); + euv::ExprUseVisitor::new(&mut clcx, &infcx, param_env, &bccx.region_maps, bccx.tables) + .consume_body(body); } #[derive(PartialEq)] diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 85a09969ac8..ae68fb651f6 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -18,7 +18,6 @@ use borrowck::*; use borrowck::move_data::MoveData; -use rustc::infer::InferCtxt; use rustc::middle::expr_use_visitor as euv; use rustc::middle::mem_categorization as mc; use rustc::middle::mem_categorization::Categorization; @@ -40,11 +39,9 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, body: hir::BodyId) -> (Vec>, move_data::MoveData<'tcx>) { let def_id = bccx.tcx.hir.body_owner_def_id(body); - let infcx = bccx.tcx.borrowck_fake_infer_ctxt(body); let param_env = bccx.tcx.param_env(def_id); let mut glcx = GatherLoanCtxt { bccx: bccx, - infcx: &infcx, all_loans: Vec::new(), item_ub: region::CodeExtent::Misc(body.node_id), move_data: MoveData::new(), @@ -52,7 +49,9 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, }; let body = glcx.bccx.tcx.hir.body(body); - euv::ExprUseVisitor::new(&mut glcx, &bccx.region_maps, &infcx, param_env).consume_body(body); + let infcx = bccx.tcx.borrowck_fake_infer_ctxt(); + euv::ExprUseVisitor::new(&mut glcx, &infcx, param_env, &bccx.region_maps, bccx.tables) + .consume_body(body); glcx.report_potential_errors(); let GatherLoanCtxt { all_loans, move_data, .. } = glcx; @@ -61,7 +60,6 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, struct GatherLoanCtxt<'a, 'tcx: 'a> { bccx: &'a BorrowckCtxt<'a, 'tcx>, - infcx: &'a InferCtxt<'a, 'tcx, 'tcx>, move_data: move_data::MoveData<'tcx>, move_error_collector: move_error::MoveErrorCollector<'tcx>, all_loans: Vec>, @@ -158,7 +156,7 @@ fn mutate(&mut self, } fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) { - let ty = self.infcx.tables.borrow().node_id_to_type(id); + let ty = self.bccx.tables.node_id_to_type(id); gather_moves::gather_decl(self.bccx, &self.move_data, id, ty); } } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 7c3076fda4f..17cb60792c6 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -493,11 +493,12 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// /// FIXME: this should be done by borrowck. fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { - cx.tcx.infer_ctxt(cx.tables).enter(|infcx| { + cx.tcx.infer_ctxt(()).enter(|infcx| { let mut checker = MutationChecker { cx: cx, }; - ExprUseVisitor::new(&mut checker, cx.region_maps, &infcx, cx.param_env).walk_expr(guard); + ExprUseVisitor::new(&mut checker, &infcx, cx.param_env, cx.region_maps, cx.tables) + .walk_expr(guard); }); } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 7490ee60e1f..8d549154e11 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -83,7 +83,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t }; let src = MirSource::from_node(tcx, id); - tcx.infer_ctxt(body_id).enter(|infcx| { + tcx.infer_ctxt(()).enter(|infcx| { let cx = Cx::new(&infcx, src); let mut mir = if cx.tables().tainted_by_errors { build::construct_error(cx, body_id) diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 5b7b52a72b0..2bb6b39966a 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -37,6 +37,7 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, pub param_env: ty::ParamEnv<'tcx>, pub region_maps: Rc, + pub tables: &'a ty::TypeckTables<'gcx>, /// This is `Constness::Const` if we are compiling a `static`, /// `const`, or the body of a `const fn`. @@ -67,6 +68,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, src: MirSource) -> Cx<'a, 'gcx, let param_env = tcx.param_env(src_def_id); let region_maps = tcx.region_maps(src_def_id); + let tables = tcx.typeck_tables_of(src_def_id); let attrs = tcx.hir.attrs(src_id); @@ -82,7 +84,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, src: MirSource) -> Cx<'a, 'gcx, // Constants and const fn's always need overflow checks. check_overflow |= constness == hir::Constness::Const; - Cx { tcx, infcx, param_env, region_maps, constness, src, check_overflow } + Cx { tcx, infcx, param_env, region_maps, tables, constness, src, check_overflow } } } @@ -184,7 +186,7 @@ pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { } pub fn tables(&self) -> &'a ty::TypeckTables<'gcx> { - self.infcx.tables.expect_interned() + self.tables } pub fn check_overflow(&self) -> bool { diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 65a9334bbae..f7889385688 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -138,11 +138,12 @@ fn visit_nested_body(&mut self, body_id: hir::BodyId) { self.check_const_eval(&body.value); } - let outer_penv = self.tcx.infer_ctxt(body_id).enter(|infcx| { + let outer_penv = self.tcx.infer_ctxt(()).enter(|infcx| { let param_env = self.tcx.param_env(item_def_id); let outer_penv = mem::replace(&mut self.param_env, param_env); let region_maps = &self.tcx.region_maps(item_def_id); - euv::ExprUseVisitor::new(self, region_maps, &infcx, param_env).consume_body(body); + euv::ExprUseVisitor::new(self, &infcx, param_env, region_maps, self.tables) + .consume_body(body); outer_penv }); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 04469dcaf2b..f2fdc59762b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4186,7 +4186,7 @@ fn consider_hint_about_removing_semicolon(&self, hir::StmtSemi(ref e, _) => e, _ => return, }; - let last_expr_ty = self.expr_ty(last_expr); + let last_expr_ty = self.node_ty(last_expr.id); if self.can_sub(self.param_env, last_expr_ty, expected_ty).is_err() { return; } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 9c3e5cd1f40..616de1fc412 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -824,15 +824,21 @@ fn constrain_call<'b, I: Iterator>(&mut self, } } + /// Create a temporary `MemCategorizationContext` and pass it to the closure. + fn with_mc(&self, f: F) -> R + where F: for<'b> FnOnce(mc::MemCategorizationContext<'b, 'gcx, 'tcx>) -> R + { + f(mc::MemCategorizationContext::new(&self.infcx, + &self.region_maps, + &self.tables.borrow())) + } + /// Invoked on any adjustments that occur. Checks that if this is a region pointer being /// dereferenced, the lifetime of the pointer includes the deref expr. fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult> { debug!("constrain_adjustments(expr={:?})", expr); - let mut cmt = { - let mc = mc::MemCategorizationContext::new(self, &self.region_maps); - mc.cat_expr_unadjusted(expr)? - }; + let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; let tables = self.tables.borrow(); let adjustments = tables.expr_adjustments(&expr); @@ -886,10 +892,7 @@ fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult { return; } Some(ref expr) => &**expr, }; - let mc = &mc::MemCategorizationContext::new(self, &self.region_maps); - let discr_cmt = ignore_err!(mc.cat_expr(init_expr)); - self.link_pattern(mc, discr_cmt, &local.pat); + let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))); + self.link_pattern(discr_cmt, &local.pat); } /// Computes the guarantors for any ref bindings in a match and @@ -1010,12 +1009,11 @@ fn link_local(&self, local: &hir::Local) { /// linked to the lifetime of its guarantor (if any). fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) { debug!("regionck::for_match()"); - let mc = &mc::MemCategorizationContext::new(self, &self.region_maps); - let discr_cmt = ignore_err!(mc.cat_expr(discr)); + let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))); debug!("discr_cmt={:?}", discr_cmt); for arm in arms { for root_pat in &arm.pats { - self.link_pattern(mc, discr_cmt.clone(), &root_pat); + self.link_pattern(discr_cmt.clone(), &root_pat); } } } @@ -1025,30 +1023,28 @@ fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) { /// linked to the lifetime of its guarantor (if any). fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) { debug!("regionck::link_fn_args(body_scope={:?})", body_scope); - let mc = &mc::MemCategorizationContext::new(self, &self.region_maps); for arg in args { let arg_ty = self.node_ty(arg.id); let re_scope = self.tcx.mk_region(ty::ReScope(body_scope)); - let arg_cmt = mc.cat_rvalue( - arg.id, arg.pat.span, re_scope, arg_ty); + let arg_cmt = self.with_mc(|mc| { + mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty) + }); debug!("arg_ty={:?} arg_cmt={:?} arg={:?}", arg_ty, arg_cmt, arg); - self.link_pattern(mc, arg_cmt, &arg.pat); + self.link_pattern(arg_cmt, &arg.pat); } } /// Link lifetimes of any ref bindings in `root_pat` to the pointers found /// in the discriminant, if needed. - fn link_pattern<'t>(&self, - mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>, - discr_cmt: mc::cmt<'tcx>, - root_pat: &hir::Pat) { + fn link_pattern(&self, discr_cmt: mc::cmt<'tcx>, root_pat: &hir::Pat) { debug!("link_pattern(discr_cmt={:?}, root_pat={:?})", discr_cmt, root_pat); - let _ = mc.cat_pattern(discr_cmt, root_pat, |_, sub_cmt, sub_pat| { + let _ = self.with_mc(|mc| { + mc.cat_pattern(discr_cmt, root_pat, |sub_cmt, sub_pat| { match sub_pat.node { // `ref x` pattern PatKind::Binding(hir::BindByRef(mutbl), ..) => { @@ -1057,7 +1053,8 @@ fn link_pattern<'t>(&self, } _ => {} } - }); + }) + }); } /// Link lifetime of borrowed pointer resulting from autoref to lifetimes in the value being diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 1f0911bb234..400ca59e143 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -142,7 +142,11 @@ fn analyze_closure(&self, adjust_closure_kinds: NodeMap(), adjust_upvar_captures: ty::UpvarCaptureMap::default(), }; - euv::ExprUseVisitor::new(&mut delegate, region_maps, self, self.param_env) + euv::ExprUseVisitor::new(&mut delegate, + &self.infcx, + self.param_env, + region_maps, + &self.tables.borrow()) .consume_body(body); // Write the adjusted values back into the main tables. -- 2.44.0