about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-12-27 06:58:35 +0000
committerbors <bors@rust-lang.org>2014-12-27 06:58:35 +0000
commit16e4fef9bf195351673ac664cff5ba97c766d0ad (patch)
treef2ff59404589fa3f7a4747e0551344a131fbc60d
parent18842f89f084c52588fe7cffe07f87bf6e90796a (diff)
parent4856456dd7db4ae43bb4fd14c46b5d59e36cc37c (diff)
downloadrust-16e4fef9bf195351673ac664cff5ba97c766d0ad.tar.gz
rust-16e4fef9bf195351673ac664cff5ba97c766d0ad.zip
auto merge of #20158 : nikomatsakis/rust/fn-inference-refactor, r=eddyb
Various refactorings simplifying the mem-categorization and regionck interface. This is working towards an improvement for closure-and-upvar-mode inference.

r? @eddyb 
-rw-r--r--src/librustc/middle/expr_use_visitor.rs131
-rw-r--r--src/librustc/middle/mem_categorization.rs156
-rw-r--r--src/librustc/middle/traits/select.rs3
-rw-r--r--src/librustc/middle/ty.rs22
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs7
-rw-r--r--src/librustc_trans/trans/common.rs22
-rw-r--r--src/librustc_typeck/check/mod.rs25
-rw-r--r--src/librustc_typeck/check/regionck.rs107
8 files changed, 202 insertions, 271 deletions
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index bf939e98338..c7dd4dd2646 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -302,22 +302,6 @@ pub struct ExprUseVisitor<'d,'t,'tcx,TYPER:'t> {
     param_env: ParameterEnvironment<'tcx>,
 }
 
-// If the TYPER 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.
-//
-// Note that this macro appears similar to try!(), but, unlike try!(),
-// it does not propagate the error.
-macro_rules! return_if_err {
-    ($inp: expr) => (
-        match $inp {
-            Ok(v) => v,
-            Err(()) => return
-        }
-    )
-}
-
 /// Whether the elements of an overloaded operation are passed by value or by reference
 enum PassArgs {
     ByValue,
@@ -348,7 +332,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                          decl: &ast::FnDecl,
                          body: &ast::Block) {
         for arg in decl.inputs.iter() {
-            let arg_ty = return_if_err!(self.typer.node_ty(arg.pat.id));
+            let arg_ty = self.typer.node_ty(arg.pat.id);
 
             let fn_body_scope = region::CodeExtent::from_node_id(body.id);
             let arg_cmt = self.mc.cat_rvalue(
@@ -385,7 +369,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     pub fn consume_expr(&mut self, expr: &ast::Expr) {
         debug!("consume_expr(expr={})", expr.repr(self.tcx()));
 
-        let cmt = return_if_err!(self.mc.cat_expr(expr));
+        let cmt = self.mc.cat_expr(expr);
         self.delegate_consume(expr.id, expr.span, cmt);
         self.walk_expr(expr);
     }
@@ -394,7 +378,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                    assignment_expr: &ast::Expr,
                    expr: &ast::Expr,
                    mode: MutateMode) {
-        let cmt = return_if_err!(self.mc.cat_expr(expr));
+        let cmt = self.mc.cat_expr(expr);
         self.delegate.mutate(assignment_expr.id, assignment_expr.span, cmt, mode);
         self.walk_expr(expr);
     }
@@ -407,7 +391,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
         debug!("borrow_expr(expr={}, r={}, bk={})",
                expr.repr(self.tcx()), r.repr(self.tcx()), bk.repr(self.tcx()));
 
-        let cmt = return_if_err!(self.mc.cat_expr(expr));
+        let cmt = self.mc.cat_expr(expr);
         self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause);
 
         // Note: Unlike consume, we can ignore ExprParen. cat_expr
@@ -500,7 +484,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             }
 
             ast::ExprMatch(ref discr, ref arms, _) => {
-                let discr_cmt = return_if_err!(self.mc.cat_expr(&**discr));
+                let discr_cmt = self.mc.cat_expr(&**discr);
                 self.borrow_expr(&**discr, ty::ReEmpty, ty::ImmBorrow, MatchDiscriminant);
 
                 // treatment of the discriminant is handled while walking the arms.
@@ -559,7 +543,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
 
                 // Fetch the type of the value that the iteration yields to
                 // produce the pattern's categorized mutable type.
-                let pattern_type = return_if_err!(self.typer.node_ty(pat.id));
+                let pattern_type = self.typer.node_ty(pat.id);
                 let blk_scope = region::CodeExtent::from_node_id(blk.id);
                 let pat_cmt = self.mc.cat_rvalue(pat.id,
                                                  pat.span,
@@ -647,7 +631,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     }
 
     fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
-        let callee_ty = ty::expr_ty_adjusted(self.tcx(), callee);
+        let callee_ty = self.typer.expr_ty_adjusted(callee);
         debug!("walk_callee: callee={} callee_ty={}",
                callee.repr(self.tcx()), callee_ty.repr(self.tcx()));
         let call_scope = region::CodeExtent::from_node_id(call.id);
@@ -670,22 +654,19 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             }
             _ => {
                 let overloaded_call_type =
-                    match self.tcx()
-                              .method_map
-                              .borrow()
-                              .get(&MethodCall::expr(call.id)) {
-                    Some(ref method_callee) => {
-                        OverloadedCallType::from_method_origin(
-                            self.tcx(),
-                            &method_callee.origin)
-                    }
-                    None => {
-                        self.tcx().sess.span_bug(
-                            callee.span,
-                            format!("unexpected callee type {}",
-                                    callee_ty.repr(self.tcx()))[])
-                    }
-                };
+                    match self.typer.node_method_origin(MethodCall::expr(call.id)) {
+                        Some(method_origin) => {
+                            OverloadedCallType::from_method_origin(
+                                self.tcx(),
+                                &method_origin)
+                        }
+                        None => {
+                            self.tcx().sess.span_bug(
+                                callee.span,
+                                format!("unexpected callee type {}",
+                                        callee_ty.repr(self.tcx())).as_slice())
+                        }
+                    };
                 match overloaded_call_type {
                     FnMutOverloadedCall => {
                         self.borrow_expr(callee,
@@ -747,7 +728,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                 // "assigns", which is handled by
                 // `walk_pat`:
                 self.walk_expr(&**expr);
-                let init_cmt = return_if_err!(self.mc.cat_expr(&**expr));
+                let init_cmt = self.mc.cat_expr(&**expr);
                 self.walk_irrefutable_pat(init_cmt, &*local.pat);
             }
         }
@@ -781,7 +762,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             None => { return; }
         };
 
-        let with_cmt = return_if_err!(self.mc.cat_expr(&*with_expr));
+        let with_cmt = self.mc.cat_expr(&*with_expr);
 
         // Select just those fields of the `with`
         // expression that will actually be used
@@ -836,7 +817,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                         // rvalue.
                         debug!("walk_adjustment(AutoAddEnv|AdjustReifyFnPointer)");
                         let cmt_unadjusted =
-                            return_if_err!(self.mc.cat_expr_unadjusted(expr));
+                            self.mc.cat_expr_unadjusted(expr);
                         self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
                     }
                     ty::AdjustDerefRef(ty::AutoDerefRef {
@@ -870,7 +851,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
             match self.typer.node_method_ty(deref_id) {
                 None => {}
                 Some(method_ty) => {
-                    let cmt = return_if_err!(self.mc.cat_expr_autoderefd(expr, i));
+                    let cmt = self.mc.cat_expr_autoderefd(expr, i);
                     let self_ty = ty::ty_fn_args(method_ty)[0];
                     let (m, r) = match self_ty.sty {
                         ty::ty_rptr(r, ref m) => (m.mutbl, r),
@@ -900,15 +881,14 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                 assert!(n == 1, format!("Expected exactly 1 deref with Uniq \
                                          AutoRefs, found: {}", n));
                 let cmt_unadjusted =
-                    return_if_err!(self.mc.cat_expr_unadjusted(expr));
+                    self.mc.cat_expr_unadjusted(expr);
                 self.delegate_consume(expr.id, expr.span, cmt_unadjusted);
                 return;
             }
             _ => {}
         }
 
-        let cmt_derefd = return_if_err!(
-            self.mc.cat_expr_autoderefd(expr, n));
+        let cmt_derefd = self.mc.cat_expr_autoderefd(expr, n);
         debug!("walk_adjustment: cmt_derefd={}",
                cmt_derefd.repr(self.tcx()));
 
@@ -1001,7 +981,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                                mode: &mut TrackMatchMode<Span>) {
         debug!("determine_pat_move_mode cmt_discr={} pat={}", cmt_discr.repr(self.tcx()),
                pat.repr(self.tcx()));
-        return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
+        self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
             let tcx = self.typer.tcx();
             let def_map = &self.typer.tcx().def_map;
             if pat_util::pat_is_binding(def_map, pat) {
@@ -1024,7 +1004,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                     }
                 }
             }
-        }));
+        });
     }
 
     /// The core driver for walking a pattern; `match_mode` must be
