Skip to content

Commit ae0ab4c

Browse files
author
Mara
committed
♻️ extract propagate_loss: reduce monomorphization surface for coverage
Extract propagate_loss() from .eh() and compose() so LLVM creates fewer per-closure monomorphizations. 100% function coverage, 0 actual uncovered source lines (verified via JSON/LCOV export). LLVM summary reports 99.79% due to region-weighted monomorphization phantoms — an inherent limitation for generic Rust, not missing test coverage. Co-Authored-By: Mara <mara@systemic.engineer>
1 parent c306ef1 commit ae0ab4c

1 file changed

Lines changed: 16 additions & 10 deletions

File tree

src/lib.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,20 @@ pub enum Imperfect<T, E, L: Loss> {
100100
Failure(E, L),
101101
}
102102

103+
/// Propagate accumulated loss through the next step's result.
104+
///
105+
/// Extracted as a standalone function so that LLVM creates a single
106+
/// monomorphization per `(T, E, L)` triple, rather than one per closure.
107+
/// This avoids phantom "missed lines" in coverage from closure-specific
108+
/// monomorphizations that never exercise certain match arms.
109+
fn propagate_loss<T, E, L: Loss>(loss: L, next: Imperfect<T, E, L>) -> Imperfect<T, E, L> {
110+
match next {
111+
Imperfect::Success(u) => Imperfect::Partial(u, loss),
112+
Imperfect::Partial(u, loss2) => Imperfect::Partial(u, loss.combine(loss2)),
113+
Imperfect::Failure(e, loss2) => Imperfect::Failure(e, loss.combine(loss2)),
114+
}
115+
}
116+
103117
impl<T, E, L: Loss> Imperfect<T, E, L> {
104118
/// Returns `true` if the result has a value (Success or Partial).
105119
pub fn is_ok(&self) -> bool {
@@ -192,11 +206,7 @@ impl<T, E, L: Loss> Imperfect<T, E, L> {
192206
pub fn eh<U>(self, f: impl FnOnce(T) -> Imperfect<U, E, L>) -> Imperfect<U, E, L> {
193207
match self {
194208
Imperfect::Success(t) => f(t),
195-
Imperfect::Partial(t, loss) => match f(t) {
196-
Imperfect::Success(u) => Imperfect::Partial(u, loss),
197-
Imperfect::Partial(u, loss2) => Imperfect::Partial(u, loss.combine(loss2)),
198-
Imperfect::Failure(e, loss2) => Imperfect::Failure(e, loss.combine(loss2)),
199-
},
209+
Imperfect::Partial(t, loss) => propagate_loss(loss, f(t)),
200210
Imperfect::Failure(e, loss) => Imperfect::Failure(e, loss),
201211
}
202212
}
@@ -228,11 +238,7 @@ impl<T, E, L: Loss> Imperfect<T, E, L> {
228238
match self {
229239
Imperfect::Failure(e, loss) => Imperfect::Failure(e.into(), loss),
230240
Imperfect::Success(_) => next,
231-
Imperfect::Partial(_, loss) => match next {
232-
Imperfect::Success(u) => Imperfect::Partial(u, loss),
233-
Imperfect::Partial(u, loss2) => Imperfect::Partial(u, loss.combine(loss2)),
234-
Imperfect::Failure(e, loss2) => Imperfect::Failure(e, loss.combine(loss2)),
235-
},
241+
Imperfect::Partial(_, loss) => propagate_loss(loss, next),
236242
}
237243
}
238244
}

0 commit comments

Comments
 (0)