Rust 2024 Let-Chain Candidate
Description
Rust 2024 supports let conditions in boolean chains, so an if let wrapping a single nested if can often be collapsed into one condition.
This rule reports the outer if only when neither branch has an else, the outer block contains a single inner if statement, and either the outer or inner condition is an if let.
YAML
yaml
id: rust-2024-let-chain-candidate
language: Rust
severity: hint
message: nested if conditions can be collapsed into a Rust 2024 let-chain
utils:
# The nested if statement should be the only statement in its block.
sole-child:
all:
- nthChild: 1
- nthChild:
position: 1
reverse: true
# Let-chains can only preserve behavior when there is no else branch.
if-no-else:
kind: if_expression
not:
has:
field: alternative
kind: else_clause
# At least one side of the nested if pair must be an if let.
if-let-no-else:
matches: if-no-else
has:
field: condition
kind: let_condition
# Match an inner if that is the sole statement inside the outer if block.
sole-inner-if-stmt:
kind: expression_statement
matches: sole-child
has:
matches: if-no-else
# Same as above, but require the inner if to be an if let.
sole-inner-if-let-stmt:
kind: expression_statement
matches: sole-child
has:
matches: if-let-no-else
rule:
# Start from an outer if without an else branch.
matches: if-no-else
# Its direct consequence block must contain exactly one inner if statement.
has:
field: consequence
kind: block
has:
matches: sole-inner-if-stmt
# Either the outer condition or the inner condition must bind with if let.
any:
- matches: if-let-no-else
- has:
field: consequence
kind: block
has:
matches: sole-inner-if-let-stmtExample
rs
fn handle_request(user: Option<User>, cfg: Config) {
if let Some(user) = user {
if user.is_active() {
grant_access(user);
}
}
if cfg!(debug_assertions) {
if let Some(path) = cfg.log_path() {
enable_file_logging(path);
}
}
// OK: the inner if is not the only statement in the block.
if let Some(user) = current_user() {
audit(&user);
if user.is_admin() {
grant_admin(user);
}
}
// OK: this has an else branch.
if let Some(path) = cfg.cache_path() {
if path.exists() {
load_cache(path);
}
} else {
rebuild_cache();
}
}Contributed by
Codex (GPT-5.5 high fast)