Rollup merge of #41050 - jseyfried:fix_derive_parsing, r=petrochenkov
macros: fix bug parsing `#[derive]` invocations Fixes #40962 (introduced in #40346). r? @nrc
This commit is contained in:
commit
89b364d687
4 changed files with 46 additions and 3 deletions
|
@ -222,8 +222,10 @@ impl<'a> base::Resolver for Resolver<'a> {
|
||||||
let name = unwrap_or!(attrs[i].name(), continue);
|
let name = unwrap_or!(attrs[i].name(), continue);
|
||||||
|
|
||||||
if name == "derive" {
|
if name == "derive" {
|
||||||
let result = attrs[i].parse_list(&self.session.parse_sess,
|
let result = attrs[i].parse_list(&self.session.parse_sess, |parser| {
|
||||||
|parser| parser.parse_path(PathStyle::Mod));
|
parser.parse_path_allowing_meta(PathStyle::Mod)
|
||||||
|
});
|
||||||
|
|
||||||
let mut traits = match result {
|
let mut traits = match result {
|
||||||
Ok(traits) => traits,
|
Ok(traits) => traits,
|
||||||
Err(mut e) => {
|
Err(mut e) => {
|
||||||
|
|
|
@ -26,7 +26,8 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec
|
||||||
return true;
|
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() => {
|
Ok(ref traits) if traits.is_empty() => {
|
||||||
cx.span_warn(attr.span, "empty trait list in `derive`");
|
cx.span_warn(attr.span, "empty trait list in `derive`");
|
||||||
false
|
false
|
||||||
|
|
|
@ -1767,6 +1767,26 @@ impl<'a> Parser<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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:
|
/// Examples:
|
||||||
/// - `a::b<T,U>::c<V,W>`
|
/// - `a::b<T,U>::c<V,W>`
|
||||||
/// - `a::b<T,U>::c(V) -> W`
|
/// - `a::b<T,U>::c(V) -> W`
|
||||||
|
|
20
src/test/run-pass/issue-40962.rs
Normal file
20
src/test/run-pass/issue-40962.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// 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() {}
|
Loading…
Add table
Add a link
Reference in a new issue