diff --git a/src/librustc/middle/typeck/check/method/confirm.rs b/src/librustc/middle/typeck/check/method/confirm.rs index af8ef09d2a0..c53befcc10d 100644 --- a/src/librustc/middle/typeck/check/method/confirm.rs +++ b/src/librustc/middle/typeck/check/method/confirm.rs @@ -31,6 +31,7 @@ struct ConfirmContext<'a, 'tcx:'a> { fcx: &'a FnCtxt<'a, 'tcx>, span: Span, self_expr: &'a ast::Expr, + call_expr: &'a ast::Expr, } struct InstantiatedMethodSig<'tcx> { @@ -56,6 +57,7 @@ struct InstantiatedMethodSig<'tcx> { pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, span: Span, self_expr: &ast::Expr, + call_expr: &ast::Expr, unadjusted_self_ty: Ty<'tcx>, pick: probe::Pick<'tcx>, supplied_method_types: Vec>) @@ -66,17 +68,18 @@ pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, pick.repr(fcx.tcx()), supplied_method_types.repr(fcx.tcx())); - let mut confirm_cx = ConfirmContext::new(fcx, span, self_expr); + let mut confirm_cx = ConfirmContext::new(fcx, span, self_expr, call_expr); confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types) } impl<'a,'tcx> ConfirmContext<'a,'tcx> { fn new(fcx: &'a FnCtxt<'a, 'tcx>, span: Span, - self_expr: &'a ast::Expr) + self_expr: &'a ast::Expr, + call_expr: &'a ast::Expr) -> ConfirmContext<'a, 'tcx> { - ConfirmContext { fcx: fcx, span: span, self_expr: self_expr } + ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr } } fn confirm(&mut self, @@ -469,6 +472,10 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { traits::ObligationCause::misc(self.span), method_bounds_substs, method_bounds); + + self.fcx.add_default_region_param_bounds( + method_bounds_substs, + self.call_expr); } /////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc/middle/typeck/check/method/mod.rs b/src/librustc/middle/typeck/check/method/mod.rs index 411948ed6b4..0f4152644ad 100644 --- a/src/librustc/middle/typeck/check/method/mod.rs +++ b/src/librustc/middle/typeck/check/method/mod.rs @@ -79,7 +79,7 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_name: ast::Name, self_ty: Ty<'tcx>, supplied_method_types: Vec>, - call_expr_id: ast::NodeId, + call_expr: &ast::Expr, self_expr: &ast::Expr) -> Result, MethodError> { @@ -100,14 +100,14 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, * - `self_expr`: the self expression (`foo`) */ - debug!("lookup(method_name={}, self_ty={}, call_expr_id={}, self_expr={})", + debug!("lookup(method_name={}, self_ty={}, call_expr={}, self_expr={})", method_name.repr(fcx.tcx()), self_ty.repr(fcx.tcx()), - call_expr_id, + call_expr.repr(fcx.tcx()), self_expr.repr(fcx.tcx())); - let pick = try!(probe::probe(fcx, span, method_name, self_ty, call_expr_id)); - Ok(confirm::confirm(fcx, span, self_expr, self_ty, pick, supplied_method_types)) + let pick = try!(probe::probe(fcx, span, method_name, self_ty, call_expr.id)); + Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types)) } pub fn lookup_in_trait<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 543eb44697c..266b105efc2 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2050,6 +2050,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + pub fn add_default_region_param_bounds(&self, + substs: &Substs<'tcx>, + expr: &ast::Expr) + { + for &ty in substs.types.iter() { + let default_bound = ty::ReScope(expr.id); + let origin = infer::RelateDefaultParamBound(expr.span, ty); + self.register_region_obligation(origin, ty, default_bound); + } + } + pub fn add_obligations_for_parameters(&self, cause: traits::ObligationCause<'tcx>, substs: &Substs<'tcx>, @@ -3180,7 +3191,7 @@ fn check_expr_with_unifier<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, method_name.node.name, expr_t, tps, - expr.id, + expr, rcvr) { Ok(method) => { let method_ty = method.ty; @@ -4693,11 +4704,7 @@ fn constrain_path_type_parameters(fcx: &FnCtxt, expr: &ast::Expr) { fcx.opt_node_ty_substs(expr.id, |item_substs| { - for &ty in item_substs.substs.types.iter() { - let default_bound = ty::ReScope(expr.id); - let origin = infer::RelateDefaultParamBound(expr.span, ty); - fcx.register_region_obligation(origin, ty, default_bound); - } + fcx.add_default_region_param_bounds(&item_substs.substs, expr); }); } diff --git a/src/test/compile-fail/regions-escape-method.rs b/src/test/compile-fail/regions-escape-method.rs new file mode 100644 index 00000000000..f92c264784a --- /dev/null +++ b/src/test/compile-fail/regions-escape-method.rs @@ -0,0 +1,26 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test a method call where the parameter `B` would (illegally) be +// inferred to a region bound in the method argument. If this program +// were accepted, then the closure passed to `s.f` could escape its +// argument. + +struct S; + +impl S { + fn f(&self, _: |&i32| -> B) { + } +} + +fn main() { + let s = S; + s.f(|p| p) //~ ERROR cannot infer +}