|
1 | 1 | #![no_std]
|
2 | 2 |
|
3 |
| -//! Annotations a function that "throws" a Result. |
| 3 | +//! Annotates a function that "throws" a Result. |
4 | 4 | //!
|
5 |
| -//! Inside functions tagged with `throws`, you can use `?` and the `throw!` macro to return errors, |
6 |
| -//! but you don't need to wrap the successful return values in `Ok`. |
| 5 | +//! Inside functions tagged with either `throws` or `try_fn`, you can use `?` and the `throw!` |
| 6 | +//! macro to return errors, but you don't need to wrap the successful return values in `Ok`. |
7 | 7 | //!
|
8 |
| -//! Using this syntax, you can write fallible functions almost as if they were nonfallible. Every |
| 8 | +//! Using this syntax, you can write fallible functions almost as if they were infallible. Every |
9 | 9 | //! time a function call would return a `Result`, you "re-raise" the error using `?`, and if you
|
10 | 10 | //! wish to raise your own error, you can return it with the `throw!` macro.
|
11 | 11 | //!
|
| 12 | +//! The difference between `throws` and `try_fn` is in the function signature, with `throws` you |
| 13 | +//! write the signature as if it were infallible too, it will be transformed into a `Result` for |
| 14 | +//! you. With `try_fn` you write the signature as normal and only the body of the function will be |
| 15 | +//! transformed. |
| 16 | +//! |
12 | 17 | //! ## Example
|
| 18 | +//! |
13 | 19 | //! ```
|
14 | 20 | //! use std::io::{self, Read};
|
15 | 21 | //!
|
16 |
| -//! use culpa::{throw, throws}; |
| 22 | +//! use culpa::{throw, throws, try_fn}; |
17 | 23 | //!
|
18 | 24 | //! #[throws(io::Error)]
|
19 | 25 | //! fn check() {
|
|
27 | 33 | //!
|
28 | 34 | //! println!("Okay!");
|
29 | 35 | //! }
|
| 36 | +//! |
| 37 | +//! #[try_fn] |
| 38 | +//! fn check_as_try_fn() -> std::io::Result<()> { |
| 39 | +//! let mut file = std::fs::File::open("The_House_of_the_Spirits.txt")?; |
| 40 | +//! let mut text = String::new(); |
| 41 | +//! file.read_to_string(&mut text)?; |
| 42 | +//! |
| 43 | +//! if !text.starts_with("Barrabas came to us by sea, the child Clara wrote") { |
| 44 | +//! throw!(io::Error::from_raw_os_error(22)); |
| 45 | +//! } |
| 46 | +//! |
| 47 | +//! println!("Okay!"); |
| 48 | +//! } |
30 | 49 | //! ```
|
31 | 50 | //!
|
32 |
| -//! # Default Error Type |
| 51 | +//! # `throws` Default Error Type |
33 | 52 | //!
|
34 |
| -//! This macro supports a "default error type" - if you do not pass a type to the macro, it will |
35 |
| -//! use the type named `Error` in this scope. So if you have defined an error type in this |
36 |
| -//! module, that will be the error thrown by this function. |
| 53 | +//! The `throws` macro supports a "default error type" - if you do not pass a type to the macro, it |
| 54 | +//! will use the type named `Error` in the current scope. So if you have defined an error type in |
| 55 | +//! the module, that will be the error thrown by this function. |
37 | 56 | //!
|
38 | 57 | //! You can access this feature by omitting the arguments entirely or by passing `_` as the type.
|
39 | 58 | //!
|
|
43 | 62 | //! use culpa::throws;
|
44 | 63 | //!
|
45 | 64 | //! // Set the default error type for this module:
|
46 |
| -//! type Error = std::io::Error; |
| 65 | +//! use std::io::Error; |
47 | 66 | //!
|
48 | 67 | //! #[throws]
|
49 | 68 | //! fn print() {
|
|
54 | 73 | //!
|
55 | 74 | //! # Throwing as an Option
|
56 | 75 | //!
|
57 |
| -//! This syntax can also support functions which return an `Option` instead of a `Result`. The |
58 |
| -//! way to access this is to pass `as Option` as the argument to `throw`. |
| 76 | +//! This syntax can also support functions which return an `Option` instead of a `Result`. To use |
| 77 | +//! this with `throws` pass `as Option` as the argument in place of the error type, to use it with |
| 78 | +//! `try_fn` just put it as the return type like normal |
59 | 79 | //!
|
60 | 80 | //! In functions that return `Option`, you can use the `throw!()` macro without any argument to
|
61 | 81 | //! return `None`.
|
62 | 82 | //!
|
63 | 83 | //! ## Example
|
64 | 84 | //!
|
65 | 85 | //! ```
|
66 |
| -//! use culpa::{throw, throws}; |
67 |
| -//! |
68 |
| -//! #[throws(as Option)] |
| 86 | +//! #[culpa::throws(as Option)] |
69 | 87 | //! fn example<T: Eq + Ord>(slice: &[T], needle: &T) -> usize {
|
70 | 88 | //! if !slice.contains(needle) {
|
71 |
| -//! throw!(); |
| 89 | +//! culpa::throw!(); |
| 90 | +//! } |
| 91 | +//! slice.binary_search(needle).ok()? |
| 92 | +//! } |
| 93 | +//! |
| 94 | +//! #[culpa::try_fn] |
| 95 | +//! fn example_as_try_fn<T: Eq + Ord>(slice: &[T], needle: &T) -> Option<usize> { |
| 96 | +//! if !slice.contains(needle) { |
| 97 | +//! culpa::throw!(); |
72 | 98 | //! }
|
73 | 99 | //! slice.binary_search(needle).ok()?
|
74 | 100 | //! }
|
|
78 | 104 | //!
|
79 | 105 | //! The `?` syntax in Rust is controlled by a trait called `Try`, which is currently unstable.
|
80 | 106 | //! Because this feature is unstable and I don't want to maintain compatibility if its interface
|
81 |
| -//! changes, this crate currently only works with two stable `Try` types: Result and Option. |
| 107 | +//! changes, this crate currently only works with two stable `Try` types: `Result` and `Option`. |
82 | 108 | //! However, its designed so that it will hopefully support other `Try` types as well in the
|
83 | 109 | //! future.
|
84 | 110 | //!
|
85 | 111 | //! It's worth noting that `Try` also has some other stable implementations: specifically `Poll`.
|
86 | 112 | //! Because of the somewhat unusual implementation of `Try` for those types, this crate does not
|
87 | 113 | //! support `throws` syntax on functions that return `Poll` (so you can't use this syntax when
|
88 |
| -//! implementing a Future by hand, for example). I hope to come up with a way to support Poll in |
89 |
| -//! the future. |
| 114 | +//! implementing a `Future` by hand, for example). I hope to come up with a way to support `Poll` |
| 115 | +//! in the future. |
90 | 116 |
|
91 | 117 | #[doc(inline)]
|
92 | 118 | /// Annotates a function that "throws" a Result.
|
93 | 119 | ///
|
94 | 120 | /// See the main crate docs for more details.
|
95 | 121 | pub use culpa_macros::throws;
|
96 | 122 |
|
| 123 | +#[doc(inline)] |
| 124 | +/// Annotates a function that implicitly wraps a try block. |
| 125 | +/// |
| 126 | +/// See the main crate docs for more details. |
| 127 | +pub use culpa_macros::try_fn; |
| 128 | + |
97 | 129 | /// Throw an error.
|
98 | 130 | ///
|
99 | 131 | /// This macro is equivalent to `Err($err)?`.
|
@@ -215,3 +247,9 @@ pub mod __internal {
|
215 | 247 | /// }
|
216 | 248 | /// ```
|
217 | 249 | const _DEAD_CODE: () = ();
|
| 250 | + |
| 251 | +/// ```compile_fail |
| 252 | +/// #[culpa::try_(())] |
| 253 | +/// fn f() {} |
| 254 | +/// ``` |
| 255 | +const _NO_TRY_ARGS: () = (); |
0 commit comments