Skip to content

Commit

Permalink
also query type_uninhabited_from
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Sep 27, 2022
1 parent c19daa4 commit 67fd09d
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 40 deletions.
14 changes: 11 additions & 3 deletions compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2425,8 +2425,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
}

/// Determines whether the given type is inhabited. `None` means that we don't know.
fn ty_inhabited(ty: Ty<'_>) -> Option<bool> {
fn ty_inhabited<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option<bool> {
use rustc_type_ir::sty::TyKind::*;
if !cx.tcx.type_uninhabited_from(cx.param_env.and(ty)).is_empty() {
// This is definitely uninhabited from some module.
return Some(false);
}
match ty.kind() {
Never => Some(false),
Int(_) | Uint(_) | Float(_) | Bool | Char | RawPtr(_) => Some(true),
Expand All @@ -2436,10 +2440,13 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
}
}
/// Determines whether a product type formed from a list of types is inhabited.
fn tys_inhabited<'tcx>(tys: impl Iterator<Item = Ty<'tcx>>) -> Option<bool> {
fn tys_inhabited<'tcx>(
cx: &LateContext<'tcx>,
tys: impl Iterator<Item = Ty<'tcx>>,
) -> Option<bool> {
let mut definitely_inhabited = true; // with no fields, we are definitely inhabited.
for ty in tys {
match ty_inhabited(ty) {
match ty_inhabited(cx, ty) {
// If any type is uninhabited, the product is uninhabited.
Some(false) => return Some(false),
// Otherwise go searching for a `None`.
Expand Down Expand Up @@ -2550,6 +2557,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
let span = cx.tcx.def_span(adt_def.did());
let mut potential_variants = adt_def.variants().iter().filter_map(|variant| {
let inhabited = tys_inhabited(
cx,
variant.fields.iter().map(|field| field.ty(cx.tcx, substs)),
);
let definitely_inhabited = match inhabited {
Expand Down
36 changes: 18 additions & 18 deletions src/test/ui/consts/const-eval/ub-enum.32bit.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:23:1
--> $DIR/ub-enum.rs:24:1
|
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000001, but expected a valid enum tag
Expand All @@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:26:1
--> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -22,7 +22,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:30:1
--> $DIR/ub-enum.rs:31:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -33,7 +33,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:43:1
--> $DIR/ub-enum.rs:44:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x00000000, but expected a valid enum tag
Expand All @@ -44,7 +44,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:45:1
--> $DIR/ub-enum.rs:46:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -55,7 +55,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:49:1
--> $DIR/ub-enum.rs:50:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -66,13 +66,13 @@ LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:59:42
--> $DIR/ub-enum.rs:60:42
|
LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:64:1
--> $DIR/ub-enum.rs:65:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -83,7 +83,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:82:1
--> $DIR/ub-enum.rs:83:1
|
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(B)>.0: encountered a value of the never type `!`
Expand All @@ -94,7 +94,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:84:1
--> $DIR/ub-enum.rs:85:1
|
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
Expand All @@ -105,7 +105,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:92:1
--> $DIR/ub-enum.rs:93:1
|
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
Expand All @@ -116,13 +116,13 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
}

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:97:77
--> $DIR/ub-enum.rs:98:77
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:99:77
--> $DIR/ub-enum.rs:100:77
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
Expand All @@ -132,7 +132,7 @@ error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0080`.
Future incompatibility report: Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:26:1
--> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -145,7 +145,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:30:1
--> $DIR/ub-enum.rs:31:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -158,7 +158,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:45:1
--> $DIR/ub-enum.rs:46:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -171,7 +171,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:49:1
--> $DIR/ub-enum.rs:50:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -184,7 +184,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:64:1
--> $DIR/ub-enum.rs:65:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand Down
36 changes: 18 additions & 18 deletions src/test/ui/consts/const-eval/ub-enum.64bit.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:23:1
--> $DIR/ub-enum.rs:24:1
|
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
| ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000001, but expected a valid enum tag
Expand All @@ -10,7 +10,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:26:1
--> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -22,7 +22,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:30:1
--> $DIR/ub-enum.rs:31:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -33,7 +33,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:43:1
--> $DIR/ub-enum.rs:44:1
|
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
| ^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-tag>: encountered 0x0000000000000000, but expected a valid enum tag
Expand All @@ -44,7 +44,7 @@ LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
}

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:45:1
--> $DIR/ub-enum.rs:46:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -55,7 +55,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:49:1
--> $DIR/ub-enum.rs:50:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -66,13 +66,13 @@ LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:59:42
--> $DIR/ub-enum.rs:60:42
|
LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory

error: any use of this value will cause an error
--> $DIR/ub-enum.rs:64:1
--> $DIR/ub-enum.rs:65:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -83,7 +83,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:82:1
--> $DIR/ub-enum.rs:83:1
|
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(B)>.0: encountered a value of the never type `!`
Expand All @@ -94,7 +94,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:84:1
--> $DIR/ub-enum.rs:85:1
|
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
Expand All @@ -105,7 +105,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute
}

error[E0080]: it is undefined behavior to use this value
--> $DIR/ub-enum.rs:92:1
--> $DIR/ub-enum.rs:93:1
|
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
Expand All @@ -116,13 +116,13 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
}

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:97:77
--> $DIR/ub-enum.rs:98:77
|
LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type

error[E0080]: evaluation of constant value failed
--> $DIR/ub-enum.rs:99:77
--> $DIR/ub-enum.rs:100:77
|
LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(0u64) };
| ^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
Expand All @@ -132,7 +132,7 @@ error: aborting due to 13 previous errors
For more information about this error, try `rustc --explain E0080`.
Future incompatibility report: Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:26:1
--> $DIR/ub-enum.rs:27:1
|
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -145,7 +145,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:30:1
--> $DIR/ub-enum.rs:31:1
|
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -158,7 +158,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:45:1
--> $DIR/ub-enum.rs:46:1
|
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -171,7 +171,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:49:1
--> $DIR/ub-enum.rs:50:1
|
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand All @@ -184,7 +184,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };

Future breakage diagnostic:
error: any use of this value will cause an error
--> $DIR/ub-enum.rs:64:1
--> $DIR/ub-enum.rs:65:1
|
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
Expand Down
1 change: 1 addition & 0 deletions src/test/ui/consts/const-eval/ub-enum.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// stderr-per-bitwidth
#![feature(never_type)]
#![allow(invalid_value)]

use std::mem;

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/lint/invalid_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ enum OneFruitNonZero {

enum TwoUninhabited {
A(!),
B(!),
B(Void),
}

#[allow(unused)]
Expand Down

0 comments on commit 67fd09d

Please sign in to comment.