$ pacman -S git \
make \
diffutils \
+ tar \
mingw-w64-x86_64-python2 \
mingw-w64-x86_64-cmake \
mingw-w64-x86_64-gcc
4. You decide to use the resource.
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
-three. The ownership system in Rust does this through a concept called
-lifetimes, which describe the scope that a reference is valid for.
+three. In the small example above the Rust compiler is able to report the issue
+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
_descriptive_, not _prescriptive_. This means that how long a reference is valid
validity of references. The compiler can do so without annotations in simple
cases, but needs the programmers support in complex scenarios.
-```rust
-// implicit
-fn foo(x: &i32) {
-}
+[traits]: traits.html
-// explicit
-fn bar<'a>(x: &'a i32) {
-}
-```
+# Syntax
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
-["Lifetime Elision"][lifetime-elision] below) them in common cases.
-Before we get to that, though, let’s break the explicit example down:
+["Lifetime Elision"][lifetime-elision] below) them in common cases. Before we
+get to that, though, let’s look at a short example with explicit lifetimes:
[lifetime-elision]: #lifetime-elision
[generics]: generics.html
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
-% `type` Aliases
+% Type Aliases
The `type` keyword lets you declare an alias of another type:
//! ```
//!
//! 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
//! use std::hash::{Hash, Hasher, SipHasher};
/// The `H` type parameter is an abstract hash state that is used by 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:
///
/// ```text
/// ```
///
/// 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
///
/// 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
-/// from calling `.hash()` on each field.
+/// from calling [`.hash()`] on each field.
///
/// ## How can I implement `Hash`?
///
/// }
/// }
/// ```
+///
+/// [`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")]
pub trait Hash {
/// Feeds this value into the state given, updating the hasher as necessary.
#[stable(feature = "rust1", since = "1.0.0")]
fn finish(&self) -> u64;
- /// Writes some data into this `Hasher`
+ /// Writes some data into this `Hasher`.
#[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, bytes: &[u8]);
- /// Write a single `u8` into this hasher
+ /// Write a single `u8` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u8(&mut self, i: u8) {
self.write(&[i])
}
- /// Write a single `u16` into this hasher.
+ /// Writes a single `u16` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u16(&mut self, i: u16) {
self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
}
- /// Write a single `u32` into this hasher.
+ /// Writes a single `u32` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u32(&mut self, i: u32) {
self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
}
- /// Write a single `u64` into this hasher.
+ /// Writes a single `u64` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_u64(&mut self, i: u64) {
self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
}
- /// Write a single `usize` into this hasher.
+ /// Writes a single `usize` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_usize(&mut self, i: usize) {
self.write(bytes);
}
- /// Write a single `i8` into this hasher.
+ /// Writes a single `i8` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i8(&mut self, i: i8) {
self.write_u8(i as u8)
}
- /// Write a single `i16` into this hasher.
+ /// Writes a single `i16` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i16(&mut self, i: i16) {
self.write_u16(i as u16)
}
- /// Write a single `i32` into this hasher.
+ /// Writes a single `i32` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i32(&mut self, i: i32) {
self.write_u32(i as u32)
}
- /// Write a single `i64` into this hasher.
+ /// Writes a single `i64` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_i64(&mut self, i: i64) {
self.write_u64(i as u64)
}
- /// Write a single `isize` into this hasher.
+ /// Writes a single `isize` into this hasher.
#[inline]
#[stable(feature = "hasher_write", since = "1.3.0")]
fn write_isize(&mut self, i: isize) {
pub trait FullOps: Sized {
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
/// 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`,
/// 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`,
/// 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`
/// 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 {
/// 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`.
-const SMALL_POW5: [(u64, usize); 3] = [
- (125, 3),
- (15625, 6),
- (1_220_703_125, 13),
-];
+const SMALL_POW5: [(u64, usize); 3] = [(125, 3), (15625, 6), (1_220_703_125, 13)];
macro_rules! define_bignum {
($name:ident: type=$ty:ty, n=$n:expr) => (
pub fn normalize(&self) -> Fp {
let mut f = self.f;
let mut e = self.e;
- if f >> (64 - 32) == 0 { f <<= 32; e -= 32; }
- if f >> (64 - 16) == 0 { 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; }
+ if f >> (64 - 32) == 0 {
+ f <<= 32;
+ e -= 32;
+ }
+ if f >> (64 - 16) == 0 {
+ 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));
Fp { f: f, e: e }
}
assert!(edelta >= 0);
let edelta = edelta as usize;
assert_eq!(self.f << edelta >> edelta, self.f);
- Fp { f: self.f << edelta, e: e }
+ Fp {
+ f: self.f << edelta,
+ e: e,
+ }
}
}
/// Not a Number (NaN).
#[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 (∞).
#[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 (-∞).
#[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.
#[stable(feature = "rust1", since = "1.0.0")]
issue = "32110")]
impl Float for f32 {
#[inline]
- fn nan() -> f32 { NAN }
+ fn nan() -> f32 {
+ NAN
+ }
#[inline]
- fn infinity() -> f32 { INFINITY }
+ fn infinity() -> f32 {
+ INFINITY
+ }
#[inline]
- fn neg_infinity() -> f32 { NEG_INFINITY }
+ fn neg_infinity() -> f32 {
+ NEG_INFINITY
+ }
#[inline]
- fn zero() -> f32 { 0.0 }
+ fn zero() -> f32 {
+ 0.0
+ }
#[inline]
- fn neg_zero() -> f32 { -0.0 }
+ fn neg_zero() -> f32 {
+ -0.0
+ }
#[inline]
- fn one() -> f32 { 1.0 }
+ fn one() -> f32 {
+ 1.0
+ }
/// Returns `true` if the number is NaN.
#[inline]
- fn is_nan(self) -> bool { self != self }
+ fn is_nan(self) -> bool {
+ self != self
+ }
/// Returns `true` if the number is infinite.
#[inline]
let bits: u32 = unsafe { mem::transmute(self) };
match (bits & MAN_MASK, bits & EXP_MASK) {
- (0, 0) => Fp::Zero,
- (_, 0) => Fp::Subnormal,
+ (0, 0) => Fp::Zero,
+ (_, 0) => Fp::Subnormal,
(0, EXP_MASK) => Fp::Infinite,
(_, EXP_MASK) => Fp::Nan,
- _ => Fp::Normal,
+ _ => Fp::Normal,
}
}
/// Returns the reciprocal (multiplicative inverse) of the number.
#[inline]
- fn recip(self) -> f32 { 1.0 / self }
+ fn recip(self) -> f32 {
+ 1.0 / self
+ }
#[inline]
fn powi(self, n: i32) -> f32 {
/// Converts to degrees, assuming the number is in radians.
#[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.
#[inline]
/// Not a Number (NaN).
#[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 (∞).
#[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 (-∞).
#[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.
#[stable(feature = "rust1", since = "1.0.0")]
issue = "32110")]
impl Float for f64 {
#[inline]
- fn nan() -> f64 { NAN }
+ fn nan() -> f64 {
+ NAN
+ }
#[inline]
- fn infinity() -> f64 { INFINITY }
+ fn infinity() -> f64 {
+ INFINITY
+ }
#[inline]
- fn neg_infinity() -> f64 { NEG_INFINITY }
+ fn neg_infinity() -> f64 {
+ NEG_INFINITY
+ }
#[inline]
- fn zero() -> f64 { 0.0 }
+ fn zero() -> f64 {
+ 0.0
+ }
#[inline]
- fn neg_zero() -> f64 { -0.0 }
+ fn neg_zero() -> f64 {
+ -0.0
+ }
#[inline]
- fn one() -> f64 { 1.0 }
+ fn one() -> f64 {
+ 1.0
+ }
/// Returns `true` if the number is NaN.
#[inline]
- fn is_nan(self) -> bool { self != self }
+ fn is_nan(self) -> bool {
+ self != self
+ }
/// Returns `true` if the number is infinite.
#[inline]
let bits: u64 = unsafe { mem::transmute(self) };
match (bits & MAN_MASK, bits & EXP_MASK) {
- (0, 0) => Fp::Zero,
- (_, 0) => Fp::Subnormal,
+ (0, 0) => Fp::Zero,
+ (_, 0) => Fp::Subnormal,
(0, EXP_MASK) => Fp::Infinite,
(_, EXP_MASK) => Fp::Nan,
- _ => Fp::Normal,
+ _ => Fp::Normal,
}
}
/// Returns the reciprocal (multiplicative inverse) of the number.
#[inline]
- fn recip(self) -> f64 { 1.0 / self }
+ fn recip(self) -> f64 {
+ 1.0 / self
+ }
#[inline]
fn powi(self, n: i32) -> f64 {
/// Converts to degrees, assuming the number is in radians.
#[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.
#[inline]
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[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")]
impl<T: fmt::Debug> fmt::Debug for Wrapping<T> {
/// Positive or negative infinity.
#[stable(feature = "rust1", since = "1.0.0")]
- Infinite ,
+ Infinite,
/// Positive or negative zero.
#[stable(feature = "rust1", since = "1.0.0")]
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
-fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
- -> Result<T, ParseIntError> {
+fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> {
use self::IntErrorKind::*;
use self::ParseIntError as PIE;
let (is_positive, digits) = match src[0] {
b'+' => (true, &src[1..]),
b'-' if is_signed_ty => (false, &src[1..]),
- _ => (true, src)
+ _ => (true, src),
};
if digits.is_empty() {
/// [`i8::from_str_radix()`]: ../../std/primitive.i8.html#method.from_str_radix
#[derive(Debug, Clone, PartialEq, Eq)]
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct ParseIntError { kind: IntErrorKind }
+pub struct ParseIntError {
+ kind: IntErrorKind,
+}
#[derive(Debug, Clone, PartialEq, Eq)]
enum IntErrorKind {
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 i32: u32 = (1 << 5) - 1;
pub const i64: u32 = (1 << 6) - 1;
pub use self::platform::isize;
- pub const u8: u32 = i8;
+ pub const u8: u32 = i8;
pub const u16: u32 = i16;
pub const u32: u32 = i32;
pub const u64: u32 = i64;
/// Parse an individual log level that is either a number or a symbolic log level
fn parse_log_level(level: &str) -> Option<u32> {
level.parse::<u32>()
- .ok()
- .or_else(|| {
- let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
- pos.map(|p| p as u32 + 1)
- })
- .map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
+ .ok()
+ .or_else(|| {
+ let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
+ pos.map(|p| p as u32 + 1)
+ })
+ .map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
}
/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo")
continue;
}
let mut parts = s.split('=');
- let (log_level, name) = match (parts.next(),
- parts.next().map(|s| s.trim()),
- parts.next()) {
- (Some(part0), None, None) => {
- // if the single argument is a log-level string or number,
- // treat that as a global fallback
- match parse_log_level(part0) {
- Some(num) => (num, None),
- None => (::MAX_LOG_LEVEL, Some(part0)),
+ let (log_level, name) =
+ match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
+ (Some(part0), None, None) => {
+ // if the single argument is a log-level string or number,
+ // treat that as a global fallback
+ match parse_log_level(part0) {
+ Some(num) => (num, None),
+ 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) => {
+ match parse_log_level(part1) {
+ Some(num) => (num, Some(part0)),
+ _ => {
+ println!("warning: invalid logging spec '{}', ignoring it", part1);
+ continue;
+ }
}
}
- }
- _ => {
- println!("warning: invalid logging spec '{}', ignoring it", s);
- continue;
- }
- };
+ _ => {
+ println!("warning: invalid logging spec '{}', ignoring it", s);
+ continue;
+ }
+ };
dirs.push(LogDirective {
name: name.map(str::to_owned),
level: log_level,
err
}
ResolutionError::VariableNotBoundInPattern(variable_name, from, to) => {
- struct_span_err!(resolver.session,
+ let mut err = struct_span_err!(resolver.session,
span,
E0408,
"variable `{}` from pattern #{} is not bound in pattern #{}",
variable_name,
from,
- to)
+ to);
+ err.span_label(span, &format!("pattern doesn't bind `{}`", variable_name));
+ err
}
ResolutionError::VariableBoundWithDifferentMode(variable_name,
pattern_number,
Lifetime,
PreludeTy,
PreludeVal,
+ QuestionMark,
}
/// Trait that controls writing the output of syntax highlighting. Users should
token::Dot | token::DotDot | token::DotDotDot | token::Comma | token::Semi |
token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) |
token::CloseDelim(token::Brace) | token::CloseDelim(token::Paren) |
- token::CloseDelim(token::NoDelim) |
- token::Question => Class::None,
+ token::CloseDelim(token::NoDelim) => Class::None,
+
+ token::Question => Class::QuestionMark,
+
token::Dollar => {
if self.lexer.peek().tok.is_ident() {
self.in_macro_nonterminal = true;
Class::Lifetime => "lifetime",
Class::PreludeTy => "prelude-ty",
Class::PreludeVal => "prelude-val",
+ Class::QuestionMark => "question-mark"
}
}
}
pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
pre.rust .lifetime { color: #B76514; }
+pre.rust .question-mark {
+ color: #ff9011;
+ font-weight: bold;
+}
.rusttest { display: none; }
pre.rust { position: relative; }
/// The `BufReader` struct adds buffering to any reader.
///
-/// 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.
-/// A `BufReader` performs large, infrequent reads on the underlying `Read`
+/// 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.
+/// A `BufReader` performs large, infrequent reads on the underlying [`Read`]
/// 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
///
/// ```
/// Wraps a writer and buffers its output.
///
/// 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
/// and writes it to an underlying writer in large, infrequent batches.
///
///
/// # 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
/// use std::io::prelude::*;
/// 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
/// 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")]
pub struct BufWriter<W: Write> {
inner: Option<W>,
/// This function will return an error if the RwLock is poisoned. An RwLock
/// is poisoned whenever a writer panics while holding an exclusive lock.
/// 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]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
/// This function will return an error if the RwLock is poisoned. An RwLock
/// is poisoned whenever a writer panics while holding an exclusive lock.
/// 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]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
let x = Some(0);
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`
}
}
fn main() {
use bar::foo::{alpha, charlie};
match alpha {
- alpha | beta => {} //~ ERROR variable `beta` from pattern #2 is not bound in pattern #1
- charlie => {}
+ alpha | beta => {} //~ ERROR variable `beta` from pattern #2 is not bound in pattern #1
+ charlie => {} //~| NOTE pattern doesn't bind `beta`
}
}
fn main() {
let y = 1;
match y {
- 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
+ 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
+ //~| NOTE pattern doesn't bind `a`
+ //~| NOTE pattern doesn't bind `b`
}
}