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+ r#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,13 @@ 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 r#const => err ( format ! ( "({arg}) as {}" , fn_sig. output( ) ) ) ,
77+ // " using `x8::from`
78+ ( Bool , Int ( ..) | Uint ( ..) ) => err ( format ! ( "{}::from({arg})" , fn_sig. output( ) ) ) ,
7479 // u8 → bool
80+ // also want to fix parentheses, maybe
7581 ( Uint ( _) , Bool ) => err ( format ! ( "({arg} == 1)" ) ) ,
7682 _ => return None ,
7783 } )
@@ -88,7 +94,17 @@ impl<'tcx> Visitor<'tcx> for UnnecessaryTransmuteChecker<'_, 'tcx> {
8894 && self . tcx . is_intrinsic ( func_def_id, sym:: transmute)
8995 && let span = self . body . source_info ( location) . span
9096 && let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( arg)
91- && let Some ( lint) = self . is_unnecessary_transmute ( func, snippet, span)
97+ && let def_id = self . body . source . def_id ( )
98+ && let Some ( lint) = self . is_unnecessary_transmute (
99+ func,
100+ snippet,
101+ span,
102+ self . tcx . is_conditionally_const ( def_id)
103+ || matches ! (
104+ self . tcx. def_kind( def_id) ,
105+ AnonConst | Const | Static { .. } | AssocConst | InlineConst
106+ ) ,
107+ )
92108 && let Some ( hir_id) = terminator. source_info . scope . lint_root ( & self . body . source_scopes )
93109 {
94110 self . tcx . emit_node_span_lint ( UNNECESSARY_TRANSMUTES , hir_id, span, lint) ;
0 commit comments