Skip to content

Commit 18b75bf

Browse files
committed
Fix ICE monomorphize collection encountered polymorphic constant
1 parent 1b198b3 commit 18b75bf

File tree

5 files changed

+103
-10
lines changed

5 files changed

+103
-10
lines changed

compiler/rustc_monomorphize/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
2222
2323
monomorphize_type_length_limit = reached the type-length limit while instantiating `{$shrunk}`
2424
25+
monomorphize_unexpected_polymorphic_constant = unexpected polymorphic constant
26+
2527
monomorphize_unknown_cgu_collection_mode =
2628
unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
2729

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ use std::path::PathBuf;
193193

194194
use crate::errors::{
195195
EncounteredErrorWhileInstantiating, LargeAssignmentsLint, RecursionLimit, TypeLengthLimit,
196+
UnexpectedPolymorphicConst,
196197
};
197198

198199
#[derive(PartialEq)]
@@ -705,11 +706,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
705706
// The `monomorphize` call should have evaluated that constant already.
706707
Ok(val) => val,
707708
Err(ErrorHandled::Reported(_)) => return,
708-
Err(ErrorHandled::TooGeneric) => span_bug!(
709-
self.body.source_info(location).span,
710-
"collection encountered polymorphic constant: {:?}",
711-
literal
712-
),
709+
Err(ErrorHandled::TooGeneric) => {
710+
self.tcx.sess.emit_fatal(UnexpectedPolymorphicConst {
711+
span: self.body.source_info(location).span,
712+
})
713+
}
713714
}
714715
}
715716
_ => return,
@@ -720,11 +721,11 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
720721
// The `monomorphize` call should have evaluated that constant already.
721722
Ok(val) => val,
722723
Err(ErrorHandled::Reported(_)) => return,
723-
Err(ErrorHandled::TooGeneric) => span_bug!(
724-
self.body.source_info(location).span,
725-
"collection encountered polymorphic constant: {:?}",
726-
literal
727-
),
724+
Err(ErrorHandled::TooGeneric) => {
725+
self.tcx.sess.emit_fatal(UnexpectedPolymorphicConst {
726+
span: self.body.source_info(location).span,
727+
})
728+
}
728729
}
729730
}
730731
};

compiler/rustc_monomorphize/src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,10 @@ pub struct EncounteredErrorWhileInstantiating {
9898
pub struct UnknownCguCollectionMode<'a> {
9999
pub mode: &'a str,
100100
}
101+
102+
#[derive(Diagnostic)]
103+
#[diag(monomorphize_unexpected_polymorphic_constant)]
104+
pub struct UnexpectedPolymorphicConst {
105+
#[primary_span]
106+
pub span: Span,
107+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// build-fail
2+
use std::marker::PhantomData;
3+
4+
trait MyTrait {
5+
fn virtualize(&self) -> &dyn MyTrait;
6+
}
7+
8+
struct VirtualWrapper<T, const L: u8>(T);
9+
10+
impl<T, const L: u8> VirtualWrapper<T, L> {
11+
pub fn wrap(value: &T) -> &Self {
12+
unsafe { &*(value as *const T as *const Self) }
13+
}
14+
}
15+
16+
impl<T: MyTrait + 'static, const L: u8> MyTrait for VirtualWrapper<T, L> {
17+
fn virtualize(&self) -> &dyn MyTrait {
18+
unsafe { virtualize_my_trait(L, self) }
19+
// unsafe { virtualize_my_trait(L, &self.0) } // <-- this code fixes the problem
20+
}
21+
}
22+
23+
const unsafe fn virtualize_my_trait<T>(level: u8, obj: &T) -> &dyn MyTrait
24+
where
25+
T: MyTrait + 'static,
26+
{
27+
const fn gen_vtable_ptr<T, const L: u8>() -> *const ()
28+
where
29+
T: MyTrait + 'static,
30+
{
31+
let [_, vtable] = unsafe {
32+
std::mem::transmute::<*const dyn MyTrait, [*const (); 2]>(std::ptr::null::<
33+
VirtualWrapper<T, L>,
34+
>())
35+
};
36+
vtable
37+
}
38+
39+
struct Vtable<T>(PhantomData<T>);
40+
41+
impl<T> Vtable<T>
42+
where
43+
T: MyTrait + 'static,
44+
{
45+
const LEVELS: [*const (); 2] = [gen_vtable_ptr::<T, 1>(), gen_vtable_ptr::<T, 2>()];
46+
}
47+
48+
let vtable = Vtable::<T>::LEVELS[(level != 0) as usize]; //~ ERROR unexpected polymorphic constant
49+
50+
let data = obj as *const T as *const ();
51+
let ptr: *const dyn MyTrait = std::mem::transmute([data, vtable]);
52+
53+
&*ptr
54+
}
55+
56+
struct SomeData<const N: usize>([u8; N]);
57+
58+
impl<const N: usize> MyTrait for SomeData<N> {
59+
fn virtualize(&self) -> &dyn MyTrait {
60+
VirtualWrapper::<Self, 0>::wrap(self)
61+
}
62+
}
63+
64+
fn main() {
65+
let test = SomeData([0; 256]);
66+
test.virtualize();
67+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: reached the recursion limit finding the struct tail for `[u8; 256]`
2+
|
3+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
4+
5+
error: reached the recursion limit finding the struct tail for `[u8; 256]`
6+
|
7+
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]`
8+
9+
error: unexpected polymorphic constant
10+
--> $DIR/issue-114484-unexpected-polymorphic-const.rs:48:18
11+
|
12+
LL | let vtable = Vtable::<T>::LEVELS[(level != 0) as usize];
13+
| ^^^^^^^^^^^^^^^^^^^
14+
15+
error: aborting due to 3 previous errors
16+

0 commit comments

Comments
 (0)