@@ -80,6 +80,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
80
80
( "visible_private_types" , "1.0.0" , Active ) ,
81
81
( "slicing_syntax" , "1.0.0" , Accepted ) ,
82
82
( "box_syntax" , "1.0.0" , Active ) ,
83
+ ( "placement_in_syntax" , "1.0.0" , Active ) ,
83
84
( "pushpop_unsafe" , "1.2.0" , Active ) ,
84
85
( "on_unimplemented" , "1.0.0" , Active ) ,
85
86
( "simd_ffi" , "1.0.0" , Active ) ,
@@ -326,6 +327,8 @@ pub struct Features {
326
327
pub allow_trace_macros : bool ,
327
328
pub allow_internal_unstable : bool ,
328
329
pub allow_custom_derive : bool ,
330
+ pub allow_placement_in : bool ,
331
+ pub allow_box : bool ,
329
332
pub allow_pushpop_unsafe : bool ,
330
333
pub simd_ffi : bool ,
331
334
pub unmarked_api : bool ,
@@ -350,6 +353,8 @@ impl Features {
350
353
allow_trace_macros : false ,
351
354
allow_internal_unstable : false ,
352
355
allow_custom_derive : false ,
356
+ allow_placement_in : false ,
357
+ allow_box : false ,
353
358
allow_pushpop_unsafe : false ,
354
359
simd_ffi : false ,
355
360
unmarked_api : false ,
@@ -361,6 +366,29 @@ impl Features {
361
366
}
362
367
}
363
368
369
+ const EXPLAIN_BOX_SYNTAX : & ' static str =
370
+ "box expression syntax is experimental; you can call `Box::new` instead." ;
371
+
372
+ const EXPLAIN_PLACEMENT_IN : & ' static str =
373
+ "placement-in expression syntax is experimental and subject to change." ;
374
+
375
+ const EXPLAIN_PUSHPOP_UNSAFE : & ' static str =
376
+ "push/pop_unsafe macros are experimental and subject to change." ;
377
+
378
+ pub fn check_for_box_syntax ( f : Option < & Features > , diag : & SpanHandler , span : Span ) {
379
+ if let Some ( & Features { allow_box : true , .. } ) = f {
380
+ return ;
381
+ }
382
+ emit_feature_err ( diag, "box_syntax" , span, EXPLAIN_BOX_SYNTAX ) ;
383
+ }
384
+
385
+ pub fn check_for_placement_in ( f : Option < & Features > , diag : & SpanHandler , span : Span ) {
386
+ if let Some ( & Features { allow_placement_in : true , .. } ) = f {
387
+ return ;
388
+ }
389
+ emit_feature_err ( diag, "placement_in_syntax" , span, EXPLAIN_PLACEMENT_IN ) ;
390
+ }
391
+
364
392
pub fn check_for_pushpop_syntax ( f : Option < & Features > , diag : & SpanHandler , span : Span ) {
365
393
if let Some ( & Features { allow_pushpop_unsafe : true , .. } ) = f {
366
394
return ;
@@ -376,6 +404,11 @@ struct Context<'a> {
376
404
}
377
405
378
406
impl < ' a > Context < ' a > {
407
+ fn enable_feature ( & mut self , feature : & ' static str ) {
408
+ debug ! ( "enabling feature: {}" , feature) ;
409
+ self . features . push ( feature) ;
410
+ }
411
+
379
412
fn gate_feature ( & self , feature : & str , span : Span , explain : & str ) {
380
413
let has_feature = self . has_feature ( feature) ;
381
414
debug ! ( "gate_feature(feature = {:?}, span = {:?}); has? {}" , feature, span, has_feature) ;
@@ -498,6 +531,26 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
498
531
fn visit_attribute ( & mut self , attr : & ' v ast:: Attribute ) {
499
532
self . context . check_attribute ( attr, true ) ;
500
533
}
534
+
535
+ fn visit_expr ( & mut self , e : & ast:: Expr ) {
536
+ // Issue 22181: overloaded-`box` and placement-`in` are
537
+ // implemented via a desugaring expansion, so their feature
538
+ // gates go into MacroVisitor since that works pre-expansion.
539
+ //
540
+ // Issue 22234: we also check during expansion as well.
541
+ // But we keep these checks as a pre-expansion check to catch
542
+ // uses in e.g. conditionalized code.
543
+
544
+ if let ast:: ExprBox ( None , _) = e. node {
545
+ self . context . gate_feature ( "box_syntax" , e. span , EXPLAIN_BOX_SYNTAX ) ;
546
+ }
547
+
548
+ if let ast:: ExprBox ( Some ( _) , _) = e. node {
549
+ self . context . gate_feature ( "placement_in_syntax" , e. span , EXPLAIN_PLACEMENT_IN ) ;
550
+ }
551
+
552
+ visit:: walk_expr ( self , e) ;
553
+ }
501
554
}
502
555
503
556
struct PostExpansionVisitor < ' a > {
@@ -764,7 +817,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
764
817
match KNOWN_FEATURES . iter ( )
765
818
. find ( |& & ( n, _, _) | name == n) {
766
819
Some ( & ( name, _, Active ) ) => {
767
- cx. features . push ( name) ;
820
+ cx. enable_feature ( name) ;
768
821
}
769
822
Some ( & ( _, _, Removed ) ) => {
770
823
span_handler. span_err ( mi. span , "feature has been removed" ) ;
@@ -797,6 +850,8 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
797
850
allow_trace_macros : cx. has_feature ( "trace_macros" ) ,
798
851
allow_internal_unstable : cx. has_feature ( "allow_internal_unstable" ) ,
799
852
allow_custom_derive : cx. has_feature ( "custom_derive" ) ,
853
+ allow_placement_in : cx. has_feature ( "placement_in_syntax" ) ,
854
+ allow_box : cx. has_feature ( "box_syntax" ) ,
800
855
allow_pushpop_unsafe : cx. has_feature ( "pushpop_unsafe" ) ,
801
856
simd_ffi : cx. has_feature ( "simd_ffi" ) ,
802
857
unmarked_api : cx. has_feature ( "unmarked_api" ) ,
0 commit comments