Repository navigation
ICE when compiling smallvec::SmallVecData<[f64; 4]>::heap_mut #61
Description
Activity
It seems that some issues can be avoided by patching the code of dependencies. I hope I can get to the bottom of it some time, then I'll share what I changed so you can see what caused the issue
It also seems that later on icu_collator it just freezes
Thank you for trying it out and for the report! I'm taking a look at that crash now, it just looks like a small bug that should be easy to fix. It's happening when compiling
smallvec::SmallVecData<[f64; 4]>::heap_mut. I'll look at the freeze after.- addedA-lower2Involving the 2nd lowering pass (OOMIR -> JVM)Involving the 2nd lowering pass (OOMIR -> JVM)I-ICEIssues causing an ICE in the codegen backendIssues causing an ICE in the codegen backendC-BugFunctionality that is claimed to be supported isn't working correctly in certain circumstances.Functionality that is claimed to be supported isn't working correctly in certain circumstances.S-In DevelopmentIssue with a contributor actively working on the needed development.Issue with a contributor actively working on the needed development.
on Sep 22, 2026 - changed the title
[-]Crash compiling project with parking_lot_core[/-][+]ICE when compiling `smallvec::SmallVecData<[f64; 4]>::heap_mut`[/+]on Sep 22, 2026 MRE (can probably be a bit smaller still, but it's just what I'm working with right now)
use std::mem::{ManuallyDrop, MaybeUninit}; use std::ptr::NonNull; trait Array { type Item; } impl Array for [f64; 4] { type Item = f64; } union Data<A: Array> { inline: ManuallyDrop<MaybeUninit<A>>, heap: (NonNull<A::Item>, usize), } impl<A: Array> Data<A> { unsafe fn heap_mut(&mut self) -> (NonNull<A::Item>, &mut usize) { let heap = unsafe { &mut self.heap }; (heap.0, &mut heap.1) } unsafe fn inline_mut(&mut self) -> NonNull<A::Item> { unsafe { NonNull::new_unchecked(self.inline.as_mut_ptr() as *mut A::Item) } } } pub fn run() { let mut data = Data::<[f64; 4]> { inline: ManuallyDrop::new(MaybeUninit::new([1.0, 2.0, 3.0, 4.0])), }; unsafe { let pointer = data.inline_mut(); assert_eq!(*pointer.as_ptr().add(2), 3.0); } let mut heap = [5.0, 6.0, 7.0, 8.0, 9.0]; data = Data { heap: (NonNull::new(heap.as_mut_ptr()).unwrap(), heap.len()), }; unsafe { let (pointer, len) = data.heap_mut(); assert_eq!(pointer.as_ptr(), heap.as_mut_ptr()); *len -= 1; pointer.as_ptr().add(4).write(99.0); assert_eq!(data.heap.1, 4); assert_eq!(heap[4], 99.0); } }
Thank you for trying it out and for the report! I'm taking a look at that crash now, it just looks like a small bug that should be easy to fix. It's happening when compiling
smallvec::SmallVecData<[f64; 4]>::heap_mut. I'll look at the freeze after.I actually think I found the freeze. It's in
oomir::Function, specifically constant tables, which results in 34GB footprint for icu_* crates before the compiler crashes with OOM on my machineI actually think I found the freeze. It's in oomir::Function, specifically constant tables, which results in 34GB footprint for icu_* crates before the compiler crashes with OOM on my machine
Oh perfect, thank you! Can you try it with the experimental branch? I cleaned up a bunch of memory usage there. It's here: #57
But I will still look into that memory issue and make a fix for mainline, because experimental isn't ready to be released yet.
The crash issue was a tiny fix, I made a very silly mistake sorry! Pushed here, will wait for CI to go green before calling it fixed. Can you also try pulling the change and confirming it fixes it on your end too?
OK CI's passed and I'm going to bed now but I'll look into how to fix the freeze on
maintomorrow.Oh, good night!
I've been fixing some issues with my local rust setup and only now was able to start a new compilation with memory improvements, still waiting. Thanks for your fast responses!
Well, I've encountered several issues after working around this one, not sure if they are all related or different, I'll be testing that later as well. For now not doing anything crazy, just trying to compile xD.Yeah it seems that memory explosion doesn't happen on that experimental branch!
UPD: or not... I don't get how cargo sorts crates for compilation, I think I saw it had compiled once, but now I'm back to that freeze, LLM reports it stuck inrustc_codegen_jvm::java_exports::lower_public_library_exports -> lower_mono_function -> emit -> repeating oomir::constant::Constant::clone(I'm not that cool to analyze running programs myself)
Thank you for trying it! Sorry for the delay, I was working on getting runtime speed in the experimental branch to something acceptable so I could merge it and stop working on 2 different versions. I've done that and merged it now.
I have now also fixed the problem leading to that freeze in the experimental branch, which just got merged in.
Can you please test again with the latest
main? Thanks again for helping make it better! :)Sorry for a delayed response, I've been digging through a bunch of errors related to jvm-unknown-jvm being, well, an unknown target: such crates as
tar,stackeranddirsrely on system libraries and thus refuse to compile for jvm. Luckily, those aren't reaaally required for initial testing, so for now I mostly plugged them with no-ops and called it a day.The build now progressed to another failure, I link the report here. rustc-ice-2026-09-27T13_03_22-86270.txt To be clear, this is also a not-so-required dependency, and I might switch from wasmi to much more jvmish chicory runtime later, but I think you might wanna know about this anyway.
If it's helpful for debugging or something, I've put my current progress into cargo-jvm-experiment branch.
Thank you for your time!
No worries, I spent longer replying to you! :)
Thank you for linking that failure. There's no need to switch dependencies, it was just a silly mistake by me and I fixed that up in b0813e4
Thank you also for linking the branch, I had some free time today so I've just been working the whole day on eliminating all the issues in the compiler that came up one by one (it was so useful for finding edge cases, they were all mostly just little oversights that needed small fixes!).
I'm happy to say now that Typst on JVM is now working (though, for more complex documents, there might still be issues). I got it to generate this "Hello world!" image below, using your branch + latest
mainof this compiler.Can you try it and check it works for you (you may have to bump the JVM stack size)? If you also have any problems that come up with more complex documents that would be really helpful as well. :)
As I think Typst is really useful because it covers so much in getting a document to compile, I also added compiling a hello world Typst document (using Typst compiled to JVM from that branch) to the regression suite on CI: bd1f78f

