rust/tests/ui/manual_unwrap_or.fixed
Samuel Tardieu 94233fb0ee Unify manual_unwrap_or and manual_unwrap_or_default code
Both lints share a lot of characteristics but were implemented in
unrelated ways. This unifies them, saving around 100 SLOC in the
process, and making one more test trigger the lint. Also, this removes
useless blocks in suggestions.
2025-03-25 18:03:41 +01:00

253 lines
5 KiB
Rust

#![allow(dead_code)]
#![allow(
unused_variables,
clippy::unnecessary_wraps,
clippy::unnecessary_literal_unwrap,
clippy::manual_unwrap_or_default
)]
fn option_unwrap_or() {
// int case
Some(1).unwrap_or(42);
// int case reversed
Some(1).unwrap_or(42);
// richer none expr
Some(1).unwrap_or(1 + 42);
// multiline case
#[rustfmt::skip]
Some(1).unwrap_or(42 + 42
+ 42 + 42 + 42
+ 42 + 42 + 42);
// string case
Some("Bob").unwrap_or("Alice");
// don't lint
match Some(1) {
Some(i) => i + 2,
None => 42,
};
match Some(1) {
Some(i) => i,
None => return,
};
for j in 0..4 {
match Some(j) {
Some(i) => i,
None => continue,
};
match Some(j) {
Some(i) => i,
None => break,
};
}
// cases where the none arm isn't a constant expression
// are not linted due to potential ownership issues
// ownership issue example, don't lint
struct NonCopyable;
let mut option: Option<NonCopyable> = None;
match option {
Some(x) => x,
None => {
option = Some(NonCopyable);
// some more code ...
option.unwrap()
},
};
// ownership issue example, don't lint
let option: Option<&str> = None;
match option {
Some(s) => s,
None => &format!("{} {}!", "hello", "world"),
};
Some(1).unwrap_or(42);
//don't lint
if let Some(x) = Some(1) {
x + 1
} else {
42
};
if let Some(x) = Some(1) {
x
} else {
return;
};
for j in 0..4 {
if let Some(x) = Some(j) {
x
} else {
continue;
};
if let Some(x) = Some(j) {
x
} else {
break;
};
}
}
fn result_unwrap_or() {
// int case
Ok::<i32, &str>(1).unwrap_or(42);
// int case, scrutinee is a binding
let a = Ok::<i32, &str>(1);
a.unwrap_or(42);
// int case, suggestion must surround Result expr with parentheses
(Ok(1) as Result<i32, &str>).unwrap_or(42);
// method call case, suggestion must not surround Result expr `s.method()` with parentheses
struct S;
impl S {
fn method(self) -> Option<i32> {
Some(42)
}
}
let s = S {};
s.method().unwrap_or(42);
// int case reversed
Ok::<i32, &str>(1).unwrap_or(42);
// richer none expr
Ok::<i32, &str>(1).unwrap_or(1 + 42);
// multiline case
#[rustfmt::skip]
Ok::<i32, &str>(1).unwrap_or(42 + 42
+ 42 + 42 + 42
+ 42 + 42 + 42);
// string case
Ok::<&str, &str>("Bob").unwrap_or("Alice");
// don't lint
match Ok::<i32, &str>(1) {
Ok(i) => i + 2,
Err(_) => 42,
};
match Ok::<i32, &str>(1) {
Ok(i) => i,
Err(_) => return,
};
for j in 0..4 {
match Ok::<i32, &str>(j) {
Ok(i) => i,
Err(_) => continue,
};
match Ok::<i32, &str>(j) {
Ok(i) => i,
Err(_) => break,
};
}
// don't lint, Err value is used
match Ok::<&str, &str>("Alice") {
Ok(s) => s,
Err(s) => s,
};
Ok::<&str, &str>("Alice").unwrap_or("Bob");
Ok::<i32, i32>(1).unwrap_or(42);
//don't lint
if let Ok(x) = Ok::<i32, i32>(1) {
x + 1
} else {
42
};
if let Ok(x) = Ok::<i32, i32>(1) {
x
} else {
return;
};
for j in 0..4 {
if let Ok(x) = Ok::<i32, i32>(j) {
x
} else {
continue;
};
if let Ok(x) = Ok::<i32, i32>(j) {
x
} else {
break;
};
}
}
// don't lint in const fn
const fn const_fn_option_unwrap_or() {
match Some(1) {
Some(s) => s,
None => 0,
};
}
const fn const_fn_result_unwrap_or() {
match Ok::<&str, &str>("Alice") {
Ok(s) => s,
Err(_) => "Bob",
};
}
mod issue6965 {
macro_rules! some_macro {
() => {
if 1 > 2 { Some(1) } else { None }
};
}
fn test() {
let _ = some_macro!().unwrap_or(0);
}
}
use std::rc::Rc;
fn format_name(name: Option<&Rc<str>>) -> &str {
match name {
None => "<anon>",
Some(name) => name,
}
}
fn implicit_deref_ref() {
let _: &str = match Some(&"bye") {
None => "hi",
Some(s) => s,
};
}
mod issue_13018 {
use std::collections::HashMap;
type RefName = i32;
pub fn get(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
if let Some(names) = index.get(&id) { names } else { &[] }
}
pub fn get_match(index: &HashMap<usize, Vec<RefName>>, id: usize) -> &[RefName] {
match index.get(&id) {
Some(names) => names,
None => &[],
}
}
}
fn implicit_deref(v: Vec<String>) {
let _ = if let Some(s) = v.first() { s } else { "" };
}
fn allowed_manual_unwrap_or_zero() -> u32 {
Some(42).unwrap_or(0)
}
fn main() {}