about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-12-10 19:04:25 +0000
committerbors <bors@rust-lang.org>2017-12-10 19:04:25 +0000
commit2d4df9584bebbdc72db77f550a6786819a3a791f (patch)
treee33d4d136d7072c37404d16b8685f8c9090f6d05
parent2537a499c2f1983011ad04ba2e59e5ff2e2989b6 (diff)
parent172f16bc9dcaa928af973f693589754d86473435 (diff)
downloadrust-2d4df9584bebbdc72db77f550a6786819a3a791f.tar.gz
rust-2d4df9584bebbdc72db77f550a6786819a3a791f.zip
Auto merge of #46232 - canndrew:never-docs, r=QuietMisdreavus
Add docs for never primitive

cc @nikomatsakis, @QuietMisdreavus
-rw-r--r--src/librustdoc/clean/mod.rs6
-rw-r--r--src/librustdoc/html/format.rs2
-rw-r--r--src/libstd/primitive_docs.rs128
3 files changed, 135 insertions, 1 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index fbff6e83fb9..0e25d639e45 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1802,6 +1802,7 @@ pub enum PrimitiveType {
     RawPointer,
     Reference,
     Fn,
+    Never,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
@@ -1843,6 +1844,7 @@ impl Type {
             RawPointer(..) => Some(PrimitiveType::RawPointer),
             BorrowedRef { type_: box Generic(..), .. } => Some(PrimitiveType::Reference),
             BareFunction(..) => Some(PrimitiveType::Fn),
+            Never => Some(PrimitiveType::Never),
             _ => None,
         }
     }
@@ -1891,6 +1893,7 @@ impl GetDefId for Type {
                 Primitive(PrimitiveType::Tuple).def_id()
             },
             BareFunction(..) => Primitive(PrimitiveType::Fn).def_id(),
+            Never => Primitive(PrimitiveType::Never).def_id(),
             Slice(..) => Primitive(PrimitiveType::Slice).def_id(),
             Array(..) => Primitive(PrimitiveType::Array).def_id(),
             RawPointer(..) => Primitive(PrimitiveType::RawPointer).def_id(),
@@ -1927,6 +1930,7 @@ impl PrimitiveType {
             "pointer" => Some(PrimitiveType::RawPointer),
             "reference" => Some(PrimitiveType::Reference),
             "fn" => Some(PrimitiveType::Fn),
+            "never" => Some(PrimitiveType::Never),
             _ => None,
         }
     }
@@ -1958,6 +1962,7 @@ impl PrimitiveType {
             RawPointer => "pointer",
             Reference => "reference",
             Fn => "fn",
+            Never => "never",
         }
     }
 
