@@ -1876,7 +1876,7 @@ declare_lint_pass!(InvalidValue => [INVALID_VALUE]);
1876
1876
impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for InvalidValue {
1877
1877
fn check_expr ( & mut self , cx : & LateContext < ' a , ' tcx > , expr : & hir:: Expr ) {
1878
1878
1879
- #[ derive( Debug ) ]
1879
+ #[ derive( Debug , Copy , Clone , PartialEq ) ]
1880
1880
enum InitKind { Zeroed , Uninit } ;
1881
1881
1882
1882
/// Determine if this expression is a "dangerous initialization".
@@ -1911,14 +1911,23 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
1911
1911
1912
1912
/// Return `Some` only if we are sure this type does *not*
1913
1913
/// allow zero initialization.
1914
- fn ty_find_init_error < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> Option < InitError > {
1914
+ fn ty_find_init_error < ' tcx > (
1915
+ tcx : TyCtxt < ' tcx > ,
1916
+ ty : Ty < ' tcx > ,
1917
+ init : InitKind ,
1918
+ ) -> Option < InitError > {
1915
1919
use rustc:: ty:: TyKind :: * ;
1916
1920
match ty. sty {
1917
1921
// Primitive types that don't like 0 as a value.
1918
1922
Ref ( ..) => Some ( ( format ! ( "References must be non-null" ) , None ) ) ,
1919
1923
Adt ( ..) if ty. is_box ( ) => Some ( ( format ! ( "`Box` must be non-null" ) , None ) ) ,
1920
1924
FnPtr ( ..) => Some ( ( format ! ( "Function pointers must be non-null" ) , None ) ) ,
1921
1925
Never => Some ( ( format ! ( "The never type (`!`) has no valid value" ) , None ) ) ,
1926
+ // Primitive types with other constraints
1927
+ Bool if init == InitKind :: Uninit =>
1928
+ Some ( ( format ! ( "Booleans must be `true` or `false`" ) , None ) ) ,
1929
+ Char if init == InitKind :: Uninit =>
1930
+ Some ( ( format ! ( "Characters must be a valid unicode codepoint" ) , None ) ) ,
1922
1931
// Recurse for some compound types.
1923
1932
Adt ( adt_def, substs) if !adt_def. is_union ( ) => {
1924
1933
match adt_def. variants . len ( ) {
@@ -1931,6 +1940,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
1931
1940
ty_find_init_error (
1932
1941
tcx,
1933
1942
field. ty ( tcx, substs) ,
1943
+ init,
1934
1944
) . map ( |( mut msg, span) | if span. is_none ( ) {
1935
1945
// Point to this field, should be helpful for figuring
1936
1946
// out where the source of the error is.
@@ -1949,11 +1959,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
1949
1959
}
1950
1960
Tuple ( ..) => {
1951
1961
// Proceed recursively, check all fields.
1952
- ty. tuple_fields ( ) . find_map ( |field| ty_find_init_error ( tcx, field) )
1962
+ ty. tuple_fields ( ) . find_map ( |field| ty_find_init_error ( tcx, field, init ) )
1953
1963
}
1954
1964
// FIXME: Would be nice to also warn for `NonNull`/`NonZero*`.
1955
- // FIXME: *Only for `mem::uninitialized`*, we could also warn for `bool`,
1956
- // `char`, and any multivariant enum.
1965
+ // FIXME: *Only for `mem::uninitialized`*, we could also warn for multivariant enum.
1957
1966
// Conservative fallback.
1958
1967
_ => None ,
1959
1968
}
@@ -1964,7 +1973,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue {
1964
1973
// using zeroed or uninitialized memory.
1965
1974
// We are extremely conservative with what we warn about.
1966
1975
let conjured_ty = cx. tables . expr_ty ( expr) ;
1967
- if let Some ( ( msg, span) ) = ty_find_init_error ( cx. tcx , conjured_ty) {
1976
+ if let Some ( ( msg, span) ) = ty_find_init_error ( cx. tcx , conjured_ty, init ) {
1968
1977
let mut err = cx. struct_span_lint (
1969
1978
INVALID_VALUE ,
1970
1979
expr. span ,
0 commit comments