about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2015-02-12 11:30:16 +0100
committerFelix S. Klock II <pnkfelix@pnkfx.org>2015-07-22 15:33:59 +0200
commitb325e4f28e0735bb951bdf9f1db1206bd3ee715b (patch)
tree85936fe4b2c7a27c44ceaf8b48149adb577c920b /src
parentd79bbbc4ef20a11680a004b600a90281e4c5e04a (diff)
downloadrust-b325e4f28e0735bb951bdf9f1db1206bd3ee715b.tar.gz
rust-b325e4f28e0735bb951bdf9f1db1206bd3ee715b.zip
Add feature-gates for desugaring-based `box` and placement-`in`.
update test/compile-fail/feature-gate-box-expr.rs to reflect new feature gates.

Part of what lands with Issue 22181.
Diffstat (limited to 'src')
-rw-r--r--src/liballoc/lib.rs2
-rw-r--r--src/libstd/lib.rs1
-rw-r--r--src/libsyntax/ext/expand.rs7
-rw-r--r--src/libsyntax/feature_gate.rs57
-rw-r--r--src/test/compile-fail/feature-gate-box-expr.rs5
5 files changed, 70 insertions, 2 deletions
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index ead0b4259a9..d72b52615eb 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -82,8 +82,10 @@
 #![feature(no_std)]
 #![feature(nonzero)]
 #![feature(optin_builtin_traits)]
+#![feature(placement_in_syntax)]
 #![feature(raw)]
 #![feature(staged_api)]
+#![feature(placement_in_syntax)]
 #![feature(unboxed_closures)]
 #![feature(unique)]
 #![feature(unsafe_no_drop_flag, filling_drop)]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 82bc1314ad5..784f5eecf0b 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -234,6 +234,7 @@
 #![feature(no_std)]
 #![feature(oom)]
 #![feature(optin_builtin_traits)]
+#![feature(placement_in_syntax)]
 #![feature(rand)]
 #![feature(raw)]
 #![feature(reflect_marker)]
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 208446ed046..93e744287ba 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -56,6 +56,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
         });
     }
 
