Skip to content

Commit 8a41b40

Browse files
authored
Merge pull request #37 from ubolonton/replace-failure
Replace `failure` with `thiserror` and `anyhow`
2 parents 661dbee + 01f19c9 commit 8a41b40

File tree

8 files changed

+29
-29
lines changed

8 files changed

+29
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
55

66
## [Unreleased]
7+
- Replaced `failure` with `anyhow` and `thiserror`. Re-export `anyhow` as `emacs::error::anyhow`.
78

89
## [0.15.1] - 2021-01-06
910
- Fixed compilation errors on new versions of `syn`, which removed the `export` module.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ include = [
2323
]
2424

2525
[dependencies]
26-
failure = { version = "0.1.5", features = ["std"] }
27-
failure_derive = "0.1.5"
26+
thiserror = "1.0"
27+
anyhow = "1.0"
2828
ctor = "0.1.12"
2929
once_cell = "1.2.0"
3030
emacs_module = { path = "emacs-module", version = "0.12.0" }

guide/src/custom-types.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,10 @@ fn init(env: &Env) -> Result<()> {
6565
}
6666

6767
#[defun]
68-
fn process(v: Value<'_>) -> Result<Value<'_>> {
68+
fn get(v: Value<'_>, key: String) -> Result<Value<'_>> {
6969
let lock: &RwLock<Map> = v.into_rust()?;
70-
let map = lock.try_read().map_err(|_| failure::err_msg("map is busy"))?;
71-
Ok(map.get(&key).into_lisp(v.env)?)
70+
let map = lock.try_read().map_err(|_| Error::msg("map is busy"))?;
71+
map.get(&key).into_lisp(v.env)
7272
}
7373
```
7474

guide/src/errors.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
Emacs Lisp's [error handling mechanism](https://www.gnu.org/software/emacs/manual/html_node/elisp/Handling-Errors.html) uses [non-local exits](https://www.gnu.org/software/emacs/manual/html_node/elisp/Nonlocal-Exits.html). Rust uses `Result` enum. `emacs-module-rs` converts between the 2 at the Rust-Lisp boundaries (more precisely, Rust-C).
44

5-
The chosen error type is the `Error` struct from [`failure` crate](https://github.com/withoutboats/failure):
5+
The chosen error type is the `Error` struct from [`anyhow` crate](https://github.com/dtolnay/anyhow):
66

77
```rust
8-
pub type Result<T> = result::Result<T, failure::Error>;
8+
pub type Result<T> = result::Result<T, anyhow::Error>;
99
```
1010

1111
## Handling Lisp Errors in Rust
@@ -32,7 +32,7 @@ match env.call("insert", &[some_text]) {
3232
}
3333
```
3434

35-
Note the use of `unsafe` to extract the error symbol as a `Value`. The reason is that, `ErrorKind::Signal` is marked `Send+Sync`, for compatibility with `failure`, while `Value` is lifetime-bound by `env`. The `unsafe` contract here requires the error being handled (and its `TempValue`) to come from this `env`, not from another thread, or from a global/thread-local storage.
35+
Note the use of `unsafe` to extract the error symbol as a `Value`. The reason is that, `ErrorKind::Signal` is marked `Send+Sync`, for compatibility with `anyhow`, while `Value` is lifetime-bound by `env`. The `unsafe` contract here requires the error being handled (and its `TempValue`) to come from this `env`, not from another thread, or from a global/thread-local storage.
3636

3737
### Catching Values Thrown by Lisp
3838

src/error.rs

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
#[doc(no_inline)]
2-
pub use failure::Error;
3-
use failure_derive::Fail;
2+
pub use anyhow::{self, Error};
43
use std::mem::MaybeUninit;
54
use std::result;
65
use std::thread;
76
use std::any::Any;
7+
use thiserror::Error;
88

99
use super::IntoLisp;
1010
use super::{Env, Value};
1111
use emacs_module::*;
12+
use crate::{symbol, GlobalRef};
1213

1314
// We use const instead of enum, in case Emacs add more exit statuses in the future.
1415
// See https://github.com/rust-lang/rust/issues/36927
@@ -21,26 +22,26 @@ pub struct TempValue {
2122
raw: emacs_value,
2223
}
2324

24-
const WRONG_TYPE_USER_PTR: &str = "rust-wrong-type-user-ptr";
25-
const ERROR: &str = "rust-error";
26-
const PANIC: &str = "rust-panic";
25+
pub const WRONG_TYPE_USER_PTR: &str = "rust-wrong-type-user-ptr";
26+
pub const ERROR: &str = "rust-error";
27+
pub const PANIC: &str = "rust-panic";
2728

2829
/// Error types generic to all Rust dynamic modules.
2930
///
3031
/// This list is intended to grow over time and it is not recommended to exhaustively match against
3132
/// it.
32-
#[derive(Debug, Fail)]
33+
#[derive(Debug, Error)]
3334
pub enum ErrorKind {
3435
/// An [error] signaled by Lisp code.
3536
///
3637
/// [error]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Signaling-Errors.html
37-
#[fail(display = "Non-local signal: symbol={:?} data={:?}", symbol, data)]
38+
#[error("Non-local signal: symbol={symbol:?} data={data:?}")]
3839
Signal { symbol: TempValue, data: TempValue },
3940

4041
/// A [non-local exit] thrown by Lisp code.
4142
///
4243
/// [non-local exit]: https://www.gnu.org/software/emacs/manual/html_node/elisp/Catch-and-Throw.html
43-
#[fail(display = "Non-local throw: tag={:?} value={:?}", tag, value)]
44+
#[error("Non-local throw: tag={tag:?} value={value:?}")]
4445
Throw { tag: TempValue, value: TempValue },
4546

4647
/// An error indicating that the given value is not a `user-ptr` of the expected type.
@@ -71,7 +72,7 @@ pub enum ErrorKind {
7172
/// (unwrap (wrap 7)) ; 7
7273
/// (unwrap (wrap-f 7)) ; *** Eval error *** Wrong type user-ptr: "expected: RefCell"
7374
/// ```
74-
#[fail(display = "expected: {}", expected)]
75+
#[error("expected: {expected}")]
7576
WrongTypeUserPtr { expected: &'static str },
7677
}
7778

@@ -142,7 +143,7 @@ impl Env {
142143
Err(error) => match error.downcast_ref::<ErrorKind>() {
143144
Some(err) => self.handle_known(err),
144145
_ => self
145-
.signal_str(ERROR, &format!("{}", error))
146+
.signal_internal(symbol::rust_error, &format!("{}", error))
146147
.unwrap_or_else(|_| panic!("Failed to signal {}", error)),
147148
},
148149
}
@@ -168,7 +169,7 @@ impl Env {
168169
if let Err(error) = m {
169170
m = Ok(format!("{:#?}", error));
170171
}
171-
self.signal_str(PANIC, &m.expect("Logic error")).expect("Fail to signal panic")
172+
self.signal_internal(symbol::rust_panic, &m.expect("Logic error")).expect("Fail to signal panic")
172173
}
173174
}
174175
}
@@ -191,17 +192,15 @@ impl Env {
191192
ErrorKind::Signal { symbol, data } => self.signal(symbol.raw, data.raw),
192193
ErrorKind::Throw { tag, value } => self.throw(tag.raw, value.raw),
193194
ErrorKind::WrongTypeUserPtr { .. } => self
194-
.signal_str(WRONG_TYPE_USER_PTR, &format!("{}", err))
195+
.signal_internal(symbol::rust_wrong_type_user_ptr, &format!("{}", err))
195196
.unwrap_or_else(|_| panic!("Failed to signal {}", err)),
196197
}
197198
}
198199

199-
// TODO: Prepare static values for the symbols.
200-
fn signal_str(&self, symbol: &str, message: &str) -> Result<emacs_value> {
200+
fn signal_internal(&self, symbol: &GlobalRef, message: &str) -> Result<emacs_value> {
201201
let message = message.into_lisp(&self)?;
202202
let data = self.list([message])?;
203-
let symbol = self.intern(symbol)?;
204-
unsafe { Ok(self.signal(symbol.raw, data.raw)) }
203+
unsafe { Ok(self.signal(symbol.bind(self).raw, data.raw)) }
205204
}
206205

207206
fn define_error(&self, name: &str, message: &str, parents: &[&str]) -> Result<Value<'_>> {

src/lib.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,14 @@
3030
#[doc(inline)]
3131
pub use emacs_macros::{defun, module};
3232

33-
#[doc(no_inline)]
34-
pub use failure::{self, Error};
35-
3633
#[doc(inline)]
3734
pub use self::{
3835
env::Env,
3936
value::Value,
4037
global::GlobalRef,
4138
types::{FromLisp, IntoLisp, Transfer, Vector},
4239
func::CallEnv,
43-
error::{ErrorKind, Result, ResultExt},
40+
error::{ErrorKind, Result, ResultExt, Error},
4441
};
4542

4643
#[macro_use] mod macros;

src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ macro_rules! global_refs {
7474
};
7575
($registrator_name:ident ($init_method:ident) =>
7676
$(
77-
$name:ident $( => $lisp_name:literal )?
77+
$name:ident $( => $lisp_name:expr )?
7878
)*
7979
) => {
8080
global_refs! {

src/symbol.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@
22

33
global_refs! {common(init_to_symbol) =>
44
nil t
5+
rust_error => crate::error::ERROR
6+
rust_panic => crate::error::PANIC
7+
rust_wrong_type_user_ptr => crate::error::WRONG_TYPE_USER_PTR
58
}

0 commit comments

Comments
 (0)