Skip to content

Commit 6a9448b

Browse files
committed
Fix bug parsing #[derive] macro invocations.
1 parent 5309a3e commit 6a9448b

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

src/librustc_resolve/macros.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,10 @@ impl<'a> base::Resolver for Resolver<'a> {
222222
let name = unwrap_or!(attrs[i].name(), continue);
223223

224224
if name == "derive" {
225-
let result = attrs[i].parse_list(&self.session.parse_sess,
226-
|parser| parser.parse_path(PathStyle::Mod));
225+
let result = attrs[i].parse_list(&self.session.parse_sess, |parser| {
226+
parser.parse_path_allowing_meta(PathStyle::Mod)
227+
});
228+
227229
let mut traits = match result {
228230
Ok(traits) => traits,
229231
Err(mut e) => {

src/libsyntax/ext/derive.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec
2626
return true;
2727
}
2828

29-
match attr.parse_list(cx.parse_sess, |parser| parser.parse_path(PathStyle::Mod)) {
29+
match attr.parse_list(cx.parse_sess,
30+
|parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
3031
Ok(ref traits) if traits.is_empty() => {
3132
cx.span_warn(attr.span, "empty trait list in `derive`");
3233
false

src/libsyntax/parse/parser.rs

+20
Original file line numberDiff line numberDiff line change
@@ -1754,6 +1754,26 @@ impl<'a> Parser<'a> {
17541754
})
17551755
}
17561756

1757+
/// Like `parse_path`, but also supports parsing `Word` meta items into paths for back-compat.
1758+
/// This is used when parsing derive macro paths in `#[derive]` attributes.
1759+
pub fn parse_path_allowing_meta(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
1760+
let meta_ident = match self.token {
1761+
token::Interpolated(ref nt) => match **nt {
1762+
token::NtMeta(ref meta) => match meta.node {
1763+
ast::MetaItemKind::Word => Some(ast::Ident::with_empty_ctxt(meta.name)),
1764+
_ => None,
1765+
},
1766+
_ => None,
1767+
},
1768+
_ => None,
1769+
};
1770+
if let Some(ident) = meta_ident {
1771+
self.bump();
1772+
return Ok(ast::Path::from_ident(self.prev_span, ident));
1773+
}
1774+
self.parse_path(mode)
1775+
}
1776+
17571777
/// Examples:
17581778
/// - `a::b<T,U>::c<V,W>`
17591779
/// - `a::b<T,U>::c(V) -> W`

src/test/run-pass/issue-40962.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
macro_rules! m {
12+
($i:meta) => {
13+
#[derive($i)]
14+
struct S;
15+
}
16+
}
17+
18+
m!(Clone);
19+
20+
fn main() {}

0 commit comments

Comments
 (0)