about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-04-20 03:08:24 +0000
committerbors <bors@rust-lang.org>2021-04-20 03:08:24 +0000
commitb2c20b51ed838368d3f2bdccb63f401bcddb7e1c (patch)
treeb0af4165f7549a3915410a8d8e52587a7e8bf948 /compiler
parente888a57da83fca78d6e64af0a347d06d9161affe (diff)
parentd1d7fb1ae53a02f5073a7cf0ab1497aaa9617ebe (diff)
downloadrust-b2c20b51ed838368d3f2bdccb63f401bcddb7e1c.tar.gz
rust-b2c20b51ed838368d3f2bdccb63f401bcddb7e1c.zip
Auto merge of #84295 - richkadel:continue-coverage, r=tmandry
Add coverage to continue statements

`continue` statements were missing coverage. This was particularly
noticeable in a match pattern that contained only a `continue`
statement, leaving the branch appear uncounted. This PR addresses the
problem and adds tests to prove it.

r? `@tmandry`
cc: `@wesleywiser`
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs15
1 files changed, 15 insertions, 0 deletions
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index b637b9b70bd..41fc925c049 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -618,6 +618,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             }
         } else {
             assert!(value.is_none(), "`return` and `break` should have a destination");
+            if self.tcx.sess.instrument_coverage() {
+                // Unlike `break` and `return`, which push an `Assign` statement to MIR, from which
+                // a Coverage code region can be generated, `continue` needs no `Assign`; but
+                // without one, the `InstrumentCoverage` MIR pass cannot generate a code region for
+                // `continue`. Coverage will be missing unless we add a dummy `Assign` to MIR.
+                self.add_dummy_assignment(&span, block, source_info);
+            }
         }
 
         let region_scope = self.scopes.breakable_scopes[break_index].region_scope;
@@ -643,6 +650,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.start_new_block().unit()
     }
 
+    // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue`
+    // statement.
+    fn add_dummy_assignment(&mut self, span: &Span, block: BasicBlock, source_info: SourceInfo) {
+        let local_decl = LocalDecl::new(self.tcx.mk_unit(), *span).internal();
+        let temp_place = Place::from(self.local_decls.push(local_decl));
+        self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx);
+    }
+
     crate fn exit_top_scope(
         &mut self,
         mut block: BasicBlock,