@@ -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 } ;
@@ -229,6 +229,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
229
229
module. directory . pop ( ) ;
230
230
self . cx . root_path = module. directory . clone ( ) ;
231
231
self . cx . current_expansion . module = Rc :: new ( module) ;
232
+ self . cx . current_expansion . crate_span = Some ( krate. span ) ;
232
233
233
234
let orig_mod_span = krate. module . inner ;
234
235
@@ -531,11 +532,36 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
531
532
let path = & mac. node . path ;
532
533
533
534
let ident = ident. unwrap_or_else ( || keywords:: Invalid . ident ( ) ) ;
534
- let validate_and_set_expn_info = |def_site_span,
535
+ let validate_and_set_expn_info = |this : & mut Self , // arg instead of capture
536
+ def_site_span : Option < Span > ,
535
537
allow_internal_unstable,
536
- allow_internal_unsafe| {
538
+ allow_internal_unsafe,
539
+ // can't infer this type
540
+ unstable_feature : Option < ( Symbol , u32 ) > | {
541
+
542
+ // feature-gate the macro invocation
543
+ if let Some ( ( feature, issue) ) = unstable_feature {
544
+ let crate_span = this. cx . current_expansion . crate_span . unwrap ( ) ;
545
+ // don't stability-check macros in the same crate
546
+ // (the only time this is null is for syntax extensions registered as macros)
547
+ if def_site_span. map_or ( false , |def_span| !crate_span. contains ( def_span) )
548
+ && !span. allows_unstable ( ) && this. cx . ecfg . features . map_or ( true , |feats| {
549
+ // macro features will count as lib features
550
+ !feats. declared_lib_features . iter ( ) . any ( |& ( feat, _) | feat == feature)
551
+ } ) {
552
+ let explain = format ! ( "macro {}! is unstable" , path) ;
553
+ emit_feature_err ( this. cx . parse_sess , & * feature. as_str ( ) , span,
554
+ GateIssue :: Library ( Some ( issue) ) , & explain) ;
555
+ this. cx . trace_macros_diag ( ) ;
556
+ return Err ( kind. dummy ( span) ) ;
557
+ }
558
+ }
559
+
537
560
if ident. name != keywords:: Invalid . name ( ) {
538
- return Err ( format ! ( "macro {}! expects no ident argument, given '{}'" , path, ident) ) ;
561
+ let msg = format ! ( "macro {}! expects no ident argument, given '{}'" , path, ident) ;
562
+ this. cx . span_err ( path. span , & msg) ;
563
+ this. cx . trace_macros_diag ( ) ;
564
+ return Err ( kind. dummy ( span) ) ;
539
565
}
540
566
mark. set_expn_info ( ExpnInfo {
541
567
call_site : span,
@@ -551,11 +577,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
551
577
552
578
let opt_expanded = match * ext {
553
579
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)
580
+ if let Err ( dummy_span) = validate_and_set_expn_info ( self , def_span. map ( |( _, s) | s) ,
581
+ false , false , None ) {
582
+ dummy_span
559
583
} else {
560
584
kind. make_from ( expand. expand ( self . cx , span, mac. node . stream ( ) ) )
561
585
}
@@ -565,14 +589,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
565
589
ref expander,
566
590
def_info,
567
591
allow_internal_unstable,
568
- allow_internal_unsafe
592
+ allow_internal_unsafe,
593
+ unstable_feature,
569
594
} => {
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)
595
+ if let Err ( dummy_span) = validate_and_set_expn_info ( self , def_info. map ( |( _, s) | s) ,
596
+ allow_internal_unstable,
597
+ allow_internal_unsafe,
598
+ unstable_feature) {
599
+ dummy_span
576
600
} else {
577
601
kind. make_from ( expander. expand ( self . cx , span, mac. node . stream ( ) ) )
578
602
}
0 commit comments