id: prefer-unwrap-or-else
language: Rust
severity: hint
message: Pass the default value as a closure to avoid eager evaluation.
note: |
`.unwrap_or(expr)` always evaluates `expr`, even when the `Option` is
`Some`. When `expr` is a function or method call (e.g. `Vec::new()`,
`String::from(...)`, `path.display().to_string()`), that cost is wasted
on the `Some` branch. Switch to `.unwrap_or_else(|| expr)` so the
default is only built when actually needed.
This rule only triggers when the default is a *call expression*.
Literal defaults like `unwrap_or(0)` or `unwrap_or("")` are fine and
are intentionally not flagged.
rule:
pattern: $OPT.unwrap_or($DEFAULT)
constraints:
DEFAULT:
kind: call_expression
fix: $OPT.unwrap_or_else(|| $DEFAULT)
files:
- "**/*.rs"