]> git.lizzy.rs Git - rust.git/commitdiff
introduce "call-site-scope" as the outermost scope
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 23 Mar 2016 16:26:37 +0000 (12:26 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 23 Mar 2016 20:42:55 +0000 (16:42 -0400)
also, when exiting a scope, assign the final goto terminator with the
target scope's id

src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/mir_map.rs

index 4c9e2c0c5fa6d51b358cea0f04fbda0a96da7186..30c039cdde0c3e5b5ec13da488b71c02b68c3640 100644 (file)
@@ -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()
             }
index c00acae7dc4758ef2bb265130d620278c0711e5c..a88b138a44ddea3d67f7b04e53822f659d64c639 100644 (file)
@@ -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<Ty<'tcx>>,
                           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<Ty<'tcx>>,
                      explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
-                     argument_extent: CodeExtent,
+                     argument_scope_id: ScopeId,
                      ast_block: &'tcx hir::Block)
-                     -> BlockAnd<(Vec<ArgDecl<'tcx>>, ScopeId)>
+                     -> BlockAnd<Vec<ArgDecl<'tcx>>>
     {
-        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> {
index cc9a4c4e7144bd9ef8ad837fb59777a282d68244..acca2637c82c193def7a28f4acea41605e1bbe92 100644 (file)
@@ -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
index 006c55633f85bf7b2ecfeb03c8e3dae0692afc7f..5a6e2edfdf9e78745df9a95d8822f96237ecfd63 100644 (file)
@@ -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);