@@ -1039,11 +1019,11 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
 
         let mc = &self.mc;
         let typer = self.typer;
-        let tcx = typer.tcx();
         let def_map = &self.typer.tcx().def_map;
         let delegate = &mut self.delegate;
         let param_env = &mut self.param_env;
-        return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
+
+        mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
             if pat_util::pat_is_binding(def_map, pat) {
                 let tcx = typer.tcx();
 
@@ -1053,17 +1033,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                        match_mode);
 
                 // pat_ty: the type of the binding being produced.
-                let pat_ty = return_if_err!(typer.node_ty(pat.id));
+                let pat_ty = typer.node_ty(pat.id);
 
                 // Each match binding is effectively an assignment to the
                 // binding being produced.
                 let def = def_map.borrow()[pat.id].clone();
-                match mc.cat_def(pat.id, pat.span, pat_ty, def) {
-                    Ok(binding_cmt) => {
-                        delegate.mutate(pat.id, pat.span, binding_cmt, Init);
-                    }
-                    Err(_) => { }
-                }
+                let binding_cmt = mc.cat_def(pat.id, pat.span, pat_ty, def);
+                delegate.mutate(pat.id, pat.span, binding_cmt, Init);
 
                 // It is also a borrow or copy/move of the value being matched.
                 match pat.node {
@@ -1097,15 +1073,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                         // borrow of the elements of the vector being
                         // matched.
 
-                        let (slice_cmt, slice_mutbl, slice_r) = {
-                            match mc.cat_slice_pattern(cmt_pat, &**slice_pat) {
-                                Ok(v) => v,
-                                Err(()) => {
-                                    tcx.sess.span_bug(slice_pat.span,
-                                                      "Err from mc")
-                                }
-                            }
-                        };
+                        let (slice_cmt, slice_mutbl, slice_r) =
+                            mc.cat_slice_pattern(cmt_pat, &**slice_pat);
 
                         // Note: We declare here that the borrow
                         // occurs upon entering the `[...]`
@@ -1135,13 +1104,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                     _ => { }
                 }
             }
-        }));
+        });
 
         // Do a second pass over the pattern, calling `matched_pat` on
         // 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| {
+        mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
             let def_map = def_map.borrow();
             let tcx = typer.tcx();
 
@@ -1222,7 +1191,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                     // cases either.
                 }
             }
