Skip to content

Commit c711531

Browse files
committed
Add some comments and fix a typo
1 parent b4c5471 commit c711531

File tree

4 files changed

+64
-5
lines changed

4 files changed

+64
-5
lines changed

src/librustc_mir/build/expr/as_rvalue.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
191191
.map(|upvar| unpack!(block = this.as_operand(block, scope, upvar)))
192192
.collect();
193193
let result = if let Some(interior) = interior {
194-
// Add the state operand
194+
// Add the state operand since it follows the upvars in the generator
195+
// struct. See librustc_mir/transform/generator.rs for more details.
195196
operands.push(Operand::Constant(box Constant {
196197
span: expr_span,
197198
ty: this.hir.tcx().types.u32,

src/librustc_mir/transform/generator.rs

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,57 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

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.
1262
1363
use rustc::hir;
1464
use rustc::hir::def_id::DefId;
@@ -515,7 +565,7 @@ fn insert_panic_on_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
515565
});
516566
}
517567

518-
fn creator_generator_resume_function<'a, 'tcx>(
568+
fn create_generator_resume_function<'a, 'tcx>(
519569
tcx: TyCtxt<'a, 'tcx, 'tcx>,
520570
mut transform: TransformVisitor<'a, 'tcx>,
521571
def_id: DefId,
@@ -731,6 +781,6 @@ impl MirPass for StateTransform {
731781
mir.generator_drop = Some(box drop_shim);
732782

733783
// 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);
735785
}
736786
}

src/librustc_mir/util/elaborate_drops.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -752,10 +752,13 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
752752
fn open_drop<'a>(&mut self) -> BasicBlock {
753753
let ty = self.lvalue_ty(self.lvalue);
754754
match ty.sty {
755+
ty::TyClosure(def_id, substs) |
755756
// Note that `elaborate_drops` only drops the upvars of a generator,
756757
// and this is ok because `open_drop` here can only be reached
757758
// within that own generator's resume function.
758-
ty::TyClosure(def_id, substs) |
759+
// This should only happen for the self argument on the resume function.
760+
// It effetively only contains upvars until the generator transformation runs.
761+
// See librustc_mir/transform/generator.rs for more details.
759762
ty::TyGenerator(def_id, substs, _) => {
760763
let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect();
761764
self.open_drop_for_tuple(&tys)

src/librustc_typeck/check/generator_interior.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
//! This calculates the types which has storage which lives across a suspension point in a
12+
//! generator from the perspective of typeck. The actual types used at runtime
13+
//! is calculated in `rustc_mir::transform::generator` and may be a subset of the
14+
//! types computed here.
15+
1116
use log;
1217
use rustc::hir::def_id::DefId;
1318
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};

0 commit comments

Comments
 (0)