From ee67e14034438972c5aae46f8773fe69f20f14aa Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 23 Mar 2018 10:57:28 +0100 Subject: [PATCH] Stabilize the copy_closures and clone_closures features In addition to the `Fn*` family of traits, closures now implement `Copy` (and similarly `Clone`) if all of the captures do. --- src/librustc/dep_graph/dep_node.rs | 2 -- src/librustc/lib.rs | 2 +- src/librustc/traits/select.rs | 8 ++---- src/librustc/ty/context.rs | 8 ------ src/librustc/ty/maps/config.rs | 12 --------- src/librustc/ty/maps/mod.rs | 3 --- src/librustc/ty/maps/plumbing.rs | 2 -- src/librustc_metadata/cstore.rs | 10 ------- src/librustc_metadata/cstore_impl.rs | 3 --- src/librustc_typeck/lib.rs | 2 +- src/libsyntax/feature_gate.rs | 26 +++---------------- src/test/compile-fail/not-clone-closure.rs | 2 -- src/test/compile-fail/not-copy-closure.rs | 3 --- .../unboxed-closer-non-implicit-copyable.rs | 19 -------------- src/test/run-pass/clone-closure.rs | 2 -- src/test/run-pass/copy-closure.rs | 3 --- src/test/ui/feature-gate-clone-closures.rs | 21 --------------- .../ui/feature-gate-clone-closures.stderr | 11 -------- src/test/ui/feature-gate-copy-closures.rs | 19 -------------- src/test/ui/feature-gate-copy-closures.stderr | 13 ---------- .../borrowck-call-is-borrow-issue-12224.rs | 5 +++- ...borrowck-call-is-borrow-issue-12224.stderr | 8 +++--- 22 files changed, 15 insertions(+), 169 deletions(-) delete mode 100644 src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs delete mode 100644 src/test/ui/feature-gate-clone-closures.rs delete mode 100644 src/test/ui/feature-gate-clone-closures.stderr delete mode 100644 src/test/ui/feature-gate-copy-closures.rs delete mode 100644 src/test/ui/feature-gate-copy-closures.stderr diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 1e2e4e5a69f..5421d2add25 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -616,8 +616,6 @@ define_dep_nodes!( <'tcx> [input] MissingExternCrateItem(CrateNum), [input] UsedCrateSource(CrateNum), [input] PostorderCnums, - [] HasCloneClosures(CrateNum), - [] HasCopyClosures(CrateNum), // This query is not expected to have inputs -- as a result, it's // not a good candidate for "replay" because it's essentially a diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 22b07c8cc04..a759ce59cb6 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -45,7 +45,7 @@ #![feature(box_syntax)] #![feature(conservative_impl_trait)] #![feature(const_fn)] -#![feature(copy_closures, clone_closures)] +#![cfg_attr(stage0, feature(copy_closures, clone_closures))] #![feature(core_intrinsics)] #![feature(drain_filter)] #![feature(dyn_trait)] diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 4db81cf1dec..f414374d008 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2086,12 +2086,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyClosure(def_id, substs) => { let trait_id = obligation.predicate.def_id(); - let copy_closures = - Some(trait_id) == self.tcx().lang_items().copy_trait() && - self.tcx().has_copy_closures(def_id.krate); - let clone_closures = - Some(trait_id) == self.tcx().lang_items().clone_trait() && - self.tcx().has_clone_closures(def_id.krate); + let copy_closures = Some(trait_id) == self.tcx().lang_items().copy_trait(); + let clone_closures = Some(trait_id) == self.tcx().lang_items().clone_trait(); if copy_closures || clone_closures { Where(ty::Binder(substs.upvar_tys(def_id, self.tcx()).collect())) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index fd3465f59eb..f56d866cba5 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2520,14 +2520,6 @@ pub fn provide(providers: &mut ty::maps::Providers) { assert_eq!(cnum, LOCAL_CRATE); tcx.output_filenames.clone() }; - providers.has_copy_closures = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - tcx.features().copy_closures - }; - providers.has_clone_closures = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - tcx.features().clone_closures - }; providers.features_query = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); Lrc::new(tcx.sess.features_untracked().clone()) diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 117d9219312..400bc6ba415 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -604,24 +604,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::output_filenames<'tcx> { } } -impl<'tcx> QueryDescription<'tcx> for queries::has_clone_closures<'tcx> { - fn describe(_tcx: TyCtxt, _: CrateNum) -> String { - format!("seeing if the crate has enabled `Clone` closures") - } -} - impl<'tcx> QueryDescription<'tcx> for queries::vtable_methods<'tcx> { fn describe(tcx: TyCtxt, key: ty::PolyTraitRef<'tcx> ) -> String { format!("finding all methods for trait {}", tcx.item_path_str(key.def_id())) } } -impl<'tcx> QueryDescription<'tcx> for queries::has_copy_closures<'tcx> { - fn describe(_tcx: TyCtxt, _: CrateNum) -> String { - format!("seeing if the crate has enabled `Copy` closures") - } -} - impl<'tcx> QueryDescription<'tcx> for queries::features_query<'tcx> { fn describe(_tcx: TyCtxt, _: CrateNum) -> String { format!("looking up enabled feature gates") diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 6c3b4efb932..95e00418658 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -382,9 +382,6 @@ define_maps! { <'tcx> [] fn output_filenames: output_filenames_node(CrateNum) -> Arc, - [] fn has_copy_closures: HasCopyClosures(CrateNum) -> bool, - [] fn has_clone_closures: HasCloneClosures(CrateNum) -> bool, - // Erases regions from `ty` to yield a new type. // Normally you would just use `tcx.erase_regions(&value)`, // however, which uses this query as a kind of cache. diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 4170fa76797..d9caf94ed7f 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -917,8 +917,6 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, } DepKind::UsedCrateSource => { force!(used_crate_source, krate!()); } DepKind::PostorderCnums => { force!(postorder_cnums, LOCAL_CRATE); } - DepKind::HasCloneClosures => { force!(has_clone_closures, krate!()); } - DepKind::HasCopyClosures => { force!(has_copy_closures, krate!()); } DepKind::Freevars => { force!(freevars, def_id!()); } DepKind::MaybeUnusedTraitImport => { diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index bd5ad93946e..b9623f28540 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -228,16 +228,6 @@ impl CrateMetadata { attr::contains_name(&attrs, "no_builtins") } - pub fn has_copy_closures(&self, sess: &Session) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess); - attr::contains_feature_attr(&attrs, "copy_closures") - } - - pub fn has_clone_closures(&self, sess: &Session) -> bool { - let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess); - attr::contains_feature_attr(&attrs, "clone_closures") - } - pub fn panic_strategy(&self) -> PanicStrategy { self.root.panic_strategy.clone() } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 2de27f3a1c3..f02a1831db2 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -256,9 +256,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, used_crate_source => { Lrc::new(cdata.source.clone()) } - has_copy_closures => { cdata.has_copy_closures(tcx.sess) } - has_clone_closures => { cdata.has_clone_closures(tcx.sess) } - exported_symbols => { let cnum = cdata.cnum; assert!(cnum != LOCAL_CRATE); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9f98932f24b..8a1d87fe1ea 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -76,7 +76,7 @@ This API is completely unstable and subject to change. #![feature(box_patterns)] #![feature(box_syntax)] #![feature(conservative_impl_trait)] -#![feature(copy_closures, clone_closures)] +#![cfg_attr(stage0, feature(copy_closures, clone_closures))] #![feature(crate_visibility_modifier)] #![feature(from_ref)] #![feature(match_default_bindings)] diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 915396d29fe..73d088fb585 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -391,10 +391,6 @@ declare_features! ( // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008) (active, non_exhaustive, "1.22.0", Some(44109), None), - // Copy/Clone closures (RFC 2132) - (active, clone_closures, "1.22.0", Some(44490), None), - (active, copy_closures, "1.22.0", Some(44490), None), - // allow `'_` placeholder lifetimes (active, underscore_lifetimes, "1.22.0", Some(44524), None), @@ -556,6 +552,9 @@ declare_features! ( (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None), // allow `..=` in patterns (RFC 1192) (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None), + // Copy/Clone closures (RFC 2132) + (accepted, clone_closures, "1.26.0", Some(44490), None), + (accepted, copy_closures, "1.26.0", Some(44490), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1867,8 +1866,6 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], struct FeatureChecker { proc_macro: Option, custom_attribute: Option, - copy_closures: Option, - clone_closures: Option, } impl FeatureChecker { @@ -1884,14 +1881,6 @@ impl FeatureChecker { if features.custom_attribute { self.custom_attribute = self.custom_attribute.or(Some(span)); } - - if features.copy_closures { - self.copy_closures = self.copy_closures.or(Some(span)); - } - - if features.clone_closures { - self.clone_closures = self.clone_closures.or(Some(span)); - } } fn check(self, handler: &Handler) { @@ -1903,15 +1892,6 @@ impl FeatureChecker { FatalError.raise(); } - - if let (Some(span), None) = (self.copy_closures, self.clone_closures) { - handler.struct_span_err(span, "`#![feature(copy_closures)]` can only be used with \ - `#![feature(clone_closures)]`") - .span_note(span, "`#![feature(copy_closures)]` declared here") - .emit(); - - FatalError.raise(); - } } } diff --git a/src/test/compile-fail/not-clone-closure.rs b/src/test/compile-fail/not-clone-closure.rs index 2a30dc4fdd4..967cb3610ca 100644 --- a/src/test/compile-fail/not-clone-closure.rs +++ b/src/test/compile-fail/not-clone-closure.rs @@ -10,8 +10,6 @@ // Check that closures do not implement `Clone` if their environment is not `Clone`. -#![feature(clone_closures)] - struct S(i32); fn main() { diff --git a/src/test/compile-fail/not-copy-closure.rs b/src/test/compile-fail/not-copy-closure.rs index 271e6d5fc90..10567c5c961 100644 --- a/src/test/compile-fail/not-copy-closure.rs +++ b/src/test/compile-fail/not-copy-closure.rs @@ -10,9 +10,6 @@ // Check that closures do not implement `Copy` if their environment is not `Copy`. -#![feature(copy_closures)] -#![feature(clone_closures)] - fn main() { let mut a = 5; let hello = || { diff --git a/src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs b/src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs deleted file mode 100644 index 2d559794919..00000000000 --- a/src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -#![feature(unboxed_closures)] - -fn to_fn_once>(f: F) -> F { f } - -fn main() { - let f = to_fn_once(move|| ()); - f(); - f(); //~ ERROR use of moved value -} diff --git a/src/test/run-pass/clone-closure.rs b/src/test/run-pass/clone-closure.rs index 7f554c77fc4..0fe3711d8d3 100644 --- a/src/test/run-pass/clone-closure.rs +++ b/src/test/run-pass/clone-closure.rs @@ -10,8 +10,6 @@ // Check that closures implement `Clone`. -#![feature(clone_closures)] - #[derive(Clone)] struct S(i32); diff --git a/src/test/run-pass/copy-closure.rs b/src/test/run-pass/copy-closure.rs index 309c83ebd99..a211d6fc3a3 100644 --- a/src/test/run-pass/copy-closure.rs +++ b/src/test/run-pass/copy-closure.rs @@ -10,9 +10,6 @@ // Check that closures implement `Copy`. -#![feature(copy_closures)] -#![feature(clone_closures)] - fn call T>(f: F) -> T { f() } fn main() { diff --git a/src/test/ui/feature-gate-clone-closures.rs b/src/test/ui/feature-gate-clone-closures.rs deleted file mode 100644 index a15153ea7bf..00000000000 --- a/src/test/ui/feature-gate-clone-closures.rs +++ /dev/null @@ -1,21 +0,0 @@ -// 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. - -#[derive(Clone)] -struct S(i32); - -fn main() { - let a = S(5); - let hello = move || { - println!("Hello {}", a.0); - }; - - let hello = hello.clone(); //~ ERROR no method named `clone` found for type -} diff --git a/src/test/ui/feature-gate-clone-closures.stderr b/src/test/ui/feature-gate-clone-closures.stderr deleted file mode 100644 index 7038a76380d..00000000000 --- a/src/test/ui/feature-gate-clone-closures.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0599]: no method named `clone` found for type `[closure@$DIR/feature-gate-clone-closures.rs:16:17: 18:6 a:_]` in the current scope - --> $DIR/feature-gate-clone-closures.rs:20:23 - | -LL | let hello = hello.clone(); //~ ERROR no method named `clone` found for type - | ^^^^^ - | - = note: hello is a function, perhaps you wish to call it - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/feature-gate-copy-closures.rs b/src/test/ui/feature-gate-copy-closures.rs deleted file mode 100644 index b11b09eb9fd..00000000000 --- a/src/test/ui/feature-gate-copy-closures.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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. - -fn main() { - let a = 5; - let hello = || { - println!("Hello {}", a); - }; - - let b = hello; - let c = hello; //~ ERROR use of moved value: `hello` [E0382] -} diff --git a/src/test/ui/feature-gate-copy-closures.stderr b/src/test/ui/feature-gate-copy-closures.stderr deleted file mode 100644 index e72680b69ea..00000000000 --- a/src/test/ui/feature-gate-copy-closures.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0382]: use of moved value: `hello` - --> $DIR/feature-gate-copy-closures.rs:18:9 - | -LL | let b = hello; - | - value moved here -LL | let c = hello; //~ ERROR use of moved value: `hello` [E0382] - | ^ value used here after move - | - = note: move occurs because `hello` has type `[closure@$DIR/feature-gate-copy-closures.rs:13:17: 15:6 a:&i32]`, which does not implement the `Copy` trait - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs index 8e03c303e54..e8227971691 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs @@ -58,7 +58,10 @@ fn test6() { fn test7() { fn foo(_: F) where F: FnMut(Box, isize) {} - let mut f = |g: Box, b: isize| {}; + let s = String::new(); // Capture to make f !Copy + let mut f = move |g: Box, b: isize| { + let _ = s.len(); + }; f(Box::new(|a| { foo(f); //~^ ERROR cannot move `f` into closure because it is borrowed diff --git a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr index 318b77dedcb..2e7e1e07441 100644 --- a/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr +++ b/src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr @@ -28,7 +28,7 @@ LL | f.f.call_mut(()) | ^^^ cannot borrow as mutable error[E0504]: cannot move `f` into closure because it is borrowed - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13 | LL | f(Box::new(|a| { | - borrow of `f` occurs here @@ -36,11 +36,11 @@ LL | foo(f); | ^ move into closure occurs here error[E0507]: cannot move out of captured outer variable in an `FnMut` closure - --> $DIR/borrowck-call-is-borrow-issue-12224.rs:63:13 + --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13 | -LL | let mut f = |g: Box, b: isize| {}; +LL | let mut f = move |g: Box, b: isize| { | ----- captured outer variable -LL | f(Box::new(|a| { +... LL | foo(f); | ^ cannot move out of captured outer variable in an `FnMut` closure