1
1
use clippy_config:: msrvs:: { self , Msrv } ;
2
2
use clippy_utils:: diagnostics:: span_lint_and_sugg;
3
3
use clippy_utils:: in_constant;
4
- use clippy_utils:: source:: snippet_opt;
4
+ use clippy_utils:: source:: { snippet_opt, snippet_with_applicability } ;
5
5
use clippy_utils:: ty:: is_isize_or_usize;
6
6
use rustc_errors:: Applicability ;
7
- use rustc_hir:: { Expr , ExprKind } ;
7
+ use rustc_hir:: { Expr , ExprKind , QPath , TyKind } ;
8
8
use rustc_lint:: LateContext ;
9
9
use rustc_middle:: ty:: { self , FloatTy , Ty } ;
10
10
@@ -16,6 +16,7 @@ pub(super) fn check(
16
16
cast_op : & Expr < ' _ > ,
17
17
cast_from : Ty < ' _ > ,
18
18
cast_to : Ty < ' _ > ,
19
+ cast_to_hir : & rustc_hir:: Ty < ' _ > ,
19
20
msrv : & Msrv ,
20
21
) {
21
22
if !should_lint ( cx, expr, cast_from, cast_to, msrv) {
@@ -24,11 +25,11 @@ pub(super) fn check(
24
25
25
26
// The suggestion is to use a function call, so if the original expression
26
27
// has parens on the outside, they are no longer needed.
27
- let mut applicability = Applicability :: MachineApplicable ;
28
+ let mut app = Applicability :: MachineApplicable ;
28
29
let opt = snippet_opt ( cx, cast_op. span . source_callsite ( ) ) ;
29
30
let sugg = opt. as_ref ( ) . map_or_else (
30
31
|| {
31
- applicability = Applicability :: HasPlaceholders ;
32
+ app = Applicability :: HasPlaceholders ;
32
33
".."
33
34
} ,
34
35
|snip| {
@@ -40,10 +41,27 @@ pub(super) fn check(
40
41
} ,
41
42
) ;
42
43
44
+ // Display the type alias instead of the aliased type. Fixes #11285
45
+ //
46
+ // FIXME: Once `lazy_type_alias` is stabilized(?) we should use `rustc_middle` types instead,
47
+ // this will allow us to display the right type with `cast_from` as well.
48
+ let cast_to_fmt = if let TyKind :: Path ( QPath :: Resolved ( None , path) ) = cast_to_hir. kind
49
+ // It's a bit annoying but the turbofish is optional for types. A type in an `as` cast
50
+ // shouldn't have these if they're primitives, which are the only things we deal with.
51
+ //
52
+ // This could be removed for performance if this check is determined to have a pretty major
53
+ // effect.
54
+ && path. segments . iter ( ) . all ( |segment| segment. args . is_none ( ) )
55
+ {
56
+ snippet_with_applicability ( cx, cast_to_hir. span , ".." , & mut app)
57
+ } else {
58
+ cast_to. to_string ( ) . into ( )
59
+ } ;
60
+
43
61
let message = if cast_from. is_bool ( ) {
44
- format ! ( "casting `{cast_from: }` to `{cast_to: }` is more cleanly stated with `{cast_to: }::from(_)`" )
62
+ format ! ( "casting `{cast_from}` to `{cast_to_fmt }` is more cleanly stated with `{cast_to_fmt }::from(_)`" )
45
63
} else {
46
- format ! ( "casting `{cast_from}` to `{cast_to }` may become silently lossy if you later change the type" )
64
+ format ! ( "casting `{cast_from}` to `{cast_to_fmt }` may become silently lossy if you later change the type" )
47
65
} ;
48
66
49
67
span_lint_and_sugg (
@@ -52,8 +70,8 @@ pub(super) fn check(
52
70
expr. span ,
53
71
& message,
54
72
"try" ,
55
- format ! ( "{cast_to }::from({sugg})" ) ,
56
- applicability ,
73
+ format ! ( "{cast_to_fmt }::from({sugg})" ) ,
74
+ app ,
57
75
) ;
58
76
}
59
77
0 commit comments