Skip to content

Commit 7010d8c

Browse files
committed
add Yield and Return type into generator
1 parent 7c609eb commit 7010d8c

File tree

3 files changed

+56
-9
lines changed

3 files changed

+56
-9
lines changed

src/librustc/ty/sty.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,17 @@ pub enum TypeVariants<'tcx> {
256256
/// closure C wind up influencing the decisions we ought to make for
257257
/// closure C (which would then require fixed point iteration to
258258
/// handle). Plus it fixes an ICE. :P
259+
///
260+
/// ## Generators
261+
///
262+
/// Perhaps surprisingly, `ClosureSubsts` are also used for
263+
/// generators. In that case, what is written above is only half-true
264+
/// -- the set of type parameters is similar, but the role of CK and
265+
/// CS are different. CK represents the "yield type" and CS
266+
/// represents the "return type" of the generator.
267+
///
268+
/// It'd be nice to split this struct into ClosureSubsts and
269+
/// GeneratorSubsts, I believe. -nmatsakis
259270
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
260271
pub struct ClosureSubsts<'tcx> {
261272
/// Lifetime and type parameters from the enclosing function,
@@ -310,6 +321,31 @@ impl<'tcx> ClosureSubsts<'tcx> {
310321
pub fn closure_sig_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
311322
self.split(def_id, tcx).closure_sig_ty
312323
}
324+
325+
/// Returns the type representing the yield type of the generator.
326+
pub fn generator_yield_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
327+
self.closure_kind_ty(def_id, tcx)
328+
}
329+
330+
/// Returns the type representing the return type of the generator.
331+
pub fn generator_return_ty(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> Ty<'tcx> {
332+
self.closure_sig_ty(def_id, tcx)
333+
}
334+
335+
/// Return the "generator signature", which consists of its yield
336+
/// and return types.
337+
///
338+
/// NB. We treat this as a `PolyGenSig`, but since it only
339+
/// contains associated types of the generator, at present it
340+
/// never binds any regions.
341+
pub fn generator_poly_sig(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> PolyGenSig<'tcx> {
342+
ty::Binder(
343+
ty::GenSig {
344+
yield_ty: self.generator_yield_ty(def_id, tcx),
345+
return_ty: self.generator_return_ty(def_id, tcx),
346+
}
347+
)
348+
}
313349
}
314350

315351
impl<'tcx> ClosureSubsts<'tcx> {

src/librustc_typeck/check/closure.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
//! Code for type-checking closure expressions.
1212
13-
use super::{check_fn, Expectation, FnCtxt};
13+
use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
1414

1515
use astconv::AstConv;
1616
use rustc::hir::def_id::DefId;
@@ -79,7 +79,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
7979

8080
debug!("check_closure: ty_of_closure returns {:?}", liberated_sig);
8181

82-
let interior = check_fn(
82+
let generator_types = check_fn(
8383
self,
8484
self.param_env,
8585
liberated_sig,
@@ -106,13 +106,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
106106
let substs = ty::ClosureSubsts { substs };
107107
let closure_type = self.tcx.mk_closure(expr_def_id, substs);
108108

109-
if let Some(interior) = interior {
109+
if let Some(GeneratorTypes { yield_ty, interior }) = generator_types {
110110
self.demand_eqtype(expr.span,
111-
ty::ClosureKind::FnOnce.to_ty(self.tcx),
112-
substs.closure_kind_ty(expr_def_id, self.tcx));
111+
yield_ty,
112+
substs.generator_yield_ty(expr_def_id, self.tcx));
113113
self.demand_eqtype(expr.span,
114-
self.tcx.types.char, // for generator, use some bogus type
115-
substs.closure_sig_ty(expr_def_id, self.tcx));
114+
liberated_sig.output(),
115+
substs.generator_return_ty(expr_def_id, self.tcx));
116116
return self.tcx.mk_generator(expr_def_id, substs, interior);
117117
}
118118

src/librustc_typeck/check/mod.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,17 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
972972
_: hir::BodyId, _: Span, _: ast::NodeId) { }
973973
}
974974

975+
/// When `check_fn` is invoked on a generator (i.e., a body that
976+
/// includes yield), it returns back some information about the yield
977+
/// points.
978+
struct GeneratorTypes<'tcx> {
979+
/// Type of value that is yielded.
980+
yield_ty: ty::Ty<'tcx>,
981+
982+
/// Types that are captured (see `GeneratorInterior` for more).
983+
interior: ty::GeneratorInterior<'tcx>
984+
}
985+
975986
/// Helper used for fns and closures. Does the grungy work of checking a function
976987
/// body and returns the function context used for that purpose, since in the case of a fn item
977988
/// there is still a bit more to do.
@@ -985,7 +996,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
985996
fn_id: ast::NodeId,
986997
body: &'gcx hir::Body,
987998
can_be_generator: bool)
988-
-> (FnCtxt<'a, 'gcx, 'tcx>, Option<ty::GeneratorInterior<'tcx>>)
999+
-> (FnCtxt<'a, 'gcx, 'tcx>, Option<GeneratorTypes<'tcx>>)
9891000
{
9901001
let mut fn_sig = fn_sig.clone();
9911002

@@ -1047,7 +1058,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
10471058

10481059
inherited.tables.borrow_mut().generator_interiors_mut().insert(fn_hir_id, interior);
10491060

1050-
Some(interior)
1061+
Some(GeneratorTypes { yield_ty: gen_sig.yield_ty, interior: interior })
10511062
} else {
10521063
inherited.tables.borrow_mut().generator_sigs_mut().insert(fn_hir_id, None);
10531064
None

0 commit comments

Comments
 (0)