diff options
| author | bors <bors@rust-lang.org> | 2016-08-13 23:37:11 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-08-13 23:37:11 -0700 |
| commit | eec30ea65792fd07826a931a9e0c5dfa3c050b2f (patch) | |
| tree | c4f14a765997dc294bc19ff6ce7e48501ef5b962 /src/libsyntax | |
| parent | 2b7ea14cc492fa010f8a914044faebd6c27333ab (diff) | |
| parent | 95b68aa5eacac7fb6340829289871da6e517e8b0 (diff) | |
| download | rust-eec30ea65792fd07826a931a9e0c5dfa3c050b2f.tar.gz rust-eec30ea65792fd07826a931a9e0c5dfa3c050b2f.zip | |
Auto merge of #35453 - jseyfried:hygienize_metavariables, r=nrc
macros: Make metavariables hygienic
This PR makes metavariables hygienic. For example, consider:
```rust
macro_rules! foo {
($x:tt) => { // Suppose that this token tree argument is always a metavariable.
macro_rules! bar { ($x:expr, $y:expr) => { ($x, $y) } }
}
}
fn main() {
foo!($z); // This currently compiles.
foo!($y); // This is an error today but compiles after this PR.
}
```
Today, the `macro_rules! bar { ... }` definition is only valid when the metavariable passed to `foo` is not `$y` (since it unhygienically conflicts with the `$y` in the definition of `bar`) or `$x` (c.f. #35450).
After this PR, the definition of `bar` is always valid (and `bar!(a, b)` always expands to `(a, b)` as expected).
This can break code that was allowed in #34925 (landed two weeks ago). For example,
```rust
macro_rules! outer {
($t:tt) => {
macro_rules! inner { ($i:item) => { $t } }
}
}
outer!($i); // This `$i` should not interact with the `$i` in the definition of `inner!`.
inner!(fn main() {}); // After this PR, this is an error ("unknown macro variable `i`").
```
Due to the severe limitations on nested `macro_rules!` before #34925, this is not a breaking change for stable/beta.
Fixes #35450.
r? @nrc
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/tt/macro_parser.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/transcribe.rs | 10 |
3 files changed, 12 insertions, 12 deletions
diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 813afb93576..7db03e9a863 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -79,7 +79,7 @@ pub use self::ParseResult::*; use self::TokenTreeOrTokenTreeVec::*; use ast; -use ast::{Name, Ident}; +use ast::Ident; use syntax_pos::{self, BytePos, mk_sp, Span}; use codemap::Spanned; use errors::FatalError; @@ -202,9 +202,9 @@ pub enum NamedMatch { } pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>]) - -> ParseResult<HashMap<Name, Rc<NamedMatch>>> { + -> ParseResult<HashMap<Ident, Rc<NamedMatch>>> { fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc<NamedMatch>], - ret_val: &mut HashMap<Name, Rc<NamedMatch>>, idx: &mut usize) + ret_val: &mut HashMap<Ident, Rc<NamedMatch>>, idx: &mut usize) -> Result<(), (syntax_pos::Span, String)> { match *m { TokenTree::Sequence(_, ref seq) => { @@ -218,7 +218,7 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>]) } } TokenTree::Token(sp, MatchNt(bind_name, _)) => { - match ret_val.entry(bind_name.name) { + match ret_val.entry(bind_name) { Vacant(spot) => { spot.insert(res[*idx].clone()); *idx += 1; @@ -257,7 +257,7 @@ pub enum ParseResult<T> { Error(syntax_pos::Span, String) } -pub type NamedParseResult = ParseResult<HashMap<Name, Rc<NamedMatch>>>; +pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>; pub type PositionalParseResult = ParseResult<Vec<Rc<NamedMatch>>>; /// Perform a token equality check, ignoring syntax context (that is, an diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index db12ef24f71..d197741e9a3 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -302,7 +302,7 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, let mut valid = true; // Extract the arguments: - let lhses = match **argument_map.get(&lhs_nm.name).unwrap() { + let lhses = match **argument_map.get(&lhs_nm).unwrap() { MatchedSeq(ref s, _) => { s.iter().map(|m| match **m { MatchedNonterminal(NtTT(ref tt)) => { @@ -315,7 +315,7 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, _ => cx.span_bug(def.span, "wrong-structured lhs") }; - let rhses = match **argument_map.get(&rhs_nm.name).unwrap() { + let rhses = match **argument_map.get(&rhs_nm).unwrap() { MatchedSeq(ref s, _) => { s.iter().map(|m| match **m { MatchedNonterminal(NtTT(ref tt)) => (**tt).clone(), diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 29a300b172e..939425378de 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -9,7 +9,7 @@ // except according to those terms. use self::LockstepIterSize::*; -use ast::{Ident, Name}; +use ast::Ident; use syntax_pos::{Span, DUMMY_SP}; use errors::{Handler, DiagnosticBuilder}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; @@ -38,7 +38,7 @@ pub struct TtReader<'a> { /// the unzipped tree: stack: Vec<TtFrame>, /* for MBE-style macro transcription */ - interpolations: HashMap<Name, Rc<NamedMatch>>, + interpolations: HashMap<Ident, Rc<NamedMatch>>, imported_from: Option<Ident>, // Some => return imported_from as the next token @@ -57,7 +57,7 @@ pub struct TtReader<'a> { /// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can /// (and should) be None. pub fn new_tt_reader(sp_diag: &Handler, - interp: Option<HashMap<Name, Rc<NamedMatch>>>, + interp: Option<HashMap<Ident, Rc<NamedMatch>>>, imported_from: Option<Ident>, src: Vec<tokenstream::TokenTree>) -> TtReader { @@ -71,7 +71,7 @@ pub fn new_tt_reader(sp_diag: &Handler, /// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can /// (and should) be None. pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler, - interp: Option<HashMap<Name, Rc<NamedMatch>>>, + interp: Option<HashMap<Ident, Rc<NamedMatch>>>, imported_from: Option<Ident>, src: Vec<tokenstream::TokenTree>, desugar_doc_comments: bool) @@ -119,7 +119,7 @@ fn lookup_cur_matched_by_matched(r: &TtReader, start: Rc<NamedMatch>) -> Rc<Name } fn lookup_cur_matched(r: &TtReader, name: Ident) -> Option<Rc<NamedMatch>> { - let matched_opt = r.interpolations.get(&name.name).cloned(); + let matched_opt = r.interpolations.get(&name).cloned(); matched_opt.map(|s| lookup_cur_matched_by_matched(r, s)) } |
