Auto merge of #37170 - jonathandturner:rollup, r=jonathandturner

Rollup of 10 pull requests

- Successful merges: #36307, #36755, #36961, #37102, #37115, #37119, #37122, #37123, #37141, #37159
- Failed merges:
This commit is contained in:
bors 2016-10-14 16:15:42 -07:00 committed by GitHub
commit a8d189af90
19 changed files with 284 additions and 129 deletions

View File

@ -89,6 +89,7 @@ build.
$ pacman -S git \ $ pacman -S git \
make \ make \
diffutils \ diffutils \
tar \
mingw-w64-x86_64-python2 \ mingw-w64-x86_64-python2 \
mingw-w64-x86_64-cmake \ mingw-w64-x86_64-cmake \
mingw-w64-x86_64-gcc mingw-w64-x86_64-gcc

View File

@ -50,11 +50,78 @@ complicated. For example, imagine this set of operations:
4. You decide to use the resource. 4. You decide to use the resource.
Uh oh! Your reference is pointing to an invalid resource. This is called a Uh oh! Your reference is pointing to an invalid resource. This is called a
dangling pointer or use after free, when the resource is memory. dangling pointer or use after free, when the resource is memory. A small
example of such a situation would be:
```rust,compile_fail
let r; // Introduce reference: r
{
let i = 1; // Introduce scoped value: i
r = &i; // Store reference of i in r
} // i goes out of scope and is dropped.
println!("{}", r); // r still refers to i
```
To fix this, we have to make sure that step four never happens after step To fix this, we have to make sure that step four never happens after step
three. The ownership system in Rust does this through a concept called three. In the small example above the Rust compiler is able to report the issue
lifetimes, which describe the scope that a reference is valid for. as it can see the lifetimes of the various values in the function.
When we have a function that takes arguments by reference the situation becomes
more complex. Consider the following example:
```rust,compile_fail,E0106
fn skip_prefix(line: &str, prefix: &str) -> &str {
// ...
# line
}
let line = "lang:en=Hello World!";
let lang = "en";
let v;
{
let p = format!("lang:{}=", lang); // -+ p goes into scope
v = skip_prefix(line, p.as_str()); // |
} // -+ p goes out of scope
println!("{}", v);
```
Here we have a function `skip_prefix` which takes two `&str` references
as parameters and returns a single `&str` reference. We call it
by passing in references to `line` and `p`: Two variables with different
lifetimes. Now the safety of the `println!`-line depends on whether the
reference returned by `skip_prefix` function references the still living
`line` or the already dropped `p` string.
Because of the above ambiguity, Rust will refuse to compile the example
code. To get it to compile we need to tell the compiler more about the
lifetimes of the references. This can be done by making the lifetimes
explicit in the function declaration:
```rust
fn skip_prefix<'a, 'b>(line: &'a str, prefix: &'b str) -> &'a str {
// ...
# line
}
```
Let's examine the changes without going too deep into the syntax for now -
we'll get to that later. The first change was adding the `<'a, 'b>` after the
method name. This introduces two lifetime parameters: `'a` and `'b`. Next each
reference in the function signature was associated with one of the lifetime
parameters by adding the lifetime name after the `&`. This tells the compiler
how the lifetimes between different references are related.
As a result the compiler is now able to deduce that the return value of
`skip_prefix` has the same lifetime as the `line` parameter, which makes the `v`
reference safe to use even after the `p` goes out of scope in the original
example.
In addition to the compiler being able to validate the usage of `skip_prefix`
return value, it can also ensure that the implementation follows the contract
established by the function declaration. This is useful especially when you are
implementing traits that are introduced [later in the book][traits].
**Note** It's important to understand that lifetime annotations are **Note** It's important to understand that lifetime annotations are
_descriptive_, not _prescriptive_. This means that how long a reference is valid _descriptive_, not _prescriptive_. This means that how long a reference is valid
@ -63,20 +130,14 @@ give information about lifetimes to the compiler that uses them to check the
validity of references. The compiler can do so without annotations in simple validity of references. The compiler can do so without annotations in simple
cases, but needs the programmers support in complex scenarios. cases, but needs the programmers support in complex scenarios.
```rust [traits]: traits.html
// implicit
fn foo(x: &i32) {
}
// explicit # Syntax
fn bar<'a>(x: &'a i32) {
}
```
The `'a` reads the lifetime a. Technically, every reference has some lifetime The `'a` reads the lifetime a. Technically, every reference has some lifetime
associated with it, but the compiler lets you elide (i.e. omit, see associated with it, but the compiler lets you elide (i.e. omit, see
["Lifetime Elision"][lifetime-elision] below) them in common cases. ["Lifetime Elision"][lifetime-elision] below) them in common cases. Before we
Before we get to that, though, lets break the explicit example down: get to that, though, lets look at a short example with explicit lifetimes:
[lifetime-elision]: #lifetime-elision [lifetime-elision]: #lifetime-elision
@ -94,7 +155,8 @@ focus on the lifetimes aspect.
[generics]: generics.html [generics]: generics.html
We use `<>` to declare our lifetimes. This says that `bar` has one lifetime, We use `<>` to declare our lifetimes. This says that `bar` has one lifetime,
`'a`. If we had two reference parameters, it would look like this: `'a`. If we had two reference parameters with different lifetimes, it would
look like this:
```rust,ignore ```rust,ignore

