Skip to content

Commit f4f3913

Browse files
committed
Forbid $$crate
1 parent 144227d commit f4f3913

File tree

3 files changed

+64
-8
lines changed

3 files changed

+64
-8
lines changed

compiler/rustc_expand/src/mbe/quoted.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::mbe::macro_parser::count_metavar_decls;
22
use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree};
33

44
use rustc_ast::token::{self, Delimiter, Token};
5+
use rustc_ast::tokenstream::Cursor;
56
use rustc_ast::{tokenstream, NodeId};
67
use rustc_ast_pretty::pprust;
78
use rustc_feature::Features;
@@ -136,7 +137,7 @@ fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess,
136137
/// - `features`: language features so we can do feature gating.
137138
fn parse_tree(
138139
tree: tokenstream::TokenTree,
139-
outer_trees: &mut impl Iterator<Item = tokenstream::TokenTree>,
140+
outer_trees: &mut Cursor,
140141
parsing_patterns: bool,
141142
sess: &ParseSess,
142143
node_id: NodeId,
@@ -150,13 +151,13 @@ fn parse_tree(
150151
// FIXME: Handle `Invisible`-delimited groups in a more systematic way
151152
// during parsing.
152153
let mut next = outer_trees.next();
153-
let mut trees: Box<dyn Iterator<Item = tokenstream::TokenTree>>;
154+
let mut trees_owned = None;
154155
if let Some(tokenstream::TokenTree::Delimited(_, Delimiter::Invisible, tts)) = next {
155-
trees = Box::new(tts.into_trees());
156-
next = trees.next();
157-
} else {
158-
trees = Box::new(outer_trees);
156+
let mut local_trees = tts.into_trees();
157+
next = local_trees.next();
158+
trees_owned = Some(local_trees);
159159
}
160+
let trees = if let Some(ref mut elem) = trees_owned { elem } else { outer_trees };
160161

161162
match next {
162163
// `tree` is followed by a delimited set of token trees.
@@ -205,7 +206,7 @@ fn parse_tree(
205206
let sequence = parse(tts, parsing_patterns, sess, node_id, features, edition);
206207
// Get the Kleene operator and optional separator
207208
let (separator, kleene) =
208-
parse_sep_and_kleene_op(&mut trees, delim_span.entire(), sess);
209+
parse_sep_and_kleene_op(trees, delim_span.entire(), sess);
209210
// Count the number of captured "names" (i.e., named metavars)
210211
let num_captures =
211212
if parsing_patterns { count_metavar_decls(&sequence) } else { 0 };
@@ -235,9 +236,18 @@ fn parse_tree(
235236
&Token { kind: token::Dollar, span },
236237
);
237238
}
239+
if let Some(tokenstream::TokenTree::Token(ref token)) = trees.look_ahead(0)
240+
&& let Some((ident, is_raw)) = token.ident()
241+
&& ident.name == kw::Crate && !is_raw
242+
{
243+
sess.span_diagnostic.span_err(
244+
token.span,
245+
&format!("unexpected token: {}", pprust::token_to_string(token))
246+
);
247+
sess.span_diagnostic.note_without_error("`$$crate` is not allowed in any context");
248+
}
238249
TokenTree::token(token::Dollar, span)
239250
}
240-
241251
// `tree` is followed by some other token. This is an error.
242252
Some(tokenstream::TokenTree::Token(token)) => {
243253
let msg = format!(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// All possible usages of $$crate are currently forbidden
2+
3+
pub const IDX: usize = 1;
4+
5+
macro_rules! _direct_usage_super {
6+
() => {
7+
macro_rules! _direct_usage_sub {
8+
() => {{
9+
$$crate
10+
//~^ ERROR unexpected token: crate
11+
}};
12+
}
13+
};
14+
}
15+
16+
macro_rules! indirect_usage_crate {
17+
($d:tt) => {
18+
const _FOO: usize = $d$d crate::IDX;
19+
//~^ ERROR expected expression, found `$`
20+
};
21+
}
22+
macro_rules! indirect_usage_use {
23+
($d:tt) => {
24+
indirect_usage_crate!($d);
25+
}
26+
}
27+
indirect_usage_use!($);
28+
29+
fn main() {
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: unexpected token: crate
2+
--> $DIR/dollar_dollar_crate.rs:9:19
3+
|
4+
LL | $$crate
5+
| ^^^^^
6+
7+
note: `$$crate` is not allowed in any context
8+
9+
error: expected expression, found `$`
10+
--> $DIR/dollar_dollar_crate.rs:18:29
11+
|
12+
LL | const _FOO: usize = $d$d crate::IDX;
13+
| ^^ expected expression
14+
15+
error: aborting due to 2 previous errors
16+

0 commit comments

Comments
 (0)