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 =
}
}
_ => {
- 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;
}
};
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;
}
}
}
// 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 }
#[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 { }
}
// 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
--- /dev/null
+// 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() {}
--- /dev/null
+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
+