Thanks, that's really cool!
Compilation for some reason produces two jars, typst-shared.jar and typst_shared.jar, almost the same size, not sure what's that about. Also, while debug version seems to work, release one fails with:
Exception in thread "main" java.lang.NoClassDefFoundError: org/rustlang/alloc/mono/Mono_619 at typst_shared.typst_shared.main(main.rs) Caused by: java.lang.ClassNotFoundException: org.rustlang.alloc.mono.Mono_619 at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:502) ... 1 moreAnyway, debug is enough for me to start adapting libraries and fuzzing, so, Skeletor will probably return later with more news xD
Thanks, more testing would be really helpful, I appreciate it!
The two jars are expected, it's because the project defines both a binary and a library.
typst-shared.jaris the executable fromsrc/main.rsand thentypst_shared.jaris the library fromsrc/lib.rs, acdylib. Though maybe I should make that clearer in documentation somewhere.Thank you also for finding the release bug. I looked into it and it was just that we didn't handle ThinLTO properly and it only needed a small fix. I've fixed it now and added Typst release to CI, see dc27718
I also managed to get some more complex ones working (and integrated into CI in both debug and release). It just needed fixing a couple more tiny bugs in the codegen, I've attached some of them below. I pushed it just before you left your comment!

Also, sorry for how slow the compiled version currently is. I'm playing around with JFR to figure out where the bottlenecks are and how to make faster. I guess that's one of the very useful benefits of targeting JVM that there is such good tooling.
Seems like the error changed, but isn't gone
$ java -jar target/jvm-unknown-jvm/release/typst-shared.jar Exception in thread "main" java.lang.NoSuchMethodError: 'typst_utils$crate154066864e868daa$.version_.TypstVersion typst_utils$crate154066864e868daa$.version_.version()' at typst_library.foundations.sys.module(Unknown Source) at typst_library.foundations.define$relative(Unknown Source) at typst_library.foundations.define(Unknown Source) at typst_library.typst_library.global$relative(Unknown Source) at typst_library.typst_library.global(Unknown Source) at typst_library.typst_library.build$9f914d43e8dc8749(Unknown Source) at typst_shared.world.library.stdlib.stdlib(Unknown Source) at typst_shared.typst_shared.main(main.rs)Also, sorry for how slow the compiled version currently is. I'm playing around with JFR to figure out where the bottlenecks are and how to make faster. I guess that's one of the very useful benefits of targeting JVM that there is such good tooling.
< The first version of my response was irrelevant due to my inability to read lol, so I'm editing it >
Sure, some decline in efficiency is expected. I will profile something as well on my own, perhaps I'll return with suggestions. For now, my concern is that Typst uses a lot of
EcoStrings,SmallVecs and other stuff that's very optimized for native targets, but requires bytewise shenanigans on jvm which probably are less efficient than just using native java stuff like arrays, lists and strings. And I will take a great pleasure in forking them and optimizing for jvm backend :)Exception in thread "main" java.lang.NoSuchMethodError: 'typst_utils$crate154066864e868daa$.version_.TypstVersion typst_utils$crate154066864e868daa$.version_.version()'On second thought, just changing
versionto be:pub fn version() -> TypstVersion { *crate::singleton!(TypstVersion, { return TypstVersion { major: 0, minor: 14, patch: 2, raw: "0.14.2", commit: None, }; }) }seems to have solved the issue, which means the issue is in the fact it asks for env variables to be set during compilation
Regarding speed, I didn't see mentions of this in readme, but from my understanding of the compiler code,
&T, when it's not&dyn Trait, is mapped just as pointer, into thePointerwrapper. But why? From my point of view, the less we use raw Pointers, the better for the efficiency on the jvm.
Hi!
So, as promised, I tried to feed your compiler a big project. And here's a panic:
I couldn't understand what really have happened there, as to my understanding the error message isn't really helpful. Additionally, I found out that parking lot itself compiles cleanly, so it's how it used is the issue.
If you need, I tried compiling https://github.com/LDemetrios/typst-shared-library/tree/shared-lib-v2 . I probably will end up later substituting parking lot dependencies with proper JVM synchronization, but that's gonna be when I understand your compiler better xD