@@ -61,33 +61,73 @@ units](../appendix/glossary.md#codegen-unit).
6161## Polymorphization
6262
6363As mentioned above, monomorphization produces fast code, but it comes at the
64- cost of compile time and binary size. [ MIR
65- optimizations] ( ../mir/optimizations.md ) can help a bit with this. Another
66- optimization currently under development is called _ polymorphization_ .
67-
68- The general idea is that often we can share some code between monomorphized
69- copies of code. More precisely, if a MIR block is not dependent on a type
70- parameter, it may not need to be monomorphized into many copies. Consider the
71- following example:
64+ cost of compile time and binary size. [ MIR optimizations] [ miropt ] can help a
65+ bit with this.
66+
67+ In addition to MIR optimizations, rustc attempts to determine when fewer
68+ copies of functions are necessary and avoid making those copies - known
69+ as "polymorphization". When a function-like item is found during
70+ monomorphization collection, the
71+ [ ` rustc_mir::monomorphize::polymorphize::unused_generic_params ` ] [ polymorph ]
72+ query is invoked, which traverses the MIR of the item to determine on which
73+ generic parameters the item might not need duplicated.
74+
75+ Currently, polymorphization only looks for unused generic parameters. These
76+ are relatively rare in functions, but closures inherit the generic
77+ parameters of their parent function and it is common for closures to not
78+ use those inherited parameters. Without polymorphization, a copy of these
79+ closures would be created for each copy of the parent function. By
80+ creating fewer copies, less LLVM IR is generated and needs processed.
81+
82+ ` unused_generic_params ` returns a ` FiniteBitSet<u64> ` where a bit is set if
83+ the generic parameter of the corresponding index is unused. Any parameters
84+ after the first sixty-four are considered used.
85+
86+ The results of polymorphization analysis are used in the
87+ [ ` Instance::polymorphize ` ] [ inst_polymorph ] function to replace the
88+ [ ` Instance ` ] [ inst ] 's substitutions for the unused generic parameters with their
89+ identity substitutions.
90+
91+ Consider the example below:
7292
7393``` rust
74- pub fn f () {
75- g :: <bool >();
76- g :: <usize >();
94+ fn foo <A , B >() {
95+ let x : Option <B > = None ;
7796}
7897
79- fn g <T >() -> usize {
80- let n = 1 ;
81- let closure = || n ;
82- closure ()
98+ fn main () {
99+ foo :: <u16 , u32 >();
100+ foo :: <u64 , u32 >();
83101}
84102```
85103
86- In this case, we would currently collect `[ f, g::<bool >, g::<usize >,
87- g::<bool >::{{closure}}, g::<usize >::{{closure}}] `, but notice that the two
88- closures would be identical -- they don't depend on the type parameter ` T ` of
89- function ` g ` . So we only need to emit one copy of the closure.
104+ During monomorphization collection, ` foo ` will be collected with the
105+ substitutions ` [u16, u32] ` and ` [u64, u32] ` (from its invocations in ` main ` ).
106+ ` foo ` has the identity substitutions ` [A, B] ` (or
107+ ` [ty::Param(0), ty::Param(1)] ` ).
108+
109+ Polymorphization will identify ` A ` as being unused and it will be replaced in
110+ the substitutions with the identity parameter before being added to the set
111+ of collected items - thereby reducing the copies from two (` [u16, u32] ` and
112+ ` [u64, u32] ` ) to one (` [A, u32] ` ).
113+
114+ ` unused_generic_params ` will also invoked during code generation when the
115+ symbol name for ` foo ` is being computed for use in the callsites of ` foo `
116+ (which have the regular substitutions present, otherwise there would be a
117+ symbol mismatch between the caller and the function).
118+
119+ As a result of polymorphization, items collected during monomorphization
120+ cannot be assumed to be monomorphic.
121+
122+ It is intended that polymorphization be extended to more advanced cases,
123+ such as where only the size/alignment of a generic parameter are required.
90124
91- For more information, see [ this thread on github] [ polymorph ] .
125+ More details on polymorphization are available in the
126+ [ master's thesis] [ thesis ] associated with polymorphization's initial
127+ implementation.
92128
93- [ polymorph ] : https://github.com/rust-lang/rust/issues/46477
129+ [ miropt ] : ../mir/optimizations.md
130+ [ polymorph ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_mir/monomorphize/polymorphize/fn.unused_generic_params.html
131+ [ inst ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/instance/struct.Instance.html
132+ [ inst_polymorph ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/instance/struct.Instance.html#method.polymorphize
133+ [ thesis ] : https://davidtw.co/media/masters_dissertation.pdf
0 commit comments