update fold_method to return a smallvector

This is nice for macros, to allow them to expand into multiple methods
This commit is contained in:
John Clements
2014-07-12 22:33:30 -07:00
parent b293a6604b
commit c4cc3ba130
3 changed files with 38 additions and 15 deletions

View File

@@ -114,7 +114,7 @@ pub trait Folder {
noop_fold_type_method(m, self)
}
fn fold_method(&mut self, m: Gc<Method>) -> Gc<Method> {
fn fold_method(&mut self, m: Gc<Method>) -> SmallVector<Gc<Method>> {
noop_fold_method(&*m, self)
}
@@ -465,10 +465,16 @@ fn fold_interpolated<T: Folder>(nt : &token::Nonterminal, fld: &mut T) -> token:
match *nt {
token::NtItem(item) =>
token::NtItem(fld.fold_item(item)
// this is probably okay, because the only folds likely
// to peek inside interpolated nodes will be renamings/markings,
// which map single items to single items
.expect_one("expected fold to produce exactly one item")),
token::NtBlock(block) => token::NtBlock(fld.fold_block(block)),
token::NtStmt(stmt) =>
token::NtStmt(fld.fold_stmt(stmt)
// this is probably okay, because the only folds likely
// to peek inside interpolated nodes will be renamings/markings,
// which map single items to single items
.expect_one("expected fold to produce exactly one statement")),
token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)),
token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)),
@@ -683,15 +689,26 @@ pub fn noop_fold_item_underscore<T: Folder>(i: &Item_, folder: &mut T) -> Item_
ItemImpl(fold_generics(generics, folder),
ifce.as_ref().map(|p| fold_trait_ref(p, folder)),
folder.fold_ty(ty),
methods.iter().map(|x| folder.fold_method(*x)).collect()
methods.iter().flat_map(|x| folder.fold_method(*x).move_iter()).collect()
)
}
ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
let methods = methods.iter().map(|method| {
match *method {
Required(ref m) => Required(folder.fold_type_method(m)),
Provided(method) => Provided(folder.fold_method(method))
}
let methods = methods.iter().flat_map(|method| {
let r = match *method {
Required(ref m) =>
SmallVector::one(Required(folder.fold_type_method(m))).move_iter(),
Provided(method) => {
// the awkward collect/iter idiom here is because
// even though an iter and a map satisfy the same trait bound,
// they're not actually the same type, so the method arms
// don't unify.
let methods : SmallVector<ast::TraitMethod> =
folder.fold_method(method).move_iter()
.map(|m| Provided(m)).collect();
methods.move_iter()
}
};
r
}).collect();
ItemTrait(fold_generics(generics, folder),
unbound.clone(),
@@ -791,9 +808,11 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem,
}
}
pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> Gc<Method> {
// Default fold over a method.
// Invariant: produces exactly one method.
pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> SmallVector<Gc<Method>> {
let id = folder.new_id(m.id); // Needs to be first, for ast_map.
box(GC) Method {
SmallVector::one(box(GC) Method {
attrs: m.attrs.iter().map(|a| folder.fold_attribute(*a)).collect(),
id: id,
span: folder.new_span(m.span),
@@ -809,7 +828,7 @@ pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> Gc<Method> {
},
MethMac(ref mac) => MethMac(folder.fold_mac(mac)),
}
}
})
}
pub fn noop_fold_pat<T: Folder>(p: Gc<Pat>, folder: &mut T) -> Gc<Pat> {