Skip to content

Commit f7df011

Browse files
committed
remove parent fn call check, make .try_into().unwrap()
1 parent f6b64d1 commit f7df011

6 files changed

+131
-85
lines changed

clippy_lints/src/methods/unnecessary_fallible_conversions.rs

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ enum FunctionKind {
1818
TryFromFunction,
1919
/// `t.try_into()`
2020
TryIntoMethod,
21-
/// `U::try_into()`
21+
/// `U::try_into(t)`
2222
TryIntoFunction,
2323
}
2424

@@ -40,31 +40,48 @@ fn check<'tcx>(
4040
// If `T: TryFrom<U>` and `T: From<U>` both exist, then that means that the `TryFrom`
4141
// _must_ be from the blanket impl and cannot have been manually implemented
4242
// (else there would be conflicting impls, even with #![feature(spec)]), so we don't even need to check
43-
// what `<T as TryFrom<U>>::Error` is.
43+
// what `<T as TryFrom<U>>::Error` is: it's always `Infallible`
4444
&& implements_trait(cx, self_ty, from_into_trait, &[other_ty])
45-
// Avoid linting if this is an argument to a function: `f(i32.try_into())`.
46-
// The function expects a `Result` either way, so users would need to wrap it back in `Ok(..)`
47-
// and save on nothing
48-
&& get_parent_expr(cx, expr).map_or(true, |parent| !matches!(parent.kind, ExprKind::Call(..)))
4945
{
46+
let parent_unwrap_call = get_parent_expr(cx, expr)
47+
.and_then(|parent| {
48+
if let ExprKind::MethodCall(path, .., span) = parent.kind
49+
&& let sym::unwrap | sym::expect = path.ident.name
50+
{
51+
Some(span)
52+
} else {
53+
None
54+
}
55+
});
56+
57+
let (sugg, span, applicability) = match kind {
58+
FunctionKind::TryIntoMethod if let Some(unwrap_span) = parent_unwrap_call => {
59+
// Extend the span to include the unwrap/expect call:
60+
// `foo.try_into().expect("..")`
61+
// ^^^^^^^^^^^^^^^^^^^^^^^
62+
//
63+
// `try_into().unwrap()` specifically can be trivially replaced with just `into()`,
64+
// so that can be machine-applicable
65+
66+
("into()", primary_span.with_hi(unwrap_span.hi()), Applicability::MachineApplicable)
67+
}
68+
FunctionKind::TryFromFunction => ("From::from", primary_span, Applicability::Unspecified),
69+
FunctionKind::TryIntoFunction => ("Into::into", primary_span, Applicability::Unspecified),
70+
FunctionKind::TryIntoMethod => ("into", primary_span, Applicability::Unspecified),
71+
};
72+
5073
span_lint_and_sugg(
5174
cx,
5275
UNNECESSARY_FALLIBLE_CONVERSIONS,
53-
primary_span,
76+
span,
5477
match kind {
5578
FunctionKind::TryFromFunction => "calling `TryFrom::try_from` when `From` could be used",
5679
FunctionKind::TryIntoMethod
5780
| FunctionKind::TryIntoFunction => "calling `TryInto::try_into` when `Into` could be used",
5881
},
5982
"use",
60-
match kind {
61-
FunctionKind::TryFromFunction => "From::from".into(),
62-
FunctionKind::TryIntoFunction => "Into::into".into(),
63-
FunctionKind::TryIntoMethod => "into".into(),
64-
},
65-
// Suggestion likely results in compile errors, so it needs to be adjusted a bit by the user
66-
// (e.g. removing `unwrap()`s as a result, changing type annotations, ...)
67-
Applicability::Unspecified
83+
sugg.into(),
84+
applicability
6885
);
6986
}
7087
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![warn(clippy::unnecessary_fallible_conversions)]
2+
3+
fn main() {
4+
let _: i64 = 0i32.into();
5+
let _: i64 = 0i32.into();
6+
}
Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,6 @@
1-
//@aux-build:proc_macros.rs
2-
//@no-rustfix
31
#![warn(clippy::unnecessary_fallible_conversions)]
42

