block = unpack!(this.stmt_expr(block, expr, None));
block.and(this.unit_rvalue())
}
- ExprKind::Yield { value } => {
- let value = unpack!(block = this.as_operand(block, scope, value));
- let resume = this.cfg.start_new_block();
- let cleanup = this.generator_drop_cleanup();
- this.cfg.terminate(
- block,
- source_info,
- TerminatorKind::Yield { value: value, resume: resume, drop: cleanup },
- );
- resume.and(this.unit_rvalue())
- }
- ExprKind::Literal { .. }
+ ExprKind::Yield { .. }
+ | ExprKind::Literal { .. }
| ExprKind::StaticRef { .. }
| ExprKind::Block { .. }
| ExprKind::Match { .. }
| ExprKind::Adt { .. }
| ExprKind::Borrow { .. }
| ExprKind::AddressOf { .. }
+ | ExprKind::Yield { .. }
| ExprKind::Call { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
ExprKind::Array { .. }
| ExprKind::Repeat { .. }
| ExprKind::Assign { .. }
| ExprKind::AssignOp { .. }
- | ExprKind::Yield { .. }
| ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
ExprKind::Literal { .. } | ExprKind::StaticRef { .. } => Some(Category::Constant),
block.unit()
}
+ ExprKind::Yield { value } => {
+ let scope = this.local_scope();
+ let value = unpack!(block = this.as_operand(block, scope, value));
+ let resume = this.cfg.start_new_block();
+ let cleanup = this.generator_drop_cleanup();
+ this.cfg.terminate(
+ block,
+ source_info,
+ TerminatorKind::Yield {
+ value,
+ resume,
+ resume_arg: destination.clone(),
+ drop: cleanup,
+ },
+ );
+ resume.unit()
+ }
+
// these are the cases that are more naturally handled by some other mode
ExprKind::Unary { .. }
| ExprKind::Binary { .. }
| ExprKind::Tuple { .. }
| ExprKind::Closure { .. }
| ExprKind::Literal { .. }
- | ExprKind::StaticRef { .. }
- | ExprKind::Yield { .. } => {
+ | ExprKind::StaticRef { .. } => {
debug_assert!(match Category::of(&expr.kind).unwrap() {
// should be handled above
Category::Rvalue(RvalueFunc::Into) => false,
let fn_sig = cx.tables().liberated_fn_sigs()[id];
let fn_def_id = tcx.hir().local_def_id(id);
+ let safety = match fn_sig.unsafety {
+ hir::Unsafety::Normal => Safety::Safe,
+ hir::Unsafety::Unsafe => Safety::FnUnsafe,
+ };
+
+ let body = tcx.hir().body(body_id);
let ty = tcx.type_of(fn_def_id);
let mut abi = fn_sig.abi;
let implicit_argument = match ty.kind {
abi = Abi::Rust;
vec![ArgInfo(liberated_closure_env_ty(tcx, id, body_id), None, None, None)]
}
- ty::Generator(..) => {
+ ty::Generator(def_id, substs, _) => {
let gen_ty = tcx.body_tables(body_id).node_type(id);
- vec![
- ArgInfo(gen_ty, None, None, None),
- ArgInfo(tcx.mk_unit(), None, None, None),
- ]
+ let resume_ty = substs.as_generator().resume_ty(def_id, tcx);
+
+ // The resume argument may be missing, in that case we need to provide it here.
+ if body.params.is_empty() {
+ vec![
+ ArgInfo(gen_ty, None, None, None),
+ ArgInfo(resume_ty, None, None, None),
+ ]
+ } else {
+ vec![ArgInfo(gen_ty, None, None, None)]
+ }
}
_ => vec![],
};
- let safety = match fn_sig.unsafety {
- hir::Unsafety::Normal => Safety::Safe,
- hir::Unsafety::Unsafe => Safety::FnUnsafe,
- };
-
- let body = tcx.hir().body(body_id);
let explicit_arguments = body.params.iter().enumerate().map(|(index, arg)| {
let owner_id = tcx.hir().body_owner(body_id);
let opt_ty_info;