Make yield and gen arg outside generator literals an error and update tests

This commit is contained in:
John Kåre Alsaker 2017-07-08 19:30:14 +02:00
parent 5efb0cbe04
commit bc9b4deeb5
7 changed files with 64 additions and 32 deletions

View File

@ -82,7 +82,7 @@ fn check_closure(&self,
self.param_env,
&fn_sig);
let interior = check_fn(self, self.param_env, fn_sig, decl, expr.id, body).1;
let interior = check_fn(self, self.param_env, fn_sig, decl, expr.id, body, true).1;
if let Some(interior) = interior {
let closure_substs = ty::ClosureSubsts {

View File

@ -871,7 +871,7 @@ fn typeck_tables_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env,
&fn_sig);
check_fn(&inh, param_env, fn_sig, decl, id, body).0
check_fn(&inh, param_env, fn_sig, decl, id, body, false).0
} else {
let fcx = FnCtxt::new(&inh, param_env, body.value.id);
let expected_type = tcx.type_of(def_id);
@ -987,7 +987,8 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
fn_sig: ty::FnSig<'tcx>,
decl: &'gcx hir::FnDecl,
fn_id: ast::NodeId,
body: &'gcx hir::Body)
body: &'gcx hir::Body,
can_be_generator: bool)
-> (FnCtxt<'a, 'gcx, 'tcx>, Option<ty::GeneratorInterior<'tcx>>)
{
let mut fn_sig = fn_sig.clone();
@ -1014,22 +1015,30 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
let def_id = fcx.tcx.hir.local_def_id(fn_id);
let span = body.value.span;
if fcx.tcx.sess.verbose() {
println!("checking body {} {}", fn_id, can_be_generator);
}
if let Some(ref impl_arg) = body.impl_arg {
let impl_arg_ty = fcx.infcx.type_var_for_impl_arg(span, def_id);
if can_be_generator {
let impl_arg_ty = fcx.infcx.type_var_for_impl_arg(span, def_id);
// Require impl_arg: 'static
let cause = traits::ObligationCause::new(span, body.value.id, traits::MiscObligation);;
fcx.fulfillment_cx.borrow_mut()
.register_region_obligation(impl_arg_ty,
fcx.tcx.types.re_static,
cause);
// Require impl_arg: 'static
let cause = traits::ObligationCause::new(span,
body.value.id,
traits::MiscObligation);
fcx.fulfillment_cx.borrow_mut()
.register_region_obligation(impl_arg_ty,
fcx.tcx.types.re_static,
cause);
fcx.impl_arg_ty = Some(impl_arg_ty);
fcx.impl_arg_ty = Some(impl_arg_ty);
// Write the type to the impl arg id
fcx.write_ty(impl_arg.id, impl_arg_ty);
// Write the type to the impl arg id
fcx.write_ty(impl_arg.id, impl_arg_ty);
fcx.suspend_ty = Some(fcx.next_ty_var(TypeVariableOrigin::TypeInference(span)));
fcx.suspend_ty = Some(fcx.next_ty_var(TypeVariableOrigin::TypeInference(span)));
}
}
GatherLocalsVisitor { fcx: &fcx, }.visit_body(body);
@ -1050,7 +1059,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
fcx.write_ty(arg.id, arg_ty);
}
let gen_ty = if body.is_generator() {
let gen_ty = if can_be_generator && body.is_generator() {
let gen_sig = ty::GenSig {
impl_arg_ty: fcx.impl_arg_ty.unwrap(),
suspend_ty: fcx.suspend_ty.unwrap(),
@ -3994,7 +4003,7 @@ fn check_expr_kind(&self,
}
None => {
struct_span_err!(self.tcx.sess, expr.span, E0803,
"impl arg expression outside of function body").emit();
"gen arg expression outside of generator literal").emit();
tcx.types.err
}
}
@ -4006,7 +4015,7 @@ fn check_expr_kind(&self,
}
None => {
struct_span_err!(self.tcx.sess, expr.span, E0802,
"yield statement outside of function body").emit();
"yield statement outside of generator literal").emit();
}
}
tcx.mk_nil()

View File

@ -4668,7 +4668,7 @@ fn i_am_a_function() {}
E0592, // duplicate definitions with name `{}`
// E0613, // Removed (merged with E0609)
E0801, // unexpected generator return
E0802, // yield statement outside of function body
E0803, // impl arg expression outside of function body
E0802, // yield statement outside of generator literal
E0803, // gen arg expression outside of generator literal
E0804, // cannot determine the type for the implicit argument of this generator
}

View File

@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(generators)]
const A: u8 = { yield 3u8; gen arg; 3u8};
//~^ ERROR yield statement outside
//~| ERROR gen arg expression outside

View File

@ -0,0 +1,15 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(generators)]
fn main() { yield; gen arg; }
//~^ ERROR yield statement outside
//~| ERROR gen arg expression outside

View File

@ -10,14 +10,6 @@
#![feature(generators)]
const A: u8 = { yield 3u8; gen arg; 3u8};
//~^ ERROR yield statement outside
//~| ERROR gen arg expression outside
static B: u8 = { yield 3u8; gen arg; 3u8};
//~^ ERROR yield statement outside
//~| ERROR gen arg expression outside
fn main() { yield; gen arg; }
//~^ ERROR yield statement outside
//~| ERROR gen arg expression outside

View File

@ -34,14 +34,15 @@ fn test() -> impl Generator<Return=(), Yield=u8> {
}
fn main() {
let start = 6;
let end = 11;
let closure_test = || {
for i in start..end {
yield i
let closure_test = |start| {
|| {
for i in start..end {
yield i
}
}
};
assert!(W(test()).chain(W(closure_test)).eq(1..11));
assert!(W(test()).chain(W(closure_test(6))).eq(1..11));
}