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
@ -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)]
|
||||
|
@ -234,6 +234,7 @@
|
||||
#![feature(no_std)]
|
||||
#![feature(oom)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(placement_in_syntax)]
|
||||
#![feature(rand)]
|
||||
#![feature(raw)]
|
||||
#![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 {
|
||||
|
||||
// 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;
|
||||
|
||||
|
@ -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"),
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user