]> git.lizzy.rs Git - rust.git/commitdiff
only set non-ADT derive error once per attribute, not per trait
authorZack M. Davis <code@zackmdavis.net>
Wed, 23 Aug 2017 02:22:52 +0000 (19:22 -0700)
committerZack M. Davis <code@zackmdavis.net>
Fri, 22 Sep 2017 04:20:23 +0000 (21:20 -0700)
A slight eccentricity of this change is that now non-ADT-derive errors prevent
derive-macro-not-found errors from surfacing (see changes to the
gating-of-derive compile-fail tests).

Resolves #43927.

src/libsyntax/ext/expand.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/test/compile-fail/feature-gate/issue-43106-gating-of-derive-2.rs
src/test/compile-fail/feature-gate/issue-43106-gating-of-derive.rs
src/test/ui/span/issue-43927-non-ADT-derive.rs [new file with mode: 0644]
src/test/ui/span/issue-43927-non-ADT-derive.stderr [new file with mode: 0644]

index de9c085cc78177e62f24198c68152e0eca80b708..3a1b93425307e18715f77e9d0e88d28bec144a55 100644 (file)
@@ -282,6 +282,24 @@ fn expand(&mut self, expansion: Expansion) -> Expansion {
                     let expansion = self.expand_invoc(invoc, ext);
                     self.collect_invocations(expansion, &[])
                 } else if let InvocationKind::Attr { attr: None, traits, item } = invoc.kind {
+                    let derive_allowed = match item {
+                        Annotatable::Item(ref item) => match item.node {
+                            ast::ItemKind::Struct(..) |
+                            ast::ItemKind::Enum(..) |
+                            ast::ItemKind::Union(..) => true,
+                            _ => false,
+                        },
+                        _ => false,
+                    };
+                    if !derive_allowed {
+                        let span = item.attrs().iter()
+                            .find(|attr| attr.check_name("derive"))
+                            .expect("`derive` attribute should exist").span;
+                        self.cx.span_err(span,
+                                         "`derive` may only be applied to structs, enums \
+                                          and unions");
+                    }
+
                     let item = item
                         .map_attrs(|mut attrs| { attrs.retain(|a| a.path != "derive"); attrs });
                     let item_with_markers =
index d701810e2e9f2fd9b025ae7db0c4326038beb8d4..5c1ca19d635f7dc865e94d51f98f1df19cda7216 100644 (file)
@@ -428,8 +428,9 @@ pub fn expand_ext(&self,
                         }
                     }
                     _ => {
-                        cx.span_err(mitem.span,
-                                    "`derive` may only be applied to structs, enums and unions");
+                        // Non-ADT derive is an error, but it should have been
+                        // set earlier; see
+                        // libsyntax/ext/expand.rs:MacroExpander::expand()
                         return;
                     }
                 };
@@ -448,8 +449,10 @@ pub fn expand_ext(&self,
                 push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
             }
             _ => {
-                cx.span_err(mitem.span,
-                            "`derive` may only be applied to structs and enums");
+                // Non-Item derive is an error, but it should have been
+                // set earlier; see
+                // libsyntax/ext/expand.rs:MacroExpander::expand()
+                return;
             }
         }
     }
index be82d0a5f6dd892a49ea8ec03d5ec975c2049452..2dbc6cb140db3f957c01f288516fefdc6f6e72b6 100644 (file)
@@ -8,23 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// `#![derive]` is interpreted (and raises errors) when it occurs at
-// contexts other than ADT definitions. This test checks cases where
-// the derive-macro does not exist.
+// This test checks cases where the derive-macro does not exist.
 
-#![derive(x3300)]
-//~^ ERROR cannot find derive macro `x3300` in this scope
-
-#[derive(x3300)]
-//~^ ERROR cannot find derive macro `x3300` in this scope
 mod derive {
-    mod inner { #![derive(x3300)] }
-    //~^ ERROR cannot find derive macro `x3300` in this scope
-
-    #[derive(x3300)]
-    //~^ ERROR cannot find derive macro `x3300` in this scope
-    fn derive() { }
-
     #[derive(x3300)]
     //~^ ERROR cannot find derive macro `x3300` in this scope
     union U { f: i32 }
@@ -36,12 +22,4 @@ enum E { }
     #[derive(x3300)]
     //~^ ERROR cannot find derive macro `x3300` in this scope
     struct S;
-
-    #[derive(x3300)]
-    //~^ ERROR cannot find derive macro `x3300` in this scope
-    type T = S;
-
-    #[derive(x3300)]
-    //~^ ERROR cannot find derive macro `x3300` in this scope
-    impl S { }
 }
index 41c3d0ef561380b708e118065784f3b119f2784e..e5293ebb94ddc8c0161a9147737efdd3385e473e 100644 (file)
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// `#![derive]` is interpreted (and raises errors) when it occurs at
-// contexts other than ADT definitions. This test checks cases where
-// the derive-macro exists.
+// `#![derive]` raises errors when it occurs at contexts other than ADT
+// definitions.
 
 #![derive(Debug)]
 //~^ ERROR `derive` may only be applied to structs, enums and unions
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.rs b/src/test/ui/span/issue-43927-non-ADT-derive.rs
new file mode 100644 (file)
index 0000000..cf2a4b8
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+
+#![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+struct DerivedOn;
+
+fn main() {}
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.stderr b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
new file mode 100644 (file)
index 0000000..4cfbb6d
--- /dev/null
@@ -0,0 +1,8 @@
+error: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-43927-non-ADT-derive.rs:13:1
+   |
+13 | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+