-        }));
+        });
     }
 
     fn walk_captures(&mut self, closure_expr: &ast::Expr) {
@@ -1246,15 +1215,15 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                             freevars: &[ty::Freevar]) {
         for freevar in freevars.iter() {
             let id_var = freevar.def.def_id().node;
-            let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
-                                                               closure_expr.span,
-                                                               freevar.def));
+            let cmt_var = self.cat_captured_var(closure_expr.id,
+                                                closure_expr.span,
+                                                freevar.def);
 
             // Lookup the kind of borrow the callee requires, as
             // inferred by regionbk
             let upvar_id = ty::UpvarId { var_id: id_var,
                                          closure_expr_id: closure_expr.id };
-            let upvar_borrow = self.tcx().upvar_borrow_map.borrow()[upvar_id].clone();
+            let upvar_borrow = self.typer.upvar_borrow(upvar_id);
 
             self.delegate.borrow(closure_expr.id,
                                  closure_expr.span,
@@ -1269,13 +1238,11 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                               closure_expr: &ast::Expr,
                               freevars: &[ty::Freevar]) {
         for freevar in freevars.iter() {
-            let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
-                                                               closure_expr.span,
-                                                               freevar.def));
-            let mode = copy_or_move(self.tcx(),
-                                    cmt_var.ty,
-                                    &self.param_env,
-                                    CaptureMove);
+            let cmt_var = self.cat_captured_var(closure_expr.id,
+                                                closure_expr.span,
+                                                freevar.def);
+            let mode = copy_or_move(self.tcx(), cmt_var.ty,
+                                    &self.param_env, CaptureMove);
             self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode);
         }
     }
@@ -1284,11 +1251,11 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                         closure_id: ast::NodeId,
                         closure_span: Span,
                         upvar_def: def::Def)
-                        -> mc::McResult<mc::cmt<'tcx>> {
+                        -> mc::cmt<'tcx> {
         // Create the cmt for the variable being borrowed, from the
         // caller's perspective
         let var_id = upvar_def.def_id().node;
-        let var_ty = try!(self.typer.node_ty(var_id));
+        let var_ty = self.typer.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 932a124ed33..9f7472c2c73 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -264,8 +264,6 @@ pub struct MemCategorizationContext<'t,TYPER:'t> {
 
 impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {}
 
-pub type McResult<T> = Result<T, ()>;
-
 /// The `Typer` trait provides the interface for the mem-categorization
 /// module to the results of the type check. It can be used to query
 /// the type assigned to an expression node, to inquire after adjustments,
@@ -284,8 +282,11 @@ pub type McResult<T> = Result<T, ()>;
 /// can be sure that only `Ok` results will occur.
 pub trait Typer<'tcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
-    fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>>;
+    fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx>;
+    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx>;
     fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>>;
+    fn node_method_origin(&self, method_call: ty::MethodCall)
+                          -> Option<ty::MethodOrigin<'tcx>>;
     fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>;
     fn is_method_call(&self, id: ast::NodeId) -> bool;
     fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent>;
@@ -374,15 +375,6 @@ impl MutabilityCategory {
     }
 }
 
-macro_rules! if_ok {
-    ($inp: expr) => (
-        match $inp {
-            Ok(v) => { v }
-            Err(e) => { return Err(e); }
-        }
-    )
-}
-
 impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
     pub fn new(typer: &'t TYPER) -> MemCategorizationContext<'t,TYPER> {
         MemCategorizationContext { typer: typer }
@@ -392,22 +384,22 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         self.typer.tcx()
     }
 
-    fn expr_ty(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
+    fn expr_ty(&self, expr: &ast::Expr) -> Ty<'tcx> {
         self.typer.node_ty(expr.id)
     }
 
-    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
-        let unadjusted_ty = if_ok!(self.expr_ty(expr));
-        Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty,
-                         self.typer.adjustments().borrow().get(&expr.id),
-                         |method_call| self.typer.node_method_ty(method_call)))
+    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
+        let unadjusted_ty = self.expr_ty(expr);
+        ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty,
+                      self.typer.adjustments().borrow().get(&expr.id),
+                      |method_call| self.typer.node_method_ty(method_call))
     }
 
-    fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
+    fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
         self.typer.node_ty(id)
     }
 
-    fn pat_ty(&self, pat: &ast::Pat) -> McResult<Ty<'tcx>> {
+    fn pat_ty(&self, pat: &ast::Pat) -> Ty<'tcx> {
         let tcx = self.typer.tcx();
         let base_ty = self.typer.node_ty(pat.id);
         // FIXME (Issue #18207): This code detects whether we are
@@ -419,11 +411,9 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                 // a bind-by-ref means that the base_ty will be the type of the ident itself,
                 // but what we want here is the type of the underlying value being borrowed.
                 // So peel off one-level, turning the &T into T.
-                base_ty.map(|t| {
-                    ty::deref(t, false).unwrap_or_else(|| {
-                        panic!("encountered BindByRef with non &-type");
-                    }).ty
-                })
+                ty::deref(base_ty, false).unwrap_or_else(|| {
+                    panic!("encountered BindByRef with non &-type");
+                }).ty
             }
             _ => base_ty,
         };
@@ -432,7 +422,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         ret_ty
     }
 
-    pub fn cat_expr(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
+    pub fn cat_expr(&self, expr: &ast::Expr) -> cmt<'tcx> {
         match self.typer.adjustments().borrow().get(&expr.id) {
             None => {
                 // No adjustments.
@@ -446,8 +436,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                                expr.repr(self.tcx()));
                         // Convert a bare fn to a closure by adding NULL env.
                         // Result is an rvalue.
-                        let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
-                        Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
+                        let expr_ty = self.expr_ty_adjusted(expr);
+                        self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)
                     }
 
                     ty::AdjustDerefRef(
@@ -457,8 +447,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                                expr.repr(self.tcx()));
                         // Equivalent to &*expr or something similar.
                         // Result is an rvalue.
