Skip to content

Commit 0357257

Browse files
committed
Allow path as value in name-value attribute
1 parent 4c0c5e0 commit 0357257

File tree

13 files changed

+114
-14
lines changed

13 files changed

+114
-14
lines changed

compiler/rustc_parse/src/parser/attr.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ impl<'a> Parser<'a> {
159159
/// PATH `{` TOKEN_STREAM `}`
160160
/// PATH
161161
/// PATH `=` UNSUFFIXED_LIT
162+
/// PATH `=` PATH
162163
/// The delimiters or `=` are still put into the resulting token stream.
163164
pub fn parse_attr_item(&mut self, capture_tokens: bool) -> PResult<'a, ast::AttrItem> {
164165
let item = match self.token.kind {
@@ -230,6 +231,11 @@ impl<'a> Parser<'a> {
230231

231232
crate fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> {
232233
let lit = self.parse_lit()?;
234+
self.require_unsuffixed(&lit);
235+
Ok(lit)
236+
}
237+
238+
crate fn require_unsuffixed(&self, lit: &ast::Lit) {
233239
debug!("checking if {:?} is unusuffixed", lit);
234240

235241
if !lit.kind.is_unsuffixed() {
@@ -240,8 +246,6 @@ impl<'a> Parser<'a> {
240246
)
241247
.emit();
242248
}
243-
244-
Ok(lit)
245249
}
246250

247251
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -934,16 +934,22 @@ impl<'a> Parser<'a> {
934934
is_interpolated_expr = true;
935935
}
936936
}
937-
let token_tree = if is_interpolated_expr {
937+
let token_stream: TokenStream = if is_interpolated_expr {
938938
// We need to accept arbitrary interpolated expressions to continue
939939
// supporting things like `doc = $expr` that work on stable.
940940
// Non-literal interpolated expressions are rejected after expansion.
941-
self.parse_token_tree()
941+
self.parse_token_tree().into()
942+
} else if let Some(lit) = self.parse_opt_lit() {
943+
self.require_unsuffixed(&lit);
944+
lit.token_tree().into()
945+
} else if self.check(&token::ModSep) || self.token.ident().is_some() {
946+
self.collect_tokens_only(|this| this.parse_path(PathStyle::Mod))?
942947
} else {
943-
self.parse_unsuffixed_lit()?.token_tree()
948+
let msg = "expected a literal or ::-separated path";
949+
return Err(self.struct_span_err(self.token.span, msg));
944950
};
945951

946-
MacArgs::Eq(eq_span, token_tree.into())
952+
MacArgs::Eq(eq_span, token_stream)
947953
} else {
948954
MacArgs::Empty
949955
}
@@ -1254,6 +1260,14 @@ impl<'a> Parser<'a> {
12541260
Ok((ret, Some(LazyTokenStream::new(lazy_impl))))
12551261
}
12561262

1263+
fn collect_tokens_only<R>(
1264+
&mut self,
1265+
f: impl FnOnce(&mut Self) -> PResult<'a, R>,
1266+
) -> PResult<'a, TokenStream> {
1267+
let (_ignored, tokens) = self.collect_tokens(f)?;
1268+
Ok(tokens)
1269+
}
1270+
12571271
/// `::{` or `::*`
12581272
fn is_import_coupler(&mut self) -> bool {
12591273
self.check(&token::ModSep)

src/test/ui/attr-eq-token-tree.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
#[my_attr = !] //~ ERROR unexpected token: `!`
1+
#[my_attr = !] //~ ERROR expected a literal or ::-separated path
22
fn main() {}

src/test/ui/attr-eq-token-tree.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: unexpected token: `!`
1+
error: expected a literal or ::-separated path
22
--> $DIR/attr-eq-token-tree.rs:1:13
33
|
44
LL | #[my_attr = !]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#[cfg(any())]
2+
extern "C++" {
3+
#[namespace = std::experimental]
4+
type any;
5+
6+
#[rust = std::option::Option<T>]
7+
//~^ ERROR expected one of `::` or `]`, found `<`
8+
type optional;
9+
}
10+
11+
fn main() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: expected one of `::` or `]`, found `<`
2+
--> $DIR/path-eq-path.rs:6:33
3+
|
4+
LL | extern "C++" {
5+
| - while parsing this item list starting here
6+
...
7+
LL | #[rust = std::option::Option<T>]
8+
| ^ expected one of `::` or `]`
9+
...
10+
LL | }
11+
| - the item list ends here
12+
13+
error: aborting due to previous error
14+

src/test/ui/macros/macro-attribute.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
#[doc = $not_there] //~ ERROR unexpected token: `$`
1+
#[doc = $not_there] //~ ERROR expected a literal or ::-separated path
22
fn main() { }

src/test/ui/macros/macro-attribute.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: unexpected token: `$`
1+
error: expected a literal or ::-separated path
22
--> $DIR/macro-attribute.rs:1:9
33
|
44
LL | #[doc = $not_there]

src/test/ui/parser/attr-bad-meta-2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
#[path =] //~ ERROR unexpected token: `]`
1+
#[path =] //~ ERROR expected a literal or ::-separated path
22
mod m {}

src/test/ui/parser/attr-bad-meta-2.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: unexpected token: `]`
1+
error: expected a literal or ::-separated path
22
--> $DIR/attr-bad-meta-2.rs:1:9
33
|
44
LL | #[path =]

0 commit comments

Comments
 (0)