Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forbid $$crate #99193

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions compiler/rustc_expand/src/mbe/quoted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::mbe::macro_parser::count_metavar_decls;
use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree};

use rustc_ast::token::{self, Delimiter, Token};
use rustc_ast::tokenstream::Cursor;
use rustc_ast::{tokenstream, NodeId};
use rustc_ast_pretty::pprust;
use rustc_feature::Features;
Expand Down Expand Up @@ -136,7 +137,7 @@ fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &ParseSess,
/// - `features`: language features so we can do feature gating.
fn parse_tree(
tree: tokenstream::TokenTree,
outer_trees: &mut impl Iterator<Item = tokenstream::TokenTree>,
outer_trees: &mut Cursor,
c410-f3r marked this conversation as resolved.
Show resolved Hide resolved
parsing_patterns: bool,
sess: &ParseSess,
node_id: NodeId,
Expand All @@ -150,13 +151,13 @@ fn parse_tree(
// FIXME: Handle `Invisible`-delimited groups in a more systematic way
// during parsing.
let mut next = outer_trees.next();
let mut trees: Box<dyn Iterator<Item = tokenstream::TokenTree>>;
let mut trees_owned = None;
if let Some(tokenstream::TokenTree::Delimited(_, Delimiter::Invisible, tts)) = next {
trees = Box::new(tts.into_trees());
next = trees.next();
} else {
trees = Box::new(outer_trees);
let mut local_trees = tts.into_trees();
next = local_trees.next();
trees_owned = Some(local_trees);
}
let trees = if let Some(ref mut elem) = trees_owned { elem } else { outer_trees };
c410-f3r marked this conversation as resolved.
Show resolved Hide resolved

match next {
// `tree` is followed by a delimited set of token trees.
Expand Down Expand Up @@ -205,7 +206,7 @@ fn parse_tree(
let sequence = parse(tts, parsing_patterns, sess, node_id, features, edition);
// Get the Kleene operator and optional separator
let (separator, kleene) =
parse_sep_and_kleene_op(&mut trees, delim_span.entire(), sess);
parse_sep_and_kleene_op(trees, delim_span.entire(), sess);
// Count the number of captured "names" (i.e., named metavars)
let num_captures =
if parsing_patterns { count_metavar_decls(&sequence) } else { 0 };
Expand Down Expand Up @@ -235,9 +236,18 @@ fn parse_tree(
&Token { kind: token::Dollar, span },
);
}
if let Some(tokenstream::TokenTree::Token(ref token)) = trees.look_ahead(0)
&& let Some((ident, is_raw)) = token.ident()
&& ident.name == kw::Crate && !is_raw
{
sess.span_diagnostic.span_err(
token.span,
&format!("unexpected token: {}", pprust::token_to_string(token))
);
sess.span_diagnostic.note_without_error("`$$crate` is not allowed in any context");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not directly span_err on this message? Should we point to the two $ tokens too?

}
TokenTree::token(token::Dollar, span)
}

// `tree` is followed by some other token. This is an error.
Some(tokenstream::TokenTree::Token(token)) => {
let msg = format!(
Expand Down
30 changes: 30 additions & 0 deletions src/test/ui/macros/rfc-3086-metavar-expr/dollar_dollar_crate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// All possible usages of $$crate are currently forbidden

pub const IDX: usize = 1;

macro_rules! _direct_usage_super {
() => {
macro_rules! _direct_usage_sub {
() => {{
$$crate
//~^ ERROR unexpected token: crate
}};
}
};
}

macro_rules! indirect_usage_crate {
($d:tt) => {
const _FOO: usize = $d$d crate::IDX;
//~^ ERROR expected expression, found `$`
};
}
macro_rules! indirect_usage_use {
($d:tt) => {
indirect_usage_crate!($d);
}
}
indirect_usage_use!($);

fn main() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
error: unexpected token: crate
--> $DIR/dollar_dollar_crate.rs:9:19
|
LL | $$crate
| ^^^^^

note: `$$crate` is not allowed in any context

error: expected expression, found `$`
--> $DIR/dollar_dollar_crate.rs:18:29
|
LL | const _FOO: usize = $d$d crate::IDX;
| ^^ expected expression

error: aborting due to 2 previous errors