Skip to content

Commit 243c5a5

Browse files
committed
fix handling of CallScopeData
This fixes the tests for issue rust-lang#29793
1 parent cbcae7f commit 243c5a5

File tree

4 files changed

+53
-6
lines changed

4 files changed

+53
-6
lines changed

Diff for: src/librustc_mir/borrow_check/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
use rustc::hir;
1414
use rustc::hir::def_id::DefId;
15+
use rustc::hir::map::definitions::DefPathData;
1516
use rustc::infer::InferCtxt;
1617
use rustc::ty::{self, ParamEnv, TyCtxt};
1718
use rustc::ty::maps::Providers;
@@ -131,6 +132,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
131132
move_data: move_data,
132133
param_env: param_env,
133134
};
135+
let body_id = match tcx.def_key(def_id).disambiguated_data.data {
136+
DefPathData::StructCtor |
137+
DefPathData::EnumVariant(_) => None,
138+
_ => Some(tcx.hir.body_owned_by(id))
139+
};
140+
134141
let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
135142
let mut flow_inits = FlowInProgress::new(do_dataflow(
136143
tcx,
@@ -206,7 +213,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
206213
id,
207214
&attributes,
208215
&dead_unwinds,
209-
Borrows::new(tcx, mir, opt_regioncx),
216+
Borrows::new(tcx, mir, opt_regioncx, def_id, body_id),
210217
|bd, i| bd.location(i),
211218
));
212219

Diff for: src/librustc_mir/build/cfg.rs

+11
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ impl<'tcx> CFG<'tcx> {
5151
source_info: SourceInfo,
5252
region_scope: region::Scope) {
5353
if tcx.sess.emit_end_regions() {
54+
if let region::ScopeData::CallSite(_) = region_scope.data() {
55+
// The CallSite scope (aka the root scope) is sort of weird, in that it is
56+
// supposed to "separate" the "interior" and "exterior" of a closure. Being
57+
// that, it is not really a part of the region hierarchy, but for some
58+
// reason it *is* considered a part of it.
59+
//
60+
// It should die a hopefully painful death with NLL, so let's leave this hack
61+
// for now so that nobody can complain about soundness.
62+
return
63+
}
64+
5465
self.push(block, Statement {
5566
source_info,
5667
kind: StatementKind::EndRegion(region_scope),

Diff for: src/librustc_mir/dataflow/impls/borrows.rs

+26-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use rustc::hir;
12+
use rustc::hir::def_id::DefId;
13+
use rustc::middle::region;
1114
use rustc::mir::{self, Location, Mir};
1215
use rustc::mir::visit::Visitor;
1316
use rustc::ty::{self, Region, TyCtxt};
@@ -27,13 +30,16 @@ use borrow_check::nll::ToRegionVid;
2730
use syntax_pos::Span;
2831

2932
use std::fmt;
33+
use std::rc::Rc;
3034

3135
// `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be
3236
// uniquely identified in the MIR by the `Location` of the assigment
3337
// statement in which it appears on the right hand side.
3438
pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
3539
tcx: TyCtxt<'a, 'gcx, 'tcx>,
3640
mir: &'a Mir<'tcx>,
41+
scope_tree: Rc<region::ScopeTree>,
42+
root_scope: Option<region::Scope>,
3743
borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>,
3844
location_map: FxHashMap<Location, BorrowIndex>,
3945
region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
@@ -69,8 +75,14 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
6975
impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
7076
pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
7177
mir: &'a Mir<'tcx>,
72-
nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>)
78+
nonlexical_regioncx: Option<RegionInferenceContext<'tcx>>,
79+
def_id: DefId,
80+
body_id: Option<hir::BodyId>)
7381
-> Self {
82+
let scope_tree = tcx.region_scope_tree(def_id);
83+
let root_scope = body_id.map(|body_id| {
84+
region::Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id)
85+
});
7486
let mut visitor = GatherBorrows {
7587
tcx,
7688
mir,
@@ -83,6 +95,8 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
8395
return Borrows { tcx: tcx,
8496
mir: mir,
8597
borrows: visitor.idx_vec,
98+
scope_tree,
99+
root_scope,
86100
location_map: visitor.location_map,
87101
region_map: visitor.region_map,
88102
region_span_map: visitor.region_span_map,
@@ -253,8 +267,17 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
253267
// like unwind paths, we do not always emit `EndRegion` statements, so we
254268
// add some kills here as a "backup" and to avoid spurious error messages.
255269
for (borrow_index, borrow_data) in self.borrows.iter_enumerated() {
256-
if let ReScope(..) = borrow_data.region {
257-
sets.kill(&borrow_index);
270+
if let ReScope(scope) = borrow_data.region {
271+
// Check that the scope is not actually a scope from a function that is
272+
// a parent of our closure. Note that the CallSite scope itself is
273+
// *outside* of the closure, for some weird reason.
274+
if let Some(root_scope) = self.root_scope {
275+
if *scope != root_scope &&
276+
self.scope_tree.is_subscope_of(*scope, root_scope)
277+
{
278+
sets.kill(&borrow_index);
279+
}
280+
}
258281
}
259282
}
260283
}

Diff for: src/test/compile-fail/region-borrow-params-issue-29793-big.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
// behavior (because the improperly accepted closure was actually
1717
// able to be invoked).
1818

19+
// ignore-tidy-linelength
20+
// revisions: ast mir
21+
//[mir]compile-flags: -Z borrowck=mir
22+
1923
struct WrapA<F>(Option<F>);
2024

2125
impl<F> WrapA<F> {
@@ -75,9 +79,11 @@ impl<F, T> WrapA<F>
7579
fn main() {
7680
let mut w = WrapA::new().set(|x: usize, y: usize| {
7781
WrapB::new().set(|t: bool| if t { x } else { y }) // (separate errors for `x` vs `y`)
78-
//~^ ERROR `x` does not live long enough
79-
//~| ERROR `y` does not live long enough
82+
//[ast]~^ ERROR `x` does not live long enough
83+
//[ast]~| ERROR `y` does not live long enough
8084
});
85+
//[mir]~^ ERROR borrowed value does not live long enough
86+
//[mir]~| ERROR borrowed value does not live long enough
8187

8288
w.handle(); // This works
8389
// w.handle_ref(); // This doesn't

0 commit comments

Comments
 (0)