Skip to content

Fix ICE monomorphize collection encountered polymorphic constant #114985

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
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
2 changes: 2 additions & 0 deletions compiler/rustc_monomorphize/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 11 additions & 10 deletions compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ use std::path::PathBuf;

use crate::errors::{
EncounteredErrorWhileInstantiating, LargeAssignmentsLint, RecursionLimit, TypeLengthLimit,
UnexpectedPolymorphicConst,
};

#[derive(PartialEq)]
Expand Down Expand Up @@ -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,
Expand All @@ -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,
})
}
}
}
};
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_monomorphize/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
67 changes: 67 additions & 0 deletions tests/ui/invalid/issue-114484-unexpected-polymorphic-const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// build-fail
use std::marker::PhantomData;

trait MyTrait {
fn virtualize(&self) -> &dyn MyTrait;
}

struct VirtualWrapper<T, const L: u8>(T);

impl<T, const L: u8> VirtualWrapper<T, L> {
pub fn wrap(value: &T) -> &Self {
unsafe { &*(value as *const T as *const Self) }
}
}

impl<T: MyTrait + 'static, const L: u8> MyTrait for VirtualWrapper<T, L> {
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<T>(level: u8, obj: &T) -> &dyn MyTrait
where
T: MyTrait + 'static,
{
const fn gen_vtable_ptr<T, const L: u8>() -> *const ()
where
T: MyTrait + 'static,
{
let [_, vtable] = unsafe {
std::mem::transmute::<*const dyn MyTrait, [*const (); 2]>(std::ptr::null::<
VirtualWrapper<T, L>,
>())
};
vtable
}

struct Vtable<T>(PhantomData<T>);

impl<T> Vtable<T>
where
T: MyTrait + 'static,
{
const LEVELS: [*const (); 2] = [gen_vtable_ptr::<T, 1>(), gen_vtable_ptr::<T, 2>()];
}

let vtable = Vtable::<T>::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<const N: usize>([u8; N]);

impl<const N: usize> MyTrait for SomeData<N> {
fn virtualize(&self) -> &dyn MyTrait {
VirtualWrapper::<Self, 0>::wrap(self)
}
}

fn main() {
let test = SomeData([0; 256]);
test.virtualize();
}
16 changes: 16 additions & 0 deletions tests/ui/invalid/issue-114484-unexpected-polymorphic-const.stderr
Original file line number Diff line number Diff line change
@@ -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::<T>::LEVELS[(level != 0) as usize];
| ^^^^^^^^^^^^^^^^^^^

error: aborting due to 3 previous errors