######################################################################
# 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
* [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
[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
* [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)
% 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:
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 {
## 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 {
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.
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`
}
```
-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
% 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
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:
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:
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
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
^
```
-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:
```
`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
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;
```
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;
# 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].
# }
```
-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.
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
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
```
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
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
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
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>) {
```
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
```
-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
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
# }
```
-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
```
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.
% 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.
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
+-----------+
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
# 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:
```
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`.
```
`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.
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
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:
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`:
```
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`:
}
```
-(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;
```
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.
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
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}
}
```
-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 {
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;
```
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:
```
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:
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}
## 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;
```
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
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.
% 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
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.
# 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
# }
```
-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
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.
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.
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
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.
}
```
-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 `*`.
```
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 {
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
})
```
-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";
```
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
}
```
-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
# 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:
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
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`.
* `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
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.
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
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:
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 {
# 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.
```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
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 };
+```
% 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
}
```
-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; }
}
```
-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:
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.
## 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.
(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:
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.
### 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]:
[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
`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,
```
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
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;
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:
% 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);
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,
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);
```
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`.
+++ /dev/null
-% Unsafe Code
-
-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
-safe, but the compiler is not able to verify this is true. To write these kinds
-of programs, we need to tell the compiler to relax its restrictions a bit. For
-this, Rust has a keyword, `unsafe`. Code using `unsafe` has less restrictions
-than normal code does.
-
-Let’s go over the syntax, and then we’ll talk semantics. `unsafe` is used in
-two contexts. The first one is to mark a function as unsafe:
-
-```rust
-unsafe fn danger_will_robinson() {
- // scary stuff
-}
-```
-
-All functions called from [FFI][ffi] must be marked as `unsafe`, for example.
-The second use of `unsafe` is an unsafe block:
-
-[ffi]: ffi.html
-
-```rust
-unsafe {
- // scary stuff
-}
-```
-
-It’s important to be able to explicitly delineate code that may have bugs that
-cause big problems. If a Rust program segfaults, you can be sure it’s somewhere
-in the sections marked `unsafe`.
-
-# What does ‘safe’ mean?
-
-Safe, in the context of Rust, means “doesn’t do anything unsafe.” Easy!
-
-Okay, let’s try again: what is not safe to do? Here’s a list:
-
-* Data races
-* Dereferencing a null/dangling raw pointer
-* Reads of [undef][undef] (uninitialized) memory
-* Breaking the [pointer aliasing rules][aliasing] with raw pointers.
-* `&mut T` and `&T` follow LLVM’s scoped [noalias][noalias] model, except if
- the `&T` contains an `UnsafeCell<U>`. Unsafe code must not violate these
- aliasing guarantees.
-* Mutating an immutable value/reference without `UnsafeCell<U>`
-* Invoking undefined behavior via compiler intrinsics:
- * Indexing outside of the bounds of an object with `std::ptr::offset`
- (`offset` intrinsic), with
- the exception of one byte past the end which is permitted.
- * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
- intrinsics) on overlapping buffers
-* Invalid values in primitive types, even in private fields/locals:
- * Null/dangling references or boxes
- * A value other than `false` (0) or `true` (1) in a `bool`
- * A discriminant in an `enum` not included in its type definition
- * A value in a `char` which is a surrogate or above `char::MAX`
- * Non-UTF-8 byte sequences in a `str`
-* Unwinding into Rust from foreign code or unwinding from Rust into foreign
- code.
-
-[noalias]: http://llvm.org/docs/LangRef.html#noalias
-[undef]: http://llvm.org/docs/LangRef.html#undefined-values
-[aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules
-
-Whew! That’s a bunch of stuff. It’s also important to notice all kinds of
-behaviors that are certainly bad, but are expressly _not_ unsafe:
-
-* Deadlocks
-* Reading data from private fields
-* Leaks due to reference count cycles
-* Exiting without calling destructors
-* Sending signals
-* Accessing/modifying the file system
-* 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`
-specifically.
-
-# Unsafe Superpowers
-
-In both unsafe functions and unsafe blocks, Rust will let you do three things
-that you normally can not do. Just three. Here they are:
-
-1. Access or update a [static mutable variable][static].
-2. Dereference a raw pointer.
-3. Call unsafe functions. This is the most powerful ability.
-
-That’s it. It’s important that `unsafe` does not, for example, ‘turn off the
-borrow checker’. Adding `unsafe` to some random Rust code doesn’t change its
-semantics, it won’t just start accepting anything.
-
-But it will let you write things that _do_ break some of the rules. Let’s go
-over these three abilities in order.
-
-## Access or update a `static mut`
-
-Rust has a feature called ‘`static mut`’ which allows for mutable global state.
-Doing so can cause a data race, and as such is inherently not safe. For more
-details, see the [static][static] section of the book.
-
-[static]: static.html
-
-## Dereference a raw pointer
-
-Raw pointers let you do arbitrary pointer arithmetic, and can cause a number of
-different memory safety and security issues. In some senses, the ability to
-dereference an arbitrary pointer is one of the most dangerous things you can
-do. For more on raw pointers, see [their section of the book][rawpointers].
-
-[rawpointers]: raw-pointers.html
-
-## Call unsafe functions
-
-This last ability works with both aspects of `unsafe`: you can only call
-functions marked `unsafe` from inside an unsafe block.
-
-This ability is powerful and varied. Rust exposes some [compiler
-intrinsics][intrinsics] as unsafe functions, and some unsafe functions bypass
-safety checks, trading safety for speed.
-
-I’ll repeat again: even though you _can_ do arbitrary things in unsafe blocks
-and functions doesn’t mean you should. The compiler will act as though you’re
-upholding its invariants, so be careful!
-
-[intrinsics]: intrinsics.html
--- /dev/null
+% 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
+safe, but the compiler is not able to verify this is true. To write these kinds
+of programs, we need to tell the compiler to relax its restrictions a bit. For
+this, Rust has a keyword, `unsafe`. Code using `unsafe` has less restrictions
+than normal code does.
+
+Let’s go over the syntax, and then we’ll talk semantics. `unsafe` is used in
+two contexts. The first one is to mark a function as unsafe:
+
+```rust
+unsafe fn danger_will_robinson() {
+ // scary stuff
+}
+```
+
+All functions called from [FFI][ffi] must be marked as `unsafe`, for example.
+The second use of `unsafe` is an unsafe block:
+
+[ffi]: ffi.html
+
+```rust
+unsafe {
+ // scary stuff
+}
+```
+
+It’s important to be able to explicitly delineate code that may have bugs that
+cause big problems. If a Rust program segfaults, you can be sure it’s somewhere
+in the sections marked `unsafe`.
+
+# What does ‘safe’ mean?
+
+Safe, in the context of Rust, means “doesn’t do anything unsafe.” Easy!
+
+Okay, let’s try again: what is not safe to do? Here’s a list:
+
+* Data races
+* Dereferencing a null/dangling raw pointer
+* Reads of [undef][undef] (uninitialized) memory
+* Breaking the [pointer aliasing rules][aliasing] with raw pointers.
+* `&mut T` and `&T` follow LLVM’s scoped [noalias][noalias] model, except if
+ the `&T` contains an `UnsafeCell<U>`. Unsafe code must not violate these
+ aliasing guarantees.
+* Mutating an immutable value/reference without `UnsafeCell<U>`
+* Invoking undefined behavior via compiler intrinsics:
+ * Indexing outside of the bounds of an object with `std::ptr::offset`
+ (`offset` intrinsic), with
+ the exception of one byte past the end which is permitted.
+ * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
+ intrinsics) on overlapping buffers
+* Invalid values in primitive types, even in private fields/locals:
+ * Null/dangling references or boxes
+ * A value other than `false` (0) or `true` (1) in a `bool`
+ * A discriminant in an `enum` not included in its type definition
+ * A value in a `char` which is a surrogate or above `char::MAX`
+ * Non-UTF-8 byte sequences in a `str`
+* Unwinding into Rust from foreign code or unwinding from Rust into foreign
+ code.
+
+[noalias]: http://llvm.org/docs/LangRef.html#noalias
+[undef]: http://llvm.org/docs/LangRef.html#undefined-values
+[aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules
+
+Whew! That’s a bunch of stuff. It’s also important to notice all kinds of
+behaviors that are certainly bad, but are expressly _not_ unsafe:
+
+* Deadlocks
+* Reading data from private fields
+* Leaks due to reference count cycles
+* Exiting without calling destructors
+* Sending signals
+* Accessing/modifying the file system
+* Integer overflow
+
+Rust cannot prevent all kinds of software problems. Buggy code can and will be
+written in Rust. These things aren’t great, but they don’t qualify as `unsafe`
+specifically.
+
+# Unsafe Superpowers
+
+In both unsafe functions and unsafe blocks, Rust will let you do three things
+that you normally can not do. Just three. Here they are:
+
+1. Access or update a [static mutable variable][static].
+2. Dereference a raw pointer.
+3. Call unsafe functions. This is the most powerful ability.
+
+That’s it. It’s important that `unsafe` does not, for example, ‘turn off the
+borrow checker’. Adding `unsafe` to some random Rust code doesn’t change its
+semantics, it won’t just start accepting anything.
+
+But it will let you write things that _do_ break some of the rules. Let’s go
+over these three abilities in order.
+
+## Access or update a `static mut`
+
+Rust has a feature called ‘`static mut`’ which allows for mutable global state.
+Doing so can cause a data race, and as such is inherently not safe. For more
+details, see the [static][static] section of the book.
+
+[static]: static.html
+
+## Dereference a raw pointer
+
+Raw pointers let you do arbitrary pointer arithmetic, and can cause a number of
+different memory safety and security issues. In some senses, the ability to
+dereference an arbitrary pointer is one of the most dangerous things you can
+do. For more on raw pointers, see [their section of the book][rawpointers].
+
+[rawpointers]: raw-pointers.html
+
+## Call unsafe functions
+
+This last ability works with both aspects of `unsafe`: you can only call
+functions marked `unsafe` from inside an unsafe block.
+
+This ability is powerful and varied. Rust exposes some [compiler
+intrinsics][intrinsics] as unsafe functions, and some unsafe functions bypass
+safety checks, trading safety for speed.
+
+I’ll repeat again: even though you _can_ do arbitrary things in unsafe blocks
+and functions doesn’t mean you should. The compiler will act as though you’re
+upholding its invariants, so be careful!
+
+[intrinsics]: intrinsics.html
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)
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(' '):
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;
use core::any::Any;
use core::cmp::Ordering;
-use core::default::Default;
use core::fmt;
use core::hash::{self, Hash};
use core::mem;
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;
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
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() }
}
}
//! ```
//! # #![feature(collections, core, step_by)]
//! use std::collections::{BitSet, BitVec};
-//! use std::num::Float;
//! use std::iter;
//!
//! let max_prime = 10000;
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};
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};
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,
+ }
+ }
}
}
}
}
- /// 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
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;
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> {
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) }
}
}
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)
//! # #![feature(core, std_misc)]
//! use std::fmt;
//! use std::f64;
-//! use std::num::Float;
//!
//! #[derive(Debug)]
//! struct Vector2D {
//! 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)
//! }
//! }
//! Example usage is:
//!
//! ```
-//! # #![feature(old_io)]
//! # #![allow(unused_must_use)]
//! use std::io::Write;
//! let mut w = Vec::new();
//! off, some example usage is:
//!
//! ```
-//! # #![feature(old_io)]
//! use std::fmt;
//! use std::io::{self, Write};
//!
#![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)]
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;
}
}
- /// 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.
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}
}
}
#[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;
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};
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};
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;
/*
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.
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;
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]
}
}
-#[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]
self.push_str(s);
Ok(())
}
+
+ #[inline]
+ fn write_char(&mut self, c: char) -> fmt::Result {
+ self.push(c);
+ Ok(())
+ }
}
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};
&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
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 }
+ }
}
}
}
}
-#[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> {
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};
}
}
- /// 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]
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,
+ }
}
}
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};
}
}
- /// 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
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) }
}
}
#![feature(hash)]
#![feature(rand)]
#![feature(rustc_private)]
-#![feature(str_words)]
#![feature(test)]
#![feature(unboxed_closures)]
#![feature(unicode)]
}
#[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"])
}
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 {
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`
/// # 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,
) -> 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");
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)
};
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;
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;
#![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;
#[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
}
// 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),
#[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),
#[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),
#![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 {
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..]) };
use prelude::*;
-use default::Default;
use mem;
pub use self::sip::SipHasher;
#![allow(deprecated)] // until the next snapshot for inherent wrapping ops
use prelude::*;
-use default::Default;
use super::Hasher;
/// An implementation of SipHash 2-4.
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;
/// 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
}
}
-/// 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")]
#[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 */
#[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.
}
#[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.
}
/// 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
}
)
}
-/// `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 { }
-
-#[allow(deprecated)]
-impl<T:?Sized> MarkerTrait for T { }
+#[cfg(stage0)]
+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.
#[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 .. { }
//! 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 {}
#![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;
#[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;
#[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;
#[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 }
}
}
- #[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) };
/// The fractional part of the number, satisfying:
///
/// ```
- /// # #![feature(core)]
- /// use std::num::Float;
- ///
/// let x = 1.65f32;
/// assert!(x == x.trunc() + x.fract())
/// ```
#![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;
#[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;
#[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;
#[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 }
}
}
- #[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) };
/// The fractional part of the number, satisfying:
///
/// ```
- /// # #![feature(core)]
- /// use std::num::Float;
- ///
/// let x = 1.65f64;
/// assert!(x == x.trunc() + x.fract())
/// ```
"{} 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)
+ }
+ }
+}
#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)]
-use self::wrapping::{OverflowingOps, WrappingOps};
+use self::wrapping::OverflowingOps;
use char::CharExt;
-use clone::Clone;
-use cmp::{PartialEq, Eq, PartialOrd, Ord};
+use cmp::{Eq, PartialOrd};
use fmt;
use intrinsics;
-use iter::Iterator;
use marker::Copy;
use mem::size_of;
-use ops::{Add, Sub, Mul, Div, Rem, Neg};
-use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use str::{FromStr, StrExt};
}
zero_one_impl_float! { f32 f64 }
-/// A built-in signed or unsigned integer.
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(since = "1.0.0",
- reason = "replaced by inherent methods; for generics, use rust-lang/num")]
-#[allow(deprecated)]
-pub trait Int
- : Copy + Clone
- + NumCast
- + PartialOrd + Ord
- + PartialEq + Eq
- + Add<Output=Self>
- + Sub<Output=Self>
- + Mul<Output=Self>
- + Div<Output=Self>
- + Rem<Output=Self>
- + Not<Output=Self>
- + BitAnd<Output=Self>
- + BitOr<Output=Self>
- + BitXor<Output=Self>
- + Shl<usize, Output=Self>
- + Shr<usize, Output=Self>
- + WrappingOps
- + OverflowingOps
-{
- /// Returns the `0` value of this integer type.
- // FIXME (#5527): Should be an associated constant
- #[unstable(feature = "core",
- reason = "unsure about its place in the world")]
- fn zero() -> Self;
-
- /// Returns the `1` value of this integer type.
- // FIXME (#5527): Should be an associated constant
- #[unstable(feature = "core",
- reason = "unsure about its place in the world")]
- fn one() -> Self;
-
- /// Returns the smallest value that can be represented by this integer type.
- // FIXME (#5527): Should be and associated constant
- #[unstable(feature = "core",
- reason = "unsure about its place in the world")]
- fn min_value() -> Self;
-
- /// Returns the largest value that can be represented by this integer type.
- // FIXME (#5527): Should be and associated constant
- #[unstable(feature = "core",
- reason = "unsure about its place in the world")]
- fn max_value() -> Self;
-
- /// Returns the number of ones in the binary representation of `self`.
- ///
- /// # Examples
- ///
- /// ```
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
- /// let n = 0b01001100u8;
- ///
- /// assert_eq!(n.count_ones(), 3);
- /// ```
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
- fn count_ones(self) -> u32;
-
- /// Returns the number of zeros in the binary representation of `self`.
- ///
- /// # Examples
- ///
- /// ```
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
- /// let n = 0b01001100u8;
- ///
- /// assert_eq!(n.count_zeros(), 5);
- /// ```
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
- #[inline]
- fn count_zeros(self) -> u32 {
- (!self).count_ones()
- }
-
- /// Returns the number of leading zeros in the binary representation
- /// of `self`.
- ///
- /// # Examples
- ///
- /// ```
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
- /// let n = 0b0101000u16;
- ///
- /// assert_eq!(n.leading_zeros(), 10);
- /// ```
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
- fn leading_zeros(self) -> u32;
-
- /// Returns the number of trailing zeros in the binary representation
- /// of `self`.
- ///
- /// # Examples
- ///
- /// ```
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
- /// let n = 0b0101000u16;
- ///
- /// assert_eq!(n.trailing_zeros(), 3);
- /// ```
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
- fn trailing_zeros(self) -> u32;
-
- /// Shifts the bits to the left by a specified amount, `n`, wrapping
- /// the truncated bits to the end of the resulting integer.
- ///
- /// # Examples
- ///
- /// ```
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
- /// let n = 0x0123456789ABCDEFu64;
- /// let m = 0x3456789ABCDEF012u64;
- ///
- /// assert_eq!(n.rotate_left(12), m);
- /// ```
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
- fn rotate_left(self, n: u32) -> Self;
-
- /// Shifts the bits to the right by a specified amount, `n`, wrapping
- /// the truncated bits to the beginning of the resulting integer.
- ///
- /// # Examples
- ///
- /// ```
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
- /// let n = 0x0123456789ABCDEFu64;
- /// let m = 0xDEF0123456789ABCu64;
- ///
- /// assert_eq!(n.rotate_right(12), m);
- /// ```
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
- fn rotate_right(self, n: u32) -> Self;
-
- /// Reverses the byte order of the integer.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// let n = 0x0123456789ABCDEFu64;
- /// let m = 0xEFCDAB8967452301u64;
- ///
- /// assert_eq!(n.swap_bytes(), m);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn swap_bytes(self) -> Self;
-
- /// Converts an integer from big endian to the target's endianness.
- ///
- /// On big endian this is a no-op. On little endian the bytes are swapped.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// let n = 0x0123456789ABCDEFu64;
- ///
- /// if cfg!(target_endian = "big") {
- /// assert_eq!(Int::from_be(n), n)
- /// } else {
- /// assert_eq!(Int::from_be(n), n.swap_bytes())
- /// }
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- fn from_be(x: Self) -> Self {
- if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
- }
-
- /// Converts an integer from little endian to the target's endianness.
- ///
- /// On little endian this is a no-op. On big endian the bytes are swapped.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// let n = 0x0123456789ABCDEFu64;
- ///
- /// if cfg!(target_endian = "little") {
- /// assert_eq!(Int::from_le(n), n)
- /// } else {
- /// assert_eq!(Int::from_le(n), n.swap_bytes())
- /// }
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- fn from_le(x: Self) -> Self {
- if cfg!(target_endian = "little") { x } else { x.swap_bytes() }
- }
-
- /// Converts `self` to big endian from the target's endianness.
- ///
- /// On big endian this is a no-op. On little endian the bytes are swapped.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// let n = 0x0123456789ABCDEFu64;
- ///
- /// if cfg!(target_endian = "big") {
- /// assert_eq!(n.to_be(), n)
- /// } else {
- /// assert_eq!(n.to_be(), n.swap_bytes())
- /// }
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- fn to_be(self) -> Self { // or not to be?
- if cfg!(target_endian = "big") { self } else { self.swap_bytes() }
- }
-
- /// Converts `self` to little endian from the target's endianness.
- ///
- /// On little endian this is a no-op. On big endian the bytes are swapped.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// let n = 0x0123456789ABCDEFu64;
- ///
- /// if cfg!(target_endian = "little") {
- /// assert_eq!(n.to_le(), n)
- /// } else {
- /// assert_eq!(n.to_le(), n.swap_bytes())
- /// }
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- fn to_le(self) -> Self {
- if cfg!(target_endian = "little") { self } else { self.swap_bytes() }
- }
-
- /// Checked integer addition. Computes `self + other`, returning `None` if
- /// overflow occurred.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// assert_eq!(5u16.checked_add(65530), Some(65535));
- /// assert_eq!(6u16.checked_add(65530), None);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn checked_add(self, other: Self) -> Option<Self>;
-
- /// Checked integer subtraction. Computes `self - other`, returning `None`
- /// if underflow occurred.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// assert_eq!((-127i8).checked_sub(1), Some(-128));
- /// assert_eq!((-128i8).checked_sub(1), None);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn checked_sub(self, other: Self) -> Option<Self>;
-
- /// Checked integer multiplication. Computes `self * other`, returning
- /// `None` if underflow or overflow occurred.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// assert_eq!(5u8.checked_mul(51), Some(255));
- /// assert_eq!(5u8.checked_mul(52), None);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn checked_mul(self, other: Self) -> Option<Self>;
-
- /// Checked integer division. Computes `self / other`, returning `None` if
- /// `other == 0` or the operation results in underflow or overflow.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// assert_eq!((-127i8).checked_div(-1), Some(127));
- /// assert_eq!((-128i8).checked_div(-1), None);
- /// assert_eq!((1i8).checked_div(0), None);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn checked_div(self, other: Self) -> Option<Self>;
-
- /// Saturating integer addition. Computes `self + other`, saturating at
- /// the numeric bounds instead of overflowing.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// assert_eq!(5u16.saturating_add(65534), 65535);
- /// assert_eq!((-5i16).saturating_add(-32767), -32768);
- /// assert_eq!(100u32.saturating_add(4294967294), 4294967295);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- fn saturating_add(self, other: Self) -> Self {
- match self.checked_add(other) {
- Some(x) => x,
- None if other >= Int::zero() => Int::max_value(),
- None => Int::min_value(),
- }
- }
-
- /// Saturating integer subtraction. Computes `self - other`, saturating at
- /// the numeric bounds instead of overflowing.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::num::Int;
- ///
- /// assert_eq!(5u16.saturating_sub(65534), 0);
- /// assert_eq!(5i16.saturating_sub(-32767), 32767);
- /// assert_eq!(100u32.saturating_sub(4294967294), 0);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- fn saturating_sub(self, other: Self) -> Self {
- match self.checked_sub(other) {
- Some(x) => x,
- None if other >= Int::zero() => Int::min_value(),
- None => Int::max_value(),
- }
- }
-
- /// Raises self to the power of `exp`, using exponentiation by squaring.
- ///
- /// # Examples
- ///
- /// ```
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
- /// assert_eq!(2.pow(4), 16);
- /// ```
- #[unstable(feature = "core",
- reason = "pending integer conventions")]
- #[inline]
- fn pow(self, mut exp: u32) -> Self {
- let mut base = self;
- let mut acc: Self = Int::one();
-
- let mut prev_base = self;
- let mut base_oflo = false;
- while exp > 0 {
- if (exp & 1) == 1 {
- if base_oflo {
- // ensure overflow occurs in the same manner it
- // would have otherwise (i.e. signal any exception
- // it would have otherwise).
- acc = acc * (prev_base * prev_base);
- } else {
- acc = acc * base;
- }
- }
- prev_base = base;
- let (new_base, new_base_oflo) = base.overflowing_mul(base);
- base = new_base;
- base_oflo = new_base_oflo;
- exp /= 2;
- }
- acc
- }
-}
-
macro_rules! checked_op {
($T:ty, $U:ty, $op:path, $x:expr, $y:expr) => {{
let (result, overflowed) = unsafe { $op($x as $U, $y as $U) };
}}
}
-macro_rules! uint_impl {
- ($T:ty = $ActualT:ty, $BITS:expr,
- $ctpop:path,
- $ctlz:path,
- $cttz:path,
- $bswap:path,
- $add_with_overflow:path,
- $sub_with_overflow:path,
- $mul_with_overflow:path) => {
- #[stable(feature = "rust1", since = "1.0.0")]
- #[allow(deprecated)]
- impl Int for $T {
- #[inline]
- fn zero() -> $T { 0 }
-
- #[inline]
- fn one() -> $T { 1 }
-
- #[inline]
- fn min_value() -> $T { 0 }
-
- #[inline]
- fn max_value() -> $T { !0 }
-
- #[inline]
- fn count_ones(self) -> u32 {
- unsafe { $ctpop(self as $ActualT) as u32 }
- }
-
- #[inline]
- fn leading_zeros(self) -> u32 {
- unsafe { $ctlz(self as $ActualT) as u32 }
- }
-
- #[inline]
- fn trailing_zeros(self) -> u32 {
- unsafe { $cttz(self as $ActualT) as u32 }
- }
-
- #[inline]
- fn rotate_left(self, n: u32) -> $T {
- // Protect against undefined behaviour for over-long bit shifts
- let n = n % $BITS;
- (self << n) | (self >> (($BITS - n) % $BITS))
- }
-
- #[inline]
- fn rotate_right(self, n: u32) -> $T {
- // Protect against undefined behaviour for over-long bit shifts
- let n = n % $BITS;
- (self >> n) | (self << (($BITS - n) % $BITS))
- }
-
- #[inline]
- fn swap_bytes(self) -> $T {
- unsafe { $bswap(self as $ActualT) as $T }
- }
-
- #[inline]
- fn checked_add(self, other: $T) -> Option<$T> {
- checked_op!($T, $ActualT, $add_with_overflow, self, other)
- }
-
- #[inline]
- fn checked_sub(self, other: $T) -> Option<$T> {
- checked_op!($T, $ActualT, $sub_with_overflow, self, other)
- }
-
- #[inline]
- fn checked_mul(self, other: $T) -> Option<$T> {
- checked_op!($T, $ActualT, $mul_with_overflow, self, other)
- }
-
- #[inline]
- fn checked_div(self, v: $T) -> Option<$T> {
- match v {
- 0 => None,
- v => Some(self / v),
- }
- }
- }
- }
-}
-
/// Swapping a single byte is a no-op. This is marked as `unsafe` for
/// consistency with the other `bswap` intrinsics.
unsafe fn bswap8(x: u8) -> u8 { x }
-uint_impl! { u8 = u8, 8,
- intrinsics::ctpop8,
- intrinsics::ctlz8,
- intrinsics::cttz8,
- bswap8,
- intrinsics::u8_add_with_overflow,
- intrinsics::u8_sub_with_overflow,
- intrinsics::u8_mul_with_overflow }
-
-uint_impl! { u16 = u16, 16,
- intrinsics::ctpop16,
- intrinsics::ctlz16,
- intrinsics::cttz16,
- intrinsics::bswap16,
- intrinsics::u16_add_with_overflow,
- intrinsics::u16_sub_with_overflow,
- intrinsics::u16_mul_with_overflow }
-
-uint_impl! { u32 = u32, 32,
- intrinsics::ctpop32,
- intrinsics::ctlz32,
- intrinsics::cttz32,
- intrinsics::bswap32,
- intrinsics::u32_add_with_overflow,
- intrinsics::u32_sub_with_overflow,
- intrinsics::u32_mul_with_overflow }
-
-uint_impl! { u64 = u64, 64,
- intrinsics::ctpop64,
- intrinsics::ctlz64,
- intrinsics::cttz64,
- intrinsics::bswap64,
- intrinsics::u64_add_with_overflow,
- intrinsics::u64_sub_with_overflow,
- intrinsics::u64_mul_with_overflow }
-
-#[cfg(target_pointer_width = "32")]
-uint_impl! { usize = u32, 32,
- intrinsics::ctpop32,
- intrinsics::ctlz32,
- intrinsics::cttz32,
- intrinsics::bswap32,
- intrinsics::u32_add_with_overflow,
- intrinsics::u32_sub_with_overflow,
- intrinsics::u32_mul_with_overflow }
-
-#[cfg(target_pointer_width = "64")]
-uint_impl! { usize = u64, 64,
- intrinsics::ctpop64,
- intrinsics::ctlz64,
- intrinsics::cttz64,
- intrinsics::bswap64,
- intrinsics::u64_add_with_overflow,
- intrinsics::u64_sub_with_overflow,
- intrinsics::u64_mul_with_overflow }
-
-macro_rules! int_impl {
- ($T:ty = $ActualT:ty, $UnsignedT:ty, $BITS:expr,
- $add_with_overflow:path,
- $sub_with_overflow:path,
- $mul_with_overflow:path) => {
- #[stable(feature = "rust1", since = "1.0.0")]
- #[allow(deprecated)]
- impl Int for $T {
- #[inline]
- fn zero() -> $T { 0 }
-
- #[inline]
- fn one() -> $T { 1 }
-
- #[inline]
- fn min_value() -> $T { (-1 as $T) << ($BITS - 1) }
-
- #[inline]
- fn max_value() -> $T { let min: $T = Int::min_value(); !min }
-
- #[inline]
- fn count_ones(self) -> u32 { (self as $UnsignedT).count_ones() }
-
- #[inline]
- fn leading_zeros(self) -> u32 {
- (self as $UnsignedT).leading_zeros()
- }
-
- #[inline]
- fn trailing_zeros(self) -> u32 {
- (self as $UnsignedT).trailing_zeros()
- }
-
- #[inline]
- fn rotate_left(self, n: u32) -> $T {
- (self as $UnsignedT).rotate_left(n) as $T
- }
-
- #[inline]
- fn rotate_right(self, n: u32) -> $T {
- (self as $UnsignedT).rotate_right(n) as $T
- }
-
- #[inline]
- fn swap_bytes(self) -> $T {
- (self as $UnsignedT).swap_bytes() as $T
- }
-
- #[inline]
- fn checked_add(self, other: $T) -> Option<$T> {
- checked_op!($T, $ActualT, $add_with_overflow, self, other)
- }
-
- #[inline]
- fn checked_sub(self, other: $T) -> Option<$T> {
- checked_op!($T, $ActualT, $sub_with_overflow, self, other)
- }
-
- #[inline]
- fn checked_mul(self, other: $T) -> Option<$T> {
- checked_op!($T, $ActualT, $mul_with_overflow, self, other)
- }
-
- #[inline]
- fn checked_div(self, v: $T) -> Option<$T> {
- match v {
- 0 => None,
- -1 if self == Int::min_value()
- => None,
- v => Some(self / v),
- }
- }
- }
- }
-}
-
-int_impl! { i8 = i8, u8, 8,
- intrinsics::i8_add_with_overflow,
- intrinsics::i8_sub_with_overflow,
- intrinsics::i8_mul_with_overflow }
-
-int_impl! { i16 = i16, u16, 16,
- intrinsics::i16_add_with_overflow,
- intrinsics::i16_sub_with_overflow,
- intrinsics::i16_mul_with_overflow }
-
-int_impl! { i32 = i32, u32, 32,
- intrinsics::i32_add_with_overflow,
- intrinsics::i32_sub_with_overflow,
- intrinsics::i32_mul_with_overflow }
-
-int_impl! { i64 = i64, u64, 64,
- intrinsics::i64_add_with_overflow,
- intrinsics::i64_sub_with_overflow,
- intrinsics::i64_mul_with_overflow }
-
-#[cfg(target_pointer_width = "32")]
-int_impl! { isize = i32, u32, 32,
- intrinsics::i32_add_with_overflow,
- intrinsics::i32_sub_with_overflow,
- intrinsics::i32_mul_with_overflow }
-
-#[cfg(target_pointer_width = "64")]
-int_impl! { isize = i64, u64, 64,
- intrinsics::i64_add_with_overflow,
- intrinsics::i64_sub_with_overflow,
- intrinsics::i64_mul_with_overflow }
-
-/// A built-in two's complement integer.
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(since = "1.0.0",
- reason = "replaced by inherent methods; for generics, use rust-lang/num")]
-#[allow(deprecated)]
-pub trait SignedInt
- : Int
- + Neg<Output=Self>
-{
- /// Computes the absolute value of `self`. `Int::min_value()` will be
- /// returned if the number is `Int::min_value()`.
- #[unstable(feature = "core", reason = "overflow in debug builds?")]
- fn abs(self) -> Self;
-
- /// Returns a number representing sign of `self`.
- ///
- /// - `0` if the number is zero
- /// - `1` if the number is positive
- /// - `-1` if the number is negative
- #[stable(feature = "rust1", since = "1.0.0")]
- fn signum(self) -> Self;
-
- /// Returns `true` if `self` is positive and `false` if the number
- /// is zero or negative.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_positive(self) -> bool;
-
- /// Returns `true` if `self` is negative and `false` if the number
- /// is zero or positive.
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_negative(self) -> bool;
-}
-
-macro_rules! signed_int_impl {
- ($T:ty) => {
- #[stable(feature = "rust1", since = "1.0.0")]
- #[allow(deprecated)]
- impl SignedInt for $T {
- #[inline]
- fn abs(self) -> $T {
- if self.is_negative() { -self } else { self }
- }
-
- #[inline]
- fn signum(self) -> $T {
- match self {
- n if n > 0 => 1,
- 0 => 0,
- _ => -1,
- }
- }
-
- #[inline]
- fn is_positive(self) -> bool { self > 0 }
-
- #[inline]
- fn is_negative(self) -> bool { self < 0 }
- }
- }
-}
-
-signed_int_impl! { i8 }
-signed_int_impl! { i16 }
-signed_int_impl! { i32 }
-signed_int_impl! { i64 }
-signed_int_impl! { isize }
-
// `Int` + `SignedInt` implemented for signed integers
macro_rules! int_impl {
- ($T:ty = $ActualT:ty, $UnsignedT:ty, $BITS:expr,
+ ($T:ident = $ActualT:ty, $UnsignedT:ty, $BITS:expr,
$add_with_overflow:path,
$sub_with_overflow:path,
$mul_with_overflow:path) => {
/// Returns the largest value that can be represented by this integer type.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn max_value() -> $T {
- let min: $T = Int::min_value(); !min
+ let min = $T::min_value(); !min
}
/// Converts a string slice in a given base to an integer.
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub fn from_str_radix(src: &str, radix: u32) -> Result<$T, ParseIntError> {
- <Self as FromStrRadix>::from_str_radix(src, radix)
+ from_str_radix(src, radix)
}
/// Returns the number of ones in the binary representation of `self`.
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0b01001100u8;
///
/// assert_eq!(n.count_ones(), 3);
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0b01001100u8;
///
/// assert_eq!(n.count_zeros(), 5);
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0b0101000u16;
///
/// assert_eq!(n.leading_zeros(), 10);
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0b0101000u16;
///
/// assert_eq!(n.trailing_zeros(), 3);
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
/// let m = 0x3456789ABCDEF012u64;
///
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
/// let m = 0xDEF0123456789ABCu64;
///
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
/// let m = 0xEFCDAB8967452301u64;
///
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
///
/// if cfg!(target_endian = "big") {
- /// assert_eq!(Int::from_be(n), n)
+ /// assert_eq!(u64::from_be(n), n)
/// } else {
- /// assert_eq!(Int::from_be(n), n.swap_bytes())
+ /// assert_eq!(u64::from_be(n), n.swap_bytes())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
///
/// if cfg!(target_endian = "little") {
- /// assert_eq!(Int::from_le(n), n)
+ /// assert_eq!(u64::from_le(n), n)
/// } else {
- /// assert_eq!(Int::from_le(n), n.swap_bytes())
+ /// assert_eq!(u64::from_le(n), n.swap_bytes())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
///
/// if cfg!(target_endian = "big") {
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
///
/// if cfg!(target_endian = "little") {
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// assert_eq!(5u16.checked_add(65530), Some(65535));
/// assert_eq!(6u16.checked_add(65530), None);
/// ```
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// assert_eq!((-127i8).checked_sub(1), Some(-128));
/// assert_eq!((-128i8).checked_sub(1), None);
/// ```
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// assert_eq!(5u8.checked_mul(51), Some(255));
/// assert_eq!(5u8.checked_mul(52), None);
/// ```
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// assert_eq!((-127i8).checked_div(-1), Some(127));
/// assert_eq!((-128i8).checked_div(-1), None);
/// assert_eq!((1i8).checked_div(0), None);
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
pub fn from_str_radix(src: &str, radix: u32) -> Result<$T, ParseIntError> {
- <Self as FromStrRadix>::from_str_radix(src, radix)
+ from_str_radix(src, radix)
}
/// Returns the number of ones in the binary representation of `self`.
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0b01001100u8;
///
/// assert_eq!(n.count_ones(), 3);
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0b01001100u8;
///
/// assert_eq!(n.count_zeros(), 5);
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0b0101000u16;
///
/// assert_eq!(n.leading_zeros(), 10);
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0b0101000u16;
///
/// assert_eq!(n.trailing_zeros(), 3);
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
/// let m = 0x3456789ABCDEF012u64;
///
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
/// let m = 0xDEF0123456789ABCu64;
///
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
/// let m = 0xEFCDAB8967452301u64;
///
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
///
/// if cfg!(target_endian = "big") {
- /// assert_eq!(Int::from_be(n), n)
+ /// assert_eq!(u64::from_be(n), n)
/// } else {
- /// assert_eq!(Int::from_be(n), n.swap_bytes())
+ /// assert_eq!(u64::from_be(n), n.swap_bytes())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
///
/// if cfg!(target_endian = "little") {
- /// assert_eq!(Int::from_le(n), n)
+ /// assert_eq!(u64::from_le(n), n)
/// } else {
- /// assert_eq!(Int::from_le(n), n.swap_bytes())
+ /// assert_eq!(u64::from_le(n), n.swap_bytes())
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
///
/// if cfg!(target_endian = "big") {
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// let n = 0x0123456789ABCDEFu64;
///
/// if cfg!(target_endian = "little") {
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// assert_eq!(5u16.checked_add(65530), Some(65535));
/// assert_eq!(6u16.checked_add(65530), None);
/// ```
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// assert_eq!((-127i8).checked_sub(1), Some(-128));
/// assert_eq!((-128i8).checked_sub(1), None);
/// ```
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// assert_eq!(5u8.checked_mul(51), Some(255));
/// assert_eq!(5u8.checked_mul(52), None);
/// ```
/// # Examples
///
/// ```rust
- /// use std::num::Int;
- ///
/// assert_eq!((-127i8).checked_div(-1), Some(127));
/// assert_eq!((-128i8).checked_div(-1), None);
/// assert_eq!((1i8).checked_div(0), None);
/// # Examples
///
/// ```rust
- /// # #![feature(core)]
- /// use std::num::Int;
- ///
- /// assert_eq!(2.pow(4), 16);
+ /// assert_eq!(2i32.pow(4), 16);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
intrinsics::u64_mul_with_overflow }
}
-/// A generic trait for converting a value to a number.
-#[unstable(feature = "core", reason = "trait is likely to be removed")]
-pub trait ToPrimitive {
- /// Converts the value of `self` to an `isize`.
- #[inline]
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0", reason = "use to_isize")]
- fn to_int(&self) -> Option<isize> {
- self.to_i64().and_then(|x| x.to_isize())
- }
-
- /// Converts the value of `self` to an `isize`.
- #[inline]
- fn to_isize(&self) -> Option<isize> {
- self.to_i64().and_then(|x| x.to_isize())
- }
-
- /// Converts the value of `self` to an `i8`.
- #[inline]
- fn to_i8(&self) -> Option<i8> {
- self.to_i64().and_then(|x| x.to_i8())
- }
-
- /// Converts the value of `self` to an `i16`.
- #[inline]
- fn to_i16(&self) -> Option<i16> {
- self.to_i64().and_then(|x| x.to_i16())
- }
-
- /// Converts the value of `self` to an `i32`.
- #[inline]
- fn to_i32(&self) -> Option<i32> {
- self.to_i64().and_then(|x| x.to_i32())
- }
-
- /// Converts the value of `self` to an `i64`.
- fn to_i64(&self) -> Option<i64>;
-
- /// Converts the value of `self` to an `usize`.
- #[inline]
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0", reason = "use to_usize")]
- fn to_uint(&self) -> Option<usize> {
- self.to_u64().and_then(|x| x.to_usize())
- }
-
- /// Converts the value of `self` to a `usize`.
- #[inline]
- fn to_usize(&self) -> Option<usize> {
- self.to_u64().and_then(|x| x.to_usize())
- }
-
- /// Converts the value of `self` to an `u8`.
- #[inline]
- fn to_u8(&self) -> Option<u8> {
- self.to_u64().and_then(|x| x.to_u8())
- }
-
- /// Converts the value of `self` to an `u16`.
- #[inline]
- fn to_u16(&self) -> Option<u16> {
- self.to_u64().and_then(|x| x.to_u16())
- }
-
- /// Converts the value of `self` to an `u32`.
- #[inline]
- fn to_u32(&self) -> Option<u32> {
- self.to_u64().and_then(|x| x.to_u32())
- }
-
- /// Converts the value of `self` to an `u64`.
- #[inline]
- fn to_u64(&self) -> Option<u64>;
-
- /// Converts the value of `self` to an `f32`.
- #[inline]
- fn to_f32(&self) -> Option<f32> {
- self.to_f64().and_then(|x| x.to_f32())
- }
-
- /// Converts the value of `self` to an `f64`.
- #[inline]
- fn to_f64(&self) -> Option<f64> {
- self.to_i64().and_then(|x| x.to_f64())
- }
-}
-
-macro_rules! impl_to_primitive_int_to_int {
- ($SrcT:ty, $DstT:ty, $slf:expr) => (
- {
- if size_of::<$SrcT>() <= size_of::<$DstT>() {
- Some($slf as $DstT)
- } else {
- let n = $slf as i64;
- let min_value: $DstT = Int::min_value();
- let max_value: $DstT = Int::max_value();
- if min_value as i64 <= n && n <= max_value as i64 {
- Some($slf as $DstT)
- } else {
- None
- }
- }
- }
- )
-}
-
-macro_rules! impl_to_primitive_int_to_uint {
- ($SrcT:ty, $DstT:ty, $slf:expr) => (
- {
- let zero: $SrcT = Int::zero();
- let max_value: $DstT = Int::max_value();
- if zero <= $slf && $slf as u64 <= max_value as u64 {
- Some($slf as $DstT)
- } else {
- None
- }
- }
- )
-}
-
-macro_rules! impl_to_primitive_int {
- ($T:ty) => (
- impl ToPrimitive for $T {
- #[inline]
- fn to_int(&self) -> Option<isize> { impl_to_primitive_int_to_int!($T, isize, *self) }
- #[inline]
- fn to_isize(&self) -> Option<isize> { impl_to_primitive_int_to_int!($T, isize, *self) }
- #[inline]
- fn to_i8(&self) -> Option<i8> { impl_to_primitive_int_to_int!($T, i8, *self) }
- #[inline]
- fn to_i16(&self) -> Option<i16> { impl_to_primitive_int_to_int!($T, i16, *self) }
- #[inline]
- fn to_i32(&self) -> Option<i32> { impl_to_primitive_int_to_int!($T, i32, *self) }
- #[inline]
- fn to_i64(&self) -> Option<i64> { impl_to_primitive_int_to_int!($T, i64, *self) }
-
- #[inline]
- fn to_uint(&self) -> Option<usize> { impl_to_primitive_int_to_uint!($T, usize, *self) }
- #[inline]
- fn to_usize(&self) -> Option<usize> { impl_to_primitive_int_to_uint!($T, usize, *self) }
- #[inline]
- fn to_u8(&self) -> Option<u8> { impl_to_primitive_int_to_uint!($T, u8, *self) }
- #[inline]
- fn to_u16(&self) -> Option<u16> { impl_to_primitive_int_to_uint!($T, u16, *self) }
- #[inline]
- fn to_u32(&self) -> Option<u32> { impl_to_primitive_int_to_uint!($T, u32, *self) }
- #[inline]
- fn to_u64(&self) -> Option<u64> { impl_to_primitive_int_to_uint!($T, u64, *self) }
-
- #[inline]
- fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
- #[inline]
- fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
- }
- )
-}
-
-impl_to_primitive_int! { isize }
-impl_to_primitive_int! { i8 }
-impl_to_primitive_int! { i16 }
-impl_to_primitive_int! { i32 }
-impl_to_primitive_int! { i64 }
-
-macro_rules! impl_to_primitive_uint_to_int {
- ($DstT:ty, $slf:expr) => (
- {
- let max_value: $DstT = Int::max_value();
- if $slf as u64 <= max_value as u64 {
- Some($slf as $DstT)
- } else {
- None
- }
- }
- )
-}
-
-macro_rules! impl_to_primitive_uint_to_uint {
- ($SrcT:ty, $DstT:ty, $slf:expr) => (
- {
- if size_of::<$SrcT>() <= size_of::<$DstT>() {
- Some($slf as $DstT)
- } else {
- let zero: $SrcT = Int::zero();
- let max_value: $DstT = Int::max_value();
- if zero <= $slf && $slf as u64 <= max_value as u64 {
- Some($slf as $DstT)
- } else {
- None
- }
- }
- }
- )
-}
-
-macro_rules! impl_to_primitive_uint {
- ($T:ty) => (
- impl ToPrimitive for $T {
- #[inline]
- fn to_int(&self) -> Option<isize> { impl_to_primitive_uint_to_int!(isize, *self) }
- #[inline]
- fn to_isize(&self) -> Option<isize> { impl_to_primitive_uint_to_int!(isize, *self) }
- #[inline]
- fn to_i8(&self) -> Option<i8> { impl_to_primitive_uint_to_int!(i8, *self) }
- #[inline]
- fn to_i16(&self) -> Option<i16> { impl_to_primitive_uint_to_int!(i16, *self) }
- #[inline]
- fn to_i32(&self) -> Option<i32> { impl_to_primitive_uint_to_int!(i32, *self) }
- #[inline]
- fn to_i64(&self) -> Option<i64> { impl_to_primitive_uint_to_int!(i64, *self) }
-
- #[inline]
- fn to_uint(&self) -> Option<usize> { impl_to_primitive_uint_to_uint!($T, usize, *self) }
- #[inline]
- fn to_usize(&self) -> Option<usize> {
- impl_to_primitive_uint_to_uint!($T, usize, *self)
- }
- #[inline]
- fn to_u8(&self) -> Option<u8> { impl_to_primitive_uint_to_uint!($T, u8, *self) }
- #[inline]
- fn to_u16(&self) -> Option<u16> { impl_to_primitive_uint_to_uint!($T, u16, *self) }
- #[inline]
- fn to_u32(&self) -> Option<u32> { impl_to_primitive_uint_to_uint!($T, u32, *self) }
- #[inline]
- fn to_u64(&self) -> Option<u64> { impl_to_primitive_uint_to_uint!($T, u64, *self) }
-
- #[inline]
- fn to_f32(&self) -> Option<f32> { Some(*self as f32) }
- #[inline]
- fn to_f64(&self) -> Option<f64> { Some(*self as f64) }
- }
- )
-}
-
-impl_to_primitive_uint! { usize }
-impl_to_primitive_uint! { u8 }
-impl_to_primitive_uint! { u16 }
-impl_to_primitive_uint! { u32 }
-impl_to_primitive_uint! { u64 }
-
-macro_rules! impl_to_primitive_float_to_float {
- ($SrcT:ident, $DstT:ident, $slf:expr) => (
- if size_of::<$SrcT>() <= size_of::<$DstT>() {
- Some($slf as $DstT)
- } else {
- let n = $slf as f64;
- let max_value: $SrcT = ::$SrcT::MAX;
- if -max_value as f64 <= n && n <= max_value as f64 {
- Some($slf as $DstT)
- } else {
- None
- }
- }
- )
-}
-
-macro_rules! impl_to_primitive_float {
- ($T:ident) => (
- impl ToPrimitive for $T {
- #[inline]
- fn to_int(&self) -> Option<isize> { Some(*self as isize) }
- #[inline]
- fn to_isize(&self) -> Option<isize> { Some(*self as isize) }
- #[inline]
- fn to_i8(&self) -> Option<i8> { Some(*self as i8) }
- #[inline]
- fn to_i16(&self) -> Option<i16> { Some(*self as i16) }
- #[inline]
- fn to_i32(&self) -> Option<i32> { Some(*self as i32) }
- #[inline]
- fn to_i64(&self) -> Option<i64> { Some(*self as i64) }
-
- #[inline]
- fn to_uint(&self) -> Option<usize> { Some(*self as usize) }
- #[inline]
- fn to_usize(&self) -> Option<usize> { Some(*self as usize) }
- #[inline]
- fn to_u8(&self) -> Option<u8> { Some(*self as u8) }
- #[inline]
- fn to_u16(&self) -> Option<u16> { Some(*self as u16) }
- #[inline]
- fn to_u32(&self) -> Option<u32> { Some(*self as u32) }
- #[inline]
- fn to_u64(&self) -> Option<u64> { Some(*self as u64) }
-
- #[inline]
- fn to_f32(&self) -> Option<f32> { impl_to_primitive_float_to_float!($T, f32, *self) }
- #[inline]
- fn to_f64(&self) -> Option<f64> { impl_to_primitive_float_to_float!($T, f64, *self) }
- }
- )
-}
-
-impl_to_primitive_float! { f32 }
-impl_to_primitive_float! { f64 }
-
-/// A generic trait for converting a number to a value.
-#[unstable(feature = "core", reason = "trait is likely to be removed")]
-pub trait FromPrimitive : ::marker::Sized {
- /// Converts an `isize` to return an optional value of this type. If the
- /// value cannot be represented by this value, the `None` is returned.
- #[inline]
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0", reason = "use from_isize")]
- fn from_int(n: isize) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
- }
-
- /// Converts an `isize` to return an optional value of this type. If the
- /// value cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_isize(n: isize) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
- }
-
- /// Converts an `i8` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_i8(n: i8) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
- }
-
- /// Converts an `i16` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_i16(n: i16) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
- }
-
- /// Converts an `i32` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_i32(n: i32) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
- }
-
- /// Converts an `i64` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- fn from_i64(n: i64) -> Option<Self>;
-
- /// Converts an `usize` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0", reason = "use from_usize")]
- fn from_uint(n: usize) -> Option<Self> {
- FromPrimitive::from_u64(n as u64)
- }
-
- /// Converts a `usize` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_usize(n: usize) -> Option<Self> {
- FromPrimitive::from_u64(n as u64)
- }
-
- /// Converts an `u8` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_u8(n: u8) -> Option<Self> {
- FromPrimitive::from_u64(n as u64)
- }
-
- /// Converts an `u16` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_u16(n: u16) -> Option<Self> {
- FromPrimitive::from_u64(n as u64)
- }
-
- /// Converts an `u32` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_u32(n: u32) -> Option<Self> {
- FromPrimitive::from_u64(n as u64)
- }
-
- /// Converts an `u64` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- fn from_u64(n: u64) -> Option<Self>;
-
- /// Converts a `f32` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_f32(n: f32) -> Option<Self> {
- FromPrimitive::from_f64(n as f64)
- }
-
- /// Converts a `f64` to return an optional value of this type. If the
- /// type cannot be represented by this value, the `None` is returned.
- #[inline]
- fn from_f64(n: f64) -> Option<Self> {
- FromPrimitive::from_i64(n as i64)
- }
-}
-
-/// A utility function that just calls `FromPrimitive::from_int`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-#[deprecated(since = "1.0.0", reason = "use from_isize")]
-pub fn from_int<A: FromPrimitive>(n: isize) -> Option<A> {
- FromPrimitive::from_isize(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_isize`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_isize<A: FromPrimitive>(n: isize) -> Option<A> {
- FromPrimitive::from_isize(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_i8`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_i8<A: FromPrimitive>(n: i8) -> Option<A> {
- FromPrimitive::from_i8(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_i16`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_i16<A: FromPrimitive>(n: i16) -> Option<A> {
- FromPrimitive::from_i16(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_i32`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_i32<A: FromPrimitive>(n: i32) -> Option<A> {
- FromPrimitive::from_i32(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_i64`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_i64<A: FromPrimitive>(n: i64) -> Option<A> {
- FromPrimitive::from_i64(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_uint`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-#[deprecated(since = "1.0.0", reason = "use from_uint")]
-pub fn from_uint<A: FromPrimitive>(n: usize) -> Option<A> {
- FromPrimitive::from_usize(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_usize`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_usize<A: FromPrimitive>(n: usize) -> Option<A> {
- FromPrimitive::from_usize(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_u8`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_u8<A: FromPrimitive>(n: u8) -> Option<A> {
- FromPrimitive::from_u8(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_u16`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_u16<A: FromPrimitive>(n: u16) -> Option<A> {
- FromPrimitive::from_u16(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_u32`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_u32<A: FromPrimitive>(n: u32) -> Option<A> {
- FromPrimitive::from_u32(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_u64`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_u64<A: FromPrimitive>(n: u64) -> Option<A> {
- FromPrimitive::from_u64(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_f32`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_f32<A: FromPrimitive>(n: f32) -> Option<A> {
- FromPrimitive::from_f32(n)
-}
-
-/// A utility function that just calls `FromPrimitive::from_f64`.
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn from_f64<A: FromPrimitive>(n: f64) -> Option<A> {
- FromPrimitive::from_f64(n)
-}
-
-macro_rules! impl_from_primitive {
- ($T:ty, $to_ty:ident) => (
- #[allow(deprecated)]
- impl FromPrimitive for $T {
- #[inline] fn from_int(n: isize) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_i8(n: i8) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_i16(n: i16) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_i32(n: i32) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_i64(n: i64) -> Option<$T> { n.$to_ty() }
-
- #[inline] fn from_uint(n: usize) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_u8(n: u8) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_u16(n: u16) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_u32(n: u32) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_u64(n: u64) -> Option<$T> { n.$to_ty() }
-
- #[inline] fn from_f32(n: f32) -> Option<$T> { n.$to_ty() }
- #[inline] fn from_f64(n: f64) -> Option<$T> { n.$to_ty() }
- }
- )
-}
-
-impl_from_primitive! { isize, to_int }
-impl_from_primitive! { i8, to_i8 }
-impl_from_primitive! { i16, to_i16 }
-impl_from_primitive! { i32, to_i32 }
-impl_from_primitive! { i64, to_i64 }
-impl_from_primitive! { usize, to_uint }
-impl_from_primitive! { u8, to_u8 }
-impl_from_primitive! { u16, to_u16 }
-impl_from_primitive! { u32, to_u32 }
-impl_from_primitive! { u64, to_u64 }
-impl_from_primitive! { f32, to_f32 }
-impl_from_primitive! { f64, to_f64 }
-
-/// Casts from one machine scalar to another.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(core)]
-/// use std::num;
-///
-/// let twenty: f32 = num::cast(0x14).unwrap();
-/// assert_eq!(twenty, 20f32);
-/// ```
-///
-#[inline]
-#[unstable(feature = "core", reason = "likely to be removed")]
-pub fn cast<T: NumCast,U: NumCast>(n: T) -> Option<U> {
- NumCast::from(n)
-}
-
-/// An interface for casting between machine scalars.
-#[unstable(feature = "core", reason = "trait is likely to be removed")]
-pub trait NumCast: ToPrimitive {
- /// Creates a number from another value that can be converted into a primitive via the
- /// `ToPrimitive` trait.
- fn from<T: ToPrimitive>(n: T) -> Option<Self>;
-}
-
-macro_rules! impl_num_cast {
- ($T:ty, $conv:ident) => (
- impl NumCast for $T {
- #[inline]
- #[allow(deprecated)]
- fn from<N: ToPrimitive>(n: N) -> Option<$T> {
- // `$conv` could be generated using `concat_idents!`, but that
- // macro seems to be broken at the moment
- n.$conv()
- }
- }
- )
-}
-
-impl_num_cast! { u8, to_u8 }
-impl_num_cast! { u16, to_u16 }
-impl_num_cast! { u32, to_u32 }
-impl_num_cast! { u64, to_u64 }
-impl_num_cast! { usize, to_uint }
-impl_num_cast! { i8, to_i8 }
-impl_num_cast! { i16, to_i16 }
-impl_num_cast! { i32, to_i32 }
-impl_num_cast! { i64, to_i64 }
-impl_num_cast! { isize, to_int }
-impl_num_cast! { f32, to_f32 }
-impl_num_cast! { f64, to_f64 }
-
/// Used for representing the classification of floating point numbers
#[derive(Copy, Clone, PartialEq, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
}
/// A built-in floating point number.
-// FIXME(#5527): In a future version of Rust, many of these functions will
-// become constants.
-//
-// FIXME(#8888): Several of these functions have a parameter named
-// `unused_self`. Removing it requires #8888 to be fixed.
-#[unstable(feature = "core",
- reason = "distribution of methods between core/std is unclear")]
#[doc(hidden)]
-pub trait Float
- : Copy + Clone
- + NumCast
- + PartialOrd
- + PartialEq
- + Neg<Output=Self>
- + Add<Output=Self>
- + Sub<Output=Self>
- + Mul<Output=Self>
- + Div<Output=Self>
- + Rem<Output=Self>
-{
+pub trait Float {
/// Returns the NaN value.
fn nan() -> Self;
/// Returns the infinite value.
fn infinity() -> Self;
/// Returns the negative infinite value.
fn neg_infinity() -> Self;
- /// Returns the `0` value.
- fn zero() -> Self;
/// Returns -0.0.
fn neg_zero() -> Self;
- /// Returns the `1` value.
+ /// Returns 0.0.
+ fn zero() -> Self;
+ /// Returns 1.0.
fn one() -> Self;
-
- // FIXME (#5527): These should be associated constants
-
- /// Returns the number of binary digits of mantissa that this type supports.
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MANTISSA_DIGITS` or \
- `std::f64::MANTISSA_DIGITS` as appropriate")]
- fn mantissa_digits(unused_self: Option<Self>) -> usize;
- /// Returns the number of base-10 digits of precision that this type supports.
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")]
- fn digits(unused_self: Option<Self>) -> usize;
- /// Returns the difference between 1.0 and the smallest representable number larger than 1.0.
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")]
- fn epsilon() -> Self;
- /// Returns the minimum binary exponent that this type can represent.
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")]
- fn min_exp(unused_self: Option<Self>) -> isize;
- /// Returns the maximum binary exponent that this type can represent.
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")]
- fn max_exp(unused_self: Option<Self>) -> isize;
- /// Returns the minimum base-10 exponent that this type can represent.
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")]
- fn min_10_exp(unused_self: Option<Self>) -> isize;
- /// Returns the maximum base-10 exponent that this type can represent.
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")]
- fn max_10_exp(unused_self: Option<Self>) -> isize;
- /// Returns the smallest finite value that this type can represent.
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MIN` or `std::f64::MIN` as appropriate")]
- fn min_value() -> Self;
- /// Returns the smallest normalized positive number that this type can represent.
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MIN_POSITIVE` or \
- `std::f64::MIN_POSITIVE` as appropriate")]
- fn min_pos_value(unused_self: Option<Self>) -> Self;
- /// Returns the largest finite value that this type can represent.
- #[unstable(feature = "core")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MAX` or `std::f64::MAX` as appropriate")]
- fn max_value() -> Self;
+ /// Parses the string `s` with the radix `r` as a float.
+ fn from_str_radix(s: &str, r: u32) -> Result<Self, ParseFloatError>;
/// Returns true if this value is NaN and false otherwise.
fn is_nan(self) -> bool;
/// Returns the mantissa, exponent and sign as integers, respectively.
fn integer_decode(self) -> (u64, i16, i8);
- /// Returns the largest integer less than or equal to a number.
+ /// Return the largest integer less than or equal to a number.
fn floor(self) -> Self;
- /// Returns the smallest integer greater than or equal to a number.
+ /// Return the smallest integer greater than or equal to a number.
fn ceil(self) -> Self;
- /// Returns the nearest integer to a number. Round half-way cases away from
+ /// Return the nearest integer to a number. Round half-way cases away from
/// `0.0`.
fn round(self) -> Self;
- /// Returns the integer part of a number.
+ /// Return the integer part of a number.
fn trunc(self) -> Self;
- /// Returns the fractional part of a number.
+ /// Return the fractional part of a number.
fn fract(self) -> Self;
/// Computes the absolute value of `self`. Returns `Float::nan()` if the
/// error. This produces a more accurate result with better performance than
/// a separate multiplication operation followed by an add.
fn mul_add(self, a: Self, b: Self) -> Self;
- /// Takes the reciprocal (inverse) of a number, `1/x`.
+ /// Take the reciprocal (inverse) of a number, `1/x`.
fn recip(self) -> Self;
- /// Raises a number to an integer power.
+ /// Raise a number to an integer power.
///
/// Using this function is generally faster than using `powf`
fn powi(self, n: i32) -> Self;
- /// Raises a number to a floating point power.
+ /// Raise a number to a floating point power.
fn powf(self, n: Self) -> Self;
- /// Takes the square root of a number.
+ /// Take the square root of a number.
///
/// Returns NaN if `self` is a negative number.
fn sqrt(self) -> Self;
- /// Takes the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
+ /// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
fn rsqrt(self) -> Self;
/// Returns `e^(self)`, (the exponential function).
/// Returns the base 10 logarithm of the number.
fn log10(self) -> Self;
- /// Converts radians to degrees.
+ /// Convert radians to degrees.
fn to_degrees(self) -> Self;
- /// Converts degrees to radians.
+ /// Convert degrees to radians.
fn to_radians(self) -> Self;
}
-/// A generic trait for converting a string with a radix (base) to a value
-#[unstable(feature = "core", reason = "needs reevaluation")]
-#[deprecated(since = "1.0.0",
- reason = "moved to inherent methods; use e.g. i32::from_str_radix")]
-pub trait FromStrRadix {
- #[unstable(feature = "core", reason = "needs reevaluation")]
- #[deprecated(since = "1.0.0", reason = "moved to inherent methods")]
- type Err;
-
- #[unstable(feature = "core", reason = "needs reevaluation")]
- #[deprecated(since = "1.0.0",
- reason = "moved to inherent methods; use e.g. i32::from_str_radix")]
- #[allow(deprecated)]
- fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::Err>;
-}
-
-/// A utility function that just calls `FromStrRadix::from_str_radix`.
-#[unstable(feature = "core", reason = "needs reevaluation")]
-#[deprecated(since = "1.0.0", reason = "use e.g. i32::from_str_radix")]
-#[allow(deprecated)]
-pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: u32)
- -> Result<T, T::Err> {
- FromStrRadix::from_str_radix(str, radix)
-}
-
-macro_rules! from_str_radix_float_impl {
- ($T:ty) => {
+macro_rules! from_str_float_impl {
+ ($T:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for $T {
type Err = ParseFloatError;
///
/// # Return value
///
- /// `Err(ParseFloatError)` if the string did not represent a valid number.
- /// Otherwise, `Ok(n)` where `n` is the floating-point number represented by `src`.
+ /// `Err(ParseFloatError)` if the string did not represent a valid
+ /// number. Otherwise, `Ok(n)` where `n` is the floating-point
+ /// number represented by `src`.
#[inline]
#[allow(deprecated)]
fn from_str(src: &str) -> Result<$T, ParseFloatError> {
- from_str_radix(src, 10)
- }
- }
-
- #[stable(feature = "rust1", since = "1.0.0")]
- #[allow(deprecated)]
- impl FromStrRadix for $T {
- type Err = ParseFloatError;
-
- /// Converts a string in a given base to a float.
- ///
- /// Due to possible conflicts, this function does **not** accept
- /// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
- /// does it recognize exponents of any kind.
- ///
- /// Leading and trailing whitespace represent an error.
- ///
- /// # Arguments
- ///
- /// * src - A string
- /// * radix - The base to use. Must lie in the range [2 .. 36]
- ///
- /// # Return value
- ///
- /// `Err(ParseFloatError)` if the string did not represent a valid number.
- /// Otherwise, `Ok(n)` where `n` is the floating-point number represented by `src`.
- fn from_str_radix(src: &str, radix: u32)
- -> Result<$T, ParseFloatError> {
- use self::FloatErrorKind::*;
- use self::ParseFloatError as PFE;
- assert!(radix >= 2 && radix <= 36,
- "from_str_radix_float: must lie in the range `[2, 36]` - found {}",
- radix);
-
- // 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)
+ $T::from_str_radix(src, 10)
}
}
}
}
-from_str_radix_float_impl! { f32 }
-from_str_radix_float_impl! { f64 }
+from_str_float_impl!(f32);
+from_str_float_impl!(f64);
macro_rules! from_str_radix_int_impl {
- ($T:ty) => {
+ ($($T:ident)*) => {$(
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
impl FromStr for $T {
type Err = ParseIntError;
- #[inline]
fn from_str(src: &str) -> Result<$T, ParseIntError> {
from_str_radix(src, 10)
}
}
+ )*}
+}
+from_str_radix_int_impl! { isize i8 i16 i32 i64 usize u8 u16 u32 u64 }
- #[stable(feature = "rust1", since = "1.0.0")]
- #[allow(deprecated)]
- impl FromStrRadix for $T {
- type Err = ParseIntError;
- fn from_str_radix(src: &str, radix: u32)
- -> Result<$T, ParseIntError> {
- use self::IntErrorKind::*;
- use self::ParseIntError as PIE;
- assert!(radix >= 2 && radix <= 36,
- "from_str_radix_int: must lie in the range `[2, 36]` - found {}",
- radix);
-
- let is_signed_ty = (0 as $T) > Int::min_value();
-
- match src.slice_shift_char() {
- Some(('-', "")) => Err(PIE { kind: Empty }),
- Some(('-', src)) if is_signed_ty => {
- // The number is negative
- let mut result = 0;
- for c in src.chars() {
- let x = match c.to_digit(radix) {
- Some(x) => x,
- None => return Err(PIE { kind: InvalidDigit }),
- };
- result = match result.checked_mul(radix as $T) {
- Some(result) => result,
- None => return Err(PIE { kind: Underflow }),
- };
- result = match result.checked_sub(x as $T) {
- Some(result) => result,
- None => return Err(PIE { kind: Underflow }),
- };
- }
- Ok(result)
- },
- Some((_, _)) => {
- // The number is signed
- let mut result = 0;
- for c in src.chars() {
- let x = match c.to_digit(radix) {
- Some(x) => x,
- None => return Err(PIE { kind: InvalidDigit }),
- };
- result = match result.checked_mul(radix as $T) {
- Some(result) => result,
- None => return Err(PIE { kind: Overflow }),
- };
- result = match result.checked_add(x as $T) {
- Some(result) => result,
- None => return Err(PIE { kind: Overflow }),
- };
- }
- Ok(result)
- },
- None => Err(ParseIntError { kind: Empty }),
- }
+#[doc(hidden)]
+trait FromStrRadixHelper: PartialOrd + Copy {
+ fn min_value() -> Self;
+ fn from_u32(u: u32) -> Self;
+ fn checked_mul(&self, other: u32) -> Option<Self>;
+ fn checked_sub(&self, other: u32) -> Option<Self>;
+ fn checked_add(&self, other: u32) -> Option<Self>;
+}
+
+macro_rules! doit {
+ ($($t:ident)*) => ($(impl FromStrRadixHelper for $t {
+ fn min_value() -> Self { <$t>::min_value() }
+ fn from_u32(u: u32) -> Self { u as $t }
+ fn checked_mul(&self, other: u32) -> Option<Self> {
+ <$t>::checked_mul(*self, other as $t)
+ }
+ fn checked_sub(&self, other: u32) -> Option<Self> {
+ <$t>::checked_sub(*self, other as $t)
+ }
+ fn checked_add(&self, other: u32) -> Option<Self> {
+ <$t>::checked_add(*self, other as $t)
+ }
+ })*)
+}
+doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
+
+fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
+ -> Result<T, ParseIntError> {
+ use self::IntErrorKind::*;
+ use self::ParseIntError as PIE;
+ assert!(radix >= 2 && radix <= 36,
+ "from_str_radix_int: must lie in the range `[2, 36]` - found {}",
+ radix);
+
+ let is_signed_ty = T::from_u32(0) > T::min_value();
+
+ match src.slice_shift_char() {
+ Some(('-', "")) => Err(PIE { kind: Empty }),
+ Some(('-', src)) if is_signed_ty => {
+ // The number is negative
+ let mut result = T::from_u32(0);
+ for c in src.chars() {
+ let x = match c.to_digit(radix) {
+ Some(x) => x,
+ None => return Err(PIE { kind: InvalidDigit }),
+ };
+ result = match result.checked_mul(radix) {
+ Some(result) => result,
+ None => return Err(PIE { kind: Underflow }),
+ };
+ result = match result.checked_sub(x) {
+ Some(result) => result,
+ None => return Err(PIE { kind: Underflow }),
+ };
}
- }
+ Ok(result)
+ },
+ Some((_, _)) => {
+ // The number is signed
+ let mut result = T::from_u32(0);
+ for c in src.chars() {
+ let x = match c.to_digit(radix) {
+ Some(x) => x,
+ None => return Err(PIE { kind: InvalidDigit }),
+ };
+ result = match result.checked_mul(radix) {
+ Some(result) => result,
+ None => return Err(PIE { kind: Overflow }),
+ };
+ result = match result.checked_add(x) {
+ Some(result) => result,
+ None => return Err(PIE { kind: Overflow }),
+ };
+ }
+ Ok(result)
+ },
+ None => Err(ParseIntError { kind: Empty }),
}
}
-from_str_radix_int_impl! { isize }
-from_str_radix_int_impl! { i8 }
-from_str_radix_int_impl! { i16 }
-from_str_radix_int_impl! { i32 }
-from_str_radix_int_impl! { i64 }
-from_str_radix_int_impl! { usize }
-from_str_radix_int_impl! { u8 }
-from_str_radix_int_impl! { u16 }
-from_str_radix_int_impl! { u32 }
-from_str_radix_int_impl! { u64 }
/// An error which can be returned when parsing an integer.
#[derive(Debug, Clone, PartialEq)]
/// An error which can be returned when parsing a float.
#[derive(Debug, Clone, PartialEq)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct ParseFloatError { kind: FloatErrorKind }
+pub struct ParseFloatError { pub kind: FloatErrorKind }
#[derive(Debug, Clone, PartialEq)]
-enum FloatErrorKind {
+pub enum FloatErrorKind {
Empty,
Invalid,
}
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};
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);
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>;
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
/////////////////////////////////////////////////////////////////////////
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
/////////////////////////////////////////////////////////////////////////////
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;
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`).
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
/////////////////////////////////////////////////////////////////////////
// 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() }
}
}
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;
// 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")]
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};
}
}
-/// 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)]
#[test]
fn test_user_defined_eq() {
- use core::num::SignedInt;
-
// Our type.
struct SketchyNum {
num : isize
use core::iter::*;
use core::iter::order::*;
use core::iter::MinMaxResult::*;
-use core::num::SignedInt;
use core::usize;
use core::cmp;
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];
// 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)]
#![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;
// 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;
#[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);
}
#[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!(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!(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("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!($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!($T::from_str_radix("Z", 35).ok(), None::<$T>);
+ assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
}
#[test]
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;
/// 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);
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));
}
// 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};
#[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);
}
}
#![deny(missing_docs)]
#![feature(staged_api)]
-#![feature(str_words)]
#![feature(str_char)]
#![cfg_attr(test, feature(rustc_private))]
// 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(' ');
}
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;
//! 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
//! 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};
// 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};
}
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
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
#[cfg(test)]
mod tests {
- use std::num::Int;
use std::prelude::v1::*;
use distributions::{Sample, IndependentSample};
use super::Range as Range;
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 {
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.
use core::iter::{order, repeat};
use super::{ReseedingRng, ReseedWithDefault};
- use std::default::Default;
use {SeedableRng, Rng};
struct Counter {
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,
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: {}",
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 {
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 {
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##"
#![feature(staged_api)]
#![feature(std_misc)]
#![feature(path_ext)]
-#![feature(str_words)]
#![feature(str_char)]
#![feature(into_cow)]
#![feature(slice_patterns)]
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;
pub mod ppaux;
pub mod nodemap;
pub mod lev_distance;
+ pub mod num;
}
pub mod lib {
--- /dev/null
+// 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
+ }
+ }
+ }
+}
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,
-
- tag_tree = 0x51,
-
- 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,
+enum_from_u32! {
+ #[derive(Copy, Clone, PartialEq)]
+ #[repr(usize)]
+ pub enum astencode_tag { // Reserves 0x50 -- 0x6f
+ tag_ast = 0x50,
+
+ tag_tree = 0x51,
+
+ 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,
+ }
}
pub const tag_item_trait_item_sort: usize = 0x70;
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
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;
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
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
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
});
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;
+ }
}
};
use std::cell::Cell;
use std::io::SeekFrom;
use std::io::prelude::*;
-use std::num::FromPrimitive;
use std::rc::Rc;
use std::fmt::Debug;
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(
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;
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};
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.
$( $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 {
}
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 => "???"
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};
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;
-> bool {
match v {
Some(s) => {
- for s in s.words() {
+ for s in s.split_whitespace() {
slot.push(s.to_string());
}
true
-> 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
},
--- /dev/null
+// 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)
+ }
+}
//! 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;
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).
// 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 }
+ for file in archive.iter() {
+ let filename = match file.name() {
+ Some(s) => s,
+ None => continue,
+ };
if filename.contains(".SYMDEF") { continue }
+ if skip(filename) { continue }
- let filename = format!("r-{}-{}", name, filename);
- // LLDB (as mentioned in back::link) crashes on filenames of exactly
- // 16 bytes in length. If we're including an object file with
- // exactly 16-bytes of characters, give it some prefix so that it's
- // not 16 bytes.
- let filename = if filename.len() == 16 {
- format!("lldb-fix-{}", filename)
- } else {
- filename
- };
- let new_filename = self.work_dir.path().join(&filename[..]);
- try!(fs::rename(&file, &new_filename));
- self.members.push(PathBuf::from(filename));
+ // An archive can contain files of the same name multiple times, so
+ // we need to be sure to not have them overwrite one another when we
+ // extract them. Consequently we need to find a truly unique file
+ // name for us!
+ let mut new_filename = String::new();
+ for n in 0.. {
+ let n = if n == 0 {String::new()} else {format!("-{}", n)};
+ new_filename = format!("r{}-{}-{}", n, name, filename);
+
+ // LLDB (as mentioned in back::link) crashes on filenames of
+ // exactly
+ // 16 bytes in length. If we're including an object file with
+ // exactly 16-bytes of characters, give it some prefix so
+ // that it's not 16 bytes.
+ new_filename = if new_filename.len() == 16 {
+ format!("lldb-fix-{}", new_filename)
+ } else {
+ new_filename
+ };
+
+ let present = self.members.iter().filter_map(|p| {
+ p.file_name().and_then(|f| f.to_str())
+ }).any(|s| s == new_filename);
+ if !present {
+ break
+ }
+ }
+ let dst = self.work_dir.path().join(&new_filename);
+ try!(try!(File::create(&dst)).write_all(file.data()));
+ self.members.push(PathBuf::from(new_filename));
}
+
Ok(())
}
}
extern crate syntax;
extern crate libc;
extern crate serialize;
+extern crate rustc_llvm;
#[macro_use] extern crate log;
pub mod abi;
//! 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;
/// 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.")
}
// 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 {
//! 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 {
}
}
- /// 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 }
}
}
}
}
}
}
+
+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 }
+}
#![feature(libc)]
#![feature(link_args)]
#![feature(staged_api)]
+#![feature(unsafe_destructor)]
extern crate libc;
#[macro_use] #[no_link] extern crate rustc_bitflags;
#[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;
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;
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]) {
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 => {
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), (), |_| {
}
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)
}
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),
});
pub use self::Repr::*;
-#[allow(deprecated)]
-use std::num::Int;
use std::rc::Rc;
use llvm::{ValueRef, True, IntEQ, IntNE};
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));
// 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);
)
}
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);
}
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" => {
use trans::type_::Type;
-#[allow(deprecated)]
-use std::num::Int;
use syntax::abi;
use syntax::ast;
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};
}
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>,
}
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;
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]
}
}
-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() }
}
};
// 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
#![feature(std_misc)]
#![feature(test)]
#![feature(unicode)]
-#![feature(str_words)]
#![feature(path_ext)]
#![feature(path_relative_from)]
#![feature(slice_patterns)]
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();
}
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());
}
}
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;
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",
}
}
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
}
}
/// 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
}
/// 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
}
#[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() {
}
}
-/// 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) {
($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.
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> {
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)
+ }
}
}
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};
}
// 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) {
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
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) }
}
}
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};
#[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> {
use prelude::v1::*;
-use iter::IntoIterator;
use error::Error;
use ffi::{OsStr, OsString};
use fmt;
}
fn eq(a: Option<OsString>, b: Option<&str>) {
- assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::from_str).map(|s| &*s));
+ assert_eq!(a.as_ref().map(|s| &**s), b.map(OsStr::new).map(|s| &*s));
}
#[test]
fn join_paths_unix() {
fn test_eq(input: &[&str], output: &str) -> bool {
&*join_paths(input.iter().cloned()).unwrap() ==
- OsStr::from_str(output)
+ OsStr::new(output)
}
assert!(test_eq(&[], ""));
fn join_paths_windows() {
fn test_eq(input: &[&str], output: &str) -> bool {
&*join_paths(input.iter().cloned()).unwrap() ==
- OsStr::from_str(output)
+ OsStr::new(output)
}
assert!(test_eq(&[], ""));
mod c_str;
mod os_str;
-
-// FIXME (#21670): these should be defined in the os_str module
-/// Freely convertible to an `&OsStr` slice.
-#[unstable(feature = "std_misc")]
-pub trait AsOsStr {
- /// Converts to an `&OsStr` slice.
- fn as_os_str(&self) -> &OsStr;
-}
use sys::os_str::{Buf, Slice};
use sys_common::{AsInner, IntoInner, FromInner};
-use super::AsOsStr;
/// Owned, mutable OS strings.
#[derive(Clone)]
s.as_ref()
}
- /// Coerces directly from a `&str` slice to a `&OsStr` slice.
- #[stable(feature = "rust1", since = "1.0.0")]
- #[deprecated(since = "1.0.0",
- reason = "use `OsStr::new` instead")]
- pub fn from_str(s: &str) -> &OsStr {
- unsafe { mem::transmute(Slice::from_str(s)) }
- }
-
/// Yields a `&str` slice if the `OsStr` is valid unicode.
///
/// This conversion may entail doing a check for UTF-8 validity.
fn to_owned(&self) -> OsString { self.to_os_string() }
}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
-impl<'a, T: AsOsStr + ?Sized> AsOsStr for &'a T {
- fn as_os_str(&self) -> &OsStr {
- (*self).as_os_str()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
-impl AsOsStr for OsStr {
- fn as_os_str(&self) -> &OsStr {
- self
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
-impl AsOsStr for OsString {
- fn as_os_str(&self) -> &OsStr {
- &self[..]
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
-impl AsOsStr for str {
- fn as_os_str(&self) -> &OsStr {
- unsafe { mem::transmute(Slice::from_str(self)) }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
-impl AsOsStr for String {
- fn as_os_str(&self) -> &OsStr {
- unsafe { mem::transmute(Slice::from_str(self)) }
- }
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for OsStr {
fn as_ref(&self) -> &OsStr {
/// Given a path, query the file system to get information about a file,
/// directory, etc.
///
-/// This function will traverse soft links to query information about the
+/// This function will traverse symbolic links to query information about the
/// destination file.
///
/// # Examples
fs_imp::link(src.as_ref(), dst.as_ref())
}
-/// Creates a new soft link on the filesystem.
+/// Creates a new symbolic link on the filesystem.
///
-/// The `dst` path will be a soft link pointing to the `src` path.
+/// The `dst` path will be a symbolic link pointing to the `src` path.
+/// On Windows, this will be a file symlink, not a directory symlink;
+/// for this reason, the platform-specific `std::os::unix::fs::symlink`
+/// and `std::os::windows::fs::{symlink_file, symlink_dir}` should be
+/// used instead to make the intent explicit.
///
/// # Examples
///
/// # Ok(())
/// # }
/// ```
+#[deprecated(since = "1.0.0",
+ reason = "replaced with std::os::unix::fs::symlink and \
+ std::os::windows::fs::{symlink_file, symlink_dir}")]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
fs_imp::symlink(src.as_ref(), dst.as_ref())
}
-/// Reads a soft link, returning the file that the link points to.
+/// Reads a symbolic link, returning the file that the link points to.
///
/// # Errors
///
/// This function will return an error on failure. Failure conditions include
-/// reading a file that does not exist or reading a file that is not a soft
+/// reading a file that does not exist or reading a file that is not a symbolic
/// link.
///
/// # Examples
/// Removes a directory at this path, after removing all its contents. Use
/// carefully!
///
-/// This function does **not** follow soft links and it will simply remove the
-/// soft link itself.
+/// This function does **not** follow symbolic links and it will simply remove the
+/// symbolic link itself.
///
/// # Errors
///
Error { repr: Repr::Os(code) }
}
- /// Creates a new instance of an `Error` from a particular OS error code.
- #[unstable(feature = "io", reason = "deprecated")]
- #[deprecated(since = "1.0.0", reason = "renamed to from_raw_os_error")]
- pub fn from_os_error(code: i32) -> Error {
- Error { repr: Repr::Os(code) }
- }
-
/// Returns the OS error that this error represents (if any).
///
/// If this `Error` was constructed via `last_os_error` then this function
#![feature(std_misc)]
#![feature(slice_patterns)]
#![feature(debug_builders)]
+#![feature(zero_one)]
+#![cfg_attr(test, feature(float_from_str_radix))]
#![cfg_attr(test, feature(test, rustc_private, std_misc))]
// Don't link to std. We are std.
use prelude::v1::*;
use io::{self, Error, ErrorKind};
-#[allow(deprecated)] // Int
-use num::Int;
use sys_common::net2 as net_imp;
pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
Both,
}
-#[allow(deprecated)] // Int
-fn hton<I: Int>(i: I) -> I { i.to_be() }
-#[allow(deprecated)] // Int
-fn ntoh<I: Int>(i: I) -> I { Int::from_be(i) }
+#[doc(hidden)]
+trait NetInt {
+ fn from_be(i: Self) -> Self;
+ fn to_be(&self) -> Self;
+}
+macro_rules! doit {
+ ($($t:ident)*) => ($(impl NetInt for $t {
+ fn from_be(i: Self) -> Self { <$t>::from_be(i) }
+ fn to_be(&self) -> Self { <$t>::to_be(*self) }
+ })*)
+}
+doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
+
+fn hton<I: NetInt>(i: I) -> I { i.to_be() }
+fn ntoh<I: NetInt>(i: I) -> I { I::from_be(i) }
fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
where F: FnMut(&SocketAddr) -> io::Result<T>
use prelude::v1::*;
+use core::num;
use intrinsics;
use libc::c_int;
-use num::{Float, FpCategory};
-use num::strconv;
-use num::strconv::ExponentFormat::{ExpNone, ExpDec};
-use num::strconv::SignificantDigits::{DigAll, DigMax, DigExact};
-use num::strconv::SignFormat::SignNeg;
-
-use core::num;
+use num::{FpCategory, ParseFloatError};
+use sys_common::FromInner;
-pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE};
-pub use core::f32::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP};
+pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
+pub use core::f32::{MIN_EXP, MAX_EXP, MIN_10_EXP};
pub use core::f32::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY};
pub use core::f32::{MIN, MIN_POSITIVE, MAX};
pub use core::f32::consts;
}
}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
-impl Float for f32 {
- #[inline]
- fn nan() -> f32 { num::Float::nan() }
- #[inline]
- fn infinity() -> f32 { num::Float::infinity() }
- #[inline]
- fn neg_infinity() -> f32 { num::Float::neg_infinity() }
- #[inline]
- fn zero() -> f32 { num::Float::zero() }
- #[inline]
- fn neg_zero() -> f32 { num::Float::neg_zero() }
- #[inline]
- fn one() -> f32 { num::Float::one() }
-
- #[allow(deprecated)]
- #[inline]
- fn mantissa_digits(unused_self: Option<f32>) -> usize {
- num::Float::mantissa_digits(unused_self)
- }
- #[allow(deprecated)]
- #[inline]
- fn digits(unused_self: Option<f32>) -> usize { num::Float::digits(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn epsilon() -> f32 { num::Float::epsilon() }
- #[allow(deprecated)]
- #[inline]
- fn min_exp(unused_self: Option<f32>) -> isize { num::Float::min_exp(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn max_exp(unused_self: Option<f32>) -> isize { num::Float::max_exp(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn min_10_exp(unused_self: Option<f32>) -> isize { num::Float::min_10_exp(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn max_10_exp(unused_self: Option<f32>) -> isize { num::Float::max_10_exp(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn min_value() -> f32 { num::Float::min_value() }
- #[allow(deprecated)]
- #[inline]
- fn min_pos_value(unused_self: Option<f32>) -> f32 { num::Float::min_pos_value(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn max_value() -> f32 { num::Float::max_value() }
-
- #[inline]
- fn is_nan(self) -> bool { num::Float::is_nan(self) }
- #[inline]
- fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
- #[inline]
- fn is_finite(self) -> bool { num::Float::is_finite(self) }
- #[inline]
- fn is_normal(self) -> bool { num::Float::is_normal(self) }
- #[inline]
- fn classify(self) -> FpCategory { num::Float::classify(self) }
-
- #[inline]
- fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) }
-
- #[inline]
- fn floor(self) -> f32 { num::Float::floor(self) }
- #[inline]
- fn ceil(self) -> f32 { num::Float::ceil(self) }
- #[inline]
- fn round(self) -> f32 { num::Float::round(self) }
- #[inline]
- fn trunc(self) -> f32 { num::Float::trunc(self) }
- #[inline]
- fn fract(self) -> f32 { num::Float::fract(self) }
-
- #[inline]
- fn abs(self) -> f32 { num::Float::abs(self) }
- #[inline]
- fn signum(self) -> f32 { num::Float::signum(self) }
- #[inline]
- fn is_positive(self) -> bool { num::Float::is_positive(self) }
- #[inline]
- fn is_negative(self) -> bool { num::Float::is_negative(self) }
-
- #[inline]
- fn mul_add(self, a: f32, b: f32) -> f32 { num::Float::mul_add(self, a, b) }
- #[inline]
- fn recip(self) -> f32 { num::Float::recip(self) }
-
- #[inline]
- fn powi(self, n: i32) -> f32 { num::Float::powi(self, n) }
- #[inline]
- fn powf(self, n: f32) -> f32 { num::Float::powf(self, n) }
-
- #[inline]
- fn sqrt(self) -> f32 { num::Float::sqrt(self) }
- #[inline]
- fn rsqrt(self) -> f32 { num::Float::rsqrt(self) }
-
- #[inline]
- fn exp(self) -> f32 { num::Float::exp(self) }
- #[inline]
- fn exp2(self) -> f32 { num::Float::exp2(self) }
- #[inline]
- fn ln(self) -> f32 { num::Float::ln(self) }
- #[inline]
- fn log(self, base: f32) -> f32 { num::Float::log(self, base) }
- #[inline]
- fn log2(self) -> f32 { num::Float::log2(self) }
- #[inline]
- fn log10(self) -> f32 { num::Float::log10(self) }
- #[inline]
- fn to_degrees(self) -> f32 { num::Float::to_degrees(self) }
- #[inline]
- fn to_radians(self) -> f32 { num::Float::to_radians(self) }
-
- /// Constructs a floating point number by multiplying `x` by 2 raised to the
- /// power of `exp`
- #[inline]
- fn ldexp(self, exp: isize) -> f32 {
- unsafe { cmath::ldexpf(self, exp as c_int) }
- }
-
- /// Breaks the number into a normalized fraction and a base-2 exponent,
- /// satisfying:
- ///
- /// - `self = x * pow(2, exp)`
- /// - `0.5 <= abs(x) < 1.0`
- #[inline]
- fn frexp(self) -> (f32, isize) {
- unsafe {
- let mut exp = 0;
- let x = cmath::frexpf(self, &mut exp);
- (x, exp as isize)
- }
- }
-
- /// Returns the next representable floating-point value in the direction of
- /// `other`.
- #[inline]
- fn next_after(self, other: f32) -> f32 {
- unsafe { cmath::nextafterf(self, other) }
- }
-
- #[inline]
- fn max(self, other: f32) -> f32 {
- unsafe { cmath::fmaxf(self, other) }
- }
-
- #[inline]
- fn min(self, other: f32) -> f32 {
- unsafe { cmath::fminf(self, other) }
- }
-
- #[inline]
- fn abs_sub(self, other: f32) -> f32 {
- unsafe { cmath::fdimf(self, other) }
- }
-
- #[inline]
- fn cbrt(self) -> f32 {
- unsafe { cmath::cbrtf(self) }
- }
-
- #[inline]
- fn hypot(self, other: f32) -> f32 {
- unsafe { cmath::hypotf(self, other) }
- }
-
- #[inline]
- fn sin(self) -> f32 {
- unsafe { intrinsics::sinf32(self) }
- }
-
- #[inline]
- fn cos(self) -> f32 {
- unsafe { intrinsics::cosf32(self) }
- }
-
- #[inline]
- fn tan(self) -> f32 {
- unsafe { cmath::tanf(self) }
- }
-
- #[inline]
- fn asin(self) -> f32 {
- unsafe { cmath::asinf(self) }
- }
-
- #[inline]
- fn acos(self) -> f32 {
- unsafe { cmath::acosf(self) }
- }
-
- #[inline]
- fn atan(self) -> f32 {
- unsafe { cmath::atanf(self) }
- }
-
- #[inline]
- fn atan2(self, other: f32) -> f32 {
- unsafe { cmath::atan2f(self, other) }
- }
-
- /// Simultaneously computes the sine and cosine of the number
- #[inline]
- fn sin_cos(self) -> (f32, f32) {
- (self.sin(), self.cos())
- }
-
- /// Returns the exponential of the number, minus `1`, in a way that is
- /// accurate even if the number is close to zero
- #[inline]
- fn exp_m1(self) -> f32 {
- unsafe { cmath::expm1f(self) }
- }
-
- /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more
- /// accurately than if the operations were performed separately
- #[inline]
- fn ln_1p(self) -> f32 {
- unsafe { cmath::log1pf(self) }
- }
-
- #[inline]
- fn sinh(self) -> f32 {
- unsafe { cmath::sinhf(self) }
- }
-
- #[inline]
- fn cosh(self) -> f32 {
- unsafe { cmath::coshf(self) }
- }
-
- #[inline]
- fn tanh(self) -> f32 {
- unsafe { cmath::tanhf(self) }
- }
-
- /// Inverse hyperbolic sine
- ///
- /// # Returns
- ///
- /// - on success, the inverse hyperbolic sine of `self` will be returned
- /// - `self` if `self` is `0.0`, `-0.0`, `INFINITY`, or `NEG_INFINITY`
- /// - `NAN` if `self` is `NAN`
- #[inline]
- fn asinh(self) -> f32 {
- match self {
- NEG_INFINITY => NEG_INFINITY,
- x => (x + ((x * x) + 1.0).sqrt()).ln(),
- }
- }
-
- /// Inverse hyperbolic cosine
- ///
- /// # Returns
- ///
- /// - on success, the inverse hyperbolic cosine of `self` will be returned
- /// - `INFINITY` if `self` is `INFINITY`
- /// - `NAN` if `self` is `NAN` or `self < 1.0` (including `NEG_INFINITY`)
- #[inline]
- fn acosh(self) -> f32 {
- match self {
- x if x < 1.0 => Float::nan(),
- x => (x + ((x * x) - 1.0).sqrt()).ln(),
- }
- }
-
- /// Inverse hyperbolic tangent
- ///
- /// # Returns
- ///
- /// - on success, the inverse hyperbolic tangent of `self` will be returned
- /// - `self` if `self` is `0.0` or `-0.0`
- /// - `INFINITY` if `self` is `1.0`
- /// - `NEG_INFINITY` if `self` is `-1.0`
- /// - `NAN` if the `self` is `NAN` or outside the domain of `-1.0 <= self <= 1.0`
- /// (including `INFINITY` and `NEG_INFINITY`)
- #[inline]
- fn atanh(self) -> f32 {
- 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
- }
-}
-
#[cfg(not(test))]
#[lang = "f32"]
#[stable(feature = "rust1", since = "1.0.0")]
impl f32 {
+ /// Parses a float as with a given radix
+ #[unstable(feature = "float_from_str_radix", reason = "recently moved API")]
+ pub fn from_str_radix(s: &str, radix: u32) -> Result<f32, ParseFloatError> {
+ num::Float::from_str_radix(s, radix).map_err(FromInner::from_inner)
+ }
+
/// Returns `true` if this value is `NaN` and false otherwise.
///
/// ```
#[inline]
pub fn is_sign_positive(self) -> bool { num::Float::is_positive(self) }
- #[stable(feature = "rust1", since = "1.0.0")]
- #[deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
- #[inline]
- pub fn is_positive(self) -> bool { num::Float::is_positive(self) }
-
/// Returns `true` if `self`'s sign is negative, including `-0.0`
/// and `NEG_INFINITY`.
///
#[inline]
pub fn is_sign_negative(self) -> bool { num::Float::is_negative(self) }
- #[stable(feature = "rust1", since = "1.0.0")]
- #[deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
- #[inline]
- pub fn is_negative(self) -> bool { num::Float::is_negative(self) }
-
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
/// error. This produces a more accurate result with better performance than
/// a separate multiplication operation followed by an add.
#[inline]
pub fn sqrt(self) -> f32 { num::Float::sqrt(self) }
- /// Takes the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::f32;
- ///
- /// let f = 4.0f32;
- ///
- /// let abs_difference = (f.rsqrt() - 0.5).abs();
- ///
- /// assert!(abs_difference <= f32::EPSILON);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- #[deprecated(since = "1.0.0", reason = "use self.sqrt().recip() instead")]
- #[inline]
- pub fn rsqrt(self) -> f32 { num::Float::rsqrt(self) }
-
/// Returns `e^(self)`, (the exponential function).
///
/// ```
#[inline]
pub fn acosh(self) -> f32 {
match self {
- x if x < 1.0 => Float::nan(),
+ x if x < 1.0 => ::f32::NAN,
x => (x + ((x * x) - 1.0).sqrt()).ln(),
}
}
}
}
-//
-// Section: String Conversions
-//
-
-/// Converts a float to a string
-///
-/// # Arguments
-///
-/// * num - The float value
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-#[deprecated(since = "1.0.0", reason = "use the ToString trait instead")]
-pub fn to_string(num: f32) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 10, true, SignNeg, DigAll, ExpNone, false);
- r
-}
-
-/// Converts a float to a string in hexadecimal format
-///
-/// # Arguments
-///
-/// * num - The float value
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-#[deprecated(since = "1.0.0", reason = "use format! instead")]
-pub fn to_str_hex(num: f32) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 16, true, SignNeg, DigAll, ExpNone, false);
- r
-}
-
-/// Converts a float to a string in a given radix, and a flag indicating
-/// whether it's a special value
-///
-/// # Arguments
-///
-/// * num - The float value
-/// * radix - The base to use
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-#[deprecated(since = "1.0.0", reason = "use format! instead")]
-pub fn to_str_radix_special(num: f32, rdx: u32) -> (String, bool) {
- strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false)
-}
-
-/// Converts a float to a string with exactly the number of
-/// provided significant digits
-///
-/// # Arguments
-///
-/// * num - The float value
-/// * digits - The number of significant digits
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-pub fn to_str_exact(num: f32, dig: usize) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 10, true, SignNeg, DigExact(dig), ExpNone, false);
- r
-}
-
-/// Converts a float to a string with a maximum number of
-/// significant digits
-///
-/// # Arguments
-///
-/// * num - The float value
-/// * digits - The number of significant digits
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-pub fn to_str_digits(num: f32, dig: usize) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 10, true, SignNeg, DigMax(dig), ExpNone, false);
- r
-}
-
-/// Converts a float to a string using the exponential notation with exactly the number of
-/// provided digits after the decimal point in the significand
-///
-/// # Arguments
-///
-/// * num - The float value
-/// * digits - The number of digits after the decimal point
-/// * upper - Use `E` instead of `e` for the exponent sign
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-pub fn to_str_exp_exact(num: f32, dig: usize, upper: bool) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 10, true, SignNeg, DigExact(dig), ExpDec, upper);
- r
-}
-
-/// Converts a float to a string using the exponential notation with the maximum number of
-/// digits after the decimal point in the significand
-///
-/// # Arguments
-///
-/// * num - The float value
-/// * digits - The number of digits after the decimal point
-/// * upper - Use `E` instead of `e` for the exponent sign
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-pub fn to_str_exp_digits(num: f32, dig: usize, upper: bool) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 10, true, SignNeg, DigMax(dig), ExpDec, upper);
- r
-}
-
#[cfg(test)]
mod tests {
+ use f32;
use f32::*;
use num::*;
use num::FpCategory as Fp;
#[test]
fn test_nan() {
- let nan: f32 = Float::nan();
+ let nan: f32 = f32::NAN;
assert!(nan.is_nan());
assert!(!nan.is_infinite());
assert!(!nan.is_finite());
#[test]
fn test_infinity() {
- let inf: f32 = Float::infinity();
+ let inf: f32 = f32::INFINITY;
assert!(inf.is_infinite());
assert!(!inf.is_finite());
assert!(inf.is_sign_positive());
#[test]
fn test_neg_infinity() {
- let neg_inf: f32 = Float::neg_infinity();
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert!(neg_inf.is_infinite());
assert!(!neg_inf.is_finite());
assert!(!neg_inf.is_sign_positive());
#[test]
fn test_zero() {
- let zero: f32 = Float::zero();
+ let zero: f32 = 0.0f32;
assert_eq!(0.0, zero);
assert!(!zero.is_infinite());
assert!(zero.is_finite());
#[test]
fn test_neg_zero() {
- let neg_zero: f32 = Float::neg_zero();
+ let neg_zero: f32 = -0.0;
assert_eq!(0.0, neg_zero);
assert!(!neg_zero.is_infinite());
assert!(neg_zero.is_finite());
#[test]
fn test_one() {
- let one: f32 = Float::one();
+ let one: f32 = 1.0f32;
assert_eq!(1.0, one);
assert!(!one.is_infinite());
assert!(one.is_finite());
#[test]
fn test_is_nan() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert!(nan.is_nan());
assert!(!0.0f32.is_nan());
assert!(!5.3f32.is_nan());
#[test]
fn test_is_infinite() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert!(!nan.is_infinite());
assert!(inf.is_infinite());
assert!(neg_inf.is_infinite());
#[test]
fn test_is_finite() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert!(!nan.is_finite());
assert!(!inf.is_finite());
assert!(!neg_inf.is_finite());
#[test]
fn test_is_normal() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let zero: f32 = Float::zero();
- let neg_zero: f32 = Float::neg_zero();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
+ let zero: f32 = 0.0f32;
+ let neg_zero: f32 = -0.0;
assert!(!nan.is_normal());
assert!(!inf.is_normal());
assert!(!neg_inf.is_normal());
#[test]
fn test_classify() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let zero: f32 = Float::zero();
- let neg_zero: f32 = Float::neg_zero();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
+ let zero: f32 = 0.0f32;
+ let neg_zero: f32 = -0.0;
assert_eq!(nan.classify(), Fp::Nan);
assert_eq!(inf.classify(), Fp::Infinite);
assert_eq!(neg_inf.classify(), Fp::Infinite);
#[test]
fn test_mul_add() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert_approx_eq!(12.3f32.mul_add(4.5, 6.7), 62.05);
assert_approx_eq!((-12.3f32).mul_add(-4.5, -6.7), 48.65);
assert_approx_eq!(0.0f32.mul_add(8.9, 1.2), 1.2);
#[test]
fn test_recip() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert_eq!(1.0f32.recip(), 1.0);
assert_eq!(2.0f32.recip(), 0.5);
assert_eq!((-0.4f32).recip(), -2.5);
#[test]
fn test_powi() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert_eq!(1.0f32.powi(1), 1.0);
assert_approx_eq!((-3.1f32).powi(2), 9.61);
assert_approx_eq!(5.9f32.powi(-2), 0.028727);
#[test]
fn test_powf() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert_eq!(1.0f32.powf(1.0), 1.0);
assert_approx_eq!(3.4f32.powf(4.5), 246.408218);
assert_approx_eq!(2.7f32.powf(-3.2), 0.041652);
assert_eq!(INFINITY.sqrt(), INFINITY);
}
- #[test]
- fn test_rsqrt() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- assert!(nan.rsqrt().is_nan());
- assert_eq!(inf.rsqrt(), 0.0);
- assert!(neg_inf.rsqrt().is_nan());
- assert!((-1.0f32).rsqrt().is_nan());
- assert_eq!((-0.0f32).rsqrt(), neg_inf);
- assert_eq!(0.0f32.rsqrt(), inf);
- assert_eq!(1.0f32.rsqrt(), 1.0);
- assert_eq!(4.0f32.rsqrt(), 0.5);
- }
-
#[test]
fn test_exp() {
assert_eq!(1.0, 0.0f32.exp());
assert_approx_eq!(2.718282, 1.0f32.exp());
assert_approx_eq!(148.413162, 5.0f32.exp());
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let nan: f32 = Float::nan();
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
+ let nan: f32 = f32::NAN;
assert_eq!(inf, inf.exp());
assert_eq!(0.0, neg_inf.exp());
assert!(nan.exp().is_nan());
assert_eq!(32.0, 5.0f32.exp2());
assert_eq!(1.0, 0.0f32.exp2());
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let nan: f32 = Float::nan();
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
+ let nan: f32 = f32::NAN;
assert_eq!(inf, inf.exp2());
assert_eq!(0.0, neg_inf.exp2());
assert!(nan.exp2().is_nan());
#[test]
fn test_ln() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert_approx_eq!(1.0f32.exp().ln(), 1.0);
assert!(nan.ln().is_nan());
assert_eq!(inf.ln(), inf);
#[test]
fn test_log() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert_eq!(10.0f32.log(10.0), 1.0);
assert_approx_eq!(2.3f32.log(3.5), 0.664858);
- assert_eq!(1.0f32.exp().log(1.0.exp()), 1.0);
+ assert_eq!(1.0f32.exp().log(1.0f32.exp()), 1.0);
assert!(1.0f32.log(1.0).is_nan());
assert!(1.0f32.log(-13.9).is_nan());
assert!(nan.log(2.3).is_nan());
#[test]
fn test_log2() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert_approx_eq!(10.0f32.log2(), 3.321928);
assert_approx_eq!(2.3f32.log2(), 1.201634);
assert_approx_eq!(1.0f32.exp().log2(), 1.442695);
#[test]
fn test_log10() {
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert_eq!(10.0f32.log10(), 1.0);
assert_approx_eq!(2.3f32.log10(), 0.361728);
assert_approx_eq!(1.0f32.exp().log10(), 0.434294);
#[test]
fn test_to_degrees() {
let pi: f32 = consts::PI;
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert_eq!(0.0f32.to_degrees(), 0.0);
assert_approx_eq!((-5.8f32).to_degrees(), -332.315521);
assert_eq!(pi.to_degrees(), 180.0);
#[test]
fn test_to_radians() {
let pi: f32 = consts::PI;
- let nan: f32 = Float::nan();
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
+ let nan: f32 = f32::NAN;
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
assert_eq!(0.0f32.to_radians(), 0.0);
assert_approx_eq!(154.6f32.to_radians(), 2.698279);
assert_approx_eq!((-332.31f32).to_radians(), -5.799903);
fn test_ldexp() {
// We have to use from_str until base-2 exponents
// are supported in floating-point literals
- let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
- let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
- let f3: f32 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap();
- assert_eq!(1f32.ldexp(-123), f1);
- assert_eq!(1f32.ldexp(-111), f2);
- assert_eq!(Float::ldexp(1.75f32, -12), f3);
+ let f1: f32 = f32::from_str_radix("1p-123", 16).unwrap();
+ let f2: f32 = f32::from_str_radix("1p-111", 16).unwrap();
+ let f3: f32 = f32::from_str_radix("1.Cp-12", 16).unwrap();
+ assert_eq!(f32::ldexp(1f32, -123), f1);
+ assert_eq!(f32::ldexp(1f32, -111), f2);
+ assert_eq!(f32::ldexp(1.75f32, -12), f3);
- assert_eq!(Float::ldexp(0f32, -123), 0f32);
- assert_eq!(Float::ldexp(-0f32, -123), -0f32);
+ assert_eq!(f32::ldexp(0f32, -123), 0f32);
+ assert_eq!(f32::ldexp(-0f32, -123), -0f32);
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let nan: f32 = Float::nan();
- assert_eq!(Float::ldexp(inf, -123), inf);
- assert_eq!(Float::ldexp(neg_inf, -123), neg_inf);
- assert!(Float::ldexp(nan, -123).is_nan());
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
+ let nan: f32 = f32::NAN;
+ assert_eq!(f32::ldexp(inf, -123), inf);
+ assert_eq!(f32::ldexp(neg_inf, -123), neg_inf);
+ assert!(f32::ldexp(nan, -123).is_nan());
}
#[test]
fn test_frexp() {
// We have to use from_str until base-2 exponents
// are supported in floating-point literals
- let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
- let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
- let f3: f32 = FromStrRadix::from_str_radix("1.Cp-123", 16).unwrap();
+ let f1: f32 = f32::from_str_radix("1p-123", 16).unwrap();
+ let f2: f32 = f32::from_str_radix("1p-111", 16).unwrap();
+ let f3: f32 = f32::from_str_radix("1.Cp-123", 16).unwrap();
let (x1, exp1) = f1.frexp();
let (x2, exp2) = f2.frexp();
let (x3, exp3) = f3.frexp();
assert_eq!((x1, exp1), (0.5f32, -122));
assert_eq!((x2, exp2), (0.5f32, -110));
assert_eq!((x3, exp3), (0.875f32, -122));
- assert_eq!(Float::ldexp(x1, exp1), f1);
- assert_eq!(Float::ldexp(x2, exp2), f2);
- assert_eq!(Float::ldexp(x3, exp3), f3);
+ assert_eq!(f32::ldexp(x1, exp1), f1);
+ assert_eq!(f32::ldexp(x2, exp2), f2);
+ assert_eq!(f32::ldexp(x3, exp3), f3);
assert_eq!(0f32.frexp(), (0f32, 0));
assert_eq!((-0f32).frexp(), (-0f32, 0));
#[test] #[cfg_attr(windows, ignore)] // FIXME #8755
fn test_frexp_nowin() {
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let nan: f32 = Float::nan();
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
+ let nan: f32 = f32::NAN;
assert_eq!(match inf.frexp() { (x, _) => x }, inf);
assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
assert!(match nan.frexp() { (x, _) => x.is_nan() })
assert_eq!(0.0f32.asinh(), 0.0f32);
assert_eq!((-0.0f32).asinh(), -0.0f32);
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let nan: f32 = Float::nan();
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
+ let nan: f32 = f32::NAN;
assert_eq!(inf.asinh(), inf);
assert_eq!(neg_inf.asinh(), neg_inf);
assert!(nan.asinh().is_nan());
assert_eq!(1.0f32.acosh(), 0.0f32);
assert!(0.999f32.acosh().is_nan());
- let inf: f32 = Float::infinity();
- let neg_inf: f32 = Float::neg_infinity();
- let nan: f32 = Float::nan();
+ let inf: f32 = f32::INFINITY;
+ let neg_inf: f32 = f32::NEG_INFINITY;
+ let nan: f32 = f32::NAN;
assert_eq!(inf.acosh(), inf);
assert!(neg_inf.acosh().is_nan());
assert!(nan.acosh().is_nan());
assert_eq!(0.0f32.atanh(), 0.0f32);
assert_eq!((-0.0f32).atanh(), -0.0f32);
- let inf32: f32 = Float::infinity();
- let neg_inf32: f32 = Float::neg_infinity();
+ let inf32: f32 = f32::INFINITY;
+ let neg_inf32: f32 = f32::NEG_INFINITY;
assert_eq!(1.0f32.atanh(), inf32);
assert_eq!((-1.0f32).atanh(), neg_inf32);
assert!(2f64.atanh().atanh().is_nan());
assert!((-2f64).atanh().atanh().is_nan());
- let inf64: f32 = Float::infinity();
- let neg_inf64: f32 = Float::neg_infinity();
- let nan32: f32 = Float::nan();
+ let inf64: f32 = f32::INFINITY;
+ let neg_inf64: f32 = f32::NEG_INFINITY;
+ let nan32: f32 = f32::NAN;
assert!(inf64.atanh().is_nan());
assert!(neg_inf64.atanh().is_nan());
assert!(nan32.atanh().is_nan());
let frac_pi_8: f32 = consts::FRAC_PI_8;
let frac_1_pi: f32 = consts::FRAC_1_PI;
let frac_2_pi: f32 = consts::FRAC_2_PI;
- let frac_2_sqrtpi: f32 = consts::FRAC_2_SQRTPI;
- let sqrt2: f32 = consts::SQRT2;
- let frac_1_sqrt2: f32 = consts::FRAC_1_SQRT2;
+ let frac_2_sqrtpi: f32 = consts::FRAC_2_SQRT_PI;
+ let sqrt2: f32 = consts::SQRT_2;
+ let frac_1_sqrt2: f32 = consts::FRAC_1_SQRT_2;
let e: f32 = consts::E;
let log2_e: f32 = consts::LOG2_E;
let log10_e: f32 = consts::LOG10_E;
use prelude::v1::*;
+use core::num;
use intrinsics;
use libc::c_int;
-use num::{Float, FpCategory};
-use num::strconv;
-use num::strconv::ExponentFormat::{ExpNone, ExpDec};
-use num::strconv::SignificantDigits::{DigAll, DigMax, DigExact};
-use num::strconv::SignFormat::SignNeg;
-
-use core::num;
+use num::{FpCategory, ParseFloatError};
+use sys_common::FromInner;
-pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE};
-pub use core::f64::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP};
+pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON};
+pub use core::f64::{MIN_EXP, MAX_EXP, MIN_10_EXP};
pub use core::f64::{MAX_10_EXP, NAN, INFINITY, NEG_INFINITY};
pub use core::f64::{MIN, MIN_POSITIVE, MAX};
pub use core::f64::consts;
}
}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow(deprecated)]
-impl Float for f64 {
- // inlined methods from `num::Float`
- #[inline]
- fn nan() -> f64 { num::Float::nan() }
- #[inline]
- fn infinity() -> f64 { num::Float::infinity() }
- #[inline]
- fn neg_infinity() -> f64 { num::Float::neg_infinity() }
- #[inline]
- fn zero() -> f64 { num::Float::zero() }
- #[inline]
- fn neg_zero() -> f64 { num::Float::neg_zero() }
- #[inline]
- fn one() -> f64 { num::Float::one() }
-
-
- #[allow(deprecated)]
- #[inline]
- fn mantissa_digits(unused_self: Option<f64>) -> usize {
- num::Float::mantissa_digits(unused_self)
- }
- #[allow(deprecated)]
- #[inline]
- fn digits(unused_self: Option<f64>) -> usize { num::Float::digits(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn epsilon() -> f64 { num::Float::epsilon() }
- #[allow(deprecated)]
- #[inline]
- fn min_exp(unused_self: Option<f64>) -> isize { num::Float::min_exp(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn max_exp(unused_self: Option<f64>) -> isize { num::Float::max_exp(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn min_10_exp(unused_self: Option<f64>) -> isize { num::Float::min_10_exp(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn max_10_exp(unused_self: Option<f64>) -> isize { num::Float::max_10_exp(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn min_value() -> f64 { num::Float::min_value() }
- #[allow(deprecated)]
- #[inline]
- fn min_pos_value(unused_self: Option<f64>) -> f64 { num::Float::min_pos_value(unused_self) }
- #[allow(deprecated)]
- #[inline]
- fn max_value() -> f64 { num::Float::max_value() }
-
- #[inline]
- fn is_nan(self) -> bool { num::Float::is_nan(self) }
- #[inline]
- fn is_infinite(self) -> bool { num::Float::is_infinite(self) }
- #[inline]
- fn is_finite(self) -> bool { num::Float::is_finite(self) }
- #[inline]
- fn is_normal(self) -> bool { num::Float::is_normal(self) }
- #[inline]
- fn classify(self) -> FpCategory { num::Float::classify(self) }
-
- #[inline]
- fn integer_decode(self) -> (u64, i16, i8) { num::Float::integer_decode(self) }
-
- #[inline]
- fn floor(self) -> f64 { num::Float::floor(self) }
- #[inline]
- fn ceil(self) -> f64 { num::Float::ceil(self) }
- #[inline]
- fn round(self) -> f64 { num::Float::round(self) }
- #[inline]
- fn trunc(self) -> f64 { num::Float::trunc(self) }
- #[inline]
- fn fract(self) -> f64 { num::Float::fract(self) }
-
- #[inline]
- fn abs(self) -> f64 { num::Float::abs(self) }
- #[inline]
- fn signum(self) -> f64 { num::Float::signum(self) }
- #[inline]
- fn is_positive(self) -> bool { num::Float::is_positive(self) }
- #[inline]
- fn is_negative(self) -> bool { num::Float::is_negative(self) }
-
- #[inline]
- fn mul_add(self, a: f64, b: f64) -> f64 { num::Float::mul_add(self, a, b) }
- #[inline]
- fn recip(self) -> f64 { num::Float::recip(self) }
-
- #[inline]
- fn powi(self, n: i32) -> f64 { num::Float::powi(self, n) }
- #[inline]
- fn powf(self, n: f64) -> f64 { num::Float::powf(self, n) }
-
- #[inline]
- fn sqrt(self) -> f64 { num::Float::sqrt(self) }
- #[inline]
- fn rsqrt(self) -> f64 { num::Float::rsqrt(self) }
-
- #[inline]
- fn exp(self) -> f64 { num::Float::exp(self) }
- #[inline]
- fn exp2(self) -> f64 { num::Float::exp2(self) }
- #[inline]
- fn ln(self) -> f64 { num::Float::ln(self) }
- #[inline]
- fn log(self, base: f64) -> f64 { num::Float::log(self, base) }
- #[inline]
- fn log2(self) -> f64 { num::Float::log2(self) }
- #[inline]
- fn log10(self) -> f64 { num::Float::log10(self) }
-
- #[inline]
- fn to_degrees(self) -> f64 { num::Float::to_degrees(self) }
- #[inline]
- fn to_radians(self) -> f64 { num::Float::to_radians(self) }
-
- #[inline]
- fn ldexp(self, exp: isize) -> f64 {
- unsafe { cmath::ldexp(self, exp as c_int) }
- }
-
- /// Breaks the number into a normalized fraction and a base-2 exponent,
- /// satisfying:
- ///
- /// - `self = x * pow(2, exp)`
- /// - `0.5 <= abs(x) < 1.0`
- #[inline]
- fn frexp(self) -> (f64, isize) {
- unsafe {
- let mut exp = 0;
- let x = cmath::frexp(self, &mut exp);
- (x, exp as isize)
- }
- }
-
- /// Returns the next representable floating-point value in the direction of
- /// `other`.
- #[inline]
- fn next_after(self, other: f64) -> f64 {
- unsafe { cmath::nextafter(self, other) }
- }
-
- #[inline]
- fn max(self, other: f64) -> f64 {
- unsafe { cmath::fmax(self, other) }
- }
-
- #[inline]
- fn min(self, other: f64) -> f64 {
- unsafe { cmath::fmin(self, other) }
- }
-
- #[inline]
- fn abs_sub(self, other: f64) -> f64 {
- unsafe { cmath::fdim(self, other) }
- }
-
- #[inline]
- fn cbrt(self) -> f64 {
- unsafe { cmath::cbrt(self) }
- }
-
- #[inline]
- fn hypot(self, other: f64) -> f64 {
- unsafe { cmath::hypot(self, other) }
- }
-
- #[inline]
- fn sin(self) -> f64 {
- unsafe { intrinsics::sinf64(self) }
- }
-
- #[inline]
- fn cos(self) -> f64 {
- unsafe { intrinsics::cosf64(self) }
- }
-
- #[inline]
- fn tan(self) -> f64 {
- unsafe { cmath::tan(self) }
- }
-
- #[inline]
- fn asin(self) -> f64 {
- unsafe { cmath::asin(self) }
- }
-
- #[inline]
- fn acos(self) -> f64 {
- unsafe { cmath::acos(self) }
- }
-
- #[inline]
- fn atan(self) -> f64 {
- unsafe { cmath::atan(self) }
- }
-
- #[inline]
- fn atan2(self, other: f64) -> f64 {
- unsafe { cmath::atan2(self, other) }
- }
-
- /// Simultaneously computes the sine and cosine of the number
- #[inline]
- fn sin_cos(self) -> (f64, f64) {
- (self.sin(), self.cos())
- }
-
- /// Returns the exponential of the number, minus `1`, in a way that is
- /// accurate even if the number is close to zero
- #[inline]
- fn exp_m1(self) -> f64 {
- unsafe { cmath::expm1(self) }
- }
-
- /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more
- /// accurately than if the operations were performed separately
- #[inline]
- fn ln_1p(self) -> f64 {
- unsafe { cmath::log1p(self) }
- }
-
- #[inline]
- fn sinh(self) -> f64 {
- unsafe { cmath::sinh(self) }
- }
-
- #[inline]
- fn cosh(self) -> f64 {
- unsafe { cmath::cosh(self) }
- }
-
- #[inline]
- fn tanh(self) -> f64 {
- unsafe { cmath::tanh(self) }
- }
-
- /// Inverse hyperbolic sine
- ///
- /// # Returns
- ///
- /// - on success, the inverse hyperbolic sine of `self` will be returned
- /// - `self` if `self` is `0.0`, `-0.0`, `INFINITY`, or `NEG_INFINITY`
- /// - `NAN` if `self` is `NAN`
- #[inline]
- fn asinh(self) -> f64 {
- match self {
- NEG_INFINITY => NEG_INFINITY,
- x => (x + ((x * x) + 1.0).sqrt()).ln(),
- }
- }
-
- /// Inverse hyperbolic cosine
- ///
- /// # Returns
- ///
- /// - on success, the inverse hyperbolic cosine of `self` will be returned
- /// - `INFINITY` if `self` is `INFINITY`
- /// - `NAN` if `self` is `NAN` or `self < 1.0` (including `NEG_INFINITY`)
- #[inline]
- fn acosh(self) -> f64 {
- match self {
- x if x < 1.0 => Float::nan(),
- x => (x + ((x * x) - 1.0).sqrt()).ln(),
- }
- }
-
- /// Inverse hyperbolic tangent
- ///
- /// # Returns
- ///
- /// - on success, the inverse hyperbolic tangent of `self` will be returned
- /// - `self` if `self` is `0.0` or `-0.0`
- /// - `INFINITY` if `self` is `1.0`
- /// - `NEG_INFINITY` if `self` is `-1.0`
- /// - `NAN` if the `self` is `NAN` or outside the domain of `-1.0 <= self <= 1.0`
- /// (including `INFINITY` and `NEG_INFINITY`)
- #[inline]
- fn atanh(self) -> f64 {
- 0.5 * ((2.0 * self) / (1.0 - self)).ln_1p()
- }
-}
-
#[cfg(not(test))]
#[lang = "f64"]
#[stable(feature = "rust1", since = "1.0.0")]
impl f64 {
+ /// Parses a float as with a given radix
+ #[unstable(feature = "float_from_str_radix", reason = "recently moved API")]
+ pub fn from_str_radix(s: &str, radix: u32) -> Result<f64, ParseFloatError> {
+ num::Float::from_str_radix(s, radix).map_err(FromInner::from_inner)
+ }
+
/// Returns `true` if this value is `NaN` and false otherwise.
///
/// ```
#[inline]
pub fn sqrt(self) -> f64 { num::Float::sqrt(self) }
- /// Takes the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// let f = 4.0_f64;
- ///
- /// let abs_difference = (f.rsqrt() - 0.5).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- #[deprecated(since = "1.0.0", reason = "use self.sqrt().recip() instead")]
- #[inline]
- pub fn rsqrt(self) -> f64 { num::Float::rsqrt(self) }
-
/// Returns `e^(self)`, (the exponential function).
///
/// ```
#[inline]
pub fn acosh(self) -> f64 {
match self {
- x if x < 1.0 => Float::nan(),
+ x if x < 1.0 => NAN,
x => (x + ((x * x) - 1.0).sqrt()).ln(),
}
}
}
}
-//
-// Section: String Conversions
-//
-
-/// Converts a float to a string
-///
-/// # Arguments
-///
-/// * num - The float value
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-#[deprecated(since = "1.0.0", reason = "use the ToString trait instead")]
-pub fn to_string(num: f64) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 10, true, SignNeg, DigAll, ExpNone, false);
- r
-}
-
-/// Converts a float to a string in hexadecimal format
-///
-/// # Arguments
-///
-/// * num - The float value
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-#[deprecated(since = "1.0.0", reason = "use format! instead")]
-pub fn to_str_hex(num: f64) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 16, true, SignNeg, DigAll, ExpNone, false);
- r
-}
-
-/// Converts a float to a string in a given radix, and a flag indicating
-/// whether it's a special value
-///
-/// # Arguments
-///
-/// * num - The float value
-/// * radix - The base to use
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-#[deprecated(since = "1.0.0", reason = "use format! instead")]
-pub fn to_str_radix_special(num: f64, rdx: u32) -> (String, bool) {
- strconv::float_to_str_common(num, rdx, true, SignNeg, DigAll, ExpNone, false)
-}
-
-/// Converts a float to a string with exactly the number of
-/// provided significant digits
-///
-/// # Arguments
-///
-/// * num - The float value
-/// * digits - The number of significant digits
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-pub fn to_str_exact(num: f64, dig: usize) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 10, true, SignNeg, DigExact(dig), ExpNone, false);
- r
-}
-
-/// Converts a float to a string with a maximum number of
-/// significant digits
-///
-/// # Arguments
-///
-/// * num - The float value
-/// * digits - The number of significant digits
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-pub fn to_str_digits(num: f64, dig: usize) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 10, true, SignNeg, DigMax(dig), ExpNone, false);
- r
-}
-
-/// Converts a float to a string using the exponential notation with exactly the number of
-/// provided digits after the decimal point in the significand
-///
-/// # Arguments
-///
-/// * num - The float value
-/// * digits - The number of digits after the decimal point
-/// * upper - Use `E` instead of `e` for the exponent sign
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-pub fn to_str_exp_exact(num: f64, dig: usize, upper: bool) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 10, true, SignNeg, DigExact(dig), ExpDec, upper);
- r
-}
-
-/// Converts a float to a string using the exponential notation with the maximum number of
-/// digits after the decimal point in the significand
-///
-/// # Arguments
-///
-/// * num - The float value
-/// * digits - The number of digits after the decimal point
-/// * upper - Use `E` instead of `e` for the exponent sign
-#[inline]
-#[unstable(feature = "std_misc", reason = "may be removed or relocated")]
-pub fn to_str_exp_digits(num: f64, dig: usize, upper: bool) -> String {
- let (r, _) = strconv::float_to_str_common(
- num, 10, true, SignNeg, DigMax(dig), ExpDec, upper);
- r
-}
-
#[cfg(test)]
mod tests {
+ use f64;
use f64::*;
use num::*;
use num::FpCategory as Fp;
#[test]
fn test_nan() {
- let nan: f64 = Float::nan();
+ let nan: f64 = NAN;
assert!(nan.is_nan());
assert!(!nan.is_infinite());
assert!(!nan.is_finite());
#[test]
fn test_infinity() {
- let inf: f64 = Float::infinity();
+ let inf: f64 = INFINITY;
assert!(inf.is_infinite());
assert!(!inf.is_finite());
assert!(inf.is_sign_positive());
#[test]
fn test_neg_infinity() {
- let neg_inf: f64 = Float::neg_infinity();
+ let neg_inf: f64 = NEG_INFINITY;
assert!(neg_inf.is_infinite());
assert!(!neg_inf.is_finite());
assert!(!neg_inf.is_sign_positive());
#[test]
fn test_zero() {
- let zero: f64 = Float::zero();
+ let zero: f64 = 0.0f64;
assert_eq!(0.0, zero);
assert!(!zero.is_infinite());
assert!(zero.is_finite());
#[test]
fn test_neg_zero() {
- let neg_zero: f64 = Float::neg_zero();
+ let neg_zero: f64 = -0.0;
assert_eq!(0.0, neg_zero);
assert!(!neg_zero.is_infinite());
assert!(neg_zero.is_finite());
#[test]
fn test_one() {
- let one: f64 = Float::one();
+ let one: f64 = 1.0f64;
assert_eq!(1.0, one);
assert!(!one.is_infinite());
assert!(one.is_finite());
#[test]
fn test_is_nan() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert!(nan.is_nan());
assert!(!0.0f64.is_nan());
assert!(!5.3f64.is_nan());
#[test]
fn test_is_infinite() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert!(!nan.is_infinite());
assert!(inf.is_infinite());
assert!(neg_inf.is_infinite());
#[test]
fn test_is_finite() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert!(!nan.is_finite());
assert!(!inf.is_finite());
assert!(!neg_inf.is_finite());
#[test]
fn test_is_normal() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let zero: f64 = Float::zero();
- let neg_zero: f64 = Float::neg_zero();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
+ let zero: f64 = 0.0f64;
+ let neg_zero: f64 = -0.0;
assert!(!nan.is_normal());
assert!(!inf.is_normal());
assert!(!neg_inf.is_normal());
#[test]
fn test_classify() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let zero: f64 = Float::zero();
- let neg_zero: f64 = Float::neg_zero();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
+ let zero: f64 = 0.0f64;
+ let neg_zero: f64 = -0.0;
assert_eq!(nan.classify(), Fp::Nan);
assert_eq!(inf.classify(), Fp::Infinite);
assert_eq!(neg_inf.classify(), Fp::Infinite);
#[test]
fn test_mul_add() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert_approx_eq!(12.3f64.mul_add(4.5, 6.7), 62.05);
assert_approx_eq!((-12.3f64).mul_add(-4.5, -6.7), 48.65);
assert_approx_eq!(0.0f64.mul_add(8.9, 1.2), 1.2);
#[test]
fn test_recip() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert_eq!(1.0f64.recip(), 1.0);
assert_eq!(2.0f64.recip(), 0.5);
assert_eq!((-0.4f64).recip(), -2.5);
#[test]
fn test_powi() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert_eq!(1.0f64.powi(1), 1.0);
assert_approx_eq!((-3.1f64).powi(2), 9.61);
assert_approx_eq!(5.9f64.powi(-2), 0.028727);
#[test]
fn test_powf() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert_eq!(1.0f64.powf(1.0), 1.0);
assert_approx_eq!(3.4f64.powf(4.5), 246.408183);
assert_approx_eq!(2.7f64.powf(-3.2), 0.041652);
assert_eq!(INFINITY.sqrt(), INFINITY);
}
- #[test]
- fn test_rsqrt() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- assert!(nan.rsqrt().is_nan());
- assert_eq!(inf.rsqrt(), 0.0);
- assert!(neg_inf.rsqrt().is_nan());
- assert!((-1.0f64).rsqrt().is_nan());
- assert_eq!((-0.0f64).rsqrt(), neg_inf);
- assert_eq!(0.0f64.rsqrt(), inf);
- assert_eq!(1.0f64.rsqrt(), 1.0);
- assert_eq!(4.0f64.rsqrt(), 0.5);
- }
-
#[test]
fn test_exp() {
assert_eq!(1.0, 0.0f64.exp());
assert_approx_eq!(2.718282, 1.0f64.exp());
assert_approx_eq!(148.413159, 5.0f64.exp());
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let nan: f64 = Float::nan();
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
+ let nan: f64 = NAN;
assert_eq!(inf, inf.exp());
assert_eq!(0.0, neg_inf.exp());
assert!(nan.exp().is_nan());
assert_eq!(32.0, 5.0f64.exp2());
assert_eq!(1.0, 0.0f64.exp2());
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let nan: f64 = Float::nan();
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
+ let nan: f64 = NAN;
assert_eq!(inf, inf.exp2());
assert_eq!(0.0, neg_inf.exp2());
assert!(nan.exp2().is_nan());
#[test]
fn test_ln() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert_approx_eq!(1.0f64.exp().ln(), 1.0);
assert!(nan.ln().is_nan());
assert_eq!(inf.ln(), inf);
#[test]
fn test_log() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert_eq!(10.0f64.log(10.0), 1.0);
assert_approx_eq!(2.3f64.log(3.5), 0.664858);
- assert_eq!(1.0f64.exp().log(1.0.exp()), 1.0);
+ assert_eq!(1.0f64.exp().log(1.0f64.exp()), 1.0);
assert!(1.0f64.log(1.0).is_nan());
assert!(1.0f64.log(-13.9).is_nan());
assert!(nan.log(2.3).is_nan());
#[test]
fn test_log2() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert_approx_eq!(10.0f64.log2(), 3.321928);
assert_approx_eq!(2.3f64.log2(), 1.201634);
assert_approx_eq!(1.0f64.exp().log2(), 1.442695);
#[test]
fn test_log10() {
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert_eq!(10.0f64.log10(), 1.0);
assert_approx_eq!(2.3f64.log10(), 0.361728);
assert_approx_eq!(1.0f64.exp().log10(), 0.434294);
#[test]
fn test_to_degrees() {
let pi: f64 = consts::PI;
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert_eq!(0.0f64.to_degrees(), 0.0);
assert_approx_eq!((-5.8f64).to_degrees(), -332.315521);
assert_eq!(pi.to_degrees(), 180.0);
#[test]
fn test_to_radians() {
let pi: f64 = consts::PI;
- let nan: f64 = Float::nan();
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let nan: f64 = NAN;
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
assert_eq!(0.0f64.to_radians(), 0.0);
assert_approx_eq!(154.6f64.to_radians(), 2.698279);
assert_approx_eq!((-332.31f64).to_radians(), -5.799903);
fn test_ldexp() {
// We have to use from_str until base-2 exponents
// are supported in floating-point literals
- let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
- let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
- let f3: f64 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap();
- assert_eq!(1f64.ldexp(-123), f1);
- assert_eq!(1f64.ldexp(-111), f2);
- assert_eq!(Float::ldexp(1.75f64, -12), f3);
+ let f1: f64 = f64::from_str_radix("1p-123", 16).unwrap();
+ let f2: f64 = f64::from_str_radix("1p-111", 16).unwrap();
+ let f3: f64 = f64::from_str_radix("1.Cp-12", 16).unwrap();
+ assert_eq!(f64::ldexp(1f64, -123), f1);
+ assert_eq!(f64::ldexp(1f64, -111), f2);
+ assert_eq!(f64::ldexp(1.75f64, -12), f3);
- assert_eq!(Float::ldexp(0f64, -123), 0f64);
- assert_eq!(Float::ldexp(-0f64, -123), -0f64);
+ assert_eq!(f64::ldexp(0f64, -123), 0f64);
+ assert_eq!(f64::ldexp(-0f64, -123), -0f64);
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let nan: f64 = Float::nan();
- assert_eq!(Float::ldexp(inf, -123), inf);
- assert_eq!(Float::ldexp(neg_inf, -123), neg_inf);
- assert!(Float::ldexp(nan, -123).is_nan());
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
+ let nan: f64 = NAN;
+ assert_eq!(f64::ldexp(inf, -123), inf);
+ assert_eq!(f64::ldexp(neg_inf, -123), neg_inf);
+ assert!(f64::ldexp(nan, -123).is_nan());
}
#[test]
fn test_frexp() {
// We have to use from_str until base-2 exponents
// are supported in floating-point literals
- let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
- let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
- let f3: f64 = FromStrRadix::from_str_radix("1.Cp-123", 16).unwrap();
+ let f1: f64 = f64::from_str_radix("1p-123", 16).unwrap();
+ let f2: f64 = f64::from_str_radix("1p-111", 16).unwrap();
+ let f3: f64 = f64::from_str_radix("1.Cp-123", 16).unwrap();
let (x1, exp1) = f1.frexp();
let (x2, exp2) = f2.frexp();
let (x3, exp3) = f3.frexp();
assert_eq!((x1, exp1), (0.5f64, -122));
assert_eq!((x2, exp2), (0.5f64, -110));
assert_eq!((x3, exp3), (0.875f64, -122));
- assert_eq!(Float::ldexp(x1, exp1), f1);
- assert_eq!(Float::ldexp(x2, exp2), f2);
- assert_eq!(Float::ldexp(x3, exp3), f3);
+ assert_eq!(f64::ldexp(x1, exp1), f1);
+ assert_eq!(f64::ldexp(x2, exp2), f2);
+ assert_eq!(f64::ldexp(x3, exp3), f3);
assert_eq!(0f64.frexp(), (0f64, 0));
assert_eq!((-0f64).frexp(), (-0f64, 0));
#[test] #[cfg_attr(windows, ignore)] // FIXME #8755
fn test_frexp_nowin() {
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let nan: f64 = Float::nan();
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
+ let nan: f64 = NAN;
assert_eq!(match inf.frexp() { (x, _) => x }, inf);
assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf);
assert!(match nan.frexp() { (x, _) => x.is_nan() })
assert_eq!(0.0f64.asinh(), 0.0f64);
assert_eq!((-0.0f64).asinh(), -0.0f64);
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let nan: f64 = Float::nan();
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
+ let nan: f64 = NAN;
assert_eq!(inf.asinh(), inf);
assert_eq!(neg_inf.asinh(), neg_inf);
assert!(nan.asinh().is_nan());
assert_eq!(1.0f64.acosh(), 0.0f64);
assert!(0.999f64.acosh().is_nan());
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let nan: f64 = Float::nan();
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
+ let nan: f64 = NAN;
assert_eq!(inf.acosh(), inf);
assert!(neg_inf.acosh().is_nan());
assert!(nan.acosh().is_nan());
assert_eq!(0.0f64.atanh(), 0.0f64);
assert_eq!((-0.0f64).atanh(), -0.0f64);
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
- let nan: f64 = Float::nan();
+ let inf: f64 = INFINITY;
+ let neg_inf: f64 = NEG_INFINITY;
+ let nan: f64 = NAN;
assert_eq!(1.0f64.atanh(), inf);
assert_eq!((-1.0f64).atanh(), neg_inf);
assert!(2f64.atanh().atanh().is_nan());
let frac_pi_8: f64 = consts::FRAC_PI_8;
let frac_1_pi: f64 = consts::FRAC_1_PI;
let frac_2_pi: f64 = consts::FRAC_2_PI;
- let frac_2_sqrtpi: f64 = consts::FRAC_2_SQRTPI;
- let sqrt2: f64 = consts::SQRT2;
- let frac_1_sqrt2: f64 = consts::FRAC_1_SQRT2;
+ let frac_2_sqrtpi: f64 = consts::FRAC_2_SQRT_PI;
+ let sqrt2: f64 = consts::SQRT_2;
+ let frac_1_sqrt2: f64 = consts::FRAC_1_SQRT_2;
let e: f64 = consts::E;
let log2_e: f64 = consts::LOG2_E;
let log10_e: f64 = consts::LOG10_E;
#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)]
-#![allow(deprecated)]
-#[cfg(test)] use fmt::Debug;
-use ops::{Add, Sub, Mul, Div, Rem, Neg};
+use fmt;
+use core::num;
-use marker::Copy;
-use clone::Clone;
-use cmp::{PartialOrd, PartialEq};
-
-pub use core::num::{Int, SignedInt, Zero, One};
-pub use core::num::{cast, FromPrimitive, NumCast, ToPrimitive};
-pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64};
-pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64};
-pub use core::num::{from_f32, from_f64};
-pub use core::num::{FromStrRadix, from_str_radix};
-pub use core::num::{FpCategory, ParseIntError, ParseFloatError};
+pub use core::num::{Zero, One};
+pub use core::num::{FpCategory, ParseIntError};
pub use core::num::{wrapping, Wrapping};
-use option::Option;
-
-#[unstable(feature = "std_misc", reason = "likely to be removed")]
-pub mod strconv;
-
-/// Mathematical operations on primitive floating point numbers.
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(since = "1.0.0",
- reason = "replaced by inherent methods; use rust-lang/num for generics")]
-pub trait Float
- : Copy + Clone
- + NumCast
- + PartialOrd
- + PartialEq
- + Neg<Output=Self>
- + Add<Output=Self>
- + Sub<Output=Self>
- + Mul<Output=Self>
- + Div<Output=Self>
- + Rem<Output=Self>
-{
- // inlined methods from `num::Float`
- /// Returns the `NaN` value.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let nan: f32 = Float::nan();
- ///
- /// assert!(nan.is_nan());
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn nan() -> Self;
- /// Returns the infinite value.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- /// use std::f32;
- ///
- /// let infinity: f32 = Float::infinity();
- ///
- /// assert!(infinity.is_infinite());
- /// assert!(!infinity.is_finite());
- /// assert!(infinity > f32::MAX);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn infinity() -> Self;
- /// Returns the negative infinite value.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- /// use std::f32;
- ///
- /// let neg_infinity: f32 = Float::neg_infinity();
- ///
- /// assert!(neg_infinity.is_infinite());
- /// assert!(!neg_infinity.is_finite());
- /// assert!(neg_infinity < f32::MIN);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn neg_infinity() -> Self;
- /// Returns `0.0`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let inf: f32 = Float::infinity();
- /// let zero: f32 = Float::zero();
- /// let neg_zero: f32 = Float::neg_zero();
- ///
- /// assert_eq!(zero, neg_zero);
- /// assert_eq!(7.0f32/inf, zero);
- /// assert_eq!(zero * 10.0, zero);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn zero() -> Self;
- /// Returns `-0.0`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let inf: f32 = Float::infinity();
- /// let zero: f32 = Float::zero();
- /// let neg_zero: f32 = Float::neg_zero();
- ///
- /// assert_eq!(zero, neg_zero);
- /// assert_eq!(7.0f32/inf, zero);
- /// assert_eq!(zero * 10.0, zero);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn neg_zero() -> Self;
- /// Returns `1.0`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let one: f32 = Float::one();
- ///
- /// assert_eq!(one, 1.0f32);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn one() -> Self;
-
- // FIXME (#5527): These should be associated constants
-
- /// Deprecated: use `std::f32::MANTISSA_DIGITS` or `std::f64::MANTISSA_DIGITS`
- /// instead.
- #[unstable(feature = "std_misc")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MANTISSA_DIGITS` or \
- `std::f64::MANTISSA_DIGITS` as appropriate")]
- fn mantissa_digits(unused_self: Option<Self>) -> usize;
- /// Deprecated: use `std::f32::DIGITS` or `std::f64::DIGITS` instead.
- #[unstable(feature = "std_misc")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")]
- fn digits(unused_self: Option<Self>) -> usize;
- /// Deprecated: use `std::f32::EPSILON` or `std::f64::EPSILON` instead.
- #[unstable(feature = "std_misc")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::EPSILON` or `std::f64::EPSILON` as appropriate")]
- fn epsilon() -> Self;
- /// Deprecated: use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` instead.
- #[unstable(feature = "std_misc")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")]
- fn min_exp(unused_self: Option<Self>) -> isize;
- /// Deprecated: use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` instead.
- #[unstable(feature = "std_misc")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")]
- fn max_exp(unused_self: Option<Self>) -> isize;
- /// Deprecated: use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` instead.
- #[unstable(feature = "std_misc")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")]
- fn min_10_exp(unused_self: Option<Self>) -> isize;
- /// Deprecated: use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` instead.
- #[unstable(feature = "std_misc")]
- #[deprecated(since = "1.0.0",
- reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")]
- fn max_10_exp(unused_self: Option<Self>) -> isize;
-
- /// Returns the smallest finite value that this type can represent.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let x: f64 = Float::min_value();
- ///
- /// assert_eq!(x, f64::MIN);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn min_value() -> Self;
- /// Returns the smallest normalized positive number that this type can represent.
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn min_pos_value(unused_self: Option<Self>) -> Self;
- /// Returns the largest finite value that this type can represent.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let x: f64 = Float::max_value();
- /// assert_eq!(x, f64::MAX);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn max_value() -> Self;
- /// Returns `true` if this value is `NaN` and false otherwise.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let nan = f64::NAN;
- /// let f = 7.0;
- ///
- /// assert!(nan.is_nan());
- /// assert!(!f.is_nan());
- /// ```
- #[unstable(feature = "std_misc", reason = "position is undecided")]
- fn is_nan(self) -> bool;
- /// Returns `true` if this value is positive infinity or negative infinity and
- /// false otherwise.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- /// use std::f32;
- ///
- /// let f = 7.0f32;
- /// let inf: f32 = Float::infinity();
- /// let neg_inf: f32 = Float::neg_infinity();
- /// let nan: f32 = f32::NAN;
- ///
- /// assert!(!f.is_infinite());
- /// assert!(!nan.is_infinite());
- ///
- /// assert!(inf.is_infinite());
- /// assert!(neg_inf.is_infinite());
- /// ```
- #[unstable(feature = "std_misc", reason = "position is undecided")]
- fn is_infinite(self) -> bool;
- /// Returns `true` if this number is neither infinite nor `NaN`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- /// use std::f32;
- ///
- /// let f = 7.0f32;
- /// let inf: f32 = Float::infinity();
- /// let neg_inf: f32 = Float::neg_infinity();
- /// let nan: f32 = f32::NAN;
- ///
- /// assert!(f.is_finite());
- ///
- /// assert!(!nan.is_finite());
- /// assert!(!inf.is_finite());
- /// assert!(!neg_inf.is_finite());
- /// ```
- #[unstable(feature = "std_misc", reason = "position is undecided")]
- fn is_finite(self) -> bool;
-
- /// Returns `true` if the number is neither zero, infinite,
- /// [subnormal][subnormal], or `NaN`.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f32;
- ///
- /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
- /// let max = f32::MAX;
- /// let lower_than_min = 1.0e-40_f32;
- /// let zero = 0.0f32;
- ///
- /// assert!(min.is_normal());
- /// assert!(max.is_normal());
- ///
- /// assert!(!zero.is_normal());
- /// assert!(!f32::NAN.is_normal());
- /// assert!(!f32::INFINITY.is_normal());
- /// // Values between `0` and `min` are Subnormal.
- /// assert!(!lower_than_min.is_normal());
- /// ```
- /// [subnormal]: http://en.wikipedia.org/wiki/Denormal_number
- #[unstable(feature = "std_misc", reason = "position is undecided")]
- fn is_normal(self) -> bool;
-
- /// Returns the floating point category of the number. If only one property
- /// is going to be tested, it is generally faster to use the specific
- /// predicate instead.
- ///
- /// ```
- /// use std::num::{Float, FpCategory};
- /// use std::f32;
- ///
- /// let num = 12.4f32;
- /// let inf = f32::INFINITY;
- ///
- /// assert_eq!(num.classify(), FpCategory::Normal);
- /// assert_eq!(inf.classify(), FpCategory::Infinite);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn classify(self) -> FpCategory;
-
- /// Returns the mantissa, base 2 exponent, and sign as integers, respectively.
- /// The original number can be recovered by `sign * mantissa * 2 ^ exponent`.
- /// The floating point encoding is documented in the [Reference][floating-point].
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let num = 2.0f32;
- ///
- /// // (8388608, -22, 1)
- /// let (mantissa, exponent, sign) = num.integer_decode();
- /// let sign_f = sign as f32;
- /// let mantissa_f = mantissa as f32;
- /// let exponent_f = num.powf(exponent as f32);
- ///
- /// // 1 * 8388608 * 2^(-22) == 2
- /// let abs_difference = (sign_f * mantissa_f * exponent_f - num).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- /// [floating-point]: ../../../../../reference.html#machine-types
- #[unstable(feature = "std_misc", reason = "signature is undecided")]
- fn integer_decode(self) -> (u64, i16, i8);
-
- /// Returns the largest integer less than or equal to a number.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let f = 3.99;
- /// let g = 3.0;
- ///
- /// assert_eq!(f.floor(), 3.0);
- /// assert_eq!(g.floor(), 3.0);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn floor(self) -> Self;
- /// Returns the smallest integer greater than or equal to a number.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let f = 3.01;
- /// let g = 4.0;
- ///
- /// assert_eq!(f.ceil(), 4.0);
- /// assert_eq!(g.ceil(), 4.0);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn ceil(self) -> Self;
- /// Returns the nearest integer to a number. Round half-way cases away from
- /// `0.0`.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let f = 3.3;
- /// let g = -3.3;
- ///
- /// assert_eq!(f.round(), 3.0);
- /// assert_eq!(g.round(), -3.0);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn round(self) -> Self;
- /// Returns the integer part of a number.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let f = 3.3;
- /// let g = -3.7;
- ///
- /// assert_eq!(f.trunc(), 3.0);
- /// assert_eq!(g.trunc(), -3.0);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn trunc(self) -> Self;
- /// Returns the fractional part of a number.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let x = 3.5;
- /// let y = -3.5;
- /// let abs_difference_x = (x.fract() - 0.5).abs();
- /// let abs_difference_y = (y.fract() - (-0.5)).abs();
- ///
- /// assert!(abs_difference_x < 1e-10);
- /// assert!(abs_difference_y < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn fract(self) -> Self;
- /// Computes the absolute value of `self`. Returns `Float::nan()` if the
- /// number is `Float::nan()`.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let x = 3.5;
- /// let y = -3.5;
- ///
- /// let abs_difference_x = (x.abs() - x).abs();
- /// let abs_difference_y = (y.abs() - (-y)).abs();
- ///
- /// assert!(abs_difference_x < 1e-10);
- /// assert!(abs_difference_y < 1e-10);
- ///
- /// assert!(f64::NAN.abs().is_nan());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn abs(self) -> Self;
- /// Returns a number that represents the sign of `self`.
- ///
- /// - `1.0` if the number is positive, `+0.0` or `Float::infinity()`
- /// - `-1.0` if the number is negative, `-0.0` or `Float::neg_infinity()`
- /// - `Float::nan()` if the number is `Float::nan()`
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let f = 3.5;
- ///
- /// assert_eq!(f.signum(), 1.0);
- /// assert_eq!(f64::NEG_INFINITY.signum(), -1.0);
- ///
- /// assert!(f64::NAN.signum().is_nan());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn signum(self) -> Self;
- /// Returns `true` if `self` is positive, including `+0.0` and
- /// `Float::infinity()`.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let nan: f64 = f64::NAN;
- ///
- /// let f = 7.0;
- /// let g = -7.0;
- ///
- /// assert!(f.is_positive());
- /// assert!(!g.is_positive());
- /// // Requires both tests to determine if is `NaN`
- /// assert!(!nan.is_positive() && !nan.is_negative());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_positive(self) -> bool;
- /// Returns `true` if `self` is negative, including `-0.0` and
- /// `Float::neg_infinity()`.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let nan = f64::NAN;
- ///
- /// let f = 7.0;
- /// let g = -7.0;
- ///
- /// assert!(!f.is_negative());
- /// assert!(g.is_negative());
- /// // Requires both tests to determine if is `NaN`.
- /// assert!(!nan.is_positive() && !nan.is_negative());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn is_negative(self) -> bool;
-
- /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
- /// error. This produces a more accurate result with better performance than
- /// a separate multiplication operation followed by an add.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let m = 10.0;
- /// let x = 4.0;
- /// let b = 60.0;
- ///
- /// // 100.0
- /// let abs_difference = (m.mul_add(x, b) - (m*x + b)).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn mul_add(self, a: Self, b: Self) -> Self;
- /// Takes the reciprocal (inverse) of a number, `1/x`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let x = 2.0;
- /// let abs_difference = (x.recip() - (1.0/x)).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn recip(self) -> Self;
-
- /// Raises a number to an integer power.
- ///
- /// Using this function is generally faster than using `powf`
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let x = 2.0;
- /// let abs_difference = (x.powi(2) - x*x).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn powi(self, n: i32) -> Self;
- /// Raises a number to a floating point power.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let x = 2.0;
- /// let abs_difference = (x.powf(2.0) - x*x).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn powf(self, n: Self) -> Self;
- /// Takes the square root of a number.
- ///
- /// Returns NaN if `self` is a negative number.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let positive = 4.0;
- /// let negative = -4.0;
- ///
- /// let abs_difference = (positive.sqrt() - 2.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// assert!(negative.sqrt().is_nan());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn sqrt(self) -> Self;
-
- /// Takes the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let f = 4.0;
- ///
- /// let abs_difference = (f.rsqrt() - 0.5).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn rsqrt(self) -> Self;
-
- /// Returns `e^(self)`, (the exponential function).
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let one = 1.0;
- /// // e^1
- /// let e = one.exp();
- ///
- /// // ln(e) - 1 == 0
- /// let abs_difference = (e.ln() - 1.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn exp(self) -> Self;
- /// Returns `2^(self)`.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let f = 2.0;
- ///
- /// // 2^2 - 4 == 0
- /// let abs_difference = (f.exp2() - 4.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn exp2(self) -> Self;
- /// Returns the natural logarithm of the number.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let one = 1.0;
- /// // e^1
- /// let e = one.exp();
- ///
- /// // ln(e) - 1 == 0
- /// let abs_difference = (e.ln() - 1.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn ln(self) -> Self;
- /// Returns the logarithm of the number with respect to an arbitrary base.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let ten = 10.0;
- /// let two = 2.0;
- ///
- /// // log10(10) - 1 == 0
- /// let abs_difference_10 = (ten.log(10.0) - 1.0).abs();
- ///
- /// // log2(2) - 1 == 0
- /// let abs_difference_2 = (two.log(2.0) - 1.0).abs();
- ///
- /// assert!(abs_difference_10 < 1e-10);
- /// assert!(abs_difference_2 < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn log(self, base: Self) -> Self;
- /// Returns the base 2 logarithm of the number.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let two = 2.0;
- ///
- /// // log2(2) - 1 == 0
- /// let abs_difference = (two.log2() - 1.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn log2(self) -> Self;
- /// Returns the base 10 logarithm of the number.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let ten = 10.0;
- ///
- /// // log10(10) - 1 == 0
- /// let abs_difference = (ten.log10() - 1.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn log10(self) -> Self;
-
- /// Converts radians to degrees.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64::consts;
- ///
- /// let angle = consts::PI;
- ///
- /// let abs_difference = (angle.to_degrees() - 180.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc", reason = "desirability is unclear")]
- fn to_degrees(self) -> Self;
- /// Converts degrees to radians.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- /// use std::f64::consts;
- ///
- /// let angle = 180.0;
- ///
- /// let abs_difference = (angle.to_radians() - consts::PI).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc", reason = "desirability is unclear")]
- fn to_radians(self) -> Self;
- /// Constructs a floating point number of `x*2^exp`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// // 3*2^2 - 12 == 0
- /// let abs_difference = (Float::ldexp(3.0, 2) - 12.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "pending integer conventions")]
- fn ldexp(self, exp: isize) -> Self;
- /// Breaks the number into a normalized fraction and a base-2 exponent,
- /// satisfying:
- ///
- /// * `self = x * 2^exp`
- /// * `0.5 <= abs(x) < 1.0`
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let x = 4.0;
- ///
- /// // (1/2)*2^3 -> 1 * 8/2 -> 4.0
- /// let f = x.frexp();
- /// let abs_difference_0 = (f.0 - 0.5).abs();
- /// let abs_difference_1 = (f.1 as f64 - 3.0).abs();
- ///
- /// assert!(abs_difference_0 < 1e-10);
- /// assert!(abs_difference_1 < 1e-10);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "pending integer conventions")]
- fn frexp(self) -> (Self, isize);
- /// Returns the next representable floating-point value in the direction of
- /// `other`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let x = 1.0f32;
- ///
- /// let abs_diff = (x.next_after(2.0) - 1.00000011920928955078125_f32).abs();
- ///
- /// assert!(abs_diff < 1e-10);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn next_after(self, other: Self) -> Self;
-
- /// Returns the maximum of the two numbers.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let x = 1.0;
- /// let y = 2.0;
- ///
- /// assert_eq!(x.max(y), y);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn max(self, other: Self) -> Self;
- /// Returns the minimum of the two numbers.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let x = 1.0;
- /// let y = 2.0;
- ///
- /// assert_eq!(x.min(y), x);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn min(self, other: Self) -> Self;
-
- /// The positive difference of two numbers.
- ///
- /// * If `self <= other`: `0:0`
- /// * Else: `self - other`
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let x = 3.0;
- /// let y = -3.0;
- ///
- /// let abs_difference_x = (x.abs_sub(1.0) - 2.0).abs();
- /// let abs_difference_y = (y.abs_sub(1.0) - 0.0).abs();
- ///
- /// assert!(abs_difference_x < 1e-10);
- /// assert!(abs_difference_y < 1e-10);
- /// ```
- #[unstable(feature = "std_misc", reason = "may be renamed")]
- fn abs_sub(self, other: Self) -> Self;
- /// Takes the cubic root of a number.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let x = 8.0;
- ///
- /// // x^(1/3) - 2 == 0
- /// let abs_difference = (x.cbrt() - 2.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc", reason = "may be renamed")]
- fn cbrt(self) -> Self;
- /// Calculates the length of the hypotenuse of a right-angle triangle given
- /// legs of length `x` and `y`.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let x = 2.0;
- /// let y = 3.0;
- ///
- /// // sqrt(x^2 + y^2)
- /// let abs_difference = (x.hypot(y) - (x.powi(2) + y.powi(2)).sqrt()).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc",
- reason = "unsure about its place in the world")]
- fn hypot(self, other: Self) -> Self;
-
- /// Computes the sine of a number (in radians).
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let x = f64::consts::PI/2.0;
- ///
- /// let abs_difference = (x.sin() - 1.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn sin(self) -> Self;
- /// Computes the cosine of a number (in radians).
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let x = 2.0*f64::consts::PI;
- ///
- /// let abs_difference = (x.cos() - 1.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn cos(self) -> Self;
- /// Computes the tangent of a number (in radians).
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let x = f64::consts::PI/4.0;
- /// let abs_difference = (x.tan() - 1.0).abs();
- ///
- /// assert!(abs_difference < 1e-14);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn tan(self) -> Self;
- /// Computes the arcsine of a number. Return value is in radians in
- /// the range [-pi/2, pi/2] or NaN if the number is outside the range
- /// [-1, 1].
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let f = f64::consts::PI / 2.0;
- ///
- /// // asin(sin(pi/2))
- /// let abs_difference = (f.sin().asin() - f64::consts::PI / 2.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn asin(self) -> Self;
- /// Computes the arccosine of a number. Return value is in radians in
- /// the range [0, pi] or NaN if the number is outside the range
- /// [-1, 1].
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let f = f64::consts::PI / 4.0;
- ///
- /// // acos(cos(pi/4))
- /// let abs_difference = (f.cos().acos() - f64::consts::PI / 4.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn acos(self) -> Self;
- /// Computes the arctangent of a number. Return value is in radians in the
- /// range [-pi/2, pi/2];
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let f = 1.0;
- ///
- /// // atan(tan(1))
- /// let abs_difference = (f.tan().atan() - 1.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn atan(self) -> Self;
- /// Computes the four quadrant arctangent of `self` (`y`) and `other` (`x`).
- ///
- /// * `x = 0`, `y = 0`: `0`
- /// * `x >= 0`: `arctan(y/x)` -> `[-pi/2, pi/2]`
- /// * `y >= 0`: `arctan(y/x) + pi` -> `(pi/2, pi]`
- /// * `y < 0`: `arctan(y/x) - pi` -> `(-pi, -pi/2)`
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let pi = f64::consts::PI;
- /// // All angles from horizontal right (+x)
- /// // 45 deg counter-clockwise
- /// let x1 = 3.0;
- /// let y1 = -3.0;
- ///
- /// // 135 deg clockwise
- /// let x2 = -3.0;
- /// let y2 = 3.0;
- ///
- /// let abs_difference_1 = (y1.atan2(x1) - (-pi/4.0)).abs();
- /// let abs_difference_2 = (y2.atan2(x2) - 3.0*pi/4.0).abs();
- ///
- /// assert!(abs_difference_1 < 1e-10);
- /// assert!(abs_difference_2 < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn atan2(self, other: Self) -> Self;
- /// Simultaneously computes the sine and cosine of the number, `x`. Returns
- /// `(sin(x), cos(x))`.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let x = f64::consts::PI/4.0;
- /// let f = x.sin_cos();
- ///
- /// let abs_difference_0 = (f.0 - x.sin()).abs();
- /// let abs_difference_1 = (f.1 - x.cos()).abs();
- ///
- /// assert!(abs_difference_0 < 1e-10);
- /// assert!(abs_difference_0 < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn sin_cos(self) -> (Self, Self);
-
- /// Returns `e^(self) - 1` in a way that is accurate even if the
- /// number is close to zero.
- ///
- /// ```
- /// # #![feature(std_misc)]
- /// use std::num::Float;
- ///
- /// let x = 7.0;
- ///
- /// // e^(ln(7)) - 1
- /// let abs_difference = (x.ln().exp_m1() - 6.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc", reason = "may be renamed")]
- fn exp_m1(self) -> Self;
- /// Returns `ln(1+n)` (natural logarithm) more accurately than if
- /// the operations were performed separately.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let x = f64::consts::E - 1.0;
- ///
- /// // ln(1 + (e - 1)) == ln(e) == 1
- /// let abs_difference = (x.ln_1p() - 1.0).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[unstable(feature = "std_misc", reason = "may be renamed")]
- fn ln_1p(self) -> Self;
-
- /// Hyperbolic sine function.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let e = f64::consts::E;
- /// let x = 1.0;
- ///
- /// let f = x.sinh();
- /// // Solving sinh() at 1 gives `(e^2-1)/(2e)`
- /// let g = (e*e - 1.0)/(2.0*e);
- /// let abs_difference = (f - g).abs();
- ///
- /// assert!(abs_difference < 1e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn sinh(self) -> Self;
- /// Hyperbolic cosine function.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let e = f64::consts::E;
- /// let x = 1.0;
- /// let f = x.cosh();
- /// // Solving cosh() at 1 gives this result
- /// let g = (e*e + 1.0)/(2.0*e);
- /// let abs_difference = (f - g).abs();
- ///
- /// // Same result
- /// assert!(abs_difference < 1.0e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn cosh(self) -> Self;
- /// Hyperbolic tangent function.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let e = f64::consts::E;
- /// let x = 1.0;
- ///
- /// let f = x.tanh();
- /// // Solving tanh() at 1 gives `(1 - e^(-2))/(1 + e^(-2))`
- /// let g = (1.0 - e.powi(-2))/(1.0 + e.powi(-2));
- /// let abs_difference = (f - g).abs();
- ///
- /// assert!(abs_difference < 1.0e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn tanh(self) -> Self;
- /// Inverse hyperbolic sine function.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let x = 1.0;
- /// let f = x.sinh().asinh();
- ///
- /// let abs_difference = (f - x).abs();
- ///
- /// assert!(abs_difference < 1.0e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn asinh(self) -> Self;
- /// Inverse hyperbolic cosine function.
- ///
- /// ```
- /// use std::num::Float;
- ///
- /// let x = 1.0;
- /// let f = x.cosh().acosh();
- ///
- /// let abs_difference = (f - x).abs();
- ///
- /// assert!(abs_difference < 1.0e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn acosh(self) -> Self;
- /// Inverse hyperbolic tangent function.
- ///
- /// ```
- /// use std::num::Float;
- /// use std::f64;
- ///
- /// let e = f64::consts::E;
- /// let f = e.tanh().atanh();
- ///
- /// let abs_difference = (f - e).abs();
- ///
- /// assert!(abs_difference < 1.0e-10);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- fn atanh(self) -> Self;
-}
+#[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem};
+#[cfg(test)] use cmp::PartialEq;
+#[cfg(test)] use marker::Copy;
/// Helper function for testing numeric operations
#[cfg(test)]
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
+ + Rem<Output=T> + fmt::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);
assert_eq!(ten.rem(two), ten % two);
}
+/// An error which can be returned when parsing a float.
+#[derive(Debug, Clone, PartialEq)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct ParseFloatError { inner: num::ParseFloatError }
+
+impl ::sys_common::FromInner<num::ParseFloatError> for ParseFloatError {
+ fn from_inner(inner: num::ParseFloatError) -> ParseFloatError {
+ ParseFloatError { inner: inner }
+ }
+}
+
+impl ParseFloatError {
+ #[unstable(feature = "core", reason = "available through Error trait")]
+ pub fn description(&self) -> &str {
+ self.inner.description()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for ParseFloatError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ self.description().fmt(f)
+ }
+}
+
#[cfg(test)]
mod tests {
use core::prelude::*;
use u64;
use usize;
use string::ToString;
-
- macro_rules! test_cast_20 {
- ($_20:expr) => ({
- let _20 = $_20;
-
- assert_eq!(20usize, _20.to_uint().unwrap());
- assert_eq!(20u8, _20.to_u8().unwrap());
- assert_eq!(20u16, _20.to_u16().unwrap());
- assert_eq!(20u32, _20.to_u32().unwrap());
- assert_eq!(20u64, _20.to_u64().unwrap());
- assert_eq!(20, _20.to_int().unwrap());
- assert_eq!(20i8, _20.to_i8().unwrap());
- assert_eq!(20i16, _20.to_i16().unwrap());
- assert_eq!(20i32, _20.to_i32().unwrap());
- assert_eq!(20i64, _20.to_i64().unwrap());
- assert_eq!(20f32, _20.to_f32().unwrap());
- assert_eq!(20f64, _20.to_f64().unwrap());
-
- assert_eq!(_20, NumCast::from(20usize).unwrap());
- assert_eq!(_20, NumCast::from(20u8).unwrap());
- assert_eq!(_20, NumCast::from(20u16).unwrap());
- assert_eq!(_20, NumCast::from(20u32).unwrap());
- assert_eq!(_20, NumCast::from(20u64).unwrap());
- assert_eq!(_20, NumCast::from(20).unwrap());
- assert_eq!(_20, NumCast::from(20i8).unwrap());
- assert_eq!(_20, NumCast::from(20i16).unwrap());
- assert_eq!(_20, NumCast::from(20i32).unwrap());
- assert_eq!(_20, NumCast::from(20i64).unwrap());
- assert_eq!(_20, NumCast::from(20f32).unwrap());
- assert_eq!(_20, NumCast::from(20f64).unwrap());
-
- assert_eq!(_20, cast(20usize).unwrap());
- assert_eq!(_20, cast(20u8).unwrap());
- assert_eq!(_20, cast(20u16).unwrap());
- assert_eq!(_20, cast(20u32).unwrap());
- assert_eq!(_20, cast(20u64).unwrap());
- assert_eq!(_20, cast(20).unwrap());
- assert_eq!(_20, cast(20i8).unwrap());
- assert_eq!(_20, cast(20i16).unwrap());
- assert_eq!(_20, cast(20i32).unwrap());
- assert_eq!(_20, cast(20i64).unwrap());
- assert_eq!(_20, cast(20f32).unwrap());
- assert_eq!(_20, cast(20f64).unwrap());
- })
- }
-
- #[test] fn test_u8_cast() { test_cast_20!(20u8) }
- #[test] fn test_u16_cast() { test_cast_20!(20u16) }
- #[test] fn test_u32_cast() { test_cast_20!(20u32) }
- #[test] fn test_u64_cast() { test_cast_20!(20u64) }
- #[test] fn test_uint_cast() { test_cast_20!(20usize) }
- #[test] fn test_i8_cast() { test_cast_20!(20i8) }
- #[test] fn test_i16_cast() { test_cast_20!(20i16) }
- #[test] fn test_i32_cast() { test_cast_20!(20i32) }
- #[test] fn test_i64_cast() { test_cast_20!(20i64) }
- #[test] fn test_int_cast() { test_cast_20!(20) }
- #[test] fn test_f32_cast() { test_cast_20!(20f32) }
- #[test] fn test_f64_cast() { test_cast_20!(20f64) }
-
- #[test]
- fn test_cast_range_int_min() {
- assert_eq!(isize::MIN.to_int(), Some(isize::MIN as isize));
- assert_eq!(isize::MIN.to_i8(), None);
- assert_eq!(isize::MIN.to_i16(), None);
- // isize::MIN.to_i32() is word-size specific
- assert_eq!(isize::MIN.to_i64(), Some(isize::MIN as i64));
- assert_eq!(isize::MIN.to_uint(), None);
- assert_eq!(isize::MIN.to_u8(), None);
- assert_eq!(isize::MIN.to_u16(), None);
- assert_eq!(isize::MIN.to_u32(), None);
- assert_eq!(isize::MIN.to_u64(), None);
-
- #[cfg(target_pointer_width = "32")]
- fn check_word_size() {
- assert_eq!(isize::MIN.to_i32(), Some(isize::MIN as i32));
- }
-
- #[cfg(target_pointer_width = "64")]
- fn check_word_size() {
- assert_eq!(isize::MIN.to_i32(), None);
- }
-
- check_word_size();
- }
-
- #[test]
- fn test_cast_range_i8_min() {
- assert_eq!(i8::MIN.to_int(), Some(i8::MIN as isize));
- assert_eq!(i8::MIN.to_i8(), Some(i8::MIN as i8));
- assert_eq!(i8::MIN.to_i16(), Some(i8::MIN as i16));
- assert_eq!(i8::MIN.to_i32(), Some(i8::MIN as i32));
- assert_eq!(i8::MIN.to_i64(), Some(i8::MIN as i64));
- assert_eq!(i8::MIN.to_uint(), None);
- assert_eq!(i8::MIN.to_u8(), None);
- assert_eq!(i8::MIN.to_u16(), None);
- assert_eq!(i8::MIN.to_u32(), None);
- assert_eq!(i8::MIN.to_u64(), None);
- }
-
- #[test]
- fn test_cast_range_i16_min() {
- assert_eq!(i16::MIN.to_int(), Some(i16::MIN as isize));
- assert_eq!(i16::MIN.to_i8(), None);
- assert_eq!(i16::MIN.to_i16(), Some(i16::MIN as i16));
- assert_eq!(i16::MIN.to_i32(), Some(i16::MIN as i32));
- assert_eq!(i16::MIN.to_i64(), Some(i16::MIN as i64));
- assert_eq!(i16::MIN.to_uint(), None);
- assert_eq!(i16::MIN.to_u8(), None);
- assert_eq!(i16::MIN.to_u16(), None);
- assert_eq!(i16::MIN.to_u32(), None);
- assert_eq!(i16::MIN.to_u64(), None);
- }
-
- #[test]
- fn test_cast_range_i32_min() {
- assert_eq!(i32::MIN.to_int(), Some(i32::MIN as isize));
- assert_eq!(i32::MIN.to_i8(), None);
- assert_eq!(i32::MIN.to_i16(), None);
- assert_eq!(i32::MIN.to_i32(), Some(i32::MIN as i32));
- assert_eq!(i32::MIN.to_i64(), Some(i32::MIN as i64));
- assert_eq!(i32::MIN.to_uint(), None);
- assert_eq!(i32::MIN.to_u8(), None);
- assert_eq!(i32::MIN.to_u16(), None);
- assert_eq!(i32::MIN.to_u32(), None);
- assert_eq!(i32::MIN.to_u64(), None);
- }
-
- #[test]
- fn test_cast_range_i64_min() {
- // i64::MIN.to_int() is word-size specific
- assert_eq!(i64::MIN.to_i8(), None);
- assert_eq!(i64::MIN.to_i16(), None);
- assert_eq!(i64::MIN.to_i32(), None);
- assert_eq!(i64::MIN.to_i64(), Some(i64::MIN as i64));
- assert_eq!(i64::MIN.to_uint(), None);
- assert_eq!(i64::MIN.to_u8(), None);
- assert_eq!(i64::MIN.to_u16(), None);
- assert_eq!(i64::MIN.to_u32(), None);
- assert_eq!(i64::MIN.to_u64(), None);
-
- #[cfg(target_pointer_width = "32")]
- fn check_word_size() {
- assert_eq!(i64::MIN.to_int(), None);
- }
-
- #[cfg(target_pointer_width = "64")]
- fn check_word_size() {
- assert_eq!(i64::MIN.to_int(), Some(i64::MIN as isize));
- }
-
- check_word_size();
- }
-
- #[test]
- fn test_cast_range_int_max() {
- assert_eq!(isize::MAX.to_int(), Some(isize::MAX as isize));
- assert_eq!(isize::MAX.to_i8(), None);
- assert_eq!(isize::MAX.to_i16(), None);
- // isize::MAX.to_i32() is word-size specific
- assert_eq!(isize::MAX.to_i64(), Some(isize::MAX as i64));
- assert_eq!(isize::MAX.to_u8(), None);
- assert_eq!(isize::MAX.to_u16(), None);
- // isize::MAX.to_u32() is word-size specific
- assert_eq!(isize::MAX.to_u64(), Some(isize::MAX as u64));
-
- #[cfg(target_pointer_width = "32")]
- fn check_word_size() {
- assert_eq!(isize::MAX.to_i32(), Some(isize::MAX as i32));
- assert_eq!(isize::MAX.to_u32(), Some(isize::MAX as u32));
- }
-
- #[cfg(target_pointer_width = "64")]
- fn check_word_size() {
- assert_eq!(isize::MAX.to_i32(), None);
- assert_eq!(isize::MAX.to_u32(), None);
- }
-
- check_word_size();
- }
-
- #[test]
- fn test_cast_range_i8_max() {
- assert_eq!(i8::MAX.to_int(), Some(i8::MAX as isize));
- assert_eq!(i8::MAX.to_i8(), Some(i8::MAX as i8));
- assert_eq!(i8::MAX.to_i16(), Some(i8::MAX as i16));
- assert_eq!(i8::MAX.to_i32(), Some(i8::MAX as i32));
- assert_eq!(i8::MAX.to_i64(), Some(i8::MAX as i64));
- assert_eq!(i8::MAX.to_uint(), Some(i8::MAX as usize));
- assert_eq!(i8::MAX.to_u8(), Some(i8::MAX as u8));
- assert_eq!(i8::MAX.to_u16(), Some(i8::MAX as u16));
- assert_eq!(i8::MAX.to_u32(), Some(i8::MAX as u32));
- assert_eq!(i8::MAX.to_u64(), Some(i8::MAX as u64));
- }
-
- #[test]
- fn test_cast_range_i16_max() {
- assert_eq!(i16::MAX.to_int(), Some(i16::MAX as isize));
- assert_eq!(i16::MAX.to_i8(), None);
- assert_eq!(i16::MAX.to_i16(), Some(i16::MAX as i16));
- assert_eq!(i16::MAX.to_i32(), Some(i16::MAX as i32));
- assert_eq!(i16::MAX.to_i64(), Some(i16::MAX as i64));
- assert_eq!(i16::MAX.to_uint(), Some(i16::MAX as usize));
- assert_eq!(i16::MAX.to_u8(), None);
- assert_eq!(i16::MAX.to_u16(), Some(i16::MAX as u16));
- assert_eq!(i16::MAX.to_u32(), Some(i16::MAX as u32));
- assert_eq!(i16::MAX.to_u64(), Some(i16::MAX as u64));
- }
-
- #[test]
- fn test_cast_range_i32_max() {
- assert_eq!(i32::MAX.to_int(), Some(i32::MAX as isize));
- assert_eq!(i32::MAX.to_i8(), None);
- assert_eq!(i32::MAX.to_i16(), None);
- assert_eq!(i32::MAX.to_i32(), Some(i32::MAX as i32));
- assert_eq!(i32::MAX.to_i64(), Some(i32::MAX as i64));
- assert_eq!(i32::MAX.to_uint(), Some(i32::MAX as usize));
- assert_eq!(i32::MAX.to_u8(), None);
- assert_eq!(i32::MAX.to_u16(), None);
- assert_eq!(i32::MAX.to_u32(), Some(i32::MAX as u32));
- assert_eq!(i32::MAX.to_u64(), Some(i32::MAX as u64));
- }
-
- #[test]
- fn test_cast_range_i64_max() {
- // i64::MAX.to_int() is word-size specific
- assert_eq!(i64::MAX.to_i8(), None);
- assert_eq!(i64::MAX.to_i16(), None);
- assert_eq!(i64::MAX.to_i32(), None);
- assert_eq!(i64::MAX.to_i64(), Some(i64::MAX as i64));
- // i64::MAX.to_uint() is word-size specific
- assert_eq!(i64::MAX.to_u8(), None);
- assert_eq!(i64::MAX.to_u16(), None);
- assert_eq!(i64::MAX.to_u32(), None);
- assert_eq!(i64::MAX.to_u64(), Some(i64::MAX as u64));
-
- #[cfg(target_pointer_width = "32")]
- fn check_word_size() {
- assert_eq!(i64::MAX.to_int(), None);
- assert_eq!(i64::MAX.to_uint(), None);
- }
-
- #[cfg(target_pointer_width = "64")]
- fn check_word_size() {
- assert_eq!(i64::MAX.to_int(), Some(i64::MAX as isize));
- assert_eq!(i64::MAX.to_uint(), Some(i64::MAX as usize));
- }
-
- check_word_size();
- }
-
- #[test]
- fn test_cast_range_uint_min() {
- assert_eq!(usize::MIN.to_int(), Some(usize::MIN as isize));
- assert_eq!(usize::MIN.to_i8(), Some(usize::MIN as i8));
- assert_eq!(usize::MIN.to_i16(), Some(usize::MIN as i16));
- assert_eq!(usize::MIN.to_i32(), Some(usize::MIN as i32));
- assert_eq!(usize::MIN.to_i64(), Some(usize::MIN as i64));
- assert_eq!(usize::MIN.to_uint(), Some(usize::MIN as usize));
- assert_eq!(usize::MIN.to_u8(), Some(usize::MIN as u8));
- assert_eq!(usize::MIN.to_u16(), Some(usize::MIN as u16));
- assert_eq!(usize::MIN.to_u32(), Some(usize::MIN as u32));
- assert_eq!(usize::MIN.to_u64(), Some(usize::MIN as u64));
- }
-
- #[test]
- fn test_cast_range_u8_min() {
- assert_eq!(u8::MIN.to_int(), Some(u8::MIN as isize));
- assert_eq!(u8::MIN.to_i8(), Some(u8::MIN as i8));
- assert_eq!(u8::MIN.to_i16(), Some(u8::MIN as i16));
- assert_eq!(u8::MIN.to_i32(), Some(u8::MIN as i32));
- assert_eq!(u8::MIN.to_i64(), Some(u8::MIN as i64));
- assert_eq!(u8::MIN.to_uint(), Some(u8::MIN as usize));
- assert_eq!(u8::MIN.to_u8(), Some(u8::MIN as u8));
- assert_eq!(u8::MIN.to_u16(), Some(u8::MIN as u16));
- assert_eq!(u8::MIN.to_u32(), Some(u8::MIN as u32));
- assert_eq!(u8::MIN.to_u64(), Some(u8::MIN as u64));
- }
-
- #[test]
- fn test_cast_range_u16_min() {
- assert_eq!(u16::MIN.to_int(), Some(u16::MIN as isize));
- assert_eq!(u16::MIN.to_i8(), Some(u16::MIN as i8));
- assert_eq!(u16::MIN.to_i16(), Some(u16::MIN as i16));
- assert_eq!(u16::MIN.to_i32(), Some(u16::MIN as i32));
- assert_eq!(u16::MIN.to_i64(), Some(u16::MIN as i64));
- assert_eq!(u16::MIN.to_uint(), Some(u16::MIN as usize));
- assert_eq!(u16::MIN.to_u8(), Some(u16::MIN as u8));
- assert_eq!(u16::MIN.to_u16(), Some(u16::MIN as u16));
- assert_eq!(u16::MIN.to_u32(), Some(u16::MIN as u32));
- assert_eq!(u16::MIN.to_u64(), Some(u16::MIN as u64));
- }
-
- #[test]
- fn test_cast_range_u32_min() {
- assert_eq!(u32::MIN.to_int(), Some(u32::MIN as isize));
- assert_eq!(u32::MIN.to_i8(), Some(u32::MIN as i8));
- assert_eq!(u32::MIN.to_i16(), Some(u32::MIN as i16));
- assert_eq!(u32::MIN.to_i32(), Some(u32::MIN as i32));
- assert_eq!(u32::MIN.to_i64(), Some(u32::MIN as i64));
- assert_eq!(u32::MIN.to_uint(), Some(u32::MIN as usize));
- assert_eq!(u32::MIN.to_u8(), Some(u32::MIN as u8));
- assert_eq!(u32::MIN.to_u16(), Some(u32::MIN as u16));
- assert_eq!(u32::MIN.to_u32(), Some(u32::MIN as u32));
- assert_eq!(u32::MIN.to_u64(), Some(u32::MIN as u64));
- }
-
- #[test]
- fn test_cast_range_u64_min() {
- assert_eq!(u64::MIN.to_int(), Some(u64::MIN as isize));
- assert_eq!(u64::MIN.to_i8(), Some(u64::MIN as i8));
- assert_eq!(u64::MIN.to_i16(), Some(u64::MIN as i16));
- assert_eq!(u64::MIN.to_i32(), Some(u64::MIN as i32));
- assert_eq!(u64::MIN.to_i64(), Some(u64::MIN as i64));
- assert_eq!(u64::MIN.to_uint(), Some(u64::MIN as usize));
- assert_eq!(u64::MIN.to_u8(), Some(u64::MIN as u8));
- assert_eq!(u64::MIN.to_u16(), Some(u64::MIN as u16));
- assert_eq!(u64::MIN.to_u32(), Some(u64::MIN as u32));
- assert_eq!(u64::MIN.to_u64(), Some(u64::MIN as u64));
- }
-
- #[test]
- fn test_cast_range_uint_max() {
- assert_eq!(usize::MAX.to_int(), None);
- assert_eq!(usize::MAX.to_i8(), None);
- assert_eq!(usize::MAX.to_i16(), None);
- assert_eq!(usize::MAX.to_i32(), None);
- // usize::MAX.to_i64() is word-size specific
- assert_eq!(usize::MAX.to_u8(), None);
- assert_eq!(usize::MAX.to_u16(), None);
- // usize::MAX.to_u32() is word-size specific
- assert_eq!(usize::MAX.to_u64(), Some(usize::MAX as u64));
-
- #[cfg(target_pointer_width = "32")]
- fn check_word_size() {
- assert_eq!(usize::MAX.to_u32(), Some(usize::MAX as u32));
- assert_eq!(usize::MAX.to_i64(), Some(usize::MAX as i64));
- }
-
- #[cfg(target_pointer_width = "64")]
- fn check_word_size() {
- assert_eq!(usize::MAX.to_u32(), None);
- assert_eq!(usize::MAX.to_i64(), None);
- }
-
- check_word_size();
- }
-
- #[test]
- fn test_cast_range_u8_max() {
- assert_eq!(u8::MAX.to_int(), Some(u8::MAX as isize));
- assert_eq!(u8::MAX.to_i8(), None);
- assert_eq!(u8::MAX.to_i16(), Some(u8::MAX as i16));
- assert_eq!(u8::MAX.to_i32(), Some(u8::MAX as i32));
- assert_eq!(u8::MAX.to_i64(), Some(u8::MAX as i64));
- assert_eq!(u8::MAX.to_uint(), Some(u8::MAX as usize));
- assert_eq!(u8::MAX.to_u8(), Some(u8::MAX as u8));
- assert_eq!(u8::MAX.to_u16(), Some(u8::MAX as u16));
- assert_eq!(u8::MAX.to_u32(), Some(u8::MAX as u32));
- assert_eq!(u8::MAX.to_u64(), Some(u8::MAX as u64));
- }
-
- #[test]
- fn test_cast_range_u16_max() {
- assert_eq!(u16::MAX.to_int(), Some(u16::MAX as isize));
- assert_eq!(u16::MAX.to_i8(), None);
- assert_eq!(u16::MAX.to_i16(), None);
- assert_eq!(u16::MAX.to_i32(), Some(u16::MAX as i32));
- assert_eq!(u16::MAX.to_i64(), Some(u16::MAX as i64));
- assert_eq!(u16::MAX.to_uint(), Some(u16::MAX as usize));
- assert_eq!(u16::MAX.to_u8(), None);
- assert_eq!(u16::MAX.to_u16(), Some(u16::MAX as u16));
- assert_eq!(u16::MAX.to_u32(), Some(u16::MAX as u32));
- assert_eq!(u16::MAX.to_u64(), Some(u16::MAX as u64));
- }
-
- #[test]
- fn test_cast_range_u32_max() {
- // u32::MAX.to_int() is word-size specific
- assert_eq!(u32::MAX.to_i8(), None);
- assert_eq!(u32::MAX.to_i16(), None);
- assert_eq!(u32::MAX.to_i32(), None);
- assert_eq!(u32::MAX.to_i64(), Some(u32::MAX as i64));
- assert_eq!(u32::MAX.to_uint(), Some(u32::MAX as usize));
- assert_eq!(u32::MAX.to_u8(), None);
- assert_eq!(u32::MAX.to_u16(), None);
- assert_eq!(u32::MAX.to_u32(), Some(u32::MAX as u32));
- assert_eq!(u32::MAX.to_u64(), Some(u32::MAX as u64));
-
- #[cfg(target_pointer_width = "32")]
- fn check_word_size() {
- assert_eq!(u32::MAX.to_int(), None);
- }
-
- #[cfg(target_pointer_width = "64")]
- fn check_word_size() {
- assert_eq!(u32::MAX.to_int(), Some(u32::MAX as isize));
- }
-
- check_word_size();
- }
-
- #[test]
- fn test_cast_range_u64_max() {
- assert_eq!(u64::MAX.to_int(), None);
- assert_eq!(u64::MAX.to_i8(), None);
- assert_eq!(u64::MAX.to_i16(), None);
- assert_eq!(u64::MAX.to_i32(), None);
- assert_eq!(u64::MAX.to_i64(), None);
- // u64::MAX.to_uint() is word-size specific
- assert_eq!(u64::MAX.to_u8(), None);
- assert_eq!(u64::MAX.to_u16(), None);
- assert_eq!(u64::MAX.to_u32(), None);
- assert_eq!(u64::MAX.to_u64(), Some(u64::MAX as u64));
-
- #[cfg(target_pointer_width = "32")]
- fn check_word_size() {
- assert_eq!(u64::MAX.to_uint(), None);
- }
-
- #[cfg(target_pointer_width = "64")]
- fn check_word_size() {
- assert_eq!(u64::MAX.to_uint(), Some(u64::MAX as usize));
- }
-
- check_word_size();
- }
+ use ops::Mul;
#[test]
fn test_saturating_add_uint() {
#[test]
fn test_saturating_add_int() {
use isize::{MIN,MAX};
- assert_eq!(3.saturating_add(5), 8);
- assert_eq!(3.saturating_add(MAX-1), MAX);
+ assert_eq!(3i32.saturating_add(5), 8);
+ assert_eq!(3isize.saturating_add(MAX-1), MAX);
assert_eq!(MAX.saturating_add(MAX), MAX);
assert_eq!((MAX-2).saturating_add(1), MAX-1);
- assert_eq!(3.saturating_add(-5), -2);
+ assert_eq!(3i32.saturating_add(-5), -2);
assert_eq!(MIN.saturating_add(-1), MIN);
- assert_eq!((-2).saturating_add(-MAX), MIN);
+ assert_eq!((-2isize).saturating_add(-MAX), MIN);
}
#[test]
fn test_saturating_sub_int() {
use isize::{MIN,MAX};
- assert_eq!(3.saturating_sub(5), -2);
+ assert_eq!(3i32.saturating_sub(5), -2);
assert_eq!(MIN.saturating_sub(1), MIN);
- assert_eq!((-2).saturating_sub(MAX), MIN);
- assert_eq!(3.saturating_sub(-5), 8);
- assert_eq!(3.saturating_sub(-(MAX-1)), MAX);
+ assert_eq!((-2isize).saturating_sub(MAX), MIN);
+ assert_eq!(3i32.saturating_sub(-5), 8);
+ assert_eq!(3isize.saturating_sub(-(MAX-1)), MAX);
assert_eq!(MAX.saturating_sub(-MAX), MAX);
assert_eq!((MAX-2).saturating_sub(-1), MAX-1);
}
test_checked_next_power_of_two! { test_checked_next_power_of_two_u64, u64 }
test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, usize }
- #[derive(PartialEq, Debug)]
- struct Value { x: isize }
-
- impl ToPrimitive for Value {
- fn to_i64(&self) -> Option<i64> { self.x.to_i64() }
- fn to_u64(&self) -> Option<u64> { self.x.to_u64() }
- }
-
- impl FromPrimitive for Value {
- fn from_i64(n: i64) -> Option<Value> { Some(Value { x: n as isize }) }
- fn from_u64(n: u64) -> Option<Value> { Some(Value { x: n as isize }) }
- }
-
- #[test]
- fn test_to_primitive() {
- let value = Value { x: 5 };
- assert_eq!(value.to_int(), Some(5));
- assert_eq!(value.to_i8(), Some(5));
- assert_eq!(value.to_i16(), Some(5));
- assert_eq!(value.to_i32(), Some(5));
- assert_eq!(value.to_i64(), Some(5));
- assert_eq!(value.to_uint(), Some(5));
- assert_eq!(value.to_u8(), Some(5));
- assert_eq!(value.to_u16(), Some(5));
- assert_eq!(value.to_u32(), Some(5));
- assert_eq!(value.to_u64(), Some(5));
- assert_eq!(value.to_f32(), Some(5f32));
- assert_eq!(value.to_f64(), Some(5f64));
- }
-
- #[test]
- fn test_from_primitive() {
- assert_eq!(from_int(5), Some(Value { x: 5 }));
- assert_eq!(from_i8(5), Some(Value { x: 5 }));
- assert_eq!(from_i16(5), Some(Value { x: 5 }));
- assert_eq!(from_i32(5), Some(Value { x: 5 }));
- assert_eq!(from_i64(5), Some(Value { x: 5 }));
- assert_eq!(from_uint(5), Some(Value { x: 5 }));
- assert_eq!(from_u8(5), Some(Value { x: 5 }));
- assert_eq!(from_u16(5), Some(Value { x: 5 }));
- assert_eq!(from_u32(5), Some(Value { x: 5 }));
- assert_eq!(from_u64(5), Some(Value { x: 5 }));
- assert_eq!(from_f32(5f32), Some(Value { x: 5 }));
- assert_eq!(from_f64(5f64), Some(Value { x: 5 }));
- }
-
#[test]
fn test_pow() {
- fn naive_pow<T: Int>(base: T, exp: usize) -> T {
- let one: T = Int::one();
+ fn naive_pow<T: Mul<Output=T> + One + Copy>(base: T, exp: usize) -> T {
+ let one: T = T::one();
(0..exp).fold(one, |acc, _| acc * base)
}
macro_rules! assert_pow {
assert_eq!(result, naive_pow($num, $exp));
}}
}
- assert_pow!((3, 0 ) => 1);
- assert_pow!((5, 1 ) => 5);
- assert_pow!((-4, 2 ) => 16);
- assert_pow!((8, 3 ) => 512);
- assert_pow!((2u64, 50) => 1125899906842624);
+ assert_pow!((3u32, 0 ) => 1);
+ assert_pow!((5u32, 1 ) => 5);
+ assert_pow!((-4i32, 2 ) => 16);
+ assert_pow!((8u32, 3 ) => 512);
+ assert_pow!((2u64, 50) => 1125899906842624);
}
#[test]
mod bench {
extern crate test;
use self::test::Bencher;
- use num::Int;
use prelude::v1::*;
#[bench]
fn bench_pow_function(b: &mut Bencher) {
- let v = (0..1024).collect::<Vec<_>>();
- b.iter(|| {v.iter().fold(0, |old, new| old.pow(*new as u32));});
+ let v = (0..1024).collect::<Vec<u32>>();
+ b.iter(|| {v.iter().fold(0u32, |old, new| old.pow(*new as u32));});
}
}
+++ /dev/null
-// Copyright 2013-2014 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.
-
-#![allow(missing_docs)]
-#![allow(deprecated)]
-
-use self::ExponentFormat::*;
-use self::SignificantDigits::*;
-use self::SignFormat::*;
-
-use char;
-use num::{self, Int, Float, ToPrimitive};
-use num::FpCategory as Fp;
-use ops::FnMut;
-use string::String;
-use vec::Vec;
-
-/// A flag that specifies whether to use exponential (scientific) notation.
-#[derive(Copy, Clone)]
-pub enum ExponentFormat {
- /// Do not use exponential notation.
- ExpNone,
- /// Use exponential notation with the exponent having a base of 10 and the
- /// exponent sign being `e` or `E`. For example, 1000 would be printed
- /// 1e3.
- ExpDec,
- /// Use exponential notation with the exponent having a base of 2 and the
- /// exponent sign being `p` or `P`. For example, 8 would be printed 1p3.
- ExpBin,
-}
-
-/// The number of digits used for emitting the fractional part of a number, if
-/// any.
-#[derive(Copy, Clone)]
-pub enum SignificantDigits {
- /// All calculable digits will be printed.
- ///
- /// Note that bignums or fractions may cause a surprisingly large number
- /// of digits to be printed.
- DigAll,
-
- /// At most the given number of digits will be printed, truncating any
- /// trailing zeroes.
- DigMax(usize),
-
- /// Precisely the given number of digits will be printed.
- DigExact(usize)
-}
-
-/// How to emit the sign of a number.
-#[derive(Copy, Clone)]
-pub enum SignFormat {
- /// No sign will be printed. The exponent sign will also be emitted.
- SignNone,
- /// `-` will be printed for negative values, but no sign will be emitted
- /// for positive numbers.
- SignNeg,
- /// `+` will be printed for positive values, and `-` will be printed for
- /// negative values.
- SignAll,
-}
-
-/// Converts an integral number to its string representation as a byte vector.
-/// This is meant to be a common base implementation for all integral string
-/// conversion functions like `to_string()` or `to_str_radix()`.
-///
-/// # Arguments
-///
-/// - `num` - The number to convert. Accepts any number that
-/// implements the numeric traits.
-/// - `radix` - Base to use. Accepts only the values 2-36.
-/// - `sign` - How to emit the sign. Options are:
-/// - `SignNone`: No sign at all. Basically emits `abs(num)`.
-/// - `SignNeg`: Only `-` on negative values.
-/// - `SignAll`: Both `+` on positive, and `-` on negative numbers.
-/// - `f` - a callback which will be invoked for each ascii character
-/// which composes the string representation of this integer
-///
-/// # Panics
-///
-/// - Panics if `radix` < 2 or `radix` > 36.
-fn int_to_str_bytes_common<T, F>(num: T, radix: usize, sign: SignFormat, mut f: F) where
- T: Int,
- F: FnMut(u8),
-{
- assert!(2 <= radix && radix <= 36);
-
- let _0: T = Int::zero();
-
- let neg = num < _0;
- let radix_gen: T = num::cast(radix).unwrap();
-
- let mut deccum = num;
- // This is just for integral types, the largest of which is a u64. The
- // smallest base that we can have is 2, so the most number of digits we're
- // ever going to have is 64
- let mut buf = [0; 64];
- let mut cur = 0;
-
- // Loop at least once to make sure at least a `0` gets emitted.
- loop {
- // Calculate the absolute value of each digit instead of only
- // doing it once for the whole number because a
- // representable negative number doesn't necessary have an
- // representable additive inverse of the same type
- // (See twos complement). But we assume that for the
- // numbers [-35 .. 0] we always have [0 .. 35].
- let current_digit_signed = deccum % radix_gen;
- let current_digit = if current_digit_signed < _0 {
- _0 - current_digit_signed
- } else {
- current_digit_signed
- };
- buf[cur] = match current_digit.to_u8().unwrap() {
- i @ 0...9 => b'0' + i,
- i => b'a' + (i - 10),
- };
- cur += 1;
-
- deccum = deccum / radix_gen;
- // No more digits to calculate for the non-fractional part -> break
- if deccum == _0 { break; }
- }
-
- // Decide what sign to put in front
- match sign {
- SignNeg | SignAll if neg => { f(b'-'); }
- SignAll => { f(b'+'); }
- _ => ()
- }
-
- // We built the number in reverse order, so un-reverse it here
- while cur > 0 {
- cur -= 1;
- f(buf[cur]);
- }
-}
-
-/// Converts a number to its string representation as a byte vector.
-/// This is meant to be a common base implementation for all numeric string
-/// conversion functions like `to_string()` or `to_str_radix()`.
-///
-/// # Arguments
-///
-/// - `num` - The number to convert. Accepts any number that
-/// implements the numeric traits.
-/// - `radix` - Base to use. Accepts only the values 2-36. If the exponential notation
-/// is used, then this base is only used for the significand. The exponent
-/// itself always printed using a base of 10.
-/// - `negative_zero` - Whether to treat the special value `-0` as
-/// `-0` or as `+0`.
-/// - `sign` - How to emit the sign. See `SignFormat`.
-/// - `digits` - The amount of digits to use for emitting the fractional
-/// part, if any. See `SignificantDigits`.
-/// - `exp_format` - Whether or not to use the exponential (scientific) notation.
-/// See `ExponentFormat`.
-/// - `exp_capital` - Whether or not to use a capital letter for the exponent sign, if
-/// exponential notation is desired.
-///
-/// # Return value
-///
-/// A tuple containing the byte vector, and a boolean flag indicating
-/// whether it represents a special value like `inf`, `-inf`, `NaN` or not.
-/// It returns a tuple because there can be ambiguity between a special value
-/// and a number representation at higher bases.
-///
-/// # Panics
-///
-/// - Panics if `radix` < 2 or `radix` > 36.
-/// - Panics if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
-/// between digit and exponent sign `'e'`.
-/// - Panics if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
-/// between digit and exponent sign `'p'`.
-pub fn float_to_str_bytes_common<T: Float>(
- num: T, radix: u32, negative_zero: bool,
- sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool
- ) -> (Vec<u8>, bool) {
- assert!(2 <= radix && radix <= 36);
- match exp_format {
- ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
- => panic!("float_to_str_bytes_common: radix {} incompatible with \
- use of 'e' as decimal exponent", radix),
- ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
- => panic!("float_to_str_bytes_common: radix {} incompatible with \
- use of 'p' as binary exponent", radix),
- _ => ()
- }
-
- let _0: T = Float::zero();
- let _1: T = Float::one();
-
- match num.classify() {
- Fp::Nan => { return (b"NaN".to_vec(), true); }
- Fp::Infinite if num > _0 => {
- return match sign {
- SignAll => (b"+inf".to_vec(), true),
- _ => (b"inf".to_vec(), true)
- };
- }
- Fp::Infinite if num < _0 => {
- return match sign {
- SignNone => (b"inf".to_vec(), true),
- _ => (b"-inf".to_vec(), true),
- };
- }
- _ => {}
- }
-
- let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity());
- let mut buf = Vec::new();
- let radix_gen: T = num::cast(radix as isize).unwrap();
-
- let (num, exp) = match exp_format {
- ExpNone => (num, 0),
- ExpDec | ExpBin => {
- if num == _0 {
- (num, 0)
- } else {
- let (exp, exp_base) = match exp_format {
- ExpDec => (num.abs().log10().floor(), num::cast::<f64, T>(10.0f64).unwrap()),
- ExpBin => (num.abs().log2().floor(), num::cast::<f64, T>(2.0f64).unwrap()),
- ExpNone => unreachable!()
- };
-
- (num / exp_base.powf(exp), num::cast::<T, i32>(exp).unwrap())
- }
- }
- };
-
- // First emit the non-fractional part, looping at least once to make
- // sure at least a `0` gets emitted.
- let mut deccum = num.trunc();
- loop {
- // Calculate the absolute value of each digit instead of only
- // doing it once for the whole number because a
- // representable negative number doesn't necessary have an
- // representable additive inverse of the same type
- // (See twos complement). But we assume that for the
- // numbers [-35 .. 0] we always have [0 .. 35].
- let current_digit = (deccum % radix_gen).abs();
-
- // Decrease the deccumulator one digit at a time
- deccum = deccum / radix_gen;
- deccum = deccum.trunc();
-
- buf.push(char::from_digit(current_digit.to_isize().unwrap() as u32, radix)
- .unwrap() as u8);
-
- // No more digits to calculate for the non-fractional part -> break
- if deccum == _0 { break; }
- }
-
- // If limited digits, calculate one digit more for rounding.
- let (limit_digits, digit_count, exact) = match digits {
- DigAll => (false, 0, false),
- DigMax(count) => (true, count+1, false),
- DigExact(count) => (true, count+1, true)
- };
-
- // Decide what sign to put in front
- match sign {
- SignNeg | SignAll if neg => {
- buf.push(b'-');
- }
- SignAll => {
- buf.push(b'+');
- }
- _ => ()
- }
-
- buf.reverse();
-
- // Remember start of the fractional digits.
- // Points one beyond end of buf if none get generated,
- // or at the '.' otherwise.
- let start_fractional_digits = buf.len();
-
- // Now emit the fractional part, if any
- deccum = num.fract();
- if deccum != _0 || (limit_digits && exact && digit_count > 0) {
- buf.push(b'.');
- let mut dig = 0;
-
- // calculate new digits while
- // - there is no limit and there are digits left
- // - or there is a limit, it's not reached yet and
- // - it's exact
- // - or it's a maximum, and there are still digits left
- while (!limit_digits && deccum != _0)
- || (limit_digits && dig < digit_count && (
- exact
- || (!exact && deccum != _0)
- )
- ) {
- // Shift first fractional digit into the integer part
- deccum = deccum * radix_gen;
-
- // Calculate the absolute value of each digit.
- // See note in first loop.
- let current_digit = deccum.trunc().abs();
-
- buf.push(char::from_digit(
- current_digit.to_isize().unwrap() as u32, radix).unwrap() as u8);
-
- // Decrease the deccumulator one fractional digit at a time
- deccum = deccum.fract();
- dig += 1;
- }
-
- // If digits are limited, and that limit has been reached,
- // cut off the one extra digit, and depending on its value
- // round the remaining ones.
- if limit_digits && dig == digit_count {
- let ascii2value = |chr: u8| {
- (chr as char).to_digit(radix).unwrap()
- };
- let value2ascii = |val: u32| {
- char::from_digit(val, radix).unwrap() as u8
- };
-
- let extra_digit = ascii2value(buf.pop().unwrap());
- if extra_digit >= radix / 2 { // -> need to round
- let mut i: isize = buf.len() as isize - 1;
- loop {
- // If reached left end of number, have to
- // insert additional digit:
- if i < 0
- || buf[i as usize] == b'-'
- || buf[i as usize] == b'+' {
- buf.insert((i + 1) as usize, value2ascii(1));
- break;
- }
-
- // Skip the '.'
- if buf[i as usize] == b'.' { i -= 1; continue; }
-
- // Either increment the digit,
- // or set to 0 if max and carry the 1.
- let current_digit = ascii2value(buf[i as usize]);
- if current_digit < (radix - 1) {
- buf[i as usize] = value2ascii(current_digit+1);
- break;
- } else {
- buf[i as usize] = value2ascii(0);
- i -= 1;
- }
- }
- }
- }
- }
-
- // if number of digits is not exact, remove all trailing '0's up to
- // and including the '.'
- if !exact {
- let buf_max_i = buf.len() - 1;
-
- // index to truncate from
- let mut i = buf_max_i;
-
- // discover trailing zeros of fractional part
- while i > start_fractional_digits && buf[i] == b'0' {
- i -= 1;
- }
-
- // Only attempt to truncate digits if buf has fractional digits
- if i >= start_fractional_digits {
- // If buf ends with '.', cut that too.
- if buf[i] == b'.' { i -= 1 }
-
- // only resize buf if we actually remove digits
- if i < buf_max_i {
- buf = buf[.. (i + 1)].to_vec();
- }
- }
- } // If exact and trailing '.', just cut that
- else {
- let max_i = buf.len() - 1;
- if buf[max_i] == b'.' {
- buf = buf[.. max_i].to_vec();
- }
- }
-
- match exp_format {
- ExpNone => (),
- _ => {
- buf.push(match exp_format {
- ExpDec if exp_upper => 'E',
- ExpDec if !exp_upper => 'e',
- ExpBin if exp_upper => 'P',
- ExpBin if !exp_upper => 'p',
- _ => unreachable!()
- } as u8);
-
- int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c));
- }
- }
-
- (buf, false)
-}
-
-/// Converts a number to its string representation. This is a wrapper for
-/// `to_str_bytes_common()`, for details see there.
-#[inline]
-pub fn float_to_str_common<T: Float>(
- num: T, radix: u32, negative_zero: bool,
- sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool
- ) -> (String, bool) {
- let (bytes, special) = float_to_str_bytes_common(num, radix,
- negative_zero, sign, digits, exp_format, exp_capital);
- (String::from_utf8(bytes).unwrap(), special)
-}
-
-// Some constants for from_str_bytes_common's input validation,
-// they define minimum radix values for which the character is a valid digit.
-const DIGIT_P_RADIX: u32 = ('p' as u32) - ('a' as u32) + 11;
-const DIGIT_E_RADIX: u32 = ('e' as u32) - ('a' as u32) + 11;
-
-#[cfg(test)]
-mod tests {
- use core::num::wrapping::WrappingOps;
- use string::ToString;
-
- #[test]
- fn test_int_to_str_overflow() {
- let mut i8_val: i8 = 127;
- assert_eq!(i8_val.to_string(), "127");
-
- i8_val = i8_val.wrapping_add(1);
- assert_eq!(i8_val.to_string(), "-128");
-
- let mut i16_val: i16 = 32_767;
- assert_eq!(i16_val.to_string(), "32767");
-
- i16_val = i16_val.wrapping_add(1);
- assert_eq!(i16_val.to_string(), "-32768");
-
- let mut i32_val: i32 = 2_147_483_647;
- assert_eq!(i32_val.to_string(), "2147483647");
-
- i32_val = i32_val.wrapping_add(1);
- assert_eq!(i32_val.to_string(), "-2147483648");
-
- let mut i64_val: i64 = 9_223_372_036_854_775_807;
- assert_eq!(i64_val.to_string(), "9223372036854775807");
-
- i64_val = i64_val.wrapping_add(1);
- assert_eq!(i64_val.to_string(), "-9223372036854775808");
- }
-}
-
-#[cfg(test)]
-mod bench {
- #![allow(deprecated)] // rand
- extern crate test;
-
- mod usize {
- use super::test::Bencher;
- use rand::{thread_rng, Rng};
- use std::fmt;
-
- #[inline]
- fn to_string(x: usize, base: u8) {
- format!("{}", fmt::radix(x, base));
- }
-
- #[bench]
- fn to_str_bin(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { to_string(rng.gen::<usize>(), 2); })
- }
-
- #[bench]
- fn to_str_oct(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { to_string(rng.gen::<usize>(), 8); })
- }
-
- #[bench]
- fn to_str_dec(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { to_string(rng.gen::<usize>(), 10); })
- }
-
- #[bench]
- fn to_str_hex(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { to_string(rng.gen::<usize>(), 16); })
- }
-
- #[bench]
- fn to_str_base_36(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { to_string(rng.gen::<usize>(), 36); })
- }
- }
-
- mod isize {
- use super::test::Bencher;
- use rand::{thread_rng, Rng};
- use std::fmt;
-
- #[inline]
- fn to_string(x: isize, base: u8) {
- format!("{}", fmt::radix(x, base));
- }
-
- #[bench]
- fn to_str_bin(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { to_string(rng.gen::<isize>(), 2); })
- }
-
- #[bench]
- fn to_str_oct(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { to_string(rng.gen::<isize>(), 8); })
- }
-
- #[bench]
- fn to_str_dec(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { to_string(rng.gen::<isize>(), 10); })
- }
-
- #[bench]
- fn to_str_hex(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { to_string(rng.gen::<isize>(), 16); })
- }
-
- #[bench]
- fn to_str_base_36(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { to_string(rng.gen::<isize>(), 36); })
- }
- }
-
- mod f64 {
- use super::test::Bencher;
- use rand::{thread_rng, Rng};
- use f64;
-
- #[bench]
- fn float_to_string(b: &mut Bencher) {
- let mut rng = thread_rng();
- b.iter(|| { f64::to_string(rng.gen()); })
- }
- }
-}
#![doc(hidden)]
#![allow(unsigned_negation)]
-macro_rules! uint_module { ($T:ty) => (
+macro_rules! uint_module { ($T:ident) => (
#[cfg(test)]
mod tests {
use prelude::v1::*;
- use num::FromStrRadix;
fn from_str<T: ::str::FromStr>(t: &str) -> Option<T> {
::str::FromStr::from_str(t).ok()
#[test]
pub fn test_parse_bytes() {
- 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 u16));
- assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Ok(65535 as u16));
- assert_eq!(FromStrRadix::from_str_radix("z", 36), Ok(35 as $T));
-
- assert_eq!(FromStrRadix::from_str_radix("Z", 10).ok(), None::<$T>);
- assert_eq!(FromStrRadix::from_str_radix("_", 2).ok(), None::<$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!(u16::from_str_radix("123", 16), Ok(291 as u16));
+ assert_eq!(u16::from_str_radix("ffff", 16), Ok(65535 as u16));
+ assert_eq!($T::from_str_radix("z", 36), Ok(35 as $T));
+
+ assert_eq!($T::from_str_radix("Z", 10).ok(), None::<$T>);
+ assert_eq!($T::from_str_radix("_", 2).ok(), None::<$T>);
}
}
use sys::stdio::Stderr;
use thread;
-// Defined in this module instead of old_io::stdio so that the unwinding
thread_local! {
pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
RefCell::new(None)
use ascii::*;
use borrow::{Borrow, IntoCow, ToOwned, Cow};
use cmp;
-use iter::{self, IntoIterator};
+use iter;
use mem;
use ops::{self, Deref};
use string::String;
use vec::Vec;
use fmt;
-use ffi::{OsStr, OsString, AsOsStr};
+use ffi::{OsStr, OsString};
use self::platform::{is_sep_byte, is_verbatim_sep, MAIN_SEP_STR, parse_prefix};
}
}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
-impl AsOsStr for PathBuf {
- fn as_os_str(&self) -> &OsStr {
- &self.inner[..]
- }
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl Into<OsString> for PathBuf {
fn into(self) -> OsString {
}
}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
-impl AsOsStr for Path {
- fn as_os_str(&self) -> &OsStr {
- &self.inner
- }
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Path {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
}
}
-/// Freely convertible to a `Path`.
-#[unstable(feature = "std_misc")]
-#[deprecated(since = "1.0.0", reason = "use std::convert::AsRef<Path> instead")]
-pub trait AsPath {
- /// Converts to a `Path`.
- #[unstable(feature = "std_misc")]
- fn as_path(&self) -> &Path;
-}
-
-#[unstable(feature = "std_misc")]
-#[deprecated(since = "1.0.0", reason = "use std::convert::AsRef<Path> instead")]
-#[allow(deprecated)]
-impl<T: AsOsStr + ?Sized> AsPath for T {
- fn as_path(&self) -> &Path { Path::new(self.as_os_str()) }
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for Path {
fn as_ref(&self) -> &Path { self }
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use boxed::Box;
#[stable(feature = "rust1", since = "1.0.0")]
+#[doc(no_inline)] pub use borrow::ToOwned;
+#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use clone::Clone;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
-#[unstable(feature = "convert")]
+#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From};
#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use iter::DoubleEndedIterator;
+#[doc(no_inline)] pub use default::Default;
#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use iter::ExactSizeIterator;
+#[doc(no_inline)] pub use iter::{Iterator, Extend, IntoIterator};
#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use iter::{Iterator, Extend};
+#[doc(no_inline)] pub use iter::{DoubleEndedIterator, ExactSizeIterator};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use option::Option::{self, Some, None};
#[stable(feature = "rust1", since = "1.0.0")]
use prelude::v1::*;
use super::ReaderRng;
- use num::Int;
use rand::Rng;
#[test]
0, 0, 0, 0, 0, 0, 0, 3][..];
let mut rng = ReaderRng::new(v);
- assert_eq!(rng.next_u64(), 1.to_be());
- assert_eq!(rng.next_u64(), 2.to_be());
- assert_eq!(rng.next_u64(), 3.to_be());
+ assert_eq!(rng.next_u64(), 1u64.to_be());
+ assert_eq!(rng.next_u64(), 2u64.to_be());
+ assert_eq!(rng.next_u64(), 3u64.to_be());
}
#[test]
fn test_reader_rng_u32() {
let v = &[0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3][..];
let mut rng = ReaderRng::new(v);
- assert_eq!(rng.next_u32(), 1.to_be());
- assert_eq!(rng.next_u32(), 2.to_be());
- assert_eq!(rng.next_u32(), 3.to_be());
+ assert_eq!(rng.next_u32(), 1u32.to_be());
+ assert_eq!(rng.next_u32(), 2u32.to_be());
+ assert_eq!(rng.next_u32(), 3u32.to_be());
}
#[test]
fn test_reader_rng_fill_bytes() {
}
}
- /// Deprecated: use `wait_timeout_ms` instead.
- #[unstable(feature = "std_misc")]
- #[deprecated(since = "1.0.0", reason = "use wait_timeout_ms instead")]
- pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration)
- -> LockResult<(MutexGuard<'a, T>, bool)> {
- self.wait_timeout_ms(guard, dur.num_milliseconds() as u32)
- }
-
/// Waits on this condition variable for a notification, timing out after a
/// specified duration.
///
+++ /dev/null
-// Copyright 2013-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.
-
-#![allow(deprecated)]
-
-use prelude::v1::*;
-use self::SocketStatus::*;
-use self::InAddr::*;
-
-use ffi::{CString, CStr};
-use old_io::net::addrinfo;
-use old_io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
-use old_io::{IoResult, IoError};
-use libc::{self, c_char, c_int};
-use mem;
-use num::Int;
-use ptr::{self, null, null_mut};
-use str;
-use sys::{self, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
- wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
- decode_error_detailed};
-use sync::{Arc, Mutex};
-#[cfg(not(target_os = "linux"))]
-use sync::MutexGuard;
-use sys_common::{self, keep_going, short_write, timeout};
-use cmp;
-use old_io;
-
-// FIXME: move uses of Arc and deadline tracking to std::io
-
-#[derive(Debug)]
-pub enum SocketStatus {
- Readable,
- Writable,
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// sockaddr and misc bindings
-////////////////////////////////////////////////////////////////////////////////
-
-pub fn htons(u: u16) -> u16 {
- u.to_be()
-}
-pub fn ntohs(u: u16) -> u16 {
- Int::from_be(u)
-}
-
-pub enum InAddr {
- In4Addr(libc::in_addr),
- In6Addr(libc::in6_addr),
-}
-
-pub fn ip_to_inaddr(ip: IpAddr) -> InAddr {
- match ip {
- Ipv4Addr(a, b, c, d) => {
- let ip = ((a as u32) << 24) |
- ((b as u32) << 16) |
- ((c as u32) << 8) |
- ((d as u32) << 0);
- In4Addr(libc::in_addr {
- s_addr: Int::from_be(ip)
- })
- }
- Ipv6Addr(a, b, c, d, e, f, g, h) => {
- In6Addr(libc::in6_addr {
- s6_addr: [
- htons(a),
- htons(b),
- htons(c),
- htons(d),
- htons(e),
- htons(f),
- htons(g),
- htons(h),
- ]
- })
- }
- }
-}
-
-pub fn addr_to_sockaddr(addr: SocketAddr,
- storage: &mut libc::sockaddr_storage)
- -> libc::socklen_t {
- unsafe {
- let len = match ip_to_inaddr(addr.ip) {
- In4Addr(inaddr) => {
- let storage = storage as *mut _ as *mut libc::sockaddr_in;
- (*storage).sin_family = libc::AF_INET as libc::sa_family_t;
- (*storage).sin_port = htons(addr.port);
- (*storage).sin_addr = inaddr;
- mem::size_of::<libc::sockaddr_in>()
- }
- In6Addr(inaddr) => {
- let storage = storage as *mut _ as *mut libc::sockaddr_in6;
- (*storage).sin6_family = libc::AF_INET6 as libc::sa_family_t;
- (*storage).sin6_port = htons(addr.port);
- (*storage).sin6_addr = inaddr;
- mem::size_of::<libc::sockaddr_in6>()
- }
- };
- return len as libc::socklen_t;
- }
-}
-
-pub fn socket(addr: SocketAddr, ty: libc::c_int) -> IoResult<sock_t> {
- unsafe {
- let fam = match addr.ip {
- Ipv4Addr(..) => libc::AF_INET,
- Ipv6Addr(..) => libc::AF_INET6,
- };
- match libc::socket(fam, ty, 0) as i32 {
- -1 => Err(last_net_error()),
- fd => Ok(fd as sock_t),
- }
- }
-}
-
-pub fn setsockopt<T>(fd: sock_t, opt: libc::c_int, val: libc::c_int,
- payload: T) -> IoResult<()> {
- unsafe {
- let payload = &payload as *const T as *const libc::c_void;
- let ret = libc::setsockopt(fd, opt, val,
- payload,
- mem::size_of::<T>() as libc::socklen_t);
- if ret != 0 {
- Err(last_net_error())
- } else {
- Ok(())
- }
- }
-}
-
-pub fn getsockopt<T: Copy>(fd: sock_t, opt: libc::c_int,
- val: libc::c_int) -> IoResult<T> {
- unsafe {
- let mut slot: T = mem::zeroed();
- let mut len = mem::size_of::<T>() as libc::socklen_t;
- let ret = c::getsockopt(fd, opt, val,
- &mut slot as *mut _ as *mut _,
- &mut len);
- if ret != 0 {
- Err(last_net_error())
- } else {
- assert!(len as usize == mem::size_of::<T>());
- Ok(slot)
- }
- }
-}
-
-pub fn sockname(fd: sock_t,
- f: unsafe extern "system" fn(sock_t, *mut libc::sockaddr,
- *mut libc::socklen_t) -> libc::c_int)
- -> IoResult<SocketAddr>
-{
- let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
- let mut len = mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
- unsafe {
- let storage = &mut storage as *mut libc::sockaddr_storage;
- let ret = f(fd,
- storage as *mut libc::sockaddr,
- &mut len as *mut libc::socklen_t);
- if ret != 0 {
- return Err(last_net_error())
- }
- }
- return sockaddr_to_addr(&storage, len as usize);
-}
-
-pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
- len: usize) -> IoResult<SocketAddr> {
- match storage.ss_family as libc::c_int {
- libc::AF_INET => {
- assert!(len as usize >= mem::size_of::<libc::sockaddr_in>());
- let storage: &libc::sockaddr_in = unsafe {
- mem::transmute(storage)
- };
- let ip = (storage.sin_addr.s_addr as u32).to_be();
- let a = (ip >> 24) as u8;
- let b = (ip >> 16) as u8;
- let c = (ip >> 8) as u8;
- let d = (ip >> 0) as u8;
- Ok(SocketAddr {
- ip: Ipv4Addr(a, b, c, d),
- port: ntohs(storage.sin_port),
- })
- }
- libc::AF_INET6 => {
- assert!(len as usize >= mem::size_of::<libc::sockaddr_in6>());
- let storage: &libc::sockaddr_in6 = unsafe {
- mem::transmute(storage)
- };
- let a = ntohs(storage.sin6_addr.s6_addr[0]);
- let b = ntohs(storage.sin6_addr.s6_addr[1]);
- let c = ntohs(storage.sin6_addr.s6_addr[2]);
- let d = ntohs(storage.sin6_addr.s6_addr[3]);
- let e = ntohs(storage.sin6_addr.s6_addr[4]);
- let f = ntohs(storage.sin6_addr.s6_addr[5]);
- let g = ntohs(storage.sin6_addr.s6_addr[6]);
- let h = ntohs(storage.sin6_addr.s6_addr[7]);
- Ok(SocketAddr {
- ip: Ipv6Addr(a, b, c, d, e, f, g, h),
- port: ntohs(storage.sin6_port),
- })
- }
- _ => {
- Err(IoError {
- kind: old_io::InvalidInput,
- desc: "invalid argument",
- detail: None,
- })
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// get_host_addresses
-////////////////////////////////////////////////////////////////////////////////
-
-extern "system" {
- fn getaddrinfo(node: *const c_char, service: *const c_char,
- hints: *const libc::addrinfo,
- res: *mut *mut libc::addrinfo) -> c_int;
- fn freeaddrinfo(res: *mut libc::addrinfo);
-}
-
-pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>,
- hint: Option<addrinfo::Hint>)
- -> Result<Vec<addrinfo::Info>, IoError>
-{
- sys::init_net();
-
- assert!(host.is_some() || servname.is_some());
-
- let c_host = match host {
- Some(x) => Some(try!(CString::new(x))),
- None => None,
- };
- let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
- let c_serv = match servname {
- Some(x) => Some(try!(CString::new(x))),
- None => None,
- };
- let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
-
- let hint = hint.map(|hint| {
- libc::addrinfo {
- ai_flags: hint.flags as c_int,
- ai_family: hint.family as c_int,
- ai_socktype: 0,
- ai_protocol: 0,
- ai_addrlen: 0,
- ai_canonname: null_mut(),
- ai_addr: null_mut(),
- ai_next: null_mut()
- }
- });
-
- let hint_ptr = hint.as_ref().map_or(null(), |x| {
- x as *const libc::addrinfo
- });
- let mut res = null_mut();
-
- // Make the call
- let s = unsafe {
- getaddrinfo(c_host, c_serv, hint_ptr, &mut res)
- };
-
- // Error?
- if s != 0 {
- return Err(last_gai_error(s));
- }
-
- // Collect all the results we found
- let mut addrs = Vec::new();
- let mut rp = res;
- while !rp.is_null() {
- unsafe {
- let addr = try!(sockaddr_to_addr(mem::transmute((*rp).ai_addr),
- (*rp).ai_addrlen as usize));
- addrs.push(addrinfo::Info {
- address: addr,
- family: (*rp).ai_family as usize,
- socktype: None,
- protocol: None,
- flags: (*rp).ai_flags as usize
- });
-
- rp = (*rp).ai_next as *mut libc::addrinfo;
- }
- }
-
- unsafe { freeaddrinfo(res); }
-
- Ok(addrs)
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// get_address_name
-////////////////////////////////////////////////////////////////////////////////
-
-extern "system" {
- fn getnameinfo(sa: *const libc::sockaddr, salen: libc::socklen_t,
- host: *mut c_char, hostlen: libc::size_t,
- serv: *mut c_char, servlen: libc::size_t,
- flags: c_int) -> c_int;
-}
-
-const NI_MAXHOST: usize = 1025;
-
-pub fn get_address_name(addr: IpAddr) -> Result<String, IoError> {
- let addr = SocketAddr{ip: addr, port: 0};
-
- let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
- let len = addr_to_sockaddr(addr, &mut storage);
-
- let mut hostbuf = [0 as c_char; NI_MAXHOST];
-
- let res = unsafe {
- getnameinfo(&storage as *const _ as *const libc::sockaddr, len,
- hostbuf.as_mut_ptr(), NI_MAXHOST as libc::size_t,
- ptr::null_mut(), 0,
- 0)
- };
-
- if res != 0 {
- return Err(last_gai_error(res));
- }
-
- unsafe {
- let data = CStr::from_ptr(hostbuf.as_ptr());
- Ok(str::from_utf8(data.to_bytes()).unwrap().to_string())
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Timeout helpers
-//
-// The read/write functions below are the helpers for reading/writing a socket
-// with a possible deadline specified. This is generally viewed as a timed out
-// I/O operation.
-//
-// From the application's perspective, timeouts apply to the I/O object, not to
-// the underlying file descriptor (it's one timeout per object). This means that
-// we can't use the SO_RCVTIMEO and corresponding send timeout option.
-//
-// The next idea to implement timeouts would be to use nonblocking I/O. An
-// invocation of select() would wait (with a timeout) for a socket to be ready.
-// Once its ready, we can perform the operation. Note that the operation *must*
-// be nonblocking, even though select() says the socket is ready. This is
-// because some other thread could have come and stolen our data (handles can be
-// cloned).
-//
-// To implement nonblocking I/O, the first option we have is to use the
-// O_NONBLOCK flag. Remember though that this is a global setting, affecting all
-// I/O objects, so this was initially viewed as unwise.
-//
-// It turns out that there's this nifty MSG_DONTWAIT flag which can be passed to
-// send/recv, but the niftiness wears off once you realize it only works well on
-// Linux [1] [2]. This means that it's pretty easy to get a nonblocking
-// operation on Linux (no flag fiddling, no affecting other objects), but not on
-// other platforms.
-//
-// To work around this constraint on other platforms, we end up using the
-// original strategy of flipping the O_NONBLOCK flag. As mentioned before, this
-// could cause other objects' blocking operations to suddenly become
-// nonblocking. To get around this, a "blocking operation" which returns EAGAIN
-// falls back to using the same code path as nonblocking operations, but with an
-// infinite timeout (select + send/recv). This helps emulate blocking
-// reads/writes despite the underlying descriptor being nonblocking, as well as
-// optimizing the fast path of just hitting one syscall in the good case.
-//
-// As a final caveat, this implementation uses a mutex so only one thread is
-// doing a nonblocking operation at at time. This is the operation that comes
-// after the select() (at which point we think the socket is ready). This is
-// done for sanity to ensure that the state of the O_NONBLOCK flag is what we
-// expect (wouldn't want someone turning it on when it should be off!). All
-// operations performed in the lock are *nonblocking* to avoid holding the mutex
-// forever.
-//
-// So, in summary, Linux uses MSG_DONTWAIT and doesn't need mutexes, everyone
-// else uses O_NONBLOCK and mutexes with some trickery to make sure blocking
-// reads/writes are still blocking.
-//
-// Fun, fun!
-//
-// [1] http://twistedmatrix.com/pipermail/twisted-commits/2012-April/034692.html
-// [2] http://stackoverflow.com/questions/19819198/does-send-msg-dontwait
-
-pub fn read<T, L, R>(fd: sock_t, deadline: u64, mut lock: L, mut read: R) -> IoResult<usize> where
- L: FnMut() -> T,
- R: FnMut(bool) -> libc::c_int,
-{
- let mut ret = -1;
- if deadline == 0 {
- ret = retry(|| read(false));
- }
-
- if deadline != 0 || (ret == -1 && wouldblock()) {
- let deadline = match deadline {
- 0 => None,
- n => Some(n),
- };
- loop {
- // With a timeout, first we wait for the socket to become
- // readable using select(), specifying the relevant timeout for
- // our previously set deadline.
- try!(await(&[fd], deadline, Readable));
-
- // At this point, we're still within the timeout, and we've
- // determined that the socket is readable (as returned by
- // select). We must still read the socket in *nonblocking* mode
- // because some other thread could come steal our data. If we
- // fail to read some data, we retry (hence the outer loop) and
- // wait for the socket to become readable again.
- let _guard = lock();
- match retry(|| read(deadline.is_some())) {
- -1 if wouldblock() => {}
- -1 => return Err(last_net_error()),
- n => { ret = n; break }
- }
- }
- }
-
- match ret {
- 0 => Err(sys_common::eof()),
- n if n < 0 => Err(last_net_error()),
- n => Ok(n as usize)
- }
-}
-
-pub fn write<T, L, W>(fd: sock_t,
- deadline: u64,
- buf: &[u8],
- write_everything: bool,
- mut lock: L,
- mut write: W) -> IoResult<usize> where
- L: FnMut() -> T,
- W: FnMut(bool, *const u8, usize) -> i64,
-{
- let mut ret = -1;
- let mut written = 0;
- if deadline == 0 {
- if write_everything {
- ret = keep_going(buf, |inner, len| {
- written = buf.len() - len;
- write(false, inner, len)
- });
- } else {
- ret = retry(|| { write(false, buf.as_ptr(), buf.len()) });
- if ret > 0 { written = ret as usize; }
- }
- }
-
- if deadline != 0 || (ret == -1 && wouldblock()) {
- let deadline = match deadline {
- 0 => None,
- n => Some(n),
- };
- while written < buf.len() && (write_everything || written == 0) {
- // As with read(), first wait for the socket to be ready for
- // the I/O operation.
- match await(&[fd], deadline, Writable) {
- Err(ref e) if e.kind == old_io::EndOfFile && written > 0 => {
- assert!(deadline.is_some());
- return Err(short_write(written, "short write"))
- }
- Err(e) => return Err(e),
- Ok(()) => {}
- }
-
- // Also as with read(), we use MSG_DONTWAIT to guard ourselves
- // against unforeseen circumstances.
- let _guard = lock();
- let ptr = buf[written..].as_ptr();
- let len = buf.len() - written;
- match retry(|| write(deadline.is_some(), ptr, len)) {
- -1 if wouldblock() => {}
- -1 => return Err(last_net_error()),
- n => { written += n as usize; }
- }
- }
- ret = 0;
- }
- if ret < 0 {
- Err(last_net_error())
- } else {
- Ok(written)
- }
-}
-
-// See http://developerweb.net/viewtopic.php?id=3196 for where this is
-// derived from.
-pub fn connect_timeout(fd: sock_t,
- addrp: *const libc::sockaddr,
- len: libc::socklen_t,
- timeout_ms: u64) -> IoResult<()> {
- #[cfg(unix)] use libc::EINPROGRESS as INPROGRESS;
- #[cfg(windows)] use libc::WSAEINPROGRESS as INPROGRESS;
- #[cfg(unix)] use libc::EWOULDBLOCK as WOULDBLOCK;
- #[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK;
-
- // Make sure the call to connect() doesn't block
- set_nonblocking(fd, true);
-
- let ret = match unsafe { libc::connect(fd, addrp, len) } {
- // If the connection is in progress, then we need to wait for it to
- // finish (with a timeout). The current strategy for doing this is
- // to use select() with a timeout.
- -1 if os::errno() as isize == INPROGRESS as isize ||
- os::errno() as isize == WOULDBLOCK as isize => {
- let mut set: c::fd_set = unsafe { mem::zeroed() };
- c::fd_set(&mut set, fd);
- match await(fd, &mut set, timeout_ms) {
- 0 => Err(timeout("connection timed out")),
- -1 => Err(last_net_error()),
- _ => {
- let err: libc::c_int = try!(
- getsockopt(fd, libc::SOL_SOCKET, libc::SO_ERROR));
- if err == 0 {
- Ok(())
- } else {
- Err(decode_error_detailed(err))
- }
- }
- }
- }
-
- -1 => Err(last_net_error()),
- _ => Ok(()),
- };
-
- // be sure to turn blocking I/O back on
- set_nonblocking(fd, false);
- return ret;
-
- #[cfg(unix)]
- fn await(fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int {
- let start = timer::now();
- retry(|| unsafe {
- // Recalculate the timeout each iteration (it is generally
- // undefined what the value of the 'tv' is after select
- // returns EINTR).
- let mut tv = ms_to_timeval(timeout - (timer::now() - start));
- c::select(fd + 1, ptr::null_mut(), set as *mut _,
- ptr::null_mut(), &mut tv)
- })
- }
- #[cfg(windows)]
- fn await(_fd: sock_t, set: &mut c::fd_set, timeout: u64) -> libc::c_int {
- let mut tv = ms_to_timeval(timeout);
- unsafe { c::select(1, ptr::null_mut(), set, ptr::null_mut(), &mut tv) }
- }
-}
-
-pub fn await(fds: &[sock_t], deadline: Option<u64>,
- status: SocketStatus) -> IoResult<()> {
- let mut set: c::fd_set = unsafe { mem::zeroed() };
- let mut max = 0;
- for &fd in fds {
- c::fd_set(&mut set, fd);
- max = cmp::max(max, fd + 1);
- }
- if cfg!(windows) {
- max = fds.len() as sock_t;
- }
-
- let (read, write) = match status {
- Readable => (&mut set as *mut _, ptr::null_mut()),
- Writable => (ptr::null_mut(), &mut set as *mut _),
- };
- let mut tv: libc::timeval = unsafe { mem::zeroed() };
-
- match retry(|| {
- let now = timer::now();
- let tvp = match deadline {
- None => ptr::null_mut(),
- Some(deadline) => {
- // If we're past the deadline, then pass a 0 timeout to
- // select() so we can poll the status
- let ms = if deadline < now {0} else {deadline - now};
- tv = ms_to_timeval(ms);
- &mut tv as *mut _
- }
- };
- let r = unsafe {
- c::select(max as libc::c_int, read, write, ptr::null_mut(), tvp)
- };
- r
- }) {
- -1 => Err(last_net_error()),
- 0 => Err(timeout("timed out")),
- _ => Ok(()),
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Basic socket representation
-////////////////////////////////////////////////////////////////////////////////
-
-struct Inner {
- fd: sock_t,
-
- // Unused on Linux, where this lock is not necessary.
- #[allow(dead_code)]
- lock: Mutex<()>,
-}
-
-impl Inner {
- fn new(fd: sock_t) -> Inner {
- Inner { fd: fd, lock: Mutex::new(()) }
- }
-}
-
-impl Drop for Inner {
- fn drop(&mut self) { unsafe { close_sock(self.fd); } }
-}
-
-#[cfg(not(target_os = "linux"))]
-pub struct Guard<'a> {
- pub fd: sock_t,
- pub guard: MutexGuard<'a, ()>,
-}
-
-#[cfg(not(target_os = "linux"))]
-#[unsafe_destructor]
-impl<'a> Drop for Guard<'a> {
- fn drop(&mut self) {
- set_nonblocking(self.fd, false);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TCP streams
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct TcpStream {
- inner: Arc<Inner>,
- read_deadline: u64,
- write_deadline: u64,
-}
-
-impl TcpStream {
- pub fn connect(addr: SocketAddr, timeout: Option<u64>) -> IoResult<TcpStream> {
- sys::init_net();
-
- let fd = try!(socket(addr, libc::SOCK_STREAM));
- let ret = TcpStream::new(fd);
-
- let mut storage = unsafe { mem::zeroed() };
- let len = addr_to_sockaddr(addr, &mut storage);
- let addrp = &storage as *const _ as *const libc::sockaddr;
-
- match timeout {
- Some(timeout) => {
- try!(connect_timeout(fd, addrp, len, timeout));
- Ok(ret)
- },
- None => {
- match retry(|| unsafe { libc::connect(fd, addrp, len) }) {
- -1 => Err(last_error()),
- _ => Ok(ret),
- }
- }
- }
- }
-
- pub fn new(fd: sock_t) -> TcpStream {
- TcpStream {
- inner: Arc::new(Inner::new(fd)),
- read_deadline: 0,
- write_deadline: 0,
- }
- }
-
- pub fn fd(&self) -> sock_t { self.inner.fd }
-
- pub fn set_nodelay(&mut self, nodelay: bool) -> IoResult<()> {
- setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_NODELAY,
- nodelay as libc::c_int)
- }
-
- pub fn set_keepalive(&mut self, seconds: Option<usize>) -> IoResult<()> {
- let ret = setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_KEEPALIVE,
- seconds.is_some() as libc::c_int);
- match seconds {
- Some(n) => ret.and_then(|()| self.set_tcp_keepalive(n)),
- None => ret,
- }
- }
-
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> {
- setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPALIVE,
- seconds as libc::c_int)
- }
- #[cfg(any(target_os = "freebsd",
- target_os = "dragonfly"))]
- fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> {
- setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE,
- seconds as libc::c_int)
- }
- #[cfg(target_os = "openbsd")]
- fn set_tcp_keepalive(&mut self, seconds: usize) -> IoResult<()> {
- setsockopt(self.fd(), libc::IPPROTO_TCP, libc::SO_KEEPALIVE,
- seconds as libc::c_int)
- }
- #[cfg(not(any(target_os = "macos",
- target_os = "ios",
- target_os = "freebsd",
- target_os = "dragonfly",
- target_os = "openbsd")))]
- fn set_tcp_keepalive(&mut self, _seconds: usize) -> IoResult<()> {
- Ok(())
- }
-
- #[cfg(target_os = "linux")]
- fn lock_nonblocking(&self) {}
-
- #[cfg(not(target_os = "linux"))]
- fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
- let ret = Guard {
- fd: self.fd(),
- guard: self.inner.lock.lock().unwrap(),
- };
- set_nonblocking(self.fd(), true);
- ret
- }
-
- pub fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
- let fd = self.fd();
- let dolock = || self.lock_nonblocking();
- let doread = |nb| unsafe {
- let flags = if nb {c::MSG_DONTWAIT} else {0};
- libc::recv(fd,
- buf.as_mut_ptr() as *mut libc::c_void,
- buf.len() as wrlen,
- flags) as libc::c_int
- };
- read(fd, self.read_deadline, dolock, doread)
- }
-
- pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
- let fd = self.fd();
- let dolock = || self.lock_nonblocking();
- let dowrite = |nb: bool, buf: *const u8, len: usize| unsafe {
- let flags = if nb {c::MSG_DONTWAIT} else {0};
- libc::send(fd,
- buf as *const _,
- len as wrlen,
- flags) as i64
- };
- write(fd, self.write_deadline, buf, true, dolock, dowrite).map(|_| ())
- }
- pub fn peer_name(&mut self) -> IoResult<SocketAddr> {
- sockname(self.fd(), libc::getpeername)
- }
-
- pub fn close_write(&mut self) -> IoResult<()> {
- super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_WR) })
- }
- pub fn close_read(&mut self) -> IoResult<()> {
- super::mkerr_libc(unsafe { libc::shutdown(self.fd(), libc::SHUT_RD) })
- }
-
- pub fn set_timeout(&mut self, timeout: Option<u64>) {
- let deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
- self.read_deadline = deadline;
- self.write_deadline = deadline;
- }
- pub fn set_read_timeout(&mut self, timeout: Option<u64>) {
- self.read_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
- }
- pub fn set_write_timeout(&mut self, timeout: Option<u64>) {
- self.write_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
- }
-
- pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
- sockname(self.fd(), libc::getsockname)
- }
-}
-
-impl Clone for TcpStream {
- fn clone(&self) -> TcpStream {
- TcpStream {
- inner: self.inner.clone(),
- read_deadline: 0,
- write_deadline: 0,
- }
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// UDP
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct UdpSocket {
- inner: Arc<Inner>,
- read_deadline: u64,
- write_deadline: u64,
-}
-
-impl UdpSocket {
- pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
- sys::init_net();
-
- let fd = try!(socket(addr, libc::SOCK_DGRAM));
- let ret = UdpSocket {
- inner: Arc::new(Inner::new(fd)),
- read_deadline: 0,
- write_deadline: 0,
- };
-
- let mut storage = unsafe { mem::zeroed() };
- let len = addr_to_sockaddr(addr, &mut storage);
- let addrp = &storage as *const _ as *const libc::sockaddr;
-
- match unsafe { libc::bind(fd, addrp, len) } {
- -1 => Err(last_error()),
- _ => Ok(ret),
- }
- }
-
- pub fn fd(&self) -> sock_t { self.inner.fd }
-
- pub fn set_broadcast(&mut self, on: bool) -> IoResult<()> {
- setsockopt(self.fd(), libc::SOL_SOCKET, libc::SO_BROADCAST,
- on as libc::c_int)
- }
-
- pub fn set_multicast_loop(&mut self, on: bool) -> IoResult<()> {
- setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP,
- on as libc::c_int)
- }
-
- pub fn set_membership(&mut self, addr: IpAddr, opt: libc::c_int) -> IoResult<()> {
- match ip_to_inaddr(addr) {
- In4Addr(addr) => {
- let mreq = libc::ip_mreq {
- imr_multiaddr: addr,
- // interface == INADDR_ANY
- imr_interface: libc::in_addr { s_addr: 0x0 },
- };
- setsockopt(self.fd(), libc::IPPROTO_IP, opt, mreq)
- }
- In6Addr(addr) => {
- let mreq = libc::ip6_mreq {
- ipv6mr_multiaddr: addr,
- ipv6mr_interface: 0,
- };
- setsockopt(self.fd(), libc::IPPROTO_IPV6, opt, mreq)
- }
- }
- }
-
- #[cfg(target_os = "linux")]
- fn lock_nonblocking(&self) {}
-
- #[cfg(not(target_os = "linux"))]
- fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
- let ret = Guard {
- fd: self.fd(),
- guard: self.inner.lock.lock().unwrap(),
- };
- set_nonblocking(self.fd(), true);
- ret
- }
-
- pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
- sockname(self.fd(), libc::getsockname)
- }
-
- pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(usize, SocketAddr)> {
- let fd = self.fd();
- let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
- let storagep = &mut storage as *mut _ as *mut libc::sockaddr;
- let mut addrlen: libc::socklen_t =
- mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
-
- let dolock = || self.lock_nonblocking();
- let n = try!(read(fd, self.read_deadline, dolock, |nb| unsafe {
- let flags = if nb {c::MSG_DONTWAIT} else {0};
- libc::recvfrom(fd,
- buf.as_mut_ptr() as *mut libc::c_void,
- buf.len() as msglen_t,
- flags,
- storagep,
- &mut addrlen) as libc::c_int
- }));
- Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize).unwrap()))
- }
-
- pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
- let mut storage = unsafe { mem::zeroed() };
- let dstlen = addr_to_sockaddr(dst, &mut storage);
- let dstp = &storage as *const _ as *const libc::sockaddr;
-
- let fd = self.fd();
- let dolock = || self.lock_nonblocking();
- let dowrite = |nb, buf: *const u8, len: usize| unsafe {
- let flags = if nb {c::MSG_DONTWAIT} else {0};
- libc::sendto(fd,
- buf as *const libc::c_void,
- len as msglen_t,
- flags,
- dstp,
- dstlen) as i64
- };
-
- let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite));
- assert!(n == buf.len(), "UDP packet not completely written.");
- Ok(())
- }
-
- pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
- match multi {
- Ipv4Addr(..) => {
- self.set_membership(multi, libc::IP_ADD_MEMBERSHIP)
- }
- Ipv6Addr(..) => {
- self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP)
- }
- }
- }
- pub fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
- match multi {
- Ipv4Addr(..) => {
- self.set_membership(multi, libc::IP_DROP_MEMBERSHIP)
- }
- Ipv6Addr(..) => {
- self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP)
- }
- }
- }
-
- pub fn multicast_time_to_live(&mut self, ttl: isize) -> IoResult<()> {
- setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_MULTICAST_TTL,
- ttl as libc::c_int)
- }
- pub fn time_to_live(&mut self, ttl: isize) -> IoResult<()> {
- setsockopt(self.fd(), libc::IPPROTO_IP, libc::IP_TTL, ttl as libc::c_int)
- }
-
- pub fn set_timeout(&mut self, timeout: Option<u64>) {
- let deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
- self.read_deadline = deadline;
- self.write_deadline = deadline;
- }
- pub fn set_read_timeout(&mut self, timeout: Option<u64>) {
- self.read_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
- }
- pub fn set_write_timeout(&mut self, timeout: Option<u64>) {
- self.write_deadline = timeout.map(|a| timer::now() + a).unwrap_or(0);
- }
-}
-
-impl Clone for UdpSocket {
- fn clone(&self) -> UdpSocket {
- UdpSocket {
- inner: self.inner.clone(),
- read_deadline: 0,
- write_deadline: 0,
- }
- }
-}
use cmp;
use fmt;
use hash::{Hash, Hasher};
-use iter::{FromIterator, IntoIterator};
+use iter::FromIterator;
use mem;
-#[allow(deprecated)] // Int
-use num::Int;
use ops;
use slice;
use str;
use sys::time;
use sys::sync as ffi;
use time::Duration;
-use num::{Int, NumCast};
pub struct Condvar { inner: UnsafeCell<ffi::pthread_cond_t> }
let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut());
debug_assert_eq!(r, 0);
- let seconds = NumCast::from(dur.num_seconds());
- let timeout = match seconds.and_then(|s| sys_now.tv_sec.checked_add(s)) {
+ let seconds = dur.num_seconds() as libc::time_t;
+ let timeout = match sys_now.tv_sec.checked_add(seconds) {
Some(sec) => {
libc::timespec {
tv_sec: sec,
}
None => {
libc::timespec {
- tv_sec: Int::max_value(),
+ tv_sec: <libc::time_t>::max_value(),
tv_nsec: 1_000_000_000 - 1,
}
}
#[unstable(feature = "fs_ext",
reason = "may want a more useful mode abstraction")]
pub mod fs {
+ use sys;
use sys_common::{FromInner, AsInner, AsInnerMut};
use fs::{Permissions, OpenOptions};
+ use path::Path;
+ use convert::AsRef;
+ use io;
/// Unix-specific extensions to `Permissions`
pub trait PermissionsExt {
self.as_inner_mut().mode(mode); self
}
}
+
+ /// Creates a new symbolic link on the filesystem.
+ ///
+ /// The `dst` path will be a symbolic link pointing to the `src` path.
+ ///
+ /// # Note
+ ///
+ /// On Windows, you must specify whether a symbolic link points to a file
+ /// or directory. Use `os::windows::fs::symlink_file` to create a
+ /// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
+ /// symbolic link to a directory. Additionally, the process must have
+ /// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
+ /// symbolic link.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(fs_ext)]
+ /// use std::os::unix::fs;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// try!(fs::symlink("a.txt", "b.txt"));
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
+ {
+ sys::fs2::symlink(src.as_ref(), dst.as_ref())
+ }
+
}
////////////////////////////////////////////////////////////////////////////////
+++ /dev/null
-// Copyright 2014 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.
-
-#![allow(deprecated)]
-
-use libc;
-use sys::os;
-
-use sys::fs::FileDesc;
-
-pub type signal = libc::c_int;
-
-pub fn new() -> (signal, signal) {
- let (a, b) = unsafe { os::pipe().unwrap() };
- (a.unwrap(), b.unwrap())
-}
-
-pub fn signal(fd: libc::c_int) {
- FileDesc::new(fd, false).write(&[0]).unwrap();
-}
-
-pub fn close(fd: libc::c_int) {
- let _fd = FileDesc::new(fd, true);
-}
use io::{self, ErrorKind};
use libc;
-use num::{Int, SignedInt};
+use num::One;
+use ops::Neg;
pub mod backtrace;
pub mod c;
}
}
-#[inline]
-#[allow(deprecated)]
-pub fn retry<T, F> (mut f: F) -> T where
- T: SignedInt,
- F: FnMut() -> T,
-{
- let one: T = Int::one();
- loop {
- let n = f();
- if n == -one && os::errno() == libc::EINTR as i32 { }
- else { return n }
- }
-}
-
-#[allow(deprecated)]
-pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
- let one: T = Int::one();
+pub fn cvt<T: One + PartialEq + Neg<Output=T>>(t: T) -> io::Result<T> {
+ let one: T = T::one();
if t == -one {
Err(io::Error::last_os_error())
} else {
#[allow(deprecated)]
pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
- where T: SignedInt, F: FnMut() -> T
+ where T: One + PartialEq + Neg<Output=T>, F: FnMut() -> T
{
loop {
match cvt(f()) {
use libc::{self, pid_t, c_void, c_int, gid_t, uid_t};
use ptr;
use sys::pipe2::AnonPipe;
-use sys::{self, retry, c, cvt};
+use sys::{self, c, cvt, cvt_r};
use sys::fs2::{File, OpenOptions};
////////////////////////////////////////////////////////////////////////////////
}
}
};
- retry(|| libc::dup2(fd.raw(), dst)) != -1
+ cvt_r(|| libc::dup2(fd.raw(), dst)).is_ok()
};
if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) }
pub fn wait(&self) -> io::Result<ExitStatus> {
let mut status = 0 as c_int;
- try!(cvt(retry(|| unsafe { c::waitpid(self.pid, &mut status, 0) })));
+ try!(cvt_r(|| unsafe { c::waitpid(self.pid, &mut status, 0) }));
Ok(translate_status(status))
}
pub fn try_wait(&self) -> Option<ExitStatus> {
let mut status = 0 as c_int;
- match retry(|| unsafe {
+ match cvt_r(|| unsafe {
c::waitpid(self.pid, &mut status, c::WNOHANG)
}) {
- n if n == self.pid => Some(translate_status(status)),
- 0 => None,
- n => panic!("unknown waitpid error `{}`: {}", n,
- io::Error::last_os_error()),
+ Ok(0) => None,
+ Ok(n) if n == self.pid => Some(translate_status(status)),
+ Ok(n) => panic!("unkown pid: {}", n),
+ Err(e) => panic!("unknown waitpid error: {}", e),
}
}
}
pub const FSCTL_GET_REPARSE_POINT: libc::DWORD = 0x900a8;
pub const IO_REPARSE_TAG_SYMLINK: libc::DWORD = 0xa000000c;
+pub const SYMBOLIC_LINK_FLAG_DIRECTORY: libc::DWORD = 0x1;
+
// Note that these are not actually HANDLEs, just values to pass to GetStdHandle
pub const STD_INPUT_HANDLE: libc::DWORD = -10i32 as libc::DWORD;
pub const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD;
#[unstable(feature = "fs_ext", reason = "may require more thought/methods")]
pub mod fs {
use fs::OpenOptions;
+ use sys;
use sys_common::AsInnerMut;
+ use path::Path;
+ use convert::AsRef;
+ use io;
/// Windows-specific extensions to `OpenOptions`
pub trait OpenOptionsExt {
self.as_inner_mut().share_mode(access); self
}
}
+
+ /// Creates a new file symbolic link on the filesystem.
+ ///
+ /// The `dst` path will be a file symbolic link pointing to the `src`
+ /// path.
+ ///
+ /// # Examples
+ ///
+ /// ```ignore
+ /// #![feature(fs_ext)]
+ /// use std::os::windows::fs;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// try!(fs::symlink_file("a.txt", "b.txt"));
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
+ -> io::Result<()>
+ {
+ sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), false)
+ }
+
+ /// Creates a new directory symlink on the filesystem.
+ ///
+ /// The `dst` path will be a directory symbolic link pointing to the `src`
+ /// path.
+ ///
+ /// # Examples
+ ///
+ /// ```ignore
+ /// #![feature(fs_ext)]
+ /// use std::os::windows::fs;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// try!(fs::symlink_file("a", "b"));
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>> (src: P, dst: Q)
+ -> io::Result<()>
+ {
+ sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), true)
+ }
}
/// A prelude for conveniently writing platform-specific code.
use io::prelude::*;
use os::windows::prelude::*;
-use default::Default;
-use ffi::{OsString, AsOsStr};
+use ffi::OsString;
use fmt;
use io::{self, Error, SeekFrom};
use libc::{self, HANDLE};
}
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
+ symlink_inner(src, dst, false)
+}
+
+pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
use sys::c::compat::kernel32::CreateSymbolicLinkW;
let src = to_utf16(src);
let dst = to_utf16(dst);
+ let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 };
try!(cvt(unsafe {
- CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), 0) as libc::BOOL
+ CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as libc::BOOL
}));
Ok(())
}
use ffi::{OsStr, OsString};
use io::{self, ErrorKind};
use libc;
-#[allow(deprecated)]
-use num::Int;
+use num::Zero;
use os::windows::ffi::{OsStrExt, OsStringExt};
use path::PathBuf;
}
}
-#[allow(deprecated)]
-fn cvt<I: Int>(i: I) -> io::Result<I> {
- if i == Int::zero() {
+fn cvt<I: PartialEq + Zero>(i: I) -> io::Result<I> {
+ if i == I::zero() {
Err(io::Error::last_os_error())
} else {
Ok(i)
use libc::{self, c_int, c_void};
use mem;
use net::SocketAddr;
-#[allow(deprecated)]
-use num::{SignedInt, Int};
+use num::One;
+use ops::Neg;
use rt;
use sync::{Once, ONCE_INIT};
use sys::c;
/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1)
/// and if so, returns the last error from the Windows socket interface. . This
/// function must be called before another call to the socket API is made.
-///
-/// FIXME: generics needed?
-#[allow(deprecated)]
-pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
- let one: T = Int::one();
+pub fn cvt<T: One + Neg<Output=T> + PartialEq>(t: T) -> io::Result<T> {
+ let one: T = T::one();
if t == -one {
Err(last_error())
} else {
/// Provides the functionality of `cvt` for a closure.
#[allow(deprecated)]
-pub fn cvt_r<T: SignedInt, F>(mut f: F) -> io::Result<T> where F: FnMut() -> T {
+pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>
+ where F: FnMut() -> T, T: One + Neg<Output=T> + PartialEq
+{
cvt(f())
}
// read the *child's* PATH if one is provided. See #15149 for more details.
let program = cfg.env.as_ref().and_then(|env| {
for (key, v) in env {
- if OsStr::from_str("PATH") != &**key { continue }
+ if OsStr::new("PATH") != &**key { continue }
// Split the value and test each path to see if the
// program exists.
fn test_make_command_line() {
fn test_wrapper(prog: &str, args: &[&str]) -> String {
String::from_utf16(
- &make_command_line(OsStr::from_str(prog),
+ &make_command_line(OsStr::new(prog),
&args.iter()
.map(|a| OsString::from(a))
.collect::<Vec<OsString>>())).unwrap()
imp::sleep(Duration::milliseconds(ms as i64))
}
-/// Deprecated: use `sleep_ms` instead.
-#[unstable(feature = "thread_sleep",
- reason = "recently added, needs an RFC, and `Duration` itself is \
- unstable")]
-#[deprecated(since = "1.0.0", reason = "use sleep_ms instead")]
-pub fn sleep(dur: Duration) {
- imp::sleep(dur)
-}
-
/// Blocks unless or until the current thread's token is made available (may wake spuriously).
///
/// See the module doc for more detail.
*guard = false;
}
-/// Deprecated: use `park_timeout_ms`
-#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")]
-#[deprecated(since = "1.0.0", reason = "use park_timeout_ms instead")]
-pub fn park_timeout(duration: Duration) {
- park_timeout_ms(duration.num_milliseconds() as u32)
-}
-
////////////////////////////////////////////////////////////////////////////////
// Thread
////////////////////////////////////////////////////////////////////////////////
#![unstable(feature = "std_misc")]
+use prelude::v1::*;
+
use {fmt, i64};
-use ops::{Add, Sub, Mul, Div, Neg, FnOnce};
-use option::Option;
-use option::Option::{Some, None};
-#[allow(deprecated)] // Int
-use num::Int;
-use result::Result::Ok;
+use ops::{Add, Sub, Mul, Div, Neg};
/// The number of nanoseconds in a microsecond.
const NANOS_PER_MICRO: i32 = 1000;
use ptr::P;
use std::fmt;
-#[allow(deprecated)]
-use std::num::Int;
use std::rc::Rc;
use serialize::{Encodable, Decodable, Encoder, Decoder};
}
impl Sign {
- #[allow(deprecated)] // Int
- pub fn new<T:Int>(n: T) -> Sign {
- if n < Int::zero() {
- Minus
- } else {
- Plus
- }
+ pub fn new<T: IntSign>(n: T) -> Sign {
+ n.sign()
}
}
+pub trait IntSign {
+ fn sign(&self) -> Sign;
+}
+macro_rules! doit {
+ ($($t:ident)*) => ($(impl IntSign for $t {
+ #[allow(unused_comparisons)]
+ fn sign(&self) -> Sign {
+ if *self < 0 {Minus} else {Plus}
+ }
+ })*)
+}
+doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
+
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum LitIntType {
SignedIntLit(IntTy, Sign),
pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: Option<&Ty>) -> Ident {
let mut pretty = match ty {
Some(t) => pprust::ty_to_string(t),
- None => String::from_str("..")
+ None => String::from("..")
};
match *trait_ref {
pub use self::MacroFormat::*;
use std::cell::RefCell;
-use std::num::ToPrimitive;
use std::ops::{Add, Sub};
use std::rc::Rc;
use std::fmt;
-use libc::c_uint;
use serialize::{Encodable, Decodable, Encoder, Decoder};
pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(!1);
impl ExpnId {
- pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId {
- ExpnId(cookie)
+ pub fn from_u32(id: u32) -> ExpnId {
+ ExpnId(id)
}
- pub fn to_llvm_cookie(self) -> i32 {
- let ExpnId(cookie) = self;
- cookie as i32
+ pub fn into_u32(self) -> u32 {
+ self.0
}
}
// FIXME #12884: no efficient/safe way to remove from the start of a string
// and reuse the allocation.
let mut src = if src.starts_with("\u{feff}") {
- String::from_str(&src[3..])
+ String::from(&src[3..])
} else {
- String::from_str(&src[..])
+ String::from(&src[..])
};
// Append '\n' in case it's not already there.
pub fn new_imported_filemap(&self,
filename: FileName,
source_len: usize,
- file_local_lines: Vec<BytePos>,
- file_local_multibyte_chars: Vec<MultiByteChar>)
+ mut file_local_lines: Vec<BytePos>,
+ mut file_local_multibyte_chars: Vec<MultiByteChar>)
-> Rc<FileMap> {
let mut files = self.files.borrow_mut();
let start_pos = match files.last() {
let end_pos = Pos::from_usize(start_pos + source_len);
let start_pos = Pos::from_usize(start_pos);
- let lines = file_local_lines.map_in_place(|pos| pos + start_pos);
- let multibyte_chars = file_local_multibyte_chars.map_in_place(|mbc| MultiByteChar {
- pos: mbc.pos + start_pos,
- bytes: mbc.bytes
- });
+ for pos in &mut file_local_lines {
+ *pos = *pos + start_pos;
+ }
+
+ for mbc in &mut file_local_multibyte_chars {
+ mbc.pos = mbc.pos + start_pos;
+ }
let filemap = Rc::new(FileMap {
name: filename,
src: None,
start_pos: start_pos,
end_pos: end_pos,
- lines: RefCell::new(lines),
- multibyte_chars: RefCell::new(multibyte_chars),
+ lines: RefCell::new(file_local_lines),
+ multibyte_chars: RefCell::new(file_local_multibyte_chars),
});
files.push(filemap.clone());
pub fn record_expansion(&self, expn_info: ExpnInfo) -> ExpnId {
let mut expansions = self.expansions.borrow_mut();
expansions.push(expn_info);
- ExpnId(expansions.len().to_u32().expect("too many ExpnInfo's!") - 1)
+ let len = expansions.len();
+ if len > u32::max_value() as usize {
+ panic!("too many ExpnInfo's!");
+ }
+ ExpnId(len as u32 - 1)
}
pub fn with_expn_info<T, F>(&self, id: ExpnId, f: F) -> T where
return fold::noop_fold_attribute(attr, self);
}
- let (cfg, mi) = match attr.meta_item_list() {
- Some([ref cfg, ref mi]) => (cfg, mi),
+ let attr_list = match attr.meta_item_list() {
+ Some(attr_list) => attr_list,
+ None => {
+ self.diag.span_err(attr.span, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
+ return None;
+ }
+ };
+ let (cfg, mi) = match (attr_list.len(), attr_list.get(0), attr_list.get(1)) {
+ (2, Some(cfg), Some(mi)) => (cfg, mi),
_ => {
self.diag.span_err(attr.span, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
return None;
}
try!(write!(&mut err.dst, "{}", s));
- let mut s = String::from_str("^");
+ let mut s = String::from("^");
let count = match lastc {
// Most terminals have a tab stop every eight columns by default
'\t' => 8 - col%8,
span: Span,
token_tree: &[TokenTree])
-> Box<MacResult+'cx> {
- let code = match token_tree {
- [ast::TtToken(_, token::Ident(code, _))] => code,
+ let code = match (token_tree.len(), token_tree.get(0)) {
+ (1, Some(&ast::TtToken(_, token::Ident(code, _)))) => code,
_ => unreachable!()
};
with_used_diagnostics(|diagnostics| {
));
}
});
- MacEager::expr(quote_expr!(ecx, ()))
+ MacEager::expr(ecx.expr_tuple(span, Vec::new()))
}
pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
span: Span,
token_tree: &[TokenTree])
-> Box<MacResult+'cx> {
- let (code, description) = match token_tree {
- [ast::TtToken(_, token::Ident(ref code, _))] => {
+ let (code, description) = match (
+ token_tree.len(),
+ token_tree.get(0),
+ token_tree.get(1),
+ token_tree.get(2)
+ ) {
+ (1, Some(&ast::TtToken(_, token::Ident(ref code, _))), None, None) => {
(code, None)
},
- [ast::TtToken(_, token::Ident(ref code, _)),
- ast::TtToken(_, token::Comma),
- ast::TtToken(_, token::Literal(token::StrRaw(description, _), None))] => {
+ (3, Some(&ast::TtToken(_, token::Ident(ref code, _))),
+ Some(&ast::TtToken(_, token::Comma)),
+ Some(&ast::TtToken(_, token::Literal(token::StrRaw(description, _), None)))) => {
(code, Some(description))
}
_ => unreachable!()
let sym = Ident::new(token::gensym(&(
"__register_diagnostic_".to_string() + &token::get_ident(*code)
)));
- MacEager::items(SmallVector::many(vec![quote_item!(ecx, mod $sym {}).unwrap()]))
+ MacEager::items(SmallVector::many(vec![
+ ecx.item_mod(
+ span,
+ span,
+ sym,
+ Vec::new(),
+ Vec::new()
+ )
+ ]))
}
pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
span: Span,
token_tree: &[TokenTree])
-> Box<MacResult+'cx> {
- let name = match token_tree {
- [ast::TtToken(_, token::Ident(ref name, _))] => name,
+ let name = match (token_tree.len(), token_tree.get(0)) {
+ (1, Some(&ast::TtToken(_, token::Ident(ref name, _)))) => name,
_ => unreachable!()
};
(descriptions.len(), ecx.expr_vec(span, descriptions))
});
- MacEager::items(SmallVector::many(vec![quote_item!(ecx,
- pub static $name: [(&'static str, &'static str); $count] = $expr;
- ).unwrap()]))
+ let static_ = ecx.lifetime(span, ecx.name_of("'static"));
+ let ty_str = ecx.ty_rptr(
+ span,
+ ecx.ty_ident(span, ecx.ident_of("str")),
+ Some(static_),
+ ast::MutImmutable,
+ );
+
+ let ty = ecx.ty(
+ span,
+ ast::TyFixedLengthVec(
+ ecx.ty(
+ span,
+ ast::TyTup(vec![ty_str.clone(), ty_str])
+ ),
+ ecx.expr_usize(span, count),
+ ),
+ );
+
+ MacEager::items(SmallVector::many(vec![
+ P(ast::Item {
+ ident: name.clone(),
+ attrs: Vec::new(),
+ id: ast::DUMMY_NODE_ID,
+ node: ast::ItemStatic(
+ ty,
+ ast::MutImmutable,
+ expr,
+ ),
+ vis: ast::Public,
+ span: span,
+ })
+ ]))
}
impl MacEager {
$(
pub fn $fld(v: $t) -> Box<MacResult> {
- box MacEager {
+ Box::new(MacEager {
$fld: Some(v),
..Default::default()
- }
+ })
}
)*
}
/// Use this as a return value after hitting any errors and
/// calling `span_err`.
pub fn any(sp: Span) -> Box<MacResult+'static> {
- box DummyResult { expr_only: false, span: sp }
+ Box::new(DummyResult { expr_only: false, span: sp })
}
/// Create a default MacResult that can only be an expression.
/// if an error is encountered internally, the user will receive
/// an error that they also used it in the wrong place.
pub fn expr(sp: Span) -> Box<MacResult+'static> {
- box DummyResult { expr_only: true, span: sp }
+ Box::new(DummyResult { expr_only: true, span: sp })
}
/// A plain dummy expression.
// }
let new = {
- let other_f = match other_fs {
- [ref o_f] => o_f,
+ let other_f = match (other_fs.len(), other_fs.get(0)) {
+ (1, Some(o_f)) => o_f,
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
};
cs_fold(
true, // use foldl
|cx, span, subexpr, self_f, other_fs| {
- let other_f = match other_fs {
- [ref o_f] => o_f,
+ let other_f = match (other_fs.len(), other_fs.get(0)) {
+ (1, Some(o_f)) => o_f,
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`")
};
cs_fold(
true, // use foldl
|cx, span, subexpr, self_f, other_fs| {
- let other_f = match other_fs {
- [ref o_f] => o_f,
+ let other_f = match (other_fs.len(), other_fs.get(0)) {
+ (1, Some(o_f)) => o_f,
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`")
};
let ordering_ty = Literal(path_std!(cx, core::cmp::Ordering));
let ret_ty = Literal(Path::new_(pathvec_std!(cx, core::option::Option),
None,
- vec![box ordering_ty],
+ vec![Box::new(ordering_ty)],
true));
let inline = cx.meta_word(span, InternedString::new("inline"));
// }
let new = {
- let other_f = match other_fs {
- [ref o_f] => o_f,
+ let other_f = match (other_fs.len(), other_fs.get(0)) {
+ (1, Some(o_f)) => o_f,
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
};
get use the binops to avoid auto-deref dereferencing too many
layers of pointers, if the type includes pointers.
*/
- let other_f = match other_fs {
- [ref o_f] => o_f,
+ let other_f = match (other_fs.len(), other_fs.get(0)) {
+ (1, Some(o_f)) => o_f,
_ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
};
vec!(), true))))
},
explicit_self: None,
- args: vec!(Ptr(box Literal(Path::new_local("__D")),
+ args: vec!(Ptr(Box::new(Literal(Path::new_local("__D"))),
Borrowed(None, MutMutable))),
ret_ty: Literal(Path::new_(
pathvec_std!(cx, core::result::Result),
None,
- vec!(box Self_, box Literal(Path::new_(
+ vec!(Box::new(Self_), Box::new(Literal(Path::new_(
vec!["__D", "Error"], None, vec![], false
- ))),
+ )))),
true
)),
attributes: Vec::new(),
vec!(), true))))
},
explicit_self: borrowed_explicit_self(),
- args: vec!(Ptr(box Literal(Path::new_local("__S")),
+ args: vec!(Ptr(Box::new(Literal(Path::new_local("__S"))),
Borrowed(None, MutMutable))),
ret_ty: Literal(Path::new_(
pathvec_std!(cx, core::result::Result),
None,
- vec!(box Tuple(Vec::new()), box Literal(Path::new_(
+ vec!(Box::new(Tuple(Vec::new())), Box::new(Literal(Path::new_(
vec!["__S", "Error"], None, vec![], false
- ))),
+ )))),
true
)),
attributes: Vec::new(),
Self_ if nonstatic => {
self_args.push(arg_expr);
}
- Ptr(box Self_, _) if nonstatic => {
+ Ptr(ref ty, _) if **ty == Self_ && nonstatic => {
self_args.push(cx.expr_deref(trait_.span, arg_expr))
}
_ => {
subpats.push(p);
idents
};
- for self_arg_name in self_arg_names.tail() {
+ for self_arg_name in &self_arg_names[1..] {
let (p, idents) = mk_self_pat(cx, &self_arg_name[..]);
subpats.push(p);
self_pats_idents.push(idents);
use ptr::P;
/// The types of pointers
-#[derive(Clone)]
+#[derive(Clone, Eq, PartialEq)]
pub enum PtrTy<'a> {
/// &'lifetime mut
Borrowed(Option<&'a str>, ast::Mutability),
/// A path, e.g. `::std::option::Option::<i32>` (global). Has support
/// for type parameters and a lifetime.
-#[derive(Clone)]
+#[derive(Clone, Eq, PartialEq)]
pub struct Path<'a> {
pub path: Vec<&'a str> ,
pub lifetime: Option<&'a str>,
}
/// A type. Supports pointers, Self, and literals
-#[derive(Clone)]
+#[derive(Clone, Eq, PartialEq)]
pub enum Ty<'a> {
Self_,
/// &/Box/ Ty
}
pub fn borrowed_self<'r>() -> Ty<'r> {
- borrowed(box Self_)
+ borrowed(Box::new(Self_))
}
pub fn nil_ty<'r>() -> Ty<'r> {
vec![path_std!(cx, core::hash::Hasher)])],
},
explicit_self: borrowed_explicit_self(),
- args: vec!(Ptr(box Literal(arg), Borrowed(None, MutMutable))),
+ args: vec!(Ptr(Box::new(Literal(arg)), Borrowed(None, MutMutable))),
ret_ty: nil_ty(),
attributes: vec![],
combine_substructure: combine_substructure(Box::new(|a, b, c| {
}
fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
- let state_expr = match substr.nonself_args {
- [ref state_expr] => state_expr,
+ let state_expr = match (substr.nonself_args.len(), substr.nonself_args.get(0)) {
+ (1, Some(o_f)) => o_f,
_ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`")
};
let call_hash = |span, thing_expr| {
args: vec!(Literal(path_local!(i64))),
ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option),
None,
- vec!(box Self_),
+ vec!(Box::new(Self_)),
true)),
// #[inline] liable to cause code-bloat
attributes: attrs.clone(),
args: vec!(Literal(path_local!(u64))),
ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option),
None,
- vec!(box Self_),
+ vec!(Box::new(Self_)),
true)),
// #[inline] liable to cause code-bloat
attributes: attrs,
}
fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
- let n = match substr.nonself_args {
- [ref n] => n,
+ let n = match (substr.nonself_args.len(), substr.nonself_args.get(0)) {
+ (1, Some(o_f)) => o_f,
_ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(FromPrimitive)`")
};
push: &mut FnMut(P<Item>))
{
// &mut ::std::fmt::Formatter
- let fmtr = Ptr(box Literal(path_std!(cx, core::fmt::Formatter)),
+ let fmtr = Ptr(Box::new(Literal(path_std!(cx, core::fmt::Formatter))),
Borrowed(None, ast::MutMutable));
let trait_def = TraitDef {
"xx" == string
}).collect();
let cxbinds: &[&ast::Ident] = &cxbinds[..];
- let cxbind = match cxbinds {
- [b] => b,
+ let cxbind = match (cxbinds.len(), cxbinds.get(0)) {
+ (1, Some(b)) => *b,
_ => panic!("expected just one binding for ext_cx")
};
let resolved_binding = mtwt::resolve(*cxbind);
}
}
- box ExpandResult { p: p }
+ Box::new(ExpandResult { p: p })
}
// include_str! : read the given file, insert it as a literal string expr
return base::DummyResult::any(sp);
}
-
- match tt {
- [ast::TtToken(_, ref tok)] if tok.is_keyword(keywords::True) => {
+ match (tt.len(), tt.first()) {
+ (1, Some(&ast::TtToken(_, ref tok))) if tok.is_keyword(keywords::True) => {
cx.set_trace_macros(true);
}
- [ast::TtToken(_, ref tok)] if tok.is_keyword(keywords::False) => {
+ (1, Some(&ast::TtToken(_, ref tok))) if tok.is_keyword(keywords::False) => {
cx.set_trace_macros(false);
}
_ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"),
-> Box<MatcherPos> {
let match_idx_hi = count_names(&ms[..]);
let matches: Vec<_> = (0..match_idx_hi).map(|_| Vec::new()).collect();
- box MatcherPos {
+ Box::new(MatcherPos {
stack: vec![],
top_elts: TtSeq(ms),
sep: sep,
match_cur: 0,
match_hi: match_idx_hi,
sp_lo: lo
- }
+ })
}
/// NamedMatch is a pattern-match result for a single token::MATCH_NONTERMINAL:
let matches: Vec<_> = (0..ei.matches.len())
.map(|_| Vec::new()).collect();
let ei_t = ei;
- cur_eis.push(box MatcherPos {
+ cur_eis.push(Box::new(MatcherPos {
stack: vec![],
sep: seq.separator.clone(),
idx: 0,
up: Some(ei_t),
sp_lo: sp.lo,
top_elts: Tt(TtSequence(sp, seq)),
- });
+ }));
}
TtToken(_, MatchNt(..)) => {
// Built-in nonterminals never start with these tokens,
"ty" => token::NtTy(p.parse_ty()),
// this could be handled like a token, since it is one
"ident" => match p.token {
- token::Ident(sn,b) => { panictry!(p.bump()); token::NtIdent(box sn,b) }
+ token::Ident(sn,b) => { panictry!(p.bump()); token::NtIdent(Box::new(sn),b) }
_ => {
let token_str = pprust::token_to_string(&p.token);
panic!(p.fatal(&format!("expected ident, found {}",
}
},
"path" => {
- token::NtPath(box panictry!(p.parse_path(LifetimeAndTypesWithoutColons)))
+ token::NtPath(Box::new(panictry!(p.parse_path(LifetimeAndTypesWithoutColons))))
}
"meta" => token::NtMeta(p.parse_meta_item()),
_ => {
panictry!(p.check_unknown_macro_variable());
// Let the context choose how to interpret the result.
// Weird, but useful for X-macros.
- return box ParserAnyMacro {
+ return Box::new(ParserAnyMacro {
parser: RefCell::new(p),
// Pass along the original expansion site and the name of the macro
// macro leaves unparsed tokens.
site_span: sp,
macro_ident: name
- }
+ })
}
Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
best_fail_spot = sp;
_ => cx.span_bug(def.span, "wrong-structured rhs")
};
- let exp: Box<_> = box MacroRulesMacroExpander {
+ let exp: Box<_> = Box::new(MacroRulesMacroExpander {
name: def.ident,
imported_from: def.imported_from,
lhses: lhses,
rhses: rhses,
- };
+ });
NormalTT(exp, Some(def.span), def.allow_internal_unstable)
}
// sidestep the interpolation tricks for ident because
// (a) idents can be in lots of places, so it'd be a pain
// (b) we actually can, since it's a token.
- MatchedNonterminal(NtIdent(box sn, b)) => {
+ MatchedNonterminal(NtIdent(ref sn, b)) => {
r.cur_span = sp;
- r.cur_tok = token::Ident(sn, b);
+ r.cur_tok = token::Ident(**sn, b);
return ret_val;
}
MatchedNonterminal(ref other_whole_nt) => {
token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)),
token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)),
token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)),
- token::NtIdent(box id, is_mod_name) =>
- token::NtIdent(box fld.fold_ident(id), is_mod_name),
+ token::NtIdent(id, is_mod_name) =>
+ token::NtIdent(Box::new(fld.fold_ident(*id)), is_mod_name),
token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)),
- token::NtPath(box path) => token::NtPath(box fld.fold_path(path)),
+ token::NtPath(path) => token::NtPath(Box::new(fld.fold_path(*path))),
token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&*tt))),
}
}
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
-#![feature(box_patterns)]
-#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(libc)]
-#![feature(quote, unsafe_destructor)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(unicode)]
-#![feature(path_ext)]
#![feature(str_char)]
-#![feature(into_cow)]
-#![feature(slice_patterns)]
extern crate arena;
extern crate fmt_macros;
pub mod ptr;
pub mod show_span;
pub mod std_inject;
+pub mod str;
pub mod test;
pub mod visit;
use ast;
use codemap::{BytePos, CharPos, CodeMap, Pos};
use diagnostic;
-use parse::lexer::{is_whitespace, Reader};
-use parse::lexer::{StringReader, TokenAndSpan};
use parse::lexer::is_block_doc_comment;
+use parse::lexer::{StringReader, TokenAndSpan};
+use parse::lexer::{is_whitespace, Reader};
use parse::lexer;
use print::pprust;
+use str::char_at;
use std::io::Read;
use std::usize;
let mut col = col.to_usize();
let mut cursor: usize = 0;
while col > 0 && cursor < len {
- let ch = s.char_at(cursor);
+ let ch = char_at(s, cursor);
if !ch.is_whitespace() {
return None;
}
rdr.bump();
rdr.bump();
- let mut curr_line = String::from_str("/*");
+ let mut curr_line = String::from("/*");
// doc-comments are not really comments, they are attributes
if (rdr.curr_is('*') && !rdr.nextch_is('*')) || rdr.curr_is('!') {
use codemap;
use diagnostic::SpanHandler;
use ext::tt::transcribe::tt_next_token;
-use parse::token;
use parse::token::str_to_ident;
+use parse::token;
+use str::char_at;
-use std::borrow::{IntoCow, Cow};
+use std::borrow::Cow;
use std::char;
use std::fmt;
use std::mem::replace;
s: &'b str, errmsg: &'b str) -> Cow<'b, str> {
let mut i = 0;
while i < s.len() {
- let ch = s.char_at(i);
+ let ch = char_at(s, i);
let next = i + ch.len_utf8();
if ch == '\r' {
- if next < s.len() && s.char_at(next) == '\n' {
- return translate_crlf_(self, start, s, errmsg, i).into_cow();
+ if next < s.len() && char_at(s, next) == '\n' {
+ return translate_crlf_(self, start, s, errmsg, i).into();
}
let pos = start + BytePos(i as u32);
let end_pos = start + BytePos(next as u32);
}
i = next;
}
- return s.into_cow();
+ return s.into();
fn translate_crlf_(rdr: &StringReader, start: BytePos,
s: &str, errmsg: &str, mut i: usize) -> String {
let mut buf = String::with_capacity(s.len());
let mut j = 0;
while i < s.len() {
- let ch = s.char_at(i);
+ let ch = char_at(s, i);
let next = i + ch.len_utf8();
if ch == '\r' {
if j < i { buf.push_str(&s[j..i]); }
j = next;
- if next >= s.len() || s.char_at(next) != '\n' {
+ if next >= s.len() || char_at(s, next) != '\n' {
let pos = start + BytePos(i as u32);
let end_pos = start + BytePos(next as u32);
rdr.err_span_(pos, end_pos, errmsg);
if current_byte_offset < self.source_text.len() {
assert!(self.curr.is_some());
let last_char = self.curr.unwrap();
- let ch = self.source_text.char_at(current_byte_offset);
+ let ch = char_at(&self.source_text, current_byte_offset);
let next = current_byte_offset + ch.len_utf8();
let byte_offset_diff = next - current_byte_offset;
self.pos = self.pos + Pos::from_usize(byte_offset_diff);
pub fn nextch(&self) -> Option<char> {
let offset = self.byte_offset(self.pos).to_usize();
if offset < self.source_text.len() {
- Some(self.source_text.char_at(offset))
+ Some(char_at(&self.source_text, offset))
} else {
None
}
let offset = self.byte_offset(self.pos).to_usize();
let s = &self.source_text[..];
if offset >= s.len() { return None }
- let next = offset + s.char_at(offset).len_utf8();
+ let next = offset + char_at(s, offset).len_utf8();
if next < s.len() {
- Some(s.char_at(next))
+ Some(char_at(s, next))
} else {
None
}
let string = if has_cr {
self.translate_crlf(start_bpos, string,
"bare CR not allowed in block doc-comment")
- } else { string.into_cow() };
+ } else { string.into() };
token::DocComment(token::intern(&string[..]))
} else {
token::Comment
use parse::attr::ParserAttr;
use parse::parser::Parser;
use ptr::P;
-
+use str::char_at;
use std::cell::{Cell, RefCell};
use std::fs::File;
use std::io::Read;
use std::iter;
-#[allow(deprecated)] // Int
-use std::num::Int;
use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::str;
// parsing tt's probably shouldn't require a parser at all.
let cfg = Vec::new();
let srdr = lexer::StringReader::new(&sess.span_diagnostic, filemap);
- let mut p1 = Parser::new(sess, cfg, box srdr);
+ let mut p1 = Parser::new(sess, cfg, Box::new(srdr));
panictry!(p1.parse_all_token_trees())
}
tts: Vec<ast::TokenTree>,
cfg: ast::CrateConfig) -> Parser<'a> {
let trdr = lexer::new_tt_reader(&sess.span_diagnostic, None, None, tts);
- let mut p = Parser::new(sess, cfg, box trdr);
+ let mut p = Parser::new(sess, cfg, Box::new(trdr));
panictry!(p.check_unknown_macro_variable());
p
}
use super::lexer::make_reader_with_embedded_idents as make_reader;
let cfg = Vec::new();
let srdr = make_reader(&sess.span_diagnostic, filemap);
- let mut p1 = Parser::new(sess, cfg, box srdr);
+ let mut p1 = Parser::new(sess, cfg, Box::new(srdr));
panictry!(p1.parse_all_token_trees())
}
}
// check if `s` looks like i32 or u1234 etc.
fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool {
s.len() > 1 &&
- first_chars.contains(&s.char_at(0)) &&
+ first_chars.contains(&char_at(s, 0)) &&
s[1..].chars().all(|c| '0' <= c && c <= '9')
}
let orig = s;
let mut ty = ast::UnsuffixedIntLit(ast::Plus);
- if s.char_at(0) == '0' && s.len() > 1 {
- match s.char_at(1) {
+ if char_at(s, 0) == '0' && s.len() > 1 {
+ match char_at(s, 1) {
'x' => base = 16,
'o' => base = 8,
'b' => base = 2,
fn string_to_tts_macro () {
let tts = string_to_tts("macro_rules! zip (($a)=>($a))".to_string());
let tts: &[ast::TokenTree] = &tts[..];
- match tts {
- [ast::TtToken(_, token::Ident(name_macro_rules, token::Plain)),
- ast::TtToken(_, token::Not),
- ast::TtToken(_, token::Ident(name_zip, token::Plain)),
- ast::TtDelimited(_, ref macro_delimed)]
+
+ match (tts.len(), tts.get(0), tts.get(1), tts.get(2), tts.get(3)) {
+ (
+ 4,
+ Some(&ast::TtToken(_, token::Ident(name_macro_rules, token::Plain))),
+ Some(&ast::TtToken(_, token::Not)),
+ Some(&ast::TtToken(_, token::Ident(name_zip, token::Plain))),
+ Some(&ast::TtDelimited(_, ref macro_delimed)),
+ )
if name_macro_rules.as_str() == "macro_rules"
&& name_zip.as_str() == "zip" => {
- match ¯o_delimed.tts[..] {
- [ast::TtDelimited(_, ref first_delimed),
- ast::TtToken(_, token::FatArrow),
- ast::TtDelimited(_, ref second_delimed)]
+ let tts = ¯o_delimed.tts[..];
+ match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) {
+ (
+ 3,
+ Some(&ast::TtDelimited(_, ref first_delimed)),
+ Some(&ast::TtToken(_, token::FatArrow)),
+ Some(&ast::TtDelimited(_, ref second_delimed)),
+ )
if macro_delimed.delim == token::Paren => {
- match &first_delimed.tts[..] {
- [ast::TtToken(_, token::Dollar),
- ast::TtToken(_, token::Ident(name, token::Plain))]
+ let tts = &first_delimed.tts[..];
+ match (tts.len(), tts.get(0), tts.get(1)) {
+ (
+ 2,
+ Some(&ast::TtToken(_, token::Dollar)),
+ Some(&ast::TtToken(_, token::Ident(name, token::Plain))),
+ )
if first_delimed.delim == token::Paren
&& name.as_str() == "a" => {},
_ => panic!("value 3: {:?}", **first_delimed),
}
- match &second_delimed.tts[..] {
- [ast::TtToken(_, token::Dollar),
- ast::TtToken(_, token::Ident(name, token::Plain))]
+ let tts = &second_delimed.tts[..];
+ match (tts.len(), tts.get(0), tts.get(1)) {
+ (
+ 2,
+ Some(&ast::TtToken(_, token::Dollar)),
+ Some(&ast::TtToken(_, token::Ident(name, token::Plain))),
+ )
if second_delimed.delim == token::Paren
&& name.as_str() == "a" => {},
_ => panic!("value 4: {:?}", **second_delimed),
use diagnostic::FatalError;
use std::collections::HashSet;
+use std::fs;
use std::io::prelude::*;
use std::mem;
use std::path::{Path, PathBuf};
// leave it in the input
Ok(())
} else {
- let mut expected = edible.iter().map(|x| TokenType::Token(x.clone()))
- .collect::<Vec<_>>();
- expected.extend(inedible.iter().map(|x| TokenType::Token(x.clone())));
- expected.push_all(&*self.expected_tokens);
+ let mut expected = edible.iter()
+ .map(|x| TokenType::Token(x.clone()))
+ .chain(inedible.iter().map(|x| TokenType::Token(x.clone())))
+ .chain(self.expected_tokens.iter().cloned())
+ .collect::<Vec<_>>();
expected.sort_by(|a, b| a.to_string().cmp(&b.to_string()));
expected.dedup();
let expect = tokens_to_string(&expected[..]);
debug!("commit_expr {:?}", e);
if let ExprPath(..) = e.node {
// might be unit-struct construction; check for recoverableinput error.
- let mut expected = edible.iter().cloned().collect::<Vec<_>>();
- expected.push_all(inedible);
+ let expected = edible.iter()
+ .cloned()
+ .chain(inedible.iter().cloned())
+ .collect::<Vec<_>>();
try!(self.check_for_erroneous_unit_struct_expecting(&expected[..]));
}
self.expect_one_of(edible, inedible)
if self.last_token
.as_ref()
.map_or(false, |t| t.is_ident() || t.is_path()) {
- let mut expected = edible.iter().cloned().collect::<Vec<_>>();
- expected.push_all(&inedible);
+ let expected = edible.iter()
+ .cloned()
+ .chain(inedible.iter().cloned())
+ .collect::<Vec<_>>();
try!(self.check_for_erroneous_unit_struct_expecting(&expected));
}
self.expect_one_of(edible, inedible)
self.last_span = self.span;
// Stash token for error recovery (sometimes; clone is not necessarily cheap).
self.last_token = if self.token.is_ident() || self.token.is_path() {
- Some(box self.token.clone())
+ Some(Box::new(self.token.clone()))
} else {
None
};
debug!("parse_trait_methods(): parsing provided method");
let (inner_attrs, body) =
try!(p.parse_inner_attrs_and_block());
- attrs.push_all(&inner_attrs[..]);
+ attrs.extend(inner_attrs.iter().cloned());
Some(body)
}
token::Interpolated(token::NtPath(_)) => Some(try!(self.bump_and_get())),
_ => None,
};
- if let Some(token::Interpolated(token::NtPath(box path))) = found {
- return Ok(path);
+ if let Some(token::Interpolated(token::NtPath(path))) = found {
+ return Ok(*path);
}
let lo = self.span.lo;
let secondary_path_str = format!("{}/mod.rs", mod_name);
let default_path = dir_path.join(&default_path_str[..]);
let secondary_path = dir_path.join(&secondary_path_str[..]);
- let default_exists = default_path.exists();
- let secondary_exists = secondary_path.exists();
+ let default_exists = fs::metadata(&default_path).is_ok();
+ let secondary_exists = fs::metadata(&secondary_path).is_ok();
if !self.owns_directory {
self.span_err(id_sp,
let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut();
match included_mod_stack.iter().position(|p| *p == path) {
Some(i) => {
- let mut err = String::from_str("circular modules: ");
+ let mut err = String::from("circular modules: ");
let len = included_mod_stack.len();
for p in &included_mod_stack[i.. len] {
err.push_str(&p.to_string_lossy());
assert_eq!(n, szs.len());
let mut i = left;
let mut l = lim;
- let mut s = string::String::from_str("[");
+ let mut s = string::String::from("[");
while i != right && l != 0 {
l -= 1;
if i != left {
use ptr::P;
use std_inject;
-use std::{ascii, mem};
+use std::ascii;
use std::io::{self, Write, Read};
use std::iter;
pub fn to_string<F>(f: F) -> String where
F: FnOnce(&mut State) -> io::Result<()>,
{
- use std::raw::TraitObject;
- let mut s = rust_printer(box Vec::new());
- f(&mut s).unwrap();
- eof(&mut s.s).unwrap();
- let wr = unsafe {
- // FIXME(pcwalton): A nasty function to extract the string from an `Write`
- // that we "know" to be a `Vec<u8>` that works around the lack of checked
- // downcasts.
- let obj: &TraitObject = mem::transmute(&s.s.out);
- mem::transmute::<*mut (), &Vec<u8>>(obj.data)
- };
- String::from_utf8(wr.clone()).unwrap()
+ let mut wr = Vec::new();
+ {
+ let mut printer = rust_printer(Box::new(&mut wr));
+ f(&mut printer).unwrap();
+ eof(&mut printer.s).unwrap();
+ }
+ String::from_utf8(wr).unwrap()
}
pub fn binop_to_string(op: BinOpToken) -> &'static str {
match lit.node {
ast::LitStr(ref st, style) => self.print_string(&st, style),
ast::LitByte(byte) => {
- let mut res = String::from_str("b'");
+ let mut res = String::from("b'");
res.extend(ascii::escape_default(byte).map(|c| c as char));
res.push('\'');
word(&mut self.s, &res[..])
}
ast::LitChar(ch) => {
- let mut res = String::from_str("'");
+ let mut res = String::from("'");
res.extend(ch.escape_default());
res.push('\'');
word(&mut self.s, &res[..])
/// Construct a `P<T>` from a `T` value.
pub fn P<T: 'static>(value: T) -> P<T> {
P {
- ptr: box value
+ ptr: Box::new(value)
}
}
--- /dev/null
+// Copyright 2012-2014 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 fn char_at(s: &str, byte: usize) -> char {
+ s[byte..].chars().next().unwrap()
+}
use parse::parser::Parser;
use parse::token;
use ptr::P;
+use str::char_at;
/// Map a string to tts, using a made-up filename:
pub fn string_to_tts(source_str: String) -> Vec<ast::TokenTree> {
else if idx_a == a.len() {return false;}
else if idx_b == b.len() {
// maybe the stuff left in a is all ws?
- if is_whitespace(a.char_at(idx_a)) {
+ if is_whitespace(char_at(a, idx_a)) {
return scan_for_non_ws_or_end(a,idx_a) == a.len();
} else {
return false;
}
}
// ws in both given and pattern:
- else if is_whitespace(a.char_at(idx_a))
- && is_whitespace(b.char_at(idx_b)) {
+ else if is_whitespace(char_at(a, idx_a))
+ && is_whitespace(char_at(b, idx_b)) {
idx_a = scan_for_non_ws_or_end(a,idx_a);
idx_b = scan_for_non_ws_or_end(b,idx_b);
}
// ws in given only:
- else if is_whitespace(a.char_at(idx_a)) {
+ else if is_whitespace(char_at(a, idx_a)) {
idx_a = scan_for_non_ws_or_end(a,idx_a);
}
// *don't* silently eat ws in expected only.
- else if a.char_at(idx_a) == b.char_at(idx_b) {
+ else if char_at(a, idx_a) == char_at(b, idx_b) {
idx_a += 1;
idx_b += 1;
}
fn scan_for_non_ws_or_end(a : &str, idx: usize) -> usize {
let mut i = idx;
let len = a.len();
- while (i < len) && (is_whitespace(a.char_at(i))) {
+ while (i < len) && (is_whitespace(char_at(a, i))) {
i += 1;
}
i
let result: &[T] = &[];
result
}
- One(ref v) => slice::ref_slice(v),
+ One(ref v) => {
+ // FIXME: Could be replaced with `slice::ref_slice(v)` when it is stable.
+ unsafe { slice::from_raw_parts(v, 1) }
+ }
Many(ref vs) => vs
}
}
assert_eq!(numfnames.len(), numnames.len());
assert_eq!(stringfnames.len(), stringnames.len());
}
-
- #[test]
- #[ignore(reason = "no ncurses on buildbots, needs a bundled terminfo file to test against")]
- fn test_parse() {
- // FIXME #6870: Distribute a compiled file in src/tests and test there
- // parse(old_io::fs_reader(&p("/usr/share/terminfo/r/rxvt-256color")).unwrap(), false);
- }
}
#![feature(std_misc)]
#![feature(libc)]
#![feature(set_stdio)]
-#![cfg_attr(test, feature(old_io))]
extern crate getopts;
extern crate serialize;
use std::io::prelude::*;
use std::io;
use std::iter::repeat;
-use std::num::{Float, Int};
use std::path::PathBuf;
use std::sync::mpsc::{channel, Sender};
use std::sync::{Arc, Mutex};
#[derive(Clone, PartialEq)]
pub struct BenchSamples {
- ns_iter_summ: stats::Summary<f64>,
+ ns_iter_summ: stats::Summary,
mb_s: usize,
}
}
// This is a more statistics-driven benchmark algorithm
- pub fn auto_bench<F>(&mut self, mut f: F) -> stats::Summary<f64> where F: FnMut(&mut Bencher) {
+ pub fn auto_bench<F>(&mut self, mut f: F) -> stats::Summary where F: FnMut(&mut Bencher) {
// Initial bench run to get ballpark figure.
let mut n = 1;
self.bench_n(n, |x| f(x));
use std::cmp::Ordering::{self, Less, Greater, Equal};
use std::mem;
-use std::num::{Float, FromPrimitive};
-fn local_cmp<T:Float>(x: T, y: T) -> Ordering {
+fn local_cmp(x: f64, y: f64) -> Ordering {
// arbitrarily decide that NaNs are larger than everything.
if y.is_nan() {
Less
}
}
-fn local_sort<T: Float>(v: &mut [T]) {
- v.sort_by(|x: &T, y: &T| local_cmp(*x, *y));
+fn local_sort(v: &mut [f64]) {
+ v.sort_by(|x: &f64, y: &f64| local_cmp(*x, *y));
}
/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
-pub trait Stats <T: Float + FromPrimitive> {
+pub trait Stats {
/// Sum of the samples.
///
/// Depends on IEEE-754 arithmetic guarantees. See proof of correctness at:
/// ["Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates"]
/// (http://www.cs.cmu.edu/~quake-papers/robust-arithmetic.ps)
- fn sum(&self) -> T;
+ fn sum(&self) -> f64;
/// Minimum value of the samples.
- fn min(&self) -> T;
+ fn min(&self) -> f64;
/// Maximum value of the samples.
- fn max(&self) -> T;
+ fn max(&self) -> f64;
/// Arithmetic mean (average) of the samples: sum divided by sample-count.
///
/// See: https://en.wikipedia.org/wiki/Arithmetic_mean
- fn mean(&self) -> T;
+ fn mean(&self) -> f64;
/// Median of the samples: value separating the lower half of the samples from the higher half.
/// Equal to `self.percentile(50.0)`.
///
/// See: https://en.wikipedia.org/wiki/Median
- fn median(&self) -> T;
+ fn median(&self) -> f64;
/// Variance of the samples: bias-corrected mean of the squares of the differences of each
/// sample from the sample mean. Note that this calculates the _sample variance_ rather than the
/// than `n`.
///
/// See: https://en.wikipedia.org/wiki/Variance
- fn var(&self) -> T;
+ fn var(&self) -> f64;
/// Standard deviation: the square root of the sample variance.
///
/// `median_abs_dev` for unknown distributions.
///
/// See: https://en.wikipedia.org/wiki/Standard_deviation
- fn std_dev(&self) -> T;
+ fn std_dev(&self) -> f64;
/// Standard deviation as a percent of the mean value. See `std_dev` and `mean`.
///
/// Note: this is not a robust statistic for non-normal distributions. Prefer the
/// `median_abs_dev_pct` for unknown distributions.
- fn std_dev_pct(&self) -> T;
+ fn std_dev_pct(&self) -> f64;
/// Scaled median of the absolute deviations of each sample from the sample median. This is a
/// robust (distribution-agnostic) estimator of sample variability. Use this in preference to
/// deviation.
///
/// See: http://en.wikipedia.org/wiki/Median_absolute_deviation
- fn median_abs_dev(&self) -> T;
+ fn median_abs_dev(&self) -> f64;
/// Median absolute deviation as a percent of the median. See `median_abs_dev` and `median`.
- fn median_abs_dev_pct(&self) -> T;
+ fn median_abs_dev_pct(&self) -> f64;
/// Percentile: the value below which `pct` percent of the values in `self` fall. For example,
/// percentile(95.0) will return the value `v` such that 95% of the samples `s` in `self`
/// Calculated by linear interpolation between closest ranks.
///
/// See: http://en.wikipedia.org/wiki/Percentile
- fn percentile(&self, pct: T) -> T;
+ fn percentile(&self, pct: f64) -> f64;
/// Quartiles of the sample: three values that divide the sample into four equal groups, each
/// with 1/4 of the data. The middle value is the median. See `median` and `percentile`. This
/// is otherwise equivalent.
///
/// See also: https://en.wikipedia.org/wiki/Quartile
- fn quartiles(&self) -> (T,T,T);
+ fn quartiles(&self) -> (f64,f64,f64);
/// Inter-quartile range: the difference between the 25th percentile (1st quartile) and the 75th
/// percentile (3rd quartile). See `quartiles`.
///
/// See also: https://en.wikipedia.org/wiki/Interquartile_range
- fn iqr(&self) -> T;
+ fn iqr(&self) -> f64;
}
/// Extracted collection of all the summary statistics of a sample set.
#[derive(Clone, PartialEq)]
#[allow(missing_docs)]
-pub struct Summary<T> {
- pub sum: T,
- pub min: T,
- pub max: T,
- pub mean: T,
- pub median: T,
- pub var: T,
- pub std_dev: T,
- pub std_dev_pct: T,
- pub median_abs_dev: T,
- pub median_abs_dev_pct: T,
- pub quartiles: (T,T,T),
- pub iqr: T,
+pub struct Summary {
+ pub sum: f64,
+ pub min: f64,
+ pub max: f64,
+ pub mean: f64,
+ pub median: f64,
+ pub var: f64,
+ pub std_dev: f64,
+ pub std_dev_pct: f64,
+ pub median_abs_dev: f64,
+ pub median_abs_dev_pct: f64,
+ pub quartiles: (f64,f64,f64),
+ pub iqr: f64,
}
-impl<T: Float + FromPrimitive> Summary<T> {
+impl Summary {
/// Construct a new summary of a sample set.
- pub fn new(samples: &[T]) -> Summary<T> {
+ pub fn new(samples: &[f64]) -> Summary {
Summary {
sum: samples.sum(),
min: samples.min(),
}
}
-impl<T: Float + FromPrimitive> Stats<T> for [T] {
+impl Stats for [f64] {
// FIXME #11059 handle NaN, inf and overflow
- fn sum(&self) -> T {
+ fn sum(&self) -> f64 {
let mut partials = vec![];
for &x in self {
// This inner loop applies `hi`/`lo` summation to each
// partial so that the list of partial sums remains exact.
for i in 0..partials.len() {
- let mut y: T = partials[i];
+ let mut y: f64 = partials[i];
if x.abs() < y.abs() {
mem::swap(&mut x, &mut y);
}
// `lo`. Together `hi+lo` are exactly equal to `x+y`.
let hi = x + y;
let lo = y - (hi - x);
- if lo != Float::zero() {
+ if lo != 0.0 {
partials[j] = lo;
j += 1;
}
partials.truncate(j+1);
}
}
- let zero: T = Float::zero();
+ let zero: f64 = 0.0;
partials.iter().fold(zero, |p, q| p + *q)
}
- fn min(&self) -> T {
+ fn min(&self) -> f64 {
assert!(!self.is_empty());
self.iter().fold(self[0], |p, q| p.min(*q))
}
- fn max(&self) -> T {
+ fn max(&self) -> f64 {
assert!(!self.is_empty());
self.iter().fold(self[0], |p, q| p.max(*q))
}
- fn mean(&self) -> T {
+ fn mean(&self) -> f64 {
assert!(!self.is_empty());
- self.sum() / FromPrimitive::from_usize(self.len()).unwrap()
+ self.sum() / (self.len() as f64)
}
- fn median(&self) -> T {
- self.percentile(FromPrimitive::from_usize(50).unwrap())
+ fn median(&self) -> f64 {
+ self.percentile(50 as f64)
}
- fn var(&self) -> T {
+ fn var(&self) -> f64 {
if self.len() < 2 {
- Float::zero()
+ 0.0
} else {
let mean = self.mean();
- let mut v: T = Float::zero();
+ let mut v: f64 = 0.0;
for s in self {
let x = *s - mean;
v = v + x*x;
// NB: this is _supposed to be_ len-1, not len. If you
// change it back to len, you will be calculating a
// population variance, not a sample variance.
- let denom = FromPrimitive::from_usize(self.len()-1).unwrap();
+ let denom = (self.len() - 1) as f64;
v/denom
}
}
- fn std_dev(&self) -> T {
+ fn std_dev(&self) -> f64 {
self.var().sqrt()
}
- fn std_dev_pct(&self) -> T {
- let hundred = FromPrimitive::from_usize(100).unwrap();
+ fn std_dev_pct(&self) -> f64 {
+ let hundred = 100 as f64;
(self.std_dev() / self.mean()) * hundred
}
- fn median_abs_dev(&self) -> T {
+ fn median_abs_dev(&self) -> f64 {
let med = self.median();
- let abs_devs: Vec<T> = self.iter().map(|&v| (med - v).abs()).collect();
+ let abs_devs: Vec<f64> = self.iter().map(|&v| (med - v).abs()).collect();
// This constant is derived by smarter statistics brains than me, but it is
// consistent with how R and other packages treat the MAD.
- let number = FromPrimitive::from_f64(1.4826).unwrap();
+ let number = 1.4826;
abs_devs.median() * number
}
- fn median_abs_dev_pct(&self) -> T {
- let hundred = FromPrimitive::from_usize(100).unwrap();
+ fn median_abs_dev_pct(&self) -> f64 {
+ let hundred = 100 as f64;
(self.median_abs_dev() / self.median()) * hundred
}
- fn percentile(&self, pct: T) -> T {
+ fn percentile(&self, pct: f64) -> f64 {
let mut tmp = self.to_vec();
local_sort(&mut tmp);
percentile_of_sorted(&tmp, pct)
}
- fn quartiles(&self) -> (T,T,T) {
+ fn quartiles(&self) -> (f64,f64,f64) {
let mut tmp = self.to_vec();
local_sort(&mut tmp);
- let first = FromPrimitive::from_usize(25).unwrap();
+ let first = 25f64;
let a = percentile_of_sorted(&tmp, first);
- let secound = FromPrimitive::from_usize(50).unwrap();
+ let secound = 50f64;
let b = percentile_of_sorted(&tmp, secound);
- let third = FromPrimitive::from_usize(75).unwrap();
+ let third = 75f64;
let c = percentile_of_sorted(&tmp, third);
(a,b,c)
}
- fn iqr(&self) -> T {
+ fn iqr(&self) -> f64 {
let (a,_,c) = self.quartiles();
c - a
}
// Helper function: extract a value representing the `pct` percentile of a sorted sample-set, using
// linear interpolation. If samples are not sorted, return nonsensical value.
-fn percentile_of_sorted<T: Float + FromPrimitive>(sorted_samples: &[T],
- pct: T) -> T {
+fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 {
assert!(!sorted_samples.is_empty());
if sorted_samples.len() == 1 {
return sorted_samples[0];
}
- let zero: T = Float::zero();
+ let zero: f64 = 0.0;
assert!(zero <= pct);
- let hundred = FromPrimitive::from_usize(100).unwrap();
+ let hundred = 100f64;
assert!(pct <= hundred);
if pct == hundred {
return sorted_samples[sorted_samples.len() - 1];
}
- let length = FromPrimitive::from_usize(sorted_samples.len() - 1).unwrap();
+ let length = (sorted_samples.len() - 1) as f64;
let rank = (pct / hundred) * length;
let lrank = rank.floor();
let d = rank - lrank;
- let n = lrank.to_usize().unwrap();
+ let n = lrank as usize;
let lo = sorted_samples[n];
let hi = sorted_samples[n+1];
lo + (hi - lo) * d
}
-/// Winsorize a set of samples, replacing values above the `100-pct` percentile and below the `pct`
-/// percentile with those percentiles themselves. This is a way of minimizing the effect of
-/// outliers, at the cost of biasing the sample. It differs from trimming in that it does not
-/// change the number of samples, just changes the values of those that are outliers.
+/// Winsorize a set of samples, replacing values above the `100-pct` percentile
+/// and below the `pct` percentile with those percentiles themselves. This is a
+/// way of minimizing the effect of outliers, at the cost of biasing the sample.
+/// It differs from trimming in that it does not change the number of samples,
+/// just changes the values of those that are outliers.
///
/// See: http://en.wikipedia.org/wiki/Winsorising
-pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) {
+pub fn winsorize(samples: &mut [f64], pct: f64) {
let mut tmp = samples.to_vec();
local_sort(&mut tmp);
let lo = percentile_of_sorted(&tmp, pct);
- let hundred: T = FromPrimitive::from_usize(100).unwrap();
+ let hundred = 100 as f64;
let hi = percentile_of_sorted(&tmp, hundred-pct);
for samp in samples {
if *samp > hi {
macro_rules! assert_approx_eq {
($a:expr, $b:expr) => ({
- use std::num::Float;
let (a, b) = (&$a, &$b);
assert!((*a - *b).abs() < 1.0e-6,
"{} is not approximately equal to {}", *a, *b);
})
}
- fn check(samples: &[f64], summ: &Summary<f64>) {
+ fn check(samples: &[f64], summ: &Summary) {
let summ2 = Summary::new(samples);
options.NoFramePointerElim = true;
ExecutionEngine *ee =
- #if LLVM_VERSION_MINOR <= 5
- EngineBuilder(unwrap(mod))
- .setMCJITMemoryManager(unwrap(mref))
- #else
+ #if LLVM_VERSION_MINOR >= 6
EngineBuilder(std::unique_ptr<Module>(unwrap(mod)))
.setMCJITMemoryManager(std::unique_ptr<RustJITMemoryManager>(unwrap(mref)))
+ #else
+ EngineBuilder(unwrap(mod))
+ .setMCJITMemoryManager(unwrap(mref))
#endif
.setEngineKind(EngineKind::JIT)
.setErrorStr(&error_str)
TargetOptions Options;
Options.PositionIndependentExecutable = PositionIndependentExecutable;
Options.NoFramePointerElim = NoFramePointerElim;
-#if LLVM_VERSION_MINOR < 5
- Options.EnableSegmentedStacks = EnableSegmentedStacks;
-#endif
Options.FloatABIType = FloatABI::Default;
Options.UseSoftFloat = UseSoftFloat;
if (UseSoftFloat) {
PassManagerBase *PM = unwrap(PMR);
#if LLVM_VERSION_MINOR >= 6
PM->add(new DataLayoutPass());
-#elif LLVM_VERSION_MINOR == 5
- PM->add(new DataLayoutPass(unwrap(M)));
#else
- PM->add(new DataLayout(unwrap(M)));
+ PM->add(new DataLayoutPass(unwrap(M)));
#endif
unwrap(TM)->addAnalysisPasses(*PM);
}
raw_fd_ostream OS(path, EC, sys::fs::F_None);
if (EC)
ErrorInfo = EC.message();
-#elif LLVM_VERSION_MINOR >= 4
- raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None);
#else
- raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary);
+ raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None);
#endif
if (ErrorInfo != "") {
LLVMRustSetLastError(ErrorInfo.c_str());
raw_fd_ostream OS(path, EC, sys::fs::F_None);
if (EC)
ErrorInfo = EC.message();
-#elif LLVM_VERSION_MINOR >= 4
- raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None);
#else
- raw_fd_ostream OS(path, ErrorInfo, raw_fd_ostream::F_Binary);
+ raw_fd_ostream OS(path, ErrorInfo, sys::fs::F_None);
#endif
formatted_raw_ostream FOS(OS);
-#if LLVM_VERSION_MINOR >= 5
PM->add(createPrintModulePass(FOS));
-#else
- PM->add(createPrintModulePass(&FOS));
-#endif
PM->run(*unwrap(M));
}
bool isLocalToUnit,
LLVMValueRef Val,
LLVMMetadataRef Decl = NULL) {
-#if LLVM_VERSION_MINOR == 6
+#if LLVM_VERSION_MINOR >= 6
return wrap(Builder->createGlobalVariable(unwrapDI<DIDescriptor>(Context),
#else
return wrap(Builder->createStaticVariable(unwrapDI<DIDescriptor>(Context),
int64_t* AddrOps,
unsigned AddrOpsCount,
unsigned ArgNo) {
-#if LLVM_VERSION_MINOR < 6
+#if LLVM_VERSION_MINOR == 5
if (AddrOpsCount > 0) {
SmallVector<llvm::Value *, 16> addr_ops;
llvm::Type *Int64Ty = Type::getInt64Ty(unwrap<MDNode>(Scope)->getContext());
extern "C" bool
LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
Module *Dst = unwrap(dst);
-#if LLVM_VERSION_MINOR == 5
- MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
- ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
-#else
+#if LLVM_VERSION_MINOR >= 6
std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
+#else
+ MemoryBuffer* buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
+ ErrorOr<Module *> Src = llvm::getLazyBitcodeModule(buf, Dst->getContext());
#endif
if (!Src) {
LLVMRustSetLastError(Src.getError().message().c_str());
return ret;
}
-extern "C" const char*
#if LLVM_VERSION_MINOR >= 6
-LLVMRustArchiveReadSection(OwningBinary<Archive> *ob, char *name, size_t *size) {
-
- Archive *ar = ob->getBinary();
+typedef OwningBinary<Archive> RustArchive;
+#define GET_ARCHIVE(a) ((a)->getBinary())
#else
-LLVMRustArchiveReadSection(Archive *ar, char *name, size_t *size) {
+typedef Archive RustArchive;
+#define GET_ARCHIVE(a) (a)
#endif
- Archive::child_iterator child = ar->child_begin(),
- end = ar->child_end();
- for (; child != end; ++child) {
- ErrorOr<StringRef> name_or_err = child->getName();
- if (name_or_err.getError()) continue;
- StringRef sect_name = name_or_err.get();
- if (sect_name.trim(" ") == name) {
- StringRef buf = child->getBuffer();
- *size = buf.size();
- return buf.data();
- }
- }
- return NULL;
+extern "C" void
+LLVMRustDestroyArchive(RustArchive *ar) {
+ delete ar;
+}
+
+struct RustArchiveIterator {
+ Archive::child_iterator cur;
+ Archive::child_iterator end;
+};
+
+extern "C" RustArchiveIterator*
+LLVMRustArchiveIteratorNew(RustArchive *ra) {
+ Archive *ar = GET_ARCHIVE(ra);
+ RustArchiveIterator *rai = new RustArchiveIterator();
+ rai->cur = ar->child_begin();
+ rai->end = ar->child_end();
+ return rai;
+}
+
+extern "C" const Archive::Child*
+LLVMRustArchiveIteratorCurrent(RustArchiveIterator *rai) {
+ if (rai->cur == rai->end)
+ return NULL;
+ const Archive::Child &ret = *rai->cur;
+ return &ret;
}
extern "C" void
-#if LLVM_VERSION_MINOR >= 6
-LLVMRustDestroyArchive(OwningBinary<Archive> *ar) {
-#else
-LLVMRustDestroyArchive(Archive *ar) {
-#endif
- delete ar;
+LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
+ if (rai->cur == rai->end)
+ return;
+ ++rai->cur;
}
extern "C" void
-LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) {
- GlobalValue *V = unwrap<GlobalValue>(Value);
- V->setDLLStorageClass(GlobalValue::DLLExportStorageClass);
+LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) {
+ delete rai;
}
-extern "C" int
-LLVMVersionMinor() {
- return LLVM_VERSION_MINOR;
+extern "C" const char*
+LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
+ ErrorOr<StringRef> name_or_err = child->getName();
+ if (name_or_err.getError())
+ return NULL;
+ StringRef name = name_or_err.get();
+ *size = name.size();
+ return name.data();
}
-extern "C" int
-LLVMVersionMajor() {
- return LLVM_VERSION_MAJOR;
+extern "C" const char*
+LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
+ StringRef buf = child->getBuffer();
+ *size = buf.size();
+ return buf.data();
+}
+
+extern "C" void
+LLVMRustSetDLLExportStorageClass(LLVMValueRef Value) {
+ GlobalValue *V = unwrap<GlobalValue>(Value);
+ V->setDLLStorageClass(GlobalValue::DLLExportStorageClass);
}
// Note that the two following functions look quite similar to the
#include "llvm-c/ExecutionEngine.h"
#include "llvm-c/Object.h"
-#if LLVM_VERSION_MINOR >= 5
#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/Linker/Linker.h"
-#else
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/DebugInfo.h"
-#include "llvm/DIBuilder.h"
-#include "llvm/Linker.h"
-#endif
// Used by RustMCJITMemoryManager::getPointerToNamedFunction()
// to get around glibc issues. See the function for more information.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(core)]
-
-use std::marker::MarkerTrait;
-
-pub trait Foo : MarkerTrait {
+pub trait Foo {
fn bar();
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(std_misc, old_path)]
+#![feature(std_misc)]
use std::dynamic_lib::DynamicLibrary;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(core)]
-
-trait Foo : ::std::marker::MarkerTrait {}
+trait Foo {}
pub mod bar {
use std::marker;
- pub trait Bar: marker::MarkerTrait + 'static {}
+ pub trait Bar: 'static {}
impl Bar for .. {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
#![feature(core)]
-use std::marker::MarkerTrait;
-
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
//! (#14132).
#![crate_name = "a"]
-#![feature(core)]
-
-use std::marker::MarkerTrait;
macro_rules! three {
() => { 3 }
}
-pub trait U : MarkerTrait {}
-pub trait V : MarkerTrait {}
+pub trait U {}
+pub trait V {}
impl U for () {}
impl V for () {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(core)]
-
-pub trait Foo : ::std::marker::MarkerTrait {
+pub trait Foo {
}
impl Foo for isize {
#![feature(optin_builtin_traits, core)]
#![crate_type = "rlib"]
-use std::marker::MarkerTrait;
-
-pub trait DefaultedTrait : MarkerTrait { }
+pub trait DefaultedTrait { }
impl DefaultedTrait for .. { }
pub struct Something<T> { t: T }
#![feature(rand, core)]
use std::f32::consts::PI;
-use std::num::Float;
use std::__rand::{Rng, thread_rng};
#[derive(Copy, Clone)]
let long_lived_tree = bottom_up_tree(&long_lived_arena, 0, max_depth);
let messages = (min_depth..max_depth + 1).step_by(2).map(|depth| {
- use std::num::Int;
- let iterations = 2.pow((max_depth - depth + min_depth) as u32);
+ let iterations = 2i32.pow((max_depth - depth + min_depth) as u32);
thread::spawn(move || inner(depth, iterations))
}).collect::<Vec<_>>();
use std::fs::File;
use std::io::{self, BufWriter};
use std::io::prelude::*;
-use std::num::Float;
const LINE_LENGTH: usize = 60;
const IM: u32 = 139968;
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
-#![feature(core)]
-
-use std::num::Float;
+use std::mem;
const PI: f64 = 3.141592653589793;
const SOLAR_MASS: f64 = 4.0 * PI * PI;
/// longer contain the mutable reference. This is a safe operation because the
/// two mutable borrows are entirely disjoint.
fn shift_mut_ref<'a, T>(r: &mut &'a mut [T]) -> Option<&'a mut T> {
- use std::mem;
- use std::raw::Repr;
-
- if r.is_empty() { return None }
- unsafe {
- let mut raw = r.repr();
- let ret = raw.data as *mut T;
- raw.data = raw.data.offset(1);
- raw.len -= 1;
- *r = mem::transmute(raw);
- Some({ &mut *ret })
- }
+ let res = mem::replace(r, &mut []);
+ if res.is_empty() { return None }
+ let (a, b) = res.split_at_mut(1);
+ *r = b;
+ Some(&mut a[0])
}
use std::iter::repeat;
use std::thread;
use std::mem;
-use std::num::Float;
use std::os;
use std::env;
use std::raw::Repr;
use std::io::prelude::*;
use std::io;
use std::iter::repeat;
-use std::num::Int;
use std::env;
// Computes a single solution to a given 9x9 sudoku
// Check that an associated type cannot be bound in an expression path.
-trait Foo : ::std::marker::MarkerTrait {
+trait Foo {
type A;
fn bar() -> isize;
}
// Test that we do not ICE when an impl is missing an associated type (and that we report
// a useful error, of course).
-trait Trait : ::std::marker::MarkerTrait {
+trait Trait {
type Type;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo : ::std::marker::MarkerTrait {
+trait Foo {
type X;
type Y;
}
// which checks that the trait interface itself is not considered an
// error as long as all impls satisfy the constraint.
-trait Get : ::std::marker::MarkerTrait {
+trait Get {
type Value;
}
// which checks that the trait interface itself is not considered an
// error as long as all impls satisfy the constraint.
-trait Get : ::std::marker::MarkerTrait {
+trait Get {
type Value;
}
// Check that an associated type cannot be bound in an expression path.
-trait Foo : ::std::marker::MarkerTrait {
+trait Foo {
type A;
fn bar() -> isize;
}
use std::cell::RefCell;
-trait Trait : ::std::marker::MarkerTrait {}
+trait Trait {}
pub fn main() {
let x: Vec<Trait + Sized> = Vec::new();
use std::fmt::Debug;
use std::default::Default;
-use std::marker::MarkerTrait;
// Test that two blanket impls conflict (at least without negative
// bounds). After all, some other crate could implement Even or Odd
fn get(&self) -> usize;
}
-trait Even : MarkerTrait { }
+trait Even { }
-trait Odd : MarkerTrait { }
+trait Odd { }
impl Even for isize { }
fn get(&self) -> usize;
}
-trait Even : ::std::marker::MarkerTrait { }
+trait Even {}
-trait Odd : ::std::marker::MarkerTrait { }
+trait Odd {}
impl<T:Even> MyTrait for T { //~ ERROR E0119
fn get(&self) -> usize { 0 }
#![feature(optin_builtin_traits)]
-trait MyTrait : ::std::marker::MarkerTrait {}
+trait MyTrait {}
struct TestType<T>(::std::marker::PhantomData<T>);
#![feature(optin_builtin_traits)]
-use std::marker::MarkerTrait;
-
-trait MyTrait: MarkerTrait {}
+trait MyTrait {}
impl MyTrait for .. {}
impl MyTrait for .. {}
//~^ ERROR conflicting implementations for trait `MyTrait`
-trait MySafeTrait: MarkerTrait {}
+trait MySafeTrait {}
unsafe impl MySafeTrait for .. {}
//~^ ERROR implementing the trait `MySafeTrait` is not unsafe
-unsafe trait MyUnsafeTrait: MarkerTrait {}
+unsafe trait MyUnsafeTrait {}
impl MyUnsafeTrait for .. {}
//~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
extern crate coherence_copy_like_lib as lib;
-use std::marker::MarkerTrait;
-
struct MyType { x: i32 }
-trait MyTrait : MarkerTrait { }
+trait MyTrait { }
impl<T: lib::MyCopy> MyTrait for T { } //~ ERROR E0119
extern crate coherence_copy_like_lib as lib;
-use std::marker::MarkerTrait;
-
struct MyType { x: i32 }
-trait MyTrait : MarkerTrait { }
+trait MyTrait { }
impl<T: lib::MyCopy> MyTrait for T { } //~ ERROR E0119
// `MyStruct` is not declared fundamental, therefore this would
extern crate coherence_copy_like_lib as lib;
-use std::marker::MarkerTrait;
-
struct MyType { x: i32 }
-trait MyTrait : MarkerTrait { }
+trait MyTrait { }
impl<T: lib::MyCopy> MyTrait for T { } //~ ERROR E0119
// Tuples are not fundamental, therefore this would require that
}
struct Foo;
-trait Bar : ::std::marker::MarkerTrait {}
+trait Bar {}
impl Bar for Foo {}
pub fn main() {
// Test implicit coercions involving DSTs and raw pointers.
-use std::marker::MarkerTrait;
-
struct S;
-trait T : MarkerTrait {}
+trait T {}
impl T for S {}
struct Foo<T: ?Sized> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::num::SignedInt;
-
fn main() {
- let _f = 10.abs; //~ ERROR attempted to take value of method
+ let _f = 10i32.abs; //~ ERROR attempted to take value of method
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::marker::MarkerTrait;
-
-trait Node : MarkerTrait {
+trait Node {
fn zomg();
}
// except according to those terms.
use std::fmt::Debug;
-use std::marker::MarkerTrait;
-trait Str : MarkerTrait {}
+trait Str {}
trait Something {
fn yay<T: Debug>(_: Option<Self>, thing: &[T]);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::marker::MarkerTrait;
-
-trait ListItem<'a> : MarkerTrait {
+trait ListItem<'a> {
fn list_name() -> &'a str;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::marker::MarkerTrait;
-
-pub trait AbstractRenderer : MarkerTrait {}
+pub trait AbstractRenderer {}
fn _create_render(_: &()) ->
AbstractRenderer
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(unboxed_closures)]
-
use std::any::Any;
use std::any::TypeId;
-use std::marker::MarkerTrait;
-pub trait Pt : MarkerTrait {}
-pub trait Rt : MarkerTrait {}
+pub trait Pt {}
+pub trait Rt {}
trait Private<P: Pt, R: Rt> {
fn call(&self, p: P, r: R);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::marker::MarkerTrait;
-
fn add_state(op: <isize as HasState>::State) {
//~^ ERROR the trait `HasState` is not implemented for the type `isize`
}
-trait HasState : MarkerTrait {
+trait HasState {
type State;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::marker::MarkerTrait;
-
-trait Foo : MarkerTrait {
+trait Foo {
type Item;
}
// cause compiler to loop. Note that no instances
// of such a type could ever be constructed.
-use std::marker::MarkerTrait;
-
struct t(Box<t>); //~ ERROR this type cannot be instantiated
-trait to_str_2 : MarkerTrait {
+trait to_str_2 {
fn my_to_string() -> String;
}
// away.
use std::cell::RefCell;
-use std::marker::MarkerTrait;
use std::ops::{Shl, Shr};
-pub trait Subscriber : MarkerTrait {
+pub trait Subscriber {
type Input;
}
#![feature(optin_builtin_traits)]
-use std::marker::MarkerTrait;
-
-unsafe trait Trait: MarkerTrait {
+unsafe trait Trait {
//~^ error: traits with default impls (`e.g. unsafe impl Trait for ..`) must have no methods or associated items
type Output;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::num::ToPrimitive;
+pub trait ToPrimitive {
+ fn to_int(&self) -> isize { 0 }
+}
+
+impl ToPrimitive for i32 {}
+impl ToPrimitive for isize {}
trait Add {
fn to_int(&self) -> isize;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::marker::MarkerTrait;
-
-trait I : MarkerTrait {}
+trait I {}
type K = I+'static;
fn foo(_x: K) {} //~ ERROR: the trait `core::marker::Sized` is not implemented
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::marker::MarkerTrait;
-
-trait A : MarkerTrait {}
+trait A {}
struct Struct {
r: A+'static
Struct { r: r }
}
-trait Curve : MarkerTrait {}
+trait Curve {}
enum E {X(Curve+'static)}
fn main() {}
// Test the mechanism for warning about possible missing `self` declarations.
-use std::marker::MarkerTrait;
-
trait CtxtFn {
fn f8(self, usize) -> usize;
fn f9(usize) -> usize; //~ NOTE candidate
}
-trait OtherTrait : MarkerTrait {
+trait OtherTrait {
fn f9(usize) -> usize; //~ NOTE candidate
}
// declaration to match against, so we wind up prisizeing it as a
// candidate. This seems not unreasonable -- perhaps the user meant to
// implement it, after all.
-trait UnusedTrait : MarkerTrait {
+trait UnusedTrait {
fn f9(usize) -> usize; //~ NOTE candidate
}
}
}
-trait ManyImplTrait : MarkerTrait {
+trait ManyImplTrait {
fn is_str() -> bool { //~ NOTE candidate
false
}
// Test which of the builtin types are considered POD.
-use std::marker::MarkerTrait;
use std::rc::Rc;
fn assert_copy<T:Copy>() { }
-trait Dummy : MarkerTrait { }
+trait Dummy { }
#[derive(Copy, Clone)]
struct MyStruct {
#![feature(box_syntax)]
-use std::marker::MarkerTrait;
-
-trait Foo : MarkerTrait {
+trait Foo {
}
impl<T:Copy> Foo for T {
// in this file all test the "kind" violates detected during kindck.
// See all `regions-bounded-by-send.rs`
-use std::marker::MarkerTrait;
-
fn assert_send<T:Send>() { }
-trait Dummy : MarkerTrait { }
+trait Dummy { }
trait Message : Send { }
// careful with object types, who knows what they close over...
// is broken into two parts because some errors occur in distinct
// phases in the compiler. See kindck-send-object2.rs as well!
-use std::marker::MarkerTrait;
-
fn assert_send<T:Send+'static>() { }
-trait Dummy : MarkerTrait { }
+trait Dummy { }
// careful with object types, who knows what they close over...
fn test51<'a>() {
// Continue kindck-send-object1.rs.
-use std::marker::MarkerTrait;
-
fn assert_send<T:Send>() { }
-trait Dummy : MarkerTrait { }
+trait Dummy { }
fn test50() {
assert_send::<&'static Dummy>(); //~ ERROR the trait `core::marker::Sync` is not implemented
fn bar(&self) -> Private<isize> { panic!() }
}
-pub trait ParamTrait<T> : marker::MarkerTrait {
+pub trait ParamTrait<T> {
fn foo() -> T;
}
// Test that an object type `Box<Foo>` is not considered to implement the
// trait `Foo`. Issue #5087.
-use std::marker::MarkerTrait;
-
-trait Foo : MarkerTrait {}
+trait Foo {}
fn take_foo<F:Foo>(f: F) {}
fn take_object(f: Box<Foo>) { take_foo(f); }
//~^ ERROR the trait `Foo` is not implemented
// Check that we correctly prevent users from making trait objects
// from traits with static methods.
-trait Foo : ::std::marker::MarkerTrait {
+trait Foo {
fn foo();
}
#![feature(optin_builtin_traits)]
-use std::marker::{MarkerTrait, PhantomData};
+use std::marker::{PhantomData};
-unsafe trait Zen: MarkerTrait {}
+unsafe trait Zen {}
unsafe impl Zen for .. {}
// public type, private value
pub mod foo1 {
- use std::marker::MarkerTrait;
-
- pub trait Bar : MarkerTrait {
+ pub trait Bar {
}
pub struct Baz;
// private type, public value
pub mod foo2 {
- trait Bar : ::std::marker::MarkerTrait {
+ trait Bar {
}
pub struct Baz;
// neither public
pub mod foo3 {
- trait Bar : ::std::marker::MarkerTrait {
+ trait Bar {
}
pub struct Baz;
// Test that attempts to implicitly coerce a value into an
// object respect the lifetime bound on the object type.
-trait Foo : ::std::marker::MarkerTrait {}
+trait Foo {}
impl<'a> Foo for &'a [u8] {}
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
// FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-use std::marker::MarkerTrait;
-
-trait X : MarkerTrait {}
+trait X {}
trait Iter {
type Item: X;
#![feature(box_syntax)]
-use std::marker::MarkerTrait;
-
-trait Foo : MarkerTrait { }
+trait Foo { }
impl<'a> Foo for &'a isize { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait TraitNotAStruct : ::std::marker::MarkerTrait { }
+trait TraitNotAStruct {}
fn main() {
TraitNotAStruct{ value: 0 };
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::marker::MarkerTrait;
-
-trait Trait : MarkerTrait {}
+trait Trait {}
struct Foo<T:Trait> {
x: T,
// Tests for "default" bounds inferred for traits with no bounds list.
-use std::marker::MarkerTrait;
-
-trait Foo : MarkerTrait {}
+trait Foo {}
fn a(_x: Box<Foo+Send>) {
}
// trait impl is only applied to a trait object, not concrete types which implement
// the trait.
-use std::marker::MarkerTrait;
-
-trait T : MarkerTrait {}
+trait T {}
impl<'a> T+'a {
fn foo(&self) {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::num::Int;
+use std::ops::Add;
-trait BrokenAdd: Int {
+trait BrokenAdd: Copy + Add<Output=Self> {
fn broken_add<T>(&self, rhs: T) -> Self {
*self + rhs //~ ERROR mismatched types
//~| expected `Self`
}
}
-impl<T: Int> BrokenAdd for T {}
+impl<T: Copy + Add<Output=T>> BrokenAdd for T {}
pub fn main() {
let foo: u8 = 0;
#![feature(optin_builtin_traits)]
-use std::marker::MarkerTrait;
-
-trait MyTrait: MarkerTrait {}
+trait MyTrait {}
impl MyTrait for .. {}
#![feature(optin_builtin_traits)]
-use std::marker::MarkerTrait;
-
-trait MyTrait: MarkerTrait {}
+trait MyTrait {}
impl MyTrait for .. {}
impl<T> !MyTrait for *mut T {}
#![feature(optin_builtin_traits)]
-use std::marker::MarkerTrait;
-
-trait MyTrait: MarkerTrait {}
+trait MyTrait {}
impl MyTrait for .. {}
-unsafe trait MyUnsafeTrait: MarkerTrait {}
+unsafe trait MyUnsafeTrait {}
unsafe impl MyUnsafeTrait for .. {}
#![feature(optin_builtin_traits)]
-use std::marker::MarkerTrait;
-
-trait Defaulted : MarkerTrait { }
+trait Defaulted { }
impl Defaulted for .. { }
impl<'a,T:Signed> Defaulted for &'a T { }
impl<'a,T:Signed> Defaulted for &'a mut T { }
fn is_defaulted<T:Defaulted>() { }
-trait Signed : MarkerTrait { }
+trait Signed { }
impl Signed for i32 { }
fn main() {
#![feature(optin_builtin_traits)]
-use std::marker::MarkerTrait;
-
trait MyTrait : 'static {}
impl MyTrait for .. {}
#![feature(optin_builtin_traits)]
-use std::marker::MarkerTrait;
-
-trait NotImplemented: MarkerTrait { }
+trait NotImplemented { }
trait MyTrait : NotImplemented {}
#![feature(optin_builtin_traits)]
-use std::marker::MarkerTrait;
+trait NotImplemented { }
-trait NotImplemented: MarkerTrait { }
-
-trait MyTrait: MarkerTrait
+trait MyTrait
where Option<Self> : NotImplemented
{}
// Test `?Sized` local variables.
-use std::marker;
-
-trait T : marker::MarkerTrait { }
+trait T {}
fn f1<X: ?Sized>(x: &X) {
let _: X; // <-- this is OK, no bindings created, no initializer.
// Test sized-ness checking in substitution in impls.
-use std::marker::MarkerTrait;
-
-trait T : MarkerTrait {}
+trait T {}
// I would like these to fail eventually.
// impl - bounded
// aux-build:issue13213aux.rs
-#![feature(old_io)]
-
extern crate issue13213aux;
// compile-flags:-g
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(optin_builtin_traits, core)]
+#![feature(optin_builtin_traits)]
// pp-exact
-use std::marker::MarkerTrait;
-
-trait MyTrait: MarkerTrait { }
+trait MyTrait { }
impl MyTrait for .. { }
--- /dev/null
+-include ../tools.mk
+
+all:
+ mkdir $(TMPDIR)/a
+ mkdir $(TMPDIR)/b
+ $(CC) -c -o $(TMPDIR)/a/foo.o foo.c
+ $(CC) -c -o $(TMPDIR)/b/foo.o bar.c
+ ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o
+ $(RUSTC) foo.rs
+ $(RUSTC) bar.rs
+ $(call RUN,bar)
--- /dev/null
+// 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.
+
+void bar() {}
--- /dev/null
+// 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.
+
+extern crate foo;
+
+fn main() {
+ foo::baz();
+}
--- /dev/null
+// 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.
+
+void foo() {}
--- /dev/null
+// 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.
+
+#![crate_type = "rlib"]
+
+#[link(name = "foo", kind = "static")]
+extern {
+ fn foo();
+ fn bar();
+}
+
+pub fn baz() {
+ unsafe {
+ foo();
+ bar();
+ }
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(old_io, old_path)]
-
use std::env;
use std::fs::File;
use std::process::Command;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(std_misc, old_path, os)]
+#![feature(std_misc)]
use std::dynamic_lib::DynamicLibrary;
-use std::os;
use std::path::Path;
pub fn main() {
use sub::sub2;
use sub::sub2::nested_struct as sub_struct;
use std::num::One;
-use std::num::cast;
-use std::num::{from_int,from_i8,from_i32};
use std::mem::size_of;
// import tests
fn foo(x: &One) {}
- let _: Option<u8> = from_i32(45);
let x = 42;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(core)]
-
-use std::marker::MarkerTrait;
-
-trait Foo : MarkerTrait {
+trait Foo {
type T;
}
// pretty-expanded FIXME #23616
-#![feature(core)]
-
-use std::marker::MarkerTrait;
-
impl X for f64 { type Y = isize; }
-trait X : MarkerTrait { type Y; }
+trait X { type Y; }
fn main() {}
#![feature(core)]
-use std::marker::MarkerTrait;
use std::slice;
-trait Bound : MarkerTrait {}
+trait Bound {}
impl<'a> Bound for &'a i32 {}
// pretty-expanded FIXME #23616
-#![feature(core)]
#![allow(dead_code)]
-use std::marker::MarkerTrait;
-
-pub trait Integral : MarkerTrait {
+pub trait Integral {
type Opposite;
}
// `Item` originates in a where-clause, not the declaration of
// `T`. Issue #20300.
-
-#![feature(core)]
-
-use std::marker::{MarkerTrait, PhantomData};
+use std::marker::{PhantomData};
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
use std::sync::atomic::Ordering::SeqCst;
static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
// Preamble.
-trait Trait : MarkerTrait { type Item; }
+trait Trait { type Item; }
struct Struct;
impl Trait for Struct {
type Item = u32;
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
-#![feature(unboxed_closures, old_io)]
-
-use std::mem;
+#![feature(unboxed_closures)]
fn call_it<F>(f: F)
where F : FnOnce(String) -> String
macro_rules! assert_approx_eq {
($a:expr, $b:expr) => ({
- use std::num::Float;
let (a, b) = (&$a, &$b);
assert!((*a - *b).abs() < 1.0e-6,
"{} is not approximately equal to {}", *a, *b);
Quux(u32),
}
-#[derive(FromPrimitive)]
enum Baz { A=0, B=5, }
fn main() {
+++ /dev/null
-// Copyright 2013-2014 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.
-
-#![feature(core)]
-
-use std::num::FromPrimitive;
-use std::isize;
-
-#[derive(PartialEq, FromPrimitive, Debug)]
-enum A {
- Foo = isize::MAX,
- Bar = 1,
- Baz = 3,
- Qux,
-}
-
-pub fn main() {
- let x: Option<A> = FromPrimitive::from_int(isize::MAX);
- assert_eq!(x, Some(A::Foo));
-
- let x: Option<A> = FromPrimitive::from_int(1);
- assert_eq!(x, Some(A::Bar));
-
- let x: Option<A> = FromPrimitive::from_int(3);
- assert_eq!(x, Some(A::Baz));
-
- let x: Option<A> = FromPrimitive::from_int(4);
- assert_eq!(x, Some(A::Qux));
-
- let x: Option<A> = FromPrimitive::from_int(5);
- assert_eq!(x, None);
-}
// except according to those terms.
-#![feature(str_words)]
-
fn main() {
let foo = "hello".to_string();
- let foo: Vec<&str> = foo.words().collect();
+ let foo: Vec<&str> = foo.split_whitespace().collect();
let invalid_string = &foo[0];
assert_eq!(*invalid_string, "hello");
}
// pretty-expanded FIXME #23616
-use std::num::Int;
+use std::ops::Add;
-fn wsucc<T:Int>(n: T) -> T { n + { return n } }
+fn wsucc<T:Add<Output=T> + Copy>(n: T) -> T { n + { return n } }
pub fn main() { }
+++ /dev/null
-// Copyright 2014 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.
-
-
-#![feature(std_misc)]
-
-use std::num::strconv::ExponentFormat::{ExpBin, ExpDec};
-use std::num::strconv::SignificantDigits::DigMax;
-use std::num::strconv::SignFormat::{SignAll, SignNeg};
-use std::num::strconv::float_to_str_common as to_string;
-
-macro_rules! t {
- ($a:expr, $b:expr) => { { let (r, _) = $a; assert_eq!(r, $b.to_string()); } }
-}
-
-pub fn main() {
- // Basic usage
- t!(to_string(1.2345678e-5f64, 10, true, SignNeg, DigMax(6), ExpDec, false),
- "1.234568e-5");
-
- // Hexadecimal output
- t!(to_string(7.281738281250e+01f64, 16, true, SignAll, DigMax(6), ExpBin, false),
- "+1.2345p+6");
- t!(to_string(-1.777768135071e-02f64, 16, true, SignAll, DigMax(6), ExpBin, false),
- "-1.2345p-6");
-
- // Some denormals
- t!(to_string(4.9406564584124654e-324f64, 10, true, SignNeg, DigMax(6), ExpBin, false),
- "1p-1074");
- t!(to_string(2.2250738585072009e-308f64, 10, true, SignNeg, DigMax(6), ExpBin, false),
- "1p-1022");
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(core)]
-
-use std::marker::MarkerTrait;
-
-trait A : MarkerTrait {
+trait A {
extern "fastcall" fn test1(i: i32);
extern fn test2(i: i32);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-#![feature(std_misc)]
-
-use std::num::Float;
+use std::f64;
pub fn main() {
- let nan: f64 = Float::nan();
+ let nan: f64 = f64::NAN;
assert!((nan).is_nan());
- let inf: f64 = Float::infinity();
- let neg_inf: f64 = Float::neg_infinity();
+ let inf: f64 = f64::INFINITY;
+ let neg_inf: f64 = -f64::INFINITY;
assert_eq!(-inf, neg_inf);
assert!( nan != nan);
macro_rules! assert_approx_eq {
($a:expr, $b:expr) => ({
- use std::num::Float;
let (a, b) = (&$a, &$b);
assert!((*a - *b).abs() < 1.0e-6,
"{} is not approximately equal to {}", *a, *b);
// Make sure that if a process doesn't have its stdio/stderr descriptors set up
// that we don't die in a large ball of fire
-#![feature(old_io)]
-
use std::env;
use std::process::{Command, Stdio};
#![feature(collections)]
-extern crate collections;
-
use std::collections::BitVec;
-use std::num::Float;
fn main() {
// Generate sieve of Eratosthenes for n up to 1e6
// except according to those terms.
-#![feature(rustc_private, old_io)]
+#![feature(rustc_private)]
extern crate rbml;
extern crate serialize;
// pretty-expanded FIXME #23616
-#![feature(core)]
-
-use std::marker::MarkerTrait;
-
-trait Foo : MarkerTrait {
+trait Foo {
fn quux(u8) {}
}
// except according to those terms.
-#![feature(old_io, io)]
-
use std::env;
use std::process::Command;
use std::io::{self, Write};
trait IntoIterator {
type Iter: Iterator;
- fn into_iter(self) -> Self::Iter;
+ fn into_iter2(self) -> Self::Iter;
}
impl<I> IntoIterator for I where I: Iterator {
type Iter = I;
- fn into_iter(self) -> I {
+ fn into_iter2(self) -> I {
self
}
}
fn desugared_for_loop_bad<T>(v: Vec<T>) {
- match IntoIterator::into_iter(v.iter()) {
+ match IntoIterator::into_iter2(v.iter()) {
mut iter => {
loop {
match ::std::iter::Iterator::next(&mut iter) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+#![feature(zero_one)]
-#![feature(core)]
-
-use std::num::Int;
+use std::num::Zero;
use std::thread;
-// Avoid using constants, which would trigger compile-time errors.
-fn min_val<T: Int>() -> T { Int::min_value() }
-fn zero<T: Int>() -> T { Int::zero() }
-
fn main() {
- assert!(thread::spawn(move|| { min_val::<isize>() / -1; }).join().is_err());
- assert!(thread::spawn(move|| { min_val::<i8>() / -1; }).join().is_err());
- assert!(thread::spawn(move|| { min_val::<i16>() / -1; }).join().is_err());
- assert!(thread::spawn(move|| { min_val::<i32>() / -1; }).join().is_err());
- assert!(thread::spawn(move|| { min_val::<i64>() / -1; }).join().is_err());
- assert!(thread::spawn(move|| { 1isize / zero::<isize>(); }).join().is_err());
- assert!(thread::spawn(move|| { 1i8 / zero::<i8>(); }).join().is_err());
- assert!(thread::spawn(move|| { 1i16 / zero::<i16>(); }).join().is_err());
- assert!(thread::spawn(move|| { 1i32 / zero::<i32>(); }).join().is_err());
- assert!(thread::spawn(move|| { 1i64 / zero::<i64>(); }).join().is_err());
- assert!(thread::spawn(move|| { min_val::<isize>() % -1; }).join().is_err());
- assert!(thread::spawn(move|| { min_val::<i8>() % -1; }).join().is_err());
- assert!(thread::spawn(move|| { min_val::<i16>() % -1; }).join().is_err());
- assert!(thread::spawn(move|| { min_val::<i32>() % -1; }).join().is_err());
- assert!(thread::spawn(move|| { min_val::<i64>() % -1; }).join().is_err());
- assert!(thread::spawn(move|| { 1isize % zero::<isize>(); }).join().is_err());
- assert!(thread::spawn(move|| { 1i8 % zero::<i8>(); }).join().is_err());
- assert!(thread::spawn(move|| { 1i16 % zero::<i16>(); }).join().is_err());
- assert!(thread::spawn(move|| { 1i32 % zero::<i32>(); }).join().is_err());
- assert!(thread::spawn(move|| { 1i64 % zero::<i64>(); }).join().is_err());
+ assert!(thread::spawn(move|| { isize::min_value() / -1; }).join().is_err());
+ assert!(thread::spawn(move|| { i8::min_value() / -1; }).join().is_err());
+ assert!(thread::spawn(move|| { i16::min_value() / -1; }).join().is_err());
+ assert!(thread::spawn(move|| { i32::min_value() / -1; }).join().is_err());
+ assert!(thread::spawn(move|| { i64::min_value() / -1; }).join().is_err());
+ assert!(thread::spawn(move|| { 1isize / isize::zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i8 / i8::zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i16 / i16::zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i32 / i32::zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i64 / i64::zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { isize::min_value() % -1; }).join().is_err());
+ assert!(thread::spawn(move|| { i8::min_value() % -1; }).join().is_err());
+ assert!(thread::spawn(move|| { i16::min_value() % -1; }).join().is_err());
+ assert!(thread::spawn(move|| { i32::min_value() % -1; }).join().is_err());
+ assert!(thread::spawn(move|| { i64::min_value() % -1; }).join().is_err());
+ assert!(thread::spawn(move|| { 1isize % isize::zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i8 % i8::zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i16 % i16::zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i32 % i32::zero(); }).join().is_err());
+ assert!(thread::spawn(move|| { 1i64 % i64::zero(); }).join().is_err());
}
// ignore-android: FIXME(#10379)
// ignore-windows: std::dynamic_lib does not work on Windows well
-#![feature(std_misc, old_path)]
+#![feature(std_misc)]
extern crate linkage_visibility as foo;
// exec-env:RUST_LOG=debug
// compile-flags:-C debug-assertions=y
-#![feature(old_io, rustc_private)]
+#![feature(rustc_private)]
#[macro_use]
extern crate log;
// temporary. Issue #19147.
-#![feature(core, old_io)]
+#![feature(core)]
-use std::mem;
use std::slice;
pub type IoResult<T> = Result<T, ()>;
// pretty-expanded FIXME #23616
-#![feature(core)]
-
-use std::marker::MarkerTrait;
-
-trait Serializer : MarkerTrait {
+trait Serializer {
}
trait Serializable {
// necessary. Testing the methods of the impls is done within the source
// file for each numeric type.
-
-#![feature(core)]
-
use std::ops::Add;
-use std::num::ToPrimitive;
pub fn main() {
// ints
assert_eq!(15_u16.add(6u16), 21_u16);
assert_eq!(15_u32.add(6u32), 21_u32);
assert_eq!(15_u64.add(6u64), 21_u64);
-
-// floats
- // num
- assert_eq!(10_f32.to_i32().unwrap(), 10);
- assert_eq!(10_f64.to_i32().unwrap(), 10);
}
use std::cell::RefCell;
use std::rc::Rc;
-use std::num::ToPrimitive;
#[derive(PartialEq, Debug)]
struct Point {
pub fn main() {
let box_5: Box<_> = box 5_usize;
- assert_eq!(Rc::new(5_usize).to_uint(), Some(5));
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
- assert_eq!((Box::new(&Box::new(&Rc::new(Box::new(Box::new(&box_5)))))).to_uint(), Some(5));
let point = Rc::new(Point {x: 2, y: 4});
assert_eq!(point.x, 2);
assert_eq!(point.y, 4);
// intact.
// ignore-aarch64
-#![feature(path, fs, os, io, old_path)]
use std::io::prelude::*;
use std::io;
use std::fs;
use std::process::Command;
-use std::os;
use std::env;
-use std::path::{Path, PathBuf};
+use std::path::Path;
fn main() {
let my_args = env::args().collect::<Vec<_>>();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(start, os, std_misc, old_io)]
+#![feature(start, std_misc)]
use std::ffi::CStr;
use std::process::{Command, Output};
-use std::os;
use std::rt::unwind::try;
-use std::rt;
use std::str;
-use std::thread::Thread;
-use std::thunk::Thunk;
#[start]
fn start(argc: isize, argv: *const *const u8) -> isize {
// pretty-expanded FIXME #23616
-#![feature(optin_builtin_traits, core)]
-
-use std::marker::{MarkerTrait, Send};
+#![feature(optin_builtin_traits)]
struct TestType;
impl TestType {}
-trait TestTrait : MarkerTrait {}
+trait TestTrait {}
impl !Send for TestType {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// pretty-expanded FIXME #23616
-
-#![allow(unknown_features)]
-#![feature(box_syntax, old_io, std_misc, io, set_panic, set_stdio)]
+#![feature(box_syntax, set_stdio)]
use std::io::prelude::*;
use std::io;
// pretty-expanded FIXME #23616
-#![feature(core)]
-
-trait Foo : ::std::marker::MarkerTrait {
+trait Foo {
}
fn b(_x: Box<Foo+Send>) {
#![feature(core)]
-trait U : ::std::marker::MarkerTrait {}
+trait U {}
trait T<X: U> { fn get(self) -> X; }
-trait S2<Y: U> : ::std::marker::MarkerTrait {
+trait S2<Y: U> {
fn m(x: Box<T<Y>+'static>) {}
}
// pretty-expanded FIXME #23616
-#![feature(core)]
-
trait I { fn i(&self) -> Self; }
-trait A<T:I> : ::std::marker::MarkerTrait {
+trait A<T:I> {
fn id(x:T) -> T { x.i() }
}
trait J<T> { fn j(&self) -> T; }
-trait B<T:J<T>> : ::std::marker::MarkerTrait {
+trait B<T:J<T>> {
fn id(x:T) -> T { x.j() }
}
-trait C : ::std::marker::MarkerTrait {
+trait C {
fn id<T:J<T>>(x:T) -> T { x.j() }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![allow(unknown_features)]
-#![feature(box_syntax, old_io, io)]
+#![feature(box_syntax)]
use std::io::{self, Write};
// pretty-expanded FIXME #23616
-#![feature(core)]
-
-use std::cmp::{PartialEq, PartialOrd};
-use std::num::NumCast;
-
-pub trait NumExt: NumCast + PartialEq + PartialOrd {}
+pub trait NumExt: PartialEq + PartialOrd {}
pub trait FloatExt: NumExt {}
-fn greater_than_one<T: NumExt>(n: &T) -> bool { *n > NumCast::from(1).unwrap() }
-fn greater_than_one_float<T: FloatExt>(n: &T) -> bool { *n > NumCast::from(1).unwrap() }
+fn greater_than_one<T: NumExt>(n: &T) -> bool { loop {} }
+fn greater_than_one_float<T: FloatExt>(n: &T) -> bool { loop {} }
pub fn main() {}
#![feature(core)]
use std::cmp::PartialOrd;
-use std::num::NumCast;
+
+pub trait NumCast {
+ fn from(i: i32) -> Option<Self>;
+}
pub trait Num {
fn from_int(i: isize) -> Self;
// pretty-expanded FIXME #23616
-#![feature(core)]
-
-use std::cmp::PartialOrd;
-use std::num::NumCast;
+pub trait NumCast {
+ fn from(i: i32) -> Option<Self>;
+}
pub trait NumExt: NumCast + PartialOrd { }
// A more complex example of numeric extensions
-#![feature(core)]
-
-use std::cmp::{PartialEq, PartialOrd};
-use std::num::NumCast;
-
-pub trait TypeExt : ::std::marker::MarkerTrait { }
+pub trait TypeExt {}
impl TypeExt for u8 {}
impl TypeExt for u16 {}
impl TypeExt for f64 {}
-pub trait NumExt: TypeExt + PartialEq + PartialOrd + NumCast {}
+pub trait NumExt: TypeExt + PartialEq + PartialOrd {}
impl NumExt for u8 {}
impl NumExt for u16 {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(core)]
-
-use std::cmp::{PartialEq, PartialOrd};
-use std::num::NumCast;
+pub trait NumCast {
+ fn from(i: i32) -> Option<Self>;
+}
pub trait NumExt: PartialEq + PartialOrd + NumCast {}
impl NumExt for f32 {}
+impl NumCast for f32 {
+ fn from(i: i32) -> Option<f32> { Some(i as f32) }
+}
fn num_eq_one<T: NumExt>(n: T) {
println!("{}", n == NumCast::from(1).unwrap())
// pretty-expanded FIXME #23616
-#![feature(core)]
-
-use std::cmp::PartialEq;
-use std::num::NumCast;
+pub trait NumCast {
+ fn from(i: i32) -> Option<Self>;
+}
pub trait NumExt: PartialEq + NumCast {}
impl NumExt for f32 {}
impl NumExt for isize {}
+impl NumCast for f32 {
+ fn from(i: i32) -> Option<f32> { Some(i as f32) }
+}
+impl NumCast for isize {
+ fn from(i: i32) -> Option<isize> { Some(i as isize) }
+}
+
fn num_eq_one<T:NumExt>() -> T {
NumCast::from(1).unwrap()
}
// Test for issue #4183: use of Self in supertraits.
-
-use std::num::Float as StdFloat;
-
pub static FUZZY_EPSILON: f64 = 0.1;
pub trait FuzzyEq<Eps> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+pub trait MyEq {}
-#![feature(core)]
-
-pub trait MyEq : ::std::marker::MarkerTrait { }
-
-pub trait MyNum : ::std::marker::MarkerTrait {
+pub trait MyNum {
fn from_int(isize) -> Self;
}
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures, core)]
+pub trait ToPrimitive {
+ fn to_int(&self) {}
+}
-use std::num::ToPrimitive;
+impl ToPrimitive for isize {}
+impl ToPrimitive for i32 {}
+impl ToPrimitive for usize {}
fn doit<T,F>(val: T, f: &F)
where F : Fn(T)
{
- f.call((val,))
+ f(val)
}
pub fn main() {
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures, core)]
+pub trait ToPrimitive {
+ fn to_int(&self) {}
+}
-use std::num::ToPrimitive;
+impl ToPrimitive for isize {}
+impl ToPrimitive for i32 {}
+impl ToPrimitive for usize {}
-fn doit<T>(val: T, f: &Fn(T)) { f.call((val,)) }
+fn doit<T>(val: T, f: &Fn(T)) { f(val) }
pub fn main() {
doit(0, &|x /*: isize*/ | { x.to_int(); });
// pretty-expanded FIXME #23616
-#![feature(unboxed_closures, core)]
+pub trait ToPrimitive {
+ fn to_int(&self) {}
+}
-use std::num::ToPrimitive;
+impl ToPrimitive for isize {}
+impl ToPrimitive for i32 {}
+impl ToPrimitive for usize {}
fn doit<T,F>(val: T, f: &F)
where F : Fn(&T)
{
- f.call((&val,))
+ f(&val)
}
pub fn main() {
#![feature(non_ascii_idents)]
-use std::num::Float;
-
pub fn main() {
let ε = 0.00001f64;
let Π = 3.14f64;