From 1d9be09b6a1338ecf1d56d79d33ba661450234cf Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sun, 21 Jan 2018 22:09:54 +0800 Subject: [PATCH 1/4] add docs for never type --- src/types.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/types.md b/src/types.md index 77a05cc37..f937d1492 100644 --- a/src/types.md +++ b/src/types.md @@ -17,6 +17,7 @@ types: * The [machine types] (integer and floating-point). * The [machine-dependent integer types]. * The [textual types] `char` and `str`. +* The [never type] `!` There are also some primitive constructs for generic types built in to the language: @@ -31,6 +32,7 @@ language: [machine types]: #machine-types [machine-dependent integer types]: #machine-dependent-integer-types [textual types]: #textual-types +[never-type]: #never-type [Tuples]: #tuple-types [Arrays]: #array-and-slice-types [Slices]: #array-and-slice-types @@ -84,6 +86,13 @@ unsigned bytes holding a sequence of UTF-8 code points. Since `str` is a [dynamically sized type], it is not a _first-class_ type, but can only be instantiated through a pointer type, such as `&str`. +## Never type + +The never type `!` is a type with no values, representing the result of +computations that never complete. Although it has size `0` the empty bit +pattern is not a valid representation. Expressions of type `!` can be coerced +into any other type. + ## Tuple types A tuple *type* is a heterogeneous product of other types, called the *elements* From ae2211d07513bb23acd6cd01fd5b3fd44cba8856 Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Sun, 21 Jan 2018 23:19:15 +0800 Subject: [PATCH 2/4] updates for `!` type stabilisation Remove section on diverging function since they are no longer special. Modify wording around description of `loop` accordingly. Add `!` to any coercion to list of coercions. --- src/expressions/loop-expr.md | 10 ++++---- src/items/functions.md | 46 ------------------------------------ src/type-coercions.md | 2 ++ 3 files changed, 6 insertions(+), 52 deletions(-) diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index 2577689bd..c0d6d6c6b 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -36,12 +36,10 @@ Only `loop` supports [evaluation to non-trivial values](#break-and-loop-values). A `loop` expression repeats execution of its body continuously: `loop { println!("I live."); }`. -A `loop` expression without an associated `break` expression is -[diverging](items/functions.html#diverging-functions), and doesn't -return anything. A `loop` expression containing associated -[`break` expression(s)](#break-expressions) -may terminate, and must have type compatible with the value of the `break` -expression(s). +A `loop` expression without an associated `break` expression is diverging and +so has type `!`. A `loop` expression containing associated +[`break` expression(s)](#break-expressions) may terminate, and must have type +compatible with the value of the `break` expression(s). ## Predicate loops diff --git a/src/items/functions.md b/src/items/functions.md index 16b4a3e8c..ce9521067 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -93,52 +93,6 @@ sufficient context to determine the type parameters. For example, [path]: paths.html -## Diverging functions - -A special kind of function can be declared with a `!` character where the -output type would normally be. For example: - -```rust -fn my_err(s: &str) -> ! { - println!("{}", s); - panic!(); -} -``` - -We call such functions "diverging" because they never return a value to the -caller. Every control path in a diverging function must end with a `panic!()`, -a loop expression without an associated break expression, or a call to another -diverging function on every control path. The `!` annotation does *not* denote -a type. - -It might be necessary to declare a diverging function because as mentioned -previously, the typechecker checks that every control path in a function ends -with a [`return`] or diverging expression. So, if `my_err` were declared -without the `!` annotation, the following code would not typecheck: - -[`return`]: expressions/return-expr.html - -```rust -# fn my_err(s: &str) -> ! { panic!() } - -fn f(i: i32) -> i32 { - if i == 42 { - return 42; - } - else { - my_err("Bad number!"); - } -} -``` - -This will not compile without the `!` annotation on `my_err`, since the `else` -branch of the conditional in `f` does not return an `i32`, as required by the -signature of `f`. Adding the `!` annotation to `my_err` informs the typechecker -that, should control ever enter `my_err`, no further type judgments about `f` -need to hold, since control will never resume in any context that relies on -those judgments. Thus the return type on `f` only needs to reflect the `if` -branch of the conditional. - ## Extern functions Extern functions are part of Rust's foreign function interface, providing the diff --git a/src/type-coercions.md b/src/type-coercions.md index 22b6ceefc..c8719aee4 100644 --- a/src/type-coercions.md +++ b/src/type-coercions.md @@ -148,6 +148,8 @@ Coercion is allowed between the following types: * Non capturing closures to `fn` pointers +* `!` to any `T` + ### Unsized Coercions The following coercions are called `unsized coercions`, since they From fdab6682cc4f4a6316a7941d57f3a70a7398d06c Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Thu, 1 Feb 2018 16:03:16 +0800 Subject: [PATCH 3/4] Fix some nits around `!` changes --- src/expressions/loop-expr.md | 6 +++--- src/items/functions.md | 2 +- src/types.md | 7 +++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index c0d6d6c6b..9cd1120ba 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -37,9 +37,9 @@ A `loop` expression repeats execution of its body continuously: `loop { println!("I live."); }`. A `loop` expression without an associated `break` expression is diverging and -so has type `!`. A `loop` expression containing associated -[`break` expression(s)](#break-expressions) may terminate, and must have type -compatible with the value of the `break` expression(s). +has type [`!`](types.html#never-type). A `loop` expression containing +associated [`break` expression(s)](#break-expressions) may terminate, and must +have type compatible with the value of the `break` expression(s). ## Predicate loops diff --git a/src/items/functions.md b/src/items/functions.md index ce9521067..0ccdeaa61 100644 --- a/src/items/functions.md +++ b/src/items/functions.md @@ -123,4 +123,4 @@ As non-Rust calling conventions do not support unwinding, unwinding past the end of an extern function will cause the process to abort. In LLVM, this is implemented by executing an illegal instruction. -[external blocks]: items/external-blocks.html \ No newline at end of file +[external blocks]: items/external-blocks.html diff --git a/src/types.md b/src/types.md index f937d1492..1cf257d19 100644 --- a/src/types.md +++ b/src/types.md @@ -89,9 +89,8 @@ instantiated through a pointer type, such as `&str`. ## Never type The never type `!` is a type with no values, representing the result of -computations that never complete. Although it has size `0` the empty bit -pattern is not a valid representation. Expressions of type `!` can be coerced -into any other type. +computations that never complete. Expressions of type `!` can be coerced into +any other type. ## Tuple types @@ -662,4 +661,4 @@ impl Printable for String { [issue 47010]: https://github.com/rust-lang/rust/issues/47010 [issue 33140]: https://github.com/rust-lang/rust/issues/33140 [_PATH_]: paths.html -[_LIFETIME_OR_LABEL_]: tokens.html#lifetimes-and-loop-labels \ No newline at end of file +[_LIFETIME_OR_LABEL_]: tokens.html#lifetimes-and-loop-labels From 867194177fa76c1c2a5c8bfe0d369af6c413a24d Mon Sep 17 00:00:00 2001 From: Andrew Cann Date: Mon, 12 Feb 2018 22:58:33 +0800 Subject: [PATCH 4/4] Add ! to list of Copy types --- src/special-types-and-traits.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/special-types-and-traits.md b/src/special-types-and-traits.md index 497eceb3d..119a1c36b 100644 --- a/src/special-types-and-traits.md +++ b/src/special-types-and-traits.md @@ -52,7 +52,7 @@ whose type implements `Copy` are copied rather than moved upon assignment. fields that are not `Copy`. `Copy` is implemented by the compiler for * [Numeric types] -* `char` and `bool` +* `char`, `bool` and [`!`] * [Tuples] of `Copy` types * [Arrays] of `Copy` types * [Shared references] @@ -151,3 +151,4 @@ compiler, not by [implementation items]. [Tuples]: types.html#tuple-types [Type parameters]: types.html#type-parameters [variance]: ../nomicon/subtyping.html +[`!`]: types.html#never-type