about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-09-21 00:35:33 +0000
committerbors <bors@rust-lang.org>2017-09-21 00:35:33 +0000
commite2504cfc7615b9247d4546672e31a9803f4b88ba (patch)
treeb6700e23d1a39a841a02491e8f7e2dee0a2e12c7 /src/libsyntax
parent870483a57f9e3e1daee6543a4ace2cf875b74541 (diff)
parent3fa3fe01b65ec4dde20c66c6bedcd28e2f83f8b6 (diff)
downloadrust-e2504cfc7615b9247d4546672e31a9803f4b88ba.tar.gz
rust-e2504cfc7615b9247d4546672e31a9803f4b88ba.zip
Auto merge of #44551 - scalexm:copy-clone-closures, r=arielb1
Implement `Copy`/`Clone` for closures

Implement RFC [#2132](https://github.com/rust-lang/rfcs/pull/2132) (tracking issue: #44490).

NB: I'm not totally sure about the whole feature gates thing, that's my first PR of this kind...
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/attr.rs14
-rw-r--r--src/libsyntax/feature_gate.rs31
2 files changed, 41 insertions, 4 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 36ab3737f38..b1f796084df 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -500,6 +500,20 @@ pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str) -> Option<S
         .and_then(|at| at.value_str())
 }
 
+/// Check if `attrs` contains an attribute like `#![feature(feature_name)]`.
+/// This will not perform any "sanity checks" on the form of the attributes.
+pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool {
+    attrs.iter().any(|item| {
+        item.check_name("feature") &&
+        item.meta_item_list().map(|list| {
+            list.iter().any(|mi| {
+                mi.word().map(|w| w.name() == feature_name)
+                         .unwrap_or(false)
+            })
+        }).unwrap_or(false)
+    })
+}
+
 /* Higher-level applications */
 
 pub fn find_crate_name(attrs: &[Attribute]) -> Option<Symbol> {
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index ae0dd872963..6560943a932 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -385,6 +385,10 @@ declare_features! (
 
     // allow '|' at beginning of match arms (RFC 1925)
     (active, match_beginning_vert, "1.21.0", Some(44101)),
+
+    // Copy/Clone closures (RFC 2132)
+    (active, clone_closures, "1.22.0", Some(44490)),
+    (active, copy_closures, "1.22.0", Some(44490)),
 );
 
 declare_features! (
@@ -1573,7 +1577,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {
     let mut features = Features::new();
 
-    let mut feature_checker = MutexFeatureChecker::default();
+    let mut feature_checker = FeatureChecker::default();
 
     for attr in krate_attrs {
         if !attr.check_name("feature") {
@@ -1622,14 +1626,16 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> F
     features
 }
 
-// A collector for mutually-exclusive features and their flag spans
+/// A collector for mutually exclusive and interdependent features and their flag spans.
 #[derive(Default)]
-struct MutexFeatureChecker {
+struct FeatureChecker {
     proc_macro: Option<Span>,
     custom_attribute: Option<Span>,
+    copy_closures: Option<Span>,
+    clone_closures: Option<Span>,
 }
 
-impl MutexFeatureChecker {
+impl FeatureChecker {
     // If this method turns out to be a hotspot due to branching,
     // the branching can be eliminated by modifying `set!()` to set these spans
     // only for the features that need to be checked for mutual exclusion.
@@ -1642,6 +1648,14 @@ impl MutexFeatureChecker {
         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) {
@@ -1653,6 +1667,15 @@ impl MutexFeatureChecker {
 
             panic!(FatalError);
         }
+
+        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();
+
+            panic!(FatalError);
+        }
     }
 }