@@ -194,14 +194,47 @@ mod prim_bool {}
194194/// # `!` and traits
195195///
196196/// 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`]
198231/// for example:
199232///
200233/// ```
201234/// #![feature(never_type)]
202235/// # use std::fmt;
203236/// # trait Debug {
204- /// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
237+ /// # fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result;
205238/// # }
206239/// impl Debug for ! {
207240/// fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
0 commit comments