Auto merge of #34570 - jseyfried:no_rename, r=nrc
Simplify the macro hygiene algorithm This PR removes renaming from the hygiene algorithm and treats differently marked identifiers as unequal. This change makes the scope of identifiers in `macro_rules!` items empty. That is, identifiers in `macro_rules!` definitions do not inherit any semantics from the `macro_rules!`'s scope. Since `macro_rules!` macros are items, the scope of their identifiers "should" be the same as that of other items; in particular, the scope should contain only items. Since all items are unhygienic today, this would mean the scope should be empty. However, the scope of an identifier in a `macro_rules!` statement today is the scope that the identifier would have if it replaced the `macro_rules!` (excluding anything unhygienic, i.e. locals only). To continue to support this, this PR tracks the scope of each `macro_rules!` and uses it in `resolve` to ensure that an identifier expanded from a `macro_rules!` gets a chance to resolve to the locals in the `macro_rules!`'s scope. This PR is a pure refactoring. After this PR, - `syntax::ext::expand` is much simpler. - We can expand macros in any order without causing problems for hygiene (needed for macro modularization). - We can deprecate or remove today's `macro_rules!` scope easily. - Expansion performance improves by 25%, post-expansion memory usage decreases by ~5%. - Expanding a block is no longer quadratic in the number of `let` statements (fixes #10607). r? @nrc
This commit is contained in:
commit
4db1874f4c
10 changed files with 251 additions and 806 deletions
|
@ -15,7 +15,6 @@ pub use self::Lit::*;
|
|||
pub use self::Token::*;
|
||||
|
||||
use ast::{self, BinOpKind};
|
||||
use ext::mtwt;
|
||||
use ptr::P;
|
||||
use util::interner::Interner;
|
||||
use tokenstream;
|
||||
|
@ -313,17 +312,6 @@ impl Token {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Hygienic identifier equality comparison.
|
||||
///
|
||||
/// See `styntax::ext::mtwt`.
|
||||
pub fn mtwt_eq(&self, other : &Token) -> bool {
|
||||
match (self, other) {
|
||||
(&Ident(id1), &Ident(id2)) | (&Lifetime(id1), &Lifetime(id2)) =>
|
||||
mtwt::resolve(id1) == mtwt::resolve(id2),
|
||||
_ => *self == *other
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
|
||||
|
@ -650,21 +638,3 @@ pub fn fresh_name(src: ast::Ident) -> ast::Name {
|
|||
pub fn fresh_mark() -> ast::Mrk {
|
||||
gensym("mark").0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ast;
|
||||
use ext::mtwt;
|
||||
|
||||
fn mark_ident(id : ast::Ident, m : ast::Mrk) -> ast::Ident {
|
||||
ast::Ident::new(id.name, mtwt::apply_mark(m, id.ctxt))
|
||||
}
|
||||
|
||||
#[test] fn mtwt_token_eq_test() {
|
||||
assert!(Gt.mtwt_eq(&Gt));
|
||||
let a = str_to_ident("bac");
|
||||
let a1 = mark_ident(a,92);
|
||||
assert!(Ident(a).mtwt_eq(&Ident(a1)));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue