Skip to content

Commit 0b6ec70

Browse files
committed
Ensure that the type parameters passed to methods outlive the call expression. Fixes #18899.
1 parent cf7df1e commit 0b6ec70

File tree

4 files changed

+54
-14
lines changed

4 files changed

+54
-14
lines changed

src/librustc/middle/typeck/check/method/confirm.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ struct ConfirmContext<'a, 'tcx:'a> {
3131
fcx: &'a FnCtxt<'a, 'tcx>,
3232
span: Span,
3333
self_expr: &'a ast::Expr,
34+
call_expr: &'a ast::Expr,
3435
}
3536

3637
struct InstantiatedMethodSig<'tcx> {
@@ -56,6 +57,7 @@ struct InstantiatedMethodSig<'tcx> {
5657
pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
5758
span: Span,
5859
self_expr: &ast::Expr,
60+
call_expr: &ast::Expr,
5961
unadjusted_self_ty: Ty<'tcx>,
6062
pick: probe::Pick<'tcx>,
6163
supplied_method_types: Vec<Ty<'tcx>>)
@@ -66,17 +68,18 @@ pub fn confirm<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
6668
pick.repr(fcx.tcx()),
6769
supplied_method_types.repr(fcx.tcx()));
6870

69-
let mut confirm_cx = ConfirmContext::new(fcx, span, self_expr);
71+
let mut confirm_cx = ConfirmContext::new(fcx, span, self_expr, call_expr);
7072
confirm_cx.confirm(unadjusted_self_ty, pick, supplied_method_types)
7173
}
7274

7375
impl<'a,'tcx> ConfirmContext<'a,'tcx> {
7476
fn new(fcx: &'a FnCtxt<'a, 'tcx>,
7577
span: Span,
76-
self_expr: &'a ast::Expr)
78+
self_expr: &'a ast::Expr,
79+
call_expr: &'a ast::Expr)
7780
-> ConfirmContext<'a, 'tcx>
7881
{
79-
ConfirmContext { fcx: fcx, span: span, self_expr: self_expr }
82+
ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr }
8083
}
8184

8285
fn confirm(&mut self,
@@ -469,6 +472,10 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
469472
traits::ObligationCause::misc(self.span),
470473
method_bounds_substs,
471474
method_bounds);
475+
476+
self.fcx.add_default_region_param_bounds(
477+
method_bounds_substs,
478+
self.call_expr);
472479
}
473480

474481
///////////////////////////////////////////////////////////////////////////

src/librustc/middle/typeck/check/method/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
7979
method_name: ast::Name,
8080
self_ty: Ty<'tcx>,
8181
supplied_method_types: Vec<Ty<'tcx>>,
82-
call_expr_id: ast::NodeId,
82+
call_expr: &ast::Expr,
8383
self_expr: &ast::Expr)
8484
-> Result<MethodCallee<'tcx>, MethodError>
8585
{
@@ -100,14 +100,14 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
100100
* - `self_expr`: the self expression (`foo`)
101101
*/
102102

103-
debug!("lookup(method_name={}, self_ty={}, call_expr_id={}, self_expr={})",
103+
debug!("lookup(method_name={}, self_ty={}, call_expr={}, self_expr={})",
104104
method_name.repr(fcx.tcx()),
105105
self_ty.repr(fcx.tcx()),
106-
call_expr_id,
106+
call_expr.repr(fcx.tcx()),
107107
self_expr.repr(fcx.tcx()));
108108

109-
let pick = try!(probe::probe(fcx, span, method_name, self_ty, call_expr_id));
110-
Ok(confirm::confirm(fcx, span, self_expr, self_ty, pick, supplied_method_types))
109+
let pick = try!(probe::probe(fcx, span, method_name, self_ty, call_expr.id));
110+
Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types))
111111
}
112112

113113
pub fn lookup_in_trait<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,

src/librustc/middle/typeck/check/mod.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,6 +2050,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
20502050
}
20512051
}
20522052

2053+
pub fn add_default_region_param_bounds(&self,
2054+
substs: &Substs<'tcx>,
2055+
expr: &ast::Expr)
2056+
{
2057+
for &ty in substs.types.iter() {
2058+
let default_bound = ty::ReScope(expr.id);
2059+
let origin = infer::RelateDefaultParamBound(expr.span, ty);
2060+
self.register_region_obligation(origin, ty, default_bound);
2061+
}
2062+
}
2063+
20532064
pub fn add_obligations_for_parameters(&self,
20542065
cause: traits::ObligationCause<'tcx>,
20552066
substs: &Substs<'tcx>,
@@ -3180,7 +3191,7 @@ fn check_expr_with_unifier<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
31803191
method_name.node.name,
31813192
expr_t,
31823193
tps,
3183-
expr.id,
3194+
expr,
31843195
rcvr) {
31853196
Ok(method) => {
31863197
let method_ty = method.ty;
@@ -4693,11 +4704,7 @@ fn constrain_path_type_parameters(fcx: &FnCtxt,
46934704
expr: &ast::Expr)
46944705
{
46954706
fcx.opt_node_ty_substs(expr.id, |item_substs| {
4696-
for &ty in item_substs.substs.types.iter() {
4697-
let default_bound = ty::ReScope(expr.id);
4698-
let origin = infer::RelateDefaultParamBound(expr.span, ty);
4699-
fcx.register_region_obligation(origin, ty, default_bound);
4700-
}
4707+
fcx.add_default_region_param_bounds(&item_substs.substs, expr);
47014708
});
47024709
}
47034710

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test a method call where the parameter `B` would (illegally) be
12+
// inferred to a region bound in the method argument. If this program
13+
// were accepted, then the closure passed to `s.f` could escape its
14+
// argument.
15+
16+
struct S;
17+
18+
impl S {
19+
fn f<B>(&self, _: |&i32| -> B) {
20+
}
21+
}
22+
23+
fn main() {
24+
let s = S;
25+
s.f(|p| p) //~ ERROR cannot infer
26+
}

0 commit comments

Comments
 (0)