11#[ doc( no_inline) ]
2+ use std:: { any:: Any , fmt:: Display , mem:: MaybeUninit , result, thread} ;
3+
24pub use anyhow:: { self , Error } ;
3- use std:: mem:: MaybeUninit ;
4- use std:: result;
5- use std:: thread;
6- use std:: any:: Any ;
75use thiserror:: Error ;
86
9- use super :: IntoLisp ;
10- use super :: { Env , Value } ;
117use emacs_module:: * ;
12- use crate :: { symbol:: { self , IntoLispSymbol } , GlobalRef } ;
13- use crate :: call:: IntoLispArgs ;
8+
9+ use crate :: {
10+ Env , Value , IntoLisp ,
11+ GlobalRef ,
12+ symbol:: { self , IntoLispSymbol } ,
13+ call:: IntoLispArgs ,
14+ } ;
1415
1516// We use const instead of enum, in case Emacs add more exit statuses in the future.
1617// See https://github.com/rust-lang/rust/issues/36927
@@ -132,6 +133,7 @@ impl TempValue {
132133// XXX: Technically these are unsound, but they are necessary to use the `Fail` trait. We ensure
133134// safety by marking TempValue methods as unsafe.
134135unsafe impl Send for TempValue { }
136+
135137unsafe impl Sync for TempValue { }
136138
137139impl Env {
@@ -149,16 +151,14 @@ impl Env {
149151 Err ( ErrorKind :: Signal {
150152 symbol : unsafe { TempValue :: new ( symbol. assume_init ( ) ) } ,
151153 data : unsafe { TempValue :: new ( data. assume_init ( ) ) } ,
152- }
153- . into ( ) )
154+ } . into ( ) )
154155 }
155156 ( THROW , tag, value) => {
156157 self . non_local_exit_clear ( ) ;
157158 Err ( ErrorKind :: Throw {
158159 tag : unsafe { TempValue :: new ( tag. assume_init ( ) ) } ,
159160 value : unsafe { TempValue :: new ( value. assume_init ( ) ) } ,
160- }
161- . into ( ) )
161+ } . into ( ) )
162162 }
163163 _ => panic ! ( "Unexpected non local exit status {}" , status) ,
164164 }
@@ -195,7 +195,7 @@ impl Env {
195195 if let Err ( error) = m {
196196 m = match error. downcast :: < ErrorKind > ( ) {
197197 // TODO: Explain safety.
198- Ok ( err) => unsafe { return self . handle_known ( & * err) } ,
198+ Ok ( err) => unsafe { return self . handle_known ( & * err) ; } ,
199199 Err ( error) => Err ( error) ,
200200 }
201201 }
@@ -210,12 +210,12 @@ impl Env {
210210 pub ( crate ) fn define_core_errors ( & self ) -> Result < ( ) > {
211211 // FIX: Make panics louder than errors, by somehow make sure that 'rust-panic is
212212 // not a sub-type of 'error.
213- self . define_error ( symbol:: rust_panic, "Rust panic" , ( symbol:: error, ) ) ?;
214- self . define_error ( symbol:: rust_error, "Rust error" , ( symbol:: error, ) ) ?;
213+ self . define_error ( symbol:: rust_panic, "Rust panic" , ( symbol:: error, ) ) ?;
214+ self . define_error ( symbol:: rust_error, "Rust error" , ( symbol:: error, ) ) ?;
215215 self . define_error (
216216 symbol:: rust_wrong_type_user_ptr,
217217 "Wrong type user-ptr" ,
218- ( symbol:: rust_error, self . intern ( "wrong-type-argument" ) ?)
218+ ( symbol:: rust_error, self . intern ( "wrong-type-argument" ) ?) ,
219219 ) ?;
220220 Ok ( ( ) )
221221 }
@@ -287,46 +287,21 @@ impl Env {
287287 }
288288}
289289
290- /// Emacs-specific extension methods for [`Result`].
290+ /// Emacs-specific extension methods for the standard library's [`Result`].
291291///
292- /// [`Result`]: type. Result.html
292+ /// [`Result`]: result:: Result
293293pub trait ResultExt < T , E > {
294- /// Unwraps a result, yielding the content of an [`Ok`].
295- ///
296- /// # Panics
297- ///
298- /// Panics if the value is an [`Err`], using a sensible panic value.
294+ /// Converts the error into a Lisp signal if this result is an [`Err`]. The first element of the
295+ /// associated signal data will be a string formatted with [`Display::fmt`].
299296 ///
300- /// If the underlying error is an [`ErrorKind`], it will be used as the value of the panic,
301- /// which makes the `#[defun]` behave as if the corresponding non-local exit was propagated.
302- /// Otherwise, tries to use [`Display`] to get a descriptive error message.
303- ///
304- /// This is useful when errors cannot be propagated using [`Result`], e.g. callbacks whose types
305- /// are dictated by 3rd-party libraries.
306- ///
307- /// # Safety
308- ///
309- /// The panic must not propagate across an FFI boundary, e.g. this must not be used in callbacks
310- /// that will be called by C code. See Rust's [`issue #52652`].
311- ///
312- /// [`Ok`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok
313- /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
314- /// [`ErrorKind`]: enum.ErrorKind.html
315- /// [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
316- /// [`Result`]: type.Result.html
317- /// [`issue #52652`]: https://github.com/rust-lang/rust/issues/52652
318- #[ deprecated( since = "0.12.0" , note = "Use Result or a variable to track error instead" ) ]
319- unsafe fn unwrap_or_propagate ( self ) -> T ;
297+ /// If the result is an [`Ok`], it is returned unchanged.
298+ fn or_signal < ' e , S > ( self , env : & ' e Env , symbol : S ) -> Result < T > where S : IntoLispSymbol < ' e > ;
320299}
321300
322- impl < T > ResultExt < T , Error > for Result < T > {
323- #[ inline]
324- unsafe fn unwrap_or_propagate ( self ) -> T {
325- self . unwrap_or_else ( |error| {
326- match error. downcast :: < ErrorKind > ( ) {
327- Ok ( err) => panic ! ( err) ,
328- Err ( error) => panic ! ( "{}" , error) ,
329- } ;
330- } )
301+ impl < T , E : Display > ResultExt < T , E > for result:: Result < T , E > {
302+ fn or_signal < ' e , S > ( self , env : & ' e Env , symbol : S ) -> Result < T > where S : IntoLispSymbol < ' e > {
303+ self . or_else ( |err| env. signal ( symbol, (
304+ format ! ( "{}" , err) ,
305+ ) ) )
331306 }
332307}
0 commit comments