1
+ use rustc_hir:: def:: DefKind :: * ;
1
2
use rustc_middle:: mir:: visit:: Visitor ;
2
3
use rustc_middle:: mir:: { Body , Location , Operand , Terminator , TerminatorKind } ;
3
4
use rustc_middle:: ty:: * ;
@@ -29,6 +30,7 @@ impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> {
29
30
function : & Operand < ' tcx > ,
30
31
arg : String ,
31
32
span : Span ,
33
+ is_in_const : bool ,
32
34
) -> Option < Error > {
33
35
let fn_sig = function. ty ( self . body , self . tcx ) . fn_sig ( self . tcx ) . skip_binder ( ) ;
34
36
let [ input] = fn_sig. inputs ( ) else { return None } ;
@@ -69,9 +71,15 @@ impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> {
69
71
( Float ( ty) , Uint ( ..) ) => err ( format ! ( "{}::to_bits({arg})" , ty. name_str( ) ) ) ,
70
72
// uNN → fNN
71
73
( Uint ( _) , Float ( ty) ) => err ( format ! ( "{}::from_bits({arg})" , ty. name_str( ) ) ) ,
72
- // bool → { x8 }
73
- ( Bool , Int ( ..) | Uint ( ..) ) => err ( format ! ( "({arg}) as {}" , fn_sig. output( ) ) ) ,
74
+ // bool → { x8 } in const context
75
+ // is it possible to know when the parentheses arent necessary?
76
+ ( Bool , Int ( ..) | Uint ( ..) ) if is_in_const => {
77
+ err ( format ! ( "({arg}) as {}" , fn_sig. output( ) ) )
78
+ }
79
+ // " using `x8::from`
80
+ ( Bool , Int ( ..) | Uint ( ..) ) => err ( format ! ( "{}::from({arg})" , fn_sig. output( ) ) ) ,
74
81
// u8 → bool
82
+ // also want to fix parentheses, maybe
75
83
( Uint ( _) , Bool ) => err ( format ! ( "({arg} == 1)" ) ) ,
76
84
_ => return None ,
77
85
} )
@@ -88,7 +96,18 @@ impl<'tcx> Visitor<'tcx> for UnnecessaryTransmuteChecker<'_, 'tcx> {
88
96
&& self . tcx . is_intrinsic ( func_def_id, sym:: transmute)
89
97
&& let span = self . body . source_info ( location) . span
90
98
&& let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( arg)
91
- && let Some ( lint) = self . is_unnecessary_transmute ( func, snippet, span)
99
+ && let def_id = self . body . source . def_id ( )
100
+ && let Some ( lint) = self . is_unnecessary_transmute (
101
+ func,
102
+ snippet,
103
+ span,
104
+ self . tcx . is_const_fn ( def_id)
105
+ || self . tcx . is_conditionally_const ( def_id)
106
+ || matches ! (
107
+ self . tcx. def_kind( def_id) ,
108
+ AnonConst | Const | Static { .. } | AssocConst | InlineConst
109
+ ) ,
110
+ )
92
111
&& let Some ( hir_id) = terminator. source_info . scope . lint_root ( & self . body . source_scopes )
93
112
{
94
113
self . tcx . emit_node_span_lint ( UNNECESSARY_TRANSMUTES , hir_id, span, lint) ;
0 commit comments