Skip to content

Commit 0191b49

Browse files
author
Jakub Bukaj
committed
rollup merge of #18940: nikomatsakis/issue-18899
Ensure that the type parameters passed to methods outlive the call expression. Fixes #18899. This is yet another case of forgotten to consistently enforce the constraints in every instance where they apply. Might be nice to try and refactor to make this whole thing more DRY, but for now here's a targeted fix. r? @pcwalton
2 parents cbdaf2e + 2477bc4 commit 0191b49

File tree

6 files changed

+71
-31
lines changed

6 files changed

+71
-31
lines changed

src/libcollections/bit.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,10 +1678,10 @@ impl<'a> Iterator<uint> for TwoBitPositions<'a> {
16781678
mod tests {
16791679
use std::prelude::*;
16801680
use std::iter::range_step;
1681-
use std::u32;
16821681
use std::rand;
16831682
use std::rand::Rng;
1684-
use test::Bencher;
1683+
use std::u32;
1684+
use test::{Bencher, black_box};
16851685

16861686
use super::{Bitv, BitvSet, from_fn, from_bytes};
16871687
use bitv;
@@ -2676,8 +2676,8 @@ mod tests {
26762676
for _ in range(0u, 100) {
26772677
bitv |= 1 << ((r.next_u32() as uint) % u32::BITS);
26782678
}
2679-
&bitv
2680-
})
2679+
black_box(&bitv)
2680+
});
26812681
}
26822682

26832683
#[bench]
@@ -2688,8 +2688,8 @@ mod tests {
26882688
for _ in range(0u, 100) {
26892689
bitv.set((r.next_u32() as uint) % BENCH_BITS, true);
26902690
}
2691-
&bitv
2692-
})
2691+
black_box(&bitv)
2692+
});
26932693
}
26942694

26952695
#[bench]
@@ -2700,8 +2700,8 @@ mod tests {
27002700
for _ in range(0u, 100) {
27012701
bitv.set((r.next_u32() as uint) % BENCH_BITS, r.gen());
27022702
}
2703-
&bitv
2704-
})
2703+
black_box(&bitv);
2704+
});
27052705
}
27062706

27072707
#[bench]
@@ -2712,8 +2712,8 @@ mod tests {
27122712
for _ in range(0u, 100) {
27132713
bitv.set((r.next_u32() as uint) % u32::BITS, true);
27142714
}
2715-
&bitv
2716-
})
2715+
black_box(&bitv);
2716+
});
27172717
}
27182718

27192719
#[bench]
@@ -2724,8 +2724,8 @@ mod tests {
27242724
for _ in range(0u, 100) {
27252725
bitv.insert((r.next_u32() as uint) % u32::BITS);
27262726
}
2727-
&bitv
2728-
})
2727+
black_box(&bitv);
2728+
});
27292729
}
27302730

27312731
#[bench]
@@ -2736,8 +2736,8 @@ mod tests {
27362736
for _ in range(0u, 100) {
27372737
bitv.insert((r.next_u32() as uint) % BENCH_BITS);
27382738
}
2739-
&bitv
2740-
})
2739+
black_box(&bitv);
2740+
});
27412741
}
27422742

27432743
#[bench]

src/libcollections/slice.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,7 +2084,7 @@ mod bench {
20842084
use std::rand::{weak_rng, Rng};
20852085
use std::mem;
20862086
use std::ptr;
2087-
use test::Bencher;
2087+
use test::{Bencher, black_box};
20882088

20892089
use vec::Vec;
20902090

@@ -2140,8 +2140,8 @@ mod bench {
21402140
let mut vec: Vec<uint> = vec![];
21412141
b.iter(|| {
21422142
vec.push(0);
2143-
&vec
2144-
})
2143+
black_box(&vec);
2144+
});
21452145
}
21462146

21472147
#[bench]

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)