From 26591986032abbad0490a45da6ba7252178c1c82 Mon Sep 17 00:00:00 2001 From: Matthew Piziak Date: Wed, 17 Aug 2016 19:07:39 -0400 Subject: [PATCH 01/21] show how iterating over `RangeTo` and `RangeToInclusive` fails Feedback on PR #35701 seems to be positive, so this does the same thing for `RangeTo` and `RangeToInclusive`. --- src/libcore/ops.rs | 55 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 4ac1b8394f450..92d41c03e9aeb 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -1610,17 +1610,33 @@ impl> RangeFrom { /// /// It cannot serve as an iterator because it doesn't have a starting point. /// +/// # Examples +/// +/// The `..{integer}` syntax is a `RangeTo`: +/// +/// ``` +/// assert_eq!((..5), std::ops::RangeTo{ end: 5 }); /// ``` -/// fn main() { -/// assert_eq!((..5), std::ops::RangeTo{ end: 5 }); /// -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ .. ], [0,1,2,3]); -/// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo -/// assert_eq!(arr[1.. ], [ 1,2,3]); -/// assert_eq!(arr[1..3], [ 1,2 ]); +/// It does not have an `IntoIterator` implementation, so you can't use it in a +/// `for` loop directly. This won't compile: +/// +/// ```ignore +/// for i in ..5 { +/// // ... /// } /// ``` +/// +/// When used as a slicing index, `RangeTo` produces a slice of all array +/// elements before the index indicated by `end`. +/// +/// ``` +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ .. ], [0,1,2,3]); +/// assert_eq!(arr[ ..3], [0,1,2 ]); // RangeTo +/// assert_eq!(arr[1.. ], [ 1,2,3]); +/// assert_eq!(arr[1..3], [ 1,2 ]); +/// ``` #[derive(Copy, Clone, PartialEq, Eq, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeTo { @@ -1748,16 +1764,31 @@ impl> RangeInclusive { /// /// # Examples /// +/// The `...{integer}` syntax is a `RangeToInclusive`: +/// /// ``` /// #![feature(inclusive_range,inclusive_range_syntax)] -/// fn main() { -/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 }); +/// assert_eq!((...5), std::ops::RangeToInclusive{ end: 5 }); +/// ``` /// -/// let arr = [0, 1, 2, 3]; -/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive -/// assert_eq!(arr[1...2], [ 1,2 ]); +/// It does not have an `IntoIterator` implementation, so you can't use it in a +/// `for` loop directly. This won't compile: +/// +/// ```ignore +/// for i in ...5 { +/// // ... /// } /// ``` +/// +/// When used as a slicing index, `RangeToInclusive` produces a slice of all +/// array elements up to and including the index indicated by `end`. +/// +/// ``` +/// #![feature(inclusive_range_syntax)] +/// let arr = [0, 1, 2, 3]; +/// assert_eq!(arr[ ...2], [0,1,2 ]); // RangeToInclusive +/// assert_eq!(arr[1...2], [ 1,2 ]); +/// ``` #[derive(Copy, Clone, PartialEq, Eq, Hash)] #[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")] pub struct RangeToInclusive { From e4dd785b591b771882b1c61a541048d57dc86442 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 20 Aug 2016 15:20:22 -0400 Subject: [PATCH 02/21] Correct formatting docs: fmt::Result != io::Result<()> --- src/libcollections/fmt.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index b7cbfb60ec4e9..428ed319ce941 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -165,9 +165,9 @@ //! provides some helper methods. //! //! Additionally, the return value of this function is `fmt::Result` which is a -//! typedef to `Result<(), std::io::Error>` (also known as `std::io::Result<()>`). -//! Formatting implementations should ensure that they return errors from `write!` -//! correctly (propagating errors upward). +//! typedef to `Result<(), std::fmt::Error>`. Formatting implementations should +//! ensure that they return errors from `write!` correctly (propagating errors +//! upward). //! //! An example of implementing the formatting traits would look //! like: From f2655e23ff1b377f09cfbb19253a7ea50cd2c4f3 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sat, 20 Aug 2016 15:27:37 -0400 Subject: [PATCH 03/21] Note that formatters should not return spurious errors. Doing otherwise would break traits like `ToString`. --- src/libcollections/fmt.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index 428ed319ce941..a1b4461949c6e 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -166,8 +166,14 @@ //! //! Additionally, the return value of this function is `fmt::Result` which is a //! typedef to `Result<(), std::fmt::Error>`. Formatting implementations should -//! ensure that they return errors from `write!` correctly (propagating errors -//! upward). +//! ensure that they propagate errors from the `Formatter` (e.g., when calling +//! `write!`) however, they should never return errors spuriously. That is, a +//! formatting implementation must and may only return an error if the passed-in +//! `Formatter` returns an error. This is because, contrary to what the function +//! signature might suggest, string formatting is an infallible operation. +//! This function only returns a result because writing to the underlying stream +//! might fail and it must provide a way to propagate the fact that an error has +//! occurred back up the stack. //! //! An example of implementing the formatting traits would look //! like: From c7d5f7e5e638775e45c4fdc64f3b91bdbfca9c28 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Tue, 23 Aug 2016 10:47:28 -0400 Subject: [PATCH 04/21] Rust has type aliases, not typedefs. They're the same thing but it's better to keep the terminology consistent. --- src/libcollections/fmt.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index a1b4461949c6e..beb3e6b3d4e31 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -165,15 +165,15 @@ //! provides some helper methods. //! //! Additionally, the return value of this function is `fmt::Result` which is a -//! typedef to `Result<(), std::fmt::Error>`. Formatting implementations should -//! ensure that they propagate errors from the `Formatter` (e.g., when calling -//! `write!`) however, they should never return errors spuriously. That is, a -//! formatting implementation must and may only return an error if the passed-in -//! `Formatter` returns an error. This is because, contrary to what the function -//! signature might suggest, string formatting is an infallible operation. -//! This function only returns a result because writing to the underlying stream -//! might fail and it must provide a way to propagate the fact that an error has -//! occurred back up the stack. +//! type alias of `Result<(), std::fmt::Error>`. Formatting implementations +//! should ensure that they propagate errors from the `Formatter` (e.g., when +//! calling `write!`) however, they should never return errors spuriously. That +//! is, a formatting implementation must and may only return an error if the +//! passed-in `Formatter` returns an error. This is because, contrary to what +//! the function signature might suggest, string formatting is an infallible +//! operation. This function only returns a result because writing to the +//! underlying stream might fail and it must provide a way to propagate the fact +//! that an error has occurred back up the stack. //! //! An example of implementing the formatting traits would look //! like: From 67b9cd3fe136247e928d11daa12749d0488464c9 Mon Sep 17 00:00:00 2001 From: Matthew Piziak Date: Thu, 18 Aug 2016 17:46:34 -0400 Subject: [PATCH 05/21] improve documentation for `Fn*` traits I can think of a few things we may want to accomplish with the documentation of the `Fn`, `FnMut`, and `FnOnce` traits: - the relationship between these traits and the closures that implement them - examples of non-closure implementations - the relationship between these traits and Rust's ownership semantics add module-level documentation for `Fn*` traits Describe how `Fn*` traits, closure types, and ownership semantics are linked, and provide examples of higher-level functions that take `Fn*`s. more examples for `Fn*` traits create correct (though not yet elegant) examples for `FnMut` and `FnOnce` add trait links to module-level documentation third time's a charm! argument -> capture for trait documentation This wording will need to be supported with better examples for capturing eventually. correct `FnOnce` example I also fixed some of the trait wording here to make the concept of capturing clearer; though that still needs more work. replace `x + x` with `x * 2` for `fn double` --- src/libcore/ops.rs | 165 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 5a1993e741c60..a8a557ce68111 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -68,6 +68,73 @@ //! ``` //! //! See the documentation for each trait for an example implementation. +//! +//! The [`Fn`], [`FnMut`], and [`FnOnce`] traits are implemented by types that can be +//! invoked like functions. Note that `Fn` takes `&self`, `FnMut` takes `&mut +//! self` and `FnOnce` takes `self`. These correspond to the three kinds of +//! methods that can be invoked on an instance: call-by-reference, +//! call-by-mutable-reference, and call-by-value. The most common use of these +//! traits is to act as bounds to higher-level functions that take functions or +//! closures as arguments. +//! +//! [`Fn`]: trait.Fn.html +//! [`FnMut`]: trait.FnMut.html +//! [`FnOnce`]: trait.FnOnce.html +//! +//! Taking a `Fn` as a parameter: +//! +//! ```rust +//! fn call_with_one(func: F) -> usize +//! where F: Fn(usize) -> usize +//! { +//! func(1) +//! } +//! +//! let double = |x| x * 2; +//! assert_eq!(call_with_one(double), 2); +//! ``` +//! +//! Taking a `FnMut` as a parameter: +//! +//! ```rust +//! fn do_twice(mut func: F) +//! where F: FnMut() +//! { +//! func(); +//! func(); +//! } +//! +//! let mut x: usize = 1; +//! { +//! let add_two_to_x = || x += 2; +//! do_twice(add_two_to_x); +//! } +//! +//! assert_eq!(x, 5); +//! ``` +//! +//! Taking a `FnOnce` as a parameter: +//! +//! ```rust +//! fn consume_with_relish(func: F) +//! where F: FnOnce() -> String +//! { +//! // `func` consumes its captured variables, so it cannot be run more +//! // than once +//! println!("Consumed: {}", func()); +//! +//! println!("Delicious!"); +//! +//! // Attempting to invoke `func()` again will throw a `use of moved +//! // value` error for `func` +//! } +//! +//! let x = String::from("x"); +//! let consume_and_return_x = move || x; +//! consume_with_relish(consume_and_return_x); +//! +//! // `consume_and_return_x` can no longer be invoked at this point +//! ``` #![stable(feature = "rust1", since = "1.0.0")] @@ -2027,6 +2094,35 @@ impl<'a, T: ?Sized> DerefMut for &'a mut T { } /// A version of the call operator that takes an immutable receiver. +/// +/// # Examples +/// +/// Closures automatically implement this trait, which allows them to be +/// invoked. Note, however, that `Fn` takes an immutable reference to any +/// captured variables. To take a mutable capture, implement [`FnMut`], and to +/// consume the capture, implement [`FnOnce`]. +/// +/// [`FnMut`]: trait.FnMut.html +/// [`FnOnce`]: trait.FnOnce.html +/// +/// ``` +/// let square = |x| x * x; +/// assert_eq!(square(5), 25); +/// ``` +/// +/// Closures can also be passed to higher-level functions through a `Fn` +/// parameter (or a `FnMut` or `FnOnce` parameter, which are supertraits of +/// `Fn`). +/// +/// ``` +/// fn call_with_one(func: F) -> usize +/// where F: Fn(usize) -> usize { +/// func(1) +/// } +/// +/// let double = |x| x * 2; +/// assert_eq!(call_with_one(double), 2); +/// ``` #[lang = "fn"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] @@ -2038,6 +2134,40 @@ pub trait Fn : FnMut { } /// A version of the call operator that takes a mutable receiver. +/// +/// # Examples +/// +/// Closures that mutably capture variables automatically implement this trait, +/// which allows them to be invoked. +/// +/// ``` +/// let mut x = 5; +/// { +/// let mut square_x = || x *= x; +/// square_x(); +/// } +/// assert_eq!(x, 25); +/// ``` +/// +/// Closures can also be passed to higher-level functions through a `FnMut` +/// parameter (or a `FnOnce` parameter, which is a supertrait of `FnMut`). +/// +/// ``` +/// fn do_twice(mut func: F) +/// where F: FnMut() +/// { +/// func(); +/// func(); +/// } +/// +/// let mut x: usize = 1; +/// { +/// let add_two_to_x = || x += 2; +/// do_twice(add_two_to_x); +/// } +/// +/// assert_eq!(x, 5); +/// ``` #[lang = "fn_mut"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] @@ -2049,6 +2179,41 @@ pub trait FnMut : FnOnce { } /// A version of the call operator that takes a by-value receiver. +/// +/// # Examples +/// +/// By-value closures automatically implement this trait, which allows them to +/// be invoked. +/// +/// ``` +/// let x = 5; +/// let square_x = move || x * x; +/// assert_eq!(square_x(), 25); +/// ``` +/// +/// By-value Closures can also be passed to higher-level functions through a +/// `FnOnce` parameter. +/// +/// ``` +/// fn consume_with_relish(func: F) +/// where F: FnOnce() -> String +/// { +/// // `func` consumes its captured variables, so it cannot be run more +/// // than once +/// println!("Consumed: {}", func()); +/// +/// println!("Delicious!"); +/// +/// // Attempting to invoke `func()` again will throw a `use of moved +/// // value` error for `func` +/// } +/// +/// let x = String::from("x"); +/// let consume_and_return_x = move || x; +/// consume_with_relish(consume_and_return_x); +/// +/// // `consume_and_return_x` can no longer be invoked at this point +/// ``` #[lang = "fn_once"] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] From ff3a761f79cc43f5465215ad1301ac1789d6e4df Mon Sep 17 00:00:00 2001 From: Matthew Piziak Date: Sat, 20 Aug 2016 15:42:16 -0400 Subject: [PATCH 06/21] add more-evocative examples for `Shl` and `Shr` r? @steveklabnik add examples that lift `<<` and `>>` to a trivial struct replace `Scalar` structs with struct tuples add `fn main` wrappers to enable Rust Playground "Run" button --- src/libcore/ops.rs | 94 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 18 deletions(-) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 5a1993e741c60..3bf7653935661 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -852,25 +852,54 @@ bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// /// # Examples /// -/// A trivial implementation of `Shl`. When `Foo << Foo` happens, it ends up -/// calling `shl`, and therefore, `main` prints `Shifting left!`. +/// An implementation of `Shl` that lifts the `<<` operation on integers to a +/// `Scalar` struct. /// /// ``` /// use std::ops::Shl; /// -/// struct Foo; +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); /// -/// impl Shl for Foo { -/// type Output = Foo; +/// impl Shl for Scalar { +/// type Output = Self; /// -/// fn shl(self, _rhs: Foo) -> Foo { -/// println!("Shifting left!"); -/// self +/// fn shl(self, Scalar(rhs): Self) -> Scalar { +/// let Scalar(lhs) = self; +/// Scalar(lhs << rhs) +/// } +/// } +/// fn main() { +/// assert_eq!(Scalar(4) << Scalar(2), Scalar(16)); +/// } +/// ``` +/// +/// An implementation of `Shl` that spins a vector leftward by a given amount. +/// +/// ``` +/// use std::ops::Shl; +/// +/// #[derive(PartialEq, Debug)] +/// struct SpinVector { +/// vec: Vec, +/// } +/// +/// impl Shl for SpinVector { +/// type Output = Self; +/// +/// fn shl(self, rhs: usize) -> SpinVector { +/// // rotate the vector by `rhs` places +/// let (a, b) = self.vec.split_at(rhs); +/// let mut spun_vector: Vec = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// SpinVector { vec: spun_vector } /// } /// } /// /// fn main() { -/// Foo << Foo; +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } << 2, +/// SpinVector { vec: vec![2, 3, 4, 0, 1] }); /// } /// ``` #[lang = "shl"] @@ -924,25 +953,54 @@ shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize } /// /// # Examples /// -/// A trivial implementation of `Shr`. When `Foo >> Foo` happens, it ends up -/// calling `shr`, and therefore, `main` prints `Shifting right!`. +/// An implementation of `Shr` that lifts the `>>` operation on integers to a +/// `Scalar` struct. /// /// ``` /// use std::ops::Shr; /// -/// struct Foo; +/// #[derive(PartialEq, Debug)] +/// struct Scalar(usize); /// -/// impl Shr for Foo { -/// type Output = Foo; +/// impl Shr for Scalar { +/// type Output = Self; /// -/// fn shr(self, _rhs: Foo) -> Foo { -/// println!("Shifting right!"); -/// self +/// fn shr(self, Scalar(rhs): Self) -> Scalar { +/// let Scalar(lhs) = self; +/// Scalar(lhs >> rhs) +/// } +/// } +/// fn main() { +/// assert_eq!(Scalar(16) >> Scalar(2), Scalar(4)); +/// } +/// ``` +/// +/// An implementation of `Shr` that spins a vector rightward by a given amount. +/// +/// ``` +/// use std::ops::Shr; +/// +/// #[derive(PartialEq, Debug)] +/// struct SpinVector { +/// vec: Vec, +/// } +/// +/// impl Shr for SpinVector { +/// type Output = Self; +/// +/// fn shr(self, rhs: usize) -> SpinVector { +/// // rotate the vector by `rhs` places +/// let (a, b) = self.vec.split_at(self.vec.len() - rhs); +/// let mut spun_vector: Vec = vec![]; +/// spun_vector.extend_from_slice(b); +/// spun_vector.extend_from_slice(a); +/// SpinVector { vec: spun_vector } /// } /// } /// /// fn main() { -/// Foo >> Foo; +/// assert_eq!(SpinVector { vec: vec![0, 1, 2, 3, 4] } >> 2, +/// SpinVector { vec: vec![3, 4, 0, 1, 2] }); /// } /// ``` #[lang = "shr"] From bf22a7a71ab47a7d2074134b02b02df1d6ce497e Mon Sep 17 00:00:00 2001 From: Vincent Esche Date: Wed, 24 Aug 2016 15:43:28 +0200 Subject: [PATCH 07/21] Updated code sample in chapter on syntax extensions. The affected API apparently had changed with commit d59accfb065843d12db9180a4f504664e3d23ef1. --- src/doc/book/compiler-plugins.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/book/compiler-plugins.md b/src/doc/book/compiler-plugins.md index 8426d5a626549..a9a81843ab199 100644 --- a/src/doc/book/compiler-plugins.md +++ b/src/doc/book/compiler-plugins.md @@ -46,10 +46,10 @@ extern crate rustc; extern crate rustc_plugin; use syntax::parse::token; -use syntax::ast::TokenTree; +use syntax::tokenstream::TokenTree; use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax::ext::build::AstBuilder; // trait for expr_usize -use syntax_pos::Span; +use syntax::ext::quote::rt::Span; use rustc_plugin::Registry; fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) @@ -69,7 +69,7 @@ fn expand_rn(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) } let text = match args[0] { - TokenTree::Token(_, token::Ident(s, _)) => s.to_string(), + TokenTree::Token(_, token::Ident(s)) => s.to_string(), _ => { cx.span_err(sp, "argument should be a single identifier"); return DummyResult::any(sp); From 905644de5db7f73fab275345795562330d007315 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 24 Aug 2016 02:20:51 -0400 Subject: [PATCH 08/21] Rename {uint,int} methods to {usize,isize}. --- src/librbml/lib.rs | 8 ++++---- src/librbml/opaque.rs | 26 +++++++++++++------------- src/libserialize/collection_impls.rs | 4 ++-- src/libserialize/json.rs | 12 ++++++------ src/libserialize/serialize.rs | 16 ++++++++-------- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/librbml/lib.rs b/src/librbml/lib.rs index 4edbeab5dfb11..adbdc9af9cc8d 100644 --- a/src/librbml/lib.rs +++ b/src/librbml/lib.rs @@ -726,7 +726,7 @@ pub mod reader { fn read_u8(&mut self) -> DecodeResult { Ok(doc_as_u8(self.next_doc(EsU8)?)) } - fn read_uint(&mut self) -> DecodeResult { + fn read_usize(&mut self) -> DecodeResult { let v = self._next_int(EsU8, EsU64)?; if v > (::std::usize::MAX as u64) { Err(IntTooBig(v as usize)) @@ -747,7 +747,7 @@ pub mod reader { fn read_i8(&mut self) -> DecodeResult { Ok(doc_as_u8(self.next_doc(EsI8)?) as i8) } - fn read_int(&mut self) -> DecodeResult { + fn read_isize(&mut self) -> DecodeResult { let v = self._next_int(EsI8, EsI64)? as i64; if v > (isize::MAX as i64) || v < (isize::MIN as i64) { debug!("FIXME \\#6122: Removing this makes this function miscompile"); @@ -1219,7 +1219,7 @@ pub mod writer { Ok(()) } - fn emit_uint(&mut self, v: usize) -> EncodeResult { + fn emit_usize(&mut self, v: usize) -> EncodeResult { self.emit_u64(v as u64) } fn emit_u64(&mut self, v: u64) -> EncodeResult { @@ -1247,7 +1247,7 @@ pub mod writer { self.wr_tagged_raw_u8(EsU8 as usize, v) } - fn emit_int(&mut self, v: isize) -> EncodeResult { + fn emit_isize(&mut self, v: isize) -> EncodeResult { self.emit_i64(v as i64) } fn emit_i64(&mut self, v: i64) -> EncodeResult { diff --git a/src/librbml/opaque.rs b/src/librbml/opaque.rs index 10f419d169181..6dc7a72b1b1bb 100644 --- a/src/librbml/opaque.rs +++ b/src/librbml/opaque.rs @@ -54,7 +54,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { Ok(()) } - fn emit_uint(&mut self, v: usize) -> EncodeResult { + fn emit_usize(&mut self, v: usize) -> EncodeResult { write_uleb128!(self, v) } @@ -75,7 +75,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { Ok(()) } - fn emit_int(&mut self, v: isize) -> EncodeResult { + fn emit_isize(&mut self, v: isize) -> EncodeResult { write_sleb128!(self, v) } @@ -120,7 +120,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { } fn emit_str(&mut self, v: &str) -> EncodeResult { - self.emit_uint(v.len())?; + self.emit_usize(v.len())?; let _ = self.cursor.write_all(v.as_bytes()); Ok(()) } @@ -139,7 +139,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { -> EncodeResult where F: FnOnce(&mut Self) -> EncodeResult { - self.emit_uint(v_id)?; + self.emit_usize(v_id)?; f(self) } @@ -221,7 +221,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { fn emit_seq(&mut self, len: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult { - self.emit_uint(len)?; + self.emit_usize(len)?; f(self) } @@ -234,7 +234,7 @@ impl<'a> serialize::Encoder for Encoder<'a> { fn emit_map(&mut self, len: usize, f: F) -> EncodeResult where F: FnOnce(&mut Encoder<'a>) -> EncodeResult { - self.emit_uint(len)?; + self.emit_usize(len)?; f(self) } @@ -329,7 +329,7 @@ impl<'a> serialize::Decoder for Decoder<'a> { Ok(value) } - fn read_uint(&mut self) -> Result { + fn read_usize(&mut self) -> Result { read_uleb128!(self, usize) } @@ -351,7 +351,7 @@ impl<'a> serialize::Decoder for Decoder<'a> { unsafe { Ok(::std::mem::transmute(as_u8)) } } - fn read_int(&mut self) -> Result { + fn read_isize(&mut self) -> Result { read_sleb128!(self, isize) } @@ -376,7 +376,7 @@ impl<'a> serialize::Decoder for Decoder<'a> { } fn read_str(&mut self) -> Result { - let len = self.read_uint()?; + let len = self.read_usize()?; let s = ::std::str::from_utf8(&self.data[self.position..self.position + len]).unwrap(); self.position += len; Ok(s.to_string()) @@ -391,7 +391,7 @@ impl<'a> serialize::Decoder for Decoder<'a> { fn read_enum_variant(&mut self, _: &[&str], mut f: F) -> Result where F: FnMut(&mut Decoder<'a>, usize) -> Result { - let disr = self.read_uint()?; + let disr = self.read_usize()?; f(self, disr) } @@ -404,7 +404,7 @@ impl<'a> serialize::Decoder for Decoder<'a> { fn read_enum_struct_variant(&mut self, _: &[&str], mut f: F) -> Result where F: FnMut(&mut Decoder<'a>, usize) -> Result { - let disr = self.read_uint()?; + let disr = self.read_usize()?; f(self, disr) } @@ -483,7 +483,7 @@ impl<'a> serialize::Decoder for Decoder<'a> { fn read_seq(&mut self, f: F) -> Result where F: FnOnce(&mut Decoder<'a>, usize) -> Result { - let len = self.read_uint()?; + let len = self.read_usize()?; f(self, len) } @@ -496,7 +496,7 @@ impl<'a> serialize::Decoder for Decoder<'a> { fn read_map(&mut self, f: F) -> Result where F: FnOnce(&mut Decoder<'a>, usize) -> Result { - let len = self.read_uint()?; + let len = self.read_usize()?; f(self, len) } diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index 5d652ba2f55bb..7b5092e8848e4 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -136,7 +136,7 @@ impl< for item in self { bits |= item.to_usize(); } - s.emit_uint(bits) + s.emit_usize(bits) } } @@ -144,7 +144,7 @@ impl< T: Decodable + CLike > Decodable for EnumSet { fn decode(d: &mut D) -> Result, D::Error> { - let bits = d.read_uint()?; + let bits = d.read_usize()?; let mut set = EnumSet::new(); for bit in 0..(mem::size_of::()*8) { if bits & (1 << bit) != 0 { diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 6c4b6c4506b81..34df594e84756 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -495,13 +495,13 @@ impl<'a> ::Encoder for Encoder<'a> { Ok(()) } - fn emit_uint(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } + fn emit_usize(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } - fn emit_int(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } + fn emit_isize(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } @@ -743,13 +743,13 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { Ok(()) } - fn emit_uint(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } + fn emit_usize(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } - fn emit_int(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } + fn emit_isize(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) } @@ -2137,12 +2137,12 @@ impl ::Decoder for Decoder { expect!(self.pop(), Null) } - read_primitive! { read_uint, usize } + read_primitive! { read_usize, usize } read_primitive! { read_u8, u8 } read_primitive! { read_u16, u16 } read_primitive! { read_u32, u32 } read_primitive! { read_u64, u64 } - read_primitive! { read_int, isize } + read_primitive! { read_isize, isize } read_primitive! { read_i8, i8 } read_primitive! { read_i16, i16 } read_primitive! { read_i32, i32 } diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 0fcab1347d160..b75ec5dad8ddd 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -24,12 +24,12 @@ pub trait Encoder { // Primitive types: fn emit_nil(&mut self) -> Result<(), Self::Error>; - fn emit_uint(&mut self, v: usize) -> Result<(), Self::Error>; + fn emit_usize(&mut self, v: usize) -> Result<(), Self::Error>; fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>; fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>; fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>; fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>; - fn emit_int(&mut self, v: isize) -> Result<(), Self::Error>; + fn emit_isize(&mut self, v: isize) -> Result<(), Self::Error>; fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>; fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>; fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>; @@ -108,12 +108,12 @@ pub trait Decoder { // Primitive types: fn read_nil(&mut self) -> Result<(), Self::Error>; - fn read_uint(&mut self) -> Result; + fn read_usize(&mut self) -> Result; fn read_u64(&mut self) -> Result; fn read_u32(&mut self) -> Result; fn read_u16(&mut self) -> Result; fn read_u8(&mut self) -> Result; - fn read_int(&mut self) -> Result; + fn read_isize(&mut self) -> Result; fn read_i64(&mut self) -> Result; fn read_i32(&mut self) -> Result; fn read_i16(&mut self) -> Result; @@ -200,13 +200,13 @@ pub trait Decodable: Sized { impl Encodable for usize { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_uint(*self) + s.emit_usize(*self) } } impl Decodable for usize { fn decode(d: &mut D) -> Result { - d.read_uint() + d.read_usize() } } @@ -260,13 +260,13 @@ impl Decodable for u64 { impl Encodable for isize { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_int(*self) + s.emit_isize(*self) } } impl Decodable for isize { fn decode(d: &mut D) -> Result { - d.read_int() + d.read_isize() } } From cf8e1fee1619b29fb1d9a355f28a9f992426dd5a Mon Sep 17 00:00:00 2001 From: Matthew Piziak Date: Thu, 25 Aug 2016 16:20:21 -0400 Subject: [PATCH 09/21] add a simple example for `thread::current()` --- src/libstd/thread/mod.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index f06c105d30e65..42260cf195ffa 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -322,6 +322,24 @@ pub fn spawn(f: F) -> JoinHandle where } /// Gets a handle to the thread that invokes it. +/// +/// #Examples +/// +/// Getting a handle to the current thread with `thread::current()`: +/// +/// ``` +/// use std::thread; +/// +/// let handler = thread::Builder::new() +/// .name("named thread".into()) +/// .spawn(|| { +/// let handle = thread::current(); +/// assert_eq!(handle.name(), Some("named thread")); +/// }) +/// .unwrap(); +/// +/// handler.join().unwrap(); +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn current() -> Thread { thread_info::current_thread().expect("use of std::thread::current() is not \ From f4c55dd08f8e02145d28f2ccdc07cf3e9d9ffc1b Mon Sep 17 00:00:00 2001 From: "changchun.fan" Date: Mon, 22 Aug 2016 15:37:08 +0800 Subject: [PATCH 10/21] Fix documentation in cell mod --- src/libcore/cell.rs | 49 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 2af48ef2fabe3..9b8c1be231ad2 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -119,26 +119,55 @@ //! `Cell`. //! //! ``` +//! #![feature(core_intrinsics)] +//! #![feature(shared)] //! use std::cell::Cell; +//! use std::ptr::Shared; +//! use std::intrinsics::abort; +//! use std::intrinsics::assume; //! -//! struct Rc { -//! ptr: *mut RcBox +//! struct Rc { +//! ptr: Shared> //! } //! -//! struct RcBox { -//! # #[allow(dead_code)] +//! struct RcBox { +//! strong: Cell, +//! refcount: Cell, //! value: T, -//! refcount: Cell //! } //! -//! impl Clone for Rc { +//! impl Clone for Rc { //! fn clone(&self) -> Rc { -//! unsafe { -//! (*self.ptr).refcount.set((*self.ptr).refcount.get() + 1); -//! Rc { ptr: self.ptr } -//! } +//! self.inc_strong(); +//! Rc { ptr: self.ptr } +//! } +//! } +//! +//! trait RcBoxPtr { +//! +//! fn inner(&self) -> &RcBox; +//! +//! fn strong(&self) -> usize { +//! self.inner().strong.get() +//! } +//! +//! fn inc_strong(&self) { +//! self.inner() +//! .strong +//! .set(self.strong() +//! .checked_add(1) +//! .unwrap_or_else(|| unsafe { abort() })); //! } //! } +//! +//! impl RcBoxPtr for Rc { +//! fn inner(&self) -> &RcBox { +//! unsafe { +//! assume(!(*(&self.ptr as *const _ as *const *const ())).is_null()); +//! &(**self.ptr) +//! } +//! } +//! } //! ``` //! From e2d9974b3b9a1021894c532b293e7624eaeb1e1c Mon Sep 17 00:00:00 2001 From: Matthew Piziak Date: Thu, 25 Aug 2016 15:29:19 -0400 Subject: [PATCH 11/21] improve `BitAnd` trait documentation This pull request is based on the discussion in PR #35927. Add a module-level note that `&&` and `||` are short-circuiting operators and not overloadable. Add a simple `Scalar` example that lifts the `&` operator to a trivial struct tuple. Make `BooleanVector` a struct tuple. Derive `PartialEq` for `BooleanVector` instead of implementing it. Adds a `fn main` wrapper so that the example can integrate with Rust Playground. simplified bitand expression add a comment explaining what "rhs" means --- src/libcore/ops.rs | 62 ++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 21 deletions(-) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index b9adaf0206d94..128cf8f05bb59 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -21,6 +21,11 @@ //! custom operators are required, you should look toward macros or compiler //! plugins to extend Rust's syntax. //! +//! Note that the `&&` and `||` operators short-circuit, i.e. they only +//! evaluate their second operand if it contributes to the result. Since this +//! behavior is not enforceable by traits, `&&` and `||` are not supported as +//! overloadable operators. +//! //! Many of the operators take their operands by value. In non-generic //! contexts involving built-in types, this is usually not a problem. //! However, using these operators in generic code, requires some @@ -793,41 +798,56 @@ not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 } /// /// # Examples /// -/// In this example, the `BitAnd` trait is implemented for a `BooleanVector` -/// struct. +/// In this example, the `&` operator is lifted to a trivial `Scalar` type. /// /// ``` /// use std::ops::BitAnd; /// -/// #[derive(Debug)] -/// struct BooleanVector { -/// value: Vec, -/// }; +/// #[derive(Debug, PartialEq)] +/// struct Scalar(bool); /// -/// impl BitAnd for BooleanVector { +/// impl BitAnd for Scalar { /// type Output = Self; /// +/// // rhs is the "right-hand side" of the expression `a & b` /// fn bitand(self, rhs: Self) -> Self { -/// BooleanVector { -/// value: self.value -/// .iter() -/// .zip(rhs.value.iter()) -/// .map(|(x, y)| *x && *y) -/// .collect(), -/// } +/// Scalar(self.0 & rhs.0) /// } /// } /// -/// impl PartialEq for BooleanVector { -/// fn eq(&self, other: &Self) -> bool { -/// self.value == other.value +/// fn main() { +/// assert_eq!(Scalar(true) & Scalar(true), Scalar(true)); +/// assert_eq!(Scalar(true) & Scalar(false), Scalar(false)); +/// assert_eq!(Scalar(false) & Scalar(true), Scalar(false)); +/// assert_eq!(Scalar(false) & Scalar(false), Scalar(false)); +/// } +/// ``` +/// +/// In this example, the `BitAnd` trait is implemented for a `BooleanVector` +/// struct. +/// +/// ``` +/// use std::ops::BitAnd; +/// +/// #[derive(Debug, PartialEq)] +/// struct BooleanVector(Vec); +/// +/// impl BitAnd for BooleanVector { +/// type Output = Self; +/// +/// fn bitand(self, BooleanVector(rhs): Self) -> Self { +/// let BooleanVector(lhs) = self; +/// assert_eq!(lhs.len(), rhs.len()); +/// BooleanVector(lhs.iter().zip(rhs.iter()).map(|(x, y)| *x && *y).collect()) /// } /// } /// -/// let bv1 = BooleanVector { value: vec![true, true, false, false] }; -/// let bv2 = BooleanVector { value: vec![true, false, true, false] }; -/// let expected = BooleanVector { value: vec![true, false, false, false] }; -/// assert_eq!(bv1 & bv2, expected); +/// fn main() { +/// let bv1 = BooleanVector(vec![true, true, false, false]); +/// let bv2 = BooleanVector(vec![true, false, true, false]); +/// let expected = BooleanVector(vec![true, false, false, false]); +/// assert_eq!(bv1 & bv2, expected); +/// } /// ``` #[lang = "bitand"] #[stable(feature = "rust1", since = "1.0.0")] From eea03f5caab3ca6aa6789cce3d8e699fb7ac1404 Mon Sep 17 00:00:00 2001 From: William Lee Date: Sat, 27 Aug 2016 12:23:19 -0400 Subject: [PATCH 12/21] Fixes #35280 to update E0194 to support new error message format. Part of #35233. --- src/librustc_typeck/check/wfcheck.rs | 6 ++++-- src/test/compile-fail/E0194.rs | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e2080906ca242..0073506a11225 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -658,7 +658,9 @@ fn error_392<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, param_name: ast::N } fn error_194(tcx: TyCtxt, span: Span, name: ast::Name) { - span_err!(tcx.sess, span, E0194, + struct_span_err!(tcx.sess, span, E0194, "type parameter `{}` shadows another type parameter of the same name", - name); + name) + .span_label(span, &format!("`{}` shadows another type parameter", name)) + .emit(); } diff --git a/src/test/compile-fail/E0194.rs b/src/test/compile-fail/E0194.rs index 96b3062cacb78..fa94c88328a86 100644 --- a/src/test/compile-fail/E0194.rs +++ b/src/test/compile-fail/E0194.rs @@ -10,7 +10,9 @@ trait Foo { fn do_something(&self) -> T; - fn do_something_else(&self, bar: T); //~ ERROR E0194 + fn do_something_else(&self, bar: T); + //~^ ERROR E0194 + //~| NOTE `T` shadows another type parameter } fn main() { From a068fc70ab38adea73f84a8f8c6f826454ce563b Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Sat, 6 Aug 2016 12:49:17 +0200 Subject: [PATCH 13/21] Doc: explain why Box/Rc/Arc methods do not take self This can be confusing for newcomers, especially due to the argument name "this". --- src/liballoc/arc.rs | 6 ++++++ src/liballoc/boxed.rs | 4 ++++ src/liballoc/rc.rs | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 9c9f1e7b9de07..b54b71cabd1e9 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -71,6 +71,12 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// does not use atomics, making it both thread-unsafe as well as significantly /// faster when updating the reference count. /// +/// Note: the inherent methods defined on `Arc` are all associated functions, +/// which means that you have to call them as e.g. `Arc::get_mut(&value)` +/// instead of `value.get_mut()`. This is so that there are no conflicts with +/// methods on the inner type `T`, which are what you want to call in the +/// majority of cases. +/// /// # Examples /// /// In this example, a large vector of data will be shared by several threads. First we diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index c8a78f84f1857..70c429cc3600a 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -271,6 +271,10 @@ impl Box { /// proper way to do so is to convert the raw pointer back into a /// `Box` with the `Box::from_raw` function. /// + /// Note: this is an associated function, which means that you have + /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This + /// is so that there is no conflict with a method on the inner type. + /// /// # Examples /// /// ``` diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 8e43e9eec1608..c24c7ca47ad05 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -182,6 +182,12 @@ struct RcBox { /// A reference-counted pointer type over an immutable value. /// /// See the [module level documentation](./index.html) for more details. +/// +/// Note: the inherent methods defined on `Rc` are all associated functions, +/// which means that you have to call them as e.g. `Rc::get_mut(&value)` instead +/// of `value.get_mut()`. This is so that there are no conflicts with methods +/// on the inner type `T`, which are what you want to call in the majority of +/// cases. #[cfg_attr(stage0, unsafe_no_drop_flag)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Rc { From 9c256ec94bd2270508ded3dfa569b5d440140213 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Sun, 28 Aug 2016 19:16:13 -0400 Subject: [PATCH 14/21] Add test for #35423 Closes #35423 --- src/test/run-pass/issue-35423.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/test/run-pass/issue-35423.rs diff --git a/src/test/run-pass/issue-35423.rs b/src/test/run-pass/issue-35423.rs new file mode 100644 index 0000000000000..35d0c305ed834 --- /dev/null +++ b/src/test/run-pass/issue-35423.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main () { + let x = 4; + match x { + ref r if *r < 0 => println!("got negative num {} < 0", r), + e @ 1 ... 100 => println!("got number within range [1,100] {}", e), + _ => println!("no"), + } +} From 46fc80c44e8dfa974210c441eaf53c89dfad031e Mon Sep 17 00:00:00 2001 From: Mikhail Modin Date: Sat, 27 Aug 2016 23:28:38 +0300 Subject: [PATCH 15/21] update error E0451 to new format --- src/librustc_privacy/lib.rs | 19 +++++++++++++------ src/test/compile-fail/E0451.rs | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 028632ad7c006..51202b5e3987d 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -384,8 +384,10 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { fn check_field(&mut self, span: Span, def: ty::AdtDef<'tcx>, field: ty::FieldDef<'tcx>) { if def.adt_kind() == ty::AdtKind::Struct && !field.vis.is_accessible_from(self.curitem, &self.tcx.map) { - span_err!(self.tcx.sess, span, E0451, "field `{}` of struct `{}` is private", - field.name, self.tcx.item_path_str(def.did)); + struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of struct `{}` is private", + field.name, self.tcx.item_path_str(def.did)) + .span_label(span, &format!("field `{}` is private", field.name)) + .emit(); } } @@ -425,14 +427,19 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { let method = self.tcx.tables.borrow().method_map[&method_call]; self.check_method(expr.span, method.def_id); } - hir::ExprStruct(..) => { + hir::ExprStruct(_, ref fields, _) => { let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap(); let variant = adt.variant_of_def(self.tcx.expect_def(expr.id)); // RFC 736: ensure all unmentioned fields are visible. // Rather than computing the set of unmentioned fields // (i.e. `all_fields - fields`), just check them all. - for field in &variant.fields { - self.check_field(expr.span, adt, field); + for field in variant.fields.iter() { + let span = if let Some(f) = fields.iter().find(|f| f.name.node == field.name) { + f.span + } else { + expr.span + }; + self.check_field(span, adt, field); } } hir::ExprPath(..) => { @@ -472,7 +479,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap(); let variant = adt.variant_of_def(self.tcx.expect_def(pattern.id)); for field in fields { - self.check_field(pattern.span, adt, variant.field_named(field.node.name)); + self.check_field(field.span, adt, variant.field_named(field.node.name)); } } PatKind::TupleStruct(_, ref fields, ddpos) => { diff --git a/src/test/compile-fail/E0451.rs b/src/test/compile-fail/E0451.rs index 9e4a8713a33e0..f7b106d160dae 100644 --- a/src/test/compile-fail/E0451.rs +++ b/src/test/compile-fail/E0451.rs @@ -13,8 +13,24 @@ mod Bar { pub a: isize, b: isize, } + + pub struct FooTuple ( + pub isize, + isize, + ); +} + +fn pat_match(foo: Bar::Foo) { + let Bar::Foo{a:a, b:b} = foo; //~ ERROR E0451 + //~^ NOTE field `b` is private +} + +fn pat_match_tuple(foo: Bar::FooTuple) { + let Bar::FooTuple(a,b) = foo; //~ ERROR E0451 + //~^ NOTE field `1` is private } fn main() { let f = Bar::Foo{ a: 0, b: 0 }; //~ ERROR E0451 + //~^ NOTE field `b` is private } From d6fc2baa11f0fc5223d4e4b9f84e60ca60e64871 Mon Sep 17 00:00:00 2001 From: Mohit Agarwal Date: Mon, 29 Aug 2016 16:20:08 +0530 Subject: [PATCH 16/21] Update E0260 to new error format Updates #35515. Part of #35233. r? @jonathandturner --- src/librustc_resolve/lib.rs | 6 +++++- src/test/compile-fail/E0260.rs | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6a4a48377c783..9d0c93f3e9dd2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -3354,7 +3354,11 @@ impl<'a> Resolver<'a> { e.span_label(span, &"already imported"); e }, - (true, _) | (_, true) => struct_span_err!(self.session, span, E0260, "{}", msg), + (true, _) | (_, true) => { + let mut e = struct_span_err!(self.session, span, E0260, "{}", msg); + e.span_label(span, &format!("`{}` already imported", name)); + e + }, _ => match (old_binding.is_import(), binding.is_import()) { (false, false) => { let mut e = struct_span_err!(self.session, span, E0428, "{}", msg); diff --git a/src/test/compile-fail/E0260.rs b/src/test/compile-fail/E0260.rs index d20829bf4d415..63647cb41035a 100644 --- a/src/test/compile-fail/E0260.rs +++ b/src/test/compile-fail/E0260.rs @@ -9,8 +9,11 @@ // except according to those terms. extern crate collections; +//~^ NOTE previous import of `collections` here -mod collections { //~ ERROR E0260 +mod collections { +//~^ ERROR `collections` has already been imported in this module [E0260] +//~| NOTE `collections` already imported pub trait MyTrait { fn do_something(); } From 58ced1635b6c7766b18d47af45bcd484af578ab5 Mon Sep 17 00:00:00 2001 From: Paul Fanelli Date: Sun, 28 Aug 2016 00:38:04 +0000 Subject: [PATCH 17/21] Update E0463 error message to new format --- src/librustc_metadata/loader.rs | 8 +++++--- src/test/compile-fail/E0463.rs | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs index b2c87db8ef566..44d7861066da3 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/loader.rs @@ -342,9 +342,11 @@ impl<'a> Context<'a> { "found crate `{}` compiled by an incompatible version of rustc{}", self.ident, add) } else { - struct_span_err!(self.sess, self.span, E0463, - "can't find crate for `{}`{}", - self.ident, add) + let mut err = struct_span_err!(self.sess, self.span, E0463, + "can't find crate for `{}`{}", + self.ident, add); + err.span_label(self.span, &format!("can't find crate")); + err }; if !self.rejected_via_triple.is_empty() { diff --git a/src/test/compile-fail/E0463.rs b/src/test/compile-fail/E0463.rs index 3eff107365af1..3ce5b83e89fd4 100644 --- a/src/test/compile-fail/E0463.rs +++ b/src/test/compile-fail/E0463.rs @@ -9,7 +9,9 @@ // except according to those terms. #![feature(plugin)] -#![plugin(cookie_monster)] //~ ERROR E0463 +#![plugin(cookie_monster)] +//~^ ERROR E0463 +//~| NOTE can't find crate extern crate cake_is_a_lie; fn main() { From 01083baec26591a0b48752b3003fd73f4e07631e Mon Sep 17 00:00:00 2001 From: zjhmale Date: Mon, 29 Aug 2016 22:31:08 +0800 Subject: [PATCH 18/21] Update E0089 to new error format --- src/librustc_typeck/check/mod.rs | 20 ++++++++++++-------- src/test/compile-fail/E0089.rs | 4 +++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fb24971c4251d..a846383309975 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4427,14 +4427,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // use inference variables instead of the provided types. *segment = None; } else if !(can_omit && types.len() == 0) && types.len() < required_len { - let qualifier = - if type_defs.len() != required_len { "at least " } else { "" }; - span_err!(self.tcx.sess, span, E0089, - "too few type parameters provided: \ - expected {}{}, found {}", - qualifier, - count(required_len), - count(types.len())); + let adjust = |len| if len > 1 { "parameters" } else { "parameter" }; + let required_param_str = adjust(required_len); + let actual_param_str = adjust(types.len()); + struct_span_err!(self.tcx.sess, span, E0089, + "too few type parameters provided: \ + expected {} {}, found {} {}", + count(required_len), + required_param_str, + count(types.len()), + actual_param_str) + .span_label(span, &format!("expected {} type {}", required_len, required_param_str)) + .emit(); } if !bindings.is_empty() { diff --git a/src/test/compile-fail/E0089.rs b/src/test/compile-fail/E0089.rs index 3b52f76bf09cc..9ce36523709e5 100644 --- a/src/test/compile-fail/E0089.rs +++ b/src/test/compile-fail/E0089.rs @@ -11,5 +11,7 @@ fn foo() {} fn main() { - foo::(); //~ ERROR E0089 + foo::(); +//~^ ERROR E0089 +//~| NOTE expected 2 type parameters } From 6355528ffda28e77850f739d5c51ab48e8a68bb1 Mon Sep 17 00:00:00 2001 From: Gavin Baker Date: Mon, 29 Aug 2016 11:55:30 +1000 Subject: [PATCH 19/21] E0164 Update error format #35269 - Fixes #35269 - Part of #35233 r? @jonathandturner --- src/librustc_typeck/check/_match.rs | 3 ++- src/test/compile-fail/E0164.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 78175c85b19bf..225468cb9f40c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -574,7 +574,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { tcx.sess.add_lint(lint::builtin::MATCH_OF_UNIT_VARIANT_VIA_PAREN_DOTDOT, pat.id, pat.span, msg); } else { - span_err!(tcx.sess, pat.span, E0164, "{}", msg); + struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg) + .span_label(pat.span, &format!("not a tuple variant or struct")).emit(); on_error(); } }; diff --git a/src/test/compile-fail/E0164.rs b/src/test/compile-fail/E0164.rs index 491b2e9e5b246..1665a80bead77 100644 --- a/src/test/compile-fail/E0164.rs +++ b/src/test/compile-fail/E0164.rs @@ -13,6 +13,7 @@ enum Foo { B { i: u32 } } fn bar(foo: Foo) -> u32 { match foo { Foo::B(i) => i, //~ ERROR E0164 + //~| NOTE not a tuple variant or struct } } From 28c5edb9f6a35dcd1bf4af102457d26a2de9d76e Mon Sep 17 00:00:00 2001 From: Gavin Baker Date: Mon, 29 Aug 2016 12:52:02 +1000 Subject: [PATCH 20/21] E0165 Update error format #35270 - Fixes #35270 - Part of #35233 r? @jonathandturner --- src/librustc_const_eval/check_match.rs | 5 ++++- src/test/compile-fail/E0165.rs | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 82c142c919e34..e71a780dd89bc 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -324,7 +324,10 @@ fn check_arms(cx: &MatchCheckCtxt, let &(ref first_arm_pats, _) = &arms[0]; let first_pat = &first_arm_pats[0]; let span = first_pat.span; - span_err!(cx.tcx.sess, span, E0165, "irrefutable while-let pattern"); + struct_span_err!(cx.tcx.sess, span, E0165, + "irrefutable while-let pattern") + .span_label(span, &format!("irrefutable pattern")) + .emit(); }, hir::MatchSource::ForLoopDesugar => { diff --git a/src/test/compile-fail/E0165.rs b/src/test/compile-fail/E0165.rs index cca714bbcc1bf..142635fc6ee45 100644 --- a/src/test/compile-fail/E0165.rs +++ b/src/test/compile-fail/E0165.rs @@ -13,6 +13,7 @@ struct Irrefutable(i32); fn main() { let irr = Irrefutable(0); while let Irrefutable(x) = irr { //~ ERROR E0165 + //~| irrefutable pattern // ... } } From 2967dcc4d7bf0722fb348092a254aaa12deaa6d8 Mon Sep 17 00:00:00 2001 From: Gavin Baker Date: Mon, 29 Aug 2016 13:05:06 +1000 Subject: [PATCH 21/21] E0184 Update error format #35275 - Fixes #35275 - Part of #35233 r? @jonathandturner --- src/librustc_typeck/coherence/mod.rs | 6 ++++-- src/test/compile-fail/E0184.rs | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 7d6cee7b3bac1..f743ef2187561 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -348,9 +348,11 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { .emit(); } Err(CopyImplementationError::HasDestructor) => { - span_err!(tcx.sess, span, E0184, + struct_span_err!(tcx.sess, span, E0184, "the trait `Copy` may not be implemented for this type; \ - the type has a destructor"); + the type has a destructor") + .span_label(span, &format!("Copy not allowed on types with destructors")) + .emit(); } } }); diff --git a/src/test/compile-fail/E0184.rs b/src/test/compile-fail/E0184.rs index 5d72d00ffe876..9ec2eeba5cc5f 100644 --- a/src/test/compile-fail/E0184.rs +++ b/src/test/compile-fail/E0184.rs @@ -9,6 +9,8 @@ // except according to those terms. #[derive(Copy)] //~ ERROR E0184 + //~| NOTE Copy not allowed on types with destructors + //~| NOTE in this expansion of #[derive(Copy)] struct Foo; impl Drop for Foo {