Skip to content

Commit a71ab45

Browse files
Rollup merge of #118198 - Zalathar:if-not, r=cjgillot
coverage: Use `SpanMarker` to improve coverage spans for `if !` expressions Coverage instrumentation works by extracting source code spans from MIR. However, some kinds of syntax are effectively erased during MIR building, so their spans don't necessarily exist anywhere in MIR, making them invisible to the coverage instrumentor (unless we resort to various heuristics and hacks to recover them). This PR introduces `CoverageKind::SpanMarker`, which is a new variant of `StatementKind::Coverage`. Its sole purpose is to represent spans that would otherwise not appear in MIR, so that the coverage instrumentor can extract them. When coverage is enabled, the MIR builder can insert these dummy statements as needed, to improve the accuracy of spans used by coverage mappings. Fixes #115468. --- ```@rustbot``` label +A-code-coverage
2 parents 608f324 + d90fd02 commit a71ab45

File tree

11 files changed

+168
-24
lines changed

11 files changed

+168
-24
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
100100

101101
let Coverage { kind } = coverage;
102102
match *kind {
103+
// Span markers are only meaningful during MIR instrumentation,
104+
// and have no effect during codegen.
105+
CoverageKind::SpanMarker => {}
103106
CoverageKind::CounterIncrement { id } => {
104107
func_coverage.mark_counter_id_seen(id);
105108
// We need to explicitly drop the `RefMut` before calling into `instrprof_increment`,

compiler/rustc_middle/src/mir/coverage.rs

+8
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ impl Debug for CovTerm {
7676

7777
#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
7878
pub enum CoverageKind {
79+
/// Marks a span that might otherwise not be represented in MIR, so that
80+
/// coverage instrumentation can associate it with its enclosing block/BCB.
81+
///
82+
/// Only used by the `InstrumentCoverage` pass, and has no effect during
83+
/// codegen.
84+
SpanMarker,
85+
7986
/// Marks the point in MIR control flow represented by a coverage counter.
8087
///
8188
/// This is eventually lowered to `llvm.instrprof.increment` in LLVM IR.
@@ -99,6 +106,7 @@ impl Debug for CoverageKind {
99106
fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
100107
use CoverageKind::*;
101108
match self {
109+
SpanMarker => write!(fmt, "SpanMarker"),
102110
CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()),
103111
ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()),
104112
}

compiler/rustc_mir_build/src/build/cfg.rs

+13
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,19 @@ impl<'tcx> CFG<'tcx> {
101101
self.push(block, stmt);
102102
}
103103

104+
/// Adds a dummy statement whose only role is to associate a span with its
105+
/// enclosing block for the purposes of coverage instrumentation.
106+
///
107+
/// This results in more accurate coverage reports for certain kinds of
108+
/// syntax (e.g. `continue` or `if !`) that would otherwise not appear in MIR.
109+
pub(crate) fn push_coverage_span_marker(&mut self, block: BasicBlock, source_info: SourceInfo) {
110+
let kind = StatementKind::Coverage(Box::new(Coverage {
111+
kind: coverage::CoverageKind::SpanMarker,
112+
}));
113+
let stmt = Statement { source_info, kind };
114+
self.push(block, stmt);
115+
}
116+
104117
pub(crate) fn terminate(
105118
&mut self,
106119
block: BasicBlock,

compiler/rustc_mir_build/src/build/matches/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
9090
let local_scope = this.local_scope();
9191
let (success_block, failure_block) =
9292
this.in_if_then_scope(local_scope, expr_span, |this| {
93+
// Help out coverage instrumentation by injecting a dummy statement with
94+
// the original condition's span (including `!`). This fixes #115468.
95+
if this.tcx.sess.instrument_coverage() {
96+
this.cfg.push_coverage_span_marker(block, this.source_info(expr_span));
97+
}
9398
this.then_else_break(
9499
block,
95100
&this.thir[arg],

compiler/rustc_mir_build/src/build/scope.rs

+8-16
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ use rustc_index::{IndexSlice, IndexVec};
9090
use rustc_middle::middle::region;
9191
use rustc_middle::mir::*;
9292
use rustc_middle::thir::{Expr, LintLevel};
93-
use rustc_middle::ty::Ty;
9493
use rustc_session::lint::Level;
9594
use rustc_span::{Span, DUMMY_SP};
9695

@@ -660,14 +659,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
660659
(None, Some(_)) => {
661660
panic!("`return`, `become` and `break` with value and must have a destination")
662661
}
663-
(None, None) if self.tcx.sess.instrument_coverage() => {
664-
// Unlike `break` and `return`, which push an `Assign` statement to MIR, from which
665-
// a Coverage code region can be generated, `continue` needs no `Assign`; but
666-
// without one, the `InstrumentCoverage` MIR pass cannot generate a code region for
667-
// `continue`. Coverage will be missing unless we add a dummy `Assign` to MIR.
668-
self.add_dummy_assignment(span, block, source_info);
662+
(None, None) => {
663+
if self.tcx.sess.instrument_coverage() {
664+
// Normally we wouldn't build any MIR in this case, but that makes it
665+
// harder for coverage instrumentation to extract a relevant span for
666+
// `continue` expressions. So here we inject a dummy statement with the
667+
// desired span.
668+
self.cfg.push_coverage_span_marker(block, source_info);
669+
}
669670
}
670-
(None, None) => {}
671671
}
672672

673673
let region_scope = self.scopes.breakable_scopes[break_index].region_scope;
@@ -723,14 +723,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
723723
self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
724724
}
725725

726-
// Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue`
727-
// statement.
728-
fn add_dummy_assignment(&mut self, span: Span, block: BasicBlock, source_info: SourceInfo) {
729-
let local_decl = LocalDecl::new(Ty::new_unit(self.tcx), span);
730-
let temp_place = Place::from(self.local_decls.push(local_decl));
731-
self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx);
732-
}
733-
734726
fn leave_top_scope(&mut self, block: BasicBlock) -> BasicBlock {
735727
// If we are emitting a `drop` statement, we need to have the cached
736728
// diverge cleanup pads ready in case that drop panics.

compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,13 @@ fn is_closure(statement: &Statement<'_>) -> bool {
9292
/// If the MIR `Statement` has a span contributive to computing coverage spans,
9393
/// return it; otherwise return `None`.
9494
fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
95+
use mir::coverage::CoverageKind;
96+
9597
match statement.kind {
9698
// These statements have spans that are often outside the scope of the executed source code
9799
// for their parent `BasicBlock`.
98100
StatementKind::StorageLive(_)
99101
| StatementKind::StorageDead(_)
100-
// Coverage should not be encountered, but don't inject coverage coverage
101-
| StatementKind::Coverage(_)
102102
// Ignore `ConstEvalCounter`s
103103
| StatementKind::ConstEvalCounter
104104
// Ignore `Nop`s
@@ -122,9 +122,13 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
122122
// If and when the Issue is resolved, remove this special case match pattern:
123123
StatementKind::FakeRead(box (FakeReadCause::ForGuardBinding, _)) => None,
124124

125-
// Retain spans from all other statements
125+
// Retain spans from most other statements.
126126
StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding`
127127
| StatementKind::Intrinsic(..)
128+
| StatementKind::Coverage(box mir::Coverage {
129+
// The purpose of `SpanMarker` is to be matched and accepted here.
130+
kind: CoverageKind::SpanMarker
131+
})
128132
| StatementKind::Assign(_)
129133
| StatementKind::SetDiscriminant { .. }
130134
| StatementKind::Deinit(..)
@@ -133,6 +137,11 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option<Span> {
133137
| StatementKind::AscribeUserType(_, _) => {
134138
Some(statement.source_info.span)
135139
}
140+
141+
StatementKind::Coverage(box mir::Coverage {
142+
// These coverage statements should not exist prior to coverage instrumentation.
143+
kind: CoverageKind::CounterIncrement { .. } | CoverageKind::ExpressionUsed { .. }
144+
}) => bug!("Unexpected coverage statement found during coverage instrumentation: {statement:?}"),
136145
}
137146
}
138147

tests/coverage/if_not.cov-map

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
Function name: if_not::if_not
2+
Raw bytes (86): 0x[01, 01, 10, 01, 05, 05, 02, 3f, 09, 05, 02, 09, 3a, 3f, 09, 05, 02, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0d, 32, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0a, 01, 04, 01, 03, 0d, 02, 04, 05, 02, 06, 05, 02, 06, 00, 07, 3f, 03, 09, 01, 0d, 3a, 02, 05, 02, 06, 09, 02, 06, 00, 07, 37, 03, 09, 01, 0d, 32, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 2f, 03, 01, 00, 02]
3+
Number of files: 1
4+
- file 0 => global file 1
5+
Number of expressions: 16
6+
- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
7+
- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
8+
- expression 2 operands: lhs = Expression(15, Add), rhs = Counter(2)
9+
- expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub)
10+
- expression 4 operands: lhs = Counter(2), rhs = Expression(14, Sub)
11+
- expression 5 operands: lhs = Expression(15, Add), rhs = Counter(2)
12+
- expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub)
13+
- expression 7 operands: lhs = Expression(13, Add), rhs = Counter(3)
14+
- expression 8 operands: lhs = Counter(2), rhs = Expression(14, Sub)
15+
- expression 9 operands: lhs = Expression(15, Add), rhs = Counter(2)
16+
- expression 10 operands: lhs = Counter(1), rhs = Expression(0, Sub)
17+
- expression 11 operands: lhs = Counter(3), rhs = Expression(12, Sub)
18+
- expression 12 operands: lhs = Expression(13, Add), rhs = Counter(3)
19+
- expression 13 operands: lhs = Counter(2), rhs = Expression(14, Sub)
20+
- expression 14 operands: lhs = Expression(15, Add), rhs = Counter(2)
21+
- expression 15 operands: lhs = Counter(1), rhs = Expression(0, Sub)
22+
Number of file 0 mappings: 10
23+
- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13)
24+
- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 2, 6)
25+
= (c0 - c1)
26+
- Code(Counter(1)) at (prev + 2, 6) to (start + 0, 7)
27+
- Code(Expression(15, Add)) at (prev + 3, 9) to (start + 1, 13)
28+
= (c1 + (c0 - c1))
29+
- Code(Expression(14, Sub)) at (prev + 2, 5) to (start + 2, 6)
30+
= ((c1 + (c0 - c1)) - c2)
31+
- Code(Counter(2)) at (prev + 2, 6) to (start + 0, 7)
32+
- Code(Expression(13, Add)) at (prev + 3, 9) to (start + 1, 13)
33+
= (c2 + ((c1 + (c0 - c1)) - c2))
34+
- Code(Expression(12, Sub)) at (prev + 2, 5) to (start + 2, 6)
35+
= ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)
36+
- Code(Counter(3)) at (prev + 2, 12) to (start + 2, 6)
37+
- Code(Expression(11, Add)) at (prev + 3, 1) to (start + 0, 2)
38+
= (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3))
39+

tests/coverage/if_not.coverage

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
LL| |#![feature(coverage_attribute)]
2+
LL| |// edition: 2021
3+
LL| |
4+
LL| 12|fn if_not(cond: bool) {
5+
LL| 12| if
6+
LL| 12| !
7+
LL| 12| cond
8+
LL| 4| {
9+
LL| 4| println!("cond was false");
10+
LL| 8| }
11+
LL| |
12+
LL| | if
13+
LL| 12| !
14+
LL| 12| cond
15+
LL| 4| {
16+
LL| 4| println!("cond was false");
17+
LL| 8| }
18+
LL| |
19+
LL| | if
20+
LL| 12| !
21+
LL| 12| cond
22+
LL| 4| {
23+
LL| 4| println!("cond was false");
24+
LL| 8| } else {
25+
LL| 8| println!("cond was true");
26+
LL| 8| }
27+
LL| 12|}
28+
LL| |
29+
LL| |#[coverage(off)]
30+
LL| |fn main() {
31+
LL| | for _ in 0..8 {
32+
LL| | if_not(std::hint::black_box(true));
33+
LL| | }
34+
LL| | for _ in 0..4 {
35+
LL| | if_not(std::hint::black_box(false));
36+
LL| | }
37+
LL| |}
38+

tests/coverage/if_not.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#![feature(coverage_attribute)]
2+
// edition: 2021
3+
4+
fn if_not(cond: bool) {
5+
if
6+
!
7+
cond
8+
{
9+
println!("cond was false");
10+
}
11+
12+
if
13+
!
14+
cond
15+
{
16+
println!("cond was false");
17+
}
18+
19+
if
20+
!
21+
cond
22+
{
23+
println!("cond was false");
24+
} else {
25+
println!("cond was true");
26+
}
27+
}
28+
29+
#[coverage(off)]
30+
fn main() {
31+
for _ in 0..8 {
32+
if_not(std::hint::black_box(true));
33+
}
34+
for _ in 0..4 {
35+
if_not(std::hint::black_box(false));
36+
}
37+
}

tests/coverage/lazy_boolean.cov-map

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Function name: lazy_boolean::main
2-
Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 04, 09, 00, 10, ea, 04, 01, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 09, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02]
2+
Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 03, 09, 01, 10, ea, 04, 02, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 08, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02]
33
Number of files: 1
44
- file 0 => global file 1
55
Number of expressions: 164
@@ -194,17 +194,17 @@ Number of file 0 mappings: 28
194194
- Code(Expression(157, Add)) at (prev + 0, 20) to (start + 0, 25)
195195
= (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4))
196196
- Code(Counter(5)) at (prev + 0, 29) to (start + 0, 34)
197-
- Code(Expression(155, Add)) at (prev + 4, 9) to (start + 0, 16)
197+
- Code(Expression(155, Add)) at (prev + 3, 9) to (start + 1, 16)
198198
= (c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5))
199-
- Code(Expression(154, Sub)) at (prev + 1, 5) to (start + 3, 6)
199+
- Code(Expression(154, Sub)) at (prev + 2, 5) to (start + 3, 6)
200200
= ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)
201201
- Code(Counter(6)) at (prev + 3, 6) to (start + 0, 7)
202202
- Code(Expression(153, Add)) at (prev + 3, 9) to (start + 0, 16)
203203
= (c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6))
204204
- Code(Counter(7)) at (prev + 1, 5) to (start + 3, 6)
205205
- Code(Expression(152, Sub)) at (prev + 5, 5) to (start + 3, 6)
206206
= ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)
207-
- Code(Expression(151, Add)) at (prev + 5, 9) to (start + 0, 16)
207+
- Code(Expression(151, Add)) at (prev + 5, 8) to (start + 0, 16)
208208
= (c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7))
209209
- Code(Expression(150, Sub)) at (prev + 0, 17) to (start + 2, 6)
210210
= ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)

tests/coverage/lazy_boolean.coverage

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
^0
3333
LL| |
3434
LL| | if
35-
LL| | !
35+
LL| 1| !
3636
LL| 1| is_true
3737
LL| 0| {
3838
LL| 0| a = 2

0 commit comments

Comments
 (0)