Boolean Type
Rust's boolean type, written bool, represents a logical truth value that can be in one of two states: true or false.
Literals and Basic Usage
The keywords true and false are the only two values of type bool:
fn main() {
let is_active = true; // Inferred as `bool`
let is_complete: bool = false; // Explicitly annotated as `bool`
println!("is_active = {is_active}, is_complete = {is_complete}");
}
is_active = true, is_complete = false
Booleans are produced by comparison operators (==, !=, <, >, <=, >=), logical operators (!, &&, ||), and predicate methods across the standard library (such as .is_empty(), .contains(), .is_some(), and .is_ok()):
fn main() {
let temperature = 22;
let is_comfortable = temperature >= 18 && temperature <= 25;
let text = "Rust";
let has_text = !text.is_empty();
println!("is_comfortable: {is_comfortable}");
println!("has_text: {has_text}");
}
is_comfortable: true
has_text: true
Memory Representation and Size (1 Byte)
Although a boolean logically requires only a single bit of information (0 or 1), CPUs address memory in whole bytes. Consequently, a bool in Rust occupies 1 byte (8 bits) in memory with a 1-byte alignment:
| Value | Byte Representation (Hex) | Binary Pattern |
|---|---|---|
false |
0x00 |
0b0000_0000 |
true |
0x01 |
0b0000_0001 |
| Invalid (Unused bit patterns) | 0x02 through 0xFF (2..=255) |
0b0000_0010 .. 0b1111_1111 |
Niche Optimization with Option<bool>
Because a valid bool only ever uses bit patterns 0 and 1, the remaining 254 byte values (2 through 255) are unused niches. The Rust compiler automatically uses one of these unused bit patterns (0x02) to represent None inside Option<bool>, so Option<bool> takes 1 byte of memory—the exact same size as a plain bool!
bool (1 byte): Option<bool> (also 1 byte!):
+-------------------+ +-------------------+
| 0x00 -> false | | 0x00 -> Some(false)|
| 0x01 -> true | | 0x01 -> Some(true) |
| 0x02..0xFF unused | | 0x02 -> None |
+-------------------+ +-------------------+
use std::mem::size_of;
fn main() {
println!("size_of::<bool>() = {} byte", size_of::<bool>());
println!("size_of::<Option<bool>>() = {} byte", size_of::<Option<bool>>());
}
size_of::<bool>() = 1 byte
size_of::<Option<bool>>() = 1 byte
Pattern Matching on bool
Because bool has only two possible values, a match expression over a bool is exhaustive as soon as it covers both true and false:
fn describe_state(online: bool) -> &'static str {
match online {
true => "Connected to server",
false => "Offline mode",
}
}
fn main() {
println!("{}", describe_state(true));
println!("{}", describe_state(false));
}
Connected to server
Offline mode
Omitting either true or false in a match expression fails to compile (E0004: non-exhaustive patterns).
Converting Between bool and Integers
Converting bool to an Integer (false -> 0, true -> 1)
A bool can be converted to any integer type losslessly using From::from (such as u8::from(flag) or i32::from(flag)) or the as cast operator (flag as usize):
falsealways converts to0.truealways converts to1.
fn main() {
let flags = [true, false, true, true, false];
// Count how many `true` values exist by converting each `bool` to `usize`
let mut active_count: usize = 0;
for flag in flags {
active_count += usize::from(flag);
}
println!("false as u8 = {}", false as u8);
println!("true as u8 = {}", true as u8);
println!("Active count: {active_count}");
}
false as u8 = 0
true as u8 = 1
Active count: 3
Converting an Integer to bool
Rust forbids casting an integer to a bool with as bool. Instead, write an explicit comparison such as n != 0:
// ❌ does not compile
fn main() {
let status_code = 1;
let ok = status_code as bool;
}
error[E0054]: cannot cast `i32` as `bool`
--> src/main.rs:3:14
|
3 | let ok = status_code as bool;
| ^^^^^^^^^^^^^^^^^^^ help: compare with zero instead: `status_code != 0`
error: aborting due to 1 previous error
Built-In Methods on bool: then and then_some
The bool type provides two convenient methods for turning a boolean condition directly into an Option<T> without writing an if / else block:
| Method | Signature | Behavior |
|---|---|---|
b.then_some(val) |
fn then_some<T>(self, t: T) -> Option<T> |
Eagerly evaluates val; returns Some(val) if b is true, or None if b is false |
b.then(|| expr) |
fn then<T, F>(self, f: F) -> Option<T> |
Lazily runs closure f only if b is true, returning Some(f()) or None |
fn main() {
let is_member = true;
let is_vip = false;
let discount = is_member.then_some(10);
let vip_badge = is_vip.then(|| String::from("Gold Star"));
println!("discount: {discount:?}");
println!("vip_badge: {vip_badge:?}");
}
discount: Some(10)
vip_badge: None
Ordering of bool Values (false < true)
Because false has the numeric representation 0 and true has the representation 1, bool implements Ord with false < true:
fn main() {
assert!(false < true);
let mut statuses = [true, false, true, false];
statuses.sort();
println!("Sorted booleans: {statuses:?}");
}
Sorted booleans: [false, false, true, true]