This commit deprecates rev_iter, mut_rev_iter, move_rev_iter everywhere (except treemap) and also
deprecates related functions like rsplit, rev_components, and rev_str_components. In every case,
these functions can be replaced with the non-reversed form followed by a call to .rev(). To make this
more concrete, a translation table for all functional changes necessary follows:
* container.rev_iter() -> container.iter().rev()
* container.mut_rev_iter() -> container.mut_iter().rev()
* container.move_rev_iter() -> container.move_iter().rev()
* sliceorstr.rsplit(sep) -> sliceorstr.split(sep).rev()
* path.rev_components() -> path.components().rev()
* path.rev_str_components() -> path.str_components().rev()
In terms of the type system, this change also deprecates any specialized reversed iterator types (except
in treemap), opting instead to use Rev directly if any type annotations are needed. However, since
methods directly returning reversed iterators are now discouraged, the need for such annotations should
be small. However, in those cases, the general pattern for conversion is to take whatever follows Rev in
the original reversed name and surround it with Rev<>:
* RevComponents<'a> -> Rev<Components<'a>>
* RevStrComponents<'a> -> Rev<StrComponents<'a>>
* RevItems<'a, T> -> Rev<Items<'a, T>>
* etc.
The reasoning behind this change is that it makes the standard API much simpler without reducing readability,
performance, or power. The presence of functions such as rev_iter adds more boilerplate code to libraries
(all of which simply call .iter().rev()), clutters up the documentation, and only helps code by saving two
characters. Additionally, the numerous type synonyms that were used to make the type signatures look nice
like RevItems add even more boilerplate and clutter up the docs even more. With this change, all that cruft
goes away.
[breaking-change]
This makes the splitting functions in std::slice return DoubleEndedIterators. Unfortunately,
splitn and rsplitn cannot provide such an interface and so must return different types. As a
result, the following changes were made:
* RevSplits was removed in favor of explicitly using Rev
* Splits can no longer bound the number of splits done
* Splits now implements DoubleEndedIterator
* SplitsN was added, taking the role of what both Splits and RevSplits used to be
* rsplit returns Rev<Splits<'a, T>> instead of RevSplits<'a, T>
* splitn returns SplitsN<'a, T> instead of Splits<'a, T>
* rsplitn returns SplitsN<'a, T> instead of RevSplits<'a, T>
All functions that were previously implemented on each return value still are, so outside of changing
of type annotations, existing code should work out of the box. In the rare case that code relied
on the return types of split and splitn or of rsplit and rsplitn being the same, the previous
behavior can be emulated by calling splitn or rsplitn with a bount of uint::MAX.
The value of this change comes in multiple parts:
* Consistency. The splitting code in std::str is structured similarly to the new slice splitting code,
having separate CharSplits and CharSplitsN types.
* Smaller API. Although this commit doesn't implement it, using a DoubleEndedIterator for splitting
means that rsplit, path::RevComponents, path::RevStrComponents, Path::rev_components, and
Path::rev_str_components are no longer needed - they can be emulated simply with .rev().
* Power. DoubleEndedIterators are able to traverse the list from both sides at once instead of only
forwards or backwards.
* Efficiency. For the common case of using split instead of splitn, the iterator is slightly smaller
and slightly faster.
[breaking-change]
This alters the borrow checker's requirements on invoking closures from
requiring an immutable borrow to requiring a unique immutable borrow. This means
that it is illegal to invoke a closure through a `&` pointer because there is no
guarantee that is not aliased. This does not mean that a closure is required to
be in a mutable location, but rather a location which can be proven to be
unique (often through a mutable pointer).
For example, the following code is unsound and is no longer allowed:
type Fn<'a> = ||:'a;
fn call(f: |Fn|) {
f(|| {
f(|| {})
});
}
fn main() {
call(|a| {
a();
});
}
There is no replacement for this pattern. For all closures which are stored in
structures, it was previously allowed to invoke the closure through `&self` but
it now requires invocation through `&mut self`.
The standard library has a good number of violations of this new rule, but the
fixes will be separated into multiple breaking change commits.
Closes#12224
Many iterators go through a closure when dealing with the `idx` method, which
are invalid after the previous change (closures cannot be invoked through a `&`
pointer). This commit alters the `fn idx` method on the RandomAccessIterator
to take `&mut self` rather than `&self`.
[breaking-change]
This removes all resizability support for ~[T] vectors in preparation of DST.
The only growable vector remaining is Vec<T>. In summary, the following methods
from ~[T] and various functions were removed. Each method/function has an
equivalent on the Vec type in std::vec unless otherwise stated.
* slice::OwnedCloneableVector
* slice::OwnedEqVector
* slice::append
* slice::append_one
* slice::build (no replacement)
* slice::bytes::push_bytes
* slice::from_elem
* slice::from_fn
* slice::with_capacity
* ~[T].capacity()
* ~[T].clear()
* ~[T].dedup()
* ~[T].extend()
* ~[T].grow()
* ~[T].grow_fn()
* ~[T].grow_set()
* ~[T].insert()
* ~[T].pop()
* ~[T].push()
* ~[T].push_all()
* ~[T].push_all_move()
* ~[T].remove()
* ~[T].reserve()
* ~[T].reserve_additional()
* ~[T].reserve_exect()
* ~[T].retain()
* ~[T].set_len()
* ~[T].shift()
* ~[T].shrink_to_fit()
* ~[T].swap_remove()
* ~[T].truncate()
* ~[T].unshift()
* ~str.clear()
* ~str.set_len()
* ~str.truncate()
Note that no other API changes were made. Existing apis that took or returned
~[T] continue to do so.
[breaking-change]
Closures did not have their bounds printed at all, nor their lifetimes. Trait
bounds were also printed in angle brackets rather than after a colon with a '+'
inbetween them.
Note that on the current task::spawn [1] documentation page, there is no mention
of a `Send` bound even though it is crucially important!
[1] - http://static.rust-lang.org/doc/master/std/task/fn.task.html
Summary:
So far, we've used the term POD "Plain Old Data" to refer to types that
can be safely copied. However, this term is not consistent with the
other built-in bounds that use verbs instead. This patch renames the Pod
kind into Copy.
RFC: 0003-opt-in-builtin-traits
Test Plan: make check
Reviewers: cmr
Differential Revision: http://phabricator.octayn.net/D3
std: remove the `equals` method from `TotalEq`.
`TotalEq` is now just an assertion about the `Eq` impl of a
type (i.e. `==` is a total equality if a type implements `TotalEq`) so
the extra method is just confusing.
Also, a new method magically appeared as a hack to allow deriving to
assert that the contents of a struct/enum are also TotalEq, because the
deriving infrastructure makes it very hard to do anything but create a
trait method. (You didn't hear about this horrible work-around from me
:(.)
`TotalEq` is now just an assertion about the `Eq` impl of a
type (i.e. `==` is a total equality if a type implements `TotalEq`) so
the extra method is just confusing.
Also, a new method magically appeared as a hack to allow deriving to
assert that the contents of a struct/enum are also TotalEq, because the
deriving infrastructure makes it very hard to do anything but create a
trait method. (You didn't hear about this horrible work-around from me
:(.)
This needs to be removed as part of removing `~[T]`. Partial type hints
are now allowed, and will remove the need to add a version of this
method for `Vec<T>`. For now, this involves a few workarounds for
partial type hints not completely working.