diff --git a/tests/fail/dyn-call-trait-mismatch.rs b/tests/fail/dyn-call-trait-mismatch.rs index f71df9a1c9..982d57b737 100644 --- a/tests/fail/dyn-call-trait-mismatch.rs +++ b/tests/fail/dyn-call-trait-mismatch.rs @@ -1,5 +1,5 @@ -// Validation stops this too early. -//@compile-flags: -Zmiri-disable-validation +// Validation and SB stop this too early. +//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows trait T1 { #[allow(dead_code)] diff --git a/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs b/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs new file mode 100644 index 0000000000..c46031de2d --- /dev/null +++ b/tests/pass/issues/issue-miri-3541-dyn-vtable-trait-normalization.rs @@ -0,0 +1,40 @@ +#![feature(ptr_metadata)] +// This test is the result of minimizing the `emplacable` crate to reproduce +// . + +use std::{ops::FnMut, ptr::Pointee}; + +pub type EmplacerFn<'a, T> = dyn for<'b> FnMut(::Metadata) + 'a; + +#[repr(transparent)] +pub struct Emplacer<'a, T>(EmplacerFn<'a, T>) +where + T: ?Sized; + +impl<'a, T> Emplacer<'a, T> +where + T: ?Sized, +{ + pub unsafe fn from_fn<'b>(emplacer_fn: &'b mut EmplacerFn<'a, T>) -> &'b mut Self { + // This used to trigger: + // constructing invalid value: wrong trait in wide pointer vtable: expected + // `std::ops::FnMut(<[std::boxed::Box] as std::ptr::Pointee>::Metadata)`, but encountered + // `std::ops::FnMut<(usize,)>`. + unsafe { &mut *((emplacer_fn as *mut EmplacerFn<'a, T>) as *mut Self) } + } +} + +pub fn box_new_with() +where + T: ?Sized, +{ + let emplacer_closure = &mut |_meta| { + unreachable!(); + }; + + unsafe { Emplacer::::from_fn(emplacer_closure) }; +} + +fn main() { + box_new_with::<[Box]>(); +}