diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index ae64db88d8c5..0f68b1597784 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -82,7 +82,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { 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 { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index cf8b1d9c8f26..1d1631c4fa7e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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>) { 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } 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() diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 4313aa59202f..0463f82ccce2 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -4668,7 +4668,7 @@ register_diagnostics! { 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 } diff --git a/src/test/compile-fail/generator/yield-in-const.rs b/src/test/compile-fail/generator/yield-in-const.rs new file mode 100644 index 000000000000..5176f3c5f568 --- /dev/null +++ b/src/test/compile-fail/generator/yield-in-const.rs @@ -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 or the MIT license +// , 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 diff --git a/src/test/compile-fail/generator/yield-in-function.rs b/src/test/compile-fail/generator/yield-in-function.rs new file mode 100644 index 000000000000..95ec1224421f --- /dev/null +++ b/src/test/compile-fail/generator/yield-in-function.rs @@ -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 or the MIT license +// , 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 diff --git a/src/test/compile-fail/generator/invalid-positions.rs b/src/test/compile-fail/generator/yield-in-static.rs similarity index 73% rename from src/test/compile-fail/generator/invalid-positions.rs rename to src/test/compile-fail/generator/yield-in-static.rs index c2f5b20d5758..f4cad13ce8eb 100644 --- a/src/test/compile-fail/generator/invalid-positions.rs +++ b/src/test/compile-fail/generator/yield-in-static.rs @@ -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 diff --git a/src/test/run-pass/generator/iterator-count.rs b/src/test/run-pass/generator/iterator-count.rs index c415ef2beb30..e44aa0592357 100644 --- a/src/test/run-pass/generator/iterator-count.rs +++ b/src/test/run-pass/generator/iterator-count.rs @@ -34,14 +34,15 @@ fn test() -> impl Generator { } 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)); }