Skip to content

Commit 4aae781

Browse files
committed
Add info about ! and impl Trait
1 parent 62850d8 commit 4aae781

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

library/std/src/primitive_docs.rs

+35-2
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)