5-
extern crate proc_macros;
6-
7-
struct Foo;
8-
impl TryFrom<i32> for Foo {
9-
type Error = ();
10-
fn try_from(_: i32) -> Result<Self, Self::Error> {
11-
Ok(Foo)
12-
}
13-
}
14-
impl From<i64> for Foo {
15-
fn from(_: i64) -> Self {
16-
Foo
17-
}
18-
}
19-
203
fn main() {
21-
// `Foo` only implements `TryFrom<i32>` and not `From<i32>`, so don't lint
22-
let _: Result<Foo, _> = 0i32.try_into();
23-
let _: Result<Foo, _> = i32::try_into(0i32);
24-
let _: Result<Foo, _> = Foo::try_from(0i32);
25-
26-
// ... it does impl From<i64> however
27-
let _: Result<Foo, _> = 0i64.try_into();
28-
//~^ ERROR: calling `TryInto::try_into` when `Into` could be used
29-
let _: Result<Foo, _> = i64::try_into(0i64);
30-
//~^ ERROR: calling `TryInto::try_into` when `Into` could be used
31-
let _: Result<Foo, _> = Foo::try_from(0i64);
32-
//~^ ERROR: calling `TryFrom::try_from` when `From` could be used
33-
34-
let _: Result<i64, _> = 0i32.try_into();
35-
//~^ ERROR: calling `TryInto::try_into` when `Into` could be used
36-
let _: Result<i64, _> = i32::try_into(0i32);
37-
//~^ ERROR: calling `TryInto::try_into` when `Into` could be used
38-
let _: Result<i64, _> = <_>::try_from(0i32);
39-
//~^ ERROR: calling `TryFrom::try_from` when `From` could be used
40-
41-
// From a macro
42-
let _: Result<i64, _> = proc_macros::external!(0i32).try_into();
4+
let _: i64 = 0i32.try_into().unwrap();
5+
let _: i64 = 0i32.try_into().expect("can't happen");
436
}
Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,17 @@
11
error: calling `TryInto::try_into` when `Into` could be used
2-
--> $DIR/unnecessary_fallible_conversions.rs:27:34
2+
--> $DIR/unnecessary_fallible_conversions.rs:4:23
33
|
4-
LL | let _: Result<Foo, _> = 0i64.try_into();
5-
| ^^^^^^^^ help: use: `into`
4+
LL | let _: i64 = 0i32.try_into().unwrap();
5+
| ^^^^^^^^^^^^^^^^^^^ help: use: `into()`
66
|
77
= note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings`
88
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]`
99

1010
error: calling `TryInto::try_into` when `Into` could be used
11-
--> $DIR/unnecessary_fallible_conversions.rs:29:29
11+
--> $DIR/unnecessary_fallible_conversions.rs:5:23
1212
|
13-
LL | let _: Result<Foo, _> = i64::try_into(0i64);
14-
| ^^^^^^^^^^^^^ help: use: `Into::into`
13+
LL | let _: i64 = 0i32.try_into().expect("can't happen");
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `into()`
1515

