Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Referencify bool type #940

Merged
merged 3 commits into from
Feb 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/behavior-considered-undefined.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down Expand Up @@ -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
Expand Down
15 changes: 8 additions & 7 deletions src/expressions/if-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
> | _IfExpression_
> | _IfLetExpression_ ) )<sup>\?</sup>

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
Expand Down Expand Up @@ -52,8 +52,8 @@ assert_eq!(y, "Bigger");
> | _IfLetExpression_ ) )<sup>\?</sup>

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.
Expand Down Expand Up @@ -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
7 changes: 4 additions & 3 deletions src/expressions/loop-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ have type compatible with the value of the `break` expression(s).
> _PredicateLoopExpression_ :\
> &nbsp;&nbsp; `while` [_Expression_]<sub>_except struct expression_</sub> [_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:
Expand Down Expand Up @@ -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
Expand Down
36 changes: 20 additions & 16 deletions src/expressions/operator-expr.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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` |
| <code>&#124;</code> | 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` |
| <code>&#124;</code> | 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.

Expand Down Expand Up @@ -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
Expand Down
16 changes: 10 additions & 6 deletions src/items/unions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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
127 changes: 114 additions & 13 deletions src/types/boolean.md
Original file line number Diff line number Diff line change
@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason this doesn't list other traits like the operator traits? It does seem like a little bit of a gray area of which trait impls are part of the "language", but it is not clear to me how that line is drawn.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just referenced the traits on the special traits page, and didn't think too much about the operator traits. It is an oversight, sorta. There's inherent behavior with the operators themselves, but the trait implementations are library-side:

macro_rules! bitand_impl {
    ($($t:ty)*) => ($(
        #[stable(feature = "rust1", since = "1.0.0")]
        impl BitAnd for $t {
            type Output = $t;

            #[inline]
            fn bitand(self, rhs: $t) -> $t { self & rhs }
        }

        forward_ref_binop! { impl BitAnd, bitand for $t, $t }
    )*)
}

bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }

Comparison operators are also built-in that way.


How about I add truth tables for all the things you can do with a boolean, and then link to those from the operator expressions?

[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

<!-- This is washy wording --> 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` | [<code>a &#124; b</code>][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