Skip to content

Commit c4cc3ba

Browse files
committed
update fold_method to return a smallvector
This is nice for macros, to allow them to expand into multiple methods
1 parent b293a66 commit c4cc3ba

File tree

3 files changed

+38
-15
lines changed

3 files changed

+38
-15
lines changed

src/librustc/middle/astencode.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,9 @@ fn simplify_ast(ii: e::InlinedItemRef) -> ast::InlinedItem {
345345
// HACK we're not dropping items.
346346
e::IIItemRef(i) => ast::IIItem(fold::noop_fold_item(i, &mut fld)
347347
.expect_one("expected one item")),
348-
e::IIMethodRef(d, p, m) => ast::IIMethod(d, p, fold::noop_fold_method(m, &mut fld)),
348+
e::IIMethodRef(d, p, m) => ast::IIMethod(d, p, fold::noop_fold_method(m, &mut fld)
349+
.expect_one(
350+
"noop_fold_method must produce exactly one method")),
349351
e::IIForeignRef(i) => ast::IIForeign(fold::noop_fold_foreign_item(i, &mut fld))
350352
}
351353
}
@@ -387,7 +389,8 @@ fn renumber_and_map_ast(xcx: &ExtendedDecodeContext,
387389
ast::IIItem(fld.fold_item(i).expect_one("expected one item"))
388390
}
389391
ast::IIMethod(d, is_provided, m) => {
390-
ast::IIMethod(xcx.tr_def_id(d), is_provided, fld.fold_method(m))
392+
ast::IIMethod(xcx.tr_def_id(d), is_provided, fld.fold_method(m)
393+
.expect_one("expected one method"))
391394
}
392395
ast::IIForeign(i) => ast::IIForeign(fld.fold_foreign_item(i))
393396
}

src/libsyntax/ast_map.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -571,13 +571,14 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
571571
m
572572
}
573573

574-
fn fold_method(&mut self, m: Gc<Method>) -> Gc<Method> {
574+
fn fold_method(&mut self, m: Gc<Method>) -> SmallVector<Gc<Method>> {
575575
let parent = self.parent;
576576
self.parent = DUMMY_NODE_ID;
577-
let m = fold::noop_fold_method(&*m, self);
577+
let m = fold::noop_fold_method(&*m, self).expect_one(
578+
"noop_fold_method must produce exactly one method");
578579
assert_eq!(self.parent, m.id);
579580
self.parent = parent;
580-
m
581+
SmallVector::one(m)
581582
}
582583

583584
fn fold_fn_decl(&mut self, decl: &FnDecl) -> P<FnDecl> {

src/libsyntax/fold.rs

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ pub trait Folder {
114114
noop_fold_type_method(m, self)
115115
}
116116

117-
fn fold_method(&mut self, m: Gc<Method>) -> Gc<Method> {
117+
fn fold_method(&mut self, m: Gc<Method>) -> SmallVector<Gc<Method>> {
118118
noop_fold_method(&*m, self)
119119
}
120120

@@ -465,10 +465,16 @@ fn fold_interpolated<T: Folder>(nt : &token::Nonterminal, fld: &mut T) -> token:
465465
match *nt {
466466
token::NtItem(item) =>
467467
token::NtItem(fld.fold_item(item)
468+
// this is probably okay, because the only folds likely
469+
// to peek inside interpolated nodes will be renamings/markings,
470+
// which map single items to single items
468471
.expect_one("expected fold to produce exactly one item")),
469472
token::NtBlock(block) => token::NtBlock(fld.fold_block(block)),
470473
token::NtStmt(stmt) =>
471474
token::NtStmt(fld.fold_stmt(stmt)
475+
// this is probably okay, because the only folds likely
476+
// to peek inside interpolated nodes will be renamings/markings,
477+
// which map single items to single items
472478
.expect_one("expected fold to produce exactly one statement")),
473479
token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)),
474480
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_
683689
ItemImpl(fold_generics(generics, folder),
684690
ifce.as_ref().map(|p| fold_trait_ref(p, folder)),
685691
folder.fold_ty(ty),
686-
methods.iter().map(|x| folder.fold_method(*x)).collect()
692+
methods.iter().flat_map(|x| folder.fold_method(*x).move_iter()).collect()
687693
)
688694
}
689695
ItemTrait(ref generics, ref unbound, ref traits, ref methods) => {
690-
let methods = methods.iter().map(|method| {
691-
match *method {
692-
Required(ref m) => Required(folder.fold_type_method(m)),
693-
Provided(method) => Provided(folder.fold_method(method))
694-
}
696+
let methods = methods.iter().flat_map(|method| {
697+
let r = match *method {
698+
Required(ref m) =>
699+
SmallVector::one(Required(folder.fold_type_method(m))).move_iter(),
700+
Provided(method) => {
701+
// the awkward collect/iter idiom here is because
702+
// even though an iter and a map satisfy the same trait bound,
703+
// they're not actually the same type, so the method arms
704+
// don't unify.
705+
let methods : SmallVector<ast::TraitMethod> =
706+
folder.fold_method(method).move_iter()
707+
.map(|m| Provided(m)).collect();
708+
methods.move_iter()
709+
}
710+
};
711+
r
695712
}).collect();
696713
ItemTrait(fold_generics(generics, folder),
697714
unbound.clone(),
@@ -791,9 +808,11 @@ pub fn noop_fold_foreign_item<T: Folder>(ni: &ForeignItem,
791808
}
792809
}
793810

794-
pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> Gc<Method> {
811+
// Default fold over a method.
812+
// Invariant: produces exactly one method.
813+
pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> SmallVector<Gc<Method>> {
795814
let id = folder.new_id(m.id); // Needs to be first, for ast_map.
796-
box(GC) Method {
815+
SmallVector::one(box(GC) Method {
797816
attrs: m.attrs.iter().map(|a| folder.fold_attribute(*a)).collect(),
798817
id: id,
799818
span: folder.new_span(m.span),
@@ -809,7 +828,7 @@ pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> Gc<Method> {
809828
},
810829
MethMac(ref mac) => MethMac(folder.fold_mac(mac)),
811830
}
812-
}
831+
})
813832
}
814833

815834
pub fn noop_fold_pat<T: Folder>(p: Gc<Pat>, folder: &mut T) -> Gc<Pat> {

0 commit comments

Comments
 (0)