Skip to content

Commit 2bff3d8

Browse files
committed
Auto merge of #4446 - mikerite:fix-4437, r=phansch
Fix `match_as_ref` bad suggestion Fixes #4437 changelog: Fix `match_as_ref` bad suggestion
2 parents 28a8a6a + 0c83325 commit 2bff3d8

File tree

4 files changed

+76
-3
lines changed

4 files changed

+76
-3
lines changed

clippy_lints/src/matches.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,24 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &
624624
} else {
625625
"as_mut"
626626
};
627+
628+
let output_ty = cx.tables.expr_ty(expr);
629+
let input_ty = cx.tables.expr_ty(ex);
630+
631+
let cast = if_chain! {
632+
if let ty::Adt(_, substs) = input_ty.sty;
633+
let input_ty = substs.type_at(0);
634+
if let ty::Adt(_, substs) = output_ty.sty;
635+
let output_ty = substs.type_at(0);
636+
if let ty::Ref(_, output_ty, _) = output_ty.sty;
637+
if input_ty != output_ty;
638+
then {
639+
".map(|x| x as _)"
640+
} else {
641+
""
642+
}
643+
};
644+
627645
let mut applicability = Applicability::MachineApplicable;
628646
span_lint_and_sugg(
629647
cx,
@@ -632,9 +650,10 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &
632650
&format!("use {}() instead", suggestion),
633651
"try this",
634652
format!(
635-
"{}.{}()",
653+
"{}.{}(){}",
636654
snippet_with_applicability(cx, ex.span, "_", &mut applicability),
637-
suggestion
655+
suggestion,
656+
cast,
638657
),
639658
applicability,
640659
)

tests/ui/match_as_ref.fixed

+21
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,25 @@ fn match_as_ref() {
1111
let borrow_mut: Option<&mut ()> = mut_owned.as_mut();
1212
}
1313

14+
mod issue4437 {
15+
use std::{error::Error, fmt, num::ParseIntError};
16+
17+
#[derive(Debug)]
18+
struct E {
19+
source: Option<ParseIntError>,
20+
}
21+
22+
impl Error for E {
23+
fn source(&self) -> Option<&(dyn Error + 'static)> {
24+
self.source.as_ref().map(|x| x as _)
25+
}
26+
}
27+
28+
impl fmt::Display for E {
29+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30+
unimplemented!()
31+
}
32+
}
33+
}
34+
1435
fn main() {}

tests/ui/match_as_ref.rs

+24
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,28 @@ fn match_as_ref() {
1717
};
1818
}
1919

20+
mod issue4437 {
21+
use std::{error::Error, fmt, num::ParseIntError};
22+
23+
#[derive(Debug)]
24+
struct E {
25+
source: Option<ParseIntError>,
26+
}
27+
28+
impl Error for E {
29+
fn source(&self) -> Option<&(dyn Error + 'static)> {
30+
match self.source {
31+
Some(ref s) => Some(s),
32+
None => None,
33+
}
34+
}
35+
}
36+
37+
impl fmt::Display for E {
38+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39+
unimplemented!()
40+
}
41+
}
42+
}
43+
2044
fn main() {}

tests/ui/match_as_ref.stderr

+10-1
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,14 @@ LL | | Some(ref mut v) => Some(v),
2020
LL | | };
2121
| |_____^ help: try this: `mut_owned.as_mut()`
2222

23-
error: aborting due to 2 previous errors
23+
error: use as_ref() instead
24+
--> $DIR/match_as_ref.rs:30:13
25+
|
26+
LL | / match self.source {
27+
LL | | Some(ref s) => Some(s),
28+
LL | | None => None,
29+
LL | | }
30+
| |_____________^ help: try this: `self.source.as_ref().map(|x| x as _)`
31+
32+
error: aborting due to 3 previous errors
2433

0 commit comments

Comments
 (0)