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