-                        let expr_ty = if_ok!(self.expr_ty_adjusted(expr));
-                        Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
+                        let expr_ty = self.expr_ty_adjusted(expr);
+                        self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)
                     }
 
                     ty::AdjustDerefRef(
@@ -475,39 +465,39 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
     pub fn cat_expr_autoderefd(&self,
                                expr: &ast::Expr,
                                autoderefs: uint)
-                               -> McResult<cmt<'tcx>> {
-        let mut cmt = if_ok!(self.cat_expr_unadjusted(expr));
+                               -> cmt<'tcx> {
+        let mut cmt = self.cat_expr_unadjusted(expr);
         debug!("cat_expr_autoderefd: autoderefs={}, cmt={}",
                autoderefs,
                cmt.repr(self.tcx()));
         for deref in range(1u, autoderefs + 1) {
             cmt = self.cat_deref(expr, cmt, deref, false);
         }
-        return Ok(cmt);
+        return cmt;
     }
 
-    pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
+    pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> cmt<'tcx> {
         debug!("cat_expr: id={} expr={}", expr.id, expr.repr(self.tcx()));
 
-        let expr_ty = if_ok!(self.expr_ty(expr));
+        let expr_ty = self.expr_ty(expr);
         match expr.node {
           ast::ExprUnary(ast::UnDeref, ref e_base) => {
-            let base_cmt = if_ok!(self.cat_expr(&**e_base));
-            Ok(self.cat_deref(expr, base_cmt, 0, false))
+            let base_cmt = self.cat_expr(&**e_base);
+            self.cat_deref(expr, base_cmt, 0, false)
           }
 
           ast::ExprField(ref base, f_name) => {
-            let base_cmt = if_ok!(self.cat_expr(&**base));
+            let base_cmt = self.cat_expr(&**base);
             debug!("cat_expr(cat_field): id={} expr={} base={}",
                    expr.id,
                    expr.repr(self.tcx()),
                    base_cmt.repr(self.tcx()));
-            Ok(self.cat_field(expr, base_cmt, f_name.node.name, expr_ty))
+            self.cat_field(expr, base_cmt, f_name.node.name, expr_ty)
           }
 
           ast::ExprTupField(ref base, idx) => {
-            let base_cmt = if_ok!(self.cat_expr(&**base));
-            Ok(self.cat_tup_field(expr, base_cmt, idx.node, expr_ty))
+            let base_cmt = self.cat_expr(&**base);
+            self.cat_tup_field(expr, base_cmt, idx.node, expr_ty)
           }
 
           ast::ExprIndex(ref base, _) => {
@@ -517,14 +507,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                     // If this is an index implemented by a method call, then it will
                     // include an implicit deref of the result.
                     let ret_ty = ty::ty_fn_ret(method_ty).unwrap();
-                    Ok(self.cat_deref(expr,
-                                      self.cat_rvalue_node(expr.id(),
-                                                           expr.span(),
-                                                           ret_ty), 1, true))
+                    self.cat_deref(expr,
+                                   self.cat_rvalue_node(expr.id(),
+                                                        expr.span(),
+                                                        ret_ty), 1, true)
                 }
                 None => {
-                    let base_cmt = if_ok!(self.cat_expr(&**base));
-                    Ok(self.cat_index(expr, base_cmt))
+                    let base_cmt = self.cat_expr(&**base);
+                    self.cat_index(expr, base_cmt)
                 }
             }
           }
@@ -550,7 +540,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
           ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
           ast::ExprInlineAsm(..) | ast::ExprBox(..) |
           ast::ExprForLoop(..) => {
-            Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
+            self.cat_rvalue_node(expr.id(), expr.span(), expr_ty)
           }
 
           ast::ExprIfLet(..) => {
@@ -567,43 +557,43 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                    span: Span,
                    expr_ty: Ty<'tcx>,
                    def: def::Def)
-                   -> McResult<cmt<'tcx>> {
+                   -> cmt<'tcx> {
         debug!("cat_def: id={} expr={} def={}",
                id, expr_ty.repr(self.tcx()), def);
 
         match def {
           def::DefStruct(..) | def::DefVariant(..) | def::DefFn(..) |
           def::DefStaticMethod(..) | def::DefConst(..) => {
-                Ok(self.cat_rvalue_node(id, span, expr_ty))
+                self.cat_rvalue_node(id, span, expr_ty)
           }
           def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
           def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
           def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
           def::DefLabel(_) | def::DefSelfTy(..) | def::DefMethod(..) |
           def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
-              Ok(Rc::new(cmt_ {
+              Rc::new(cmt_ {
                   id:id,
                   span:span,
                   cat:cat_static_item,
                   mutbl: McImmutable,
                   ty:expr_ty,
                   note: NoteNone
-              }))
+              })
           }
 
           def::DefStatic(_, mutbl) => {
-              Ok(Rc::new(cmt_ {
+              Rc::new(cmt_ {
                   id:id,
                   span:span,
                   cat:cat_static_item,
                   mutbl: if mutbl { McDeclared } else { McImmutable},
                   ty:expr_ty,
                   note: NoteNone
-              }))
+              })
           }
 
           def::DefUpvar(var_id, fn_node_id, _) => {
-              let ty = if_ok!(self.node_ty(fn_node_id));
+              let ty = self.node_ty(fn_node_id);
               match ty.sty {
                   ty::ty_closure(ref closure_ty) => {
                       // Translate old closure type info into unboxed
@@ -641,14 +631,14 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
           }
 
           def::DefLocal(vid) => {
-            Ok(Rc::new(cmt_ {
+            Rc::new(cmt_ {
                 id: id,
                 span: span,
                 cat: cat_local(vid),
                 mutbl: MutabilityCategory::from_local(self.tcx(), vid),
                 ty: expr_ty,
                 note: NoteNone
-            }))
+            })
           }
         }
     }
