1+ use rustc_hir:: def:: DefKind :: * ;
12use rustc_middle:: mir:: visit:: Visitor ;
23use rustc_middle:: mir:: { Body , Location , Operand , Terminator , TerminatorKind } ;
34use rustc_middle:: ty:: * ;
@@ -29,6 +30,7 @@ impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> {
2930 function : & Operand < ' tcx > ,
3031 arg : String ,
3132 span : Span ,
33+ is_in_const : bool ,
3234 ) -> Option < Error > {
3335 let fn_sig = function. ty ( self . body , self . tcx ) . fn_sig ( self . tcx ) . skip_binder ( ) ;
3436 let [ input] = fn_sig. inputs ( ) else { return None } ;
@@ -69,9 +71,15 @@ impl<'a, 'tcx> UnnecessaryTransmuteChecker<'a, 'tcx> {
6971 ( Float ( ty) , Uint ( ..) ) => err ( format ! ( "{}::to_bits({arg})" , ty. name_str( ) ) ) ,
7072 // uNN → fNN
7173 ( 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( ) ) ) ,
7481 // u8 → bool
82+ // also want to fix parentheses, maybe
7583 ( Uint ( _) , Bool ) => err ( format ! ( "({arg} == 1)" ) ) ,
7684 _ => return None ,
7785 } )
@@ -88,7 +96,18 @@ impl<'tcx> Visitor<'tcx> for UnnecessaryTransmuteChecker<'_, 'tcx> {
8896 && self . tcx . is_intrinsic ( func_def_id, sym:: transmute)
8997 && let span = self . body . source_info ( location) . span
9098 && 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+ )
92111 && let Some ( hir_id) = terminator. source_info . scope . lint_root ( & self . body . source_scopes )
93112 {
94113 self . tcx . emit_node_span_lint ( UNNECESSARY_TRANSMUTES , hir_id, span, lint) ;
0 commit comments