Skip to content

Commit a276e75

Browse files
committed
introduce "call-site-scope" as the outermost scope
also, when exiting a scope, assign the final goto terminator with the target scope's id
1 parent 1c0fa34 commit a276e75

File tree

4 files changed

+84
-57
lines changed

4 files changed

+84
-57
lines changed

Diff for: src/librustc_mir/build/expr/into.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
261261
block
262262
}
263263
};
264-
let extent = this.extent_of_outermost_scope();
264+
let extent = this.extent_of_return_scope();
265265
this.exit_scope(expr_span, extent, block, END_BLOCK);
266266
this.cfg.start_new_block().unit()
267267
}

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

+63-46
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use hair::cx::Cx;
12-
use rustc::middle::region::CodeExtent;
12+
use rustc::middle::region::{CodeExtent, CodeExtentData};
1313
use rustc::middle::ty::{FnOutput, Ty};
1414
use rustc::mir::repr::*;
1515
use rustc_data_structures::fnv::FnvHashMap;
@@ -153,12 +153,14 @@ macro_rules! unpack {
153153
154154
pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
155155
span: Span,
156+
fn_id: ast::NodeId,
157+
body_id: ast::NodeId,
156158
implicit_arguments: Vec<Ty<'tcx>>,
157159
explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
158-
argument_extent: CodeExtent,
159160
return_ty: FnOutput<'tcx>,
160161
ast_block: &'tcx hir::Block)
161162
-> (Mir<'tcx>, ScopeAuxiliaryVec) {
163+
let tcx = hir.tcx();
162164
let cfg = CFG { basic_blocks: vec![] };
163165

164166
let mut builder = Builder {
@@ -178,27 +180,41 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
178180
assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
179181
assert_eq!(builder.cfg.start_new_block(), END_BLOCK);
180182

181-
let mut block = START_BLOCK;
182-
let (arg_decls, arg_scope_id) =
183-
unpack!(block = builder.args_and_body(block,
184-
implicit_arguments,
185-
explicit_arguments,
186-
argument_extent,
187-
ast_block));
188183

189-
builder.cfg.terminate(block, arg_scope_id, span,
190-
TerminatorKind::Goto { target: END_BLOCK });
191-
builder.cfg.terminate(END_BLOCK, arg_scope_id, span,
192-
TerminatorKind::Return);
184+
let mut arg_decls = None; // assigned to `Some` in closures below
185+
let call_site_extent =
186+
tcx.region_maps.lookup_code_extent(
187+
CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id });
188+
let _ = builder.in_scope(call_site_extent, START_BLOCK, |builder, call_site_scope_id| {
189+
let mut block = START_BLOCK;
190+
let arg_extent =
191+
tcx.region_maps.lookup_code_extent(
192+
CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id });
193+
unpack!(block = builder.in_scope(arg_extent, block, |builder, arg_scope_id| {
194+
arg_decls = Some(unpack!(block = builder.args_and_body(block,
195+
implicit_arguments,
196+
explicit_arguments,
197+
arg_scope_id,
198+
ast_block)));
199+
block.unit()
200+
}));
201+
202+
builder.cfg.terminate(block, call_site_scope_id, span,
203+
TerminatorKind::Goto { target: END_BLOCK });
204+
builder.cfg.terminate(END_BLOCK, call_site_scope_id, span,
205+
TerminatorKind::Return);
206+
207+
END_BLOCK.unit()
208+
});
193209

194210
assert!(
195211
builder.cfg.basic_blocks
196212
.iter()
197213
.enumerate()
198214
.all(|(index, block)| {
199215
if block.terminator.is_none() {
200-
panic!("no terminator on block {:?} in {:?}",
201-
index, argument_extent)
216+
panic!("no terminator on block {:?} in fn {:?}",
217+
index, fn_id)
202218
}
203219
true
204220
}));
@@ -208,7 +224,7 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
208224
basic_blocks: builder.cfg.basic_blocks,
209225
scopes: builder.scope_datas,
210226
var_decls: builder.var_decls,
211-
arg_decls: arg_decls,
227+
arg_decls: arg_decls.take().expect("args never built?"),
212228
temp_decls: builder.temp_decls,
213229
return_ty: return_ty,
214230
span: span
@@ -222,39 +238,40 @@ impl<'a,'tcx> Builder<'a,'tcx> {
222238
mut block: BasicBlock,
223239
implicit_arguments: Vec<Ty<'tcx>>,
224240
explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
225-
argument_extent: CodeExtent,
241+
argument_scope_id: ScopeId,
226242
ast_block: &'tcx hir::Block)
227-
-> BlockAnd<(Vec<ArgDecl<'tcx>>, ScopeId)>
243+
-> BlockAnd<Vec<ArgDecl<'tcx>>>
228244
{
229-
self.in_scope(argument_extent, block, |this, argument_scope_id| {
230-
// to start, translate the argument patterns and collect the argument types.
231-
let implicits = implicit_arguments.into_iter().map(|ty| (ty, None));
232-
let explicits = explicit_arguments.into_iter().map(|(ty, pat)| (ty, Some(pat)));
245+
// to start, translate the argument patterns and collect the argument types.
246+
let implicits = implicit_arguments.into_iter().map(|ty| (ty, None));
247+
let explicits = explicit_arguments.into_iter().map(|(ty, pat)| (ty, Some(pat)));
233248
let arg_decls =
234-
implicits
235-
.chain(explicits)
236-
.enumerate()
237-
.map(|(index, (ty, pattern))| {
238-
let lvalue = Lvalue::Arg(index as u32);
239-
if let Some(pattern) = pattern {
240-
let pattern = this.hir.irrefutable_pat(pattern);
241-
unpack!(block = this.lvalue_into_pattern(block,
242-
argument_scope_id,
243-
pattern,
244-
&lvalue));
245-
}
246-
// Make sure we drop (parts of) the argument even when not matched on.
247-
this.schedule_drop(pattern.as_ref().map_or(ast_block.span, |pat| pat.span),
248-
argument_extent, &lvalue, ty);
249-
ArgDecl { ty: ty, spread: false }
250-
})
251-
.collect();
252-
253-
// start the first basic block and translate the body
254-
unpack!(block = this.ast_block(&Lvalue::ReturnPointer, block, ast_block));
255-
256-
block.and((arg_decls, argument_scope_id))
257-
})
249+
implicits
250+
.chain(explicits)
251+
.enumerate()
252+
.map(|(index, (ty, pattern))| {
253+
let lvalue = Lvalue::Arg(index as u32);
254+
if let Some(pattern) = pattern {
255+
let pattern = self.hir.irrefutable_pat(pattern);
256+
unpack!(block = self.lvalue_into_pattern(block,
257+
argument_scope_id,
258+
pattern,
259+
&lvalue));
260+
}
261+
262+
// Make sure we drop (parts of) the argument even when not matched on.
263+
let argument_extent = self.scope_auxiliary[argument_scope_id].extent;
264+
self.schedule_drop(pattern.as_ref().map_or(ast_block.span, |pat| pat.span),
265+
argument_extent, &lvalue, ty);
266+
267+
ArgDecl { ty: ty, spread: false }
268+
})
269+
.collect();
270+
271+
// start the first basic block and translate the body
272+
unpack!(block = self.ast_block(&Lvalue::ReturnPointer, block, ast_block));
273+
274+
block.and(arg_decls)
258275
}
259276

260277
fn get_unit_temp(&mut self) -> Lvalue<'tcx> {

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

+18-5
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ should go to.
8787
*/
8888

8989
use build::{BlockAnd, BlockAndExtension, Builder, CFG, ScopeAuxiliary};
90-
use rustc::middle::region::CodeExtent;
90+
use rustc::middle::region::{CodeExtent, CodeExtentData};
9191
use rustc::middle::lang_items;
9292
use rustc::middle::subst::{Substs, Subst, VecPerParamSpace};
9393
use rustc::middle::ty::{self, Ty, TyCtxt};
@@ -326,9 +326,13 @@ impl<'a,'tcx> Builder<'a,'tcx> {
326326
.push(self.cfg.current_location(block));
327327
}
328328

329-
let scope_id = self.innermost_scope_id();
329+
assert!(scope_count < self.scopes.len(),
330+
"should never use `exit_scope` to pop *ALL* scopes");
331+
let scope = self.scopes.iter().rev().skip(scope_count)
332+
.next()
333+
.unwrap();
330334
self.cfg.terminate(block,
331-
scope_id,
335+
scope.id,
332336
span,
333337
TerminatorKind::Goto { target: target });
334338
}
@@ -365,8 +369,17 @@ impl<'a,'tcx> Builder<'a,'tcx> {
365369
self.scopes.last().map(|scope| scope.extent).unwrap()
366370
}
367371

368-
pub fn extent_of_outermost_scope(&self) -> CodeExtent {
369-
self.scopes.first().map(|scope| scope.extent).unwrap()
372+
/// Returns the extent of the scope which should be exited by a
373+
/// return.
374+
pub fn extent_of_return_scope(&self) -> CodeExtent {
375+
// The outermost scope (`scopes[0]`) will be the `CallSiteScope`.
376+
// We want `scopes[1]`, which is the `ParameterScope`.
377+
assert!(self.scopes.len() >= 2);
378+
assert!(match self.hir.tcx().region_maps.code_extent_data(self.scopes[1].extent) {
379+
CodeExtentData::ParameterScope { .. } => true,
380+
_ => false,
381+
});
382+
self.scopes[1].extent
370383
}
371384

372385
// Scheduling drops

Diff for: src/librustc_mir/mir_map.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ use hair::cx::Cx;
2727

2828
use rustc::mir::mir_map::MirMap;
2929
use rustc::middle::infer;
30-
use rustc::middle::region::CodeExtentData;
3130
use rustc::middle::traits::ProjectionMode;
3231
use rustc::middle::ty::{self, Ty, TyCtxt};
3332
use rustc::util::common::ErrorReported;
@@ -180,15 +179,13 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
180179
})
181180
.collect();
182181

183-
let parameter_scope =
184-
cx.tcx().region_maps.lookup_code_extent(
185-
CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id });
186182
let (mut mir, scope_auxiliary) =
187183
build::construct(cx,
188184
span,
185+
fn_id,
186+
body.id,
189187
implicit_arg_tys,
190188
arguments,
191-
parameter_scope,
192189
fn_sig.output,
193190
body);
194191

0 commit comments

Comments
 (0)