1use crate::error::{Fault, RuntimeError};
5use crate::weight::Weight;
6use probl_syntax::Span;
7
8#[derive(Clone, Debug, Default)]
10pub struct Failures {
11 pub groups: Vec<Failure>,
13 pub weight: Weight,
15 pub squares: Weight,
17 pub runs: u64,
19 pub before_evidence: bool,
23}
24
25#[derive(Clone, Debug)]
27pub struct Failure {
28 pub error: RuntimeError,
30 pub weight: Weight,
31 pub squares: Weight,
33 pub runs: u64,
36 pub first_run: Option<u32>,
37 pub before_evidence: bool,
39}
40
41impl Failures {
42 pub fn is_empty(&self) -> bool {
43 self.groups.is_empty()
44 }
45
46 pub fn record(&mut self, error: RuntimeError, weight: Weight, run: Option<u32>, before_evidence: bool) {
49 let runs = run.is_some() as u64;
50 let squares = if run.is_some() { weight * weight } else { Weight::ZERO };
51 self.weight += weight;
52 self.squares += squares;
53 self.runs += runs;
54 self.before_evidence |= before_evidence;
55 let (span, fault) = (error.span, error.fault);
56 match self.group(span, fault) {
57 Some(g) => {
58 g.weight += weight;
59 g.squares += squares;
60 g.runs += runs;
61 g.before_evidence |= before_evidence;
62 }
63 None => self.groups.push(Failure {
64 error,
65 weight,
66 squares,
67 runs,
68 first_run: run,
69 before_evidence,
70 }),
71 }
72 }
73
74 pub fn absorb(&mut self, other: &Failures, times: Weight, run: Option<u32>, before_evidence: bool) {
79 for theirs in &other.groups {
80 self.absorb_group(theirs, times, run, before_evidence);
81 }
82 }
83
84 pub fn absorb_group(&mut self, theirs: &Failure, times: Weight, run: Option<u32>, before_evidence: bool) {
86 let weight = theirs.weight * times;
87 let squares = theirs.squares * times * times;
88 let before_evidence = theirs.before_evidence || before_evidence;
89 self.weight += weight;
90 self.squares += squares;
91 self.runs += theirs.runs;
92 self.before_evidence |= before_evidence;
93 match self.group(theirs.error.span, theirs.error.fault) {
94 Some(g) => {
95 g.weight += weight;
96 g.squares += squares;
97 g.runs += theirs.runs;
98 g.before_evidence |= before_evidence;
99 }
100 None => self.groups.push(Failure {
101 error: theirs.error.clone(),
102 weight,
103 squares,
104 runs: theirs.runs,
105 first_run: run.or(theirs.first_run),
106 before_evidence,
107 }),
108 }
109 }
110
111 pub fn append(&mut self, later: Failures) {
113 self.weight += later.weight;
114 self.squares += later.squares;
115 self.runs += later.runs;
116 self.before_evidence |= later.before_evidence;
117 for theirs in later.groups {
118 match self.group(theirs.error.span, theirs.error.fault) {
119 Some(g) => {
120 g.weight += theirs.weight;
121 g.squares += theirs.squares;
122 g.runs += theirs.runs;
123 g.before_evidence |= theirs.before_evidence;
124 }
125 None => self.groups.push(theirs),
126 }
127 }
128 }
129
130 fn group(&mut self, span: Span, fault: Option<Fault>) -> Option<&mut Failure> {
131 self.groups
132 .iter_mut()
133 .find(|g| g.error.span == span && g.error.fault == fault)
134 }
135}