Skip to content

Commit c56b47a

Browse files
committed
Some TLC for the MoveMap trait
1 parent 0608b1d commit c56b47a

File tree

11 files changed

+131
-98
lines changed

11 files changed

+131
-98
lines changed

src/librustc_front/fold.rs

+7-37
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,7 @@ use syntax::codemap::{respan, Span, Spanned};
2020
use syntax::owned_slice::OwnedSlice;
2121
use syntax::ptr::P;
2222
use syntax::parse::token;
23-
use std::ptr;
24-
25-
// This could have a better place to live.
26-
pub trait MoveMap<T> {
27-
fn move_map<F>(self, f: F) -> Self where F: FnMut(T) -> T;
28-
}
29-
30-
impl<T> MoveMap<T> for Vec<T> {
31-
fn move_map<F>(mut self, mut f: F) -> Vec<T>
32-
where F: FnMut(T) -> T
33-
{
34-
for p in &mut self {
35-
unsafe {
36-
// FIXME(#5016) this shouldn't need to zero to be safe.
37-
ptr::write(p, f(ptr::read_and_drop(p)));
38-
}
39-
}
40-
self
41-
}
42-
}
43-
44-
impl<T> MoveMap<T> for OwnedSlice<T> {
45-
fn move_map<F>(self, f: F) -> OwnedSlice<T>
46-
where F: FnMut(T) -> T
47-
{
48-
OwnedSlice::from_vec(self.into_vec().move_map(f))
49-
}
50-
}
23+
use syntax::util::move_map::MoveMap;
5124

5225
pub trait Folder : Sized {
5326
// Any additions to this trait should happen in form
@@ -333,7 +306,7 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
333306
}
334307

335308
pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribute> {
336-
attrs.into_iter().flat_map(|x| fld.fold_attribute(x)).collect()
309+
attrs.move_flat_map(|x| fld.fold_attribute(x))
337310
}
338311

