Ensure that the type parameters passed to methods outlive the call expression. Fixes #18899.
This commit is contained in:
parent
cf7df1e638
commit
0b6ec70197
@ -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<Ty<'tcx>>)
|
||||
@ -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);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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<Ty<'tcx>>,
|
||||
call_expr_id: ast::NodeId,
|
||||
call_expr: &ast::Expr,
|
||||
self_expr: &ast::Expr)
|
||||
-> Result<MethodCallee<'tcx>, 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>,
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
26
src/test/compile-fail/regions-escape-method.rs
Normal file
26
src/test/compile-fail/regions-escape-method.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<B>(&self, _: |&i32| -> B) {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let s = S;
|
||||
s.f(|p| p) //~ ERROR cannot infer
|
||||
}
|
Loading…
Reference in New Issue
Block a user