+    let expr_span = e.span;
     return e.and_then(|ast::Expr {id, node, span}| match node {
 
         // expr_mac should really be expr_ext or something; it's the
@@ -94,6 +95,12 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
             //     InPlace::finalize(place)
             // })
 
+            // Ensure feature-gate is enabled
+            feature_gate::check_for_placement_in(
+                fld.cx.ecfg.features,
+                &fld.cx.parse_sess.span_diagnostic,
+                expr_span);
+
             let value_span = value_expr.span;
             let placer_span = placer.span;
 
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 69d120cff60..8c6855036f6 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -80,6 +80,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
     ("visible_private_types", "1.0.0", Active),
     ("slicing_syntax", "1.0.0", Accepted),
     ("box_syntax", "1.0.0", Active),
+    ("placement_in_syntax", "1.0.0", Active),
     ("pushpop_unsafe", "1.2.0", Active),
     ("on_unimplemented", "1.0.0", Active),
     ("simd_ffi", "1.0.0", Active),
@@ -326,6 +327,8 @@ pub struct Features {
     pub allow_trace_macros: bool,
     pub allow_internal_unstable: bool,
     pub allow_custom_derive: bool,
+    pub allow_placement_in: bool,
+    pub allow_box: bool,
     pub allow_pushpop_unsafe: bool,
     pub simd_ffi: bool,
     pub unmarked_api: bool,
@@ -350,6 +353,8 @@ impl Features {
             allow_trace_macros: false,
             allow_internal_unstable: false,
             allow_custom_derive: false,
+            allow_placement_in: false,
+            allow_box: false,
             allow_pushpop_unsafe: false,
             simd_ffi: false,
             unmarked_api: false,
@@ -361,6 +366,29 @@ impl Features {
     }
 }
 
+const EXPLAIN_BOX_SYNTAX: &'static str =
+    "box expression syntax is experimental; you can call `Box::new` instead.";
+
+const EXPLAIN_PLACEMENT_IN: &'static str =
+    "placement-in expression syntax is experimental and subject to change.";
+
+const EXPLAIN_PUSHPOP_UNSAFE: &'static str =
+    "push/pop_unsafe macros are experimental and subject to change.";
+
+pub fn check_for_box_syntax(f: Option<&Features>, diag: &SpanHandler, span: Span) {
+    if let Some(&Features { allow_box: true, .. }) = f {
+        return;
+    }
+    emit_feature_err(diag, "box_syntax", span, EXPLAIN_BOX_SYNTAX);
+}
+
+pub fn check_for_placement_in(f: Option<&Features>, diag: &SpanHandler, span: Span) {
+    if let Some(&Features { allow_placement_in: true, .. }) = f {
+        return;
+    }
+    emit_feature_err(diag, "placement_in_syntax", span, EXPLAIN_PLACEMENT_IN);
+}
+
 pub fn check_for_pushpop_syntax(f: Option<&Features>, diag: &SpanHandler, span: Span) {
     if let Some(&Features { allow_pushpop_unsafe: true, .. }) = f {
         return;
@@ -376,6 +404,11 @@ struct Context<'a> {
 }
 
 impl<'a> Context<'a> {
+    fn enable_feature(&mut self, feature: &'static str) {
+        debug!("enabling feature: {}", feature);
+        self.features.push(feature);
+    }
+
     fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
         let has_feature = self.has_feature(feature);
         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", feature, span, has_feature);
@@ -498,6 +531,26 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
     fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
         self.context.check_attribute(attr, true);
     }
+
+    fn visit_expr(&mut self, e: &ast::Expr) {
+        // Issue 22181: overloaded-`box` and placement-`in` are
+        // implemented via a desugaring expansion, so their feature
+        // gates go into MacroVisitor since that works pre-expansion.
+        //
+        // Issue 22234: we also check during expansion as well.
+        // But we keep these checks as a pre-expansion check to catch
+        // uses in e.g. conditionalized code.
+
+        if let ast::ExprBox(None, _) = e.node {
+            self.context.gate_feature("box_syntax", e.span, EXPLAIN_BOX_SYNTAX);
+        }
+
+        if let ast::ExprBox(Some(_), _) = e.node {
+            self.context.gate_feature("placement_in_syntax", e.span, EXPLAIN_PLACEMENT_IN);
+        }
+
+        visit::walk_expr(self, e);
+    }
 }
 
 struct PostExpansionVisitor<'a> {
@@ -764,7 +817,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
                     match KNOWN_FEATURES.iter()
                                         .find(|& &(n, _, _)| name == n) {
                         Some(&(name, _, Active)) => {
-                            cx.features.push(name);
+                            cx.enable_feature(name);
                         }
                         Some(&(_, _, Removed)) => {
                             span_handler.span_err(mi.span, "feature has been removed");
@@ -797,6 +850,8 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
         allow_trace_macros: cx.has_feature("trace_macros"),
         allow_internal_unstable: cx.has_feature("allow_internal_unstable"),
         allow_custom_derive: cx.has_feature("custom_derive"),
+        allow_placement_in: cx.has_feature("placement_in_syntax"),
+        allow_box: cx.has_feature("box_syntax"),
         allow_pushpop_unsafe: cx.has_feature("pushpop_unsafe"),
         simd_ffi: cx.has_feature("simd_ffi"),
         unmarked_api: cx.has_feature("unmarked_api"),
diff --git a/src/test/compile-fail/feature-gate-box-expr.rs b/src/test/compile-fail/feature-gate-box-expr.rs
index 8f8b035f4a9..f5c9a63b79b 100644
--- a/src/test/compile-fail/feature-gate-box-expr.rs
+++ b/src/test/compile-fail/feature-gate-box-expr.rs
@@ -17,6 +17,9 @@ fn main() {
     let x = box () 'c'; //~ ERROR box expression syntax is experimental
     println!("x: {}", x);
 
-    let x = box (HEAP) 'c'; //~ ERROR box expression syntax is experimental
+    let x = box (HEAP) 'c'; //~ ERROR placement-in expression syntax is experimental
+    println!("x: {}", x);
+
+    let x = in HEAP { 'c' }; //~ ERROR placement-in expression syntax is experimental
     println!("x: {}", x);
 }