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.
This commit is contained in:
Simon Sapin 2018-03-23 10:57:28 +01:00
parent 52f7e8836c
commit ee67e14034
22 changed files with 15 additions and 169 deletions

View File

@ -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

View File

@ -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)]

View File

@ -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()))

View File

@ -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())

View File

@ -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")

View File

@ -382,9 +382,6 @@ define_maps! { <'tcx>
[] fn output_filenames: output_filenames_node(CrateNum)
-> Arc<OutputFilenames>,
[] 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.

View File

@ -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 => {

View File

@ -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()
}

View File

@ -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);

View File

@ -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)]

View File

@ -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<Span>,
custom_attribute: Option<Span>,
copy_closures: Option<Span>,
clone_closures: Option<Span>,
}
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();
}
}
}

View File

@ -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() {

View File

@ -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 = || {

View File

@ -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 <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(unboxed_closures)]
fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
fn main() {
let f = to_fn_once(move|| ());
f();
f(); //~ ERROR use of moved value
}

View File

@ -10,8 +10,6 @@
// Check that closures implement `Clone`.
#![feature(clone_closures)]
#[derive(Clone)]
struct S(i32);

View File

@ -10,9 +10,6 @@
// Check that closures implement `Copy`.
#![feature(copy_closures)]
#![feature(clone_closures)]
fn call<T, F: FnOnce() -> T>(f: F) -> T { f() }
fn main() {

View File

@ -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 <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.
#[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
}

View File

@ -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`.

View File

@ -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 <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.
fn main() {
let a = 5;
let hello = || {
println!("Hello {}", a);
};
let b = hello;
let c = hello; //~ ERROR use of moved value: `hello` [E0382]
}

View File

@ -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`.

View File

@ -58,7 +58,10 @@ fn test6() {
fn test7() {
fn foo<F>(_: F) where F: FnMut(Box<FnMut(isize)>, isize) {}
let mut f = |g: Box<FnMut(isize)>, b: isize| {};
let s = String::new(); // Capture to make f !Copy
let mut f = move |g: Box<FnMut(isize)>, b: isize| {
let _ = s.len();
};
f(Box::new(|a| {
foo(f);
//~^ ERROR cannot move `f` into closure because it is borrowed

View File

@ -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<FnMut(isize)>, b: isize| {};
LL | let mut f = move |g: Box<FnMut(isize)>, b: isize| {
| ----- captured outer variable
LL | f(Box::new(|a| {
...
LL | foo(f);
| ^ cannot move out of captured outer variable in an `FnMut` closure