Skip to content

Commit 165cc9e

Browse files
committed
auto merge of #5213 : erickt/rust/vec-ref, r=graydon
This patch series changes a handful of vec functions to return references instead of copies. The one downside with making this change is that these functions aren't usable in a couple cases now due to some purity complaints. For example, this [change](erickt@c31e81a#L1R87). I couldn't figure out a way to get `last` to work on a `@mut ~[...]` type, so I ended up having to use `*crate_cache[crate_cache.len() - 1].metas`.
2 parents 7c9b808 + 743cfce commit 165cc9e

26 files changed

+308
-183
lines changed

src/libcore/vec.rs

+167-69
Original file line numberDiff line numberDiff line change
@@ -211,40 +211,41 @@ pub pure fn build_sized_opt<A>(size: Option<uint>,
211211
// Accessors
212212

213213
/// Returns the first element of a vector
214-
pub pure fn head<T:Copy>(v: &[const T]) -> T { v[0] }
215-
216-
/// Returns a vector containing all but the first element of a slice
217-
pub pure fn tail<T:Copy>(v: &[const T]) -> ~[T] {
218-
slice(v, 1u, len(v)).to_vec()
214+
pub pure fn head<T>(v: &r/[T]) -> &r/T {
215+
if v.len() == 0 { fail!(~"head: empty vector") }
216+
&v[0]
219217
}
220218
221-
/**
222-
* Returns a vector containing all but the first `n` \
223-
* elements of a slice
224-
*/
225-
pub pure fn tailn<T:Copy>(v: &[const T], n: uint) -> ~[T] {
226-
slice(v, n, len(v)).to_vec()
219+
/// Returns `Some(x)` where `x` is the first element of the slice `v`,
220+
/// or `None` if the vector is empty.
221+
pub pure fn head_opt<T>(v: &r/[T]) -> Option<&r/T> {
222+
if v.len() == 0 { None } else { Some(&v[0]) }
227223
}
228224
225+
/// Returns a vector containing all but the first element of a slice
226+
pub pure fn tail<T>(v: &r/[T]) -> &r/[T] { slice(v, 1, v.len()) }
227+
228+
/// Returns a vector containing all but the first `n` elements of a slice
229+
pub pure fn tailn<T>(v: &r/[T], n: uint) -> &r/[T] { slice(v, n, v.len()) }
230+
229231
/// Returns a vector containing all but the last element of a slice
230-
pub pure fn init<T:Copy>(v: &[const T]) -> ~[T] {
231-
assert len(v) != 0u;
232-
slice(v, 0u, len(v) - 1u).to_vec()
232+
pub pure fn init<T>(v: &r/[T]) -> &r/[T] { slice(v, 0, v.len() - 1) }
233+
234+
/// Returns a vector containing all but the last `n' elements of a slice
235+
pub pure fn initn<T>(v: &r/[T], n: uint) -> &r/[T] {
236+
slice(v, 0, v.len() - n)
233237
}
234238
235239
/// Returns the last element of the slice `v`, failing if the slice is empty.
236-
pub pure fn last<T:Copy>(v: &[const T]) -> T {
237-
if len(v) == 0u { fail!(~"last_unsafe: empty vector") }
238-
v[len(v) - 1u]
240+
pub pure fn last<T>(v: &r/[T]) -> &r/T {
241+
if v.len() == 0 { fail!(~"last: empty vector") }
242+
&v[v.len() - 1]
239243
}
240244
241-
/**
242-
* Returns `Some(x)` where `x` is the last element of the slice `v`,
243-
* or `none` if the vector is empty.
244-
*/
245-
pub pure fn last_opt<T:Copy>(v: &[const T]) -> Option<T> {
246-
if len(v) == 0u { return None; }
247-
Some(v[len(v) - 1u])
245+
/// Returns `Some(x)` where `x` is the last element of the slice `v`, or
246+
/// `None` if the vector is empty.
247+
pub pure fn last_opt<T>(v: &r/[T]) -> Option<&r/T> {
248+
if v.len() == 0 { None } else { Some(&v[v.len() - 1]) }
248249
}
249250
250251
/// Return a slice that points into another slice.
@@ -1692,41 +1693,29 @@ impl<T> Container for &[const T] {
16921693
}
16931694

16941695
pub trait CopyableVector<T> {
1695-
pure fn head(&self) -> T;
1696-
pure fn init(&self) -> ~[T];
1697-
pure fn last(&self) -> T;
16981696
pure fn slice(&self, start: uint, end: uint) -> ~[T];
1699-
pure fn tail(&self) -> ~[T];
17001697
}
17011698

17021699
/// Extension methods for vectors
1703-
impl<T:Copy> CopyableVector<T> for &[const T] {
1704-
/// Returns the first element of a vector
1705-
#[inline]
1706-
pure fn head(&self) -> T { head(*self) }
1707-
1708-
/// Returns all but the last elemnt of a vector
1709-
#[inline]
1710-
pure fn init(&self) -> ~[T] { init(*self) }
1711-
1712-
/// Returns the last element of a `v`, failing if the vector is empty.
1713-
#[inline]
1714-
pure fn last(&self) -> T { last(*self) }
1715-
1700+
impl<T: Copy> CopyableVector<T> for &[const T] {
17161701
/// Returns a copy of the elements from [`start`..`end`) from `v`.
17171702
#[inline]
17181703
pure fn slice(&self, start: uint, end: uint) -> ~[T] {
17191704
slice(*self, start, end).to_vec()
17201705
}
1721-
1722-
/// Returns all but the first element of a vector
1723-
#[inline]
1724-
pure fn tail(&self) -> ~[T] { tail(*self) }
17251706
}
17261707

17271708
pub trait ImmutableVector<T> {
17281709
pure fn view(&self, start: uint, end: uint) -> &self/[T];
1729-
pure fn foldr<U:Copy>(&self, z: U, p: fn(t: &T, u: U) -> U) -> U;
1710+
pure fn head(&self) -> &self/T;
1711+
pure fn head_opt(&self) -> Option<&self/T>;
1712+
pure fn tail(&self) -> &self/[T];
1713+
pure fn tailn(&self, n: uint) -> &self/[T];
1714+
pure fn init(&self) -> &self/[T];
1715+
pure fn initn(&self, n: uint) -> &self/[T];
1716+
pure fn last(&self) -> &self/T;
1717+
pure fn last_opt(&self) -> Option<&self/T>;
1718+
pure fn foldr<U: Copy>(&self, z: U, p: fn(t: &T, u: U) -> U) -> U;
17301719
pure fn map<U>(&self, f: fn(t: &T) -> U) -> ~[U];
17311720
pure fn mapi<U>(&self, f: fn(uint, t: &T) -> U) -> ~[U];
17321721
fn map_r<U>(&self, f: fn(x: &T) -> U) -> ~[U];
@@ -1743,6 +1732,38 @@ impl<T> ImmutableVector<T> for &[T] {
17431732
slice(*self, start, end)
17441733
}
17451734

1735+
/// Returns the first element of a vector, failing if the vector is empty.
1736+
#[inline]
1737+
pure fn head(&self) -> &self/T { head(*self) }
1738+
1739+
/// Returns the first element of a vector
1740+
#[inline]
1741+
pure fn head_opt(&self) -> Option<&self/T> { head_opt(*self) }
1742+
1743+
/// Returns all but the first element of a vector
1744+
#[inline]
1745+
pure fn tail(&self) -> &self/[T] { tail(*self) }
1746+
1747+
/// Returns all but the first `n' elements of a vector
1748+
#[inline]
1749+
pure fn tailn(&self, n: uint) -> &self/[T] { tailn(*self, n) }
1750+
1751+
/// Returns all but the last elemnt of a vector
1752+
#[inline]
1753+
pure fn init(&self) -> &self/[T] { init(*self) }
1754+
1755+
/// Returns all but the last `n' elemnts of a vector
1756+
#[inline]
1757+
pure fn initn(&self, n: uint) -> &self/[T] { initn(*self, n) }
1758+
1759+
/// Returns the last element of a `v`, failing if the vector is empty.
1760+
#[inline]
1761+
pure fn last(&self) -> &self/T { last(*self) }
1762+
1763+
/// Returns the last element of a `v`, failing if the vector is empty.
1764+
#[inline]
1765+
pure fn last_opt(&self) -> Option<&self/T> { last_opt(*self) }
1766+
17461767
/// Reduce a vector from right to left
17471768
#[inline]
17481769
pure fn foldr<U:Copy>(&self, z: U, p: fn(t: &T, u: U) -> U) -> U {
@@ -2570,27 +2591,117 @@ mod tests {
25702591

25712592
#[test]
25722593
fn test_head() {
2573-
let a = ~[11, 12];
2574-
assert (head(a) == 11);
2594+
let mut a = ~[11];
2595+
assert a.head() == &11;
2596+
a = ~[11, 12];
2597+
assert a.head() == &11;
2598+
}
2599+
2600+
#[test]
2601+
#[should_fail]
2602+
#[ignore(cfg(windows))]
2603+
fn test_head_empty() {
2604+
let a: ~[int] = ~[];
2605+
a.head();
2606+
}
2607+
2608+
#[test]
2609+
fn test_head_opt() {
2610+
let mut a = ~[];
2611+
assert a.head_opt() == None;
2612+
a = ~[11];
2613+
assert a.head_opt().unwrap() == &11;
2614+
a = ~[11, 12];
2615+
assert a.head_opt().unwrap() == &11;
25752616
}
25762617

25772618
#[test]
25782619
fn test_tail() {
25792620
let mut a = ~[11];
2580-
assert (tail(a) == ~[]);
2621+
assert a.tail() == &[];
2622+
a = ~[11, 12];
2623+
assert a.tail() == &[12];
2624+
}
2625+
2626+
#[test]
2627+
#[should_fail]
2628+
#[ignore(cfg(windows))]
2629+
fn test_tail_empty() {
2630+
let a: ~[int] = ~[];
2631+
a.tail();
2632+
}
25812633

2634+
#[test]
2635+
fn test_tailn() {
2636+
let mut a = ~[11, 12, 13];
2637+
assert a.tailn(0) == &[11, 12, 13];
2638+
a = ~[11, 12, 13];
2639+
assert a.tailn(2) == &[13];
2640+
}
2641+
2642+
#[test]
2643+
#[should_fail]
2644+
#[ignore(cfg(windows))]
2645+
fn test_tailn_empty() {
2646+
let a: ~[int] = ~[];
2647+
a.tailn(2);
2648+
}
2649+
2650+
#[test]
2651+
fn test_init() {
2652+
let mut a = ~[11];
2653+
assert a.init() == &[];
25822654
a = ~[11, 12];
2583-
assert (tail(a) == ~[12]);
2655+
assert a.init() == &[11];
2656+
}
2657+
2658+
#[init]
2659+
#[should_fail]
2660+
#[ignore(cfg(windows))]
2661+
fn test_init_empty() {
2662+
let a: ~[int] = ~[];
2663+
a.init();
2664+
}
2665+
2666+
#[test]
2667+
fn test_initn() {
2668+
let mut a = ~[11, 12, 13];
2669+
assert a.initn(0) == &[11, 12, 13];
2670+
a = ~[11, 12, 13];
2671+
assert a.initn(2) == &[11];
2672+
}
2673+
2674+
#[init]
2675+
#[should_fail]
2676+
#[ignore(cfg(windows))]
2677+
fn test_initn_empty() {
2678+
let a: ~[int] = ~[];
2679+
a.initn(2);
25842680
}
25852681

25862682
#[test]
25872683
fn test_last() {
2588-
let mut n = last_opt(~[]);
2589-
assert (n.is_none());
2590-
n = last_opt(~[1, 2, 3]);
2591-
assert (n == Some(3));
2592-
n = last_opt(~[1, 2, 3, 4, 5]);
2593-
assert (n == Some(5));
2684+
let mut a = ~[11];
2685+
assert a.last() == &11;
2686+
a = ~[11, 12];
2687+
assert a.last() == &12;
2688+
}
2689+
2690+
#[test]
2691+
#[should_fail]
2692+
fn test_last_empty() {
2693+
let a: ~[int] = ~[];
2694+
a.last();
2695+
}
2696+
2697+
#[test]
2698+
fn test_last_opt() {
2699+
let mut a = ~[];
2700+
assert a.last_opt() == None;
2701+
a = ~[11];
2702+
assert a.last_opt().unwrap() == &11;
2703+
a = ~[11, 12];
2704+
assert a.last_opt().unwrap() == &12;
25942705
}
25952706

25962707
#[test]
@@ -3262,12 +3373,6 @@ mod tests {
32623373
assert (v2[1] == 10);
32633374
}
32643375

3265-
#[test]
3266-
fn test_init() {
3267-
let v = init(~[1, 2, 3]);
3268-
assert v == ~[1, 2];
3269-
}
3270-
32713376
#[test]
32723377
fn test_split() {
32733378
fn f(x: &int) -> bool { *x == 3 }
@@ -3332,13 +3437,6 @@ mod tests {
33323437
(~[], ~[1, 2, 3]);
33333438
}
33343439

3335-
#[test]
3336-
#[should_fail]
3337-
#[ignore(cfg(windows))]
3338-
fn test_init_empty() {
3339-
init::<int>(~[]);
3340-
}
3341-
33423440
#[test]
33433441
fn test_concat() {
33443442
assert concat(~[~[1], ~[2,3]]) == ~[1, 2, 3];

src/librust/rust.rc

+8-4
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ fn cmd_help(args: &[~str]) -> ValidUsage {
130130
UsgExec(commandline) => {
131131
let words = str::words(commandline);
132132
let (prog, args) = (words.head(), words.tail());
133-
run::run_program(prog, args);
133+
run::run_program(*prog, args);
134134
}
135135
}
136136
Valid
@@ -186,7 +186,10 @@ fn do_command(command: &Command, args: &[~str]) -> ValidUsage {
186186
Exec(commandline) => {
187187
let words = str::words(commandline);
188188
let (prog, prog_args) = (words.head(), words.tail());
189-
let exitstatus = run::run_program(prog, prog_args + args);
189+
let exitstatus = run::run_program(
190+
*prog,
191+
vec::append(vec::from_slice(prog_args), args)
192+
);
190193
os::set_exit_status(exitstatus);
191194
Valid
192195
}
@@ -221,11 +224,12 @@ fn usage() {
221224
}
222225

223226
pub fn main() {
224-
let args = os::args().tail();
227+
let os_args = os::args();
228+
let args = os_args.tail();
225229

226230
if !args.is_empty() {
227231
for commands.each |command| {
228-
if command.cmd == args.head() {
232+
if command.cmd == *args.head() {
229233
let result = do_command(command, args.tail());
230234
if result.is_valid() { return; }
231235
}

src/librustc/metadata/creader.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ struct cache_entry {
6565
metas: @~[@ast::meta_item]
6666
}
6767

68-
fn dump_crates(+crate_cache: @mut ~[cache_entry]) {
68+
fn dump_crates(crate_cache: @mut ~[cache_entry]) {
6969
debug!("resolved crates:");
7070
for crate_cache.each |entry| {
7171
debug!("cnum: %?", entry.cnum);
@@ -81,7 +81,9 @@ fn warn_if_multiple_versions(e: @mut Env,
8181

8282
if crate_cache.len() != 0u {
8383
let name = loader::crate_name_from_metas(
84-
/*bad*/copy *crate_cache.last().metas);
84+
*crate_cache[crate_cache.len() - 1].metas
85+
);
86+
8587
let (matches, non_matches) =
8688
partition(crate_cache.map_to_vec(|&entry| {
8789
let othername = loader::crate_name_from_metas(

src/librustc/metadata/decoder.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -558,16 +558,18 @@ pub fn maybe_get_item_ast(intr: @ident_interner, cdata: cmd, tcx: ty::ctxt,
558558
-> csearch::found_ast {
559559
debug!("Looking up item: %d", id);
560560
let item_doc = lookup_item(id, cdata.data);
561-
let path = vec::init(item_path(intr, item_doc));
561+
let path = {
562+
let item_path = item_path(intr, item_doc);
563+
vec::from_slice(item_path.init())
564+
};
562565
match decode_inlined_item(cdata, tcx, path, item_doc) {
563566
Some(ref ii) => csearch::found((/*bad*/copy *ii)),
564567
None => {
565568
match item_parent_item(item_doc) {
566569
Some(did) => {
567570
let did = translate_def_id(cdata, did);
568571
let parent_item = lookup_item(did.node, cdata.data);
569-
match decode_inlined_item(cdata, tcx, path,
570-
parent_item) {
572+
match decode_inlined_item(cdata, tcx, path, parent_item) {
571573
Some(ref ii) => csearch::found_parent(did, (/*bad*/copy *ii)),
572574
None => csearch::not_found
573575
}

0 commit comments

Comments
 (0)