@@ -81,6 +81,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Status)] = &[
81
81
( "visible_private_types" , "1.0.0" , Active ) ,
82
82
( "slicing_syntax" , "1.0.0" , Accepted ) ,
83
83
( "box_syntax" , "1.0.0" , Active ) ,
84
+ ( "placement_in_syntax" , "1.0.0" , Active ) ,
84
85
( "on_unimplemented" , "1.0.0" , Active ) ,
85
86
( "simd_ffi" , "1.0.0" , Active ) ,
86
87
@@ -324,6 +325,8 @@ pub struct Features {
324
325
pub allow_trace_macros : bool ,
325
326
pub allow_internal_unstable : bool ,
326
327
pub allow_custom_derive : bool ,
328
+ pub allow_placement_in : bool ,
329
+ pub allow_box : bool ,
327
330
pub old_orphan_check : bool ,
328
331
pub simd_ffi : bool ,
329
332
pub unmarked_api : bool ,
@@ -346,6 +349,8 @@ impl Features {
346
349
allow_trace_macros : false ,
347
350
allow_internal_unstable : false ,
348
351
allow_custom_derive : false ,
352
+ allow_placement_in : false ,
353
+ allow_box : false ,
349
354
old_orphan_check : false ,
350
355
simd_ffi : false ,
351
356
unmarked_api : false ,
@@ -355,6 +360,26 @@ impl Features {
355
360
}
356
361
}
357
362
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
+
358
383
struct Context < ' a > {
359
384
features : Vec < & ' static str > ,
360
385
span_handler : & ' a SpanHandler ,
@@ -363,6 +388,11 @@ struct Context<'a> {
363
388
}
364
389
365
390
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
+
366
396
fn gate_feature ( & self , feature : & str , span : Span , explain : & str ) {
367
397
let has_feature = self . has_feature ( feature) ;
368
398
debug ! ( "gate_feature(feature = {:?}, span = {:?}); has? {}" , feature, span, has_feature) ;
@@ -482,6 +512,26 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
482
512
fn visit_attribute ( & mut self , attr : & ' v ast:: Attribute ) {
483
513
self . context . check_attribute ( attr) ;
484
514
}
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
+ }
485
535
}
486
536
487
537
struct PostExpansionVisitor < ' a > {
@@ -647,12 +697,6 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
647
697
648
698
fn visit_expr ( & mut self , e : & ast:: Expr ) {
649
699
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
- }
656
700
ast:: ExprLit ( ref lit) => {
657
701
match lit. node {
658
702
ast:: LitInt ( _, ty) => {
@@ -754,10 +798,10 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::C
754
798
match KNOWN_FEATURES . iter ( )
755
799
. find ( |& & ( n, _, _) | name == n) {
756
800
Some ( & ( name, _, Active ) ) => {
757
- cx. features . push ( name) ;
801
+ cx. enable_feature ( name) ;
758
802
}
759
803
Some ( & ( name, _, Deprecated ) ) => {
760
- cx. features . push ( name) ;
804
+ cx. enable_feature ( name) ;
761
805
span_handler. span_warn (
762
806
mi. span ,
763
807
"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
794
838
allow_trace_macros : cx. has_feature ( "trace_macros" ) ,
795
839
allow_internal_unstable : cx. has_feature ( "allow_internal_unstable" ) ,
796
840
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" ) ,
797
843
old_orphan_check : cx. has_feature ( "old_orphan_check" ) ,
798
844
simd_ffi : cx. has_feature ( "simd_ffi" ) ,
799
845
unmarked_api : cx. has_feature ( "unmarked_api" ) ,
0 commit comments