@@ -663,7 +653,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                  kind: ty::UnboxedClosureKind,
                  mode: ast::CaptureClause,
                  is_unboxed: bool)
-                 -> McResult<cmt<'tcx>> {
+                 -> cmt<'tcx> {
         // An upvar can have up to 3 components.  The base is a
         // `cat_upvar`.  Next, we add a deref through the implicit
         // environment pointer with an anonymous free region 'env and
@@ -685,7 +675,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         // FnOnce         | copied               | upvar -> &'up bk
         // old stack      | N/A                  | upvar -> &'env mut -> &'up bk
         // old proc/once  | copied               | N/A
-        let var_ty = if_ok!(self.node_ty(var_id));
+        let var_ty = self.node_ty(var_id);
 
         let upvar_id = ty::UpvarId { var_id: var_id,
                                      closure_expr_id: fn_node_id };
@@ -733,7 +723,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         });
 
         // First, switch by capture mode
-        Ok(match mode {
+        match mode {
             ast::CaptureByValue => {
                 let mut base = cmt_ {
                     id: id,
@@ -815,7 +805,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                     note: NoteUpvarRef(upvar_id)
                 })
             }
-        })
+        }
     }
 
     pub fn cat_rvalue_node(&self,
@@ -1064,13 +1054,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
     pub fn cat_slice_pattern(&self,
                              vec_cmt: cmt<'tcx>,
                              slice_pat: &ast::Pat)
-                             -> McResult<(cmt<'tcx>, ast::Mutability, ty::Region)> {
-        let slice_ty = if_ok!(self.node_ty(slice_pat.id));
+                             -> (cmt<'tcx>, ast::Mutability, ty::Region) {
+        let slice_ty = self.node_ty(slice_pat.id);
         let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(),
                                                     slice_pat,
                                                     slice_ty);
         let cmt_slice = self.cat_index(slice_pat, self.deref_vec(slice_pat, vec_cmt));
-        return Ok((cmt_slice, slice_mutbl, slice_r));
+        return (cmt_slice, slice_mutbl, slice_r);
 
         /// In a pattern like [a, b, ..c], normally `c` has slice type, but if you have [a, b,
         /// ..ref c], then the type of `ref c` will be `&&[]`, so to extract the slice details we
@@ -1130,7 +1120,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                        cmt: cmt<'tcx>,
                        pat: &ast::Pat,
                        op: |&MemCategorizationContext<'t, TYPER>, cmt<'tcx>, &ast::Pat|)
-                       -> McResult<()> {
+    {
         // Here, `cmt` is the categorization for the value being
         // matched and pat is the pattern it is being matched against.
         //
@@ -1210,30 +1200,30 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                 Some(&def::DefVariant(..)) => {
                     // variant(x, y, z)
                     for (i, subpat) in subpats.iter().enumerate() {
-                        let subpat_ty = if_ok!(self.pat_ty(&**subpat)); // see (*2)
+                        let subpat_ty = self.pat_ty(&**subpat); // see (*2)
 
                         let subcmt =
                             self.cat_imm_interior(
                                 pat, cmt.clone(), subpat_ty,
                                 InteriorField(PositionalField(i)));
 
-                        if_ok!(self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z)));
+                        self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z));
                     }
                 }
                 Some(&def::DefStruct(..)) => {
                     for (i, subpat) in subpats.iter().enumerate() {
-                        let subpat_ty = if_ok!(self.pat_ty(&**subpat)); // see (*2)
+                        let subpat_ty = self.pat_ty(&**subpat); // see (*2)
                         let cmt_field =
                             self.cat_imm_interior(
                                 pat, cmt.clone(), subpat_ty,
                                 InteriorField(PositionalField(i)));
-                        if_ok!(self.cat_pattern(cmt_field, &**subpat,
-                                                |x,y,z| op(x,y,z)));
+                        self.cat_pattern(cmt_field, &**subpat,
+                                         |x,y,z| op(x,y,z));
                     }
                 }
                 Some(&def::DefConst(..)) => {
                     for subpat in subpats.iter() {
-                        if_ok!(self.cat_pattern(cmt.clone(), &**subpat, |x,y,z| op(x,y,z)));
+                        self.cat_pattern(cmt.clone(), &**subpat, |x,y,z| op(x,y,z));
                     }
                 }
                 _ => {
@@ -1245,7 +1235,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
           }
 
           ast::PatIdent(_, _, Some(ref subpat)) => {
-              if_ok!(self.cat_pattern(cmt, &**subpat, op));
+              self.cat_pattern(cmt, &**subpat, op);
           }
 
           ast::PatIdent(_, _, None) => {
@@ -1255,43 +1245,43 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
           ast::PatStruct(_, ref field_pats, _) => {
             // {f1: p1, ..., fN: pN}
             for fp in field_pats.iter() {
-                let field_ty = if_ok!(self.pat_ty(&*fp.node.pat)); // see (*2)
+                let field_ty = self.pat_ty(&*fp.node.pat); // see (*2)
                 let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.ident.name, field_ty);
-                if_ok!(self.cat_pattern(cmt_field, &*fp.node.pat, |x,y,z| op(x,y,z)));
+                self.cat_pattern(cmt_field, &*fp.node.pat, |x,y,z| op(x,y,z));
             }
           }
 
           ast::PatTup(ref subpats) => {
             // (p1, ..., pN)
             for (i, subpat) in subpats.iter().enumerate() {
-                let subpat_ty = if_ok!(self.pat_ty(&**subpat)); // see (*2)
+                let subpat_ty = self.pat_ty(&**subpat); // see (*2)
                 let subcmt =
                     self.cat_imm_interior(
                         pat, cmt.clone(), subpat_ty,
                         InteriorField(PositionalField(i)));
-                if_ok!(self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z)));
+                self.cat_pattern(subcmt, &**subpat, |x,y,z| op(x,y,z));
             }
           }
 
           ast::PatBox(ref subpat) | ast::PatRegion(ref subpat) => {
             // @p1, ~p1, ref p1
             let subcmt = self.cat_deref(pat, cmt, 0, false);
-            if_ok!(self.cat_pattern(subcmt, &**subpat, op));
+            self.cat_pattern(subcmt, &**subpat, op);
           }
 
           ast::PatVec(ref before, ref slice, ref after) => {
               let elt_cmt = self.cat_index(pat, self.deref_vec(pat, cmt));
               for before_pat in before.iter() {
-                  if_ok!(self.cat_pattern(elt_cmt.clone(), &**before_pat,
-                                          |x,y,z| op(x,y,z)));
+                  self.cat_pattern(elt_cmt.clone(), &**before_pat,
+                                   |x,y,z| op(x,y,z));
               }
               for slice_pat in slice.iter() {
-                  let slice_ty = if_ok!(self.pat_ty(&**slice_pat));
+                  let slice_ty = self.pat_ty(&**slice_pat);
                   let slice_cmt = self.cat_rvalue_node(pat.id(), pat.span(), slice_ty);
-                  if_ok!(self.cat_pattern(slice_cmt, &**slice_pat, |x,y,z| op(x,y,z)));
+                  self.cat_pattern(slice_cmt, &**slice_pat, |x,y,z| op(x,y,z));
               }
               for after_pat in after.iter() {
-                  if_ok!(self.cat_pattern(elt_cmt.clone(), &**after_pat, |x,y,z| op(x,y,z)));
+                  self.cat_pattern(elt_cmt.clone(), &**after_pat, |x,y,z| op(x,y,z));
               }
           }
 