View File

@ -1,4 +1,4 @@
% `type` Aliases % Type Aliases
The `type` keyword lets you declare an alias of another type: The `type` keyword lets you declare an alias of another type:

View File

@ -38,7 +38,9 @@
//! ``` //! ```
//! //!
//! If you need more control over how a value is hashed, you need to implement //! If you need more control over how a value is hashed, you need to implement
//! the `Hash` trait: //! the [`Hash`] trait:
//!
//! [`Hash`]: trait.Hash.html
//! //!
//! ```rust //! ```rust
//! use std::hash::{Hash, Hasher, SipHasher}; //! use std::hash::{Hash, Hasher, SipHasher};
@ -90,7 +92,7 @@ mod sip;
/// The `H` type parameter is an abstract hash state that is used by the `Hash` /// The `H` type parameter is an abstract hash state that is used by the `Hash`
/// to compute the hash. /// to compute the hash.
/// ///
/// If you are also implementing `Eq`, there is an additional property that /// If you are also implementing [`Eq`], there is an additional property that
/// is important: /// is important:
/// ///
/// ```text /// ```text
@ -98,13 +100,13 @@ mod sip;
/// ``` /// ```
/// ///
/// In other words, if two keys are equal, their hashes should also be equal. /// In other words, if two keys are equal, their hashes should also be equal.
/// `HashMap` and `HashSet` both rely on this behavior. /// [`HashMap`] and [`HashSet`] both rely on this behavior.
/// ///
/// ## Derivable /// ## Derivable
/// ///
/// This trait can be used with `#[derive]` if all fields implement `Hash`. /// This trait can be used with `#[derive]` if all fields implement `Hash`.
/// When `derive`d, the resulting hash will be the combination of the values /// When `derive`d, the resulting hash will be the combination of the values
/// from calling `.hash()` on each field. /// from calling [`.hash()`] on each field.
/// ///
/// ## How can I implement `Hash`? /// ## How can I implement `Hash`?
/// ///
@ -127,6 +129,11 @@ mod sip;
/// } /// }
/// } /// }
/// ``` /// ```
///
/// [`Eq`]: ../../std/cmp/trait.Eq.html
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
/// [`.hash()`]: #tymethod.hash
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub trait Hash { pub trait Hash {
/// Feeds this value into the state given, updating the hasher as necessary. /// Feeds this value into the state given, updating the hasher as necessary.
@ -151,35 +158,35 @@ pub trait Hasher {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn finish(&self) -> u64; fn finish(&self) -> u64;
/// Writes some data into this `Hasher` /// Writes some data into this `Hasher`.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, bytes: &[u8]); fn write(&mut self, bytes: &[u8]);
/// Write a single `u8` into this hasher /// Write a single `u8` into this hasher.
#[inline] #[inline]
#[stable(feature = "hasher_write", since = "1.3.0")] #[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u8(&mut self, i: u8) { fn write_u8(&mut self, i: u8) {
self.write(&[i]) self.write(&[i])
} }
/// Write a single `u16` into this hasher. /// Writes a single `u16` into this hasher.
#[inline] #[inline]
#[stable(feature = "hasher_write", since = "1.3.0")] #[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u16(&mut self, i: u16) { fn write_u16(&mut self, i: u16) {
self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) }) self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
} }
/// Write a single `u32` into this hasher. /// Writes a single `u32` into this hasher.
#[inline] #[inline]
#[stable(feature = "hasher_write", since = "1.3.0")] #[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u32(&mut self, i: u32) { fn write_u32(&mut self, i: u32) {
self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) }) self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
} }
/// Write a single `u64` into this hasher. /// Writes a single `u64` into this hasher.
#[inline] #[inline]
#[stable(feature = "hasher_write", since = "1.3.0")] #[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u64(&mut self, i: u64) { fn write_u64(&mut self, i: u64) {
self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) }) self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
} }
/// Write a single `usize` into this hasher. /// Writes a single `usize` into this hasher.
#[inline] #[inline]
#[stable(feature = "hasher_write", since = "1.3.0")] #[stable(feature = "hasher_write", since = "1.3.0")]
fn write_usize(&mut self, i: usize) { fn write_usize(&mut self, i: usize) {
@ -189,31 +196,31 @@ pub trait Hasher {
self.write(bytes); self.write(bytes);
} }
/// Write a single `i8` into this hasher. /// Writes a single `i8` into this hasher.
#[inline] #[inline]
#[stable(feature = "hasher_write", since = "1.3.0")] #[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i8(&mut self, i: i8) { fn write_i8(&mut self, i: i8) {
self.write_u8(i as u8) self.write_u8(i as u8)
} }
/// Write a single `i16` into this hasher. /// Writes a single `i16` into this hasher.
#[inline] #[inline]
#[stable(feature = "hasher_write", since = "1.3.0")] #[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i16(&mut self, i: i16) { fn write_i16(&mut self, i: i16) {
self.write_u16(i as u16) self.write_u16(i as u16)
} }
/// Write a single `i32` into this hasher. /// Writes a single `i32` into this hasher.
#[inline] #[inline]
#[stable(feature = "hasher_write", since = "1.3.0")] #[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i32(&mut self, i: i32) { fn write_i32(&mut self, i: i32) {
self.write_u32(i as u32) self.write_u32(i as u32)
} }
/// Write a single `i64` into this hasher. /// Writes a single `i64` into this hasher.
#[inline] #[inline]
#[stable(feature = "hasher_write", since = "1.3.0")] #[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i64(&mut self, i: i64) { fn write_i64(&mut self, i: i64) {
self.write_u64(i as u64) self.write_u64(i as u64)
} }
/// Write a single `isize` into this hasher. /// Writes a single `isize` into this hasher.
#[inline] #[inline]
#[stable(feature = "hasher_write", since = "1.3.0")] #[stable(feature = "hasher_write", since = "1.3.0")]
fn write_isize(&mut self, i: isize) { fn write_isize(&mut self, i: isize) {

View File

@ -34,19 +34,22 @@ use intrinsics;
pub trait FullOps: Sized { pub trait FullOps: Sized {
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`, /// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
/// where `W` is the number of bits in `Self`. /// where `W` is the number of bits in `Self`.
fn full_add(self, other: Self, carry: bool) -> (bool /*carry*/, Self); fn full_add(self, other: Self, carry: bool) -> (bool /* carry */, Self);
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`, /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`,
/// where `W` is the number of bits in `Self`. /// where `W` is the number of bits in `Self`.
fn full_mul(self, other: Self, carry: Self) -> (Self /*carry*/, Self); fn full_mul(self, other: Self, carry: Self) -> (Self /* carry */, Self);
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`, /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`,
/// where `W` is the number of bits in `Self`. /// where `W` is the number of bits in `Self`.
fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /*carry*/, Self); fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /* carry */, Self);
/// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem` /// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem`
/// and `0 <= rem < other`, where `W` is the number of bits in `Self`. /// and `0 <= rem < other`, where `W` is the number of bits in `Self`.
fn full_div_rem(self, other: Self, borrow: Self) -> (Self /*quotient*/, Self /*remainder*/); fn full_div_rem(self,
other: Self,
borrow: Self)
-> (Self /* quotient */, Self /* remainder */);
} }
macro_rules! impl_full_ops { macro_rules! impl_full_ops {
@ -100,11 +103,7 @@ impl_full_ops! {
/// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value /// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value
/// that's a power of five, plus the corresponding exponent. Used in `mul_pow5`. /// that's a power of five, plus the corresponding exponent. Used in `mul_pow5`.
const SMALL_POW5: [(u64, usize); 3] = [ const SMALL_POW5: [(u64, usize); 3] = [(125, 3), (15625, 6), (1_220_703_125, 13)];
(125, 3),
(15625, 6),
(1_220_703_125, 13),
];
macro_rules! define_bignum { macro_rules! define_bignum {
($name:ident: type=$ty:ty, n=$n:expr) => ( ($name:ident: type=$ty:ty, n=$n:expr) => (

View File

@ -49,12 +49,30 @@ impl Fp {
pub fn normalize(&self) -> Fp { pub fn normalize(&self) -> Fp {
let mut f = self.f; let mut f = self.f;
let mut e = self.e; let mut e = self.e;
if f >> (64 - 32) == 0 { f <<= 32; e -= 32; } if f >> (64 - 32) == 0 {
if f >> (64 - 16) == 0 { f <<= 16; e -= 16; } f <<= 32;
if f >> (64 - 8) == 0 { f <<= 8; e -= 8; } e -= 32;
if f >> (64 - 4) == 0 { f <<= 4; e -= 4; } }
if f >> (64 - 2) == 0 { f <<= 2; e -= 2; } if f >> (64 - 16) == 0 {
if f >> (64 - 1) == 0 { f <<= 1; e -= 1; } f <<= 16;
e -= 16;
}
if f >> (64 - 8) == 0 {
f <<= 8;
e -= 8;
}
if f >> (64 - 4) == 0 {
f <<= 4;
e -= 4;
}
if f >> (64 - 2) == 0 {
f <<= 2;
e -= 2;
}
if f >> (64 - 1) == 0 {
f <<= 1;
e -= 1;
}
debug_assert!(f >= (1 >> 63)); debug_assert!(f >= (1 >> 63));
Fp { f: f, e: e } Fp { f: f, e: e }
} }
@ -66,6 +84,9 @@ impl Fp {
assert!(edelta >= 0); assert!(edelta >= 0);
let edelta = edelta as usize; let edelta = edelta as usize;
assert_eq!(self.f << edelta >> edelta, self.f); assert_eq!(self.f << edelta >> edelta, self.f);
Fp { f: self.f << edelta, e: e } Fp {
f: self.f << edelta,
e: e,
}
} }
} }

View File

@ -61,13 +61,13 @@ pub const MAX_10_EXP: i32 = 38;
/// Not a Number (NaN). /// Not a Number (NaN).
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const NAN: f32 = 0.0_f32/0.0_f32; pub const NAN: f32 = 0.0_f32 / 0.0_f32;
/// Infinity (∞). /// Infinity (∞).
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const INFINITY: f32 = 1.0_f32/0.0_f32; pub const INFINITY: f32 = 1.0_f32 / 0.0_f32;
/// Negative infinity (-∞). /// Negative infinity (-∞).
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const NEG_INFINITY: f32 = -1.0_f32/0.0_f32; pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;
/// Basic mathematical constants. /// Basic mathematical constants.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -144,26 +144,40 @@ pub mod consts {
issue = "32110")] issue = "32110")]
impl Float for f32 { impl Float for f32 {
#[inline] #[inline]
fn nan() -> f32 { NAN } fn nan() -> f32 {
NAN
}
#[inline] #[inline]
fn infinity() -> f32 { INFINITY } fn infinity() -> f32 {
INFINITY
}
#[inline] #[inline]
fn neg_infinity() -> f32 { NEG_INFINITY } fn neg_infinity() -> f32 {
NEG_INFINITY
}
#[inline] #[inline]
fn zero() -> f32 { 0.0 } fn zero() -> f32 {
0.0
}
#[inline] #[inline]
fn neg_zero() -> f32 { -0.0 } fn neg_zero() -> f32 {
-0.0
}
#[inline] #[inline]
fn one() -> f32 { 1.0 } fn one() -> f32 {
1.0
}
/// Returns `true` if the number is NaN. /// Returns `true` if the number is NaN.
#[inline] #[inline]
fn is_nan(self) -> bool { self != self } fn is_nan(self) -> bool {
self != self
}
/// Returns `true` if the number is infinite. /// Returns `true` if the number is infinite.
#[inline] #[inline]
@ -192,11 +206,11 @@ impl Float for f32 {
let bits: u32 = unsafe { mem::transmute(self) }; let bits: u32 = unsafe { mem::transmute(self) };
match (bits & MAN_MASK, bits & EXP_MASK) { match (bits & MAN_MASK, bits & EXP_MASK) {
(0, 0) => Fp::Zero, (0, 0) => Fp::Zero,
(_, 0) => Fp::Subnormal, (_, 0) => Fp::Subnormal,
(0, EXP_MASK) => Fp::Infinite, (0, EXP_MASK) => Fp::Infinite,
(_, EXP_MASK) => Fp::Nan, (_, EXP_MASK) => Fp::Nan,
_ => Fp::Normal, _ => Fp::Normal,
} }
} }
@ -252,7 +266,9 @@ impl Float for f32 {
/// Returns the reciprocal (multiplicative inverse) of the number. /// Returns the reciprocal (multiplicative inverse) of the number.
#[inline] #[inline]
fn recip(self) -> f32 { 1.0 / self } fn recip(self) -> f32 {
1.0 / self
}
#[inline] #[inline]
fn powi(self, n: i32) -> f32 { fn powi(self, n: i32) -> f32 {
@ -261,7 +277,9 @@ impl Float for f32 {
/// Converts to degrees, assuming the number is in radians. /// Converts to degrees, assuming the number is in radians.
#[inline] #[inline]
fn to_degrees(self) -> f32 { self * (180.0f32 / consts::PI) } fn to_degrees(self) -> f32 {
self * (180.0f32 / consts::PI)
}
/// Converts to radians, assuming the number is in degrees. /// Converts to radians, assuming the number is in degrees.
#[inline] #[inline]

View File

@ -61,13 +61,13 @@ pub const MAX_10_EXP: i32 = 308;
/// Not a Number (NaN). /// Not a Number (NaN).
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const NAN: f64 = 0.0_f64/0.0_f64; pub const NAN: f64 = 0.0_f64 / 0.0_f64;
/// Infinity (∞). /// Infinity (∞).
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const INFINITY: f64 = 1.0_f64/0.0_f64; pub const INFINITY: f64 = 1.0_f64 / 0.0_f64;
/// Negative infinity (-∞). /// Negative infinity (-∞).
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub const NEG_INFINITY: f64 = -1.0_f64/0.0_f64; pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
/// Basic mathematical constants. /// Basic mathematical constants.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -144,26 +144,40 @@ pub mod consts {
issue = "32110")] issue = "32110")]
impl Float for f64 { impl Float for f64 {
#[inline] #[inline]
fn nan() -> f64 { NAN } fn nan() -> f64 {
NAN
}
#[inline] #[inline]
fn infinity() -> f64 { INFINITY } fn infinity() -> f64 {
INFINITY
}
#[inline] #[inline]
fn neg_infinity() -> f64 { NEG_INFINITY } fn neg_infinity() -> f64 {
NEG_INFINITY
}
#[inline] #[inline]
fn zero() -> f64 { 0.0 } fn zero() -> f64 {
0.0
}
#[inline] #[inline]
fn neg_zero() -> f64 { -0.0 } fn neg_zero() -> f64 {
-0.0
}
#[inline] #[inline]
fn one() -> f64 { 1.0 } fn one() -> f64 {
1.0
}
/// Returns `true` if the number is NaN. /// Returns `true` if the number is NaN.
#[inline] #[inline]
fn is_nan(self) -> bool { self != self } fn is_nan(self) -> bool {
self != self
}
/// Returns `true` if the number is infinite. /// Returns `true` if the number is infinite.
#[inline] #[inline]
@ -192,11 +206,11 @@ impl Float for f64 {
let bits: u64 = unsafe { mem::transmute(self) }; let bits: u64 = unsafe { mem::transmute(self) };
match (bits & MAN_MASK, bits & EXP_MASK) { match (bits & MAN_MASK, bits & EXP_MASK) {
(0, 0) => Fp::Zero, (0, 0) => Fp::Zero,
(_, 0) => Fp::Subnormal, (_, 0) => Fp::Subnormal,
(0, EXP_MASK) => Fp::Infinite, (0, EXP_MASK) => Fp::Infinite,
(_, EXP_MASK) => Fp::Nan, (_, EXP_MASK) => Fp::Nan,
_ => Fp::Normal, _ => Fp::Normal,
} }
} }
@ -252,7 +266,9 @@ impl Float for f64 {
/// Returns the reciprocal (multiplicative inverse) of the number. /// Returns the reciprocal (multiplicative inverse) of the number.
#[inline] #[inline]
fn recip(self) -> f64 { 1.0 / self } fn recip(self) -> f64 {
1.0 / self
}
#[inline] #[inline]
fn powi(self, n: i32) -> f64 { fn powi(self, n: i32) -> f64 {
@ -261,7 +277,9 @@ impl Float for f64 {
/// Converts to degrees, assuming the number is in radians. /// Converts to degrees, assuming the number is in radians.
#[inline] #[inline]
fn to_degrees(self) -> f64 { self * (180.0f64 / consts::PI) } fn to_degrees(self) -> f64 {
self * (180.0f64 / consts::PI)
}
/// Converts to radians, assuming the number is in degrees. /// Converts to radians, assuming the number is in degrees.
#[inline] #[inline]

View File

@ -43,7 +43,8 @@ use str::FromStr;
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)]
pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T); pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")]
pub T);
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug> fmt::Debug for Wrapping<T> { impl<T: fmt::Debug> fmt::Debug for Wrapping<T> {
@ -2402,7 +2403,7 @@ pub enum FpCategory {
/// Positive or negative infinity. /// Positive or negative infinity.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
Infinite , Infinite,
/// Positive or negative zero. /// Positive or negative zero.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -2662,8 +2663,7 @@ macro_rules! doit {
} }
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize } doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> {
-> Result<T, ParseIntError> {
use self::IntErrorKind::*; use self::IntErrorKind::*;
use self::ParseIntError as PIE; use self::ParseIntError as PIE;
@ -2686,7 +2686,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
let (is_positive, digits) = match src[0] { let (is_positive, digits) = match src[0] {
b'+' => (true, &src[1..]), b'+' => (true, &src[1..]),
b'-' if is_signed_ty => (false, &src[1..]), b'-' if is_signed_ty => (false, &src[1..]),
_ => (true, src) _ => (true, src),
}; };
if digits.is_empty() { if digits.is_empty() {
@ -2738,7 +2738,9 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
/// [`i8::from_str_radix()`]: ../../std/primitive.i8.html#method.from_str_radix /// [`i8::from_str_radix()`]: ../../std/primitive.i8.html#method.from_str_radix
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct ParseIntError { kind: IntErrorKind } pub struct ParseIntError {
kind: IntErrorKind,
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
enum IntErrorKind { enum IntErrorKind {

View File

@ -310,13 +310,13 @@ mod shift_max {
pub const isize: u32 = super::i64; pub const isize: u32 = super::i64;
} }
pub const i8: u32 = (1 << 3) - 1; pub const i8: u32 = (1 << 3) - 1;
pub const i16: u32 = (1 << 4) - 1; pub const i16: u32 = (1 << 4) - 1;
pub const i32: u32 = (1 << 5) - 1; pub const i32: u32 = (1 << 5) - 1;
pub const i64: u32 = (1 << 6) - 1; pub const i64: u32 = (1 << 6) - 1;
pub use self::platform::isize; pub use self::platform::isize;
pub const u8: u32 = i8; pub const u8: u32 = i8;
pub const u16: u32 = i16; pub const u16: u32 = i16;
pub const u32: u32 = i32; pub const u32: u32 = i32;
pub const u64: u32 = i64; pub const u64: u32 = i64;

View File

@ -22,12 +22,12 @@ pub const LOG_LEVEL_NAMES: [&'static str; 5] = ["ERROR", "WARN", "INFO", "DEBUG"
/// Parse an individual log level that is either a number or a symbolic log level /// Parse an individual log level that is either a number or a symbolic log level
fn parse_log_level(level: &str) -> Option<u32> { fn parse_log_level(level: &str) -> Option<u32> {
level.parse::<u32>() level.parse::<u32>()
.ok() .ok()
.or_else(|| { .or_else(|| {
let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level)); let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
pos.map(|p| p as u32 + 1) pos.map(|p| p as u32 + 1)
}) })
.map(|p| cmp::min(p, ::MAX_LOG_LEVEL)) .map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
} }
/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo") /// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo")
@ -52,32 +52,31 @@ pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<String>) {
continue; continue;
} }
let mut parts = s.split('='); let mut parts = s.split('=');
let (log_level, name) = match (parts.next(), let (log_level, name) =
parts.next().map(|s| s.trim()), match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
parts.next()) { (Some(part0), None, None) => {
(Some(part0), None, None) => { // if the single argument is a log-level string or number,
// if the single argument is a log-level string or number, // treat that as a global fallback
// treat that as a global fallback match parse_log_level(part0) {
match parse_log_level(part0) { Some(num) => (num, None),
Some(num) => (num, None), None => (::MAX_LOG_LEVEL, Some(part0)),
None => (::MAX_LOG_LEVEL, Some(part0)),
}
}
(Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
(Some(part0), Some(part1), None) => {
match parse_log_level(part1) {
Some(num) => (num, Some(part0)),
_ => {
println!("warning: invalid logging spec '{}', ignoring it", part1);
continue;
} }
} }
} (Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
_ => { (Some(part0), Some(part1), None) => {
println!("warning: invalid logging spec '{}', ignoring it", s); match parse_log_level(part1) {
continue; Some(num) => (num, Some(part0)),
} _ => {
}; println!("warning: invalid logging spec '{}', ignoring it", part1);
continue;
}
}
}
_ => {
println!("warning: invalid logging spec '{}', ignoring it", s);
continue;
}
};
dirs.push(LogDirective { dirs.push(LogDirective {
name: name.map(str::to_owned), name: name.map(str::to_owned),
level: log_level, level: log_level,

View File

@ -276,13 +276,15 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
err err
} }
ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => { ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => {
struct_span_err!(resolver.session, let mut err = struct_span_err!(resolver.session,
span, span,
E0408, E0408,
"variable `{}` from pattern #{} is not bound in pattern #{}", "variable `{}` from pattern #{} is not bound in pattern #{}",
variable_name, variable_name,
from, from,
to) to);
err.span_label(span, &format!("pattern doesn't bind `{}`", variable_name));
err
} }
ResolutionError::VariableBoundWithDifferentMode(variable_name, ResolutionError::VariableBoundWithDifferentMode(variable_name,
pattern_number, pattern_number,

View File

@ -104,6 +104,7 @@ pub enum Class {
Lifetime, Lifetime,
PreludeTy, PreludeTy,
PreludeVal, PreludeVal,
QuestionMark,
} }
/// Trait that controls writing the output of syntax highlighting. Users should /// Trait that controls writing the output of syntax highlighting. Users should
@ -237,8 +238,10 @@ impl<'a> Classifier<'a> {
token::Dot | token::DotDot | token::DotDotDot | token::Comma | token::Semi | token::Dot | token::DotDot | token::DotDotDot | token::Comma | token::Semi |
token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) | token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) |
token::CloseDelim(token::Brace) | token::CloseDelim(token::Paren) | token::CloseDelim(token::Brace) | token::CloseDelim(token::Paren) |
token::CloseDelim(token::NoDelim) | token::CloseDelim(token::NoDelim) => Class::None,
token::Question => Class::None,
token::Question => Class::QuestionMark,
token::Dollar => { token::Dollar => {
if self.lexer.peek().tok.is_ident() { if self.lexer.peek().tok.is_ident() {
self.in_macro_nonterminal = true; self.in_macro_nonterminal = true;
@ -348,6 +351,7 @@ impl Class {
Class::Lifetime => "lifetime", Class::Lifetime => "lifetime",
Class::PreludeTy => "prelude-ty", Class::PreludeTy => "prelude-ty",
Class::PreludeVal => "prelude-val", Class::PreludeVal => "prelude-val",
Class::QuestionMark => "question-mark"
} }
} }
} }

View File

@ -570,6 +570,10 @@ pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; } pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
pre.rust .lifetime { color: #B76514; } pre.rust .lifetime { color: #B76514; }
pre.rust .question-mark {
color: #ff9011;
font-weight: bold;
}
.rusttest { display: none; } .rusttest { display: none; }
pre.rust { position: relative; } pre.rust { position: relative; }

View File

@ -20,11 +20,15 @@ use memchr;
/// The `BufReader` struct adds buffering to any reader. /// The `BufReader` struct adds buffering to any reader.
/// ///
/// It can be excessively inefficient to work directly with a `Read` instance. /// It can be excessively inefficient to work directly with a [`Read`] instance.
/// For example, every call to `read` on `TcpStream` results in a system call. /// For example, every call to [`read`] on [`TcpStream`] results in a system call.
/// A `BufReader` performs large, infrequent reads on the underlying `Read` /// A `BufReader` performs large, infrequent reads on the underlying [`Read`]
/// and maintains an in-memory buffer of the results. /// and maintains an in-memory buffer of the results.
/// ///
/// [`Read`]: ../../std/io/trait.Read.html
/// [`read`]: ../../std/net/struct.TcpStream.html#method.read
/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
@ -254,7 +258,7 @@ impl<R: Seek> Seek for BufReader<R> {
/// Wraps a writer and buffers its output. /// Wraps a writer and buffers its output.
/// ///
/// It can be excessively inefficient to work directly with something that /// It can be excessively inefficient to work directly with something that
/// implements `Write`. For example, every call to `write` on `TcpStream` /// implements [`Write`]. For example, every call to [`write`] on [`TcpStream`]
/// results in a system call. A `BufWriter` keeps an in-memory buffer of data /// results in a system call. A `BufWriter` keeps an in-memory buffer of data
/// and writes it to an underlying writer in large, infrequent batches. /// and writes it to an underlying writer in large, infrequent batches.
/// ///
@ -262,7 +266,7 @@ impl<R: Seek> Seek for BufReader<R> {
/// ///
/// # Examples /// # Examples
/// ///
/// Let's write the numbers one through ten to a `TcpStream`: /// Let's write the numbers one through ten to a [`TcpStream`]:
/// ///
/// ```no_run /// ```no_run
/// use std::io::prelude::*; /// use std::io::prelude::*;
@ -294,6 +298,10 @@ impl<R: Seek> Seek for BufReader<R> {
/// By wrapping the stream with a `BufWriter`, these ten writes are all grouped /// By wrapping the stream with a `BufWriter`, these ten writes are all grouped
/// together by the buffer, and will all be written out in one system call when /// together by the buffer, and will all be written out in one system call when
/// the `stream` is dropped. /// the `stream` is dropped.
///
/// [`Write`]: ../../std/io/trait.Write.html
/// [`write`]: ../../std/net/struct.TcpStream.html#method.write
/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct BufWriter<W: Write> { pub struct BufWriter<W: Write> {
inner: Option<W>, inner: Option<W>,

View File

@ -136,6 +136,10 @@ impl<T: ?Sized> RwLock<T> {
/// This function will return an error if the RwLock is poisoned. An RwLock /// This function will return an error if the RwLock is poisoned. An RwLock
/// is poisoned whenever a writer panics while holding an exclusive lock. /// is poisoned whenever a writer panics while holding an exclusive lock.
/// The failure will occur immediately after the lock has been acquired. /// The failure will occur immediately after the lock has been acquired.
///
/// # Panics
///
/// This function might panic when called if the lock is already held by the current thread.
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn read(&self) -> LockResult<RwLockReadGuard<T>> { pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
@ -188,6 +192,10 @@ impl<T: ?Sized> RwLock<T> {
/// This function will return an error if the RwLock is poisoned. An RwLock /// This function will return an error if the RwLock is poisoned. An RwLock
/// is poisoned whenever a writer panics while holding an exclusive lock. /// is poisoned whenever a writer panics while holding an exclusive lock.
/// An error will be returned when the lock is acquired. /// An error will be returned when the lock is acquired.
///
/// # Panics
///
/// This function might panic when called if the lock is already held by the current thread.
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> { pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {

View File

@ -12,7 +12,7 @@ fn main() {
let x = Some(0); let x = Some(0);
match x { match x {
Some(y) | None => {} //~ ERROR E0408 Some(y) | None => {} //~ ERROR variable `y` from pattern #1 is not bound in pattern #2
_ => () _ => () //~| NOTE pattern doesn't bind `y`
} }
} }

View File

@ -19,7 +19,7 @@ mod bar {
fn main() { fn main() {
use bar::foo::{alpha, charlie}; use bar::foo::{alpha, charlie};
match alpha { match alpha {
alpha | beta => {} //~ ERROR variable `beta` from pattern #2 is not bound in pattern #1 alpha | beta => {} //~ ERROR variable `beta` from pattern #2 is not bound in pattern #1
charlie => {} charlie => {} //~| NOTE pattern doesn't bind `beta`
} }
} }

View File

@ -11,7 +11,9 @@
fn main() { fn main() {
let y = 1; let y = 1;
match y { match y {
a | b => {} //~ ERROR variable `a` from pattern #1 is not bound in pattern #2 a | b => {} //~ ERROR variable `a` from pattern #1 is not bound in pattern #2
//~^ ERROR variable `b` from pattern #2 is not bound in pattern #1 //~^ ERROR variable `b` from pattern #2 is not bound in pattern #1
//~| NOTE pattern doesn't bind `a`
//~| NOTE pattern doesn't bind `b`
} }
} }