Skip to content

Commit 211012b

Browse files
committed
Add namespace support for rename operation
Maintains two renaming tables, one for regular idents and one for lifetime idents (a loop label is of lifetime kind) so that let bindings and loop labels with same name won't clash. Closes rust-lang#12512.
1 parent 8a55cd9 commit 211012b

File tree

9 files changed

+188
-77
lines changed

9 files changed

+188
-77
lines changed

src/librustc/middle/resolve.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4177,7 +4177,7 @@ impl Resolver {
41774177
fn binding_mode_map(&mut self, pat: @Pat) -> BindingMap {
41784178
let mut result = HashMap::new();
41794179
pat_bindings(self.def_map, pat, |binding_mode, _id, sp, path| {
4180-
let name = mtwt::resolve(path_to_ident(path));
4180+
let name = mtwt::resolve(path_to_ident(path), PlainIdent);
41814181
result.insert(name,
41824182
binding_info {span: sp,
41834183
binding_mode: binding_mode});
@@ -4412,7 +4412,7 @@ impl Resolver {
44124412
// what you want).
44134413

44144414
let ident = path.segments.get(0).identifier;
4415-
let renamed = mtwt::resolve(ident);
4415+
let renamed = mtwt::resolve(ident, PlainIdent);
44164416

44174417
match self.resolve_bare_identifier_pattern(ident) {
44184418
FoundStructOrEnumVariant(def, lp)
@@ -4966,7 +4966,7 @@ impl Resolver {
49664966
let search_result;
49674967
match namespace {
49684968
ValueNS => {
4969-
let renamed = mtwt::resolve(ident);
4969+
let renamed = mtwt::resolve(ident, PlainIdent);
49704970
let mut value_ribs = self.value_ribs.borrow_mut();
49714971
search_result = self.search_ribs(value_ribs.get(),
49724972
renamed,
@@ -5214,7 +5214,7 @@ impl Resolver {
52145214
let rib = label_ribs.get()[label_ribs.get().len() -
52155215
1];
52165216
let mut bindings = rib.bindings.borrow_mut();
5217-
let renamed = mtwt::resolve(label);
5217+
let renamed = mtwt::resolve(label, LifetimeIdent);
52185218
bindings.get().insert(renamed, def_like);
52195219
}
52205220

@@ -5226,7 +5226,7 @@ impl Resolver {
52265226

52275227
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
52285228
let mut label_ribs = self.label_ribs.borrow_mut();
5229-
let renamed = mtwt::resolve(label);
5229+
let renamed = mtwt::resolve(label, LifetimeIdent);
52305230
match self.search_ribs(label_ribs.get(), renamed, expr.span) {
52315231
None =>
52325232
self.resolve_error(expr.span,

src/libsyntax/ast.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ impl Eq for Ident {
7575
}
7676
}
7777

78+
// This can not be more fine-grained because of loop label. It starts
79+
// as a `token::LIFETIME` then becomes part of `ExprLoop`, `ExprForLoop`,
80+
// `ExprBreak` or `ExprAgain` and is represented as an `ast::Ident`, not
81+
// an `ast::Lifetime` as others do. Even so, it is still considered to
82+
// be one of LifetimeIdent.
83+
#[deriving(Clone, Eq, Encodable, Decodable, Hash)]
84+
pub enum IdentKind {
85+
PlainIdent,
86+
LifetimeIdent
87+
}
88+
7889
/// A SyntaxContext represents a chain of macro-expandings
7990
/// and renamings. Each macro expansion corresponds to
8091
/// a fresh uint

src/libsyntax/ext/base.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,20 +148,24 @@ pub struct BlockInfo {
148148
// should macros escape from this scope?
149149
macros_escape: bool,
150150
// what are the pending renames?
151-
pending_renames: RenameList,
151+
pending_renames: RenameLists,
152152
}
153153

154154
impl BlockInfo {
155155
pub fn new() -> BlockInfo {
156156
BlockInfo {
157157
macros_escape: false,
158-
pending_renames: Vec::new(),
158+
pending_renames: RenameLists { plain: Vec::new(), lifetime: Vec::new() },
159159
}
160160
}
161161
}
162162

163163
// a list of ident->name renamings
164164
pub type RenameList = Vec<(ast::Ident, Name)>;
165+
pub struct RenameLists {
166+
plain: RenameList,
167+
lifetime: RenameList
168+
}
165169

166170
// The base map of methods for expanding syntax extension
167171
// AST nodes into full ASTs

src/libsyntax/ext/expand.rs

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use ast::{P, Block, Crate, DeclLocal, ExprMac};
1212
use ast::{Local, Ident, MacInvocTT};
1313
use ast::{ItemMac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi};
14-
use ast::TokenTree;
14+
use ast::{IdentKind, LifetimeIdent, PlainIdent, TokenTree};
1515
use ast;
1616
use ext::mtwt;
1717
use ext::build::AstBuilder;
@@ -228,15 +228,15 @@ fn expand_loop_block(loop_block: P<Block>,
228228
// syntax context otherwise an unrelated `break` or `continue` in
229229
// the same context will pick that up in the deferred renaming pass
230230
// and be renamed incorrectly.
231-
let mut rename_list = vec!(rename);
231+
let mut rename_list = RenameLists { plain: Vec::new(), lifetime: vec!(rename)};
232232
let mut rename_fld = renames_to_fold(&mut rename_list);
233-
let renamed_ident = rename_fld.fold_ident(label);
233+
let renamed_ident = rename_fld.fold_ident(label, LifetimeIdent);
234234

235235
// The rename *must* be added to the enclosed syntax context for
236236
// `break` or `continue` to pick up because by definition they are
237237
// in a block enclosed by loop head.
238238
fld.extsbox.push_frame();
239-
fld.extsbox.info().pending_renames.push(rename);
239+
fld.extsbox.info().pending_renames.lifetime.push(rename);
240240
let expanded_block = expand_block_elts(loop_block, fld);
241241
fld.extsbox.pop_frame();
242242

@@ -627,10 +627,11 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
627627
let mut name_finder = new_name_finder(Vec::new());
628628
name_finder.visit_pat(expanded_pat,());
629629
// generate fresh names, push them to a new pending list
630-
let mut new_pending_renames = Vec::new();
630+
let mut new_pending_renames = RenameLists { plain: Vec::new(),
631+
lifetime: Vec::new() };
631632
for ident in name_finder.ident_accumulator.iter() {
632633
let new_name = fresh_name(ident);
633-
new_pending_renames.push((*ident,new_name));
634+
new_pending_renames.plain.push((*ident,new_name));
634635
}
635636
let rewritten_pat = {
636637
let mut rename_fld =
@@ -640,7 +641,8 @@ fn expand_non_macro_stmt(s: &Stmt, fld: &mut MacroExpander)
640641
rename_fld.fold_pat(expanded_pat)
641642
};
642643
// add them to the existing pending renames:
643-
fld.extsbox.info().pending_renames.push_all_move(new_pending_renames);
644+
fld.extsbox.info().pending_renames
645+
.plain.push_all_move(new_pending_renames.plain);
644646
// also, don't forget to expand the init:
645647
let new_init_opt = init.map(|e| fld.fold_expr(e));
646648
let rewritten_local =
@@ -760,13 +762,17 @@ pub fn expand_block_elts(b: &Block, fld: &mut MacroExpander) -> P<Block> {
760762
}
761763

762764
pub struct IdentRenamer<'a> {
763-
renames: &'a mut RenameList,
765+
renames: &'a mut RenameLists,
764766
}
765767

766768
impl<'a> Folder for IdentRenamer<'a> {
767-
fn fold_ident(&mut self, id: Ident) -> Ident {
768-
let new_ctxt = self.renames.iter().fold(id.ctxt, |ctxt, &(from, to)| {
769-
mtwt::new_rename(from, to, ctxt)
769+
fn fold_ident(&mut self, id: Ident, ns: IdentKind) -> Ident {
770+
let rs = match ns {
771+
PlainIdent => &self.renames.plain,
772+
LifetimeIdent => &self.renames.lifetime
773+
};
774+
let new_ctxt = rs.iter().fold(id.ctxt, |ctxt, &(from, to)| {
775+
mtwt::new_rename(from, to, ctxt, ns)
770776
});
771777
Ident {
772778
name: id.name,
@@ -777,7 +783,7 @@ impl<'a> Folder for IdentRenamer<'a> {
777783

778784
// given a mutable list of renames, return a tree-folder that applies those
779785
// renames.
780-
pub fn renames_to_fold<'a>(renames: &'a mut RenameList) -> IdentRenamer<'a> {
786+
pub fn renames_to_fold<'a>(renames: &'a mut RenameLists) -> IdentRenamer<'a> {
781787
IdentRenamer {
782788
renames: renames,
783789
}
@@ -849,18 +855,18 @@ pub fn expand_crate(parse_sess: @parse::ParseSess,
849855
struct Marker { mark: Mrk }
850856

851857
impl Folder for Marker {
852-
fn fold_ident(&mut self, id: Ident) -> Ident {
858+
fn fold_ident(&mut self, id: Ident, ns: IdentKind) -> Ident {
853859
ast::Ident {
854860
name: id.name,
855-
ctxt: mtwt::new_mark(self.mark, id.ctxt)
861+
ctxt: mtwt::new_mark(self.mark, id.ctxt, ns)
856862
}
857863
}
858864
fn fold_mac(&mut self, m: &ast::Mac) -> ast::Mac {
859865
let macro = match m.node {
860866
MacInvocTT(ref path, ref tts, ctxt) => {
861867
MacInvocTT(self.fold_path(path),
862868
fold_tts(tts.as_slice(), self),
863-
mtwt::new_mark(self.mark, ctxt))
869+
mtwt::new_mark(self.mark, ctxt, PlainIdent))
864870
}
865871
};
866872
Spanned {
@@ -1148,8 +1154,9 @@ mod test {
11481154
// must be one check clause for each binding:
11491155
assert_eq!(bindings.len(),bound_connections.len());
11501156
for (binding_idx,shouldmatch) in bound_connections.iter().enumerate() {
1151-
let binding_name = mtwt::resolve(*bindings.get(binding_idx));
1152-
let binding_marks = mtwt::marksof(bindings.get(binding_idx).ctxt, invalid_name);
1157+
let binding_name = mtwt::resolve(*bindings.get(binding_idx), ast::PlainIdent);
1158+
let binding_marks = mtwt::marksof(bindings.get(binding_idx).ctxt,
1159+
invalid_name, ast::PlainIdent);
11531160
// shouldmatch can't name varrefs that don't exist:
11541161
assert!((shouldmatch.len() == 0) ||
11551162
(varrefs.len() > *shouldmatch.iter().max().unwrap()));
@@ -1160,17 +1167,18 @@ mod test {
11601167
assert_eq!(varref.segments.len(),1);
11611168
let varref_name = mtwt::resolve(varref.segments
11621169
.get(0)
1163-
.identifier);
1170+
.identifier,
1171+
ast::PlainIdent);
11641172
let varref_marks = mtwt::marksof(varref.segments
11651173
.get(0)
11661174
.identifier
11671175
.ctxt,
1168-
invalid_name);
1176+
invalid_name, ast::PlainIdent);
11691177
if !(varref_name==binding_name) {
11701178
println!("uh oh, should match but doesn't:");
11711179
println!("varref: {:?}",varref);
11721180
println!("binding: {:?}", *bindings.get(binding_idx));
1173-
mtwt::with_sctable(|x| mtwt::display_sctable(x));
1181+
mtwt::with_sctable(ast::PlainIdent, |x| mtwt::display_sctable(x));
11741182
}
11751183
assert_eq!(varref_name,binding_name);
11761184
if bound_ident_check {
@@ -1180,7 +1188,7 @@ mod test {
11801188
}
11811189
} else {
11821190
let fail = (varref.segments.len() == 1)
1183-
&& (mtwt::resolve(varref.segments.get(0).identifier)
1191+
&& (mtwt::resolve(varref.segments.get(0).identifier, ast::PlainIdent)
11841192
== binding_name);
11851193
// temp debugging:
11861194
if fail {
@@ -1197,7 +1205,7 @@ mod test {
11971205
varref.segments.get(0).identifier.name,
11981206
string.get());
11991207
println!("binding: {:?}", *bindings.get(binding_idx));
1200-
mtwt::with_sctable(|x| mtwt::display_sctable(x));
1208+
mtwt::with_sctable(ast::PlainIdent, |x| mtwt::display_sctable(x));
12011209
}
12021210
assert!(!fail);
12031211
}
@@ -1227,7 +1235,7 @@ foo_module!()
12271235
[b] => b,
12281236
_ => fail!("expected just one binding for ext_cx")
12291237
};
1230-
let resolved_binding = mtwt::resolve(*cxbind);
1238+
let resolved_binding = mtwt::resolve(*cxbind, ast::PlainIdent);
12311239
// find all the xx varrefs:
12321240
let mut path_finder = new_path_finder(Vec::new());
12331241
visit::walk_crate(&mut path_finder, &cr, ());
@@ -1238,17 +1246,17 @@ foo_module!()
12381246
p.segments.len() == 1
12391247
&& "xx" == token::get_ident(p.segments.get(0).identifier).get()
12401248
}).enumerate() {
1241-
if mtwt::resolve(v.segments.get(0).identifier) != resolved_binding {
1249+
if mtwt::resolve(v.segments.get(0).identifier, ast::PlainIdent) != resolved_binding {
12421250
println!("uh oh, xx binding didn't match xx varref:");
12431251
println!("this is xx varref \\# {:?}",idx);
12441252
println!("binding: {:?}",cxbind);
12451253
println!("resolves to: {:?}",resolved_binding);
12461254
println!("varref: {:?}",v.segments.get(0).identifier);
12471255
println!("resolves to: {:?}",
1248-
mtwt::resolve(v.segments.get(0).identifier));
1249-
mtwt::with_sctable(|x| mtwt::display_sctable(x));
1256+
mtwt::resolve(v.segments.get(0).identifier, ast::PlainIdent));
1257+
mtwt::with_sctable(ast::PlainIdent, |x| mtwt::display_sctable(x));
12501258
}
1251-
assert_eq!(mtwt::resolve(v.segments.get(0).identifier),
1259+
assert_eq!(mtwt::resolve(v.segments.get(0).identifier, ast::PlainIdent),
12521260
resolved_binding);
12531261
};
12541262
}

0 commit comments

Comments
 (0)