Auto merge of #22796 - Manishearth:rollup, r=Manishearth
This commit is contained in:
commit
4db0b32467
139 changed files with 1692 additions and 1087 deletions
|
|
@ -68,7 +68,7 @@ There are questions that are asked quite often, and so we've made FAQs for them:
|
|||
* [Language Design FAQ](complement-design-faq.html)
|
||||
* [Language FAQ](complement-lang-faq.html)
|
||||
* [Project FAQ](complement-project-faq.html)
|
||||
* [How to submit a bug report](complement-bugreport.html)
|
||||
* [How to submit a bug report](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports)
|
||||
|
||||
# The standard library
|
||||
|
||||
|
|
|
|||
|
|
@ -731,15 +731,20 @@ Rust syntax is restricted in two ways:
|
|||
pairs when they occur at the beginning of, or immediately after, a `$(...)*`;
|
||||
requiring a distinctive token in front can solve the problem.
|
||||
|
||||
## Syntax extensions useful for the macro author
|
||||
## Syntax extensions useful in macros
|
||||
|
||||
* `stringify!` : turn the identifier argument into a string literal
|
||||
* `concat!` : concatenates a comma-separated list of literals
|
||||
|
||||
## Syntax extensions for macro debugging
|
||||
|
||||
* `log_syntax!` : print out the arguments at compile time
|
||||
* `trace_macros!` : supply `true` or `false` to enable or disable macro expansion logging
|
||||
* `stringify!` : turn the identifier argument into a string literal
|
||||
* `concat!` : concatenates a comma-separated list of literals
|
||||
* `concat_idents!` : create a new identifier by concatenating the arguments
|
||||
|
||||
The following attributes are used for quasiquoting in procedural macros:
|
||||
## Quasiquoting
|
||||
|
||||
The following syntax extensions are used for quasiquoting Rust syntax trees,
|
||||
usually in [procedural macros](book/plugins.html#syntax-extensions):
|
||||
|
||||
* `quote_expr!`
|
||||
* `quote_item!`
|
||||
|
|
@ -748,6 +753,8 @@ The following attributes are used for quasiquoting in procedural macros:
|
|||
* `quote_tokens!`
|
||||
* `quote_ty!`
|
||||
|
||||
Documentation is very limited at the moment.
|
||||
|
||||
# Crates and source files
|
||||
|
||||
Rust is a *compiled* language. Its semantics obey a *phase distinction*
|
||||
|
|
|
|||
|
|
@ -192,19 +192,58 @@ To keep this system simple and correct, `#[macro_use] extern crate ...` may
|
|||
only appear at the root of your crate, not inside `mod`. This ensures that
|
||||
`$crate` is a single identifier.
|
||||
|
||||
# A final note
|
||||
# The deep end
|
||||
|
||||
Macros, as currently implemented, are not for the faint of heart. Even
|
||||
ordinary syntax errors can be more difficult to debug when they occur inside a
|
||||
macro, and errors caused by parse problems in generated code can be very
|
||||
tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
|
||||
states, invoking `trace_macros!(true)` will automatically print those
|
||||
intermediate states out, and passing the flag `--pretty expanded` as a
|
||||
command-line argument to the compiler will show the result of expansion.
|
||||
The introductory chapter mentioned recursive macros, but it did not give the
|
||||
full story. Recursive macros are useful for another reason: Each recursive
|
||||
invocation gives you another opportunity to pattern-match the macro's
|
||||
arguments.
|
||||
|
||||
As an extreme example, it is possible, though hardly advisable, to implement
|
||||
the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
|
||||
within Rust's macro system.
|
||||
|
||||
```rust
|
||||
#![feature(trace_macros)]
|
||||
|
||||
macro_rules! bct {
|
||||
// cmd 0: d ... => ...
|
||||
(0, $($ps:tt),* ; $_d:tt)
|
||||
=> (bct!($($ps),*, 0 ; ));
|
||||
(0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
|
||||
=> (bct!($($ps),*, 0 ; $($ds),*));
|
||||
|
||||
// cmd 1p: 1 ... => 1 ... p
|
||||
(1, $p:tt, $($ps:tt),* ; 1)
|
||||
=> (bct!($($ps),*, 1, $p ; 1, $p));
|
||||
(1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
|
||||
=> (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
|
||||
|
||||
// cmd 1p: 0 ... => 0 ...
|
||||
(1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
|
||||
=> (bct!($($ps),*, 1, $p ; $($ds),*));
|
||||
|
||||
// halt on empty data string
|
||||
( $($ps:tt),* ; )
|
||||
=> (());
|
||||
}
|
||||
|
||||
fn main() {
|
||||
trace_macros!(true);
|
||||
# /* just check the definition
|
||||
bct!(0, 0, 1, 1, 1 ; 1, 0, 1);
|
||||
# */
|
||||
}
|
||||
```
|
||||
|
||||
Exercise: use macros to reduce duplication in the above definition of the
|
||||
`bct!` macro.
|
||||
|
||||
# Procedural macros
|
||||
|
||||
If Rust's macro system can't do what you need, you may want to write a
|
||||
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
|
||||
macros, this is significantly more work, the interfaces are much less stable,
|
||||
and the warnings about debugging apply ten-fold. In exchange you get the
|
||||
and bugs can be much harder to track down. In exchange you get the
|
||||
flexibility of running arbitrary Rust code within the compiler. Syntax
|
||||
extension plugins are sometimes called *procedural macros* for this reason.
|
||||
|
|
|
|||
|
|
@ -223,6 +223,78 @@ let input = io::stdin().read_line()
|
|||
.ok()
|
||||
.expect("Failed to read line");
|
||||
```
|
||||
|
||||
`ok()` converts the `IoResult` into an `Option`, and `expect()` does the same
|
||||
thing as `unwrap()`, but takes a message. This message is passed along to the
|
||||
underlying `panic!`, providing a better error message if the code errors.
|
||||
|
||||
# Using `try!`
|
||||
|
||||
When writing code that calls many functions that return the `Result` type, the
|
||||
error handling can be tedious. The `try!` macro hides some of the boilerplate
|
||||
of propagating errors up the call stack.
|
||||
|
||||
It replaces this:
|
||||
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
||||
struct Info {
|
||||
name: String,
|
||||
age: i32,
|
||||
rating: i32,
|
||||
}
|
||||
|
||||
fn write_info(info: &Info) -> io::Result<()> {
|
||||
let mut file = File::open("my_best_friends.txt").unwrap();
|
||||
|
||||
if let Err(e) = writeln!(&mut file, "name: {}", info.name) {
|
||||
return Err(e)
|
||||
}
|
||||
if let Err(e) = writeln!(&mut file, "age: {}", info.age) {
|
||||
return Err(e)
|
||||
}
|
||||
if let Err(e) = writeln!(&mut file, "rating: {}", info.rating) {
|
||||
return Err(e)
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
```
|
||||
|
||||
With this:
|
||||
|
||||
```rust
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
|
||||
struct Info {
|
||||
name: String,
|
||||
age: i32,
|
||||
rating: i32,
|
||||
}
|
||||
|
||||
fn write_info(info: &Info) -> io::Result<()> {
|
||||
let mut file = try!(File::open("my_best_friends.txt"));
|
||||
|
||||
try!(writeln!(&mut file, "name: {}", info.name));
|
||||
try!(writeln!(&mut file, "age: {}", info.age));
|
||||
try!(writeln!(&mut file, "rating: {}", info.rating));
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
```
|
||||
|
||||
Wrapping an expression in `try!` will result in the unwrapped success (`Ok`)
|
||||
value, unless the result is `Err`, in which case `Err` is returned early from
|
||||
the enclosing function.
|
||||
|
||||
It's worth noting that you can only use `try!` from a function that returns a
|
||||
`Result`, which means that you cannot use `try!` inside of `main()`, because
|
||||
`main()` doesn't return anything.
|
||||
|
||||
`try!` makes use of [`FromError`](../std/error/#the-fromerror-trait) to determine
|
||||
what to return in the error case.
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ macro_rules! vec {
|
|||
};
|
||||
}
|
||||
# fn main() {
|
||||
# assert_eq!(&[1,2,3], &vec![1,2,3]);
|
||||
# assert_eq!([1,2,3], vec![1,2,3]);
|
||||
# }
|
||||
```
|
||||
|
||||
|
|
@ -189,14 +189,12 @@ shorthand for a data type could be valid as either an expression or a pattern.
|
|||
|
||||
## Repetition
|
||||
|
||||
The repetition behavior can seem somewhat magical, especially when multiple
|
||||
names are bound at multiple nested levels of repetition. The two rules to keep
|
||||
in mind are:
|
||||
The repetition operator follows two principal rules:
|
||||
|
||||
1. the behavior of `$(...)*` is to walk through one "layer" of repetitions, for
|
||||
all of the `$name`s it contains, in lockstep, and
|
||||
1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s
|
||||
it contains, in lockstep, and
|
||||
2. each `$name` must be under at least as many `$(...)*`s as it was matched
|
||||
against. If it is under more, it'll be duplicated, as appropriate.
|
||||
against. If it is under more, it'll be duplicated, as appropriate.
|
||||
|
||||
This baroque macro illustrates the duplication of variables from outer
|
||||
repetition levels.
|
||||
|
|
@ -226,6 +224,10 @@ That's most of the matcher syntax. These examples use `$(...)*`, which is a
|
|||
more" match. Both forms optionally include a separator, which can be any token
|
||||
except `+` or `*`.
|
||||
|
||||
This system is based on
|
||||
"[Macro-by-Example](http://www.cs.indiana.edu/ftp/techreports/TR206.pdf)"
|
||||
(PDF link).
|
||||
|
||||
# Hygiene
|
||||
|
||||
Some languages implement macros using simple text substitution, which leads to
|
||||
|
|
@ -273,19 +275,26 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks.
|
|||
})
|
||||
```
|
||||
|
||||
This looks reasonable, but watch what happens in this example:
|
||||
Here's a simple use case that goes terribly wrong:
|
||||
|
||||
```text
|
||||
const char *state = "reticulating splines";
|
||||
LOG(state);
|
||||
LOG(state)
|
||||
```
|
||||
|
||||
The program will likely segfault, after it tries to execute
|
||||
This expands to
|
||||
|
||||
```text
|
||||
printf("log(%d): %s\n", state, state);
|
||||
const char *state = "reticulating splines";
|
||||
int state = get_log_state();
|
||||
if (state > 0) {
|
||||
printf("log(%d): %s\n", state, state);
|
||||
}
|
||||
```
|
||||
|
||||
The second variable named `state` shadows the first one. This is a problem
|
||||
because the print statement should refer to both of them.
|
||||
|
||||
The equivalent Rust macro has the desired behavior.
|
||||
|
||||
```rust
|
||||
|
|
@ -357,6 +366,64 @@ fn main() {
|
|||
|
||||
[items]: ../reference.html#items
|
||||
|
||||
# Recursive macros
|
||||
|
||||
A macro's expansion can include more macro invocations, including invocations
|
||||
of the very same macro being expanded. These recursive macros are useful for
|
||||
processing tree-structured input, as illustrated by this (simplistic) HTML
|
||||
shorthand:
|
||||
|
||||
```rust
|
||||
# #![allow(unused_must_use)]
|
||||
macro_rules! write_html {
|
||||
($w:expr, ) => (());
|
||||
|
||||
($w:expr, $e:tt) => (write!($w, "{}", $e));
|
||||
|
||||
($w:expr, $tag:ident [ $($inner:tt)* ] $($rest:tt)*) => {{
|
||||
write!($w, "<{}>", stringify!($tag));
|
||||
write_html!($w, $($inner)*);
|
||||
write!($w, "</{}>", stringify!($tag));
|
||||
write_html!($w, $($rest)*);
|
||||
}};
|
||||
}
|
||||
|
||||
fn main() {
|
||||
# // FIXME(#21826)
|
||||
use std::fmt::Write;
|
||||
let mut out = String::new();
|
||||
|
||||
write_html!(&mut out,
|
||||
html[
|
||||
head[title["Macros guide"]]
|
||||
body[h1["Macros are the best!"]]
|
||||
]);
|
||||
|
||||
assert_eq!(out,
|
||||
"<html><head><title>Macros guide</title></head>\
|
||||
<body><h1>Macros are the best!</h1></body></html>");
|
||||
}
|
||||
```
|
||||
|
||||
# Debugging macro code
|
||||
|
||||
To see the results of expanding macros, run `rustc --pretty expanded`. The
|
||||
output represents a whole crate, so you can also feed it back in to `rustc`,
|
||||
which will sometimes produce better error messages than the original
|
||||
compilation. Note that the `--pretty expanded` output may have a different
|
||||
meaning if multiple variables of the same name (but different syntax contexts)
|
||||
are in play in the same scope. In this case `--pretty expanded,hygiene` will
|
||||
tell you about the syntax contexts.
|
||||
|
||||
`rustc` provides two syntax extensions that help with macro debugging. For now,
|
||||
they are unstable and require feature gates.
|
||||
|
||||
* `log_syntax!(...)` will print its arguments to standard output, at compile
|
||||
time, and "expand" to nothing.
|
||||
|
||||
* `trace_macros!(true)` will enable a compiler message every time a macro is
|
||||
expanded. Use `trace_macros!(false)` later in expansion to turn it off.
|
||||
|
||||
# Further reading
|
||||
|
||||
The [advanced macros chapter][] goes into more detail about macro syntax. It
|
||||
|
|
|
|||
|
|
@ -146,14 +146,7 @@ a more involved macro example, see
|
|||
|
||||
## Tips and tricks
|
||||
|
||||
To see the results of expanding syntax extensions, run
|
||||
`rustc --pretty expanded`. The output represents a whole crate, so you
|
||||
can also feed it back in to `rustc`, which will sometimes produce better
|
||||
error messages than the original compilation. Note that the
|
||||
`--pretty expanded` output may have a different meaning if multiple
|
||||
variables of the same name (but different syntax contexts) are in play
|
||||
in the same scope. In this case `--pretty expanded,hygiene` will tell
|
||||
you about the syntax contexts.
|
||||
Some of the [macro debugging tips](macros.html#debugging-macro-code) are applicable.
|
||||
|
||||
You can use [`syntax::parse`](../syntax/parse/index.html) to turn token trees into
|
||||
higher-level syntax elements like expressions:
|
||||
|
|
@ -184,6 +177,11 @@ and return
|
|||
[`DummyResult`](../syntax/ext/base/struct.DummyResult.html),
|
||||
so that the compiler can continue and find further errors.
|
||||
|
||||
To print syntax fragments for debugging, you can use
|
||||
[`span_note`](../syntax/ext/base/struct.ExtCtxt.html#method.span_note) together
|
||||
with
|
||||
[`syntax::print::pprust::*_to_string`](http://doc.rust-lang.org/syntax/print/pprust/index.html#functions).
|
||||
|
||||
The example above produced an integer literal using
|
||||
[`AstBuilder::expr_uint`](../syntax/ext/build/trait.AstBuilder.html#tymethod.expr_uint).
|
||||
As an alternative to the `AstBuilder` trait, `libsyntax` provides a set of
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@
|
|||
#![feature(unboxed_closures)]
|
||||
#![feature(unsafe_no_drop_flag)]
|
||||
#![feature(core)]
|
||||
#![feature(unique)]
|
||||
#![cfg_attr(test, feature(test, alloc, rustc_private))]
|
||||
#![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
|
||||
feature(libc))]
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ impl<T: Ord> BinaryHeap<T> {
|
|||
/// heap.push(3);
|
||||
///
|
||||
/// let vec = heap.into_sorted_vec();
|
||||
/// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7]);
|
||||
/// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]);
|
||||
/// ```
|
||||
pub fn into_sorted_vec(mut self) -> Vec<T> {
|
||||
let mut end = self.len();
|
||||
|
|
|
|||
|
|
@ -640,13 +640,13 @@ impl BitVec {
|
|||
/// let mut bv = BitVec::from_elem(3, true);
|
||||
/// bv.set(1, false);
|
||||
///
|
||||
/// assert_eq!(bv.to_bytes(), vec!(0b10100000));
|
||||
/// assert_eq!(bv.to_bytes(), [0b10100000]);
|
||||
///
|
||||
/// let mut bv = BitVec::from_elem(9, false);
|
||||
/// bv.set(2, true);
|
||||
/// bv.set(8, true);
|
||||
///
|
||||
/// assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000));
|
||||
/// assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]);
|
||||
/// ```
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
fn bit(bit_vec: &BitVec, byte: usize, bit: usize) -> u8 {
|
||||
|
|
@ -806,7 +806,7 @@ impl BitVec {
|
|||
/// let mut bv = BitVec::from_bytes(&[0b01001011]);
|
||||
/// bv.grow(2, true);
|
||||
/// assert_eq!(bv.len(), 10);
|
||||
/// assert_eq!(bv.to_bytes(), vec!(0b01001011, 0b11000000));
|
||||
/// assert_eq!(bv.to_bytes(), [0b01001011, 0b11000000]);
|
||||
/// ```
|
||||
pub fn grow(&mut self, n: usize, value: bool) {
|
||||
// Note: we just bulk set all the bits in the last word in this fn in multiple places
|
||||
|
|
@ -978,7 +978,7 @@ impl Ord for BitVec {
|
|||
impl fmt::Debug for BitVec {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
for bit in self {
|
||||
try!(write!(fmt, "{}", if bit { 1u32 } else { 0u32 }));
|
||||
try!(write!(fmt, "{}", if bit { 1 } else { 0 }));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -1752,7 +1752,7 @@ impl BitSet {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Debug for BitSet {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(fmt, "BitSet {{"));
|
||||
try!(write!(fmt, "{{"));
|
||||
let mut first = true;
|
||||
for n in self {
|
||||
if !first {
|
||||
|
|
@ -2285,12 +2285,12 @@ mod tests {
|
|||
fn test_to_bytes() {
|
||||
let mut bv = BitVec::from_elem(3, true);
|
||||
bv.set(1, false);
|
||||
assert_eq!(bv.to_bytes(), vec!(0b10100000));
|
||||
assert_eq!(bv.to_bytes(), [0b10100000]);
|
||||
|
||||
let mut bv = BitVec::from_elem(9, false);
|
||||
bv.set(2, true);
|
||||
bv.set(8, true);
|
||||
assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000));
|
||||
assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2655,7 +2655,7 @@ mod bit_set_test {
|
|||
s.insert(10);
|
||||
s.insert(50);
|
||||
s.insert(2);
|
||||
assert_eq!("BitSet {1, 2, 10, 50}", format!("{:?}", s));
|
||||
assert_eq!("{1, 2, 10, 50}", format!("{:?}", s));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2675,7 +2675,7 @@ mod bit_set_test {
|
|||
let bit_vec: BitSet = usizes.into_iter().collect();
|
||||
|
||||
let idxs: Vec<_> = bit_vec.iter().collect();
|
||||
assert_eq!(idxs, vec![0, 2, 3]);
|
||||
assert_eq!(idxs, [0, 2, 3]);
|
||||
|
||||
let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect();
|
||||
let real: Vec<_> = range_step(0, 10000, 2).collect();
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
let result = stack.with(move |pusher, node| {
|
||||
// Same basic logic as found in `find`, but with PartialSearchStack mediating the
|
||||
// actual nodes for us
|
||||
return match Node::search(node, &key) {
|
||||
match Node::search(node, &key) {
|
||||
Found(mut handle) => {
|
||||
// Perfect match, swap the values and return the old one
|
||||
mem::swap(handle.val_mut(), &mut value);
|
||||
|
|
@ -372,7 +372,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
}
|
||||
});
|
||||
match result {
|
||||
Finished(ret) => { return ret; },
|
||||
Finished(ret) => return ret,
|
||||
Continue((new_stack, renewed_key, renewed_val)) => {
|
||||
stack = new_stack;
|
||||
key = renewed_key;
|
||||
|
|
@ -439,7 +439,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
let mut stack = stack::PartialSearchStack::new(self);
|
||||
loop {
|
||||
let result = stack.with(move |pusher, node| {
|
||||
return match Node::search(node, key) {
|
||||
match Node::search(node, key) {
|
||||
Found(handle) => {
|
||||
// Perfect match. Terminate the stack here, and remove the entry
|
||||
Finished(Some(pusher.seal(handle).remove()))
|
||||
|
|
@ -899,7 +899,7 @@ impl<K: Ord, V: Ord> Ord for BTreeMap<K, V> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "BTreeMap {{"));
|
||||
try!(write!(f, "{{"));
|
||||
|
||||
for (i, (k, v)) in self.iter().enumerate() {
|
||||
if i != 0 { try!(write!(f, ", ")); }
|
||||
|
|
@ -1281,7 +1281,7 @@ impl<K, V> BTreeMap<K, V> {
|
|||
/// a.insert(2, "b");
|
||||
///
|
||||
/// let keys: Vec<usize> = a.keys().cloned().collect();
|
||||
/// assert_eq!(keys, vec![1,2,]);
|
||||
/// assert_eq!(keys, [1, 2]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
|
||||
|
|
@ -1303,7 +1303,7 @@ impl<K, V> BTreeMap<K, V> {
|
|||
/// a.insert(2, "b");
|
||||
///
|
||||
/// let values: Vec<&str> = a.values().cloned().collect();
|
||||
/// assert_eq!(values, vec!["a","b"]);
|
||||
/// assert_eq!(values, ["a", "b"]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn values<'a>(&'a self) -> Values<'a, K, V> {
|
||||
|
|
@ -1560,7 +1560,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||
let mut stack = stack::PartialSearchStack::new(self);
|
||||
loop {
|
||||
let result = stack.with(move |pusher, node| {
|
||||
return match Node::search(node, &key) {
|
||||
match Node::search(node, &key) {
|
||||
Found(handle) => {
|
||||
// Perfect match
|
||||
Finished(Occupied(OccupiedEntry {
|
||||
|
|
|
|||
|
|
@ -1136,12 +1136,12 @@ impl<K, V> Node<K, V> {
|
|||
// This must be followed by insert_edge on an internal node.
|
||||
#[inline]
|
||||
unsafe fn insert_kv(&mut self, index: usize, key: K, val: V) -> &mut V {
|
||||
ptr::copy_memory(
|
||||
ptr::copy(
|
||||
self.keys_mut().as_mut_ptr().offset(index as isize + 1),
|
||||
self.keys().as_ptr().offset(index as isize),
|
||||
self.len() - index
|
||||
);
|
||||
ptr::copy_memory(
|
||||
ptr::copy(
|
||||
self.vals_mut().as_mut_ptr().offset(index as isize + 1),
|
||||
self.vals().as_ptr().offset(index as isize),
|
||||
self.len() - index
|
||||
|
|
@ -1158,7 +1158,7 @@ impl<K, V> Node<K, V> {
|
|||
// This can only be called immediately after a call to insert_kv.
|
||||
#[inline]
|
||||
unsafe fn insert_edge(&mut self, index: usize, edge: Node<K, V>) {
|
||||
ptr::copy_memory(
|
||||
ptr::copy(
|
||||
self.edges_mut().as_mut_ptr().offset(index as isize + 1),
|
||||
self.edges().as_ptr().offset(index as isize),
|
||||
self.len() - index
|
||||
|
|
@ -1191,12 +1191,12 @@ impl<K, V> Node<K, V> {
|
|||
let key = ptr::read(self.keys().get_unchecked(index));
|
||||
let val = ptr::read(self.vals().get_unchecked(index));
|
||||
|
||||
ptr::copy_memory(
|
||||
ptr::copy(
|
||||
self.keys_mut().as_mut_ptr().offset(index as isize),
|
||||
self.keys().as_ptr().offset(index as isize + 1),
|
||||
self.len() - index - 1
|
||||
);
|
||||
ptr::copy_memory(
|
||||
ptr::copy(
|
||||
self.vals_mut().as_mut_ptr().offset(index as isize),
|
||||
self.vals().as_ptr().offset(index as isize + 1),
|
||||
self.len() - index - 1
|
||||
|
|
@ -1212,7 +1212,7 @@ impl<K, V> Node<K, V> {
|
|||
unsafe fn remove_edge(&mut self, index: usize) -> Node<K, V> {
|
||||
let edge = ptr::read(self.edges().get_unchecked(index));
|
||||
|
||||
ptr::copy_memory(
|
||||
ptr::copy(
|
||||
self.edges_mut().as_mut_ptr().offset(index as isize),
|
||||
self.edges().as_ptr().offset(index as isize + 1),
|
||||
self.len() - index + 1
|
||||
|
|
@ -1239,18 +1239,18 @@ impl<K, V> Node<K, V> {
|
|||
unsafe {
|
||||
right._len = self.len() / 2;
|
||||
let right_offset = self.len() - right.len();
|
||||
ptr::copy_nonoverlapping_memory(
|
||||
ptr::copy_nonoverlapping(
|
||||
right.keys_mut().as_mut_ptr(),
|
||||
self.keys().as_ptr().offset(right_offset as isize),
|
||||
right.len()
|
||||
);
|
||||
ptr::copy_nonoverlapping_memory(
|
||||
ptr::copy_nonoverlapping(
|
||||
right.vals_mut().as_mut_ptr(),
|
||||
self.vals().as_ptr().offset(right_offset as isize),
|
||||
right.len()
|
||||
);
|
||||
if !self.is_leaf() {
|
||||
ptr::copy_nonoverlapping_memory(
|
||||
ptr::copy_nonoverlapping(
|
||||
right.edges_mut().as_mut_ptr(),
|
||||
self.edges().as_ptr().offset(right_offset as isize),
|
||||
right.len() + 1
|
||||
|
|
@ -1280,18 +1280,18 @@ impl<K, V> Node<K, V> {
|
|||
ptr::write(self.keys_mut().get_unchecked_mut(old_len), key);
|
||||
ptr::write(self.vals_mut().get_unchecked_mut(old_len), val);
|
||||
|
||||
ptr::copy_nonoverlapping_memory(
|
||||
ptr::copy_nonoverlapping(
|
||||
self.keys_mut().as_mut_ptr().offset(old_len as isize + 1),
|
||||
right.keys().as_ptr(),
|
||||
right.len()
|
||||
);
|
||||
ptr::copy_nonoverlapping_memory(
|
||||
ptr::copy_nonoverlapping(
|
||||
self.vals_mut().as_mut_ptr().offset(old_len as isize + 1),
|
||||
right.vals().as_ptr(),
|
||||
right.len()
|
||||
);
|
||||
if !self.is_leaf() {
|
||||
ptr::copy_nonoverlapping_memory(
|
||||
ptr::copy_nonoverlapping(
|
||||
self.edges_mut().as_mut_ptr().offset(old_len as isize + 1),
|
||||
right.edges().as_ptr(),
|
||||
right.len() + 1
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ impl<T> BTreeSet<T> {
|
|||
/// }
|
||||
///
|
||||
/// let v: Vec<usize> = set.iter().cloned().collect();
|
||||
/// assert_eq!(v, vec![1,2,3,4]);
|
||||
/// assert_eq!(v, [1, 2, 3, 4]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
|
|
@ -138,7 +138,7 @@ impl<T> BTreeSet<T> {
|
|||
/// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
|
||||
///
|
||||
/// let v: Vec<usize> = set.into_iter().collect();
|
||||
/// assert_eq!(v, vec![1,2,3,4]);
|
||||
/// assert_eq!(v, [1, 2, 3, 4]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
|
|
@ -197,7 +197,7 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// b.insert(3);
|
||||
///
|
||||
/// let diff: Vec<usize> = a.difference(&b).cloned().collect();
|
||||
/// assert_eq!(diff, vec![1]);
|
||||
/// assert_eq!(diff, [1]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
|
||||
|
|
@ -220,7 +220,7 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// b.insert(3);
|
||||
///
|
||||
/// let sym_diff: Vec<usize> = a.symmetric_difference(&b).cloned().collect();
|
||||
/// assert_eq!(sym_diff, vec![1,3]);
|
||||
/// assert_eq!(sym_diff, [1, 3]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet<T>)
|
||||
|
|
@ -244,7 +244,7 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// b.insert(3);
|
||||
///
|
||||
/// let intersection: Vec<usize> = a.intersection(&b).cloned().collect();
|
||||
/// assert_eq!(intersection, vec![2]);
|
||||
/// assert_eq!(intersection, [2]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>)
|
||||
|
|
@ -266,7 +266,7 @@ impl<T: Ord> BTreeSet<T> {
|
|||
/// b.insert(2);
|
||||
///
|
||||
/// let union: Vec<usize> = a.union(&b).cloned().collect();
|
||||
/// assert_eq!(union, vec![1,2]);
|
||||
/// assert_eq!(union, [1, 2]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> Union<'a, T> {
|
||||
|
|
@ -534,7 +534,7 @@ impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet<T>> for &'a BTreeSet<T> {
|
|||
///
|
||||
/// let result = &a - &b;
|
||||
/// let result_vec: Vec<_> = result.into_iter().collect();
|
||||
/// assert_eq!(result_vec, vec![1, 2]);
|
||||
/// assert_eq!(result_vec, [1, 2]);
|
||||
/// ```
|
||||
fn sub(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
|
||||
self.difference(rhs).cloned().collect()
|
||||
|
|
@ -557,7 +557,7 @@ impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet<T>> for &'a BTreeSet<T> {
|
|||
///
|
||||
/// let result = &a ^ &b;
|
||||
/// let result_vec: Vec<_> = result.into_iter().collect();
|
||||
/// assert_eq!(result_vec, vec![1, 4]);
|
||||
/// assert_eq!(result_vec, [1, 4]);
|
||||
/// ```
|
||||
fn bitxor(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
|
||||
self.symmetric_difference(rhs).cloned().collect()
|
||||
|
|
@ -580,7 +580,7 @@ impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet<T>> for &'a BTreeSet<T> {
|
|||
///
|
||||
/// let result = &a & &b;
|
||||
/// let result_vec: Vec<_> = result.into_iter().collect();
|
||||
/// assert_eq!(result_vec, vec![2, 3]);
|
||||
/// assert_eq!(result_vec, [2, 3]);
|
||||
/// ```
|
||||
fn bitand(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
|
||||
self.intersection(rhs).cloned().collect()
|
||||
|
|
@ -603,7 +603,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>> for &'a BTreeSet<T> {
|
|||
///
|
||||
/// let result = &a | &b;
|
||||
/// let result_vec: Vec<_> = result.into_iter().collect();
|
||||
/// assert_eq!(result_vec, vec![1, 2, 3, 4, 5]);
|
||||
/// assert_eq!(result_vec, [1, 2, 3, 4, 5]);
|
||||
/// ```
|
||||
fn bitor(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
|
||||
self.union(rhs).cloned().collect()
|
||||
|
|
@ -613,7 +613,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>> for &'a BTreeSet<T> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Debug> Debug for BTreeSet<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "BTreeSet {{"));
|
||||
try!(write!(f, "{{"));
|
||||
|
||||
for (i, x) in self.iter().enumerate() {
|
||||
if i != 0 { try!(write!(f, ", ")); }
|
||||
|
|
@ -911,7 +911,7 @@ mod test {
|
|||
|
||||
let set_str = format!("{:?}", set);
|
||||
|
||||
assert_eq!(set_str, "BTreeSet {1, 2}");
|
||||
assert_eq!(format!("{:?}", empty), "BTreeSet {}");
|
||||
assert_eq!(set_str, "{1, 2}");
|
||||
assert_eq!(format!("{:?}", empty), "{}");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ impl<E> Copy for EnumSet<E> {}
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<E:CLike + fmt::Debug> fmt::Debug for EnumSet<E> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(fmt, "EnumSet {{"));
|
||||
try!(write!(fmt, "{{"));
|
||||
let mut first = true;
|
||||
for e in self {
|
||||
if !first {
|
||||
|
|
@ -314,11 +314,11 @@ mod test {
|
|||
#[test]
|
||||
fn test_show() {
|
||||
let mut e = EnumSet::new();
|
||||
assert!(format!("{:?}", e) == "EnumSet {}");
|
||||
assert!(format!("{:?}", e) == "{}");
|
||||
e.insert(A);
|
||||
assert!(format!("{:?}", e) == "EnumSet {A}");
|
||||
assert!(format!("{:?}", e) == "{A}");
|
||||
e.insert(C);
|
||||
assert!(format!("{:?}", e) == "EnumSet {A, C}");
|
||||
assert!(format!("{:?}", e) == "{A, C}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -428,19 +428,19 @@ mod test {
|
|||
|
||||
e1.insert(A);
|
||||
let elems: ::vec::Vec<_> = e1.iter().collect();
|
||||
assert_eq!(vec![A], elems);
|
||||
assert_eq!([A], elems);
|
||||
|
||||
e1.insert(C);
|
||||
let elems: ::vec::Vec<_> = e1.iter().collect();
|
||||
assert_eq!(vec![A,C], elems);
|
||||
assert_eq!([A,C], elems);
|
||||
|
||||
e1.insert(C);
|
||||
let elems: ::vec::Vec<_> = e1.iter().collect();
|
||||
assert_eq!(vec![A,C], elems);
|
||||
assert_eq!([A,C], elems);
|
||||
|
||||
e1.insert(B);
|
||||
let elems: ::vec::Vec<_> = e1.iter().collect();
|
||||
assert_eq!(vec![A,B,C], elems);
|
||||
assert_eq!([A,B,C], elems);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -458,35 +458,35 @@ mod test {
|
|||
|
||||
let e_union = e1 | e2;
|
||||
let elems: ::vec::Vec<_> = e_union.iter().collect();
|
||||
assert_eq!(vec![A,B,C], elems);
|
||||
assert_eq!([A,B,C], elems);
|
||||
|
||||
let e_intersection = e1 & e2;
|
||||
let elems: ::vec::Vec<_> = e_intersection.iter().collect();
|
||||
assert_eq!(vec![C], elems);
|
||||
assert_eq!([C], elems);
|
||||
|
||||
// Another way to express intersection
|
||||
let e_intersection = e1 - (e1 - e2);
|
||||
let elems: ::vec::Vec<_> = e_intersection.iter().collect();
|
||||
assert_eq!(vec![C], elems);
|
||||
assert_eq!([C], elems);
|
||||
|
||||
let e_subtract = e1 - e2;
|
||||
let elems: ::vec::Vec<_> = e_subtract.iter().collect();
|
||||
assert_eq!(vec![A], elems);
|
||||
assert_eq!([A], elems);
|
||||
|
||||
// Bitwise XOR of two sets, aka symmetric difference
|
||||
let e_symmetric_diff = e1 ^ e2;
|
||||
let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
|
||||
assert_eq!(vec![A,B], elems);
|
||||
assert_eq!([A,B], elems);
|
||||
|
||||
// Another way to express symmetric difference
|
||||
let e_symmetric_diff = (e1 - e2) | (e2 - e1);
|
||||
let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
|
||||
assert_eq!(vec![A,B], elems);
|
||||
assert_eq!([A,B], elems);
|
||||
|
||||
// Yet another way to express symmetric difference
|
||||
let e_symmetric_diff = (e1 | e2) - (e1 & e2);
|
||||
let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
|
||||
assert_eq!(vec![A,B], elems);
|
||||
assert_eq!([A,B], elems);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#![feature(unboxed_closures)]
|
||||
#![feature(unicode)]
|
||||
#![feature(unsafe_destructor)]
|
||||
#![feature(unique)]
|
||||
#![feature(unsafe_no_drop_flag)]
|
||||
#![cfg_attr(test, feature(rand, rustc_private, test))]
|
||||
#![cfg_attr(test, allow(deprecated))] // rand
|
||||
|
|
|
|||
|
|
@ -777,7 +777,7 @@ impl<'a, A> IterMut<'a, A> {
|
|||
/// }
|
||||
/// {
|
||||
/// let vec: Vec<_> = list.into_iter().collect();
|
||||
/// assert_eq!(vec, vec![1, 2, 3, 4]);
|
||||
/// assert_eq!(vec, [1, 2, 3, 4]);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
|
|
@ -918,7 +918,7 @@ impl<A: Clone> Clone for LinkedList<A> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: fmt::Debug> fmt::Debug for LinkedList<A> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "LinkedList ["));
|
||||
try!(write!(f, "["));
|
||||
|
||||
for (i, e) in self.iter().enumerate() {
|
||||
if i != 0 { try!(write!(f, ", ")); }
|
||||
|
|
@ -1273,7 +1273,7 @@ mod tests {
|
|||
}
|
||||
check_links(&m);
|
||||
assert_eq!(m.len(), 3 + len * 2);
|
||||
assert_eq!(m.into_iter().collect::<Vec<_>>(), vec![-2,0,1,2,3,4,5,6,7,8,9,0,1]);
|
||||
assert_eq!(m.into_iter().collect::<Vec<_>>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1387,10 +1387,10 @@ mod tests {
|
|||
#[test]
|
||||
fn test_show() {
|
||||
let list: LinkedList<_> = (0..10).collect();
|
||||
assert_eq!(format!("{:?}", list), "LinkedList [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
|
||||
assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
|
||||
|
||||
let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
|
||||
assert_eq!(format!("{:?}", list), "LinkedList [\"just\", \"one\", \"test\", \"more\"]");
|
||||
assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]");
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
///
|
||||
/// ```
|
||||
/// let v = vec![1; 3];
|
||||
/// assert_eq!(v, vec![1, 1, 1]);
|
||||
/// assert_eq!(v, [1, 1, 1]);
|
||||
/// ```
|
||||
///
|
||||
/// Note that unlike array expressions this syntax supports all elements
|
||||
|
|
|
|||
|
|
@ -1331,12 +1331,10 @@ fn insertion_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> O
|
|||
|
||||
if i != j {
|
||||
let tmp = ptr::read(read_ptr);
|
||||
ptr::copy_memory(buf_v.offset(j + 1),
|
||||
&*buf_v.offset(j),
|
||||
(i - j) as usize);
|
||||
ptr::copy_nonoverlapping_memory(buf_v.offset(j),
|
||||
&tmp,
|
||||
1);
|
||||
ptr::copy(buf_v.offset(j + 1),
|
||||
&*buf_v.offset(j),
|
||||
(i - j) as usize);
|
||||
ptr::copy_nonoverlapping(buf_v.offset(j), &tmp, 1);
|
||||
mem::forget(tmp);
|
||||
}
|
||||
}
|
||||
|
|
@ -1409,10 +1407,10 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
|
|||
// j + 1 could be `len` (for the last `i`), but in
|
||||
// that case, `i == j` so we don't copy. The
|
||||
// `.offset(j)` is always in bounds.
|
||||
ptr::copy_memory(buf_dat.offset(j + 1),
|
||||
&*buf_dat.offset(j),
|
||||
i - j as usize);
|
||||
ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1);
|
||||
ptr::copy(buf_dat.offset(j + 1),
|
||||
&*buf_dat.offset(j),
|
||||
i - j as usize);
|
||||
ptr::copy_nonoverlapping(buf_dat.offset(j), read_ptr, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1460,11 +1458,11 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
|
|||
if left == right_start {
|
||||
// the number remaining in this run.
|
||||
let elems = (right_end as usize - right as usize) / mem::size_of::<T>();
|
||||
ptr::copy_nonoverlapping_memory(out, &*right, elems);
|
||||
ptr::copy_nonoverlapping(out, &*right, elems);
|
||||
break;
|
||||
} else if right == right_end {
|
||||
let elems = (right_start as usize - left as usize) / mem::size_of::<T>();
|
||||
ptr::copy_nonoverlapping_memory(out, &*left, elems);
|
||||
ptr::copy_nonoverlapping(out, &*left, elems);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1478,7 +1476,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
|
|||
} else {
|
||||
step(&mut left)
|
||||
};
|
||||
ptr::copy_nonoverlapping_memory(out, &*to_copy, 1);
|
||||
ptr::copy_nonoverlapping(out, &*to_copy, 1);
|
||||
step(&mut out);
|
||||
}
|
||||
}
|
||||
|
|
@ -1492,7 +1490,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
|
|||
// write the result to `v` in one go, so that there are never two copies
|
||||
// of the same object in `v`.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len);
|
||||
ptr::copy_nonoverlapping(v.as_mut_ptr(), &*buf_dat, len);
|
||||
}
|
||||
|
||||
// increment the pointer, returning the old pointer.
|
||||
|
|
@ -1779,10 +1777,10 @@ mod tests {
|
|||
let mut v = vec![1, 2, 3, 4, 5];
|
||||
let mut e = v.swap_remove(0);
|
||||
assert_eq!(e, 1);
|
||||
assert_eq!(v, vec![5, 2, 3, 4]);
|
||||
assert_eq!(v, [5, 2, 3, 4]);
|
||||
e = v.swap_remove(3);
|
||||
assert_eq!(e, 4);
|
||||
assert_eq!(v, vec![5, 2, 3]);
|
||||
assert_eq!(v, [5, 2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -1890,7 +1888,7 @@ mod tests {
|
|||
fn test_retain() {
|
||||
let mut v = vec![1, 2, 3, 4, 5];
|
||||
v.retain(is_odd);
|
||||
assert_eq!(v, vec![1, 3, 5]);
|
||||
assert_eq!(v, [1, 3, 5]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2159,45 +2157,45 @@ mod tests {
|
|||
let v: [Vec<i32>; 0] = [];
|
||||
let c = v.concat();
|
||||
assert_eq!(c, []);
|
||||
let d = [vec![1], vec![2,3]].concat();
|
||||
assert_eq!(d, vec![1, 2, 3]);
|
||||
let d = [vec![1], vec![2, 3]].concat();
|
||||
assert_eq!(d, [1, 2, 3]);
|
||||
|
||||
let v: &[&[_]] = &[&[1], &[2, 3]];
|
||||
assert_eq!(v.connect(&0), vec![1, 0, 2, 3]);
|
||||
assert_eq!(v.connect(&0), [1, 0, 2, 3]);
|
||||
let v: &[&[_]] = &[&[1], &[2], &[3]];
|
||||
assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]);
|
||||
assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_connect() {
|
||||
let v: [Vec<i32>; 0] = [];
|
||||
assert_eq!(v.connect(&0), vec![]);
|
||||
assert_eq!([vec![1], vec![2, 3]].connect(&0), vec![1, 0, 2, 3]);
|
||||
assert_eq!([vec![1], vec![2], vec![3]].connect(&0), vec![1, 0, 2, 0, 3]);
|
||||
assert_eq!(v.connect(&0), []);
|
||||
assert_eq!([vec![1i], vec![2, 3]].connect(&0), [1, 0, 2, 3]);
|
||||
assert_eq!([vec![1i], vec![2], vec![3]].connect(&0), [1, 0, 2, 0, 3]);
|
||||
|
||||
let v: [&[_]; 2] = [&[1], &[2, 3]];
|
||||
assert_eq!(v.connect(&0), vec![1, 0, 2, 3]);
|
||||
assert_eq!(v.connect(&0), [1, 0, 2, 3]);
|
||||
let v: [&[_]; 3] = [&[1], &[2], &[3]];
|
||||
assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]);
|
||||
assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert() {
|
||||
let mut a = vec![1, 2, 4];
|
||||
a.insert(2, 3);
|
||||
assert_eq!(a, vec![1, 2, 3, 4]);
|
||||
assert_eq!(a, [1, 2, 3, 4]);
|
||||
|
||||
let mut a = vec![1, 2, 3];
|
||||
a.insert(0, 0);
|
||||
assert_eq!(a, vec![0, 1, 2, 3]);
|
||||
assert_eq!(a, [0, 1, 2, 3]);
|
||||
|
||||
let mut a = vec![1, 2, 3];
|
||||
a.insert(3, 4);
|
||||
assert_eq!(a, vec![1, 2, 3, 4]);
|
||||
assert_eq!(a, [1, 2, 3, 4]);
|
||||
|
||||
let mut a = vec![];
|
||||
a.insert(0, 1);
|
||||
assert_eq!(a, vec![1]);
|
||||
assert_eq!(a, [1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2212,16 +2210,16 @@ mod tests {
|
|||
let mut a = vec![1, 2, 3, 4];
|
||||
|
||||
assert_eq!(a.remove(2), 3);
|
||||
assert_eq!(a, vec![1, 2, 4]);
|
||||
assert_eq!(a, [1, 2, 4]);
|
||||
|
||||
assert_eq!(a.remove(2), 4);
|
||||
assert_eq!(a, vec![1, 2]);
|
||||
assert_eq!(a, [1, 2]);
|
||||
|
||||
assert_eq!(a.remove(0), 1);
|
||||
assert_eq!(a, vec![2]);
|
||||
assert_eq!(a, [2]);
|
||||
|
||||
assert_eq!(a.remove(0), 2);
|
||||
assert_eq!(a, vec![]);
|
||||
assert_eq!(a, []);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
/// ```
|
||||
/// let v: Vec<char> = "abc åäö".chars().collect();
|
||||
///
|
||||
/// assert_eq!(v, vec!['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
|
||||
/// assert_eq!(v, ['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn chars(&self) -> Chars {
|
||||
|
|
@ -600,20 +600,20 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
///
|
||||
/// ```
|
||||
/// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
|
||||
/// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
|
||||
/// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
|
||||
///
|
||||
/// let v: Vec<&str> = "".split('X').collect();
|
||||
/// assert_eq!(v, vec![""]);
|
||||
/// assert_eq!(v, [""]);
|
||||
/// ```
|
||||
///
|
||||
/// More complex patterns with a lambda:
|
||||
///
|
||||
/// ```
|
||||
/// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
|
||||
/// assert_eq!(v, vec!["abc", "def", "ghi"]);
|
||||
/// assert_eq!(v, ["abc", "def", "ghi"]);
|
||||
///
|
||||
/// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
|
||||
/// assert_eq!(v, vec!["lion", "", "tiger", "leopard"]);
|
||||
/// assert_eq!(v, ["lion", "", "tiger", "leopard"]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
|
||||
|
|
@ -632,23 +632,23 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
///
|
||||
/// ```
|
||||
/// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect();
|
||||
/// assert_eq!(v, vec!["Mary", "had", "a little lambda"]);
|
||||
/// assert_eq!(v, ["Mary", "had", "a little lambda"]);
|
||||
///
|
||||
/// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect();
|
||||
/// assert_eq!(v, vec!["lion", "", "tigerXleopard"]);
|
||||
/// assert_eq!(v, ["lion", "", "tigerXleopard"]);
|
||||
///
|
||||
/// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect();
|
||||
/// assert_eq!(v, vec!["abcXdef"]);
|
||||
/// assert_eq!(v, ["abcXdef"]);
|
||||
///
|
||||
/// let v: Vec<&str> = "".splitn(1, 'X').collect();
|
||||
/// assert_eq!(v, vec![""]);
|
||||
/// assert_eq!(v, [""]);
|
||||
/// ```
|
||||
///
|
||||
/// More complex patterns with a lambda:
|
||||
///
|
||||
/// ```
|
||||
/// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect();
|
||||
/// assert_eq!(v, vec!["abc", "def2ghi"]);
|
||||
/// assert_eq!(v, ["abc", "def2ghi"]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
|
||||
|
|
@ -669,17 +669,17 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
///
|
||||
/// ```
|
||||
/// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
|
||||
/// assert_eq!(v, vec!["A", "B"]);
|
||||
/// assert_eq!(v, ["A", "B"]);
|
||||
///
|
||||
/// let v: Vec<&str> = "A..B..".split_terminator('.').collect();
|
||||
/// assert_eq!(v, vec!["A", "", "B", ""]);
|
||||
/// assert_eq!(v, ["A", "", "B", ""]);
|
||||
/// ```
|
||||
///
|
||||
/// More complex patterns with a lambda:
|
||||
///
|
||||
/// ```
|
||||
/// let v: Vec<&str> = "abc1def2ghi3".split_terminator(|c: char| c.is_numeric()).collect();
|
||||
/// assert_eq!(v, vec!["abc", "def", "ghi"]);
|
||||
/// assert_eq!(v, ["abc", "def", "ghi"]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
|
||||
|
|
@ -699,17 +699,17 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
///
|
||||
/// ```
|
||||
/// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect();
|
||||
/// assert_eq!(v, vec!["lamb", "little", "Mary had a"]);
|
||||
/// assert_eq!(v, ["lamb", "little", "Mary had a"]);
|
||||
///
|
||||
/// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect();
|
||||
/// assert_eq!(v, vec!["leopard", "tiger", "lionX"]);
|
||||
/// assert_eq!(v, ["leopard", "tiger", "lionX"]);
|
||||
/// ```
|
||||
///
|
||||
/// More complex patterns with a lambda:
|
||||
///
|
||||
/// ```
|
||||
/// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect();
|
||||
/// assert_eq!(v, vec!["ghi", "abc1def"]);
|
||||
/// assert_eq!(v, ["ghi", "abc1def"]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> {
|
||||
|
|
@ -727,13 +727,13 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
///
|
||||
/// ```
|
||||
/// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect();
|
||||
/// assert_eq!(v, vec![(0,3), (6,9), (12,15)]);
|
||||
/// assert_eq!(v, [(0,3), (6,9), (12,15)]);
|
||||
///
|
||||
/// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect();
|
||||
/// assert_eq!(v, vec![(1,4), (4,7)]);
|
||||
/// assert_eq!(v, [(1,4), (4,7)]);
|
||||
///
|
||||
/// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect();
|
||||
/// assert_eq!(v, vec![(0, 3)]); // only the first `aba`
|
||||
/// assert_eq!(v, [(0, 3)]); // only the first `aba`
|
||||
/// ```
|
||||
#[unstable(feature = "collections",
|
||||
reason = "might have its iterator type changed")]
|
||||
|
|
@ -749,10 +749,10 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
///
|
||||
/// ```
|
||||
/// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect();
|
||||
/// assert_eq!(v, vec!["", "XXX", "YYY", ""]);
|
||||
/// assert_eq!(v, ["", "XXX", "YYY", ""]);
|
||||
///
|
||||
/// let v: Vec<&str> = "1abcabc2".split_str("abc").collect();
|
||||
/// assert_eq!(v, vec!["1", "", "2"]);
|
||||
/// assert_eq!(v, ["1", "", "2"]);
|
||||
/// ```
|
||||
#[unstable(feature = "collections")]
|
||||
#[deprecated(since = "1.0.0", reason = "use `split()` with a `&str`")]
|
||||
|
|
@ -770,7 +770,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
/// let four_lines = "foo\nbar\n\nbaz";
|
||||
/// let v: Vec<&str> = four_lines.lines().collect();
|
||||
///
|
||||
/// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
|
||||
/// assert_eq!(v, ["foo", "bar", "", "baz"]);
|
||||
/// ```
|
||||
///
|
||||
/// Leaving off the trailing character:
|
||||
|
|
@ -779,7 +779,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
/// let four_lines = "foo\nbar\n\nbaz\n";
|
||||
/// let v: Vec<&str> = four_lines.lines().collect();
|
||||
///
|
||||
/// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
|
||||
/// assert_eq!(v, ["foo", "bar", "", "baz"]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn lines(&self) -> Lines {
|
||||
|
|
@ -796,7 +796,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
/// let four_lines = "foo\r\nbar\n\r\nbaz";
|
||||
/// let v: Vec<&str> = four_lines.lines_any().collect();
|
||||
///
|
||||
/// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
|
||||
/// assert_eq!(v, ["foo", "bar", "", "baz"]);
|
||||
/// ```
|
||||
///
|
||||
/// Leaving off the trailing character:
|
||||
|
|
@ -805,7 +805,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
/// let four_lines = "foo\r\nbar\n\r\nbaz\n";
|
||||
/// let v: Vec<&str> = four_lines.lines_any().collect();
|
||||
///
|
||||
/// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
|
||||
/// assert_eq!(v, ["foo", "bar", "", "baz"]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn lines_any(&self) -> LinesAny {
|
||||
|
|
@ -1441,7 +1441,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||
/// let some_words = " Mary had\ta little \n\t lamb";
|
||||
/// let v: Vec<&str> = some_words.words().collect();
|
||||
///
|
||||
/// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
|
||||
/// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
|
||||
/// ```
|
||||
#[unstable(feature = "str_words",
|
||||
reason = "the precise algorithm to use is unclear")]
|
||||
|
|
@ -2400,17 +2400,17 @@ mod tests {
|
|||
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
|
||||
|
||||
let split: Vec<&str> = data.splitn(3, ' ').collect();
|
||||
assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
|
||||
assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
|
||||
|
||||
let split: Vec<&str> = data.splitn(3, |c: char| c == ' ').collect();
|
||||
assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
|
||||
assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
|
||||
|
||||
// Unicode
|
||||
let split: Vec<&str> = data.splitn(3, 'ä').collect();
|
||||
assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
|
||||
assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
|
||||
|
||||
let split: Vec<&str> = data.splitn(3, |c: char| c == 'ä').collect();
|
||||
assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
|
||||
assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2418,17 +2418,17 @@ mod tests {
|
|||
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
|
||||
|
||||
let split: Vec<&str> = data.split('\n').collect();
|
||||
assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
|
||||
assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
|
||||
|
||||
let split: Vec<&str> = data.split_terminator('\n').collect();
|
||||
assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
|
||||
assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_words() {
|
||||
let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
|
||||
let words: Vec<&str> = data.words().collect();
|
||||
assert_eq!(words, vec!["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
|
||||
assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2513,11 +2513,11 @@ mod tests {
|
|||
fn test_lines() {
|
||||
let data = "\nMäry häd ä little lämb\n\nLittle lämb\n";
|
||||
let lines: Vec<&str> = data.lines().collect();
|
||||
assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]);
|
||||
assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
|
||||
|
||||
let data = "\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
|
||||
let lines: Vec<&str> = data.lines().collect();
|
||||
assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]);
|
||||
assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ impl String {
|
|||
/// let invalid_vec = vec![240, 144, 128];
|
||||
/// let s = String::from_utf8(invalid_vec).err().unwrap();
|
||||
/// assert_eq!(s.utf8_error(), Utf8Error::TooShort);
|
||||
/// assert_eq!(s.into_bytes(), vec![240, 144, 128]);
|
||||
/// assert_eq!(s.into_bytes(), [240, 144, 128]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -340,7 +340,7 @@ impl String {
|
|||
/// ```
|
||||
/// let s = String::from_str("hello");
|
||||
/// let bytes = s.into_bytes();
|
||||
/// assert_eq!(bytes, vec![104, 101, 108, 108, 111]);
|
||||
/// assert_eq!(bytes, [104, 101, 108, 108, 111]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -568,9 +568,9 @@ impl String {
|
|||
|
||||
let CharRange { ch, next } = self.char_range_at(idx);
|
||||
unsafe {
|
||||
ptr::copy_memory(self.vec.as_mut_ptr().offset(idx as isize),
|
||||
self.vec.as_ptr().offset(next as isize),
|
||||
len - next);
|
||||
ptr::copy(self.vec.as_mut_ptr().offset(idx as isize),
|
||||
self.vec.as_ptr().offset(next as isize),
|
||||
len - next);
|
||||
self.vec.set_len(len - (next - idx));
|
||||
}
|
||||
ch
|
||||
|
|
@ -598,12 +598,12 @@ impl String {
|
|||
let amt = ch.encode_utf8(&mut bits).unwrap();
|
||||
|
||||
unsafe {
|
||||
ptr::copy_memory(self.vec.as_mut_ptr().offset((idx + amt) as isize),
|
||||
self.vec.as_ptr().offset(idx as isize),
|
||||
len - idx);
|
||||
ptr::copy_memory(self.vec.as_mut_ptr().offset(idx as isize),
|
||||
bits.as_ptr(),
|
||||
amt);
|
||||
ptr::copy(self.vec.as_mut_ptr().offset((idx + amt) as isize),
|
||||
self.vec.as_ptr().offset(idx as isize),
|
||||
len - idx);
|
||||
ptr::copy(self.vec.as_mut_ptr().offset(idx as isize),
|
||||
bits.as_ptr(),
|
||||
amt);
|
||||
self.vec.set_len(len + amt);
|
||||
}
|
||||
}
|
||||
|
|
@ -619,7 +619,7 @@ impl String {
|
|||
/// let mut s = String::from_str("hello");
|
||||
/// unsafe {
|
||||
/// let vec = s.as_mut_vec();
|
||||
/// assert!(vec == &mut vec![104, 101, 108, 108, 111]);
|
||||
/// assert!(vec == &[104, 101, 108, 108, 111]);
|
||||
/// vec.reverse();
|
||||
/// }
|
||||
/// assert_eq!(s.as_slice(), "olleh");
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ use borrow::{Cow, IntoCow};
|
|||
/// for x in vec.iter() {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// assert_eq!(vec, vec![7, 1, 2, 3]);
|
||||
/// assert_eq!(vec, [7, 1, 2, 3]);
|
||||
/// ```
|
||||
///
|
||||
/// The `vec!` macro is provided to make initialization more convenient:
|
||||
|
|
@ -101,7 +101,7 @@ use borrow::{Cow, IntoCow};
|
|||
/// ```
|
||||
/// let mut vec = vec![1, 2, 3];
|
||||
/// vec.push(4);
|
||||
/// assert_eq!(vec, vec![1, 2, 3, 4]);
|
||||
/// assert_eq!(vec, [1, 2, 3, 4]);
|
||||
/// ```
|
||||
///
|
||||
/// Use a `Vec<T>` as an efficient stack:
|
||||
|
|
@ -242,7 +242,7 @@ impl<T> Vec<T> {
|
|||
///
|
||||
/// // Put everything back together into a Vec
|
||||
/// let rebuilt = Vec::from_raw_parts(p, len, cap);
|
||||
/// assert_eq!(rebuilt, vec![4, 5, 6]);
|
||||
/// assert_eq!(rebuilt, [4, 5, 6]);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
|
|
@ -267,7 +267,7 @@ impl<T> Vec<T> {
|
|||
pub unsafe fn from_raw_buf(ptr: *const T, elts: usize) -> Vec<T> {
|
||||
let mut dst = Vec::with_capacity(elts);
|
||||
dst.set_len(elts);
|
||||
ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
|
||||
ptr::copy_nonoverlapping(dst.as_mut_ptr(), ptr, elts);
|
||||
dst
|
||||
}
|
||||
|
||||
|
|
@ -404,7 +404,7 @@ impl<T> Vec<T> {
|
|||
/// ```
|
||||
/// let mut vec = vec![1, 2, 3, 4];
|
||||
/// vec.truncate(2);
|
||||
/// assert_eq!(vec, vec![1, 2]);
|
||||
/// assert_eq!(vec, [1, 2]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn truncate(&mut self, len: usize) {
|
||||
|
|
@ -505,10 +505,10 @@ impl<T> Vec<T> {
|
|||
/// let mut v = vec!["foo", "bar", "baz", "qux"];
|
||||
///
|
||||
/// assert_eq!(v.swap_remove(1), "bar");
|
||||
/// assert_eq!(v, vec!["foo", "qux", "baz"]);
|
||||
/// assert_eq!(v, ["foo", "qux", "baz"]);
|
||||
///
|
||||
/// assert_eq!(v.swap_remove(0), "foo");
|
||||
/// assert_eq!(v, vec!["baz", "qux"]);
|
||||
/// assert_eq!(v, ["baz", "qux"]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -531,9 +531,9 @@ impl<T> Vec<T> {
|
|||
/// ```
|
||||
/// let mut vec = vec![1, 2, 3];
|
||||
/// vec.insert(1, 4);
|
||||
/// assert_eq!(vec, vec![1, 4, 2, 3]);
|
||||
/// assert_eq!(vec, [1, 4, 2, 3]);
|
||||
/// vec.insert(4, 5);
|
||||
/// assert_eq!(vec, vec![1, 4, 2, 3, 5]);
|
||||
/// assert_eq!(vec, [1, 4, 2, 3, 5]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn insert(&mut self, index: usize, element: T) {
|
||||
|
|
@ -548,7 +548,7 @@ impl<T> Vec<T> {
|
|||
let p = self.as_mut_ptr().offset(index as isize);
|
||||
// Shift everything over to make space. (Duplicating the
|
||||
// `index`th element into two consecutive places.)
|
||||
ptr::copy_memory(p.offset(1), &*p, len - index);
|
||||
ptr::copy(p.offset(1), &*p, len - index);
|
||||
// Write it in, overwriting the first copy of the `index`th
|
||||
// element.
|
||||
ptr::write(&mut *p, element);
|
||||
|
|
@ -569,7 +569,7 @@ impl<T> Vec<T> {
|
|||
/// ```
|
||||
/// let mut v = vec![1, 2, 3];
|
||||
/// assert_eq!(v.remove(1), 2);
|
||||
/// assert_eq!(v, vec![1, 3]);
|
||||
/// assert_eq!(v, [1, 3]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn remove(&mut self, index: usize) -> T {
|
||||
|
|
@ -585,7 +585,7 @@ impl<T> Vec<T> {
|
|||
ret = ptr::read(ptr);
|
||||
|
||||
// Shift everything down to fill in that spot.
|
||||
ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1);
|
||||
ptr::copy(ptr, &*ptr.offset(1), len - index - 1);
|
||||
}
|
||||
self.set_len(len - 1);
|
||||
ret
|
||||
|
|
@ -603,7 +603,7 @@ impl<T> Vec<T> {
|
|||
/// ```
|
||||
/// let mut vec = vec![1, 2, 3, 4];
|
||||
/// vec.retain(|&x| x%2 == 0);
|
||||
/// assert_eq!(vec, vec![2, 4]);
|
||||
/// assert_eq!(vec, [2, 4]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool {
|
||||
|
|
@ -636,7 +636,7 @@ impl<T> Vec<T> {
|
|||
/// ```rust
|
||||
/// let mut vec = vec!(1, 2);
|
||||
/// vec.push(3);
|
||||
/// assert_eq!(vec, vec!(1, 2, 3));
|
||||
/// assert_eq!(vec, [1, 2, 3]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -674,7 +674,7 @@ impl<T> Vec<T> {
|
|||
/// ```rust
|
||||
/// let mut vec = vec![1, 2, 3];
|
||||
/// assert_eq!(vec.pop(), Some(3));
|
||||
/// assert_eq!(vec, vec![1, 2]);
|
||||
/// assert_eq!(vec, [1, 2]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -701,8 +701,8 @@ impl<T> Vec<T> {
|
|||
/// let mut vec = vec![1, 2, 3];
|
||||
/// let mut vec2 = vec![4, 5, 6];
|
||||
/// vec.append(&mut vec2);
|
||||
/// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]);
|
||||
/// assert_eq!(vec2, vec![]);
|
||||
/// assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
|
||||
/// assert_eq!(vec2, []);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "collections",
|
||||
|
|
@ -718,7 +718,7 @@ impl<T> Vec<T> {
|
|||
self.reserve(other.len());
|
||||
let len = self.len();
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping_memory(
|
||||
ptr::copy_nonoverlapping(
|
||||
self.get_unchecked_mut(len),
|
||||
other.as_ptr(),
|
||||
other.len());
|
||||
|
|
@ -1019,8 +1019,8 @@ impl<T> Vec<T> {
|
|||
/// ```
|
||||
/// let mut vec = vec![1,2,3];
|
||||
/// let vec2 = vec.split_off(1);
|
||||
/// assert_eq!(vec, vec![1]);
|
||||
/// assert_eq!(vec2, vec![2, 3]);
|
||||
/// assert_eq!(vec, [1]);
|
||||
/// assert_eq!(vec2, [2, 3]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "collections",
|
||||
|
|
@ -1036,7 +1036,7 @@ impl<T> Vec<T> {
|
|||
self.set_len(at);
|
||||
other.set_len(other_len);
|
||||
|
||||
ptr::copy_nonoverlapping_memory(
|
||||
ptr::copy_nonoverlapping(
|
||||
other.as_mut_ptr(),
|
||||
self.as_ptr().offset(at as isize),
|
||||
other.len());
|
||||
|
|
@ -1057,11 +1057,11 @@ impl<T: Clone> Vec<T> {
|
|||
/// ```
|
||||
/// let mut vec = vec!["hello"];
|
||||
/// vec.resize(3, "world");
|
||||
/// assert_eq!(vec, vec!["hello", "world", "world"]);
|
||||
/// assert_eq!(vec, ["hello", "world", "world"]);
|
||||
///
|
||||
/// let mut vec = vec![1, 2, 3, 4];
|
||||
/// vec.resize(2, 0);
|
||||
/// assert_eq!(vec, vec![1, 2]);
|
||||
/// assert_eq!(vec, [1, 2]);
|
||||
/// ```
|
||||
#[unstable(feature = "collections",
|
||||
reason = "matches collection reform specification; waiting for dust to settle")]
|
||||
|
|
@ -1085,7 +1085,7 @@ impl<T: Clone> Vec<T> {
|
|||
/// ```
|
||||
/// let mut vec = vec![1];
|
||||
/// vec.push_all(&[2, 3, 4]);
|
||||
/// assert_eq!(vec, vec![1, 2, 3, 4]);
|
||||
/// assert_eq!(vec, [1, 2, 3, 4]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "collections",
|
||||
|
|
@ -1121,7 +1121,7 @@ impl<T: PartialEq> Vec<T> {
|
|||
///
|
||||
/// vec.dedup();
|
||||
///
|
||||
/// assert_eq!(vec, vec![1, 2, 3, 2]);
|
||||
/// assert_eq!(vec, [1, 2, 3, 2]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn dedup(&mut self) {
|
||||
|
|
@ -2105,7 +2105,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
assert!(values == vec![2, 3, 5, 6, 7]);
|
||||
assert_eq!(values, [2, 3, 5, 6, 7]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2147,7 +2147,7 @@ mod tests {
|
|||
fn test_retain() {
|
||||
let mut vec = vec![1, 2, 3, 4];
|
||||
vec.retain(|&x| x % 2 == 0);
|
||||
assert!(vec == vec![2, 4]);
|
||||
assert_eq!(vec, [2, 4]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2207,13 +2207,13 @@ mod tests {
|
|||
let a = [1, 2, 3];
|
||||
let ptr = a.as_ptr();
|
||||
let b = Vec::from_raw_buf(ptr, 3);
|
||||
assert_eq!(b, vec![1, 2, 3]);
|
||||
assert_eq!(b, [1, 2, 3]);
|
||||
|
||||
// Test on-heap copy-from-buf.
|
||||
let c = vec![1, 2, 3, 4, 5];
|
||||
let ptr = c.as_ptr();
|
||||
let d = Vec::from_raw_buf(ptr, 5);
|
||||
assert_eq!(d, vec![1, 2, 3, 4, 5]);
|
||||
assert_eq!(d, [1, 2, 3, 4, 5]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2375,7 +2375,7 @@ mod tests {
|
|||
for i in vec {
|
||||
vec2.push(i);
|
||||
}
|
||||
assert!(vec2 == vec![1, 2, 3]);
|
||||
assert_eq!(vec2, [1, 2, 3]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2385,7 +2385,7 @@ mod tests {
|
|||
for i in vec.into_iter().rev() {
|
||||
vec2.push(i);
|
||||
}
|
||||
assert!(vec2 == vec![3, 2, 1]);
|
||||
assert_eq!(vec2, [3, 2, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2395,7 +2395,7 @@ mod tests {
|
|||
for i in vec {
|
||||
vec2.push(i);
|
||||
}
|
||||
assert!(vec2 == vec![(), (), ()]);
|
||||
assert_eq!(vec2, [(), (), ()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2443,16 +2443,16 @@ mod tests {
|
|||
let mut vec = vec![1, 2, 3];
|
||||
let mut vec2 = vec![4, 5, 6];
|
||||
vec.append(&mut vec2);
|
||||
assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(vec2, vec![]);
|
||||
assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(vec2, []);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_off() {
|
||||
let mut vec = vec![1, 2, 3, 4, 5, 6];
|
||||
let vec2 = vec.split_off(4);
|
||||
assert_eq!(vec, vec![1, 2, 3, 4]);
|
||||
assert_eq!(vec2, vec![5, 6]);
|
||||
assert_eq!(vec, [1, 2, 3, 4]);
|
||||
assert_eq!(vec2, [5, 6]);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ impl<T> VecDeque<T> {
|
|||
self.cap);
|
||||
debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
|
||||
self.cap);
|
||||
ptr::copy_memory(
|
||||
ptr::copy(
|
||||
self.ptr.offset(dst as isize),
|
||||
self.ptr.offset(src as isize),
|
||||
len);
|
||||
|
|
@ -147,7 +147,7 @@ impl<T> VecDeque<T> {
|
|||
self.cap);
|
||||
debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
|
||||
self.cap);
|
||||
ptr::copy_nonoverlapping_memory(
|
||||
ptr::copy_nonoverlapping(
|
||||
self.ptr.offset(dst as isize),
|
||||
self.ptr.offset(src as isize),
|
||||
len);
|
||||
|
|
@ -1343,22 +1343,22 @@ impl<T> VecDeque<T> {
|
|||
// `at` lies in the first half.
|
||||
let amount_in_first = first_len - at;
|
||||
|
||||
ptr::copy_nonoverlapping_memory(*other.ptr,
|
||||
first_half.as_ptr().offset(at as isize),
|
||||
amount_in_first);
|
||||
ptr::copy_nonoverlapping(*other.ptr,
|
||||
first_half.as_ptr().offset(at as isize),
|
||||
amount_in_first);
|
||||
|
||||
// just take all of the second half.
|
||||
ptr::copy_nonoverlapping_memory(other.ptr.offset(amount_in_first as isize),
|
||||
second_half.as_ptr(),
|
||||
second_len);
|
||||
ptr::copy_nonoverlapping(other.ptr.offset(amount_in_first as isize),
|
||||
second_half.as_ptr(),
|
||||
second_len);
|
||||
} else {
|
||||
// `at` lies in the second half, need to factor in the elements we skipped
|
||||
// in the first half.
|
||||
let offset = at - first_len;
|
||||
let amount_in_second = second_len - offset;
|
||||
ptr::copy_nonoverlapping_memory(*other.ptr,
|
||||
second_half.as_ptr().offset(offset as isize),
|
||||
amount_in_second);
|
||||
ptr::copy_nonoverlapping(*other.ptr,
|
||||
second_half.as_ptr().offset(offset as isize),
|
||||
amount_in_second);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1754,7 +1754,7 @@ impl<A> Extend<A> for VecDeque<A> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: fmt::Debug> fmt::Debug for VecDeque<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "VecDeque ["));
|
||||
try!(write!(f, "["));
|
||||
|
||||
for (i, e) in self.iter().enumerate() {
|
||||
if i != 0 { try!(write!(f, ", ")); }
|
||||
|
|
@ -2105,7 +2105,7 @@ mod tests {
|
|||
let mut d: VecDeque<_> = (0..5).collect();
|
||||
d.pop_front();
|
||||
d.swap(0, 3);
|
||||
assert_eq!(d.iter().cloned().collect::<Vec<_>>(), vec!(4, 2, 3, 1));
|
||||
assert_eq!(d.iter().cloned().collect::<Vec<_>>(), [4, 2, 3, 1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2435,12 +2435,12 @@ mod tests {
|
|||
#[test]
|
||||
fn test_show() {
|
||||
let ringbuf: VecDeque<_> = (0..10).collect();
|
||||
assert_eq!(format!("{:?}", ringbuf), "VecDeque [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
|
||||
assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
|
||||
|
||||
let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter()
|
||||
.cloned()
|
||||
.collect();
|
||||
assert_eq!(format!("{:?}", ringbuf), "VecDeque [\"just\", \"one\", \"test\", \"more\"]");
|
||||
assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -2868,17 +2868,17 @@ mod tests {
|
|||
|
||||
// normal append
|
||||
a.append(&mut b);
|
||||
assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(b.iter().cloned().collect(), vec![]);
|
||||
assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []);
|
||||
|
||||
// append nothing to something
|
||||
a.append(&mut b);
|
||||
assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(b.iter().cloned().collect(), vec![]);
|
||||
assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []);
|
||||
|
||||
// append something to nothing
|
||||
b.append(&mut a);
|
||||
assert_eq!(b.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(a.iter().cloned().collect(), vec![]);
|
||||
assert_eq!(b.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
|
||||
assert_eq!(a.iter().cloned().collect::<Vec<_>>(), []);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -308,7 +308,7 @@ impl<V> VecMap<V> {
|
|||
///
|
||||
/// let vec: Vec<(usize, &str)> = map.into_iter().collect();
|
||||
///
|
||||
/// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
|
||||
/// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<V> {
|
||||
|
|
@ -425,7 +425,7 @@ impl<V> VecMap<V> {
|
|||
///
|
||||
/// let vec: Vec<(usize, &str)> = map.drain().collect();
|
||||
///
|
||||
/// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
|
||||
/// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
|
||||
/// ```
|
||||
#[unstable(feature = "collections",
|
||||
reason = "matches collection reform specification, waiting for dust to settle")]
|
||||
|
|
@ -739,7 +739,7 @@ impl<V: Ord> Ord for VecMap<V> {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<V: fmt::Debug> fmt::Debug for VecMap<V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "VecMap {{"));
|
||||
try!(write!(f, "{{"));
|
||||
|
||||
for (i, (k, v)) in self.iter().enumerate() {
|
||||
if i != 0 { try!(write!(f, ", ")); }
|
||||
|
|
@ -1226,7 +1226,7 @@ mod test_map {
|
|||
|
||||
let vec: Vec<_> = map.drain().collect();
|
||||
|
||||
assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
|
||||
assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
|
||||
assert_eq!(map.len(), 0);
|
||||
}
|
||||
|
||||
|
|
@ -1318,8 +1318,8 @@ mod test_map {
|
|||
map.insert(3, 4);
|
||||
|
||||
let map_str = format!("{:?}", map);
|
||||
assert!(map_str == "VecMap {1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
|
||||
assert_eq!(format!("{:?}", empty), "VecMap {}");
|
||||
assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
|
||||
assert_eq!(format!("{:?}", empty), "{}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ extern "rust-intrinsic" {
|
|||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "core")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
|
||||
|
||||
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
|
||||
|
|
@ -323,13 +323,12 @@ extern "rust-intrinsic" {
|
|||
/// }
|
||||
/// ```
|
||||
///
|
||||
#[unstable(feature = "core")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn copy_memory<T>(dst: *mut T, src: *const T, count: usize);
|
||||
|
||||
/// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
|
||||
/// bytes of memory starting at `dst` to `c`.
|
||||
#[unstable(feature = "core",
|
||||
reason = "uncertain about naming and semantics")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn set_memory<T>(dst: *mut T, val: u8, count: usize);
|
||||
|
||||
/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
|
||||
|
|
|
|||
|
|
@ -582,8 +582,8 @@ pub trait IteratorExt: Iterator + Sized {
|
|||
/// ```
|
||||
/// let vec = vec![1, 2, 3, 4];
|
||||
/// let (even, odd): (Vec<_>, Vec<_>) = vec.into_iter().partition(|&n| n % 2 == 0);
|
||||
/// assert_eq!(even, vec![2, 4]);
|
||||
/// assert_eq!(odd, vec![1, 3]);
|
||||
/// assert_eq!(even, [2, 4]);
|
||||
/// assert_eq!(odd, [1, 3]);
|
||||
/// ```
|
||||
#[unstable(feature = "core",
|
||||
reason = "recently added as part of collections reform")]
|
||||
|
|
|
|||
|
|
@ -203,9 +203,9 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
|
|||
let mut t: T = uninitialized();
|
||||
|
||||
// Perform the swap, `&mut` pointers never alias
|
||||
ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
|
||||
ptr::copy_nonoverlapping_memory(x, &*y, 1);
|
||||
ptr::copy_nonoverlapping_memory(y, &t, 1);
|
||||
ptr::copy_nonoverlapping(&mut t, &*x, 1);
|
||||
ptr::copy_nonoverlapping(x, &*y, 1);
|
||||
ptr::copy_nonoverlapping(y, &t, 1);
|
||||
|
||||
// y and t now point to the same thing, but we need to completely forget `t`
|
||||
// because it's no longer relevant.
|
||||
|
|
|
|||
|
|
@ -1672,6 +1672,7 @@ macro_rules! from_str_radix_int_impl {
|
|||
let is_signed_ty = (0 as $T) > Int::min_value();
|
||||
|
||||
match src.slice_shift_char() {
|
||||
Some(('-', "")) => Err(PIE { kind: Empty }),
|
||||
Some(('-', src)) if is_signed_ty => {
|
||||
// The number is negative
|
||||
let mut result = 0;
|
||||
|
|
|
|||
|
|
@ -556,7 +556,7 @@ impl<T> Option<T> {
|
|||
/// ```
|
||||
/// let x = Some("string");
|
||||
/// let v: Vec<&str> = x.into_iter().collect();
|
||||
/// assert_eq!(v, vec!["string"]);
|
||||
/// assert_eq!(v, ["string"]);
|
||||
///
|
||||
/// let x = None;
|
||||
/// let v: Vec<&str> = x.into_iter().collect();
|
||||
|
|
|
|||
|
|
@ -101,16 +101,28 @@ use cmp::Ordering::{self, Less, Equal, Greater};
|
|||
|
||||
// FIXME #19649: intrinsic docs don't render, so these have no docs :(
|
||||
|
||||
#[unstable(feature = "core")]
|
||||
pub use intrinsics::copy_nonoverlapping_memory;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use intrinsics::copy_nonoverlapping_memory as copy_nonoverlapping;
|
||||
|
||||
#[unstable(feature = "core")]
|
||||
pub use intrinsics::copy_memory;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use intrinsics::copy_memory as copy;
|
||||
|
||||
#[unstable(feature = "core",
|
||||
reason = "uncertain about naming and semantics")]
|
||||
pub use intrinsics::set_memory;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use intrinsics::set_memory as write_bytes;
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to `copy_nonoverlapping`")]
|
||||
pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to `copy`")]
|
||||
pub fn copy_memory<T>(dst: *mut T, src: *const T, count: usize);
|
||||
|
||||
#[unstable(feature = "core",
|
||||
reason = "uncertain about naming and semantics")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to `write_bytes`")]
|
||||
pub fn set_memory<T>(dst: *mut T, val: u8, count: usize);
|
||||
}
|
||||
|
||||
/// Creates a null raw pointer.
|
||||
///
|
||||
|
|
@ -150,8 +162,9 @@ pub fn null_mut<T>() -> *mut T { 0 as *mut T }
|
|||
#[inline]
|
||||
#[unstable(feature = "core",
|
||||
reason = "may play a larger role in std::ptr future extensions")]
|
||||
#[deprecated(since = "1.0.0", reason = "use `write_bytes` instead")]
|
||||
pub unsafe fn zero_memory<T>(dst: *mut T, count: usize) {
|
||||
set_memory(dst, 0, count);
|
||||
write_bytes(dst, 0, count);
|
||||
}
|
||||
|
||||
/// Swaps the values at two mutable locations of the same type, without
|
||||
|
|
@ -169,9 +182,9 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
|
|||
let t: *mut T = &mut tmp;
|
||||
|
||||
// Perform the swap
|
||||
copy_nonoverlapping_memory(t, &*x, 1);
|
||||
copy_memory(x, &*y, 1); // `x` and `y` may overlap
|
||||
copy_nonoverlapping_memory(y, &*t, 1);
|
||||
copy_nonoverlapping(t, &*x, 1);
|
||||
copy(x, &*y, 1); // `x` and `y` may overlap
|
||||
copy_nonoverlapping(y, &*t, 1);
|
||||
|
||||
// y and t now point to the same thing, but we need to completely forget `tmp`
|
||||
// because it's no longer relevant.
|
||||
|
|
@ -207,7 +220,7 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub unsafe fn read<T>(src: *const T) -> T {
|
||||
let mut tmp: T = mem::uninitialized();
|
||||
copy_nonoverlapping_memory(&mut tmp, src, 1);
|
||||
copy_nonoverlapping(&mut tmp, src, 1);
|
||||
tmp
|
||||
}
|
||||
|
||||
|
|
@ -224,7 +237,7 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
|
|||
let tmp = read(&*dest);
|
||||
|
||||
// Now zero out `dest`:
|
||||
zero_memory(dest, 1);
|
||||
write_bytes(dest, 0, 1);
|
||||
|
||||
tmp
|
||||
}
|
||||
|
|
@ -248,9 +261,9 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
|
|||
|
||||
/// Methods on raw pointers
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait PtrExt: Sized {
|
||||
pub trait PtrExt {
|
||||
/// The type which is being pointed at
|
||||
type Target;
|
||||
type Target: ?Sized;
|
||||
|
||||
/// Returns true if the pointer is null.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -279,14 +292,14 @@ pub trait PtrExt: Sized {
|
|||
/// Otherwise `offset` invokes Undefined Behaviour, regardless of whether
|
||||
/// the pointer is used.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe fn offset(self, count: isize) -> Self;
|
||||
unsafe fn offset(self, count: isize) -> Self where Self::Target: Sized;
|
||||
}
|
||||
|
||||
/// Methods on mutable raw pointers
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait MutPtrExt {
|
||||
/// The type which is being pointed at
|
||||
type Target;
|
||||
type Target: ?Sized;
|
||||
|
||||
/// Returns `None` if the pointer is null, or else returns a mutable
|
||||
/// reference to the value wrapped in `Some`.
|
||||
|
|
@ -302,7 +315,7 @@ pub trait MutPtrExt {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> PtrExt for *const T {
|
||||
impl<T: ?Sized> PtrExt for *const T {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
|
|
@ -311,7 +324,7 @@ impl<T> PtrExt for *const T {
|
|||
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe fn offset(self, count: isize) -> *const T {
|
||||
unsafe fn offset(self, count: isize) -> *const T where T: Sized {
|
||||
intrinsics::offset(self, count)
|
||||
}
|
||||
|
||||
|
|
@ -329,7 +342,7 @@ impl<T> PtrExt for *const T {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> PtrExt for *mut T {
|
||||
impl<T: ?Sized> PtrExt for *mut T {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
|
|
@ -338,7 +351,7 @@ impl<T> PtrExt for *mut T {
|
|||
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe fn offset(self, count: isize) -> *mut T {
|
||||
unsafe fn offset(self, count: isize) -> *mut T where T: Sized {
|
||||
intrinsics::offset(self, count) as *mut T
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +369,7 @@ impl<T> PtrExt for *mut T {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> MutPtrExt for *mut T {
|
||||
impl<T: ?Sized> MutPtrExt for *mut T {
|
||||
type Target = T;
|
||||
|
||||
#[inline]
|
||||
|
|
@ -374,33 +387,25 @@ impl<T> MutPtrExt for *mut T {
|
|||
|
||||
// Equality for pointers
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> PartialEq for *const T {
|
||||
impl<T: ?Sized> PartialEq for *const T {
|
||||
#[inline]
|
||||
fn eq(&self, other: &*const T) -> bool {
|
||||
*self == *other
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &*const T) -> bool { !self.eq(other) }
|
||||
fn eq(&self, other: &*const T) -> bool { *self == *other }
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Eq for *const T {}
|
||||
impl<T: ?Sized> Eq for *const T {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> PartialEq for *mut T {
|
||||
impl<T: ?Sized> PartialEq for *mut T {
|
||||
#[inline]
|
||||
fn eq(&self, other: &*mut T) -> bool {
|
||||
*self == *other
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &*mut T) -> bool { !self.eq(other) }
|
||||
fn eq(&self, other: &*mut T) -> bool { *self == *other }
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Eq for *mut T {}
|
||||
impl<T: ?Sized> Eq for *mut T {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for *const T {
|
||||
impl<T: ?Sized> Clone for *const T {
|
||||
#[inline]
|
||||
fn clone(&self) -> *const T {
|
||||
*self
|
||||
|
|
@ -408,7 +413,7 @@ impl<T> Clone for *const T {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Clone for *mut T {
|
||||
impl<T: ?Sized> Clone for *mut T {
|
||||
#[inline]
|
||||
fn clone(&self) -> *mut T {
|
||||
*self
|
||||
|
|
@ -452,7 +457,7 @@ mod externfnpointers {
|
|||
|
||||
// Comparison for pointers
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Ord for *const T {
|
||||
impl<T: ?Sized> Ord for *const T {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &*const T) -> Ordering {
|
||||
if self < other {
|
||||
|
|
@ -466,7 +471,7 @@ impl<T> Ord for *const T {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> PartialOrd for *const T {
|
||||
impl<T: ?Sized> PartialOrd for *const T {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
|
|
@ -486,7 +491,7 @@ impl<T> PartialOrd for *const T {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> Ord for *mut T {
|
||||
impl<T: ?Sized> Ord for *mut T {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &*mut T) -> Ordering {
|
||||
if self < other {
|
||||
|
|
@ -500,7 +505,7 @@ impl<T> Ord for *mut T {
|
|||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> PartialOrd for *mut T {
|
||||
impl<T: ?Sized> PartialOrd for *mut T {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
|
|
@ -527,8 +532,8 @@ impl<T> PartialOrd for *mut T {
|
|||
/// modified without a unique path to the `Unique` reference. Useful
|
||||
/// for building abstractions like `Vec<T>` or `Box<T>`, which
|
||||
/// internally use raw pointers to manage the memory that they own.
|
||||
#[unstable(feature = "core", reason = "recently added to this module")]
|
||||
pub struct Unique<T:?Sized> {
|
||||
#[unstable(feature = "unique")]
|
||||
pub struct Unique<T: ?Sized> {
|
||||
pointer: NonZero<*const T>,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
|
@ -537,39 +542,37 @@ pub struct Unique<T:?Sized> {
|
|||
/// reference is unaliased. Note that this aliasing invariant is
|
||||
/// unenforced by the type system; the abstraction using the
|
||||
/// `Unique` must enforce it.
|
||||
#[unstable(feature = "core", reason = "recently added to this module")]
|
||||
#[unstable(feature = "unique")]
|
||||
unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
|
||||
|
||||
/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
|
||||
/// reference is unaliased. Note that this aliasing invariant is
|
||||
/// unenforced by the type system; the abstraction using the
|
||||
/// `Unique` must enforce it.
|
||||
#[unstable(feature = "core", reason = "recently added to this module")]
|
||||
#[unstable(feature = "unique")]
|
||||
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
|
||||
|
||||
impl<T:?Sized> Unique<T> {
|
||||
impl<T: ?Sized> Unique<T> {
|
||||
/// Create a new `Unique`.
|
||||
#[unstable(feature = "core",
|
||||
reason = "recently added to this module")]
|
||||
#[unstable(feature = "unique")]
|
||||
pub unsafe fn new(ptr: *mut T) -> Unique<T> {
|
||||
Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData }
|
||||
}
|
||||
|
||||
/// Dereference the content.
|
||||
#[unstable(feature = "core",
|
||||
reason = "recently added to this module")]
|
||||
#[unstable(feature = "unique")]
|
||||
pub unsafe fn get(&self) -> &T {
|
||||
&**self.pointer
|
||||
}
|
||||
|
||||
/// Mutably dereference the content.
|
||||
#[unstable(feature = "core",
|
||||
reason = "recently added to this module")]
|
||||
#[unstable(feature = "unique")]
|
||||
pub unsafe fn get_mut(&mut self) -> &mut T {
|
||||
&mut ***self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "unique")]
|
||||
impl<T:?Sized> Deref for Unique<T> {
|
||||
type Target = *mut T;
|
||||
|
||||
|
|
|
|||
|
|
@ -548,11 +548,11 @@ impl<T, E> Result<T, E> {
|
|||
/// ```
|
||||
/// let x: Result<u32, &str> = Ok(5);
|
||||
/// let v: Vec<u32> = x.into_iter().collect();
|
||||
/// assert_eq!(v, vec![5]);
|
||||
/// assert_eq!(v, [5]);
|
||||
///
|
||||
/// let x: Result<u32, &str> = Err("nothing!");
|
||||
/// let v: Vec<u32> = x.into_iter().collect();
|
||||
/// assert_eq!(v, vec![]);
|
||||
/// assert_eq!(v, []);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
|
|||
|
|
@ -1500,7 +1500,7 @@ pub mod bytes {
|
|||
impl MutableByteVector for [u8] {
|
||||
#[inline]
|
||||
fn set_memory(&mut self, value: u8) {
|
||||
unsafe { ptr::set_memory(self.as_mut_ptr(), value, self.len()) };
|
||||
unsafe { ptr::write_bytes(self.as_mut_ptr(), value, self.len()) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1514,9 +1514,9 @@ pub mod bytes {
|
|||
// `dst` is unaliasable, so we know statically it doesn't overlap
|
||||
// with `src`.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(),
|
||||
src.as_ptr(),
|
||||
len_src);
|
||||
ptr::copy_nonoverlapping(dst.as_mut_ptr(),
|
||||
src.as_ptr(),
|
||||
len_src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ fn test_multi_iter() {
|
|||
fn test_counter_from_iter() {
|
||||
let it = count(0, 5).take(10);
|
||||
let xs: Vec<int> = FromIterator::from_iter(it);
|
||||
assert!(xs == vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
|
||||
assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -104,7 +104,7 @@ fn test_iterator_chain() {
|
|||
fn test_filter_map() {
|
||||
let it = count(0, 1).take(10)
|
||||
.filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
|
||||
assert!(it.collect::<Vec<uint>>() == vec![0*0, 2*2, 4*4, 6*6, 8*8]);
|
||||
assert_eq!(it.collect::<Vec<uint>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -730,12 +730,12 @@ fn test_random_access_cycle() {
|
|||
|
||||
#[test]
|
||||
fn test_double_ended_range() {
|
||||
assert!((11..14).rev().collect::<Vec<_>>() == vec![13, 12, 11]);
|
||||
assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
|
||||
for _ in (10..0).rev() {
|
||||
panic!("unreachable");
|
||||
}
|
||||
|
||||
assert!((11..14).rev().collect::<Vec<_>>() == vec![13, 12, 11]);
|
||||
assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
|
||||
for _ in (10..0).rev() {
|
||||
panic!("unreachable");
|
||||
}
|
||||
|
|
@ -743,10 +743,9 @@ fn test_double_ended_range() {
|
|||
|
||||
#[test]
|
||||
fn test_range() {
|
||||
assert!((0..5).collect::<Vec<_>>() == vec![0, 1, 2, 3, 4]);
|
||||
assert!((-10..-1).collect::<Vec<_>>() ==
|
||||
vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]);
|
||||
assert!((0..5).rev().collect::<Vec<_>>() == vec![4, 3, 2, 1, 0]);
|
||||
assert_eq!((0..5).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
|
||||
assert_eq!((-10..-1).collect::<Vec<_>>(), [-10, -9, -8, -7, -6, -5, -4, -3, -2]);
|
||||
assert_eq!((0..5).rev().collect::<Vec<_>>(), [4, 3, 2, 1, 0]);
|
||||
assert_eq!((200..-5).count(), 0);
|
||||
assert_eq!((200..-5).rev().count(), 0);
|
||||
assert_eq!((200..200).count(), 0);
|
||||
|
|
@ -767,38 +766,28 @@ fn test_range_inclusive() {
|
|||
vec![5, 4, 3, 2, 1, 0]);
|
||||
assert_eq!(range_inclusive(200, -5).count(), 0);
|
||||
assert_eq!(range_inclusive(200, -5).rev().count(), 0);
|
||||
assert!(range_inclusive(200, 200).collect::<Vec<int>>() == vec![200]);
|
||||
assert!(range_inclusive(200, 200).rev().collect::<Vec<int>>() == vec![200]);
|
||||
assert_eq!(range_inclusive(200, 200).collect::<Vec<int>>(), [200]);
|
||||
assert_eq!(range_inclusive(200, 200).rev().collect::<Vec<int>>(), [200]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_step() {
|
||||
assert!(range_step(0, 20, 5).collect::<Vec<int>>() ==
|
||||
vec![0, 5, 10, 15]);
|
||||
assert!(range_step(20, 0, -5).collect::<Vec<int>>() ==
|
||||
vec![20, 15, 10, 5]);
|
||||
assert!(range_step(20, 0, -6).collect::<Vec<int>>() ==
|
||||
vec![20, 14, 8, 2]);
|
||||
assert!(range_step(200u8, 255, 50).collect::<Vec<u8>>() ==
|
||||
vec![200u8, 250]);
|
||||
assert!(range_step(200, -5, 1).collect::<Vec<int>>() == vec![]);
|
||||
assert!(range_step(200, 200, 1).collect::<Vec<int>>() == vec![]);
|
||||
assert_eq!(range_step(0, 20, 5).collect::<Vec<int>>(), [0, 5, 10, 15]);
|
||||
assert_eq!(range_step(20, 0, -5).collect::<Vec<int>>(), [20, 15, 10, 5]);
|
||||
assert_eq!(range_step(20, 0, -6).collect::<Vec<int>>(), [20, 14, 8, 2]);
|
||||
assert_eq!(range_step(200u8, 255, 50).collect::<Vec<u8>>(), [200u8, 250]);
|
||||
assert_eq!(range_step(200i, -5, 1).collect::<Vec<int>>(), []);
|
||||
assert_eq!(range_step(200i, 200, 1).collect::<Vec<int>>(), []);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_step_inclusive() {
|
||||
assert!(range_step_inclusive(0, 20, 5).collect::<Vec<int>>() ==
|
||||
vec![0, 5, 10, 15, 20]);
|
||||
assert!(range_step_inclusive(20, 0, -5).collect::<Vec<int>>() ==
|
||||
vec![20, 15, 10, 5, 0]);
|
||||
assert!(range_step_inclusive(20, 0, -6).collect::<Vec<int>>() ==
|
||||
vec![20, 14, 8, 2]);
|
||||
assert!(range_step_inclusive(200u8, 255, 50).collect::<Vec<u8>>() ==
|
||||
vec![200u8, 250]);
|
||||
assert!(range_step_inclusive(200, -5, 1).collect::<Vec<int>>() ==
|
||||
vec![]);
|
||||
assert!(range_step_inclusive(200, 200, 1).collect::<Vec<int>>() ==
|
||||
vec![200]);
|
||||
assert_eq!(range_step_inclusive(0, 20, 5).collect::<Vec<int>>(), [0, 5, 10, 15, 20]);
|
||||
assert_eq!(range_step_inclusive(20, 0, -5).collect::<Vec<int>>(), [20, 15, 10, 5, 0]);
|
||||
assert_eq!(range_step_inclusive(20, 0, -6).collect::<Vec<int>>(), [20, 14, 8, 2]);
|
||||
assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<Vec<u8>>(), [200u8, 250]);
|
||||
assert_eq!(range_step_inclusive(200, -5, 1).collect::<Vec<int>>(), []);
|
||||
assert_eq!(range_step_inclusive(200, 200, 1).collect::<Vec<int>>(), [200]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ fn test_transmute() {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
assert!(vec![76u8] == transmute::<_, Vec<u8>>("L".to_string()));
|
||||
assert_eq!([76u8], transmute::<_, Vec<u8>>("L".to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ fn test_match_option_empty_vec() {
|
|||
fn test_match_option_vec() {
|
||||
let a = Some(vec![1, 2, 3, 4]);
|
||||
match a {
|
||||
Some(v) => assert_eq!(v, vec![1, 2, 3, 4]),
|
||||
Some(v) => assert_eq!(v, [1, 2, 3, 4]),
|
||||
None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,4 +122,9 @@ mod test {
|
|||
assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val));
|
||||
assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_int_from_minus_sign() {
|
||||
assert_eq!("-".parse::<i32>().ok(), None);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ fn test_ptr_subtraction() {
|
|||
m_ptr = m_ptr.offset(-1);
|
||||
}
|
||||
|
||||
assert!(xs_mut == vec![0,2,4,6,8,10,12,14,16,18]);
|
||||
assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ fn test_pattern_deref_forward() {
|
|||
fn test_empty_match_indices() {
|
||||
let data = "aä中!";
|
||||
let vec: Vec<_> = data.match_indices("").collect();
|
||||
assert_eq!(vec, vec![(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]);
|
||||
assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -69,20 +69,20 @@ fn test_rsplitn_char_iterator() {
|
|||
|
||||
let mut split: Vec<&str> = data.rsplitn(3, ' ').collect();
|
||||
split.reverse();
|
||||
assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
|
||||
let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == ' ').collect();
|
||||
split.reverse();
|
||||
assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
|
||||
// Unicode
|
||||
let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect();
|
||||
split.reverse();
|
||||
assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
|
||||
let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == 'ä').collect();
|
||||
split.reverse();
|
||||
assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -90,33 +90,33 @@ fn test_split_char_iterator() {
|
|||
let data = "\nMäry häd ä little lämb\nLittle lämb\n";
|
||||
|
||||
let split: Vec<&str> = data.split(' ').collect();
|
||||
assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
|
||||
let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
|
||||
rsplit.reverse();
|
||||
assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
|
||||
let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
|
||||
assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
|
||||
let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
|
||||
rsplit.reverse();
|
||||
assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
|
||||
|
||||
// Unicode
|
||||
let split: Vec<&str> = data.split('ä').collect();
|
||||
assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
|
||||
let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
|
||||
rsplit.reverse();
|
||||
assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
|
||||
let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
|
||||
assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
|
||||
let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
|
||||
rsplit.reverse();
|
||||
assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -125,18 +125,18 @@ fn test_rev_split_char_iterator_no_trailing() {
|
|||
|
||||
let mut split: Vec<&str> = data.split('\n').rev().collect();
|
||||
split.reverse();
|
||||
assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
|
||||
assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
|
||||
|
||||
let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
|
||||
split.reverse();
|
||||
assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
|
||||
assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_utf16_code_units() {
|
||||
use unicode::str::Utf16Encoder;
|
||||
assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
|
||||
vec![0xE9, 0xD83D, 0xDCA9])
|
||||
[0xE9, 0xD83D, 0xDCA9])
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#![feature(int_uint)]
|
||||
#![feature(libc)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(unique)]
|
||||
|
||||
#[cfg(test)] #[macro_use] extern crate log;
|
||||
|
||||
|
|
|
|||
|
|
@ -1362,7 +1362,6 @@ pub mod types {
|
|||
use types::os::arch::c95::{c_long};
|
||||
pub type off_t = i64;
|
||||
pub type dev_t = i32;
|
||||
pub type ino_t = u64;
|
||||
pub type pid_t = i32;
|
||||
pub type uid_t = u32;
|
||||
pub type gid_t = u32;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64>
|
|||
/// let mut w = SeekableMemWriter::new();
|
||||
/// w.write(&[0, 1, 2]);
|
||||
///
|
||||
/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
|
||||
/// assert_eq!(w.unwrap(), [0, 1, 2]);
|
||||
/// ```
|
||||
pub struct SeekableMemWriter {
|
||||
buf: Vec<u8>,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#![feature(staged_api)]
|
||||
#![feature(std_misc)]
|
||||
#![feature(unicode)]
|
||||
#![feature(os)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
|
||||
extern crate arena;
|
||||
|
|
|
|||
|
|
@ -1295,48 +1295,38 @@ impl LintPass for UnsafeCode {
|
|||
}
|
||||
|
||||
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
|
||||
use syntax::ast::Unsafety::Unsafe;
|
||||
|
||||
fn check_method(cx: &Context, meth: &P<ast::Method>) {
|
||||
if let ast::Method_::MethDecl(_, _, _, _, Unsafe, _, _, _) = meth.node {
|
||||
cx.span_lint(UNSAFE_CODE, meth.span, "implementation of an `unsafe` method");
|
||||
}
|
||||
}
|
||||
|
||||
match it.node {
|
||||
ast::ItemFn(_, Unsafe, _, _, _) =>
|
||||
cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` function"),
|
||||
ast::ItemTrait(ast::Unsafety::Unsafe, _, _, _) =>
|
||||
cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"),
|
||||
|
||||
ast::ItemTrait(trait_safety, _, _, ref items) => {
|
||||
if trait_safety == Unsafe {
|
||||
cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait");
|
||||
}
|
||||
|
||||
for it in items {
|
||||
match *it {
|
||||
ast::RequiredMethod(ast::TypeMethod { unsafety: Unsafe, span, ..}) =>
|
||||
cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` method"),
|
||||
ast::ProvidedMethod(ref meth) => check_method(cx, meth),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ast::ItemImpl(impl_safety, _, _, _, _, ref impls) => {
|
||||
if impl_safety == Unsafe {
|
||||
cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait");
|
||||
}
|
||||
|
||||
for item in impls {
|
||||
if let ast::ImplItem::MethodImplItem(ref meth) = *item {
|
||||
check_method(cx, meth);
|
||||
}
|
||||
}
|
||||
},
|
||||
ast::ItemImpl(ast::Unsafety::Unsafe, _, _, _, _, _) =>
|
||||
cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait"),
|
||||
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
|
||||
fn check_fn(&mut self, cx: &Context, fk: visit::FnKind, _: &ast::FnDecl,
|
||||
_: &ast::Block, span: Span, _: ast::NodeId) {
|
||||
match fk {
|
||||
visit::FkItemFn(_, _, ast::Unsafety::Unsafe, _) =>
|
||||
cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function"),
|
||||
|
||||
visit::FkMethod(_, _, m) => {
|
||||
if let ast::Method_::MethDecl(_, _, _, _, ast::Unsafety::Unsafe, _, _, _) = m.node {
|
||||
cx.span_lint(UNSAFE_CODE, m.span, "implementation of an `unsafe` method")
|
||||
}
|
||||
},
|
||||
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_ty_method(&mut self, cx: &Context, ty_method: &ast::TypeMethod) {
|
||||
if let ast::TypeMethod { unsafety: ast::Unsafety::Unsafe, span, ..} = *ty_method {
|
||||
cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` method")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ pub use self::FileMatch::*;
|
|||
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::os;
|
||||
use std::old_io::fs::PathExtensions;
|
||||
use std::old_io::fs;
|
||||
|
||||
|
|
@ -194,7 +195,7 @@ pub fn get_or_default_sysroot() -> Path {
|
|||
})
|
||||
}
|
||||
|
||||
match canonicalize(env::current_exe().ok()) {
|
||||
match canonicalize(os::self_exe_name()) {
|
||||
Some(mut p) => { p.pop(); p.pop(); p }
|
||||
None => panic!("can't determine value for sysroot")
|
||||
}
|
||||
|
|
@ -224,7 +225,7 @@ pub fn rust_path() -> Vec<Path> {
|
|||
}
|
||||
None => Vec::new()
|
||||
};
|
||||
let mut cwd = env::current_dir().unwrap();
|
||||
let mut cwd = os::getcwd().unwrap();
|
||||
// now add in default entries
|
||||
let cwd_dot_rust = cwd.join(".rust");
|
||||
if !env_rust_path.contains(&cwd_dot_rust) {
|
||||
|
|
@ -243,7 +244,7 @@ pub fn rust_path() -> Vec<Path> {
|
|||
}
|
||||
cwd.pop();
|
||||
}
|
||||
if let Some(h) = env::home_dir() {
|
||||
if let Some(h) = os::homedir() {
|
||||
let p = h.join(".rust");
|
||||
if !env_rust_path.contains(&p) && p.exists() {
|
||||
env_rust_path.push(p);
|
||||
|
|
|
|||
|
|
@ -736,12 +736,10 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
|
|||
}
|
||||
};
|
||||
return match ArchiveMetadata::new(archive).map(|ar| MetadataArchive(ar)) {
|
||||
None => {
|
||||
return Err((format!("failed to read rlib metadata: '{}'",
|
||||
filename.display())))
|
||||
}
|
||||
Some(blob) => return Ok(blob)
|
||||
}
|
||||
None => Err(format!("failed to read rlib metadata: '{}'",
|
||||
filename.display())),
|
||||
Some(blob) => Ok(blob)
|
||||
};
|
||||
}
|
||||
unsafe {
|
||||
let buf = CString::new(filename.as_vec()).unwrap();
|
||||
|
|
@ -791,7 +789,7 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
|
|||
}
|
||||
llvm::LLVMMoveToNextSection(si.llsi);
|
||||
}
|
||||
return Err(format!("metadata not found: '{}'", filename.display()));
|
||||
Err(format!("metadata not found: '{}'", filename.display()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -228,11 +228,11 @@ pub trait Combine<'tcx> : Sized {
|
|||
variadic: a.variadic});
|
||||
|
||||
|
||||
fn argvecs<'tcx, C: Combine<'tcx>>(combiner: &C,
|
||||
a_args: &[Ty<'tcx>],
|
||||
b_args: &[Ty<'tcx>])
|
||||
-> cres<'tcx, Vec<Ty<'tcx>>>
|
||||
{
|
||||
fn argvecs<'tcx, C>(combiner: &C,
|
||||
a_args: &[Ty<'tcx>],
|
||||
b_args: &[Ty<'tcx>])
|
||||
-> cres<'tcx, Vec<Ty<'tcx>>>
|
||||
where C: Combine<'tcx> {
|
||||
if a_args.len() == b_args.len() {
|
||||
a_args.iter().zip(b_args.iter())
|
||||
.map(|(a, b)| combiner.args(*a, *b)).collect()
|
||||
|
|
@ -265,13 +265,7 @@ pub trait Combine<'tcx> : Sized {
|
|||
Err(ty::terr_projection_name_mismatched(
|
||||
expected_found(self, a.item_name, b.item_name)))
|
||||
} else {
|
||||
// Note that the trait refs for the projection must be
|
||||
// *equal*. This is because there is no inherent
|
||||
// relationship between `<T as Foo>::Bar` and `<U as
|
||||
// Foo>::Bar` that we can derive based on how `T` relates
|
||||
// to `U`. Issue #21726 contains further discussion and
|
||||
// in-depth examples.
|
||||
let trait_ref = try!(self.equate().trait_refs(&*a.trait_ref, &*b.trait_ref));
|
||||
let trait_ref = try!(self.trait_refs(&*a.trait_ref, &*b.trait_ref));
|
||||
Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name })
|
||||
}
|
||||
}
|
||||
|
|
@ -351,51 +345,51 @@ pub trait Combineable<'tcx> : Repr<'tcx> + TypeFoldable<'tcx> {
|
|||
impl<'tcx,T> Combineable<'tcx> for Rc<T>
|
||||
where T : Combineable<'tcx>
|
||||
{
|
||||
fn combine<C:Combine<'tcx>>(combiner: &C,
|
||||
a: &Rc<T>,
|
||||
b: &Rc<T>)
|
||||
-> cres<'tcx, Rc<T>>
|
||||
{
|
||||
fn combine<C>(combiner: &C,
|
||||
a: &Rc<T>,
|
||||
b: &Rc<T>)
|
||||
-> cres<'tcx, Rc<T>>
|
||||
where C: Combine<'tcx> {
|
||||
Ok(Rc::new(try!(Combineable::combine(combiner, &**a, &**b))))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> {
|
||||
fn combine<C:Combine<'tcx>>(combiner: &C,
|
||||
a: &ty::TraitRef<'tcx>,
|
||||
b: &ty::TraitRef<'tcx>)
|
||||
-> cres<'tcx, ty::TraitRef<'tcx>>
|
||||
{
|
||||
fn combine<C>(combiner: &C,
|
||||
a: &ty::TraitRef<'tcx>,
|
||||
b: &ty::TraitRef<'tcx>)
|
||||
-> cres<'tcx, ty::TraitRef<'tcx>>
|
||||
where C: Combine<'tcx> {
|
||||
combiner.trait_refs(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Combineable<'tcx> for Ty<'tcx> {
|
||||
fn combine<C:Combine<'tcx>>(combiner: &C,
|
||||
a: &Ty<'tcx>,
|
||||
b: &Ty<'tcx>)
|
||||
-> cres<'tcx, Ty<'tcx>>
|
||||
{
|
||||
fn combine<C>(combiner: &C,
|
||||
a: &Ty<'tcx>,
|
||||
b: &Ty<'tcx>)
|
||||
-> cres<'tcx, Ty<'tcx>>
|
||||
where C: Combine<'tcx> {
|
||||
combiner.tys(*a, *b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Combineable<'tcx> for ty::ProjectionPredicate<'tcx> {
|
||||
fn combine<C:Combine<'tcx>>(combiner: &C,
|
||||
a: &ty::ProjectionPredicate<'tcx>,
|
||||
b: &ty::ProjectionPredicate<'tcx>)
|
||||
-> cres<'tcx, ty::ProjectionPredicate<'tcx>>
|
||||
{
|
||||
fn combine<C>(combiner: &C,
|
||||
a: &ty::ProjectionPredicate<'tcx>,
|
||||
b: &ty::ProjectionPredicate<'tcx>)
|
||||
-> cres<'tcx, ty::ProjectionPredicate<'tcx>>
|
||||
where C: Combine<'tcx> {
|
||||
combiner.projection_predicates(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Combineable<'tcx> for ty::FnSig<'tcx> {
|
||||
fn combine<C:Combine<'tcx>>(combiner: &C,
|
||||
a: &ty::FnSig<'tcx>,
|
||||
b: &ty::FnSig<'tcx>)
|
||||
-> cres<'tcx, ty::FnSig<'tcx>>
|
||||
{
|
||||
fn combine<C>(combiner: &C,
|
||||
a: &ty::FnSig<'tcx>,
|
||||
b: &ty::FnSig<'tcx>)
|
||||
-> cres<'tcx, ty::FnSig<'tcx>>
|
||||
where C: Combine<'tcx> {
|
||||
combiner.fn_sigs(a, b)
|
||||
}
|
||||
}
|
||||
|
|
@ -407,8 +401,11 @@ pub struct CombineFields<'a, 'tcx: 'a> {
|
|||
pub trace: TypeTrace<'tcx>,
|
||||
}
|
||||
|
||||
pub fn expected_found<'tcx, C: Combine<'tcx>, T>(
|
||||
this: &C, a: T, b: T) -> ty::expected_found<T> {
|
||||
pub fn expected_found<'tcx, C, T>(this: &C,
|
||||
a: T,
|
||||
b: T)
|
||||
-> ty::expected_found<T>
|
||||
where C: Combine<'tcx> {
|
||||
if this.a_is_expected() {
|
||||
ty::expected_found {expected: a, found: b}
|
||||
} else {
|
||||
|
|
@ -416,29 +413,26 @@ pub fn expected_found<'tcx, C: Combine<'tcx>, T>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>)
|
||||
-> cres<'tcx, Ty<'tcx>>
|
||||
{
|
||||
pub fn super_tys<'tcx, C>(this: &C,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>)
|
||||
-> cres<'tcx, Ty<'tcx>>
|
||||
where C: Combine<'tcx> {
|
||||
let tcx = this.infcx().tcx;
|
||||
let a_sty = &a.sty;
|
||||
let b_sty = &b.sty;
|
||||
debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
|
||||
return match (a_sty, b_sty) {
|
||||
// The "subtype" ought to be handling cases involving var:
|
||||
(&ty::ty_infer(TyVar(_)), _) |
|
||||
(_, &ty::ty_infer(TyVar(_))) => {
|
||||
tcx.sess.bug(
|
||||
&format!("{}: bot and var types should have been handled ({},{})",
|
||||
this.tag(),
|
||||
a.repr(this.infcx().tcx),
|
||||
b.repr(this.infcx().tcx)));
|
||||
}
|
||||
// The "subtype" ought to be handling cases involving var:
|
||||
(&ty::ty_infer(TyVar(_)), _)
|
||||
| (_, &ty::ty_infer(TyVar(_))) =>
|
||||
tcx.sess.bug(
|
||||
&format!("{}: bot and var types should have been handled ({},{})",
|
||||
this.tag(),
|
||||
a.repr(this.infcx().tcx),
|
||||
b.repr(this.infcx().tcx))),
|
||||
|
||||
(&ty::ty_err, _) | (_, &ty::ty_err) => {
|
||||
Ok(tcx.types.err)
|
||||
}
|
||||
(&ty::ty_err, _) | (_, &ty::ty_err) => Ok(tcx.types.err),
|
||||
|
||||
// Relate integral variables to other types
|
||||
(&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => {
|
||||
|
|
@ -475,68 +469,62 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
|
|||
unify_float_variable(this, !this.a_is_expected(), v_id, v)
|
||||
}
|
||||
|
||||
(&ty::ty_char, _) |
|
||||
(&ty::ty_bool, _) |
|
||||
(&ty::ty_int(_), _) |
|
||||
(&ty::ty_uint(_), _) |
|
||||
(&ty::ty_float(_), _) => {
|
||||
if a == b {
|
||||
Ok(a)
|
||||
} else {
|
||||
Err(ty::terr_sorts(expected_found(this, a, b)))
|
||||
(&ty::ty_char, _)
|
||||
| (&ty::ty_bool, _)
|
||||
| (&ty::ty_int(_), _)
|
||||
| (&ty::ty_uint(_), _)
|
||||
| (&ty::ty_float(_), _) => {
|
||||
if a == b {
|
||||
Ok(a)
|
||||
} else {
|
||||
Err(ty::terr_sorts(expected_found(this, a, b)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(&ty::ty_param(ref a_p), &ty::ty_param(ref b_p)) if
|
||||
a_p.idx == b_p.idx && a_p.space == b_p.space => {
|
||||
Ok(a)
|
||||
}
|
||||
(&ty::ty_param(ref a_p), &ty::ty_param(ref b_p)) if
|
||||
a_p.idx == b_p.idx && a_p.space == b_p.space => Ok(a),
|
||||
|
||||
(&ty::ty_enum(a_id, a_substs),
|
||||
&ty::ty_enum(b_id, b_substs))
|
||||
if a_id == b_id => {
|
||||
let substs = try!(this.substs(a_id,
|
||||
a_substs,
|
||||
b_substs));
|
||||
Ok(ty::mk_enum(tcx, a_id, tcx.mk_substs(substs)))
|
||||
}
|
||||
(&ty::ty_enum(a_id, a_substs), &ty::ty_enum(b_id, b_substs))
|
||||
if a_id == b_id => {
|
||||
let substs = try!(this.substs(a_id, a_substs, b_substs));
|
||||
Ok(ty::mk_enum(tcx, a_id, tcx.mk_substs(substs)))
|
||||
}
|
||||
|
||||
(&ty::ty_trait(ref a_),
|
||||
&ty::ty_trait(ref b_)) => {
|
||||
debug!("Trying to match traits {:?} and {:?}", a, b);
|
||||
let principal = try!(this.binders(&a_.principal, &b_.principal));
|
||||
let bounds = try!(this.existential_bounds(&a_.bounds, &b_.bounds));
|
||||
Ok(ty::mk_trait(tcx, principal, bounds))
|
||||
}
|
||||
(&ty::ty_trait(ref a_), &ty::ty_trait(ref b_)) => {
|
||||
debug!("Trying to match traits {:?} and {:?}", a, b);
|
||||
let principal = try!(this.binders(&a_.principal, &b_.principal));
|
||||
let bounds = try!(this.existential_bounds(&a_.bounds, &b_.bounds));
|
||||
Ok(ty::mk_trait(tcx, principal, bounds))
|
||||
}
|
||||
|
||||
(&ty::ty_struct(a_id, a_substs), &ty::ty_struct(b_id, b_substs))
|
||||
if a_id == b_id => {
|
||||
(&ty::ty_struct(a_id, a_substs), &ty::ty_struct(b_id, b_substs))
|
||||
if a_id == b_id => {
|
||||
let substs = try!(this.substs(a_id, a_substs, b_substs));
|
||||
Ok(ty::mk_struct(tcx, a_id, tcx.mk_substs(substs)))
|
||||
}
|
||||
}
|
||||
|
||||
(&ty::ty_closure(a_id, a_region, a_substs),
|
||||
&ty::ty_closure(b_id, b_region, b_substs))
|
||||
if a_id == b_id => {
|
||||
// All ty_closure types with the same id represent
|
||||
// the (anonymous) type of the same closure expression. So
|
||||
// all of their regions should be equated.
|
||||
let region = try!(this.equate().regions(*a_region, *b_region));
|
||||
let substs = try!(this.substs_variances(None, a_substs, b_substs));
|
||||
Ok(ty::mk_closure(tcx, a_id, tcx.mk_region(region), tcx.mk_substs(substs)))
|
||||
}
|
||||
(&ty::ty_closure(a_id, a_region, a_substs),
|
||||
&ty::ty_closure(b_id, b_region, b_substs))
|
||||
if a_id == b_id => {
|
||||
// All ty_closure types with the same id represent
|
||||
// the (anonymous) type of the same closure expression. So
|
||||
// all of their regions should be equated.
|
||||
let region = try!(this.equate().regions(*a_region, *b_region));
|
||||
let substs = try!(this.substs_variances(None, a_substs, b_substs));
|
||||
Ok(ty::mk_closure(tcx, a_id, tcx.mk_region(region), tcx.mk_substs(substs)))
|
||||
}
|
||||
|
||||
(&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
|
||||
let typ = try!(this.tys(a_inner, b_inner));
|
||||
Ok(ty::mk_uniq(tcx, typ))
|
||||
}
|
||||
(&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
|
||||
let typ = try!(this.tys(a_inner, b_inner));
|
||||
Ok(ty::mk_uniq(tcx, typ))
|
||||
}
|
||||
|
||||
(&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
|
||||
let mt = try!(this.mts(a_mt, b_mt));
|
||||
Ok(ty::mk_ptr(tcx, mt))
|
||||
}
|
||||
(&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
|
||||
let mt = try!(this.mts(a_mt, b_mt));
|
||||
Ok(ty::mk_ptr(tcx, mt))
|
||||
}
|
||||
|
||||
(&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
|
||||
(&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
|
||||
let r = try!(this.regions_with_variance(ty::Contravariant, *a_r, *b_r));
|
||||
|
||||
// FIXME(14985) If we have mutable references to trait objects, we
|
||||
|
|
@ -551,45 +539,43 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
|
|||
_ => try!(this.mts(a_mt, b_mt))
|
||||
};
|
||||
Ok(ty::mk_rptr(tcx, tcx.mk_region(r), mt))
|
||||
}
|
||||
}
|
||||
|
||||
(&ty::ty_vec(a_t, Some(sz_a)), &ty::ty_vec(b_t, Some(sz_b))) => {
|
||||
this.tys(a_t, b_t).and_then(|t| {
|
||||
if sz_a == sz_b {
|
||||
Ok(ty::mk_vec(tcx, t, Some(sz_a)))
|
||||
} else {
|
||||
Err(ty::terr_fixed_array_size(expected_found(this, sz_a, sz_b)))
|
||||
}
|
||||
})
|
||||
}
|
||||
(&ty::ty_vec(a_t, Some(sz_a)), &ty::ty_vec(b_t, Some(sz_b))) => {
|
||||
this.tys(a_t, b_t).and_then(|t| {
|
||||
if sz_a == sz_b {
|
||||
Ok(ty::mk_vec(tcx, t, Some(sz_a)))
|
||||
} else {
|
||||
Err(ty::terr_fixed_array_size(expected_found(this, sz_a, sz_b)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
(&ty::ty_vec(a_t, sz_a), &ty::ty_vec(b_t, sz_b)) => {
|
||||
this.tys(a_t, b_t).and_then(|t| {
|
||||
if sz_a == sz_b {
|
||||
Ok(ty::mk_vec(tcx, t, sz_a))
|
||||
(&ty::ty_vec(a_t, sz_a), &ty::ty_vec(b_t, sz_b)) => {
|
||||
this.tys(a_t, b_t).and_then(|t| {
|
||||
if sz_a == sz_b {
|
||||
Ok(ty::mk_vec(tcx, t, sz_a))
|
||||
} else {
|
||||
Err(ty::terr_sorts(expected_found(this, a, b)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
(&ty::ty_str, &ty::ty_str) => Ok(ty::mk_str(tcx)),
|
||||
|
||||
(&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) => {
|
||||
if as_.len() == bs.len() {
|
||||
as_.iter().zip(bs.iter())
|
||||
.map(|(a, b)| this.tys(*a, *b))
|
||||
.collect::<Result<_, _>>()
|
||||
.map(|ts| ty::mk_tup(tcx, ts))
|
||||
} else if as_.len() != 0 && bs.len() != 0 {
|
||||
Err(ty::terr_tuple_size(
|
||||
expected_found(this, as_.len(), bs.len())))
|
||||
} else {
|
||||
Err(ty::terr_sorts(expected_found(this, a, b)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
(&ty::ty_str, &ty::ty_str) => {
|
||||
Ok(ty::mk_str(tcx))
|
||||
}
|
||||
|
||||
(&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) => {
|
||||
if as_.len() == bs.len() {
|
||||
as_.iter().zip(bs.iter())
|
||||
.map(|(a, b)| this.tys(*a, *b))
|
||||
.collect::<Result<_, _>>()
|
||||
.map(|ts| ty::mk_tup(tcx, ts))
|
||||
} else if as_.len() != 0 && bs.len() != 0 {
|
||||
Err(ty::terr_tuple_size(
|
||||
expected_found(this, as_.len(), bs.len())))
|
||||
} else {
|
||||
Err(ty::terr_sorts(expected_found(this, a, b)))
|
||||
}
|
||||
}
|
||||
|
||||
(&ty::ty_bare_fn(a_opt_def_id, a_fty), &ty::ty_bare_fn(b_opt_def_id, b_fty))
|
||||
if a_opt_def_id == b_opt_def_id =>
|
||||
|
|
@ -598,33 +584,33 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
|
|||
Ok(ty::mk_bare_fn(tcx, a_opt_def_id, tcx.mk_bare_fn(fty)))
|
||||
}
|
||||
|
||||
(&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
|
||||
let projection_ty = try!(this.projection_tys(a_data, b_data));
|
||||
Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
|
||||
}
|
||||
(&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
|
||||
let projection_ty = try!(this.projection_tys(a_data, b_data));
|
||||
Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
|
||||
}
|
||||
|
||||
_ => Err(ty::terr_sorts(expected_found(this, a, b)))
|
||||
_ => Err(ty::terr_sorts(expected_found(this, a, b))),
|
||||
};
|
||||
|
||||
fn unify_integral_variable<'tcx, C: Combine<'tcx>>(
|
||||
this: &C,
|
||||
vid_is_expected: bool,
|
||||
vid: ty::IntVid,
|
||||
val: ty::IntVarValue) -> cres<'tcx, Ty<'tcx>>
|
||||
{
|
||||
fn unify_integral_variable<'tcx, C>(this: &C,
|
||||
vid_is_expected: bool,
|
||||
vid: ty::IntVid,
|
||||
val: ty::IntVarValue)
|
||||
-> cres<'tcx, Ty<'tcx>>
|
||||
where C: Combine<'tcx> {
|
||||
try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
|
||||
match val {
|
||||
IntType(v) => Ok(ty::mk_mach_int(this.tcx(), v)),
|
||||
UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v))
|
||||
UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v)),
|
||||
}
|
||||
}
|
||||
|
||||
fn unify_float_variable<'tcx, C: Combine<'tcx>>(
|
||||
this: &C,
|
||||
vid_is_expected: bool,
|
||||
vid: ty::FloatVid,
|
||||
val: ast::FloatTy) -> cres<'tcx, Ty<'tcx>>
|
||||
{
|
||||
fn unify_float_variable<'tcx, C>(this: &C,
|
||||
vid_is_expected: bool,
|
||||
vid: ty::FloatVid,
|
||||
val: ast::FloatTy)
|
||||
-> cres<'tcx, Ty<'tcx>>
|
||||
where C: Combine<'tcx> {
|
||||
try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
|
||||
Ok(ty::mk_mach_float(this.tcx(), val))
|
||||
}
|
||||
|
|
@ -696,12 +682,8 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> {
|
|||
None => { // ...not yet instantiated:
|
||||
// Generalize type if necessary.
|
||||
let generalized_ty = try!(match dir {
|
||||
EqTo => {
|
||||
self.generalize(a_ty, b_vid, false)
|
||||
}
|
||||
BiTo | SupertypeOf | SubtypeOf => {
|
||||
self.generalize(a_ty, b_vid, true)
|
||||
}
|
||||
EqTo => self.generalize(a_ty, b_vid, false),
|
||||
BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true),
|
||||
});
|
||||
debug!("instantiate(a_ty={}, dir={:?}, \
|
||||
b_vid={}, generalized_ty={})",
|
||||
|
|
@ -723,22 +705,14 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> {
|
|||
// to associate causes/spans with each of the relations in
|
||||
// the stack to get this right.
|
||||
match dir {
|
||||
BiTo => {
|
||||
try!(self.bivariate().tys(a_ty, b_ty));
|
||||
}
|
||||
BiTo => try!(self.bivariate().tys(a_ty, b_ty)),
|
||||
|
||||
EqTo => {
|
||||
try!(self.equate().tys(a_ty, b_ty));
|
||||
}
|
||||
EqTo => try!(self.equate().tys(a_ty, b_ty)),
|
||||
|
||||
SubtypeOf => {
|
||||
try!(self.sub().tys(a_ty, b_ty));
|
||||
}
|
||||
SubtypeOf => try!(self.sub().tys(a_ty, b_ty)),
|
||||
|
||||
SupertypeOf => {
|
||||
try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty));
|
||||
}
|
||||
}
|
||||
SupertypeOf => try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty)),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -754,11 +728,13 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> {
|
|||
make_region_vars: bool)
|
||||
-> cres<'tcx, Ty<'tcx>>
|
||||
{
|
||||
let mut generalize = Generalizer { infcx: self.infcx,
|
||||
span: self.trace.origin.span(),
|
||||
for_vid: for_vid,
|
||||
make_region_vars: make_region_vars,
|
||||
cycle_detected: false };
|
||||
let mut generalize = Generalizer {
|
||||
infcx: self.infcx,
|
||||
span: self.trace.origin.span(),
|
||||
for_vid: for_vid,
|
||||
make_region_vars: make_region_vars,
|
||||
cycle_detected: false
|
||||
};
|
||||
let u = ty.fold_with(&mut generalize);
|
||||
if generalize.cycle_detected {
|
||||
Err(ty::terr_cyclic_ty)
|
||||
|
|
|
|||
|
|
@ -1133,18 +1133,12 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
|
|||
true // changed
|
||||
}
|
||||
|
||||
ErrorValue => {
|
||||
false // no change
|
||||
}
|
||||
ErrorValue => false, // no change
|
||||
|
||||
Value(a_region) => {
|
||||
match a_data.classification {
|
||||
Expanding => {
|
||||
check_node(self, a_vid, a_data, a_region, b_region)
|
||||
}
|
||||
Contracting => {
|
||||
adjust_node(self, a_vid, a_data, a_region, b_region)
|
||||
}
|
||||
Expanding => check_node(self, a_vid, a_data, a_region, b_region),
|
||||
Contracting => adjust_node(self, a_vid, a_data, a_region, b_region),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -1154,7 +1148,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
|
|||
a_data: &mut VarData,
|
||||
a_region: Region,
|
||||
b_region: Region)
|
||||
-> bool {
|
||||
-> bool {
|
||||
if !this.is_subregion_of(a_region, b_region) {
|
||||
debug!("Setting {:?} to ErrorValue: {} not subregion of {}",
|
||||
a_vid,
|
||||
|
|
@ -1170,7 +1164,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
|
|||
a_data: &mut VarData,
|
||||
a_region: Region,
|
||||
b_region: Region)
|
||||
-> bool {
|
||||
-> bool {
|
||||
match this.glb_concrete_regions(a_region, b_region) {
|
||||
Ok(glb) => {
|
||||
if glb == a_region {
|
||||
|
|
|
|||
|
|
@ -52,9 +52,16 @@ fn overlap(selcx: &mut SelectionContext,
|
|||
b_def_id: ast::DefId)
|
||||
-> bool
|
||||
{
|
||||
debug!("overlap(a_def_id={}, b_def_id={})",
|
||||
a_def_id.repr(selcx.tcx()),
|
||||
b_def_id.repr(selcx.tcx()));
|
||||
|
||||
let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx, a_def_id);
|
||||
let (b_trait_ref, b_obligations) = impl_trait_ref_and_oblig(selcx, b_def_id);
|
||||
|
||||
debug!("overlap: a_trait_ref={}", a_trait_ref.repr(selcx.tcx()));
|
||||
debug!("overlap: b_trait_ref={}", b_trait_ref.repr(selcx.tcx()));
|
||||
|
||||
// Does `a <: b` hold? If not, no overlap.
|
||||
if let Err(_) = infer::mk_sub_poly_trait_refs(selcx.infcx(),
|
||||
true,
|
||||
|
|
@ -64,10 +71,20 @@ fn overlap(selcx: &mut SelectionContext,
|
|||
return false;
|
||||
}
|
||||
|
||||
debug!("overlap: subtraitref check succeeded");
|
||||
|
||||
// Are any of the obligations unsatisfiable? If so, no overlap.
|
||||
a_obligations.iter()
|
||||
.chain(b_obligations.iter())
|
||||
.all(|o| selcx.evaluate_obligation(o))
|
||||
let opt_failing_obligation =
|
||||
a_obligations.iter()
|
||||
.chain(b_obligations.iter())
|
||||
.find(|o| !selcx.evaluate_obligation(o));
|
||||
|
||||
if let Some(failing_obligation) = opt_failing_obligation {
|
||||
debug!("overlap: obligation unsatisfiable {}", failing_obligation.repr(selcx.tcx()));
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// Instantiate fresh variables for all bound parameters of the impl
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub use self::ObligationCauseCode::*;
|
|||
use middle::subst;
|
||||
use middle::ty::{self, HasProjectionTypes, Ty};
|
||||
use middle::ty_fold::TypeFoldable;
|
||||
use middle::infer::{self, InferCtxt};
|
||||
use middle::infer::{self, fixup_err_to_string, InferCtxt};
|
||||
use std::slice::Iter;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
|
|
@ -395,53 +395,64 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
/// Normalizes the parameter environment, reporting errors if they occur.
|
||||
pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>,
|
||||
cause: ObligationCause<'tcx>)
|
||||
-> ty::ParameterEnvironment<'a,'tcx>
|
||||
{
|
||||
match normalize_param_env(&unnormalized_env, cause) {
|
||||
Ok(p) => p,
|
||||
Err(errors) => {
|
||||
// I'm not wild about reporting errors here; I'd prefer to
|
||||
// have the errors get reported at a defined place (e.g.,
|
||||
// during typeck). Instead I have all parameter
|
||||
// environments, in effect, going through this function
|
||||
// and hence potentially reporting errors. This ensurse of
|
||||
// course that we never forget to normalize (the
|
||||
// alternative seemed like it would involve a lot of
|
||||
// manual invocations of this fn -- and then we'd have to
|
||||
// deal with the errors at each of those sites).
|
||||
//
|
||||
// In any case, in practice, typeck constructs all the
|
||||
// parameter environments once for every fn as it goes,
|
||||
// and errors will get reported then; so after typeck we
|
||||
// can be sure that no errors should occur.
|
||||
let infcx = infer::new_infer_ctxt(unnormalized_env.tcx);
|
||||
report_fulfillment_errors(&infcx, &errors);
|
||||
// I'm not wild about reporting errors here; I'd prefer to
|
||||
// have the errors get reported at a defined place (e.g.,
|
||||
// during typeck). Instead I have all parameter
|
||||
// environments, in effect, going through this function
|
||||
// and hence potentially reporting errors. This ensurse of
|
||||
// course that we never forget to normalize (the
|
||||
// alternative seemed like it would involve a lot of
|
||||
// manual invocations of this fn -- and then we'd have to
|
||||
// deal with the errors at each of those sites).
|
||||
//
|
||||
// In any case, in practice, typeck constructs all the
|
||||
// parameter environments once for every fn as it goes,
|
||||
// and errors will get reported then; so after typeck we
|
||||
// can be sure that no errors should occur.
|
||||
|
||||
// Normalized failed? use what they gave us, it's better than nothing.
|
||||
unnormalized_env
|
||||
}
|
||||
}
|
||||
}
|
||||
let tcx = unnormalized_env.tcx;
|
||||
let span = cause.span;
|
||||
let body_id = cause.body_id;
|
||||
|
||||
pub fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>,
|
||||
cause: ObligationCause<'tcx>)
|
||||
-> Result<ty::ParameterEnvironment<'a,'tcx>,
|
||||
Vec<FulfillmentError<'tcx>>>
|
||||
{
|
||||
let tcx = param_env.tcx;
|
||||
|
||||
debug!("normalize_param_env(param_env={})",
|
||||
param_env.repr(tcx));
|
||||
debug!("normalize_param_env_or_error(unnormalized_env={})",
|
||||
unnormalized_env.repr(tcx));
|
||||
|
||||
let infcx = infer::new_infer_ctxt(tcx);
|
||||
let predicates = try!(fully_normalize(&infcx, param_env, cause, ¶m_env.caller_bounds));
|
||||
let predicates = match fully_normalize(&infcx, &unnormalized_env, cause,
|
||||
&unnormalized_env.caller_bounds) {
|
||||
Ok(predicates) => predicates,
|
||||
Err(errors) => {
|
||||
report_fulfillment_errors(&infcx, &errors);
|
||||
return unnormalized_env; // an unnormalized env is better than nothing
|
||||
}
|
||||
};
|
||||
|
||||
debug!("normalize_param_env: predicates={}",
|
||||
infcx.resolve_regions_and_report_errors(body_id);
|
||||
let predicates = match infcx.fully_resolve(&predicates) {
|
||||
Ok(predicates) => predicates,
|
||||
Err(fixup_err) => {
|
||||
// If we encounter a fixup error, it means that some type
|
||||
// variable wound up unconstrained. I actually don't know
|
||||
// if this can happen, and I certainly don't expect it to
|
||||
// happen often, but if it did happen it probably
|
||||
// represents a legitimate failure due to some kind of
|
||||
// unconstrained variable, and it seems better not to ICE,
|
||||
// all things considered.
|
||||
let err_msg = fixup_err_to_string(fixup_err);
|
||||
tcx.sess.span_err(span, &err_msg);
|
||||
return unnormalized_env; // an unnormalized env is better than nothing
|
||||
}
|
||||
};
|
||||
|
||||
debug!("normalize_param_env_or_error: predicates={}",
|
||||
predicates.repr(tcx));
|
||||
|
||||
Ok(param_env.with_caller_bounds(predicates))
|
||||
unnormalized_env.with_caller_bounds(predicates)
|
||||
}
|
||||
|
||||
pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
|
||||
|
|
@ -453,8 +464,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
|
|||
{
|
||||
let tcx = closure_typer.tcx();
|
||||
|
||||
debug!("normalize_param_env(value={})",
|
||||
value.repr(tcx));
|
||||
debug!("normalize_param_env(value={})", value.repr(tcx));
|
||||
|
||||
let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
|
||||
let mut fulfill_cx = FulfillmentContext::new();
|
||||
|
|
@ -468,8 +478,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
|
|||
}
|
||||
try!(fulfill_cx.select_all_or_error(infcx, closure_typer));
|
||||
let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
|
||||
debug!("normalize_param_env: resolved_value={}",
|
||||
resolved_value.repr(tcx));
|
||||
debug!("normalize_param_env: resolved_value={}", resolved_value.repr(tcx));
|
||||
Ok(resolved_value)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1409,27 +1409,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty());
|
||||
return match self_ty.sty {
|
||||
ty::ty_infer(ty::IntVar(_)) |
|
||||
ty::ty_infer(ty::FloatVar(_)) |
|
||||
ty::ty_uint(_) |
|
||||
ty::ty_int(_) |
|
||||
ty::ty_bool |
|
||||
ty::ty_float(_) |
|
||||
ty::ty_bare_fn(..) |
|
||||
ty::ty_char => {
|
||||
ty::ty_infer(ty::IntVar(_))
|
||||
| ty::ty_infer(ty::FloatVar(_))
|
||||
| ty::ty_uint(_)
|
||||
| ty::ty_int(_)
|
||||
| ty::ty_bool
|
||||
| ty::ty_float(_)
|
||||
| ty::ty_bare_fn(..)
|
||||
| ty::ty_char => {
|
||||
// safe for everything
|
||||
Ok(If(Vec::new()))
|
||||
}
|
||||
|
||||
ty::ty_uniq(_) => { // Box<T>
|
||||
match bound {
|
||||
ty::BoundCopy => {
|
||||
Err(Unimplemented)
|
||||
}
|
||||
ty::BoundCopy => Err(Unimplemented),
|
||||
|
||||
ty::BoundSized => {
|
||||
Ok(If(Vec::new()))
|
||||
}
|
||||
ty::BoundSized => Ok(If(Vec::new())),
|
||||
|
||||
ty::BoundSync | ty::BoundSend => {
|
||||
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
|
||||
|
|
@ -1439,9 +1435,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
ty::ty_ptr(..) => { // *const T, *mut T
|
||||
match bound {
|
||||
ty::BoundCopy | ty::BoundSized => {
|
||||
Ok(If(Vec::new()))
|
||||
}
|
||||
ty::BoundCopy | ty::BoundSized => Ok(If(Vec::new())),
|
||||
|
||||
ty::BoundSync | ty::BoundSend => {
|
||||
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
|
||||
|
|
@ -1451,9 +1445,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
ty::ty_trait(ref data) => {
|
||||
match bound {
|
||||
ty::BoundSized => {
|
||||
Err(Unimplemented)
|
||||
}
|
||||
ty::BoundSized => Err(Unimplemented),
|
||||
ty::BoundCopy => {
|
||||
if data.bounds.builtin_bounds.contains(&bound) {
|
||||
Ok(If(Vec::new()))
|
||||
|
|
@ -1485,20 +1477,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
ty::BoundCopy => {
|
||||
match mutbl {
|
||||
// &mut T is affine and hence never `Copy`
|
||||
ast::MutMutable => {
|
||||
Err(Unimplemented)
|
||||
}
|
||||
ast::MutMutable => Err(Unimplemented),
|
||||
|
||||
// &T is always copyable
|
||||
ast::MutImmutable => {
|
||||
Ok(If(Vec::new()))
|
||||
}
|
||||
ast::MutImmutable => Ok(If(Vec::new())),
|
||||
}
|
||||
}
|
||||
|
||||
ty::BoundSized => {
|
||||
Ok(If(Vec::new()))
|
||||
}
|
||||
ty::BoundSized => Ok(If(Vec::new())),
|
||||
|
||||
ty::BoundSync | ty::BoundSend => {
|
||||
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
|
||||
|
|
@ -1511,14 +1497,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
match bound {
|
||||
ty::BoundCopy => {
|
||||
match *len {
|
||||
Some(_) => {
|
||||
// [T, ..n] is copy iff T is copy
|
||||
Ok(If(vec![element_ty]))
|
||||
}
|
||||
None => {
|
||||
// [T] is unsized and hence affine
|
||||
Err(Unimplemented)
|
||||
}
|
||||
// [T, ..n] is copy iff T is copy
|
||||
Some(_) => Ok(If(vec![element_ty])),
|
||||
|
||||
// [T] is unsized and hence affine
|
||||
None => Err(Unimplemented),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1543,16 +1526,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
|
||||
}
|
||||
|
||||
ty::BoundCopy | ty::BoundSized => {
|
||||
Err(Unimplemented)
|
||||
}
|
||||
ty::BoundCopy | ty::BoundSized => Err(Unimplemented),
|
||||
}
|
||||
}
|
||||
|
||||
ty::ty_tup(ref tys) => {
|
||||
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
||||
Ok(If(tys.clone()))
|
||||
}
|
||||
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
||||
ty::ty_tup(ref tys) => Ok(If(tys.clone())),
|
||||
|
||||
ty::ty_closure(def_id, _, substs) => {
|
||||
// FIXME -- This case is tricky. In the case of by-ref
|
||||
|
|
@ -1581,9 +1560,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}
|
||||
|
||||
match self.closure_typer.closure_upvars(def_id, substs) {
|
||||
Some(upvars) => {
|
||||
Ok(If(upvars.iter().map(|c| c.ty).collect()))
|
||||
}
|
||||
Some(upvars) => Ok(If(upvars.iter().map(|c| c.ty).collect())),
|
||||
None => {
|
||||
debug!("assemble_builtin_bound_candidates: no upvar types available yet");
|
||||
Ok(AmbiguousBuiltin)
|
||||
|
|
@ -1609,8 +1586,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
nominal(bound, types)
|
||||
}
|
||||
|
||||
ty::ty_projection(_) |
|
||||
ty::ty_param(_) => {
|
||||
ty::ty_projection(_) | ty::ty_param(_) => {
|
||||
// Note: A type parameter is only considered to meet a
|
||||
// particular bound if there is a where clause telling
|
||||
// us that it does, and that case is handled by
|
||||
|
|
@ -1626,12 +1602,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
Ok(AmbiguousBuiltin)
|
||||
}
|
||||
|
||||
ty::ty_err => {
|
||||
Ok(If(Vec::new()))
|
||||
}
|
||||
ty::ty_err => Ok(If(Vec::new())),
|
||||
|
||||
ty::ty_infer(ty::FreshTy(_)) |
|
||||
ty::ty_infer(ty::FreshIntTy(_)) => {
|
||||
ty::ty_infer(ty::FreshTy(_))
|
||||
| ty::ty_infer(ty::FreshIntTy(_)) => {
|
||||
self.tcx().sess.bug(
|
||||
&format!(
|
||||
"asked to assemble builtin bounds of unexpected type: {}",
|
||||
|
|
@ -1641,7 +1615,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
fn nominal<'cx, 'tcx>(bound: ty::BuiltinBound,
|
||||
types: Vec<Ty<'tcx>>)
|
||||
-> Result<BuiltinBoundConditions<'tcx>,SelectionError<'tcx>>
|
||||
-> Result<BuiltinBoundConditions<'tcx>, SelectionError<'tcx>>
|
||||
{
|
||||
// First check for markers and other nonsense.
|
||||
match bound {
|
||||
|
|
@ -1692,7 +1666,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
self.tcx().sess.bug(
|
||||
&format!(
|
||||
"asked to assemble constituent types of unexpected type: {}",
|
||||
t.repr(self.tcx()))[]);
|
||||
t.repr(self.tcx())));
|
||||
}
|
||||
|
||||
ty::ty_uniq(referent_ty) => { // Box<T>
|
||||
|
|
@ -1909,7 +1883,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
}).collect::<Result<_, _>>();
|
||||
let obligations = match obligations {
|
||||
Ok(o) => o,
|
||||
Err(ErrorReported) => Vec::new()
|
||||
Err(ErrorReported) => Vec::new(),
|
||||
};
|
||||
|
||||
let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
|
||||
|
|
@ -1937,14 +1911,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty());
|
||||
match self.constituent_types_for_ty(self_ty) {
|
||||
Some(types) => {
|
||||
Ok(self.vtable_default_impl(obligation, impl_def_id, types))
|
||||
}
|
||||
Some(types) => Ok(self.vtable_default_impl(obligation, impl_def_id, types)),
|
||||
None => {
|
||||
self.tcx().sess.bug(
|
||||
&format!(
|
||||
"asked to confirm default implementation for ambiguous type: {}",
|
||||
self_ty.repr(self.tcx()))[]);
|
||||
self_ty.repr(self.tcx())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2223,9 +2195,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
{
|
||||
match self.match_impl(impl_def_id, obligation, snapshot,
|
||||
skol_map, skol_obligation_trait_ref) {
|
||||
Ok(substs) => {
|
||||
substs
|
||||
}
|
||||
Ok(substs) => substs,
|
||||
Err(()) => {
|
||||
self.tcx().sess.bug(
|
||||
&format!("Impl {} was matchable against {} but now is not",
|
||||
|
|
@ -2273,30 +2243,26 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
skol_obligation_trait_ref.repr(self.tcx()));
|
||||
|
||||
let origin = infer::RelateOutputImplTypes(obligation.cause.span);
|
||||
match self.infcx.sub_trait_refs(false,
|
||||
origin,
|
||||
impl_trait_ref.value.clone(),
|
||||
skol_obligation_trait_ref) {
|
||||
Ok(()) => { }
|
||||
Err(e) => {
|
||||
debug!("match_impl: failed sub_trait_refs due to `{}`",
|
||||
ty::type_err_to_str(self.tcx(), &e));
|
||||
return Err(());
|
||||
}
|
||||
if let Err(e) = self.infcx.sub_trait_refs(false,
|
||||
origin,
|
||||
impl_trait_ref.value.clone(),
|
||||
skol_obligation_trait_ref) {
|
||||
debug!("match_impl: failed sub_trait_refs due to `{}`",
|
||||
ty::type_err_to_str(self.tcx(), &e));
|
||||
return Err(());
|
||||
}
|
||||
|
||||
match self.infcx.leak_check(skol_map, snapshot) {
|
||||
Ok(()) => { }
|
||||
Err(e) => {
|
||||
debug!("match_impl: failed leak check due to `{}`",
|
||||
ty::type_err_to_str(self.tcx(), &e));
|
||||
return Err(());
|
||||
}
|
||||
if let Err(e) = self.infcx.leak_check(skol_map, snapshot) {
|
||||
debug!("match_impl: failed leak check due to `{}`",
|
||||
ty::type_err_to_str(self.tcx(), &e));
|
||||
return Err(());
|
||||
}
|
||||
|
||||
debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
|
||||
Ok(Normalized { value: impl_substs,
|
||||
obligations: impl_trait_ref.obligations })
|
||||
Ok(Normalized {
|
||||
value: impl_substs,
|
||||
obligations: impl_trait_ref.obligations
|
||||
})
|
||||
}
|
||||
|
||||
fn fast_reject_trait_refs(&mut self,
|
||||
|
|
@ -2332,9 +2298,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
|
||||
-> Result<Vec<PredicateObligation<'tcx>>,()>
|
||||
{
|
||||
let () =
|
||||
try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref));
|
||||
|
||||
try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref));
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
|
|
@ -2451,7 +2415,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
|
||||
match self.tcx().trait_impls.borrow().get(&trait_def_id) {
|
||||
None => Vec::new(),
|
||||
Some(impls) => impls.borrow().clone()
|
||||
Some(impls) => impls.borrow().clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2549,9 +2513,7 @@ impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
|
|||
DefaultImplCandidate(t) => format!("DefaultImplCandidate({:?})", t),
|
||||
ProjectionCandidate => format!("ProjectionCandidate"),
|
||||
FnPointerCandidate => format!("FnPointerCandidate"),
|
||||
ObjectCandidate => {
|
||||
format!("ObjectCandidate")
|
||||
}
|
||||
ObjectCandidate => format!("ObjectCandidate"),
|
||||
ClosureCandidate(c, ref s) => {
|
||||
format!("ClosureCandidate({:?},{})", c, s.repr(tcx))
|
||||
}
|
||||
|
|
@ -2582,9 +2544,7 @@ impl<'o, 'tcx> Iterator for Option<&'o TraitObligationStack<'o, 'tcx>> {
|
|||
*self = o.previous;
|
||||
Some(o)
|
||||
}
|
||||
None => {
|
||||
None
|
||||
}
|
||||
None => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2599,15 +2559,11 @@ impl<'o, 'tcx> Repr<'tcx> for TraitObligationStack<'o, 'tcx> {
|
|||
impl<'tcx> EvaluationResult<'tcx> {
|
||||
fn may_apply(&self) -> bool {
|
||||
match *self {
|
||||
EvaluatedToOk |
|
||||
EvaluatedToAmbig |
|
||||
EvaluatedToErr(Overflow) |
|
||||
EvaluatedToErr(OutputTypeParameterMismatch(..)) => {
|
||||
true
|
||||
}
|
||||
EvaluatedToErr(Unimplemented) => {
|
||||
false
|
||||
}
|
||||
EvaluatedToOk
|
||||
| EvaluatedToAmbig
|
||||
| EvaluatedToErr(Overflow)
|
||||
| EvaluatedToErr(OutputTypeParameterMismatch(..)) => true,
|
||||
EvaluatedToErr(Unimplemented) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ use metadata::creader::CrateReader;
|
|||
use plugin::registry::Registry;
|
||||
|
||||
use std::mem;
|
||||
use std::env;
|
||||
use std::os;
|
||||
use std::dynamic_lib::DynamicLibrary;
|
||||
use std::borrow::ToOwned;
|
||||
use syntax::ast;
|
||||
|
|
@ -103,7 +103,7 @@ impl<'a> PluginLoader<'a> {
|
|||
path: Path,
|
||||
symbol: String) -> PluginRegistrarFun {
|
||||
// Make sure the path contains a / or the linker will search for it.
|
||||
let path = env::current_dir().unwrap().join(&path);
|
||||
let path = os::getcwd().unwrap().join(&path);
|
||||
|
||||
let lib = match DynamicLibrary::open(Some(&path)) {
|
||||
Ok(lib) => lib,
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ use syntax::{ast, codemap};
|
|||
|
||||
use rustc_back::target::Target;
|
||||
|
||||
use std::env;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::os;
|
||||
|
||||
pub mod config;
|
||||
pub mod search_paths;
|
||||
|
|
@ -356,7 +356,7 @@ pub fn build_session_(sopts: config::Options,
|
|||
if path.is_absolute() {
|
||||
path.clone()
|
||||
} else {
|
||||
env::current_dir().unwrap().join(&path)
|
||||
os::getcwd().unwrap().join(&path)
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -379,7 +379,7 @@ pub fn build_session_(sopts: config::Options,
|
|||
plugin_registrar_fn: Cell::new(None),
|
||||
default_sysroot: default_sysroot,
|
||||
local_crate_source_file: local_crate_source_file,
|
||||
working_dir: env::current_dir().unwrap(),
|
||||
working_dir: os::getcwd().unwrap(),
|
||||
lint_store: RefCell::new(lint::LintStore::new()),
|
||||
lints: RefCell::new(NodeMap()),
|
||||
crate_types: RefCell::new(Vec::new()),
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use std::old_io::fs::PathExtensions;
|
|||
use std::old_io::process::{Command, ProcessOutput};
|
||||
use std::old_io::{fs, TempDir};
|
||||
use std::old_io;
|
||||
use std::env;
|
||||
use std::os;
|
||||
use std::str;
|
||||
use syntax::diagnostic::Handler as ErrorHandler;
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ impl<'a> ArchiveBuilder<'a> {
|
|||
pub fn build(self) -> Archive<'a> {
|
||||
// Get an absolute path to the destination, so `ar` will work even
|
||||
// though we run it from `self.work_dir`.
|
||||
let abs_dst = env::current_dir().unwrap().join(&self.archive.dst);
|
||||
let abs_dst = os::getcwd().unwrap().join(&self.archive.dst);
|
||||
assert!(!abs_dst.is_relative());
|
||||
let mut args = vec![&abs_dst];
|
||||
let mut total_len = abs_dst.as_vec().len();
|
||||
|
|
@ -283,7 +283,7 @@ impl<'a> ArchiveBuilder<'a> {
|
|||
// First, extract the contents of the archive to a temporary directory.
|
||||
// We don't unpack directly into `self.work_dir` due to the possibility
|
||||
// of filename collisions.
|
||||
let archive = env::current_dir().unwrap().join(archive);
|
||||
let archive = os::getcwd().unwrap().join(archive);
|
||||
run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
|
||||
"x", Some(loc.path()), &[&archive]);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@
|
|||
|
||||
use std::old_io;
|
||||
use std::old_io::fs;
|
||||
use std::env;
|
||||
use std::os;
|
||||
|
||||
/// Returns an absolute path in the filesystem that `path` points to. The
|
||||
/// returned path does not contain any symlinks in its hierarchy.
|
||||
pub fn realpath(original: &Path) -> old_io::IoResult<Path> {
|
||||
static MAX_LINKS_FOLLOWED: uint = 256;
|
||||
let original = try!(env::current_dir()).join(original);
|
||||
let original = try!(os::getcwd()).join(original);
|
||||
|
||||
// Right now lstat on windows doesn't work quite well
|
||||
if cfg!(windows) {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#![feature(rustc_private)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(env)]
|
||||
#![feature(path)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate serialize;
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::old_io::IoError;
|
||||
use std::os;
|
||||
use syntax::ast;
|
||||
|
||||
pub struct RPathConfig<F, G> where
|
||||
|
|
@ -109,7 +109,7 @@ fn get_rpath_relative_to_output<F, G>(config: &mut RPathConfig<F, G>, lib: &Path
|
|||
"$ORIGIN"
|
||||
};
|
||||
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let cwd = os::getcwd().unwrap();
|
||||
let mut lib = (config.realpath)(&cwd.join(lib)).unwrap();
|
||||
lib.pop();
|
||||
let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap();
|
||||
|
|
@ -129,7 +129,7 @@ fn get_install_prefix_rpath<F, G>(config: RPathConfig<F, G>) -> String where
|
|||
let path = (config.get_install_prefix_lib_path)();
|
||||
let path = env::current_dir().unwrap().join(&path);
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
path.as_str().expect("non-utf8 component in rpath").to_string()
|
||||
path.to_str().expect("non-utf8 component in rpath").to_string()
|
||||
}
|
||||
|
||||
fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ impl Target {
|
|||
/// JSON decoding.
|
||||
pub fn search(target: &str) -> Result<Target, String> {
|
||||
use std::env;
|
||||
use std::os;
|
||||
use std::ffi::OsString;
|
||||
use std::old_io::File;
|
||||
use std::old_path::Path;
|
||||
|
|
@ -396,7 +397,7 @@ impl Target {
|
|||
|
||||
// FIXME 16351: add a sane default search path?
|
||||
|
||||
for dir in env::split_paths(&target_path) {
|
||||
for dir in os::split_paths(target_path.to_str().unwrap()).iter() {
|
||||
let p = dir.join(path.clone());
|
||||
if p.is_file() {
|
||||
return load_file(&p);
|
||||
|
|
|
|||
|
|
@ -105,10 +105,10 @@ fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
|
|||
ast::ItemConst(_, ref ex) => {
|
||||
gather_loans::gather_loans_in_static_initializer(this, &**ex);
|
||||
}
|
||||
_ => {
|
||||
visit::walk_item(this, item);
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
|
||||
visit::walk_item(this, item);
|
||||
}
|
||||
|
||||
/// Collection of conclusions determined via borrow checker analyses.
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ use super::Compilation;
|
|||
use serialize::json;
|
||||
|
||||
use std::env;
|
||||
use std::os;
|
||||
use std::ffi::OsString;
|
||||
use std::old_io::fs;
|
||||
use std::old_io;
|
||||
|
|
@ -471,7 +472,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||
if cfg!(windows) {
|
||||
_old_path = env::var_os("PATH").unwrap_or(_old_path);
|
||||
let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths();
|
||||
new_path.extend(env::split_paths(&_old_path));
|
||||
new_path.extend(os::split_paths(_old_path.to_str().unwrap()).into_iter());
|
||||
env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
|
||||
}
|
||||
let features = sess.features.borrow();
|
||||
|
|
@ -736,7 +737,7 @@ pub fn phase_6_link_output(sess: &Session,
|
|||
outputs: &OutputFilenames) {
|
||||
let old_path = env::var_os("PATH").unwrap_or(OsString::from_str(""));
|
||||
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths();
|
||||
new_path.extend(env::split_paths(&old_path));
|
||||
new_path.extend(os::split_paths(old_path.to_str().unwrap()).into_iter());
|
||||
env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
|
||||
|
||||
time(sess.time_passes(), "linking", (), |_|
|
||||
|
|
|
|||
|
|
@ -806,11 +806,11 @@ fn walk_ty() {
|
|||
let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty));
|
||||
let uniq_ty = ty::mk_uniq(tcx, tup2_ty);
|
||||
let walked: Vec<_> = uniq_ty.walk().collect();
|
||||
assert_eq!(vec!(uniq_ty,
|
||||
tup2_ty,
|
||||
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
|
||||
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
|
||||
uint_ty),
|
||||
assert_eq!([uniq_ty,
|
||||
tup2_ty,
|
||||
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
|
||||
tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
|
||||
uint_ty],
|
||||
walked);
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
};
|
||||
unsafe {
|
||||
let _icx = push_ctxt("const_expr");
|
||||
return match e.node {
|
||||
match e.node {
|
||||
ast::ExprLit(ref lit) => {
|
||||
const_lit(cx, e, &**lit)
|
||||
}
|
||||
|
|
@ -379,7 +379,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
let (te2, _) = const_expr(cx, &**e2, param_substs);
|
||||
let te2 = base::cast_shift_const_rhs(b, te1, te2);
|
||||
|
||||
return match b.node {
|
||||
match b.node {
|
||||
ast::BiAdd => {
|
||||
if is_float { llvm::LLVMConstFAdd(te1, te2) }
|
||||
else { llvm::LLVMConstAdd(te1, te2) }
|
||||
|
|
@ -433,7 +433,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
ast::ExprUnary(u, ref e) => {
|
||||
let (te, ty) = const_expr(cx, &**e, param_substs);
|
||||
let is_float = ty::type_is_fp(ty);
|
||||
return match u {
|
||||
match u {
|
||||
ast::UnUniq | ast::UnDeref => {
|
||||
const_deref(cx, te, ty).0
|
||||
}
|
||||
|
|
@ -514,8 +514,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
if expr::cast_is_noop(basety, ety) {
|
||||
return v;
|
||||
}
|
||||
return match (expr::cast_type_kind(cx.tcx(), basety),
|
||||
expr::cast_type_kind(cx.tcx(), ety)) {
|
||||
match (expr::cast_type_kind(cx.tcx(), basety),
|
||||
expr::cast_type_kind(cx.tcx(), ety)) {
|
||||
|
||||
(expr::cast_integral, expr::cast_integral) => {
|
||||
let s = ty::type_is_signed(basety) as Bool;
|
||||
|
|
@ -584,13 +584,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
}
|
||||
let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def());
|
||||
if let Some(def::DefStatic(def_id, _)) = opt_def {
|
||||
return get_static_val(cx, def_id, ety);
|
||||
get_static_val(cx, def_id, ety)
|
||||
} else {
|
||||
// If this isn't the address of a static, then keep going through
|
||||
// normal constant evaluation.
|
||||
let (v, _) = const_expr(cx, &**sub, param_substs);
|
||||
addr_of(cx, v, "ref", e.id)
|
||||
}
|
||||
|
||||
// If this isn't the address of a static, then keep going through
|
||||
// normal constant evaluation.
|
||||
let (v, _) = const_expr(cx, &**sub, param_substs);
|
||||
addr_of(cx, v, "ref", e.id)
|
||||
}
|
||||
ast::ExprAddrOf(ast::MutMutable, ref sub) => {
|
||||
let (v, _) = const_expr(cx, &**sub, param_substs);
|
||||
|
|
@ -740,7 +740,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|||
}
|
||||
_ => cx.sess().span_bug(e.span,
|
||||
"bad constant expression type in consts::const_expr")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -203,6 +203,56 @@
|
|||
//! failure, but rather because the target type `Foo<Y>` is itself just
|
||||
//! not well-formed. Basically we get to assume well-formedness of all
|
||||
//! types involved before considering variance.
|
||||
//!
|
||||
//! ### Associated types
|
||||
//!
|
||||
//! Any trait with an associated type is invariant with respect to all
|
||||
//! of its inputs. To see why this makes sense, consider what
|
||||
//! subtyping for a trait reference means:
|
||||
//!
|
||||
//! <T as Trait> <: <U as Trait>
|
||||
//!
|
||||
//! means that if I know that `T as Trait`,
|
||||
//! I also know that `U as
|
||||
//! Trait`. Moreover, if you think of it as
|
||||
//! dictionary passing style, it means that
|
||||
//! a dictionary for `<T as Trait>` is safe
|
||||
//! to use where a dictionary for `<U as
|
||||
//! Trait>` is expected.
|
||||
//!
|
||||
//! The problem is that when you can
|
||||
//! project types out from `<T as Trait>`,
|
||||
//! the relationship to types projected out
|
||||
//! of `<U as Trait>` is completely unknown
|
||||
//! unless `T==U` (see #21726 for more
|
||||
//! details). Making `Trait` invariant
|
||||
//! ensures that this is true.
|
||||
//!
|
||||
//! *Historical note: we used to preserve this invariant another way,
|
||||
//! by tweaking the subtyping rules and requiring that when a type `T`
|
||||
//! appeared as part of a projection, that was considered an invariant
|
||||
//! location, but this version does away with the need for those
|
||||
//! somewhat "special-case-feeling" rules.*
|
||||
//!
|
||||
//! Another related reason is that if we didn't make traits with
|
||||
//! associated types invariant, then projection is no longer a
|
||||
//! function with a single result. Consider:
|
||||
//!
|
||||
//! ```
|
||||
//! trait Identity { type Out; fn foo(&self); }
|
||||
//! impl<T> Identity for T { type Out = T; ... }
|
||||
//! ```
|
||||
//!
|
||||
//! Now if I have `<&'static () as Identity>::Out`, this can be
|
||||
//! validly derived as `&'a ()` for any `'a`:
|
||||
//!
|
||||
//! <&'a () as Identity> <: <&'static () as Identity>
|
||||
//! if &'static () < : &'a () -- Identity is contravariant in Self
|
||||
//! if 'static : 'a -- Subtyping rules for relations
|
||||
//!
|
||||
//! This change otoh means that `<'static () as Identity>::Out` is
|
||||
//! always `&'static ()` (which might then be upcast to `'a ()`,
|
||||
//! separately). This was helpful in solving #21750.
|
||||
|
||||
use self::VarianceTerm::*;
|
||||
use self::ParamKind::*;
|
||||
|
|
@ -613,7 +663,18 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
|
|||
&method.fty.sig,
|
||||
self.covariant);
|
||||
}
|
||||
ty::TypeTraitItem(_) => {}
|
||||
ty::TypeTraitItem(ref data) => {
|
||||
// Any trait with an associated type is
|
||||
// invariant with respect to all of its
|
||||
// inputs. See length discussion in the comment
|
||||
// on this module.
|
||||
let projection_ty = ty::mk_projection(tcx,
|
||||
trait_def.trait_ref.clone(),
|
||||
data.name);
|
||||
self.add_constraints_from_ty(&trait_def.generics,
|
||||
projection_ty,
|
||||
self.invariant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -893,7 +954,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
trait_def.generics.types.as_slice(),
|
||||
trait_def.generics.regions.as_slice(),
|
||||
trait_ref.substs,
|
||||
self.invariant);
|
||||
variance);
|
||||
}
|
||||
|
||||
ty::ty_trait(ref data) => {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use std::sync::mpsc::channel;
|
|||
use std::dynamic_lib::DynamicLibrary;
|
||||
use std::old_io::{Command, TempDir};
|
||||
use std::old_io;
|
||||
use std::env;
|
||||
use std::os;
|
||||
use std::str;
|
||||
use std::thread;
|
||||
use std::thunk::Thunk;
|
||||
|
|
@ -46,7 +46,7 @@ pub fn run(input: &str,
|
|||
let input = config::Input::File(input_path.clone());
|
||||
|
||||
let sessopts = config::Options {
|
||||
maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()),
|
||||
maybe_sysroot: Some(os::self_exe_name().unwrap().dir_path().dir_path()),
|
||||
search_paths: libs.clone(),
|
||||
crate_types: vec!(config::CrateTypeDylib),
|
||||
externs: externs.clone(),
|
||||
|
|
@ -113,7 +113,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
|
|||
let input = config::Input::Str(test.to_string());
|
||||
|
||||
let sessopts = config::Options {
|
||||
maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()),
|
||||
maybe_sysroot: Some(os::self_exe_name().unwrap().dir_path().dir_path()),
|
||||
search_paths: libs,
|
||||
crate_types: vec!(config::CrateTypeExecutable),
|
||||
output_types: vec!(config::OutputTypeExe),
|
||||
|
|
|
|||
|
|
@ -3074,19 +3074,19 @@ mod tests {
|
|||
#[test]
|
||||
fn test_decode_array() {
|
||||
let v: Vec<()> = super::decode("[]").unwrap();
|
||||
assert_eq!(v, vec![]);
|
||||
assert_eq!(v, []);
|
||||
|
||||
let v: Vec<()> = super::decode("[null]").unwrap();
|
||||
assert_eq!(v, vec![()]);
|
||||
assert_eq!(v, [()]);
|
||||
|
||||
let v: Vec<bool> = super::decode("[true]").unwrap();
|
||||
assert_eq!(v, vec![true]);
|
||||
assert_eq!(v, [true]);
|
||||
|
||||
let v: Vec<int> = super::decode("[3, 1]").unwrap();
|
||||
assert_eq!(v, vec![3, 1]);
|
||||
assert_eq!(v, [3, 1]);
|
||||
|
||||
let v: Vec<Vec<uint>> = super::decode("[[3], [1, 2]]").unwrap();
|
||||
assert_eq!(v, vec![vec![3], vec![1, 2]]);
|
||||
assert_eq!(v, [vec![3], vec![1, 2]]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -1212,7 +1212,7 @@ impl<K, V, S> Debug for HashMap<K, V, S>
|
|||
where K: Eq + Hash + Debug, V: Debug, S: HashState
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "HashMap {{"));
|
||||
try!(write!(f, "{{"));
|
||||
|
||||
for (i, (k, v)) in self.iter().enumerate() {
|
||||
if i != 0 { try!(write!(f, ", ")); }
|
||||
|
|
@ -1999,9 +1999,9 @@ mod test_map {
|
|||
|
||||
let map_str = format!("{:?}", map);
|
||||
|
||||
assert!(map_str == "HashMap {1: 2, 3: 4}" ||
|
||||
map_str == "HashMap {3: 4, 1: 2}");
|
||||
assert_eq!(format!("{:?}", empty), "HashMap {}");
|
||||
assert!(map_str == "{1: 2, 3: 4}" ||
|
||||
map_str == "{3: 4, 1: 2}");
|
||||
assert_eq!(format!("{:?}", empty), "{}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -598,7 +598,7 @@ impl<T, S> fmt::Debug for HashSet<T, S>
|
|||
S: HashState
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
try!(write!(f, "HashSet {{"));
|
||||
try!(write!(f, "{{"));
|
||||
|
||||
for (i, x) in self.iter().enumerate() {
|
||||
if i != 0 { try!(write!(f, ", ")); }
|
||||
|
|
@ -1186,8 +1186,8 @@ mod test_set {
|
|||
|
||||
let set_str = format!("{:?}", set);
|
||||
|
||||
assert!(set_str == "HashSet {1, 2}" || set_str == "HashSet {2, 1}");
|
||||
assert_eq!(format!("{:?}", empty), "HashSet {}");
|
||||
assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
|
||||
assert_eq!(format!("{:?}", empty), "{}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ use num::{Int, UnsignedInt};
|
|||
use ops::{Deref, DerefMut, Drop};
|
||||
use option::Option;
|
||||
use option::Option::{Some, None};
|
||||
use ptr::{self, PtrExt, copy_nonoverlapping_memory, Unique, zero_memory};
|
||||
use ptr::{self, PtrExt, Unique};
|
||||
use rt::heap::{allocate, deallocate, EMPTY};
|
||||
use collections::hash_state::HashState;
|
||||
|
||||
|
|
@ -477,8 +477,8 @@ impl<K, V, M: Deref<Target=RawTable<K, V>>> GapThenFull<K, V, M> {
|
|||
pub fn shift(mut self) -> Option<GapThenFull<K, V, M>> {
|
||||
unsafe {
|
||||
*self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET);
|
||||
copy_nonoverlapping_memory(self.gap.raw.key, self.full.raw.key, 1);
|
||||
copy_nonoverlapping_memory(self.gap.raw.val, self.full.raw.val, 1);
|
||||
ptr::copy_nonoverlapping(self.gap.raw.key, self.full.raw.key, 1);
|
||||
ptr::copy_nonoverlapping(self.gap.raw.val, self.full.raw.val, 1);
|
||||
}
|
||||
|
||||
let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full;
|
||||
|
|
@ -637,7 +637,7 @@ impl<K, V> RawTable<K, V> {
|
|||
pub fn new(capacity: usize) -> RawTable<K, V> {
|
||||
unsafe {
|
||||
let ret = RawTable::new_uninitialized(capacity);
|
||||
zero_memory(*ret.hashes, capacity);
|
||||
ptr::write_bytes(*ret.hashes, 0, capacity);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ use ffi::CString;
|
|||
use mem;
|
||||
use env;
|
||||
use str;
|
||||
use os;
|
||||
|
||||
pub struct DynamicLibrary {
|
||||
handle: *mut u8
|
||||
|
|
@ -102,7 +103,7 @@ impl DynamicLibrary {
|
|||
/// process
|
||||
pub fn search_path() -> Vec<Path> {
|
||||
match env::var_os(DynamicLibrary::envvar()) {
|
||||
Some(var) => env::split_paths(&var).collect(),
|
||||
Some(var) => os::split_paths(var.to_str().unwrap()),
|
||||
None => Vec::new(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ use prelude::v1::*;
|
|||
use error::Error;
|
||||
use ffi::{OsString, AsOsStr};
|
||||
use fmt;
|
||||
use old_io::IoResult;
|
||||
use io;
|
||||
use path::{AsPath, PathBuf};
|
||||
use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
|
||||
use sync::{StaticMutex, MUTEX_INIT};
|
||||
use sys::os as os_imp;
|
||||
|
|
@ -46,7 +47,7 @@ use sys::os as os_imp;
|
|||
/// let p = env::current_dir().unwrap();
|
||||
/// println!("The current directory is {}", p.display());
|
||||
/// ```
|
||||
pub fn current_dir() -> IoResult<Path> {
|
||||
pub fn current_dir() -> io::Result<PathBuf> {
|
||||
os_imp::getcwd()
|
||||
}
|
||||
|
||||
|
|
@ -57,14 +58,14 @@ pub fn current_dir() -> IoResult<Path> {
|
|||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
/// use std::old_path::Path;
|
||||
/// use std::path::Path;
|
||||
///
|
||||
/// let root = Path::new("/");
|
||||
/// assert!(env::set_current_dir(&root).is_ok());
|
||||
/// println!("Successfully changed working directory to {}!", root.display());
|
||||
/// ```
|
||||
pub fn set_current_dir(p: &Path) -> IoResult<()> {
|
||||
os_imp::chdir(p)
|
||||
pub fn set_current_dir<P: AsPath + ?Sized>(p: &P) -> io::Result<()> {
|
||||
os_imp::chdir(p.as_path())
|
||||
}
|
||||
|
||||
static ENV_LOCK: StaticMutex = MUTEX_INIT;
|
||||
|
|
@ -280,8 +281,8 @@ pub fn split_paths<T: AsOsStr + ?Sized>(unparsed: &T) -> SplitPaths {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for SplitPaths<'a> {
|
||||
type Item = Path;
|
||||
fn next(&mut self) -> Option<Path> { self.inner.next() }
|
||||
type Item = PathBuf;
|
||||
fn next(&mut self) -> Option<PathBuf> { self.inner.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
|
|
@ -305,10 +306,11 @@ pub struct JoinPathsError {
|
|||
///
|
||||
/// ```rust
|
||||
/// use std::env;
|
||||
/// use std::path::PathBuf;
|
||||
///
|
||||
/// if let Some(path) = env::var_os("PATH") {
|
||||
/// let mut paths = env::split_paths(&path).collect::<Vec<_>>();
|
||||
/// paths.push(Path::new("/home/xyz/bin"));
|
||||
/// paths.push(PathBuf::new("/home/xyz/bin"));
|
||||
/// let new_path = env::join_paths(paths.iter()).unwrap();
|
||||
/// env::set_var("PATH", &new_path);
|
||||
/// }
|
||||
|
|
@ -355,7 +357,7 @@ impl Error for JoinPathsError {
|
|||
/// None => println!("Impossible to get your home dir!")
|
||||
/// }
|
||||
/// ```
|
||||
pub fn home_dir() -> Option<Path> {
|
||||
pub fn home_dir() -> Option<PathBuf> {
|
||||
os_imp::home_dir()
|
||||
}
|
||||
|
||||
|
|
@ -369,7 +371,7 @@ pub fn home_dir() -> Option<Path> {
|
|||
/// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
|
||||
/// 'USERPROFILE' environment variable if any are set and not the empty
|
||||
/// string. Otherwise, tmpdir returns the path to the Windows directory.
|
||||
pub fn temp_dir() -> Path {
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
os_imp::temp_dir()
|
||||
}
|
||||
|
||||
|
|
@ -396,7 +398,7 @@ pub fn temp_dir() -> Path {
|
|||
/// Err(e) => println!("failed to get current exe path: {}", e),
|
||||
/// };
|
||||
/// ```
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
os_imp::current_exe()
|
||||
}
|
||||
|
||||
|
|
@ -825,6 +827,7 @@ mod tests {
|
|||
use iter::repeat;
|
||||
use rand::{self, Rng};
|
||||
use ffi::{OsString, OsStr};
|
||||
use path::PathBuf;
|
||||
|
||||
fn make_rand_name() -> OsString {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
|
@ -924,7 +927,7 @@ mod tests {
|
|||
fn split_paths_windows() {
|
||||
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
|
||||
split_paths(unparsed).collect::<Vec<_>>() ==
|
||||
parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
|
||||
parsed.iter().map(|s| PathBuf::new(*s)).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
assert!(check_parse("", &mut [""]));
|
||||
|
|
@ -944,7 +947,7 @@ mod tests {
|
|||
fn split_paths_unix() {
|
||||
fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
|
||||
split_paths(unparsed).collect::<Vec<_>>() ==
|
||||
parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
|
||||
parsed.iter().map(|s| PathBuf::new(*s)).collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
assert!(check_parse("", &mut [""]));
|
||||
|
|
|
|||
|
|
@ -25,6 +25,10 @@ use sys::fs2 as fs_imp;
|
|||
use sys_common::{AsInnerMut, FromInner, AsInner};
|
||||
use vec::Vec;
|
||||
|
||||
pub use self::tempdir::TempDir;
|
||||
|
||||
mod tempdir;
|
||||
|
||||
/// A reference to an open file on the filesystem.
|
||||
///
|
||||
/// An instance of a `File` can be read and/or written depending on what options
|
||||
|
|
@ -325,6 +329,10 @@ impl FromInner<fs_imp::FilePermissions> for Permissions {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsInner<fs_imp::FilePermissions> for Permissions {
|
||||
fn as_inner(&self) -> &fs_imp::FilePermissions { &self.0 }
|
||||
}
|
||||
|
||||
impl Iterator for ReadDir {
|
||||
type Item = io::Result<DirEntry>;
|
||||
|
||||
|
|
@ -540,7 +548,14 @@ pub fn create_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
|
|||
Some(p) if p != path => try!(create_dir_all(p)),
|
||||
_ => {}
|
||||
}
|
||||
create_dir(path)
|
||||
// If the file name of the given `path` is blank then the creation of the
|
||||
// parent directory will have taken care of the whole path for us, so we're
|
||||
// good to go.
|
||||
if path.file_name().is_none() {
|
||||
Ok(())
|
||||
} else {
|
||||
create_dir(path)
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove an existing, empty directory
|
||||
|
|
@ -1500,4 +1515,11 @@ mod tests {
|
|||
check!(fs::set_permissions(&path, perm));
|
||||
check!(fs::remove_file(&path));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mkdir_trailing_slash() {
|
||||
let tmpdir = tmpdir();
|
||||
let path = tmpdir.join("file");
|
||||
check!(fs::create_dir_all(&path.join("a/")));
|
||||
}
|
||||
}
|
||||
125
src/libstd/fs/tempdir.rs
Normal file
125
src/libstd/fs/tempdir.rs
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![unstable(feature = "tempdir", reason = "needs an RFC before stabilization")]
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use env;
|
||||
use io::{self, Error, ErrorKind};
|
||||
use fs;
|
||||
use path::{self, PathBuf, AsPath};
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
/// A wrapper for a path to temporary directory implementing automatic
|
||||
/// scope-based deletion.
|
||||
pub struct TempDir {
|
||||
path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
// How many times should we (re)try finding an unused random name? It should be
|
||||
// enough that an attacker will run out of luck before we run out of patience.
|
||||
const NUM_RETRIES: u32 = 1 << 31;
|
||||
// How many characters should we include in a random file name? It needs to
|
||||
// be enough to dissuade an attacker from trying to preemptively create names
|
||||
// of that length, but not so huge that we unnecessarily drain the random number
|
||||
// generator of entropy.
|
||||
const NUM_RAND_CHARS: uint = 12;
|
||||
|
||||
impl TempDir {
|
||||
/// Attempts to make a temporary directory inside of `tmpdir` whose name
|
||||
/// will have the prefix `prefix`. The directory will be automatically
|
||||
/// deleted once the returned wrapper is destroyed.
|
||||
///
|
||||
/// If no directory can be created, `Err` is returned.
|
||||
#[allow(deprecated)] // rand usage
|
||||
pub fn new_in<P: AsPath + ?Sized>(tmpdir: &P, prefix: &str)
|
||||
-> io::Result<TempDir> {
|
||||
let storage;
|
||||
let mut tmpdir = tmpdir.as_path();
|
||||
if !tmpdir.is_absolute() {
|
||||
let cur_dir = try!(env::current_dir());
|
||||
storage = cur_dir.join(tmpdir);
|
||||
tmpdir = &storage;
|
||||
// return TempDir::new_in(&cur_dir.join(tmpdir), prefix);
|
||||
}
|
||||
|
||||
let mut rng = thread_rng();
|
||||
for _ in 0..NUM_RETRIES {
|
||||
let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect();
|
||||
let leaf = if prefix.len() > 0 {
|
||||
format!("{}.{}", prefix, suffix)
|
||||
} else {
|
||||
// If we're given an empty string for a prefix, then creating a
|
||||
// directory starting with "." would lead to it being
|
||||
// semi-invisible on some systems.
|
||||
suffix
|
||||
};
|
||||
let path = tmpdir.join(&leaf);
|
||||
match fs::create_dir(&path) {
|
||||
Ok(_) => return Ok(TempDir { path: Some(path) }),
|
||||
Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {}
|
||||
Err(e) => return Err(e)
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::new(ErrorKind::PathAlreadyExists,
|
||||
"too many temporary directories already exist",
|
||||
None))
|
||||
}
|
||||
|
||||
/// Attempts to make a temporary directory inside of `env::temp_dir()` whose
|
||||
/// name will have the prefix `prefix`. The directory will be automatically
|
||||
/// deleted once the returned wrapper is destroyed.
|
||||
///
|
||||
/// If no directory can be created, `Err` is returned.
|
||||
#[allow(deprecated)]
|
||||
pub fn new(prefix: &str) -> io::Result<TempDir> {
|
||||
TempDir::new_in(&env::temp_dir(), prefix)
|
||||
}
|
||||
|
||||
/// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
|
||||
/// This discards the wrapper so that the automatic deletion of the
|
||||
/// temporary directory is prevented.
|
||||
pub fn into_path(mut self) -> PathBuf {
|
||||
self.path.take().unwrap()
|
||||
}
|
||||
|
||||
/// Access the wrapped `std::path::Path` to the temporary directory.
|
||||
pub fn path(&self) -> &path::Path {
|
||||
self.path.as_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Close and remove the temporary directory
|
||||
///
|
||||
/// Although `TempDir` removes the directory on drop, in the destructor
|
||||
/// any errors are ignored. To detect errors cleaning up the temporary
|
||||
/// directory, call `close` instead.
|
||||
pub fn close(mut self) -> io::Result<()> {
|
||||
self.cleanup_dir()
|
||||
}
|
||||
|
||||
fn cleanup_dir(&mut self) -> io::Result<()> {
|
||||
match self.path {
|
||||
Some(ref p) => fs::remove_dir_all(p),
|
||||
None => Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TempDir {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.cleanup_dir();
|
||||
}
|
||||
}
|
||||
|
||||
// the tests for this module need to change the path using change_dir,
|
||||
// and this doesn't play nicely with other tests so these unit tests are located
|
||||
// in src/test/run-pass/tempfile.rs
|
||||
|
|
@ -48,7 +48,7 @@ impl<R: Read> BufReader<R> {
|
|||
}
|
||||
|
||||
/// Gets a reference to the underlying reader.
|
||||
pub fn get_ref<'a>(&self) -> &R { &self.inner }
|
||||
pub fn get_ref(&self) -> &R { &self.inner }
|
||||
|
||||
/// Gets a mutable reference to the underlying reader.
|
||||
///
|
||||
|
|
@ -155,9 +155,9 @@ impl<W: Write> BufWriter<W> {
|
|||
if written > 0 {
|
||||
// NB: would be better expressed as .remove(0..n) if it existed
|
||||
unsafe {
|
||||
ptr::copy_memory(self.buf.as_mut_ptr(),
|
||||
self.buf.as_ptr().offset(written as isize),
|
||||
len - written);
|
||||
ptr::copy(self.buf.as_mut_ptr(),
|
||||
self.buf.as_ptr().offset(written as isize),
|
||||
len - written);
|
||||
}
|
||||
}
|
||||
self.buf.truncate(len - written);
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@
|
|||
#![feature(unsafe_no_drop_flag)]
|
||||
#![feature(macro_reexport)]
|
||||
#![feature(hash)]
|
||||
#![feature(unique)]
|
||||
#![cfg_attr(test, feature(test, rustc_private, env))]
|
||||
|
||||
// Don't link to std. We are std.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,6 @@ fn base_port() -> u16 {
|
|||
let dirs = ["32-opt", "32-nopt", "64-opt", "64-nopt", "64-opt-vg",
|
||||
"all-opt", "snap3", "dist"];
|
||||
dirs.iter().enumerate().find(|&(_, dir)| {
|
||||
cwd.as_str().unwrap().contains(dir)
|
||||
cwd.to_str().unwrap().contains(dir)
|
||||
}).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600
|
||||
}
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ mod test {
|
|||
fn read_bytes() {
|
||||
let mut reader = MemReader::new(vec!(10, 11, 12, 13));
|
||||
let bytes = reader.read_exact(4).unwrap();
|
||||
assert!(bytes == vec!(10, 11, 12, 13));
|
||||
assert_eq!(bytes, [10, 11, 12, 13]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -337,7 +337,7 @@ mod test {
|
|||
count: 0,
|
||||
};
|
||||
let bytes = reader.read_exact(4).unwrap();
|
||||
assert!(bytes == vec!(10, 11, 12, 13));
|
||||
assert_eq!(bytes, [10, 11, 12, 13]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -351,7 +351,7 @@ mod test {
|
|||
let mut reader = MemReader::new(vec![10, 11, 12, 13]);
|
||||
let mut buf = vec![8, 9];
|
||||
assert!(reader.push_at_least(4, 4, &mut buf).is_ok());
|
||||
assert!(buf == vec![8, 9, 10, 11, 12, 13]);
|
||||
assert_eq!(buf, [8, 9, 10, 11, 12, 13]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -361,7 +361,7 @@ mod test {
|
|||
};
|
||||
let mut buf = vec![8, 9];
|
||||
assert!(reader.push_at_least(4, 4, &mut buf).is_ok());
|
||||
assert!(buf == vec![8, 9, 10, 11, 12, 13]);
|
||||
assert_eq!(buf, [8, 9, 10, 11, 12, 13]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -369,7 +369,7 @@ mod test {
|
|||
let mut reader = MemReader::new(vec![10, 11]);
|
||||
let mut buf = vec![8, 9];
|
||||
assert!(reader.push_at_least(4, 4, &mut buf).is_err());
|
||||
assert!(buf == vec![8, 9, 10, 11]);
|
||||
assert_eq!(buf, [8, 9, 10, 11]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -379,7 +379,7 @@ mod test {
|
|||
};
|
||||
let mut buf = vec![8, 9];
|
||||
assert!(reader.push_at_least(4, 4, &mut buf).is_err());
|
||||
assert!(buf == vec![8, 9, 10]);
|
||||
assert_eq!(buf, [8, 9, 10]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -388,7 +388,7 @@ mod test {
|
|||
count: 0,
|
||||
};
|
||||
let buf = reader.read_to_end().unwrap();
|
||||
assert!(buf == vec!(10, 11, 12, 13));
|
||||
assert_eq!(buf, [10, 11, 12, 13]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -398,7 +398,7 @@ mod test {
|
|||
count: 0,
|
||||
};
|
||||
let buf = reader.read_to_end().unwrap();
|
||||
assert!(buf == vec!(10, 11));
|
||||
assert_eq!(buf, [10, 11]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ impl Writer for Vec<u8> {
|
|||
/// let mut w = MemWriter::new();
|
||||
/// w.write(&[0, 1, 2]);
|
||||
///
|
||||
/// assert_eq!(w.into_inner(), vec!(0, 1, 2));
|
||||
/// assert_eq!(w.into_inner(), [0, 1, 2]);
|
||||
/// ```
|
||||
#[unstable(feature = "io")]
|
||||
#[deprecated(since = "1.0.0",
|
||||
|
|
@ -118,7 +118,7 @@ impl Writer for MemWriter {
|
|||
///
|
||||
/// let mut r = MemReader::new(vec!(0, 1, 2));
|
||||
///
|
||||
/// assert_eq!(r.read_to_end().unwrap(), vec!(0, 1, 2));
|
||||
/// assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]);
|
||||
/// ```
|
||||
pub struct MemReader {
|
||||
buf: Vec<u8>,
|
||||
|
|
@ -321,7 +321,7 @@ impl<'a> Seek for BufWriter<'a> {
|
|||
/// let buf = [0, 1, 2, 3];
|
||||
/// let mut r = BufReader::new(&buf);
|
||||
///
|
||||
/// assert_eq!(r.read_to_end().unwrap(), vec![0, 1, 2, 3]);
|
||||
/// assert_eq!(r.read_to_end().unwrap(), [0, 1, 2, 3]);
|
||||
/// ```
|
||||
pub struct BufReader<'a> {
|
||||
buf: &'a [u8],
|
||||
|
|
@ -504,8 +504,8 @@ mod test {
|
|||
assert_eq!(&buf[..3], b);
|
||||
assert!(reader.read(&mut buf).is_err());
|
||||
let mut reader = MemReader::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
|
||||
assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
|
||||
assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
|
||||
assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]);
|
||||
assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]);
|
||||
assert!(reader.read(&mut buf).is_err());
|
||||
}
|
||||
|
||||
|
|
@ -530,8 +530,8 @@ mod test {
|
|||
assert_eq!(&buf[..3], b);
|
||||
assert!(reader.read(&mut buf).is_err());
|
||||
let mut reader = &mut &*in_buf;
|
||||
assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
|
||||
assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
|
||||
assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]);
|
||||
assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]);
|
||||
assert!(reader.read(&mut buf).is_err());
|
||||
}
|
||||
|
||||
|
|
@ -557,8 +557,8 @@ mod test {
|
|||
assert_eq!(&buf[..3], b);
|
||||
assert!(reader.read(&mut buf).is_err());
|
||||
let mut reader = BufReader::new(&in_buf);
|
||||
assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
|
||||
assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
|
||||
assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]);
|
||||
assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]);
|
||||
assert!(reader.read(&mut buf).is_err());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ mod test {
|
|||
let mut writer: old_io::IoResult<Vec<u8>> = Ok(Vec::new());
|
||||
writer.write_all(&[0, 1, 2]).unwrap();
|
||||
writer.flush().unwrap();
|
||||
assert_eq!(writer.unwrap(), vec!(0, 1, 2));
|
||||
assert_eq!(writer.unwrap(), [0, 1, 2]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -96,9 +96,10 @@ impl TempDir {
|
|||
/// deleted once the returned wrapper is destroyed.
|
||||
///
|
||||
/// If no directory can be created, `Err` is returned.
|
||||
#[allow(deprecated)]
|
||||
pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult<TempDir> {
|
||||
if !tmpdir.is_absolute() {
|
||||
let cur_dir = try!(env::current_dir());
|
||||
let cur_dir = try!(::os::getcwd());
|
||||
return TempDir::new_in(&cur_dir.join(tmpdir), prefix);
|
||||
}
|
||||
|
||||
|
|
@ -132,8 +133,9 @@ impl TempDir {
|
|||
/// deleted once the returned wrapper is destroyed.
|
||||
///
|
||||
/// If no directory can be created, `Err` is returned.
|
||||
#[allow(deprecated)]
|
||||
pub fn new(prefix: &str) -> IoResult<TempDir> {
|
||||
TempDir::new_in(&env::temp_dir(), prefix)
|
||||
TempDir::new_in(&::os::tmpdir(), prefix)
|
||||
}
|
||||
|
||||
/// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
|
||||
|
|
|
|||
|
|
@ -38,10 +38,11 @@ fn next_test_unix_socket() -> String {
|
|||
|
||||
/// Get a temporary path which could be the location of a unix socket
|
||||
#[cfg(not(target_os = "ios"))]
|
||||
#[allow(deprecated)]
|
||||
pub fn next_test_unix() -> Path {
|
||||
let string = next_test_unix_socket();
|
||||
if cfg!(unix) {
|
||||
env::temp_dir().join(string)
|
||||
::os::tmpdir().join(string)
|
||||
} else {
|
||||
Path::new(format!("{}{}", r"\\.\pipe\", string))
|
||||
}
|
||||
|
|
@ -88,7 +89,7 @@ fn base_port() -> u16 {
|
|||
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let path = env::current_dir().unwrap();
|
||||
let path_s = path.as_str().unwrap();
|
||||
let path_s = path.to_str().unwrap();
|
||||
|
||||
let mut final_base = base;
|
||||
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ mod test {
|
|||
let mut r = MemReader::new(vec!(0, 1, 2));
|
||||
{
|
||||
let mut r = LimitReader::new(r.by_ref(), 4);
|
||||
assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
|
||||
assert_eq!([0, 1, 2], r.read_to_end().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -293,9 +293,9 @@ mod test {
|
|||
let mut r = MemReader::new(vec!(0, 1, 2));
|
||||
{
|
||||
let mut r = LimitReader::new(r.by_ref(), 2);
|
||||
assert_eq!(vec!(0, 1), r.read_to_end().unwrap());
|
||||
assert_eq!([0, 1], r.read_to_end().unwrap());
|
||||
}
|
||||
assert_eq!(vec!(2), r.read_to_end().unwrap());
|
||||
assert_eq!([2], r.read_to_end().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -305,7 +305,7 @@ mod test {
|
|||
assert_eq!(3, r.limit());
|
||||
assert_eq!(0, r.read_byte().unwrap());
|
||||
assert_eq!(2, r.limit());
|
||||
assert_eq!(vec!(1, 2), r.read_to_end().unwrap());
|
||||
assert_eq!([1, 2], r.read_to_end().unwrap());
|
||||
assert_eq!(0, r.limit());
|
||||
}
|
||||
|
||||
|
|
@ -314,7 +314,7 @@ mod test {
|
|||
let mut r = MemReader::new(vec![0, 1, 2, 3, 4, 5]);
|
||||
let mut r = LimitReader::new(r.by_ref(), 1);
|
||||
r.consume(2);
|
||||
assert_eq!(vec![], r.read_to_end().unwrap());
|
||||
assert_eq!([], r.read_to_end().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -330,7 +330,7 @@ mod test {
|
|||
let mut s = ZeroReader;
|
||||
let mut buf = vec![1, 2, 3];
|
||||
assert_eq!(s.read(&mut buf), Ok(3));
|
||||
assert_eq!(vec![0, 0, 0], buf);
|
||||
assert_eq!([0, 0, 0], buf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -373,16 +373,16 @@ mod test {
|
|||
let rs = vec!(MemReader::new(vec!(0, 1)), MemReader::new(vec!()),
|
||||
MemReader::new(vec!(2, 3)));
|
||||
let mut r = ChainedReader::new(rs.into_iter());
|
||||
assert_eq!(vec!(0, 1, 2, 3), r.read_to_end().unwrap());
|
||||
assert_eq!([0, 1, 2, 3], r.read_to_end().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tee_reader() {
|
||||
let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)),
|
||||
Vec::new());
|
||||
assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
|
||||
assert_eq!([0, 1, 2], r.read_to_end().unwrap());
|
||||
let (_, w) = r.into_inner();
|
||||
assert_eq!(vec!(0, 1, 2), w);
|
||||
assert_eq!([0, 1, 2], w);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -390,7 +390,7 @@ mod test {
|
|||
let mut r = MemReader::new(vec!(0, 1, 2, 3, 4));
|
||||
let mut w = Vec::new();
|
||||
copy(&mut r, &mut w).unwrap();
|
||||
assert_eq!(vec!(0, 1, 2, 3, 4), w);
|
||||
assert_eq!([0, 1, 2, 3, 4], w);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ use ops::{Drop, FnOnce};
|
|||
use option::Option::{Some, None};
|
||||
use option::Option;
|
||||
use old_path::{Path, GenericPath, BytesContainer};
|
||||
use path::{self, PathBuf};
|
||||
use ptr::PtrExt;
|
||||
use ptr;
|
||||
use result::Result::{Err, Ok};
|
||||
|
|
@ -67,6 +68,35 @@ use vec::Vec;
|
|||
#[cfg(unix)] pub use sys::ext as unix;
|
||||
#[cfg(windows)] pub use sys::ext as windows;
|
||||
|
||||
fn err2old(new: ::io::Error) -> IoError {
|
||||
IoError {
|
||||
kind: ::old_io::OtherIoError,
|
||||
desc: "os error",
|
||||
detail: Some(new.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn path2new(path: &Path) -> PathBuf {
|
||||
PathBuf::new(path.as_str().unwrap())
|
||||
}
|
||||
#[cfg(unix)]
|
||||
fn path2new(path: &Path) -> PathBuf {
|
||||
use os::unix::prelude::*;
|
||||
PathBuf::new(<OsStr as OsStrExt>::from_bytes(path.as_vec()))
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn path2old(path: &path::Path) -> Path {
|
||||
use os::unix::prelude::*;
|
||||
use ffi::AsOsStr;
|
||||
Path::new(path.as_os_str().as_bytes())
|
||||
}
|
||||
#[cfg(windows)]
|
||||
fn path2old(path: &path::Path) -> Path {
|
||||
Path::new(path.to_str().unwrap())
|
||||
}
|
||||
|
||||
/// Get the number of cores available
|
||||
pub fn num_cpus() -> uint {
|
||||
unsafe {
|
||||
|
|
@ -100,10 +130,9 @@ pub const TMPBUF_SZ : uint = 1000;
|
|||
/// let current_working_directory = os::getcwd().unwrap();
|
||||
/// println!("The current directory is {:?}", current_working_directory.display());
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to std::env::current_dir")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn getcwd() -> IoResult<Path> {
|
||||
env::current_dir()
|
||||
env::current_dir().map_err(err2old).map(|s| path2old(&s))
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) pairs, for all the environment
|
||||
|
|
@ -245,12 +274,11 @@ pub fn unsetenv(n: &str) {
|
|||
/// None => println!("{} is not defined in the environment.", key)
|
||||
/// }
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::split_paths")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
|
||||
let b = unparsed.container_as_bytes();
|
||||
let s = str::from_utf8(b).unwrap();
|
||||
env::split_paths(s).collect()
|
||||
env::split_paths(s).map(|s| path2old(&s)).collect()
|
||||
}
|
||||
|
||||
/// Joins a collection of `Path`s appropriately for the `PATH`
|
||||
|
|
@ -274,7 +302,6 @@ pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
|
|||
/// paths.push(Path::new("/home/xyz/bin"));
|
||||
/// os::setenv(key, os::join_paths(paths.as_slice()).unwrap());
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::join_paths")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
|
||||
env::join_paths(paths.iter().map(|s| {
|
||||
|
|
@ -335,10 +362,9 @@ pub fn dll_filename(base: &str) -> String {
|
|||
/// None => println!("Unable to get the path of this executable!")
|
||||
/// };
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::current_exe")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn self_exe_name() -> Option<Path> {
|
||||
env::current_exe().ok()
|
||||
env::current_exe().ok().map(|p| path2old(&p))
|
||||
}
|
||||
|
||||
/// Optionally returns the filesystem path to the current executable which is
|
||||
|
|
@ -356,10 +382,9 @@ pub fn self_exe_name() -> Option<Path> {
|
|||
/// None => println!("Impossible to fetch the path of this executable.")
|
||||
/// };
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "use env::current_exe + dir_path/pop")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn self_exe_path() -> Option<Path> {
|
||||
env::current_exe().ok().map(|mut p| { p.pop(); p })
|
||||
env::current_exe().ok().map(|p| { let mut p = path2old(&p); p.pop(); p })
|
||||
}
|
||||
|
||||
/// Optionally returns the path to the current user's home directory if known.
|
||||
|
|
@ -386,9 +411,8 @@ pub fn self_exe_path() -> Option<Path> {
|
|||
/// None => println!("Impossible to get your home dir!")
|
||||
/// }
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::home_dir")]
|
||||
#[allow(deprecated)]
|
||||
#[unstable(feature = "os")]
|
||||
#[allow(deprecated)]
|
||||
pub fn homedir() -> Option<Path> {
|
||||
#[inline]
|
||||
#[cfg(unix)]
|
||||
|
|
@ -424,9 +448,8 @@ pub fn homedir() -> Option<Path> {
|
|||
/// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
|
||||
/// 'USERPROFILE' environment variable if any are set and not the empty
|
||||
/// string. Otherwise, tmpdir returns the path to the Windows directory.
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::temp_dir")]
|
||||
#[allow(deprecated)]
|
||||
#[unstable(feature = "os")]
|
||||
#[allow(deprecated)]
|
||||
pub fn tmpdir() -> Path {
|
||||
return lookup();
|
||||
|
||||
|
|
@ -488,7 +511,8 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
|
|||
if p.is_absolute() {
|
||||
Ok(p.clone())
|
||||
} else {
|
||||
env::current_dir().map(|mut cwd| {
|
||||
env::current_dir().map_err(err2old).map(|cwd| {
|
||||
let mut cwd = path2old(&cwd);
|
||||
cwd.push(p);
|
||||
cwd
|
||||
})
|
||||
|
|
@ -507,10 +531,9 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
|
|||
/// assert!(os::change_dir(&root).is_ok());
|
||||
/// println!("Successfully changed working directory to {}!", root.display());
|
||||
/// ```
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to env::set_current_dir")]
|
||||
#[unstable(feature = "os")]
|
||||
pub fn change_dir(p: &Path) -> IoResult<()> {
|
||||
return sys::os::chdir(p);
|
||||
sys::os::chdir(&path2new(p)).map_err(err2old)
|
||||
}
|
||||
|
||||
/// Returns the platform-specific value of errno
|
||||
|
|
|
|||
|
|
@ -188,7 +188,6 @@ mod imp {
|
|||
extern crate libc;
|
||||
|
||||
use old_io::{IoResult};
|
||||
use marker::Sync;
|
||||
use mem;
|
||||
use os;
|
||||
use rand::Rng;
|
||||
|
|
@ -214,10 +213,8 @@ mod imp {
|
|||
#[repr(C)]
|
||||
struct SecRandom;
|
||||
|
||||
unsafe impl Sync for *const SecRandom {}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;
|
||||
const kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;
|
||||
|
||||
#[link(name = "Security", kind = "framework")]
|
||||
extern "C" {
|
||||
|
|
|
|||
|
|
@ -61,9 +61,6 @@ use sync::{mutex, MutexGuard, PoisonError};
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Condvar { inner: Box<StaticCondvar> }
|
||||
|
||||
unsafe impl Send for Condvar {}
|
||||
unsafe impl Sync for Condvar {}
|
||||
|
||||
/// Statically allocated condition variables.
|
||||
///
|
||||
/// This structure is identical to `Condvar` except that it is suitable for use
|
||||
|
|
@ -83,9 +80,6 @@ pub struct StaticCondvar {
|
|||
mutex: AtomicUsize,
|
||||
}
|
||||
|
||||
unsafe impl Send for StaticCondvar {}
|
||||
unsafe impl Sync for StaticCondvar {}
|
||||
|
||||
/// Constant initializer for a statically allocated condition variable.
|
||||
#[unstable(feature = "std_misc",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ pub use self::barrier::{Barrier, BarrierWaitResult};
|
|||
pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
|
||||
|
||||
pub use self::future::Future;
|
||||
#[allow(deprecated)]
|
||||
pub use self::task_pool::TaskPool;
|
||||
|
||||
pub mod mpsc;
|
||||
|
|
|
|||
|
|
@ -152,8 +152,6 @@ pub struct StaticMutex {
|
|||
poison: poison::Flag,
|
||||
}
|
||||
|
||||
unsafe impl Sync for StaticMutex {}
|
||||
|
||||
/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
|
||||
/// dropped (falls out of scope), the lock will be unlocked.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -13,10 +13,9 @@
|
|||
//! This primitive is meant to be used to run one-time initialization. An
|
||||
//! example use case would be for initializing an FFI library.
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use isize;
|
||||
use marker::Sync;
|
||||
use mem::drop;
|
||||
use ops::FnOnce;
|
||||
use sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT};
|
||||
use sync::{StaticMutex, MUTEX_INIT};
|
||||
|
||||
|
|
@ -43,8 +42,6 @@ pub struct Once {
|
|||
lock_cnt: AtomicIsize,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Once {}
|
||||
|
||||
/// Initialization value for static `Once` values.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const ONCE_INIT: Once = Once {
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@ use fmt;
|
|||
use thread;
|
||||
|
||||
pub struct Flag { failed: UnsafeCell<bool> }
|
||||
|
||||
// This flag is only ever accessed with a lock previously held. Note that this
|
||||
// a totally private structure.
|
||||
unsafe impl Send for Flag {}
|
||||
unsafe impl Sync for Flag {}
|
||||
|
||||
pub const FLAG_INIT: Flag = Flag { failed: UnsafeCell { value: false } };
|
||||
|
||||
impl Flag {
|
||||
|
|
|
|||
|
|
@ -97,9 +97,6 @@ pub struct StaticRwLock {
|
|||
poison: poison::Flag,
|
||||
}
|
||||
|
||||
unsafe impl Send for StaticRwLock {}
|
||||
unsafe impl Sync for StaticRwLock {}
|
||||
|
||||
/// Constant initialization for a statically-initialized rwlock.
|
||||
#[unstable(feature = "std_misc",
|
||||
reason = "may be merged with RwLock in the future")]
|
||||
|
|
|
|||
|
|
@ -10,11 +10,13 @@
|
|||
|
||||
//! Abstraction of a thread pool for basic parallelism.
|
||||
|
||||
#![unstable(feature = "std_misc",
|
||||
reason = "the semantics of a failing task and whether a thread is \
|
||||
re-attached to a thread pool are somewhat unclear, and the \
|
||||
utility of this type in `std::sync` is questionable with \
|
||||
respect to the jobs of other primitives")]
|
||||
#![deprecated(since = "1.0.0",
|
||||
reason = "This kind of API needs some time to bake in \
|
||||
crates.io. This functionality is available through \
|
||||
https://crates.io/crates/threadpool")]
|
||||
#![unstable(feature = "std_misc")]
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -503,7 +503,7 @@ pub fn connect_timeout(fd: sock_t,
|
|||
#[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK;
|
||||
|
||||
// Make sure the call to connect() doesn't block
|
||||
try!(set_nonblocking(fd, true));
|
||||
set_nonblocking(fd, true);
|
||||
|
||||
let ret = match unsafe { libc::connect(fd, addrp, len) } {
|
||||
// If the connection is in progress, then we need to wait for it to
|
||||
|
|
@ -533,7 +533,7 @@ pub fn connect_timeout(fd: sock_t,
|
|||
};
|
||||
|
||||
// be sure to turn blocking I/O back on
|
||||
try!(set_nonblocking(fd, false));
|
||||
set_nonblocking(fd, false);
|
||||
return ret;
|
||||
|
||||
#[cfg(unix)]
|
||||
|
|
@ -626,7 +626,7 @@ pub struct Guard<'a> {
|
|||
#[unsafe_destructor]
|
||||
impl<'a> Drop for Guard<'a> {
|
||||
fn drop(&mut self) {
|
||||
assert!(set_nonblocking(self.fd, false).is_ok());
|
||||
set_nonblocking(self.fd, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -723,7 +723,7 @@ impl TcpStream {
|
|||
fd: self.fd(),
|
||||
guard: self.inner.lock.lock().unwrap(),
|
||||
};
|
||||
assert!(set_nonblocking(self.fd(), true).is_ok());
|
||||
set_nonblocking(self.fd(), true);
|
||||
ret
|
||||
}
|
||||
|
||||
|
|
@ -862,7 +862,7 @@ impl UdpSocket {
|
|||
fd: self.fd(),
|
||||
guard: self.inner.lock.lock().unwrap(),
|
||||
};
|
||||
assert!(set_nonblocking(self.fd(), true).is_ok());
|
||||
set_nonblocking(self.fd(), true);
|
||||
ret
|
||||
}
|
||||
|
||||
|
|
@ -887,9 +887,7 @@ impl UdpSocket {
|
|||
storagep,
|
||||
&mut addrlen) as libc::c_int
|
||||
}));
|
||||
sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| {
|
||||
Ok((n as uint, addr))
|
||||
})
|
||||
Ok((n as uint, sockaddr_to_addr(&storage, addrlen as uint).unwrap()))
|
||||
}
|
||||
|
||||
pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
|
||||
|
|
@ -910,11 +908,8 @@ impl UdpSocket {
|
|||
};
|
||||
|
||||
let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite));
|
||||
if n != buf.len() {
|
||||
Err(short_write(n, "couldn't send entire packet at once"))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
assert!(n == buf.len(), "UDP packet not completely written.");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
|
||||
|
|
|
|||
|
|
@ -1202,11 +1202,11 @@ mod tests {
|
|||
string.code_points().map(|c| c.to_char()).collect::<Vec<_>>()
|
||||
}
|
||||
let mut string = Wtf8Buf::from_str("é ");
|
||||
assert_eq!(cp(&string), vec![Some('é'), Some(' ')]);
|
||||
assert_eq!(cp(&string), [Some('é'), Some(' ')]);
|
||||
string.push(c(0xD83D));
|
||||
assert_eq!(cp(&string), vec![Some('é'), Some(' '), None]);
|
||||
assert_eq!(cp(&string), [Some('é'), Some(' '), None]);
|
||||
string.push(c(0xDCA9));
|
||||
assert_eq!(cp(&string), vec![Some('é'), Some(' '), Some('💩')]);
|
||||
assert_eq!(cp(&string), [Some('é'), Some(' '), Some('💩')]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -84,8 +84,9 @@
|
|||
/// all unix platforms we support right now, so it at least gets the job done.
|
||||
|
||||
use prelude::v1::*;
|
||||
use os::unix::prelude::*;
|
||||
|
||||
use ffi::CStr;
|
||||
use ffi::{CStr, AsOsStr};
|
||||
use old_io::IoResult;
|
||||
use libc;
|
||||
use mem;
|
||||
|
|
@ -327,7 +328,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
|
|||
};
|
||||
let filename = match selfname {
|
||||
Some(path) => {
|
||||
let bytes = path.as_vec();
|
||||
let bytes = path.as_os_str().as_bytes();
|
||||
if bytes.len() < LAST_FILENAME.len() {
|
||||
let i = bytes.iter();
|
||||
for (slot, val) in LAST_FILENAME.iter_mut().zip(i) {
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use cell::UnsafeCell;
|
||||
use libc;
|
||||
use ptr;
|
||||
use std::option::Option::{Some, None};
|
||||
use sys::mutex::{self, Mutex};
|
||||
use sys::time;
|
||||
use sys::sync as ffi;
|
||||
|
|
@ -20,6 +21,9 @@ use num::{Int, NumCast};
|
|||
|
||||
pub struct Condvar { inner: UnsafeCell<ffi::pthread_cond_t> }
|
||||
|
||||
unsafe impl Send for Condvar {}
|
||||
unsafe impl Sync for Condvar {}
|
||||
|
||||
pub const CONDVAR_INIT: Condvar = Condvar {
|
||||
inner: UnsafeCell { value: ffi::PTHREAD_COND_INITIALIZER },
|
||||
};
|
||||
|
|
|
|||
|
|
@ -173,10 +173,13 @@ impl OsStrExt for OsStr {
|
|||
|
||||
// Unix-specific extensions to `Permissions`
|
||||
pub trait PermissionsExt {
|
||||
fn mode(&self) -> i32;
|
||||
fn set_mode(&mut self, mode: i32);
|
||||
}
|
||||
|
||||
impl PermissionsExt for Permissions {
|
||||
fn mode(&self) -> i32 { self.as_inner().mode() }
|
||||
|
||||
fn set_mode(&mut self, mode: i32) {
|
||||
*self = FromInner::from_inner(FromInner::from_inner(mode));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ impl FilePermissions {
|
|||
self.mode |= 0o222;
|
||||
}
|
||||
}
|
||||
pub fn mode(&self) -> i32 { self.mode as i32 }
|
||||
}
|
||||
|
||||
impl FromInner<i32> for FilePermissions {
|
||||
|
|
|
|||
|
|
@ -214,9 +214,9 @@ pub fn wouldblock() -> bool {
|
|||
err == libc::EWOULDBLOCK as i32 || err == libc::EAGAIN as i32
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
|
||||
pub fn set_nonblocking(fd: sock_t, nb: bool) {
|
||||
let set = nb as libc::c_int;
|
||||
mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
|
||||
mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) })).unwrap();
|
||||
}
|
||||
|
||||
// nothing needed on unix platforms
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use cell::UnsafeCell;
|
||||
use marker::Sync;
|
||||
use sys::sync as ffi;
|
||||
use sys_common::mutex;
|
||||
|
||||
|
|
@ -24,6 +25,7 @@ pub const MUTEX_INIT: Mutex = Mutex {
|
|||
inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER },
|
||||
};
|
||||
|
||||
unsafe impl Send for Mutex {}
|
||||
unsafe impl Sync for Mutex {}
|
||||
|
||||
impl Mutex {
|
||||
|
|
|
|||
|
|
@ -16,12 +16,13 @@ use os::unix::*;
|
|||
use error::Error as StdError;
|
||||
use ffi::{CString, CStr, OsString, OsStr, AsOsStr};
|
||||
use fmt;
|
||||
use io;
|
||||
use iter;
|
||||
use libc::{self, c_int, c_char, c_void};
|
||||
use mem;
|
||||
use io;
|
||||
use old_io::{IoResult, IoError, fs};
|
||||
use old_io::{IoError, IoResult};
|
||||
use ptr;
|
||||
use path::{self, PathBuf};
|
||||
use slice;
|
||||
use str;
|
||||
use sys::c;
|
||||
|
|
@ -32,6 +33,14 @@ use vec;
|
|||
const BUF_BYTES: usize = 2048;
|
||||
const TMPBUF_SZ: usize = 128;
|
||||
|
||||
fn bytes2path(b: &[u8]) -> PathBuf {
|
||||
PathBuf::new(<OsStr as OsStrExt>::from_bytes(b))
|
||||
}
|
||||
|
||||
fn os2path(os: OsString) -> PathBuf {
|
||||
bytes2path(os.as_bytes())
|
||||
}
|
||||
|
||||
/// Returns the platform-specific value of errno
|
||||
pub fn errno() -> i32 {
|
||||
#[cfg(any(target_os = "macos",
|
||||
|
|
@ -102,30 +111,30 @@ pub fn error_string(errno: i32) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn getcwd() -> IoResult<Path> {
|
||||
pub fn getcwd() -> io::Result<PathBuf> {
|
||||
let mut buf = [0 as c_char; BUF_BYTES];
|
||||
unsafe {
|
||||
if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
|
||||
Err(IoError::last_error())
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(Path::new(CStr::from_ptr(buf.as_ptr()).to_bytes()))
|
||||
Ok(bytes2path(CStr::from_ptr(buf.as_ptr()).to_bytes()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn chdir(p: &Path) -> IoResult<()> {
|
||||
let p = CString::new(p.as_vec()).unwrap();
|
||||
pub fn chdir(p: &path::Path) -> io::Result<()> {
|
||||
let p = try!(CString::new(p.as_os_str().as_bytes()));
|
||||
unsafe {
|
||||
match libc::chdir(p.as_ptr()) == (0 as c_int) {
|
||||
true => Ok(()),
|
||||
false => Err(IoError::last_error()),
|
||||
false => Err(io::Error::last_os_error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SplitPaths<'a> {
|
||||
iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>,
|
||||
fn(&'a [u8]) -> Path>,
|
||||
fn(&'a [u8]) -> PathBuf>,
|
||||
}
|
||||
|
||||
pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> {
|
||||
|
|
@ -133,13 +142,13 @@ pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> {
|
|||
let unparsed = unparsed.as_bytes();
|
||||
SplitPaths {
|
||||
iter: unparsed.split(is_colon as fn(&u8) -> bool)
|
||||
.map(Path::new as fn(&'a [u8]) -> Path)
|
||||
.map(bytes2path as fn(&'a [u8]) -> PathBuf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for SplitPaths<'a> {
|
||||
type Item = Path;
|
||||
fn next(&mut self) -> Option<Path> { self.iter.next() }
|
||||
type Item = PathBuf;
|
||||
fn next(&mut self) -> Option<PathBuf> { self.iter.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
|
|
@ -174,7 +183,7 @@ impl StdError for JoinPathsError {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
unsafe {
|
||||
use libc::funcs::bsd44::*;
|
||||
use libc::consts::os::extra::*;
|
||||
|
|
@ -186,26 +195,26 @@ pub fn current_exe() -> IoResult<Path> {
|
|||
let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
|
||||
ptr::null_mut(), &mut sz, ptr::null_mut(),
|
||||
0 as libc::size_t);
|
||||
if err != 0 { return Err(IoError::last_error()); }
|
||||
if sz == 0 { return Err(IoError::last_error()); }
|
||||
if err != 0 { return Err(io::Error::last_os_error()); }
|
||||
if sz == 0 { return Err(io::Error::last_os_error()); }
|
||||
let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
|
||||
let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
|
||||
v.as_mut_ptr() as *mut libc::c_void, &mut sz,
|
||||
ptr::null_mut(), 0 as libc::size_t);
|
||||
if err != 0 { return Err(IoError::last_error()); }
|
||||
if sz == 0 { return Err(IoError::last_error()); }
|
||||
if err != 0 { return Err(io::Error::last_os_error()); }
|
||||
if sz == 0 { return Err(io::Error::last_os_error()); }
|
||||
v.set_len(sz as uint - 1); // chop off trailing NUL
|
||||
Ok(Path::new(v))
|
||||
Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(v)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
fs::readlink(&Path::new("/proc/curproc/file"))
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
::fs::read_link("/proc/curproc/file")
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
use sync::{StaticMutex, MUTEX_INIT};
|
||||
static LOCK: StaticMutex = MUTEX_INIT;
|
||||
|
||||
|
|
@ -218,7 +227,7 @@ pub fn current_exe() -> IoResult<Path> {
|
|||
unsafe {
|
||||
let v = rust_current_exe();
|
||||
if v.is_null() {
|
||||
Err(IoError::last_error())
|
||||
Err(io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(Path::new(CStr::from_ptr(v).to_bytes().to_vec()))
|
||||
}
|
||||
|
|
@ -226,22 +235,22 @@ pub fn current_exe() -> IoResult<Path> {
|
|||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
fs::readlink(&Path::new("/proc/self/exe"))
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
::fs::read_link("/proc/self/exe")
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
pub fn current_exe() -> IoResult<Path> {
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
unsafe {
|
||||
use libc::funcs::extra::_NSGetExecutablePath;
|
||||
let mut sz: u32 = 0;
|
||||
_NSGetExecutablePath(ptr::null_mut(), &mut sz);
|
||||
if sz == 0 { return Err(IoError::last_error()); }
|
||||
if sz == 0 { return Err(io::Error::last_os_error()); }
|
||||
let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
|
||||
let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
|
||||
if err != 0 { return Err(IoError::last_error()); }
|
||||
if err != 0 { return Err(io::Error::last_os_error()); }
|
||||
v.set_len(sz as uint - 1); // chop off trailing NUL
|
||||
Ok(Path::new(v))
|
||||
Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(v)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -451,22 +460,20 @@ pub fn page_size() -> usize {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> Path {
|
||||
getenv("TMPDIR".as_os_str()).map(|p| Path::new(p.into_vec())).unwrap_or_else(|| {
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
getenv("TMPDIR".as_os_str()).map(os2path).unwrap_or_else(|| {
|
||||
if cfg!(target_os = "android") {
|
||||
Path::new("/data/local/tmp")
|
||||
PathBuf::new("/data/local/tmp")
|
||||
} else {
|
||||
Path::new("/tmp")
|
||||
PathBuf::new("/tmp")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn home_dir() -> Option<Path> {
|
||||
pub fn home_dir() -> Option<PathBuf> {
|
||||
return getenv("HOME".as_os_str()).or_else(|| unsafe {
|
||||
fallback()
|
||||
}).map(|os| {
|
||||
Path::new(os.into_vec())
|
||||
});
|
||||
}).map(os2path);
|
||||
|
||||
#[cfg(any(target_os = "android",
|
||||
target_os = "ios"))]
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ impl UnixStream {
|
|||
fd: self.fd(),
|
||||
guard: unsafe { self.inner.lock.lock().unwrap() },
|
||||
};
|
||||
assert!(set_nonblocking(self.fd(), true).is_ok());
|
||||
set_nonblocking(self.fd(), true);
|
||||
ret
|
||||
}
|
||||
|
||||
|
|
@ -235,9 +235,9 @@ impl UnixListener {
|
|||
|
||||
_ => {
|
||||
let (reader, writer) = try!(unsafe { sys::os::pipe() });
|
||||
try!(set_nonblocking(reader.fd(), true));
|
||||
try!(set_nonblocking(writer.fd(), true));
|
||||
try!(set_nonblocking(self.fd(), true));
|
||||
set_nonblocking(reader.fd(), true);
|
||||
set_nonblocking(writer.fd(), true);
|
||||
set_nonblocking(self.fd(), true);
|
||||
Ok(UnixAcceptor {
|
||||
inner: Arc::new(AcceptorInner {
|
||||
listener: self,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ impl Process {
|
|||
K: BytesContainer + Eq + Hash, V: BytesContainer
|
||||
{
|
||||
use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
|
||||
use libc::funcs::bsd44::getdtablesize;
|
||||
|
||||
mod rustrt {
|
||||
extern {
|
||||
|
|
@ -82,6 +81,15 @@ impl Process {
|
|||
assert_eq!(ret, 0);
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
|
||||
unsafe fn getdtablesize() -> c_int {
|
||||
libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int
|
||||
}
|
||||
#[cfg(not(all(target_os = "android", target_arch = "aarch64")))]
|
||||
unsafe fn getdtablesize() -> c_int {
|
||||
libc::funcs::bsd44::getdtablesize()
|
||||
}
|
||||
|
||||
let dirp = cfg.cwd().map(|c| c.as_ptr()).unwrap_or(ptr::null());
|
||||
|
||||
// temporary until unboxed closures land
|
||||
|
|
@ -345,8 +353,8 @@ impl Process {
|
|||
unsafe {
|
||||
let mut pipes = [0; 2];
|
||||
assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0);
|
||||
set_nonblocking(pipes[0], true).ok().unwrap();
|
||||
set_nonblocking(pipes[1], true).ok().unwrap();
|
||||
set_nonblocking(pipes[0], true);
|
||||
set_nonblocking(pipes[1], true);
|
||||
WRITE_FD = pipes[1];
|
||||
|
||||
let mut old: c::sigaction = mem::zeroed();
|
||||
|
|
@ -362,7 +370,7 @@ impl Process {
|
|||
fn waitpid_helper(input: libc::c_int,
|
||||
messages: Receiver<Req>,
|
||||
(read_fd, old): (libc::c_int, c::sigaction)) {
|
||||
set_nonblocking(input, true).ok().unwrap();
|
||||
set_nonblocking(input, true);
|
||||
let mut set: c::fd_set = unsafe { mem::zeroed() };
|
||||
let mut tv: libc::timeval;
|
||||
let mut active = Vec::<(libc::pid_t, Sender<ProcessExit>, u64)>::new();
|
||||
|
|
|
|||
|
|
@ -141,7 +141,6 @@ impl Process {
|
|||
-> io::Result<Process>
|
||||
{
|
||||
use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
|
||||
use libc::funcs::bsd44::getdtablesize;
|
||||
|
||||
mod rustrt {
|
||||
extern {
|
||||
|
|
@ -154,6 +153,16 @@ impl Process {
|
|||
assert_eq!(ret, 0);
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
|
||||
unsafe fn getdtablesize() -> c_int {
|
||||
libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int
|
||||
}
|
||||
|
||||
#[cfg(not(all(target_os = "android", target_arch = "aarch64")))]
|
||||
unsafe fn getdtablesize() -> c_int {
|
||||
libc::funcs::bsd44::getdtablesize()
|
||||
}
|
||||
|
||||
let dirp = cfg.cwd.as_ref().map(|c| c.as_ptr()).unwrap_or(ptr::null());
|
||||
|
||||
with_envp(cfg.env.as_ref(), |envp: *const c_void| {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use cell::UnsafeCell;
|
||||
use sys::sync as ffi;
|
||||
|
||||
|
|
@ -17,6 +19,9 @@ pub const RWLOCK_INIT: RWLock = RWLock {
|
|||
inner: UnsafeCell { value: ffi::PTHREAD_RWLOCK_INITIALIZER },
|
||||
};
|
||||
|
||||
unsafe impl Send for RWLock {}
|
||||
unsafe impl Sync for RWLock {}
|
||||
|
||||
impl RWLock {
|
||||
#[inline]
|
||||
pub unsafe fn new() -> RWLock {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue