diff --git a/src/behavior-considered-undefined.md b/src/behavior-considered-undefined.md index f1ad30ada..1cc7966bf 100644 --- a/src/behavior-considered-undefined.md +++ b/src/behavior-considered-undefined.md @@ -38,7 +38,7 @@ code. a function/primitive operation or returned from a function/primitive operation. The following values are invalid (at their respective type): - * A value other than `false` (`0`) or `true` (`1`) in a `bool`. + * A value other than `false` (`0`) or `true` (`1`) in a [`bool`]. * A discriminant in an `enum` not included in the type definition. * A null `fn` pointer. * A value in a `char` which is a surrogate or above `char::MAX`. @@ -77,7 +77,8 @@ cannot be bigger than `isize::MAX` bytes. > vice versa, undefined behavior in Rust can cause adverse affects on code > executed by any FFI calls to other languages. -[`const`]: items/constant-items.html +[`bool`]: types/boolean.md +[`const`]: items/constant-items.md [noalias]: http://llvm.org/docs/LangRef.html#noalias [pointer aliasing rules]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules [undef]: http://llvm.org/docs/LangRef.html#undefined-values diff --git a/src/expressions/if-expr.md b/src/expressions/if-expr.md index 5d04bb5c7..5b63acf81 100644 --- a/src/expressions/if-expr.md +++ b/src/expressions/if-expr.md @@ -10,12 +10,12 @@ > | _IfExpression_ > | _IfLetExpression_ ) )\? -An `if` expression is a conditional branch in program control. The form of an -`if` expression is a condition expression, followed by a consequent block, any +An `if` expression is a conditional branch in program control. The syntax of an +`if` expression is a condition operand, followed by a consequent block, any number of `else if` conditions and blocks, and an optional trailing `else` -block. The condition expressions must have type `bool`. If a condition -expression evaluates to `true`, the consequent block is executed and any -subsequent `else if` or `else` block is skipped. If a condition expression +block. The condition operands must have the [boolean type]. If a condition +operand evaluates to `true`, the consequent block is executed and any +subsequent `else if` or `else` block is skipped. If a condition operand evaluates to `false`, the consequent block is skipped and any subsequent `else if` condition is evaluated. If all `if` and `else if` conditions evaluate to `false` then any `else` block is executed. An if expression evaluates to the @@ -52,8 +52,8 @@ assert_eq!(y, "Bigger"); > | _IfLetExpression_ ) )\? An `if let` expression is semantically similar to an `if` expression but in -place of a condition expression it expects the keyword `let` followed by a -pattern, an `=` and a [scrutinee] expression. If the value of the scrutinee +place of a condition operand it expects the keyword `let` followed by a +pattern, an `=` and a [scrutinee] operand. If the value of the scrutinee matches the pattern, the corresponding block will execute. Otherwise, flow proceeds to the following `else` block if it exists. Like `if` expressions, `if let` expressions have a value determined by the block that is evaluated. @@ -158,4 +158,5 @@ if let PAT = ( EXPR || EXPR ) { .. } [_MatchArmPatterns_]: match-expr.md [_eRFCIfLetChain_]: https://github.com/rust-lang/rfcs/blob/master/text/2497-if-let-chains.md#rollout-plan-and-transitioning-to-rust-2018 [`match` expression]: match-expr.md +[boolean type]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee diff --git a/src/expressions/loop-expr.md b/src/expressions/loop-expr.md index 9ddefa12f..7d475cd02 100644 --- a/src/expressions/loop-expr.md +++ b/src/expressions/loop-expr.md @@ -47,9 +47,9 @@ have type compatible with the value of the `break` expression(s). > _PredicateLoopExpression_ :\ >    `while` [_Expression_]_except struct expression_ [_BlockExpression_] -A `while` loop begins by evaluating the boolean loop conditional expression. If -the loop conditional expression evaluates to `true`, the loop body block -executes, then control returns to the loop conditional expression. If the loop +A `while` loop begins by evaluating the [boolean] loop conditional operand. If +the loop conditional operand evaluates to `true`, the loop body block +executes, then control returns to the loop conditional operand. If the loop conditional expression evaluates to `false`, the `while` expression completes. An example: @@ -294,6 +294,7 @@ expression `()`. [_MatchArmPatterns_]: match-expr.md [_Pattern_]: ../patterns.md [`match` expression]: match-expr.md +[boolean]: ../types/boolean.md [scrutinee]: ../glossary.md#scrutinee [temporary values]: ../expressions.md#temporaries [_LazyBooleanOperatorExpression_]: operator-expr.md#lazy-boolean-operators diff --git a/src/expressions/operator-expr.md b/src/expressions/operator-expr.md index acc6da26b..63d595117 100644 --- a/src/expressions/operator-expr.md +++ b/src/expressions/operator-expr.md @@ -164,10 +164,10 @@ for other types. Remember that signed integers are always represented using two's complement. The operands of all of these operators are evaluated in [value expression context][value expression] so are moved or copied. -| Symbol | Integer | `bool` | Floating Point | Overloading Trait | -|--------|-------------|-------------|----------------|--------------------| -| `-` | Negation* | | Negation | `std::ops::Neg` | -| `!` | Bitwise NOT | Logical NOT | | `std::ops::Not` | +| Symbol | Integer | `bool` | Floating Point | Overloading Trait | +|--------|-------------|-------------- |----------------|--------------------| +| `-` | Negation* | | Negation | `std::ops::Neg` | +| `!` | Bitwise NOT | [Logical NOT] | | `std::ops::Not` | \* Only for signed integer types. @@ -202,18 +202,18 @@ types. Remember that signed integers are always represented using two's complement. The operands of all of these operators are evaluated in [value expression context][value expression] so are moved or copied. -| Symbol | Integer | `bool` | Floating Point | Overloading Trait | Overloading Compound Assignment Trait | -|--------|-------------------------|-------------|----------------|--------------------| ------------------------------------- | -| `+` | Addition | | Addition | `std::ops::Add` | `std::ops::AddAssign` | -| `-` | Subtraction | | Subtraction | `std::ops::Sub` | `std::ops::SubAssign` | -| `*` | Multiplication | | Multiplication | `std::ops::Mul` | `std::ops::MulAssign` | -| `/` | Division* | | Division | `std::ops::Div` | `std::ops::DivAssign` | -| `%` | Remainder | | Remainder | `std::ops::Rem` | `std::ops::RemAssign` | -| `&` | Bitwise AND | Logical AND | | `std::ops::BitAnd` | `std::ops::BitAndAssign` | -| | | Bitwise OR | Logical OR | | `std::ops::BitOr` | `std::ops::BitOrAssign` | -| `^` | Bitwise XOR | Logical XOR | | `std::ops::BitXor` | `std::ops::BitXorAssign` | -| `<<` | Left Shift | | | `std::ops::Shl` | `std::ops::ShlAssign` | -| `>>` | Right Shift** | | | `std::ops::Shr` | `std::ops::ShrAssign` | +| Symbol | Integer | `bool` | Floating Point | Overloading Trait | Overloading Compound Assignment Trait | +|--------|-------------------------|---------------|----------------|--------------------| ------------------------------------- | +| `+` | Addition | | Addition | `std::ops::Add` | `std::ops::AddAssign` | +| `-` | Subtraction | | Subtraction | `std::ops::Sub` | `std::ops::SubAssign` | +| `*` | Multiplication | | Multiplication | `std::ops::Mul` | `std::ops::MulAssign` | +| `/` | Division* | | Division | `std::ops::Div` | `std::ops::DivAssign` | +| `%` | Remainder | | Remainder | `std::ops::Rem` | `std::ops::RemAssign` | +| `&` | Bitwise AND | [Logical AND] | | `std::ops::BitAnd` | `std::ops::BitAndAssign` | +| | | Bitwise OR | [Logical OR] | | `std::ops::BitOr` | `std::ops::BitOrAssign` | +| `^` | Bitwise XOR | [Logical XOR] | | `std::ops::BitXor` | `std::ops::BitXorAssign` | +| `<<` | Left Shift | | | `std::ops::Shl` | `std::ops::ShlAssign` | +| `>>` | Right Shift** | | | `std::ops::Shr` | `std::ops::ShrAssign` | \* Integer division rounds towards zero. @@ -522,6 +522,10 @@ dependency. [copies or moves]: ../expressions.md#moved-and-copied-types [dropping]: ../destructors.md +[logical and]: ../types/boolean.md#logical-and +[logical not]: ../types/boolean.md#logical-not +[logical or]: ../types/boolean.md#logical-or +[logical xor]: ../types/boolean.md#logical-xor [mutable]: ../expressions.md#mutability [place expression]: ../expressions.md#place-expressions-and-value-expressions [unit]: ../types/tuple.md diff --git a/src/items/unions.md b/src/items/unions.md index dabb6355c..7ad5da71e 100644 --- a/src/items/unions.md +++ b/src/items/unions.md @@ -47,13 +47,14 @@ let f = unsafe { u.f1 }; Unions have no notion of an "active field". Instead, every union access just interprets the storage at the type of the field used for the access. Reading a union field reads the bits of the union at the field's type. Fields might have a -non-zero offset (except when `#[repr(C)]` is used); in that case the bits -starting at the offset of the fields are read. It is the programmer's +non-zero offset (except when [the C representation] is used); in that case the +bits starting at the offset of the fields are read. It is the programmer's responsibility to make sure that the data is valid at the field's type. Failing -to do so results in undefined behavior. For example, reading the value `3` at -type `bool` is undefined behavior. Effectively, writing to and then reading from -a `#[repr(C)]` union is analogous to a [`transmute`] from the type used for -writing to the type used for reading. +to do so results in [undefined behavior]. For example, reading the value `3` +through of a field of the [boolean type] is undefined behavior. Effectively, +writing to and then reading from a union with [the C representation] is +analogous to a [`transmute`] from the type used for writing to the type used for +reading. Consequently, all reads of union fields have to be placed in `unsafe` blocks: @@ -182,4 +183,7 @@ checking, etc etc etc). [_StructFields_]: structs.md [`transmute`]: ../../std/mem/fn.transmute.html [`Copy`]: ../../std/marker/trait.Copy.html +[boolean type]: ../types/boolean.md [ManuallyDrop]: ../../std/mem/struct.ManuallyDrop.html +[the C representation]: ../type-layout.md#reprc-unions +[undefined behavior]: ../behavior-considered-undefined.html diff --git a/src/types/boolean.md b/src/types/boolean.md index 6c976b2a5..d8984025f 100644 --- a/src/types/boolean.md +++ b/src/types/boolean.md @@ -1,17 +1,118 @@ # Boolean type -The `bool` type is a datatype which can be either `true` or `false`. The boolean -type uses one byte of memory. It is used in comparisons and bitwise operations -like `&`, `|`, and `!`. - ```rust -fn main() { - let x = true; - let y: bool = false; // with the boolean type annotation - - // Use of booleans in conditional expressions - if x { - println!("x is true"); - } -} +let b: bool = true; ``` + +The *boolean type* or *bool* is a primitive data type that can take on one of +two values, called *true* and *false*. + +Values of this type may be created using a [literal expression] using the +keywords `true` and `false` corresponding to the value of the same name. + +This type is a part of the [language prelude] with the [name] `bool`. + +An object with the boolean type has a [size and alignment] of 1 each. The +value false has the bit pattern `0x00` and the value true has the bit pattern +`0x01`. It is [undefined behavior] for an object with the boolean type to have +any other bit pattern. + +The boolean type is the type of many operands in various [expressions]: + +* The condition operand in [if expressions] and [while expressions] +* The operands in [lazy boolean operator expressions][lazy] + +> **Note**: The boolean type acts similarly to but is not an [enumerated type]. +In practice, this mostly means that constructors are not associated to the type +(e.g. `bool::true`). + +Like all primitives, the boolean type [implements][p-impl] the +[traits][p-traits] [`Clone`][p-clone], [`Copy`][p-copy], [`Sized`][p-sized], +[`Send`][p-send], and [`Sync`][p-sync]. + +> **Note**: See the [standard library docs][std] for library operations. + +## Operations on boolean values + + When using certain operator expressions with a +boolean type for its operands, they evaluate using the rules of [boolean logic]. + +### Logical not + +| `b` | [`!b`][op-not] | +|- | - | +| `true` | `false` | +| `false` | `true` | + +### Logical or + +| `a` | `b` | [a | b][op-or] | +|- | - | - | +| `true` | `true` | `true` | +| `true` | `false` | `true` | +| `false` | `true` | `true` | +| `false` | `false` | `false` | + +### Logical and + +| `a` | `b` | [`a & b`][op-and] | +|- | - | - | +| `true` | `true` | `true` | +| `true` | `false` | `false` | +| `false` | `true` | `false` | +| `false` | `false` | `false` | + +### Logical xor + +| `a` | `b` | [`a ^ b`][op-xor] | +|- | - | - | +| `true` | `true` | `false` | +| `true` | `false` | `true` | +| `false` | `true` | `true` | +| `false` | `false` | `false` | + +### Comparisons + +| `a` | `b` | [`a == b`][op-compare] | +|- | - | - | +| `true` | `true` | `true` | +| `true` | `false` | `false` | +| `false` | `true` | `false` | +| `false` | `false` | `true` | + +| `a` | `b` | [`a > b`][op-compare] | +|- | - | - | +| `true` | `true` | `false` | +| `true` | `false` | `true` | +| `false` | `true` | `false` | +| `false` | `false` | `false` | + +* `a != b` is the same as `!(a == b)` +* `a >= b` is the same as `a == b | a > b` +* `a < b` is the same as `!(a >= b)` +* `a <= b` is the same as `a == b | a < b` + +[boolean logic]: https://en.wikipedia.org/wiki/Boolean_algebra +[enumerated type]: enum.md +[expressions]: ../expressions.md +[if expressions]: ../expressions/if-expr.md#if-expressions +[language prelude]: ../names/preludes.md#language-prelude +[lazy]: ../expressions/operator-expr.md#lazy-boolean-operators +[literal expression]: ../expressions/literal-expr.md +[name]: ../names.md +[op-and]: ../expressions/operator-expr.md#arithmetic-and-logical-binary-operators +[op-compare]: ../expressions/operator-expr.md#comparison-operators +[op-not]: ../expressions/operator-expr.md#negation-operators +[op-or]: ../expressions/operator-expr.md#arithmetic-and-logical-binary-operators +[op-xor]: ../expressions/operator-expr.md#arithmetic-and-logical-binary-operators +[p-clone]: ../special-types-and-traits.md#clone +[p-copy]: ../special-types-and-traits.md#copy +[p-impl]: ../items/implementations.md +[p-send]: ../special-types-and-traits.md#send +[p-sized]: ../special-types-and-traits.md#sized +[p-sync]: ../special-types-and-traits.md#sync +[p-traits]: ../items/traits.md +[size and alignment]: ../type-layout.md#size-and-alignment +[std]: ../../std/primitive.bool.html +[undefined behavior]: ../behavior-considered-undefined.md +[while expressions]: ../expressions/loop-expr.md#predicate-loops