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.
This commit is contained in:
parent
d79bbbc4ef
commit
b325e4f28e
5 changed files with 70 additions and 2 deletions
|
@ -82,8 +82,10 @@
|
||||||
#![feature(no_std)]
|
#![feature(no_std)]
|
||||||
#![feature(nonzero)]
|
#![feature(nonzero)]
|
||||||
#![feature(optin_builtin_traits)]
|
#![feature(optin_builtin_traits)]
|
||||||
|
#![feature(placement_in_syntax)]
|
||||||
#![feature(raw)]
|
#![feature(raw)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
|
#![feature(placement_in_syntax)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
#![feature(unique)]
|
#![feature(unique)]
|
||||||
#![feature(unsafe_no_drop_flag, filling_drop)]
|
#![feature(unsafe_no_drop_flag, filling_drop)]
|
||||||
|
|
|
@ -234,6 +234,7 @@
|
||||||
#![feature(no_std)]
|
#![feature(no_std)]
|
||||||
#![feature(oom)]
|
#![feature(oom)]
|
||||||
#![feature(optin_builtin_traits)]
|
#![feature(optin_builtin_traits)]
|
||||||
|
#![feature(placement_in_syntax)]
|
||||||
#![feature(rand)]
|
#![feature(rand)]
|
||||||
#![feature(raw)]
|
#![feature(raw)]
|
||||||
#![feature(reflect_marker)]
|
#![feature(reflect_marker)]
|
||||||
|
|
|
@ -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 {
|
return e.and_then(|ast::Expr {id, node, span}| match node {
|
||||||
|
|
||||||
// expr_mac should really be expr_ext or something; it's the
|
// 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)
|
// 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 value_span = value_expr.span;
|
||||||
let placer_span = placer.span;
|
let placer_span = placer.span;
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
|
||||||
("visible_private_types", "1.0.0", Active),
|
("visible_private_types", "1.0.0", Active),
|
||||||
("slicing_syntax", "1.0.0", Accepted),
|
("slicing_syntax", "1.0.0", Accepted),
|
||||||
("box_syntax", "1.0.0", Active),
|
("box_syntax", "1.0.0", Active),
|
||||||
|
("placement_in_syntax", "1.0.0", Active),
|
||||||
("pushpop_unsafe", "1.2.0", Active),
|
("pushpop_unsafe", "1.2.0", Active),
|
||||||
("on_unimplemented", "1.0.0", Active),
|
("on_unimplemented", "1.0.0", Active),
|
||||||
("simd_ffi", "1.0.0", Active),
|
("simd_ffi", "1.0.0", Active),
|
||||||
|
@ -326,6 +327,8 @@ pub struct Features {
|
||||||
pub allow_trace_macros: bool,
|
pub allow_trace_macros: bool,
|
||||||
pub allow_internal_unstable: bool,
|
pub allow_internal_unstable: bool,
|
||||||
pub allow_custom_derive: bool,
|
pub allow_custom_derive: bool,
|
||||||
|
pub allow_placement_in: bool,
|
||||||
|
pub allow_box: bool,
|
||||||
pub allow_pushpop_unsafe: bool,
|
pub allow_pushpop_unsafe: bool,
|
||||||
pub simd_ffi: bool,
|
pub simd_ffi: bool,
|
||||||
pub unmarked_api: bool,
|
pub unmarked_api: bool,
|
||||||
|
@ -350,6 +353,8 @@ impl Features {
|
||||||
allow_trace_macros: false,
|
allow_trace_macros: false,
|
||||||
allow_internal_unstable: false,
|
allow_internal_unstable: false,
|
||||||
allow_custom_derive: false,
|
allow_custom_derive: false,
|
||||||
|
allow_placement_in: false,
|
||||||
|
allow_box: false,
|
||||||
allow_pushpop_unsafe: false,
|
allow_pushpop_unsafe: false,
|
||||||
simd_ffi: false,
|
simd_ffi: false,
|
||||||
unmarked_api: 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) {
|
pub fn check_for_pushpop_syntax(f: Option<&Features>, diag: &SpanHandler, span: Span) {
|
||||||
if let Some(&Features { allow_pushpop_unsafe: true, .. }) = f {
|
if let Some(&Features { allow_pushpop_unsafe: true, .. }) = f {
|
||||||
return;
|
return;
|
||||||
|
@ -376,6 +404,11 @@ struct Context<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> 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) {
|
fn gate_feature(&self, feature: &str, span: Span, explain: &str) {
|
||||||
let has_feature = self.has_feature(feature);
|
let has_feature = self.has_feature(feature);
|
||||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", feature, span, has_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) {
|
fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
|
||||||
self.context.check_attribute(attr, true);
|
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> {
|
struct PostExpansionVisitor<'a> {
|
||||||
|
@ -764,7 +817,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
|
||||||
match KNOWN_FEATURES.iter()
|
match KNOWN_FEATURES.iter()
|
||||||
.find(|& &(n, _, _)| name == n) {
|
.find(|& &(n, _, _)| name == n) {
|
||||||
Some(&(name, _, Active)) => {
|
Some(&(name, _, Active)) => {
|
||||||
cx.features.push(name);
|
cx.enable_feature(name);
|
||||||
}
|
}
|
||||||
Some(&(_, _, Removed)) => {
|
Some(&(_, _, Removed)) => {
|
||||||
span_handler.span_err(mi.span, "feature has been 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_trace_macros: cx.has_feature("trace_macros"),
|
||||||
allow_internal_unstable: cx.has_feature("allow_internal_unstable"),
|
allow_internal_unstable: cx.has_feature("allow_internal_unstable"),
|
||||||
allow_custom_derive: cx.has_feature("custom_derive"),
|
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"),
|
allow_pushpop_unsafe: cx.has_feature("pushpop_unsafe"),
|
||||||
simd_ffi: cx.has_feature("simd_ffi"),
|
simd_ffi: cx.has_feature("simd_ffi"),
|
||||||
unmarked_api: cx.has_feature("unmarked_api"),
|
unmarked_api: cx.has_feature("unmarked_api"),
|
||||||
|
|
|
@ -17,6 +17,9 @@ fn main() {
|
||||||
let x = box () 'c'; //~ ERROR box expression syntax is experimental
|
let x = box () 'c'; //~ ERROR box expression syntax is experimental
|
||||||
println!("x: {}", x);
|
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);
|
println!("x: {}", x);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue