• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(clippy::needless_late_init, clippy::uninlined_format_args)]
2 
3 use core::fmt::{self, Debug, Display};
4 use core::str::FromStr;
5 use thiserror::Error;
6 
7 pub struct NoFormat;
8 
9 #[derive(Debug)]
10 pub struct DebugOnly;
11 
12 pub struct DisplayOnly;
13 
14 impl Display for DisplayOnly {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result15     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
16         f.write_str("display only")
17     }
18 }
19 
20 #[derive(Debug)]
21 pub struct DebugAndDisplay;
22 
23 impl Display for DebugAndDisplay {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result24     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
25         f.write_str("debug and display")
26     }
27 }
28 
29 // Should expand to:
30 //
31 //     impl<E> Display for EnumDebugField<E>
32 //     where
33 //         E: Debug;
34 //
35 //     impl<E> Error for EnumDebugField<E>
36 //     where
37 //         Self: Debug + Display;
38 //
39 #[derive(Error, Debug)]
40 pub enum EnumDebugGeneric<E> {
41     #[error("{0:?}")]
42     FatalError(E),
43 }
44 
45 // Should expand to:
46 //
47 //     impl<E> Display for EnumFromGeneric<E>;
48 //
49 //     impl<E> Error for EnumFromGeneric<E>
50 //     where
51 //         EnumDebugGeneric<E>: Error + 'static,
52 //         Self: Debug + Display;
53 //
54 #[derive(Error, Debug)]
55 pub enum EnumFromGeneric<E> {
56     #[error("enum from generic")]
57     Source(#[from] EnumDebugGeneric<E>),
58 }
59 
60 // Should expand to:
61 //
62 //     impl<HasDisplay, HasDebug, HasNeither> Display
63 //         for EnumCompound<HasDisplay, HasDebug, HasNeither>
64 //     where
65 //         HasDisplay: Display,
66 //         HasDebug: Debug;
67 //
68 //     impl<HasDisplay, HasDebug, HasNeither> Error
69 //         for EnumCompound<HasDisplay, HasDebug, HasNeither>
70 //     where
71 //         Self: Debug + Display;
72 //
73 #[derive(Error)]
74 pub enum EnumCompound<HasDisplay, HasDebug, HasNeither> {
75     #[error("{0} {1:?}")]
76     DisplayDebug(HasDisplay, HasDebug),
77     #[error("{0}")]
78     Display(HasDisplay, HasNeither),
79     #[error("{1:?}")]
80     Debug(HasNeither, HasDebug),
81 }
82 
83 impl<HasDisplay, HasDebug, HasNeither> Debug for EnumCompound<HasDisplay, HasDebug, HasNeither> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result84     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85         f.write_str("EnumCompound")
86     }
87 }
88 
89 #[test]
test_display_enum_compound()90 fn test_display_enum_compound() {
91     let mut instance: EnumCompound<DisplayOnly, DebugOnly, NoFormat>;
92 
93     instance = EnumCompound::DisplayDebug(DisplayOnly, DebugOnly);
94     assert_eq!(format!("{}", instance), "display only DebugOnly");
95 
96     instance = EnumCompound::Display(DisplayOnly, NoFormat);
97     assert_eq!(format!("{}", instance), "display only");
98 
99     instance = EnumCompound::Debug(NoFormat, DebugOnly);
100     assert_eq!(format!("{}", instance), "DebugOnly");
101 }
102 
103 // Should expand to:
104 //
105 //     impl<E> Display for EnumTransparentGeneric<E>
106 //     where
107 //         E: Display;
108 //
109 //     impl<E> Error for EnumTransparentGeneric<E>
110 //     where
111 //         E: Error,
112 //         Self: Debug + Display;
113 //
114 #[derive(Error, Debug)]
115 pub enum EnumTransparentGeneric<E> {
116     #[error(transparent)]
117     Other(E),
118 }
119 
120 // Should expand to:
121 //
122 //     impl<E> Display for StructDebugGeneric<E>
123 //     where
124 //         E: Debug;
125 //
126 //     impl<E> Error for StructDebugGeneric<E>
127 //     where
128 //         Self: Debug + Display;
129 //
130 #[derive(Error, Debug)]
131 #[error("{underlying:?}")]
132 pub struct StructDebugGeneric<E> {
133     pub underlying: E,
134 }
135 
136 // Should expand to:
137 //
138 //     impl<E> Error for StructFromGeneric<E>
139 //     where
140 //         StructDebugGeneric<E>: Error + 'static,
141 //         Self: Debug + Display;
142 //
143 #[derive(Error, Debug)]
144 pub struct StructFromGeneric<E> {
145     #[from]
146     pub source: StructDebugGeneric<E>,
147 }
148 
149 // Should expand to:
150 //
151 //     impl<E> Display for StructTransparentGeneric<E>
152 //     where
153 //         E: Display;
154 //
155 //     impl<E> Error for StructTransparentGeneric<E>
156 //     where
157 //         E: Error,
158 //         Self: Debug + Display;
159 //
160 #[derive(Error, Debug)]
161 #[error(transparent)]
162 pub struct StructTransparentGeneric<E>(pub E);
163 
164 // Should expand to:
165 //
166 //     impl<T: FromStr> Display for AssociatedTypeError<T>
167 //     where
168 //         T::Err: Display;
169 //
170 //     impl<T: FromStr> Error for AssociatedTypeError<T>
171 //     where
172 //         Self: Debug + Display;
173 //
174 #[derive(Error, Debug)]
175 pub enum AssociatedTypeError<T: FromStr> {
176     #[error("couldn't parse matrix")]
177     Other,
178     #[error("couldn't parse entry: {0}")]
179     EntryParseError(T::Err),
180 }
181 
182 // Regression test for https://github.com/dtolnay/thiserror/issues/345
183 #[test]
test_no_bound_on_named_fmt()184 fn test_no_bound_on_named_fmt() {
185     #[derive(Error, Debug)]
186     #[error("{thing}", thing = "...")]
187     struct Error<T> {
188         thing: T,
189     }
190 
191     let error = Error { thing: DebugOnly };
192     assert_eq!(error.to_string(), "...");
193 }
194 
195 #[test]
test_multiple_bound()196 fn test_multiple_bound() {
197     #[derive(Error, Debug)]
198     #[error("0x{thing:x} 0x{thing:X}")]
199     pub struct Error<T> {
200         thing: T,
201     }
202 
203     let error = Error { thing: 0xFFi32 };
204     assert_eq!(error.to_string(), "0xff 0xFF");
205 }
206