Skip to content

Commit 733a9ea

Browse files
committed
[option_if_let_else]: suggest .as_ref() if &Option<_>
1 parent 8fd021f commit 733a9ea

File tree

4 files changed

+64
-1
lines changed

4 files changed

+64
-1
lines changed

clippy_lints/src/option_if_let_else.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ fn try_get_option_occurrence<'tcx>(
140140
let (as_ref, as_mut) = match &expr.kind {
141141
ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
142142
ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
143+
_ if let Some(mutb) = cx.typeck_results().expr_ty(expr).ref_mutability() => {
144+
(mutb == Mutability::Not, mutb == Mutability::Mut)
145+
}
143146
_ => (bind_annotation == BindingAnnotation::REF, bind_annotation == BindingAnnotation::REF_MUT),
144147
};
145148

tests/ui/option_if_let_else.fixed

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ fn main() {
198198
let _ = res.map_or(1, |a| a + 1);
199199
let _ = res.map_or(1, |a| a + 1);
200200
let _ = res.map_or(5, |a| a + 1);
201+
issue10729::reproduce(&None);
202+
issue10729::reproduce2(&mut None);
201203
}
202204

203205
#[allow(dead_code)]
@@ -208,3 +210,19 @@ fn issue9742() -> Option<&'static str> {
208210
_ => None,
209211
}
210212
}
213+
214+
mod issue10729 {
215+
#![allow(clippy::unit_arg)]
216+
217+
pub fn reproduce(initial: &Option<String>) {
218+
// 👇 needs `.as_ref()` because initial is an `&Option<_>`
219+
initial.as_ref().map_or({}, |value| do_something(value))
220+
}
221+
222+
pub fn reproduce2(initial: &mut Option<String>) {
223+
initial.as_mut().map_or({}, |value| do_something2(value))
224+
}
225+
226+
fn do_something(_value: &str) {}
227+
fn do_something2(_value: &mut str) {}
228+
}

tests/ui/option_if_let_else.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,8 @@ fn main() {
239239
Ok(a) => a + 1,
240240
};
241241
let _ = if let Ok(a) = res { a + 1 } else { 5 };
242+
issue10729::reproduce(&None);
243+
issue10729::reproduce2(&mut None);
242244
}
243245

244246
#[allow(dead_code)]
@@ -249,3 +251,25 @@ fn issue9742() -> Option<&'static str> {
249251
_ => None,
250252
}
251253
}
254+
255+
mod issue10729 {
256+
#![allow(clippy::unit_arg)]
257+
258+
pub fn reproduce(initial: &Option<String>) {
259+
// 👇 needs `.as_ref()` because initial is an `&Option<_>`
260+
match initial {
261+
Some(value) => do_something(value),
262+
None => {},
263+
}
264+
}
265+
266+
pub fn reproduce2(initial: &mut Option<String>) {
267+
match initial {
268+
Some(value) => do_something2(value),
269+
None => {},
270+
}
271+
}
272+
273+
fn do_something(_value: &str) {}
274+
fn do_something2(_value: &mut str) {}
275+
}

tests/ui/option_if_let_else.stderr

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,5 +271,23 @@ error: use Option::map_or instead of an if let/else
271271
LL | let _ = if let Ok(a) = res { a + 1 } else { 5 };
272272
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)`
273273

274-
error: aborting due to 21 previous errors
274+
error: use Option::map_or instead of an if let/else
275+
--> $DIR/option_if_let_else.rs:260:9
276+
|
277+
LL | / match initial {
278+
LL | | Some(value) => do_something(value),
279+
LL | | None => {},
280+
LL | | }
281+
| |_________^ help: try: `initial.as_ref().map_or({}, |value| do_something(value))`
282+
283+
error: use Option::map_or instead of an if let/else
284+
--> $DIR/option_if_let_else.rs:267:9
285+
|
286+
LL | / match initial {
287+
LL | | Some(value) => do_something2(value),
288+
LL | | None => {},
289+
LL | | }
290+
| |_________^ help: try: `initial.as_mut().map_or({}, |value| do_something2(value))`
291+
292+
error: aborting due to 23 previous errors
275293

0 commit comments

Comments
 (0)