auto merge of #16895 : alexcrichton/rust/rollup, r=alexcrichton
Let's try this again!
This commit is contained in:
commit
db47aa5bdf
@ -729,6 +729,31 @@ This part is coming soon.
|
||||
|
||||
This part is coming soon.
|
||||
|
||||
# Patterns and `ref`
|
||||
|
||||
When you're trying to match something that's stored in a pointer, there may be
|
||||
a situation where matching directly isn't the best option available. Let's see
|
||||
how to properly handle this:
|
||||
|
||||
```{rust,ignore}
|
||||
fn possibly_print(x: &Option<String>) {
|
||||
match *x {
|
||||
// BAD: cannot move out of a `&`
|
||||
Some(s) => println!("{}", s)
|
||||
|
||||
// GOOD: instead take a reference into the memory of the `Option`
|
||||
Some(ref s) => println!("{}", *s),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `ref s` here means that `s` will be of type `&String`, rather than type
|
||||
`String`.
|
||||
|
||||
This is important when the type you're trying to get access to has a destructor
|
||||
and you don't want to move it, you just want a reference to it.
|
||||
|
||||
# Cheat Sheet
|
||||
|
||||
Here's a quick rundown of Rust's pointer types:
|
||||
|
@ -297,7 +297,7 @@ $ mv hello_world.rs src/hello_world.rs
|
||||
```
|
||||
|
||||
Cargo expects your source files to live inside a `src` directory. That leaves
|
||||
the top level for other things, like READMEs, licence information, and anything
|
||||
the top level for other things, like READMEs, license information, and anything
|
||||
not related to your code. Cargo helps us keep our projects nice and tidy. A
|
||||
place for everything, and everything in its place.
|
||||
|
||||
@ -315,7 +315,7 @@ Put this inside:
|
||||
[package]
|
||||
|
||||
name = "hello_world"
|
||||
version = "0.1.0"
|
||||
version = "0.0.1"
|
||||
authors = [ "Your name <you@example.com>" ]
|
||||
|
||||
[[bin]]
|
||||
@ -630,7 +630,7 @@ In Rust, however, using `let` to introduce a binding is _not_ an expression. The
|
||||
following will produce a compile-time error:
|
||||
|
||||
```{ignore}
|
||||
let x = (let y = 5i); // found `let` in ident position
|
||||
let x = (let y = 5i); // expected identifier, found keyword `let`
|
||||
```
|
||||
|
||||
The compiler is telling us here that it was expecting to see the beginning of
|
||||
@ -1743,7 +1743,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
Sometimes, this makes things more readable. Sometimes, less. Use your judgement
|
||||
Sometimes, this makes things more readable. Sometimes, less. Use your judgment
|
||||
here.
|
||||
|
||||
That's all you need to get basic input from the standard input! It's not too
|
||||
@ -1813,7 +1813,7 @@ Try it out:
|
||||
|
||||
```{notrust,ignore}
|
||||
$ cargo run
|
||||
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
|
||||
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
|
||||
Running `target/guessing_game`
|
||||
Hello, world!
|
||||
```
|
||||
@ -1959,7 +1959,7 @@ Try running our new program a few times:
|
||||
|
||||
```{notrust,ignore}
|
||||
$ cargo run
|
||||
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
|
||||
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
|
||||
Running `target/guessing_game`
|
||||
Guess the number!
|
||||
The secret number is: 7
|
||||
@ -2012,7 +2012,7 @@ And trying it out:
|
||||
|
||||
```{notrust,ignore}
|
||||
$ cargo run
|
||||
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
|
||||
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
|
||||
Running `target/guessing_game`
|
||||
Guess the number!
|
||||
The secret number is: 57
|
||||
@ -2283,7 +2283,7 @@ print an error message and return. Let's give this a shot:
|
||||
|
||||
```{notrust,ignore}
|
||||
$ cargo run
|
||||
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
|
||||
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
|
||||
Running `target/guessing_game`
|
||||
Guess the number!
|
||||
The secret number is: 17
|
||||
@ -2348,7 +2348,7 @@ Let's try it!
|
||||
|
||||
```{notrust,ignore}
|
||||
$ cargo run
|
||||
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
|
||||
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
|
||||
Running `target/guessing_game`
|
||||
Guess the number!
|
||||
The secret number is: 58
|
||||
@ -2425,7 +2425,7 @@ that `return`? If we give a non-number answer, we'll `return` and quit. Observe:
|
||||
|
||||
```{notrust,ignore}
|
||||
$ cargo run
|
||||
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
|
||||
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
|
||||
Running `target/guessing_game`
|
||||
Guess the number!
|
||||
The secret number is: 59
|
||||
@ -2557,7 +2557,7 @@ Now we should be good! Let's try:
|
||||
|
||||
```{notrust,ignore}
|
||||
$ cargo run
|
||||
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
|
||||
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
|
||||
Running `target/guessing_game`
|
||||
Guess the number!
|
||||
The secret number is: 61
|
||||
@ -2659,7 +2659,7 @@ modules, which can contain other modules, as deeply as you'd like.
|
||||
Note that we haven't mentioned anything about files yet. Rust does not impose a
|
||||
particular relationship between your filesystem structure and your module
|
||||
structure. That said, there is a conventional approach to how Rust looks for
|
||||
modules on the file system, but it's also overrideable.
|
||||
modules on the file system, but it's also overridable.
|
||||
|
||||
Enough talk, let's build something! Let's make a new project called `modules`.
|
||||
|
||||
@ -2670,10 +2670,10 @@ $ cargo new modules --bin
|
||||
|
||||
Let's double check our work by compiling:
|
||||
|
||||
```{bash,ignore}
|
||||
$ cargo build
|
||||
```{bash,notrust}
|
||||
$ cargo run
|
||||
Compiling modules v0.0.1 (file:///home/you/projects/modules)
|
||||
$ ./target/modules
|
||||
Running `target/modules`
|
||||
Hello, world!
|
||||
```
|
||||
|
||||
@ -3011,7 +3011,7 @@ markers.
|
||||
Rust provides six attributes to indicate the stability level of various
|
||||
parts of your library. The six levels are:
|
||||
|
||||
* deprecated: this item should no longer be used. No guarantee of backwards
|
||||
* deprecated: This item should no longer be used. No guarantee of backwards
|
||||
compatibility.
|
||||
* experimental: This item was only recently introduced or is otherwise in a
|
||||
state of flux. It may change significantly, or even be removed. No guarantee
|
||||
@ -3300,7 +3300,7 @@ To learn more, run the command again with --verbose.
|
||||
|
||||
Rust can't find this function. That makes sense, as we didn't write it yet!
|
||||
|
||||
In order to share this codes with our tests, we'll need to make a library crate.
|
||||
In order to share this code with our tests, we'll need to make a library crate.
|
||||
This is also just good software design: as we mentioned before, it's a good idea
|
||||
to put most of your functionality into a library crate, and have your executable
|
||||
crate use that library. This allows for code re-use.
|
||||
@ -3511,7 +3511,7 @@ exporting the name again, somewhere else.
|
||||
|
||||
We've now covered the basics of testing. Rust's tools are primitive, but they
|
||||
work well in the simple cases. There are some Rustaceans working on building
|
||||
more complicated frameworks on top of all of this, but thery're just starting
|
||||
more complicated frameworks on top of all of this, but they're just starting
|
||||
out.
|
||||
|
||||
# Pointers
|
||||
@ -3668,15 +3668,20 @@ because it's easy. And if you need precise control over when something is
|
||||
deallocated, leaving it up to your runtime can make this difficult.
|
||||
|
||||
Rust chooses a different path, and that path is called **ownership**. Any
|
||||
binding that creates a resource is the **owner** of that resource. Being an
|
||||
owner gives you three privileges, with two restrictions:
|
||||
binding that creates a resource is the **owner** of that resource.
|
||||
|
||||
Being an owner affords you some privileges:
|
||||
|
||||
1. You control when that resource is deallocated.
|
||||
2. You may lend that resource, immutably, to as many borrowers as you'd like.
|
||||
3. You may lend that resource, mutably, to a single borrower. **BUT**
|
||||
4. Once you've done so, you may not also lend it out otherwise, mutably or
|
||||
immutably.
|
||||
5. You may not lend it out mutably if you're currently lending it to someone.
|
||||
3. You may lend that resource, mutably, to a single borrower.
|
||||
|
||||
But it also comes with some restrictions:
|
||||
|
||||
1. If someone is borrowing your resource (either mutably or immutably), you may
|
||||
not mutate the resource or mutably lend it to someone.
|
||||
2. If someone is mutably borrowing your resource, you may not lend it out at
|
||||
all (mutably or immutably) or access it in any way.
|
||||
|
||||
What's up with all this 'lending' and 'borrowing'? When you allocate memory,
|
||||
you get a pointer to that memory. This pointer allows you to manipulate said
|
||||
@ -4063,7 +4068,7 @@ match x {
|
||||
}
|
||||
```
|
||||
|
||||
If you have a struct, you can desugar it inside of a pattern:
|
||||
If you have a struct, you can destructure it inside of a pattern:
|
||||
|
||||
```{rust}
|
||||
struct Point {
|
||||
@ -4223,7 +4228,7 @@ don't need to declare one. This is different from named functions, which
|
||||
default to returning unit (`()`).
|
||||
|
||||
There's one big difference between a closure and named functions, and it's in
|
||||
the name: a function "closes over its environment." What's that mean? It means
|
||||
the name: a closure "closes over its environment." What's that mean? It means
|
||||
this:
|
||||
|
||||
```{rust}
|
||||
@ -5494,7 +5499,7 @@ fn main() {
|
||||
|
||||
Whew! This isn't too terrible. You can see that we still `let x = 5i`,
|
||||
but then things get a little bit hairy. Three more bindings get set: a
|
||||
static format string, an argument vector, and the aruments. We then
|
||||
static format string, an argument vector, and the arguments. We then
|
||||
invoke the `println_args` function with the generated arguments.
|
||||
|
||||
This is the code (well, the full version) that Rust actually compiles. You can
|
||||
@ -5510,7 +5515,7 @@ Guide can help you if you want to write your own.
|
||||
|
||||
# Unsafe
|
||||
|
||||
Finally, there's one more concept that you should be aware in Rust: `unsafe`.
|
||||
Finally, there's one more Rust concept that you should be aware of: `unsafe`.
|
||||
There are two circumstances where Rust's safety provisions don't work well.
|
||||
The first is when interfacing with C code, and the second is when building
|
||||
certain kinds of abstractions.
|
||||
|
@ -2215,14 +2215,14 @@ These types help drive the compiler's analysis
|
||||
|
||||
* `begin_unwind`
|
||||
: ___Needs filling in___
|
||||
* `managed_bound`
|
||||
: This type implements "managed"
|
||||
* `no_copy_bound`
|
||||
: This type does not implement "copy", even if eligible
|
||||
* `no_send_bound`
|
||||
: This type does not implement "send", even if eligible
|
||||
* `no_sync_bound`
|
||||
: This type does not implement "sync", even if eligible
|
||||
* `managed_bound`
|
||||
: This type implements "managed"
|
||||
* `no_share_bound`
|
||||
: This type does not implement "share", even if eligible
|
||||
* `eh_personality`
|
||||
: ___Needs filling in___
|
||||
* `exchange_free`
|
||||
|
@ -12,7 +12,7 @@
|
||||
//!
|
||||
//! This is the lowest level library through which allocation in Rust can be
|
||||
//! performed where the allocation is assumed to succeed. This library will
|
||||
//! trigger a task failure when allocation fails.
|
||||
//! abort the process when allocation fails.
|
||||
//!
|
||||
//! This library, like libcore, is not intended for general usage, but rather as
|
||||
//! a building block of other libraries. The types and interfaces in this
|
||||
|
@ -160,6 +160,8 @@ pub trait Signed: Num + Neg<Self> {
|
||||
/// Computes the absolute value.
|
||||
///
|
||||
/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
|
||||
///
|
||||
/// For signed integers, `::MIN` will be returned if the number is `::MIN`.
|
||||
fn abs(&self) -> Self;
|
||||
|
||||
/// The positive difference of two numbers.
|
||||
@ -176,7 +178,7 @@ pub trait Signed: Num + Neg<Self> {
|
||||
/// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||
/// * `NaN` if the number is `NaN`
|
||||
///
|
||||
/// For `int`:
|
||||
/// For signed integers:
|
||||
///
|
||||
/// * `0` if the number is zero
|
||||
/// * `1` if the number is positive
|
||||
@ -272,6 +274,8 @@ signed_float_impl!(f64, f64::NAN, f64::INFINITY, f64::NEG_INFINITY,
|
||||
/// Computes the absolute value.
|
||||
///
|
||||
/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
|
||||
///
|
||||
/// For signed integers, `::MIN` will be returned if the number is `::MIN`.
|
||||
#[inline(always)]
|
||||
pub fn abs<T: Signed>(value: T) -> T {
|
||||
value.abs()
|
||||
@ -294,7 +298,7 @@ pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
|
||||
/// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||
/// * `NaN` if the number is `NaN`
|
||||
///
|
||||
/// For int:
|
||||
/// For signed integers:
|
||||
///
|
||||
/// * `0` if the number is zero
|
||||
/// * `1` if the number is positive
|
||||
|
@ -57,31 +57,31 @@ use raw::Slice as RawSlice;
|
||||
// Extension traits
|
||||
//
|
||||
|
||||
/// Extension methods for vectors
|
||||
/// Extension methods for immutable slices.
|
||||
#[unstable = "may merge with other traits; region parameter may disappear"]
|
||||
pub trait ImmutableSlice<'a, T> {
|
||||
/**
|
||||
* Returns a slice of self spanning the interval [`start`, `end`).
|
||||
*
|
||||
* Fails when the slice (or part of it) is outside the bounds of self,
|
||||
* or when `start` > `end`.
|
||||
*/
|
||||
/// Returns a subslice spanning the interval [`start`, `end`).
|
||||
///
|
||||
/// Fails when the end of the new slice lies beyond the end of the
|
||||
/// original slice (i.e. when `end > self.len()`) or when `start > end`.
|
||||
///
|
||||
/// Slicing with `start` equal to `end` yields an empty slice.
|
||||
#[unstable]
|
||||
fn slice(&self, start: uint, end: uint) -> &'a [T];
|
||||
|
||||
/**
|
||||
* Returns a slice of self from `start` to the end of the vec.
|
||||
*
|
||||
* Fails when `start` points outside the bounds of self.
|
||||
*/
|
||||
/// Returns a subslice from `start` to the end of the slice.
|
||||
///
|
||||
/// Fails when `start` is strictly greater than the length of the original slice.
|
||||
///
|
||||
/// Slicing from `self.len()` yields an empty slice.
|
||||
#[unstable]
|
||||
fn slice_from(&self, start: uint) -> &'a [T];
|
||||
|
||||
/**
|
||||
* Returns a slice of self from the start of the vec to `end`.
|
||||
*
|
||||
* Fails when `end` points outside the bounds of self.
|
||||
*/
|
||||
/// Returns a subslice from the start of the slice to `end`.
|
||||
///
|
||||
/// Fails when `end` is strictly greater than the length of the original slice.
|
||||
///
|
||||
/// Slicing to `0` yields an empty slice.
|
||||
#[unstable]
|
||||
fn slice_to(&self, end: uint) -> &'a [T];
|
||||
|
||||
@ -486,21 +486,26 @@ pub trait MutableSlice<'a, T> {
|
||||
/// Primarily intended for getting a &mut [T] from a [T, ..N].
|
||||
fn as_mut_slice(self) -> &'a mut [T];
|
||||
|
||||
/// Return a slice that points into another slice.
|
||||
/// Returns a mutable subslice spanning the interval [`start`, `end`).
|
||||
///
|
||||
/// Fails when the end of the new slice lies beyond the end of the
|
||||
/// original slice (i.e. when `end > self.len()`) or when `start > end`.
|
||||
///
|
||||
/// Slicing with `start` equal to `end` yields an empty slice.
|
||||
fn mut_slice(self, start: uint, end: uint) -> &'a mut [T];
|
||||
|
||||
/**
|
||||
* Returns a slice of self from `start` to the end of the vec.
|
||||
*
|
||||
* Fails when `start` points outside the bounds of self.
|
||||
*/
|
||||
/// Returns a mutable subslice from `start` to the end of the slice.
|
||||
///
|
||||
/// Fails when `start` is strictly greater than the length of the original slice.
|
||||
///
|
||||
/// Slicing from `self.len()` yields an empty slice.
|
||||
fn mut_slice_from(self, start: uint) -> &'a mut [T];
|
||||
|
||||
/**
|
||||
* Returns a slice of self from the start of the vec to `end`.
|
||||
*
|
||||
* Fails when `end` points outside the bounds of self.
|
||||
*/
|
||||
/// Returns a mutable subslice from the start of the slice to `end`.
|
||||
///
|
||||
/// Fails when `end` is strictly greater than the length of the original slice.
|
||||
///
|
||||
/// Slicing to `0` yields an empty slice.
|
||||
fn mut_slice_to(self, end: uint) -> &'a mut [T];
|
||||
|
||||
/// Returns an iterator that allows modifying each value
|
||||
@ -515,14 +520,14 @@ pub trait MutableSlice<'a, T> {
|
||||
fn mut_split(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T>;
|
||||
|
||||
/**
|
||||
* Returns an iterator over `size` elements of the vector at a time.
|
||||
* The chunks are mutable and do not overlap. If `size` does not divide the
|
||||
* length of the vector, then the last chunk will not have length
|
||||
* `size`.
|
||||
* Returns an iterator over `chunk_size` elements of the vector at a time.
|
||||
* The chunks are mutable and do not overlap. If `chunk_size` does
|
||||
* not divide the length of the vector, then the last chunk will not
|
||||
* have length `chunk_size`.
|
||||
*
|
||||
* # Failure
|
||||
*
|
||||
* Fails if `size` is 0.
|
||||
* Fails if `chunk_size` is 0.
|
||||
*/
|
||||
fn mut_chunks(self, chunk_size: uint) -> MutChunks<'a, T>;
|
||||
|
||||
|
@ -8,120 +8,154 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/*!
|
||||
|
||||
Utilities for program-wide and customizable logging
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
#![feature(phase)]
|
||||
#[phase(plugin, link)] extern crate log;
|
||||
|
||||
fn main() {
|
||||
debug!("this is a debug {}", "message");
|
||||
error!("this is printed by default");
|
||||
|
||||
if log_enabled!(log::INFO) {
|
||||
let x = 3i * 4i; // expensive computation
|
||||
info!("the answer was: {}", x);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Logging Macros
|
||||
|
||||
There are five macros that the logging subsystem uses:
|
||||
|
||||
* `log!(level, ...)` - the generic logging macro, takes a level as a u32 and any
|
||||
related `format!` arguments
|
||||
* `debug!(...)` - a macro hard-wired to the log level of `DEBUG`
|
||||
* `info!(...)` - a macro hard-wired to the log level of `INFO`
|
||||
* `warn!(...)` - a macro hard-wired to the log level of `WARN`
|
||||
* `error!(...)` - a macro hard-wired to the log level of `ERROR`
|
||||
|
||||
All of these macros use the same style of syntax as the `format!` syntax
|
||||
extension. Details about the syntax can be found in the documentation of
|
||||
`std::fmt` along with the Rust tutorial/manual.
|
||||
|
||||
If you want to check at runtime if a given logging level is enabled (e.g. if the
|
||||
information you would want to log is expensive to produce), you can use the
|
||||
following macro:
|
||||
|
||||
* `log_enabled!(level)` - returns true if logging of the given level is enabled
|
||||
|
||||
## Enabling logging
|
||||
|
||||
Log levels are controlled on a per-module basis, and by default all logging is
|
||||
disabled except for `error!` (a log level of 1). Logging is controlled via the
|
||||
`RUST_LOG` environment variable. The value of this environment variable is a
|
||||
comma-separated list of logging directives. A logging directive is of the form:
|
||||
|
||||
```text
|
||||
path::to::module=log_level
|
||||
```
|
||||
|
||||
The path to the module is rooted in the name of the crate it was compiled for,
|
||||
so if your program is contained in a file `hello.rs`, for example, to turn on
|
||||
logging for this file you would use a value of `RUST_LOG=hello`.
|
||||
Furthermore, this path is a prefix-search, so all modules nested in the
|
||||
specified module will also have logging enabled.
|
||||
|
||||
The actual `log_level` is optional to specify. If omitted, all logging will be
|
||||
enabled. If specified, the it must be either a numeric in the range of 1-255, or
|
||||
it must be one of the strings `debug`, `error`, `info`, or `warn`. If a numeric
|
||||
is specified, then all logging less than or equal to that numeral is enabled.
|
||||
For example, if logging level 3 is active, error, warn, and info logs will be
|
||||
printed, but debug will be omitted.
|
||||
|
||||
As the log level for a module is optional, the module to enable logging for is
|
||||
also optional. If only a `log_level` is provided, then the global log level for
|
||||
all modules is set to this value.
|
||||
|
||||
Some examples of valid values of `RUST_LOG` are:
|
||||
|
||||
* `hello` turns on all logging for the 'hello' module
|
||||
* `info` turns on all info logging
|
||||
* `hello=debug` turns on debug logging for 'hello'
|
||||
* `hello=3` turns on info logging for 'hello'
|
||||
* `hello,std::option` turns on hello, and std's option logging
|
||||
* `error,hello=warn` turn on global error logging and also warn for hello
|
||||
|
||||
## Filtering results
|
||||
|
||||
A RUST_LOG directive may include a regex filter. The syntax is to append `/`
|
||||
followed by a regex. Each message is checked against the regex, and is only
|
||||
logged if it matches. Note that the matching is done after formatting the log
|
||||
string but before adding any logging meta-data. There is a single filter for all
|
||||
modules.
|
||||
|
||||
Some examples:
|
||||
|
||||
* `hello/foo` turns on all logging for the 'hello' module where the log message
|
||||
includes 'foo'.
|
||||
* `info/f.o` turns on all info logging where the log message includes 'foo',
|
||||
'f1o', 'fao', etc.
|
||||
* `hello=debug/foo*foo` turns on debug logging for 'hello' where the the log
|
||||
message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
|
||||
* `error,hello=warn/[0-9] scopes` turn on global error logging and also warn for
|
||||
hello. In both cases the log message must include a single digit number
|
||||
followed by 'scopes'
|
||||
|
||||
## Performance and Side Effects
|
||||
|
||||
Each of these macros will expand to code similar to:
|
||||
|
||||
```rust,ignore
|
||||
if log_level <= my_module_log_level() {
|
||||
::log::log(log_level, format!(...));
|
||||
}
|
||||
```
|
||||
|
||||
What this means is that each of these macros are very cheap at runtime if
|
||||
they're turned off (just a load and an integer comparison). This also means that
|
||||
if logging is disabled, none of the components of the log will be executed.
|
||||
|
||||
*/
|
||||
//! Utilities for program-wide and customizable logging
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```
|
||||
//! #![feature(phase)]
|
||||
//! #[phase(plugin, link)] extern crate log;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! debug!("this is a debug {}", "message");
|
||||
//! error!("this is printed by default");
|
||||
//!
|
||||
//! if log_enabled!(log::INFO) {
|
||||
//! let x = 3i * 4i; // expensive computation
|
||||
//! info!("the answer was: {}", x);
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Assumes the binary is `main`:
|
||||
//!
|
||||
//! ```{.bash}
|
||||
//! $ RUST_LOG=error ./main
|
||||
//! ERROR:main: this is printed by default
|
||||
//! ```
|
||||
//!
|
||||
//! ```{.bash}
|
||||
//! $ RUST_LOG=info ./main
|
||||
//! ERROR:main: this is printed by default
|
||||
//! INFO:main: the answer was: 12
|
||||
//! ```
|
||||
//!
|
||||
//! ```{.bash}
|
||||
//! $ RUST_LOG=debug ./main
|
||||
//! DEBUG:main: this is a debug message
|
||||
//! ERROR:main: this is printed by default
|
||||
//! INFO:main: the answer was: 12
|
||||
//! ```
|
||||
//!
|
||||
//! You can also set the log level on a per module basis:
|
||||
//!
|
||||
//! ```{.bash}
|
||||
//! $ RUST_LOG=main=info ./main
|
||||
//! ERROR:main: this is printed by default
|
||||
//! INFO:main: the answer was: 12
|
||||
//! ```
|
||||
//!
|
||||
//! And enable all logging:
|
||||
//!
|
||||
//! ```{.bash}
|
||||
//! $ RUST_LOG=main ./main
|
||||
//! DEBUG:main: this is a debug message
|
||||
//! ERROR:main: this is printed by default
|
||||
//! INFO:main: the answer was: 12
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! ## Logging Macros
|
||||
//!
|
||||
//! There are five macros that the logging subsystem uses:
|
||||
//!
|
||||
//! * `log!(level, ...)` - the generic logging macro, takes a level as a u32 and any
|
||||
//! related `format!` arguments
|
||||
//! * `debug!(...)` - a macro hard-wired to the log level of `DEBUG`
|
||||
//! * `info!(...)` - a macro hard-wired to the log level of `INFO`
|
||||
//! * `warn!(...)` - a macro hard-wired to the log level of `WARN`
|
||||
//! * `error!(...)` - a macro hard-wired to the log level of `ERROR`
|
||||
//!
|
||||
//! All of these macros use the same style of syntax as the `format!` syntax
|
||||
//! extension. Details about the syntax can be found in the documentation of
|
||||
//! `std::fmt` along with the Rust tutorial/manual.
|
||||
//!
|
||||
//! If you want to check at runtime if a given logging level is enabled (e.g. if the
|
||||
//! information you would want to log is expensive to produce), you can use the
|
||||
//! following macro:
|
||||
//!
|
||||
//! * `log_enabled!(level)` - returns true if logging of the given level is enabled
|
||||
//!
|
||||
//! ## Enabling logging
|
||||
//!
|
||||
//! Log levels are controlled on a per-module basis, and by default all logging is
|
||||
//! disabled except for `error!` (a log level of 1). Logging is controlled via the
|
||||
//! `RUST_LOG` environment variable. The value of this environment variable is a
|
||||
//! comma-separated list of logging directives. A logging directive is of the form:
|
||||
//!
|
||||
//! ```text
|
||||
//! path::to::module=log_level
|
||||
//! ```
|
||||
//!
|
||||
//! The path to the module is rooted in the name of the crate it was compiled for,
|
||||
//! so if your program is contained in a file `hello.rs`, for example, to turn on
|
||||
//! logging for this file you would use a value of `RUST_LOG=hello`.
|
||||
//! Furthermore, this path is a prefix-search, so all modules nested in the
|
||||
//! specified module will also have logging enabled.
|
||||
//!
|
||||
//! The actual `log_level` is optional to specify. If omitted, all logging will be
|
||||
//! enabled. If specified, the it must be either a numeric in the range of 1-255, or
|
||||
//! it must be one of the strings `debug`, `error`, `info`, or `warn`. If a numeric
|
||||
//! is specified, then all logging less than or equal to that numeral is enabled.
|
||||
//! For example, if logging level 3 is active, error, warn, and info logs will be
|
||||
//! printed, but debug will be omitted.
|
||||
//!
|
||||
//! As the log level for a module is optional, the module to enable logging for is
|
||||
//! also optional. If only a `log_level` is provided, then the global log level for
|
||||
//! all modules is set to this value.
|
||||
//!
|
||||
//! Some examples of valid values of `RUST_LOG` are:
|
||||
//!
|
||||
//! * `hello` turns on all logging for the 'hello' module
|
||||
//! * `info` turns on all info logging
|
||||
//! * `hello=debug` turns on debug logging for 'hello'
|
||||
//! * `hello=3` turns on info logging for 'hello'
|
||||
//! * `hello,std::option` turns on hello, and std's option logging
|
||||
//! * `error,hello=warn` turn on global error logging and also warn for hello
|
||||
//!
|
||||
//! ## Filtering results
|
||||
//!
|
||||
//! A RUST_LOG directive may include a regex filter. The syntax is to append `/`
|
||||
//! followed by a regex. Each message is checked against the regex, and is only
|
||||
//! logged if it matches. Note that the matching is done after formatting the log
|
||||
//! string but before adding any logging meta-data. There is a single filter for all
|
||||
//! modules.
|
||||
//!
|
||||
//! Some examples:
|
||||
//!
|
||||
//! * `hello/foo` turns on all logging for the 'hello' module where the log message
|
||||
//! includes 'foo'.
|
||||
//! * `info/f.o` turns on all info logging where the log message includes 'foo',
|
||||
//! 'f1o', 'fao', etc.
|
||||
//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the the log
|
||||
//! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
|
||||
//! * `error,hello=warn/[0-9] scopes` turn on global error logging and also warn for
|
||||
//! hello. In both cases the log message must include a single digit number
|
||||
//! followed by 'scopes'
|
||||
//!
|
||||
//! ## Performance and Side Effects
|
||||
//!
|
||||
//! Each of these macros will expand to code similar to:
|
||||
//!
|
||||
//! ```rust,ignore
|
||||
//! if log_level <= my_module_log_level() {
|
||||
//! ::log::log(log_level, format!(...));
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! What this means is that each of these macros are very cheap at runtime if
|
||||
//! they're turned off (just a load and an integer comparison). This also means that
|
||||
//! if logging is disabled, none of the components of the log will be executed.
|
||||
|
||||
#![crate_name = "log"]
|
||||
#![experimental]
|
||||
|
@ -24,11 +24,31 @@
|
||||
/// #![feature(phase)]
|
||||
/// #[phase(plugin, link)] extern crate log;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// log!(log::DEBUG, "this is a debug message");
|
||||
/// log!(log::WARN, "this is a warning {}", "message");
|
||||
/// log!(6, "this is a custom logging level: {level}", level=6u);
|
||||
/// # }
|
||||
/// fn main() {
|
||||
/// log!(log::WARN, "this is a warning {}", "message");
|
||||
/// log!(log::DEBUG, "this is a debug message");
|
||||
/// log!(6, "this is a custom logging level: {level}", level=6u);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Assumes the binary is `main`:
|
||||
///
|
||||
/// ```{.bash}
|
||||
/// $ RUST_LOG=warn ./main
|
||||
/// WARN:main: this is a warning message
|
||||
/// ```
|
||||
///
|
||||
/// ```{.bash}
|
||||
/// $ RUST_LOG=debug ./main
|
||||
/// DEBUG:main: this is a debug message
|
||||
/// WARN:main: this is a warning message
|
||||
/// ```
|
||||
///
|
||||
/// ```{.bash}
|
||||
/// $ RUST_LOG=6 ./main
|
||||
/// DEBUG:main: this is a debug message
|
||||
/// WARN:main: this is a warning message
|
||||
/// 6:main: this is a custom logging level: 6
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! log(
|
||||
@ -53,11 +73,19 @@ macro_rules! log(
|
||||
/// #![feature(phase)]
|
||||
/// #[phase(plugin, link)] extern crate log;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// # let error = 3u;
|
||||
/// error!("the build has failed with error code: {}", error);
|
||||
/// # }
|
||||
/// fn main() {
|
||||
/// let error = 3u;
|
||||
/// error!("the build has failed with error code: {}", error);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Assumes the binary is `main`:
|
||||
///
|
||||
/// ```{.bash}
|
||||
/// $ RUST_LOG=error ./main
|
||||
/// ERROR:main: the build has failed with error code: 3
|
||||
/// ```
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! error(
|
||||
($($arg:tt)*) => (log!(::log::ERROR, $($arg)*))
|
||||
@ -71,10 +99,17 @@ macro_rules! error(
|
||||
/// #![feature(phase)]
|
||||
/// #[phase(plugin, link)] extern crate log;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// # let code = 3u;
|
||||
/// warn!("you may like to know that a process exited with: {}", code);
|
||||
/// # }
|
||||
/// fn main() {
|
||||
/// let code = 3u;
|
||||
/// warn!("you may like to know that a process exited with: {}", code);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Assumes the binary is `main`:
|
||||
///
|
||||
/// ```{.bash}
|
||||
/// $ RUST_LOG=warn ./main
|
||||
/// WARN:main: you may like to know that a process exited with: 3
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! warn(
|
||||
@ -89,10 +124,17 @@ macro_rules! warn(
|
||||
/// #![feature(phase)]
|
||||
/// #[phase(plugin, link)] extern crate log;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// # let ret = 3i;
|
||||
/// info!("this function is about to return: {}", ret);
|
||||
/// # }
|
||||
/// fn main() {
|
||||
/// let ret = 3i;
|
||||
/// info!("this function is about to return: {}", ret);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Assumes the binary is `main`:
|
||||
///
|
||||
/// ```{.bash}
|
||||
/// $ RUST_LOG=info ./main
|
||||
/// INFO:main: this function is about to return: 3
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! info(
|
||||
@ -109,9 +151,16 @@ macro_rules! info(
|
||||
/// #![feature(phase)]
|
||||
/// #[phase(plugin, link)] extern crate log;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// debug!("x = {x}, y = {y}", x=10i, y=20i);
|
||||
/// # }
|
||||
/// fn main() {
|
||||
/// debug!("x = {x}, y = {y}", x=10i, y=20i);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Assumes the binary is `main`:
|
||||
///
|
||||
/// ```{.bash}
|
||||
/// $ RUST_LOG=debug ./main
|
||||
/// DEBUG:main: x = 10, y = 20
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! debug(
|
||||
@ -126,14 +175,26 @@ macro_rules! debug(
|
||||
/// #![feature(phase)]
|
||||
/// #[phase(plugin, link)] extern crate log;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// # struct Point { x: int, y: int }
|
||||
/// # fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } }
|
||||
/// if log_enabled!(log::DEBUG) {
|
||||
/// let x = some_expensive_computation();
|
||||
/// debug!("x.x = {}, x.y = {}", x.x, x.y);
|
||||
/// struct Point { x: int, y: int }
|
||||
/// fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } }
|
||||
///
|
||||
/// fn main() {
|
||||
/// if log_enabled!(log::DEBUG) {
|
||||
/// let x = some_expensive_computation();
|
||||
/// debug!("x.x = {}, x.y = {}", x.x, x.y);
|
||||
/// }
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// Assumes the binary is `main`:
|
||||
///
|
||||
/// ```{.bash}
|
||||
/// $ RUST_LOG=error ./main
|
||||
/// ```
|
||||
///
|
||||
/// ```{.bash}
|
||||
/// $ RUST_LOG=debug ./main
|
||||
/// DEBUG:main: x.x = 1, x.y = 2
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! log_enabled(
|
||||
|
@ -137,15 +137,14 @@ impl<T: Clone + Integer + PartialOrd>
|
||||
}
|
||||
|
||||
/// Rounds to the nearest integer. Rounds half-way cases away from zero.
|
||||
///
|
||||
/// Note: This function is currently broken and always rounds away from zero.
|
||||
#[inline]
|
||||
pub fn round(&self) -> Ratio<T> {
|
||||
// FIXME(#15826)
|
||||
if *self < Zero::zero() {
|
||||
Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
|
||||
// a/b - 1/2 = (2*a - b)/(2*b)
|
||||
Ratio::from_integer((self.numer + self.numer - self.denom) / (self.denom + self.denom))
|
||||
} else {
|
||||
Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
|
||||
// a/b + 1/2 = (2*a + b)/(2*b)
|
||||
Ratio::from_integer((self.numer + self.numer + self.denom) / (self.denom + self.denom))
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,7 +387,11 @@ mod test {
|
||||
pub static _2: Rational = Ratio { numer: 2, denom: 1};
|
||||
pub static _1_2: Rational = Ratio { numer: 1, denom: 2};
|
||||
pub static _3_2: Rational = Ratio { numer: 3, denom: 2};
|
||||
pub static _neg1_2: Rational = Ratio { numer: -1, denom: 2};
|
||||
pub static _neg1_2: Rational = Ratio { numer: -1, denom: 2};
|
||||
pub static _1_3: Rational = Ratio { numer: 1, denom: 3};
|
||||
pub static _neg1_3: Rational = Ratio { numer: -1, denom: 3};
|
||||
pub static _2_3: Rational = Ratio { numer: 2, denom: 3};
|
||||
pub static _neg2_3: Rational = Ratio { numer: -2, denom: 3};
|
||||
|
||||
pub fn to_big(n: Rational) -> BigRational {
|
||||
Ratio::new(
|
||||
@ -578,6 +581,26 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_round() {
|
||||
assert_eq!(_1_3.ceil(), _1);
|
||||
assert_eq!(_1_3.floor(), _0);
|
||||
assert_eq!(_1_3.round(), _0);
|
||||
assert_eq!(_1_3.trunc(), _0);
|
||||
|
||||
assert_eq!(_neg1_3.ceil(), _0);
|
||||
assert_eq!(_neg1_3.floor(), -_1);
|
||||
assert_eq!(_neg1_3.round(), _0);
|
||||
assert_eq!(_neg1_3.trunc(), _0);
|
||||
|
||||
assert_eq!(_2_3.ceil(), _1);
|
||||
assert_eq!(_2_3.floor(), _0);
|
||||
assert_eq!(_2_3.round(), _1);
|
||||
assert_eq!(_2_3.trunc(), _0);
|
||||
|
||||
assert_eq!(_neg2_3.ceil(), _0);
|
||||
assert_eq!(_neg2_3.floor(), -_1);
|
||||
assert_eq!(_neg2_3.round(), -_1);
|
||||
assert_eq!(_neg2_3.trunc(), _0);
|
||||
|
||||
assert_eq!(_1_2.ceil(), _1);
|
||||
assert_eq!(_1_2.floor(), _0);
|
||||
assert_eq!(_1_2.round(), _1);
|
||||
|
@ -417,7 +417,7 @@ pub fn check_crate(sess: &Session, krate: &ast::Crate) {
|
||||
sess.span_err(mi.span, "feature has been removed");
|
||||
}
|
||||
Some(&(_, Accepted)) => {
|
||||
sess.span_warn(mi.span, "feature has added to rust, \
|
||||
sess.span_warn(mi.span, "feature has been added to Rust, \
|
||||
directive not necessary");
|
||||
}
|
||||
None => {
|
||||
|
@ -599,7 +599,7 @@ impl<'a> Parser<'a> {
|
||||
let token_str = self.this_token_to_string();
|
||||
let span = self.span;
|
||||
self.span_err(span,
|
||||
format!("found `{}` in ident position",
|
||||
format!("expected identifier, found keyword `{}`",
|
||||
token_str).as_slice());
|
||||
}
|
||||
}
|
||||
|
@ -8,5 +8,5 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn false() { } //~ ERROR found `false` in ident position
|
||||
fn false() { } //~ ERROR expected identifier, found keyword `false`
|
||||
fn main() { }
|
||||
|
@ -8,5 +8,5 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn true() { } //~ ERROR found `true` in ident position
|
||||
fn true() { } //~ ERROR expected identifier, found keyword `true`
|
||||
fn main() { }
|
||||
|
@ -20,4 +20,4 @@
|
||||
#![feature = "foo"] //~ ERROR: malformed feature
|
||||
|
||||
#![feature(test_removed_feature)] //~ ERROR: feature has been removed
|
||||
#![feature(test_accepted_feature)] //~ WARNING: feature has added
|
||||
#![feature(test_accepted_feature)] //~ WARNING: feature has been added
|
||||
|
@ -9,5 +9,5 @@
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
let super: int; //~ ERROR found `super` in ident position
|
||||
let super: int; //~ ERROR expected identifier, found keyword `super`
|
||||
}
|
||||
|
@ -9,5 +9,5 @@
|
||||
// except according to those terms.
|
||||
|
||||
pub mod break {
|
||||
//~^ ERROR found `break` in ident position
|
||||
//~^ ERROR expected identifier, found keyword `break`
|
||||
}
|
||||
|
@ -10,6 +10,6 @@
|
||||
|
||||
struct s {
|
||||
let foo: (),
|
||||
//~^ ERROR found `let` in ident position
|
||||
//~^ ERROR expected identifier, found keyword `let`
|
||||
//~^^ ERROR expected `:`, found `foo`
|
||||
}
|
||||
|
@ -10,6 +10,6 @@
|
||||
|
||||
fn f() {
|
||||
let v = [mut 1, 2, 3, 4];
|
||||
//~^ ERROR found `mut` in ident position
|
||||
//~^ ERROR expected identifier, found keyword `mut`
|
||||
//~^^ ERROR expected `]`, found `1`
|
||||
}
|
||||
|
@ -9,5 +9,5 @@
|
||||
// except according to those terms.
|
||||
|
||||
type v = [mut int];
|
||||
//~^ ERROR found `mut` in ident position
|
||||
//~^ ERROR expected identifier, found keyword `mut`
|
||||
//~^^ ERROR expected `]`, found `int`
|
||||
|
@ -10,6 +10,6 @@
|
||||
|
||||
fn f() {
|
||||
let a_box = box mut 42;
|
||||
//~^ ERROR found `mut` in ident position
|
||||
//~^ ERROR expected identifier, found keyword `mut`
|
||||
//~^^ ERROR expected `;`, found `42`
|
||||
}
|
||||
|
@ -9,5 +9,5 @@
|
||||
// except according to those terms.
|
||||
|
||||
type mut_box = Box<mut int>;
|
||||
//~^ ERROR found `mut` in ident position
|
||||
//~^ ERROR expected identifier, found keyword `mut`
|
||||
//~^^ ERROR expected `,`, found `int`
|
||||
|
@ -13,5 +13,5 @@
|
||||
fn f<X>() {}
|
||||
|
||||
pub fn main() {
|
||||
f<type>(); //~ ERROR found `type` in ident position
|
||||
f<type>(); //~ ERROR expected identifier, found keyword `type`
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user