Skip to content

Commit 6716746

Browse files
committed
Link regions in ref bindings from fn arguments.
1 parent 8a210af commit 6716746

File tree

3 files changed

+49
-6
lines changed

3 files changed

+49
-6
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
393393
decl, id, body, &inh);
394394

395395
vtable::select_all_fcx_obligations_or_error(&fcx);
396-
regionck::regionck_fn(&fcx, id, body);
396+
regionck::regionck_fn(&fcx, id, decl, body);
397397
fcx.default_diverging_type_variables_to_nil();
398398
writeback::resolve_type_vars_in_fn(&fcx, decl, body);
399399
}

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

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,11 @@ pub fn regionck_item(fcx: &FnCtxt, item: &ast::Item) {
159159
fcx.infcx().resolve_regions_and_report_errors();
160160
}
161161

162-
pub fn regionck_fn(fcx: &FnCtxt, id: ast::NodeId, blk: &ast::Block) {
162+
pub fn regionck_fn(fcx: &FnCtxt, id: ast::NodeId, decl: &ast::FnDecl, blk: &ast::Block) {
163163
let mut rcx = Rcx::new(fcx, blk.id);
164164
if fcx.err_count_since_creation() == 0 {
165165
// regionck assumes typeck succeeded
166-
rcx.visit_fn_body(id, blk);
166+
rcx.visit_fn_body(id, decl, blk);
167167
}
168168

169169
// Region checking a fn can introduce new trait obligations,
@@ -329,6 +329,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
329329

330330
fn visit_fn_body(&mut self,
331331
id: ast::NodeId,
332+
fn_decl: &ast::FnDecl,
332333
body: &ast::Block)
333334
{
334335
// When we enter a function, we can derive
@@ -344,6 +345,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
344345

345346
let len = self.region_param_pairs.len();
346347
self.relate_free_regions(fn_sig.as_slice(), body.id);
348+
link_fn_args(self, CodeExtent::from_node_id(body.id), fn_decl.inputs.as_slice());
347349
self.visit_block(body);
348350
self.visit_region_obligations(body.id);
349351
self.region_param_pairs.truncate(len);
@@ -481,9 +483,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Rcx<'a, 'tcx> {
481483
// hierarchy, and in particular the relationships between free
482484
// regions, until regionck, as described in #3238.
483485

484-
fn visit_fn(&mut self, _fk: visit::FnKind<'v>, _fd: &'v ast::FnDecl,
486+
fn visit_fn(&mut self, _fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
485487
b: &'v ast::Block, _s: Span, id: ast::NodeId) {
486-
self.visit_fn_body(id, b)
488+
self.visit_fn_body(id, fd, b)
487489
}
488490

489491
fn visit_item(&mut self, i: &ast::Item) { visit_item(self, i); }
@@ -1289,7 +1291,6 @@ fn link_local(rcx: &Rcx, local: &ast::Local) {
12891291
/// then ensures that the lifetime of the resulting pointer is
12901292
/// linked to the lifetime of its guarantor (if any).
12911293
fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
1292-
12931294
debug!("regionck::for_match()");
12941295
let mc = mc::MemCategorizationContext::new(rcx);
12951296
let discr_cmt = ignore_err!(mc.cat_expr(discr));
@@ -1301,12 +1302,32 @@ fn link_match(rcx: &Rcx, discr: &ast::Expr, arms: &[ast::Arm]) {
13011302
}
13021303
}
13031304

1305+
/// Computes the guarantors for any ref bindings in a match and
1306+
/// then ensures that the lifetime of the resulting pointer is
1307+
/// linked to the lifetime of its guarantor (if any).
1308+
fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[ast::Arg]) {
1309+
debug!("regionck::link_fn_args(body_scope={})", body_scope);
1310+
let mc = mc::MemCategorizationContext::new(rcx);
1311+
for arg in args.iter() {
1312+
let arg_ty = rcx.fcx.node_ty(arg.id);
1313+
let re_scope = ty::ReScope(body_scope);
1314+
let arg_cmt = mc.cat_rvalue(arg.id, arg.ty.span, re_scope, arg_ty);
1315+
debug!("arg_ty={} arg_cmt={}",
1316+
arg_ty.repr(rcx.tcx()),
1317+
arg_cmt.repr(rcx.tcx()));
1318+
link_pattern(rcx, mc, arg_cmt, &*arg.pat);
1319+
}
1320+
}
1321+
13041322
/// Link lifetimes of any ref bindings in `root_pat` to the pointers found in the discriminant, if
13051323
/// needed.
13061324
fn link_pattern<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
13071325
mc: mc::MemCategorizationContext<Rcx<'a, 'tcx>>,
13081326
discr_cmt: mc::cmt<'tcx>,
13091327
root_pat: &ast::Pat) {
1328+
debug!("link_pattern(discr_cmt={}, root_pat={})",
1329+
discr_cmt.repr(rcx.tcx()),
1330+
root_pat.repr(rcx.tcx()));
13101331
let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
13111332
match sub_pat.node {
13121333
// `ref x` pattern
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2014 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 that region inference correctly links up the regions when a
12+
// `ref` borrow occurs inside a fn argument.
13+
14+
#![allow(dead_code)]
15+
16+
fn with<'a>(_: |&'a Vec<int>| -> &'a Vec<int>) { }
17+
18+
fn foo() {
19+
with(|&ref ints| ints);
20+
}
21+
22+
fn main() { }

0 commit comments

Comments
 (0)