@@ -1303,8 +1293,6 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
               self.tcx().sess.span_bug(pat.span, "unexpanded macro");
           }
         }
-
-        Ok(())
     }
 
     pub fn cmt_to_string(&self, cmt: &cmt_<'tcx>) -> String {
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index f849f4c9b93..5ee6dec7830 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -1228,8 +1228,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             .iter()
                             .map(|freevar| {
                                 let freevar_def_id = freevar.def.def_id();
-                                self.typer.node_ty(freevar_def_id.node)
-                                    .unwrap_or(ty::mk_err()).subst(self.tcx(), substs)
+                                self.typer.node_ty(freevar_def_id.node).subst(self.tcx(), substs)
                             })
                             .collect();
                         Ok(If(tys))
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index c0d5d6b11cf..819defdb0ca 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -3004,9 +3004,9 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
                 // FIXME(#14449): `borrowed_contents` below assumes `&mut`
                 // unboxed closure.
                 let upvars = unboxed_closure_upvars(cx, did, substs);
-                TypeContents::union(upvars[],
-                                    |f| tc_ty(cx, f.ty, cache)) |
-                    borrowed_contents(r, MutMutable)
+                TypeContents::union(upvars.as_slice(),
+                                    |f| tc_ty(cx, f.ty, cache))
+                    | borrowed_contents(r, MutMutable)
             }
 
             ty_tup(ref tys) => {
@@ -6166,14 +6166,24 @@ impl<'tcx> mc::Typer<'tcx> for ty::ctxt<'tcx> {
         self
     }
 
-    fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
-        Ok(ty::node_id_to_type(self, id))
+    fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
+        ty::node_id_to_type(self, id)
     }
 
-    fn node_method_ty(&self, method_call: MethodCall) -> Option<Ty<'tcx>> {
+    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
+        ty::expr_ty_adjusted(self, expr)
+    }
+
+    fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
         self.method_map.borrow().get(&method_call).map(|method| method.ty)
     }
 
+    fn node_method_origin(&self, method_call: ty::MethodCall)
+                          -> Option<ty::MethodOrigin<'tcx>>
+    {
+        self.method_map.borrow().get(&method_call).map(|method| method.origin.clone())
+    }
+
     fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
         &self.adjustments
     }
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index a13001b7968..b57b76d66f7 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -516,12 +516,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
     }
 
     pub fn cat_expr(&self, expr: &ast::Expr) -> mc::cmt<'tcx> {
-        match self.mc().cat_expr(expr) {
-            Ok(c) => c,
-            Err(()) => {
-                self.tcx.sess.span_bug(expr.span, "error in mem categorization");
-            }
-        }
+        self.mc().cat_expr(expr)
     }
 
     pub fn report(&self, err: BckError<'tcx>) {
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 9a3e39ff10b..ea2a4ef6b28 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -463,8 +463,12 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
         self.tcx()
     }
 
-    fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
-        Ok(node_id_type(self, id))
+    fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
+        node_id_type(self, id)
+    }
+
+    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
+        expr_ty_adjusted(self, expr)
     }
 
     fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
@@ -475,6 +479,16 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
             .map(|method| monomorphize_type(self, method.ty))
     }
 
+    fn node_method_origin(&self, method_call: ty::MethodCall)
+                          -> Option<ty::MethodOrigin<'tcx>>
+    {
+        self.tcx()
+            .method_map
+            .borrow()
+            .get(&method_call)
+            .map(|method| method.origin.clone())
+    }
+
     fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
         &self.tcx().adjustments
     }
@@ -752,11 +766,11 @@ pub fn node_id_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, id: ast::NodeId) -> Ty
     monomorphize_type(bcx, t)
 }
 
-pub fn expr_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
+pub fn expr_ty<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
     node_id_type(bcx, ex.id)
 }
 
-pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
+pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
     monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex))
 }
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index abcd00ddcce..535a4700854 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -86,7 +86,7 @@ use check::_match::pat_ctxt;
 use middle::{const_eval, def};
 use middle::infer;
 use middle::lang_items::IteratorItem;
