Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stabilize the copy_closures and clone_closures features #49299

Merged
merged 3 commits into from
Mar 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/libcore/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@
/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
/// implementation of [`clone`] calls [`clone`] on each field.
///
/// ## Closures
///
/// Closure types automatically implement `Clone` if they capture no value from the environment
/// or if all such captured values implement `Clone` themselves.
///
/// ## How can I implement `Clone`?
///
/// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally:
Expand Down
5 changes: 5 additions & 0 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ pub trait Unsize<T: ?Sized> {
/// are allowed to access `x` after the assignment. Under the hood, both a copy and a move
/// can result in bits being copied in memory, although this is sometimes optimized away.
///
/// ## Closures
///
/// Closure types automatically implement `Copy` if they capture no value from the environment
/// or if all such captured values implement `Copy` themselves.
///
/// ## How can I implement `Copy`?
///
/// There are two ways to implement `Copy` on your type. The simplest is to use `derive`:
Expand Down
2 changes: 0 additions & 2 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
11 changes: 3 additions & 8 deletions src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2086,14 +2086,9 @@ 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);

if copy_closures || clone_closures {
let is_copy_trait = Some(trait_id) == self.tcx().lang_items().copy_trait();
let is_clone_trait = Some(trait_id) == self.tcx().lang_items().clone_trait();
if is_copy_trait || is_clone_trait {
Where(ty::Binder(substs.upvar_tys(def_id, self.tcx()).collect()))
} else {
Never
Expand Down
8 changes: 0 additions & 8 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
12 changes: 0 additions & 12 deletions src/librustc/ty/maps/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
3 changes: 0 additions & 3 deletions src/librustc/ty/maps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 0 additions & 2 deletions src/librustc/ty/maps/plumbing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down
10 changes: 0 additions & 10 deletions src/librustc_metadata/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
3 changes: 0 additions & 3 deletions src/librustc_metadata/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
26 changes: 3 additions & 23 deletions src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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) {
Expand All @@ -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();
}
}
}

Expand Down
2 changes: 0 additions & 2 deletions src/test/compile-fail/not-clone-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
3 changes: 0 additions & 3 deletions src/test/compile-fail/not-copy-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = || {
Expand Down
19 changes: 0 additions & 19 deletions src/test/compile-fail/unboxed-closer-non-implicit-copyable.rs

This file was deleted.

2 changes: 0 additions & 2 deletions src/test/run-pass/clone-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@

// Check that closures implement `Clone`.

#![feature(clone_closures)]

#[derive(Clone)]
struct S(i32);

Expand Down
3 changes: 0 additions & 3 deletions src/test/run-pass/copy-closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
21 changes: 0 additions & 21 deletions src/test/ui/feature-gate-clone-closures.rs

This file was deleted.

11 changes: 0 additions & 11 deletions src/test/ui/feature-gate-clone-closures.stderr

This file was deleted.

19 changes: 0 additions & 19 deletions src/test/ui/feature-gate-copy-closures.rs

This file was deleted.

13 changes: 0 additions & 13 deletions src/test/ui/feature-gate-copy-closures.stderr

This file was deleted.

5 changes: 4 additions & 1 deletion src/test/ui/span/borrowck-call-is-borrow-issue-12224.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/span/borrowck-call-is-borrow-issue-12224.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ 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
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

Expand Down