use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap};
use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet};
-use syntax::ext::mtwt;
use syntax::ast::{self, FloatTy};
use syntax::ast::{CRATE_NODE_ID, Name, NodeId, CrateNum, IntTy, UintTy};
use syntax::parse::token::{self, keywords};
}
// Map from the name in a pattern to its binding mode.
-type BindingMap = HashMap<Name, BindingInfo>;
+type BindingMap = HashMap<ast::Ident, BindingInfo>;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum PatternSource {
/// One local scope.
#[derive(Debug)]
struct Rib<'a> {
- bindings: HashMap<Name, Def>,
+ bindings: HashMap<ast::Ident, Def>,
kind: RibKind<'a>,
}
/// Invariant: This must only be called during main resolution, not during
/// import resolution.
fn resolve_ident_in_lexical_scope(&mut self,
- ident: ast::Ident,
+ mut ident: ast::Ident,
ns: Namespace,
record_used: bool)
-> Option<LexicalScopeBinding<'a>> {
- let name = match ns { ValueNS => mtwt::resolve(ident), TypeNS => ident.name };
+ if ns == TypeNS {
+ ident = ast::Ident::with_empty_ctxt(ident.name);
+ }
// Walk backwards up the ribs in scope.
for i in (0 .. self.get_ribs(ns).len()).rev() {
- if let Some(def) = self.get_ribs(ns)[i].bindings.get(&name).cloned() {
+ if let Some(def) = self.get_ribs(ns)[i].bindings.get(&ident).cloned() {
// The ident resolves to a type parameter or local variable.
return Some(LexicalScopeBinding::LocalDef(LocalDef {
ribs: Some((ns, i)),
/// Searches the current set of local scopes for labels.
/// Stops after meeting a closure.
- fn search_label(&self, name: Name) -> Option<Def> {
+ fn search_label(&self, ident: ast::Ident) -> Option<Def> {
for rib in self.label_ribs.iter().rev() {
match rib.kind {
NormalRibKind => {
return None;
}
}
- let result = rib.bindings.get(&name).cloned();
+ let result = rib.bindings.get(&ident).cloned();
if result.is_some() {
return result;
}
// plain insert (no renaming)
let def_id = self.definitions.local_def_id(type_parameter.id);
let def = Def::TyParam(space, index as u32, def_id, name);
- function_type_rib.bindings.insert(name, def);
+ function_type_rib.bindings.insert(ast::Ident::with_empty_ctxt(name), def);
}
self.type_ribs.push(function_type_rib);
}
let mut self_type_rib = Rib::new(NormalRibKind);
// plain insert (no renaming, types are not currently hygienic....)
- self_type_rib.bindings.insert(keywords::SelfType.name(), self_def);
+ self_type_rib.bindings.insert(keywords::SelfType.ident(), self_def);
self.type_ribs.push(self_type_rib);
f(self);
self.type_ribs.pop();
_ => false,
} {
let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
- binding_map.insert(mtwt::resolve(ident.node), binding_info);
+ binding_map.insert(ident.node, binding_info);
}
}
true
for (&key, &binding_0) in &map_0 {
match map_i.get(&key) {
None => {
- resolve_error(self,
- p.span,
- ResolutionError::VariableNotBoundInPattern(key, 1, i + 1));
+ let error = ResolutionError::VariableNotBoundInPattern(key.name, 1, i + 1);
+ resolve_error(self, p.span, error);
}
Some(binding_i) => {
if binding_0.binding_mode != binding_i.binding_mode {
resolve_error(self,
binding_i.span,
- ResolutionError::VariableBoundWithDifferentMode(key,
+ ResolutionError::VariableBoundWithDifferentMode(key.name,
i + 1));
}
}
if !map_0.contains_key(&key) {
resolve_error(self,
binding.span,
- ResolutionError::VariableNotBoundInPattern(key, i + 1, 1));
+ ResolutionError::VariableNotBoundInPattern(key.name, i + 1, 1));
}
}
}
pat_id: NodeId,
outer_pat_id: NodeId,
pat_src: PatternSource,
- bindings: &mut HashMap<Name, NodeId>)
+ bindings: &mut HashMap<ast::Ident, NodeId>)
-> PathResolution {
// Add the binding to the local ribs, if it
// doesn't already exist in the bindings map. (We
// must not add it if it's in the bindings map
// because that breaks the assumptions later
// passes make about or-patterns.)
- let renamed = mtwt::resolve(ident.node);
let mut def = Def::Local(self.definitions.local_def_id(pat_id), pat_id);
- match bindings.get(&renamed).cloned() {
+ match bindings.get(&ident.node).cloned() {
Some(id) if id == outer_pat_id => {
// `Variant(a, a)`, error
resolve_error(
Some(..) if pat_src == PatternSource::Match => {
// `Variant1(a) | Variant2(a)`, ok
// Reuse definition from the first `a`.
- def = self.value_ribs.last_mut().unwrap().bindings[&renamed];
+ def = self.value_ribs.last_mut().unwrap().bindings[&ident.node];
}
Some(..) => {
span_bug!(ident.span, "two bindings with the same name from \
None => {
// A completely fresh binding, add to the lists if it's valid.
if ident.node.name != keywords::Invalid.name() {
- bindings.insert(renamed, outer_pat_id);
- self.value_ribs.last_mut().unwrap().bindings.insert(renamed, def);
+ bindings.insert(ident.node, outer_pat_id);
+ self.value_ribs.last_mut().unwrap().bindings.insert(ident.node, def);
}
}
}
pat_src: PatternSource,
// Maps idents to the node ID for the
// outermost pattern that binds them.
- bindings: &mut HashMap<Name, NodeId>) {
+ bindings: &mut HashMap<ast::Ident, NodeId>) {
// Visit all direct subpatterns of this pattern.
let outer_pat_id = pat.id;
pat.walk(&mut |pat| {
let names = self.value_ribs
.iter()
.rev()
- .flat_map(|rib| rib.bindings.keys());
+ .flat_map(|rib| rib.bindings.keys().map(|ident| &ident.name));
if let Some(found) = find_best_match_for_name(names, name, None) {
if name != found {
fn resolve_labeled_block(&mut self, label: Option<ast::Ident>, id: NodeId, block: &Block) {
if let Some(label) = label {
- let (label, def) = (mtwt::resolve(label), Def::Label(id));
+ let def = Def::Label(id);
self.with_label_rib(|this| {
this.label_ribs.last_mut().unwrap().bindings.insert(label, def);
this.visit_block(block);
{
let rib = this.label_ribs.last_mut().unwrap();
- rib.bindings.insert(mtwt::resolve(label.node), def);
+ rib.bindings.insert(label.node, def);
}
visit::walk_expr(this, expr);
}
ExprKind::Break(Some(label)) | ExprKind::Continue(Some(label)) => {
- match self.search_label(mtwt::resolve(label.node)) {
+ match self.search_label(label.node) {
None => {
self.record_def(expr.id, err_path_resolution());
resolve_error(self,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use ast::{Block, Crate, PatKind};
-use ast::{Local, Ident, Mac_, Name, SpannedIdent};
+use ast::{Block, Crate, Ident, Mac_, Name, PatKind};
use ast::{MacStmtStyle, Mrk, Stmt, StmtKind, ItemKind};
use ast;
use attr::HasAttrs;
use feature_gate::{self, Features};
use fold;
use fold::*;
-use util::move_map::MoveMap;
-use parse::token::{fresh_mark, fresh_name, intern, keywords};
+use parse::token::{fresh_mark, intern, keywords};
use ptr::P;
use tokenstream::TokenTree;
use util::small_vector::SmallVector;
}
}
-pub fn expand_expr(mut expr: ast::Expr, fld: &mut MacroExpander) -> P<ast::Expr> {
+pub fn expand_expr(expr: ast::Expr, fld: &mut MacroExpander) -> P<ast::Expr> {
match expr.node {
// expr_mac should really be expr_ext or something; it's the
// entry-point for all syntax extensions.
ast::ExprKind::Mac(mac) => {
return expand_mac_invoc(mac, None, expr.attrs.into(), expr.span, fld);
}
-
- ast::ExprKind::While(cond, body, opt_ident) => {
- let cond = fld.fold_expr(cond);
- let (body, opt_ident) = expand_loop_block(body, opt_ident, fld);
- expr.node = ast::ExprKind::While(cond, body, opt_ident);
- }
-
- ast::ExprKind::WhileLet(pat, cond, body, opt_ident) => {
- let pat = fld.fold_pat(pat);
- let cond = fld.fold_expr(cond);
-
- // Hygienic renaming of the body.
- let ((body, opt_ident), mut rewritten_pats) =
- rename_in_scope(vec![pat],
- fld,
- (body, opt_ident),
- |rename_fld, fld, (body, opt_ident)| {
- expand_loop_block(rename_fld.fold_block(body), opt_ident, fld)
- });
- assert!(rewritten_pats.len() == 1);
-
- expr.node = ast::ExprKind::WhileLet(rewritten_pats.remove(0), cond, body, opt_ident);
- }
-
- ast::ExprKind::Loop(loop_block, opt_ident) => {
- let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
- expr.node = ast::ExprKind::Loop(loop_block, opt_ident);
- }
-
- ast::ExprKind::ForLoop(pat, head, body, opt_ident) => {
- let pat = fld.fold_pat(pat);
-
- // Hygienic renaming of the for loop body (for loop binds its pattern).
- let ((body, opt_ident), mut rewritten_pats) =
- rename_in_scope(vec![pat],
- fld,
- (body, opt_ident),
- |rename_fld, fld, (body, opt_ident)| {
- expand_loop_block(rename_fld.fold_block(body), opt_ident, fld)
- });
- assert!(rewritten_pats.len() == 1);
-
- let head = fld.fold_expr(head);
- expr.node = ast::ExprKind::ForLoop(rewritten_pats.remove(0), head, body, opt_ident);
- }
-
- ast::ExprKind::IfLet(pat, sub_expr, body, else_opt) => {
- let pat = fld.fold_pat(pat);
-
- // Hygienic renaming of the body.
- let (body, mut rewritten_pats) =
- rename_in_scope(vec![pat],
- fld,
- body,
- |rename_fld, fld, body| {
- fld.fold_block(rename_fld.fold_block(body))
- });
- assert!(rewritten_pats.len() == 1);
-
- let else_opt = else_opt.map(|else_opt| fld.fold_expr(else_opt));
- let sub_expr = fld.fold_expr(sub_expr);
- expr.node = ast::ExprKind::IfLet(rewritten_pats.remove(0), sub_expr, body, else_opt);
- }
-
- ast::ExprKind::Closure(capture_clause, fn_decl, block, fn_decl_span) => {
- let (rewritten_fn_decl, rewritten_block)
- = expand_and_rename_fn_decl_and_block(fn_decl, block, fld);
- expr.node = ast::ExprKind::Closure(capture_clause,
- rewritten_fn_decl,
- rewritten_block,
- fn_decl_span);
- }
-
- _ => expr = noop_fold_expr(expr, fld),
- };
- P(expr)
+ _ => P(noop_fold_expr(expr, fld)),
+ }
}
/// Expand a macro invocation. Returns the result of expansion.
fully_expanded
}
-/// Rename loop label and expand its loop body
-///
-/// The renaming procedure for loop is different in the sense that the loop
-/// body is in a block enclosed by loop head so the renaming of loop label
-/// must be propagated to the enclosed context.
-fn expand_loop_block(loop_block: P<Block>,
- opt_ident: Option<SpannedIdent>,
- fld: &mut MacroExpander) -> (P<Block>, Option<SpannedIdent>) {
- match opt_ident {
- Some(label) => {
- let new_label = fresh_name(label.node);
- let rename = (label.node, new_label);
-
- // The rename *must not* be added to the pending list of current
- // syntax context otherwise an unrelated `break` or `continue` in
- // the same context will pick that up in the deferred renaming pass
- // and be renamed incorrectly.
- let mut rename_list = vec!(rename);
- let mut rename_fld = IdentRenamer{renames: &mut rename_list};
- let renamed_ident = rename_fld.fold_ident(label.node);
-
- // The rename *must* be added to the enclosed syntax context for
- // `break` or `continue` to pick up because by definition they are
- // in a block enclosed by loop head.
- fld.cx.syntax_env.push_frame();
- fld.cx.syntax_env.info().pending_renames.push(rename);
- let expanded_block = expand_block_elts(loop_block, fld);
- fld.cx.syntax_env.pop_frame();
-
- (expanded_block, Some(Spanned { node: renamed_ident, span: label.span }))
- }
- None => (fld.fold_block(loop_block), opt_ident)
- }
-}
-
// eval $e with a new exts frame.
// must be a macro so that $e isn't evaluated too early.
macro_rules! with_exts_frame {
.into_iter().map(|i| i.expect_item()).collect()
}
-/// Expand item_kind
-fn expand_item_kind(item: ast::ItemKind, fld: &mut MacroExpander) -> ast::ItemKind {
- match item {
- ast::ItemKind::Fn(decl, unsafety, constness, abi, generics, body) => {
- let (rewritten_fn_decl, rewritten_body)
- = expand_and_rename_fn_decl_and_block(decl, body, fld);
- let expanded_generics = fold::noop_fold_generics(generics,fld);
- ast::ItemKind::Fn(rewritten_fn_decl, unsafety, constness, abi,
- expanded_generics, rewritten_body)
- }
- _ => noop_fold_item_kind(item, fld)
- }
-}
-
// does this attribute list contain "macro_use" ?
fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool {
for attr in attrs {
/// Expand a stmt
fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
- // perform all pending renames
- let stmt = {
- let pending_renames = &mut fld.cx.syntax_env.info().pending_renames;
- let mut rename_fld = IdentRenamer{renames:pending_renames};
- rename_fld.fold_stmt(stmt).expect_one("rename_fold didn't return one value")
- };
-
let (mac, style, attrs) = match stmt.node {
StmtKind::Mac(mac) => mac.unwrap(),
- _ => return expand_non_macro_stmt(stmt, fld)
+ _ => return noop_fold_stmt(stmt, fld)
};
let mut fully_expanded: SmallVector<ast::Stmt> =
fully_expanded
}
-// expand a non-macro stmt. this is essentially the fallthrough for
-// expand_stmt, above.
-fn expand_non_macro_stmt(stmt: Stmt, fld: &mut MacroExpander)
- -> SmallVector<Stmt> {
- // is it a let?
- match stmt.node {
- StmtKind::Local(local) => {
- // take it apart:
- let rewritten_local = local.map(|Local {id, pat, ty, init, span, attrs}| {
- // expand the ty since TyKind::FixedLengthVec contains an Expr
- // and thus may have a macro use
- let expanded_ty = ty.map(|t| fld.fold_ty(t));
- // expand the pat (it might contain macro uses):
- let expanded_pat = fld.fold_pat(pat);
- // find the PatIdents in the pattern:
- // oh dear heaven... this is going to include the enum
- // names, as well... but that should be okay, as long as
- // the new names are gensyms for the old ones.
- // generate fresh names, push them to a new pending list
- let idents = pattern_bindings(&expanded_pat);
- let mut new_pending_renames =
- idents.iter().map(|ident| (*ident, fresh_name(*ident))).collect();
- // rewrite the pattern using the new names (the old
- // ones have already been applied):
- let rewritten_pat = {
- // nested binding to allow borrow to expire:
- let mut rename_fld = IdentRenamer{renames: &mut new_pending_renames};
- rename_fld.fold_pat(expanded_pat)
- };
- // add them to the existing pending renames:
- fld.cx.syntax_env.info().pending_renames
- .extend(new_pending_renames);
- Local {
- id: id,
- ty: expanded_ty,
- pat: rewritten_pat,
- // also, don't forget to expand the init:
- init: init.map(|e| fld.fold_expr(e)),
- span: span,
- attrs: fold::fold_thin_attrs(attrs, fld),
- }
- });
- SmallVector::one(Stmt {
- id: stmt.id,
- node: StmtKind::Local(rewritten_local),
- span: stmt.span,
- })
- }
- _ => noop_fold_stmt(stmt, fld),
- }
-}
-
-// expand the arm of a 'match', renaming for macro hygiene
-fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
- // expand pats... they might contain macro uses:
- let expanded_pats = arm.pats.move_map(|pat| fld.fold_pat(pat));
- if expanded_pats.is_empty() {
- panic!("encountered match arm with 0 patterns");
- }
-
- // apply renaming and then expansion to the guard and the body:
- let ((rewritten_guard, rewritten_body), rewritten_pats) =
- rename_in_scope(expanded_pats,
- fld,
- (arm.guard, arm.body),
- |rename_fld, fld, (ag, ab)|{
- let rewritten_guard = ag.map(|g| fld.fold_expr(rename_fld.fold_expr(g)));
- let rewritten_body = fld.fold_expr(rename_fld.fold_expr(ab));
- (rewritten_guard, rewritten_body)
- });
-
- ast::Arm {
- attrs: fold::fold_attrs(arm.attrs, fld),
- pats: rewritten_pats,
- guard: rewritten_guard,
- body: rewritten_body,
- }
-}
-
-fn rename_in_scope<X, F>(pats: Vec<P<ast::Pat>>,
- fld: &mut MacroExpander,
- x: X,
- f: F)
- -> (X, Vec<P<ast::Pat>>)
- where F: Fn(&mut IdentRenamer, &mut MacroExpander, X) -> X
-{
- // all of the pats must have the same set of bindings, so use the
- // first one to extract them and generate new names:
- let idents = pattern_bindings(&pats[0]);
- let new_renames = idents.into_iter().map(|id| (id, fresh_name(id))).collect();
- // apply the renaming, but only to the PatIdents:
- let mut rename_pats_fld = PatIdentRenamer{renames:&new_renames};
- let rewritten_pats = pats.move_map(|pat| rename_pats_fld.fold_pat(pat));
-
- let mut rename_fld = IdentRenamer{ renames:&new_renames };
- (f(&mut rename_fld, fld, x), rewritten_pats)
-}
-
-/// A visitor that extracts the PatKind::Ident (binding) paths
-/// from a given thingy and puts them in a mutable
-/// array
-#[derive(Clone)]
-struct PatIdentFinder {
- ident_accumulator: Vec<ast::Ident>
-}
-
-impl Visitor for PatIdentFinder {
- fn visit_pat(&mut self, pattern: &ast::Pat) {
- match *pattern {
- ast::Pat { id: _, node: PatKind::Ident(_, ref path1, ref inner), span: _ } => {
- self.ident_accumulator.push(path1.node);
- // visit optional subpattern of PatKind::Ident:
- if let Some(ref subpat) = *inner {
- self.visit_pat(subpat)
- }
- }
- // use the default traversal for non-PatIdents
- _ => visit::walk_pat(self, pattern)
- }
- }
-}
-
-/// find the PatKind::Ident paths in a pattern
-fn pattern_bindings(pat: &ast::Pat) -> Vec<ast::Ident> {
- let mut name_finder = PatIdentFinder{ident_accumulator:Vec::new()};
- name_finder.visit_pat(pat);
- name_finder.ident_accumulator
-}
-
-/// find the PatKind::Ident paths in a
-fn fn_decl_arg_bindings(fn_decl: &ast::FnDecl) -> Vec<ast::Ident> {
- let mut pat_idents = PatIdentFinder{ident_accumulator:Vec::new()};
- for arg in &fn_decl.inputs {
- pat_idents.visit_pat(&arg.pat);
- }
- pat_idents.ident_accumulator
-}
-
-// expand a block. pushes a new exts_frame, then calls expand_block_elts
-pub fn expand_block(blk: P<Block>, fld: &mut MacroExpander) -> P<Block> {
- // see note below about treatment of exts table
- with_exts_frame!(fld.cx.syntax_env,false,
- expand_block_elts(blk, fld))
-}
-
-// expand the elements of a block.
-pub fn expand_block_elts(b: P<Block>, fld: &mut MacroExpander) -> P<Block> {
- b.map(|Block {id, stmts, rules, span}| {
- let new_stmts = stmts.into_iter().flat_map(|x| {
- // perform pending renames and expand macros in the statement
- fld.fold_stmt(x).into_iter()
- }).collect();
- Block {
- id: fld.new_id(id),
- stmts: new_stmts,
- rules: rules,
- span: span
- }
- })
-}
-
fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
match p.node {
PatKind::Mac(_) => {}
})
}
-/// A tree-folder that applies every rename in its (mutable) list
-/// to every identifier, including both bindings and varrefs
-/// (and lots of things that will turn out to be neither)
-pub struct IdentRenamer<'a> {
- renames: &'a mtwt::RenameList,
-}
-
-impl<'a> Folder for IdentRenamer<'a> {
- fn fold_ident(&mut self, id: Ident) -> Ident {
- mtwt::apply_renames(self.renames, id)
- }
- fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
- fold::noop_fold_mac(mac, self)
- }
-}
-
-/// A tree-folder that applies every rename in its list to
-/// the idents that are in PatKind::Ident patterns. This is more narrowly
-/// focused than IdentRenamer, and is needed for FnDecl,
-/// where we want to rename the args but not the fn name or the generics etc.
-pub struct PatIdentRenamer<'a> {
- renames: &'a mtwt::RenameList,
-}
-
-impl<'a> Folder for PatIdentRenamer<'a> {
- fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
- match pat.node {
- PatKind::Ident(..) => {},
- _ => return noop_fold_pat(pat, self)
- }
-
- pat.map(|ast::Pat {id, node, span}| match node {
- PatKind::Ident(binding_mode, Spanned{span: sp, node: ident}, sub) => {
- let new_ident = mtwt::apply_renames(self.renames, ident);
- let new_node =
- PatKind::Ident(binding_mode,
- Spanned{span: sp, node: new_ident},
- sub.map(|p| self.fold_pat(p)));
- ast::Pat {
- id: id,
- node: new_node,
- span: span,
- }
- },
- _ => unreachable!()
- })
- }
- fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
- fold::noop_fold_mac(mac, self)
- }
-}
-
fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
match a {
Annotatable::Item(it) => match it.node {
fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
-> SmallVector<ast::ImplItem> {
match ii.node {
- ast::ImplItemKind::Method(..) => SmallVector::one(ast::ImplItem {
- id: ii.id,
- ident: ii.ident,
- attrs: ii.attrs,
- vis: ii.vis,
- defaultness: ii.defaultness,
- node: match ii.node {
- ast::ImplItemKind::Method(sig, body) => {
- let (sig, body) = expand_and_rename_method(sig, body, fld);
- ast::ImplItemKind::Method(sig, body)
- }
- _ => unreachable!()
- },
- span: ii.span,
- }),
ast::ImplItemKind::Macro(mac) => {
expand_mac_invoc(mac, None, ii.attrs, ii.span, fld)
}
fn expand_trait_item(ti: ast::TraitItem, fld: &mut MacroExpander)
-> SmallVector<ast::TraitItem> {
match ti.node {
- ast::TraitItemKind::Method(_, Some(_)) => {
- SmallVector::one(ast::TraitItem {
- id: ti.id,
- ident: ti.ident,
- attrs: ti.attrs,
- node: match ti.node {
- ast::TraitItemKind::Method(sig, Some(body)) => {
- let (sig, body) = expand_and_rename_method(sig, body, fld);
- ast::TraitItemKind::Method(sig, Some(body))
- }
- _ => unreachable!()
- },
- span: ti.span,
- })
- }
ast::TraitItemKind::Macro(mac) => {
expand_mac_invoc(mac, None, ti.attrs, ti.span, fld)
}
}
}
-/// Given a fn_decl and a block and a MacroExpander, expand the fn_decl, then use the
-/// PatIdents in its arguments to perform renaming in the FnDecl and
-/// the block, returning both the new FnDecl and the new Block.
-fn expand_and_rename_fn_decl_and_block(fn_decl: P<ast::FnDecl>, block: P<ast::Block>,
- fld: &mut MacroExpander)
- -> (P<ast::FnDecl>, P<ast::Block>) {
- let expanded_decl = fld.fold_fn_decl(fn_decl);
- let idents = fn_decl_arg_bindings(&expanded_decl);
- let renames =
- idents.iter().map(|id| (*id,fresh_name(*id))).collect();
- // first, a renamer for the PatIdents, for the fn_decl:
- let mut rename_pat_fld = PatIdentRenamer{renames: &renames};
- let rewritten_fn_decl = rename_pat_fld.fold_fn_decl(expanded_decl);
- // now, a renamer for *all* idents, for the body:
- let mut rename_fld = IdentRenamer{renames: &renames};
- let rewritten_body = fld.fold_block(rename_fld.fold_block(block));
- (rewritten_fn_decl,rewritten_body)
-}
-
-fn expand_and_rename_method(sig: ast::MethodSig, body: P<ast::Block>,
- fld: &mut MacroExpander)
- -> (ast::MethodSig, P<ast::Block>) {
- let (rewritten_fn_decl, rewritten_body)
- = expand_and_rename_fn_decl_and_block(sig.decl, body, fld);
- (ast::MethodSig {
- generics: fld.fold_generics(sig.generics),
- abi: sig.abi,
- unsafety: sig.unsafety,
- constness: sig.constness,
- decl: rewritten_fn_decl
- }, rewritten_body)
-}
-
pub fn expand_type(t: P<ast::Ty>, fld: &mut MacroExpander) -> P<ast::Ty> {
let t = match t.node.clone() {
ast::TyKind::Mac(mac) => {
result
}
- fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
- expand_item_kind(item, self)
- }
-
fn fold_stmt(&mut self, stmt: ast::Stmt) -> SmallVector<ast::Stmt> {
expand_stmt(stmt, self)
}
fn fold_block(&mut self, block: P<Block>) -> P<Block> {
let was_in_block = ::std::mem::replace(&mut self.cx.in_block, true);
- let result = expand_block(block, self);
+ let result = with_exts_frame!(self.cx.syntax_env, false, noop_fold_block(block, self));
self.cx.in_block = was_in_block;
result
}
- fn fold_arm(&mut self, arm: ast::Arm) -> ast::Arm {
- expand_arm(arm, self)
- }
-
fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> {
expand_annotatable(Annotatable::TraitItem(P(i)), self)
.into_iter().map(|i| i.expect_trait_item()).collect()
pub use self::SyntaxContext_::*;
-use ast::{Ident, Mrk, Name, SyntaxContext};
+use ast::{Mrk, SyntaxContext};
use std::cell::RefCell;
use std::collections::HashMap;
/// The SCTable contains a table of SyntaxContext_'s. It
/// represents a flattened tree structure, to avoid having
/// managed pointers everywhere (that caused an ICE).
-/// the `marks` and `renames` fields are side-tables
-/// that ensure that adding the same mark to the same context
-/// gives you back the same context as before. This should cut
-/// down on memory use *a lot*; applying a mark to a tree containing
-/// 50 identifiers would otherwise generate 50 new contexts.
+/// The `marks` ensures that adding the same mark to the
+/// same context gives you back the same context as before.
pub struct SCTable {
table: RefCell<Vec<SyntaxContext_>>,
marks: RefCell<HashMap<(SyntaxContext,Mrk),SyntaxContext>>,
- renames: RefCell<HashMap<Name,SyntaxContext>>,
}
#[derive(PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy, Clone)]
pub enum SyntaxContext_ {
EmptyCtxt,
Mark (Mrk,SyntaxContext),
- Rename (Name),
}
-/// A list of ident->name renamings
-pub type RenameList = Vec<(Ident, Name)>;
-
/// Extend a syntax context with a given mark
pub fn apply_mark(m: Mrk, ctxt: SyntaxContext) -> SyntaxContext {
with_sctable(|table| apply_mark_internal(m, ctxt, table))
}
}
-/// Extend a syntax context with a given rename
-pub fn apply_rename(from: Ident, to: Name, ident: Ident) -> Ident {
- with_sctable(|table| apply_rename_internal(from, to, ident, table))
-}
-
-/// Extend a syntax context with a given rename and sctable (explicit memoization)
-fn apply_rename_internal(from: Ident, to: Name, ident: Ident, table: &SCTable) -> Ident {
- if (ident.name, ident.ctxt) != (from.name, from.ctxt) {
- return ident;
- }
- let ctxt = *table.renames.borrow_mut().entry(to).or_insert_with(|| {
- SyntaxContext(idx_push(&mut *table.table.borrow_mut(), Rename(to)))
- });
- Ident { ctxt: ctxt, ..ident }
-}
-
-/// Apply a list of renamings to a context
-// if these rename lists get long, it would make sense
-// to consider memoizing this fold. This may come up
-// when we add hygiene to item names.
-pub fn apply_renames(renames: &RenameList, ident: Ident) -> Ident {
- renames.iter().fold(ident, |ident, &(from, to)| {
- apply_rename(from, to, ident)
- })
-}
-
/// Fetch the SCTable from TLS, create one if it doesn't yet exist.
pub fn with_sctable<T, F>(op: F) -> T where
F: FnOnce(&SCTable) -> T,
SCTable {
table: RefCell::new(vec![EmptyCtxt]),
marks: RefCell::new(HashMap::new()),
- renames: RefCell::new(HashMap::new()),
}
}
with_sctable(|table| {
*table.table.borrow_mut() = Vec::new();
*table.marks.borrow_mut() = HashMap::new();
- *table.renames.borrow_mut() = HashMap::new();
});
}
with_sctable(|table| {
*table.table.borrow_mut() = vec![EmptyCtxt];
*table.marks.borrow_mut() = HashMap::new();
- *table.renames.borrow_mut() = HashMap::new();
});
}
(vec.len() - 1) as u32
}
-/// Resolve a syntax object to a name, per MTWT.
-pub fn resolve(id: Ident) -> Name {
- with_sctable(|sctable| {
- resolve_internal(id, sctable)
- })
-}
-
-/// Resolve a syntax object to a name, per MTWT.
-/// adding memoization to resolve 500+ seconds in resolve for librustc (!)
-fn resolve_internal(id: Ident, table: &SCTable) -> Name {
- match table.table.borrow()[id.ctxt.0 as usize] {
- EmptyCtxt => id.name,
- // ignore marks here:
- Mark(_, subctxt) => resolve_internal(Ident::new(id.name, subctxt), table),
- Rename(name) => name,
- }
-}
-
/// Return the outer mark for a context with a mark at the outside.
/// FAILS when outside is not a mark.
pub fn outer_mark(ctxt: SyntaxContext) -> Mrk {