From: Niko Matsakis Date: Wed, 23 Mar 2016 16:26:37 +0000 (-0400) Subject: introduce "call-site-scope" as the outermost scope X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=a276e755e7e272e7bbd95eb3f82f2fcc946825a5;p=rust.git introduce "call-site-scope" as the outermost scope also, when exiting a scope, assign the final goto terminator with the target scope's id --- diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 4c9e2c0c5fa..30c039cdde0 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -261,7 +261,7 @@ pub fn into_expr(&mut self, block } }; - let extent = this.extent_of_outermost_scope(); + let extent = this.extent_of_return_scope(); this.exit_scope(expr_span, extent, block, END_BLOCK); this.cfg.start_new_block().unit() } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index c00acae7dc4..a88b138a44d 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -9,7 +9,7 @@ // except according to those terms. use hair::cx::Cx; -use rustc::middle::region::CodeExtent; +use rustc::middle::region::{CodeExtent, CodeExtentData}; use rustc::middle::ty::{FnOutput, Ty}; use rustc::mir::repr::*; use rustc_data_structures::fnv::FnvHashMap; @@ -153,12 +153,14 @@ macro_rules! unpack { pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>, span: Span, + fn_id: ast::NodeId, + body_id: ast::NodeId, implicit_arguments: Vec>, explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>, - argument_extent: CodeExtent, return_ty: FnOutput<'tcx>, ast_block: &'tcx hir::Block) -> (Mir<'tcx>, ScopeAuxiliaryVec) { + let tcx = hir.tcx(); let cfg = CFG { basic_blocks: vec![] }; let mut builder = Builder { @@ -178,18 +180,32 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>, assert_eq!(builder.cfg.start_new_block(), START_BLOCK); assert_eq!(builder.cfg.start_new_block(), END_BLOCK); - let mut block = START_BLOCK; - let (arg_decls, arg_scope_id) = - unpack!(block = builder.args_and_body(block, - implicit_arguments, - explicit_arguments, - argument_extent, - ast_block)); - builder.cfg.terminate(block, arg_scope_id, span, - TerminatorKind::Goto { target: END_BLOCK }); - builder.cfg.terminate(END_BLOCK, arg_scope_id, span, - TerminatorKind::Return); + let mut arg_decls = None; // assigned to `Some` in closures below + let call_site_extent = + tcx.region_maps.lookup_code_extent( + CodeExtentData::CallSiteScope { fn_id: fn_id, body_id: body_id }); + let _ = builder.in_scope(call_site_extent, START_BLOCK, |builder, call_site_scope_id| { + let mut block = START_BLOCK; + let arg_extent = + tcx.region_maps.lookup_code_extent( + CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body_id }); + unpack!(block = builder.in_scope(arg_extent, block, |builder, arg_scope_id| { + arg_decls = Some(unpack!(block = builder.args_and_body(block, + implicit_arguments, + explicit_arguments, + arg_scope_id, + ast_block))); + block.unit() + })); + + builder.cfg.terminate(block, call_site_scope_id, span, + TerminatorKind::Goto { target: END_BLOCK }); + builder.cfg.terminate(END_BLOCK, call_site_scope_id, span, + TerminatorKind::Return); + + END_BLOCK.unit() + }); assert!( builder.cfg.basic_blocks @@ -197,8 +213,8 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>, .enumerate() .all(|(index, block)| { if block.terminator.is_none() { - panic!("no terminator on block {:?} in {:?}", - index, argument_extent) + panic!("no terminator on block {:?} in fn {:?}", + index, fn_id) } true })); @@ -208,7 +224,7 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>, basic_blocks: builder.cfg.basic_blocks, scopes: builder.scope_datas, var_decls: builder.var_decls, - arg_decls: arg_decls, + arg_decls: arg_decls.take().expect("args never built?"), temp_decls: builder.temp_decls, return_ty: return_ty, span: span @@ -222,39 +238,40 @@ fn args_and_body(&mut self, mut block: BasicBlock, implicit_arguments: Vec>, explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>, - argument_extent: CodeExtent, + argument_scope_id: ScopeId, ast_block: &'tcx hir::Block) - -> BlockAnd<(Vec>, ScopeId)> + -> BlockAnd>> { - self.in_scope(argument_extent, block, |this, argument_scope_id| { - // to start, translate the argument patterns and collect the argument types. - let implicits = implicit_arguments.into_iter().map(|ty| (ty, None)); - let explicits = explicit_arguments.into_iter().map(|(ty, pat)| (ty, Some(pat))); + // to start, translate the argument patterns and collect the argument types. + let implicits = implicit_arguments.into_iter().map(|ty| (ty, None)); + let explicits = explicit_arguments.into_iter().map(|(ty, pat)| (ty, Some(pat))); let arg_decls = - implicits - .chain(explicits) - .enumerate() - .map(|(index, (ty, pattern))| { - let lvalue = Lvalue::Arg(index as u32); - if let Some(pattern) = pattern { - let pattern = this.hir.irrefutable_pat(pattern); - unpack!(block = this.lvalue_into_pattern(block, - argument_scope_id, - pattern, - &lvalue)); - } - // Make sure we drop (parts of) the argument even when not matched on. - this.schedule_drop(pattern.as_ref().map_or(ast_block.span, |pat| pat.span), - argument_extent, &lvalue, ty); - ArgDecl { ty: ty, spread: false } - }) - .collect(); - - // start the first basic block and translate the body - unpack!(block = this.ast_block(&Lvalue::ReturnPointer, block, ast_block)); - - block.and((arg_decls, argument_scope_id)) - }) + implicits + .chain(explicits) + .enumerate() + .map(|(index, (ty, pattern))| { + let lvalue = Lvalue::Arg(index as u32); + if let Some(pattern) = pattern { + let pattern = self.hir.irrefutable_pat(pattern); + unpack!(block = self.lvalue_into_pattern(block, + argument_scope_id, + pattern, + &lvalue)); + } + + // Make sure we drop (parts of) the argument even when not matched on. + let argument_extent = self.scope_auxiliary[argument_scope_id].extent; + self.schedule_drop(pattern.as_ref().map_or(ast_block.span, |pat| pat.span), + argument_extent, &lvalue, ty); + + ArgDecl { ty: ty, spread: false } + }) + .collect(); + + // start the first basic block and translate the body + unpack!(block = self.ast_block(&Lvalue::ReturnPointer, block, ast_block)); + + block.and(arg_decls) } fn get_unit_temp(&mut self) -> Lvalue<'tcx> { diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index cc9a4c4e714..acca2637c82 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -87,7 +87,7 @@ */ use build::{BlockAnd, BlockAndExtension, Builder, CFG, ScopeAuxiliary}; -use rustc::middle::region::CodeExtent; +use rustc::middle::region::{CodeExtent, CodeExtentData}; use rustc::middle::lang_items; use rustc::middle::subst::{Substs, Subst, VecPerParamSpace}; use rustc::middle::ty::{self, Ty, TyCtxt}; @@ -326,9 +326,13 @@ pub fn exit_scope(&mut self, .push(self.cfg.current_location(block)); } - let scope_id = self.innermost_scope_id(); + assert!(scope_count < self.scopes.len(), + "should never use `exit_scope` to pop *ALL* scopes"); + let scope = self.scopes.iter().rev().skip(scope_count) + .next() + .unwrap(); self.cfg.terminate(block, - scope_id, + scope.id, span, TerminatorKind::Goto { target: target }); } @@ -365,8 +369,17 @@ pub fn extent_of_innermost_scope(&self) -> CodeExtent { self.scopes.last().map(|scope| scope.extent).unwrap() } - pub fn extent_of_outermost_scope(&self) -> CodeExtent { - self.scopes.first().map(|scope| scope.extent).unwrap() + /// Returns the extent of the scope which should be exited by a + /// return. + pub fn extent_of_return_scope(&self) -> CodeExtent { + // The outermost scope (`scopes[0]`) will be the `CallSiteScope`. + // We want `scopes[1]`, which is the `ParameterScope`. + assert!(self.scopes.len() >= 2); + assert!(match self.hir.tcx().region_maps.code_extent_data(self.scopes[1].extent) { + CodeExtentData::ParameterScope { .. } => true, + _ => false, + }); + self.scopes[1].extent } // Scheduling drops diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 006c55633f8..5a6e2edfdf9 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -27,7 +27,6 @@ use rustc::mir::mir_map::MirMap; use rustc::middle::infer; -use rustc::middle::region::CodeExtentData; use rustc::middle::traits::ProjectionMode; use rustc::middle::ty::{self, Ty, TyCtxt}; use rustc::util::common::ErrorReported; @@ -180,15 +179,13 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>, }) .collect(); - let parameter_scope = - cx.tcx().region_maps.lookup_code_extent( - CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id }); let (mut mir, scope_auxiliary) = build::construct(cx, span, + fn_id, + body.id, implicit_arg_tys, arguments, - parameter_scope, fn_sig.output, body);