@@ -1879,12 +1879,38 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
18791879 #[ derive( Debug , Copy , Clone , PartialEq ) ]
18801880 enum InitKind { Zeroed , Uninit } ;
18811881
1882+ /// Information about why a type cannot be initialized this way.
1883+ /// Contains an error message and optionally a span to point at.
1884+ type InitError = ( String , Option < Span > ) ;
1885+
1886+ /// Test if this constant is all-0.
1887+ fn is_zero ( expr : & hir:: Expr ) -> bool {
1888+ use hir:: ExprKind :: * ;
1889+ use syntax:: ast:: LitKind :: * ;
1890+ match & expr. node {
1891+ Lit ( lit) =>
1892+ if let Int ( i, _) = lit. node {
1893+ i == 0
1894+ } else {
1895+ false
1896+ } ,
1897+ Tup ( tup) =>
1898+ tup. iter ( ) . all ( is_zero) ,
1899+ _ =>
1900+ false
1901+ }
1902+ }
1903+
18821904 /// Determine if this expression is a "dangerous initialization".
18831905 fn is_dangerous_init ( cx : & LateContext < ' _ , ' _ > , expr : & hir:: Expr ) -> Option < InitKind > {
18841906 const ZEROED_PATH : & [ Symbol ] = & [ sym:: core, sym:: mem, sym:: zeroed] ;
18851907 const UININIT_PATH : & [ Symbol ] = & [ sym:: core, sym:: mem, sym:: uninitialized] ;
1908+ // `transmute` is inside an anonymous module (the `extern` block?);
1909+ // `Invalid` represents the empty string and matches that.
1910+ const TRANSMUTE_PATH : & [ Symbol ] =
1911+ & [ sym:: core, sym:: intrinsics, kw:: Invalid , sym:: transmute] ;
18861912
1887- if let hir:: ExprKind :: Call ( ref path_expr, ref _args ) = expr. node {
1913+ if let hir:: ExprKind :: Call ( ref path_expr, ref args ) = expr. node {
18881914 if let hir:: ExprKind :: Path ( ref qpath) = path_expr. node {
18891915 if let Some ( def_id) = cx. tables . qpath_res ( qpath, path_expr. hir_id )
18901916 . opt_def_id ( )
@@ -1895,20 +1921,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
18951921 if cx. match_def_path ( def_id, & UININIT_PATH ) {
18961922 return Some ( InitKind :: Uninit ) ;
18971923 }
1924+ if cx. match_def_path ( def_id, & TRANSMUTE_PATH ) {
1925+ if is_zero ( & args[ 0 ] ) {
1926+ return Some ( InitKind :: Zeroed ) ;
1927+ }
1928+ }
18981929 // FIXME: Also detect `MaybeUninit::zeroed().assume_init()` and
18991930 // `MaybeUninit::uninit().assume_init()`.
1900- // FIXME: Also detect `transmute` from 0.
19011931 }
19021932 }
19031933 }
19041934
19051935 None
19061936 }
19071937
1908- /// Information about why a type cannot be initialized this way.
1909- /// Contains an error message and optionally a span to point at.
1910- type InitError = ( String , Option < Span > ) ;
1911-
19121938 /// Return `Some` only if we are sure this type does *not*
19131939 /// allow zero initialization.
19141940 fn ty_find_init_error < ' tcx > (
0 commit comments