Skip to content

Commit 2d4df95

Browse files
committed
Auto merge of #46232 - canndrew:never-docs, r=QuietMisdreavus
Add docs for never primitive cc @nikomatsakis, @QuietMisdreavus
2 parents 2537a49 + 172f16b commit 2d4df95

File tree

3 files changed

+135
-1
lines changed

3 files changed

+135
-1
lines changed

src/librustdoc/clean/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,7 @@ pub enum PrimitiveType {
18021802
RawPointer,
18031803
Reference,
18041804
Fn,
1805+
Never,
18051806
}
18061807

18071808
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
@@ -1843,6 +1844,7 @@ impl Type {
18431844
RawPointer(..) => Some(PrimitiveType::RawPointer),
18441845
BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
18451846
BareFunction(..) => Some(PrimitiveType::Fn),
1847+
Never => Some(PrimitiveType::Never),
18461848
_ => None,
18471849
}
18481850
}
@@ -1891,6 +1893,7 @@ impl GetDefId for Type {
18911893
Primitive(PrimitiveType::Tuple).def_id()
18921894
},
18931895
BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
1896+
Never => Primitive(PrimitiveType::Never).def_id(),
18941897
Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
18951898
Array(..) => Primitive(PrimitiveType::Array).def_id(),
18961899
RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
@@ -1927,6 +1930,7 @@ impl PrimitiveType {
19271930
"pointer" => Some(PrimitiveType::RawPointer),
19281931
"reference" => Some(PrimitiveType::Reference),
19291932
"fn" => Some(PrimitiveType::Fn),
1933+
"never" => Some(PrimitiveType::Never),
19301934
_ => None,
19311935
}
19321936
}
@@ -1958,6 +1962,7 @@ impl PrimitiveType {
19581962
RawPointer => "pointer",
19591963
Reference => "reference",
19601964
Fn => "fn",
1965+
Never => "never",
19611966
}
19621967
}
19631968

