1
Fork 0

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 # 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' # 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 # NB Make sure it starts with a dot to conform to semver pre-release
# versions (section 9) # versions (section 9)
CFG_PRERELEASE_VERSION=.3 CFG_PRERELEASE_VERSION=.1
CFG_FILENAME_EXTRA=4e7c5e5c 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. * [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. * [Nightly Rust][nr] - Cutting-edge features that arent in stable builds yet.
* [Glossary][gl] - A reference of terms used in the book. * [Glossary][gl] - A reference of terms used in the book.
* [Academic Research][ar] - Literature that influenced Rust.
[gs]: getting-started.html [gs]: getting-started.html
[lr]: learn-rust.html [lr]: learn-rust.html
@ -31,6 +32,7 @@ is the first. After this:
[ss]: syntax-and-semantics.html [ss]: syntax-and-semantics.html
[nr]: nightly-rust.html [nr]: nightly-rust.html
[gl]: glossary.html [gl]: glossary.html
[ar]: academic-research.html
After reading this introduction, youll want to dive into either Learn Rust After reading this introduction, youll want to dive into either Learn Rust
or Syntax and Semantics, depending on your preference: Learn Rust if you or Syntax and Semantics, depending on your preference: Learn Rust if you

View file

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

View file

@ -1,8 +1,8 @@
% Associated Types % Associated Types
Associated types are a powerful part of Rust's type system. They're related to 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 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 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 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 and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
this: 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! 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 ## Defining associated types
Let's build that `Graph` trait. Here's the definition: Lets build that `Graph` trait. Heres the definition:
```rust ```rust
trait Graph { trait Graph {
@ -86,7 +86,7 @@ trait Graph {
## Implementing associated types ## Implementing associated types
Just like any trait, traits that use associated types use the `impl` keyword to 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 ```rust
# trait Graph { # trait Graph {
@ -118,13 +118,13 @@ impl Graph for MyGraph {
This silly implementation always returns `true` and an empty `Vec<Edge>`, but it 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 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 `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. use `struct`s for all three here.
Next is the `impl` line, which is just like implementing any other trait. 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 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 for goes on the right. Finally, we use the concrete types in our function
declarations. 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 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 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. implemented. For this, we need something more dangerous.
# `transmute` # `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 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 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 know where to look. In this case, the details about `a` are also important, and

View file

@ -1,9 +1,9 @@
% Closures % Closures
Rust not only has named functions, but anonymous functions as well. Anonymous 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 close over an environment. Rust has a really great implementation of them, as
we'll see. well see.
# Syntax # Syntax
@ -15,7 +15,7 @@ let plus_one = |x: i32| x + 1;
assert_eq!(2, plus_one(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 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 case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line
closures too: closures too:
@ -33,7 +33,7 @@ let plus_two = |x| {
assert_eq!(4, plus_two(2)); 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 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 annotate the types of arguments the closure takes or the values it returns. We
can: can:
@ -44,13 +44,13 @@ let plus_one = |x: i32| -> i32 { x + 1 };
assert_eq!(2, plus_one(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 While specifying the full type for named functions is helpful with things like
documentation and type inference, the types of closures are rarely documented 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 since theyre anonymous, and they dont cause the kinds of error-at-a-distance
that inferring named function types can. 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: here to make them look a little closer:
```rust ```rust
@ -59,11 +59,11 @@ let plus_one_v2 = |x: i32 | -> i32 { x + 1 };
let plus_one_v3 = |x: 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 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: looks like this:
```rust ```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 on `num` because the closure is already borrowing it. If we let the closure go
out of scope, we can: 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 `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. passed `nums` to a function that took ownership of it.
## `move` closures ## `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. 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 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 ```rust
let mut num = 5; 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 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 needed to declare `add_num` as `mut` too, because were mutating its
environment. environment.
If we change to a `move` closure, it's different: If we change to a `move` closure, its different:
```rust ```rust
let mut num = 5; let mut num = 5;
@ -203,8 +203,8 @@ you tons of control over what your code does, and closures are no different.
# Closure implementation # Closure implementation
Rust's implementation of closures is a bit different than other languages. They Rusts 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 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 the [traits chapter][traits] before this one, as well as the chapter on [trait
objects][trait-objects]. 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 `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 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. 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! return closures: just like any other trait!
This also means that we can choose static vs dynamic dispatch as well. First, 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: the result:
```rust ```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 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. 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 ```rust
fn call_with_one<F>(some_closure: F) -> i32 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 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 ```rust
# fn call_with_one<F>(some_closure: F) -> i32 # 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 takes a `i32` as an argument and returns an `i32`, and so the generic bound we use
is `Fn(i32) -> i32`. is `Fn(i32) -> i32`.
There's one other key point here: because we're bounding a generic with a Theres one other key point here: because were bounding a generic with a
trait, this will get monomorphized, and therefore, we'll be doing static trait, this will get monomorphized, and therefore, well be doing static
dispatch into the closure. That's pretty neat. In many langauges, closures are dispatch into the closure. Thats pretty neat. In many langauges, closures are
inherently heap allocated, and will always involve dynamic dispatch. In Rust, inherently heap allocated, and will always involve dynamic dispatch. In Rust,
we can stack allocate our closure environment, and statically dispatch the we can stack allocate our closure environment, and statically dispatch the
call. This happens quite often with iterators and their adapters, which often 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 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 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: try to return a closure from a function:
```rust,ignore ```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 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 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 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 ```rust,ignore
fn factory() -> &(Fn(i32) -> Vec<i32>) { 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 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`: here. What lifetime can we choose? `'static`:
```rust,ignore ```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? we have a `[closure <anon>:7:9: 7:20]`. Wait, what?
Because each closure generates its own environment `struct` and implementation 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 this closure. So Rust shows them as `closure <anon>`, rather than some
autogenerated name. 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 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 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 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 ```text
error: `num` does not live long enough 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 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. escape our stack frame.

View file

@ -1,16 +1,16 @@
% Crates and Modules % 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 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 that some of your functionality is private, and some is public. To facilitate
these kinds of things, Rust has a module system. these kinds of things, Rust has a module system.
# Basic terminology: Crates and Modules # Basic terminology: Crates and Modules
Rust has two distinct terms that relate to the module system: *crate* and 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 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 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 ship your crates to others with Cargo. Crates can produce an executable or a
library, depending on the project. 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 can then define a tree of sub-modules under that root module. Modules allow
you to partition your code within the crate itself. you to partition your code within the crate itself.
As an example, let's make a *phrases* crate, which will give us various phrases As an example, lets make a *phrases* crate, which will give us various phrases
in different languages. To keep things simple, we'll stick to "greetings" and in different languages. To keep things simple, well stick to greetings and
"farewells" as two kinds of phrases, and use English and Japanese (日本語) as 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: two languages for those phrases to be in. Well use this module layout:
```text ```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 modules. You can see that they form a tree, branching out from the crate
*root*, which is the root of the tree: `phrases` itself. *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: generate a new crate with Cargo:
```bash ```bash
@ -72,7 +72,7 @@ above.
# Defining Modules # 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: `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 with double-colon (`::`) notation: our four nested modules are
`english::greetings`, `english::farewells`, `japanese::greetings`, and `english::greetings`, `english::farewells`, `japanese::greetings`, and
`japanese::farewells`. Because these sub-modules are namespaced under their `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 `japanese::greetings` are distinct, even though their names are both
`greetings`. `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 `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 # 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 easier to split up crates into multiple files, and Rust supports this in two
ways. ways.
@ -141,7 +141,7 @@ mod english;
If we do that, Rust will expect to find either a `english.rs` file, or a 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. `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. already been done with the initial `mod` declaration.
Using these two techniques, we can break up our crate into two directories and 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 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 `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 chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
like this: like this:
@ -192,11 +192,11 @@ mod farewells;
Again, these declarations tell Rust to look for either Again, these declarations tell Rust to look for either
`src/english/greetings.rs` and `src/japanese/greetings.rs` or `src/english/greetings.rs` and `src/japanese/greetings.rs` or
`src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because `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! `src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew!
The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are 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`: 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 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. about the module system.
Put this in `src/japanese/farewells.rs`: 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. another crate.
# Importing External Crates # 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. 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 ```rust,ignore
extern crate phrases; extern crate phrases;
@ -259,7 +259,7 @@ fn main() {
``` ```
The `extern crate` declaration tells Rust that we need to compile and link to 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 mentioned earlier, you can use double colons to refer to sub-modules and the
functions inside of them. 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 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 `src/main.rs`. This pattern is quite common for executable crates: most
functionality is in a library crate, and the executable crate uses that 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. 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: this:
```bash ```bash
@ -287,14 +287,14 @@ note: in expansion of format_args!
phrases/src/main.rs:4:5: 4:76 note: expansion site 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. depth.
# Exporting a Public Interface # Exporting a Public Interface
Rust allows you to precisely control which aspects of your interface are 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` 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: to just this:
```{rust,ignore} ```{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} ```{rust,ignore}
pub mod english; pub mod english;
mod japanese; 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} ```{rust,ignore}
pub mod greetings; pub mod greetings;
pub mod farewells; 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} ```{rust,ignore}
pub fn hello() -> String { 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 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 `phrases::english::greetings::hello()` is very long and repetitive. Rust has
another keyword for importing names into the current scope, so that you can 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` # Importing Modules with `use`
Rust has a `use` keyword, which allows us to import names into our local scope. 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} ```{rust,ignore}
extern crate phrases; 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 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 considered best practice to import the module, rather than the function directly. In
other words, you _can_ do this: 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 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 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 error. For example, if we made the `japanese` functions public, and tried to do
this: this:
@ -423,7 +423,7 @@ error: aborting due to previous error
Could not compile `phrases`. 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: twice. Instead of this:
```{rust,ignore} ```{rust,ignore}
@ -439,11 +439,11 @@ use phrases::english::{greetings, farewells};
## Re-exporting with `pub use` ## 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 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. 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} ```{rust,ignore}
extern crate phrases; extern crate phrases;
@ -494,11 +494,11 @@ mod farewells;
``` ```
The `pub use` declaration brings the function into scope at this part of our 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 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::goodbye()` function, even though the code for them lives in
`phrases::japanese::greetings::hello()` and `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. define our external interface.
Here we have a `pub use` for each function we want to bring into the 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, 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 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 `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. display for the current directory and the parent directory.
Outside of `use`, paths are relative: `foo::bar()` refers to a function inside 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 `::foo::bar()`, it refers to a different `foo`, an absolute path from your
crate root. crate root.

View file

@ -1,20 +1,20 @@
% Macros % 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 reusing code. These units of code reuse have a rich semantic structure. For
example, functions have a type signature, type parameters have trait bounds, example, functions have a type signature, type parameters have trait bounds,
and overloaded functions must belong to a particular trait. 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 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 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 shorthand for an "expanded" syntactic form. This expansion happens early in
compilation, before any static checking. As a result, macros can capture many 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 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 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 macro code are harder to interpret, because they describe problems in the
expanded code, not the source-level form that developers use. expanded code, not the source-level form that developers use.
These drawbacks make macros something of a "feature of last resort". That's not 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 they're 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 needed for truly concise, well-abstracted code. Just keep this tradeoff in
mind. mind.
@ -40,7 +40,7 @@ let x: Vec<u32> = vec![1, 2, 3];
# assert_eq!(x, [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 But we can imagine it as syntactic shorthand for
```rust ```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 ```ignore
macro_rules! vec { ... } macro_rules! vec { ... }
``` ```
This says we're defining a macro named `vec`, much as `fn vec` would define a This says were 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 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 exclamation point, e.g. `vec!`. The exclamation point is part of the invocation
syntax and serves to distinguish a macro from an ordinary function. syntax and serves to distinguish a macro from an ordinary function.
## Matching ## 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 cases. Above, we had
```ignore ```ignore
@ -99,13 +99,13 @@ cases. Above, we had
This is like a `match` expression arm, but the matching happens on Rust syntax 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) 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. These have [their own little grammar] within the language.
[their own little grammar]: ../reference.html#macros [their own little grammar]: ../reference.html#macros
The matcher `$x:expr` will match any Rust expression, binding that syntax tree 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][]. the full possibilities are enumerated in the [advanced macros chapter][].
Surrounding the matcher with `$(...),*` will match zero or more expressions, Surrounding the matcher with `$(...),*` will match zero or more expressions,
separated by commas. 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 macro expansion. The repetition in the expansion proceeds in "lockstep" with
repetition in the matcher (more on this in a moment). repetition in the matcher (more on this in a moment).
Because `$x` was already declared as matching an expression, we don't repeat Because `$x` was already declared as matching an expression, we dont repeat
`:expr` on the right-hand side. Also, we don't include a separating comma as `: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 part of the repetition operator. Instead, we have a terminating semicolon
within the repeated block. 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 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, 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 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, 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 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 1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s
it contains, in lockstep, and it contains, in lockstep, and
2. each `$name` must be under at least as many `$(...)*`s as it was matched 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 This baroque macro illustrates the duplication of variables from outer
repetition levels. 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 "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 more" match. Both forms optionally include a separator, which can be any token
except `+` or `*`. except `+` or `*`.
@ -244,9 +244,9 @@ int main() {
``` ```
After expansion we have `5 * 2 + 3`, and multiplication has greater precedence 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 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 ```rust
macro_rules! five_times { macro_rules! five_times {
@ -261,8 +261,8 @@ fn main() {
The metavariable `$x` is parsed as a single expression node, and keeps its The metavariable `$x` is parsed as a single expression node, and keeps its
place in the syntax tree even after substitution. place in the syntax tree even after substitution.
Another common problem in macro systems is *variable capture*. Here's a C Another common problem in macro systems is variable capture. Heres a C
macro, using [a GNU C extension] to emulate Rust's expression blocks. macro, using [a GNU C extension] to emulate Rusts expression blocks.
[a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html [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 ```text
const char *state = "reticulating splines"; const char *state = "reticulating splines";
@ -315,10 +315,10 @@ fn main() {
``` ```
This works because Rust has a [hygienic macro system][]. Each macro expansion 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 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` syntax context where it was introduced. Its as though the variable `state`
inside `main` is painted a different "color" from the variable `state` inside 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 [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. with the right syntax context.
```rust ```rust
@ -368,7 +368,7 @@ fn main() {
# Recursive macros # 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 of the very same macro being expanded. These recursive macros are useful for
processing tree-structured input, as illustrated by this (simplistic) HTML processing tree-structured input, as illustrated by this (simplistic) HTML
shorthand: 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 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 [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 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 [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 must be balanced within a macro invocation. For example, `foo!([)` is
forbidden. This allows Rust to know where the macro invocation ends. 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 token tree is defined recursively as either
* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or * a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
* any other single token. * 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. which syntactic form it matches.
* `ident`: an identifier. Examples: `x`; `foo`. * `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: `=> , =` * `pat` variables must be followed by one of: `=> , =`
* Other variables may be followed by any token. * 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. breaking existing macros.
The macro system does not deal with parse ambiguity at all. For example, the 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. constructs in the language.
Definition and expansion of macros both happen in a single depth-first, 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 is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items. 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. module scope, is visible only within that item.
If a module has the `macro_use` attribute, its macros are also visible in its 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` 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 parent's `mod` then the macros will be visible in the grandparent after the parents `mod`
item, and so forth. item, and so forth.
The `macro_use` attribute can also appear on `extern crate`. In this context 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 there is no `#[macro_use]` attribute then no macros are loaded. Only macros
defined with the `#[macro_export]` attribute may be loaded. 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. as well.
An example: 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 The introductory chapter mentioned recursive macros, but it did not give the
full story. Recursive macros are useful for another reason: Each recursive 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. arguments.
As an extreme example, it is possible, though hardly advisable, to implement As an extreme example, it is possible, though hardly advisable, to implement
the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
within Rust's macro system. within Rusts macro system.
```rust ```rust
macro_rules! bct { macro_rules! bct {
@ -765,9 +765,9 @@ as `unimplemented!` until youre ready to write them.
# Procedural macros # 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!` [compiler plugin](plugins.html) instead. Compared to `macro_rules!`
macros, this is significantly more work, the interfaces are much less stable, 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 and bugs can be much harder to track down. In exchange you get the
flexibility of running arbitrary Rust code within the compiler. Syntax 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 ```rust
let a = [0, 1, 2, 3, 4]; let a = [0, 1, 2, 3, 4];
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3 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 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 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 % Trait Objects
When code involves polymorphism, there needs to be a mechanism to determine 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 two major forms of dispatch: static dispatch and dynamic dispatch. While Rust
favors static dispatch, it also supports dynamic dispatch through a mechanism favors static dispatch, it also supports dynamic dispatch through a mechanism
called 'trait objects.' called trait objects.
## Background ## Background
For the rest of this chapter, we'll need a trait and some implementations. For the rest of this chapter, well need a trait and some implementations.
Let's make a simple one, `Foo`. It has one method that is expected to return a Lets make a simple one, `Foo`. It has one method that is expected to return a
`String`. `String`.
```rust ```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 ```rust
# trait Foo { fn method(&self) -> String; } # 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 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 `String`, and then replace the call sites with calls to these specialized
functions. In other words, Rust generates something like this: 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 This has a great upside: static dispatch allows function calls to be
inlined because the callee is known at compile time, and inlining is 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 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. existing in the binary, one for each type.
Furthermore, compilers arent perfect and may “optimize” code to become slower. Furthermore, compilers arent perfect and may “optimize” code to become slower.
@ -99,7 +99,7 @@ reason.
## Dynamic dispatch ## 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 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 *any* type that implements the given trait, where the precise type can only be
known at runtime. 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`). (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 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. 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 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 Coming back to the example above, we can use the same trait to perform dynamic
dispatch with trait objects by casting: 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 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 `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 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. 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 ### Representation
The methods of the trait can be called on a trait object via a special record 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). the compiler).
Trait objects are both simple and complicated: their core representation and Trait objects are both simple and complicated: their core representation and
layout is quite straight-forward, but there are some curly error messages and layout is quite straight-forward, but there are some curly error messages and
surprising behaviors to discover. 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 `std::raw` module contains structs with layouts that are the same as the
complicated built-in types, [including trait objects][stdraw]: complicated built-in types, [including trait objects][stdraw]:
@ -199,12 +199,12 @@ pub struct TraitObject {
[stdraw]: ../std/raw/struct.TraitObject.html [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. pointer.
The data pointer addresses the data (of some unknown type `T`) that the trait 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 object is storing, and the vtable pointer points to the vtable (virtual method
table") corresponding to the implementation of `Foo` for `T`. table) corresponding to the implementation of `Foo` for `T`.
A vtable is essentially a struct of function pointers, pointing to the concrete 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 `trait_object.method()` will retrieve the correct pointer out of the vtable and
then do a dynamic call of it. For example: then do a dynamic call of it. For example:
```{rust,ignore} ```rust,ignore
struct FooVtable { struct FooVtable {
destructor: fn(*mut ()), destructor: fn(*mut ()),
size: usize, 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 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 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 `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 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 destructor, but will be used in the future, as trait objects are progressively
made more flexible. 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 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 a: String = "foo".to_string();
let x: u8 = 1; 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 where the left-hand side is an arbitrary type (`i32` in this case), not just a
plain type parameter (like `T`). plain type parameter (like `T`).
# Default methods ## Default methods
Theres one last feature of traits we should cover: default methods. Its Theres one last feature of traits we should cover: default methods. Its
easiest just to show an example: easiest just to show an example:

View file

@ -1,16 +1,20 @@
% Tuple Structs % Tuple Structs
Rust has another data type that's like a hybrid between a tuple and a struct, Rust has another data type that's like a hybrid between a [tuple][tuple] and a
called a *tuple struct*. Tuple structs do have a name, but their fields don't: [struct][struct], called a tuple struct. Tuple structs have a name, but
their fields dont:
```{rust} ```rust
struct Color(i32, i32, i32); struct Color(i32, i32, i32);
struct Point(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: These two will not be equal, even if they have the same values:
```{rust} ```rust
# struct Color(i32, i32, i32); # struct Color(i32, i32, i32);
# struct Point(i32, i32, i32); # struct Point(i32, i32, i32);
let black = Color(0, 0, 0); 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 It is almost always better to use a struct than a tuple struct. We would write
`Color` and `Point` like this instead: `Color` and `Point` like this instead:
```{rust} ```rust
struct Color { struct Color {
red: i32, red: i32,
blue: i32, blue: i32,
@ -37,12 +41,12 @@ struct Point {
Now, we have actual names, rather than positions. Good names are important, Now, we have actual names, rather than positions. Good names are important,
and with a struct, we have actual names. and with a struct, we have actual names.
There _is_ one case when a tuple struct is very useful, though, and that's a 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 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 it allows you to create a new type, distinct from that of its contained value
and expressing its own semantic meaning: and expressing its own semantic meaning:
```{rust} ```rust
struct Inches(i32); struct Inches(i32);
let length = Inches(10); 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 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`. `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 Rusts main draw is its powerful static guarantees about behavior. But safety
checks are conservative by nature: there are some programs that are actually 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 * Integer overflow
Rust cannot prevent all kinds of software problems. Buggy code can and will be 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. specifically.
# Unsafe Superpowers # Unsafe Superpowers

View file

@ -46,13 +46,8 @@ def run(args):
f.write("\n") f.write("\n")
version = run([llconfig, '--version']).strip()
# LLVM libs # LLVM libs
if version < '3.5': args = [llconfig, '--libs', '--system-libs']
args = [llconfig, '--libs']
else:
args = [llconfig, '--libs', '--system-libs']
args.extend(components) args.extend(components)
out = run(args) out = run(args)
@ -73,11 +68,6 @@ for lib in out.strip().replace("\n", ' ').split(' '):
f.write(", kind = \"static\"") f.write(", kind = \"static\"")
f.write(")]\n") 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 # LLVM ldflags
out = run([llconfig, '--ldflags']) out = run([llconfig, '--ldflags'])
for lib in out.strip().split(' '): 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::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
use core::fmt; use core::fmt;
use core::cmp::Ordering; use core::cmp::Ordering;
use core::default::Default;
use core::mem::{min_align_of, size_of}; use core::mem::{min_align_of, size_of};
use core::mem; use core::mem;
use core::nonzero::NonZero; use core::nonzero::NonZero;

View file

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

View file

@ -152,8 +152,7 @@
use core::prelude::*; use core::prelude::*;
use core::default::Default; use core::iter::{FromIterator};
use core::iter::{FromIterator, IntoIterator};
use core::mem::{zeroed, replace, swap}; use core::mem::{zeroed, replace, swap};
use core::ptr; use core::ptr;
@ -250,28 +249,6 @@ impl<T: Ord> BinaryHeap<T> {
Iter { iter: self.data.iter() } 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. /// Returns the greatest item in the binary heap, or `None` if it is empty.
/// ///
/// # Examples /// # Examples
@ -675,8 +652,25 @@ impl<T: Ord> IntoIterator for BinaryHeap<T> {
type Item = T; type Item = T;
type IntoIter = IntoIter<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> { 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)] //! # #![feature(collections, core, step_by)]
//! use std::collections::{BitSet, BitVec}; //! use std::collections::{BitSet, BitVec};
//! use std::num::Float;
//! use std::iter; //! use std::iter;
//! //!
//! let max_prime = 10000; //! let max_prime = 10000;
@ -85,12 +84,11 @@ use core::prelude::*;
use core::cmp::Ordering; use core::cmp::Ordering;
use core::cmp; use core::cmp;
use core::default::Default;
use core::fmt; use core::fmt;
use core::hash; use core::hash;
use core::iter::RandomAccessIterator; use core::iter::RandomAccessIterator;
use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat, Cloned}; 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::ops::Index;
use core::slice; use core::slice;
use core::{u8, u32, usize}; use core::{u8, u32, usize};

View file

@ -20,10 +20,9 @@ use self::Entry::*;
use core::prelude::*; use core::prelude::*;
use core::cmp::Ordering; use core::cmp::Ordering;
use core::default::Default;
use core::fmt::Debug; use core::fmt::Debug;
use core::hash::{Hash, Hasher}; use core::hash::{Hash, Hasher};
use core::iter::{Map, FromIterator, IntoIterator}; use core::iter::{Map, FromIterator};
use core::ops::Index; use core::ops::Index;
use core::{iter, fmt, mem, usize}; use core::{iter, fmt, mem, usize};
use Bound::{self, Included, Excluded, Unbounded}; use Bound::{self, Included, Excluded, Unbounded};
@ -471,8 +470,32 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
type Item = (K, V); type Item = (K, V);
type IntoIter = IntoIter<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> { 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. /// Gets an iterator over the keys of the map.
/// ///
/// # Examples /// # Examples

View file

@ -14,10 +14,9 @@
use core::prelude::*; use core::prelude::*;
use core::cmp::Ordering::{self, Less, Greater, Equal}; use core::cmp::Ordering::{self, Less, Greater, Equal};
use core::default::Default;
use core::fmt::Debug; use core::fmt::Debug;
use core::fmt; use core::fmt;
use core::iter::{Peekable, Map, FromIterator, IntoIterator}; use core::iter::{Peekable, Map, FromIterator};
use core::ops::{BitOr, BitAnd, BitXor, Sub}; use core::ops::{BitOr, BitAnd, BitXor, Sub};
use borrow::Borrow; use borrow::Borrow;
@ -132,27 +131,6 @@ impl<T> BTreeSet<T> {
pub fn iter(&self) -> Iter<T> { pub fn iter(&self) -> Iter<T> {
Iter { iter: self.map.keys() } 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> { impl<T: Ord> BTreeSet<T> {
@ -500,8 +478,24 @@ impl<T> IntoIterator for BTreeSet<T> {
type Item = T; type Item = T;
type IntoIter = IntoIter<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> { 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::prelude::*;
use core::marker; use core::marker;
use core::fmt; use core::fmt;
use core::iter::{FromIterator, IntoIterator}; use core::iter::{FromIterator};
use core::ops::{Sub, BitOr, BitAnd, BitXor}; use core::ops::{Sub, BitOr, BitAnd, BitXor};
// FIXME(contentions): implement union family of methods? (general design may be wrong here) // FIXME(contentions): implement union family of methods? (general design may be wrong here)

View file

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

View file

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

View file

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

View file

@ -98,7 +98,7 @@ use self::Direction::*;
use borrow::{Borrow, BorrowMut, ToOwned}; use borrow::{Borrow, BorrowMut, ToOwned};
use vec::Vec; 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::{Iter, IterMut};
pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split}; pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split};
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut}; pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};

View file

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

View file

@ -14,10 +14,9 @@
use core::prelude::*; use core::prelude::*;
use core::default::Default;
use core::fmt; use core::fmt;
use core::hash; use core::hash;
use core::iter::{IntoIterator, FromIterator}; use core::iter::FromIterator;
use core::mem; use core::mem;
use core::ops::{self, Deref, Add, Index}; use core::ops::{self, Deref, Add, Index};
use core::ptr; 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[..]) } 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")] #[stable(feature = "rust1", since = "1.0.0")]
impl Default for String { impl Default for String {
#[inline] #[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")] #[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Write for String { impl fmt::Write for String {
#[inline] #[inline]
@ -1082,4 +1064,10 @@ impl fmt::Write for String {
self.push_str(s); self.push_str(s);
Ok(()) 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 alloc::heap::{EMPTY, allocate, reallocate, deallocate};
use core::cmp::max; use core::cmp::max;
use core::cmp::Ordering; use core::cmp::Ordering;
use core::default::Default;
use core::fmt; use core::fmt;
use core::hash::{self, Hash}; use core::hash::{self, Hash};
use core::intrinsics::assume; use core::intrinsics::assume;
use core::iter::{repeat, FromIterator, IntoIterator}; use core::iter::{repeat, FromIterator};
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem; use core::mem;
use core::ops::{Index, IndexMut, Deref, Add}; use core::ops::{Index, IndexMut, Deref, Add};
@ -450,37 +449,6 @@ impl<T> Vec<T> {
&mut self[..] &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. /// Sets the length of a vector.
/// ///
/// This will explicitly set the size of the vector, without actually /// 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 Item = T;
type IntoIter = IntoIter<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> { 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", #[unstable(feature = "collections",
reason = "recent addition, needs more experience")] reason = "recent addition, needs more experience")]
impl<'a, T: Clone> Add<&'a [T]> for Vec<T> { impl<'a, T: Clone> Add<&'a [T]> for Vec<T> {

View file

@ -21,9 +21,8 @@
use core::prelude::*; use core::prelude::*;
use core::cmp::Ordering; use core::cmp::Ordering;
use core::default::Default;
use core::fmt; use core::fmt;
use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator}; use core::iter::{self, repeat, FromIterator, RandomAccessIterator};
use core::mem; use core::mem;
use core::ops::{Index, IndexMut}; use core::ops::{Index, IndexMut};
use core::ptr::{self, Unique}; 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 /// Returns a pair of slices which contain, in order, the contents of the
/// `VecDeque`. /// `VecDeque`.
#[inline] #[inline]
@ -1728,8 +1719,12 @@ impl<T> IntoIterator for VecDeque<T> {
type Item = T; type Item = T;
type IntoIter = IntoIter<T>; type IntoIter = IntoIter<T>;
/// Consumes the list into a front-to-back iterator yielding elements by
/// value.
fn into_iter(self) -> IntoIter<T> { 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::prelude::*;
use core::cmp::{max, Ordering}; use core::cmp::{max, Ordering};
use core::default::Default;
use core::fmt; use core::fmt;
use core::hash::{Hash, Hasher}; 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::iter;
use core::mem::{replace, swap}; use core::mem::{replace, swap};
use core::ops::{Index, IndexMut}; 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. /// Moves all elements from `other` into the map while overwriting existing keys.
/// ///
/// # Examples /// # Examples
@ -800,8 +770,32 @@ impl<T> IntoIterator for VecMap<T> {
type Item = (usize, T); type Item = (usize, T);
type IntoIter = IntoIter<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> { 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(hash)]
#![feature(rand)] #![feature(rand)]
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(str_words)]
#![feature(test)] #![feature(test)]
#![feature(unboxed_closures)] #![feature(unboxed_closures)]
#![feature(unicode)] #![feature(unicode)]

View file

@ -939,9 +939,9 @@ fn test_rsplitn() {
} }
#[test] #[test]
fn test_words() { fn test_split_whitespace() {
let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; 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"]) 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::ExponentFormat::*;
pub use self::SignificantDigits::*; pub use self::SignificantDigits::*;
use char::{self, CharExt}; use prelude::*;
use char;
use fmt; use fmt;
use iter::Iterator; use num::Float;
use num::{cast, Float, ToPrimitive};
use num::FpCategory as Fp; use num::FpCategory as Fp;
use ops::FnOnce; use ops::{Div, Rem, Mul};
use result::Result::Ok; use slice;
use slice::{self, SliceExt}; use str;
use str::{self, StrExt};
/// A flag that specifies whether to use exponential (scientific) notation. /// A flag that specifies whether to use exponential (scientific) notation.
pub enum ExponentFormat { pub enum ExponentFormat {
@ -42,6 +42,21 @@ pub enum SignificantDigits {
DigExact(usize) 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. /// Converts a float number to its string representation.
/// This is meant to be a common base implementation for various formatting styles. /// 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` /// The number is assumed to be non-negative, callers use `Formatter::pad_integral`
@ -63,7 +78,7 @@ pub enum SignificantDigits {
/// # Panics /// # Panics
/// ///
/// - Panics if `num` is negative. /// - 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, num: T,
digits: SignificantDigits, digits: SignificantDigits,
exp_format: ExponentFormat, exp_format: ExponentFormat,
@ -72,10 +87,10 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
) -> U where ) -> U where
F: FnOnce(&str) -> U, F: FnOnce(&str) -> U,
{ {
let _0: T = Float::zero(); let _0: T = T::zero();
let _1: T = Float::one(); let _1: T = T::one();
let radix: u32 = 10; 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"); 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 { let (num, exp) = match exp_format {
ExpDec if num != _0 => { ExpDec if num != _0 => {
let exp = num.log10().floor(); 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) _ => (num, 0)
}; };
@ -114,7 +129,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
deccum = deccum / radix_f; deccum = deccum / radix_f;
deccum = deccum.trunc(); 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; buf[end] = c.unwrap() as u8;
end += 1; end += 1;
@ -158,7 +173,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
let current_digit = deccum.trunc(); 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; buf[end] = c.unwrap() as u8;
end += 1; end += 1;

View file

@ -12,21 +12,16 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
use prelude::*;
use cell::{Cell, RefCell, Ref, RefMut, BorrowState}; use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
use char::CharExt; use marker::PhantomData;
use clone::Clone;
use iter::Iterator;
use marker::{Copy, PhantomData, Sized};
use mem; use mem;
use num::Float; use ops::Deref;
use option::Option;
use option::Option::{Some, None};
use result::Result::Ok;
use ops::{Deref, FnOnce};
use result; use result;
use slice::SliceExt; use num::Float;
use slice; use slice;
use str::{self, StrExt}; use str;
use self::rt::v1::Alignment; use self::rt::v1::Alignment;
pub use self::num::radix; pub use self::num::radix;
@ -83,6 +78,23 @@ pub trait Write {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn write_str(&mut self, s: &str) -> Result; 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. /// Glue for usage of the `write!` macro with implementers of this trait.
/// ///
/// This method should generally not be invoked manually, but rather through /// 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. // 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 { where F : FnOnce(&str) -> Result {
let digits = match precision { let digits = match precision {
Some(i) => float::DigExact(i), Some(i) => float::DigExact(i),
@ -950,8 +963,6 @@ macro_rules! floating { ($ty:ident) => {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl LowerExp for $ty { impl LowerExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result { fn fmt(&self, fmt: &mut Formatter) -> Result {
use num::Float;
let digits = match fmt.precision { let digits = match fmt.precision {
Some(i) => float::DigExact(i), Some(i) => float::DigExact(i),
None => float::DigMax(6), None => float::DigMax(6),
@ -969,8 +980,6 @@ macro_rules! floating { ($ty:ident) => {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl UpperExp for $ty { impl UpperExp for $ty {
fn fmt(&self, fmt: &mut Formatter) -> Result { fn fmt(&self, fmt: &mut Formatter) -> Result {
use num::Float;
let digits = match fmt.precision { let digits = match fmt.precision {
Some(i) => float::DigExact(i), Some(i) => float::DigExact(i),
None => float::DigMax(6), None => float::DigMax(6),

View file

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

View file

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

View file

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

View file

@ -64,7 +64,7 @@ use cmp::{Ord, PartialOrd, PartialEq};
use default::Default; use default::Default;
use marker; use marker;
use mem; use mem;
use num::{Int, Zero, One}; use num::{Zero, One};
use ops::{self, Add, Sub, FnMut, Mul, RangeFrom}; use ops::{self, Add, Sub, FnMut, Mul, RangeFrom};
use option::Option::{self, Some, None}; use option::Option::{self, Some, None};
use marker::Sized; 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. /// An iterator that yields sequential Fibonacci numbers, and stops on overflow.
/// ///
/// ``` /// ```
/// # #![feature(core)] /// #![feature(core)]
/// use std::iter::Unfold; /// use std::iter::Unfold;
/// use std::num::Int; // For `.checked_add()`
/// ///
/// // This iterator will yield up to the last Fibonacci number before the max /// // 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 /// // 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 { macro_rules! range_exact_iter_impl {
($($t:ty)*) => ($( ($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")] #[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/f32.rs"] pub mod f32;
#[path = "num/f64.rs"] pub mod f64; #[path = "num/f64.rs"] pub mod f64;
#[macro_use]
pub mod num; pub mod num;
/* The libcore prelude, not as all-encompassing as the libstd prelude */ /* 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")] #[stable(feature = "rust1", since = "1.0.0")]
#[lang="send"] #[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"] #[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 { pub unsafe trait Send : MarkerTrait {
// empty. // empty.
} }
@ -51,7 +60,17 @@ impl !Send for Managed { }
#[lang="sized"] #[lang="sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"] #[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 #[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 { pub trait Sized : MarkerTrait {
// Empty. // Empty.
} }
@ -199,13 +218,23 @@ pub trait Copy : Clone {
/// the `sync` crate do ensure that any mutation cannot cause data /// the `sync` crate do ensure that any mutation cannot cause data
/// races. Hence these types are `Sync`. /// races. Hence these types are `Sync`.
/// ///
/// Any types with interior mutability must also use the `std::cell::UnsafeCell` wrapper around the /// Any types with interior mutability must also use the `std::cell::UnsafeCell`
/// value(s) which can be mutated when behind a `&` reference; not doing this is undefined /// wrapper around the value(s) which can be mutated when behind a `&`
/// behaviour (for example, `transmute`-ing from `&T` to `&mut T` is illegal). /// 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")] #[stable(feature = "rust1", since = "1.0.0")]
#[lang="sync"] #[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"] #[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
#[allow(deprecated)]
pub unsafe trait Sync : MarkerTrait { pub unsafe trait Sync : MarkerTrait {
// Empty // Empty
} }
@ -272,42 +301,20 @@ macro_rules! impls{
) )
} }
/// `MarkerTrait` is deprecated and no longer needed. /// dox
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[allow(deprecated)]
#[cfg(stage0)] #[cfg(stage0)]
pub trait MarkerTrait : PhantomFn<Self,Self> { } pub trait MarkerTrait : PhantomFn<Self,Self> { }
/// `MarkerTrait` is deprecated and no longer needed. #[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> MarkerTrait for T {}
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[allow(deprecated)]
#[cfg(not(stage0))]
pub trait MarkerTrait { }
#[allow(deprecated)] /// dox
impl<T:?Sized> MarkerTrait for T { }
/// `PhantomFn` is a deprecated marker trait that is no longer needed.
#[lang="phantom_fn"] #[lang="phantom_fn"]
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.0.0", reason = "No longer needed")]
#[cfg(stage0)] #[cfg(stage0)]
pub trait PhantomFn<A:?Sized,R:?Sized=()> { 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`, /// `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 /// even though it does not. This allows you to inform the compiler about certain safety properties
/// of your code. /// of your code.
@ -454,8 +461,14 @@ mod impls {
#[rustc_reflect_like] #[rustc_reflect_like]
#[unstable(feature = "core", reason = "requires RFC and more experience")] #[unstable(feature = "core", reason = "requires RFC and more experience")]
#[allow(deprecated)] #[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 .. { } impl Reflect for .. { }

View file

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

View file

@ -16,11 +16,12 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
use prelude::*;
use intrinsics; use intrinsics;
use mem; use mem;
use num::Float; use num::{Float, ParseFloatError};
use num::FpCategory as Fp; use num::FpCategory as Fp;
use option::Option;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const RADIX: u32 = 2; pub const RADIX: u32 = 2;
@ -33,19 +34,6 @@ pub const DIGITS: u32 = 6;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const EPSILON: f32 = 1.19209290e-07_f32; 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 /// Smallest finite f32 value
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const MIN: f32 = -3.40282347e+38_f32; pub const MIN: f32 = -3.40282347e+38_f32;
@ -118,26 +106,14 @@ pub mod consts {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_2_SQRT_PI: f32 = 1.12837916709551257389615890312154517_f32; 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) /// sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const SQRT_2: f32 = 1.41421356237309504880168872420969808_f32; 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) /// 1.0/sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32; 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 /// Euler's number
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const E: f32 = 2.71828182845904523536028747135266250_f32; pub const E: f32 = 2.71828182845904523536028747135266250_f32;
@ -179,6 +155,8 @@ impl Float for f32 {
#[inline] #[inline]
fn one() -> f32 { 1.0 } fn one() -> f32 { 1.0 }
from_str_radix_float_impl! { f32 }
/// Returns `true` if the number is NaN. /// Returns `true` if the number is NaN.
#[inline] #[inline]
fn is_nan(self) -> bool { self != self } 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. /// Returns the mantissa, exponent and sign as integers.
fn integer_decode(self) -> (u64, i16, i8) { fn integer_decode(self) -> (u64, i16, i8) {
let bits: u32 = unsafe { mem::transmute(self) }; let bits: u32 = unsafe { mem::transmute(self) };
@ -310,9 +238,6 @@ impl Float for f32 {
/// The fractional part of the number, satisfying: /// The fractional part of the number, satisfying:
/// ///
/// ``` /// ```
/// # #![feature(core)]
/// use std::num::Float;
///
/// let x = 1.65f32; /// let x = 1.65f32;
/// assert!(x == x.trunc() + x.fract()) /// assert!(x == x.trunc() + x.fract())
/// ``` /// ```

View file

@ -16,11 +16,12 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
use prelude::*;
use intrinsics; use intrinsics;
use mem; use mem;
use num::Float;
use num::FpCategory as Fp; use num::FpCategory as Fp;
use option::Option; use num::{Float, ParseFloatError};
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const RADIX: u32 = 2; pub const RADIX: u32 = 2;
@ -33,19 +34,6 @@ pub const DIGITS: u32 = 15;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const EPSILON: f64 = 2.2204460492503131e-16_f64; 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 /// Smallest finite f64 value
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const MIN: f64 = -1.7976931348623157e+308_f64; pub const MIN: f64 = -1.7976931348623157e+308_f64;
@ -118,26 +106,14 @@ pub mod consts {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_2_SQRT_PI: f64 = 1.12837916709551257389615890312154517_f64; 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) /// sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const SQRT_2: f64 = 1.41421356237309504880168872420969808_f64; 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) /// 1.0/sqrt(2.0)
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64; 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 /// Euler's number
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const E: f64 = 2.71828182845904523536028747135266250_f64; pub const E: f64 = 2.71828182845904523536028747135266250_f64;
@ -179,6 +155,8 @@ impl Float for f64 {
#[inline] #[inline]
fn one() -> f64 { 1.0 } fn one() -> f64 { 1.0 }
from_str_radix_float_impl! { f64 }
/// Returns `true` if the number is NaN. /// Returns `true` if the number is NaN.
#[inline] #[inline]
fn is_nan(self) -> bool { self != self } 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. /// Returns the mantissa, exponent and sign as integers.
fn integer_decode(self) -> (u64, i16, i8) { fn integer_decode(self) -> (u64, i16, i8) {
let bits: u64 = unsafe { mem::transmute(self) }; let bits: u64 = unsafe { mem::transmute(self) };
@ -310,9 +238,6 @@ impl Float for f64 {
/// The fractional part of the number, satisfying: /// The fractional part of the number, satisfying:
/// ///
/// ``` /// ```
/// # #![feature(core)]
/// use std::num::Float;
///
/// let x = 1.65f64; /// let x = 1.65f64;
/// assert!(x == x.trunc() + x.fract()) /// assert!(x == x.trunc() + x.fract())
/// ``` /// ```

View file

@ -18,3 +18,145 @@ macro_rules! assert_approx_eq {
"{} is not approximately equal to {}", *a, *b); "{} 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 ops::*;
use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul};
use intrinsics::{i8_add_with_overflow, u8_add_with_overflow}; use intrinsics::{i8_add_with_overflow, u8_add_with_overflow};
use intrinsics::{i16_add_with_overflow, u16_add_with_overflow}; use intrinsics::{i16_add_with_overflow, u16_add_with_overflow};
use intrinsics::{i32_add_with_overflow, u32_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}; 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")] #[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
pub trait OverflowingOps { pub trait OverflowingOps {
fn overflowing_add(self, rhs: Self) -> (Self, bool); 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 { macro_rules! wrapping_impl {
($($t:ty)*) => ($( ($($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")] #[stable(feature = "rust1", since = "1.0.0")]
impl Add for Wrapping<$t> { impl Add for Wrapping<$t> {
type Output = Wrapping<$t>; type Output = Wrapping<$t>;

View file

@ -551,25 +551,6 @@ impl<T> Option<T> {
IterMut { inner: Item { opt: self.as_mut() } } 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 // Boolean operations on the values, eager and lazy
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
@ -770,6 +751,30 @@ impl<T> Default for Option<T> {
fn default() -> Option<T> { None } 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 // The Option Iterators
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////

View file

@ -37,11 +37,10 @@ pub use char::CharExt;
pub use clone::Clone; pub use clone::Clone;
pub use cmp::{PartialEq, PartialOrd, Eq, Ord}; pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
pub use convert::{AsRef, AsMut, Into, From}; pub use convert::{AsRef, AsMut, Into, From};
pub use default::Default;
pub use iter::IntoIterator;
pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator}; pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator};
pub use option::Option::{self, Some, None}; pub use option::Option::{self, Some, None};
pub use result::Result::{self, Ok, Err}; pub use result::Result::{self, Ok, Err};
pub use slice::SliceExt; pub use slice::SliceExt;
pub use str::StrExt; 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 iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSizeIterator, IntoIterator};
use ops::{FnMut, FnOnce}; use ops::{FnMut, FnOnce};
use option::Option::{self, None, Some}; use option::Option::{self, None, Some};
#[allow(deprecated)]
use slice::AsSlice;
use slice; use slice;
/// `Result` is a type that represents either success (`Ok`) or failure (`Err`). /// `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() } 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 // Boolean operations on the values, eager and lazy
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
@ -787,23 +766,27 @@ impl<T: fmt::Debug, E> Result<T, E> {
// Trait implementations // Trait implementations
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#[unstable(feature = "core", #[stable(feature = "rust1", since = "1.0.0")]
reason = "waiting on the stability of the trait itself")] impl<T, E> IntoIterator for Result<T, E> {
#[deprecated(since = "1.0.0", type Item = T;
reason = "use inherent method instead")] type IntoIter = IntoIter<T>;
#[allow(deprecated)]
impl<T, E> AsSlice<T> for Result<T, E> { /// Returns a consuming iterator over the possibly contained value.
/// Converts from `Result<T, E>` to `&[T]` (without copying) ///
/// # 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] #[inline]
fn as_slice<'a>(&'a self) -> &'a [T] { fn into_iter(self) -> IntoIter<T> {
match *self { IntoIter { inner: self.ok() }
Ok(ref x) => slice::ref_slice(x),
Err(_) => {
// work around lack of implicit coercion from fixed-size array to slice
let emp: &[_] = &[];
emp
}
}
} }
} }

View file

@ -51,7 +51,7 @@ use result::Result::{Ok, Err};
use ptr; use ptr;
use mem; use mem;
use mem::size_of; use mem::size_of;
use marker::{Send, Sized, Sync, self}; use marker::{Send, Sync, self};
use raw::Repr; use raw::Repr;
// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module. // Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
use raw::Slice as RawSlice; use raw::Slice as RawSlice;
@ -595,37 +595,6 @@ impl<T> ops::IndexMut<RangeFull> for [T] {
// Common traits // 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")] #[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Default for &'a [T] { impl<'a, T> Default for &'a [T] {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]

View file

@ -25,7 +25,6 @@ use default::Default;
use fmt; use fmt;
use iter::ExactSizeIterator; use iter::ExactSizeIterator;
use iter::{Map, Iterator, DoubleEndedIterator}; use iter::{Map, Iterator, DoubleEndedIterator};
use marker::Sized;
use mem; use mem;
use ops::{Fn, FnMut, FnOnce}; use ops::{Fn, FnMut, FnOnce};
use option::Option::{self, None, Some}; 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 /// Methods for string slices
#[allow(missing_docs)] #[allow(missing_docs)]
#[doc(hidden)] #[doc(hidden)]

View file

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

View file

@ -11,7 +11,6 @@
use core::iter::*; use core::iter::*;
use core::iter::order::*; use core::iter::order::*;
use core::iter::MinMaxResult::*; use core::iter::MinMaxResult::*;
use core::num::SignedInt;
use core::usize; use core::usize;
use core::cmp; use core::cmp;
@ -783,16 +782,6 @@ fn test_range_step() {
assert_eq!((200..200).step_by(1).collect::<Vec<isize>>(), []); 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] #[test]
fn test_reverse() { fn test_reverse() {
let mut ys = [1, 2, 3, 4, 5]; 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) // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))] #![cfg_attr(stage0, feature(custom_attribute))]
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(int_uint)]
#![feature(unboxed_closures)] #![feature(unboxed_closures)]
#![feature(unsafe_destructor)] #![feature(unsafe_destructor)]
#![feature(core)] #![feature(core)]
@ -21,13 +21,11 @@
#![feature(std_misc)] #![feature(std_misc)]
#![feature(libc)] #![feature(libc)]
#![feature(hash)] #![feature(hash)]
#![feature(io)]
#![feature(collections)]
#![feature(debug_builders)] #![feature(debug_builders)]
#![feature(unique)] #![feature(unique)]
#![feature(step_by)] #![feature(step_by)]
#![feature(slice_patterns)] #![feature(slice_patterns)]
#![allow(deprecated)] // rand #![feature(float_from_str_radix)]
extern crate core; extern crate core;
extern crate test; extern crate test;

View file

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

View file

@ -10,7 +10,6 @@
use core::cmp::PartialEq; use core::cmp::PartialEq;
use core::fmt::Debug; use core::fmt::Debug;
use core::num::{NumCast, cast};
use core::ops::{Add, Sub, Mul, Div, Rem}; use core::ops::{Add, Sub, Mul, Div, Rem};
use core::marker::Copy; use core::marker::Copy;
@ -32,18 +31,12 @@ mod u64;
/// Helper function for testing numeric operations /// Helper function for testing numeric operations
pub fn test_num<T>(ten: T, two: T) where pub fn test_num<T>(ten: T, two: T) where
T: PartialEq + NumCast T: PartialEq
+ Add<Output=T> + Sub<Output=T> + Add<Output=T> + Sub<Output=T>
+ Mul<Output=T> + Div<Output=T> + Mul<Output=T> + Div<Output=T>
+ Rem<Output=T> + Debug + Rem<Output=T> + Debug
+ Copy + 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.add(two), ten + two);
assert_eq!(ten.sub(two), ten - two); assert_eq!(ten.sub(two), ten - two);
assert_eq!(ten.mul(two), ten * two); assert_eq!(ten.mul(two), ten * two);
@ -56,33 +49,33 @@ mod test {
use core::option::Option; use core::option::Option;
use core::option::Option::{Some, None}; use core::option::Option::{Some, None};
use core::num::Float; use core::num::Float;
use core::num::from_str_radix;
#[test] #[test]
fn from_str_issue7588() { 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); 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); 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())); 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())); assert_eq!(fe, Some(Float::infinity()));
} }
#[test] #[test]
fn test_from_str_radix_float() { 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)); 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)); 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)); 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)); 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)); 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)); assert_eq!(x5, Some(-1.0));
} }

View file

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

View file

@ -91,7 +91,6 @@
#![deny(missing_docs)] #![deny(missing_docs)]
#![feature(staged_api)] #![feature(staged_api)]
#![feature(str_words)]
#![feature(str_char)] #![feature(str_char)]
#![cfg_attr(test, feature(rustc_private))] #![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 // Normalize desc to contain words separated by one space character
let mut desc_normalized_whitespace = String::new(); 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_str(word);
desc_normalized_whitespace.push(' '); desc_normalized_whitespace.push(' ');
} }

View file

@ -3536,6 +3536,30 @@ pub mod consts {
pub const IPV6_DROP_MEMBERSHIP: c_int = 21; pub const IPV6_DROP_MEMBERSHIP: c_int = 21;
pub const TCP_NODELAY: c_int = 1; 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 SOL_SOCKET: c_int = 1;
pub const SO_DEBUG: c_int = 1; pub const SO_DEBUG: c_int = 1;

View file

@ -11,8 +11,6 @@
//! The ChaCha random number generator. //! The ChaCha random number generator.
use core::prelude::*; use core::prelude::*;
use core::num::Int;
use core::num::wrapping::WrappingOps;
use {Rng, SeedableRng, Rand}; use {Rng, SeedableRng, Rand};
const KEY_WORDS : usize = 8; // 8 words for the 256-bit key 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. //! that do not need to record state.
use core::prelude::*; use core::prelude::*;
use core::num::{Float, Int}; use core::num::Float;
use core::marker::PhantomData; use core::marker::PhantomData;
use {Rng, Rand}; use {Rng, Rand};

View file

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

View file

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

View file

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

View file

@ -208,7 +208,7 @@ fn main() {
unsafe { f(); } 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##" E0152: r##"

View file

@ -38,7 +38,6 @@
#![feature(staged_api)] #![feature(staged_api)]
#![feature(std_misc)] #![feature(std_misc)]
#![feature(path_ext)] #![feature(path_ext)]
#![feature(str_words)]
#![feature(str_char)] #![feature(str_char)]
#![feature(into_cow)] #![feature(into_cow)]
#![feature(slice_patterns)] #![feature(slice_patterns)]
@ -69,6 +68,9 @@ extern crate test;
pub use rustc_llvm as llvm; pub use rustc_llvm as llvm;
#[macro_use]
mod macros;
// NB: This module needs to be declared first so diagnostics are // NB: This module needs to be declared first so diagnostics are
// registered before they are used. // registered before they are used.
pub mod diagnostics; pub mod diagnostics;
@ -142,6 +144,7 @@ pub mod util {
pub mod ppaux; pub mod ppaux;
pub mod nodemap; pub mod nodemap;
pub mod lev_distance; pub mod lev_distance;
pub mod num;
} }
pub mod lib { 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; pub const tag_items_data_item_reexport_name: usize = 0x48;
// used to encode crate_ctxt side tables // used to encode crate_ctxt side tables
#[derive(Copy, Clone, PartialEq, FromPrimitive)] enum_from_u32! {
#[repr(usize)] #[derive(Copy, Clone, PartialEq)]
pub enum astencode_tag { // Reserves 0x50 -- 0x6f #[repr(usize)]
tag_ast = 0x50, 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, tag_table = 0x53,
// GAP 0x54, 0x55 // GAP 0x54, 0x55
tag_table_def = 0x56, tag_table_def = 0x56,
tag_table_node_type = 0x57, tag_table_node_type = 0x57,
tag_table_item_subst = 0x58, tag_table_item_subst = 0x58,
tag_table_freevars = 0x59, tag_table_freevars = 0x59,
tag_table_tcache = 0x5a, tag_table_tcache = 0x5a,
tag_table_param_defs = 0x5b, tag_table_param_defs = 0x5b,
tag_table_mutbl = 0x5c, tag_table_mutbl = 0x5c,
tag_table_last_use = 0x5d, tag_table_last_use = 0x5d,
tag_table_spill = 0x5e, tag_table_spill = 0x5e,
tag_table_method_map = 0x5f, tag_table_method_map = 0x5f,
tag_table_vtable_map = 0x60, tag_table_vtable_map = 0x60,
tag_table_adjustments = 0x61, tag_table_adjustments = 0x61,
tag_table_moves_map = 0x62, tag_table_moves_map = 0x62,
tag_table_capture_map = 0x63, tag_table_capture_map = 0x63,
tag_table_closure_tys = 0x64, tag_table_closure_tys = 0x64,
tag_table_closure_kinds = 0x65, tag_table_closure_kinds = 0x65,
tag_table_upvar_capture_map = 0x66, tag_table_upvar_capture_map = 0x66,
tag_table_capture_modes = 0x67, tag_table_capture_modes = 0x67,
tag_table_object_cast_map = 0x68, tag_table_object_cast_map = 0x68,
tag_table_const_qualif = 0x69, tag_table_const_qualif = 0x69,
}
} }
pub const tag_item_trait_item_sort: usize = 0x70; pub const tag_item_trait_item_sort: usize = 0x70;

View file

@ -68,11 +68,13 @@ pub enum LinkagePreference {
RequireStatic, RequireStatic,
} }
#[derive(Copy, Clone, PartialEq, FromPrimitive)] enum_from_u32! {
pub enum NativeLibraryKind { #[derive(Copy, Clone, PartialEq)]
NativeStatic, // native static library (.a archive) pub enum NativeLibraryKind {
NativeFramework, // OSX-specific NativeStatic, // native static library (.a archive)
NativeUnknown, // default way to specify a dynamic library 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 // 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::hash::{self, Hash, SipHasher};
use std::io::prelude::*; use std::io::prelude::*;
use std::io; use std::io;
use std::num::FromPrimitive;
use std::rc::Rc; use std::rc::Rc;
use std::slice::bytes; use std::slice::bytes;
use std::str; 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 kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind);
let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name); let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name);
let kind: cstore::NativeLibraryKind = 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(); let name = name_doc.as_str().to_string();
result.push((kind, name)); result.push((kind, name));
true true
@ -1359,7 +1358,7 @@ pub fn get_native_libraries(cdata: Cmd)
pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> { pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn) 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 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(); let mut result = Vec::new();
reader::tagged_docs(items, tag_lang_items_missing, |missing_docs| { reader::tagged_docs(items, tag_lang_items_missing, |missing_docs| {
let item: lang_items::LangItem = 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); result.push(item);
true true
}); });

View file

@ -692,11 +692,16 @@ pub fn note_crate_name(diag: &SpanHandler, name: &str) {
impl ArchiveMetadata { impl ArchiveMetadata {
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> { fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
let data = match ar.read(METADATA_FILENAME) { let data = {
Some(data) => data as *const [u8], let section = ar.iter().find(|sect| {
None => { sect.name() == Some(METADATA_FILENAME)
debug!("didn't find '{}' in the archive", METADATA_FILENAME); });
return None; 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::cell::Cell;
use std::io::SeekFrom; use std::io::SeekFrom;
use std::io::prelude::*; use std::io::prelude::*;
use std::num::FromPrimitive;
use std::rc::Rc; use std::rc::Rc;
use std::fmt::Debug; use std::fmt::Debug;
@ -1713,7 +1712,8 @@ fn decode_side_tables(dcx: &DecodeContext,
debug!(">> Side table document with tag 0x{:x} \ debug!(">> Side table document with tag 0x{:x} \
found for id {} (orig {})", found for id {} (orig {})",
tag, id, id0); 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 { match decoded_tag {
None => { None => {
dcx.tcx.sess.bug( dcx.tcx.sess.bug(

View file

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

View file

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

View file

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

View file

@ -418,7 +418,7 @@ macro_rules! options {
-> bool { -> bool {
match v { match v {
Some(s) => { Some(s) => {
for s in s.words() { for s in s.split_whitespace() {
slot.push(s.to_string()); slot.push(s.to_string());
} }
true true
@ -431,7 +431,7 @@ macro_rules! options {
-> bool { -> bool {
match v { match v {
Some(s) => { 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); *slot = Some(v);
true 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 //! A helper class for dealing with static archives
use std::env; use std::env;
use std::fs; use std::fs::{self, File};
use std::io::prelude::*; use std::io::prelude::*;
use std::io; use std::io;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::{Command, Output, Stdio}; use std::process::{Command, Output, Stdio};
use std::str; use std::str;
use syntax::diagnostic::Handler as ErrorHandler; use syntax::diagnostic::Handler as ErrorHandler;
use rustc_llvm::archive_ro::ArchiveRO;
use tempdir::TempDir; use tempdir::TempDir;
@ -282,17 +283,14 @@ impl<'a> ArchiveBuilder<'a> {
mut skip: F) -> io::Result<()> mut skip: F) -> io::Result<()>
where F: FnMut(&str) -> bool, where F: FnMut(&str) -> bool,
{ {
let loc = TempDir::new("rsar").unwrap(); let archive = match ArchiveRO::open(archive) {
Some(ar) => ar,
// First, extract the contents of the archive to a temporary directory. None => return Err(io::Error::new(io::ErrorKind::Other,
// We don't unpack directly into `self.work_dir` due to the possibility "failed to open archive")),
// 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]);
// Next, we must rename all of the inputs to "guaranteed unique names". // 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 // 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 // of the files, so if two files have the same name they will override
// one another in the archive (bad). // 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 // We skip any files explicitly desired for skipping, and we also skip
// all SYMDEF files as these are just magical placeholders which get // all SYMDEF files as these are just magical placeholders which get
// re-created when we make a new archive anyway. // re-created when we make a new archive anyway.
let files = try!(fs::read_dir(loc.path())); for file in archive.iter() {
for file in files { let filename = match file.name() {
let file = try!(file).path(); Some(s) => s,
let filename = file.file_name().unwrap().to_str().unwrap(); None => continue,
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
}; };
let new_filename = self.work_dir.path().join(&filename[..]); if filename.contains(".SYMDEF") { continue }
try!(fs::rename(&file, &new_filename)); if skip(filename) { continue }
self.members.push(PathBuf::from(filename));
// 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(()) Ok(())
} }
} }

View file

@ -46,6 +46,7 @@
extern crate syntax; extern crate syntax;
extern crate libc; extern crate libc;
extern crate serialize; extern crate serialize;
extern crate rustc_llvm;
#[macro_use] extern crate log; #[macro_use] extern crate log;
pub mod abi; 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 //! use. This implementation is not intended for external use or for any use where security is
//! important. //! important.
#![allow(deprecated)] // to_be32
use std::iter::repeat; use std::iter::repeat;
use std::num::Int;
use std::slice::bytes::{MutableByteVector, copy_memory}; use std::slice::bytes::{MutableByteVector, copy_memory};
use serialize::hex::ToHex; 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 /// Adds the specified number of bytes to the bit count. panic!() if this would cause numeric
/// overflow. /// 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(); 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.") panic!("numeric overflow occurred.")
} }
@ -543,14 +540,14 @@ mod tests {
// A normal addition - no overflow occurs // A normal addition - no overflow occurs
#[test] #[test]
fn test_add_bytes_to_bits_ok() { 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 // A simple failure case - adding 1 to the max value
#[test] #[test]
#[should_panic] #[should_panic]
fn test_add_bytes_to_bits_overflow() { 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 { struct Test {

View file

@ -10,15 +10,23 @@
//! A wrapper around LLVM's archive (.a) code //! A wrapper around LLVM's archive (.a) code
use libc;
use ArchiveRef; use ArchiveRef;
use std::ffi::CString; use std::ffi::CString;
use std::slice;
use std::path::Path; use std::path::Path;
use std::slice;
use std::str;
pub struct ArchiveRO { pub struct ArchiveRO { ptr: ArchiveRef }
ptr: ArchiveRef,
pub struct Iter<'a> {
archive: &'a ArchiveRO,
ptr: ::ArchiveIteratorRef,
}
pub struct Child<'a> {
name: Option<&'a str>,
data: &'a [u8],
} }
impl ArchiveRO { impl ArchiveRO {
@ -52,18 +60,9 @@ impl ArchiveRO {
} }
} }
/// Reads a file in the archive pub fn iter(&self) -> Iter {
pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
unsafe { unsafe {
let mut size = 0 as libc::size_t; Iter { ptr: ::LLVMRustArchiveIteratorNew(self.ptr), archive: self }
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))
}
} }
} }
} }
@ -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(libc)]
#![feature(link_args)] #![feature(link_args)]
#![feature(staged_api)] #![feature(staged_api)]
#![feature(unsafe_destructor)]
extern crate libc; extern crate libc;
#[macro_use] #[no_link] extern crate rustc_bitflags; #[macro_use] #[no_link] extern crate rustc_bitflags;
@ -488,9 +489,12 @@ pub type PassRef = *mut Pass_opaque;
#[allow(missing_copy_implementations)] #[allow(missing_copy_implementations)]
pub enum TargetMachine_opaque {} pub enum TargetMachine_opaque {}
pub type TargetMachineRef = *mut TargetMachine_opaque; pub type TargetMachineRef = *mut TargetMachine_opaque;
#[allow(missing_copy_implementations)]
pub enum Archive_opaque {} pub enum Archive_opaque {}
pub type ArchiveRef = *mut 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)] #[allow(missing_copy_implementations)]
pub enum Twine_opaque {} pub enum Twine_opaque {}
pub type TwineRef = *mut Twine_opaque; pub type TwineRef = *mut Twine_opaque;
@ -2051,13 +2055,17 @@ extern {
pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef); pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef; pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef;
pub fn LLVMRustArchiveReadSection(AR: ArchiveRef, name: *const c_char, pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef;
out_len: *mut size_t) -> *const c_char; 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 LLVMRustDestroyArchive(AR: ArchiveRef);
pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef); pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef);
pub fn LLVMVersionMajor() -> c_int;
pub fn LLVMVersionMinor() -> c_int;
pub fn LLVMRustGetSectionName(SI: SectionIteratorRef, pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
data: *mut *const c_char) -> c_int; data: *mut *const c_char) -> c_int;

View file

@ -21,9 +21,6 @@ use libc;
use flate; use flate;
use std::ffi::CString; use std::ffi::CString;
use std::mem;
#[allow(deprecated)]
use std::num::Int;
pub fn run(sess: &session::Session, llmod: ModuleRef, pub fn run(sess: &session::Session, llmod: ModuleRef,
tm: TargetMachineRef, reachable: &[String]) { 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 let file = &file[3..file.len() - 5]; // chop off lib/.rlib
debug!("reading {}", file); debug!("reading {}", file);
for i in 0.. { for i in 0.. {
let bc_encoded = time(sess.time_passes(), let filename = format!("{}.{}.bytecode.deflate", file, i);
&format!("check for {}.{}.bytecode.deflate", name, i), let msg = format!("check for {}", filename);
(), let bc_encoded = time(sess.time_passes(), &msg, (), |_| {
|_| { archive.iter().find(|section| {
archive.read(&format!("{}.{}.bytecode.deflate", section.name() == Some(&filename[..])
file, i)) })
}); });
let bc_encoded = match bc_encoded { let bc_encoded = match bc_encoded {
Some(data) => data, Some(data) => data,
None => { None => {
@ -79,9 +76,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
path.display())); path.display()));
} }
// No more bitcode files to read. // No more bitcode files to read.
break; break
}, }
}; };
let bc_encoded = bc_encoded.data();
let bc_decoded = if is_versioned_bytecode_format(bc_encoded) { let bc_decoded = if is_versioned_bytecode_format(bc_encoded) {
time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), (), |_| { 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 { 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 { fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 {
return read_from_le_bytes::<u64>(bc, link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET); 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) };
#[allow(deprecated)] u64::from_le(data)
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)
} }

View file

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

View file

@ -45,8 +45,6 @@
pub use self::Repr::*; pub use self::Repr::*;
#[allow(deprecated)]
use std::num::Int;
use std::rc::Rc; use std::rc::Rc;
use llvm::{ValueRef, True, IntEQ, IntNE}; 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(), let kind = llvm::LLVMGetMDKindIDInContext(bcx.ccx().llcx(),
key.as_ptr() as *const c_char, key.len() as c_uint); 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::LLVMSetMetadata(r, kind,
llvm::LLVMMDNodeInContext(bcx.ccx().llcx(), &val, 1)); 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. // were introduced in LLVM 3.4, so we case on that.
macro_rules! compatible_ifn { macro_rules! compatible_ifn {
($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr) => ( ($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr) => (
if unsafe { llvm::LLVMVersionMinor() >= 4 } { ifn!($name, fn($($arg),*) -> $ret);
// 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);
}
) )
} }

View file

@ -2653,26 +2653,8 @@ fn set_members_of_composite_type(cx: &CrateContext,
let mut composite_types_completed = let mut composite_types_completed =
debug_context(cx).composite_types_completed.borrow_mut(); debug_context(cx).composite_types_completed.borrow_mut();
if composite_types_completed.contains(&composite_type_metadata) { if composite_types_completed.contains(&composite_type_metadata) {
let (llvm_version_major, llvm_version_minor) = unsafe { cx.sess().bug("debuginfo::set_members_of_composite_type() - \
(llvm::LLVMVersionMajor(), llvm::LLVMVersionMinor()) Already completed forward declaration re-encountered.");
};
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.");
}
} else { } else {
composite_types_completed.insert(composite_type_metadata); 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 src = to_arg_ty(bcx, llargs[2], tp_ty);
let res = AtomicCmpXchg(bcx, ptr, cmp, src, order, let res = AtomicCmpXchg(bcx, ptr, cmp, src, order,
strongest_failure_ordering); strongest_failure_ordering);
if unsafe { llvm::LLVMVersionMinor() >= 5 } { ExtractValue(bcx, res, 0)
ExtractValue(bcx, res, 0)
} else {
res
}
} }
"load" => { "load" => {

View file

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

View file

@ -45,7 +45,7 @@ mod u_str;
pub mod char; pub mod char;
pub mod str { 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::{utf8_char_width, is_utf16, Utf16Items, Utf16Item};
pub use u_str::{utf16_items, Utf16Encoder}; pub use u_str::{utf16_items, Utf16Encoder};
} }

View file

@ -25,9 +25,16 @@ use core::str::Split;
use tables::grapheme::GraphemeCat; use tables::grapheme::GraphemeCat;
/// An iterator over the words of a string, separated by a sequence of whitespace #[deprecated(reason = "struct Words is being replaced by struct SplitWhitespace",
#[stable(feature = "rust1", since = "1.0.0")] since = "1.1.0")]
pub struct Words<'a> { #[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>, inner: Filter<Split<'a, fn(char) -> bool>, fn(&&str) -> bool>,
} }
@ -36,7 +43,9 @@ pub struct Words<'a> {
pub trait UnicodeStr { pub trait UnicodeStr {
fn graphemes<'a>(&'a self, is_extended: bool) -> Graphemes<'a>; fn graphemes<'a>(&'a self, is_extended: bool) -> Graphemes<'a>;
fn grapheme_indices<'a>(&'a self, is_extended: bool) -> GraphemeIndices<'a>; fn grapheme_indices<'a>(&'a self, is_extended: bool) -> GraphemeIndices<'a>;
#[allow(deprecated)]
fn words<'a>(&'a self) -> Words<'a>; fn words<'a>(&'a self) -> Words<'a>;
fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>;
fn is_whitespace(&self) -> bool; fn is_whitespace(&self) -> bool;
fn is_alphanumeric(&self) -> bool; fn is_alphanumeric(&self) -> bool;
fn width(&self, is_cjk: bool) -> usize; 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) } GraphemeIndices { start_offset: self.as_ptr() as usize, iter: self.graphemes(is_extended) }
} }
#[allow(deprecated)]
#[inline] #[inline]
fn words(&self) -> Words { fn words(&self) -> Words {
self.split_whitespace()
}
#[inline]
fn split_whitespace(&self) -> SplitWhitespace {
fn is_not_empty(s: &&str) -> bool { !s.is_empty() } fn is_not_empty(s: &&str) -> bool { !s.is_empty() }
let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer
fn is_whitespace(c: char) -> bool { c.is_whitespace() } fn is_whitespace(c: char) -> bool { c.is_whitespace() }
let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer 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] #[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; type Item = &'a str;
fn next(&mut self) -> Option<&'a str> { self.inner.next() } 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() } 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 // 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("-"); .collect::<Vec<String>>().connect("-");
// This is a terrible hack working around how hoedown gives us rendered // This is a terrible hack working around how hoedown gives us rendered

View file

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

View file

@ -204,12 +204,10 @@ use std::io::prelude::*;
use std::io; use std::io;
use std::mem::swap; use std::mem::swap;
use std::num::FpCategory as Fp; use std::num::FpCategory as Fp;
#[allow(deprecated)]
use std::num::wrapping::WrappingOps;
use std::ops::Index; use std::ops::Index;
use std::str::FromStr; use std::str::FromStr;
use std::string; use std::string;
use std::{char, f64, fmt, num, str}; use std::{char, f64, fmt, str};
use std; use std;
use rustc_unicode::str as unicode_str; use rustc_unicode::str as unicode_str;
use rustc_unicode::str::Utf16Item; 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 { fn fmt_number_or_null(v: f64) -> string::String {
match v.classify() { match v.classify() {
Fp::Nan | Fp::Infinite => string::String::from_str("null"), Fp::Nan | Fp::Infinite => string::String::from_str("null"),
_ if v.fract() != 0f64 => f64::to_str_digits(v, 6), _ if v.fract() != 0f64 => v.to_string(),
_ => f64::to_str_digits(v, 6) + ".0", _ => v.to_string() + ".0",
} }
} }
@ -1165,7 +1163,7 @@ impl Json {
pub fn as_i64(&self) -> Option<i64> { pub fn as_i64(&self) -> Option<i64> {
match *self { match *self {
Json::I64(n) => Some(n), Json::I64(n) => Some(n),
Json::U64(n) => num::cast(n), Json::U64(n) => Some(n as i64),
_ => None _ => None
} }
} }
@ -1174,7 +1172,7 @@ impl Json {
/// Returns None otherwise. /// Returns None otherwise.
pub fn as_u64(&self) -> Option<u64> { pub fn as_u64(&self) -> Option<u64> {
match *self { match *self {
Json::I64(n) => num::cast(n), Json::I64(n) => Some(n as u64),
Json::U64(n) => Some(n), Json::U64(n) => Some(n),
_ => None _ => None
} }
@ -1184,8 +1182,8 @@ impl Json {
/// Returns None otherwise. /// Returns None otherwise.
pub fn as_f64(&self) -> Option<f64> { pub fn as_f64(&self) -> Option<f64> {
match *self { match *self {
Json::I64(n) => num::cast(n), Json::I64(n) => Some(n as f64),
Json::U64(n) => num::cast(n), Json::U64(n) => Some(n as f64),
Json::F64(n) => Some(n), Json::F64(n) => Some(n),
_ => None _ => None
} }
@ -1556,7 +1554,7 @@ impl<T: Iterator<Item=char>> Parser<T> {
#[allow(deprecated)] // possible resolve bug is mapping these to traits #[allow(deprecated)] // possible resolve bug is mapping these to traits
fn parse_u64(&mut self) -> Result<u64, ParserError> { fn parse_u64(&mut self) -> Result<u64, ParserError> {
let mut accum = 0; let mut accum = 0u64;
let last_accum = 0; // necessary to detect overflow. let last_accum = 0; // necessary to detect overflow.
match self.ch_or_null() { 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> { pub fn from_reader(rdr: &mut Read) -> Result<Json, BuilderError> {
let mut contents = Vec::new(); let mut contents = Vec::new();
match rdr.read_to_end(&mut contents) { match rdr.read_to_end(&mut contents) {
@ -2121,14 +2119,8 @@ macro_rules! read_primitive {
($name:ident, $ty:ty) => { ($name:ident, $ty:ty) => {
fn $name(&mut self) -> DecodeResult<$ty> { fn $name(&mut self) -> DecodeResult<$ty> {
match self.pop() { match self.pop() {
Json::I64(f) => match num::cast(f) { Json::I64(f) => Ok(f as $ty),
Some(f) => Ok(f), Json::U64(f) => Ok(f as $ty),
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::F64(f) => Err(ExpectedError("Integer".to_string(), format!("{}", f))), Json::F64(f) => Err(ExpectedError("Integer".to_string(), format!("{}", f))),
// re: #12967.. a type w/ numeric keys (ie HashMap<usize, V> etc) // re: #12967.. a type w/ numeric keys (ie HashMap<usize, V> etc)
// is going to have a string here, as per JSON spec. // 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() } 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. /// Gets the given key's corresponding entry in the map for in-place manipulation.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn entry(&mut self, key: K) -> Entry<K, V> { 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 Item = (K, V);
type IntoIter = IntoIter<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> { 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::HashMap;
use super::Entry::{Occupied, Vacant}; use super::Entry::{Occupied, Vacant};
use iter::{range_inclusive, range_step_inclusive, repeat}; use iter::{range_inclusive, repeat};
use cell::RefCell; use cell::RefCell;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
@ -1861,7 +1856,7 @@ mod test_map {
} }
// remove backwards // remove backwards
for i in range_step_inclusive(1000, 1, -1) { for i in (1..1001).rev() {
assert!(m.remove(&i).is_some()); assert!(m.remove(&i).is_some());
for j in range_inclusive(i, 1000) { for j in range_inclusive(i, 1000) {

View file

@ -269,34 +269,6 @@ impl<T, S> HashSet<T, S>
Iter { iter: self.map.keys() } 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. /// Visit the values representing the difference.
/// ///
/// # Examples /// # Examples
@ -848,8 +820,31 @@ impl<T, S> IntoIterator for HashSet<T, S>
type Item = T; type Item = T;
type IntoIter = IntoIter<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> { 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 marker::{Copy, Send, Sync, Sized, self};
use mem::{min_align_of, size_of}; use mem::{min_align_of, size_of};
use mem; use mem;
use num::wrapping::{OverflowingOps, WrappingOps}; use num::wrapping::OverflowingOps;
use ops::{Deref, DerefMut, Drop}; use ops::{Deref, DerefMut, Drop};
use option::Option; use option::Option;
use option::Option::{Some, None}; use option::Option::{Some, None};

View file

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