about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src
diff options
context:
space:
mode:
authorZalathar <Zalathar@users.noreply.github.com>2024-04-21 12:06:03 +1000
committerZalathar <Zalathar@users.noreply.github.com>2024-04-22 21:55:33 +1000
commit97bf5536827ea7a1ba6b7cf856dd2b22184d2527 (patch)
tree8156d6a955096954d6fa05565f11cb7c93acde45 /compiler/rustc_mir_transform/src
parenta892c2387e64ba080a6503d422931f3a0916826a (diff)
downloadrust-97bf5536827ea7a1ba6b7cf856dd2b22184d2527.tar.gz
rust-97bf5536827ea7a1ba6b7cf856dd2b22184d2527.zip
coverage: Detach MC/DC branch spans from regular branch spans
MC/DC's reliance on the existing branch coverage types is making it much harder
to improve branch coverage.
Diffstat (limited to 'compiler/rustc_mir_transform/src')
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs16
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs10
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs74
3 files changed, 77 insertions, 23 deletions
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 9e8648b0f93..d1516605fb6 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -149,13 +149,21 @@ fn create_mappings<'tcx>(
                     true_term: term_for_bcb(true_bcb),
                     false_term: term_for_bcb(false_bcb),
                 },
-                BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info } => {
-                    MappingKind::MCDCBranch {
+                BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info: None } => {
+                    MappingKind::Branch {
                         true_term: term_for_bcb(true_bcb),
                         false_term: term_for_bcb(false_bcb),
-                        mcdc_params: condition_info,
                     }
                 }
+                BcbMappingKind::MCDCBranch {
+                    true_bcb,
+                    false_bcb,
+                    condition_info: Some(mcdc_params),
+                } => MappingKind::MCDCBranch {
+                    true_term: term_for_bcb(true_bcb),
+                    false_term: term_for_bcb(false_bcb),
+                    mcdc_params,
+                },
                 BcbMappingKind::MCDCDecision { bitmap_idx, conditions_num, .. } => {
                     MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, conditions_num })
                 }
@@ -249,7 +257,7 @@ fn inject_mcdc_statements<'tcx>(
     for (true_bcb, false_bcb, condition_id) in
         coverage_spans.all_bcb_mappings().filter_map(|mapping| match mapping.kind {
             BcbMappingKind::MCDCBranch { true_bcb, false_bcb, condition_info } => {
-                Some((true_bcb, false_bcb, condition_info.condition_id))
+                Some((true_bcb, false_bcb, condition_info?.condition_id))
             }
             _ => None,
         })
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index a4cd8a38c66..8d2241783f6 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -21,7 +21,9 @@ pub(super) enum BcbMappingKind {
     MCDCBranch {
         true_bcb: BasicCoverageBlock,
         false_bcb: BasicCoverageBlock,
-        condition_info: ConditionInfo,
+        /// If `None`, this actually represents a normal branch mapping inserted
+        /// for code that was too complex for MC/DC.
+        condition_info: Option<ConditionInfo>,
     },
     /// Associates a mcdc decision with its join BCB.
     MCDCDecision { end_bcbs: BTreeSet<BasicCoverageBlock>, bitmap_idx: u32, conditions_num: u16 },
@@ -86,6 +88,12 @@ pub(super) fn generate_coverage_spans(
 
         mappings.extend(from_mir::extract_branch_mappings(
             mir_body,
+            hir_info,
+            basic_coverage_blocks,
+        ));
+
+        mappings.extend(from_mir::extract_mcdc_mappings(
+            mir_body,
             hir_info.body_span,
             basic_coverage_blocks,
         ));
diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
index b9919a2ae88..3c64591d43e 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs
@@ -366,15 +366,10 @@ impl SpanFromMir {
     }
 }
 
-pub(super) fn extract_branch_mappings(
+fn resolve_block_markers(
+    branch_info: &mir::coverage::BranchInfo,
     mir_body: &mir::Body<'_>,
-    body_span: Span,
-    basic_coverage_blocks: &CoverageGraph,
-) -> Vec<BcbMapping> {
-    let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else {
-        return vec![];
-    };
-
+) -> IndexVec<BlockMarkerId, Option<BasicBlock>> {
     let mut block_markers = IndexVec::<BlockMarkerId, Option<BasicBlock>>::from_elem_n(
         None,
         branch_info.num_block_markers,
@@ -389,6 +384,58 @@ pub(super) fn extract_branch_mappings(
         }
     }
 
+    block_markers
+}
+
+// FIXME: There is currently a lot of redundancy between
+// `extract_branch_mappings` and `extract_mcdc_mappings`. This is needed so
+// that they can each be modified without interfering with the other, but in
+// the long term we should try to bring them together again when branch coverage
+// and MC/DC coverage support are more mature.
+
+pub(super) fn extract_branch_mappings(
+    mir_body: &mir::Body<'_>,
+    hir_info: &ExtractedHirInfo,
+    basic_coverage_blocks: &CoverageGraph,
+) -> Vec<BcbMapping> {
+    let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { return vec![] };
+
+    let block_markers = resolve_block_markers(branch_info, mir_body);
+
+    branch_info
+        .branch_spans
+        .iter()
+        .filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| {
+            // For now, ignore any branch span that was introduced by
+            // expansion. This makes things like assert macros less noisy.
+            if !raw_span.ctxt().outer_expn_data().is_root() {
+                return None;
+            }
+            let (span, _) =
+                unexpand_into_body_span_with_visible_macro(raw_span, hir_info.body_span)?;
+
+            let bcb_from_marker =
+                |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?);
+
+            let true_bcb = bcb_from_marker(true_marker)?;
+            let false_bcb = bcb_from_marker(false_marker)?;
+
+            Some(BcbMapping { kind: BcbMappingKind::Branch { true_bcb, false_bcb }, span })
+        })
+        .collect::<Vec<_>>()
+}
+
+pub(super) fn extract_mcdc_mappings(
+    mir_body: &mir::Body<'_>,
+    body_span: Span,
+    basic_coverage_blocks: &CoverageGraph,
+) -> Vec<BcbMapping> {
+    let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else {
+        return vec![];
+    };
+
+    let block_markers = resolve_block_markers(branch_info, mir_body);
+
     let bcb_from_marker =
         |marker: BlockMarkerId| basic_coverage_blocks.bcb_from_bb(block_markers[marker]?);
 
@@ -406,12 +453,6 @@ pub(super) fn extract_branch_mappings(
             Some((span, true_bcb, false_bcb))
         };
 
-    let branch_filter_map = |&BranchSpan { span: raw_span, true_marker, false_marker }| {
-        check_branch_bcb(raw_span, true_marker, false_marker).map(|(span, true_bcb, false_bcb)| {
-            BcbMapping { kind: BcbMappingKind::Branch { true_bcb, false_bcb }, span }
-        })
-    };
-
     let mcdc_branch_filter_map =
         |&MCDCBranchSpan { span: raw_span, true_marker, false_marker, condition_info }| {
             check_branch_bcb(raw_span, true_marker, false_marker).map(
@@ -446,10 +487,7 @@ pub(super) fn extract_branch_mappings(
         })
     };
 
-    branch_info
-        .branch_spans
-        .iter()
-        .filter_map(branch_filter_map)
+    std::iter::empty()
         .chain(branch_info.mcdc_branch_spans.iter().filter_map(mcdc_branch_filter_map))
         .chain(branch_info.mcdc_decision_spans.iter().filter_map(decision_filter_map))
         .collect::<Vec<_>>()