Skip to content

Commit 467345b

Browse files
committed
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.
1 parent 0be597d commit 467345b

File tree

5 files changed

+72
-9
lines changed

5 files changed

+72
-9
lines changed

src/liballoc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#![feature(lang_items, unsafe_destructor)]
7373
#![feature(box_syntax)]
7474
#![feature(optin_builtin_traits)]
75+
#![feature(placement_in_syntax)]
7576
#![feature(unboxed_closures)]
7677
#![feature(unsafe_no_drop_flag)]
7778
#![feature(core)]

src/libstd/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@
116116
#![feature(linkage, thread_local, asm)]
117117
#![feature(old_impl_check)]
118118
#![feature(optin_builtin_traits)]
119+
#![feature(placement_in_syntax)]
119120
#![feature(rand)]
120121
#![feature(staged_api)]
121122
#![feature(unboxed_closures)]

src/libsyntax/ext/expand.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
110110
// InPlace::finalize(place)
111111
// }
112112

113+
// Ensure feature-gate is enabled
114+
feature_gate::check_for_placement_in(
115+
fld.cx.ecfg.features,
116+
&fld.cx.parse_sess.span_diagnostic,
117+
expr_span);
118+
113119
let value_span = value_expr.span;
114120
let placer_span = placer.span;
115121

@@ -195,6 +201,12 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
195201
// Boxed::finalize(place)
196202
// }
197203

204+
// Ensure feature-gate is enabled
205+
feature_gate::check_for_box_syntax(
206+
fld.cx.ecfg.features,
207+
&fld.cx.parse_sess.span_diagnostic,
208+
expr_span);
209+
198210
let value_span = value_expr.span;
199211

200212
let value_expr = fld.fold_expr(value_expr);

src/libsyntax/feature_gate.rs

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
8181
("visible_private_types", "1.0.0", Active),
8282
("slicing_syntax", "1.0.0", Accepted),
8383
("box_syntax", "1.0.0", Active),
84+
("placement_in_syntax", "1.0.0", Active),
8485
("on_unimplemented", "1.0.0", Active),
8586
("simd_ffi", "1.0.0", Active),
8687

@@ -324,6 +325,8 @@ pub struct Features {
324325
pub allow_trace_macros: bool,
325326
pub allow_internal_unstable: bool,
326327
pub allow_custom_derive: bool,
328+
pub allow_placement_in: bool,
329+
pub allow_box: bool,
327330
pub old_orphan_check: bool,
328331
pub simd_ffi: bool,
329332
pub unmarked_api: bool,
@@ -346,6 +349,8 @@ impl Features {
346349
allow_trace_macros: false,
347350
allow_internal_unstable: false,
348351
allow_custom_derive: false,
352+
allow_placement_in: false,
353+
allow_box: false,
349354
old_orphan_check: false,
350355
simd_ffi: false,
351356
unmarked_api: false,
@@ -355,6 +360,26 @@ impl Features {
355360
}
356361
}
357362

363+
const EXPLAIN_BOX_SYNTAX: &'static str =
364+
"box expression syntax is experimental; you can call `Box::new` instead.";
365+
366+
const EXPLAIN_PLACEMENT_IN: &'static str =
367+
"placement-in expression syntax is experimental and subject to change.";
368+
369+
pub fn check_for_box_syntax(f: Option<&Features>, diag: &SpanHandler, span: Span) {
370+
if let Some(&Features { allow_box: true, .. }) = f {
371+
return;
372+
}
373+
emit_feature_err(diag, "box_syntax", span, EXPLAIN_BOX_SYNTAX);
374+
}
375+
376+
pub fn check_for_placement_in(f: Option<&Features>, diag: &SpanHandler, span: Span) {
377+
if let Some(&Features { allow_placement_in: true, .. }) = f {
378+
return;
379+
}
380+
emit_feature_err(diag, "placement_in_syntax", span, EXPLAIN_PLACEMENT_IN);
381+
}
382+
358383
struct Context<'a> {
359384
features: Vec<&'static str>,
360385
span_handler: &'a SpanHandler,
@@ -363,6 +388,11 @@ struct Context<'a> {
363388
}
364389

