Propose polymorphization project goal - #751
Conversation
|
There is already extensive discussion of this work on Zulip. Also cc my WIP PR containing the proof of concept: rust-lang/rust#160300 |
|
A zulip topic was opened to discuss this issue. |
|
|
||
| ## Motivation | ||
|
|
||
| ### The status quo |
There was a problem hiding this comment.
This is well laid out for the build speed case. No binary size benefits though? Are we not focused on release artifacts yet?
|
|
||
| I plan to implement support for truly polymorphic code generation in Rustc. Unlike the previous polymorphization project, my design works for unused and used generic parameters alike, significantly expanding its potential benefits and sidestepping issues with determining whether parameters are relevant to codegen. The axiom is "monomorphic data, polymorphic code". In other words, unlike languages like Haskell and OCaml that generally rely on uniform representations (boxing) to enable polymorphic code generation, data layouts will stay the same under polymorphization, and only function ABIs will change. Polymorphized instances can coexist with monomorphized instances, enabling incremental improvements to the kinds of functions supported by polymorphization. In fact, polymorphization operates at the (type) parameter level, so some parameters can be polymorphized (becoming "erased types"), while others remain monomorphized, within a single function. | ||
|
|
||
| I estimate that the full version of polymorphization could speed up codegen and linking by between 30% and 2x, by eliminating up to half of generated instances in many cases. Binary sizes should also be reduced as a result, without requiring link-time optimization, helping shrink the size of artifact directories containing debug builds. As mentioned, incremental progress can be made toward this full vision, providing checkpoints with smaller but noticeable speedups and binary size reductions. |
There was a problem hiding this comment.
I see we mention binary sizes here, i think it is worth mentioning size bloat in the status quo as well
|
|
||
| Data layouts are not the only thing generic code needs to know about its type parameters. Trait methods and associated types also come into play, as do drop glue and `TypeId` information. The key is that all of this information already must be known statically at some point in the call graph. Thus, it can be threaded through implicit function arguments inserted during codegen. Essentially, each type parameter will generate a hidden extended-vtable argument containing the type's `TypeId`, its drop glue function pointer, and each of its trait methods' function pointers. Type parameters whose bounded traits have associated types will generate additional vtable arguments, one per associated type. | ||
|
|
||
| #### Prior art |
| ## Funding | ||
|
|
||
|
|
||
| | Purpose | Cost | Funded | Sponsor(s) | |
There was a problem hiding this comment.
Interested in learning more about funding needs, but I'll ask as instructed :)
There was a problem hiding this comment.
It might be worth including a loose timeline (assuming full funding)? Even just a "total X months" granularity helps, though something like "MCP after X, start of impl lands after Y, full experimental MVP Z" is even nicer.
https://rust-lang.github.io/rust-project-goals/2026/incremental-system-rethought.html#target-timeline is a great example though it's ok if that level of detail is not known and step 0 is just discovery.
|
|
||
| I plan to implement support for truly polymorphic code generation in Rustc. Unlike the previous polymorphization project, my design works for unused and used generic parameters alike, significantly expanding its potential benefits and sidestepping issues with determining whether parameters are relevant to codegen. The axiom is "monomorphic data, polymorphic code". In other words, unlike languages like Haskell and OCaml that generally rely on uniform representations (boxing) to enable polymorphic code generation, data layouts will stay the same under polymorphization, and only function ABIs will change. Polymorphized instances can coexist with monomorphized instances, enabling incremental improvements to the kinds of functions supported by polymorphization. In fact, polymorphization operates at the (type) parameter level, so some parameters can be polymorphized (becoming "erased types"), while others remain monomorphized, within a single function. | ||
|
|
||
| I estimate that the full version of polymorphization could speed up codegen and linking by between 30% and 2x, by eliminating up to half of generated instances in many cases. Binary sizes should also be reduced as a result, without requiring link-time optimization, helping shrink the size of artifact directories containing debug builds. As mentioned, incremental progress can be made toward this full vision, providing checkpoints with smaller but noticeable speedups and binary size reductions. |
There was a problem hiding this comment.
I would hoist this into an "expected outcomes" section, right now it is buried in implementation details
| | Support simple dyn-compatible traits | @camelid | | | ||
| | Support some non-dyn-compatible traits | @camelid | | |
There was a problem hiding this comment.
These seem like they would need types review, probably at least small.
Separately, the approach of adding a TyKind::Erased will need a types vibecheck.
Implement experimental support in the Rust compiler for polymorphic code generation. Instead of monomorphizing generic code, the compiler will generate type-agnostic instances and add hidden vtable parameters where needed, which should reduce compile times and generated binary sizes.
Rendered