16-
error: calling `TryFrom::try_from` when `From` could be used
17-
--> $DIR/unnecessary_fallible_conversions.rs:31:29
18-
|
19-
LL | let _: Result<Foo, _> = Foo::try_from(0i64);
20-
| ^^^^^^^^^^^^^ help: use: `From::from`
21-
22-
error: calling `TryInto::try_into` when `Into` could be used
23-
--> $DIR/unnecessary_fallible_conversions.rs:34:34
24-
|
25-
LL | let _: Result<i64, _> = 0i32.try_into();
26-
| ^^^^^^^^ help: use: `into`
27-
28-
error: calling `TryInto::try_into` when `Into` could be used
29-
--> $DIR/unnecessary_fallible_conversions.rs:36:29
30-
|
31-
LL | let _: Result<i64, _> = i32::try_into(0i32);
32-
| ^^^^^^^^^^^^^ help: use: `Into::into`
33-
34-
error: calling `TryFrom::try_from` when `From` could be used
35-
--> $DIR/unnecessary_fallible_conversions.rs:38:29
36-
|
37-
LL | let _: Result<i64, _> = <_>::try_from(0i32);
38-
| ^^^^^^^^^^^^^ help: use: `From::from`
39-
40-
error: aborting due to 6 previous errors
16+
error: aborting due to 2 previous errors
4117

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//@aux-build:proc_macros.rs
2+
//@no-rustfix
3+
#![warn(clippy::unnecessary_fallible_conversions)]
4+
5+
extern crate proc_macros;
6+
7+
struct Foo;
8+
impl TryFrom<i32> for Foo {
9+
type Error = ();
10+
fn try_from(_: i32) -> Result<Self, Self::Error> {
11+
Ok(Foo)
12+
}
13+
}
14+
impl From<i64> for Foo {
15+
fn from(_: i64) -> Self {
16+
Foo
17+
}
18+
}
19+
20+
fn main() {
21+
// `Foo` only implements `TryFrom<i32>` and not `From<i32>`, so don't lint
22+
let _: Result<Foo, _> = 0i32.try_into();
23+
let _: Result<Foo, _> = i32::try_into(0i32);
24+
let _: Result<Foo, _> = Foo::try_from(0i32);
25+
26+
// ... it does impl From<i64> however
27+
let _: Result<Foo, _> = 0i64.try_into();
28+
//~^ ERROR: calling `TryInto::try_into` when `Into` could be used
29+
let _: Result<Foo, _> = i64::try_into(0i64);
30+
//~^ ERROR: calling `TryInto::try_into` when `Into` could be used
31+
let _: Result<Foo, _> = Foo::try_from(0i64);
32+
//~^ ERROR: calling `TryFrom::try_from` when `From` could be used
33+
34+
let _: Result<i64, _> = 0i32.try_into();
35+
//~^ ERROR: calling `TryInto::try_into` when `Into` could be used
36+
let _: Result<i64, _> = i32::try_into(0i32);
37+
//~^ ERROR: calling `TryInto::try_into` when `Into` could be used
38+
let _: Result<i64, _> = <_>::try_from(0i32);
39+
//~^ ERROR: calling `TryFrom::try_from` when `From` could be used
40+
41+
// From a macro
42+
let _: Result<i64, _> = proc_macros::external!(0i32).try_into();
43+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
error: calling `TryInto::try_into` when `Into` could be used
2+
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:27:34
3+
|
4+
LL | let _: Result<Foo, _> = 0i64.try_into();
5+
| ^^^^^^^^ help: use: `into`
6+
|
7+
= note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]`
9+
10+
error: calling `TryInto::try_into` when `Into` could be used
11+
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:29:29
12+
|
13+
LL | let _: Result<Foo, _> = i64::try_into(0i64);
14+
| ^^^^^^^^^^^^^ help: use: `Into::into`
15+
16+
error: calling `TryFrom::try_from` when `From` could be used
17+
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:31:29
18+
|
19+
LL | let _: Result<Foo, _> = Foo::try_from(0i64);
20+
| ^^^^^^^^^^^^^ help: use: `From::from`
21+
22+
error: calling `TryInto::try_into` when `Into` could be used
23+
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:34:34
24+
|
25+
LL | let _: Result<i64, _> = 0i32.try_into();
26+
| ^^^^^^^^ help: use: `into`
27+
28+
error: calling `TryInto::try_into` when `Into` could be used
29+
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:36:29
30+
|
31+
LL | let _: Result<i64, _> = i32::try_into(0i32);
32+
| ^^^^^^^^^^^^^ help: use: `Into::into`
33+
34+
error: calling `TryFrom::try_from` when `From` could be used
35+
--> $DIR/unnecessary_fallible_conversions_unfixable.rs:38:29
36+
|
37+
LL | let _: Result<i64, _> = <_>::try_from(0i32);
38+
| ^^^^^^^^^^^^^ help: use: `From::from`
39+
40+
error: aborting due to 6 previous errors
41+

0 commit comments

Comments
 (0)