let name = unwrap_or!(attrs[i].name(), continue);
if name == "derive" {
- let result = attrs[i].parse_list(&self.session.parse_sess,
- |parser| parser.parse_path(PathStyle::Mod));
+ let result = attrs[i].parse_list(&self.session.parse_sess, |parser| {
+ parser.parse_path_allowing_meta(PathStyle::Mod)
+ });
+
let mut traits = match result {
Ok(traits) => traits,
Err(mut e) => {
return true;
}
- match attr.parse_list(cx.parse_sess, |parser| parser.parse_path(PathStyle::Mod)) {
+ match attr.parse_list(cx.parse_sess,
+ |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
Ok(ref traits) if traits.is_empty() => {
cx.span_warn(attr.span, "empty trait list in `derive`");
false
})
}
+ /// Like `parse_path`, but also supports parsing `Word` meta items into paths for back-compat.
+ /// This is used when parsing derive macro paths in `#[derive]` attributes.
+ pub fn parse_path_allowing_meta(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
+ let meta_ident = match self.token {
+ token::Interpolated(ref nt) => match **nt {
+ token::NtMeta(ref meta) => match meta.node {
+ ast::MetaItemKind::Word => Some(ast::Ident::with_empty_ctxt(meta.name)),
+ _ => None,
+ },
+ _ => None,
+ },
+ _ => None,
+ };
+ if let Some(ident) = meta_ident {
+ self.bump();
+ return Ok(ast::Path::from_ident(self.prev_span, ident));
+ }
+ self.parse_path(mode)
+ }
+
/// Examples:
/// - `a::b<T,U>::c<V,W>`
/// - `a::b<T,U>::c(V) -> W`
--- /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.
+
+macro_rules! m {
+ ($i:meta) => {
+ #[derive($i)]
+ struct S;
+ }
+}
+
+m!(Clone);
+
+fn main() {}