-use middle::mem_categorization::{mod, McResult};
+use middle::mem_categorization as mc;
 use middle::pat_util::{mod, pat_id_map};
 use middle::region::CodeExtent;
 use middle::subst::{mod, Subst, Substs, VecPerParamSpace, ParamSpace};
@@ -282,16 +282,31 @@ pub struct FnCtxt<'a, 'tcx: 'a> {
     ccx: &'a CrateCtxt<'a, 'tcx>,
 }
 
-impl<'a, 'tcx> mem_categorization::Typer<'tcx> for FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> {
         self.ccx.tcx
     }
-    fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
-        Ok(self.node_ty(id))
+    fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
+        let ty = self.node_ty(id);
+        self.infcx().resolve_type_vars_if_possible(&ty)
+    }
+    fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
+        let ty = self.expr_ty_adjusted(expr);
+        self.infcx().resolve_type_vars_if_possible(&ty)
     }
     fn node_method_ty(&self, method_call: ty::MethodCall)
                       -> Option<Ty<'tcx>> {
-        self.inh.method_map.borrow().get(&method_call).map(|m| m.ty)
+        self.inh.method_map.borrow()
+                           .get(&method_call)
+                           .map(|method| method.ty)
+                           .map(|ty| self.infcx().resolve_type_vars_if_possible(&ty))
+    }
+    fn node_method_origin(&self, method_call: ty::MethodCall)
+                          -> Option<ty::MethodOrigin<'tcx>>
+    {
+        self.inh.method_map.borrow()
+                           .get(&method_call)
+                           .map(|method| method.origin.clone())
     }
     fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
         &self.inh.adjustments
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 22502c0dd1a..429eee87026 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -126,7 +126,7 @@ use middle::ty::{ReScope};
 use middle::ty::{mod, Ty, MethodCall};
 use middle::infer;
 use middle::pat_util;
-use util::nodemap::{DefIdMap, NodeMap, FnvHashMap};
+use util::nodemap::{FnvHashMap};
 use util::ppaux::{ty_to_string, Repr};
 
 use syntax::{ast, ast_util};
@@ -193,19 +193,6 @@ pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 ///////////////////////////////////////////////////////////////////////////
 // INTERNALS
 
-// If mem categorization 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 and don't try to add any more region constraints.
-macro_rules! ignore_err {
-    ($inp: expr) => (
-        match $inp {
-            Ok(v) => v,
-            Err(()) => return
-        }
-    )
-}
-
 // Stores parameters for a potential call to link_region()
 // to perform if an upvar reference is marked unique/mutable after
 // it has already been processed before.
@@ -446,47 +433,6 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
     }
 }
 
