|
8 | 8 | // option. This file may not be copied, modified, or distributed
|
9 | 9 | // except according to those terms.
|
10 | 10 |
|
11 |
| -//! Transforms generators into state machines |
| 11 | +//! This is the implementation of the pass which transforms generators into state machines. |
| 12 | +//! |
| 13 | +//! MIR generation for generators creates a function which has a self argument which |
| 14 | +//! passes by value. This argument is effectively a generator type which only contains upvars and |
| 15 | +//! is only used for this argument inside the MIR for the generator. |
| 16 | +//! It is passed by value to enable upvars to be moved out of it. Drop elaboration runs on that |
| 17 | +//! MIR before this pass and creates drop flags for MIR locals. |
| 18 | +//! It will also drop the generator argument (which only consists of upvars) if any of the upvars |
| 19 | +//! are moved out of. This pass elaborates the drops of upvars / generator argument in the case |
| 20 | +//! that none of the upvars were moved out of. This is because we cannot have any drops of this |
| 21 | +//! generator in the MIR, since it is used to create the drop glue for the generator. We'd get |
| 22 | +//! infinite recursion otherwise. |
| 23 | +//! |
| 24 | +//! This pass creates the implementation for the Generator::resume function and the drop shim |
| 25 | +//! for the generator based on the MIR input. It converts the generator argument from Self to |
| 26 | +//! &mut Self adding derefs in the MIR as needed. It computes the final layout of the generator |
| 27 | +//! struct which looks like this: |
| 28 | +//! First upvars are stored |
| 29 | +//! It is followed by the generator state field. |
| 30 | +//! Then finally the MIR locals which are live across a suspension point are stored. |
| 31 | +//! |
| 32 | +//! struct Generator { |
| 33 | +//! upvars..., |
| 34 | +//! state: u32, |
| 35 | +//! mir_locals..., |
| 36 | +//! } |
| 37 | +//! |
| 38 | +//! This pass computes the meaning of the state field and the MIR locals which are live |
| 39 | +//! across a suspension point. There are however two hardcoded generator states: |
| 40 | +//! 0 - Generator have not been resumed yet |
| 41 | +//! 1 - Generator has been poisoned |
| 42 | +//! |
| 43 | +//! It also rewrites `return x` and `yield y` as setting a new generator state and returning |
| 44 | +//! GeneratorState::Complete(x) and GeneratorState::Yielded(y) respectively. |
| 45 | +//! MIR locals which are live across a suspension point are moved to the generator struct |
| 46 | +//! with references to them being updated with references to the generator struct. |
| 47 | +//! |
| 48 | +//! The pass creates two functions which have a switch on the generator state giving |
| 49 | +//! the action to take. |
| 50 | +//! |
| 51 | +//! One of them is the implementation of Generator::resume. |
| 52 | +//! For generators which have already returned it panics. |
| 53 | +//! For generators with state 0 (unresumed) it starts the execution of the generator. |
| 54 | +//! For generators with state 1 (poisoned) it panics. |
| 55 | +//! Otherwise it continues the execution from the last suspension point. |
| 56 | +//! |
| 57 | +//! The other function is the drop glue for the generator. |
| 58 | +//! For generators which have already returned it does nothing. |
| 59 | +//! For generators with state 0 (unresumed) it drops the upvars of the generator. |
| 60 | +//! For generators with state 1 (poisoned) it does nothing. |
| 61 | +//! Otherwise it drops all the values in scope at the last suspension point. |
12 | 62 |
|
13 | 63 | use rustc::hir;
|
14 | 64 | use rustc::hir::def_id::DefId;
|
@@ -515,7 +565,7 @@ fn insert_panic_on_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
515 | 565 | });
|
516 | 566 | }
|
517 | 567 |
|
518 |
| -fn creator_generator_resume_function<'a, 'tcx>( |
| 568 | +fn create_generator_resume_function<'a, 'tcx>( |
519 | 569 | tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
520 | 570 | mut transform: TransformVisitor<'a, 'tcx>,
|
521 | 571 | def_id: DefId,
|
@@ -731,6 +781,6 @@ impl MirPass for StateTransform {
|
731 | 781 | mir.generator_drop = Some(box drop_shim);
|
732 | 782 |
|
733 | 783 | // Create the Generator::resume function
|
734 |
| - creator_generator_resume_function(tcx, transform, def_id, source, mir); |
| 784 | + create_generator_resume_function(tcx, transform, def_id, source, mir); |
735 | 785 | }
|
736 | 786 | }
|
0 commit comments