339312
pub fn noop_fold_arm<T: Folder>(Arm { attrs, pats, guard, body }: Arm, fld: &mut T) -> Arm {
@@ -771,7 +744,7 @@ pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
771744
b.map(|Block { id, stmts, expr, rules, span }| {
772745
Block {
773746
id: folder.new_id(id),
774-
stmts: stmts.into_iter().map(|s| folder.fold_stmt(s)).collect(),
747+
stmts: stmts.move_map(|s| folder.fold_stmt(s)),
775748
expr: expr.map(|x| folder.fold_expr(x)),
776749
rules: rules,
777750
span: folder.new_span(span),
@@ -818,9 +791,8 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
818791
ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
819792
}
820793
ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
821-
let new_impl_items = impl_items.into_iter()
822-
.map(|item| folder.fold_impl_item(item))
823-
.collect();
794+
let new_impl_items = impl_items
795+
.move_map(|item| folder.fold_impl_item(item));
824796
let ifce = match ifce {
825797
None => None,
826798
Some(ref trait_ref) => {
@@ -836,9 +808,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
836808
}
837809
ItemTrait(unsafety, generics, bounds, items) => {
838810
let bounds = folder.fold_bounds(bounds);
839-
let items = items.into_iter()
840-
.map(|item| folder.fold_trait_item(item))
841-
.collect();
811+
let items = items.move_map(|item| folder.fold_trait_item(item));
842812
ItemTrait(unsafety, folder.fold_generics(generics), bounds, items)
843813
}
844814
}
@@ -894,7 +864,7 @@ pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T) -> P<ImplI
894864
pub fn noop_fold_mod<T: Folder>(Mod { inner, item_ids }: Mod, folder: &mut T) -> Mod {
895865
Mod {
896866
inner: folder.new_span(inner),
897-
item_ids: item_ids.into_iter().map(|x| folder.fold_item_id(x)).collect(),
867+
items_ids: item_ids.move_map(|x| folder.fold_item_id(x)),
898868
}
899869
}
900870

src/librustc_front/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#![feature(slice_patterns)]
3636
#![feature(staged_api)]
3737
#![feature(str_char)]
38-
#![feature(filling_drop)]
3938

4039
extern crate serialize;
4140
#[macro_use]

src/libsyntax/ext/deriving/generic/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ use ext::build::AstBuilder;
204204
use codemap::{self, DUMMY_SP};
205205
use codemap::Span;
206206
use diagnostic::SpanHandler;
207-
use fold::MoveMap;
207+
use util::move_map::MoveMap;
208208
use owned_slice::OwnedSlice;
209209
use parse::token::{intern, InternedString};
210210
use parse::token::special_idents;

src/libsyntax/ext/expand.rs

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use ext::base::*;
2424
use feature_gate::{self, Features, GatedCfg};
2525
use fold;
2626
use fold::*;
27+
use util::move_map::MoveMap;
2728
use parse;
2829
use parse::token::{fresh_mark, fresh_name, intern};
2930
use ptr::P;

src/libsyntax/fold.rs

+13-35
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,11 @@ use codemap::{respan, Span, Spanned};
2626
use owned_slice::OwnedSlice;
2727
use parse::token;
2828
use ptr::P;
29-
use std::ptr;
3029
use util::small_vector::SmallVector;
30+
use util::move_map::MoveMap;
3131

3232
use std::rc::Rc;
3333

34-
// This could have a better place to live.
35-
pub trait MoveMap<T> {
36-
fn move_map<F>(self, f: F) -> Self where F: FnMut(T) -> T;
37-
}
38-
39-
impl<T> MoveMap<T> for Vec<T> {
40-
fn move_map<F>(mut self, mut f: F) -> Vec<T> where F: FnMut(T) -> T {
41-
for p in &mut self {
42-
unsafe {
43-
// FIXME(#5016) this shouldn't need to zero to be safe.
44-
ptr::write(p, f(ptr::read_and_drop(p)));
45-
}
46-
}
47-
self
48-
}
49-
}
50-
51-
impl<T> MoveMap<T> for OwnedSlice<T> {
52-
fn move_map<F>(self, f: F) -> OwnedSlice<T> where F: FnMut(T) -> T {
53-
OwnedSlice::from_vec(self.into_vec().move_map(f))
54-
}
55-
}
56-
5734
pub trait Folder : Sized {
5835
// Any additions to this trait should happen in form
5936
// of a call to a public `noop_*` function that only calls
@@ -362,7 +339,7 @@ pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<
362339
}
363340

364341
pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribute> {
365-
attrs.into_iter().flat_map(|x| fld.fold_attribute(x)).collect()
342+
attrs.move_flat_map(|x| fld.fold_attribute(x))
366343
}
367344

368345
pub fn fold_thin_attrs<T: Folder>(attrs: ThinAttributes, fld: &mut T) -> ThinAttributes {
@@ -623,6 +600,8 @@ pub fn noop_fold_tt<T: Folder>(tt: &TokenTree, fld: &mut T) -> TokenTree {
623600
}
624601

625602
pub fn noop_fold_tts<T: Folder>(tts: &[TokenTree], fld: &mut T) -> Vec<TokenTree> {
603+
// FIXME: Does this have to take a tts slice?
604+
// Could use move_map otherwise...
626605
tts.iter().map(|tt| fld.fold_tt(tt)).collect()
627606
}
628607

@@ -904,7 +883,7 @@ fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T)
904883
pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
905884
b.map(|Block {id, stmts, expr, rules, span}| Block {
906885
id: folder.new_id(id),
907-
stmts: stmts.into_iter().flat_map(|s| folder.fold_stmt(s).into_iter()).collect(),
886+
stmts: stmts.move_flat_map(|s| folder.fold_stmt(s).into_iter()),
908887
expr: expr.and_then(|x| folder.fold_opt_expr(x)),
909888
rules: rules,
910889
span: folder.new_span(span),
@@ -953,9 +932,9 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
953932
ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
954933
}
955934
ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
956-
let new_impl_items = impl_items.into_iter().flat_map(|item| {
957-
folder.fold_impl_item(item).into_iter()
958-
}).collect();
935+
let new_impl_items = impl_items.move_flat_map(|item| {
936+
folder.fold_impl_item(item)
937+
});
959938
let ifce = match ifce {
960939
None => None,
961940
Some(ref trait_ref) => {
@@ -971,9 +950,9 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
971950
}
972951
ItemTrait(unsafety, generics, bounds, items) => {
973952
let bounds = folder.fold_bounds(bounds);
974-
let items = items.into_iter().flat_map(|item| {
975-
folder.fold_trait_item(item).into_iter()
976-
}).collect();
953+
let items = items.move_flat_map(|item| {
954+
folder.fold_trait_item(item)
955+
});
977956
ItemTrait(unsafety,
978957
folder.fold_generics(generics),
979958
bounds,
@@ -1032,7 +1011,7 @@ pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T)
10321011
pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod {
10331012
Mod {
10341013
inner: folder.new_span(inner),
1035-
items: items.into_iter().flat_map(|x| folder.fold_item(x).into_iter()).collect(),
1014+
items: items.move_flat_map(|x| folder.fold_item(x)),
10361015
}
10371016
}
10381017

@@ -1353,8 +1332,7 @@ pub fn noop_fold_opt_expr<T: Folder>(e: P<Expr>, folder: &mut T) -> Option<P<Exp
13531332
}
13541333

13551334
pub fn noop_fold_exprs<T: Folder>(es: Vec<P<Expr>>, folder: &mut T) -> Vec<P<Expr>> {
1356-
// FIXME: Needs a efficient in-place flat_map
1357-
es.into_iter().flat_map(|e| folder.fold_opt_expr(e)).collect()
1335+
es.move_flat_map(|e| folder.fold_opt_expr(e))
13581336
}
13591337

13601338
pub fn noop_fold_stmt<T: Folder>(Spanned {node, span}: Stmt, folder: &mut T)

src/libsyntax/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub mod util {
7070
#[cfg(test)]
7171
pub mod parser_testing;
7272
pub mod small_vector;
73+
pub mod move_map;
7374
}
7475

7576
pub mod diagnostics {

src/libsyntax/print/pprust.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1653,8 +1653,6 @@ impl<'a> State<'a> {
16531653
}
16541654
if parse::classify::stmt_ends_with_semi(&st.node) {
16551655
try!(word(&mut self.s, ";"));
1656-
} else {
1657-
//try!(word(&mut self.s, ""));
16581656
}
16591657
self.maybe_print_trailing_comment(st.span, None)
16601658
}

src/libsyntax/test.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ use entry::{self, EntryPointType};
2929
use ext::base::ExtCtxt;
3030
use ext::build::AstBuilder;
3131
use ext::expand::ExpansionConfig;
32-
use fold::{Folder, MoveMap};
32+
use fold::Folder;
33+
use util::move_map::MoveMap;
3334
use fold;
3435
use owned_slice::OwnedSlice;
3536
use parse::token::{intern, InternedString};

src/libsyntax/util/move_map.rs

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use owned_slice::OwnedSlice;
12+
13+
use std::ptr;
14+
15+
pub trait MoveMap<T>: Sized {
16+
fn move_map<F>(self, mut f: F) -> Self where F: FnMut(T) -> T {
17+
self.move_flat_map(|e| Some(f(e)))
18+
}
19+
20+
fn move_flat_map<F, I>(self, f: F) -> Self
21+
where F: FnMut(T) -> I,
22+
I: IntoIterator<Item=T>;
23+
}
24+
25+
impl<T> MoveMap<T> for Vec<T> {
26+
fn move_flat_map<F, I>(mut self, mut f: F) -> Self
27+
where F: FnMut(T) -> I,
28+
I: IntoIterator<Item=T>
29+
{
30+
let mut read_i = 0;
31+
let mut write_i = 0;
32+
unsafe {
33+
let mut old_len = self.len();
34+
self.set_len(0); // make sure we just leak elements in case of panic
35+
36+
while read_i < old_len {
37+
// move the read_i'th item out of the vector and map it
38+
// to an iterator
39+
let e = ptr::read(self.get_unchecked(read_i));
40+
let mut iter = f(e).into_iter();
41+
read_i += 1;
42+
43+
while let Some(e) = iter.next() {
44+
if write_i < read_i {
45+
ptr::write(self.get_unchecked_mut(write_i), e);
46+
write_i += 1;
47+
} else {
48+
// If this is reached we ran out of space
49+
// in the middle of the vector.
50+
// However, the vector is in a valid state here,
51+
// so we just do a somewhat inefficient insert.
52+
self.set_len(old_len);
53+
self.insert(write_i, e);
54+
55+
old_len = self.len();
56+
self.set_len(0);
57+
58+
read_i += 1;
59+
write_i += 1;
60+
}
61+
}
62+
}
63+
64+
// write_i tracks the number of actually written new items.
65+
self.set_len(write_i);
66+
}
67+
68+
self
69+
}
70+
}
71+
72+
impl<T> MoveMap<T> for OwnedSlice<T> {
73+
fn move_flat_map<F, I>(self, f: F) -> Self
74+
where F: FnMut(T) -> I,
75+
I: IntoIterator<Item=T>
76+
{
77+
OwnedSlice::from_vec(self.into_vec().move_flat_map(f))
78+
}
79+
}

src/libsyntax/util/small_vector.rs

+23-17
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::mem;
1616
use std::slice;
1717
use std::vec;
1818

19-
use fold::MoveMap;
19+
use util::move_map::MoveMap;
2020

2121
/// A vector type optimized for cases where the size is almost always 0 or 1
2222
pub struct SmallVector<T> {
@@ -134,15 +134,6 @@ impl<T> SmallVector<T> {
134134
self.into_iter()
135135
}
136136

137-
pub fn into_iter(self) -> IntoIter<T> {
138-
let repr = match self.repr {
139-
Zero => ZeroIterator,
140-
One(v) => OneIterator(v),
141-
Many(vs) => ManyIterator(vs.into_iter())
142-
};
143-
IntoIter { repr: repr }
144-
}
145-
146137
pub fn len(&self) -> usize {
147138
match self.repr {
148139
Zero => 0,
@@ -154,6 +145,19 @@ impl<T> SmallVector<T> {
154145
pub fn is_empty(&self) -> bool { self.len() == 0 }
155146
}
156147

148+
impl<T> IntoIterator for SmallVector<T> {
149+
type Item = T;
150+
type IntoIter = IntoIter<T>;
151+
fn into_iter(self) -> Self::IntoIter {
152+
let repr = match self.repr {
153+
Zero => ZeroIterator,
154+
One(v) => OneIterator(v),
155+
Many(vs) => ManyIterator(vs.into_iter())
156+
};
157+
IntoIter { repr: repr }
158+
}
159+
}
160+
157161
pub struct IntoIter<T> {
158162
repr: IntoIterRepr<T>,
159163
}
@@ -192,13 +196,15 @@ impl<T> Iterator for IntoIter<T> {
192196
}
193197

194198
impl<T> MoveMap<T> for SmallVector<T> {
195-
fn move_map<F>(self, mut f: F) -> SmallVector<T> where F: FnMut(T) -> T {
196-
let repr = match self.repr {
197-
Zero => Zero,
198-
One(v) => One(f(v)),
199-
Many(vs) => Many(vs.move_map(f))
200-
};
201-
SmallVector { repr: repr }
199+
fn move_flat_map<F, I>(self, mut f: F) -> Self
200+
where F: FnMut(T) -> I,
201+
I: IntoIterator<Item=T>
202+
{
203+
match self.repr {
204+
Zero => Self::zero(),
205+
One(v) => f(v).into_iter().collect(),
206+
Many(vs) => SmallVector { repr: Many(vs.move_flat_map(f)) },
207+
}
202208
}
203209
}
204210

0 commit comments

Comments
 (0)