about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-05-17 22:51:18 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-06-01 08:59:47 +0300
commit22510f32666d0c9c230c9d09e5bcd9eb3a6200b3 (patch)
treea3035d33e36fefda5f034f02c59376cb0bceb4db
parentb4988f07920324830558e79a1a5b3233511cfbd9 (diff)
downloadrust-22510f32666d0c9c230c9d09e5bcd9eb3a6200b3.tar.gz
rust-22510f32666d0c9c230c9d09e5bcd9eb3a6200b3.zip
rustc: replace TyFnDef in MethodCallee with just the FnSig.
-rw-r--r--src/librustc/ich/impls_ty.rs2
-rw-r--r--src/librustc/middle/effect.rs6
-rw-r--r--src/librustc/middle/expr_use_visitor.rs5
-rw-r--r--src/librustc/middle/liveness.rs6
-rw-r--r--src/librustc/middle/mem_categorization.rs10
-rw-r--r--src/librustc/ty/mod.rs8
-rw-r--r--src/librustc/ty/sty.rs9
-rw-r--r--src/librustc_mir/build/expr/into.rs9
-rw-r--r--src/librustc_mir/hair/cx/expr.rs18
-rw-r--r--src/librustc_typeck/check/_match.rs3
-rw-r--r--src/librustc_typeck/check/callee.rs16
-rw-r--r--src/librustc_typeck/check/method/confirm.rs18
-rw-r--r--src/librustc_typeck/check/method/mod.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs79
-rw-r--r--src/librustc_typeck/check/op.rs7
-rw-r--r--src/librustc_typeck/check/regionck.rs19
-rw-r--r--src/librustc_typeck/check/writeback.rs4
17 files changed, 88 insertions, 135 deletions
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 0575bfcf926..63dc2e2d8e1 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -112,7 +112,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> for ty::adjustment::Ad
 }
 
 impl_stable_hash_for!(struct ty::adjustment::Adjustment<'tcx> { kind, target });
-impl_stable_hash_for!(struct ty::MethodCallee<'tcx> { def_id, ty, substs });
+impl_stable_hash_for!(struct ty::MethodCallee<'tcx> { def_id, substs, sig });
 impl_stable_hash_for!(struct ty::UpvarId { var_id, closure_expr_id });
 impl_stable_hash_for!(struct ty::UpvarBorrow<'tcx> { kind, region });
 
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index 1d3f8e426e7..e84265cb60f 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -173,10 +173,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
         match expr.node {
             hir::ExprMethodCall(..) => {
-                let base_type = self.tables.method_map[&expr.id].ty;
+                let method_sig = self.tables.method_map[&expr.id].sig;
                 debug!("effect: method call case, base type is {:?}",
-                        base_type);
-                if type_is_unsafe_function(base_type) {
+                        method_sig);
+                if method_sig.unsafety == hir::Unsafety::Unsafe {
                     self.require_unsafe(expr.span,
                                         "invocation of unsafe method")
                 }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 64880bf4fad..73598d0bb1a 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -751,11 +751,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
 
         for &overloaded in autoderefs {
             if let Some(method) = overloaded {
-                // the method call infrastructure should have
-                // replaced all late-bound regions with variables:
-                let self_ty = method.ty.fn_sig().input(0);
+                let self_ty = method.sig.inputs()[0];
                 let self_ty = self.mc.infcx.resolve_type_vars_if_possible(&self_ty);
-                let self_ty = self.tcx().no_late_bound_regions(&self_ty).unwrap();
 
                 let (m, r) = match self_ty.sty {
                     ty::TyRef(r, ref m) => (m.mutbl, r),
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index d5c0a67f71c..fd8ca332a64 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -1073,7 +1073,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
           hir::ExprCall(ref f, ref args) => {
             // FIXME(canndrew): This is_never should really be an is_uninhabited
             let diverges = !self.tables.is_method_call(expr.id) &&
-                self.tables.expr_ty_adjusted(&f).fn_ret().0.is_never();
+                self.tables.expr_ty_adjusted(&f).fn_sig().output().0.is_never();
             let succ = if diverges {
                 self.s.exit_ln
             } else {
@@ -1084,9 +1084,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
           }
 
           hir::ExprMethodCall(.., ref args) => {
-            let method_ty = self.tables.method_map[&expr.id].ty;
+            let ret_ty = self.tables.method_map[&expr.id].sig.output();
             // FIXME(canndrew): This is_never should really be an is_uninhabited
-            let succ = if method_ty.fn_ret().0.is_never() {
+            let succ = if ret_ty.is_never() {
                 self.s.exit_ln
             } else {
                 succ
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 4e2150dc2c6..aa729c75796 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -1250,13 +1250,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                                    -> Ty<'tcx>
     {
         // When we process an overloaded `*` or `[]` etc, we often
-        // need to extract the return type of the method. These method
-        // types are generated by method resolution and always have
-        // all late-bound regions fully instantiated, so we just want
-        // to skip past the binder.
-        let ret_ty = method.ty.fn_ret();
-        let ret_ty = self.infcx.resolve_type_vars_if_possible(&ret_ty);
-        self.tcx().no_late_bound_regions(&ret_ty).unwrap()
+        // need to extract the return type of the method.
+        let ret_ty = method.sig.output();
+        self.infcx.resolve_type_vars_if_possible(&ret_ty)
     }
 }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 08016ac91bf..d138b306732 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -394,8 +394,12 @@ impl Variance {
 pub struct MethodCallee<'tcx> {
     /// Impl method ID, for inherent methods, or trait method ID, otherwise.
     pub def_id: DefId,
-    pub ty: Ty<'tcx>,
-    pub substs: &'tcx Substs<'tcx>
+    pub substs: &'tcx Substs<'tcx>,
+
+    /// Instantiated method signature, i.e. it has been substituted,
+    /// normalized, and has had late-bound lifetimes replaced
+    /// (with inference variables, during type-checking).
+    pub sig: FnSig<'tcx>,
 }
 
 // Contains information needed to resolve types and (in the future) look up
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 348d164af41..df7c2e567f7 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1313,15 +1313,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
         }
     }
 
-    /// Type accessors for substructures of types
-    pub fn fn_args(&self) -> ty::Binder<&'tcx [Ty<'tcx>]> {
-        self.fn_sig().inputs()
-    }
-
-    pub fn fn_ret(&self) -> Binder<Ty<'tcx>> {
-        self.fn_sig().output()
-    }
-
     pub fn is_fn(&self) -> bool {
         match self.sty {
             TyFnDef(..) | TyFnPtr(_) => true,
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 5982d3bdc81..d456bc3ded3 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -201,13 +201,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 exit_block.unit()
             }
             ExprKind::Call { ty, fun, args } => {
-                let diverges = match ty.sty {
-                    ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f) => {
-                        // FIXME(canndrew): This is_never should probably be an is_uninhabited
-                        f.output().skip_binder().is_never()
-                    }
-                    _ => false
-                };
+                // FIXME(canndrew): This is_never should probably be an is_uninhabited
+                let diverges = expr.ty.is_never();
                 let intrinsic = match ty.sty {
                     ty::TyFnDef(def_id, _, ref f) if
                         f.abi() == Abi::RustIntrinsic ||
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 6c48e0120ba..6428146525c 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -18,6 +18,7 @@ use rustc::hir::def::{Def, CtorKind};
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::{self, AdtKind, VariantDef, Ty};
 use rustc::ty::cast::CastKind as TyCastKind;
+use rustc::ty::subst::Subst;
 use rustc::hir;
 use syntax::ptr::P;
 
@@ -92,9 +93,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     let kind = if let Some(method) = overloaded {
                         debug!("make_mirror: overloaded autoderef (method={:?})", method);
 
-                        // Method calls always have all late-bound regions
-                        // fully instantiated.
-                        ref_ty = cx.tcx.no_late_bound_regions(&method.ty.fn_ret()).unwrap();
+                        ref_ty = method.sig.output();
                         let (region, mutbl) = match ref_ty.sty {
                             ty::TyRef(region, mt) => (region, mt.mutbl),
                             _ => span_bug!(expr.span, "autoderef returned bad type"),
@@ -265,14 +264,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
                 // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
 
+                let sig = method.sig;
                 let method = method_callee(cx, expr, method);
 
-                let sig = method.ty.fn_sig();
-
-                let sig = cx.tcx
-                    .no_late_bound_regions(&sig)
-                    .unwrap_or_else(|| span_bug!(expr.span, "method call has late-bound regions"));
-
                 assert_eq!(sig.inputs().len(), 2);
 
                 let tupled_args = Expr {
@@ -711,7 +705,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     Expr {
         temp_lifetime: temp_lifetime,
         temp_lifetime_was_shrunk: was_shrunk,
-        ty: callee.ty,
+        ty: cx.tcx.type_of(callee.def_id).subst(cx.tcx, callee.substs),
         span: expr.span,
         kind: ExprKind::Literal {
             literal: Literal::Value {
@@ -1012,9 +1006,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
     // line up (this is because `*x` and `x[y]` represent lvalues):
 
     // to find the type &T of the content returned by the method;
-    let ref_ty = method.ty.fn_ret();
-    let ref_ty = cx.tcx.no_late_bound_regions(&ref_ty).unwrap();
-    // callees always have all late-bound regions fully instantiated,
+    let ref_ty = method.sig.output();
 
     // construct the complete expression `foo()` for the overloaded call,
     // which will yield the &T type
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index bbe34f37950..33f0b0282d1 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -619,7 +619,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // Type check the path.
         let pat_ty = self.instantiate_value_path(segments, opt_ty, def, pat.span, pat.id);
         // Replace constructor type with constructed type for tuple struct patterns.
-        let pat_ty = tcx.no_late_bound_regions(&pat_ty.fn_ret()).expect("expected fn type");
+        let pat_ty = pat_ty.fn_sig().output();
+        let pat_ty = tcx.no_late_bound_regions(&pat_ty).expect("expected fn type");
         self.demand_eqtype(pat.span, expected, pat_ty);
 
         // Type check subpatterns.
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index ce3dbf8c23e..5302ba00291 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -72,11 +72,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             }
 
             Some(CallStep::Overloaded(method_callee)) => {
-                self.confirm_overloaded_call(call_expr,
-                                             callee_expr,
-                                             arg_exprs,
-                                             expected,
-                                             method_callee)
+                self.confirm_overloaded_call(call_expr, arg_exprs, expected, method_callee)
             }
         };
 
@@ -152,7 +148,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     autoref,
                     unsize: false
                 },
-                target: *method.ty.fn_sig().input(0).skip_binder()
+                target: method.sig.inputs()[0]
             });
             CallStep::Overloaded(method)
         })
@@ -302,14 +298,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
     fn confirm_overloaded_call(&self,
                                call_expr: &hir::Expr,
-                               callee_expr: &'gcx hir::Expr,
                                arg_exprs: &'gcx [hir::Expr],
                                expected: Expectation<'tcx>,
                                method_callee: ty::MethodCallee<'tcx>)
                                -> Ty<'tcx> {
         let output_type = self.check_method_argument_types(call_expr.span,
-                                                           method_callee.ty,
-                                                           callee_expr,
+                                                           Ok(method_callee),
                                                            arg_exprs,
                                                            TupleArgumentsFlag::TupleArguments,
                                                            expected);
@@ -349,9 +343,7 @@ impl<'a, 'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> {
                 // can't because of the annoying need for a TypeTrace.
                 // (This always bites me, should find a way to
                 // refactor it.)
-                let method_sig = fcx.tcx
-                    .no_late_bound_regions(&method_callee.ty.fn_sig())
-                    .unwrap();
+                let method_sig = method_callee.sig;
 
                 debug!("attempt_resolution: method_callee={:?}", method_callee);
 
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index b6cd1dfc3d0..71bcff84cc2 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -88,19 +88,20 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         debug!("all_substs={:?}", all_substs);
 
         // Create the final signature for the method, replacing late-bound regions.
-        let (method_ty, method_predicates) = self.instantiate_method_sig(&pick, all_substs);
+        let (method_sig, method_predicates) = self.instantiate_method_sig(&pick, all_substs);
 
         // Unify the (adjusted) self type with what the method expects.
-        self.unify_receivers(self_ty, method_ty.fn_sig().input(0).skip_binder());
+        self.unify_receivers(self_ty, method_sig.inputs()[0]);
 
         // Add any trait/regions obligations specified on the method's type parameters.
+        let method_ty = self.tcx.mk_fn_ptr(ty::Binder(method_sig));
         self.add_obligations(method_ty, all_substs, &method_predicates);
 
         // Create the final `MethodCallee`.
         let callee = ty::MethodCallee {
             def_id: pick.item.def_id,
-            ty: method_ty,
             substs: all_substs,
+            sig: method_sig,
         };
 
         if let Some(hir::MutMutable) = pick.autoref {
@@ -351,7 +352,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
     fn instantiate_method_sig(&mut self,
                               pick: &probe::Pick<'tcx>,
                               all_substs: &'tcx Substs<'tcx>)
-                              -> (Ty<'tcx>, ty::InstantiatedPredicates<'tcx>) {
+                              -> (ty::FnSig<'tcx>, ty::InstantiatedPredicates<'tcx>) {
         debug!("instantiate_method_sig(pick={:?}, all_substs={:?})",
                pick,
                all_substs);
@@ -382,8 +383,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         let method_sig = self.instantiate_type_scheme(self.span, all_substs, &method_sig);
         debug!("type scheme substituted, method_sig={:?}", method_sig);
 
-        (self.tcx.mk_fn_def(def_id, all_substs, ty::Binder(method_sig)),
-         method_predicates)
+        (method_sig, method_predicates)
     }
 
     fn add_obligations(&mut self,
@@ -508,11 +508,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         }) = self.tables.borrow_mut().adjustments.get_mut(&base_expr.id) {
             debug!("convert_lvalue_op_to_mutable: converting autoref of {:?}", target);
 
-            // extract method return type, which will be &mut T;
-            // all LB regions should have been instantiated during method lookup
-            let method_sig = self.tcx.no_late_bound_regions(&method.ty.fn_sig()).unwrap();
-
-            *target = method_sig.inputs()[0];
+            *target = method.sig.inputs()[0];
             if let ty::TyRef(r_, mt) = target.sty {
                 *r = r_;
                 *mutbl = mt.mutbl;
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 7397c3d48e7..dd58fdbf073 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -267,7 +267,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         obligations.push(traits::Obligation::new(cause, ty::Predicate::WellFormed(method_ty)));
 
         let autoref = match (&original_method_ty.fn_sig().input(0).skip_binder().sty,
-                                      &method_ty.fn_sig().input(0).skip_binder().sty) {
+                             &fn_sig.inputs()[0].sty) {
             (&ty::TyRef(..), &ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ })) => {
                 // Trait method is fn(&self) or fn(&mut self), need an
                 // autoref. Pull the region etc out of the type of first argument.
@@ -281,8 +281,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
         let callee = ty::MethodCallee {
             def_id: def_id,
-            ty: method_ty,
             substs: trait_ref.substs,
+            sig: fn_sig,
         };
 
         debug!("callee = {:?}", callee);
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index ed37b55d030..f8020794b98 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2156,8 +2156,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     {
         // extract method return type, which will be &T;
         // all LB regions should have been instantiated during method lookup
-        let ret_ty = method.ty.fn_ret();
-        let ret_ty = self.tcx.no_late_bound_regions(&ret_ty).unwrap();
+        let ret_ty = method.sig.output();
 
         // method returns &T, but the type as visible to user is T, so deref
         ret_ty.builtin_deref(true, NoPreference).unwrap()
@@ -2246,7 +2245,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         autoref,
                         unsize
                     },
-                    target: *method.ty.fn_sig().input(0).skip_binder()
+                    target: method.sig.inputs()[0]
                 });
 
                 self.tables.borrow_mut().method_map.insert(expr.id, method);
@@ -2321,13 +2320,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
     fn check_method_argument_types(&self,
                                    sp: Span,
-                                   method_fn_ty: Ty<'tcx>,
-                                   callee_expr: &'gcx hir::Expr,
+                                   method: Result<ty::MethodCallee<'tcx>, ()>,
                                    args_no_rcvr: &'gcx [hir::Expr],
                                    tuple_arguments: TupleArgumentsFlag,
                                    expected: Expectation<'tcx>)
                                    -> Ty<'tcx> {
-        if method_fn_ty.references_error() {
+        let has_error = match method {
+            Ok(method) => {
+                method.substs.references_error() || method.sig.references_error()
+            }
+            Err(_) => true
+        };
+        if has_error {
             let err_inputs = self.err_args(args_no_rcvr.len());
 
             let err_inputs = match tuple_arguments {
@@ -2337,27 +2341,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 
             self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr,
                                       false, tuple_arguments, None);
-            self.tcx.types.err
-        } else {
-            match method_fn_ty.sty {
-                ty::TyFnDef(def_id, .., ref fty) => {
-                    // HACK(eddyb) ignore self in the definition (see above).
-                    let expected_arg_tys = self.expected_inputs_for_expected_output(
-                        sp,
-                        expected,
-                        fty.0.output(),
-                        &fty.0.inputs()[1..]
-                    );
-                    self.check_argument_types(sp, &fty.0.inputs()[1..], &expected_arg_tys[..],
-                                              args_no_rcvr, fty.0.variadic, tuple_arguments,
-                                              self.tcx.hir.span_if_local(def_id));
-                    fty.0.output()
-                }
-                _ => {
-                    span_bug!(callee_expr.span, "method without bare fn type");
-                }
-            }
+            return self.tcx.types.err;
         }
+
+        let method = method.unwrap();
+        // HACK(eddyb) ignore self in the definition (see above).
+        let expected_arg_tys = self.expected_inputs_for_expected_output(
+            sp,
+            expected,
+            method.sig.output(),
+            &method.sig.inputs()[1..]
+        );
+        self.check_argument_types(sp, &method.sig.inputs()[1..], &expected_arg_tys[..],
+                                  args_no_rcvr, method.sig.variadic, tuple_arguments,
+                                  self.tcx.hir.span_if_local(method.def_id));
+        method.sig.output()
     }
 
     /// Generic function that factors out common logic from function calls,
@@ -2782,15 +2780,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         let expr_t = self.structurally_resolved_type(expr.span, rcvr_t);
 
         let tps = tps.iter().map(|ast_ty| self.to_ty(&ast_ty)).collect::<Vec<_>>();
-        let fn_ty = match self.lookup_method(method_name.span,
-                                             method_name.node,
-                                             expr_t,
-                                             tps,
-                                             expr,
-                                             rcvr) {
+        let method = match self.lookup_method(method_name.span,
+                                              method_name.node,
+                                              expr_t,
+                                              tps,
+                                              expr,
+                                              rcvr) {
             Ok(method) => {
                 self.tables.borrow_mut().method_map.insert(expr.id, method);
-                method.ty
+                Ok(method)
             }
             Err(error) => {
                 if method_name.node != keywords::Invalid.name() {
@@ -2801,18 +2799,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                              error,
                                              Some(args));
                 }
-                self.write_error(expr.id);
-                self.tcx.types.err
+                Err(())
             }
         };
 
         // Call the generic checker.
-        let ret_ty = self.check_method_argument_types(method_name.span, fn_ty,
-                                                      expr, &args[1..],
-                                                      DontTupleArguments,
-                                                      expected);
-
-        ret_ty
+        self.check_method_argument_types(method_name.span, method,
+                                         &args[1..],
+                                         DontTupleArguments,
+                                         expected)
     }
 
     fn check_return_expr(&self, return_expr: &'gcx hir::Expr) {
@@ -3465,7 +3460,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                     autoref,
                                     unsize: false
                                 },
-                                target: *method.ty.fn_sig().input(0).skip_binder()
+                                target: method.sig.inputs()[0]
                             });
                             oprnd_t = self.make_overloaded_lvalue_return_type(method).ty;
                             self.tables.borrow_mut().method_map.insert(expr.id, method);
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 0ac568f2090..267b2b00978 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -419,14 +419,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         autoref,
                         unsize: false
                     },
-                    target: *method.ty.fn_sig().input(0).skip_binder()
+                    target: method.sig.inputs()[0]
                 });
                 self.tables.borrow_mut().method_map.insert(expr.id, method);
 
-                // extract return type for method; all late bound regions
-                // should have been instantiated by now
-                let ret_ty = method.ty.fn_ret();
-                Ok(self.tcx.no_late_bound_regions(&ret_ty).unwrap())
+                Ok(method.sig.output())
             }
             None => {
                 Err(())
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 6cb9375c5de..9b609cac2fc 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -538,8 +538,10 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
             };
 
             self.substs_wf_in_scope(origin, &callee.substs, expr.span, expr_region);
-            self.type_must_outlive(infer::ExprTypeIsNotInScope(callee.ty, expr.span),
-                                   callee.ty, expr_region);
+            for &ty in callee.sig.inputs() {
+                self.type_must_outlive(infer::ExprTypeIsNotInScope(ty, expr.span),
+                                       ty, expr_region);
+            }
         }
 
         // Check any autoderefs or autorefs that appear.
@@ -692,9 +694,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> {
                     Some(method) => {
                         self.constrain_call(expr, Some(&base),
                                             None::<hir::Expr>.iter(), true);
-                        // late-bound regions in overloaded method calls are instantiated
-                        let fn_ret = self.tcx.no_late_bound_regions(&method.ty.fn_ret());
-                        fn_ret.unwrap()
+                        method.sig.output()
                     }
                     None => self.resolve_node_type(base.id)
                 };
@@ -933,17 +933,14 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
 
                 // Treat overloaded autoderefs as if an AutoBorrow adjustment
                 // was applied on the base type, as that is always the case.
-                let fn_sig = method.ty.fn_sig();
-                let fn_sig = // late-bound regions should have been instantiated
-                    self.tcx.no_late_bound_regions(&fn_sig).unwrap();
-                let self_ty = fn_sig.inputs()[0];
+                let self_ty = method.sig.inputs()[0];
                 let (m, r) = match self_ty.sty {
                     ty::TyRef(r, ref m) => (m.mutbl, r),
                     _ => {
                         span_bug!(
                             deref_expr.span,
                             "bad overloaded deref type {:?}",
-                            method.ty)
+                            method.sig)
                     }
                 };
 
@@ -958,7 +955,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                 self.type_must_outlive(infer::CallRcvr(deref_expr.span),
                                        self_ty, r_deref_expr);
                 self.type_must_outlive(infer::CallReturn(deref_expr.span),
-                                       fn_sig.output(), r_deref_expr);
+                                       method.sig.output(), r_deref_expr);
             }
 
             {
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 5fa5bb8f7af..455a8e1cf16 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -340,8 +340,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
                                 overloaded.map(|method| {
                                     MethodCallee {
                                         def_id: method.def_id,
-                                        ty: self.resolve(&method.ty, &span),
                                         substs: self.resolve(&method.substs, &span),
+                                        sig: self.resolve(&method.sig, &span),
                                     }
                                 })
                             }).collect(),
@@ -368,8 +368,8 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
             Some(method) => {
                 Some(MethodCallee {
                     def_id: method.def_id,
-                    ty: self.resolve(&method.ty, &method_span),
                     substs: self.resolve(&method.substs, &method_span),
+                    sig: self.resolve(&method.sig, &method_span),
                 })
             }
             None => None