@@ -194,14 +194,47 @@ mod prim_bool {}
194
194
/// # `!` and traits
195
195
///
196
196
/// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl`
197
- /// which doesn't `panic!`. As it turns out, most traits can have an `impl` for `!`. Take [`Debug`]
197
+ /// which doesn't `panic!`. The reason is that functions returning an `impl Trait` cannot have
198
+ /// divergence, i.e., returning `!`, as their only possible code path. As an example, this code
199
+ /// doesn't compile:
200
+ ///
201
+ /// ```compile_fail
202
+ /// use core::ops::Add;
203
+ ///
204
+ /// fn foo() -> impl Add<u32> {
205
+ /// unimplemented!()
206
+ /// }
207
+ /// ```
208
+ ///
209
+ /// While this code does:
210
+ ///
211
+ /// ```
212
+ /// use core::ops::Add;
213
+ ///
214
+ /// fn foo() -> impl Add<u32> {
215
+ /// if true {
216
+ /// unimplemented!()
217
+ /// } else {
218
+ /// 0
219
+ /// }
220
+ /// }
221
+ /// ```
222
+ ///
223
+ /// The reason is that, in the first example, there are many possible types for `!` to coerce
224
+ /// to, because the function's return value is polymorphic. However, in the second example, the
225
+ /// other branch returns `0` which has a concrete type that `!` can be coerced to. See issue
226
+ /// [#36375] for more information on this quirk of `!`.
227
+ ///
228
+ /// [#36375]: https://github.com/rust-lang/rust/issues/36375
229
+ ///
230
+ /// As it turns out, though, most traits can have an `impl` for `!`. Take [`Debug`]
198
231
/// for example:
199
232
///
200
233
/// ```
201
234
/// #![feature(never_type)]
202
235
/// # use std::fmt;
203
236
/// # trait Debug {
204
- /// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
237
+ /// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
205
238
/// # }
206
239
/// impl Debug for ! {
207
240
/// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
0 commit comments