diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index fdd47e6f79bd8..8c5c3830ccfd7 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -22,6 +22,8 @@ monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}` +monomorphize_unexpected_polymorphic_constant = unexpected polymorphic constant + monomorphize_unknown_cgu_collection_mode = unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 55b14ce1c3ee0..d28f380c45671 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -193,6 +193,7 @@ use std::path::PathBuf; use crate::errors::{ EncounteredErrorWhileInstantiating, LargeAssignmentsLint, RecursionLimit, TypeLengthLimit, + UnexpectedPolymorphicConst, }; #[derive(PartialEq)] @@ -705,11 +706,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { // The `monomorphize` call should have evaluated that constant already. Ok(val) => val, Err(ErrorHandled::Reported(_)) => return, - Err(ErrorHandled::TooGeneric) => span_bug!( - self.body.source_info(location).span, - "collection encountered polymorphic constant: {:?}", - literal - ), + Err(ErrorHandled::TooGeneric) => { + self.tcx.sess.emit_fatal(UnexpectedPolymorphicConst { + span: self.body.source_info(location).span, + }) + } } } _ => return, @@ -720,11 +721,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { // The `monomorphize` call should have evaluated that constant already. Ok(val) => val, Err(ErrorHandled::Reported(_)) => return, - Err(ErrorHandled::TooGeneric) => span_bug!( - self.body.source_info(location).span, - "collection encountered polymorphic constant: {:?}", - literal - ), + Err(ErrorHandled::TooGeneric) => { + self.tcx.sess.emit_fatal(UnexpectedPolymorphicConst { + span: self.body.source_info(location).span, + }) + } } } }; diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 495a73490a217..6839366a971f7 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -98,3 +98,10 @@ pub struct EncounteredErrorWhileInstantiating { pub struct UnknownCguCollectionMode<'a> { pub mode: &'a str, } + +#[derive(Diagnostic)] +#[diag(monomorphize_unexpected_polymorphic_constant)] +pub struct UnexpectedPolymorphicConst { + #[primary_span] + pub span: Span, +} diff --git a/tests/ui/invalid/issue-114484-unexpected-polymorphic-const.rs b/tests/ui/invalid/issue-114484-unexpected-polymorphic-const.rs new file mode 100644 index 0000000000000..e3e0ff931aa16 --- /dev/null +++ b/tests/ui/invalid/issue-114484-unexpected-polymorphic-const.rs @@ -0,0 +1,67 @@ +// build-fail +use std::marker::PhantomData; + +trait MyTrait { + fn virtualize(&self) -> &dyn MyTrait; +} + +struct VirtualWrapper(T); + +impl VirtualWrapper { + pub fn wrap(value: &T) -> &Self { + unsafe { &*(value as *const T as *const Self) } + } +} + +impl MyTrait for VirtualWrapper { + fn virtualize(&self) -> &dyn MyTrait { + unsafe { virtualize_my_trait(L, self) } + // unsafe { virtualize_my_trait(L, &self.0) } // <-- this code fixes the problem + } +} + +const unsafe fn virtualize_my_trait(level: u8, obj: &T) -> &dyn MyTrait +where + T: MyTrait + 'static, +{ + const fn gen_vtable_ptr() -> *const () + where + T: MyTrait + 'static, + { + let [_, vtable] = unsafe { + std::mem::transmute::<*const dyn MyTrait, [*const (); 2]>(std::ptr::null::< + VirtualWrapper, + >()) + }; + vtable + } + + struct Vtable(PhantomData); + + impl Vtable + where + T: MyTrait + 'static, + { + const LEVELS: [*const (); 2] = [gen_vtable_ptr::(), gen_vtable_ptr::()]; + } + + let vtable = Vtable::::LEVELS[(level != 0) as usize]; //~ ERROR unexpected polymorphic constant + + let data = obj as *const T as *const (); + let ptr: *const dyn MyTrait = std::mem::transmute([data, vtable]); + + &*ptr +} + +struct SomeData([u8; N]); + +impl MyTrait for SomeData { + fn virtualize(&self) -> &dyn MyTrait { + VirtualWrapper::::wrap(self) + } +} + +fn main() { + let test = SomeData([0; 256]); + test.virtualize(); +} diff --git a/tests/ui/invalid/issue-114484-unexpected-polymorphic-const.stderr b/tests/ui/invalid/issue-114484-unexpected-polymorphic-const.stderr new file mode 100644 index 0000000000000..e61e6ac26fde4 --- /dev/null +++ b/tests/ui/invalid/issue-114484-unexpected-polymorphic-const.stderr @@ -0,0 +1,16 @@ +error: reached the recursion limit finding the struct tail for `[u8; 256]` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + +error: reached the recursion limit finding the struct tail for `[u8; 256]` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` + +error: unexpected polymorphic constant + --> $DIR/issue-114484-unexpected-polymorphic-const.rs:48:18 + | +LL | let vtable = Vtable::::LEVELS[(level != 0) as usize]; + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors +