Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Comment on lines -994 to +1000

@oli-obk oli-obk Jun 9, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't come up with an example that is problematic, but I think this should just do what https://github.com/rust-lang/rust/pull/156373/changes did and bail on unsafe binders and handle them in the aggregate logic.

View changes since the review

// The above should be all the primitive types. The rest is compound, we
// check them by visiting their fields/variants.
ty::Adt(..)
Expand Down
15 changes: 15 additions & 0 deletions tests/ui/unsafe-binders/const-eval-validity-ref.rs
Original file line number Diff line number Diff line change
@@ -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]+)?(<imm>)?─*╼ )+ *│.*" -> "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() {}
14 changes: 14 additions & 0 deletions tests/ui/unsafe-binders/const-eval-validity-ref.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error[E0080]: constructing invalid value of type &RefDst: at .<deref>.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`.
17 changes: 17 additions & 0 deletions tests/ui/unsafe-binders/const-eval-validity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// regression test for <https://github.com/rust-lang/rust/issues/153362>.
//@ check-pass

#![feature(unsafe_binders)]
#![allow(incomplete_features)]

struct ThinDst {
b: unsafe<> (),
}

const fn t<const N: usize>(x: &[u8; N]) -> &ThinDst {
unsafe { std::mem::transmute(x.as_ptr()) }
}

const C1: &ThinDst = t(b"d");

fn main() {}
Loading