Auto merge of #24674 - alexcrichton:rollup, r=alexcrichton
This commit is contained in:
commit
c0eb9384af
@ -13,12 +13,12 @@
|
||||
######################################################################
|
||||
|
||||
# The version number
|
||||
CFG_RELEASE_NUM=1.0.0
|
||||
CFG_RELEASE_NUM=1.1.0
|
||||
|
||||
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
|
||||
# NB Make sure it starts with a dot to conform to semver pre-release
|
||||
# versions (section 9)
|
||||
CFG_PRERELEASE_VERSION=.3
|
||||
CFG_PRERELEASE_VERSION=.1
|
||||
|
||||
CFG_FILENAME_EXTRA=4e7c5e5c
|
||||
|
||||
|
@ -24,6 +24,7 @@ is the first. After this:
|
||||
* [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks.
|
||||
* [Nightly Rust][nr] - Cutting-edge features that aren’t in stable builds yet.
|
||||
* [Glossary][gl] - A reference of terms used in the book.
|
||||
* [Academic Research][ar] - Literature that influenced Rust.
|
||||
|
||||
[gs]: getting-started.html
|
||||
[lr]: learn-rust.html
|
||||
@ -31,6 +32,7 @@ is the first. After this:
|
||||
[ss]: syntax-and-semantics.html
|
||||
[nr]: nightly-rust.html
|
||||
[gl]: glossary.html
|
||||
[ar]: academic-research.html
|
||||
|
||||
After reading this introduction, you’ll want to dive into either ‘Learn Rust’
|
||||
or ‘Syntax and Semantics’, depending on your preference: ‘Learn Rust’ if you
|
||||
|
@ -55,6 +55,7 @@
|
||||
* [Deref coercions](deref-coercions.md)
|
||||
* [Macros](macros.md)
|
||||
* [Raw Pointers](raw-pointers.md)
|
||||
* [`unsafe`](unsafe.md)
|
||||
* [Nightly Rust](nightly-rust.md)
|
||||
* [Compiler Plugins](compiler-plugins.md)
|
||||
* [Inline Assembly](inline-assembly.md)
|
||||
|
@ -1,8 +1,8 @@
|
||||
% Associated Types
|
||||
|
||||
Associated types are a powerful part of Rust's type system. They're related to
|
||||
the idea of a 'type family', in other words, grouping multiple types together. That
|
||||
description is a bit abstract, so let's dive right into an example. If you want
|
||||
Associated types are a powerful part of Rust’s type system. They’re related to
|
||||
the idea of a ‘type family’, in other words, grouping multiple types together. That
|
||||
description is a bit abstract, so let’s dive right into an example. If you want
|
||||
to write a `Graph` trait, you have two types to be generic over: the node type
|
||||
and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
|
||||
this:
|
||||
@ -48,11 +48,11 @@ fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> uint { ... }
|
||||
|
||||
No need to deal with the `E`dge type here!
|
||||
|
||||
Let's go over all this in more detail.
|
||||
Let’s go over all this in more detail.
|
||||
|
||||
## Defining associated types
|
||||
|
||||
Let's build that `Graph` trait. Here's the definition:
|
||||
Let’s build that `Graph` trait. Here’s the definition:
|
||||
|
||||
```rust
|
||||
trait Graph {
|
||||
@ -86,7 +86,7 @@ trait Graph {
|
||||
## Implementing associated types
|
||||
|
||||
Just like any trait, traits that use associated types use the `impl` keyword to
|
||||
provide implementations. Here's a simple implementation of Graph:
|
||||
provide implementations. Here’s a simple implementation of Graph:
|
||||
|
||||
```rust
|
||||
# trait Graph {
|
||||
@ -118,13 +118,13 @@ impl Graph for MyGraph {
|
||||
This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
|
||||
gives you an idea of how to implement this kind of thing. We first need three
|
||||
`struct`s, one for the graph, one for the node, and one for the edge. If it made
|
||||
more sense to use a different type, that would work as well, we're just going to
|
||||
more sense to use a different type, that would work as well, we’re just going to
|
||||
use `struct`s for all three here.
|
||||
|
||||
Next is the `impl` line, which is just like implementing any other trait.
|
||||
|
||||
From here, we use `=` to define our associated types. The name the trait uses
|
||||
goes on the left of the `=`, and the concrete type we're `impl`ementing this
|
||||
goes on the left of the `=`, and the concrete type we’re `impl`ementing this
|
||||
for goes on the right. Finally, we use the concrete types in our function
|
||||
declarations.
|
||||
|
||||
|
@ -33,7 +33,7 @@ let b = a as u32; // four eights makes 32
|
||||
|
||||
It’s a ‘non-scalar cast’ because we have multiple values here: the four
|
||||
elements of the array. These kinds of casts are very dangerous, because they
|
||||
make assumptions about the way that multiple underlying strucutres are
|
||||
make assumptions about the way that multiple underlying structures are
|
||||
implemented. For this, we need something more dangerous.
|
||||
|
||||
# `transmute`
|
||||
@ -59,7 +59,7 @@ unsafe {
|
||||
}
|
||||
```
|
||||
|
||||
We have to wrap the operation in an `unsafe` block, but this will compile
|
||||
We have to wrap the operation in an `unsafe` block for this to compile
|
||||
successfully. Technically, only the `mem::transmute` call itself needs to be in
|
||||
the block, but it's nice in this case to enclose everything related, so you
|
||||
know where to look. In this case, the details about `a` are also important, and
|
||||
|
@ -1,9 +1,9 @@
|
||||
% Closures
|
||||
|
||||
Rust not only has named functions, but anonymous functions as well. Anonymous
|
||||
functions that have an associated environment are called 'closures', because they
|
||||
functions that have an associated environment are called ‘closures’, because they
|
||||
close over an environment. Rust has a really great implementation of them, as
|
||||
we'll see.
|
||||
we’ll see.
|
||||
|
||||
# Syntax
|
||||
|
||||
@ -15,7 +15,7 @@ let plus_one = |x: i32| x + 1;
|
||||
assert_eq!(2, plus_one(1));
|
||||
```
|
||||
|
||||
We create a binding, `plus_one`, and assign it to a closure. The closure's
|
||||
We create a binding, `plus_one`, and assign it to a closure. The closure’s
|
||||
arguments go between the pipes (`|`), and the body is an expression, in this
|
||||
case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line
|
||||
closures too:
|
||||
@ -33,7 +33,7 @@ let plus_two = |x| {
|
||||
assert_eq!(4, plus_two(2));
|
||||
```
|
||||
|
||||
You'll notice a few things about closures that are a bit different than regular
|
||||
You’ll notice a few things about closures that are a bit different than regular
|
||||
functions defined with `fn`. The first of which is that we did not need to
|
||||
annotate the types of arguments the closure takes or the values it returns. We
|
||||
can:
|
||||
@ -44,13 +44,13 @@ let plus_one = |x: i32| -> i32 { x + 1 };
|
||||
assert_eq!(2, plus_one(1));
|
||||
```
|
||||
|
||||
But we don't have to. Why is this? Basically, it was chosen for ergonomic reasons.
|
||||
But we don’t have to. Why is this? Basically, it was chosen for ergonomic reasons.
|
||||
While specifying the full type for named functions is helpful with things like
|
||||
documentation and type inference, the types of closures are rarely documented
|
||||
since they’re anonymous, and they don’t cause the kinds of error-at-a-distance
|
||||
that inferring named function types can.
|
||||
|
||||
The second is that the syntax is similar, but a bit different. I've added spaces
|
||||
The second is that the syntax is similar, but a bit different. I’ve added spaces
|
||||
here to make them look a little closer:
|
||||
|
||||
```rust
|
||||
@ -59,11 +59,11 @@ let plus_one_v2 = |x: i32 | -> i32 { x + 1 };
|
||||
let plus_one_v3 = |x: i32 | x + 1 ;
|
||||
```
|
||||
|
||||
Small differences, but they're similar in ways.
|
||||
Small differences, but they’re similar in ways.
|
||||
|
||||
# Closures and their environment
|
||||
|
||||
Closures are called such because they 'close over their environment.' It
|
||||
Closures are called such because they ‘close over their environment’. It
|
||||
looks like this:
|
||||
|
||||
```rust
|
||||
@ -105,7 +105,7 @@ fn main() {
|
||||
^
|
||||
```
|
||||
|
||||
A verbose yet helpful error message! As it says, we can't take a mutable borrow
|
||||
A verbose yet helpful error message! As it says, we can’t take a mutable borrow
|
||||
on `num` because the closure is already borrowing it. If we let the closure go
|
||||
out of scope, we can:
|
||||
|
||||
@ -140,7 +140,7 @@ let takes_nums = || nums;
|
||||
```
|
||||
|
||||
`Vec<T>` has ownership over its contents, and therefore, when we refer to it
|
||||
in our closure, we have to take ownership of `nums`. It's the same as if we'd
|
||||
in our closure, we have to take ownership of `nums`. It’s the same as if we’d
|
||||
passed `nums` to a function that took ownership of it.
|
||||
|
||||
## `move` closures
|
||||
@ -156,7 +156,7 @@ let owns_num = move |x: i32| x + num;
|
||||
|
||||
Now, even though the keyword is `move`, the variables follow normal move semantics.
|
||||
In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy
|
||||
of `num`. So what's the difference?
|
||||
of `num`. So what’s the difference?
|
||||
|
||||
```rust
|
||||
let mut num = 5;
|
||||
@ -171,11 +171,11 @@ assert_eq!(10, num);
|
||||
```
|
||||
|
||||
So in this case, our closure took a mutable reference to `num`, and then when
|
||||
we called `add_num`, it mutated the underlying value, as we'd expect. We also
|
||||
we called `add_num`, it mutated the underlying value, as we’d expect. We also
|
||||
needed to declare `add_num` as `mut` too, because we’re mutating its
|
||||
environment.
|
||||
|
||||
If we change to a `move` closure, it's different:
|
||||
If we change to a `move` closure, it’s different:
|
||||
|
||||
```rust
|
||||
let mut num = 5;
|
||||
@ -203,8 +203,8 @@ you tons of control over what your code does, and closures are no different.
|
||||
|
||||
# Closure implementation
|
||||
|
||||
Rust's implementation of closures is a bit different than other languages. They
|
||||
are effectively syntax sugar for traits. You'll want to make sure to have read
|
||||
Rust’s implementation of closures is a bit different than other languages. They
|
||||
are effectively syntax sugar for traits. You’ll want to make sure to have read
|
||||
the [traits chapter][traits] before this one, as well as the chapter on [trait
|
||||
objects][trait-objects].
|
||||
|
||||
@ -237,9 +237,9 @@ pub trait FnOnce<Args> {
|
||||
# }
|
||||
```
|
||||
|
||||
You'll notice a few differences between these traits, but a big one is `self`:
|
||||
You’ll notice a few differences between these traits, but a big one is `self`:
|
||||
`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This
|
||||
covers all three kinds of `self` via the usual method call syntax. But we've
|
||||
covers all three kinds of `self` via the usual method call syntax. But we’ve
|
||||
split them up into three traits, rather than having a single one. This gives us
|
||||
a large amount of control over what kind of closures we can take.
|
||||
|
||||
@ -253,7 +253,7 @@ Now that we know that closures are traits, we already know how to accept and
|
||||
return closures: just like any other trait!
|
||||
|
||||
This also means that we can choose static vs dynamic dispatch as well. First,
|
||||
let's write a function which takes something callable, calls it, and returns
|
||||
let’s write a function which takes something callable, calls it, and returns
|
||||
the result:
|
||||
|
||||
```rust
|
||||
@ -271,7 +271,7 @@ assert_eq!(3, answer);
|
||||
We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it
|
||||
suggests: it calls the closure, giving it `1` as an argument.
|
||||
|
||||
Let's examine the signature of `call_with_one` in more depth:
|
||||
Let’s examine the signature of `call_with_one` in more depth:
|
||||
|
||||
```rust
|
||||
fn call_with_one<F>(some_closure: F) -> i32
|
||||
@ -280,7 +280,7 @@ fn call_with_one<F>(some_closure: F) -> i32
|
||||
```
|
||||
|
||||
We take one parameter, and it has the type `F`. We also return a `i32`. This part
|
||||
isn't interesting. The next part is:
|
||||
isn’t interesting. The next part is:
|
||||
|
||||
```rust
|
||||
# fn call_with_one<F>(some_closure: F) -> i32
|
||||
@ -292,9 +292,9 @@ Because `Fn` is a trait, we can bound our generic with it. In this case, our clo
|
||||
takes a `i32` as an argument and returns an `i32`, and so the generic bound we use
|
||||
is `Fn(i32) -> i32`.
|
||||
|
||||
There's one other key point here: because we're bounding a generic with a
|
||||
trait, this will get monomorphized, and therefore, we'll be doing static
|
||||
dispatch into the closure. That's pretty neat. In many langauges, closures are
|
||||
There’s one other key point here: because we’re bounding a generic with a
|
||||
trait, this will get monomorphized, and therefore, we’ll be doing static
|
||||
dispatch into the closure. That’s pretty neat. In many langauges, closures are
|
||||
inherently heap allocated, and will always involve dynamic dispatch. In Rust,
|
||||
we can stack allocate our closure environment, and statically dispatch the
|
||||
call. This happens quite often with iterators and their adapters, which often
|
||||
@ -320,7 +320,7 @@ to our closure when we pass it to `call_with_one`, so we use `&||`.
|
||||
|
||||
It’s very common for functional-style code to return closures in various
|
||||
situations. If you try to return a closure, you may run into an error. At
|
||||
first, it may seem strange, but we'll figure it out. Here's how you'd probably
|
||||
first, it may seem strange, but we’ll figure it out. Here’s how you’d probably
|
||||
try to return a closure from a function:
|
||||
|
||||
```rust,ignore
|
||||
@ -361,7 +361,7 @@ In order to return something from a function, Rust needs to know what
|
||||
size the return type is. But since `Fn` is a trait, it could be various
|
||||
things of various sizes: many different types can implement `Fn`. An easy
|
||||
way to give something a size is to take a reference to it, as references
|
||||
have a known size. So we'd write this:
|
||||
have a known size. So we’d write this:
|
||||
|
||||
```rust,ignore
|
||||
fn factory() -> &(Fn(i32) -> Vec<i32>) {
|
||||
@ -385,7 +385,7 @@ fn factory() -> &(Fn(i32) -> i32) {
|
||||
```
|
||||
|
||||
Right. Because we have a reference, we need to give it a lifetime. But
|
||||
our `factory()` function takes no arguments, so elision doesn't kick in
|
||||
our `factory()` function takes no arguments, so elision doesn’t kick in
|
||||
here. What lifetime can we choose? `'static`:
|
||||
|
||||
```rust,ignore
|
||||
@ -414,7 +414,7 @@ error: mismatched types:
|
||||
|
||||
```
|
||||
|
||||
This error is letting us know that we don't have a `&'static Fn(i32) -> i32`,
|
||||
This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`,
|
||||
we have a `[closure <anon>:7:9: 7:20]`. Wait, what?
|
||||
|
||||
Because each closure generates its own environment `struct` and implementation
|
||||
@ -422,7 +422,7 @@ of `Fn` and friends, these types are anonymous. They exist just solely for
|
||||
this closure. So Rust shows them as `closure <anon>`, rather than some
|
||||
autogenerated name.
|
||||
|
||||
But why doesn't our closure implement `&'static Fn`? Well, as we discussed before,
|
||||
But why doesn’t our closure implement `&'static Fn`? Well, as we discussed before,
|
||||
closures borrow their environment. And in this case, our environment is based
|
||||
on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime
|
||||
of the stack frame. So if we returned this closure, the function call would be
|
||||
@ -445,7 +445,7 @@ assert_eq!(6, answer);
|
||||
# }
|
||||
```
|
||||
|
||||
We use a trait object, by `Box`ing up the `Fn`. There's just one last problem:
|
||||
We use a trait object, by `Box`ing up the `Fn`. There’s just one last problem:
|
||||
|
||||
```text
|
||||
error: `num` does not live long enough
|
||||
@ -471,5 +471,5 @@ assert_eq!(6, answer);
|
||||
```
|
||||
|
||||
By making the inner closure a `move Fn`, we create a new stack frame for our
|
||||
closure. By `Box`ing it up, we've given it a known size, and allowing it to
|
||||
closure. By `Box`ing it up, we’ve given it a known size, and allowing it to
|
||||
escape our stack frame.
|
||||
|
@ -1,16 +1,16 @@
|
||||
% Crates and Modules
|
||||
|
||||
When a project starts getting large, it's considered good software
|
||||
When a project starts getting large, it’s considered good software
|
||||
engineering practice to split it up into a bunch of smaller pieces, and then
|
||||
fit them together. It's also important to have a well-defined interface, so
|
||||
fit them together. It’s also important to have a well-defined interface, so
|
||||
that some of your functionality is private, and some is public. To facilitate
|
||||
these kinds of things, Rust has a module system.
|
||||
|
||||
# Basic terminology: Crates and Modules
|
||||
|
||||
Rust has two distinct terms that relate to the module system: *crate* and
|
||||
*module*. A crate is synonymous with a *library* or *package* in other
|
||||
languages. Hence "Cargo" as the name of Rust's package management tool: you
|
||||
Rust has two distinct terms that relate to the module system: ‘crate’ and
|
||||
‘module’. A crate is synonymous with a ‘library’ or ‘package’ in other
|
||||
languages. Hence “Cargo” as the name of Rust’s package management tool: you
|
||||
ship your crates to others with Cargo. Crates can produce an executable or a
|
||||
library, depending on the project.
|
||||
|
||||
@ -18,10 +18,10 @@ Each crate has an implicit *root module* that contains the code for that crate.
|
||||
You can then define a tree of sub-modules under that root module. Modules allow
|
||||
you to partition your code within the crate itself.
|
||||
|
||||
As an example, let's make a *phrases* crate, which will give us various phrases
|
||||
in different languages. To keep things simple, we'll stick to "greetings" and
|
||||
"farewells" as two kinds of phrases, and use English and Japanese (日本語) as
|
||||
two languages for those phrases to be in. We'll use this module layout:
|
||||
As an example, let’s make a *phrases* crate, which will give us various phrases
|
||||
in different languages. To keep things simple, we’ll stick to ‘greetings’ and
|
||||
‘farewells’ as two kinds of phrases, and use English and Japanese (日本語) as
|
||||
two languages for those phrases to be in. We’ll use this module layout:
|
||||
|
||||
```text
|
||||
+-----------+
|
||||
@ -47,7 +47,7 @@ In this example, `phrases` is the name of our crate. All of the rest are
|
||||
modules. You can see that they form a tree, branching out from the crate
|
||||
*root*, which is the root of the tree: `phrases` itself.
|
||||
|
||||
Now that we have a plan, let's define these modules in code. To start,
|
||||
Now that we have a plan, let’s define these modules in code. To start,
|
||||
generate a new crate with Cargo:
|
||||
|
||||
```bash
|
||||
@ -72,7 +72,7 @@ above.
|
||||
|
||||
# Defining Modules
|
||||
|
||||
To define each of our modules, we use the `mod` keyword. Let's make our
|
||||
To define each of our modules, we use the `mod` keyword. Let’s make our
|
||||
`src/lib.rs` look like this:
|
||||
|
||||
```
|
||||
@ -101,7 +101,7 @@ Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules
|
||||
with double-colon (`::`) notation: our four nested modules are
|
||||
`english::greetings`, `english::farewells`, `japanese::greetings`, and
|
||||
`japanese::farewells`. Because these sub-modules are namespaced under their
|
||||
parent module, the names don't conflict: `english::greetings` and
|
||||
parent module, the names don’t conflict: `english::greetings` and
|
||||
`japanese::greetings` are distinct, even though their names are both
|
||||
`greetings`.
|
||||
|
||||
@ -116,11 +116,11 @@ build deps examples libphrases-a7448e02a0468eaa.rlib native
|
||||
```
|
||||
|
||||
`libphrase-hash.rlib` is the compiled crate. Before we see how to use this
|
||||
crate from another crate, let's break it up into multiple files.
|
||||
crate from another crate, let’s break it up into multiple files.
|
||||
|
||||
# Multiple file crates
|
||||
|
||||
If each crate were just one file, these files would get very large. It's often
|
||||
If each crate were just one file, these files would get very large. It’s often
|
||||
easier to split up crates into multiple files, and Rust supports this in two
|
||||
ways.
|
||||
|
||||
@ -141,7 +141,7 @@ mod english;
|
||||
If we do that, Rust will expect to find either a `english.rs` file, or a
|
||||
`english/mod.rs` file with the contents of our module.
|
||||
|
||||
Note that in these files, you don't need to re-declare the module: that's
|
||||
Note that in these files, you don’t need to re-declare the module: that’s
|
||||
already been done with the initial `mod` declaration.
|
||||
|
||||
Using these two techniques, we can break up our crate into two directories and
|
||||
@ -180,7 +180,7 @@ mod japanese;
|
||||
|
||||
These two declarations tell Rust to look for either `src/english.rs` and
|
||||
`src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending
|
||||
on our preference. In this case, because our modules have sub-modules, we've
|
||||
on our preference. In this case, because our modules have sub-modules, we’ve
|
||||
chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
|
||||
like this:
|
||||
|
||||
@ -192,11 +192,11 @@ mod farewells;
|
||||
Again, these declarations tell Rust to look for either
|
||||
`src/english/greetings.rs` and `src/japanese/greetings.rs` or
|
||||
`src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because
|
||||
these sub-modules don't have their own sub-modules, we've chosen to make them
|
||||
these sub-modules don’t have their own sub-modules, we’ve chosen to make them
|
||||
`src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew!
|
||||
|
||||
The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are
|
||||
both empty at the moment. Let's add some functions.
|
||||
both empty at the moment. Let’s add some functions.
|
||||
|
||||
Put this in `src/english/greetings.rs`:
|
||||
|
||||
@ -223,7 +223,7 @@ fn hello() -> String {
|
||||
```
|
||||
|
||||
Of course, you can copy and paste this from this web page, or just type
|
||||
something else. It's not important that you actually put "konnichiwa" to learn
|
||||
something else. It’s not important that you actually put ‘konnichiwa’ to learn
|
||||
about the module system.
|
||||
|
||||
Put this in `src/japanese/farewells.rs`:
|
||||
@ -234,17 +234,17 @@ fn goodbye() -> String {
|
||||
}
|
||||
```
|
||||
|
||||
(This is "Sayōnara", if you're curious.)
|
||||
(This is ‘Sayōnara’, if you’re 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, let’s try to use it from
|
||||
another crate.
|
||||
|
||||
# Importing External Crates
|
||||
|
||||
We have a library crate. Let's make an executable crate that imports and uses
|
||||
We have a library crate. Let’s make an executable crate that imports and uses
|
||||
our library.
|
||||
|
||||
Make a `src/main.rs` and put this in it (it won't quite compile yet):
|
||||
Make a `src/main.rs` and put this in it (it won’t quite compile yet):
|
||||
|
||||
```rust,ignore
|
||||
extern crate phrases;
|
||||
@ -259,7 +259,7 @@ fn main() {
|
||||
```
|
||||
|
||||
The `extern crate` declaration tells Rust that we need to compile and link to
|
||||
the `phrases` crate. We can then use `phrases`' modules in this one. As we
|
||||
the `phrases` crate. We can then use `phrases`’ modules in this one. As we
|
||||
mentioned earlier, you can use double colons to refer to sub-modules and the
|
||||
functions inside of them.
|
||||
|
||||
@ -267,10 +267,10 @@ Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate,
|
||||
rather than a library crate. Our package now has two crates: `src/lib.rs` and
|
||||
`src/main.rs`. This pattern is quite common for executable crates: most
|
||||
functionality is in a library crate, and the executable crate uses that
|
||||
library. This way, other programs can also use the library crate, and it's also
|
||||
library. This way, other programs can also use the library crate, and it’s also
|
||||
a nice separation of concerns.
|
||||
|
||||
This doesn't quite work yet, though. We get four errors that look similar to
|
||||
This doesn’t quite work yet, though. We get four errors that look similar to
|
||||
this:
|
||||
|
||||
```bash
|
||||
@ -287,14 +287,14 @@ note: in expansion of format_args!
|
||||
phrases/src/main.rs:4:5: 4:76 note: expansion site
|
||||
```
|
||||
|
||||
By default, everything is private in Rust. Let's talk about this in some more
|
||||
By default, everything is private in Rust. Let’s talk about this in some more
|
||||
depth.
|
||||
|
||||
# Exporting a Public Interface
|
||||
|
||||
Rust allows you to precisely control which aspects of your interface are
|
||||
public, and so private is the default. To make things public, you use the `pub`
|
||||
keyword. Let's focus on the `english` module first, so let's reduce our `src/main.rs`
|
||||
keyword. Let’s focus on the `english` module first, so let’s reduce our `src/main.rs`
|
||||
to just this:
|
||||
|
||||
```{rust,ignore}
|
||||
@ -306,21 +306,21 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
In our `src/lib.rs`, let's add `pub` to the `english` module declaration:
|
||||
In our `src/lib.rs`, let’s add `pub` to the `english` module declaration:
|
||||
|
||||
```{rust,ignore}
|
||||
pub mod english;
|
||||
mod japanese;
|
||||
```
|
||||
|
||||
And in our `src/english/mod.rs`, let's make both `pub`:
|
||||
And in our `src/english/mod.rs`, let’s make both `pub`:
|
||||
|
||||
```{rust,ignore}
|
||||
pub mod greetings;
|
||||
pub mod farewells;
|
||||
```
|
||||
|
||||
In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration:
|
||||
In our `src/english/greetings.rs`, let’s add `pub` to our `fn` declaration:
|
||||
|
||||
```{rust,ignore}
|
||||
pub fn hello() -> String {
|
||||
@ -358,12 +358,12 @@ Goodbye in English: Goodbye.
|
||||
Now that our functions are public, we can use them. Great! However, typing out
|
||||
`phrases::english::greetings::hello()` is very long and repetitive. Rust has
|
||||
another keyword for importing names into the current scope, so that you can
|
||||
refer to them with shorter names. Let's talk about `use`.
|
||||
refer to them with shorter names. Let’s talk about `use`.
|
||||
|
||||
# Importing Modules with `use`
|
||||
|
||||
Rust has a `use` keyword, which allows us to import names into our local scope.
|
||||
Let's change our `src/main.rs` to look like this:
|
||||
Let’s change our `src/main.rs` to look like this:
|
||||
|
||||
```{rust,ignore}
|
||||
extern crate phrases;
|
||||
@ -378,7 +378,7 @@ fn main() {
|
||||
```
|
||||
|
||||
The two `use` lines import each module into the local scope, so we can refer to
|
||||
the functions by a much shorter name. By convention, when importing functions, it's
|
||||
the functions by a much shorter name. By convention, when importing functions, it’s
|
||||
considered best practice to import the module, rather than the function directly. In
|
||||
other words, you _can_ do this:
|
||||
|
||||
@ -395,7 +395,7 @@ fn main() {
|
||||
```
|
||||
|
||||
But it is not idiomatic. This is significantly more likely to introduce a
|
||||
naming conflict. In our short program, it's not a big deal, but as it grows, it
|
||||
naming conflict. In our short program, it’s not a big deal, but as it grows, it
|
||||
becomes a problem. If we have conflicting names, Rust will give a compilation
|
||||
error. For example, if we made the `japanese` functions public, and tried to do
|
||||
this:
|
||||
@ -423,7 +423,7 @@ error: aborting due to previous error
|
||||
Could not compile `phrases`.
|
||||
```
|
||||
|
||||
If we're importing multiple names from the same module, we don't have to type it out
|
||||
If we’re importing multiple names from the same module, we don’t have to type it out
|
||||
twice. Instead of this:
|
||||
|
||||
```{rust,ignore}
|
||||
@ -439,11 +439,11 @@ use phrases::english::{greetings, farewells};
|
||||
|
||||
## Re-exporting with `pub use`
|
||||
|
||||
You don't just use `use` to shorten identifiers. You can also use it inside of your crate
|
||||
You don’t just use `use` to shorten identifiers. You can also use it inside of your crate
|
||||
to re-export a function inside another module. This allows you to present an external
|
||||
interface that may not directly map to your internal code organization.
|
||||
|
||||
Let's look at an example. Modify your `src/main.rs` to read like this:
|
||||
Let’s look at an example. Modify your `src/main.rs` to read like this:
|
||||
|
||||
```{rust,ignore}
|
||||
extern crate phrases;
|
||||
@ -494,11 +494,11 @@ mod farewells;
|
||||
```
|
||||
|
||||
The `pub use` declaration brings the function into scope at this part of our
|
||||
module hierarchy. Because we've `pub use`d this inside of our `japanese`
|
||||
module hierarchy. Because we’ve `pub use`d this inside of our `japanese`
|
||||
module, we now have a `phrases::japanese::hello()` function and a
|
||||
`phrases::japanese::goodbye()` function, even though the code for them lives in
|
||||
`phrases::japanese::greetings::hello()` and
|
||||
`phrases::japanese::farewells::goodbye()`. Our internal organization doesn't
|
||||
`phrases::japanese::farewells::goodbye()`. Our internal organization doesn’t
|
||||
define our external interface.
|
||||
|
||||
Here we have a `pub use` for each function we want to bring into the
|
||||
@ -507,13 +507,13 @@ everything from `greetings` into the current scope: `pub use self::greetings::*`
|
||||
|
||||
What about the `self`? Well, by default, `use` declarations are absolute paths,
|
||||
starting from your crate root. `self` makes that path relative to your current
|
||||
place in the hierarchy instead. There's one more special form of `use`: you can
|
||||
place in the hierarchy instead. There’s one more special form of `use`: you can
|
||||
`use super::` to reach one level up the tree from your current location. Some
|
||||
people like to think of `self` as `.` and `super` as `..`, from many shells'
|
||||
people like to think of `self` as `.` and `super` as `..`, from many shells’
|
||||
display for the current directory and the parent directory.
|
||||
|
||||
Outside of `use`, paths are relative: `foo::bar()` refers to a function inside
|
||||
of `foo` relative to where we are. If that's prefixed with `::`, as in
|
||||
of `foo` relative to where we are. If that’s prefixed with `::`, as in
|
||||
`::foo::bar()`, it refers to a different `foo`, an absolute path from your
|
||||
crate root.
|
||||
|
||||
|
@ -1,20 +1,20 @@
|
||||
% Macros
|
||||
|
||||
By now you've learned about many of the tools Rust provides for abstracting and
|
||||
By now you’ve learned about many of the tools Rust provides for abstracting and
|
||||
reusing code. These units of code reuse have a rich semantic structure. For
|
||||
example, functions have a type signature, type parameters have trait bounds,
|
||||
and overloaded functions must belong to a particular trait.
|
||||
|
||||
This structure means that Rust's core abstractions have powerful compile-time
|
||||
This structure means that Rust’s core abstractions have powerful compile-time
|
||||
correctness checking. But this comes at the price of reduced flexibility. If
|
||||
you visually identify a pattern of repeated code, you may find it's difficult
|
||||
you visually identify a pattern of repeated code, you may find it’s difficult
|
||||
or cumbersome to express that pattern as a generic function, a trait, or
|
||||
anything else within Rust's semantics.
|
||||
anything else within Rust’s semantics.
|
||||
|
||||
Macros allow us to abstract at a *syntactic* level. A macro invocation is
|
||||
Macros allow us to abstract at a syntactic level. A macro invocation is
|
||||
shorthand for an "expanded" syntactic form. This expansion happens early in
|
||||
compilation, before any static checking. As a result, macros can capture many
|
||||
patterns of code reuse that Rust's core abstractions cannot.
|
||||
patterns of code reuse that Rust’s core abstractions cannot.
|
||||
|
||||
The drawback is that macro-based code can be harder to understand, because
|
||||
fewer of the built-in rules apply. Like an ordinary function, a well-behaved
|
||||
@ -23,8 +23,8 @@ difficult to design a well-behaved macro! Additionally, compiler errors in
|
||||
macro code are harder to interpret, because they describe problems in the
|
||||
expanded code, not the source-level form that developers use.
|
||||
|
||||
These drawbacks make macros something of a "feature of last resort". That's not
|
||||
to say that macros are bad; they are part of Rust because sometimes they're
|
||||
These drawbacks make macros something of a "feature of last resort". That’s not
|
||||
to say that macros are bad; they are part of Rust because sometimes they’re
|
||||
needed for truly concise, well-abstracted code. Just keep this tradeoff in
|
||||
mind.
|
||||
|
||||
@ -40,7 +40,7 @@ let x: Vec<u32> = vec![1, 2, 3];
|
||||
# assert_eq!(x, [1, 2, 3]);
|
||||
```
|
||||
|
||||
This can't be an ordinary function, because it takes any number of arguments.
|
||||
This can’t be an ordinary function, because it takes any number of arguments.
|
||||
But we can imagine it as syntactic shorthand for
|
||||
|
||||
```rust
|
||||
@ -77,20 +77,20 @@ macro_rules! vec {
|
||||
# }
|
||||
```
|
||||
|
||||
Whoa, that's a lot of new syntax! Let's break it down.
|
||||
Whoa, that’s a lot of new syntax! Let’s break it down.
|
||||
|
||||
```ignore
|
||||
macro_rules! vec { ... }
|
||||
```
|
||||
|
||||
This says we're defining a macro named `vec`, much as `fn vec` would define a
|
||||
function named `vec`. In prose, we informally write a macro's name with an
|
||||
This says we’re defining a macro named `vec`, much as `fn vec` would define a
|
||||
function named `vec`. In prose, we informally write a macro’s name with an
|
||||
exclamation point, e.g. `vec!`. The exclamation point is part of the invocation
|
||||
syntax and serves to distinguish a macro from an ordinary function.
|
||||
|
||||
## Matching
|
||||
|
||||
The macro is defined through a series of *rules*, which are pattern-matching
|
||||
The macro is defined through a series of rules, which are pattern-matching
|
||||
cases. Above, we had
|
||||
|
||||
```ignore
|
||||
@ -99,13 +99,13 @@ cases. Above, we had
|
||||
|
||||
This is like a `match` expression arm, but the matching happens on Rust syntax
|
||||
trees, at compile time. The semicolon is optional on the last (here, only)
|
||||
case. The "pattern" on the left-hand side of `=>` is known as a *matcher*.
|
||||
case. The "pattern" on the left-hand side of `=>` is known as a ‘matcher’.
|
||||
These have [their own little grammar] within the language.
|
||||
|
||||
[their own little grammar]: ../reference.html#macros
|
||||
|
||||
The matcher `$x:expr` will match any Rust expression, binding that syntax tree
|
||||
to the *metavariable* `$x`. The identifier `expr` is a *fragment specifier*;
|
||||
to the ‘metavariable’ `$x`. The identifier `expr` is a ‘fragment specifier’;
|
||||
the full possibilities are enumerated in the [advanced macros chapter][].
|
||||
Surrounding the matcher with `$(...),*` will match zero or more expressions,
|
||||
separated by commas.
|
||||
@ -158,8 +158,8 @@ Each matched expression `$x` will produce a single `push` statement in the
|
||||
macro expansion. The repetition in the expansion proceeds in "lockstep" with
|
||||
repetition in the matcher (more on this in a moment).
|
||||
|
||||
Because `$x` was already declared as matching an expression, we don't repeat
|
||||
`:expr` on the right-hand side. Also, we don't include a separating comma as
|
||||
Because `$x` was already declared as matching an expression, we don’t repeat
|
||||
`:expr` on the right-hand side. Also, we don’t include a separating comma as
|
||||
part of the repetition operator. Instead, we have a terminating semicolon
|
||||
within the repeated block.
|
||||
|
||||
@ -180,7 +180,7 @@ The outer braces are part of the syntax of `macro_rules!`. In fact, you can use
|
||||
The inner braces are part of the expanded syntax. Remember, the `vec!` macro is
|
||||
used in an expression context. To write an expression with multiple statements,
|
||||
including `let`-bindings, we use a block. If your macro expands to a single
|
||||
expression, you don't need this extra layer of braces.
|
||||
expression, you don’t need this extra layer of braces.
|
||||
|
||||
Note that we never *declared* that the macro produces an expression. In fact,
|
||||
this is not determined until we use the macro as an expression. With care, you
|
||||
@ -194,7 +194,7 @@ The repetition operator follows two principal rules:
|
||||
1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s
|
||||
it contains, in lockstep, and
|
||||
2. each `$name` must be under at least as many `$(...)*`s as it was matched
|
||||
against. If it is under more, it'll be duplicated, as appropriate.
|
||||
against. If it is under more, it’ll be duplicated, as appropriate.
|
||||
|
||||
This baroque macro illustrates the duplication of variables from outer
|
||||
repetition levels.
|
||||
@ -219,7 +219,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
That's most of the matcher syntax. These examples use `$(...)*`, which is a
|
||||
That’s most of the matcher syntax. These examples use `$(...)*`, which is a
|
||||
"zero or more" match. Alternatively you can write `$(...)+` for a "one or
|
||||
more" match. Both forms optionally include a separator, which can be any token
|
||||
except `+` or `*`.
|
||||
@ -244,9 +244,9 @@ int main() {
|
||||
```
|
||||
|
||||
After expansion we have `5 * 2 + 3`, and multiplication has greater precedence
|
||||
than addition. If you've used C macros a lot, you probably know the standard
|
||||
than addition. If you’ve used C macros a lot, you probably know the standard
|
||||
idioms for avoiding this problem, as well as five or six others. In Rust, we
|
||||
don't have to worry about it.
|
||||
don’t have to worry about it.
|
||||
|
||||
```rust
|
||||
macro_rules! five_times {
|
||||
@ -261,8 +261,8 @@ fn main() {
|
||||
The metavariable `$x` is parsed as a single expression node, and keeps its
|
||||
place in the syntax tree even after substitution.
|
||||
|
||||
Another common problem in macro systems is *variable capture*. Here's a C
|
||||
macro, using [a GNU C extension] to emulate Rust's expression blocks.
|
||||
Another common problem in macro systems is ‘variable capture’. Here’s a C
|
||||
macro, using [a GNU C extension] to emulate Rust’s expression blocks.
|
||||
|
||||
[a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
|
||||
|
||||
@ -275,7 +275,7 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks.
|
||||
})
|
||||
```
|
||||
|
||||
Here's a simple use case that goes terribly wrong:
|
||||
Here’s a simple use case that goes terribly wrong:
|
||||
|
||||
```text
|
||||
const char *state = "reticulating splines";
|
||||
@ -315,10 +315,10 @@ fn main() {
|
||||
```
|
||||
|
||||
This works because Rust has a [hygienic macro system][]. Each macro expansion
|
||||
happens in a distinct *syntax context*, and each variable is tagged with the
|
||||
syntax context where it was introduced. It's as though the variable `state`
|
||||
happens in a distinct ‘syntax context’, and each variable is tagged with the
|
||||
syntax context where it was introduced. It’s as though the variable `state`
|
||||
inside `main` is painted a different "color" from the variable `state` inside
|
||||
the macro, and therefore they don't conflict.
|
||||
the macro, and therefore they don’t conflict.
|
||||
|
||||
[hygienic macro system]: http://en.wikipedia.org/wiki/Hygienic_macro
|
||||
|
||||
@ -336,7 +336,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
Instead you need to pass the variable name into the invocation, so it's tagged
|
||||
Instead you need to pass the variable name into the invocation, so it’s tagged
|
||||
with the right syntax context.
|
||||
|
||||
```rust
|
||||
@ -368,7 +368,7 @@ fn main() {
|
||||
|
||||
# Recursive macros
|
||||
|
||||
A macro's expansion can include more macro invocations, including invocations
|
||||
A macro’s expansion can include more macro invocations, including invocations
|
||||
of the very same macro being expanded. These recursive macros are useful for
|
||||
processing tree-structured input, as illustrated by this (simplistic) HTML
|
||||
shorthand:
|
||||
@ -429,7 +429,7 @@ they are unstable and require feature gates.
|
||||
Even when Rust code contains un-expanded macros, it can be parsed as a full
|
||||
[syntax tree][ast]. This property can be very useful for editors and other
|
||||
tools that process code. It also has a few consequences for the design of
|
||||
Rust's macro system.
|
||||
Rust’s macro system.
|
||||
|
||||
[ast]: glossary.html#abstract-syntax-tree
|
||||
|
||||
@ -454,13 +454,13 @@ consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
|
||||
must be balanced within a macro invocation. For example, `foo!([)` is
|
||||
forbidden. This allows Rust to know where the macro invocation ends.
|
||||
|
||||
More formally, the macro invocation body must be a sequence of *token trees*.
|
||||
More formally, the macro invocation body must be a sequence of ‘token trees’.
|
||||
A token tree is defined recursively as either
|
||||
|
||||
* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
|
||||
* any other single token.
|
||||
|
||||
Within a matcher, each metavariable has a *fragment specifier*, identifying
|
||||
Within a matcher, each metavariable has a ‘fragment specifier’, identifying
|
||||
which syntactic form it matches.
|
||||
|
||||
* `ident`: an identifier. Examples: `x`; `foo`.
|
||||
@ -482,7 +482,7 @@ There are additional rules regarding the next token after a metavariable:
|
||||
* `pat` variables must be followed by one of: `=> , =`
|
||||
* Other variables may be followed by any token.
|
||||
|
||||
These rules provide some flexibility for Rust's syntax to evolve without
|
||||
These rules provide some flexibility for Rust’s syntax to evolve without
|
||||
breaking existing macros.
|
||||
|
||||
The macro system does not deal with parse ambiguity at all. For example, the
|
||||
@ -500,7 +500,7 @@ One downside is that scoping works differently for macros, compared to other
|
||||
constructs in the language.
|
||||
|
||||
Definition and expansion of macros both happen in a single depth-first,
|
||||
lexical-order traversal of a crate's source. So a macro defined at module scope
|
||||
lexical-order traversal of a crate’s source. So a macro defined at module scope
|
||||
is visible to any subsequent code in the same module, which includes the body
|
||||
of any subsequent child `mod` items.
|
||||
|
||||
@ -508,8 +508,8 @@ A macro defined within the body of a single `fn`, or anywhere else not at
|
||||
module scope, is visible only within that item.
|
||||
|
||||
If a module has the `macro_use` attribute, its macros are also visible in its
|
||||
parent module after the child's `mod` item. If the parent also has `macro_use`
|
||||
then the macros will be visible in the grandparent after the parent's `mod`
|
||||
parent module after the child’s `mod` item. If the parent also has `macro_use`
|
||||
then the macros will be visible in the grandparent after the parent’s `mod`
|
||||
item, and so forth.
|
||||
|
||||
The `macro_use` attribute can also appear on `extern crate`. In this context
|
||||
@ -524,7 +524,7 @@ If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
|
||||
there is no `#[macro_use]` attribute then no macros are loaded. Only macros
|
||||
defined with the `#[macro_export]` attribute may be loaded.
|
||||
|
||||
To load a crate's macros *without* linking it into the output, use `#[no_link]`
|
||||
To load a crate’s macros without linking it into the output, use `#[no_link]`
|
||||
as well.
|
||||
|
||||
An example:
|
||||
@ -619,12 +619,12 @@ only appear at the root of your crate, not inside `mod`. This ensures that
|
||||
|
||||
The introductory chapter mentioned recursive macros, but it did not give the
|
||||
full story. Recursive macros are useful for another reason: Each recursive
|
||||
invocation gives you another opportunity to pattern-match the macro's
|
||||
invocation gives you another opportunity to pattern-match the macro’s
|
||||
arguments.
|
||||
|
||||
As an extreme example, it is possible, though hardly advisable, to implement
|
||||
the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
|
||||
within Rust's macro system.
|
||||
within Rust’s macro system.
|
||||
|
||||
```rust
|
||||
macro_rules! bct {
|
||||
@ -765,9 +765,9 @@ as `unimplemented!` until you’re ready to write them.
|
||||
|
||||
# Procedural macros
|
||||
|
||||
If Rust's macro system can't do what you need, you may want to write a
|
||||
If Rust’s macro system can’t do what you need, you may want to write a
|
||||
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
|
||||
macros, this is significantly more work, the interfaces are much less stable,
|
||||
and bugs can be much harder to track down. In exchange you get the
|
||||
flexibility of running arbitrary Rust code within the compiler. Syntax
|
||||
extension plugins are sometimes called *procedural macros* for this reason.
|
||||
extension plugins are sometimes called ‘procedural macros’ for this reason.
|
||||
|
@ -168,6 +168,7 @@ like arrays:
|
||||
```rust
|
||||
let a = [0, 1, 2, 3, 4];
|
||||
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
|
||||
let complete = &a[..]; // A slice containing all of the elements in a
|
||||
```
|
||||
|
||||
Slices have type `&[T]`. We’ll talk about that `T` when we cover
|
||||
|
@ -87,3 +87,33 @@ fn main() {
|
||||
point.y = 6; // this causes an error
|
||||
}
|
||||
```
|
||||
|
||||
# Update syntax
|
||||
|
||||
A `struct` can include `..` to indicate that you want to use a copy of some
|
||||
other struct for some of the values. For example:
|
||||
|
||||
```rust
|
||||
struct Point3d {
|
||||
x: i32,
|
||||
y: i32,
|
||||
z: i32,
|
||||
}
|
||||
|
||||
let mut point = Point3d { x: 0, y: 0, z: 0 };
|
||||
point = Point3d { y: 1, .. point };
|
||||
```
|
||||
|
||||
This gives `point` a new `y`, but keeps the old `x` and `z` values. It doesn’t
|
||||
have to be the same `struct` either, you can use this syntax when making new
|
||||
ones, and it will copy the values you don’t 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 };
|
||||
```
|
||||
|
@ -1,15 +1,15 @@
|
||||
% Trait Objects
|
||||
|
||||
When code involves polymorphism, there needs to be a mechanism to determine
|
||||
which specific version is actually run. This is called 'dispatch.' There are
|
||||
which specific version is actually run. This is called ‘dispatch’. There are
|
||||
two major forms of dispatch: static dispatch and dynamic dispatch. While Rust
|
||||
favors static dispatch, it also supports dynamic dispatch through a mechanism
|
||||
called 'trait objects.'
|
||||
called ‘trait objects’.
|
||||
|
||||
## Background
|
||||
|
||||
For the rest of this chapter, we'll need a trait and some implementations.
|
||||
Let's make a simple one, `Foo`. It has one method that is expected to return a
|
||||
For the rest of this chapter, we’ll need a trait and some implementations.
|
||||
Let’s make a simple one, `Foo`. It has one method that is expected to return a
|
||||
`String`.
|
||||
|
||||
```rust
|
||||
@ -18,7 +18,7 @@ trait Foo {
|
||||
}
|
||||
```
|
||||
|
||||
We'll also implement this trait for `u8` and `String`:
|
||||
We’ll also implement this trait for `u8` and `String`:
|
||||
|
||||
```rust
|
||||
# trait Foo { fn method(&self) -> String; }
|
||||
@ -53,7 +53,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
Rust uses 'monomorphization' to perform static dispatch here. This means that
|
||||
Rust uses ‘monomorphization’ to perform static dispatch here. This means that
|
||||
Rust will create a special version of `do_something()` for both `u8` and
|
||||
`String`, and then replace the call sites with calls to these specialized
|
||||
functions. In other words, Rust generates something like this:
|
||||
@ -82,7 +82,7 @@ fn main() {
|
||||
This has a great upside: static dispatch allows function calls to be
|
||||
inlined because the callee is known at compile time, and inlining is
|
||||
the key to good optimization. Static dispatch is fast, but it comes at
|
||||
a tradeoff: 'code bloat', due to many copies of the same function
|
||||
a tradeoff: ‘code bloat’, due to many copies of the same function
|
||||
existing in the binary, one for each type.
|
||||
|
||||
Furthermore, compilers aren’t perfect and may “optimize” code to become slower.
|
||||
@ -99,7 +99,7 @@ reason.
|
||||
|
||||
## Dynamic dispatch
|
||||
|
||||
Rust provides dynamic dispatch through a feature called 'trait objects.' Trait
|
||||
Rust provides dynamic dispatch through a feature called ‘trait objects’. Trait
|
||||
objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
|
||||
*any* type that implements the given trait, where the precise type can only be
|
||||
known at runtime.
|
||||
@ -109,12 +109,12 @@ implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it
|
||||
(e.g. using `&x` as an argument to a function that takes `&Foo`).
|
||||
|
||||
These trait object coercions and casts also work for pointers like `&mut T` to
|
||||
`&mut Foo` and `Box<T>` to `Box<Foo>`, but that's all at the moment. Coercions
|
||||
`&mut Foo` and `Box<T>` to `Box<Foo>`, but that’s all at the moment. Coercions
|
||||
and casts are identical.
|
||||
|
||||
This operation can be seen as "erasing" the compiler's knowledge about the
|
||||
This operation can be seen as ‘erasing’ the compiler’s knowledge about the
|
||||
specific type of the pointer, and hence trait objects are sometimes referred to
|
||||
as "type erasure".
|
||||
as ‘type erasure’.
|
||||
|
||||
Coming back to the example above, we can use the same trait to perform dynamic
|
||||
dispatch with trait objects by casting:
|
||||
@ -167,7 +167,7 @@ on the heap to store it.
|
||||
|
||||
For `Foo`, we would need to have a value that could be at least either a
|
||||
`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which
|
||||
dependent crates may implement `Foo` (any number of bytes at all). There's no
|
||||
dependent crates may implement `Foo` (any number of bytes at all). There’s no
|
||||
way to guarantee that this last point can work if the values are stored without
|
||||
a pointer, because those other types can be arbitrarily large.
|
||||
|
||||
@ -177,14 +177,14 @@ when we are tossing a trait object around, only the size of the pointer itself.
|
||||
### Representation
|
||||
|
||||
The methods of the trait can be called on a trait object via a special record
|
||||
of function pointers traditionally called a 'vtable' (created and managed by
|
||||
of function pointers traditionally called a ‘vtable’ (created and managed by
|
||||
the compiler).
|
||||
|
||||
Trait objects are both simple and complicated: their core representation and
|
||||
layout is quite straight-forward, but there are some curly error messages and
|
||||
surprising behaviors to discover.
|
||||
|
||||
Let's start simple, with the runtime representation of a trait object. The
|
||||
Let’s start simple, with the runtime representation of a trait object. The
|
||||
`std::raw` module contains structs with layouts that are the same as the
|
||||
complicated built-in types, [including trait objects][stdraw]:
|
||||
|
||||
@ -199,12 +199,12 @@ pub struct TraitObject {
|
||||
|
||||
[stdraw]: ../std/raw/struct.TraitObject.html
|
||||
|
||||
That is, a trait object like `&Foo` consists of a "data" pointer and a "vtable"
|
||||
That is, a trait object like `&Foo` consists of a ‘data’ pointer and a ‘vtable’
|
||||
pointer.
|
||||
|
||||
The data pointer addresses the data (of some unknown type `T`) that the trait
|
||||
object is storing, and the vtable pointer points to the vtable ("virtual method
|
||||
table") corresponding to the implementation of `Foo` for `T`.
|
||||
object is storing, and the vtable pointer points to the vtable (‘virtual method
|
||||
table’) corresponding to the implementation of `Foo` for `T`.
|
||||
|
||||
|
||||
A vtable is essentially a struct of function pointers, pointing to the concrete
|
||||
@ -212,7 +212,7 @@ piece of machine code for each method in the implementation. A method call like
|
||||
`trait_object.method()` will retrieve the correct pointer out of the vtable and
|
||||
then do a dynamic call of it. For example:
|
||||
|
||||
```{rust,ignore}
|
||||
```rust,ignore
|
||||
struct FooVtable {
|
||||
destructor: fn(*mut ()),
|
||||
size: usize,
|
||||
@ -261,7 +261,7 @@ static Foo_for_String_vtable: FooVtable = FooVtable {
|
||||
```
|
||||
|
||||
The `destructor` field in each vtable points to a function that will clean up
|
||||
any resources of the vtable's type, for `u8` it is trivial, but for `String` it
|
||||
any resources of the vtable’s type, for `u8` it is trivial, but for `String` it
|
||||
will free the memory. This is necessary for owning trait objects like
|
||||
`Box<Foo>`, which need to clean-up both the `Box` allocation as well as the
|
||||
internal type when they go out of scope. The `size` and `align` fields store
|
||||
@ -270,11 +270,11 @@ essentially unused at the moment since the information is embedded in the
|
||||
destructor, but will be used in the future, as trait objects are progressively
|
||||
made more flexible.
|
||||
|
||||
Suppose we've got some values that implement `Foo`, then the explicit form of
|
||||
Suppose we’ve got some values that implement `Foo`, then the explicit form of
|
||||
construction and use of `Foo` trait objects might look a bit like (ignoring the
|
||||
type mismatches: they're all just pointers anyway):
|
||||
type mismatches: they’re all just pointers anyway):
|
||||
|
||||
```{rust,ignore}
|
||||
```rust,ignore
|
||||
let a: String = "foo".to_string();
|
||||
let x: u8 = 1;
|
||||
|
||||
|
@ -336,7 +336,7 @@ This shows off the additional feature of `where` clauses: they allow bounds
|
||||
where the left-hand side is an arbitrary type (`i32` in this case), not just a
|
||||
plain type parameter (like `T`).
|
||||
|
||||
# Default methods
|
||||
## Default methods
|
||||
|
||||
There’s one last feature of traits we should cover: default methods. It’s
|
||||
easiest just to show an example:
|
||||
|
@ -1,16 +1,20 @@
|
||||
% Tuple Structs
|
||||
|
||||
Rust has another data type that's like a hybrid between a tuple and a struct,
|
||||
called a *tuple struct*. Tuple structs do have a name, but their fields don't:
|
||||
Rust has another data type that's like a hybrid between a [tuple][tuple] and a
|
||||
[struct][struct], called a ‘tuple struct’. Tuple structs have a name, but
|
||||
their fields don’t:
|
||||
|
||||
```{rust}
|
||||
```rust
|
||||
struct Color(i32, i32, i32);
|
||||
struct Point(i32, i32, i32);
|
||||
```
|
||||
|
||||
[tuple]: primitive-types.html#tuples
|
||||
[struct]: structs.html
|
||||
|
||||
These two will not be equal, even if they have the same values:
|
||||
|
||||
```{rust}
|
||||
```rust
|
||||
# struct Color(i32, i32, i32);
|
||||
# struct Point(i32, i32, i32);
|
||||
let black = Color(0, 0, 0);
|
||||
@ -20,7 +24,7 @@ let origin = Point(0, 0, 0);
|
||||
It is almost always better to use a struct than a tuple struct. We would write
|
||||
`Color` and `Point` like this instead:
|
||||
|
||||
```{rust}
|
||||
```rust
|
||||
struct Color {
|
||||
red: i32,
|
||||
blue: i32,
|
||||
@ -37,12 +41,12 @@ struct Point {
|
||||
Now, we have actual names, rather than positions. Good names are important,
|
||||
and with a struct, we have actual names.
|
||||
|
||||
There _is_ one case when a tuple struct is very useful, though, and that's a
|
||||
tuple struct with only one element. We call this the *newtype* pattern, because
|
||||
There _is_ one case when a tuple struct is very useful, though, and that’s a
|
||||
tuple struct with only one element. We call this the ‘newtype’ pattern, because
|
||||
it allows you to create a new type, distinct from that of its contained value
|
||||
and expressing its own semantic meaning:
|
||||
|
||||
```{rust}
|
||||
```rust
|
||||
struct Inches(i32);
|
||||
|
||||
let length = Inches(10);
|
||||
@ -52,5 +56,5 @@ println!("length is {} inches", integer_length);
|
||||
```
|
||||
|
||||
As you can see here, you can extract the inner integer type through a
|
||||
destructuring `let`, as we discussed previously in 'tuples.' In this case, the
|
||||
destructuring `let`, as we discussed previously in ‘tuples’. In this case, the
|
||||
`let Inches(integer_length)` assigns `10` to `integer_length`.
|
||||
|
@ -1,4 +1,4 @@
|
||||
% Unsafe Code
|
||||
% Unsafe
|
||||
|
||||
Rust’s main draw is its powerful static guarantees about behavior. But safety
|
||||
checks are conservative by nature: there are some programs that are actually
|
||||
@ -76,7 +76,7 @@ behaviors that are certainly bad, but are expressly _not_ unsafe:
|
||||
* Integer overflow
|
||||
|
||||
Rust cannot prevent all kinds of software problems. Buggy code can and will be
|
||||
written in Rust. These things arne’t great, but they don’t qualify as `unsafe`
|
||||
written in Rust. These things aren’t great, but they don’t qualify as `unsafe`
|
||||
specifically.
|
||||
|
||||
# Unsafe Superpowers
|
@ -46,13 +46,8 @@ def run(args):
|
||||
|
||||
f.write("\n")
|
||||
|
||||
version = run([llconfig, '--version']).strip()
|
||||
|
||||
# LLVM libs
|
||||
if version < '3.5':
|
||||
args = [llconfig, '--libs']
|
||||
else:
|
||||
args = [llconfig, '--libs', '--system-libs']
|
||||
args = [llconfig, '--libs', '--system-libs']
|
||||
|
||||
args.extend(components)
|
||||
out = run(args)
|
||||
@ -73,11 +68,6 @@ for lib in out.strip().replace("\n", ' ').split(' '):
|
||||
f.write(", kind = \"static\"")
|
||||
f.write(")]\n")
|
||||
|
||||
# llvm-config before 3.5 didn't have a system-libs flag
|
||||
if version < '3.5':
|
||||
if os == 'win32':
|
||||
f.write("#[link(name = \"imagehlp\")]")
|
||||
|
||||
# LLVM ldflags
|
||||
out = run([llconfig, '--ldflags'])
|
||||
for lib in out.strip().split(' '):
|
||||
|
@ -77,7 +77,6 @@ use core::atomic;
|
||||
use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
|
||||
use core::fmt;
|
||||
use core::cmp::Ordering;
|
||||
use core::default::Default;
|
||||
use core::mem::{min_align_of, size_of};
|
||||
use core::mem;
|
||||
use core::nonzero::NonZero;
|
||||
|
@ -55,7 +55,6 @@ use core::prelude::*;
|
||||
|
||||
use core::any::Any;
|
||||
use core::cmp::Ordering;
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hash::{self, Hash};
|
||||
use core::mem;
|
||||
|
@ -152,8 +152,7 @@
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use core::default::Default;
|
||||
use core::iter::{FromIterator, IntoIterator};
|
||||
use core::iter::{FromIterator};
|
||||
use core::mem::{zeroed, replace, swap};
|
||||
use core::ptr;
|
||||
|
||||
@ -250,28 +249,6 @@ impl<T: Ord> BinaryHeap<T> {
|
||||
Iter { iter: self.data.iter() }
|
||||
}
|
||||
|
||||
/// Creates a consuming iterator, that is, one that moves each value out of
|
||||
/// the binary heap in arbitrary order. The binary heap cannot be used
|
||||
/// after calling this.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(collections)]
|
||||
/// use std::collections::BinaryHeap;
|
||||
/// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]);
|
||||
///
|
||||
/// // Print 1, 2, 3, 4 in arbitrary order
|
||||
/// for x in heap.into_iter() {
|
||||
/// // x has type i32, not &i32
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter { iter: self.data.into_iter() }
|
||||
}
|
||||
|
||||
/// Returns the greatest item in the binary heap, or `None` if it is empty.
|
||||
///
|
||||
/// # Examples
|
||||
@ -675,8 +652,25 @@ impl<T: Ord> IntoIterator for BinaryHeap<T> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
/// Creates a consuming iterator, that is, one that moves each value out of
|
||||
/// the binary heap in arbitrary order. The binary heap cannot be used
|
||||
/// after calling this.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(collections)]
|
||||
/// use std::collections::BinaryHeap;
|
||||
/// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]);
|
||||
///
|
||||
/// // Print 1, 2, 3, 4 in arbitrary order
|
||||
/// for x in heap.into_iter() {
|
||||
/// // x has type i32, not &i32
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// ```
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
IntoIter { iter: self.data.into_iter() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,6 @@
|
||||
//! ```
|
||||
//! # #![feature(collections, core, step_by)]
|
||||
//! use std::collections::{BitSet, BitVec};
|
||||
//! use std::num::Float;
|
||||
//! use std::iter;
|
||||
//!
|
||||
//! let max_prime = 10000;
|
||||
@ -85,12 +84,11 @@ use core::prelude::*;
|
||||
|
||||
use core::cmp::Ordering;
|
||||
use core::cmp;
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hash;
|
||||
use core::iter::RandomAccessIterator;
|
||||
use core::iter::{Chain, Enumerate, Repeat, Skip, Take, repeat, Cloned};
|
||||
use core::iter::{self, FromIterator, IntoIterator};
|
||||
use core::iter::{self, FromIterator};
|
||||
use core::ops::Index;
|
||||
use core::slice;
|
||||
use core::{u8, u32, usize};
|
||||
|
@ -20,10 +20,9 @@ use self::Entry::*;
|
||||
use core::prelude::*;
|
||||
|
||||
use core::cmp::Ordering;
|
||||
use core::default::Default;
|
||||
use core::fmt::Debug;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{Map, FromIterator, IntoIterator};
|
||||
use core::iter::{Map, FromIterator};
|
||||
use core::ops::Index;
|
||||
use core::{iter, fmt, mem, usize};
|
||||
use Bound::{self, Included, Excluded, Unbounded};
|
||||
@ -471,8 +470,32 @@ impl<K, V> IntoIterator for BTreeMap<K, V> {
|
||||
type Item = (K, V);
|
||||
type IntoIter = IntoIter<K, V>;
|
||||
|
||||
/// Gets an owning iterator over the entries of the map.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::BTreeMap;
|
||||
///
|
||||
/// let mut map = BTreeMap::new();
|
||||
/// map.insert(1, "a");
|
||||
/// map.insert(2, "b");
|
||||
/// map.insert(3, "c");
|
||||
///
|
||||
/// for (key, value) in map.into_iter() {
|
||||
/// println!("{}: {}", key, value);
|
||||
/// }
|
||||
/// ```
|
||||
fn into_iter(self) -> IntoIter<K, V> {
|
||||
self.into_iter()
|
||||
let len = self.len();
|
||||
let mut lca = VecDeque::new();
|
||||
lca.push_back(Traverse::traverse(self.root));
|
||||
IntoIter {
|
||||
inner: AbsIter {
|
||||
traversals: lca,
|
||||
size: len,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1263,35 +1286,6 @@ impl<K, V> BTreeMap<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an owning iterator over the entries of the map.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::BTreeMap;
|
||||
///
|
||||
/// let mut map = BTreeMap::new();
|
||||
/// map.insert(1, "a");
|
||||
/// map.insert(2, "b");
|
||||
/// map.insert(3, "c");
|
||||
///
|
||||
/// for (key, value) in map.into_iter() {
|
||||
/// println!("{}: {}", key, value);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<K, V> {
|
||||
let len = self.len();
|
||||
let mut lca = VecDeque::new();
|
||||
lca.push_back(Traverse::traverse(self.root));
|
||||
IntoIter {
|
||||
inner: AbsIter {
|
||||
traversals: lca,
|
||||
size: len,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an iterator over the keys of the map.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -14,10 +14,9 @@
|
||||
use core::prelude::*;
|
||||
|
||||
use core::cmp::Ordering::{self, Less, Greater, Equal};
|
||||
use core::default::Default;
|
||||
use core::fmt::Debug;
|
||||
use core::fmt;
|
||||
use core::iter::{Peekable, Map, FromIterator, IntoIterator};
|
||||
use core::iter::{Peekable, Map, FromIterator};
|
||||
use core::ops::{BitOr, BitAnd, BitXor, Sub};
|
||||
|
||||
use borrow::Borrow;
|
||||
@ -132,27 +131,6 @@ impl<T> BTreeSet<T> {
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
Iter { iter: self.map.keys() }
|
||||
}
|
||||
|
||||
/// Gets an iterator for moving out the BtreeSet's contents.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(core)]
|
||||
/// use std::collections::BTreeSet;
|
||||
///
|
||||
/// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
|
||||
///
|
||||
/// let v: Vec<usize> = set.into_iter().collect();
|
||||
/// assert_eq!(v, [1, 2, 3, 4]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
let first: fn((T, ())) -> T = first; // coerce to fn pointer
|
||||
|
||||
IntoIter { iter: self.map.into_iter().map(first) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> BTreeSet<T> {
|
||||
@ -500,8 +478,24 @@ impl<T> IntoIterator for BTreeSet<T> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
/// Gets an iterator for moving out the BtreeSet's contents.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(core)]
|
||||
/// use std::collections::BTreeSet;
|
||||
///
|
||||
/// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
|
||||
///
|
||||
/// let v: Vec<usize> = set.into_iter().collect();
|
||||
/// assert_eq!(v, [1, 2, 3, 4]);
|
||||
/// ```
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
let first: fn((T, ())) -> T = first; // coerce to fn pointer
|
||||
|
||||
IntoIter { iter: self.map.into_iter().map(first) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
use core::prelude::*;
|
||||
use core::marker;
|
||||
use core::fmt;
|
||||
use core::iter::{FromIterator, IntoIterator};
|
||||
use core::iter::{FromIterator};
|
||||
use core::ops::{Sub, BitOr, BitAnd, BitXor};
|
||||
|
||||
// FIXME(contentions): implement union family of methods? (general design may be wrong here)
|
||||
|
@ -175,7 +175,6 @@
|
||||
//! # #![feature(core, std_misc)]
|
||||
//! use std::fmt;
|
||||
//! use std::f64;
|
||||
//! use std::num::Float;
|
||||
//!
|
||||
//! #[derive(Debug)]
|
||||
//! struct Vector2D {
|
||||
@ -200,10 +199,11 @@
|
||||
//! let magnitude = magnitude.sqrt();
|
||||
//!
|
||||
//! // Respect the formatting flags by using the helper method
|
||||
//! // `pad_integral` on the Formatter object. See the method documentation
|
||||
//! // for details, and the function `pad` can be used to pad strings.
|
||||
//! // `pad_integral` on the Formatter object. See the method
|
||||
//! // documentation for details, and the function `pad` can be used
|
||||
//! // to pad strings.
|
||||
//! let decimals = f.precision().unwrap_or(3);
|
||||
//! let string = f64::to_str_exact(magnitude, decimals);
|
||||
//! let string = format!("{:.*}", decimals, magnitude);
|
||||
//! f.pad_integral(true, "", &string)
|
||||
//! }
|
||||
//! }
|
||||
@ -260,7 +260,6 @@
|
||||
//! Example usage is:
|
||||
//!
|
||||
//! ```
|
||||
//! # #![feature(old_io)]
|
||||
//! # #![allow(unused_must_use)]
|
||||
//! use std::io::Write;
|
||||
//! let mut w = Vec::new();
|
||||
@ -288,7 +287,6 @@
|
||||
//! off, some example usage is:
|
||||
//!
|
||||
//! ```
|
||||
//! # #![feature(old_io)]
|
||||
//! use std::fmt;
|
||||
//! use std::io::{self, Write};
|
||||
//!
|
||||
|
@ -38,6 +38,7 @@
|
||||
#![feature(unsafe_no_drop_flag, filling_drop)]
|
||||
#![feature(step_by)]
|
||||
#![feature(str_char)]
|
||||
#![feature(str_words)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(debug_builders)]
|
||||
#![feature(utf8_error)]
|
||||
|
@ -25,10 +25,9 @@ use core::prelude::*;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use core::cmp::Ordering;
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hash::{Hasher, Hash};
|
||||
use core::iter::{self, FromIterator, IntoIterator};
|
||||
use core::iter::{self, FromIterator};
|
||||
use core::mem;
|
||||
use core::ptr;
|
||||
|
||||
@ -296,13 +295,6 @@ impl<T> LinkedList<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes the list into an iterator yielding elements by value.
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter{list: self}
|
||||
}
|
||||
|
||||
/// Returns `true` if the `LinkedList` is empty.
|
||||
///
|
||||
/// This operation should compute in O(1) time.
|
||||
@ -852,8 +844,10 @@ impl<T> IntoIterator for LinkedList<T> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
/// Consumes the list into an iterator yielding elements by value.
|
||||
#[inline]
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
IntoIter{list: self}
|
||||
}
|
||||
}
|
||||
|
||||
@ -941,7 +935,7 @@ impl<A: Hash> Hash for LinkedList<A> {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::clone::Clone;
|
||||
use std::iter::Iterator;
|
||||
use std::iter::{Iterator, IntoIterator};
|
||||
use std::option::Option::{Some, None, self};
|
||||
use std::__rand::{thread_rng, Rng};
|
||||
use std::thread;
|
||||
|
@ -98,7 +98,7 @@ use self::Direction::*;
|
||||
use borrow::{Borrow, BorrowMut, ToOwned};
|
||||
use vec::Vec;
|
||||
|
||||
pub use core::slice::{Chunks, AsSlice, Windows};
|
||||
pub use core::slice::{Chunks, Windows};
|
||||
pub use core::slice::{Iter, IterMut};
|
||||
pub use core::slice::{IntSliceExt, SplitMut, ChunksMut, Split};
|
||||
pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
|
||||
|
@ -67,7 +67,7 @@ use rustc_unicode;
|
||||
use vec::Vec;
|
||||
use slice::SliceConcatExt;
|
||||
|
||||
pub use core::str::{FromStr, Utf8Error, Str};
|
||||
pub use core::str::{FromStr, Utf8Error};
|
||||
pub use core::str::{Lines, LinesAny, CharRange};
|
||||
pub use core::str::{Split, RSplit};
|
||||
pub use core::str::{SplitN, RSplitN};
|
||||
@ -76,7 +76,7 @@ pub use core::str::{Matches, RMatches};
|
||||
pub use core::str::{MatchIndices, RMatchIndices};
|
||||
pub use core::str::{from_utf8, Chars, CharIndices, Bytes};
|
||||
pub use core::str::{from_utf8_unchecked, ParseBoolError};
|
||||
pub use rustc_unicode::str::{Words, Graphemes, GraphemeIndices};
|
||||
pub use rustc_unicode::str::{SplitWhitespace, Words, Graphemes, GraphemeIndices};
|
||||
pub use core::str::pattern;
|
||||
|
||||
/*
|
||||
@ -1737,27 +1737,44 @@ impl str {
|
||||
UnicodeStr::grapheme_indices(&self[..], is_extended)
|
||||
}
|
||||
|
||||
/// An iterator over the non-empty words of `self`.
|
||||
///
|
||||
/// A 'word' is a subsequence separated by any sequence of whitespace.
|
||||
/// Sequences of whitespace
|
||||
/// are collapsed, so empty "words" are not included.
|
||||
/// An iterator over the non-empty substrings of `self` which contain no whitespace,
|
||||
/// and which are separated by any amount of whitespace.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(str_words)]
|
||||
/// # #![allow(deprecated)]
|
||||
/// let some_words = " Mary had\ta little \n\t lamb";
|
||||
/// let v: Vec<&str> = some_words.words().collect();
|
||||
///
|
||||
/// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
|
||||
/// ```
|
||||
#[deprecated(reason = "words() will be removed. Use split_whitespace() instead",
|
||||
since = "1.1.0")]
|
||||
#[unstable(feature = "str_words",
|
||||
reason = "the precise algorithm to use is unclear")]
|
||||
#[allow(deprecated)]
|
||||
pub fn words(&self) -> Words {
|
||||
UnicodeStr::words(&self[..])
|
||||
}
|
||||
|
||||
/// An iterator over the non-empty substrings of `self` which contain no whitespace,
|
||||
/// and which are separated by any amount of whitespace.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let some_words = " Mary had\ta little \n\t lamb";
|
||||
/// let v: Vec<&str> = some_words.split_whitespace().collect();
|
||||
///
|
||||
/// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
|
||||
/// ```
|
||||
#[stable(feature = "split_whitespace", since = "1.1.0")]
|
||||
pub fn split_whitespace(&self) -> SplitWhitespace {
|
||||
UnicodeStr::split_whitespace(&self[..])
|
||||
}
|
||||
|
||||
/// Returns a string's displayed width in columns.
|
||||
///
|
||||
/// Control characters have zero width.
|
||||
|
@ -14,10 +14,9 @@
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hash;
|
||||
use core::iter::{IntoIterator, FromIterator};
|
||||
use core::iter::FromIterator;
|
||||
use core::mem;
|
||||
use core::ops::{self, Deref, Add, Index};
|
||||
use core::ptr;
|
||||
@ -837,15 +836,6 @@ impl<'a, 'b> PartialEq<Cow<'a, str>> for &'b str {
|
||||
fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&self[..], &other[..]) }
|
||||
}
|
||||
|
||||
#[unstable(feature = "collections", reason = "waiting on Str stabilization")]
|
||||
#[allow(deprecated)]
|
||||
impl Str for String {
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &str {
|
||||
unsafe { mem::transmute(&*self.vec) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Default for String {
|
||||
#[inline]
|
||||
@ -1067,14 +1057,6 @@ impl<'a> IntoCow<'a, str> for &'a str {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<'a> Str for Cow<'a, str> {
|
||||
#[inline]
|
||||
fn as_slice<'b>(&'b self) -> &'b str {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Write for String {
|
||||
#[inline]
|
||||
@ -1082,4 +1064,10 @@ impl fmt::Write for String {
|
||||
self.push_str(s);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_char(&mut self, c: char) -> fmt::Result {
|
||||
self.push(c);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -53,11 +53,10 @@ use alloc::boxed::Box;
|
||||
use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
|
||||
use core::cmp::max;
|
||||
use core::cmp::Ordering;
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hash::{self, Hash};
|
||||
use core::intrinsics::assume;
|
||||
use core::iter::{repeat, FromIterator, IntoIterator};
|
||||
use core::iter::{repeat, FromIterator};
|
||||
use core::marker::PhantomData;
|
||||
use core::mem;
|
||||
use core::ops::{Index, IndexMut, Deref, Add};
|
||||
@ -450,37 +449,6 @@ impl<T> Vec<T> {
|
||||
&mut self[..]
|
||||
}
|
||||
|
||||
/// Creates a consuming iterator, that is, one that moves each value out of
|
||||
/// the vector (from start to end). The vector cannot be used after calling
|
||||
/// this.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let v = vec!["a".to_string(), "b".to_string()];
|
||||
/// for s in v.into_iter() {
|
||||
/// // s has type String, not &String
|
||||
/// println!("{}", s);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
unsafe {
|
||||
let ptr = *self.ptr;
|
||||
assume(!ptr.is_null());
|
||||
let cap = self.cap;
|
||||
let begin = ptr as *const T;
|
||||
let end = if mem::size_of::<T>() == 0 {
|
||||
(ptr as usize + self.len()) as *const T
|
||||
} else {
|
||||
ptr.offset(self.len() as isize) as *const T
|
||||
};
|
||||
mem::forget(self);
|
||||
IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end }
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the length of a vector.
|
||||
///
|
||||
/// This will explicitly set the size of the vector, without actually
|
||||
@ -1512,8 +1480,34 @@ impl<T> IntoIterator for Vec<T> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
/// Creates a consuming iterator, that is, one that moves each value out of
|
||||
/// the vector (from start to end). The vector cannot be used after calling
|
||||
/// this.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let v = vec!["a".to_string(), "b".to_string()];
|
||||
/// for s in v.into_iter() {
|
||||
/// // s has type String, not &String
|
||||
/// println!("{}", s);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
unsafe {
|
||||
let ptr = *self.ptr;
|
||||
assume(!ptr.is_null());
|
||||
let cap = self.cap;
|
||||
let begin = ptr as *const T;
|
||||
let end = if mem::size_of::<T>() == 0 {
|
||||
(ptr as usize + self.len()) as *const T
|
||||
} else {
|
||||
ptr.offset(self.len() as isize) as *const T
|
||||
};
|
||||
mem::forget(self);
|
||||
IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1597,18 +1591,6 @@ impl<T: Ord> Ord for Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collections",
|
||||
reason = "will be replaced by slice syntax")]
|
||||
#[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
|
||||
#[allow(deprecated)]
|
||||
impl<T> AsSlice<T> for Vec<T> {
|
||||
/// Deprecated: use `&mut s[..]` instead.
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "collections",
|
||||
reason = "recent addition, needs more experience")]
|
||||
impl<'a, T: Clone> Add<&'a [T]> for Vec<T> {
|
||||
|
@ -21,9 +21,8 @@
|
||||
use core::prelude::*;
|
||||
|
||||
use core::cmp::Ordering;
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
|
||||
use core::iter::{self, repeat, FromIterator, RandomAccessIterator};
|
||||
use core::mem;
|
||||
use core::ops::{Index, IndexMut};
|
||||
use core::ptr::{self, Unique};
|
||||
@ -557,14 +556,6 @@ impl<T> VecDeque<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes the list into a front-to-back iterator yielding elements by value.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter {
|
||||
inner: self,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a pair of slices which contain, in order, the contents of the
|
||||
/// `VecDeque`.
|
||||
#[inline]
|
||||
@ -1728,8 +1719,12 @@ impl<T> IntoIterator for VecDeque<T> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
/// Consumes the list into a front-to-back iterator yielding elements by
|
||||
/// value.
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
IntoIter {
|
||||
inner: self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,10 +18,9 @@ use self::Entry::*;
|
||||
use core::prelude::*;
|
||||
|
||||
use core::cmp::{max, Ordering};
|
||||
use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
|
||||
use core::iter::{Enumerate, FilterMap, Map, FromIterator};
|
||||
use core::iter;
|
||||
use core::mem::{replace, swap};
|
||||
use core::ops::{Index, IndexMut};
|
||||
@ -301,35 +300,6 @@ impl<V> VecMap<V> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator visiting all key-value pairs in ascending order of
|
||||
/// the keys, consuming the original `VecMap`.
|
||||
/// The iterator's element type is `(usize, &'r V)`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(collections)]
|
||||
/// use std::collections::VecMap;
|
||||
///
|
||||
/// let mut map = VecMap::new();
|
||||
/// map.insert(1, "a");
|
||||
/// map.insert(3, "c");
|
||||
/// map.insert(2, "b");
|
||||
///
|
||||
/// let vec: Vec<(usize, &str)> = map.into_iter().collect();
|
||||
///
|
||||
/// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<V> {
|
||||
fn filter<A>((i, v): (usize, Option<A>)) -> Option<(usize, A)> {
|
||||
v.map(|v| (i, v))
|
||||
}
|
||||
let filter: fn((usize, Option<V>)) -> Option<(usize, V)> = filter; // coerce to fn ptr
|
||||
|
||||
IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) }
|
||||
}
|
||||
|
||||
/// Moves all elements from `other` into the map while overwriting existing keys.
|
||||
///
|
||||
/// # Examples
|
||||
@ -800,8 +770,32 @@ impl<T> IntoIterator for VecMap<T> {
|
||||
type Item = (usize, T);
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
/// Returns an iterator visiting all key-value pairs in ascending order of
|
||||
/// the keys, consuming the original `VecMap`.
|
||||
/// The iterator's element type is `(usize, &'r V)`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(collections)]
|
||||
/// use std::collections::VecMap;
|
||||
///
|
||||
/// let mut map = VecMap::new();
|
||||
/// map.insert(1, "a");
|
||||
/// map.insert(3, "c");
|
||||
/// map.insert(2, "b");
|
||||
///
|
||||
/// let vec: Vec<(usize, &str)> = map.into_iter().collect();
|
||||
///
|
||||
/// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
|
||||
/// ```
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
fn filter<A>((i, v): (usize, Option<A>)) -> Option<(usize, A)> {
|
||||
v.map(|v| (i, v))
|
||||
}
|
||||
let filter: fn((usize, Option<T>)) -> Option<(usize, T)> = filter; // coerce to fn ptr
|
||||
|
||||
IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#![feature(hash)]
|
||||
#![feature(rand)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(str_words)]
|
||||
#![feature(test)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unicode)]
|
||||
|
@ -939,9 +939,9 @@ fn test_rsplitn() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_words() {
|
||||
fn test_split_whitespace() {
|
||||
let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
|
||||
let words: Vec<&str> = data.words().collect();
|
||||
let words: Vec<&str> = data.split_whitespace().collect();
|
||||
assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
|
||||
}
|
||||
|
||||
|
@ -11,15 +11,15 @@
|
||||
pub use self::ExponentFormat::*;
|
||||
pub use self::SignificantDigits::*;
|
||||
|
||||
use char::{self, CharExt};
|
||||
use prelude::*;
|
||||
|
||||
use char;
|
||||
use fmt;
|
||||
use iter::Iterator;
|
||||
use num::{cast, Float, ToPrimitive};
|
||||
use num::Float;
|
||||
use num::FpCategory as Fp;
|
||||
use ops::FnOnce;
|
||||
use result::Result::Ok;
|
||||
use slice::{self, SliceExt};
|
||||
use str::{self, StrExt};
|
||||
use ops::{Div, Rem, Mul};
|
||||
use slice;
|
||||
use str;
|
||||
|
||||
/// A flag that specifies whether to use exponential (scientific) notation.
|
||||
pub enum ExponentFormat {
|
||||
@ -42,6 +42,21 @@ pub enum SignificantDigits {
|
||||
DigExact(usize)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub trait MyFloat: Float + PartialEq + PartialOrd + Div<Output=Self> +
|
||||
Mul<Output=Self> + Rem<Output=Self> + Copy {
|
||||
fn from_u32(u: u32) -> Self;
|
||||
fn to_i32(&self) -> i32;
|
||||
}
|
||||
|
||||
macro_rules! doit {
|
||||
($($t:ident)*) => ($(impl MyFloat for $t {
|
||||
fn from_u32(u: u32) -> $t { u as $t }
|
||||
fn to_i32(&self) -> i32 { *self as i32 }
|
||||
})*)
|
||||
}
|
||||
doit! { f32 f64 }
|
||||
|
||||
/// Converts a float number to its string representation.
|
||||
/// This is meant to be a common base implementation for various formatting styles.
|
||||
/// The number is assumed to be non-negative, callers use `Formatter::pad_integral`
|
||||
@ -63,7 +78,7 @@ pub enum SignificantDigits {
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if `num` is negative.
|
||||
pub fn float_to_str_bytes_common<T: Float, U, F>(
|
||||
pub fn float_to_str_bytes_common<T: MyFloat, U, F>(
|
||||
num: T,
|
||||
digits: SignificantDigits,
|
||||
exp_format: ExponentFormat,
|
||||
@ -72,10 +87,10 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
|
||||
) -> U where
|
||||
F: FnOnce(&str) -> U,
|
||||
{
|
||||
let _0: T = Float::zero();
|
||||
let _1: T = Float::one();
|
||||
let _0: T = T::zero();
|
||||
let _1: T = T::one();
|
||||
let radix: u32 = 10;
|
||||
let radix_f: T = cast(radix).unwrap();
|
||||
let radix_f = T::from_u32(radix);
|
||||
|
||||
assert!(num.is_nan() || num >= _0, "float_to_str_bytes_common: number is negative");
|
||||
|
||||
@ -99,7 +114,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
|
||||
let (num, exp) = match exp_format {
|
||||
ExpDec if num != _0 => {
|
||||
let exp = num.log10().floor();
|
||||
(num / radix_f.powf(exp), cast::<T, i32>(exp).unwrap())
|
||||
(num / radix_f.powf(exp), exp.to_i32())
|
||||
}
|
||||
_ => (num, 0)
|
||||
};
|
||||
@ -114,7 +129,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
|
||||
deccum = deccum / radix_f;
|
||||
deccum = deccum.trunc();
|
||||
|
||||
let c = char::from_digit(current_digit.to_isize().unwrap() as u32, radix);
|
||||
let c = char::from_digit(current_digit.to_i32() as u32, radix);
|
||||
buf[end] = c.unwrap() as u8;
|
||||
end += 1;
|
||||
|
||||
@ -158,7 +173,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
|
||||
|
||||
let current_digit = deccum.trunc();
|
||||
|
||||
let c = char::from_digit(current_digit.to_isize().unwrap() as u32, radix);
|
||||
let c = char::from_digit(current_digit.to_i32() as u32, radix);
|
||||
buf[end] = c.unwrap() as u8;
|
||||
end += 1;
|
||||
|
||||
|
@ -12,21 +12,16 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
|
||||
use char::CharExt;
|
||||
use clone::Clone;
|
||||
use iter::Iterator;
|
||||
use marker::{Copy, PhantomData, Sized};
|
||||
use marker::PhantomData;
|
||||
use mem;
|
||||
use num::Float;
|
||||
use option::Option;
|
||||
use option::Option::{Some, None};
|
||||
use result::Result::Ok;
|
||||
use ops::{Deref, FnOnce};
|
||||
use ops::Deref;
|
||||
use result;
|
||||
use slice::SliceExt;
|
||||
use num::Float;
|
||||
use slice;
|
||||
use str::{self, StrExt};
|
||||
use str;
|
||||
use self::rt::v1::Alignment;
|
||||
|
||||
pub use self::num::radix;
|
||||
@ -83,6 +78,23 @@ pub trait Write {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn write_str(&mut self, s: &str) -> Result;
|
||||
|
||||
/// Writes a `char` into this writer, returning whether the write succeeded.
|
||||
///
|
||||
/// A single `char` may be encoded as more than one byte.
|
||||
/// This method can only succeed if the entire byte sequence was successfully
|
||||
/// written, and this method will not return until all data has been
|
||||
/// written or an error occurs.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an instance of `FormatError` on error.
|
||||
#[stable(feature = "fmt_write_char", since = "1.1.0")]
|
||||
fn write_char(&mut self, c: char) -> Result {
|
||||
let mut utf_8 = [0u8; 4];
|
||||
let bytes_written = c.encode_utf8(&mut utf_8).unwrap_or(0);
|
||||
self.write_str(unsafe { mem::transmute(&utf_8[..bytes_written]) })
|
||||
}
|
||||
|
||||
/// Glue for usage of the `write!` macro with implementers of this trait.
|
||||
///
|
||||
/// This method should generally not be invoked manually, but rather through
|
||||
@ -912,7 +924,8 @@ impl<'a, T> Pointer for &'a mut T {
|
||||
}
|
||||
|
||||
// Common code of floating point Debug and Display.
|
||||
fn float_to_str_common<T: Float, F>(num: &T, precision: Option<usize>, post: F) -> Result
|
||||
fn float_to_str_common<T: float::MyFloat, F>(num: &T, precision: Option<usize>,
|
||||
post: F) -> Result
|
||||
where F : FnOnce(&str) -> Result {
|
||||
let digits = match precision {
|
||||
Some(i) => float::DigExact(i),
|
||||
@ -950,8 +963,6 @@ macro_rules! floating { ($ty:ident) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl LowerExp for $ty {
|
||||
fn fmt(&self, fmt: &mut Formatter) -> Result {
|
||||
use num::Float;
|
||||
|
||||
let digits = match fmt.precision {
|
||||
Some(i) => float::DigExact(i),
|
||||
None => float::DigMax(6),
|
||||
@ -969,8 +980,6 @@ macro_rules! floating { ($ty:ident) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl UpperExp for $ty {
|
||||
fn fmt(&self, fmt: &mut Formatter) -> Result {
|
||||
use num::Float;
|
||||
|
||||
let digits = match fmt.precision {
|
||||
Some(i) => float::DigExact(i),
|
||||
None => float::DigMax(6),
|
||||
|
@ -14,12 +14,28 @@
|
||||
|
||||
#![allow(unsigned_negation)]
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use fmt;
|
||||
use iter::Iterator;
|
||||
use num::{Int, cast};
|
||||
use slice::SliceExt;
|
||||
use num::Zero;
|
||||
use ops::{Div, Rem, Sub};
|
||||
use str;
|
||||
|
||||
#[doc(hidden)]
|
||||
trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
|
||||
Sub<Output=Self> + Copy {
|
||||
fn from_u8(u: u8) -> Self;
|
||||
fn to_u8(&self) -> u8;
|
||||
}
|
||||
|
||||
macro_rules! doit {
|
||||
($($t:ident)*) => ($(impl Int for $t {
|
||||
fn from_u8(u: u8) -> $t { u as $t }
|
||||
fn to_u8(&self) -> u8 { *self as u8 }
|
||||
})*)
|
||||
}
|
||||
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
|
||||
|
||||
/// A type that represents a specific radix
|
||||
#[doc(hidden)]
|
||||
trait GenericRadix {
|
||||
@ -33,33 +49,32 @@ trait GenericRadix {
|
||||
fn digit(&self, x: u8) -> u8;
|
||||
|
||||
/// Format an integer using the radix using a formatter.
|
||||
#[allow(deprecated)] // Int
|
||||
fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// The radix can be as low as 2, so we need a buffer of at least 64
|
||||
// characters for a base 2 number.
|
||||
let zero = Int::zero();
|
||||
let zero = T::zero();
|
||||
let is_positive = x >= zero;
|
||||
let mut buf = [0; 64];
|
||||
let mut curr = buf.len();
|
||||
let base = cast(self.base()).unwrap();
|
||||
let base = T::from_u8(self.base());
|
||||
if is_positive {
|
||||
// Accumulate each digit of the number from the least significant
|
||||
// to the most significant figure.
|
||||
for byte in buf.iter_mut().rev() {
|
||||
let n = x % base; // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
*byte = self.digit(cast(n).unwrap()); // Store the digit in the buffer.
|
||||
let n = x % base; // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
*byte = self.digit(n.to_u8()); // Store the digit in the buffer.
|
||||
curr -= 1;
|
||||
if x == zero { break }; // No more digits left to accumulate.
|
||||
if x == zero { break }; // No more digits left to accumulate.
|
||||
}
|
||||
} else {
|
||||
// Do the same as above, but accounting for two's complement.
|
||||
for byte in buf.iter_mut().rev() {
|
||||
let n = zero - (x % base); // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
*byte = self.digit(cast(n).unwrap()); // Store the digit in the buffer.
|
||||
let n = zero - (x % base); // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
*byte = self.digit(n.to_u8()); // Store the digit in the buffer.
|
||||
curr -= 1;
|
||||
if x == zero { break }; // No more digits left to accumulate.
|
||||
if x == zero { break }; // No more digits left to accumulate.
|
||||
}
|
||||
}
|
||||
let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) };
|
||||
|
@ -62,7 +62,6 @@
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use default::Default;
|
||||
use mem;
|
||||
|
||||
pub use self::sip::SipHasher;
|
||||
|
@ -13,7 +13,6 @@
|
||||
#![allow(deprecated)] // until the next snapshot for inherent wrapping ops
|
||||
|
||||
use prelude::*;
|
||||
use default::Default;
|
||||
use super::Hasher;
|
||||
|
||||
/// An implementation of SipHash 2-4.
|
||||
|
@ -64,7 +64,7 @@ use cmp::{Ord, PartialOrd, PartialEq};
|
||||
use default::Default;
|
||||
use marker;
|
||||
use mem;
|
||||
use num::{Int, Zero, One};
|
||||
use num::{Zero, One};
|
||||
use ops::{self, Add, Sub, FnMut, Mul, RangeFrom};
|
||||
use option::Option::{self, Some, None};
|
||||
use marker::Sized;
|
||||
@ -2327,9 +2327,8 @@ impl<I: RandomAccessIterator, F> RandomAccessIterator for Inspect<I, F>
|
||||
/// An iterator that yields sequential Fibonacci numbers, and stops on overflow.
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(core)]
|
||||
/// #![feature(core)]
|
||||
/// use std::iter::Unfold;
|
||||
/// use std::num::Int; // For `.checked_add()`
|
||||
///
|
||||
/// // This iterator will yield up to the last Fibonacci number before the max
|
||||
/// // value of `u32`. You can simply change `u32` to `u64` in this line if
|
||||
@ -2647,80 +2646,6 @@ impl<A: Step + Zero + Clone> Iterator for StepBy<A, ops::Range<A>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the range [start, stop] by `step`. It handles overflow by stopping.
|
||||
#[derive(Clone)]
|
||||
#[unstable(feature = "core",
|
||||
reason = "likely to be replaced by range notation and adapters")]
|
||||
pub struct RangeStepInclusive<A> {
|
||||
state: A,
|
||||
stop: A,
|
||||
step: A,
|
||||
rev: bool,
|
||||
done: bool,
|
||||
}
|
||||
|
||||
/// Returns an iterator over the range [start, stop] by `step`.
|
||||
///
|
||||
/// It handles overflow by stopping.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(core)]
|
||||
/// use std::iter::range_step_inclusive;
|
||||
///
|
||||
/// for i in range_step_inclusive(0, 10, 2) {
|
||||
/// println!("{}", i);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This prints:
|
||||
///
|
||||
/// ```text
|
||||
/// 0
|
||||
/// 2
|
||||
/// 4
|
||||
/// 6
|
||||
/// 8
|
||||
/// 10
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "core",
|
||||
reason = "likely to be replaced by range notation and adapters")]
|
||||
#[allow(deprecated)]
|
||||
pub fn range_step_inclusive<A: Int>(start: A, stop: A, step: A) -> RangeStepInclusive<A> {
|
||||
let rev = step < Int::zero();
|
||||
RangeStepInclusive {
|
||||
state: start,
|
||||
stop: stop,
|
||||
step: step,
|
||||
rev: rev,
|
||||
done: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "core",
|
||||
reason = "likely to be replaced by range notation and adapters")]
|
||||
#[allow(deprecated)]
|
||||
impl<A: Int> Iterator for RangeStepInclusive<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
if !self.done && ((self.rev && self.state >= self.stop) ||
|
||||
(!self.rev && self.state <= self.stop)) {
|
||||
let result = self.state;
|
||||
match self.state.checked_add(self.step) {
|
||||
Some(x) => self.state = x,
|
||||
None => self.done = true
|
||||
}
|
||||
Some(result)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! range_exact_iter_impl {
|
||||
($($t:ty)*) => ($(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -108,6 +108,7 @@ mod uint_macros;
|
||||
#[path = "num/f32.rs"] pub mod f32;
|
||||
#[path = "num/f64.rs"] pub mod f64;
|
||||
|
||||
#[macro_use]
|
||||
pub mod num;
|
||||
|
||||
/* The libcore prelude, not as all-encompassing as the libstd prelude */
|
||||
|
@ -35,7 +35,16 @@ use hash::Hasher;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang="send"]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||
#[allow(deprecated)]
|
||||
#[cfg(not(stage0))]
|
||||
pub unsafe trait Send {
|
||||
// empty.
|
||||
}
|
||||
|
||||
/// Types able to be transferred across thread boundaries.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang="send"]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||
#[cfg(stage0)]
|
||||
pub unsafe trait Send : MarkerTrait {
|
||||
// empty.
|
||||
}
|
||||
@ -51,7 +60,17 @@ impl !Send for Managed { }
|
||||
#[lang="sized"]
|
||||
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
|
||||
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
|
||||
#[allow(deprecated)]
|
||||
#[cfg(not(stage0))]
|
||||
pub trait Sized {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Types with a constant size known at compile-time.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang="sized"]
|
||||
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
|
||||
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
|
||||
#[cfg(stage0)]
|
||||
pub trait Sized : MarkerTrait {
|
||||
// Empty.
|
||||
}
|
||||
@ -199,13 +218,23 @@ pub trait Copy : Clone {
|
||||
/// the `sync` crate do ensure that any mutation cannot cause data
|
||||
/// races. Hence these types are `Sync`.
|
||||
///
|
||||
/// Any types with interior mutability must also use the `std::cell::UnsafeCell` wrapper around the
|
||||
/// value(s) which can be mutated when behind a `&` reference; not doing this is undefined
|
||||
/// behaviour (for example, `transmute`-ing from `&T` to `&mut T` is illegal).
|
||||
/// Any types with interior mutability must also use the `std::cell::UnsafeCell`
|
||||
/// wrapper around the value(s) which can be mutated when behind a `&`
|
||||
/// reference; not doing this is undefined behaviour (for example,
|
||||
/// `transmute`-ing from `&T` to `&mut T` is illegal).
|
||||
#[cfg(not(stage0))]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang="sync"]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
|
||||
pub unsafe trait Sync {
|
||||
// Empty
|
||||
}
|
||||
|
||||
/// dox
|
||||
#[cfg(stage0)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang="sync"]
|
||||
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
|
||||
#[allow(deprecated)]
|
||||
pub unsafe trait Sync : MarkerTrait {
|
||||
// Empty
|
||||
}
|
||||
@ -272,42 +301,20 @@ macro_rules! impls{
|
||||
)
|
||||
}
|
||||
|
||||
/// `MarkerTrait` is deprecated and no longer needed.
|
||||
/// dox
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "No longer needed")]
|
||||
#[allow(deprecated)]
|
||||
#[cfg(stage0)]
|
||||
pub trait MarkerTrait : PhantomFn<Self,Self> { }
|
||||
|
||||
/// `MarkerTrait` is deprecated and no longer needed.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "No longer needed")]
|
||||
#[allow(deprecated)]
|
||||
#[cfg(not(stage0))]
|
||||
pub trait MarkerTrait { }
|
||||
#[cfg(stage0)]
|
||||
impl<T: ?Sized> MarkerTrait for T {}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<T:?Sized> MarkerTrait for T { }
|
||||
|
||||
/// `PhantomFn` is a deprecated marker trait that is no longer needed.
|
||||
/// dox
|
||||
#[lang="phantom_fn"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "No longer needed")]
|
||||
#[cfg(stage0)]
|
||||
pub trait PhantomFn<A:?Sized,R:?Sized=()> {
|
||||
}
|
||||
|
||||
/// `PhantomFn` is a deprecated marker trait that is no longer needed.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "No longer needed")]
|
||||
#[cfg(not(stage0))]
|
||||
pub trait PhantomFn<A:?Sized,R:?Sized=()> {
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
#[cfg(not(stage0))]
|
||||
impl<A:?Sized,R:?Sized,T:?Sized> PhantomFn<A,R> for T { }
|
||||
|
||||
/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
|
||||
/// even though it does not. This allows you to inform the compiler about certain safety properties
|
||||
/// of your code.
|
||||
@ -454,8 +461,14 @@ mod impls {
|
||||
#[rustc_reflect_like]
|
||||
#[unstable(feature = "core", reason = "requires RFC and more experience")]
|
||||
#[allow(deprecated)]
|
||||
pub trait Reflect : MarkerTrait {
|
||||
}
|
||||
#[cfg(not(stage0))]
|
||||
pub trait Reflect {}
|
||||
|
||||
/// dox
|
||||
#[rustc_reflect_like]
|
||||
#[unstable(feature = "core", reason = "requires RFC and more experience")]
|
||||
#[cfg(stage0)]
|
||||
pub trait Reflect: MarkerTrait {}
|
||||
|
||||
impl Reflect for .. { }
|
||||
|
||||
|
@ -10,12 +10,17 @@
|
||||
|
||||
//! Exposes the NonZero lang item which provides optimization hints.
|
||||
|
||||
use marker::{Sized, MarkerTrait};
|
||||
use marker::Sized;
|
||||
use ops::Deref;
|
||||
#[cfg(stage0)] use marker::MarkerTrait;
|
||||
|
||||
/// Unsafe trait to indicate what types are usable with the NonZero struct
|
||||
#[allow(deprecated)]
|
||||
pub unsafe trait Zeroable : MarkerTrait {}
|
||||
#[cfg(not(stage0))]
|
||||
pub unsafe trait Zeroable {}
|
||||
|
||||
/// Unsafe trait to indicate what types are usable with the NonZero struct
|
||||
#[cfg(stage0)]
|
||||
pub unsafe trait Zeroable: MarkerTrait {}
|
||||
|
||||
unsafe impl<T:?Sized> Zeroable for *const T {}
|
||||
unsafe impl<T:?Sized> Zeroable for *mut T {}
|
||||
|
@ -16,11 +16,12 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use intrinsics;
|
||||
use mem;
|
||||
use num::Float;
|
||||
use num::{Float, ParseFloatError};
|
||||
use num::FpCategory as Fp;
|
||||
use option::Option;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const RADIX: u32 = 2;
|
||||
@ -33,19 +34,6 @@ pub const DIGITS: u32 = 6;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const EPSILON: f32 = 1.19209290e-07_f32;
|
||||
|
||||
/// Smallest finite f32 value
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "use `std::f32::MIN`")]
|
||||
pub const MIN_VALUE: f32 = -3.40282347e+38_f32;
|
||||
/// Smallest positive, normalized f32 value
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "use `std::f32::MIN_POSITIVE`")]
|
||||
pub const MIN_POS_VALUE: f32 = 1.17549435e-38_f32;
|
||||
/// Largest finite f32 value
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "use `std::f32::MAX`")]
|
||||
pub const MAX_VALUE: f32 = 3.40282347e+38_f32;
|
||||
|
||||
/// Smallest finite f32 value
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MIN: f32 = -3.40282347e+38_f32;
|
||||
@ -118,26 +106,14 @@ pub mod consts {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_2_SQRT_PI: f32 = 1.12837916709551257389615890312154517_f32;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_2_SQRT_PI")]
|
||||
pub const FRAC_2_SQRTPI: f32 = 1.12837916709551257389615890312154517_f32;
|
||||
|
||||
/// sqrt(2.0)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const SQRT_2: f32 = 1.41421356237309504880168872420969808_f32;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to SQRT_2")]
|
||||
pub const SQRT2: f32 = 1.41421356237309504880168872420969808_f32;
|
||||
|
||||
/// 1.0/sqrt(2.0)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_1_SQRT_2")]
|
||||
pub const FRAC_1_SQRT2: f32 = 0.707106781186547524400844362104849039_f32;
|
||||
|
||||
/// Euler's number
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const E: f32 = 2.71828182845904523536028747135266250_f32;
|
||||
@ -179,6 +155,8 @@ impl Float for f32 {
|
||||
#[inline]
|
||||
fn one() -> f32 { 1.0 }
|
||||
|
||||
from_str_radix_float_impl! { f32 }
|
||||
|
||||
/// Returns `true` if the number is NaN.
|
||||
#[inline]
|
||||
fn is_nan(self) -> bool { self != self }
|
||||
@ -218,56 +196,6 @@ impl Float for f32 {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn mantissa_digits(_: Option<f32>) -> usize { MANTISSA_DIGITS as usize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn digits(_: Option<f32>) -> usize { DIGITS as usize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn epsilon() -> f32 { EPSILON }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn min_exp(_: Option<f32>) -> isize { MIN_EXP as isize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn max_exp(_: Option<f32>) -> isize { MAX_EXP as isize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn min_10_exp(_: Option<f32>) -> isize { MIN_10_EXP as isize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn max_10_exp(_: Option<f32>) -> isize { MAX_10_EXP as isize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn min_value() -> f32 { MIN }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn min_pos_value(_: Option<f32>) -> f32 { MIN_POSITIVE }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn max_value() -> f32 { MAX }
|
||||
|
||||
/// Returns the mantissa, exponent and sign as integers.
|
||||
fn integer_decode(self) -> (u64, i16, i8) {
|
||||
let bits: u32 = unsafe { mem::transmute(self) };
|
||||
@ -310,9 +238,6 @@ impl Float for f32 {
|
||||
/// The fractional part of the number, satisfying:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(core)]
|
||||
/// use std::num::Float;
|
||||
///
|
||||
/// let x = 1.65f32;
|
||||
/// assert!(x == x.trunc() + x.fract())
|
||||
/// ```
|
||||
|
@ -16,11 +16,12 @@
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use intrinsics;
|
||||
use mem;
|
||||
use num::Float;
|
||||
use num::FpCategory as Fp;
|
||||
use option::Option;
|
||||
use num::{Float, ParseFloatError};
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const RADIX: u32 = 2;
|
||||
@ -33,19 +34,6 @@ pub const DIGITS: u32 = 15;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
|
||||
|
||||
/// Smallest finite f64 value
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "use `std::f64::MIN`")]
|
||||
pub const MIN_VALUE: f64 = -1.7976931348623157e+308_f64;
|
||||
/// Smallest positive, normalized f64 value
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "use `std::f64::MIN_POSITIVE`")]
|
||||
pub const MIN_POS_VALUE: f64 = 2.2250738585072014e-308_f64;
|
||||
/// Largest finite f64 value
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "use `std::f64::MAX`")]
|
||||
pub const MAX_VALUE: f64 = 1.7976931348623157e+308_f64;
|
||||
|
||||
/// Smallest finite f64 value
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MIN: f64 = -1.7976931348623157e+308_f64;
|
||||
@ -118,26 +106,14 @@ pub mod consts {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_2_SQRT_PI: f64 = 1.12837916709551257389615890312154517_f64;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_2_SQRT_PI")]
|
||||
pub const FRAC_2_SQRTPI: f64 = 1.12837916709551257389615890312154517_f64;
|
||||
|
||||
/// sqrt(2.0)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const SQRT_2: f64 = 1.41421356237309504880168872420969808_f64;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to SQRT_2")]
|
||||
pub const SQRT2: f64 = 1.41421356237309504880168872420969808_f64;
|
||||
|
||||
/// 1.0/sqrt(2.0)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[deprecated(since = "1.0.0", reason = "renamed to FRAC_1_SQRT_2")]
|
||||
pub const FRAC_1_SQRT2: f64 = 0.707106781186547524400844362104849039_f64;
|
||||
|
||||
/// Euler's number
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const E: f64 = 2.71828182845904523536028747135266250_f64;
|
||||
@ -179,6 +155,8 @@ impl Float for f64 {
|
||||
#[inline]
|
||||
fn one() -> f64 { 1.0 }
|
||||
|
||||
from_str_radix_float_impl! { f64 }
|
||||
|
||||
/// Returns `true` if the number is NaN.
|
||||
#[inline]
|
||||
fn is_nan(self) -> bool { self != self }
|
||||
@ -218,56 +196,6 @@ impl Float for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn mantissa_digits(_: Option<f64>) -> usize { MANTISSA_DIGITS as usize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn digits(_: Option<f64>) -> usize { DIGITS as usize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn epsilon() -> f64 { EPSILON }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn min_exp(_: Option<f64>) -> isize { MIN_EXP as isize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn max_exp(_: Option<f64>) -> isize { MAX_EXP as isize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn min_10_exp(_: Option<f64>) -> isize { MIN_10_EXP as isize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn max_10_exp(_: Option<f64>) -> isize { MAX_10_EXP as isize }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn min_value() -> f64 { MIN }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn min_pos_value(_: Option<f64>) -> f64 { MIN_POSITIVE }
|
||||
|
||||
#[inline]
|
||||
#[unstable(feature = "core")]
|
||||
#[deprecated(since = "1.0.0")]
|
||||
fn max_value() -> f64 { MAX }
|
||||
|
||||
/// Returns the mantissa, exponent and sign as integers.
|
||||
fn integer_decode(self) -> (u64, i16, i8) {
|
||||
let bits: u64 = unsafe { mem::transmute(self) };
|
||||
@ -310,9 +238,6 @@ impl Float for f64 {
|
||||
/// The fractional part of the number, satisfying:
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(core)]
|
||||
/// use std::num::Float;
|
||||
///
|
||||
/// let x = 1.65f64;
|
||||
/// assert!(x == x.trunc() + x.fract())
|
||||
/// ```
|
||||
|
@ -18,3 +18,145 @@ macro_rules! assert_approx_eq {
|
||||
"{} is not approximately equal to {}", *a, *b);
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! from_str_radix_float_impl {
|
||||
($T:ty) => {
|
||||
fn from_str_radix(src: &str, radix: u32)
|
||||
-> Result<$T, ParseFloatError> {
|
||||
use num::FloatErrorKind::*;
|
||||
use num::ParseFloatError as PFE;
|
||||
|
||||
// Special values
|
||||
match src {
|
||||
"inf" => return Ok(Float::infinity()),
|
||||
"-inf" => return Ok(Float::neg_infinity()),
|
||||
"NaN" => return Ok(Float::nan()),
|
||||
_ => {},
|
||||
}
|
||||
|
||||
let (is_positive, src) = match src.slice_shift_char() {
|
||||
None => return Err(PFE { kind: Empty }),
|
||||
Some(('-', "")) => return Err(PFE { kind: Empty }),
|
||||
Some(('-', src)) => (false, src),
|
||||
Some((_, _)) => (true, src),
|
||||
};
|
||||
|
||||
// The significand to accumulate
|
||||
let mut sig = if is_positive { 0.0 } else { -0.0 };
|
||||
// Necessary to detect overflow
|
||||
let mut prev_sig = sig;
|
||||
let mut cs = src.chars().enumerate();
|
||||
// Exponent prefix and exponent index offset
|
||||
let mut exp_info = None::<(char, usize)>;
|
||||
|
||||
// Parse the integer part of the significand
|
||||
for (i, c) in cs.by_ref() {
|
||||
match c.to_digit(radix) {
|
||||
Some(digit) => {
|
||||
// shift significand one digit left
|
||||
sig = sig * (radix as $T);
|
||||
|
||||
// add/subtract current digit depending on sign
|
||||
if is_positive {
|
||||
sig = sig + ((digit as isize) as $T);
|
||||
} else {
|
||||
sig = sig - ((digit as isize) as $T);
|
||||
}
|
||||
|
||||
// Detect overflow by comparing to last value, except
|
||||
// if we've not seen any non-zero digits.
|
||||
if prev_sig != 0.0 {
|
||||
if is_positive && sig <= prev_sig
|
||||
{ return Ok(Float::infinity()); }
|
||||
if !is_positive && sig >= prev_sig
|
||||
{ return Ok(Float::neg_infinity()); }
|
||||
|
||||
// Detect overflow by reversing the shift-and-add process
|
||||
if is_positive && (prev_sig != (sig - digit as $T) / radix as $T)
|
||||
{ return Ok(Float::infinity()); }
|
||||
if !is_positive && (prev_sig != (sig + digit as $T) / radix as $T)
|
||||
{ return Ok(Float::neg_infinity()); }
|
||||
}
|
||||
prev_sig = sig;
|
||||
},
|
||||
None => match c {
|
||||
'e' | 'E' | 'p' | 'P' => {
|
||||
exp_info = Some((c, i + 1));
|
||||
break; // start of exponent
|
||||
},
|
||||
'.' => {
|
||||
break; // start of fractional part
|
||||
},
|
||||
_ => {
|
||||
return Err(PFE { kind: Invalid });
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// If we are not yet at the exponent parse the fractional
|
||||
// part of the significand
|
||||
if exp_info.is_none() {
|
||||
let mut power = 1.0;
|
||||
for (i, c) in cs.by_ref() {
|
||||
match c.to_digit(radix) {
|
||||
Some(digit) => {
|
||||
// Decrease power one order of magnitude
|
||||
power = power / (radix as $T);
|
||||
// add/subtract current digit depending on sign
|
||||
sig = if is_positive {
|
||||
sig + (digit as $T) * power
|
||||
} else {
|
||||
sig - (digit as $T) * power
|
||||
};
|
||||
// Detect overflow by comparing to last value
|
||||
if is_positive && sig < prev_sig
|
||||
{ return Ok(Float::infinity()); }
|
||||
if !is_positive && sig > prev_sig
|
||||
{ return Ok(Float::neg_infinity()); }
|
||||
prev_sig = sig;
|
||||
},
|
||||
None => match c {
|
||||
'e' | 'E' | 'p' | 'P' => {
|
||||
exp_info = Some((c, i + 1));
|
||||
break; // start of exponent
|
||||
},
|
||||
_ => {
|
||||
return Err(PFE { kind: Invalid });
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse and calculate the exponent
|
||||
let exp = match exp_info {
|
||||
Some((c, offset)) => {
|
||||
let base = match c {
|
||||
'E' | 'e' if radix == 10 => 10.0,
|
||||
'P' | 'p' if radix == 16 => 2.0,
|
||||
_ => return Err(PFE { kind: Invalid }),
|
||||
};
|
||||
|
||||
// Parse the exponent as decimal integer
|
||||
let src = &src[offset..];
|
||||
let (is_positive, exp) = match src.slice_shift_char() {
|
||||
Some(('-', src)) => (false, src.parse::<usize>()),
|
||||
Some(('+', src)) => (true, src.parse::<usize>()),
|
||||
Some((_, _)) => (true, src.parse::<usize>()),
|
||||
None => return Err(PFE { kind: Invalid }),
|
||||
};
|
||||
|
||||
match (is_positive, exp) {
|
||||
(true, Ok(exp)) => base.powi(exp as i32),
|
||||
(false, Ok(exp)) => 1.0 / base.powi(exp as i32),
|
||||
(_, Err(_)) => return Err(PFE { kind: Invalid }),
|
||||
}
|
||||
},
|
||||
None => 1.0, // no exponent
|
||||
};
|
||||
|
||||
Ok(sig * exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -15,8 +15,6 @@ use super::Wrapping;
|
||||
|
||||
use ops::*;
|
||||
|
||||
use intrinsics::{overflowing_add, overflowing_sub, overflowing_mul};
|
||||
|
||||
use intrinsics::{i8_add_with_overflow, u8_add_with_overflow};
|
||||
use intrinsics::{i16_add_with_overflow, u16_add_with_overflow};
|
||||
use intrinsics::{i32_add_with_overflow, u32_add_with_overflow};
|
||||
@ -32,14 +30,6 @@ use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};
|
||||
|
||||
use ::{i8,i16,i32,i64};
|
||||
|
||||
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
|
||||
#[deprecated(since = "1.0.0", reason = "moved to inherent methods")]
|
||||
pub trait WrappingOps {
|
||||
fn wrapping_add(self, rhs: Self) -> Self;
|
||||
fn wrapping_sub(self, rhs: Self) -> Self;
|
||||
fn wrapping_mul(self, rhs: Self) -> Self;
|
||||
}
|
||||
|
||||
#[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
|
||||
pub trait OverflowingOps {
|
||||
fn overflowing_add(self, rhs: Self) -> (Self, bool);
|
||||
@ -99,27 +89,6 @@ sh_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
|
||||
|
||||
macro_rules! wrapping_impl {
|
||||
($($t:ty)*) => ($(
|
||||
impl WrappingOps for $t {
|
||||
#[inline(always)]
|
||||
fn wrapping_add(self, rhs: $t) -> $t {
|
||||
unsafe {
|
||||
overflowing_add(self, rhs)
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn wrapping_sub(self, rhs: $t) -> $t {
|
||||
unsafe {
|
||||
overflowing_sub(self, rhs)
|
||||
}
|
||||
}
|
||||
#[inline(always)]
|
||||
fn wrapping_mul(self, rhs: $t) -> $t {
|
||||
unsafe {
|
||||
overflowing_mul(self, rhs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Add for Wrapping<$t> {
|
||||
type Output = Wrapping<$t>;
|
||||
|
@ -551,25 +551,6 @@ impl<T> Option<T> {
|
||||
IterMut { inner: Item { opt: self.as_mut() } }
|
||||
}
|
||||
|
||||
/// Returns a consuming iterator over the possibly contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let x = Some("string");
|
||||
/// let v: Vec<&str> = x.into_iter().collect();
|
||||
/// assert_eq!(v, ["string"]);
|
||||
///
|
||||
/// let x = None;
|
||||
/// let v: Vec<&str> = x.into_iter().collect();
|
||||
/// assert!(v.is_empty());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter { inner: Item { opt: self } }
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// Boolean operations on the values, eager and lazy
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
@ -770,6 +751,30 @@ impl<T> Default for Option<T> {
|
||||
fn default() -> Option<T> { None }
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> IntoIterator for Option<T> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
/// Returns a consuming iterator over the possibly contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let x = Some("string");
|
||||
/// let v: Vec<&str> = x.into_iter().collect();
|
||||
/// assert_eq!(v, ["string"]);
|
||||
///
|
||||
/// let x = None;
|
||||
/// let v: Vec<&str> = x.into_iter().collect();
|
||||
/// assert!(v.is_empty());
|
||||
/// ```
|
||||
#[inline]
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter { inner: Item { opt: self } }
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// The Option Iterators
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -37,11 +37,10 @@ pub use char::CharExt;
|
||||
pub use clone::Clone;
|
||||
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
|
||||
pub use convert::{AsRef, AsMut, Into, From};
|
||||
pub use default::Default;
|
||||
pub use iter::IntoIterator;
|
||||
pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator};
|
||||
pub use option::Option::{self, Some, None};
|
||||
pub use result::Result::{self, Ok, Err};
|
||||
pub use slice::SliceExt;
|
||||
pub use str::StrExt;
|
||||
|
||||
#[allow(deprecated)] pub use slice::AsSlice;
|
||||
#[allow(deprecated)] pub use str::Str;
|
||||
|
@ -234,8 +234,6 @@ use fmt;
|
||||
use iter::{Iterator, DoubleEndedIterator, FromIterator, ExactSizeIterator, IntoIterator};
|
||||
use ops::{FnMut, FnOnce};
|
||||
use option::Option::{self, None, Some};
|
||||
#[allow(deprecated)]
|
||||
use slice::AsSlice;
|
||||
use slice;
|
||||
|
||||
/// `Result` is a type that represents either success (`Ok`) or failure (`Err`).
|
||||
@ -547,25 +545,6 @@ impl<T, E> Result<T, E> {
|
||||
IterMut { inner: self.as_mut().ok() }
|
||||
}
|
||||
|
||||
/// Returns a consuming iterator over the possibly contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<u32, &str> = Ok(5);
|
||||
/// let v: Vec<u32> = x.into_iter().collect();
|
||||
/// assert_eq!(v, [5]);
|
||||
///
|
||||
/// let x: Result<u32, &str> = Err("nothing!");
|
||||
/// let v: Vec<u32> = x.into_iter().collect();
|
||||
/// assert_eq!(v, []);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter { inner: self.ok() }
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Boolean operations on the values, eager and lazy
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
@ -787,23 +766,27 @@ impl<T: fmt::Debug, E> Result<T, E> {
|
||||
// Trait implementations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[unstable(feature = "core",
|
||||
reason = "waiting on the stability of the trait itself")]
|
||||
#[deprecated(since = "1.0.0",
|
||||
reason = "use inherent method instead")]
|
||||
#[allow(deprecated)]
|
||||
impl<T, E> AsSlice<T> for Result<T, E> {
|
||||
/// Converts from `Result<T, E>` to `&[T]` (without copying)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T, E> IntoIterator for Result<T, E> {
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
/// Returns a consuming iterator over the possibly contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let x: Result<u32, &str> = Ok(5);
|
||||
/// let v: Vec<u32> = x.into_iter().collect();
|
||||
/// assert_eq!(v, [5]);
|
||||
///
|
||||
/// let x: Result<u32, &str> = Err("nothing!");
|
||||
/// let v: Vec<u32> = x.into_iter().collect();
|
||||
/// assert_eq!(v, []);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn as_slice<'a>(&'a self) -> &'a [T] {
|
||||
match *self {
|
||||
Ok(ref x) => slice::ref_slice(x),
|
||||
Err(_) => {
|
||||
// work around lack of implicit coercion from fixed-size array to slice
|
||||
let emp: &[_] = &[];
|
||||
emp
|
||||
}
|
||||
}
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter { inner: self.ok() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ use result::Result::{Ok, Err};
|
||||
use ptr;
|
||||
use mem;
|
||||
use mem::size_of;
|
||||
use marker::{Send, Sized, Sync, self};
|
||||
use marker::{Send, Sync, self};
|
||||
use raw::Repr;
|
||||
// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
|
||||
use raw::Slice as RawSlice;
|
||||
@ -595,37 +595,6 @@ impl<T> ops::IndexMut<RangeFull> for [T] {
|
||||
// Common traits
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Data that is viewable as a slice.
|
||||
#[unstable(feature = "core",
|
||||
reason = "will be replaced by slice syntax")]
|
||||
#[deprecated(since = "1.0.0",
|
||||
reason = "use std::convert::AsRef<[T]> instead")]
|
||||
pub trait AsSlice<T> {
|
||||
/// Work with `self` as a slice.
|
||||
fn as_slice<'a>(&'a self) -> &'a [T];
|
||||
}
|
||||
|
||||
#[unstable(feature = "core", reason = "trait is experimental")]
|
||||
#[allow(deprecated)]
|
||||
impl<T> AsSlice<T> for [T] {
|
||||
#[inline(always)]
|
||||
fn as_slice<'a>(&'a self) -> &'a [T] { self }
|
||||
}
|
||||
|
||||
#[unstable(feature = "core", reason = "trait is experimental")]
|
||||
#[allow(deprecated)]
|
||||
impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a U {
|
||||
#[inline(always)]
|
||||
fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
|
||||
}
|
||||
|
||||
#[unstable(feature = "core", reason = "trait is experimental")]
|
||||
#[allow(deprecated)]
|
||||
impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a mut U {
|
||||
#[inline(always)]
|
||||
fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T> Default for &'a [T] {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -25,7 +25,6 @@ use default::Default;
|
||||
use fmt;
|
||||
use iter::ExactSizeIterator;
|
||||
use iter::{Map, Iterator, DoubleEndedIterator};
|
||||
use marker::Sized;
|
||||
use mem;
|
||||
use ops::{Fn, FnMut, FnOnce};
|
||||
use option::Option::{self, None, Some};
|
||||
@ -1463,30 +1462,6 @@ mod traits {
|
||||
}
|
||||
}
|
||||
|
||||
/// Any string that can be represented as a slice
|
||||
#[unstable(feature = "core",
|
||||
reason = "Instead of taking this bound generically, this trait will be \
|
||||
replaced with one of slicing syntax (&foo[..]), deref coercions, or \
|
||||
a more generic conversion trait")]
|
||||
#[deprecated(since = "1.0.0",
|
||||
reason = "use std::convert::AsRef<str> instead")]
|
||||
pub trait Str {
|
||||
/// Work with `self` as a slice.
|
||||
fn as_slice<'a>(&'a self) -> &'a str;
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl Str for str {
|
||||
#[inline]
|
||||
fn as_slice<'a>(&'a self) -> &'a str { self }
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
impl<'a, S: ?Sized> Str for &'a S where S: Str {
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &str { Str::as_slice(*self) }
|
||||
}
|
||||
|
||||
/// Methods for string slices
|
||||
#[allow(missing_docs)]
|
||||
#[doc(hidden)]
|
||||
|
@ -110,8 +110,6 @@ fn test_partial_max() {
|
||||
|
||||
#[test]
|
||||
fn test_user_defined_eq() {
|
||||
use core::num::SignedInt;
|
||||
|
||||
// Our type.
|
||||
struct SketchyNum {
|
||||
num : isize
|
||||
|
@ -11,7 +11,6 @@
|
||||
use core::iter::*;
|
||||
use core::iter::order::*;
|
||||
use core::iter::MinMaxResult::*;
|
||||
use core::num::SignedInt;
|
||||
use core::usize;
|
||||
use core::cmp;
|
||||
|
||||
@ -783,16 +782,6 @@ fn test_range_step() {
|
||||
assert_eq!((200..200).step_by(1).collect::<Vec<isize>>(), []);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_range_step_inclusive() {
|
||||
assert_eq!(range_step_inclusive(0, 20, 5).collect::<Vec<isize>>(), [0, 5, 10, 15, 20]);
|
||||
assert_eq!(range_step_inclusive(20, 0, -5).collect::<Vec<isize>>(), [20, 15, 10, 5, 0]);
|
||||
assert_eq!(range_step_inclusive(20, 0, -6).collect::<Vec<isize>>(), [20, 14, 8, 2]);
|
||||
assert_eq!(range_step_inclusive(200, 255, 50).collect::<Vec<u8>>(), [200, 250]);
|
||||
assert_eq!(range_step_inclusive(200, -5, 1).collect::<Vec<isize>>(), []);
|
||||
assert_eq!(range_step_inclusive(200, 200, 1).collect::<Vec<isize>>(), [200]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reverse() {
|
||||
let mut ys = [1, 2, 3, 4, 5];
|
||||
|
@ -10,8 +10,8 @@
|
||||
|
||||
// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
|
||||
#![cfg_attr(stage0, feature(custom_attribute))]
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(int_uint)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unsafe_destructor)]
|
||||
#![feature(core)]
|
||||
@ -21,13 +21,11 @@
|
||||
#![feature(std_misc)]
|
||||
#![feature(libc)]
|
||||
#![feature(hash)]
|
||||
#![feature(io)]
|
||||
#![feature(collections)]
|
||||
#![feature(debug_builders)]
|
||||
#![feature(unique)]
|
||||
#![feature(step_by)]
|
||||
#![feature(slice_patterns)]
|
||||
#![allow(deprecated)] // rand
|
||||
#![feature(float_from_str_radix)]
|
||||
|
||||
extern crate core;
|
||||
extern crate test;
|
||||
|
@ -8,12 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
macro_rules! int_module { ($T:ty, $T_i:ident) => (
|
||||
macro_rules! int_module { ($T:ident, $T_i:ident) => (
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use core::$T_i::*;
|
||||
use core::isize;
|
||||
use core::num::{FromStrRadix, Int, SignedInt};
|
||||
use core::ops::{Shl, Shr, Not, BitXor, BitAnd, BitOr};
|
||||
use num;
|
||||
|
||||
@ -129,30 +128,30 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_le() {
|
||||
assert_eq!(Int::from_le(A.to_le()), A);
|
||||
assert_eq!(Int::from_le(B.to_le()), B);
|
||||
assert_eq!(Int::from_le(C.to_le()), C);
|
||||
assert_eq!(Int::from_le(_0), _0);
|
||||
assert_eq!(Int::from_le(_1), _1);
|
||||
assert_eq!($T::from_le(A.to_le()), A);
|
||||
assert_eq!($T::from_le(B.to_le()), B);
|
||||
assert_eq!($T::from_le(C.to_le()), C);
|
||||
assert_eq!($T::from_le(_0), _0);
|
||||
assert_eq!($T::from_le(_1), _1);
|
||||
assert_eq!(_0.to_le(), _0);
|
||||
assert_eq!(_1.to_le(), _1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_be() {
|
||||
assert_eq!(Int::from_be(A.to_be()), A);
|
||||
assert_eq!(Int::from_be(B.to_be()), B);
|
||||
assert_eq!(Int::from_be(C.to_be()), C);
|
||||
assert_eq!(Int::from_be(_0), _0);
|
||||
assert_eq!(Int::from_be(_1), _1);
|
||||
assert_eq!($T::from_be(A.to_be()), A);
|
||||
assert_eq!($T::from_be(B.to_be()), B);
|
||||
assert_eq!($T::from_be(C.to_be()), C);
|
||||
assert_eq!($T::from_be(_0), _0);
|
||||
assert_eq!($T::from_be(_1), _1);
|
||||
assert_eq!(_0.to_be(), _0);
|
||||
assert_eq!(_1.to_be(), _1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_signed_checked_div() {
|
||||
assert!(10.checked_div(2) == Some(5));
|
||||
assert!(5.checked_div(0) == None);
|
||||
assert!((10 as $T).checked_div(2) == Some(5));
|
||||
assert!((5 as $T).checked_div(0) == None);
|
||||
assert!(isize::MIN.checked_div(-1) == None);
|
||||
}
|
||||
|
||||
@ -180,26 +179,26 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_from_str_radix() {
|
||||
assert_eq!(FromStrRadix::from_str_radix("123", 10), Ok(123 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Ok(9 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("123", 8), Ok(83 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("123", 16), Ok(291 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Ok(65535 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Ok(65535 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("z", 36), Ok(35 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("Z", 36), Ok(35 as $T));
|
||||
assert_eq!($T::from_str_radix("123", 10), Ok(123 as $T));
|
||||
assert_eq!($T::from_str_radix("1001", 2), Ok(9 as $T));
|
||||
assert_eq!($T::from_str_radix("123", 8), Ok(83 as $T));
|
||||
assert_eq!(i32::from_str_radix("123", 16), Ok(291 as i32));
|
||||
assert_eq!(i32::from_str_radix("ffff", 16), Ok(65535 as i32));
|
||||
assert_eq!(i32::from_str_radix("FFFF", 16), Ok(65535 as i32));
|
||||
assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
|
||||
assert_eq!($T::from_str_radix("Z", 36), Ok(35 as $T));
|
||||
|
||||
assert_eq!(FromStrRadix::from_str_radix("-123", 10), Ok(-123 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Ok(-9 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-123", 8), Ok(-83 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-123", 16), Ok(-291 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Ok(-65535 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-z", 36), Ok(-35 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Ok(-35 as $T));
|
||||
assert_eq!($T::from_str_radix("-123", 10), Ok(-123 as $T));
|
||||
assert_eq!($T::from_str_radix("-1001", 2), Ok(-9 as $T));
|
||||
assert_eq!($T::from_str_radix("-123", 8), Ok(-83 as $T));
|
||||
assert_eq!(i32::from_str_radix("-123", 16), Ok(-291 as i32));
|
||||
assert_eq!(i32::from_str_radix("-ffff", 16), Ok(-65535 as i32));
|
||||
assert_eq!(i32::from_str_radix("-FFFF", 16), Ok(-65535 as i32));
|
||||
assert_eq!($T::from_str_radix("-z", 36), Ok(-35 as $T));
|
||||
assert_eq!($T::from_str_radix("-Z", 36), Ok(-35 as $T));
|
||||
|
||||
assert_eq!(FromStrRadix::from_str_radix("Z", 35).ok(), None::<$T>);
|
||||
assert_eq!(FromStrRadix::from_str_radix("-9", 2).ok(), None::<$T>);
|
||||
assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
|
||||
assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
use core::cmp::PartialEq;
|
||||
use core::fmt::Debug;
|
||||
use core::num::{NumCast, cast};
|
||||
use core::ops::{Add, Sub, Mul, Div, Rem};
|
||||
use core::marker::Copy;
|
||||
|
||||
@ -32,18 +31,12 @@ mod u64;
|
||||
|
||||
/// Helper function for testing numeric operations
|
||||
pub fn test_num<T>(ten: T, two: T) where
|
||||
T: PartialEq + NumCast
|
||||
T: PartialEq
|
||||
+ Add<Output=T> + Sub<Output=T>
|
||||
+ Mul<Output=T> + Div<Output=T>
|
||||
+ Rem<Output=T> + Debug
|
||||
+ Copy
|
||||
{
|
||||
assert_eq!(ten.add(two), cast(12).unwrap());
|
||||
assert_eq!(ten.sub(two), cast(8).unwrap());
|
||||
assert_eq!(ten.mul(two), cast(20).unwrap());
|
||||
assert_eq!(ten.div(two), cast(5).unwrap());
|
||||
assert_eq!(ten.rem(two), cast(0).unwrap());
|
||||
|
||||
assert_eq!(ten.add(two), ten + two);
|
||||
assert_eq!(ten.sub(two), ten - two);
|
||||
assert_eq!(ten.mul(two), ten * two);
|
||||
@ -56,33 +49,33 @@ mod test {
|
||||
use core::option::Option;
|
||||
use core::option::Option::{Some, None};
|
||||
use core::num::Float;
|
||||
use core::num::from_str_radix;
|
||||
|
||||
#[test]
|
||||
fn from_str_issue7588() {
|
||||
let u : Option<u8> = from_str_radix("1000", 10).ok();
|
||||
let u : Option<u8> = u8::from_str_radix("1000", 10).ok();
|
||||
assert_eq!(u, None);
|
||||
let s : Option<i16> = from_str_radix("80000", 10).ok();
|
||||
let s : Option<i16> = i16::from_str_radix("80000", 10).ok();
|
||||
assert_eq!(s, None);
|
||||
let f : Option<f32> = from_str_radix("10000000000000000000000000000000000000000", 10).ok();
|
||||
let s = "10000000000000000000000000000000000000000";
|
||||
let f : Option<f32> = f32::from_str_radix(s, 10).ok();
|
||||
assert_eq!(f, Some(Float::infinity()));
|
||||
let fe : Option<f32> = from_str_radix("1e40", 10).ok();
|
||||
let fe : Option<f32> = f32::from_str_radix("1e40", 10).ok();
|
||||
assert_eq!(fe, Some(Float::infinity()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str_radix_float() {
|
||||
let x1 : Option<f64> = from_str_radix("-123.456", 10).ok();
|
||||
let x1 : Option<f64> = f64::from_str_radix("-123.456", 10).ok();
|
||||
assert_eq!(x1, Some(-123.456));
|
||||
let x2 : Option<f32> = from_str_radix("123.456", 10).ok();
|
||||
let x2 : Option<f32> = f32::from_str_radix("123.456", 10).ok();
|
||||
assert_eq!(x2, Some(123.456));
|
||||
let x3 : Option<f32> = from_str_radix("-0.0", 10).ok();
|
||||
let x3 : Option<f32> = f32::from_str_radix("-0.0", 10).ok();
|
||||
assert_eq!(x3, Some(-0.0));
|
||||
let x4 : Option<f32> = from_str_radix("0.0", 10).ok();
|
||||
let x4 : Option<f32> = f32::from_str_radix("0.0", 10).ok();
|
||||
assert_eq!(x4, Some(0.0));
|
||||
let x4 : Option<f32> = from_str_radix("1.0", 10).ok();
|
||||
let x4 : Option<f32> = f32::from_str_radix("1.0", 10).ok();
|
||||
assert_eq!(x4, Some(1.0));
|
||||
let x5 : Option<f32> = from_str_radix("-1.0", 10).ok();
|
||||
let x5 : Option<f32> = f32::from_str_radix("-1.0", 10).ok();
|
||||
assert_eq!(x5, Some(-1.0));
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,10 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
macro_rules! uint_module { ($T:ty, $T_i:ident) => (
|
||||
macro_rules! uint_module { ($T:ident, $T_i:ident) => (
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use core::$T_i::*;
|
||||
use core::num::Int;
|
||||
use num;
|
||||
use core::ops::{BitOr, BitAnd, BitXor, Shl, Shr, Not};
|
||||
|
||||
@ -97,30 +96,30 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_le() {
|
||||
assert_eq!(Int::from_le(A.to_le()), A);
|
||||
assert_eq!(Int::from_le(B.to_le()), B);
|
||||
assert_eq!(Int::from_le(C.to_le()), C);
|
||||
assert_eq!(Int::from_le(_0), _0);
|
||||
assert_eq!(Int::from_le(_1), _1);
|
||||
assert_eq!($T::from_le(A.to_le()), A);
|
||||
assert_eq!($T::from_le(B.to_le()), B);
|
||||
assert_eq!($T::from_le(C.to_le()), C);
|
||||
assert_eq!($T::from_le(_0), _0);
|
||||
assert_eq!($T::from_le(_1), _1);
|
||||
assert_eq!(_0.to_le(), _0);
|
||||
assert_eq!(_1.to_le(), _1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_be() {
|
||||
assert_eq!(Int::from_be(A.to_be()), A);
|
||||
assert_eq!(Int::from_be(B.to_be()), B);
|
||||
assert_eq!(Int::from_be(C.to_be()), C);
|
||||
assert_eq!(Int::from_be(_0), _0);
|
||||
assert_eq!(Int::from_be(_1), _1);
|
||||
assert_eq!($T::from_be(A.to_be()), A);
|
||||
assert_eq!($T::from_be(B.to_be()), B);
|
||||
assert_eq!($T::from_be(C.to_be()), C);
|
||||
assert_eq!($T::from_be(_0), _0);
|
||||
assert_eq!($T::from_be(_1), _1);
|
||||
assert_eq!(_0.to_be(), _0);
|
||||
assert_eq!(_1.to_be(), _1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unsigned_checked_div() {
|
||||
assert!(10.checked_div(2) == Some(5));
|
||||
assert!(5.checked_div(0) == None);
|
||||
assert!((10 as $T).checked_div(2) == Some(5));
|
||||
assert!((5 as $T).checked_div(0) == None);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,6 @@
|
||||
|
||||
#![deny(missing_docs)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(str_words)]
|
||||
#![feature(str_char)]
|
||||
#![cfg_attr(test, feature(rustc_private))]
|
||||
|
||||
@ -771,7 +770,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String {
|
||||
|
||||
// Normalize desc to contain words separated by one space character
|
||||
let mut desc_normalized_whitespace = String::new();
|
||||
for word in desc.words() {
|
||||
for word in desc.split_whitespace() {
|
||||
desc_normalized_whitespace.push_str(word);
|
||||
desc_normalized_whitespace.push(' ');
|
||||
}
|
||||
|
@ -3536,6 +3536,30 @@ pub mod consts {
|
||||
pub const IPV6_DROP_MEMBERSHIP: c_int = 21;
|
||||
|
||||
pub const TCP_NODELAY: c_int = 1;
|
||||
pub const TCP_MAXSEG: c_int = 2;
|
||||
pub const TCP_CORK: c_int = 3;
|
||||
pub const TCP_KEEPIDLE: c_int = 4;
|
||||
pub const TCP_KEEPINTVL: c_int = 5;
|
||||
pub const TCP_KEEPCNT: c_int = 6;
|
||||
pub const TCP_SYNCNT: c_int = 7;
|
||||
pub const TCP_LINGER2: c_int = 8;
|
||||
pub const TCP_DEFER_ACCEPT: c_int = 9;
|
||||
pub const TCP_WINDOW_CLAMP: c_int = 10;
|
||||
pub const TCP_INFO: c_int = 11;
|
||||
pub const TCP_QUICKACK: c_int = 12;
|
||||
pub const TCP_CONGESTION: c_int = 13;
|
||||
pub const TCP_MD5SIG: c_int = 14;
|
||||
pub const TCP_COOKIE_TRANSACTIONS: c_int = 15;
|
||||
pub const TCP_THIN_LINEAR_TIMEOUTS: c_int = 16;
|
||||
pub const TCP_THIN_DUPACK: c_int = 17;
|
||||
pub const TCP_USER_TIMEOUT: c_int = 18;
|
||||
pub const TCP_REPAIR: c_int = 19;
|
||||
pub const TCP_REPAIR_QUEUE: c_int = 20;
|
||||
pub const TCP_QUEUE_SEQ: c_int = 21;
|
||||
pub const TCP_REPAIR_OPTIONS: c_int = 22;
|
||||
pub const TCP_FASTOPEN: c_int = 23;
|
||||
pub const TCP_TIMESTAMP: c_int = 24;
|
||||
|
||||
pub const SOL_SOCKET: c_int = 1;
|
||||
|
||||
pub const SO_DEBUG: c_int = 1;
|
||||
|
@ -11,8 +11,6 @@
|
||||
//! The ChaCha random number generator.
|
||||
|
||||
use core::prelude::*;
|
||||
use core::num::Int;
|
||||
use core::num::wrapping::WrappingOps;
|
||||
use {Rng, SeedableRng, Rand};
|
||||
|
||||
const KEY_WORDS : usize = 8; // 8 words for the 256-bit key
|
||||
|
@ -18,7 +18,7 @@
|
||||
//! that do not need to record state.
|
||||
|
||||
use core::prelude::*;
|
||||
use core::num::{Float, Int};
|
||||
use core::num::Float;
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use {Rng, Rand};
|
||||
|
@ -13,8 +13,6 @@
|
||||
// this is surprisingly complicated to be both generic & correct
|
||||
|
||||
use core::prelude::PartialOrd;
|
||||
use core::num::Int;
|
||||
use core::num::wrapping::WrappingOps;
|
||||
|
||||
use Rng;
|
||||
use distributions::{Sample, IndependentSample};
|
||||
@ -73,7 +71,7 @@ pub trait SampleRange {
|
||||
}
|
||||
|
||||
macro_rules! integer_impl {
|
||||
($ty:ty, $unsigned:ty) => {
|
||||
($ty:ident, $unsigned:ident) => {
|
||||
impl SampleRange for $ty {
|
||||
// we play free and fast with unsigned vs signed here
|
||||
// (when $ty is signed), but that's fine, since the
|
||||
@ -83,7 +81,7 @@ macro_rules! integer_impl {
|
||||
|
||||
fn construct_range(low: $ty, high: $ty) -> Range<$ty> {
|
||||
let range = (high as $unsigned).wrapping_sub(low as $unsigned);
|
||||
let unsigned_max: $unsigned = Int::max_value();
|
||||
let unsigned_max: $unsigned = $unsigned::max_value();
|
||||
|
||||
// this is the largest number that fits into $unsigned
|
||||
// that `range` divides evenly, so, if we've sampled
|
||||
@ -148,7 +146,6 @@ float_impl! { f64 }
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::num::Int;
|
||||
use std::prelude::v1::*;
|
||||
use distributions::{Sample, IndependentSample};
|
||||
use super::Range as Range;
|
||||
@ -168,11 +165,11 @@ mod tests {
|
||||
fn test_integers() {
|
||||
let mut rng = ::test::rng();
|
||||
macro_rules! t {
|
||||
($($ty:ty),*) => {{
|
||||
($($ty:ident),*) => {{
|
||||
$(
|
||||
let v: &[($ty, $ty)] = &[(0, 10),
|
||||
(10, 127),
|
||||
(Int::min_value(), Int::max_value())];
|
||||
($ty::min_value(), $ty::max_value())];
|
||||
for &(low, high) in v {
|
||||
let mut sampler: Range<$ty> = Range::new(low, high);
|
||||
for _ in 0..1000 {
|
||||
|
@ -14,7 +14,6 @@
|
||||
use core::prelude::*;
|
||||
|
||||
use {Rng, SeedableRng};
|
||||
use core::default::Default;
|
||||
|
||||
/// How many bytes of entropy the underling RNG is allowed to generate
|
||||
/// before it is reseeded.
|
||||
@ -126,7 +125,6 @@ mod test {
|
||||
|
||||
use core::iter::{order, repeat};
|
||||
use super::{ReseedingRng, ReseedWithDefault};
|
||||
use std::default::Default;
|
||||
use {SeedableRng, Rng};
|
||||
|
||||
struct Counter {
|
||||
|
@ -836,7 +836,6 @@ pub mod writer {
|
||||
use std::io::prelude::*;
|
||||
use std::io::{self, SeekFrom, Cursor};
|
||||
use std::slice::bytes;
|
||||
use std::num::ToPrimitive;
|
||||
|
||||
use super::{ EsVec, EsMap, EsEnum, EsSub8, EsSub32, EsVecElt, EsMapKey,
|
||||
EsU64, EsU32, EsU16, EsU8, EsI64, EsI32, EsI16, EsI8,
|
||||
@ -1070,10 +1069,10 @@ pub mod writer {
|
||||
impl<'a> Encoder<'a> {
|
||||
// used internally to emit things like the vector length and so on
|
||||
fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult {
|
||||
if let Some(v) = v.to_u8() {
|
||||
self.wr_tagged_raw_u8(EsSub8 as usize, v)
|
||||
} else if let Some(v) = v.to_u32() {
|
||||
self.wr_tagged_raw_u32(EsSub32 as usize, v)
|
||||
if v as u8 as usize == v {
|
||||
self.wr_tagged_raw_u8(EsSub8 as usize, v as u8)
|
||||
} else if v as u32 as usize == v {
|
||||
self.wr_tagged_raw_u32(EsSub32 as usize, v as u32)
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other,
|
||||
&format!("length or variant id too big: {}",
|
||||
@ -1101,21 +1100,24 @@ pub mod writer {
|
||||
self.emit_u64(v as u64)
|
||||
}
|
||||
fn emit_u64(&mut self, v: u64) -> EncodeResult {
|
||||
match v.to_u32() {
|
||||
Some(v) => self.emit_u32(v),
|
||||
None => self.wr_tagged_raw_u64(EsU64 as usize, v)
|
||||
if v as u32 as u64 == v {
|
||||
self.emit_u32(v as u32)
|
||||
} else {
|
||||
self.wr_tagged_raw_u64(EsU64 as usize, v)
|
||||
}
|
||||
}
|
||||
fn emit_u32(&mut self, v: u32) -> EncodeResult {
|
||||
match v.to_u16() {
|
||||
Some(v) => self.emit_u16(v),
|
||||
None => self.wr_tagged_raw_u32(EsU32 as usize, v)
|
||||
if v as u16 as u32 == v {
|
||||
self.emit_u16(v as u16)
|
||||
} else {
|
||||
self.wr_tagged_raw_u32(EsU32 as usize, v)
|
||||
}
|
||||
}
|
||||
fn emit_u16(&mut self, v: u16) -> EncodeResult {
|
||||
match v.to_u8() {
|
||||
Some(v) => self.emit_u8(v),
|
||||
None => self.wr_tagged_raw_u16(EsU16 as usize, v)
|
||||
if v as u8 as u16 == v {
|
||||
self.emit_u8(v as u8)
|
||||
} else {
|
||||
self.wr_tagged_raw_u16(EsU16 as usize, v)
|
||||
}
|
||||
}
|
||||
fn emit_u8(&mut self, v: u8) -> EncodeResult {
|
||||
@ -1126,21 +1128,24 @@ pub mod writer {
|
||||
self.emit_i64(v as i64)
|
||||
}
|
||||
fn emit_i64(&mut self, v: i64) -> EncodeResult {
|
||||
match v.to_i32() {
|
||||
Some(v) => self.emit_i32(v),
|
||||
None => self.wr_tagged_raw_i64(EsI64 as usize, v)
|
||||
if v as i32 as i64 == v {
|
||||
self.emit_i32(v as i32)
|
||||
} else {
|
||||
self.wr_tagged_raw_i64(EsI64 as usize, v)
|
||||
}
|
||||
}
|
||||
fn emit_i32(&mut self, v: i32) -> EncodeResult {
|
||||
match v.to_i16() {
|
||||
Some(v) => self.emit_i16(v),
|
||||
None => self.wr_tagged_raw_i32(EsI32 as usize, v)
|
||||
if v as i16 as i32 == v {
|
||||
self.emit_i16(v as i16)
|
||||
} else {
|
||||
self.wr_tagged_raw_i32(EsI32 as usize, v)
|
||||
}
|
||||
}
|
||||
fn emit_i16(&mut self, v: i16) -> EncodeResult {
|
||||
match v.to_i8() {
|
||||
Some(v) => self.emit_i8(v),
|
||||
None => self.wr_tagged_raw_i16(EsI16 as usize, v)
|
||||
if v as i8 as i16 == v {
|
||||
self.emit_i8(v as i8)
|
||||
} else {
|
||||
self.wr_tagged_raw_i16(EsI16 as usize, v)
|
||||
}
|
||||
}
|
||||
fn emit_i8(&mut self, v: i8) -> EncodeResult {
|
||||
|
@ -208,7 +208,7 @@ fn main() {
|
||||
unsafe { f(); }
|
||||
}
|
||||
|
||||
See also http://doc.rust-lang.org/book/unsafe-code.html
|
||||
See also http://doc.rust-lang.org/book/unsafe.html
|
||||
"##,
|
||||
|
||||
E0152: r##"
|
||||
|
@ -38,7 +38,6 @@
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_misc)]
|
||||
#![feature(path_ext)]
|
||||
#![feature(str_words)]
|
||||
#![feature(str_char)]
|
||||
#![feature(into_cow)]
|
||||
#![feature(slice_patterns)]
|
||||
@ -69,6 +68,9 @@ extern crate test;
|
||||
|
||||
pub use rustc_llvm as llvm;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
// NB: This module needs to be declared first so diagnostics are
|
||||
// registered before they are used.
|
||||
pub mod diagnostics;
|
||||
@ -142,6 +144,7 @@ pub mod util {
|
||||
pub mod ppaux;
|
||||
pub mod nodemap;
|
||||
pub mod lev_distance;
|
||||
pub mod num;
|
||||
}
|
||||
|
||||
pub mod lib {
|
||||
|
46
src/librustc/macros.rs
Normal file
46
src/librustc/macros.rs
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -116,37 +116,39 @@ pub const tag_items_data_item_reexport_def_id: usize = 0x47;
|
||||
pub const tag_items_data_item_reexport_name: usize = 0x48;
|
||||
|
||||
// used to encode crate_ctxt side tables
|
||||
#[derive(Copy, Clone, PartialEq, FromPrimitive)]
|
||||
#[repr(usize)]
|
||||
pub enum astencode_tag { // Reserves 0x50 -- 0x6f
|
||||
tag_ast = 0x50,
|
||||
enum_from_u32! {
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
#[repr(usize)]
|
||||
pub enum astencode_tag { // Reserves 0x50 -- 0x6f
|
||||
tag_ast = 0x50,
|
||||
|
||||
tag_tree = 0x51,
|
||||
tag_tree = 0x51,
|
||||
|
||||
tag_id_range = 0x52,
|
||||
tag_id_range = 0x52,
|
||||
|
||||
tag_table = 0x53,
|
||||
// GAP 0x54, 0x55
|
||||
tag_table_def = 0x56,
|
||||
tag_table_node_type = 0x57,
|
||||
tag_table_item_subst = 0x58,
|
||||
tag_table_freevars = 0x59,
|
||||
tag_table_tcache = 0x5a,
|
||||
tag_table_param_defs = 0x5b,
|
||||
tag_table_mutbl = 0x5c,
|
||||
tag_table_last_use = 0x5d,
|
||||
tag_table_spill = 0x5e,
|
||||
tag_table_method_map = 0x5f,
|
||||
tag_table_vtable_map = 0x60,
|
||||
tag_table_adjustments = 0x61,
|
||||
tag_table_moves_map = 0x62,
|
||||
tag_table_capture_map = 0x63,
|
||||
tag_table_closure_tys = 0x64,
|
||||
tag_table_closure_kinds = 0x65,
|
||||
tag_table_upvar_capture_map = 0x66,
|
||||
tag_table_capture_modes = 0x67,
|
||||
tag_table_object_cast_map = 0x68,
|
||||
tag_table_const_qualif = 0x69,
|
||||
tag_table = 0x53,
|
||||
// GAP 0x54, 0x55
|
||||
tag_table_def = 0x56,
|
||||
tag_table_node_type = 0x57,
|
||||
tag_table_item_subst = 0x58,
|
||||
tag_table_freevars = 0x59,
|
||||
tag_table_tcache = 0x5a,
|
||||
tag_table_param_defs = 0x5b,
|
||||
tag_table_mutbl = 0x5c,
|
||||
tag_table_last_use = 0x5d,
|
||||
tag_table_spill = 0x5e,
|
||||
tag_table_method_map = 0x5f,
|
||||
tag_table_vtable_map = 0x60,
|
||||
tag_table_adjustments = 0x61,
|
||||
tag_table_moves_map = 0x62,
|
||||
tag_table_capture_map = 0x63,
|
||||
tag_table_closure_tys = 0x64,
|
||||
tag_table_closure_kinds = 0x65,
|
||||
tag_table_upvar_capture_map = 0x66,
|
||||
tag_table_capture_modes = 0x67,
|
||||
tag_table_object_cast_map = 0x68,
|
||||
tag_table_const_qualif = 0x69,
|
||||
}
|
||||
}
|
||||
|
||||
pub const tag_item_trait_item_sort: usize = 0x70;
|
||||
|
@ -68,11 +68,13 @@ pub enum LinkagePreference {
|
||||
RequireStatic,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, FromPrimitive)]
|
||||
pub enum NativeLibraryKind {
|
||||
NativeStatic, // native static library (.a archive)
|
||||
NativeFramework, // OSX-specific
|
||||
NativeUnknown, // default way to specify a dynamic library
|
||||
enum_from_u32! {
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum NativeLibraryKind {
|
||||
NativeStatic, // native static library (.a archive)
|
||||
NativeFramework, // OSX-specific
|
||||
NativeUnknown, // default way to specify a dynamic library
|
||||
}
|
||||
}
|
||||
|
||||
// Where a crate came from on the local filesystem. One of these two options
|
||||
|
@ -35,7 +35,6 @@ use std::collections::HashMap;
|
||||
use std::hash::{self, Hash, SipHasher};
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::num::FromPrimitive;
|
||||
use std::rc::Rc;
|
||||
use std::slice::bytes;
|
||||
use std::str;
|
||||
@ -1349,7 +1348,7 @@ pub fn get_native_libraries(cdata: Cmd)
|
||||
let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind);
|
||||
let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name);
|
||||
let kind: cstore::NativeLibraryKind =
|
||||
FromPrimitive::from_u32(reader::doc_as_u32(kind_doc)).unwrap();
|
||||
cstore::NativeLibraryKind::from_u32(reader::doc_as_u32(kind_doc)).unwrap();
|
||||
let name = name_doc.as_str().to_string();
|
||||
result.push((kind, name));
|
||||
true
|
||||
@ -1359,7 +1358,7 @@ pub fn get_native_libraries(cdata: Cmd)
|
||||
|
||||
pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
|
||||
reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn)
|
||||
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
|
||||
.map(|doc| reader::doc_as_u32(doc))
|
||||
}
|
||||
|
||||
pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
|
||||
@ -1407,7 +1406,7 @@ pub fn get_missing_lang_items(cdata: Cmd)
|
||||
let mut result = Vec::new();
|
||||
reader::tagged_docs(items, tag_lang_items_missing, |missing_docs| {
|
||||
let item: lang_items::LangItem =
|
||||
FromPrimitive::from_u32(reader::doc_as_u32(missing_docs)).unwrap();
|
||||
lang_items::LangItem::from_u32(reader::doc_as_u32(missing_docs)).unwrap();
|
||||
result.push(item);
|
||||
true
|
||||
});
|
||||
|
@ -692,11 +692,16 @@ pub fn note_crate_name(diag: &SpanHandler, name: &str) {
|
||||
|
||||
impl ArchiveMetadata {
|
||||
fn new(ar: ArchiveRO) -> Option<ArchiveMetadata> {
|
||||
let data = match ar.read(METADATA_FILENAME) {
|
||||
Some(data) => data as *const [u8],
|
||||
None => {
|
||||
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
|
||||
return None;
|
||||
let data = {
|
||||
let section = ar.iter().find(|sect| {
|
||||
sect.name() == Some(METADATA_FILENAME)
|
||||
});
|
||||
match section {
|
||||
Some(s) => s.data() as *const [u8],
|
||||
None => {
|
||||
debug!("didn't find '{}' in the archive", METADATA_FILENAME);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -41,7 +41,6 @@ use syntax;
|
||||
use std::cell::Cell;
|
||||
use std::io::SeekFrom;
|
||||
use std::io::prelude::*;
|
||||
use std::num::FromPrimitive;
|
||||
use std::rc::Rc;
|
||||
use std::fmt::Debug;
|
||||
|
||||
@ -1713,7 +1712,8 @@ fn decode_side_tables(dcx: &DecodeContext,
|
||||
debug!(">> Side table document with tag 0x{:x} \
|
||||
found for id {} (orig {})",
|
||||
tag, id, id0);
|
||||
let decoded_tag: Option<c::astencode_tag> = FromPrimitive::from_usize(tag);
|
||||
let tag = tag as u32;
|
||||
let decoded_tag: Option<c::astencode_tag> = c::astencode_tag::from_u32(tag);
|
||||
match decoded_tag {
|
||||
None => {
|
||||
dcx.tcx.sess.bug(
|
||||
|
@ -20,6 +20,7 @@ use middle::{astencode, def};
|
||||
use middle::pat_util::def_to_path;
|
||||
use middle::ty::{self, Ty};
|
||||
use middle::astconv_util::ast_ty_to_prim_ty;
|
||||
use util::num::ToPrimitive;
|
||||
|
||||
use syntax::ast::{self, Expr};
|
||||
use syntax::codemap::Span;
|
||||
@ -30,7 +31,6 @@ use syntax::{ast_map, ast_util, codemap};
|
||||
|
||||
use std::borrow::{Cow, IntoCow};
|
||||
use std::num::wrapping::OverflowingOps;
|
||||
use std::num::ToPrimitive;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::hash_map::Entry::Vacant;
|
||||
use std::{i8, i16, i32, i64};
|
||||
|
@ -36,7 +36,6 @@ use syntax::visit::Visitor;
|
||||
use syntax::visit;
|
||||
|
||||
use std::iter::Enumerate;
|
||||
use std::num::FromPrimitive;
|
||||
use std::slice;
|
||||
|
||||
// The actual lang items defined come at the end of this file in one handy table.
|
||||
@ -46,9 +45,12 @@ macro_rules! lets_do_this {
|
||||
$( $variant:ident, $name:expr, $method:ident; )*
|
||||
) => {
|
||||
|
||||
#[derive(Copy, Clone, FromPrimitive, PartialEq, Eq, Hash)]
|
||||
pub enum LangItem {
|
||||
$($variant),*
|
||||
|
||||
enum_from_u32! {
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum LangItem {
|
||||
$($variant,)*
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LanguageItems {
|
||||
@ -71,7 +73,7 @@ impl LanguageItems {
|
||||
}
|
||||
|
||||
pub fn item_name(index: usize) -> &'static str {
|
||||
let item: Option<LangItem> = FromPrimitive::from_usize(index);
|
||||
let item: Option<LangItem> = LangItem::from_u32(index as u32);
|
||||
match item {
|
||||
$( Some($variant) => $name, )*
|
||||
None => "???"
|
||||
|
@ -63,6 +63,7 @@ use util::ppaux::{Repr, UserString};
|
||||
use util::common::{memoized, ErrorReported};
|
||||
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
|
||||
use util::nodemap::FnvHashMap;
|
||||
use util::num::ToPrimitive;
|
||||
|
||||
use arena::TypedArena;
|
||||
use std::borrow::{Borrow, Cow};
|
||||
@ -71,7 +72,6 @@ use std::cmp;
|
||||
use std::fmt;
|
||||
use std::hash::{Hash, SipHasher, Hasher};
|
||||
use std::mem;
|
||||
use std::num::ToPrimitive;
|
||||
use std::ops;
|
||||
use std::rc::Rc;
|
||||
use std::vec::IntoIter;
|
||||
|
@ -418,7 +418,7 @@ macro_rules! options {
|
||||
-> bool {
|
||||
match v {
|
||||
Some(s) => {
|
||||
for s in s.words() {
|
||||
for s in s.split_whitespace() {
|
||||
slot.push(s.to_string());
|
||||
}
|
||||
true
|
||||
@ -431,7 +431,7 @@ macro_rules! options {
|
||||
-> bool {
|
||||
match v {
|
||||
Some(s) => {
|
||||
let v = s.words().map(|s| s.to_string()).collect();
|
||||
let v = s.split_whitespace().map(|s| s.to_string()).collect();
|
||||
*slot = Some(v);
|
||||
true
|
||||
},
|
||||
|
98
src/librustc/util/num.rs
Normal file
98
src/librustc/util/num.rs
Normal 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)
|
||||
}
|
||||
}
|
@ -11,13 +11,14 @@
|
||||
//! A helper class for dealing with static archives
|
||||
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::fs::{self, File};
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Output, Stdio};
|
||||
use std::str;
|
||||
use syntax::diagnostic::Handler as ErrorHandler;
|
||||
use rustc_llvm::archive_ro::ArchiveRO;
|
||||
|
||||
use tempdir::TempDir;
|
||||
|
||||
@ -282,17 +283,14 @@ impl<'a> ArchiveBuilder<'a> {
|
||||
mut skip: F) -> io::Result<()>
|
||||
where F: FnMut(&str) -> bool,
|
||||
{
|
||||
let loc = TempDir::new("rsar").unwrap();
|
||||
|
||||
// First, extract the contents of the archive to a temporary directory.
|
||||
// We don't unpack directly into `self.work_dir` due to the possibility
|
||||
// of filename collisions.
|
||||
let archive = env::current_dir().unwrap().join(archive);
|
||||
run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
|
||||
"x", Some(loc.path()), &[&archive]);
|
||||
let archive = match ArchiveRO::open(archive) {
|
||||
Some(ar) => ar,
|
||||
None => return Err(io::Error::new(io::ErrorKind::Other,
|
||||
"failed to open archive")),
|
||||
};
|
||||
|
||||
// Next, we must rename all of the inputs to "guaranteed unique names".
|
||||
// We move each file into `self.work_dir` under its new unique name.
|
||||
// We write each file into `self.work_dir` under its new unique name.
|
||||
// The reason for this renaming is that archives are keyed off the name
|
||||
// of the files, so if two files have the same name they will override
|
||||
// one another in the archive (bad).
|
||||
@ -300,27 +298,46 @@ impl<'a> ArchiveBuilder<'a> {
|
||||
// We skip any files explicitly desired for skipping, and we also skip
|
||||
// all SYMDEF files as these are just magical placeholders which get
|
||||
// re-created when we make a new archive anyway.
|
||||
let files = try!(fs::read_dir(loc.path()));
|
||||
for file in files {
|
||||
let file = try!(file).path();
|
||||
let filename = file.file_name().unwrap().to_str().unwrap();
|
||||
if skip(filename) { continue }
|
||||
if filename.contains(".SYMDEF") { continue }
|
||||
|
||||
let filename = format!("r-{}-{}", name, filename);
|
||||
// LLDB (as mentioned in back::link) crashes on filenames of exactly
|
||||
// 16 bytes in length. If we're including an object file with
|
||||
// exactly 16-bytes of characters, give it some prefix so that it's
|
||||
// not 16 bytes.
|
||||
let filename = if filename.len() == 16 {
|
||||
format!("lldb-fix-{}", filename)
|
||||
} else {
|
||||
filename
|
||||
for file in archive.iter() {
|
||||
let filename = match file.name() {
|
||||
Some(s) => s,
|
||||
None => continue,
|
||||
};
|
||||
let new_filename = self.work_dir.path().join(&filename[..]);
|
||||
try!(fs::rename(&file, &new_filename));
|
||||
self.members.push(PathBuf::from(filename));
|
||||
if filename.contains(".SYMDEF") { continue }
|
||||
if skip(filename) { continue }
|
||||
|
||||
// An archive can contain files of the same name multiple times, so
|
||||
// we need to be sure to not have them overwrite one another when we
|
||||
// extract them. Consequently we need to find a truly unique file
|
||||
// name for us!
|
||||
let mut new_filename = String::new();
|
||||
for n in 0.. {
|
||||
let n = if n == 0 {String::new()} else {format!("-{}", n)};
|
||||
new_filename = format!("r{}-{}-{}", n, name, filename);
|
||||
|
||||
// LLDB (as mentioned in back::link) crashes on filenames of
|
||||
// exactly
|
||||
// 16 bytes in length. If we're including an object file with
|
||||
// exactly 16-bytes of characters, give it some prefix so
|
||||
// that it's not 16 bytes.
|
||||
new_filename = if new_filename.len() == 16 {
|
||||
format!("lldb-fix-{}", new_filename)
|
||||
} else {
|
||||
new_filename
|
||||
};
|
||||
|
||||
let present = self.members.iter().filter_map(|p| {
|
||||
p.file_name().and_then(|f| f.to_str())
|
||||
}).any(|s| s == new_filename);
|
||||
if !present {
|
||||
break
|
||||
}
|
||||
}
|
||||
let dst = self.work_dir.path().join(&new_filename);
|
||||
try!(try!(File::create(&dst)).write_all(file.data()));
|
||||
self.members.push(PathBuf::from(new_filename));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,7 @@
|
||||
extern crate syntax;
|
||||
extern crate libc;
|
||||
extern crate serialize;
|
||||
extern crate rustc_llvm;
|
||||
#[macro_use] extern crate log;
|
||||
|
||||
pub mod abi;
|
||||
|
@ -12,10 +12,7 @@
|
||||
//! use. This implementation is not intended for external use or for any use where security is
|
||||
//! important.
|
||||
|
||||
#![allow(deprecated)] // to_be32
|
||||
|
||||
use std::iter::repeat;
|
||||
use std::num::Int;
|
||||
use std::slice::bytes::{MutableByteVector, copy_memory};
|
||||
use serialize::hex::ToHex;
|
||||
|
||||
@ -61,10 +58,10 @@ impl ToBits for u64 {
|
||||
|
||||
/// Adds the specified number of bytes to the bit count. panic!() if this would cause numeric
|
||||
/// overflow.
|
||||
fn add_bytes_to_bits<T: Int + ToBits>(bits: T, bytes: T) -> T {
|
||||
fn add_bytes_to_bits(bits: u64, bytes: u64) -> u64 {
|
||||
let (new_high_bits, new_low_bits) = bytes.to_bits();
|
||||
|
||||
if new_high_bits > T::zero() {
|
||||
if new_high_bits > 0 {
|
||||
panic!("numeric overflow occurred.")
|
||||
}
|
||||
|
||||
@ -543,14 +540,14 @@ mod tests {
|
||||
// A normal addition - no overflow occurs
|
||||
#[test]
|
||||
fn test_add_bytes_to_bits_ok() {
|
||||
assert!(super::add_bytes_to_bits::<u64>(100, 10) == 180);
|
||||
assert!(super::add_bytes_to_bits(100, 10) == 180);
|
||||
}
|
||||
|
||||
// A simple failure case - adding 1 to the max value
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_add_bytes_to_bits_overflow() {
|
||||
super::add_bytes_to_bits::<u64>(u64::MAX, 1);
|
||||
super::add_bytes_to_bits(u64::MAX, 1);
|
||||
}
|
||||
|
||||
struct Test {
|
||||
|
@ -10,15 +10,23 @@
|
||||
|
||||
//! A wrapper around LLVM's archive (.a) code
|
||||
|
||||
use libc;
|
||||
use ArchiveRef;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::slice;
|
||||
use std::path::Path;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
|
||||
pub struct ArchiveRO {
|
||||
ptr: ArchiveRef,
|
||||
pub struct ArchiveRO { ptr: ArchiveRef }
|
||||
|
||||
pub struct Iter<'a> {
|
||||
archive: &'a ArchiveRO,
|
||||
ptr: ::ArchiveIteratorRef,
|
||||
}
|
||||
|
||||
pub struct Child<'a> {
|
||||
name: Option<&'a str>,
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
||||
impl ArchiveRO {
|
||||
@ -52,18 +60,9 @@ impl ArchiveRO {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads a file in the archive
|
||||
pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
|
||||
pub fn iter(&self) -> Iter {
|
||||
unsafe {
|
||||
let mut size = 0 as libc::size_t;
|
||||
let file = CString::new(file).unwrap();
|
||||
let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(),
|
||||
&mut size);
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(slice::from_raw_parts(ptr as *const u8, size as usize))
|
||||
}
|
||||
Iter { ptr: ::LLVMRustArchiveIteratorNew(self.ptr), archive: self }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,3 +74,47 @@ impl Drop for ArchiveRO {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = Child<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Child<'a>> {
|
||||
unsafe {
|
||||
let ptr = ::LLVMRustArchiveIteratorCurrent(self.ptr);
|
||||
if ptr.is_null() {
|
||||
return None
|
||||
}
|
||||
let mut name_len = 0;
|
||||
let name_ptr = ::LLVMRustArchiveChildName(ptr, &mut name_len);
|
||||
let mut data_len = 0;
|
||||
let data_ptr = ::LLVMRustArchiveChildData(ptr, &mut data_len);
|
||||
let child = Child {
|
||||
name: if name_ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
let name = slice::from_raw_parts(name_ptr as *const u8,
|
||||
name_len as usize);
|
||||
str::from_utf8(name).ok().map(|s| s.trim())
|
||||
},
|
||||
data: slice::from_raw_parts(data_ptr as *const u8,
|
||||
data_len as usize),
|
||||
};
|
||||
::LLVMRustArchiveIteratorNext(self.ptr);
|
||||
Some(child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<'a> Drop for Iter<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
::LLVMRustArchiveIteratorFree(self.ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Child<'a> {
|
||||
pub fn name(&self) -> Option<&'a str> { self.name }
|
||||
pub fn data(&self) -> &'a [u8] { self.data }
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#![feature(libc)]
|
||||
#![feature(link_args)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(unsafe_destructor)]
|
||||
|
||||
extern crate libc;
|
||||
#[macro_use] #[no_link] extern crate rustc_bitflags;
|
||||
@ -488,9 +489,12 @@ pub type PassRef = *mut Pass_opaque;
|
||||
#[allow(missing_copy_implementations)]
|
||||
pub enum TargetMachine_opaque {}
|
||||
pub type TargetMachineRef = *mut TargetMachine_opaque;
|
||||
#[allow(missing_copy_implementations)]
|
||||
pub enum Archive_opaque {}
|
||||
pub type ArchiveRef = *mut Archive_opaque;
|
||||
pub enum ArchiveIterator_opaque {}
|
||||
pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque;
|
||||
pub enum ArchiveChild_opaque {}
|
||||
pub type ArchiveChildRef = *mut ArchiveChild_opaque;
|
||||
#[allow(missing_copy_implementations)]
|
||||
pub enum Twine_opaque {}
|
||||
pub type TwineRef = *mut Twine_opaque;
|
||||
@ -2051,13 +2055,17 @@ extern {
|
||||
pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef);
|
||||
|
||||
pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef;
|
||||
pub fn LLVMRustArchiveReadSection(AR: ArchiveRef, name: *const c_char,
|
||||
out_len: *mut size_t) -> *const c_char;
|
||||
pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef;
|
||||
pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef);
|
||||
pub fn LLVMRustArchiveIteratorCurrent(AIR: ArchiveIteratorRef) -> ArchiveChildRef;
|
||||
pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef,
|
||||
size: *mut size_t) -> *const c_char;
|
||||
pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef,
|
||||
size: *mut size_t) -> *const c_char;
|
||||
pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef);
|
||||
pub fn LLVMRustDestroyArchive(AR: ArchiveRef);
|
||||
|
||||
pub fn LLVMRustSetDLLExportStorageClass(V: ValueRef);
|
||||
pub fn LLVMVersionMajor() -> c_int;
|
||||
pub fn LLVMVersionMinor() -> c_int;
|
||||
|
||||
pub fn LLVMRustGetSectionName(SI: SectionIteratorRef,
|
||||
data: *mut *const c_char) -> c_int;
|
||||
|
@ -21,9 +21,6 @@ use libc;
|
||||
use flate;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::mem;
|
||||
#[allow(deprecated)]
|
||||
use std::num::Int;
|
||||
|
||||
pub fn run(sess: &session::Session, llmod: ModuleRef,
|
||||
tm: TargetMachineRef, reachable: &[String]) {
|
||||
@ -63,13 +60,13 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
|
||||
let file = &file[3..file.len() - 5]; // chop off lib/.rlib
|
||||
debug!("reading {}", file);
|
||||
for i in 0.. {
|
||||
let bc_encoded = time(sess.time_passes(),
|
||||
&format!("check for {}.{}.bytecode.deflate", name, i),
|
||||
(),
|
||||
|_| {
|
||||
archive.read(&format!("{}.{}.bytecode.deflate",
|
||||
file, i))
|
||||
});
|
||||
let filename = format!("{}.{}.bytecode.deflate", file, i);
|
||||
let msg = format!("check for {}", filename);
|
||||
let bc_encoded = time(sess.time_passes(), &msg, (), |_| {
|
||||
archive.iter().find(|section| {
|
||||
section.name() == Some(&filename[..])
|
||||
})
|
||||
});
|
||||
let bc_encoded = match bc_encoded {
|
||||
Some(data) => data,
|
||||
None => {
|
||||
@ -79,9 +76,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
|
||||
path.display()));
|
||||
}
|
||||
// No more bitcode files to read.
|
||||
break;
|
||||
},
|
||||
break
|
||||
}
|
||||
};
|
||||
let bc_encoded = bc_encoded.data();
|
||||
|
||||
let bc_decoded = if is_versioned_bytecode_format(bc_encoded) {
|
||||
time(sess.time_passes(), &format!("decode {}.{}.bc", file, i), (), |_| {
|
||||
@ -198,19 +196,15 @@ fn is_versioned_bytecode_format(bc: &[u8]) -> bool {
|
||||
}
|
||||
|
||||
fn extract_bytecode_format_version(bc: &[u8]) -> u32 {
|
||||
return read_from_le_bytes::<u32>(bc, link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET);
|
||||
let pos = link::RLIB_BYTECODE_OBJECT_VERSION_OFFSET;
|
||||
let byte_data = &bc[pos..pos + 4];
|
||||
let data = unsafe { *(byte_data.as_ptr() as *const u32) };
|
||||
u32::from_le(data)
|
||||
}
|
||||
|
||||
fn extract_compressed_bytecode_size_v1(bc: &[u8]) -> u64 {
|
||||
return read_from_le_bytes::<u64>(bc, link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET);
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
fn read_from_le_bytes<T: Int>(bytes: &[u8], position_in_bytes: usize) -> T {
|
||||
let byte_data = &bytes[position_in_bytes..position_in_bytes + mem::size_of::<T>()];
|
||||
let data = unsafe {
|
||||
*(byte_data.as_ptr() as *const T)
|
||||
};
|
||||
|
||||
Int::from_le(data)
|
||||
let pos = link::RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET;
|
||||
let byte_data = &bc[pos..pos + 8];
|
||||
let data = unsafe { *(byte_data.as_ptr() as *const u64) };
|
||||
u64::from_le(data)
|
||||
}
|
||||
|
@ -348,7 +348,7 @@ unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext<'a>,
|
||||
|
||||
match cgcx.lto_ctxt {
|
||||
Some((sess, _)) => {
|
||||
sess.codemap().with_expn_info(ExpnId::from_llvm_cookie(cookie), |info| match info {
|
||||
sess.codemap().with_expn_info(ExpnId::from_u32(cookie), |info| match info {
|
||||
Some(ei) => sess.span_err(ei.call_site, msg),
|
||||
None => sess.err(msg),
|
||||
});
|
||||
|
@ -45,8 +45,6 @@
|
||||
|
||||
pub use self::Repr::*;
|
||||
|
||||
#[allow(deprecated)]
|
||||
use std::num::Int;
|
||||
use std::rc::Rc;
|
||||
|
||||
use llvm::{ValueRef, True, IntEQ, IntNE};
|
||||
|
@ -138,7 +138,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
|
||||
let kind = llvm::LLVMGetMDKindIDInContext(bcx.ccx().llcx(),
|
||||
key.as_ptr() as *const c_char, key.len() as c_uint);
|
||||
|
||||
let val: llvm::ValueRef = C_i32(bcx.ccx(), ia.expn_id.to_llvm_cookie());
|
||||
let val: llvm::ValueRef = C_i32(bcx.ccx(), ia.expn_id.into_u32() as i32);
|
||||
|
||||
llvm::LLVMSetMetadata(r, kind,
|
||||
llvm::LLVMMDNodeInContext(bcx.ccx().llcx(), &val, 1));
|
||||
|
@ -878,16 +878,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
|
||||
// were introduced in LLVM 3.4, so we case on that.
|
||||
macro_rules! compatible_ifn {
|
||||
($name:expr, $cname:ident ($($arg:expr),*) -> $ret:expr) => (
|
||||
if unsafe { llvm::LLVMVersionMinor() >= 4 } {
|
||||
// The `if key == $name` is already in ifn!
|
||||
ifn!($name, fn($($arg),*) -> $ret);
|
||||
} else if *key == $name {
|
||||
let f = declare::declare_cfn(ccx, stringify!($cname),
|
||||
Type::func(&[$($arg),*], &$ret),
|
||||
ty::mk_nil(ccx.tcx()));
|
||||
ccx.intrinsics().borrow_mut().insert($name, f.clone());
|
||||
return Some(f);
|
||||
}
|
||||
ifn!($name, fn($($arg),*) -> $ret);
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -2653,26 +2653,8 @@ fn set_members_of_composite_type(cx: &CrateContext,
|
||||
let mut composite_types_completed =
|
||||
debug_context(cx).composite_types_completed.borrow_mut();
|
||||
if composite_types_completed.contains(&composite_type_metadata) {
|
||||
let (llvm_version_major, llvm_version_minor) = unsafe {
|
||||
(llvm::LLVMVersionMajor(), llvm::LLVMVersionMinor())
|
||||
};
|
||||
|
||||
let actual_llvm_version = llvm_version_major * 1000000 + llvm_version_minor * 1000;
|
||||
let min_supported_llvm_version = 3 * 1000000 + 4 * 1000;
|
||||
|
||||
if actual_llvm_version < min_supported_llvm_version {
|
||||
cx.sess().warn(&format!("This version of rustc was built with LLVM \
|
||||
{}.{}. Rustc just ran into a known \
|
||||
debuginfo corruption problem thatoften \
|
||||
occurs with LLVM versions below 3.4. \
|
||||
Please use a rustc built with anewer \
|
||||
version of LLVM.",
|
||||
llvm_version_major,
|
||||
llvm_version_minor));
|
||||
} else {
|
||||
cx.sess().bug("debuginfo::set_members_of_composite_type() - \
|
||||
Already completed forward declaration re-encountered.");
|
||||
}
|
||||
cx.sess().bug("debuginfo::set_members_of_composite_type() - \
|
||||
Already completed forward declaration re-encountered.");
|
||||
} else {
|
||||
composite_types_completed.insert(composite_type_metadata);
|
||||
}
|
||||
|
@ -746,11 +746,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
let src = to_arg_ty(bcx, llargs[2], tp_ty);
|
||||
let res = AtomicCmpXchg(bcx, ptr, cmp, src, order,
|
||||
strongest_failure_ordering);
|
||||
if unsafe { llvm::LLVMVersionMinor() >= 5 } {
|
||||
ExtractValue(bcx, res, 0)
|
||||
} else {
|
||||
res
|
||||
}
|
||||
ExtractValue(bcx, res, 0)
|
||||
}
|
||||
|
||||
"load" => {
|
||||
|
@ -21,8 +21,6 @@ use util::ppaux::Repr;
|
||||
|
||||
use trans::type_::Type;
|
||||
|
||||
#[allow(deprecated)]
|
||||
use std::num::Int;
|
||||
use syntax::abi;
|
||||
use syntax::ast;
|
||||
|
||||
|
@ -45,7 +45,7 @@ mod u_str;
|
||||
pub mod char;
|
||||
|
||||
pub mod str {
|
||||
pub use u_str::{UnicodeStr, Words, Graphemes, GraphemeIndices};
|
||||
pub use u_str::{UnicodeStr, SplitWhitespace, Words, Graphemes, GraphemeIndices};
|
||||
pub use u_str::{utf8_char_width, is_utf16, Utf16Items, Utf16Item};
|
||||
pub use u_str::{utf16_items, Utf16Encoder};
|
||||
}
|
||||
|
@ -25,9 +25,16 @@ use core::str::Split;
|
||||
|
||||
use tables::grapheme::GraphemeCat;
|
||||
|
||||
/// An iterator over the words of a string, separated by a sequence of whitespace
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Words<'a> {
|
||||
#[deprecated(reason = "struct Words is being replaced by struct SplitWhitespace",
|
||||
since = "1.1.0")]
|
||||
#[unstable(feature = "str_words",
|
||||
reason = "words() will be replaced by split_whitespace() in 1.1.0")]
|
||||
pub type Words<'a> = SplitWhitespace<'a>;
|
||||
|
||||
/// An iterator over the non-whitespace substrings of a string,
|
||||
/// separated by any amount of whitespace.
|
||||
#[stable(feature = "split_whitespace", since = "1.1.0")]
|
||||
pub struct SplitWhitespace<'a> {
|
||||
inner: Filter<Split<'a, fn(char) -> bool>, fn(&&str) -> bool>,
|
||||
}
|
||||
|
||||
@ -36,7 +43,9 @@ pub struct Words<'a> {
|
||||
pub trait UnicodeStr {
|
||||
fn graphemes<'a>(&'a self, is_extended: bool) -> Graphemes<'a>;
|
||||
fn grapheme_indices<'a>(&'a self, is_extended: bool) -> GraphemeIndices<'a>;
|
||||
#[allow(deprecated)]
|
||||
fn words<'a>(&'a self) -> Words<'a>;
|
||||
fn split_whitespace<'a>(&'a self) -> SplitWhitespace<'a>;
|
||||
fn is_whitespace(&self) -> bool;
|
||||
fn is_alphanumeric(&self) -> bool;
|
||||
fn width(&self, is_cjk: bool) -> usize;
|
||||
@ -56,15 +65,21 @@ impl UnicodeStr for str {
|
||||
GraphemeIndices { start_offset: self.as_ptr() as usize, iter: self.graphemes(is_extended) }
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
#[inline]
|
||||
fn words(&self) -> Words {
|
||||
self.split_whitespace()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn split_whitespace(&self) -> SplitWhitespace {
|
||||
fn is_not_empty(s: &&str) -> bool { !s.is_empty() }
|
||||
let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer
|
||||
|
||||
fn is_whitespace(c: char) -> bool { c.is_whitespace() }
|
||||
let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer
|
||||
|
||||
Words { inner: self.split(is_whitespace).filter(is_not_empty) }
|
||||
SplitWhitespace { inner: self.split(is_whitespace).filter(is_not_empty) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -545,11 +560,11 @@ impl<I> Iterator for Utf16Encoder<I> where I: Iterator<Item=char> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Words<'a> {
|
||||
impl<'a> Iterator for SplitWhitespace<'a> {
|
||||
type Item = &'a str;
|
||||
|
||||
fn next(&mut self) -> Option<&'a str> { self.inner.next() }
|
||||
}
|
||||
impl<'a> DoubleEndedIterator for Words<'a> {
|
||||
impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
|
||||
fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() }
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
|
||||
};
|
||||
|
||||
// Transform the contents of the header into a hyphenated string
|
||||
let id = s.words().map(|s| s.to_ascii_lowercase())
|
||||
let id = s.split_whitespace().map(|s| s.to_ascii_lowercase())
|
||||
.collect::<Vec<String>>().connect("-");
|
||||
|
||||
// This is a terrible hack working around how hoedown gives us rendered
|
||||
|
@ -31,7 +31,6 @@
|
||||
#![feature(std_misc)]
|
||||
#![feature(test)]
|
||||
#![feature(unicode)]
|
||||
#![feature(str_words)]
|
||||
#![feature(path_ext)]
|
||||
#![feature(path_relative_from)]
|
||||
#![feature(slice_patterns)]
|
||||
@ -240,7 +239,7 @@ pub fn main_args(args: &[String]) -> isize {
|
||||
|
||||
let test_args = matches.opt_strs("test-args");
|
||||
let test_args: Vec<String> = test_args.iter()
|
||||
.flat_map(|s| s.words())
|
||||
.flat_map(|s| s.split_whitespace())
|
||||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
|
||||
@ -404,13 +403,13 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
|
||||
}
|
||||
clean::NameValue(ref x, ref value)
|
||||
if "passes" == *x => {
|
||||
for pass in value.words() {
|
||||
for pass in value.split_whitespace() {
|
||||
passes.push(pass.to_string());
|
||||
}
|
||||
}
|
||||
clean::NameValue(ref x, ref value)
|
||||
if "plugins" == *x => {
|
||||
for p in value.words() {
|
||||
for p in value.split_whitespace() {
|
||||
plugins.push(p.to_string());
|
||||
}
|
||||
}
|
||||
|
@ -204,12 +204,10 @@ use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::mem::swap;
|
||||
use std::num::FpCategory as Fp;
|
||||
#[allow(deprecated)]
|
||||
use std::num::wrapping::WrappingOps;
|
||||
use std::ops::Index;
|
||||
use std::str::FromStr;
|
||||
use std::string;
|
||||
use std::{char, f64, fmt, num, str};
|
||||
use std::{char, f64, fmt, str};
|
||||
use std;
|
||||
use rustc_unicode::str as unicode_str;
|
||||
use rustc_unicode::str::Utf16Item;
|
||||
@ -460,8 +458,8 @@ fn spaces(wr: &mut fmt::Write, mut n: usize) -> EncodeResult {
|
||||
fn fmt_number_or_null(v: f64) -> string::String {
|
||||
match v.classify() {
|
||||
Fp::Nan | Fp::Infinite => string::String::from_str("null"),
|
||||
_ if v.fract() != 0f64 => f64::to_str_digits(v, 6),
|
||||
_ => f64::to_str_digits(v, 6) + ".0",
|
||||
_ if v.fract() != 0f64 => v.to_string(),
|
||||
_ => v.to_string() + ".0",
|
||||
}
|
||||
}
|
||||
|
||||
@ -1165,7 +1163,7 @@ impl Json {
|
||||
pub fn as_i64(&self) -> Option<i64> {
|
||||
match *self {
|
||||
Json::I64(n) => Some(n),
|
||||
Json::U64(n) => num::cast(n),
|
||||
Json::U64(n) => Some(n as i64),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
@ -1174,7 +1172,7 @@ impl Json {
|
||||
/// Returns None otherwise.
|
||||
pub fn as_u64(&self) -> Option<u64> {
|
||||
match *self {
|
||||
Json::I64(n) => num::cast(n),
|
||||
Json::I64(n) => Some(n as u64),
|
||||
Json::U64(n) => Some(n),
|
||||
_ => None
|
||||
}
|
||||
@ -1184,8 +1182,8 @@ impl Json {
|
||||
/// Returns None otherwise.
|
||||
pub fn as_f64(&self) -> Option<f64> {
|
||||
match *self {
|
||||
Json::I64(n) => num::cast(n),
|
||||
Json::U64(n) => num::cast(n),
|
||||
Json::I64(n) => Some(n as f64),
|
||||
Json::U64(n) => Some(n as f64),
|
||||
Json::F64(n) => Some(n),
|
||||
_ => None
|
||||
}
|
||||
@ -1556,7 +1554,7 @@ impl<T: Iterator<Item=char>> Parser<T> {
|
||||
|
||||
#[allow(deprecated)] // possible resolve bug is mapping these to traits
|
||||
fn parse_u64(&mut self) -> Result<u64, ParserError> {
|
||||
let mut accum = 0;
|
||||
let mut accum = 0u64;
|
||||
let last_accum = 0; // necessary to detect overflow.
|
||||
|
||||
match self.ch_or_null() {
|
||||
@ -2059,7 +2057,7 @@ impl<T: Iterator<Item=char>> Builder<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Decodes a json value from an `&mut old_io::Reader`
|
||||
/// Decodes a json value from an `&mut io::Read`
|
||||
pub fn from_reader(rdr: &mut Read) -> Result<Json, BuilderError> {
|
||||
let mut contents = Vec::new();
|
||||
match rdr.read_to_end(&mut contents) {
|
||||
@ -2121,14 +2119,8 @@ macro_rules! read_primitive {
|
||||
($name:ident, $ty:ty) => {
|
||||
fn $name(&mut self) -> DecodeResult<$ty> {
|
||||
match self.pop() {
|
||||
Json::I64(f) => match num::cast(f) {
|
||||
Some(f) => Ok(f),
|
||||
None => Err(ExpectedError("Number".to_string(), format!("{}", f))),
|
||||
},
|
||||
Json::U64(f) => match num::cast(f) {
|
||||
Some(f) => Ok(f),
|
||||
None => Err(ExpectedError("Number".to_string(), format!("{}", f))),
|
||||
},
|
||||
Json::I64(f) => Ok(f as $ty),
|
||||
Json::U64(f) => Ok(f as $ty),
|
||||
Json::F64(f) => Err(ExpectedError("Integer".to_string(), format!("{}", f))),
|
||||
// re: #12967.. a type w/ numeric keys (ie HashMap<usize, V> etc)
|
||||
// is going to have a string here, as per JSON spec.
|
||||
|
@ -914,33 +914,6 @@ impl<K, V, S> HashMap<K, V, S>
|
||||
IterMut { inner: self.table.iter_mut() }
|
||||
}
|
||||
|
||||
/// Creates a consuming iterator, that is, one that moves each key-value
|
||||
/// pair out of the map in arbitrary order. The map cannot be used after
|
||||
/// calling this.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// let mut map = HashMap::new();
|
||||
/// map.insert("a", 1);
|
||||
/// map.insert("b", 2);
|
||||
/// map.insert("c", 3);
|
||||
///
|
||||
/// // Not possible with .iter()
|
||||
/// let vec: Vec<(&str, isize)> = map.into_iter().collect();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<K, V> {
|
||||
fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
|
||||
let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
|
||||
|
||||
IntoIter {
|
||||
inner: self.table.into_iter().map(last_two)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the given key's corresponding entry in the map for in-place manipulation.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn entry(&mut self, key: K) -> Entry<K, V> {
|
||||
@ -1388,8 +1361,30 @@ impl<K, V, S> IntoIterator for HashMap<K, V, S>
|
||||
type Item = (K, V);
|
||||
type IntoIter = IntoIter<K, V>;
|
||||
|
||||
/// Creates a consuming iterator, that is, one that moves each key-value
|
||||
/// pair out of the map in arbitrary order. The map cannot be used after
|
||||
/// calling this.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// let mut map = HashMap::new();
|
||||
/// map.insert("a", 1);
|
||||
/// map.insert("b", 2);
|
||||
/// map.insert("c", 3);
|
||||
///
|
||||
/// // Not possible with .iter()
|
||||
/// let vec: Vec<(&str, isize)> = map.into_iter().collect();
|
||||
/// ```
|
||||
fn into_iter(self) -> IntoIter<K, V> {
|
||||
self.into_iter()
|
||||
fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
|
||||
let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
|
||||
|
||||
IntoIter {
|
||||
inner: self.table.into_iter().map(last_two)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1625,7 +1620,7 @@ mod test_map {
|
||||
|
||||
use super::HashMap;
|
||||
use super::Entry::{Occupied, Vacant};
|
||||
use iter::{range_inclusive, range_step_inclusive, repeat};
|
||||
use iter::{range_inclusive, repeat};
|
||||
use cell::RefCell;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
@ -1861,7 +1856,7 @@ mod test_map {
|
||||
}
|
||||
|
||||
// remove backwards
|
||||
for i in range_step_inclusive(1000, 1, -1) {
|
||||
for i in (1..1001).rev() {
|
||||
assert!(m.remove(&i).is_some());
|
||||
|
||||
for j in range_inclusive(i, 1000) {
|
||||
|
@ -269,34 +269,6 @@ impl<T, S> HashSet<T, S>
|
||||
Iter { iter: self.map.keys() }
|
||||
}
|
||||
|
||||
/// Creates a consuming iterator, that is, one that moves each value out
|
||||
/// of the set in arbitrary order. The set cannot be used after calling
|
||||
/// this.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashSet;
|
||||
/// let mut set = HashSet::new();
|
||||
/// set.insert("a".to_string());
|
||||
/// set.insert("b".to_string());
|
||||
///
|
||||
/// // Not possible to collect to a Vec<String> with a regular `.iter()`.
|
||||
/// let v: Vec<String> = set.into_iter().collect();
|
||||
///
|
||||
/// // Will print in an arbitrary order.
|
||||
/// for x in v.iter() {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
let first: fn((T, ())) -> T = first;
|
||||
|
||||
IntoIter { iter: self.map.into_iter().map(first) }
|
||||
}
|
||||
|
||||
/// Visit the values representing the difference.
|
||||
///
|
||||
/// # Examples
|
||||
@ -848,8 +820,31 @@ impl<T, S> IntoIterator for HashSet<T, S>
|
||||
type Item = T;
|
||||
type IntoIter = IntoIter<T>;
|
||||
|
||||
/// Creates a consuming iterator, that is, one that moves each value out
|
||||
/// of the set in arbitrary order. The set cannot be used after calling
|
||||
/// this.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashSet;
|
||||
/// let mut set = HashSet::new();
|
||||
/// set.insert("a".to_string());
|
||||
/// set.insert("b".to_string());
|
||||
///
|
||||
/// // Not possible to collect to a Vec<String> with a regular `.iter()`.
|
||||
/// let v: Vec<String> = set.into_iter().collect();
|
||||
///
|
||||
/// // Will print in an arbitrary order.
|
||||
/// for x in v.iter() {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// ```
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
self.into_iter()
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
let first: fn((T, ())) -> T = first;
|
||||
|
||||
IntoIter { iter: self.map.into_iter().map(first) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ use iter::{Iterator, ExactSizeIterator};
|
||||
use marker::{Copy, Send, Sync, Sized, self};
|
||||
use mem::{min_align_of, size_of};
|
||||
use mem;
|
||||
use num::wrapping::{OverflowingOps, WrappingOps};
|
||||
use num::wrapping::OverflowingOps;
|
||||
use ops::{Deref, DerefMut, Drop};
|
||||
use option::Option;
|
||||
use option::Option::{Some, None};
|
||||
|
@ -259,19 +259,14 @@ mod dl {
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
mod dl {
|
||||
use prelude::v1::*;
|
||||
|
||||
use ffi::OsStr;
|
||||
use iter::Iterator;
|
||||
use libc;
|
||||
use libc::consts::os::extra::ERROR_CALL_NOT_IMPLEMENTED;
|
||||
use ops::FnOnce;
|
||||
use sys::os;
|
||||
use os::windows::prelude::*;
|
||||
use option::Option::{self, Some, None};
|
||||
use ptr;
|
||||
use result::Result;
|
||||
use result::Result::{Ok, Err};
|
||||
use string::String;
|
||||
use vec::Vec;
|
||||
use sys::c::compat::kernel32::SetThreadErrorMode;
|
||||
|
||||
pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user