diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index bb461ccb6f370..12c2f365a2ae7 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -991,7 +991,13 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { // Nothing to check. interp_ok(true) } - ty::UnsafeBinder(_) => todo!("FIXME(unsafe_binder)"), + ty::UnsafeBinder(unsafe_binder_ty) => { + let inner_ty = + self.ecx.tcx.instantiate_bound_regions_with_erased((*unsafe_binder_ty).into()); + let inner = value.transmute(self.ecx.layout_of(inner_ty)?, self.ecx)?; + self.visit_value(&inner)?; + interp_ok(true) + } // The above should be all the primitive types. The rest is compound, we // check them by visiting their fields/variants. ty::Adt(..) diff --git a/tests/ui/unsafe-binders/const-eval-validity-ref.rs b/tests/ui/unsafe-binders/const-eval-validity-ref.rs new file mode 100644 index 0000000000000..5ebe2d2d800a9 --- /dev/null +++ b/tests/ui/unsafe-binders/const-eval-validity-ref.rs @@ -0,0 +1,15 @@ +//@ normalize-stderr: "(the raw bytes of the constant) \(size: [0-9]*, align: [0-9]*\)" -> "$1 (size: $$SIZE, align: $$ALIGN)" +//@ normalize-stderr: "([0-9a-f][0-9a-f] |╾─*A(LLOC)?[0-9]+(\+[a-z0-9]+)?()?─*╼ )+ *│.*" -> "HEX_DUMP" +//@ normalize-stderr: "HEX_DUMP\s*\n\s*HEX_DUMP" -> "HEX_DUMP" + +#![feature(unsafe_binders)] +#![allow(incomplete_features)] + +struct RefDst { + b: unsafe<'a> &'a u32, +} + +const C1: &RefDst = unsafe { std::mem::transmute(&1usize) }; +//~^ ERROR: encountered a dangling reference + +fn main() {} diff --git a/tests/ui/unsafe-binders/const-eval-validity-ref.stderr b/tests/ui/unsafe-binders/const-eval-validity-ref.stderr new file mode 100644 index 0000000000000..790a77b5d19a7 --- /dev/null +++ b/tests/ui/unsafe-binders/const-eval-validity-ref.stderr @@ -0,0 +1,14 @@ +error[E0080]: constructing invalid value of type &RefDst: at ..b, encountered a dangling reference (0x1[noalloc] has no provenance) + --> $DIR/const-eval-validity-ref.rs:12:1 + | +LL | const C1: &RefDst = unsafe { std::mem::transmute(&1usize) }; + | ^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value + | + = note: the rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) { + HEX_DUMP + } + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/unsafe-binders/const-eval-validity.rs b/tests/ui/unsafe-binders/const-eval-validity.rs new file mode 100644 index 0000000000000..8bf29edbf72e1 --- /dev/null +++ b/tests/ui/unsafe-binders/const-eval-validity.rs @@ -0,0 +1,17 @@ +// regression test for . +//@ check-pass + +#![feature(unsafe_binders)] +#![allow(incomplete_features)] + +struct ThinDst { + b: unsafe<> (), +} + +const fn t(x: &[u8; N]) -> &ThinDst { + unsafe { std::mem::transmute(x.as_ptr()) } +} + +const C1: &ThinDst = t(b"d"); + +fn main() {}