For AI agents: A markdown version of this page is available at https://docs.datadoghq.com/security/code_security/static_analysis/static_analysis_rules/rust-code-quality/bind-instead-of-map.md. A documentation index is available at /llms.txt.

Use map instead of and_then/or_else wrapping a constructor

This product is not supported for your selected Datadog site. ().

Metadata

ID: rust-code-quality/bind-instead-of-map

Language: Rust

Severity: Warning

Category: Best Practices

Description

Using and_then(|x| Some(y)), and_then(|x| Ok(y)), or or_else(|e| Err(y)) wraps a value in a constructor only for and_then/or_else to immediately unwrap it again. The extra layer adds noise without adding clarity.

How to remediate?

Replace with the simpler combinator:

// Before
opt.and_then(|x| Some(x + 1))
// After
opt.map(|x| x + 1)

// Before
res.and_then(|x| Ok(x + 1))
// After
res.map(|x| x + 1)

// Before
res.or_else(|e| Err(e.to_string()))
// After
res.map_err(|e| e.to_string())

// Before
opt.or_else(|| None)
// After
opt

Non-Compliant Code Examples

fn option_and_then_some(opt: Option<i32>) -> Option<i32> {
    opt.and_then(|x| Some(x + 1))
}

fn result_and_then_ok(res: Result<i32, String>) -> Result<i32, String> {
    res.and_then(|x| Ok(x * 2))
}

fn result_or_else_err(res: Result<i32, String>) -> Result<i32, String> {
    res.or_else(|e| Err(e + "!"))
}

fn option_or_else_none(opt: Option<i32>) -> Option<i32> {
    opt.or_else(|| None)
}

fn option_and_then_block_closure(opt: Option<i32>) -> Option<i32> {
  opt.and_then(|x| { Some(x + 1) })
}

fn option_or_else_nested(opt: Option<i32>) -> Option<i32> {
  opt.and_then(|x| Some(inner.and_then(|y| Some(y + 1))))
}

Compliant Code Examples

fn already_map(opt: Option<i32>) -> Option<i32> {
    opt.map(|x| x + 1)
}

fn already_map_err(res: Result<i32, String>) -> Result<i32, String> {
    res.map_err(|e| e.to_string())
}

fn and_then_conditional(opt: Option<i32>) -> Option<i32> {
    opt.and_then(|x| if x > 0 { Some(x) } else { None })
}

fn or_else_returns_some(opt: Option<i32>) -> Option<i32> {
    opt.or_else(|| Some(0))
}

fn and_then_with_question_mark(opt: Option<Foo>) -> Option<(u32, Vec<String>)> {
    opt.and_then(|info| Some((info.id?, info.tags)))
}
https://static.datadoghq.com/static/images/logos/github_avatar.svg https://static.datadoghq.com/static/images/logos/vscode_avatar.svg jetbrains

Seamless integrations. Try Datadog Code Security