-impl<'fcx, 'tcx> mc::Typer<'tcx> for Rcx<'fcx, 'tcx> {
-    fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
-        self.fcx.ccx.tcx
-    }
-
-    fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
-        let t = self.resolve_node_type(id);
-        if ty::type_is_error(t) {Err(())} else {Ok(t)}
-    }
-
-    fn node_method_ty(&self, method_call: MethodCall) -> Option<Ty<'tcx>> {
-        self.resolve_method_type(method_call)
-    }
-
-    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
-        &self.fcx.inh.adjustments
-    }
-
-    fn is_method_call(&self, id: ast::NodeId) -> bool {
-        self.fcx.inh.method_map.borrow().contains_key(&MethodCall::expr(id))
-    }
-
-    fn temporary_scope(&self, id: ast::NodeId) -> Option<CodeExtent> {
-        self.tcx().region_maps.temporary_scope(id)
-    }
-
-    fn upvar_borrow(&self, id: ty::UpvarId) -> ty::UpvarBorrow {
-        self.fcx.inh.upvar_borrow_map.borrow()[id].clone()
-    }
-
-    fn capture_mode(&self, closure_expr_id: ast::NodeId)
-                    -> ast::CaptureClause {
-        self.tcx().capture_modes.borrow()[closure_expr_id].clone()
-    }
-
-    fn unboxed_closures<'a>(&'a self)
-                        -> &'a RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>> {
-        &self.fcx.inh.unboxed_closures
-    }
-}
-
 impl<'a, 'tcx, 'v> Visitor<'v> for Rcx<'a, 'tcx> {
     // (..) FIXME(#3238) should use visit_pat, not visit_arm/visit_local,
     // However, right now we run into an issue whereby some free
@@ -767,7 +713,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             constrain_bindings_in_pat(&**pat, rcx);
 
             {
-                let mc = mc::MemCategorizationContext::new(rcx);
+                let mc = mc::MemCategorizationContext::new(rcx.fcx);
                 let pat_ty = rcx.resolve_node_type(pat.id);
                 let pat_cmt = mc.cat_rvalue(pat.id,
                                             pat.span,
@@ -1080,8 +1026,8 @@ fn constrain_callee(rcx: &mut Rcx,
                 ty::RegionTraitStore(r, _) => {
                     // While we're here, link the closure's region with a unique
                     // immutable borrow (gathered later in borrowck)
-                    let mc = mc::MemCategorizationContext::new(rcx);
-                    let expr_cmt = ignore_err!(mc.cat_expr(callee_expr));
+                    let mc = mc::MemCategorizationContext::new(rcx.fcx);
+                    let expr_cmt = mc.cat_expr(callee_expr);
                     link_region(rcx, callee_expr.span, call_region,
                                 ty::UniqueImmBorrow, expr_cmt);
                     r
@@ -1189,8 +1135,8 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                                     method.ty.repr(rcx.tcx()))[])
                 };
                 {
-                    let mc = mc::MemCategorizationContext::new(rcx);
-                    let self_cmt = ignore_err!(mc.cat_expr_autoderefd(deref_expr, i));
+                    let mc = mc::MemCategorizationContext::new(rcx.fcx);
+                    let self_cmt = mc.cat_expr_autoderefd(deref_expr, i);
                     link_region(rcx, deref_expr.span, r,
                                 ty::BorrowKind::from_mutbl(m), self_cmt);
                 }
@@ -1285,8 +1231,8 @@ fn link_addr_of(rcx: &mut Rcx, expr: &ast::Expr,
     debug!("link_addr_of(base=?)");
 
     let cmt = {
-        let mc = mc::MemCategorizationContext::new(rcx);
-        ignore_err!(mc.cat_expr(base))
+        let mc = mc::MemCategorizationContext::new(rcx.fcx);
+        mc.cat_expr(base)
     };
     link_region_from_node_type(rcx, expr.span, expr.id, mutability, cmt);
 }
@@ -1300,8 +1246,8 @@ fn link_local(rcx: &Rcx, local: &ast::Local) {
         None => { return; }
         Some(ref expr) => &**expr,
     };
-    let mc = mc::MemCategorizationContext::new(rcx);
-    let discr_cmt = ignore_err!(mc.cat_expr(init_expr));
+    let mc = mc::MemCategorizationContext::new(rcx.fcx);
+    let discr_cmt = mc.cat_expr(init_expr);
     link_pattern(rcx, mc, discr_cmt, &*local.pat);
 }
 
@@ -1310,8 +1256,8 @@ fn link_local(rcx: &Rcx, local: &ast::Local) {
 /// linked to the lifetime of its guarantor (if any).
 fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
     debug!("regionck::for_match()");
-    let mc = mc::MemCategorizationContext::new(rcx);
-    let discr_cmt = ignore_err!(mc.cat_expr(discr));
+    let mc = mc::MemCategorizationContext::new(rcx.fcx);
+    let discr_cmt = mc.cat_expr(discr);
     debug!("discr_cmt={}", discr_cmt.repr(rcx.tcx()));
     for arm in arms.iter() {
         for root_pat in arm.pats.iter() {
@@ -1325,7 +1271,7 @@ fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
 /// linked to the lifetime of its guarantor (if any).
 fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) {
     debug!("regionck::link_fn_args(body_scope={})", body_scope);
-    let mc = mc::MemCategorizationContext::new(rcx);
+    let mc = mc::MemCategorizationContext::new(rcx.fcx);
     for arg in args.iter() {
         let arg_ty = rcx.fcx.node_ty(arg.id);
         let re_scope = ty::ReScope(body_scope);
@@ -1340,7 +1286,7 @@ fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) {
 /// Link lifetimes of any ref bindings in `root_pat` to the pointers found in the discriminant, if
 /// needed.
 fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
-                          mc: mc::MemCategorizationContext<Rcx<'a, 'tcx>>,
+                          mc: mc::MemCategorizationContext<FnCtxt<'a, 'tcx>>,
                           discr_cmt: mc::cmt<'tcx>,
                           root_pat: &ast::Pat) {
     debug!("link_pattern(discr_cmt={}, root_pat={})",
@@ -1357,14 +1303,11 @@ fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
 
                 // `[_, ..slice, _]` pattern
                 ast::PatVec(_, Some(ref slice_pat), _) => {
-                    match mc.cat_slice_pattern(sub_cmt, &**slice_pat) {
-                        Ok((slice_cmt, slice_mutbl, slice_r)) => {
-                            link_region(rcx, sub_pat.span, slice_r,
-                                        ty::BorrowKind::from_mutbl(slice_mutbl),
-                                        slice_cmt);
-                        }
-                        Err(()) => {}
-                    }
+                    let (slice_cmt, slice_mutbl, slice_r) =
+                        mc.cat_slice_pattern(sub_cmt, &**slice_pat);
+                    link_region(rcx, sub_pat.span, slice_r,
+                                ty::BorrowKind::from_mutbl(slice_mutbl),
+                                slice_cmt);
                 }
                 _ => {}
             }
@@ -1379,8 +1322,8 @@ fn link_autoref(rcx: &Rcx,
                 autoref: &ty::AutoRef) {
 
     debug!("link_autoref(autoref={})", autoref);
-    let mc = mc::MemCategorizationContext::new(rcx);
-    let expr_cmt = ignore_err!(mc.cat_expr_autoderefd(expr, autoderefs));
+    let mc = mc::MemCategorizationContext::new(rcx.fcx);
+    let expr_cmt = mc.cat_expr_autoderefd(expr, autoderefs);
     debug!("expr_cmt={}", expr_cmt.repr(rcx.tcx()));
 
     match *autoref {
@@ -1401,8 +1344,8 @@ fn link_by_ref(rcx: &Rcx,
     let tcx = rcx.tcx();
     debug!("link_by_ref(expr={}, callee_scope={})",
            expr.repr(tcx), callee_scope);
-    let mc = mc::MemCategorizationContext::new(rcx);
-    let expr_cmt = ignore_err!(mc.cat_expr(expr));
+    let mc = mc::MemCategorizationContext::new(rcx.fcx);
+    let expr_cmt = mc.cat_expr(expr);
     let borrow_region = ty::ReScope(callee_scope);
     link_region(rcx, expr.span, borrow_region, ty::ImmBorrow, expr_cmt);
 }
@@ -1669,8 +1612,8 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
 /// assignment expression.
 fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx,
                                          lhs: &ast::Expr) {
-    let mc = mc::MemCategorizationContext::new(rcx);
-    let cmt = ignore_err!(mc.cat_expr(lhs));
+    let mc = mc::MemCategorizationContext::new(rcx.fcx);
+    let cmt = mc.cat_expr(lhs);
     adjust_upvar_borrow_kind_for_mut(rcx, cmt);
 }