Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The * operator in Rust serves two distinct semantic purposes depending on its arity: as a unary prefix operator, it performs pointer dereferencing, and as a binary infix operator, it performs arithmetic multiplication.

Unary *: Dereference Operator

As a unary operator, * resolves a reference or pointer to its underlying memory location. Evaluating *expr yields a place expression (lvalue) of type T from a pointer or reference of type &T, &mut T, *const T, or *mut T. It only yields a value (via copy or move) when this place expression is evaluated in a value context. Trait Implementation and Desugaring For built-in reference types and the intrinsic Box<T> type, dereferencing is a compiler intrinsic operation. Notably, dereferencing a Box<T> is a special intrinsic that allows moving the underlying value out of the heap allocation, provided the underlying type does not implement the Copy trait. For user-defined smart pointers (e.g., String, Rc<T>), the * operator acts as syntactic sugar that invokes the std::ops::Deref or std::ops::DerefMut traits. Because standard Deref desugaring returns a reference, moving a value out of these types via * is not possible.
  • In an immutable context, *x desugars to *(std::ops::Deref::deref(&x)).
  • In a mutable context, *x desugars to *(std::ops::DerefMut::deref_mut(&mut x)).
// Immutable reference dereferencing (place expression in value context yields a copy for Copy types)
let val: i32 = 10;
let ref_val: &i32 = &val;
let deref_val: i32 = *ref_val; 

// Mutable reference dereferencing (place expression in assignment context)
let mut mut_val: i32 = 20;
let mut_ref: &mut i32 = &mut mut_val;
*mut_ref = 30; // Mutates the underlying memory location

// Box dereferencing (intrinsic move out of Box for non-Copy types)
let boxed_val: Box<String> = Box::new(String::from("Rust"));
let unboxed_val: String = *boxed_val; // Moves the String out of the heap allocation
// boxed_val is statically invalidated here by the borrow checker
Raw Pointers When applied to raw pointers (*const T or *mut T), the * operator bypasses Rust’s borrow checker guarantees. Because the compiler cannot guarantee the validity of the memory address, dereferencing a raw pointer is strictly an unsafe operation.
let val: i32 = 50;
let raw_ptr: *const i32 = &val as *const i32;

unsafe {
    // Requires unsafe block to evaluate the place expression
    let deref_raw: i32 = *raw_ptr;
}

Binary *: Multiplication Operator

As a binary operator, * computes the arithmetic product of its left and right operands. Trait Implementation and Desugaring The binary * operator is backed by the std::ops::Mul trait. An expression like a * b is syntactic sugar for std::ops::Mul::mul(a, b). The compound assignment variant, *=, is backed by the std::ops::MulAssign trait.
// Standard binary multiplication
let a: i32 = 5;
let b: i32 = 6;
let product: i32 = a * b; // Desugars to std::ops::Mul::mul(a, b)

// Compound assignment
let mut c: i32 = 10;
c *= 2; // Desugars to std::ops::MulAssign::mul_assign(&mut c, 2)

Syntactic Token Contexts

While not functioning as an expression operator, the * symbol is also parsed by the compiler in three specific declaration and syntax contexts:
  1. Raw Pointer Types: Used in type signatures to denote raw pointers (*const T and *mut T).
  2. Glob Imports: Used in use statements to bind all public items from a module into the current namespace (use std::collections::*;).
  3. Macro Repetitions: Used in macro_rules! definitions as a Kleene star to indicate zero or more repetitions of a token tree (e.g., $( $x:expr ),*).
Master Rust with Deep Grasping Methodology!Learn More