diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs index e2a5f97a847..2ebbb779933 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -1,17 +1,18 @@ -mod mcdc; use std::assert_matches::assert_matches; use std::collections::hash_map::Entry; use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind}; use rustc_middle::mir::{self, BasicBlock, SourceInfo, UnOp}; -use rustc_middle::thir::{ExprId, ExprKind, Thir}; +use rustc_middle::thir::{ExprId, ExprKind, Pat, Thir}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::LocalDefId; use crate::build::coverageinfo::mcdc::MCDCInfoBuilder; use crate::build::{Builder, CFG}; +mod mcdc; + pub(crate) struct BranchInfoBuilder { /// Maps condition expressions to their enclosing `!`, for better instrumentation. nots: FxHashMap, @@ -155,7 +156,7 @@ impl BranchInfoBuilder { } } -impl Builder<'_, '_> { +impl<'tcx> Builder<'_, 'tcx> { /// If branch coverage is enabled, inject marker statements into `then_block` /// and `else_block`, and record their IDs in the table of branch spans. pub(crate) fn visit_coverage_branch_condition( @@ -195,4 +196,23 @@ impl Builder<'_, '_> { branch_info.add_two_way_branch(&mut self.cfg, source_info, then_block, else_block); } + + /// If branch coverage is enabled, inject marker statements into `true_block` + /// and `false_block`, and record their IDs in the table of branches. + /// + /// Used to instrument let-else for branch coverage. + pub(crate) fn visit_coverage_conditional_let( + &mut self, + pattern: &Pat<'tcx>, // Pattern that has been matched when the true path is taken + true_block: BasicBlock, + false_block: BasicBlock, + ) { + // Bail out if branch coverage is not enabled for this function. + let Some(branch_info) = self.coverage_branch_info.as_mut() else { return }; + + // FIXME(#124144) This may need special handling when MC/DC is enabled. + + let source_info = SourceInfo { span: pattern.span, scope: self.source_scope }; + branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block); + } } diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index bce15267759..54ffafb000b 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -2452,6 +2452,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { None, true, ); + + // If branch coverage is enabled, record this branch. + this.visit_coverage_conditional_let(pattern, matching, failure); + this.break_for_else(failure, this.source_info(initializer_span)); matching.unit() }); diff --git a/tests/coverage/branch/let-else.cov-map b/tests/coverage/branch/let-else.cov-map index ad987bd6bb1..c7f7adddbc2 100644 --- a/tests/coverage/branch/let-else.cov-map +++ b/tests/coverage/branch/let-else.cov-map @@ -1,13 +1,16 @@ Function name: let_else::let_else -Raw bytes (38): 0x[01, 01, 02, 05, 09, 09, 02, 06, 01, 0c, 01, 01, 10, 02, 03, 0e, 00, 0f, 05, 00, 13, 00, 18, 09, 01, 09, 01, 0f, 02, 04, 05, 00, 0b, 07, 01, 01, 00, 02] +Raw bytes (45): 0x[01, 01, 02, 05, 09, 09, 02, 07, 01, 0c, 01, 01, 10, 20, 02, 09, 03, 09, 00, 10, 02, 00, 0e, 00, 0f, 05, 00, 13, 00, 18, 09, 01, 09, 01, 0f, 02, 04, 05, 00, 0b, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub) -Number of file 0 mappings: 6 +Number of file 0 mappings: 7 - Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) -- Code(Expression(0, Sub)) at (prev + 3, 14) to (start + 0, 15) +- Branch { true: Expression(0, Sub), false: Counter(2) } at (prev + 3, 9) to (start + 0, 16) + true = (c1 - c2) + false = c2 +- Code(Expression(0, Sub)) at (prev + 0, 14) to (start + 0, 15) = (c1 - c2) - Code(Counter(1)) at (prev + 0, 19) to (start + 0, 24) - Code(Counter(2)) at (prev + 1, 9) to (start + 1, 15) diff --git a/tests/coverage/branch/let-else.coverage b/tests/coverage/branch/let-else.coverage index 83730e1dfba..22ad8f2b0e1 100644 --- a/tests/coverage/branch/let-else.coverage +++ b/tests/coverage/branch/let-else.coverage @@ -14,6 +14,9 @@ LL| | LL| 3| let Some(x) = value else { ^2 + ------------------ + | Branch (LL:9): [True: 2, False: 1] + ------------------ LL| 1| say("none"); LL| 1| return; LL| | };