Skip to content

Commit dd0808d

Browse files
Dylan-DPCalexcrichton
authored andcommitted
added function to check if lints belong to an external macro
1 parent 4bff385 commit dd0808d

File tree

3 files changed

+53
-2
lines changed

3 files changed

+53
-2
lines changed

src/librustc/lint/context.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use self::TargetLint::*;
2929
use std::slice;
3030
use rustc_data_structures::sync::{RwLock, ReadGuard};
3131
use lint::{EarlyLintPassObject, LateLintPassObject};
32-
use lint::{Level, Lint, LintId, LintPass, LintBuffer};
32+
use lint::{self, Level, Lint, LintId, LintPass, LintBuffer};
3333
use lint::builtin::BuiltinLintDiagnostics;
3434
use lint::levels::{LintLevelSets, LintLevelsBuilder};
3535
use middle::privacy::AccessLevels;
@@ -468,7 +468,14 @@ pub trait LintContext<'tcx>: Sized {
468468

469469
/// Emit a lint at the appropriate level, for a particular span.
470470
fn span_lint<S: Into<MultiSpan>>(&self, lint: &'static Lint, span: S, msg: &str) {
471-
self.lookup_and_emit(lint, Some(span), msg);
471+
match self.lints().future_incompatible(LintId::of(lint)) {
472+
Some(_) => self.lookup_and_emit(lint, Some(span), msg),
473+
None => {
474+
if !lint::in_external_macro(lint, span) {
475+
self.lookup_and_emit(lint, Some(span), msg);
476+
}
477+
}
478+
}
472479
}
473480

474481
fn struct_span_lint<S: Into<MultiSpan>>(&self,

src/librustc/lint/mod.rs

+29
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
5454
check_crate, check_ast_crate,
5555
FutureIncompatibleInfo, BufferedEarlyLint};
5656

57+
use codemap::{ExpnFormat, ExpnInfo, Span };
58+
5759
/// Specification of a single lint.
5860
#[derive(Copy, Clone, Debug)]
5961
pub struct Lint {
@@ -669,3 +671,30 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> {
669671
pub fn provide(providers: &mut Providers) {
670672
providers.lint_levels = lint_levels;
671673
}
674+
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+
})
694+
}
695+
696+
span.ctxt()
697+
.outer()
698+
.expn_info()
699+
.map_or(false, |info| in_macro_ext(cx, &info))
700+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
#![feature(nll)]
11+
#![deny(elided_lifetime_in_path)]
12+
13+
fn main() {
14+
format!("foo {}", 22)
15+
}

0 commit comments

Comments
 (0)