@@ -2892,6 +2897,7 @@ fn build_deref_target_impls(cx: &DocContext,
28922897
RawPointer => tcx.lang_items().const_ptr_impl(),
28932898
Reference => None,
28942899
Fn => None,
2900+
Never => None,
28952901
};
28962902
if let Some(did) = did {
28972903
if !did.is_local() {

src/librustdoc/html/format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
636636
fmt::Display::fmt(t, f)?;
637637
primitive_link(f, PrimitiveType::Array, &format!("; {}]", n))
638638
}
639-
clean::Never => f.write_str("!"),
639+
clean::Never => primitive_link(f, PrimitiveType::Never, "!"),
640640
clean::RawPointer(m, ref t) => {
641641
match **t {
642642
clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {

src/libstd/primitive_docs.rs

+128
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,134 @@
6767
#[stable(feature = "rust1", since = "1.0.0")]
6868
mod prim_bool { }
6969

70+
#[doc(primitive = "never")]
71+
//
72+
/// The `!` type, also called "never".
73+
///
74+
/// `!` represents the type of computations which never resolve to any value at all. For example,
75+
/// the [`exit`] function `fn exit(code: i32) -> !` exits the process without ever returning, and
76+
/// so returns `!`.
77+
///
78+
/// `break`, `continue` and `return` expressions also have type `!`. For example we are allowed to
79+
/// write:
80+
///
81+
/// ```
82+
/// #![feature(never_type)]
83+
/// # fn foo() -> u32 {
84+
/// let x: ! = {
85+
/// return 123
86+
/// };
87+
/// # }
88+
/// ```
89+
///
90+
/// Although the `let` is pointless here, it illustrates the meaning of `!`. Since `x` is never
91+
/// assigned a value (because `return` returns from the entire function), `x` can be given type
92+
/// `!`. We could also replace `return 123` with a `panic!` or a never-ending `loop` and this code
93+
/// would still be valid.
94+
///
95+
/// A more realistic usage of `!` is in this code:
96+
///
97+
/// ```
98+
/// # fn get_a_number() -> Option<u32> { None }
99+
/// # loop {
100+
/// let num: u32 = match get_a_number() {
101+
/// Some(num) => num,
102+
/// None => break,
103+
/// };
104+
/// # }
105+
/// ```
106+
///
107+
/// Both match arms must produce values of type [`u32`], but since `break` never produces a value
108+
/// at all we know it can never produce a value which isn't a [`u32`]. This illustrates another
109+
/// behaviour of the `!` type - expressions with type `!` will coerce into any other type.
110+
///
111+
/// [`u32`]: primitive.str.html
112+
/// [`exit`]: process/fn.exit.html
113+
///
114+
/// # `!` and generics
115+
///
116+
/// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`]
117+
/// trait:
118+
///
119+
/// ```
120+
/// trait FromStr: Sized {
121+
/// type Err;
122+
/// fn from_str(s: &str) -> Result<Self, Self::Err>;
123+
/// }
124+
/// ```
125+
///
126+
/// When implementing this trait for [`String`] we need to pick a type for [`Err`]. And since
127+
/// converting a string into a string will never result in an error, the appropriate type is `!`.
128+
/// (Currently the type actually used is an enum with no variants, though this is only because `!`
129+
/// was added to Rust at a later date and it may change in the future). With an [`Err`] type of
130+
/// `!`, if we have to call [`String::from_str`] for some reason the result will be a
131+
/// [`Result<String, !>`] which we can unpack like this:
132+
///
133+
/// ```ignore (string-from-str-error-type-is-not-never-yet)
134+
/// // NOTE: This does not work today!
135+
/// let Ok(s) = String::from_str("hello");
136+
/// ```
137+
///
138+
/// Since the [`Err`] variant contains a `!`, it can never occur. So we can exhaustively match on
139+
/// [`Result<T, !>`] by just taking the [`Ok`] variant. This illustrates another behaviour of `!` -
140+
/// it can be used to "delete" certain enum variants from generic types like `Result`.
141+
///
142+
/// [`String::from_str`]: str/trait.FromStr.html#tymethod.from_str
143+
/// [`Result<String, !>`]: result/enum.Result.html
144+
/// [`Result<T, !>`]: result/enum.Result.html
145+
/// [`Ok`]: result/enum.Result.html#variant.Ok
146+
/// [`String`]: string/struct.String.html
147+
/// [`Err`]: result/enum.Result.html#variant.Err
148+
/// [`FromStr`]: str/trait.FromStr.html
149+
///
150+
/// # `!` and traits
151+
///
152+
/// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl`
153+
/// which doesn't `panic!`. As is turns out, most traits can have an `impl` for `!`. Take [`Debug`]
154+
/// for example:
155+
///
156+
/// ```
157+
/// # #![feature(never_type)]
158+
/// # use std::fmt;
159+
/// # trait Debug {
160+
/// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
161+
/// # }
162+
/// impl Debug for ! {
163+
/// fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
164+
/// *self
165+
/// }
166+
/// }
167+
/// ```
168+
///
169+
/// Once again we're using `!`'s ability to coerce into any other type, in this case
170+
/// [`fmt::Result`]. Since this method takes a `&!` as an argument we know that it can never be
171+
/// called (because there is no value of type `!` for it to be called with). Writing `*self`
172+
/// essentially tells the compiler "We know that this code can never be run, so just treat the
173+
/// entire function body has having type [`fmt::Result`]". This pattern can be used a lot when
174+
/// implementing traits for `!`. Generally, any trait which only has methods which take a `self`
175+
/// parameter should have such as impl.
176+
///
177+
/// On the other hand, one trait which would not be appropriate to implement is [`Default`]:
178+
///
179+
/// ```
180+
/// trait Default {
181+
/// fn default() -> Self;
182+
/// }
183+
/// ```
184+
///
185+
/// Since `!` has no values, it has no default value either. It's true that we could write an
186+
/// `impl` for this which simply panics, but the same is true for any type (we could `impl
187+
/// Default` for (eg.) [`File`] by just making [`default()`] panic.)
188+
///
189+
/// [`fmt::Result`]: fmt/type.Result.html
190+
/// [`File`]: fs/struct.File.html
191+
/// [`Debug`]: fmt/trait.Debug.html
192+
/// [`Default`]: default/trait.Default.html
193+
/// [`default()`]: default/trait.Default.html#tymethod.default
194+
///
195+
#[unstable(feature = "never_type_impls", issue = "35121")]
196+
mod prim_never { }
197+
70198
#[doc(primitive = "char")]
71199
//
72200
/// A character type.

0 commit comments

Comments
 (0)