Skip to content

Commit e8d970b

Browse files
Rollup merge of #156988 - RalfJung:validate-uninhabited, r=oli-obk
interpret/validity: properly treat zero-variant enums so that we do not have to check layout.is_uninhabited I am very happy to finally remove the last of these somewhat ad-hoc checks. :) r? @oli-obk
2 parents 3a37aa5 + e724fa6 commit e8d970b

10 files changed

Lines changed: 38 additions & 28 deletions

File tree

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,6 +1353,16 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
13531353
interp_ok(())
13541354
}
13551355

1356+
#[inline]
1357+
fn visit_variantless(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
1358+
let ty = val.layout.ty;
1359+
assert!(ty.is_enum(), "encountered non-enum variantless type `{ty}`");
1360+
throw_validation_failure!(
1361+
self.path,
1362+
format!("encountered a value of zero-variant enum `{ty}`")
1363+
);
1364+
}
1365+
13561366
#[inline]
13571367
fn visit_value(&mut self, val: &PlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
13581368
trace!("visit_value: {:?}, {:?}", *val, val.layout);
@@ -1557,23 +1567,14 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
15571567
}
15581568
}
15591569

1560-
// *After* all of this, check further information stored in the layout.
1561-
// On leaf types like `!` or empty enums, this will raise the error.
1562-
// This means that for types wrapping such a type, we won't ever get here, but it's
1563-
// just the simplest way to check for this case.
1564-
//
1565-
// FIXME: We could avoid some redundant checks here. For newtypes wrapping
1566-
// scalars, we do the same check on every "level" (e.g., first we check
1567-
// the fields of MyNewtype, and then we check MyNewType again).
1568-
if val.layout.is_uninhabited() {
1569-
let ty = val.layout.ty;
1570-
throw_validation_failure!(
1571-
self.path,
1572-
format!("encountered a value of uninhabited type `{ty}`")
1573-
);
1574-
}
1570+
// Assert that we checked everything there is to check about this type.
1571+
assert!(
1572+
!val.layout.is_uninhabited(),
1573+
"a value of type `{}` passed validation but that type is uninhabited",
1574+
val.layout.ty
1575+
);
15751576
if cfg!(debug_assertions) {
1576-
// Check that we don't miss any new changes to layout computation in our checks above.
1577+
// Only run expensive checks when debug assertions are enabled.
15771578
match val.layout.backend_repr {
15781579
BackendRepr::Scalar(scalar_layout) => {
15791580
if !scalar_layout.is_uninit_valid() {

compiler/rustc_const_eval/src/interpret/visitor.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
4141
fn visit_box(&mut self, _box_ty: Ty<'tcx>, _v: &Self::V) -> InterpResult<'tcx> {
4242
interp_ok(())
4343
}
44+
/// Visits the given type after it has been found to have no variants.
45+
#[inline(always)]
46+
fn visit_variantless(&mut self, _v: &Self::V) -> InterpResult<'tcx> {
47+
interp_ok(())
48+
}
4449

4550
/// Called each time we recurse down to a field of a "product-like" aggregate
4651
/// (structs, tuples, arrays and the like, but not enums), passing in old (outer)
@@ -193,7 +198,11 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
193198
self.visit_variant(v, idx, &inner)?;
194199
}
195200
// For single-variant layouts, we already did everything there is to do.
196-
Variants::Single { .. } | Variants::Empty => {}
201+
Variants::Single { .. } => {}
202+
// Non-variant layouts need special treatment by the visitor.
203+
Variants::Empty => {
204+
self.visit_variantless(v)?;
205+
}
197206
}
198207

199208
interp_ok(())

src/tools/miri/tests/fail/validity/match_binder_checks_validity1.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: Undefined Behavior: constructing invalid value of type main::Void: encountered a value of uninhabited type `main::Void`
1+
error: Undefined Behavior: constructing invalid value of type main::Void: encountered a value of zero-variant enum `main::Void`
22
--> tests/fail/validity/match_binder_checks_validity1.rs:LL:CC
33
|
44
LL | _x => println!("hi from the void!"),

tests/ui/consts/const-eval/ub-uninhabit.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0080]: constructing invalid value of type Bar: encountered a value of uninhabited type `Bar`
1+
error[E0080]: constructing invalid value of type Bar: encountered a value of zero-variant enum `Bar`
22
--> $DIR/ub-uninhabit.rs:20:35
33
|
44
LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
@@ -15,7 +15,7 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
1515
HEX_DUMP
1616
}
1717

