Skip to content

Commit f7bba79

Browse files
committed
add Yield and Return type into generator
1 parent 221d715 commit f7bba79

File tree

3 files changed

+56
-9
lines changed

3 files changed

+56
-9
lines changed

src/librustc/ty/sty.rs

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

314350
impl<'tcx> ClosureSubsts<'tcx> {

src/librustc_typeck/check/closure.rs

+7-7
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

+13-2
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,17 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
990990
_: hir::BodyId, _: Span, _: ast::NodeId) { }
991991
}
992992

993+
/// When `check_fn` is invoked on a generator (i.e., a body that
994+
/// includes yield), it returns back some information about the yield
995+
/// points.
996+
struct GeneratorTypes<'tcx> {
997+
/// Type of value that is yielded.
998+
yield_ty: ty::Ty<'tcx>,
999+
1000+
/// Types that are captured (see `GeneratorInterior` for more).
1001+
interior: ty::GeneratorInterior<'tcx>
1002+
}
1003+
9931004
/// Helper used for fns and closures. Does the grungy work of checking a function
9941005
/// body and returns the function context used for that purpose, since in the case of a fn item
9951006
/// there is still a bit more to do.
@@ -1003,7 +1014,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
10031014
fn_id: ast::NodeId,
10041015
body: &'gcx hir::Body,
10051016
can_be_generator: bool)
1006-
-> (FnCtxt<'a, 'gcx, 'tcx>, Option<ty::GeneratorInterior<'tcx>>)
1017+
-> (FnCtxt<'a, 'gcx, 'tcx>, Option<GeneratorTypes<'tcx>>)
10071018
{
10081019
let mut fn_sig = fn_sig.clone();
10091020

@@ -1065,7 +1076,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
10651076

10661077
inherited.tables.borrow_mut().generator_interiors_mut().insert(fn_hir_id, interior);
10671078

1068-
Some(interior)
1079+
Some(GeneratorTypes { yield_ty: gen_sig.yield_ty, interior: interior })
10691080
} else {
10701081
inherited.tables.borrow_mut().generator_sigs_mut().insert(fn_hir_id, None);
10711082
None

0 commit comments

Comments
 (0)