From 5b0c8acd69ba3e9e8bc84161f89f716b01e7c523 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 26 Dec 2014 09:19:37 -0500 Subject: [PATCH] typeck: boxed closures can't capture by value closes #19141 closes #20193 closes #20228 --- src/librustc_typeck/check/closure.rs | 14 +++++++++++ src/librustc_typeck/check/mod.rs | 4 ++-- .../compile-fail/borrowck-move-by-capture.rs | 2 +- src/test/compile-fail/issue-19141.rs | 15 ++++++++++++ src/test/compile-fail/issue-20193.rs | 24 +++++++++++++++++++ src/test/compile-fail/issue-20228-1.rs | 20 ++++++++++++++++ src/test/compile-fail/issue-20228-2.rs | 20 ++++++++++++++++ 7 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/issue-19141.rs create mode 100644 src/test/compile-fail/issue-20193.rs create mode 100644 src/test/compile-fail/issue-20228-1.rs create mode 100644 src/test/compile-fail/issue-20228-2.rs diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index e25543ea99241..c396dc5c6cb76 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -19,11 +19,13 @@ use middle::ty::{mod, Ty}; use rscope::RegionScope; use syntax::abi; use syntax::ast; +use syntax::ast::CaptureClause::*; use syntax::ast_util; use util::ppaux::Repr; pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, expr: &ast::Expr, + capture: ast::CaptureClause, opt_kind: Option, decl: &ast::FnDecl, body: &ast::Block, @@ -48,12 +50,24 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, fcx.infcx(), expr.span, &None); + check_boxed_closure(fcx, expr, ty::RegionTraitStore(region, ast::MutMutable), decl, body, expected); + + match capture { + CaptureByValue => { + fcx.ccx.tcx.sess.span_err( + expr.span, + "boxed closures can't capture by value, \ + if you want to use an unboxed closure, \ + explicitly annotate its kind: e.g. `move |:|`"); + }, + CaptureByRef => {} + } } Some((sig, kind)) => { check_unboxed_closure(fcx, expr, kind, decl, body, Some(sig)); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index abcd00ddcce08..7660806f5b04d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3958,8 +3958,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, ast::ExprMatch(ref discrim, ref arms, match_src) => { _match::check_match(fcx, expr, &**discrim, arms.as_slice(), expected, match_src); } - ast::ExprClosure(_, opt_kind, ref decl, ref body) => { - closure::check_expr_closure(fcx, expr, opt_kind, &**decl, &**body, expected); + ast::ExprClosure(capture, opt_kind, ref decl, ref body) => { + closure::check_expr_closure(fcx, expr, capture, opt_kind, &**decl, &**body, expected); } ast::ExprBlock(ref b) => { check_block_with_expected(fcx, &**b, expected); diff --git a/src/test/compile-fail/borrowck-move-by-capture.rs b/src/test/compile-fail/borrowck-move-by-capture.rs index aae661e5c5379..9c9641bccfa14 100644 --- a/src/test/compile-fail/borrowck-move-by-capture.rs +++ b/src/test/compile-fail/borrowck-move-by-capture.rs @@ -11,6 +11,6 @@ pub fn main() { let bar = box 3; let _g = || { - let _h = move|| -> int { *bar }; //~ ERROR cannot move out of captured outer variable + let _h = move |:| -> int { *bar }; //~ ERROR cannot move out of captured outer variable }; } diff --git a/src/test/compile-fail/issue-19141.rs b/src/test/compile-fail/issue-19141.rs new file mode 100644 index 0000000000000..545e3f8acb139 --- /dev/null +++ b/src/test/compile-fail/issue-19141.rs @@ -0,0 +1,15 @@ +// Copyright 2014 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. + +fn main() { + let n = 0u; + + let f = move || n += 1; //~error boxed closures can't capture by value +} diff --git a/src/test/compile-fail/issue-20193.rs b/src/test/compile-fail/issue-20193.rs new file mode 100644 index 0000000000000..e5d8d3327199b --- /dev/null +++ b/src/test/compile-fail/issue-20193.rs @@ -0,0 +1,24 @@ +// Copyright 2014 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. + +fn foo(t: &mut int){ + println!("{}", t); +} + +fn main() { + let test = 10; + + let h = move || { //~error boxed closures can't capture by value + let mut r = &mut test.clone(); + foo(r); + }; + + h(); +} diff --git a/src/test/compile-fail/issue-20228-1.rs b/src/test/compile-fail/issue-20228-1.rs new file mode 100644 index 0000000000000..3ff4557ae80ed --- /dev/null +++ b/src/test/compile-fail/issue-20228-1.rs @@ -0,0 +1,20 @@ +// Copyright 2014 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. + +struct S; + +impl S { + fn foo(&self) { + let _ = move || { self }; //~error boxed closures can't capture by value + } +} + +fn main() { +} diff --git a/src/test/compile-fail/issue-20228-2.rs b/src/test/compile-fail/issue-20228-2.rs new file mode 100644 index 0000000000000..5fec4268bf7c2 --- /dev/null +++ b/src/test/compile-fail/issue-20228-2.rs @@ -0,0 +1,20 @@ +// Copyright 2014 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. + +struct S; + +impl S { + fn foo(&self) { + let _ = move || { self.foo() }; //~error boxed closures can't capture by value + } +} + +fn main() { +}