@@ -2892,6 +2897,7 @@ fn build_deref_target_impls(cx: &DocContext,
             RawPointer => tcx.lang_items().const_ptr_impl(),
             Reference => None,
             Fn => None,
+            Never => None,
         };
         if let Some(did) = did {
             if !did.is_local() {
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index feb4eb603f5..53c10d101d0 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -636,7 +636,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
             fmt::Display::fmt(t, f)?;
             primitive_link(f, PrimitiveType::Array, &format!("; {}]", n))
         }
-        clean::Never => f.write_str("!"),
+        clean::Never => primitive_link(f, PrimitiveType::Never, "!"),
         clean::RawPointer(m, ref t) => {
             match **t {
                 clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => {
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 9e1da318242..a456e466341 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -67,6 +67,134 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_bool { }
 
+#[doc(primitive = "never")]
+//
+/// The `!` type, also called "never".
+///
+/// `!` represents the type of computations which never resolve to any value at all. For example,
+/// the [`exit`] function `fn exit(code: i32) -> !` exits the process without ever returning, and
+/// so returns `!`.
+///
+/// `break`, `continue` and `return` expressions also have type `!`. For example we are allowed to
+/// write:
+///
+/// ```
+/// #![feature(never_type)]
+/// # fn foo() -> u32 {
+/// let x: ! = {
+///     return 123
+/// };
+/// # }
+/// ```
+///
+/// Although the `let` is pointless here, it illustrates the meaning of `!`. Since `x` is never
+/// assigned a value (because `return` returns from the entire function), `x` can be given type
+/// `!`. We could also replace `return 123` with a `panic!` or a never-ending `loop` and this code
+/// would still be valid.
+///
+/// A more realistic usage of `!` is in this code:
+///
+/// ```
+/// # fn get_a_number() -> Option<u32> { None }
+/// # loop {
+/// let num: u32 = match get_a_number() {
+///     Some(num) => num,
+///     None => break,
+/// };
+/// # }
+/// ```
+///
+/// Both match arms must produce values of type [`u32`], but since `break` never produces a value
+/// at all we know it can never produce a value which isn't a [`u32`]. This illustrates another
+/// behaviour of the `!` type - expressions with type `!` will coerce into any other type.
+///
+/// [`u32`]: primitive.str.html
+/// [`exit`]: process/fn.exit.html
+///
+/// # `!` and generics
+///
+/// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`]
+/// trait:
+///
+/// ```
+/// trait FromStr: Sized {
+///     type Err;
+///     fn from_str(s: &str) -> Result<Self, Self::Err>;
+/// }
+/// ```
+///
+/// When implementing this trait for [`String`] we need to pick a type for [`Err`]. And since
+/// converting a string into a string will never result in an error, the appropriate type is `!`.
+/// (Currently the type actually used is an enum with no variants, though this is only because `!`
+/// was added to Rust at a later date and it may change in the future). With an [`Err`] type of
+/// `!`, if we have to call [`String::from_str`] for some reason the result will be a
+/// [`Result<String, !>`] which we can unpack like this:
+///
+/// ```ignore (string-from-str-error-type-is-not-never-yet)
+/// // NOTE: This does not work today!
+/// let Ok(s) = String::from_str("hello");
+/// ```
+///
+/// Since the [`Err`] variant contains a `!`, it can never occur. So we can exhaustively match on
+/// [`Result<T, !>`] by just taking the [`Ok`] variant. This illustrates another behaviour of `!` -
+/// it can be used to "delete" certain enum variants from generic types like `Result`.
+///
+/// [`String::from_str`]: str/trait.FromStr.html#tymethod.from_str
+/// [`Result<String, !>`]: result/enum.Result.html
+/// [`Result<T, !>`]: result/enum.Result.html
+/// [`Ok`]: result/enum.Result.html#variant.Ok
+/// [`String`]: string/struct.String.html
+/// [`Err`]: result/enum.Result.html#variant.Err
+/// [`FromStr`]: str/trait.FromStr.html
+///
+/// # `!` and traits
+///
+/// When writing your own traits, `!` should have an `impl` whenever there is an obvious `impl`
+/// which doesn't `panic!`. As is turns out, most traits can have an `impl` for `!`. Take [`Debug`]
+/// for example:
+///
+/// ```
+/// # #![feature(never_type)]
+/// # use std::fmt;
+/// # trait Debug {
+/// # fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result;
+/// # }
+/// impl Debug for ! {
+///     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+///         *self
+///     }
+/// }
+/// ```
+///
+/// Once again we're using `!`'s ability to coerce into any other type, in this case
+/// [`fmt::Result`]. Since this method takes a `&!` as an argument we know that it can never be
+/// called (because there is no value of type `!` for it to be called with). Writing `*self`
+/// essentially tells the compiler "We know that this code can never be run, so just treat the
+/// entire function body has having type [`fmt::Result`]". This pattern can be used a lot when
+/// implementing traits for `!`. Generally, any trait which only has methods which take a `self`
+/// parameter should have such as impl.
+///
+/// On the other hand, one trait which would not be appropriate to implement is [`Default`]:
+///
+/// ```
+/// trait Default {
+///     fn default() -> Self;
+/// }
+/// ```
+///
+/// Since `!` has no values, it has no default value either. It's true that we could write an
+/// `impl` for this which simply panics, but the same is true for any type (we could `impl
+/// Default` for (eg.) [`File`] by just making [`default()`] panic.)
+///
+/// [`fmt::Result`]: fmt/type.Result.html
+/// [`File`]: fs/struct.File.html
+/// [`Debug`]: fmt/trait.Debug.html
+/// [`Default`]: default/trait.Default.html
+/// [`default()`]: default/trait.Default.html#tymethod.default
+///
+#[unstable(feature = "never_type_impls", issue = "35121")]
+mod prim_never { }
+
 #[doc(primitive = "char")]
 //
 /// A character type.