1# Using generic types
2
3Error types enhanced by SNAFU may contain generic type and lifetime parameters.
4
5## Types
6
7```rust
8# use snafu::{Snafu, ensure};
9#
10#[derive(Debug, Snafu)]
11enum Error<T>
12where
13    T: std::fmt::Display,
14{
15    #[snafu(display("The value {} was too large", value))]
16    TooLarge { value: T, limit: u32 },
17
18    #[snafu(display("The value {} was too small", value))]
19    TooSmall { value: T, limit: u32 },
20}
21
22fn validate_number(value: u8) -> Result<u8, Error<u8>> {
23    ensure!(value <= 200, TooLarge { value, limit: 100u32 });
24    ensure!(value >= 100, TooSmall { value, limit: 200u32 });
25    Ok(value)
26}
27
28fn validate_string(value: &str) -> Result<&str, Error<String>> {
29    ensure!(value.len() <= 20, TooLarge { value, limit: 10u32 });
30    ensure!(value.len() >= 10, TooSmall { value, limit: 20u32 });
31    Ok(value)
32}
33```
34
35## Lifetimes
36
37```rust
38# use snafu::{Snafu, ensure};
39#
40#[derive(Debug, Snafu)]
41enum Error<'a> {
42    #[snafu(display("The username {} contains the bad word {}", value, word))]
43    BadWord { value: &'a str, word: &'static str },
44}
45
46fn validate_username<'a>(value: &'a str) -> Result<&'a str, Error<'a>> {
47    ensure!(!value.contains("stinks"), BadWord { value, word: "stinks" });
48    ensure!(!value.contains("smells"), BadWord { value, word: "smells" });
49    Ok(value)
50}
51```
52
53## Caveats
54
55A SNAFU [opaque type](crate::guide::opaque) requires that the
56contained type implements several traits, such as
57`Display`. However, type constraints cannot be automatically added
58to the opaque type because they are not allowed to reference the
59inner type without also exposing it publicly.
60
61The best option is to avoid using a generic opaque error. If you
62choose to expose a generic opaque error, you will likely need to add
63explicit duplicate type constraints:
64
65```rust
66use snafu::Snafu;
67
68#[derive(Debug, Snafu)]
69struct ApiError<T>(Error<T>)
70where                        // These lines are required to
71   T: std::fmt::Debug;       // ensure that delegation can work.
72
73#[derive(Debug, Snafu)]
74enum Error<T>
75where
76    T: std::fmt::Debug,
77{
78    #[snafu(display("Boom: {:?}", value))]
79    Boom { value: T },
80}
81```
82