18-
error[E0080]: constructing invalid value of type [Bar; 1]: at [0], encountered a value of uninhabited type `Bar`
18+
error[E0080]: constructing invalid value of type [Bar; 1]: at [0], encountered a value of zero-variant enum `Bar`
1919
--> $DIR/ub-uninhabit.rs:26:42
2020
|
2121
LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };

tests/ui/consts/const-eval/validate_uninhabited_zsts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const FOO: [empty::Empty; 3] = [foo(); 3];
1818
//~^ ERROR value of the never type
1919

2020
const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
21-
//~^ ERROR value of uninhabited type
21+
//~^ ERROR value of zero-variant enum
2222

2323
fn main() {
2424
FOO;

tests/ui/consts/const-eval/validate_uninhabited_zsts.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ note: inside `foo`
1010
LL | unsafe { std::mem::transmute(()) }
1111
| ^^^^^^^^^^^^^^^^^^^^^^^ the failure occurred here
1212

13-
error[E0080]: constructing invalid value of type empty::Empty: at .0, encountered a value of uninhabited type `Void`
13+
error[E0080]: constructing invalid value of type empty::Empty: at .0, encountered a value of zero-variant enum `Void`
1414
--> $DIR/validate_uninhabited_zsts.rs:20:42
1515
|
1616
LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];

tests/ui/consts/issue-64506.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const FOO: () = {
1414
b: (),
1515
}
1616
let x = unsafe { Foo { b: () }.a };
17-
//~^ ERROR: value of uninhabited type
17+
//~^ ERROR: value of zero-variant enum
1818
let x = &x.inner;
1919
};
2020

tests/ui/consts/issue-64506.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0080]: constructing invalid value of type ChildStdin: at .inner, encountered a value of uninhabited type `AnonPipe`
1+
error[E0080]: constructing invalid value of type ChildStdin: at .inner, encountered a value of zero-variant enum `AnonPipe`
22
--> $DIR/issue-64506.rs:16:22
33
|
44
LL | let x = unsafe { Foo { b: () }.a };

tests/ui/statics/uninhabited-static.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ extern "C" {
1010

1111
static VOID2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
1212
//~| WARN: previously accepted
13-
//~| ERROR value of uninhabited type `Void`
13+
//~| ERROR value of zero-variant enum `Void`
1414
static NEVER2: Void = unsafe { std::mem::transmute(()) }; //~ ERROR static of uninhabited type
1515
//~| WARN: previously accepted
16-
//~| ERROR value of uninhabited type `Void`
16+
//~| ERROR value of zero-variant enum `Void`
1717

1818
fn main() {}

tests/ui/statics/uninhabited-static.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ LL | static NEVER: !;
3939
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
4040
= note: for more information, see issue #74840 <https://github.com/rust-lang/rust/issues/74840>
4141

42-
error[E0080]: constructing invalid value of type Void: encountered a value of uninhabited type `Void`
42+
error[E0080]: constructing invalid value of type Void: encountered a value of zero-variant enum `Void`
4343
--> $DIR/uninhabited-static.rs:11:31
4444
|
4545
LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
4646
| ^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `VOID2` failed here
4747

48-
error[E0080]: constructing invalid value of type Void: encountered a value of uninhabited type `Void`
48+
error[E0080]: constructing invalid value of type Void: encountered a value of zero-variant enum `Void`
4949
--> $DIR/uninhabited-static.rs:14:32
5050
|
5151
LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };

0 commit comments

Comments
 (0)