about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/lint/mod.rs17
-rw-r--r--src/librustc/middle/stability.rs5
-rw-r--r--src/test/ui/deprecation/derive_on_deprecated.rs9
-rw-r--r--src/test/ui/deprecation/derive_on_deprecated_forbidden.rs9
4 files changed, 38 insertions, 2 deletions
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index c01b0ae2ccc..86a2d7af955 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -833,7 +833,8 @@ pub fn provide(providers: &mut Providers<'_>) {
 
 /// Returns whether `span` originates in a foreign crate's external macro.
 ///
-/// This is used to test whether a lint should be entirely aborted above.
+/// This is used to test whether a lint should not even begin to figure out whether it should
+/// be reported on the current node.
 pub fn in_external_macro(sess: &Session, span: Span) -> bool {
     let info = match span.ctxt().outer().expn_info() {
         Some(info) => info,
@@ -859,3 +860,17 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool {
         Err(_) => true,
     }
 }
+
+/// Returns whether `span` originates in a derive macro's expansion
+pub fn in_derive_expansion(span: Span) -> bool {
+    let info = match span.ctxt().outer().expn_info() {
+        Some(info) => info,
+        // no ExpnInfo means this span doesn't come from a macro
+        None => return false,
+    };
+
+    match info.format {
+        ExpnFormat::MacroAttribute(symbol) => symbol.as_str().starts_with("derive("),
+        _ => false,
+    }
+}
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 0a2a375e1b2..6c24cb0a7b0 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -3,7 +3,7 @@
 
 pub use self::StabilityLevel::*;
 
-use crate::lint::{self, Lint};
+use crate::lint::{self, Lint, in_derive_expansion};
 use crate::hir::{self, Item, Generics, StructField, Variant, HirId};
 use crate::hir::def::Def;
 use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
@@ -561,6 +561,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                suggestion: Option<Symbol>,
                                message: &str,
                                lint: &'static Lint| {
+            if in_derive_expansion(span) {
+                return;
+            }
             let msg = if let Some(note) = note {
                 format!("{}: {}", message, note)
             } else {
diff --git a/src/test/ui/deprecation/derive_on_deprecated.rs b/src/test/ui/deprecation/derive_on_deprecated.rs
new file mode 100644
index 00000000000..4980a7f5aa3
--- /dev/null
+++ b/src/test/ui/deprecation/derive_on_deprecated.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+#![deny(deprecated)]
+
+#[deprecated = "oh no"]
+#[derive(Default)]
+struct X;
+
+fn main() {}
diff --git a/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs b/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs
new file mode 100644
index 00000000000..235146bad9c
--- /dev/null
+++ b/src/test/ui/deprecation/derive_on_deprecated_forbidden.rs
@@ -0,0 +1,9 @@
+// compile-pass
+
+#![forbid(deprecated)]
+
+#[deprecated = "oh no"]
+#[derive(Default)]
+struct X;
+
+fn main() {}