Skip to content

Commit 2051f87

Browse files
committed
refactor: use anyhow::Error in place of String
Use the anyhow crate for errors where we're currently just using String. This makes it easier to add context to errors and avoids the need to convert to a string when bubbling up errors. Also box the `Error` field in `RichError` to reduce its size and keep clippy happy.
1 parent f930ae3 commit 2051f87

File tree

7 files changed

+40
-34
lines changed

7 files changed

+40
-34
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ either = "1.12.0"
3232
itertools = "0.13.0"
3333
arbitrary = { version = "1", optional = true, features = ["derive"] }
3434
clap = "4.5.37"
35+
anyhow = "1.0.98"
3536

3637
[target.wasm32-unknown-unknown.dependencies]
3738
getrandom = { version = "0.2", features = ["js"] }

clippy.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
11
msrv = "1.78.0"
2-
# We have an error type, `RichError`, of size 144. This is pushing it but probably fine.
3-
large-error-threshold = 145

src/error.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl<T> WithFile<T> for Result<T, RichError> {
195195
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
196196
pub struct RichError {
197197
/// The error that occurred.
198-
error: Error,
198+
error: Box<Error>,
199199
/// Area that the error spans inside the file.
200200
span: Span,
201201
/// File in which the error occurred.
@@ -208,7 +208,7 @@ impl RichError {
208208
/// Create a new error with context.
209209
pub fn new(error: Error, span: Span) -> RichError {
210210
RichError {
211-
error,
211+
error: Box::new(error),
212212
span,
213213
file: None,
214214
}
@@ -266,7 +266,7 @@ impl std::error::Error for RichError {}
266266

267267
impl From<RichError> for Error {
268268
fn from(error: RichError) -> Self {
269-
error.error
269+
*error.error
270270
}
271271
}
272272

src/lib.rs

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl TemplateProgram {
5151
/// ## Errors
5252
///
5353
/// The string is not a valid Simfony program.
54-
pub fn new<Str: Into<Arc<str>>>(s: Str) -> Result<Self, String> {
54+
pub fn new<Str: Into<Arc<str>>>(s: Str) -> anyhow::Result<Self> {
5555
let file = s.into();
5656
let parse_program = parse::Program::parse_from_str(&file)?;
5757
let ast_program = ast::Program::analyze(&parse_program).with_file(Arc::clone(&file))?;
@@ -76,10 +76,9 @@ impl TemplateProgram {
7676
&self,
7777
arguments: Arguments,
7878
include_debug_symbols: bool,
79-
) -> Result<CompiledProgram, String> {
79+
) -> anyhow::Result<CompiledProgram> {
8080
arguments
81-
.is_consistent(self.simfony.parameters())
82-
.map_err(|error| error.to_string())?;
81+
.is_consistent(self.simfony.parameters())?;
8382
Ok(CompiledProgram {
8483
debug_symbols: self.simfony.debug_symbols(self.file.as_ref()),
8584
simplicity: self
@@ -121,7 +120,7 @@ impl CompiledProgram {
121120
s: Str,
122121
arguments: Arguments,
123122
include_debug_symbols: bool,
124-
) -> Result<Self, String> {
123+
) -> anyhow::Result<Self> {
125124
TemplateProgram::new(s)
126125
.and_then(|template| template.instantiate(arguments, include_debug_symbols))
127126
}
@@ -142,7 +141,7 @@ impl CompiledProgram {
142141
///
143142
/// - Witness values have a different type than declared in the Simfony program.
144143
/// - There are missing witness values.
145-
pub fn satisfy(&self, witness_values: WitnessValues) -> Result<SatisfiedProgram, String> {
144+
pub fn satisfy(&self, witness_values: WitnessValues) -> anyhow::Result<SatisfiedProgram> {
146145
self.satisfy_with_env(witness_values, None)
147146
}
148147

@@ -157,17 +156,16 @@ impl CompiledProgram {
157156
&self,
158157
witness_values: WitnessValues,
159158
env: Option<&ElementsEnv<Arc<elements::Transaction>>>,
160-
) -> Result<SatisfiedProgram, String> {
159+
) -> anyhow::Result<SatisfiedProgram> {
161160
witness_values
162-
.is_consistent(&self.witness_types)
163-
.map_err(|e| e.to_string())?;
161+
.is_consistent(&self.witness_types)?;
164162
let simplicity_witness = named::to_witness_node(&self.simplicity, witness_values);
165163
let simplicity_redeem = match env {
166-
Some(env) => simplicity_witness.finalize_pruned(env),
167-
None => simplicity_witness.finalize_unpruned(),
164+
Some(env) => simplicity_witness.finalize_pruned(env)?,
165+
None => simplicity_witness.finalize_unpruned()?,
168166
};
169167
Ok(SatisfiedProgram {
170-
simplicity: simplicity_redeem.map_err(|e| e.to_string())?,
168+
simplicity: simplicity_redeem,
171169
debug_symbols: self.debug_symbols.clone(),
172170
})
173171
}
@@ -193,7 +191,7 @@ impl SatisfiedProgram {
193191
arguments: Arguments,
194192
witness_values: WitnessValues,
195193
include_debug_symbols: bool,
196-
) -> Result<Self, String> {
194+
) -> anyhow::Result<Self> {
197195
let compiled = CompiledProgram::new(s, arguments, include_debug_symbols)?;
198196
compiled.satisfy(witness_values)
199197
}
@@ -620,7 +618,7 @@ fn main() {
620618
) {
621619
Ok(_) => panic!("Accepted faulty program"),
622620
Err(error) => {
623-
if !error.contains("Expected expression of type `bool`, found type `()`") {
621+
if !error.to_string().contains("Expected expression of type `bool`, found type `()`") {
624622
panic!("Unexpected error: {error}")
625623
}
626624
}

src/main.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
11
use base64::display::Base64Display;
22
use base64::engine::general_purpose::STANDARD;
33
use clap::{Arg, ArgAction, Command};
4+
use anyhow::Context;
45

56
use simfony::{Arguments, CompiledProgram};
67
use std::env;
78

8-
// Directly returning Result<(), String> prints the error using Debug
9-
// Add indirection via run() to print errors using Display
10-
fn main() {
11-
if let Err(error) = run() {
12-
eprintln!("{error}");
13-
std::process::exit(1);
14-
}
15-
}
16-
17-
fn run() -> Result<(), String> {
9+
fn main() -> anyhow::Result<()> {
1810
let command = {
1911
Command::new(env!("CARGO_BIN_NAME"))
2012
.about(
@@ -56,7 +48,10 @@ fn run() -> Result<(), String> {
5648

5749
let prog_file = matches.get_one::<String>("prog_file").unwrap();
5850
let prog_path = std::path::Path::new(prog_file);
59-
let prog_text = std::fs::read_to_string(prog_path).map_err(|e| e.to_string())?;
51+
let prog_text = {
52+
std::fs::read_to_string(prog_path)
53+
.with_context(|| format!("Failed to read {}", prog_path.display()))?
54+
};
6055
let include_debug_symbols = matches.get_flag("debug");
6156

6257
let compiled = CompiledProgram::new(prog_text, Arguments::default(), include_debug_symbols)?;
@@ -65,10 +60,16 @@ fn run() -> Result<(), String> {
6560
let witness_opt = {
6661
matches
6762
.get_one::<String>("wit_file")
68-
.map(|wit_file| -> Result<simfony::WitnessValues, String> {
63+
.map(|wit_file| -> anyhow::Result<simfony::WitnessValues> {
6964
let wit_path = std::path::Path::new(wit_file);
70-
let wit_text = std::fs::read_to_string(wit_path).map_err(|e| e.to_string())?;
71-
let witness = serde_json::from_str::<simfony::WitnessValues>(&wit_text).unwrap();
65+
let wit_text = {
66+
std::fs::read_to_string(wit_path)
67+
.with_context(|| format!("Failed to read {}", wit_path.display()))?
68+
};
69+
let witness = {
70+
serde_json::from_str::<simfony::WitnessValues>(&wit_text)
71+
.with_context(|| format!("Failed to parse file {}", wit_path.display()))?
72+
};
7273
Ok(witness)
7374
})
7475
.transpose()?

src/witness.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ mod tests {
240240
Ok(_) => panic!("Ill-typed witness assignment was falsely accepted"),
241241
Err(error) => assert_eq!(
242242
"Witness `A` was declared with type `u32` but its assigned value is of type `u16`",
243-
error
243+
error.to_string(),
244244
),
245245
}
246246
}
@@ -259,6 +259,7 @@ fn main() {
259259
Ok(_) => panic!("Witness outside main was falsely accepted"),
260260
Err(error) => {
261261
assert!(error
262+
.to_string()
262263
.contains("Witness expressions are not allowed outside the `main` function"))
263264
}
264265
}

0 commit comments

Comments
 (0)