@@ -18,7 +18,7 @@ use ext::base::*;
18
18
use ext:: derive:: { add_derived_markers, collect_derives} ;
19
19
use ext:: hygiene:: { Mark , SyntaxContext } ;
20
20
use ext:: placeholders:: { placeholder, PlaceholderExpander } ;
21
- use feature_gate:: { self , Features , is_builtin_attr} ;
21
+ use feature_gate:: { self , Features , GateIssue , is_builtin_attr, emit_feature_err } ;
22
22
use fold;
23
23
use fold:: * ;
24
24
use parse:: { DirectoryOwnership , PResult } ;
@@ -531,11 +531,33 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
531
531
let path = & mac. node . path ;
532
532
533
533
let ident = ident. unwrap_or_else ( || keywords:: Invalid . ident ( ) ) ;
534
- let validate_and_set_expn_info = |def_site_span,
534
+ let validate_and_set_expn_info = |self_ : & mut Self , // arg instead of capture
535
+ def_site_span,
535
536
allow_internal_unstable,
536
- allow_internal_unsafe| {
537
+ allow_internal_unsafe,
538
+ // can't infer this type
539
+ unstable_feature : Option < ( Symbol , u32 ) > | {
540
+
541
+ // feature-gate the macro invocation
542
+ if let Some ( ( feature, issue) ) = unstable_feature {
543
+ // only if the outer span doesn't allow unstable invocations
544
+ if !span. allows_unstable ( ) && self_. cx . ecfg . features . map_or ( true , |feats| {
545
+ // macro features will count as lib features
546
+ !feats. declared_lib_features . iter ( ) . any ( |& ( feat, _) | feat == feature)
547
+ } ) {
548
+ let explain = format ! ( "macro {}! is unstable" , path) ;
549
+ emit_feature_err ( self_. cx . parse_sess , & * feature. as_str ( ) , span,
550
+ GateIssue :: Library ( Some ( issue) ) , & explain) ;
551
+ self_. cx . trace_macros_diag ( ) ;
552
+ return Err ( kind. dummy ( span) ) ;
553
+ }
554
+ }
555
+
537
556
if ident. name != keywords:: Invalid . name ( ) {
538
- return Err ( format ! ( "macro {}! expects no ident argument, given '{}'" , path, ident) ) ;
557
+ let msg = format ! ( "macro {}! expects no ident argument, given '{}'" , path, ident) ;
558
+ self_. cx . span_err ( path. span , & msg) ;
559
+ self_. cx . trace_macros_diag ( ) ;
560
+ return Err ( kind. dummy ( span) ) ;
539
561
}
540
562
mark. set_expn_info ( ExpnInfo {
541
563
call_site : span,
@@ -551,11 +573,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
551
573
552
574
let opt_expanded = match * ext {
553
575
DeclMacro ( ref expand, def_span) => {
554
- if let Err ( msg) = validate_and_set_expn_info ( def_span. map ( |( _, s) | s) ,
555
- false , false ) {
556
- self . cx . span_err ( path. span , & msg) ;
557
- self . cx . trace_macros_diag ( ) ;
558
- kind. dummy ( span)
576
+ if let Err ( dummy_span) = validate_and_set_expn_info ( self , def_span. map ( |( _, s) | s) ,
577
+ false , false , None ) {
578
+ dummy_span
559
579
} else {
560
580
kind. make_from ( expand. expand ( self . cx , span, mac. node . stream ( ) ) )
561
581
}
@@ -565,14 +585,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
565
585
ref expander,
566
586
def_info,
567
587
allow_internal_unstable,
568
- allow_internal_unsafe
588
+ allow_internal_unsafe,
589
+ unstable_feature,
569
590
} => {
570
- if let Err ( msg) = validate_and_set_expn_info ( def_info. map ( |( _, s) | s) ,
571
- allow_internal_unstable,
572
- allow_internal_unsafe) {
573
- self . cx . span_err ( path. span , & msg) ;
574
- self . cx . trace_macros_diag ( ) ;
575
- kind. dummy ( span)
591
+ if let Err ( dummy_span) = validate_and_set_expn_info ( self , def_info. map ( |( _, s) | s) ,
592
+ allow_internal_unstable,
593
+ allow_internal_unsafe,
594
+ unstable_feature) {
595
+ dummy_span
576
596
} else {
577
597
kind. make_from ( expander. expand ( self . cx , span, mac. node . stream ( ) ) )
578
598
}
0 commit comments