about summary refs log tree commit diff
path: root/src/librustc/middle
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-06-08 23:57:01 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-06-10 14:34:45 +0300
commit1f874ded52acaecd47b39e90e93d7d7a31c90dae (patch)
tree13ccd5df830dcee9516b0a0c1e5f00fb88b7284b /src/librustc/middle
parent5175bc18b5ece1f66a7bfca09202a97728f1d920 (diff)
downloadrust-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.rs41
-rw-r--r--src/librustc/middle/mem_categorization.rs94
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();