diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2017-06-08 23:57:01 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2017-06-10 14:34:45 +0300 |
| commit | 1f874ded52acaecd47b39e90e93d7d7a31c90dae (patch) | |
| tree | 13ccd5df830dcee9516b0a0c1e5f00fb88b7284b /src/librustc/middle | |
| parent | 5175bc18b5ece1f66a7bfca09202a97728f1d920 (diff) | |
| download | rust-1f874ded52acaecd47b39e90e93d7d7a31c90dae.tar.gz rust-1f874ded52acaecd47b39e90e93d7d7a31c90dae.zip | |
rustc: do not depend on infcx.tables in MemCategorizationContext.
Diffstat (limited to 'src/librustc/middle')
| -rw-r--r-- | src/librustc/middle/expr_use_visitor.rs | 41 | ||||
| -rw-r--r-- | src/librustc/middle/mem_categorization.rs | 94 |
2 files changed, 79 insertions, 56 deletions
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 @@ impl 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // 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 infer::InferCtxt; 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 @@ impl ast_node for hir::Pat { 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<T> = Result<T, ()>; @@ -386,35 +388,63 @@ impl MutabilityCategory { 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<Ty<'tcx>> { - 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<T>(&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<Ty<'tcx>>) + -> McResult<Ty<'tcx>> { + 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<Ty<'tcx>> { - self.infcx.expr_ty_adjusted(expr) + pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> { + self.resolve_type_vars_or_error(id, self.tables.node_id_to_type_opt(id)) + } + + pub fn expr_ty(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> { + self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_opt(expr)) } - fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> { - self.infcx.node_ty(id) + pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> { + self.resolve_type_vars_or_error(expr.id, self.tables.expr_ty_adjusted_opt(expr)) } fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> { - 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 @@ impl<'a, 'gcx, 'tcx> 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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { where F: FnOnce() -> McResult<cmt<'tcx>> { 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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } 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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } 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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { id: ast::NodeId, span: Span, var_id: ast::NodeId, - fn_node_id: ast::NodeId, - kind: ty::ClosureKind) + fn_node_id: ast::NodeId) -> McResult<cmt<'tcx>> { // An upvar can have up to 3 components. We translate first to a @@ -655,6 +676,11 @@ 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_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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // 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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } pub fn cat_pattern<F>(&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_<F>(&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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { 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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { 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(); |
