Skip to content

Commit 581121b

Browse files
Make ProblemReport to perform a shallow copy on clone (#158)
1 parent 0d155bf commit 581121b

File tree

1 file changed

+36
-25
lines changed

1 file changed

+36
-25
lines changed

rust/catalyst-types/src/problem_report.rs

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -96,31 +96,21 @@ impl Serialize for Report {
9696
}
9797
}
9898

99-
/// The Problem Report list
100-
#[derive(Clone)]
101-
struct Context(Arc<String>);
102-
103-
impl Serialize for Context {
104-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
105-
where S: serde::Serializer {
106-
let str = self.0.as_ref();
107-
serializer.serialize_str(str)
108-
}
109-
}
110-
111-
/// Problem Report
112-
#[derive(Clone, Serialize)]
113-
pub struct ProblemReport {
99+
/// An inner state of the report.
100+
#[derive(Serialize)]
101+
struct State {
114102
/// What context does the whole report have
115-
context: Context,
103+
context: String,
116104
/// The report itself
117-
// Note, we use this because it allows:
118-
// 1. Cheap copy of this struct.
119-
// 2. Ergonomic Inner mutability.
120-
// 3. Safety for the Problem Report to be used across threads
121105
report: Report,
122106
}
123107

108+
/// Problem Report.
109+
///
110+
/// This structure allows making a cheap copies that share the same state.
111+
#[derive(Clone, Serialize)]
112+
pub struct ProblemReport(Arc<State>);
113+
124114
impl ProblemReport {
125115
/// Creates a new `ProblemReport` with the given context string.
126116
///
@@ -138,10 +128,11 @@ impl ProblemReport {
138128
/// ```
139129
#[must_use]
140130
pub fn new(context: &str) -> Self {
141-
Self {
142-
context: Context(Arc::new(context.to_string())),
131+
let state = State {
132+
context: context.to_owned(),
143133
report: Report(ConcurrentVec::new()),
144-
}
134+
};
135+
Self(Arc::new(state))
145136
}
146137

147138
/// Determines if the problem report contains any issues.
@@ -164,12 +155,12 @@ impl ProblemReport {
164155
/// ```
165156
#[must_use]
166157
pub fn is_problematic(&self) -> bool {
167-
!self.report.0.is_empty()
158+
!self.0.report.0.is_empty()
168159
}
169160

170161
/// Add an entry to the report
171162
fn add_entry(&self, kind: Kind, context: &str) {
172-
self.report.0.push(Entry {
163+
self.0.report.0.push(Entry {
173164
kind,
174165
context: context.to_owned(),
175166
});
@@ -459,3 +450,23 @@ impl ProblemReport {
459450
);
460451
}
461452
}
453+
454+
#[cfg(test)]
455+
mod tests {
456+
use super::*;
457+
458+
// Check that the Clone implementation performs the shallow copy, so all instances share
459+
// the same state.
460+
#[test]
461+
fn clone_shared_state() {
462+
let original = ProblemReport::new("top level context");
463+
assert!(!original.is_problematic());
464+
465+
let clone = original.clone();
466+
clone.other("description", "error context");
467+
assert!(clone.is_problematic());
468+
469+
// The original report must have the same (problematic) state.
470+
assert!(original.is_problematic());
471+
}
472+
}

0 commit comments

Comments
 (0)