]> git.lizzy.rs Git - rust.git/commitdiff
also release/validate around non-Misc casts
authorRalf Jung <post@ralfj.de>
Thu, 27 Jul 2017 03:51:36 +0000 (20:51 -0700)
committerRalf Jung <post@ralfj.de>
Sun, 30 Jul 2017 08:11:59 +0000 (01:11 -0700)
src/librustc_mir/transform/add_validation.rs

index 4edcab738c37562c592386d0cdbc4e1e835bf2bc..70ef08cf2d1811b630a6894c82956bbe44689100 100644 (file)
@@ -171,42 +171,83 @@ fn run_pass<'a, 'tcx>(&self,
         }
 
         // PART 3
-        // Add ReleaseValid/AcquireValid around Ref.  Again an iterator does not seem very suited
+        // Add ReleaseValid/AcquireValid around Ref and Cast.  Again an iterator does not seem very
+        // suited
         // as we need to add new statements before and after each Ref.
         for block_data in mir.basic_blocks_mut() {
             // We want to insert statements around Ref commands as we iterate.  To this end, we
             // iterate backwards using indices.
             for i in (0..block_data.statements.len()).rev() {
-                let (dest_lval, re, src_lval) = match block_data.statements[i].kind {
-                    StatementKind::Assign(ref dest_lval, Rvalue::Ref(re, _, ref src_lval)) => {
-                        (dest_lval.clone(), re, src_lval.clone())
-                    },
-                    _ => continue,
-                };
-                // So this is a ref, and we got all the data we wanted.
-                // Do an acquire of the result -- but only what it points to, so add a Deref
-                // projection.
-                let dest_lval = Projection { base: dest_lval, elem: ProjectionElem::Deref };
-                let dest_lval = Lvalue::Projection(Box::new(dest_lval));
-                let acquire_stmt = Statement {
-                    source_info: block_data.statements[i].source_info,
-                    kind: StatementKind::Validate(ValidationOp::Acquire,
-                            vec![lval_to_operand(dest_lval)]),
-                };
-                block_data.statements.insert(i+1, acquire_stmt);
+                match block_data.statements[i].kind {
+                    // When the borrow of this ref expires, we need to recover validation.
+                    StatementKind::Assign(_, Rvalue::Ref(_, _, _)) => {
+                        // Due to a lack of NLL; we can't capture anything directly here.
+                        // Instead, we have to re-match and clone there.
+                        let (dest_lval, re, src_lval) = match block_data.statements[i].kind {
+                            StatementKind::Assign(ref dest_lval,
+                                                  Rvalue::Ref(re, _, ref src_lval)) => {
+                                (dest_lval.clone(), re, src_lval.clone())
+                            },
+                            _ => bug!("We already matched this."),
+                        };
+                        // So this is a ref, and we got all the data we wanted.
+                        // Do an acquire of the result -- but only what it points to, so add a Deref
+                        // projection.
+                        let dest_lval = Projection { base: dest_lval, elem: ProjectionElem::Deref };
+                        let dest_lval = Lvalue::Projection(Box::new(dest_lval));
+                        let acquire_stmt = Statement {
+                            source_info: block_data.statements[i].source_info,
+                            kind: StatementKind::Validate(ValidationOp::Acquire,
+                                    vec![lval_to_operand(dest_lval)]),
+                        };
+                        block_data.statements.insert(i+1, acquire_stmt);
 
-                // The source is released until the region of the borrow ends.
-                let op = match re {
-                    &RegionKind::ReScope(ce) => ValidationOp::Suspend(ce),
-                    &RegionKind::ReErased =>
-                        bug!("AddValidation pass must be run before erasing lifetimes"),
-                    _ => ValidationOp::Release,
-                };
-                let release_stmt = Statement {
-                    source_info: block_data.statements[i].source_info,
-                    kind: StatementKind::Validate(op, vec![lval_to_operand(src_lval)]),
-                };
-                block_data.statements.insert(i, release_stmt);
+                        // The source is released until the region of the borrow ends.
+                        let op = match re {
+                            &RegionKind::ReScope(ce) => ValidationOp::Suspend(ce),
+                            &RegionKind::ReErased =>
+                                bug!("AddValidation pass must be run before erasing lifetimes"),
+                            _ => ValidationOp::Release,
+                        };
+                        let release_stmt = Statement {
+                            source_info: block_data.statements[i].source_info,
+                            kind: StatementKind::Validate(op, vec![lval_to_operand(src_lval)]),
+                        };
+                        block_data.statements.insert(i, release_stmt);
+                    }
+                    // Casts can change what validation does (e.g. unsizing)
+                    StatementKind::Assign(_, Rvalue::Cast(kind, Operand::Consume(_), _))
+                        if kind != CastKind::Misc =>
+                    {
+                        // Due to a lack of NLL; we can't capture anything directly here.
+                        // Instead, we have to re-match and clone there.
+                        let (dest_lval, src_lval) = match block_data.statements[i].kind {
+                            StatementKind::Assign(ref dest_lval,
+                                    Rvalue::Cast(_, Operand::Consume(ref src_lval), _)) =>
+                            {
+                                (dest_lval.clone(), src_lval.clone())
+                            },
+                            _ => bug!("We already matched this."),
+                        };
+
+                        // Acquire of the result
+                        let acquire_stmt = Statement {
+                            source_info: block_data.statements[i].source_info,
+                            kind: StatementKind::Validate(ValidationOp::Acquire,
+                                    vec![lval_to_operand(dest_lval)]),
+                        };
+                        block_data.statements.insert(i+1, acquire_stmt);
+
+                        // Release of the input
+                        let release_stmt = Statement {
+                            source_info: block_data.statements[i].source_info,
+                            kind: StatementKind::Validate(ValidationOp::Release,
+                                                            vec![lval_to_operand(src_lval)]),
+                        };
+                        block_data.statements.insert(i, release_stmt);
+                    }
+                    _ => {},
+                }
             }
         }
     }