@@ -1879,12 +1879,38 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
1879
1879
#[ derive( Debug , Copy , Clone , PartialEq ) ]
1880
1880
enum InitKind { Zeroed , Uninit } ;
1881
1881
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
+
1882
1904
/// Determine if this expression is a "dangerous initialization".
1883
1905
fn is_dangerous_init ( cx : & LateContext < ' _ , ' _ > , expr : & hir:: Expr ) -> Option < InitKind > {
1884
1906
const ZEROED_PATH : & [ Symbol ] = & [ sym:: core, sym:: mem, sym:: zeroed] ;
1885
1907
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] ;
1886
1912
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 {
1888
1914
if let hir:: ExprKind :: Path ( ref qpath) = path_expr. node {
1889
1915
if let Some ( def_id) = cx. tables . qpath_res ( qpath, path_expr. hir_id )
1890
1916
. opt_def_id ( )
@@ -1895,20 +1921,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
1895
1921
if cx. match_def_path ( def_id, & UININIT_PATH ) {
1896
1922
return Some ( InitKind :: Uninit ) ;
1897
1923
}
1924
+ if cx. match_def_path ( def_id, & TRANSMUTE_PATH ) {
1925
+ if is_zero ( & args[ 0 ] ) {
1926
+ return Some ( InitKind :: Zeroed ) ;
1927
+ }
1928
+ }
1898
1929
// FIXME: Also detect `MaybeUninit::zeroed().assume_init()` and
1899
1930
// `MaybeUninit::uninit().assume_init()`.
1900
- // FIXME: Also detect `transmute` from 0.
1901
1931
}
1902
1932
}
1903
1933
}
1904
1934
1905
1935
None
1906
1936
}
1907
1937
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
-
1912
1938
/// Return `Some` only if we are sure this type does *not*
1913
1939
/// allow zero initialization.
1914
1940
fn ty_find_init_error < ' tcx > (
0 commit comments