365390
impl<'a> Context<'a> {
391+
fn enable_feature(&mut self, feature: &'static str) {
392+
debug!("enabling feature: {}", feature);
393+
self.features.push(feature);
394+
}
395+
366396
fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
367397
let has_feature = self.has_feature(feature);
368398
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", feature, span, has_feature);
@@ -482,6 +512,26 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
482512
fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
483513
self.context.check_attribute(attr);
484514
}
515+
516+
fn visit_expr(&mut self, e: &ast::Expr) {
517+
// Issue 22181: overloaded-`box` and placement-`in` are
518+
// implemented via a desugaring expansion, so their feature
519+
// gates go into MacroVisitor since that works pre-expansion.
520+
//
521+
// Issue 22234: we also check during expansion as well.
522+
// But we keep these checks as a pre-expansion check to catch
523+
// uses in e.g. conditionalized code.
524+
525+
if let ast::ExprBox(None, _) = e.node {
526+
self.context.gate_feature("box_syntax", e.span, EXPLAIN_BOX_SYNTAX);
527+
}
528+
529+
if let ast::ExprBox(Some(_), _) = e.node {
530+
self.context.gate_feature("placement_in_syntax", e.span, EXPLAIN_PLACEMENT_IN);
531+
}
532+
533+
visit::walk_expr(self, e);
534+
}
485535
}
486536

487537
struct PostExpansionVisitor<'a> {
@@ -647,12 +697,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
647697

648698
fn visit_expr(&mut self, e: &ast::Expr) {
649699
match e.node {
650-
ast::ExprBox(..) | ast::ExprUnary(ast::UnOp::UnUniq, _) => {
651-
self.gate_feature("box_syntax",
652-
e.span,
653-
"box expression syntax is experimental; \
654-
you can call `Box::new` instead.");
655-
}
656700
ast::ExprLit(ref lit) => {
657701
match lit.node {
658702
ast::LitInt(_, ty) => {
@@ -754,10 +798,10 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
754798
match KNOWN_FEATURES.iter()
755799
.find(|& &(n, _, _)| name == n) {
756800
Some(&(name, _, Active)) => {
757-
cx.features.push(name);
801+
cx.enable_feature(name);
758802
}
759803
Some(&(name, _, Deprecated)) => {
760-
cx.features.push(name);
804+
cx.enable_feature(name);
761805
span_handler.span_warn(
762806
mi.span,
763807
"feature is deprecated and will only be available \
@@ -794,6 +838,8 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
794838
allow_trace_macros: cx.has_feature("trace_macros"),
795839
allow_internal_unstable: cx.has_feature("allow_internal_unstable"),
796840
allow_custom_derive: cx.has_feature("custom_derive"),
841+
allow_placement_in: cx.has_feature("placement_in_syntax"),
842+
allow_box: cx.has_feature("box_syntax"),
797843
old_orphan_check: cx.has_feature("old_orphan_check"),
798844
simd_ffi: cx.has_feature("simd_ffi"),
799845
unmarked_api: cx.has_feature("unmarked_api"),

src/test/compile-fail/feature-gate-box-expr.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ fn main() {
1717
let x = box () 'c'; //~ ERROR box expression syntax is experimental
1818
println!("x: {}", x);
1919

20-
let x = box (HEAP) 'c'; //~ ERROR box expression syntax is experimental
20+
let x = box (HEAP) 'c'; //~ ERROR placement-in expression syntax is experimental
21+
println!("x: {}", x);
22+
23+
let x = in HEAP { 'c' }; //~ ERROR placement-in expression syntax is experimental
2124
println!("x: {}", x);
2225
}
2326

0 commit comments

Comments
 (0)