Auto merge of #24674 - alexcrichton:rollup, r=alexcrichton

This commit is contained in:
bors 2015-04-22 03:38:20 +00:00
commit c0eb9384af
315 changed files with 2569 additions and 8304 deletions

View File

@ -13,12 +13,12 @@
######################################################################
# The version number
CFG_RELEASE_NUM=1.0.0
CFG_RELEASE_NUM=1.1.0
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
# NB Make sure it starts with a dot to conform to semver pre-release
# versions (section 9)
CFG_PRERELEASE_VERSION=.3
CFG_PRERELEASE_VERSION=.1
CFG_FILENAME_EXTRA=4e7c5e5c

View File

@ -24,6 +24,7 @@ is the first. After this:
* [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks.
* [Nightly Rust][nr] - Cutting-edge features that arent in stable builds yet.
* [Glossary][gl] - A reference of terms used in the book.
* [Academic Research][ar] - Literature that influenced Rust.
[gs]: getting-started.html
[lr]: learn-rust.html
@ -31,6 +32,7 @@ is the first. After this:
[ss]: syntax-and-semantics.html
[nr]: nightly-rust.html
[gl]: glossary.html
[ar]: academic-research.html
After reading this introduction, youll want to dive into either Learn Rust
or Syntax and Semantics, depending on your preference: Learn Rust if you

View File

@ -55,6 +55,7 @@
* [Deref coercions](deref-coercions.md)
* [Macros](macros.md)
* [Raw Pointers](raw-pointers.md)
* [`unsafe`](unsafe.md)
* [Nightly Rust](nightly-rust.md)
* [Compiler Plugins](compiler-plugins.md)
* [Inline Assembly](inline-assembly.md)

View File

@ -1,8 +1,8 @@
% Associated Types
Associated types are a powerful part of Rust's type system. They're related to
the idea of a 'type family', in other words, grouping multiple types together. That
description is a bit abstract, so let's dive right into an example. If you want
Associated types are a powerful part of Rusts type system. Theyre related to
the idea of a type family, in other words, grouping multiple types together. That
description is a bit abstract, so lets dive right into an example. If you want
to write a `Graph` trait, you have two types to be generic over: the node type
and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
this:
@ -48,11 +48,11 @@ fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> uint { ... }
No need to deal with the `E`dge type here!
Let's go over all this in more detail.
Lets go over all this in more detail.
## Defining associated types
Let's build that `Graph` trait. Here's the definition:
Lets build that `Graph` trait. Heres the definition:
```rust
trait Graph {
@ -86,7 +86,7 @@ trait Graph {
## Implementing associated types
Just like any trait, traits that use associated types use the `impl` keyword to
provide implementations. Here's a simple implementation of Graph:
provide implementations. Heres a simple implementation of Graph:
```rust
# trait Graph {
@ -118,13 +118,13 @@ impl Graph for MyGraph {
This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
gives you an idea of how to implement this kind of thing. We first need three
`struct`s, one for the graph, one for the node, and one for the edge. If it made
more sense to use a different type, that would work as well, we're just going to
more sense to use a different type, that would work as well, were just going to
use `struct`s for all three here.
Next is the `impl` line, which is just like implementing any other trait.
From here, we use `=` to define our associated types. The name the trait uses
goes on the left of the `=`, and the concrete type we're `impl`ementing this
goes on the left of the `=`, and the concrete type were `impl`ementing this
for goes on the right. Finally, we use the concrete types in our function
declarations.

View File

@ -33,7 +33,7 @@ let b = a as u32; // four eights makes 32
Its a non-scalar cast because we have multiple values here: the four
elements of the array. These kinds of casts are very dangerous, because they
make assumptions about the way that multiple underlying strucutres are
make assumptions about the way that multiple underlying structures are
implemented. For this, we need something more dangerous.
# `transmute`
@ -59,7 +59,7 @@ unsafe {
}
```
We have to wrap the operation in an `unsafe` block, but this will compile
We have to wrap the operation in an `unsafe` block for this to compile
successfully. Technically, only the `mem::transmute` call itself needs to be in
the block, but it's nice in this case to enclose everything related, so you
know where to look. In this case, the details about `a` are also important, and

View File

@ -1,9 +1,9 @@
% Closures
Rust not only has named functions, but anonymous functions as well. Anonymous
functions that have an associated environment are called 'closures', because they
functions that have an associated environment are called closures, because they
close over an environment. Rust has a really great implementation of them, as
we'll see.
well see.
# Syntax
@ -15,7 +15,7 @@ let plus_one = |x: i32| x + 1;
assert_eq!(2, plus_one(1));
```
We create a binding, `plus_one`, and assign it to a closure. The closure's
We create a binding, `plus_one`, and assign it to a closure. The closures
arguments go between the pipes (`|`), and the body is an expression, in this
case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line
closures too:
@ -33,7 +33,7 @@ let plus_two = |x| {
assert_eq!(4, plus_two(2));
```
You'll notice a few things about closures that are a bit different than regular
Youll notice a few things about closures that are a bit different than regular
functions defined with `fn`. The first of which is that we did not need to
annotate the types of arguments the closure takes or the values it returns. We
can:
@ -44,13 +44,13 @@ let plus_one = |x: i32| -> i32 { x + 1 };
assert_eq!(2, plus_one(1));
```
But we don't have to. Why is this? Basically, it was chosen for ergonomic reasons.
But we dont have to. Why is this? Basically, it was chosen for ergonomic reasons.
While specifying the full type for named functions is helpful with things like
documentation and type inference, the types of closures are rarely documented
since theyre anonymous, and they dont cause the kinds of error-at-a-distance
that inferring named function types can.
The second is that the syntax is similar, but a bit different. I've added spaces
The second is that the syntax is similar, but a bit different. Ive added spaces
here to make them look a little closer:
```rust
@ -59,11 +59,11 @@ let plus_one_v2 = |x: i32 | -> i32 { x + 1 };
let plus_one_v3 = |x: i32 | x + 1 ;
```
Small differences, but they're similar in ways.
Small differences, but theyre similar in ways.
# Closures and their environment
Closures are called such because they 'close over their environment.' It
Closures are called such because they close over their environment. It
looks like this:
```rust
@ -105,7 +105,7 @@ fn main() {
^
```
A verbose yet helpful error message! As it says, we can't take a mutable borrow
A verbose yet helpful error message! As it says, we cant take a mutable borrow
on `num` because the closure is already borrowing it. If we let the closure go
out of scope, we can:
@ -140,7 +140,7 @@ let takes_nums = || nums;
```
`Vec<T>` has ownership over its contents, and therefore, when we refer to it
in our closure, we have to take ownership of `nums`. It's the same as if we'd
in our closure, we have to take ownership of `nums`. Its the same as if wed
passed `nums` to a function that took ownership of it.
## `move` closures
@ -156,7 +156,7 @@ let owns_num = move |x: i32| x + num;
Now, even though the keyword is `move`, the variables follow normal move semantics.
In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy
of `num`. So what's the difference?
of `num`. So whats the difference?
```rust
let mut num = 5;
@ -171,11 +171,11 @@ assert_eq!(10, num);
```
So in this case, our closure took a mutable reference to `num`, and then when
we called `add_num`, it mutated the underlying value, as we'd expect. We also
we called `add_num`, it mutated the underlying value, as wed expect. We also
needed to declare `add_num` as `mut` too, because were mutating its
environment.
If we change to a `move` closure, it's different:
If we change to a `move` closure, its different:
```rust
let mut num = 5;
@ -203,8 +203,8 @@ you tons of control over what your code does, and closures are no different.
# Closure implementation
Rust's implementation of closures is a bit different than other languages. They
are effectively syntax sugar for traits. You'll want to make sure to have read
Rusts implementation of closures is a bit different than other languages. They
are effectively syntax sugar for traits. Youll want to make sure to have read
the [traits chapter][traits] before this one, as well as the chapter on [trait
objects][trait-objects].
@ -237,9 +237,9 @@ pub trait FnOnce<Args> {
# }
```
You'll notice a few differences between these traits, but a big one is `self`:
Youll notice a few differences between these traits, but a big one is `self`:
`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This
covers all three kinds of `self` via the usual method call syntax. But we've
covers all three kinds of `self` via the usual method call syntax. But weve
split them up into three traits, rather than having a single one. This gives us
a large amount of control over what kind of closures we can take.
@ -253,7 +253,7 @@ Now that we know that closures are traits, we already know how to accept and
return closures: just like any other trait!
This also means that we can choose static vs dynamic dispatch as well. First,
let's write a function which takes something callable, calls it, and returns
lets write a function which takes something callable, calls it, and returns
the result:
```rust
@ -271,7 +271,7 @@ assert_eq!(3, answer);
We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it
suggests: it calls the closure, giving it `1` as an argument.
Let's examine the signature of `call_with_one` in more depth:
Lets examine the signature of `call_with_one` in more depth:
```rust
fn call_with_one<F>(some_closure: F) -> i32
@ -280,7 +280,7 @@ fn call_with_one<F>(some_closure: F) -> i32
```
We take one parameter, and it has the type `F`. We also return a `i32`. This part
isn't interesting. The next part is:
isnt interesting. The next part is:
```rust
# fn call_with_one<F>(some_closure: F) -> i32
@ -292,9 +292,9 @@ Because `Fn` is a trait, we can bound our generic with it. In this case, our clo
takes a `i32` as an argument and returns an `i32`, and so the generic bound we use
is `Fn(i32) -> i32`.
There's one other key point here: because we're bounding a generic with a
trait, this will get monomorphized, and therefore, we'll be doing static
dispatch into the closure. That's pretty neat. In many langauges, closures are
Theres one other key point here: because were bounding a generic with a
trait, this will get monomorphized, and therefore, well be doing static
dispatch into the closure. Thats pretty neat. In many langauges, closures are
inherently heap allocated, and will always involve dynamic dispatch. In Rust,
we can stack allocate our closure environment, and statically dispatch the
call. This happens quite often with iterators and their adapters, which often
@ -320,7 +320,7 @@ to our closure when we pass it to `call_with_one`, so we use `&||`.
Its very common for functional-style code to return closures in various
situations. If you try to return a closure, you may run into an error. At
first, it may seem strange, but we'll figure it out. Here's how you'd probably
first, it may seem strange, but well figure it out. Heres how youd probably
try to return a closure from a function:
```rust,ignore
@ -361,7 +361,7 @@ In order to return something from a function, Rust needs to know what
size the return type is. But since `Fn` is a trait, it could be various
things of various sizes: many different types can implement `Fn`. An easy
way to give something a size is to take a reference to it, as references
have a known size. So we'd write this:
have a known size. So wed write this:
```rust,ignore
fn factory() -> &(Fn(i32) -> Vec<i32>) {
@ -385,7 +385,7 @@ fn factory() -> &(Fn(i32) -> i32) {
```
Right. Because we have a reference, we need to give it a lifetime. But
our `factory()` function takes no arguments, so elision doesn't kick in
our `factory()` function takes no arguments, so elision doesnt kick in
here. What lifetime can we choose? `'static`:
```rust,ignore
@ -414,7 +414,7 @@ error: mismatched types:
```
This error is letting us know that we don't have a `&'static Fn(i32) -> i32`,
This error is letting us know that we dont have a `&'static Fn(i32) -> i32`,
we have a `[closure <anon>:7:9: 7:20]`. Wait, what?
Because each closure generates its own environment `struct` and implementation
@ -422,7 +422,7 @@ of `Fn` and friends, these types are anonymous. They exist just solely for
this closure. So Rust shows them as `closure <anon>`, rather than some
autogenerated name.
But why doesn't our closure implement `&'static Fn`? Well, as we discussed before,
But why doesnt our closure implement `&'static Fn`? Well, as we discussed before,
closures borrow their environment. And in this case, our environment is based
on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime
of the stack frame. So if we returned this closure, the function call would be
@ -445,7 +445,7 @@ assert_eq!(6, answer);
# }
```
We use a trait object, by `Box`ing up the `Fn`. There's just one last problem:
We use a trait object, by `Box`ing up the `Fn`. Theres just one last problem:
```text
error: `num` does not live long enough
@ -471,5 +471,5 @@ assert_eq!(6, answer);
```
By making the inner closure a `move Fn`, we create a new stack frame for our
closure. By `Box`ing it up, we've given it a known size, and allowing it to
closure. By `Box`ing it up, weve given it a known size, and allowing it to
escape our stack frame.

View File

@ -1,16 +1,16 @@
% Crates and Modules
When a project starts getting large, it's considered good software
When a project starts getting large, its considered good software
engineering practice to split it up into a bunch of smaller pieces, and then
fit them together. It's also important to have a well-defined interface, so
fit them together. Its also important to have a well-defined interface, so
that some of your functionality is private, and some is public. To facilitate
these kinds of things, Rust has a module system.
# Basic terminology: Crates and Modules
Rust has two distinct terms that relate to the module system: *crate* and
*module*. A crate is synonymous with a *library* or *package* in other
languages. Hence "Cargo" as the name of Rust's package management tool: you
Rust has two distinct terms that relate to the module system: crate and
module. A crate is synonymous with a library or package in other
languages. Hence “Cargo” as the name of Rusts package management tool: you
ship your crates to others with Cargo. Crates can produce an executable or a
library, depending on the project.
@ -18,10 +18,10 @@ Each crate has an implicit *root module* that contains the code for that crate.
You can then define a tree of sub-modules under that root module. Modules allow
you to partition your code within the crate itself.
As an example, let's make a *phrases* crate, which will give us various phrases
in different languages. To keep things simple, we'll stick to "greetings" and
"farewells" as two kinds of phrases, and use English and Japanese (日本語) as
two languages for those phrases to be in. We'll use this module layout:
As an example, lets make a *phrases* crate, which will give us various phrases
in different languages. To keep things simple, well stick to greetings and
farewells as two kinds of phrases, and use English and Japanese (日本語) as
two languages for those phrases to be in. Well use this module layout:
```text
+-----------+
@ -47,7 +47,7 @@ In this example, `phrases` is the name of our crate. All of the rest are
modules. You can see that they form a tree, branching out from the crate
*root*, which is the root of the tree: `phrases` itself.
Now that we have a plan, let's define these modules in code. To start,
Now that we have a plan, lets define these modules in code. To start,
generate a new crate with Cargo:
```bash
@ -72,7 +72,7 @@ above.
# Defining Modules
To define each of our modules, we use the `mod` keyword. Let's make our
To define each of our modules, we use the `mod` keyword. Lets make our
`src/lib.rs` look like this:
```
@ -101,7 +101,7 @@ Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules
with double-colon (`::`) notation: our four nested modules are
`english::greetings`, `english::farewells`, `japanese::greetings`, and
`japanese::farewells`. Because these sub-modules are namespaced under their
parent module, the names don't conflict: `english::greetings` and
parent module, the names dont conflict: `english::greetings` and
`japanese::greetings` are distinct, even though their names are both
`greetings`.
@ -116,11 +116,11 @@ build deps examples libphrases-a7448e02a0468eaa.rlib native
```
`libphrase-hash.rlib` is the compiled crate. Before we see how to use this
crate from another crate, let's break it up into multiple files.
crate from another crate, lets break it up into multiple files.
# Multiple file crates
If each crate were just one file, these files would get very large. It's often
If each crate were just one file, these files would get very large. Its often
easier to split up crates into multiple files, and Rust supports this in two
ways.
@ -141,7 +141,7 @@ mod english;
If we do that, Rust will expect to find either a `english.rs` file, or a
`english/mod.rs` file with the contents of our module.
Note that in these files, you don't need to re-declare the module: that's
Note that in these files, you dont need to re-declare the module: thats
already been done with the initial `mod` declaration.
Using these two techniques, we can break up our crate into two directories and
@ -180,7 +180,7 @@ mod japanese;
These two declarations tell Rust to look for either `src/english.rs` and
`src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending
on our preference. In this case, because our modules have sub-modules, we've
on our preference. In this case, because our modules have sub-modules, weve
chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
like this:
@ -192,11 +192,11 @@ mod farewells;
Again, these declarations tell Rust to look for either
`src/english/greetings.rs` and `src/japanese/greetings.rs` or
`src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because
these sub-modules don't have their own sub-modules, we've chosen to make them
these sub-modules dont have their own sub-modules, weve chosen to make them
`src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew!
The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are
both empty at the moment. Let's add some functions.
both empty at the moment. Lets add some functions.
Put this in `src/english/greetings.rs`:
@ -223,7 +223,7 @@ fn hello() -> String {
```
Of course, you can copy and paste this from this web page, or just type
something else. It's not important that you actually put "konnichiwa" to learn
something else. Its not important that you actually put konnichiwa to learn
about the module system.
Put this in `src/japanese/farewells.rs`:
@ -234,17 +234,17 @@ fn goodbye() -> String {
}
```
(This is "Sayōnara", if you're curious.)
(This is Sayōnara, if youre curious.)
Now that we have some functionality in our crate, let's try to use it from
Now that we have some functionality in our crate, lets try to use it from
another crate.
# Importing External Crates
We have a library crate. Let's make an executable crate that imports and uses
We have a library crate. Lets make an executable crate that imports and uses
our library.
Make a `src/main.rs` and put this in it (it won't quite compile yet):
Make a `src/main.rs` and put this in it (it wont quite compile yet):
```rust,ignore
extern crate phrases;
@ -259,7 +259,7 @@ fn main() {
```
The `extern crate` declaration tells Rust that we need to compile and link to
the `phrases` crate. We can then use `phrases`' modules in this one. As we
the `phrases` crate. We can then use `phrases` modules in this one. As we
mentioned earlier, you can use double colons to refer to sub-modules and the
functions inside of them.
@ -267,10 +267,10 @@ Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate,
rather than a library crate. Our package now has two crates: `src/lib.rs` and
`src/main.rs`. This pattern is quite common for executable crates: most
functionality is in a library crate, and the executable crate uses that
library. This way, other programs can also use the library crate, and it's also
library. This way, other programs can also use the library crate, and its also
a nice separation of concerns.
This doesn't quite work yet, though. We get four errors that look similar to
This doesnt quite work yet, though. We get four errors that look similar to
this:
```bash
@ -287,14 +287,14 @@ note: in expansion of format_args!
phrases/src/main.rs:4:5: 4:76 note: expansion site
```
By default, everything is private in Rust. Let's talk about this in some more
By default, everything is private in Rust. Lets talk about this in some more
depth.
# Exporting a Public Interface
Rust allows you to precisely control which aspects of your interface are
public, and so private is the default. To make things public, you use the `pub`
keyword. Let's focus on the `english` module first, so let's reduce our `src/main.rs`
keyword. Lets focus on the `english` module first, so lets reduce our `src/main.rs`
to just this:
```{rust,ignore}
@ -306,21 +306,21 @@ fn main() {
}
```
In our `src/lib.rs`, let's add `pub` to the `english` module declaration:
In our `src/lib.rs`, lets add `pub` to the `english` module declaration:
```{rust,ignore}
pub mod english;
mod japanese;
```
And in our `src/english/mod.rs`, let's make both `pub`:
And in our `src/english/mod.rs`, lets make both `pub`:
```{rust,ignore}
pub mod greetings;
pub mod farewells;
```
In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration:
In our `src/english/greetings.rs`, lets add `pub` to our `fn` declaration:
```{rust,ignore}
pub fn hello() -> String {
@ -358,12 +358,12 @@ Goodbye in English: Goodbye.
Now that our functions are public, we can use them. Great! However, typing out
`phrases::english::greetings::hello()` is very long and repetitive. Rust has
another keyword for importing names into the current scope, so that you can
refer to them with shorter names. Let's talk about `use`.
refer to them with shorter names. Lets talk about `use`.
# Importing Modules with `use`
Rust has a `use` keyword, which allows us to import names into our local scope.
Let's change our `src/main.rs` to look like this:
Lets change our `src/main.rs` to look like this:
```{rust,ignore}
extern crate phrases;
@ -378,7 +378,7 @@ fn main() {
```
The two `use` lines import each module into the local scope, so we can refer to
the functions by a much shorter name. By convention, when importing functions, it's
the functions by a much shorter name. By convention, when importing functions, its
considered best practice to import the module, rather than the function directly. In
other words, you _can_ do this:
@ -395,7 +395,7 @@ fn main() {
```
But it is not idiomatic. This is significantly more likely to introduce a
naming conflict. In our short program, it's not a big deal, but as it grows, it
naming conflict. In our short program, its not a big deal, but as it grows, it
becomes a problem. If we have conflicting names, Rust will give a compilation
error. For example, if we made the `japanese` functions public, and tried to do
this:
@ -423,7 +423,7 @@ error: aborting due to previous error
Could not compile `phrases`.
```
If we're importing multiple names from the same module, we don't have to type it out
If were importing multiple names from the same module, we dont have to type it out
twice. Instead of this:
```{rust,ignore}
@ -439,11 +439,11 @@ use phrases::english::{greetings, farewells};
## Re-exporting with `pub use`
You don't just use `use` to shorten identifiers. You can also use it inside of your crate
You dont just use `use` to shorten identifiers. You can also use it inside of your crate
to re-export a function inside another module. This allows you to present an external
interface that may not directly map to your internal code organization.
Let's look at an example. Modify your `src/main.rs` to read like this:
Lets look at an example. Modify your `src/main.rs` to read like this:
```{rust,ignore}
extern crate phrases;
@ -494,11 +494,11 @@ mod farewells;
```
The `pub use` declaration brings the function into scope at this part of our
module hierarchy. Because we've `pub use`d this inside of our `japanese`
module hierarchy. Because weve `pub use`d this inside of our `japanese`
module, we now have a `phrases::japanese::hello()` function and a
`phrases::japanese::goodbye()` function, even though the code for them lives in
`phrases::japanese::greetings::hello()` and
`phrases::japanese::farewells::goodbye()`. Our internal organization doesn't
`phrases::japanese::farewells::goodbye()`. Our internal organization doesnt
define our external interface.
Here we have a `pub use` for each function we want to bring into the
@ -507,13 +507,13 @@ everything from `greetings` into the current scope: `pub use self::greetings::*`
What about the `self`? Well, by default, `use` declarations are absolute paths,
starting from your crate root. `self` makes that path relative to your current
place in the hierarchy instead. There's one more special form of `use`: you can
place in the hierarchy instead. Theres one more special form of `use`: you can
`use super::` to reach one level up the tree from your current location. Some
people like to think of `self` as `.` and `super` as `..`, from many shells'
people like to think of `self` as `.` and `super` as `..`, from many shells
display for the current directory and the parent directory.
Outside of `use`, paths are relative: `foo::bar()` refers to a function inside
of `foo` relative to where we are. If that's prefixed with `::`, as in
of `foo` relative to where we are. If thats prefixed with `::`, as in
`::foo::bar()`, it refers to a different `foo`, an absolute path from your
crate root.

View File

@ -1,20 +1,20 @@
% Macros
By now you've learned about many of the tools Rust provides for abstracting and
By now youve learned about many of the tools Rust provides for abstracting and
reusing code. These units of code reuse have a rich semantic structure. For
example, functions have a type signature, type parameters have trait bounds,
and overloaded functions must belong to a particular trait.
This structure means that Rust's core abstractions have powerful compile-time
This structure means that Rusts core abstractions have powerful compile-time
correctness checking. But this comes at the price of reduced flexibility. If
you visually identify a pattern of repeated code, you may find it's difficult
you visually identify a pattern of repeated code, you may find its difficult
or cumbersome to express that pattern as a generic function, a trait, or
anything else within Rust's semantics.
anything else within Rusts semantics.
Macros allow us to abstract at a *syntactic* level. A macro invocation is
Macros allow us to abstract at a syntactic level. A macro invocation is
shorthand for an "expanded" syntactic form. This expansion happens early in
compilation, before any static checking. As a result, macros can capture many
patterns of code reuse that Rust's core abstractions cannot.
patterns of code reuse that Rusts core abstractions cannot.
The drawback is that macro-based code can be harder to understand, because
fewer of the built-in rules apply. Like an ordinary function, a well-behaved
@ -23,8 +23,8 @@ difficult to design a well-behaved macro! Additionally, compiler errors in
macro code are harder to interpret, because they describe problems in the
expanded code, not the source-level form that developers use.
These drawbacks make macros something of a "feature of last resort". That's not
to say that macros are bad; they are part of Rust because sometimes they're
These drawbacks make macros something of a "feature of last resort". Thats not
to say that macros are bad; they are part of Rust because sometimes theyre
needed for truly concise, well-abstracted code. Just keep this tradeoff in
mind.
@ -40,7 +40,7 @@ let x: Vec<u32> = vec![1, 2, 3];
# assert_eq!(x, [1, 2, 3]);
```
This can't be an ordinary function, because it takes any number of arguments.
This cant be an ordinary function, because it takes any number of arguments.
But we can imagine it as syntactic shorthand for
```rust
@ -77,20 +77,20 @@ macro_rules! vec {
# }
```
Whoa, that's a lot of new syntax! Let's break it down.
Whoa, thats a lot of new syntax! Lets break it down.
```ignore
macro_rules! vec { ... }
```
This says we're defining a macro named `vec`, much as `fn vec` would define a
function named `vec`. In prose, we informally write a macro's name with an
This says were defining a macro named `vec`, much as `fn vec` would define a
function named `vec`. In prose, we informally write a macros name with an
exclamation point, e.g. `vec!`. The exclamation point is part of the invocation
syntax and serves to distinguish a macro from an ordinary function.
## Matching
The macro is defined through a series of *rules*, which are pattern-matching
The macro is defined through a series of rules, which are pattern-matching
cases. Above, we had
```ignore
@ -99,13 +99,13 @@ cases. Above, we had
This is like a `match` expression arm, but the matching happens on Rust syntax
trees, at compile time. The semicolon is optional on the last (here, only)
case. The "pattern" on the left-hand side of `=>` is known as a *matcher*.
case. The "pattern" on the left-hand side of `=>` is known as a matcher.
These have [their own little grammar] within the language.
[their own little grammar]: ../reference.html#macros
The matcher `$x:expr` will match any Rust expression, binding that syntax tree
to the *metavariable* `$x`. The identifier `expr` is a *fragment specifier*;
to the metavariable `$x`. The identifier `expr` is a fragment specifier;
the full possibilities are enumerated in the [advanced macros chapter][].
Surrounding the matcher with `$(...),*` will match zero or more expressions,
separated by commas.
@ -158,8 +158,8 @@ Each matched expression `$x` will produce a single `push` statement in the
macro expansion. The repetition in the expansion proceeds in "lockstep" with
repetition in the matcher (more on this in a moment).
Because `$x` was already declared as matching an expression, we don't repeat
`:expr` on the right-hand side. Also, we don't include a separating comma as
Because `$x` was already declared as matching an expression, we dont repeat
`:expr` on the right-hand side. Also, we dont include a separating comma as
part of the repetition operator. Instead, we have a terminating semicolon
within the repeated block.
@ -180,7 +180,7 @@ The outer braces are part of the syntax of `macro_rules!`. In fact, you can use
The inner braces are part of the expanded syntax. Remember, the `vec!` macro is
used in an expression context. To write an expression with multiple statements,
including `let`-bindings, we use a block. If your macro expands to a single
expression, you don't need this extra layer of braces.
expression, you dont need this extra layer of braces.
Note that we never *declared* that the macro produces an expression. In fact,
this is not determined until we use the macro as an expression. With care, you
@ -194,7 +194,7 @@ The repetition operator follows two principal rules:
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, itll be duplicated, as appropriate.
This baroque macro illustrates the duplication of variables from outer
repetition levels.
@ -219,7 +219,7 @@ fn main() {
}
```
That's most of the matcher syntax. These examples use `$(...)*`, which is a
Thats most of the matcher syntax. These examples use `$(...)*`, which is a
"zero or more" match. Alternatively you can write `$(...)+` for a "one or
more" match. Both forms optionally include a separator, which can be any token
except `+` or `*`.
@ -244,9 +244,9 @@ int main() {
```
After expansion we have `5 * 2 + 3`, and multiplication has greater precedence
than addition. If you've used C macros a lot, you probably know the standard
than addition. If youve used C macros a lot, you probably know the standard
idioms for avoiding this problem, as well as five or six others. In Rust, we
don't have to worry about it.
dont have to worry about it.
```rust
macro_rules! five_times {
@ -261,8 +261,8 @@ fn main() {
The metavariable `$x` is parsed as a single expression node, and keeps its
place in the syntax tree even after substitution.
Another common problem in macro systems is *variable capture*. Here's a C
macro, using [a GNU C extension] to emulate Rust's expression blocks.
Another common problem in macro systems is variable capture. Heres a C
macro, using [a GNU C extension] to emulate Rusts expression blocks.
[a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
@ -275,7 +275,7 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks.
})
```
Here's a simple use case that goes terribly wrong:
Heres a simple use case that goes terribly wrong:
```text
const char *state = "reticulating splines";
@ -315,10 +315,10 @@ fn main() {
```
This works because Rust has a [hygienic macro system][]. Each macro expansion
happens in a distinct *syntax context*, and each variable is tagged with the
syntax context where it was introduced. It's as though the variable `state`
happens in a distinct syntax context, and each variable is tagged with the
syntax context where it was introduced. Its as though the variable `state`
inside `main` is painted a different "color" from the variable `state` inside
the macro, and therefore they don't conflict.
the macro, and therefore they dont conflict.
[hygienic macro system]: http://en.wikipedia.org/wiki/Hygienic_macro
@ -336,7 +336,7 @@ fn main() {
}
```
Instead you need to pass the variable name into the invocation, so it's tagged
Instead you need to pass the variable name into the invocation, so its tagged
with the right syntax context.
```rust
@ -368,7 +368,7 @@ fn main() {
# Recursive macros
A macro's expansion can include more macro invocations, including invocations
A macros 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:
@ -429,7 +429,7 @@ they are unstable and require feature gates.
Even when Rust code contains un-expanded macros, it can be parsed as a full
[syntax tree][ast]. This property can be very useful for editors and other
tools that process code. It also has a few consequences for the design of
Rust's macro system.
Rusts macro system.
[ast]: glossary.html#abstract-syntax-tree
@ -454,13 +454,13 @@ consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
must be balanced within a macro invocation. For example, `foo!([)` is
forbidden. This allows Rust to know where the macro invocation ends.
More formally, the macro invocation body must be a sequence of *token trees*.
More formally, the macro invocation body must be a sequence of token trees.
A token tree is defined recursively as either
* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
* any other single token.
Within a matcher, each metavariable has a *fragment specifier*, identifying
Within a matcher, each metavariable has a fragment specifier, identifying
which syntactic form it matches.
* `ident`: an identifier. Examples: `x`; `foo`.
@ -482,7 +482,7 @@ There are additional rules regarding the next token after a metavariable:
* `pat` variables must be followed by one of: `=> , =`
* Other variables may be followed by any token.
These rules provide some flexibility for Rust's syntax to evolve without
These rules provide some flexibility for Rusts syntax to evolve without
breaking existing macros.
The macro system does not deal with parse ambiguity at all. For example, the
@ -500,7 +500,7 @@ One downside is that scoping works differently for macros, compared to other
constructs in the language.
Definition and expansion of macros both happen in a single depth-first,
lexical-order traversal of a crate's source. So a macro defined at module scope
lexical-order traversal of a crates source. So a macro defined at module scope
is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items.
@ -508,8 +508,8 @@ A macro defined within the body of a single `fn`, or anywhere else not at
module scope, is visible only within that item.
If a module has the `macro_use` attribute, its macros are also visible in its
parent module after the child's `mod` item. If the parent also has `macro_use`
then the macros will be visible in the grandparent after the parent's `mod`
parent module after the childs `mod` item. If the parent also has `macro_use`
then the macros will be visible in the grandparent after the parents `mod`
item, and so forth.
The `macro_use` attribute can also appear on `extern crate`. In this context
@ -524,7 +524,7 @@ If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
there is no `#[macro_use]` attribute then no macros are loaded. Only macros
defined with the `#[macro_export]` attribute may be loaded.
To load a crate's macros *without* linking it into the output, use `#[no_link]`
To load a crates macros without linking it into the output, use `#[no_link]`
as well.
An example:
@ -619,12 +619,12 @@ only appear at the root of your crate, not inside `mod`. This ensures that
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
invocation gives you another opportunity to pattern-match the macros
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.
within Rusts macro system.
```rust
macro_rules! bct {
@ -765,9 +765,9 @@ as `unimplemented!` until youre ready to write them.
# Procedural macros
If Rust's macro system can't do what you need, you may want to write a
If Rusts macro system cant 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 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.
extension plugins are sometimes called procedural macros for this reason.

View File

@ -168,6 +168,7 @@ like arrays:
```rust
let a = [0, 1, 2, 3, 4];
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
let complete = &a[..]; // A slice containing all of the elements in a
```
Slices have type `&[T]`. Well talk about that `T` when we cover

View File

@ -87,3 +87,33 @@ fn main() {
point.y = 6; // this causes an error
}
```
# Update syntax
A `struct` can include `..` to indicate that you want to use a copy of some
other struct for some of the values. For example:
```rust
struct Point3d {
x: i32,
y: i32,
z: i32,
}
let mut point = Point3d { x: 0, y: 0, z: 0 };
point = Point3d { y: 1, .. point };
```
This gives `point` a new `y`, but keeps the old `x` and `z` values. It doesnt
have to be the same `struct` either, you can use this syntax when making new
ones, and it will copy the values you dont specify:
```rust
# struct Point3d {
# x: i32,
# y: i32,
# z: i32,
# }
let origin = Point3d { x: 0, y: 0, z: 0 };
let point = Point3d { z: 1, x: 2, .. origin };
```

View File

@ -1,15 +1,15 @@
% Trait Objects
When code involves polymorphism, there needs to be a mechanism to determine
which specific version is actually run. This is called 'dispatch.' There are
which specific version is actually run. This is called dispatch. There are
two major forms of dispatch: static dispatch and dynamic dispatch. While Rust
favors static dispatch, it also supports dynamic dispatch through a mechanism
called 'trait objects.'
called trait objects.
## Background
For the rest of this chapter, we'll need a trait and some implementations.
Let's make a simple one, `Foo`. It has one method that is expected to return a
For the rest of this chapter, well need a trait and some implementations.
Lets make a simple one, `Foo`. It has one method that is expected to return a
`String`.
```rust
@ -18,7 +18,7 @@ trait Foo {
}
```
We'll also implement this trait for `u8` and `String`:
Well also implement this trait for `u8` and `String`:
```rust
# trait Foo { fn method(&self) -> String; }
@ -53,7 +53,7 @@ fn main() {
}
```
Rust uses 'monomorphization' to perform static dispatch here. This means that
Rust uses monomorphization to perform static dispatch here. This means that
Rust will create a special version of `do_something()` for both `u8` and
`String`, and then replace the call sites with calls to these specialized
functions. In other words, Rust generates something like this:
@ -82,7 +82,7 @@ fn main() {
This has a great upside: static dispatch allows function calls to be
inlined because the callee is known at compile time, and inlining is
the key to good optimization. Static dispatch is fast, but it comes at
a tradeoff: 'code bloat', due to many copies of the same function
a tradeoff: code bloat, due to many copies of the same function
existing in the binary, one for each type.
Furthermore, compilers arent perfect and may “optimize” code to become slower.
@ -99,7 +99,7 @@ reason.
## Dynamic dispatch
Rust provides dynamic dispatch through a feature called 'trait objects.' Trait
Rust provides dynamic dispatch through a feature called trait objects. Trait
objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
*any* type that implements the given trait, where the precise type can only be
known at runtime.
@ -109,12 +109,12 @@ implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it
(e.g. using `&x` as an argument to a function that takes `&Foo`).
These trait object coercions and casts also work for pointers like `&mut T` to
`&mut Foo` and `Box<T>` to `Box<Foo>`, but that's all at the moment. Coercions
`&mut Foo` and `Box<T>` to `Box<Foo>`, but thats all at the moment. Coercions
and casts are identical.
This operation can be seen as "erasing" the compiler's knowledge about the
This operation can be seen as erasing the compilers knowledge about the
specific type of the pointer, and hence trait objects are sometimes referred to
as "type erasure".
as type erasure.
Coming back to the example above, we can use the same trait to perform dynamic
dispatch with trait objects by casting:
@ -167,7 +167,7 @@ on the heap to store it.
For `Foo`, we would need to have a value that could be at least either a
`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which
dependent crates may implement `Foo` (any number of bytes at all). There's no
dependent crates may implement `Foo` (any number of bytes at all). Theres no
way to guarantee that this last point can work if the values are stored without
a pointer, because those other types can be arbitrarily large.
@ -177,14 +177,14 @@ when we are tossing a trait object around, only the size of the pointer itself.
### Representation
The methods of the trait can be called on a trait object via a special record
of function pointers traditionally called a 'vtable' (created and managed by
of function pointers traditionally called a vtable (created and managed by
the compiler).
Trait objects are both simple and complicated: their core representation and
layout is quite straight-forward, but there are some curly error messages and
surprising behaviors to discover.
Let's start simple, with the runtime representation of a trait object. The
Lets start simple, with the runtime representation of a trait object. The
`std::raw` module contains structs with layouts that are the same as the
complicated built-in types, [including trait objects][stdraw]:
@ -199,12 +199,12 @@ pub struct TraitObject {
[stdraw]: ../std/raw/struct.TraitObject.html
That is, a trait object like `&Foo` consists of a "data" pointer and a "vtable"
That is, a trait object like `&Foo` consists of a data pointer and a vtable
pointer.
The data pointer addresses the data (of some unknown type `T`) that the trait
object is storing, and the vtable pointer points to the vtable ("virtual method
table") corresponding to the implementation of `Foo` for `T`.
object is storing, and the vtable pointer points to the vtable (virtual method
table) corresponding to the implementation of `Foo` for `T`.
A vtable is essentially a struct of function pointers, pointing to the concrete
@ -212,7 +212,7 @@ piece of machine code for each method in the implementation. A method call like
`trait_object.method()` will retrieve the correct pointer out of the vtable and
then do a dynamic call of it. For example:
```{rust,ignore}
```rust,ignore
struct FooVtable {
destructor: fn(*mut ()),
size: usize,
@ -261,7 +261,7 @@ static Foo_for_String_vtable: FooVtable = FooVtable {
```
The `destructor` field in each vtable points to a function that will clean up
any resources of the vtable's type, for `u8` it is trivial, but for `String` it
any resources of the vtables type, for `u8` it is trivial, but for `String` it
will free the memory. This is necessary for owning trait objects like
`Box<Foo>`, which need to clean-up both the `Box` allocation as well as the
internal type when they go out of scope. The `size` and `align` fields store
@ -270,11 +270,11 @@ essentially unused at the moment since the information is embedded in the
destructor, but will be used in the future, as trait objects are progressively
made more flexible.
Suppose we've got some values that implement `Foo`, then the explicit form of
Suppose weve got some values that implement `Foo`, then the explicit form of
construction and use of `Foo` trait objects might look a bit like (ignoring the
type mismatches: they're all just pointers anyway):
type mismatches: theyre all just pointers anyway):
```{rust,ignore}
```rust,ignore
let a: String = "foo".to_string();
let x: u8 = 1;

View File

@ -336,7 +336,7 @@ This shows off the additional feature of `where` clauses: they allow bounds
where the left-hand side is an arbitrary type (`i32` in this case), not just a
plain type parameter (like `T`).
# Default methods
## Default methods
Theres one last feature of traits we should cover: default methods. Its
easiest just to show an example:

View File

@ -1,16 +1,20 @@
% Tuple Structs
Rust has another data type that's like a hybrid between a tuple and a struct,
called a *tuple struct*. Tuple structs do have a name, but their fields don't:
Rust has another data type that's like a hybrid between a [tuple][tuple] and a
[struct][struct], called a tuple struct. Tuple structs have a name, but
their fields dont:
```{rust}
```rust
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
```
[tuple]: primitive-types.html#tuples
[struct]: structs.html
These two will not be equal, even if they have the same values:
```{rust}
```rust
# struct Color(i32, i32, i32);
# struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
@ -20,7 +24,7 @@ let origin = Point(0, 0, 0);
It is almost always better to use a struct than a tuple struct. We would write
`Color` and `Point` like this instead:
```{rust}
```rust
struct Color {
red: i32,
blue: i32,
@ -37,12 +41,12 @@ struct Point {
Now, we have actual names, rather than positions. Good names are important,
and with a struct, we have actual names.
There _is_ one case when a tuple struct is very useful, though, and that's a
tuple struct with only one element. We call this the *newtype* pattern, because
There _is_ one case when a tuple struct is very useful, though, and thats a
tuple struct with only one element. We call this the newtype pattern, because
it allows you to create a new type, distinct from that of its contained value
and expressing its own semantic meaning:
```{rust}
```rust
struct Inches(i32);
let length = Inches(10);
@ -52,5 +56,5 @@ println!("length is {} inches", integer_length);
```
As you can see here, you can extract the inner integer type through a
destructuring `let`, as we discussed previously in 'tuples.' In this case, the
destructuring `let`, as we discussed previously in tuples. In this case, the
`let Inches(integer_length)` assigns `10` to `integer_length`.

View File

@ -1,4 +1,4 @@
% Unsafe Code
% Unsafe
Rusts main draw is its powerful static guarantees about behavior. But safety
checks are conservative by nature: there are some programs that are actually
@ -76,7 +76,7 @@ behaviors that are certainly bad, but are expressly _not_ unsafe:
* Integer overflow
Rust cannot prevent all kinds of software problems. Buggy code can and will be
written in Rust. These things arnet great, but they dont qualify as `unsafe`
written in Rust. These things arent great, but they dont qualify as `unsafe`
specifically.
# Unsafe Superpowers

View File

@ -46,13 +46,8 @@ def run(args):
f.write("\n")
version = run([llconfig, '--version']).strip()
# LLVM libs
if version < '3.5':
args = [llconfig, '--libs']
else:
args = [llconfig, '--libs', '--system-libs']
args = [llconfig, '--libs', '--system-libs']
args.extend(components)
out = run(args)
@ -73,11 +68,6 @@ for lib in out.strip().replace("\n", ' ').split(' '):
f.write(", kind = \"static\"")
f.write(")]\n")
# llvm-config before 3.5 didn't have a system-libs flag
if version < '3.5':
if os == 'win32':
f.write("#[link(name = \"imagehlp\")]")
# LLVM ldflags
out = run([llconfig, '--ldflags'])
for lib in out.strip().split(' '):

View File

@ -77,7 +77,6 @@ use core::atomic;
use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
use core::fmt;
use core::cmp::Ordering;
use core::default::Default;
use core::mem::{min_align_of, size_of};
use core::mem;
use core::nonzero::NonZero;

View File

@ -55,7 +55,6 @@ use core::prelude::*;
use core::any::Any;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
use core::hash::{self, Hash};
use core::mem;

View File

@ -152,8 +152,7 @@
use core::prelude::*;
use core::default::Default;
use core::iter::{FromIterator, IntoIterator};
use core::iter::{FromIterator};
use core::mem::{zeroed, replace, swap};
use core::ptr;
@ -250,28 +249,6 @@ impl<T: Ord> BinaryHeap<T> {
Iter { iter: self.data.iter() }
}
/// Creates a consuming iterator, that is, one that moves each value out of
/// the binary heap in arbitrary order. The binary heap cannot be used
/// after calling this.
///
/// # Examples
///
/// ```
/// # #![feature(collections)]
/// use std::collections::BinaryHeap;
/// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]);
///
/// // Print 1, 2, 3, 4 in arbitrary order
/// for x in heap.into_iter() {
/// // x has type i32, not &i32
/// println!("{}", x);
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<T> {
IntoIter { iter: self.data.into_iter() }
}
/// Returns the greatest item in the binary heap, or `None` if it is empty.
///
/// # Examples
@ -675,8 +652,25 @@ impl<T: Ord> IntoIterator for BinaryHeap<T> {
type Item = T;
type IntoIter = IntoIter<T>;
/// Creates a consuming iterator, that is, one that moves each value out of
/// the binary heap in arbitrary order. The binary heap cannot be used
/// after calling this.
///
/// # Examples
///
/// ```
/// # #![feature(collections)]
/// use std::collections::BinaryHeap;
/// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]);
///
/// // Print 1, 2, 3, 4 in arbitrary order
/// for x in heap.into_iter() {
/// // x has type i32, not &i32
/// println!("{}", x);
/// }
/// ```
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
IntoIter { iter: self.data.into_iter() }
}
}

View File

@ -40,7 +40,6 @@
//! ```
//! # #![feature(collections, core, step_by)]
//! use std::collections::{BitSet, BitVec};
//! use std::num::Float;
//! use std::iter;
//!
//! let max_prime = 10000;
@ -85,12 +84,11 @@ use core::prelude::*;
use core::cmp::Ordering;
use core::cmp;
use core::default::Default;
use core::fmt;
use core::hash;
use core::iter::RandomAccessIterator;
use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat, Cloned};
use core::iter::{self, FromIterator, IntoIterator};
use core::iter::{self, FromIterator};
use core::ops::Index;
use core::slice;
use core::{u8, u32, usize};

View File

@ -20,10 +20,9 @@ use self::Entry::*;
use core::prelude::*;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt::Debug;
use core::hash::{Hash, Hasher};
use core::iter::{Map, FromIterator, IntoIterator};
use core::iter::{Map, FromIterator};
use core::ops::Index;
use core::{iter, fmt, mem, usize};
use Bound::{self, Included, Excluded, Unbounded};
@ -471,8 +470,32 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
/// Gets an owning iterator over the entries of the map.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// map.insert(3, "c");
///
/// for (key, value) in map.into_iter() {
/// println!("{}: {}", key, value);
/// }
/// ```
fn into_iter(self) -> IntoIter<K, V> {
self.into_iter()
let len = self.len();
let mut lca = VecDeque::new();
lca.push_back(Traverse::traverse(self.root));
IntoIter {
inner: AbsIter {
traversals: lca,
size: len,
}
}
}
}
@ -1263,35 +1286,6 @@ impl<K, V> BTreeMap<K, V> {
}
}
/// Gets an owning iterator over the entries of the map.
///
/// # Examples
///
/// ```
/// use std::collections::BTreeMap;
///
/// let mut map = BTreeMap::new();
/// map.insert(1, "a");
/// map.insert(2, "b");
/// map.insert(3, "c");
///
/// for (key, value) in map.into_iter() {
/// println!("{}: {}", key, value);
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<K, V> {
let len = self.len();
let mut lca = VecDeque::new();
lca.push_back(Traverse::traverse(self.root));
IntoIter {
inner: AbsIter {
traversals: lca,
size: len,
}
}
}
/// Gets an iterator over the keys of the map.
///
/// # Examples

View File

@ -14,10 +14,9 @@
use core::prelude::*;
use core::cmp::Ordering::{self, Less, Greater, Equal};
use core::default::Default;
use core::fmt::Debug;
use core::fmt;
use core::iter::{Peekable, Map, FromIterator, IntoIterator};
use core::iter::{Peekable, Map, FromIterator};
use core::ops::{BitOr, BitAnd, BitXor, Sub};
use borrow::Borrow;
@ -132,27 +131,6 @@ impl<T> BTreeSet<T> {
pub fn iter(&self) -> Iter<T> {
Iter { iter: self.map.keys() }
}
/// Gets an iterator for moving out the BtreeSet's contents.
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::collections::BTreeSet;
///
/// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
///
/// let v: Vec<usize> = set.into_iter().collect();
/// assert_eq!(v, [1, 2, 3, 4]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<T> {
fn first<A, B>((a, _): (A, B)) -> A { a }
let first: fn((T, ())) -> T = first; // coerce to fn pointer
IntoIter { iter: self.map.into_iter().map(first) }
}
}
impl<T: Ord> BTreeSet<T> {
@ -500,8 +478,24 @@ impl<T> IntoIterator for BTreeSet<T> {
type Item = T;
type IntoIter = IntoIter<T>;
/// Gets an iterator for moving out the BtreeSet's contents.
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::collections::BTreeSet;
///
/// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
///
/// let v: Vec<usize> = set.into_iter().collect();
/// assert_eq!(v, [1, 2, 3, 4]);
/// ```
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
fn first<A, B>((a, _): (A, B)) -> A { a }
let first: fn((T, ())) -> T = first; // coerce to fn pointer
IntoIter { iter: self.map.into_iter().map(first) }
}
}

View File

@ -16,7 +16,7 @@
use core::prelude::*;
use core::marker;
use core::fmt;
use core::iter::{FromIterator, IntoIterator};
use core::iter::{FromIterator};
use core::ops::{Sub, BitOr, BitAnd, BitXor};
// FIXME(contentions): implement union family of methods? (general design may be wrong here)

View File

@ -175,7 +175,6 @@
//! # #![feature(core, std_misc)]
//! use std::fmt;
//! use std::f64;
//! use std::num::Float;
//!
//! #[derive(Debug)]
//! struct Vector2D {
@ -200,10 +199,11 @@
//! let magnitude = magnitude.sqrt();
//!
//! // Respect the formatting flags by using the helper method
//! // `pad_integral` on the Formatter object. See the method documentation
//! // for details, and the function `pad` can be used to pad strings.
//! // `pad_integral` on the Formatter object. See the method
//! // documentation for details, and the function `pad` can be used
//! // to pad strings.
//! let decimals = f.precision().unwrap_or(3);
//! let string = f64::to_str_exact(magnitude, decimals);
//! let string = format!("{:.*}", decimals, magnitude);
//! f.pad_integral(true, "", &string)
//! }
//! }
@ -260,7 +260,6 @@
//! Example usage is:
//!
//! ```
//! # #![feature(old_io)]
//! # #![allow(unused_must_use)]
//! use std::io::Write;
//! let mut w = Vec::new();
@ -288,7 +287,6 @@
//! off, some example usage is:
//!
//! ```
//! # #![feature(old_io)]
//! use std::fmt;
//! use std::io::{self, Write};
//!

View File

@ -38,6 +38,7 @@
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(step_by)]
#![feature(str_char)]
#![feature(str_words)]
#![feature(slice_patterns)]
#![feature(debug_builders)]
#![feature(utf8_error)]

View File

@ -25,10 +25,9 @@ use core::prelude::*;
use alloc::boxed::Box;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
use core::hash::{Hasher, Hash};
use core::iter::{self, FromIterator, IntoIterator};
use core::iter::{self, FromIterator};
use core::mem;
use core::ptr;
@ -296,13 +295,6 @@ impl<T> LinkedList<T> {
}
}
/// Consumes the list into an iterator yielding elements by value.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<T> {
IntoIter{list: self}
}
/// Returns `true` if the `LinkedList` is empty.
///
/// This operation should compute in O(1) time.
@ -852,8 +844,10 @@ impl<T> IntoIterator for LinkedList<T> {
type Item = T;
type IntoIter = IntoIter<T>;
/// Consumes the list into an iterator yielding elements by value.
#[inline]
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
IntoIter{list: self}
}
}
@ -941,7 +935,7 @@ impl<A: Hash> Hash for LinkedList<A> {
#[cfg(test)]
mod test {
use std::clone::Clone;
use std::iter::Iterator;
use std::iter::{Iterator, IntoIterator};
use std::option::Option::{Some, None, self};
use std::__rand::{thread_rng, Rng};
use std::thread;

View File

@ -98,7 +98,7 @@ use self::Direction::*;
use borrow::{Borrow, BorrowMut, ToOwned};
use vec::Vec;
pub use core::slice::{Chunks, AsSlice, Windows};
pub use core::slice::{Chunks, Windows};
pub use core::slice::{Iter, IterMut};
pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split};
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};

View File

@ -67,7 +67,7 @@ use rustc_unicode;
use vec::Vec;
use slice::SliceConcatExt;
pub use core::str::{FromStr, Utf8Error, Str};
pub use core::str::{FromStr, Utf8Error};
pub use core::str::{Lines, LinesAny, CharRange};
pub use core::str::{Split, RSplit};
pub use core::str::{SplitN, RSplitN};
@ -76,7 +76,7 @@ pub use core::str::{Matches, RMatches};
pub use core::str::{MatchIndices, RMatchIndices};
pub use core::str::{from_utf8, Chars, CharIndices, Bytes};
pub use core::str::{from_utf8_unchecked, ParseBoolError};
pub use rustc_unicode::str::{Words, Graphemes, GraphemeIndices};
pub use rustc_unicode::str::{SplitWhitespace, Words, Graphemes, GraphemeIndices};
pub use core::str::pattern;
/*
@ -1737,27 +1737,44 @@ impl str {
UnicodeStr::grapheme_indices(&self[..], is_extended)
}
/// An iterator over the non-empty words of `self`.
///
/// A 'word' is a subsequence separated by any sequence of whitespace.
/// Sequences of whitespace
/// are collapsed, so empty "words" are not included.
/// An iterator over the non-empty substrings of `self` which contain no whitespace,
/// and which are separated by any amount of whitespace.
///
/// # Examples
///
/// ```
/// # #![feature(str_words)]
/// # #![allow(deprecated)]
/// let some_words = " Mary had\ta little \n\t lamb";
/// let v: Vec<&str> = some_words.words().collect();
///
/// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
/// ```
#[deprecated(reason = "words() will be removed. Use split_whitespace() instead",
since = "1.1.0")]
#[unstable(feature = "str_words",
reason = "the precise algorithm to use is unclear")]
#[allow(deprecated)]
pub fn words(&self) -> Words {
UnicodeStr::words(&self[..])
}
/// An iterator over the non-empty substrings of `self` which contain no whitespace,
/// and which are separated by any amount of whitespace.
///
/// # Examples
///
/// ```
/// let some_words = " Mary had\ta little \n\t lamb";
/// let v: Vec<&str> = some_words.split_whitespace().collect();
///
/// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
/// ```
#[stable(feature = "split_whitespace", since = "1.1.0")]
pub fn split_whitespace(&self) -> SplitWhitespace {
UnicodeStr::split_whitespace(&self[..])
}
/// Returns a string's displayed width in columns.
///
/// Control characters have zero width.

View File

@ -14,10 +14,9 @@
use core::prelude::*;
use core::default::Default;
use core::fmt;
use core::hash;
use core::iter::{IntoIterator, FromIterator};
use core::iter::FromIterator;
use core::mem;
use core::ops::{self, Deref, Add, Index};
use core::ptr;
@ -837,15 +836,6 @@ impl<'a, 'b> PartialEq<Cow<'a, str>> for &'b str {
fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&self[..], &other[..]) }
}
#[unstable(feature = "collections", reason = "waiting on Str stabilization")]
#[allow(deprecated)]
impl Str for String {
#[inline]
fn as_slice(&self) -> &str {
unsafe { mem::transmute(&*self.vec) }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Default for String {
#[inline]
@ -1067,14 +1057,6 @@ impl<'a> IntoCow<'a, str> for &'a str {
}
}
#[allow(deprecated)]
impl<'a> Str for Cow<'a, str> {
#[inline]
fn as_slice<'b>(&'b self) -> &'b str {
&**self
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Write for String {
#[inline]
@ -1082,4 +1064,10 @@ impl fmt::Write for String {
self.push_str(s);
Ok(())
}
#[inline]
fn write_char(&mut self, c: char) -> fmt::Result {
self.push(c);
Ok(())
}
}

View File

@ -53,11 +53,10 @@ use alloc::boxed::Box;
use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
use core::cmp::max;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
use core::hash::{self, Hash};
use core::intrinsics::assume;
use core::iter::{repeat, FromIterator, IntoIterator};
use core::iter::{repeat, FromIterator};
use core::marker::PhantomData;
use core::mem;
use core::ops::{Index, IndexMut, Deref, Add};
@ -450,37 +449,6 @@ impl<T> Vec<T> {
&mut self[..]
}
/// Creates a consuming iterator, that is, one that moves each value out of
/// the vector (from start to end). The vector cannot be used after calling
/// this.
///
/// # Examples
///
/// ```
/// let v = vec!["a".to_string(), "b".to_string()];
/// for s in v.into_iter() {
/// // s has type String, not &String
/// println!("{}", s);
/// }
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<T> {
unsafe {
let ptr = *self.ptr;
assume(!ptr.is_null());
let cap = self.cap;
let begin = ptr as *const T;
let end = if mem::size_of::<T>() == 0 {
(ptr as usize + self.len()) as *const T
} else {
ptr.offset(self.len() as isize) as *const T
};
mem::forget(self);
IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end }
}
}
/// Sets the length of a vector.
///
/// This will explicitly set the size of the vector, without actually
@ -1512,8 +1480,34 @@ impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
/// Creates a consuming iterator, that is, one that moves each value out of
/// the vector (from start to end). The vector cannot be used after calling
/// this.
///
/// # Examples
///
/// ```
/// let v = vec!["a".to_string(), "b".to_string()];
/// for s in v.into_iter() {
/// // s has type String, not &String
/// println!("{}", s);
/// }
/// ```
#[inline]
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
unsafe {
let ptr = *self.ptr;
assume(!ptr.is_null());
let cap = self.cap;
let begin = ptr as *const T;
let end = if mem::size_of::<T>() == 0 {
(ptr as usize + self.len()) as *const T
} else {
ptr.offset(self.len() as isize) as *const T
};
mem::forget(self);
IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end }
}
}
}
@ -1597,18 +1591,6 @@ impl<T: Ord> Ord for Vec<T> {
}
}
#[unstable(feature = "collections",
reason = "will be replaced by slice syntax")]
#[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
#[allow(deprecated)]
impl<T> AsSlice<T> for Vec<T> {
/// Deprecated: use `&mut s[..]` instead.
#[inline]
fn as_slice(&self) -> &[T] {
self
}
}
#[unstable(feature = "collections",
reason = "recent addition, needs more experience")]
impl<'a, T: Clone> Add<&'a [T]> for Vec<T> {

View File

@ -21,9 +21,8 @@
use core::prelude::*;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
use core::iter::{self, repeat, FromIterator, RandomAccessIterator};
use core::mem;
use core::ops::{Index, IndexMut};
use core::ptr::{self, Unique};
@ -557,14 +556,6 @@ impl<T> VecDeque<T> {
}
}
/// Consumes the list into a front-to-back iterator yielding elements by value.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<T> {
IntoIter {
inner: self,
}
}
/// Returns a pair of slices which contain, in order, the contents of the
/// `VecDeque`.
#[inline]
@ -1728,8 +1719,12 @@ impl<T> IntoIterator for VecDeque<T> {
type Item = T;
type IntoIter = IntoIter<T>;
/// Consumes the list into a front-to-back iterator yielding elements by
/// value.
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
IntoIter {
inner: self,
}
}
}

View File

@ -18,10 +18,9 @@ use self::Entry::*;
use core::prelude::*;
use core::cmp::{max, Ordering};
use core::default::Default;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
use core::iter::{Enumerate, FilterMap, Map, FromIterator};
use core::iter;
use core::mem::{replace, swap};
use core::ops::{Index, IndexMut};
@ -301,35 +300,6 @@ impl<V> VecMap<V> {
}
}
/// Returns an iterator visiting all key-value pairs in ascending order of
/// the keys, consuming the original `VecMap`.
/// The iterator's element type is `(usize, &'r V)`.
///
/// # Examples
///
/// ```
/// # #![feature(collections)]
/// use std::collections::VecMap;
///
/// let mut map = VecMap::new();
/// map.insert(1, "a");
/// map.insert(3, "c");
/// map.insert(2, "b");
///
/// let vec: Vec<(usize, &str)> = map.into_iter().collect();
///
/// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<V> {
fn filter<A>((i, v): (usize, Option<A>)) -> Option<(usize, A)> {
v.map(|v| (i, v))
}
let filter: fn((usize, Option<V>)) -> Option<(usize, V)> = filter; // coerce to fn ptr
IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) }
}
/// Moves all elements from `other` into the map while overwriting existing keys.
///
/// # Examples
@ -800,8 +770,32 @@ impl<T> IntoIterator for VecMap<T> {
type Item = (usize, T);
type IntoIter = IntoIter<T>;
/// Returns an iterator visiting all key-value pairs in ascending order of
/// the keys, consuming the original `VecMap`.
/// The iterator's element type is `(usize, &'r V)`.
///
/// # Examples
///
/// ```
/// # #![feature(collections)]
/// use std::collections::VecMap;
///
/// let mut map = VecMap::new();
/// map.insert(1, "a");
/// map.insert(3, "c");
/// map.insert(2, "b");
///
/// let vec: Vec<(usize, &str)> = map.into_iter().collect();
///
/// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
/// ```
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
fn filter<A>((i, v): (usize, Option<A>)) -> Option<(usize, A)> {
v.map(|v| (i, v))
}
let filter: fn((usize, Option<T>)) -> Option<(usize, T)> = filter; // coerce to fn ptr
IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) }
}
}

View File

@ -14,7 +14,6 @@
#![feature(hash)]
#![feature(rand)]
#![feature(rustc_private)]
#![feature(str_words)]
#![feature(test)]
#![feature(unboxed_closures)]
#![feature(unicode)]

View File

@ -939,9 +939,9 @@ fn test_rsplitn() {
}
#[test]
fn test_words() {
fn test_split_whitespace() {
let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
let words: Vec<&str> = data.words().collect();
let words: Vec<&str> = data.split_whitespace().collect();
assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
}

View File

@ -11,15 +11,15 @@
pub use self::ExponentFormat::*;
pub use self::SignificantDigits::*;
use char::{self, CharExt};
use prelude::*;
use char;
use fmt;
use iter::Iterator;
use num::{cast, Float, ToPrimitive};
use num::Float;
use num::FpCategory as Fp;
use ops::FnOnce;
use result::Result::Ok;
use slice::{self, SliceExt};
use str::{self, StrExt};
use ops::{Div, Rem, Mul};
use slice;
use str;
/// A flag that specifies whether to use exponential (scientific) notation.
pub enum ExponentFormat {
@ -42,6 +42,21 @@ pub enum SignificantDigits {
DigExact(usize)
}
#[doc(hidden)]
pub trait MyFloat: Float + PartialEq + PartialOrd + Div<Output=Self> +
Mul<Output=Self> + Rem<Output=Self> + Copy {
fn from_u32(u: u32) -> Self;
fn to_i32(&self) -> i32;
}
macro_rules! doit {
($($t:ident)*) => ($(impl MyFloat for $t {
fn from_u32(u: u32) -> $t { u as $t }
fn to_i32(&self) -> i32 { *self as i32 }
})*)
}
doit! { f32 f64 }
/// Converts a float number to its string representation.
/// This is meant to be a common base implementation for various formatting styles.
/// The number is assumed to be non-negative, callers use `Formatter::pad_integral`
@ -63,7 +78,7 @@ pub enum SignificantDigits {
/// # Panics
///
/// - Panics if `num` is negative.
pub fn float_to_str_bytes_common<T: Float, U, F>(
pub fn float_to_str_bytes_common<T: MyFloat, U, F>(
num: T,
digits: SignificantDigits,
exp_format: ExponentFormat,
@ -72,10 +87,10 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
) -> U where
F: FnOnce(&str) -> U,
{
let _0: T = Float::zero();
let _1: T = Float::one();
let _0: T = T::zero();
let _1: T = T::one();
let radix: u32 = 10;
let radix_f: T = cast(radix).unwrap();
let radix_f = T::from_u32(radix);
assert!(num.is_nan() || num >= _0, "float_to_str_bytes_common: number is negative");
@ -99,7 +114,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
let (num, exp) = match exp_format {
ExpDec if num != _0 => {
let exp = num.log10().floor();
(num / radix_f.powf(exp), cast::<T, i32>(exp).unwrap())
(num / radix_f.powf(exp), exp.to_i32())
}
_ => (num, 0)
};
@ -114,7 +129,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
deccum = deccum / radix_f;
deccum = deccum.trunc();
let c = char::from_digit(current_digit.to_isize().unwrap() as u32, radix);
let c = char::from_digit(current_digit.to_i32() as u32, radix);
buf[end] = c.unwrap() as u8;
end += 1;
@ -158,7 +173,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
let current_digit = deccum.trunc();
let c = char::from_digit(current_digit.to_isize().unwrap() as u32, radix);
let c = char::from_digit(current_digit.to_i32() as u32, radix);
buf[end] = c.unwrap() as u8;
end += 1;

View File

@ -12,21 +12,16 @@
#![stable(feature = "rust1", since = "1.0.0")]
use prelude::*;
use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
use char::CharExt;
use clone::Clone;
use iter::Iterator;
use marker::{Copy, PhantomData, Sized};
use marker::PhantomData;
use mem;
use num::Float;
use option::Option;
use option::Option::{Some, None};
use result::Result::Ok;
use ops::{Deref, FnOnce};
use ops::Deref;
use result;
use slice::SliceExt;
use num::Float;
use slice;
use str::{self, StrExt};
use str;
use self::rt::v1::Alignment;
pub use self::num::radix;
@ -83,6 +78,23 @@ pub trait Write {
#[stable(feature = "rust1", since = "1.0.0")]
fn write_str(&mut self, s: &str) -> Result;
/// Writes a `char` into this writer, returning whether the write succeeded.
///
/// A single `char` may be encoded as more than one byte.
/// This method can only succeed if the entire byte sequence was successfully
/// written, and this method will not return until all data has been
/// written or an error occurs.
///
/// # Errors
///
/// This function will return an instance of `FormatError` on error.
#[stable(feature = "fmt_write_char", since = "1.1.0")]
fn write_char(&mut self, c: char) -> Result {
let mut utf_8 = [0u8; 4];
let bytes_written = c.encode_utf8(&mut utf_8).unwrap_or(0);
self.write_str(unsafe { mem::transmute(&utf_8[..bytes_written]) })
}
/// Glue for usage of the `write!` macro with implementers of this trait.
///
/// This method should generally not be invoked manually, but rather through
@ -912,7 +924,8 @@ impl<'a, T> Pointer for &'a mut T {
}
// Common code of floating point Debug and Display.
fn float_to_str_common<T: Float, F>(num: &T, precision: Option<usize>, post: F) -> Result
fn float_to_str_common<T: float::MyFloat, F>(num: &T, precision: Option<usize>,
post: F) -> Result
where F : FnOnce(&str) -> Result {
let digits = match precision {
Some(i) => float::DigExact(i),
@ -950,8 +963,6 @@ macro_rules! floating { ($ty:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl LowerExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
use num::Float;
let digits = match fmt.precision {
Some(i) => float::DigExact(i),
None => float::DigMax(6),
@ -969,8 +980,6 @@ macro_rules! floating { ($ty:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl UpperExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result {
use num::Float;
let digits = match fmt.precision {
Some(i) => float::DigExact(i),
None => float::DigMax(6),

View File

@ -14,12 +14,28 @@
#![allow(unsigned_negation)]
use prelude::*;
use fmt;
use iter::Iterator;
use num::{Int, cast};
use slice::SliceExt;
use num::Zero;
use ops::{Div, Rem, Sub};
use str;
#[doc(hidden)]
trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
Sub<Output=Self> + Copy {
fn from_u8(u: u8) -> Self;
fn to_u8(&self) -> u8;
}
macro_rules! doit {
($($t:ident)*) => ($(impl Int for $t {
fn from_u8(u: u8) -> $t { u as $t }
fn to_u8(&self) -> u8 { *self as u8 }
})*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
/// A type that represents a specific radix
#[doc(hidden)]
trait GenericRadix {
@ -33,33 +49,32 @@ trait GenericRadix {
fn digit(&self, x: u8) -> u8;
/// Format an integer using the radix using a formatter.
#[allow(deprecated)] // Int
fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
// The radix can be as low as 2, so we need a buffer of at least 64
// characters for a base 2 number.
let zero = Int::zero();
let zero = T::zero();
let is_positive = x >= zero;
let mut buf = [0; 64];
let mut curr = buf.len();
let base = cast(self.base()).unwrap();
let base = T::from_u8(self.base());
if is_positive {
// Accumulate each digit of the number from the least significant
// to the most significant figure.
for byte in buf.iter_mut().rev() {
let n = x % base; // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = self.digit(cast(n).unwrap()); // Store the digit in the buffer.
let n = x % base; // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = self.digit(n.to_u8()); // Store the digit in the buffer.
curr -= 1;
if x == zero { break }; // No more digits left to accumulate.
if x == zero { break }; // No more digits left to accumulate.
}
} else {
// Do the same as above, but accounting for two's complement.
for byte in buf.iter_mut().rev() {
let n = zero - (x % base); // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = self.digit(cast(n).unwrap()); // Store the digit in the buffer.
let n = zero - (x % base); // Get the current place value.
x = x / base; // Deaccumulate the number.
*byte = self.digit(n.to_u8()); // Store the digit in the buffer.
curr -= 1;
if x == zero { break }; // No more digits left to accumulate.
if x == zero { break }; // No more digits left to accumulate.
}
}
let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) };

View File

@ -62,7 +62,6 @@
use prelude::*;
use default::Default;
use mem;
pub use self::sip::SipHasher;

View File

@ -13,7 +13,6 @@
#![allow(deprecated)] // until the next snapshot for inherent wrapping ops
use prelude::*;
use default::Default;
use super::Hasher;
/// An implementation of SipHash 2-4.

View File

@ -64,7 +64,7 @@ use cmp::{Ord, PartialOrd, PartialEq};
use default::Default;
use marker;
use mem;
use num::{Int, Zero, One};
use num::{Zero, One};
use ops::{self, Add, Sub, FnMut, Mul, RangeFrom};
use option::Option::{self, Some, None};
use marker::Sized;
@ -2327,9 +2327,8 @@ impl<I: RandomAccessIterator, F> RandomAccessIterator for Inspect<I, F>
/// An iterator that yields sequential Fibonacci numbers, and stops on overflow.
///
/// ```
/// # #![feature(core)]
/// #![feature(core)]
/// use std::iter::Unfold;
/// use std::num::Int; // For `.checked_add()`
///
/// // This iterator will yield up to the last Fibonacci number before the max
/// // value of `u32`. You can simply change `u32` to `u64` in this line if
@ -2647,80 +2646,6 @@ impl<A: Step + Zero + Clone> Iterator for StepBy<A, ops::Range<A>> {
}
}
/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping.
#[derive(Clone)]
#[unstable(feature = "core",
reason = "likely to be replaced by range notation and adapters")]
pub struct RangeStepInclusive<A> {
state: A,
stop: A,
step: A,
rev: bool,
done: bool,
}
/// Returns an iterator over the range [start, stop] by `step`.
///
/// It handles overflow by stopping.
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::iter::range_step_inclusive;
///
/// for i in range_step_inclusive(0, 10, 2) {
/// println!("{}", i);
/// }
/// ```
///
/// This prints:
///
/// ```text
/// 0
/// 2
/// 4
/// 6
/// 8
/// 10
/// ```
#[inline]
#[unstable(feature = "core",
reason = "likely to be replaced by range notation and adapters")]
#[allow(deprecated)]
pub fn range_step_inclusive<A: Int>(start: A, stop: A, step: A) -> RangeStepInclusive<A> {
let rev = step < Int::zero();
RangeStepInclusive {
state: start,
stop: stop,
step: step,
rev: rev,
done: false,
}
}
#[unstable(feature = "core",
reason = "likely to be replaced by range notation and adapters")]
#[allow(deprecated)]
impl<A: Int> Iterator for RangeStepInclusive<A> {
type Item = A;
#[inline]
fn next(&mut self) -> Option<A> {
if !self.done && ((self.rev && self.state >= self.stop) ||
(!self.rev && self.state <= self.stop)) {
let result = self.state;
match self.state.checked_add(self.step) {
Some(x) => self.state = x,
None => self.done = true
}
Some(result)
} else {
None
}
}
}
macro_rules! range_exact_iter_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -108,6 +108,7 @@ mod uint_macros;
#[path = "num/f32.rs"] pub mod f32;
#[path = "num/f64.rs"] pub mod f64;
#[macro_use]
pub mod num;
/* The libcore prelude, not as all-encompassing as the libstd prelude */

View File

@ -35,7 +35,16 @@ use hash::Hasher;
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[allow(deprecated)]
#[cfg(not(stage0))]
pub unsafe trait Send {
// empty.
}
/// Types able to be transferred across thread boundaries.
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[cfg(stage0)]
pub unsafe trait Send : MarkerTrait {
// empty.
}
@ -51,7 +60,17 @@ impl !Send for Managed { }
#[lang="sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[allow(deprecated)]
#[cfg(not(stage0))]
pub trait Sized {
// Empty.
}
/// Types with a constant size known at compile-time.
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[cfg(stage0)]
pub trait Sized : MarkerTrait {
// Empty.
}
@ -199,13 +218,23 @@ pub trait Copy : Clone {
/// the `sync` crate do ensure that any mutation cannot cause data
/// races. Hence these types are `Sync`.
///
/// Any types with interior mutability must also use the `std::cell::UnsafeCell` wrapper around the
/// value(s) which can be mutated when behind a `&` reference; not doing this is undefined
/// behaviour (for example, `transmute`-ing from `&T` to `&mut T` is illegal).
/// Any types with interior mutability must also use the `std::cell::UnsafeCell`
/// wrapper around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
pub unsafe trait Sync {
// Empty
}
/// dox
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
#[allow(deprecated)]
pub unsafe trait Sync : MarkerTrait {
// Empty
}
@ -272,42 +301,20 @@ macro_rules! impls{
)
}
/// `MarkerTrait` is deprecated and no longer needed.
/// dox
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[allow(deprecated)]
#[cfg(stage0)]
pub trait MarkerTrait : PhantomFn<Self,Self> { }
/// `MarkerTrait` is deprecated and no longer needed.
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[allow(deprecated)]
#[cfg(not(stage0))]
pub trait MarkerTrait { }
#[cfg(stage0)]
impl<T: ?Sized> MarkerTrait for T {}
#[allow(deprecated)]
impl<T:?Sized> MarkerTrait for T { }
/// `PhantomFn` is a deprecated marker trait that is no longer needed.
/// dox
#[lang="phantom_fn"]
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[cfg(stage0)]
pub trait PhantomFn<A:?Sized,R:?Sized=()> {
}
/// `PhantomFn` is a deprecated marker trait that is no longer needed.
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[cfg(not(stage0))]
pub trait PhantomFn<A:?Sized,R:?Sized=()> {
}
#[allow(deprecated)]
#[cfg(not(stage0))]
impl<A:?Sized,R:?Sized,T:?Sized> PhantomFn<A,R> for T { }
/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
/// even though it does not. This allows you to inform the compiler about certain safety properties
/// of your code.
@ -454,8 +461,14 @@ mod impls {
#[rustc_reflect_like]
#[unstable(feature = "core", reason = "requires RFC and more experience")]
#[allow(deprecated)]
pub trait Reflect : MarkerTrait {
}
#[cfg(not(stage0))]
pub trait Reflect {}
/// dox
#[rustc_reflect_like]
#[unstable(feature = "core", reason = "requires RFC and more experience")]
#[cfg(stage0)]
pub trait Reflect: MarkerTrait {}
impl Reflect for .. { }

View File

@ -10,12 +10,17 @@
//! Exposes the NonZero lang item which provides optimization hints.
use marker::{Sized, MarkerTrait};
use marker::Sized;
use ops::Deref;
#[cfg(stage0)] use marker::MarkerTrait;
/// Unsafe trait to indicate what types are usable with the NonZero struct
#[allow(deprecated)]
pub unsafe trait Zeroable : MarkerTrait {}
#[cfg(not(stage0))]
pub unsafe trait Zeroable {}
/// Unsafe trait to indicate what types are usable with the NonZero struct
#[cfg(stage0)]
pub unsafe trait Zeroable: MarkerTrait {}
unsafe impl<T:?Sized> Zeroable for *const T {}
unsafe impl<T:?Sized> Zeroable for *mut T {}

View File

@ -16,11 +16,12 @@
#![stable(feature = "rust1", since = "1.0.0")]
use prelude::*;
use intrinsics;
use mem;
use num::Float;
use num::{Float, ParseFloatError};
use num::FpCategory as Fp;
use option::Option;
#[stable(feature = "rust1", since = "1.0.0")]
pub const RADIX: u32 = 2;
@ -33,19 +34,6 @@ pub const DIGITS: u32 = 6;
#[stable(feature = "rust1", since = "1.0.0")]
pub const EPSILON: f32 = 1.19209290e-07_f32;
/// Smallest finite f32 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f32::MIN`")]
pub const MIN_VALUE: f32 = -3.40282347e+38_f32;
/// Smallest positive, normalized f32 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f32::MIN_POSITIVE`")]
pub const MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
/// Largest finite f32 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f32::MAX`")]
pub const MAX_VALUE: f32 = 3.40282347e+38_f32;
/// Smallest finite f32 value
#[stable(feature = "rust1", since = "1.0.0")]
pub const MIN: f32 = -3.40282347e+38_f32;
@ -118,26 +106,14 @@ pub mod consts {
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_2_SQRT_PI: f32 = 1.12837916709551257389615890312154517_f32;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_2_SQRT_PI")]
pub const FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;
/// sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")]
pub const SQRT_2: f32 = 1.41421356237309504880168872420969808_f32;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to SQRT_2")]
pub const SQRT2: f32 = 1.41421356237309504880168872420969808_f32;
/// 1.0/sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_1_SQRT_2")]
pub const FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;
/// Euler's number
#[stable(feature = "rust1", since = "1.0.0")]
pub const E: f32 = 2.71828182845904523536028747135266250_f32;
@ -179,6 +155,8 @@ impl Float for f32 {
#[inline]
fn one() -> f32 { 1.0 }
from_str_radix_float_impl! { f32 }
/// Returns `true` if the number is NaN.
#[inline]
fn is_nan(self) -> bool { self != self }
@ -218,56 +196,6 @@ impl Float for f32 {
}
}
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn mantissa_digits(_: Option<f32>) -> usize { MANTISSA_DIGITS as usize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn digits(_: Option<f32>) -> usize { DIGITS as usize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn epsilon() -> f32 { EPSILON }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_exp(_: Option<f32>) -> isize { MIN_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_exp(_: Option<f32>) -> isize { MAX_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_10_exp(_: Option<f32>) -> isize { MIN_10_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_10_exp(_: Option<f32>) -> isize { MAX_10_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_value() -> f32 { MIN }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_pos_value(_: Option<f32>) -> f32 { MIN_POSITIVE }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_value() -> f32 { MAX }
/// Returns the mantissa, exponent and sign as integers.
fn integer_decode(self) -> (u64, i16, i8) {
let bits: u32 = unsafe { mem::transmute(self) };
@ -310,9 +238,6 @@ impl Float for f32 {
/// The fractional part of the number, satisfying:
///
/// ```
/// # #![feature(core)]
/// use std::num::Float;
///
/// let x = 1.65f32;
/// assert!(x == x.trunc() + x.fract())
/// ```

View File

@ -16,11 +16,12 @@
#![stable(feature = "rust1", since = "1.0.0")]
use prelude::*;
use intrinsics;
use mem;
use num::Float;
use num::FpCategory as Fp;
use option::Option;
use num::{Float, ParseFloatError};
#[stable(feature = "rust1", since = "1.0.0")]
pub const RADIX: u32 = 2;
@ -33,19 +34,6 @@ pub const DIGITS: u32 = 15;
#[stable(feature = "rust1", since = "1.0.0")]
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
/// Smallest finite f64 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f64::MIN`")]
pub const MIN_VALUE: f64 = -1.7976931348623157e+308_f64;
/// Smallest positive, normalized f64 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f64::MIN_POSITIVE`")]
pub const MIN_POS_VALUE: f64 = 2.2250738585072014e-308_f64;
/// Largest finite f64 value
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "use `std::f64::MAX`")]
pub const MAX_VALUE: f64 = 1.7976931348623157e+308_f64;
/// Smallest finite f64 value
#[stable(feature = "rust1", since = "1.0.0")]
pub const MIN: f64 = -1.7976931348623157e+308_f64;
@ -118,26 +106,14 @@ pub mod consts {
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_2_SQRT_PI: f64 = 1.12837916709551257389615890312154517_f64;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_2_SQRT_PI")]
pub const FRAC_2_SQRTPI: f64 = 1.12837916709551257389615890312154517_f64;
/// sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")]
pub const SQRT_2: f64 = 1.41421356237309504880168872420969808_f64;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to SQRT_2")]
pub const SQRT2: f64 = 1.41421356237309504880168872420969808_f64;
/// 1.0/sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64;
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_1_SQRT_2")]
pub const FRAC_1_SQRT2: f64 = 0.707106781186547524400844362104849039_f64;
/// Euler's number
#[stable(feature = "rust1", since = "1.0.0")]
pub const E: f64 = 2.71828182845904523536028747135266250_f64;
@ -179,6 +155,8 @@ impl Float for f64 {
#[inline]
fn one() -> f64 { 1.0 }
from_str_radix_float_impl! { f64 }
/// Returns `true` if the number is NaN.
#[inline]
fn is_nan(self) -> bool { self != self }
@ -218,56 +196,6 @@ impl Float for f64 {
}
}
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn mantissa_digits(_: Option<f64>) -> usize { MANTISSA_DIGITS as usize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn digits(_: Option<f64>) -> usize { DIGITS as usize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn epsilon() -> f64 { EPSILON }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_exp(_: Option<f64>) -> isize { MIN_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_exp(_: Option<f64>) -> isize { MAX_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_10_exp(_: Option<f64>) -> isize { MIN_10_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_10_exp(_: Option<f64>) -> isize { MAX_10_EXP as isize }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_value() -> f64 { MIN }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn min_pos_value(_: Option<f64>) -> f64 { MIN_POSITIVE }
#[inline]
#[unstable(feature = "core")]
#[deprecated(since = "1.0.0")]
fn max_value() -> f64 { MAX }
/// Returns the mantissa, exponent and sign as integers.
fn integer_decode(self) -> (u64, i16, i8) {
let bits: u64 = unsafe { mem::transmute(self) };
@ -310,9 +238,6 @@ impl Float for f64 {
/// The fractional part of the number, satisfying:
///
/// ```
/// # #![feature(core)]
/// use std::num::Float;
///
/// let x = 1.65f64;
/// assert!(x == x.trunc() + x.fract())
/// ```

View File

@ -18,3 +18,145 @@ macro_rules! assert_approx_eq {
"{} is not approximately equal to {}", *a, *b);
})
}
macro_rules! from_str_radix_float_impl {
($T:ty) => {
fn from_str_radix(src: &str, radix: u32)
-> Result<$T, ParseFloatError> {
use num::FloatErrorKind::*;
use num::ParseFloatError as PFE;
// Special values
match src {
"inf" => return Ok(Float::infinity()),
"-inf" => return Ok(Float::neg_infinity()),
"NaN" => return Ok(Float::nan()),
_ => {},
}
let (is_positive, src) = match src.slice_shift_char() {
None => return Err(PFE { kind: Empty }),
Some(('-', "")) => return Err(PFE { kind: Empty }),
Some(('-', src)) => (false, src),
Some((_, _)) => (true, src),
};
// The significand to accumulate
let mut sig = if is_positive { 0.0 } else { -0.0 };
// Necessary to detect overflow
let mut prev_sig = sig;
let mut cs = src.chars().enumerate();
// Exponent prefix and exponent index offset
let mut exp_info = None::<(char, usize)>;
// Parse the integer part of the significand
for (i, c) in cs.by_ref() {
match c.to_digit(radix) {
Some(digit) => {
// shift significand one digit left
sig = sig * (radix as $T);
// add/subtract current digit depending on sign
if is_positive {
sig = sig + ((digit as isize) as $T);
} else {
sig = sig - ((digit as isize) as $T);
}
// Detect overflow by comparing to last value, except
// if we've not seen any non-zero digits.
if prev_sig != 0.0 {
if is_positive && sig <= prev_sig
{ return Ok(Float::infinity()); }
if !is_positive && sig >= prev_sig
{ return Ok(Float::neg_infinity()); }
// Detect overflow by reversing the shift-and-add process
if is_positive && (prev_sig != (sig - digit as $T) / radix as $T)
{ return Ok(Float::infinity()); }
if !is_positive && (prev_sig != (sig + digit as $T) / radix as $T)
{ return Ok(Float::neg_infinity()); }
}
prev_sig = sig;
},
None => match c {
'e' | 'E' | 'p' | 'P' => {
exp_info = Some((c, i + 1));
break; // start of exponent
},
'.' => {
break; // start of fractional part
},
_ => {
return Err(PFE { kind: Invalid });
},
},
}
}
// If we are not yet at the exponent parse the fractional
// part of the significand
if exp_info.is_none() {
let mut power = 1.0;
for (i, c) in cs.by_ref() {
match c.to_digit(radix) {
Some(digit) => {
// Decrease power one order of magnitude
power = power / (radix as $T);
// add/subtract current digit depending on sign
sig = if is_positive {
sig + (digit as $T) * power
} else {
sig - (digit as $T) * power
};
// Detect overflow by comparing to last value
if is_positive && sig < prev_sig
{ return Ok(Float::infinity()); }
if !is_positive && sig > prev_sig
{ return Ok(Float::neg_infinity()); }
prev_sig = sig;
},
None => match c {
'e' | 'E' | 'p' | 'P' => {
exp_info = Some((c, i + 1));
break; // start of exponent
},
_ => {
return Err(PFE { kind: Invalid });
},
},
}
}
}
// Parse and calculate the exponent
let exp = match exp_info {
Some((c, offset)) => {
let base = match c {
'E' | 'e' if radix == 10 => 10.0,
'P' | 'p' if radix == 16 => 2.0,
_ => return Err(PFE { kind: Invalid }),
};
// Parse the exponent as decimal integer
let src = &src[offset..];
let (is_positive, exp) = match src.slice_shift_char() {
Some(('-', src)) => (false, src.parse::<usize>()),
Some(('+', src)) => (true, src.parse::<usize>()),
Some((_, _)) => (true, src.parse::<usize>()),
None => return Err(PFE { kind: Invalid }),
};
match (is_positive, exp) {
(true, Ok(exp)) => base.powi(exp as i32),
(false, Ok(exp)) => 1.0 / base.powi(exp as i32),
(_, Err(_)) => return Err(PFE { kind: Invalid }),
}
},
None => 1.0, // no exponent
};
Ok(sig * exp)
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,6 @@ use super::Wrapping;
use ops::*;
use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul};
use intrinsics::{i8_add_with_overflow, u8_add_with_overflow};
use intrinsics::{i16_add_with_overflow, u16_add_with_overflow};
use intrinsics::{i32_add_with_overflow, u32_add_with_overflow};
@ -32,14 +30,6 @@ use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};
use ::{i8,i16,i32,i64};
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
#[deprecated(since = "1.0.0", reason = "moved to inherent methods")]
pub trait WrappingOps {
fn wrapping_add(self, rhs: Self) -> Self;
fn wrapping_sub(self, rhs: Self) -> Self;
fn wrapping_mul(self, rhs: Self) -> Self;
}
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
pub trait OverflowingOps {
fn overflowing_add(self, rhs: Self) -> (Self, bool);
@ -99,27 +89,6 @@ sh_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
macro_rules! wrapping_impl {
($($t:ty)*) => ($(
impl WrappingOps for $t {
#[inline(always)]
fn wrapping_add(self, rhs: $t) -> $t {
unsafe {
overflowing_add(self, rhs)
}
}
#[inline(always)]
fn wrapping_sub(self, rhs: $t) -> $t {
unsafe {
overflowing_sub(self, rhs)
}
}
#[inline(always)]
fn wrapping_mul(self, rhs: $t) -> $t {
unsafe {
overflowing_mul(self, rhs)
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Add for Wrapping<$t> {
type Output = Wrapping<$t>;

View File

@ -551,25 +551,6 @@ impl<T> Option<T> {
IterMut { inner: Item { opt: self.as_mut() } }
}
/// Returns a consuming iterator over the possibly contained value.
///
/// # Examples
///
/// ```
/// let x = Some("string");
/// let v: Vec<&str> = x.into_iter().collect();
/// assert_eq!(v, ["string"]);
///
/// let x = None;
/// let v: Vec<&str> = x.into_iter().collect();
/// assert!(v.is_empty());
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<T> {
IntoIter { inner: Item { opt: self } }
}
/////////////////////////////////////////////////////////////////////////
// Boolean operations on the values, eager and lazy
/////////////////////////////////////////////////////////////////////////
@ -770,6 +751,30 @@ impl<T> Default for Option<T> {
fn default() -> Option<T> { None }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> IntoIterator for Option<T> {
type Item = T;
type IntoIter = IntoIter<T>;
/// Returns a consuming iterator over the possibly contained value.
///
/// # Examples
///
/// ```
/// let x = Some("string");
/// let v: Vec<&str> = x.into_iter().collect();
/// assert_eq!(v, ["string"]);
///
/// let x = None;
/// let v: Vec<&str> = x.into_iter().collect();
/// assert!(v.is_empty());
/// ```
#[inline]
fn into_iter(self) -> IntoIter<T> {
IntoIter { inner: Item { opt: self } }
}
}
/////////////////////////////////////////////////////////////////////////////
// The Option Iterators
/////////////////////////////////////////////////////////////////////////////

View File

@ -37,11 +37,10 @@ pub use char::CharExt;
pub use clone::Clone;
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
pub use convert::{AsRef, AsMut, Into, From};
pub use default::Default;
pub use iter::IntoIterator;
pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator};
pub use option::Option::{self, Some, None};
pub use result::Result::{self, Ok, Err};
pub use slice::SliceExt;
pub use str::StrExt;
#[allow(deprecated)] pub use slice::AsSlice;
#[allow(deprecated)] pub use str::Str;

View File

@ -234,8 +234,6 @@ use fmt;
use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSizeIterator, IntoIterator};
use ops::{FnMut, FnOnce};
use option::Option::{self, None, Some};
#[allow(deprecated)]
use slice::AsSlice;
use slice;
/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
@ -547,25 +545,6 @@ impl<T, E> Result<T, E> {
IterMut { inner: self.as_mut().ok() }
}
/// Returns a consuming iterator over the possibly contained value.
///
/// # Examples
///
/// ```
/// let x: Result<u32, &str> = Ok(5);
/// let v: Vec<u32> = x.into_iter().collect();
/// assert_eq!(v, [5]);
///
/// let x: Result<u32, &str> = Err("nothing!");
/// let v: Vec<u32> = x.into_iter().collect();
/// assert_eq!(v, []);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<T> {
IntoIter { inner: self.ok() }
}
////////////////////////////////////////////////////////////////////////
// Boolean operations on the values, eager and lazy
/////////////////////////////////////////////////////////////////////////
@ -787,23 +766,27 @@ impl<T: fmt::Debug, E> Result<T, E> {
// Trait implementations
/////////////////////////////////////////////////////////////////////////////
#[unstable(feature = "core",
reason = "waiting on the stability of the trait itself")]
#[deprecated(since = "1.0.0",
reason = "use inherent method instead")]
#[allow(deprecated)]
impl<T, E> AsSlice<T> for Result<T, E> {
/// Converts from `Result<T, E>` to `&[T]` (without copying)
#[stable(feature = "rust1", since = "1.0.0")]
impl<T, E> IntoIterator for Result<T, E> {
type Item = T;
type IntoIter = IntoIter<T>;
/// Returns a consuming iterator over the possibly contained value.
///
/// # Examples
///
/// ```
/// let x: Result<u32, &str> = Ok(5);
/// let v: Vec<u32> = x.into_iter().collect();
/// assert_eq!(v, [5]);
///
/// let x: Result<u32, &str> = Err("nothing!");
/// let v: Vec<u32> = x.into_iter().collect();
/// assert_eq!(v, []);
/// ```
#[inline]
fn as_slice<'a>(&'a self) -> &'a [T] {
match *self {
Ok(ref x) => slice::ref_slice(x),
Err(_) => {
// work around lack of implicit coercion from fixed-size array to slice
let emp: &[_] = &[];
emp
}
}
fn into_iter(self) -> IntoIter<T> {
IntoIter { inner: self.ok() }
}
}

View File

@ -51,7 +51,7 @@ use result::Result::{Ok, Err};
use ptr;
use mem;
use mem::size_of;
use marker::{Send, Sized, Sync, self};
use marker::{Send, Sync, self};
use raw::Repr;
// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
use raw::Slice as RawSlice;
@ -595,37 +595,6 @@ impl<T> ops::IndexMut<RangeFull> for [T] {
// Common traits
////////////////////////////////////////////////////////////////////////////////
/// Data that is viewable as a slice.
#[unstable(feature = "core",
reason = "will be replaced by slice syntax")]
#[deprecated(since = "1.0.0",
reason = "use std::convert::AsRef<[T]> instead")]
pub trait AsSlice<T> {
/// Work with `self` as a slice.
fn as_slice<'a>(&'a self) -> &'a [T];
}
#[unstable(feature = "core", reason = "trait is experimental")]
#[allow(deprecated)]
impl<T> AsSlice<T> for [T] {
#[inline(always)]
fn as_slice<'a>(&'a self) -> &'a [T] { self }
}
#[unstable(feature = "core", reason = "trait is experimental")]
#[allow(deprecated)]
impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a U {
#[inline(always)]
fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
}
#[unstable(feature = "core", reason = "trait is experimental")]
#[allow(deprecated)]
impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a mut U {
#[inline(always)]
fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Default for &'a [T] {
#[stable(feature = "rust1", since = "1.0.0")]

View File

@ -25,7 +25,6 @@ use default::Default;
use fmt;
use iter::ExactSizeIterator;
use iter::{Map, Iterator, DoubleEndedIterator};
use marker::Sized;
use mem;
use ops::{Fn, FnMut, FnOnce};
use option::Option::{self, None, Some};
@ -1463,30 +1462,6 @@ mod traits {
}
}
/// Any string that can be represented as a slice
#[unstable(feature = "core",
reason = "Instead of taking this bound generically, this trait will be \
replaced with one of slicing syntax (&foo[..]), deref coercions, or \
a more generic conversion trait")]
#[deprecated(since = "1.0.0",
reason = "use std::convert::AsRef<str> instead")]
pub trait Str {
/// Work with `self` as a slice.
fn as_slice<'a>(&'a self) -> &'a str;
}
#[allow(deprecated)]
impl Str for str {
#[inline]
fn as_slice<'a>(&'a self) -> &'a str { self }
}
#[allow(deprecated)]
impl<'a, S: ?Sized> Str for &'a S where S: Str {
#[inline]
fn as_slice(&self) -> &str { Str::as_slice(*self) }
}
/// Methods for string slices
#[allow(missing_docs)]
#[doc(hidden)]

View File

@ -110,8 +110,6 @@ fn test_partial_max() {
#[test]
fn test_user_defined_eq() {
use core::num::SignedInt;
// Our type.
struct SketchyNum {
num : isize

View File

@ -11,7 +11,6 @@
use core::iter::*;
use core::iter::order::*;
use core::iter::MinMaxResult::*;
use core::num::SignedInt;
use core::usize;
use core::cmp;
@ -783,16 +782,6 @@ fn test_range_step() {
assert_eq!((200..200).step_by(1).collect::<Vec<isize>>(), []);
}
#[test]
fn test_range_step_inclusive() {
assert_eq!(range_step_inclusive(0, 20, 5).collect::<Vec<isize>>(), [0, 5, 10, 15, 20]);
assert_eq!(range_step_inclusive(20, 0, -5).collect::<Vec<isize>>(), [20, 15, 10, 5, 0]);
assert_eq!(range_step_inclusive(20, 0, -6).collect::<Vec<isize>>(), [20, 14, 8, 2]);
assert_eq!(range_step_inclusive(200, 255, 50).collect::<Vec<u8>>(), [200, 250]);
assert_eq!(range_step_inclusive(200, -5, 1).collect::<Vec<isize>>(), []);
assert_eq!(range_step_inclusive(200, 200, 1).collect::<Vec<isize>>(), [200]);
}
#[test]
fn test_reverse() {
let mut ys = [1, 2, 3, 4, 5];

View File

@ -10,8 +10,8 @@
// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![feature(box_syntax)]
#![feature(int_uint)]
#![feature(unboxed_closures)]
#![feature(unsafe_destructor)]
#![feature(core)]
@ -21,13 +21,11 @@
#![feature(std_misc)]
#![feature(libc)]
#![feature(hash)]
#![feature(io)]
#![feature(collections)]
#![feature(debug_builders)]
#![feature(unique)]
#![feature(step_by)]
#![feature(slice_patterns)]
#![allow(deprecated)] // rand
#![feature(float_from_str_radix)]
extern crate core;
extern crate test;

View File

@ -8,12 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
macro_rules! int_module { ($T:ty, $T_i:ident) => (
macro_rules! int_module { ($T:ident, $T_i:ident) => (
#[cfg(test)]
mod tests {
use core::$T_i::*;
use core::isize;
use core::num::{FromStrRadix, Int, SignedInt};
use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr};
use num;
@ -129,30 +128,30 @@ mod tests {
#[test]
fn test_le() {
assert_eq!(Int::from_le(A.to_le()), A);
assert_eq!(Int::from_le(B.to_le()), B);
assert_eq!(Int::from_le(C.to_le()), C);
assert_eq!(Int::from_le(_0), _0);
assert_eq!(Int::from_le(_1), _1);
assert_eq!($T::from_le(A.to_le()), A);
assert_eq!($T::from_le(B.to_le()), B);
assert_eq!($T::from_le(C.to_le()), C);
assert_eq!($T::from_le(_0), _0);
assert_eq!($T::from_le(_1), _1);
assert_eq!(_0.to_le(), _0);
assert_eq!(_1.to_le(), _1);
}
#[test]
fn test_be() {
assert_eq!(Int::from_be(A.to_be()), A);
assert_eq!(Int::from_be(B.to_be()), B);
assert_eq!(Int::from_be(C.to_be()), C);
assert_eq!(Int::from_be(_0), _0);
assert_eq!(Int::from_be(_1), _1);
assert_eq!($T::from_be(A.to_be()), A);
assert_eq!($T::from_be(B.to_be()), B);
assert_eq!($T::from_be(C.to_be()), C);
assert_eq!($T::from_be(_0), _0);
assert_eq!($T::from_be(_1), _1);
assert_eq!(_0.to_be(), _0);
assert_eq!(_1.to_be(), _1);
}
#[test]
fn test_signed_checked_div() {
assert!(10.checked_div(2) == Some(5));
assert!(5.checked_div(0) == None);
assert!((10 as $T).checked_div(2) == Some(5));
assert!((5 as $T).checked_div(0) == None);
assert!(isize::MIN.checked_div(-1) == None);
}
@ -180,26 +179,26 @@ mod tests {
#[test]
fn test_from_str_radix() {
assert_eq!(FromStrRadix::from_str_radix("123", 10), Ok(123 as $T));
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Ok(9 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 8), Ok(83 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 16), Ok(291 as i32));
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Ok(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Ok(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("z", 36), Ok(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 36), Ok(35 as $T));
assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32));
assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 10), Ok(-123 as $T));
assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Ok(-9 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 8), Ok(-83 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 16), Ok(-291 as i32));
assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Ok(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-z", 36), Ok(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Ok(-35 as $T));
assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T));
assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T));
assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T));
assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 35).ok(), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("-9", 2).ok(), None::<$T>);
assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
}
#[test]

View File

@ -10,7 +10,6 @@
use core::cmp::PartialEq;
use core::fmt::Debug;
use core::num::{NumCast, cast};
use core::ops::{Add, Sub, Mul, Div, Rem};
use core::marker::Copy;
@ -32,18 +31,12 @@ mod u64;
/// Helper function for testing numeric operations
pub fn test_num<T>(ten: T, two: T) where
T: PartialEq + NumCast
T: PartialEq
+ Add<Output=T> + Sub<Output=T>
+ Mul<Output=T> + Div<Output=T>
+ Rem<Output=T> + Debug
+ Copy
{
assert_eq!(ten.add(two), cast(12).unwrap());
assert_eq!(ten.sub(two), cast(8).unwrap());
assert_eq!(ten.mul(two), cast(20).unwrap());
assert_eq!(ten.div(two), cast(5).unwrap());
assert_eq!(ten.rem(two), cast(0).unwrap());
assert_eq!(ten.add(two), ten + two);
assert_eq!(ten.sub(two), ten - two);
assert_eq!(ten.mul(two), ten * two);
@ -56,33 +49,33 @@ mod test {
use core::option::Option;
use core::option::Option::{Some, None};
use core::num::Float;
use core::num::from_str_radix;
#[test]
fn from_str_issue7588() {
let u : Option<u8> = from_str_radix("1000", 10).ok();
let u : Option<u8> = u8::from_str_radix("1000", 10).ok();
assert_eq!(u, None);
let s : Option<i16> = from_str_radix("80000", 10).ok();
let s : Option<i16> = i16::from_str_radix("80000", 10).ok();
assert_eq!(s, None);
let f : Option<f32> = from_str_radix("10000000000000000000000000000000000000000", 10).ok();
let s = "10000000000000000000000000000000000000000";
let f : Option<f32> = f32::from_str_radix(s, 10).ok();
assert_eq!(f, Some(Float::infinity()));
let fe : Option<f32> = from_str_radix("1e40", 10).ok();
let fe : Option<f32> = f32::from_str_radix("1e40", 10).ok();
assert_eq!(fe, Some(Float::infinity()));
}
#[test]
fn test_from_str_radix_float() {
let x1 : Option<f64> = from_str_radix("-123.456", 10).ok();
let x1 : Option<f64> = f64::from_str_radix("-123.456", 10).ok();
assert_eq!(x1, Some(-123.456));
let x2 : Option<f32> = from_str_radix("123.456", 10).ok();
let x2 : Option<f32> = f32::from_str_radix("123.456", 10).ok();
assert_eq!(x2, Some(123.456));
let x3 : Option<f32> = from_str_radix("-0.0", 10).ok();
let x3 : Option<f32> = f32::from_str_radix("-0.0", 10).ok();
assert_eq!(x3, Some(-0.0));
let x4 : Option<f32> = from_str_radix("0.0", 10).ok();
let x4 : Option<f32> = f32::from_str_radix("0.0", 10).ok();
assert_eq!(x4, Some(0.0));
let x4 : Option<f32> = from_str_radix("1.0", 10).ok();
let x4 : Option<f32> = f32::from_str_radix("1.0", 10).ok();
assert_eq!(x4, Some(1.0));
let x5 : Option<f32> = from_str_radix("-1.0", 10).ok();
let x5 : Option<f32> = f32::from_str_radix("-1.0", 10).ok();
assert_eq!(x5, Some(-1.0));
}

View File

@ -8,11 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
macro_rules! uint_module { ($T:ty, $T_i:ident) => (
macro_rules! uint_module { ($T:ident, $T_i:ident) => (
#[cfg(test)]
mod tests {
use core::$T_i::*;
use core::num::Int;
use num;
use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not};
@ -97,30 +96,30 @@ mod tests {
#[test]
fn test_le() {
assert_eq!(Int::from_le(A.to_le()), A);
assert_eq!(Int::from_le(B.to_le()), B);
assert_eq!(Int::from_le(C.to_le()), C);
assert_eq!(Int::from_le(_0), _0);
assert_eq!(Int::from_le(_1), _1);
assert_eq!($T::from_le(A.to_le()), A);
assert_eq!($T::from_le(B.to_le()), B);
assert_eq!($T::from_le(C.to_le()), C);
assert_eq!($T::from_le(_0), _0);
assert_eq!($T::from_le(_1), _1);
assert_eq!(_0.to_le(), _0);
assert_eq!(_1.to_le(), _1);
}
#[test]
fn test_be() {
assert_eq!(Int::from_be(A.to_be()), A);
assert_eq!(Int::from_be(B.to_be()), B);
assert_eq!(Int::from_be(C.to_be()), C);
assert_eq!(Int::from_be(_0), _0);
assert_eq!(Int::from_be(_1), _1);
assert_eq!($T::from_be(A.to_be()), A);
assert_eq!($T::from_be(B.to_be()), B);
assert_eq!($T::from_be(C.to_be()), C);
assert_eq!($T::from_be(_0), _0);
assert_eq!($T::from_be(_1), _1);
assert_eq!(_0.to_be(), _0);
assert_eq!(_1.to_be(), _1);
}
#[test]
fn test_unsigned_checked_div() {
assert!(10.checked_div(2) == Some(5));
assert!(5.checked_div(0) == None);
assert!((10 as $T).checked_div(2) == Some(5));
assert!((5 as $T).checked_div(0) == None);
}
}

View File

@ -91,7 +91,6 @@
#![deny(missing_docs)]
#![feature(staged_api)]
#![feature(str_words)]
#![feature(str_char)]
#![cfg_attr(test, feature(rustc_private))]
@ -771,7 +770,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String {
// Normalize desc to contain words separated by one space character
let mut desc_normalized_whitespace = String::new();
for word in desc.words() {
for word in desc.split_whitespace() {
desc_normalized_whitespace.push_str(word);
desc_normalized_whitespace.push(' ');
}

View File

@ -3536,6 +3536,30 @@ pub mod consts {
pub const IPV6_DROP_MEMBERSHIP: c_int = 21;
pub const TCP_NODELAY: c_int = 1;
pub const TCP_MAXSEG: c_int = 2;
pub const TCP_CORK: c_int = 3;
pub const TCP_KEEPIDLE: c_int = 4;
pub const TCP_KEEPINTVL: c_int = 5;
pub const TCP_KEEPCNT: c_int = 6;
pub const TCP_SYNCNT: c_int = 7;
pub const TCP_LINGER2: c_int = 8;
pub const TCP_DEFER_ACCEPT: c_int = 9;
pub const TCP_WINDOW_CLAMP: c_int = 10;
pub const TCP_INFO: c_int = 11;
pub const TCP_QUICKACK: c_int = 12;
pub const TCP_CONGESTION: c_int = 13;
pub const TCP_MD5SIG: c_int = 14;
pub const TCP_COOKIE_TRANSACTIONS: c_int = 15;
pub const TCP_THIN_LINEAR_TIMEOUTS: c_int = 16;
pub const TCP_THIN_DUPACK: c_int = 17;
pub const TCP_USER_TIMEOUT: c_int = 18;
pub const TCP_REPAIR: c_int = 19;
pub const TCP_REPAIR_QUEUE: c_int = 20;
pub const TCP_QUEUE_SEQ: c_int = 21;
pub const TCP_REPAIR_OPTIONS: c_int = 22;
pub const TCP_FASTOPEN: c_int = 23;
pub const TCP_TIMESTAMP: c_int = 24;
pub const SOL_SOCKET: c_int = 1;
pub const SO_DEBUG: c_int = 1;

View File

@ -11,8 +11,6 @@
//! The ChaCha random number generator.
use core::prelude::*;
use core::num::Int;
use core::num::wrapping::WrappingOps;
use {Rng, SeedableRng, Rand};
const KEY_WORDS : usize = 8; // 8 words for the 256-bit key

View File

@ -18,7 +18,7 @@
//! that do not need to record state.
use core::prelude::*;
use core::num::{Float, Int};
use core::num::Float;
use core::marker::PhantomData;
use {Rng, Rand};

View File

@ -13,8 +13,6 @@
// this is surprisingly complicated to be both generic & correct
use core::prelude::PartialOrd;
use core::num::Int;
use core::num::wrapping::WrappingOps;
use Rng;
use distributions::{Sample, IndependentSample};
@ -73,7 +71,7 @@ pub trait SampleRange {
}
macro_rules! integer_impl {
($ty:ty, $unsigned:ty) => {
($ty:ident, $unsigned:ident) => {
impl SampleRange for $ty {
// we play free and fast with unsigned vs signed here
// (when $ty is signed), but that's fine, since the
@ -83,7 +81,7 @@ macro_rules! integer_impl {
fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
let range = (high as $unsigned).wrapping_sub(low as $unsigned);
let unsigned_max: $unsigned = Int::max_value();
let unsigned_max: $unsigned = $unsigned::max_value();
// this is the largest number that fits into $unsigned
// that `range` divides evenly, so, if we've sampled
@ -148,7 +146,6 @@ float_impl! { f64 }
#[cfg(test)]
mod tests {
use std::num::Int;
use std::prelude::v1::*;
use distributions::{Sample, IndependentSample};
use super::Range as Range;
@ -168,11 +165,11 @@ mod tests {
fn test_integers() {
let mut rng = ::test::rng();
macro_rules! t {
($($ty:ty),*) => {{
($($ty:ident),*) => {{
$(
let v: &[($ty, $ty)] = &[(0, 10),
(10, 127),
(Int::min_value(), Int::max_value())];
($ty::min_value(), $ty::max_value())];
for &(low, high) in v {
let mut sampler: Range<$ty> = Range::new(low, high);
for _ in 0..1000 {

View File

@ -14,7 +14,6 @@
use core::prelude::*;
use {Rng, SeedableRng};
use core::default::Default;
/// How many bytes of entropy the underling RNG is allowed to generate
/// before it is reseeded.
@ -126,7 +125,6 @@ mod test {
use core::iter::{order, repeat};
use super::{ReseedingRng, ReseedWithDefault};
use std::default::Default;
use {SeedableRng, Rng};
struct Counter {

View File

@ -836,7 +836,6 @@ pub mod writer {
use std::io::prelude::*;
use std::io::{self, SeekFrom, Cursor};
use std::slice::bytes;
use std::num::ToPrimitive;
use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
@ -1070,10 +1069,10 @@ pub mod writer {
impl<'a> Encoder<'a> {
// used internally to emit things like the vector length and so on
fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult {
if let Some(v) = v.to_u8() {
self.wr_tagged_raw_u8(EsSub8 as usize, v)
} else if let Some(v) = v.to_u32() {
self.wr_tagged_raw_u32(EsSub32 as usize, v)
if v as u8 as usize == v {
self.wr_tagged_raw_u8(EsSub8 as usize, v as u8)
} else if v as u32 as usize == v {
self.wr_tagged_raw_u32(EsSub32 as usize, v as u32)
} else {
Err(io::Error::new(io::ErrorKind::Other,
&format!("length or variant id too big: {}",
@ -1101,21 +1100,24 @@ pub mod writer {
self.emit_u64(v as u64)
}
fn emit_u64(&mut self, v: u64) -> EncodeResult {
match v.to_u32() {
Some(v) => self.emit_u32(v),
None => self.wr_tagged_raw_u64(EsU64 as usize, v)
if v as u32 as u64 == v {
self.emit_u32(v as u32)
} else {
self.wr_tagged_raw_u64(EsU64 as usize, v)
}
}
fn emit_u32(&mut self, v: u32) -> EncodeResult {
match v.to_u16() {
Some(v) => self.emit_u16(v),
None => self.wr_tagged_raw_u32(EsU32 as usize, v)
if v as u16 as u32 == v {
self.emit_u16(v as u16)
} else {
self.wr_tagged_raw_u32(EsU32 as usize, v)
}
}
fn emit_u16(&mut self, v: u16) -> EncodeResult {
match v.to_u8() {
Some(v) => self.emit_u8(v),
None => self.wr_tagged_raw_u16(EsU16 as usize, v)
if v as u8 as u16 == v {
self.emit_u8(v as u8)
} else {
self.wr_tagged_raw_u16(EsU16 as usize, v)
}
}
fn emit_u8(&mut self, v: u8) -> EncodeResult {
@ -1126,21 +1128,24 @@ pub mod writer {
self.emit_i64(v as i64)
}
fn emit_i64(&mut self, v: i64) -> EncodeResult {
match v.to_i32() {
Some(v) => self.emit_i32(v),
None => self.wr_tagged_raw_i64(EsI64 as usize, v)
if v as i32 as i64 == v {
self.emit_i32(v as i32)
} else {
self.wr_tagged_raw_i64(EsI64 as usize, v)
}
}
fn emit_i32(&mut self, v: i32) -> EncodeResult {
match v.to_i16() {
Some(v) => self.emit_i16(v),
None => self.wr_tagged_raw_i32(EsI32 as usize, v)
if v as i16 as i32 == v {
self.emit_i16(v as i16)
} else {
self.wr_tagged_raw_i32(EsI32 as usize, v)
}
}
fn emit_i16(&mut self, v: i16) -> EncodeResult {
match v.to_i8() {
Some(v) => self.emit_i8(v),
None => self.wr_tagged_raw_i16(EsI16 as usize, v)
if v as i8 as i16 == v {
self.emit_i8(v as i8)
} else {
self.wr_tagged_raw_i16(EsI16 as usize, v)
}
}
fn emit_i8(&mut self, v: i8) -> EncodeResult {

View File

@ -208,7 +208,7 @@ fn main() {
unsafe { f(); }
}
See also http://doc.rust-lang.org/book/unsafe-code.html
See also http://doc.rust-lang.org/book/unsafe.html
"##,
E0152: r##"

View File

@ -38,7 +38,6 @@
#![feature(staged_api)]
#![feature(std_misc)]
#![feature(path_ext)]
#![feature(str_words)]
#![feature(str_char)]
#![feature(into_cow)]
#![feature(slice_patterns)]
@ -69,6 +68,9 @@ extern crate test;
pub use rustc_llvm as llvm;
#[macro_use]
mod macros;
// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;
@ -142,6 +144,7 @@ pub mod util {
pub mod ppaux;
pub mod nodemap;
pub mod lev_distance;
pub mod num;
}
pub mod lib {

46
src/librustc/macros.rs Normal file
View File

@ -0,0 +1,46 @@
// 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.
macro_rules! enum_from_u32 {
($(#[$attr:meta])* pub enum $name:ident {
$($variant:ident = $e:expr,)*
}) => {
$(#[$attr])*
pub enum $name {
$($variant = $e),*
}
impl $name {
pub fn from_u32(u: u32) -> Option<$name> {
$(if u == $name::$variant as u32 {
return Some($name::$variant)
})*
None
}
}
};
($(#[$attr:meta])* pub enum $name:ident {
$($variant:ident,)*
}) => {
$(#[$attr])*
pub enum $name {
$($variant,)*
}
impl $name {
pub fn from_u32(u: u32) -> Option<$name> {
$(if u == $name::$variant as u32 {
return Some($name::$variant)
})*
None
}
}
}
}

View File

@ -116,37 +116,39 @@ pub const tag_items_data_item_reexport_def_id: usize = 0x47;
pub const tag_items_data_item_reexport_name: usize = 0x48;
// used to encode crate_ctxt side tables
#[derive(Copy, Clone, PartialEq, FromPrimitive)]
#[repr(usize)]
pub enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_ast = 0x50,
enum_from_u32! {
#[derive(Copy, Clone, PartialEq)]
#[repr(usize)]
pub enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_ast = 0x50,
tag_tree = 0x51,
tag_tree = 0x51,
tag_id_range = 0x52,
tag_id_range = 0x52,
tag_table = 0x53,
// GAP 0x54, 0x55
tag_table_def = 0x56,
tag_table_node_type = 0x57,
tag_table_item_subst = 0x58,
tag_table_freevars = 0x59,
tag_table_tcache = 0x5a,
tag_table_param_defs = 0x5b,
tag_table_mutbl = 0x5c,
tag_table_last_use = 0x5d,
tag_table_spill = 0x5e,
tag_table_method_map = 0x5f,
tag_table_vtable_map = 0x60,
tag_table_adjustments = 0x61,
tag_table_moves_map = 0x62,
tag_table_capture_map = 0x63,
tag_table_closure_tys = 0x64,
tag_table_closure_kinds = 0x65,
tag_table_upvar_capture_map = 0x66,
tag_table_capture_modes = 0x67,
tag_table_object_cast_map = 0x68,
tag_table_const_qualif = 0x69,
tag_table = 0x53,
// GAP 0x54, 0x55
tag_table_def = 0x56,
tag_table_node_type = 0x57,
tag_table_item_subst = 0x58,
tag_table_freevars = 0x59,
tag_table_tcache = 0x5a,
tag_table_param_defs = 0x5b,
tag_table_mutbl = 0x5c,
tag_table_last_use = 0x5d,
tag_table_spill = 0x5e,
tag_table_method_map = 0x5f,
tag_table_vtable_map = 0x60,
tag_table_adjustments = 0x61,
tag_table_moves_map = 0x62,
tag_table_capture_map = 0x63,
tag_table_closure_tys = 0x64,
tag_table_closure_kinds = 0x65,
tag_table_upvar_capture_map = 0x66,
tag_table_capture_modes = 0x67,
tag_table_object_cast_map = 0x68,
tag_table_const_qualif = 0x69,
}
}
pub const tag_item_trait_item_sort: usize = 0x70;

View File

@ -68,11 +68,13 @@ pub enum LinkagePreference {
RequireStatic,
}
#[derive(Copy, Clone, PartialEq, FromPrimitive)]
pub enum NativeLibraryKind {
NativeStatic, // native static library (.a archive)
NativeFramework, // OSX-specific
NativeUnknown, // default way to specify a dynamic library
enum_from_u32! {
#[derive(Copy, Clone, PartialEq)]
pub enum NativeLibraryKind {
NativeStatic, // native static library (.a archive)
NativeFramework, // OSX-specific
NativeUnknown, // default way to specify a dynamic library
}
}
// Where a crate came from on the local filesystem. One of these two options

View File

@ -35,7 +35,6 @@ use std::collections::HashMap;
use std::hash::{self, Hash, SipHasher};
use std::io::prelude::*;
use std::io;
use std::num::FromPrimitive;
use std::rc::Rc;
use std::slice::bytes;
use std::str;
@ -1349,7 +1348,7 @@ pub fn get_native_libraries(cdata: Cmd)
let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind);
let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name);
let kind: cstore::NativeLibraryKind =
FromPrimitive::from_u32(reader::doc_as_u32(kind_doc)).unwrap();
cstore::NativeLibraryKind::from_u32(reader::doc_as_u32(kind_doc)).unwrap();
let name = name_doc.as_str().to_string();
result.push((kind, name));
true
@ -1359,7 +1358,7 @@ pub fn get_native_libraries(cdata: Cmd)
pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn)
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
.map(|doc| reader::doc_as_u32(doc))
}
pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
@ -1407,7 +1406,7 @@ pub fn get_missing_lang_items(cdata: Cmd)
let mut result = Vec::new();
reader::tagged_docs(items, tag_lang_items_missing, |missing_docs| {
let item: lang_items::LangItem =
FromPrimitive::from_u32(reader::doc_as_u32(missing_docs)).unwrap();
lang_items::LangItem::from_u32(reader::doc_as_u32(missing_docs)).unwrap();
result.push(item);
true
});

View File

@ -692,11 +692,16 @@ pub fn note_crate_name(diag: &SpanHandler, name: &str) {
impl ArchiveMetadata {
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
let data = match ar.read(METADATA_FILENAME) {
Some(data) => data as *const [u8],
None => {
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
return None;
let data = {
let section = ar.iter().find(|sect| {
sect.name() == Some(METADATA_FILENAME)
});
match section {
Some(s) => s.data() as *const [u8],
None => {
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
return None;
}
}
};

View File

@ -41,7 +41,6 @@ use syntax;
use std::cell::Cell;
use std::io::SeekFrom;
use std::io::prelude::*;
use std::num::FromPrimitive;
use std::rc::Rc;
use std::fmt::Debug;
@ -1713,7 +1712,8 @@ fn decode_side_tables(dcx: &DecodeContext,
debug!(">> Side table document with tag 0x{:x} \
found for id {} (orig {})",
tag, id, id0);
let decoded_tag: Option<c::astencode_tag> = FromPrimitive::from_usize(tag);
let tag = tag as u32;
let decoded_tag: Option<c::astencode_tag> = c::astencode_tag::from_u32(tag);
match decoded_tag {
None => {
dcx.tcx.sess.bug(

View File

@ -20,6 +20,7 @@ use middle::{astencode, def};
use middle::pat_util::def_to_path;
use middle::ty::{self, Ty};
use middle::astconv_util::ast_ty_to_prim_ty;
use util::num::ToPrimitive;
use syntax::ast::{self, Expr};
use syntax::codemap::Span;
@ -30,7 +31,6 @@ use syntax::{ast_map, ast_util, codemap};
use std::borrow::{Cow, IntoCow};
use std::num::wrapping::OverflowingOps;
use std::num::ToPrimitive;
use std::cmp::Ordering;
use std::collections::hash_map::Entry::Vacant;
use std::{i8, i16, i32, i64};

View File

@ -36,7 +36,6 @@ use syntax::visit::Visitor;
use syntax::visit;
use std::iter::Enumerate;
use std::num::FromPrimitive;
use std::slice;
// The actual lang items defined come at the end of this file in one handy table.
@ -46,9 +45,12 @@ macro_rules! lets_do_this {
$( $variant:ident, $name:expr, $method:ident; )*
) => {
#[derive(Copy, Clone, FromPrimitive, PartialEq, Eq, Hash)]
pub enum LangItem {
$($variant),*
enum_from_u32! {
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub enum LangItem {
$($variant,)*
}
}
pub struct LanguageItems {
@ -71,7 +73,7 @@ impl LanguageItems {
}
pub fn item_name(index: usize) -> &'static str {
let item: Option<LangItem> = FromPrimitive::from_usize(index);
let item: Option<LangItem> = LangItem::from_u32(index as u32);
match item {
$( Some($variant) => $name, )*
None => "???"

View File

@ -63,6 +63,7 @@ use util::ppaux::{Repr, UserString};
use util::common::{memoized, ErrorReported};
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
use util::nodemap::FnvHashMap;
use util::num::ToPrimitive;
use arena::TypedArena;
use std::borrow::{Borrow, Cow};
@ -71,7 +72,6 @@ use std::cmp;
use std::fmt;
use std::hash::{Hash, SipHasher, Hasher};
use std::mem;
use std::num::ToPrimitive;
use std::ops;
use std::rc::Rc;
use std::vec::IntoIter;

View File

@ -418,7 +418,7 @@ macro_rules! options {
-> bool {
match v {
Some(s) => {
for s in s.words() {
for s in s.split_whitespace() {
slot.push(s.to_string());
}
true
@ -431,7 +431,7 @@ macro_rules! options {
-> bool {
match v {
Some(s) => {
let v = s.words().map(|s| s.to_string()).collect();
let v = s.split_whitespace().map(|s| s.to_string()).collect();
*slot = Some(v);
true
},

98
src/librustc/util/num.rs Normal file
View File

@ -0,0 +1,98 @@
// 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.
pub trait ToPrimitive {
fn to_i8(&self) -> Option<i8>;
fn to_i16(&self) -> Option<i16>;
fn to_i32(&self) -> Option<i32>;
fn to_i64(&self) -> Option<i64>;
fn to_u8(&self) -> Option<u8>;
fn to_u16(&self) -> Option<u16>;
fn to_u32(&self) -> Option<u32>;
fn to_u64(&self) -> Option<u64>;
}
impl ToPrimitive for i64 {
fn to_i8(&self) -> Option<i8> {
if *self < i8::min_value() as i64 || *self > i8::max_value() as i64 {
None
} else {
Some(*self as i8)
}
}
fn to_i16(&self) -> Option<i16> {
if *self < i16::min_value() as i64 || *self > i16::max_value() as i64 {
None
} else {
Some(*self as i16)
}
}
fn to_i32(&self) -> Option<i32> {
if *self < i32::min_value() as i64 || *self > i32::max_value() as i64 {
None
} else {
Some(*self as i32)
}
}
fn to_i64(&self) -> Option<i64> {
Some(*self)
}
fn to_u8(&self) -> Option<u8> {
if *self < 0 || *self > u8::max_value() as i64 {
None
} else {
Some(*self as u8)
}
}
fn to_u16(&self) -> Option<u16> {
if *self < 0 || *self > u16::max_value() as i64 {
None
} else {
Some(*self as u16)
}
}
fn to_u32(&self) -> Option<u32> {
if *self < 0 || *self > u32::max_value() as i64 {
None
} else {
Some(*self as u32)
}
}
fn to_u64(&self) -> Option<u64> {
if *self < 0 {None} else {Some(*self as u64)}
}
}
impl ToPrimitive for u64 {
fn to_i8(&self) -> Option<i8> {
if *self > i8::max_value() as u64 {None} else {Some(*self as i8)}
}
fn to_i16(&self) -> Option<i16> {
if *self > i16::max_value() as u64 {None} else {Some(*self as i16)}
}
fn to_i32(&self) -> Option<i32> {
if *self > i32::max_value() as u64 {None} else {Some(*self as i32)}
}
fn to_i64(&self) -> Option<i64> {
if *self > i64::max_value() as u64 {None} else {Some(*self as i64)}
}
fn to_u8(&self) -> Option<u8> {
if *self > u8::max_value() as u64 {None} else {Some(*self as u8)}
}
fn to_u16(&self) -> Option<u16> {
if *self > u16::max_value() as u64 {None} else {Some(*self as u16)}
}
fn to_u32(&self) -> Option<u32> {
if *self > u32::max_value() as u64 {None} else {Some(*self as u32)}
}
fn to_u64(&self) -> Option<u64> {
Some(*self)
}
}

View File

@ -11,13 +11,14 @@
//! A helper class for dealing with static archives
use std::env;
use std::fs;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io;
use std::path::{Path, PathBuf};
use std::process::{Command, Output, Stdio};
use std::str;
use syntax::diagnostic::Handler as ErrorHandler;
use rustc_llvm::archive_ro::ArchiveRO;
use tempdir::TempDir;
@ -282,17 +283,14 @@ impl<'a> ArchiveBuilder<'a> {
mut skip: F) -> io::Result<()>
where F: FnMut(&str) -> bool,
{
let loc = TempDir::new("rsar").unwrap();
// 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);
run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
"x", Some(loc.path()), &[&archive]);
let archive = match ArchiveRO::open(archive) {
Some(ar) => ar,
None => return Err(io::Error::new(io::ErrorKind::Other,
"failed to open archive")),
};
// Next, we must rename all of the inputs to "guaranteed unique names".
// We move each file into `self.work_dir` under its new unique name.
// We write each file into `self.work_dir` under its new unique name.
// The reason for this renaming is that archives are keyed off the name
// of the files, so if two files have the same name they will override
// one another in the archive (bad).
@ -300,27 +298,46 @@ impl<'a> ArchiveBuilder<'a> {
// We skip any files explicitly desired for skipping, and we also skip
// all SYMDEF files as these are just magical placeholders which get
// re-created when we make a new archive anyway.
let files = try!(fs::read_dir(loc.path()));
for file in files {
let file = try!(file).path();
let filename = file.file_name().unwrap().to_str().unwrap();
if skip(filename) { continue }
if filename.contains(".SYMDEF") { continue }
let filename = format!("r-{}-{}", name, filename);
// LLDB (as mentioned in back::link) crashes on filenames of exactly
// 16 bytes in length. If we're including an object file with
// exactly 16-bytes of characters, give it some prefix so that it's
// not 16 bytes.
let filename = if filename.len() == 16 {
format!("lldb-fix-{}", filename)
} else {
filename
for file in archive.iter() {
let filename = match file.name() {
Some(s) => s,
None => continue,
};
let new_filename = self.work_dir.path().join(&filename[..]);
try!(fs::rename(&file, &new_filename));
self.members.push(PathBuf::from(filename));
if filename.contains(".SYMDEF") { continue }
if skip(filename) { continue }
// An archive can contain files of the same name multiple times, so
// we need to be sure to not have them overwrite one another when we
// extract them. Consequently we need to find a truly unique file
// name for us!
let mut new_filename = String::new();
for n in 0.. {
let n = if n == 0 {String::new()} else {format!("-{}", n)};
new_filename = format!("r{}-{}-{}", n, name, filename);
// LLDB (as mentioned in back::link) crashes on filenames of
// exactly
// 16 bytes in length. If we're including an object file with
// exactly 16-bytes of characters, give it some prefix so
// that it's not 16 bytes.
new_filename = if new_filename.len() == 16 {
format!("lldb-fix-{}", new_filename)
} else {
new_filename
};
let present = self.members.iter().filter_map(|p| {
p.file_name().and_then(|f| f.to_str())
}).any(|s| s == new_filename);
if !present {
break
}
}
let dst = self.work_dir.path().join(&new_filename);
try!(try!(File::create(&dst)).write_all(file.data()));
self.members.push(PathBuf::from(new_filename));
}
Ok(())
}
}

View File

@ -46,6 +46,7 @@
extern crate syntax;
extern crate libc;
extern crate serialize;
extern crate rustc_llvm;
#[macro_use] extern crate log;
pub mod abi;

View File

@ -12,10 +12,7 @@
//! use. This implementation is not intended for external use or for any use where security is
//! important.
#![allow(deprecated)] // to_be32
use std::iter::repeat;
use std::num::Int;
use std::slice::bytes::{MutableByteVector, copy_memory};
use serialize::hex::ToHex;
@ -61,10 +58,10 @@ impl ToBits for u64 {
/// Adds the specified number of bytes to the bit count. panic!() if this would cause numeric
/// overflow.
fn add_bytes_to_bits<T: Int + ToBits>(bits: T, bytes: T) -> T {
fn add_bytes_to_bits(bits: u64, bytes: u64) -> u64 {
let (new_high_bits, new_low_bits) = bytes.to_bits();
if new_high_bits > T::zero() {
if new_high_bits > 0 {
panic!("numeric overflow occurred.")
}
@ -543,14 +540,14 @@ mod tests {
// A normal addition - no overflow occurs
#[test]
fn test_add_bytes_to_bits_ok() {
assert!(super::add_bytes_to_bits::<u64>(100, 10) == 180);
assert!(super::add_bytes_to_bits(100, 10) == 180);
}
// A simple failure case - adding 1 to the max value
#[test]
#[should_panic]
fn test_add_bytes_to_bits_overflow() {
super::add_bytes_to_bits::<u64>(u64::MAX, 1);
super::add_bytes_to_bits(u64::MAX, 1);
}
struct Test {

View File

@ -10,15 +10,23 @@
//! A wrapper around LLVM's archive (.a) code
use libc;
use ArchiveRef;
use std::ffi::CString;
use std::slice;
use std::path::Path;
use std::slice;
use std::str;
pub struct ArchiveRO {
ptr: ArchiveRef,
pub struct ArchiveRO { ptr: ArchiveRef }
pub struct Iter<'a> {
archive: &'a ArchiveRO,
ptr: ::ArchiveIteratorRef,
}
pub struct Child<'a> {
name: Option<&'a str>,
data: &'a [u8],
}
impl ArchiveRO {
@ -52,18 +60,9 @@ impl ArchiveRO {
}
}
/// Reads a file in the archive
pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
pub fn iter(&self) -> Iter {
unsafe {
let mut size = 0 as libc::size_t;
let file = CString::new(file).unwrap();
let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(),
&mut size);
if ptr.is_null() {
None
} else {
Some(slice::from_raw_parts(ptr as *const u8, size as usize))
}
Iter { ptr: ::LLVMRustArchiveIteratorNew(self.ptr), archive: self }
}
}
}
@ -75,3 +74,47 @@ impl Drop for ArchiveRO {
}
}
}
impl<'a> Iterator for Iter<'a> {
type Item = Child<'a>;
fn next(&mut self) -> Option<Child<'a>> {
unsafe {
let ptr = ::LLVMRustArchiveIteratorCurrent(self.ptr);
if ptr.is_null() {
return None
}
let mut name_len = 0;
let name_ptr = ::LLVMRustArchiveChildName(ptr, &mut name_len);
let mut data_len = 0;
let data_ptr = ::LLVMRustArchiveChildData(ptr, &mut data_len);
let child = Child {
name: if name_ptr.is_null() {
None
} else {
let name = slice::from_raw_parts(name_ptr as *const u8,
name_len as usize);
str::from_utf8(name).ok().map(|s| s.trim())
},
data: slice::from_raw_parts(data_ptr as *const u8,
data_len as usize),
};
::LLVMRustArchiveIteratorNext(self.ptr);
Some(child)
}
}
}
#[unsafe_destructor]
impl<'a> Drop for Iter<'a> {
fn drop(&mut self) {
unsafe {
::LLVMRustArchiveIteratorFree(self.ptr);
}
}
}
impl<'a> Child<'a> {
pub fn name(&self) -> Option<&'a str> { self.name }
pub fn data(&self) -> &'a [u8] { self.data }
}

View File

@ -30,6 +30,7 @@
#![feature(libc)]
#![feature(link_args)]
#![feature(staged_api)]
#![feature(unsafe_destructor)]
extern crate libc;
#[macro_use] #[no_link] extern crate rustc_bitflags;
@ -488,9 +489,12 @@ pub type PassRef = *mut Pass_opaque;
#[allow(missing_copy_implementations)]
pub enum TargetMachine_opaque {}
pub type TargetMachineRef = *mut TargetMachine_opaque;
#[allow(missing_copy_implementations)]
pub enum Archive_opaque {}
pub type ArchiveRef = *mut Archive_opaque;
pub enum ArchiveIterator_opaque {}
pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque;
pub enum ArchiveChild_opaque {}
pub type ArchiveChildRef = *mut ArchiveChild_opaque;
#[allow(missing_copy_implementations)]
pub enum Twine_opaque {}
pub type TwineRef = *mut Twine_opaque;
@ -2051,13 +2055,17 @@ extern {
pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef;
pub fn LLVMRustArchiveReadSection(AR: ArchiveRef, name: *const c_char,
out_len: *mut size_t) -> *const c_char;
pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef;
pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef);
pub fn LLVMRustArchiveIteratorCurrent(AIR: ArchiveIteratorRef) -> ArchiveChildRef;
pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef,
size: *mut size_t) -> *const c_char;
pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef,
size: *mut size_t) -> *const c_char;
pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef);
pub fn LLVMRustDestroyArchive(AR: ArchiveRef);
pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef);
pub fn LLVMVersionMajor() -> c_int;
pub fn LLVMVersionMinor() -> c_int;
pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
data: *mut *const c_char) -> c_int;

View File

@ -21,9 +21,6 @@ use libc;
use flate;
use std::ffi::CString;
use std::mem;
#[allow(deprecated)]
use std::num::Int;
pub fn run(sess: &session::Session, llmod: ModuleRef,
tm: TargetMachineRef, reachable: &[String]) {
@ -63,13 +60,13 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
let file = &file[3..file.len() - 5]; // chop off lib/.rlib
debug!("reading {}", file);
for i in 0.. {
let bc_encoded = time(sess.time_passes(),
&format!("check for {}.{}.bytecode.deflate", name, i),
(),
|_| {
archive.read(&format!("{}.{}.bytecode.deflate",
file, i))
});
let filename = format!("{}.{}.bytecode.deflate", file, i);
let msg = format!("check for {}", filename);
let bc_encoded = time(sess.time_passes(), &msg, (), |_| {
archive.iter().find(|section| {
section.name() == Some(&filename[..])
})
});
let bc_encoded = match bc_encoded {
Some(data) => data,
None => {
@ -79,9 +76,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
path.display()));
}
// No more bitcode files to read.
break;
},
break
}
};
let bc_encoded = bc_encoded.data();
let bc_decoded = if is_versioned_bytecode_format(bc_encoded) {
time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), (), |_| {
@ -198,19 +196,15 @@ fn is_versioned_bytecode_format(bc: &[u8]) -> bool {
}
fn extract_bytecode_format_version(bc: &[u8]) -> u32 {
return read_from_le_bytes::<u32>(bc, link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET);
let pos = link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET;
let byte_data = &bc[pos..pos + 4];
let data = unsafe { *(byte_data.as_ptr() as *const u32) };
u32::from_le(data)
}
fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 {
return read_from_le_bytes::<u64>(bc, link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET);
}
#[allow(deprecated)]
fn read_from_le_bytes<T: Int>(bytes: &[u8], position_in_bytes: usize) -> T {
let byte_data = &bytes[position_in_bytes..position_in_bytes + mem::size_of::<T>()];
let data = unsafe {
*(byte_data.as_ptr() as *const T)
};
Int::from_le(data)
let pos = link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET;
let byte_data = &bc[pos..pos + 8];
let data = unsafe { *(byte_data.as_ptr() as *const u64) };
u64::from_le(data)
}

View File

@ -348,7 +348,7 @@ unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<'a>,
match cgcx.lto_ctxt {
Some((sess, _)) => {
sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info {
sess.codemap().with_expn_info(ExpnId::from_u32(cookie), |info| match info {
Some(ei) => sess.span_err(ei.call_site, msg),
None => sess.err(msg),
});

View File

@ -45,8 +45,6 @@
pub use self::Repr::*;
#[allow(deprecated)]
use std::num::Int;
use std::rc::Rc;
use llvm::{ValueRef, True, IntEQ, IntNE};

View File

@ -138,7 +138,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
let kind = llvm::LLVMGetMDKindIDInContext(bcx.ccx().llcx(),
key.as_ptr() as *const c_char, key.len() as c_uint);
let val: llvm::ValueRef = C_i32(bcx.ccx(), ia.expn_id.to_llvm_cookie());
let val: llvm::ValueRef = C_i32(bcx.ccx(), ia.expn_id.into_u32() as i32);
llvm::LLVMSetMetadata(r, kind,
llvm::LLVMMDNodeInContext(bcx.ccx().llcx(), &val, 1));

View File

@ -878,16 +878,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
// were introduced in LLVM 3.4, so we case on that.
macro_rules! compatible_ifn {
($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr) => (
if unsafe { llvm::LLVMVersionMinor() >= 4 } {
// The `if key == $name` is already in ifn!
ifn!($name, fn($($arg),*) -> $ret);
} else if *key == $name {
let f = declare::declare_cfn(ccx, stringify!($cname),
Type::func(&[$($arg),*], &$ret),
ty::mk_nil(ccx.tcx()));
ccx.intrinsics().borrow_mut().insert($name, f.clone());
return Some(f);
}
ifn!($name, fn($($arg),*) -> $ret);
)
}

View File

@ -2653,26 +2653,8 @@ fn set_members_of_composite_type(cx: &CrateContext,
let mut composite_types_completed =
debug_context(cx).composite_types_completed.borrow_mut();
if composite_types_completed.contains(&composite_type_metadata) {
let (llvm_version_major, llvm_version_minor) = unsafe {
(llvm::LLVMVersionMajor(), llvm::LLVMVersionMinor())
};
let actual_llvm_version = llvm_version_major * 1000000 + llvm_version_minor * 1000;
let min_supported_llvm_version = 3 * 1000000 + 4 * 1000;
if actual_llvm_version < min_supported_llvm_version {
cx.sess().warn(&format!("This version of rustc was built with LLVM \
{}.{}. Rustc just ran into a known \
debuginfo corruption problem thatoften \
occurs with LLVM versions below 3.4. \
Please use a rustc built with anewer \
version of LLVM.",
llvm_version_major,
llvm_version_minor));
} else {
cx.sess().bug("debuginfo::set_members_of_composite_type() - \
Already completed forward declaration re-encountered.");
}
cx.sess().bug("debuginfo::set_members_of_composite_type() - \
Already completed forward declaration re-encountered.");
} else {
composite_types_completed.insert(composite_type_metadata);
}

View File

@ -746,11 +746,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let src = to_arg_ty(bcx, llargs[2], tp_ty);
let res = AtomicCmpXchg(bcx, ptr, cmp, src, order,
strongest_failure_ordering);
if unsafe { llvm::LLVMVersionMinor() >= 5 } {
ExtractValue(bcx, res, 0)
} else {
res
}
ExtractValue(bcx, res, 0)
}
"load" => {

View File

@ -21,8 +21,6 @@ use util::ppaux::Repr;
use trans::type_::Type;
#[allow(deprecated)]
use std::num::Int;
use syntax::abi;
use syntax::ast;

View File

@ -45,7 +45,7 @@ mod u_str;
pub mod char;
pub mod str {
pub use u_str::{UnicodeStr, Words, Graphemes, GraphemeIndices};
pub use u_str::{UnicodeStr, SplitWhitespace, Words, Graphemes, GraphemeIndices};
pub use u_str::{utf8_char_width, is_utf16, Utf16Items, Utf16Item};
pub use u_str::{utf16_items, Utf16Encoder};
}

View File

@ -25,9 +25,16 @@ use core::str::Split;
use tables::grapheme::GraphemeCat;
/// An iterator over the words of a string, separated by a sequence of whitespace
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Words<'a> {
#[deprecated(reason = "struct Words is being replaced by struct SplitWhitespace",
since = "1.1.0")]
#[unstable(feature = "str_words",
reason = "words() will be replaced by split_whitespace() in 1.1.0")]
pub type Words<'a> = SplitWhitespace<'a>;
/// An iterator over the non-whitespace substrings of a string,
/// separated by any amount of whitespace.
#[stable(feature = "split_whitespace", since = "1.1.0")]
pub struct SplitWhitespace<'a> {
inner: Filter<Split<'a, fn(char) -> bool>, fn(&&str) -> bool>,
}
@ -36,7 +43,9 @@ pub struct Words<'a> {
pub trait UnicodeStr {
fn graphemes<'a>(&'a self, is_extended: bool) -> Graphemes<'a>;
fn grapheme_indices<'a>(&'a self, is_extended: bool) -> GraphemeIndices<'a>;
#[allow(deprecated)]
fn words<'a>(&'a self) -> Words<'a>;
fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>;
fn is_whitespace(&self) -> bool;
fn is_alphanumeric(&self) -> bool;
fn width(&self, is_cjk: bool) -> usize;
@ -56,15 +65,21 @@ impl UnicodeStr for str {
GraphemeIndices { start_offset: self.as_ptr() as usize, iter: self.graphemes(is_extended) }
}
#[allow(deprecated)]
#[inline]
fn words(&self) -> Words {
self.split_whitespace()
}
#[inline]
fn split_whitespace(&self) -> SplitWhitespace {
fn is_not_empty(s: &&str) -> bool { !s.is_empty() }
let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer
fn is_whitespace(c: char) -> bool { c.is_whitespace() }
let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer
Words { inner: self.split(is_whitespace).filter(is_not_empty) }
SplitWhitespace { inner: self.split(is_whitespace).filter(is_not_empty) }
}
#[inline]
@ -545,11 +560,11 @@ impl<I> Iterator for Utf16Encoder<I> where I: Iterator<Item=char> {
}
}
impl<'a> Iterator for Words<'a> {
impl<'a> Iterator for SplitWhitespace<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> { self.inner.next() }
}
impl<'a> DoubleEndedIterator for Words<'a> {
impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() }
}

View File

@ -274,7 +274,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
};
// Transform the contents of the header into a hyphenated string
let id = s.words().map(|s| s.to_ascii_lowercase())
let id = s.split_whitespace().map(|s| s.to_ascii_lowercase())
.collect::<Vec<String>>().connect("-");
// This is a terrible hack working around how hoedown gives us rendered

View File

@ -31,7 +31,6 @@
#![feature(std_misc)]
#![feature(test)]
#![feature(unicode)]
#![feature(str_words)]
#![feature(path_ext)]
#![feature(path_relative_from)]
#![feature(slice_patterns)]
@ -240,7 +239,7 @@ pub fn main_args(args: &[String]) -> isize {
let test_args = matches.opt_strs("test-args");
let test_args: Vec<String> = test_args.iter()
.flat_map(|s| s.words())
.flat_map(|s| s.split_whitespace())
.map(|s| s.to_string())
.collect();
@ -404,13 +403,13 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
}
clean::NameValue(ref x, ref value)
if "passes" == *x => {
for pass in value.words() {
for pass in value.split_whitespace() {
passes.push(pass.to_string());
}
}
clean::NameValue(ref x, ref value)
if "plugins" == *x => {
for p in value.words() {
for p in value.split_whitespace() {
plugins.push(p.to_string());
}
}

View File

@ -204,12 +204,10 @@ use std::io::prelude::*;
use std::io;
use std::mem::swap;
use std::num::FpCategory as Fp;
#[allow(deprecated)]
use std::num::wrapping::WrappingOps;
use std::ops::Index;
use std::str::FromStr;
use std::string;
use std::{char, f64, fmt, num, str};
use std::{char, f64, fmt, str};
use std;
use rustc_unicode::str as unicode_str;
use rustc_unicode::str::Utf16Item;
@ -460,8 +458,8 @@ fn spaces(wr: &mut fmt::Write, mut n: usize) -> EncodeResult {
fn fmt_number_or_null(v: f64) -> string::String {
match v.classify() {
Fp::Nan | Fp::Infinite => string::String::from_str("null"),
_ if v.fract() != 0f64 => f64::to_str_digits(v, 6),
_ => f64::to_str_digits(v, 6) + ".0",
_ if v.fract() != 0f64 => v.to_string(),
_ => v.to_string() + ".0",
}
}
@ -1165,7 +1163,7 @@ impl Json {
pub fn as_i64(&self) -> Option<i64> {
match *self {
Json::I64(n) => Some(n),
Json::U64(n) => num::cast(n),
Json::U64(n) => Some(n as i64),
_ => None
}
}
@ -1174,7 +1172,7 @@ impl Json {
/// Returns None otherwise.
pub fn as_u64(&self) -> Option<u64> {
match *self {
Json::I64(n) => num::cast(n),
Json::I64(n) => Some(n as u64),
Json::U64(n) => Some(n),
_ => None
}
@ -1184,8 +1182,8 @@ impl Json {
/// Returns None otherwise.
pub fn as_f64(&self) -> Option<f64> {
match *self {
Json::I64(n) => num::cast(n),
Json::U64(n) => num::cast(n),
Json::I64(n) => Some(n as f64),
Json::U64(n) => Some(n as f64),
Json::F64(n) => Some(n),
_ => None
}
@ -1556,7 +1554,7 @@ impl<T: Iterator<Item=char>> Parser<T> {
#[allow(deprecated)] // possible resolve bug is mapping these to traits
fn parse_u64(&mut self) -> Result<u64, ParserError> {
let mut accum = 0;
let mut accum = 0u64;
let last_accum = 0; // necessary to detect overflow.
match self.ch_or_null() {
@ -2059,7 +2057,7 @@ impl<T: Iterator<Item=char>> Builder<T> {
}
}
/// Decodes a json value from an `&mut old_io::Reader`
/// Decodes a json value from an `&mut io::Read`
pub fn from_reader(rdr: &mut Read) -> Result<Json, BuilderError> {
let mut contents = Vec::new();
match rdr.read_to_end(&mut contents) {
@ -2121,14 +2119,8 @@ macro_rules! read_primitive {
($name:ident, $ty:ty) => {
fn $name(&mut self) -> DecodeResult<$ty> {
match self.pop() {
Json::I64(f) => match num::cast(f) {
Some(f) => Ok(f),
None => Err(ExpectedError("Number".to_string(), format!("{}", f))),
},
Json::U64(f) => match num::cast(f) {
Some(f) => Ok(f),
None => Err(ExpectedError("Number".to_string(), format!("{}", f))),
},
Json::I64(f) => Ok(f as $ty),
Json::U64(f) => Ok(f as $ty),
Json::F64(f) => Err(ExpectedError("Integer".to_string(), format!("{}", f))),
// re: #12967.. a type w/ numeric keys (ie HashMap<usize, V> etc)
// is going to have a string here, as per JSON spec.

View File

@ -914,33 +914,6 @@ impl<K, V, S> HashMap<K, V, S>
IterMut { inner: self.table.iter_mut() }
}
/// Creates a consuming iterator, that is, one that moves each key-value
/// pair out of the map in arbitrary order. The map cannot be used after
/// calling this.
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
///
/// let mut map = HashMap::new();
/// map.insert("a", 1);
/// map.insert("b", 2);
/// map.insert("c", 3);
///
/// // Not possible with .iter()
/// let vec: Vec<(&str, isize)> = map.into_iter().collect();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<K, V> {
fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
IntoIter {
inner: self.table.into_iter().map(last_two)
}
}
/// Gets the given key's corresponding entry in the map for in-place manipulation.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn entry(&mut self, key: K) -> Entry<K, V> {
@ -1388,8 +1361,30 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S>
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
/// Creates a consuming iterator, that is, one that moves each key-value
/// pair out of the map in arbitrary order. The map cannot be used after
/// calling this.
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
///
/// let mut map = HashMap::new();
/// map.insert("a", 1);
/// map.insert("b", 2);
/// map.insert("c", 3);
///
/// // Not possible with .iter()
/// let vec: Vec<(&str, isize)> = map.into_iter().collect();
/// ```
fn into_iter(self) -> IntoIter<K, V> {
self.into_iter()
fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
IntoIter {
inner: self.table.into_iter().map(last_two)
}
}
}
@ -1625,7 +1620,7 @@ mod test_map {
use super::HashMap;
use super::Entry::{Occupied, Vacant};
use iter::{range_inclusive, range_step_inclusive, repeat};
use iter::{range_inclusive, repeat};
use cell::RefCell;
use rand::{thread_rng, Rng};
@ -1861,7 +1856,7 @@ mod test_map {
}
// remove backwards
for i in range_step_inclusive(1000, 1, -1) {
for i in (1..1001).rev() {
assert!(m.remove(&i).is_some());
for j in range_inclusive(i, 1000) {

View File

@ -269,34 +269,6 @@ impl<T, S> HashSet<T, S>
Iter { iter: self.map.keys() }
}
/// Creates a consuming iterator, that is, one that moves each value out
/// of the set in arbitrary order. The set cannot be used after calling
/// this.
///
/// # Examples
///
/// ```
/// use std::collections::HashSet;
/// let mut set = HashSet::new();
/// set.insert("a".to_string());
/// set.insert("b".to_string());
///
/// // Not possible to collect to a Vec<String> with a regular `.iter()`.
/// let v: Vec<String> = set.into_iter().collect();
///
/// // Will print in an arbitrary order.
/// for x in v.iter() {
/// println!("{}", x);
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<T> {
fn first<A, B>((a, _): (A, B)) -> A { a }
let first: fn((T, ())) -> T = first;
IntoIter { iter: self.map.into_iter().map(first) }
}
/// Visit the values representing the difference.
///
/// # Examples
@ -848,8 +820,31 @@ impl<T, S> IntoIterator for HashSet<T, S>
type Item = T;
type IntoIter = IntoIter<T>;
/// Creates a consuming iterator, that is, one that moves each value out
/// of the set in arbitrary order. The set cannot be used after calling
/// this.
///
/// # Examples
///
/// ```
/// use std::collections::HashSet;
/// let mut set = HashSet::new();
/// set.insert("a".to_string());
/// set.insert("b".to_string());
///
/// // Not possible to collect to a Vec<String> with a regular `.iter()`.
/// let v: Vec<String> = set.into_iter().collect();
///
/// // Will print in an arbitrary order.
/// for x in v.iter() {
/// println!("{}", x);
/// }
/// ```
fn into_iter(self) -> IntoIter<T> {
self.into_iter()
fn first<A, B>((a, _): (A, B)) -> A { a }
let first: fn((T, ())) -> T = first;
IntoIter { iter: self.map.into_iter().map(first) }
}
}

View File

@ -17,7 +17,7 @@ use iter::{Iterator, ExactSizeIterator};
use marker::{Copy, Send, Sync, Sized, self};
use mem::{min_align_of, size_of};
use mem;
use num::wrapping::{OverflowingOps, WrappingOps};
use num::wrapping::OverflowingOps;
use ops::{Deref, DerefMut, Drop};
use option::Option;
use option::Option::{Some, None};

View File

@ -259,19 +259,14 @@ mod dl {
#[cfg(target_os = "windows")]
mod dl {
use prelude::v1::*;
use ffi::OsStr;
use iter::Iterator;
use libc;
use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
use ops::FnOnce;
use sys::os;
use os::windows::prelude::*;
use option::Option::{self, Some, None};
use ptr;
use result::Result;
use result::Result::{Ok, Err};
use string::String;
use vec::Vec;
use sys::c::compat::kernel32::SetThreadErrorMode;
pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {

Some files were not shown because too many files have changed in this diff Show More