diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 588e275455af..6c3f96bbec64 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1490,8 +1490,27 @@ impl LintPass for Stability { } fn check_expr(&mut self, cx: &Context, e: &ast::Expr) { - // if the expression was produced by a macro expansion, - if e.span.expn_id != NO_EXPANSION { return } + // skip if `e` is not from macro arguments + let skip = cx.tcx.sess.codemap().with_expn_info(e.span.expn_id, |expninfo| { + match expninfo { + Some(ref info) => { + if info.call_site.expn_id != NO_EXPANSION || + !( e.span.lo > info.call_site.lo && e.span.hi < info.call_site.hi ) { + // This code is not from the arguments, + // or this macro call was generated by an other macro + // We can't handle it. + true + } else if info.callee.span.is_none() { + // We don't want to mess with compiler builtins. + true + } else { + false + } + }, + _ => { false } + } + }); + if skip { return; } let id = match e.node { ast::ExprPath(..) | ast::ExprStruct(..) => { diff --git a/src/test/auxiliary/lint_stability.rs b/src/test/auxiliary/lint_stability.rs index b0090c63969a..bae86f04b23b 100644 --- a/src/test/auxiliary/lint_stability.rs +++ b/src/test/auxiliary/lint_stability.rs @@ -181,3 +181,13 @@ pub struct LockedTupleStruct(pub int); macro_rules! macro_test( () => (deprecated()); ) + +#[macro_export] +macro_rules! macro_test_arg( + ($func:expr) => ($func); +) + +#[macro_export] +macro_rules! macro_test_arg_nested( + ($func:ident) => (macro_test_arg!($func())); +) diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index f5cee22ac2c0..6a36e2707404 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -109,12 +109,14 @@ mod cross_crate { let _ = FrozenTupleStruct (1); let _ = LockedTupleStruct (1); - // At the moment, the following just checks that the stability - // level of expanded code does not trigger the - // lint. Eventually, we will want to lint the contents of the + // At the moment, the lint checker only checks stability in + // in the arguments of macros. + // Eventually, we will want to lint the contents of the // macro in the module *defining* it. Also, stability levels // on macros themselves are not yet linted. macro_test!(); + macro_test_arg!(deprecated_text()); //~ ERROR use of deprecated item: text + macro_test_arg_nested!(deprecated_text); } fn test_method_param(foo: F) {