@@ -41,7 +41,7 @@ use lint::builtin::BuiltinLintDiagnostics;
41
41
use session:: { Session , DiagnosticMessageId } ;
42
42
use std:: hash;
43
43
use syntax:: ast;
44
- use syntax:: codemap:: MultiSpan ;
44
+ use syntax:: codemap:: { MultiSpan , ExpnFormat } ;
45
45
use syntax:: edition:: Edition ;
46
46
use syntax:: symbol:: Symbol ;
47
47
use syntax:: visit as ast_visit;
@@ -54,8 +54,6 @@ pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
54
54
check_crate, check_ast_crate,
55
55
FutureIncompatibleInfo , BufferedEarlyLint } ;
56
56
57
- use codemap:: { ExpnFormat , ExpnInfo , Span } ;
58
-
59
57
/// Specification of a single lint.
60
58
#[ derive( Copy , Clone , Debug ) ]
61
59
pub struct Lint {
@@ -570,6 +568,22 @@ pub fn struct_lint_level<'a>(sess: &'a Session,
570
568
future_incompatible. reference) ;
571
569
err. warn ( & explanation) ;
572
570
err. note ( & citation) ;
571
+
572
+ // If this lint is *not* a future incompatibility warning then we want to be
573
+ // sure to not be too noisy in some situations. If this code originates in a
574
+ // foreign macro, aka something that this crate did not itself author, then
575
+ // it's likely that there's nothing this crate can do about it. We probably
576
+ // want to skip the lint entirely.
577
+ //
578
+ // For some lints though (like unreachable code) there's clear actionable
579
+ // items to take care of (delete the macro invocation). As a result we have
580
+ // a few lints we whitelist here for allowing a lint even though it's in a
581
+ // foreign macro invocation.
582
+ } else if lint_id != LintId :: of ( builtin:: UNREACHABLE_CODE ) &&
583
+ lint_id != LintId :: of ( builtin:: DEPRECATED ) {
584
+ if err. span . primary_spans ( ) . iter ( ) . any ( |s| in_external_macro ( sess, * s) ) {
585
+ err. cancel ( ) ;
586
+ }
573
587
}
574
588
575
589
return err
@@ -672,29 +686,31 @@ pub fn provide(providers: &mut Providers) {
672
686
providers. lint_levels = lint_levels;
673
687
}
674
688
675
- pub fn in_external_macro < ' a , T : LintContext < ' a > > ( cx : & T , span : Span ) -> bool {
676
- /// Invokes `in_macro` with the expansion info of the given span slightly
677
- /// heavy, try to use
678
- /// this after other checks have already happened.
679
- fn in_macro_ext < ' a , T : LintContext < ' a > > ( cx : & T , info : & ExpnInfo ) -> bool {
680
- // no ExpnInfo = no macro
681
- if let ExpnFormat :: MacroAttribute ( ..) = info. callee . format {
682
- // these are all plugins
683
- return true ;
684
- }
685
- // no span for the callee = external macro
686
- info. callee . span . map_or ( true , |span| {
687
- // no snippet = external macro or compiler-builtin expansion
688
- cx. sess ( )
689
- . codemap ( )
690
- . span_to_snippet ( span)
691
- . ok ( )
692
- . map_or ( true , |code| !code. starts_with ( "macro_rules" ) )
693
- } )
689
+ /// Returns whether `span` originates in a foreign crate's external macro.
690
+ ///
691
+ /// This is used to test whether a lint should be entirely aborted above.
692
+ pub fn in_external_macro ( sess : & Session , span : Span ) -> bool {
693
+ let info = match span. ctxt ( ) . outer ( ) . expn_info ( ) {
694
+ Some ( info) => info,
695
+ // no ExpnInfo means this span doesn't come from a macro
696
+ None => return false ,
697
+ } ;
698
+
699
+ match info. format {
700
+ ExpnFormat :: MacroAttribute ( ..) => return true , // definitely a plugin
701
+ ExpnFormat :: CompilerDesugaring ( _) => return true , // well, it's "external"
702
+ ExpnFormat :: MacroBang ( ..) => { } // check below
694
703
}
695
704
696
- span. ctxt ( )
697
- . outer ( )
698
- . expn_info ( )
699
- . map_or ( false , |info| in_macro_ext ( cx, & info) )
705
+ let def_site = match info. def_site {
706
+ Some ( span) => span,
707
+ // no span for the def_site means it's an external macro
708
+ None => return true ,
709
+ } ;
710
+
711
+ match sess. codemap ( ) . span_to_snippet ( def_site) {
712
+ Ok ( code) => !code. starts_with ( "macro_rules" ) ,
713
+ // no snippet = external macro or compiler-builtin expansion
714
+ Err ( _) => true ,
715
+ }
700
716
}
0 commit comments