From cba5f6bd01bc3ba692c355ca82212db069cd800c Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Tue, 5 Dec 2017 18:07:28 +0100 Subject: [PATCH 01/41] Rewrite Borrow's trait documentation. --- src/libcore/borrow.rs | 147 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 132 insertions(+), 15 deletions(-) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 61558034e63eb..76f6215fae659 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -12,26 +12,143 @@ #![stable(feature = "rust1", since = "1.0.0")] -/// A trait for borrowing data. +// impl Borrow for String +// impl Borrow for Arc +// impl HashSet { fn get(&self, q: &Q) where K: Borrow } + +/// A trait identifying how borrowed data behaves. +/// +/// If a type implements this trait, it signals that a reference to it behaves +/// exactly like a reference to `Borrowed`. As a consequence, if a trait is +/// implemented both by `Self` and `Borrowed`, all trait methods that +/// take a `&self` argument must produce the same result in both +/// implementations. +/// +/// As a consequence, this trait should only be implemented for types managing +/// a value of another type without modifying its behavior. Examples are +/// smart pointers such as [`Box`] or [`Rc`] as well the owned version of +/// slices such as [`Vec`]. +/// +/// A relaxed version that allows providing a reference to some other type +/// without any further promises is available through [`AsRef`]. +/// +/// When writing generic code, a use of `Borrow` should always be justified +/// by additional trait bounds, making it clear that the two types need to +/// behave identically in a certain context. If the code should merely be +/// able to operate on any type that can produce a reference to a given type, +/// you should use [`AsRef`] instead. +/// +/// The companion trait [`BorrowMut`] provides the same guarantees for +/// mutable references. +/// +/// [`Box`]: ../boxed/struct.Box.html +/// [`Rc`]: ../rc/struct.Rc.html +/// [`Vec`]: ../vec/struct.Vec.html +/// [`AsRef`]: ../convert/trait.AsRef.html +/// [`BorrowMut`]: trait.BorrowMut.html +/// +/// # Examples +/// +/// As a data collection, [`HashMap`] owns both keys and values. If the key’s +/// actual data is wrapped in a managing type of some kind, it should, +/// however, still be possible to search for a value using a reference to the +/// key’s data. For instance, if the key is a string, then it is likely +/// stored with the hash map as a [`String`], while it should be possible +/// to search using a [`&str`][`str`]. Thus, `insert` needs to operate on a +/// string while `get` needs to be able to use a `&str`. +/// +/// Slightly simplified, the relevant parts of `HashMap` look like this: +/// +/// ``` +/// use std::borrow::Borrow; +/// use std::hash::Hash; +/// +/// pub struct HashMap { +/// # marker: ::std::marker::PhantomData<(K, V)>, +/// // fields omitted +/// } +/// +/// impl HashMap { +/// pub fn insert(&self, key: K, value: V) -> Option +/// where K: Hash + Eq +/// { +/// # unimplemented!() +/// // ... +/// } +/// +/// pub fn get(&self, k: &Q) -> Option<&V> +/// where K: Borrow, +/// Q: Hash + Eq + ?Sized +/// { +/// # unimplemented!() +/// // ... +/// } +/// } +/// ``` +/// +/// The entire hash map is generic over the stored type for the key, `K`. +/// When inserting a value, the map is given such a `K` and needs to find +/// the correct hash bucket and check if the key is already present based +/// on that `K` value. It therefore requires `K: Hash + Eq`. +/// +/// In order to search for a value based on the key’s data, the `get` method +/// is generic over some type `Q`. Technically, it needs to convert that `Q` +/// into a `K` in order to use `K`’s [`Hash`] implementation to be able to +/// arrive at the same hash value as during insertion in order to look into +/// the right hash bucket. Since `K` is some kind of owned value, this likely +/// would involve cloning and isn’t really practical. +/// +/// Instead, `get` relies on `Q`’s implementation of `Hash` and uses `Borrow` +/// to indicate that `K`’s implementation of `Hash` must produce the same +/// result as `Q`’s by demanding that `K: Borrow`. +/// +/// As a consequence, the hash map breaks if a `K` wrapping a `Q` value +/// produces a different hash than `Q`. For instance, image you have a +/// type that wraps a string but compares ASCII letters case-insensitive: +/// +/// ``` +/// use std::ascii::AsciiExt; +/// +/// pub struct CIString(String); +/// +/// impl PartialEq for CIString { +/// fn eq(&self, other: &Self) -> bool { +/// self.0.eq_ignore_ascii_case(&other.0) +/// } +/// } /// -/// In general, there may be several ways to "borrow" a piece of data. The -/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T` -/// (a mutable borrow). But types like `Vec` provide additional kinds of -/// borrows: the borrowed slices `&[T]` and `&mut [T]`. +/// impl Eq for CIString { } +/// ``` /// -/// When writing generic code, it is often desirable to abstract over all ways -/// of borrowing data from a given type. That is the role of the `Borrow` -/// trait: if `T: Borrow`, then `&U` can be borrowed from `&T`. A given -/// type can be borrowed as multiple different types. In particular, `Vec: -/// Borrow>` and `Vec: Borrow<[T]>`. +/// Because two equal values need to produce the same hash value, the +/// implementation of `Hash` need to reflect that, too: /// -/// If you are implementing `Borrow` and both `Self` and `Borrowed` implement -/// `Hash`, `Eq`, and/or `Ord`, they must produce the same result. +/// ``` +/// # use std::ascii::AsciiExt; +/// # use std::hash::{Hash, Hasher}; +/// # pub struct CIString(String); +/// impl Hash for CIString { +/// fn hash(&self, state: &mut H) { +/// for c in self.0.as_bytes() { +/// c.to_ascii_lowercase().hash(state) +/// } +/// } +/// } +/// ``` /// -/// `Borrow` is very similar to, but different than, `AsRef`. See -/// [the book][book] for more. +/// Can `CIString` implement `Borrow`? It certainly can provide a +/// reference to a string slice via its contained owned string. But because +/// its `Hash` implementation differs, it cannot fulfill the guarantee for +/// `Borrow` that all common trait implementations must behave the same way +/// and must not, in fact, implement `Borrow`. If it wants to allow +/// others access to the underlying `str`, it can do that via `AsRef` +/// which doesn’t carry any such restrictions. /// -/// [book]: ../../book/first-edition/borrow-and-asref.html +/// [`Hash`]: ../hash/trait.Hash.html +/// [`HashMap`]: ../collections/struct.HashMap.html +/// [`String`]: ../string/struct.String.html +/// [`str`]: ../primitive.str.html +/// #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrows from an owned value. From c4ea700041f78a016dca557c2da86006a7bbedf8 Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Tue, 5 Dec 2017 18:28:29 +0100 Subject: [PATCH 02/41] Remove trailing white space. --- src/libcore/borrow.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 76f6215fae659..4d4a07f59d147 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -100,12 +100,12 @@ /// /// Instead, `get` relies on `Q`’s implementation of `Hash` and uses `Borrow` /// to indicate that `K`’s implementation of `Hash` must produce the same -/// result as `Q`’s by demanding that `K: Borrow`. +/// result as `Q`’s by demanding that `K: Borrow`. /// /// As a consequence, the hash map breaks if a `K` wrapping a `Q` value /// produces a different hash than `Q`. For instance, image you have a /// type that wraps a string but compares ASCII letters case-insensitive: -/// +/// /// ``` /// use std::ascii::AsciiExt; /// @@ -148,7 +148,7 @@ /// [`HashMap`]: ../collections/struct.HashMap.html /// [`String`]: ../string/struct.String.html /// [`str`]: ../primitive.str.html -/// +/// #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrows from an owned value. From 85e8a9ba00e8ac090ceaac619110264e8e8bf6c6 Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Thu, 7 Dec 2017 16:50:37 +0100 Subject: [PATCH 03/41] Include feedback and try to make examples build on all channels. --- src/libcore/borrow.rs | 60 +++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 4d4a07f59d147..77006193a5857 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -12,10 +12,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -// impl Borrow for String -// impl Borrow for Arc -// impl HashSet { fn get(&self, q: &Q) where K: Borrow } - /// A trait identifying how borrowed data behaves. /// /// If a type implements this trait, it signals that a reference to it behaves @@ -26,10 +22,10 @@ /// /// As a consequence, this trait should only be implemented for types managing /// a value of another type without modifying its behavior. Examples are -/// smart pointers such as [`Box`] or [`Rc`] as well the owned version of -/// slices such as [`Vec`]. +/// smart pointers such as [`Box`] or [`Rc`] as well the owned version +/// of slices such as [`Vec`]. /// -/// A relaxed version that allows providing a reference to some other type +/// A relaxed version that allows converting a reference to some other type /// without any further promises is available through [`AsRef`]. /// /// When writing generic code, a use of `Borrow` should always be justified @@ -41,23 +37,24 @@ /// The companion trait [`BorrowMut`] provides the same guarantees for /// mutable references. /// -/// [`Box`]: ../boxed/struct.Box.html -/// [`Rc`]: ../rc/struct.Rc.html -/// [`Vec`]: ../vec/struct.Vec.html +/// [`Box`]: ../boxed/struct.Box.html +/// [`Rc`]: ../rc/struct.Rc.html +/// [`Vec`]: ../vec/struct.Vec.html /// [`AsRef`]: ../convert/trait.AsRef.html /// [`BorrowMut`]: trait.BorrowMut.html /// /// # Examples /// -/// As a data collection, [`HashMap`] owns both keys and values. If the key’s -/// actual data is wrapped in a managing type of some kind, it should, -/// however, still be possible to search for a value using a reference to the -/// key’s data. For instance, if the key is a string, then it is likely -/// stored with the hash map as a [`String`], while it should be possible -/// to search using a [`&str`][`str`]. Thus, `insert` needs to operate on a -/// string while `get` needs to be able to use a `&str`. +/// As a data collection, [`HashMap`] owns both keys and values. If +/// the key’s actual data is wrapped in a managing type of some kind, it +/// should, however, still be possible to search for a value using a +/// reference to the key’s data. For instance, if the key is a string, then +/// it is likely stored with the hash map as a [`String`], while it should +/// be possible to search using a [`&str`][`str`]. Thus, `insert` needs to +/// operate on a `String` while `get` needs to be able to use a `&str`. /// -/// Slightly simplified, the relevant parts of `HashMap` look like this: +/// Slightly simplified, the relevant parts of `HashMap` look like +/// this: /// /// ``` /// use std::borrow::Borrow; @@ -70,15 +67,16 @@ /// /// impl HashMap { /// pub fn insert(&self, key: K, value: V) -> Option -/// where K: Hash + Eq +/// where K: Hash + Eq /// { /// # unimplemented!() /// // ... /// } /// /// pub fn get(&self, k: &Q) -> Option<&V> -/// where K: Borrow, -/// Q: Hash + Eq + ?Sized +/// where +/// K: Borrow, +/// Q: Hash + Eq + ?Sized /// { /// # unimplemented!() /// // ... @@ -86,10 +84,11 @@ /// } /// ``` /// -/// The entire hash map is generic over the stored type for the key, `K`. -/// When inserting a value, the map is given such a `K` and needs to find -/// the correct hash bucket and check if the key is already present based -/// on that `K` value. It therefore requires `K: Hash + Eq`. +/// The entire hash map is generic over a key type `K`. Because these keys +/// are stored by with the hash map, this type as to own the key’s data. +/// When inserting a key-value pair, the map is given such a `K` and needs +/// to find the correct hash bucket and check if the key is already present +/// based on that `K`. It therefore requires `K: Hash + Eq`. /// /// In order to search for a value based on the key’s data, the `get` method /// is generic over some type `Q`. Technically, it needs to convert that `Q` @@ -103,10 +102,11 @@ /// result as `Q`’s by demanding that `K: Borrow`. /// /// As a consequence, the hash map breaks if a `K` wrapping a `Q` value -/// produces a different hash than `Q`. For instance, image you have a -/// type that wraps a string but compares ASCII letters case-insensitive: +/// produces a different hash than `Q`. For instance, imagine you have a +/// type that wraps a string but compares ASCII letters ignoring their case: /// /// ``` +/// # #[allow(unused_imports)] /// use std::ascii::AsciiExt; /// /// pub struct CIString(String); @@ -121,10 +121,10 @@ /// ``` /// /// Because two equal values need to produce the same hash value, the -/// implementation of `Hash` need to reflect that, too: +/// implementation of `Hash` needs to reflect that, too: /// /// ``` -/// # use std::ascii::AsciiExt; +/// # #[allow(unused_imports)] use std::ascii::AsciiExt; /// # use std::hash::{Hash, Hasher}; /// # pub struct CIString(String); /// impl Hash for CIString { @@ -145,7 +145,7 @@ /// which doesn’t carry any such restrictions. /// /// [`Hash`]: ../hash/trait.Hash.html -/// [`HashMap`]: ../collections/struct.HashMap.html +/// [`HashMap`]: ../collections/struct.HashMap.html /// [`String`]: ../string/struct.String.html /// [`str`]: ../primitive.str.html /// From fc6c6383f6999d87c92be3dfd5f09c357be41135 Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Wed, 13 Dec 2017 08:48:29 +0100 Subject: [PATCH 04/41] Fix documentation links. --- src/libcore/borrow.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 77006193a5857..33e4c8780d638 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -37,10 +37,10 @@ /// The companion trait [`BorrowMut`] provides the same guarantees for /// mutable references. /// -/// [`Box`]: ../boxed/struct.Box.html -/// [`Rc`]: ../rc/struct.Rc.html -/// [`Vec`]: ../vec/struct.Vec.html -/// [`AsRef`]: ../convert/trait.AsRef.html +/// [`Box`]: ../../std/boxed/struct.Box.html +/// [`Rc`]: ../../std/rc/struct.Rc.html +/// [`Vec`]: ../../std/vec/struct.Vec.html +/// [`AsRef`]: ../../std/convert/trait.AsRef.html /// [`BorrowMut`]: trait.BorrowMut.html /// /// # Examples @@ -144,10 +144,10 @@ /// others access to the underlying `str`, it can do that via `AsRef` /// which doesn’t carry any such restrictions. /// -/// [`Hash`]: ../hash/trait.Hash.html -/// [`HashMap`]: ../collections/struct.HashMap.html -/// [`String`]: ../string/struct.String.html -/// [`str`]: ../primitive.str.html +/// [`Hash`]: ../../std/hash/trait.Hash.html +/// [`HashMap`]: ../../std/collections/struct.HashMap.html +/// [`String`]: ../../std/string/struct.String.html +/// [`str`]: ../../std/primitive.str.html /// #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { From 7ae7e5393367cdc9a630cd56911ab42f499c091f Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Thu, 8 Feb 2018 11:07:05 +0100 Subject: [PATCH 05/41] New introduction and revised hash map explanation. --- src/libcore/borrow.rs | 74 +++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 33e4c8780d638..1f692d019c3de 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -14,19 +14,28 @@ /// A trait identifying how borrowed data behaves. /// -/// If a type implements this trait, it signals that a reference to it behaves -/// exactly like a reference to `Borrowed`. As a consequence, if a trait is -/// implemented both by `Self` and `Borrowed`, all trait methods that -/// take a `&self` argument must produce the same result in both -/// implementations. -/// -/// As a consequence, this trait should only be implemented for types managing -/// a value of another type without modifying its behavior. Examples are -/// smart pointers such as [`Box`] or [`Rc`] as well the owned version -/// of slices such as [`Vec`]. -/// -/// A relaxed version that allows converting a reference to some other type -/// without any further promises is available through [`AsRef`]. +/// In Rust, it is common to provide different representations of a type for +/// different use cases. For instance, storage location and management for a +/// value can be specifically chosen as appropriate for a particular use via +/// pointer types such as [`Box`] or [`Rc`] or one can opt into +/// concurrency via synchronization types such as [`Mutex`], avoiding the +/// associated cost when in parallel doesn’t happen. Beyond these generic +/// wrappers that can be used with any type, some types provide optional +/// facets providing potentially costly functionality. An example for such a +/// type is [`String`] which adds the ability to extend a string to the basic +/// [`str`]. This requires keeping additional information unnecessary for a +/// simple, imutable string. +/// +/// These types signal that they are a specialized representation of a basic +/// type `T` by implementing `Borrow`. The method `borrow` provides a way +/// to convert a reference to the type into a reference to the underlying +/// basic type. +/// +/// If a type implementing `Borrow` implements other traits also +/// implemented by `T`, these implementations behave identically if the trait +/// is concerned with the data rather than its representation. For instance, +/// the comparison traits such as `PartialEq` or `PartialOrd` must behave +/// identical for `T` and any type implemeting `Borrow`. /// /// When writing generic code, a use of `Borrow` should always be justified /// by additional trait bounds, making it clear that the two types need to @@ -37,11 +46,13 @@ /// The companion trait [`BorrowMut`] provides the same guarantees for /// mutable references. /// -/// [`Box`]: ../../std/boxed/struct.Box.html -/// [`Rc`]: ../../std/rc/struct.Rc.html -/// [`Vec`]: ../../std/vec/struct.Vec.html /// [`AsRef`]: ../../std/convert/trait.AsRef.html /// [`BorrowMut`]: trait.BorrowMut.html +/// [`Box`]: ../../std/boxed/struct.Box.html +/// [`Mutex`]: ../../std/sync/struct.Mutex.html +/// [`Rc`]: ../../std/rc/struct.Rc.html +/// [`str`]: ../../std/primitive.str.html +/// [`String`]: ../../std/string/struct.String.html /// /// # Examples /// @@ -85,30 +96,34 @@ /// ``` /// /// The entire hash map is generic over a key type `K`. Because these keys -/// are stored by with the hash map, this type as to own the key’s data. +/// are stored with the hash map, this type has to own the key’s data. /// When inserting a key-value pair, the map is given such a `K` and needs /// to find the correct hash bucket and check if the key is already present /// based on that `K`. It therefore requires `K: Hash + Eq`. /// -/// In order to search for a value based on the key’s data, the `get` method -/// is generic over some type `Q`. Technically, it needs to convert that `Q` -/// into a `K` in order to use `K`’s [`Hash`] implementation to be able to -/// arrive at the same hash value as during insertion in order to look into -/// the right hash bucket. Since `K` is some kind of owned value, this likely -/// would involve cloning and isn’t really practical. +/// When searching for a value in the map, however, having to provide a +/// reference to a `K` as the key to search for would require to always +/// create such an owned value. For string keys, this would mean a `String` +/// value needs to be created just for the search for cases where only a +/// `str` is available. /// -/// Instead, `get` relies on `Q`’s implementation of `Hash` and uses `Borrow` -/// to indicate that `K`’s implementation of `Hash` must produce the same -/// result as `Q`’s by demanding that `K: Borrow`. +/// Instead, the `get` method is generic over the type of the underlying key +/// data, called `Q` in the method signature above. It states that `K` is a +/// representation of `Q` by requiring that `K: Borrow`. By additionally +/// requiring `Q: Hash + Eq`, it demands that `K` and `Q` have +/// implementations of the `Hash` and `Eq` traits that procude identical +/// results. +/// +/// The implementation of `get` relies in particular on identical +/// implementations of `Hash` by determining the key’s hash bucket by calling +/// `Hash::hash` on the `Q` value even though it inserted the key based on +/// the hash value calculated from the `K` value. /// /// As a consequence, the hash map breaks if a `K` wrapping a `Q` value /// produces a different hash than `Q`. For instance, imagine you have a /// type that wraps a string but compares ASCII letters ignoring their case: /// /// ``` -/// # #[allow(unused_imports)] -/// use std::ascii::AsciiExt; -/// /// pub struct CIString(String); /// /// impl PartialEq for CIString { @@ -124,7 +139,6 @@ /// implementation of `Hash` needs to reflect that, too: /// /// ``` -/// # #[allow(unused_imports)] use std::ascii::AsciiExt; /// # use std::hash::{Hash, Hasher}; /// # pub struct CIString(String); /// impl Hash for CIString { From 44be054a2acbeeb682d02a5f88ddedc0cb5c9bf2 Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Tue, 27 Feb 2018 16:24:52 +0100 Subject: [PATCH 06/41] Further refinement of Borrow documentation. --- src/libcore/borrow.rs | 68 +++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 32 deletions(-) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 1f692d019c3de..c0f1989f87944 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -17,36 +17,41 @@ /// In Rust, it is common to provide different representations of a type for /// different use cases. For instance, storage location and management for a /// value can be specifically chosen as appropriate for a particular use via -/// pointer types such as [`Box`] or [`Rc`] or one can opt into -/// concurrency via synchronization types such as [`Mutex`], avoiding the -/// associated cost when in parallel doesn’t happen. Beyond these generic +/// pointer types such as [`Box`] or [`Rc`]. Beyond these generic /// wrappers that can be used with any type, some types provide optional /// facets providing potentially costly functionality. An example for such a /// type is [`String`] which adds the ability to extend a string to the basic /// [`str`]. This requires keeping additional information unnecessary for a -/// simple, imutable string. +/// simple, immutable string. /// /// These types signal that they are a specialized representation of a basic /// type `T` by implementing `Borrow`. The method `borrow` provides a way -/// to convert a reference to the type into a reference to the underlying -/// basic type. +/// to convert a reference to the type into a reference to this basic type +/// `T`. /// -/// If a type implementing `Borrow` implements other traits also -/// implemented by `T`, these implementations behave identically if the trait -/// is concerned with the data rather than its representation. For instance, -/// the comparison traits such as `PartialEq` or `PartialOrd` must behave -/// identical for `T` and any type implemeting `Borrow`. +/// Further, when providing implementations for additional traits, it needs +/// to be considered whether they should behave identical to those of the +/// underlying type as a consequence of acting as a representation of that +/// underlying type. /// -/// When writing generic code, a use of `Borrow` should always be justified -/// by additional trait bounds, making it clear that the two types need to -/// behave identically in a certain context. If the code should merely be -/// able to operate on any type that can produce a reference to a given type, -/// you should use [`AsRef`] instead. +/// Generic code typically uses `Borrow` when it not only needs access +/// to a reference of the underlying type but relies on the identical +/// behavior of these additional trait implementations. These traits are +/// likely to appear as additional trait bounds. /// -/// The companion trait [`BorrowMut`] provides the same guarantees for -/// mutable references. +/// If generic code merely needs to work for all types that can +/// provide a reference to related type `T`, it is often better to use +/// [`AsRef`] as more types can safely implement it. /// -/// [`AsRef`]: ../../std/convert/trait.AsRef.html +/// If a type implementing `Borrow` also wishes to allow mutable access +/// to the underlying type `T`, it can do so by implementing the companion +/// trait [`BorrowMut`]. +/// +/// Note also that it is perfectly fine for a single type to have multiple +/// implementations of `Borrow` for different `T`s. In fact, a blanket +/// implementation lets every type be at least a borrow of itself. +/// +/// [`AsRef`]: ../../std/convert/trait.AsRef.html /// [`BorrowMut`]: trait.BorrowMut.html /// [`Box`]: ../../std/boxed/struct.Box.html /// [`Mutex`]: ../../std/sync/struct.Mutex.html @@ -111,7 +116,7 @@ /// data, called `Q` in the method signature above. It states that `K` is a /// representation of `Q` by requiring that `K: Borrow`. By additionally /// requiring `Q: Hash + Eq`, it demands that `K` and `Q` have -/// implementations of the `Hash` and `Eq` traits that procude identical +/// implementations of the `Hash` and `Eq` traits that produce identical /// results. /// /// The implementation of `get` relies in particular on identical @@ -124,15 +129,15 @@ /// type that wraps a string but compares ASCII letters ignoring their case: /// /// ``` -/// pub struct CIString(String); +/// pub struct CaseInsensitiveString(String); /// -/// impl PartialEq for CIString { +/// impl PartialEq for CaseInsensitiveString { /// fn eq(&self, other: &Self) -> bool { /// self.0.eq_ignore_ascii_case(&other.0) /// } /// } /// -/// impl Eq for CIString { } +/// impl Eq for CaseInsensitiveString { } /// ``` /// /// Because two equal values need to produce the same hash value, the @@ -140,8 +145,8 @@ /// /// ``` /// # use std::hash::{Hash, Hasher}; -/// # pub struct CIString(String); -/// impl Hash for CIString { +/// # pub struct CaseInsensitiveString(String); +/// impl Hash for CaseInsensitiveString { /// fn hash(&self, state: &mut H) { /// for c in self.0.as_bytes() { /// c.to_ascii_lowercase().hash(state) @@ -150,13 +155,12 @@ /// } /// ``` /// -/// Can `CIString` implement `Borrow`? It certainly can provide a -/// reference to a string slice via its contained owned string. But because -/// its `Hash` implementation differs, it cannot fulfill the guarantee for -/// `Borrow` that all common trait implementations must behave the same way -/// and must not, in fact, implement `Borrow`. If it wants to allow -/// others access to the underlying `str`, it can do that via `AsRef` -/// which doesn’t carry any such restrictions. +/// Can `CaseInsensitiveString` implement `Borrow`? It certainly can +/// provide a reference to a string slice via its contained owned string. +/// But because its `Hash` implementation differs, it behaves differently +/// from `str` and therefore must not, in fact, implement `Borrow`. +/// If it wants to allow others access to the underlying `str`, it can do +/// that via `AsRef` which doesn’t carry any extra requirements. /// /// [`Hash`]: ../../std/hash/trait.Hash.html /// [`HashMap`]: ../../std/collections/struct.HashMap.html From 5766e71fa7b3378d0b30d026eae23293e8e8bb32 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 13 Mar 2018 21:36:49 -0400 Subject: [PATCH 07/41] Cache the specialization_graph query Fixes #48987 --- src/librustc/traits/specialize/specialization_graph.rs | 2 ++ src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/maps/config.rs | 1 + src/librustc/ty/maps/on_disk_cache.rs | 1 + src/librustc/ty/maps/plumbing.rs | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index f8b895177f381..e0d662657b7de 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -36,6 +36,7 @@ use util::nodemap::{DefIdMap, FxHashMap}; /// parents of a given specializing impl, which is needed for extracting /// default items amongst other things. In the simple "chain" rule, every impl /// has at most one parent. +#[derive(RustcEncodable, RustcDecodable)] pub struct Graph { // all impls have a parent; the "root" impls have as their parent the def_id // of the trait @@ -47,6 +48,7 @@ pub struct Graph { /// Children of a given impl, grouped into blanket/non-blanket varieties as is /// done in `TraitDef`. +#[derive(RustcEncodable, RustcDecodable)] struct Children { // Impls of a trait (or specializations of a given impl). To allow for // quicker lookup, the impls are indexed by a simplified version of their diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 93d8a4d979de6..889648a46be12 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -28,7 +28,7 @@ pub type SimplifiedType = SimplifiedTypeGen; /// because we sometimes need to use SimplifiedTypeGen values as stable sorting /// keys (in which case we use a DefPathHash as id-type) but in the general case /// the non-stable but fast to construct DefId-version is the better choice. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, RustcEncodable, RustcDecodable)] pub enum SimplifiedTypeGen where D: Copy + Debug + Ord + Eq + Hash { diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 11675f542873d..008e3b7d85969 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -721,3 +721,4 @@ impl_disk_cacheable_query!(type_of, |def_id| def_id.is_local()); impl_disk_cacheable_query!(predicates_of, |def_id| def_id.is_local()); impl_disk_cacheable_query!(used_trait_imports, |def_id| def_id.is_local()); impl_disk_cacheable_query!(trans_fn_attrs, |_| true); +impl_disk_cacheable_query!(specialization_graph_of, |_| true); diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs index 35e874b74d9ae..e7dd4c82254c0 100644 --- a/src/librustc/ty/maps/on_disk_cache.rs +++ b/src/librustc/ty/maps/on_disk_cache.rs @@ -221,6 +221,7 @@ impl<'sess> OnDiskCache<'sess> { encode_query_results::(tcx, enc, qri)?; encode_query_results::(tcx, enc, qri)?; encode_query_results::(tcx, enc, qri)?; + encode_query_results::(tcx, enc, qri)?; // const eval is special, it only encodes successfully evaluated constants use ty::maps::plumbing::GetCacheInternal; diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index bc7186f781a82..0bff13a71e39d 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -1001,4 +1001,5 @@ impl_load_from_cache!( PredicatesOfItem => predicates_of, UsedTraitImports => used_trait_imports, TransFnAttrs => trans_fn_attrs, + SpecializationGraph => specialization_graph_of, ); From 0b111e677c6bd58cf046d925493c5413c05773fe Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 8 Mar 2018 16:29:35 +0800 Subject: [PATCH 08/41] change &self to self and fix lifetime annotations --- src/librustc_borrowck/borrowck/mod.rs | 28 ++-- src/librustc_mir/util/borrowck_errors.rs | 178 +++++++++++++---------- 2 files changed, 119 insertions(+), 87 deletions(-) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index bb198adea4a6a..93d6247eeae47 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -253,28 +253,28 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> { used_mut_nodes: RefCell>, } -impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> { - fn struct_span_err_with_code<'a, S: Into>(&'a self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'a> +impl<'a, 'b, 'tcx: 'b> BorrowckErrors<'a> for &'a BorrowckCtxt<'b, 'tcx> { + fn struct_span_err_with_code>(self, + sp: S, + msg: &str, + code: DiagnosticId) + -> DiagnosticBuilder<'a> { self.tcx.sess.struct_span_err_with_code(sp, msg, code) } - fn struct_span_err<'a, S: Into>(&'a self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'a> + fn struct_span_err>(self, + sp: S, + msg: &str) + -> DiagnosticBuilder<'a> { self.tcx.sess.struct_span_err(sp, msg) } - fn cancel_if_wrong_origin<'a>(&'a self, - mut diag: DiagnosticBuilder<'a>, - o: Origin) - -> DiagnosticBuilder<'a> + fn cancel_if_wrong_origin(self, + mut diag: DiagnosticBuilder<'a>, + o: Origin) + -> DiagnosticBuilder<'a> { if !o.should_emit_errors(self.tcx.borrowck_mode()) { self.tcx.sess.diagnostic().cancel(&mut diag); diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 89242ca32bcbf..48575584530c9 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -52,30 +52,34 @@ impl Origin { } } -pub trait BorrowckErrors { - fn struct_span_err_with_code<'a, S: Into>(&'a self, +pub trait BorrowckErrors<'cx> { + fn struct_span_err_with_code>(self, sp: S, msg: &str, code: DiagnosticId) - -> DiagnosticBuilder<'a>; + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy; - fn struct_span_err<'a, S: Into>(&'a self, + fn struct_span_err>(self, sp: S, msg: &str) - -> DiagnosticBuilder<'a>; + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy; /// Cancels the given error if we shouldn't emit errors for a given /// origin in the current mode. /// /// Always make sure that the error gets passed through this function /// before you return it. - fn cancel_if_wrong_origin<'a>(&'a self, - diag: DiagnosticBuilder<'a>, + fn cancel_if_wrong_origin(self, + diag: DiagnosticBuilder<'cx>, o: Origin) - -> DiagnosticBuilder<'a>; + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy; - fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder<'_> + fn cannot_move_when_borrowed(self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let err = struct_span_err!(self, span, E0505, "cannot move out of `{}` because it is borrowed{OGN}", @@ -83,13 +87,14 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_use_when_mutably_borrowed(&self, + fn cannot_use_when_mutably_borrowed(self, span: Span, desc: &str, borrow_span: Span, borrow_desc: &str, o: Origin) - -> DiagnosticBuilder<'_> + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, span, E0503, "cannot use `{}` because it was mutably borrowed{OGN}", @@ -101,12 +106,13 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_act_on_uninitialized_variable(&self, + fn cannot_act_on_uninitialized_variable(self, span: Span, verb: &str, desc: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let err = struct_span_err!(self, span, E0381, "{} of possibly uninitialized variable: `{}`{OGN}", @@ -114,7 +120,7 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_mutably_borrow_multiply(&self, + fn cannot_mutably_borrow_multiply(self, new_loan_span: Span, desc: &str, opt_via: &str, @@ -122,7 +128,8 @@ pub trait BorrowckErrors { old_opt_via: &str, old_load_end_span: Option, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, new_loan_span, E0499, "cannot borrow `{}`{} as mutable more than once at a time{OGN}", @@ -148,13 +155,14 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_uniquely_borrow_by_two_closures(&self, + fn cannot_uniquely_borrow_by_two_closures(self, new_loan_span: Span, desc: &str, old_loan_span: Span, old_load_end_span: Option, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, new_loan_span, E0524, "two closures require unique access to `{}` at the same time{OGN}", @@ -173,7 +181,7 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_uniquely_borrow_by_one_closure(&self, + fn cannot_uniquely_borrow_by_one_closure(self, new_loan_span: Span, desc_new: &str, opt_via: &str, @@ -182,7 +190,8 @@ pub trait BorrowckErrors { old_opt_via: &str, previous_end_span: Option, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, new_loan_span, E0500, "closure requires unique access to `{}` but {} is already borrowed{}{OGN}", @@ -197,7 +206,7 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_reborrow_already_uniquely_borrowed(&self, + fn cannot_reborrow_already_uniquely_borrowed(self, new_loan_span: Span, desc_new: &str, opt_via: &str, @@ -206,7 +215,8 @@ pub trait BorrowckErrors { old_opt_via: &str, previous_end_span: Option, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, new_loan_span, E0501, "cannot borrow `{}`{} as {} because previous closure \ @@ -222,7 +232,7 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_reborrow_already_borrowed(&self, + fn cannot_reborrow_already_borrowed(self, span: Span, desc_new: &str, msg_new: &str, @@ -233,7 +243,8 @@ pub trait BorrowckErrors { msg_old: &str, old_load_end_span: Option, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, span, E0502, "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}", @@ -246,8 +257,9 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_assign_to_borrowed(&self, span: Span, borrow_span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder + fn cannot_assign_to_borrowed(self, span: Span, borrow_span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, span, E0506, "cannot assign to `{}` because it is borrowed{OGN}", @@ -259,8 +271,9 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_move_into_closure(&self, span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder + fn cannot_move_into_closure(self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let err = struct_span_err!(self, span, E0504, "cannot move `{}` into closure because it is borrowed{OGN}", @@ -269,8 +282,9 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_reassign_immutable(&self, span: Span, desc: &str, is_arg: bool, o: Origin) - -> DiagnosticBuilder + fn cannot_reassign_immutable(self, span: Span, desc: &str, is_arg: bool, o: Origin) + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let msg = if is_arg { "to immutable argument" @@ -284,7 +298,8 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_assign(&self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder + fn cannot_assign(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let err = struct_span_err!(self, span, E0594, "cannot assign to {}{OGN}", @@ -292,14 +307,16 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_assign_static(&self, span: Span, desc: &str, o: Origin) - -> DiagnosticBuilder + fn cannot_assign_static(self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { self.cannot_assign(span, &format!("immutable static item `{}`", desc), o) } - fn cannot_move_out_of(&self, move_from_span: Span, move_from_desc: &str, o: Origin) - -> DiagnosticBuilder + fn cannot_move_out_of(self, move_from_span: Span, move_from_desc: &str, o: Origin) + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, move_from_span, E0507, "cannot move out of {}{OGN}", @@ -311,12 +328,13 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_move_out_of_interior_noncopy(&self, + fn cannot_move_out_of_interior_noncopy(self, move_from_span: Span, ty: ty::Ty, is_index: bool, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let type_name = match (&ty.sty, is_index) { (&ty::TyArray(_, _), true) => "array", @@ -332,11 +350,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_move_out_of_interior_of_drop(&self, + fn cannot_move_out_of_interior_of_drop(self, move_from_span: Span, container_ty: ty::Ty, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, move_from_span, E0509, "cannot move out of type `{}`, \ @@ -347,13 +366,14 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_act_on_moved_value(&self, + fn cannot_act_on_moved_value(self, use_span: Span, verb: &str, optional_adverb_for_moved: &str, moved_path: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let err = struct_span_err!(self, use_span, E0382, "{} of {}moved value: `{}`{OGN}", @@ -362,11 +382,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_partially_reinit_an_uninit_struct(&self, + fn cannot_partially_reinit_an_uninit_struct(self, span: Span, uninit_path: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let err = struct_span_err!(self, span, @@ -377,11 +398,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn closure_cannot_assign_to_borrowed(&self, + fn closure_cannot_assign_to_borrowed(self, span: Span, descr: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}", descr, OGN=o); @@ -389,11 +411,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_borrow_path_as_mutable(&self, + fn cannot_borrow_path_as_mutable(self, span: Span, path: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}", path, OGN=o); @@ -401,11 +424,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_borrow_across_generator_yield(&self, + fn cannot_borrow_across_generator_yield(self, span: Span, yield_span: Span, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, span, @@ -417,11 +441,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn path_does_not_live_long_enough(&self, + fn path_does_not_live_long_enough(self, span: Span, path: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}", path, OGN=o); @@ -429,11 +454,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn lifetime_too_short_for_reborrow(&self, + fn lifetime_too_short_for_reborrow(self, span: Span, path: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let err = struct_span_err!(self, span, E0598, "lifetime of {} is too short to guarantee \ @@ -443,12 +469,13 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_act_on_capture_in_sharable_fn(&self, + fn cannot_act_on_capture_in_sharable_fn(self, span: Span, bad_thing: &str, help: (Span, &str), o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let (help_span, help_msg) = help; let mut err = struct_span_err!(self, span, E0387, @@ -459,11 +486,12 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_assign_into_immutable_reference(&self, + fn cannot_assign_into_immutable_reference(self, span: Span, bad_thing: &str, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}", bad_thing, OGN=o); @@ -472,12 +500,13 @@ pub trait BorrowckErrors { self.cancel_if_wrong_origin(err, o) } - fn cannot_capture_in_long_lived_closure(&self, + fn cannot_capture_in_long_lived_closure(self, closure_span: Span, borrowed_path: &str, capture_span: Span, o: Origin) - -> DiagnosticBuilder + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { let mut err = struct_span_err!(self, closure_span, E0373, "closure may outlive the current function, \ @@ -491,28 +520,31 @@ pub trait BorrowckErrors { } } -impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> { - fn struct_span_err_with_code<'a, S: Into>(&'a self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'a> +impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> { + fn struct_span_err_with_code>(self, + sp: S, + msg: &str, + code: DiagnosticId) + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { self.sess.struct_span_err_with_code(sp, msg, code) } - fn struct_span_err<'a, S: Into>(&'a self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'a> + fn struct_span_err>(self, + sp: S, + msg: &str) + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { self.sess.struct_span_err(sp, msg) } - fn cancel_if_wrong_origin<'a>(&'a self, - mut diag: DiagnosticBuilder<'a>, - o: Origin) - -> DiagnosticBuilder<'a> + fn cancel_if_wrong_origin(self, + mut diag: DiagnosticBuilder<'cx>, + o: Origin) + -> DiagnosticBuilder<'cx> + where Self: Sized + Copy { if !o.should_emit_errors(self.borrowck_mode()) { self.sess.diagnostic().cancel(&mut diag); From c62d9eb729deec2437ad36220207cd4720452274 Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sun, 11 Mar 2018 01:03:51 +0000 Subject: [PATCH 09/41] fix formatting --- src/librustc_mir/util/borrowck_errors.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 48575584530c9..bcd7a3e7cd347 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -54,16 +54,16 @@ impl Origin { pub trait BorrowckErrors<'cx> { fn struct_span_err_with_code>(self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'cx> + sp: S, + msg: &str, + code: DiagnosticId) + -> DiagnosticBuilder<'cx> where Self: Sized + Copy; fn struct_span_err>(self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'cx> + sp: S, + msg: &str) + -> DiagnosticBuilder<'cx> where Self: Sized + Copy; /// Cancels the given error if we shouldn't emit errors for a given @@ -72,9 +72,9 @@ pub trait BorrowckErrors<'cx> { /// Always make sure that the error gets passed through this function /// before you return it. fn cancel_if_wrong_origin(self, - diag: DiagnosticBuilder<'cx>, - o: Origin) - -> DiagnosticBuilder<'cx> + diag: DiagnosticBuilder<'cx>, + o: Origin) + -> DiagnosticBuilder<'cx> where Self: Sized + Copy; fn cannot_move_when_borrowed(self, span: Span, desc: &str, o: Origin) From 50f2884dcdc0c9ba8f24b0c2014f60cb85b0e717 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Fri, 16 Mar 2018 12:43:22 -0500 Subject: [PATCH 10/41] Replace many of the last references to readmes --- src/librustc/dep_graph/README.md | 297 +----------------- src/librustc/infer/higher_ranked/mod.rs | 5 +- .../infer/lexical_region_resolve/README.md | 8 +- .../infer/region_constraints/README.md | 9 +- src/librustc/infer/region_constraints/mod.rs | 6 +- src/librustc/middle/liveness.rs | 8 +- src/librustc/middle/region.rs | 6 +- src/librustc/mir/mod.rs | 4 +- src/librustc/ty/sty.rs | 3 +- src/librustc_back/README.md | 8 +- src/librustc_borrowck/borrowck/README.md | 5 + src/librustc_driver/README.md | 6 +- src/librustc_trans/README.md | 8 +- src/libsyntax/README.md | 10 +- 14 files changed, 56 insertions(+), 327 deletions(-) diff --git a/src/librustc/dep_graph/README.md b/src/librustc/dep_graph/README.md index c8d0362f17c8e..f1f383d7ad126 100644 --- a/src/librustc/dep_graph/README.md +++ b/src/librustc/dep_graph/README.md @@ -1,295 +1,4 @@ -# Dependency graph for incremental compilation +To learn more about how dependency tracking works in rustc, see the [rustc +guide]. -This module contains the infrastructure for managing the incremental -compilation dependency graph. This README aims to explain how it ought -to be used. In this document, we'll first explain the overall -strategy, and then share some tips for handling specific scenarios. - -The high-level idea is that we want to instrument the compiler to -track which parts of the AST and other IR are read/written by what. -This way, when we come back later, we can look at this graph and -determine what work needs to be redone. - -### The dependency graph - -The nodes of the graph are defined by the enum `DepNode`. They represent -one of three things: - -1. HIR nodes (like `Hir(DefId)`) represent the HIR input itself. -2. Data nodes (like `TypeOfItem(DefId)`) represent some computed - information about a particular item. -3. Procedure nodes (like `CoherenceCheckTrait(DefId)`) represent some - procedure that is executing. Usually this procedure is - performing some kind of check for errors. You can think of them as - computed values where the value being computed is `()` (and the - value may fail to be computed, if an error results). - -An edge `N1 -> N2` is added between two nodes if either: - -- the value of `N1` is used to compute `N2`; -- `N1` is read by the procedure `N2`; -- the procedure `N1` writes the value `N2`. - -The latter two conditions are equivalent to the first one if you think -of procedures as values. - -### Basic tracking - -There is a very general strategy to ensure that you have a correct, if -sometimes overconservative, dependency graph. The two main things you have -to do are (a) identify shared state and (b) identify the current tasks. - -### Identifying shared state - -Identify "shared state" that will be written by one pass and read by -another. In particular, we need to identify shared state that will be -read "across items" -- that is, anything where changes in one item -could invalidate work done for other items. So, for example: - -1. The signature for a function is "shared state". -2. The computed type of some expression in the body of a function is - not shared state, because if it changes it does not itself - invalidate other functions (though it may be that it causes new - monomorphizations to occur, but that's handled independently). - -Put another way: if the HIR for an item changes, we are going to -recompile that item for sure. But we need the dep tracking map to tell -us what *else* we have to recompile. Shared state is anything that is -used to communicate results from one item to another. - -### Identifying the current task, tracking reads/writes, etc - -FIXME(#42293). This text needs to be rewritten for the new red-green -system, which doesn't fully exist yet. - -#### Dependency tracking map - -`DepTrackingMap` is a particularly convenient way to correctly store -shared state. A `DepTrackingMap` is a special hashmap that will add -edges automatically when `get` and `insert` are called. The idea is -that, when you get/insert a value for the key `K`, we will add an edge -from/to the node `DepNode::Variant(K)` (for some variant specific to -the map). - -Each `DepTrackingMap` is parameterized by a special type `M` that -implements `DepTrackingMapConfig`; this trait defines the key and value -types of the map, and also defines a fn for converting from the key to -a `DepNode` label. You don't usually have to muck about with this by -hand, there is a macro for creating it. You can see the complete set -of `DepTrackingMap` definitions in `librustc/middle/ty/maps.rs`. - -As an example, let's look at the `adt_defs` map. The `adt_defs` map -maps from the def-id of a struct/enum to its `AdtDef`. It is defined -using this macro: - -```rust -dep_map_ty! { AdtDefs: ItemSignature(DefId) -> ty::AdtDefMaster<'tcx> } -// ~~~~~~~ ~~~~~~~~~~~~~ ~~~~~ ~~~~~~~~~~~~~~~~~~~~~~ -// | | Key type Value type -// | DepNode variant -// Name of map id type -``` - -this indicates that a map id type `AdtDefs` will be created. The key -of the map will be a `DefId` and value will be -`ty::AdtDefMaster<'tcx>`. The `DepNode` will be created by -`DepNode::ItemSignature(K)` for a given key. - -Once that is done, you can just use the `DepTrackingMap` like any -other map: - -```rust -let mut map: DepTrackingMap = DepTrackingMap::new(dep_graph); -map.insert(key, value); // registers dep_graph.write -map.get(key; // registers dep_graph.read -``` - -#### Memoization - -One particularly interesting case is memoization. If you have some -shared state that you compute in a memoized fashion, the correct thing -to do is to define a `RefCell` for it and use the -`memoize` helper: - -```rust -map.memoize(key, || /* compute value */) -``` - -This will create a graph that looks like - - ... -> MapVariant(key) -> CurrentTask - -where `MapVariant` is the `DepNode` variant that the map is associated with, -and `...` are whatever edges the `/* compute value */` closure creates. - -In particular, using the memoize helper is much better than writing -the obvious code yourself: - -```rust -if let Some(result) = map.get(key) { - return result; -} -let value = /* compute value */; -map.insert(key, value); -``` - -If you write that code manually, the dependency graph you get will -include artificial edges that are not necessary. For example, imagine that -two tasks, A and B, both invoke the manual memoization code, but A happens -to go first. The resulting graph will be: - - ... -> A -> MapVariant(key) -> B - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // caused by A writing to MapVariant(key) - ~~~~~~~~~~~~~~~~~~~~ // caused by B reading from MapVariant(key) - -This graph is not *wrong*, but it encodes a path from A to B that -should not exist. In contrast, using the memoized helper, you get: - - ... -> MapVariant(key) -> A - | - +----------> B - -which is much cleaner. - -**Be aware though that the closure is executed with `MapVariant(key)` -pushed onto the stack as the current task!** That means that you must -add explicit `read` calls for any shared state that it accesses -implicitly from its environment. See the section on "explicit calls to -read and write when starting a new subtask" above for more details. - -### How to decide where to introduce a new task - -Certainly, you need at least one task on the stack: any attempt to -`read` or `write` shared state will panic if there is no current -task. But where does it make sense to introduce subtasks? The basic -rule is that a subtask makes sense for any discrete unit of work you -may want to skip in the future. Adding a subtask separates out the -reads/writes from *that particular subtask* versus the larger -context. An example: you might have a 'meta' task for all of borrow -checking, and then subtasks for borrow checking individual fns. (Seen -in this light, memoized computations are just a special case where we -may want to avoid redoing the work even within the context of one -compilation.) - -The other case where you might want a subtask is to help with refining -the reads/writes for some later bit of work that needs to be memoized. -For example, we create a subtask for type-checking the body of each -fn. However, in the initial version of incr. comp. at least, we do -not expect to actually *SKIP* type-checking -- we only expect to skip -trans. However, it's still useful to create subtasks for type-checking -individual items, because, otherwise, if a fn sig changes, we won't -know which callers are affected -- in fact, because the graph would be -so coarse, we'd just have to retrans everything, since we can't -distinguish which fns used which fn sigs. - -### Testing the dependency graph - -There are various ways to write tests against the dependency graph. -The simplest mechanism are the -`#[rustc_if_this_changed]` and `#[rustc_then_this_would_need]` -annotations. These are used in compile-fail tests to test whether the -expected set of paths exist in the dependency graph. As an example, -see `src/test/compile-fail/dep-graph-caller-callee.rs`. - -The idea is that you can annotate a test like: - -```rust -#[rustc_if_this_changed] -fn foo() { } - -#[rustc_then_this_would_need(TypeckTables)] //~ ERROR OK -fn bar() { foo(); } - -#[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path -fn baz() { } -``` - -This will check whether there is a path in the dependency graph from -`Hir(foo)` to `TypeckTables(bar)`. An error is reported for each -`#[rustc_then_this_would_need]` annotation that indicates whether a -path exists. `//~ ERROR` annotations can then be used to test if a -path is found (as demonstrated above). - -### Debugging the dependency graph - -#### Dumping the graph - -The compiler is also capable of dumping the dependency graph for your -debugging pleasure. To do so, pass the `-Z dump-dep-graph` flag. The -graph will be dumped to `dep_graph.{txt,dot}` in the current -directory. You can override the filename with the `RUST_DEP_GRAPH` -environment variable. - -Frequently, though, the full dep graph is quite overwhelming and not -particularly helpful. Therefore, the compiler also allows you to filter -the graph. You can filter in three ways: - -1. All edges originating in a particular set of nodes (usually a single node). -2. All edges reaching a particular set of nodes. -3. All edges that lie between given start and end nodes. - -To filter, use the `RUST_DEP_GRAPH_FILTER` environment variable, which should -look like one of the following: - -``` -source_filter // nodes originating from source_filter --> target_filter // nodes that can reach target_filter -source_filter -> target_filter // nodes in between source_filter and target_filter -``` - -`source_filter` and `target_filter` are a `&`-separated list of strings. -A node is considered to match a filter if all of those strings appear in its -label. So, for example: - -``` -RUST_DEP_GRAPH_FILTER='-> TypeckTables' -``` - -would select the predecessors of all `TypeckTables` nodes. Usually though you -want the `TypeckTables` node for some particular fn, so you might write: - -``` -RUST_DEP_GRAPH_FILTER='-> TypeckTables & bar' -``` - -This will select only the `TypeckTables` nodes for fns with `bar` in their name. - -Perhaps you are finding that when you change `foo` you need to re-type-check `bar`, -but you don't think you should have to. In that case, you might do: - -``` -RUST_DEP_GRAPH_FILTER='Hir&foo -> TypeckTables & bar' -``` - -This will dump out all the nodes that lead from `Hir(foo)` to -`TypeckTables(bar)`, from which you can (hopefully) see the source -of the erroneous edge. - -#### Tracking down incorrect edges - -Sometimes, after you dump the dependency graph, you will find some -path that should not exist, but you will not be quite sure how it came -to be. **When the compiler is built with debug assertions,** it can -help you track that down. Simply set the `RUST_FORBID_DEP_GRAPH_EDGE` -environment variable to a filter. Every edge created in the dep-graph -will be tested against that filter -- if it matches, a `bug!` is -reported, so you can easily see the backtrace (`RUST_BACKTRACE=1`). - -The syntax for these filters is the same as described in the previous -section. However, note that this filter is applied to every **edge** -and doesn't handle longer paths in the graph, unlike the previous -section. - -Example: - -You find that there is a path from the `Hir` of `foo` to the type -check of `bar` and you don't think there should be. You dump the -dep-graph as described in the previous section and open `dep-graph.txt` -to see something like: - - Hir(foo) -> Collect(bar) - Collect(bar) -> TypeckTables(bar) - -That first edge looks suspicious to you. So you set -`RUST_FORBID_DEP_GRAPH_EDGE` to `Hir&foo -> Collect&bar`, re-run, and -then observe the backtrace. Voila, bug fixed! +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/query.html diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index a317e0699b4bb..d44f2ec95492f 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -580,7 +580,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// the pop occurs as part of the rollback, so an explicit call is not /// needed (but is also permitted). /// - /// See `README.md` for more details. + /// For more information about how skolemization for HRTBs works, see + /// the [rustc guide]. + /// + /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html pub fn skolemize_late_bound_regions(&self, binder: &ty::Binder, snapshot: &CombinedSnapshot<'a, 'tcx>) diff --git a/src/librustc/infer/lexical_region_resolve/README.md b/src/librustc/infer/lexical_region_resolve/README.md index a90230870a6c0..0086aed3e7c97 100644 --- a/src/librustc/infer/lexical_region_resolve/README.md +++ b/src/librustc/infer/lexical_region_resolve/README.md @@ -1,14 +1,16 @@ # Region inference +> WARNING: This README is obsolete and will be removed soon! For +> more info on how the current borrowck works, see the [rustc guide]. + +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html + ## Terminology Note that we use the terms region and lifetime interchangeably. ## Introduction -See the [general inference README](../README.md) for an overview of -how lexical-region-solving fits into the bigger picture. - Region inference uses a somewhat more involved algorithm than type inference. It is not the most efficient thing ever written though it seems to work well enough in practice (famous last words). The reason diff --git a/src/librustc/infer/region_constraints/README.md b/src/librustc/infer/region_constraints/README.md index 95f9c8c835398..07b87e2012dde 100644 --- a/src/librustc/infer/region_constraints/README.md +++ b/src/librustc/infer/region_constraints/README.md @@ -1,18 +1,25 @@ # Region constraint collection +> WARNING: This README is obsolete and will be removed soon! For +> more info on how the current borrowck works, see the [rustc guide]. + +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html + ## Terminology Note that we use the terms region and lifetime interchangeably. ## Introduction -As described in the [inference README](../README.md), and unlike +As described in the rustc guide [chapter on type inference][ti], and unlike normal type inference, which is similar in spirit to H-M and thus works progressively, the region type inference works by accumulating constraints over the course of a function. Finally, at the end of processing a function, we process and solve the constraints all at once. +[ti]: https://rust-lang-nursery.github.io/rustc-guide/type-inference.html + The constraints are always of one of three possible forms: - `ConstrainVarSubVar(Ri, Rj)` states that region variable Ri must be diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 0c8e49fda1840..e864485539b2d 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -468,8 +468,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> { /// the APIs in `higher_ranked/mod.rs`, such as /// `skolemize_late_bound_regions` and `plug_leaks`, which will /// guide you on this path (ensure that the `SkolemizationMap` is - /// consumed and you are good). There are also somewhat extensive - /// comments in `higher_ranked/README.md`. + /// consumed and you are good). For more info on how skolemization + /// for HRTBs works, see the [rustc guide]. + /// + /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html /// /// The `snapshot` argument to this function is not really used; /// it's just there to make it explicit which snapshot bounds the diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index d13b16dce8986..966353b53a95a 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -402,12 +402,10 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) { fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { for pat in &arm.pats { - // for struct patterns, take note of which fields used shorthand (`x` - // rather than `x: x`) + // for struct patterns, take note of which fields used shorthand (`x` rather than `x: x`) // - // FIXME: according to the rust-lang-nursery/rustc-guide book and - // librustc/README.md, `NodeId`s are to be phased out in favor of - // `HirId`s; however, we need to match the signature of `each_binding`, + // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be phased + // out in favor of `HirId`s; however, we need to match the signature of `each_binding`, // which uses `NodeIds`. let mut shorthand_field_ids = NodeSet(); if let hir::PatKind::Struct(_, ref fields, _) = pat.node { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index c73930553cdea..c7396b34c4689 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -11,8 +11,10 @@ //! This file builds up the `ScopeTree`, which describes //! the parent links in the region hierarchy. //! -//! Most of the documentation on regions can be found in -//! `middle/infer/region_constraints/README.md` +//! For more information about how MIR-based region-checking works, +//! see the [rustc guide]. +//! +//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html use ich::{StableHashingContext, NodeIdHashingMode}; use util::nodemap::{FxHashMap, FxHashSet}; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 939710ffd2b86..64a1729982a31 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -8,9 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! MIR datatypes and passes. See the module-level [README] for details. +//! MIR datatypes and passes. See the [rustc guide] for more info. //! -//! [README]: https://github.com/rust-lang/rust/blob/master/src/librustc/mir/README.md +//! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html use graphviz::IntoCow; use middle::const_val::ConstVal; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index ae053d7f4f58d..bb5c7b5fd2a5e 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -991,10 +991,11 @@ pub type Region<'tcx> = &'tcx RegionKind; /// the inference variable is supposed to satisfy the relation /// *for every value of the skolemized region*. To ensure that doesn't /// happen, you can use `leak_check`. This is more clearly explained -/// by infer/higher_ranked/README.md. +/// by the [rustc guide]. /// /// [1]: http://smallcultfollowing.com/babysteps/blog/2013/10/29/intermingled-parameter-lists/ /// [2]: http://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ +/// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html #[derive(Clone, PartialEq, Eq, Hash, Copy, RustcEncodable, RustcDecodable, PartialOrd, Ord)] pub enum RegionKind { // Region bound in a type or fn declaration which will be diff --git a/src/librustc_back/README.md b/src/librustc_back/README.md index bd99c687bb6ad..3c01692c12b3c 100644 --- a/src/librustc_back/README.md +++ b/src/librustc_back/README.md @@ -1,6 +1,6 @@ -NB: This crate is part of the Rust compiler. For an overview of the -compiler as a whole, see -[the README.md file found in `librustc`](../librustc/README.md). - `librustc_back` contains some very low-level details that are specific to different LLVM targets and so forth. + +For more information about how trans works, see the [rustc guide]. + +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html diff --git a/src/librustc_borrowck/borrowck/README.md b/src/librustc_borrowck/borrowck/README.md index da2b1ef0b1c02..29f03c06ab759 100644 --- a/src/librustc_borrowck/borrowck/README.md +++ b/src/librustc_borrowck/borrowck/README.md @@ -1,5 +1,10 @@ % The Borrow Checker +> WARNING: This README is more or less obsolete, and will be removed +> soon! The new system is described in the [rustc guide]. + +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir-borrowck.html + This pass has the job of enforcing memory safety. This is a subtle topic. This docs aim to explain both the practice and the theory behind the borrow checker. They start with a high-level overview of diff --git a/src/librustc_driver/README.md b/src/librustc_driver/README.md index 839d1831f9544..fef249a9e4eb8 100644 --- a/src/librustc_driver/README.md +++ b/src/librustc_driver/README.md @@ -1,7 +1,3 @@ -NB: This crate is part of the Rust compiler. For an overview of the -compiler as a whole, see -[the README.md file found in `librustc`](../librustc/README.md). - The `driver` crate is effectively the "main" function for the rust compiler. It orchestrates the compilation process and "knits together" the code from the other crates within rustc. This crate itself does @@ -9,4 +5,6 @@ not contain any of the "main logic" of the compiler (though it does have some code related to pretty printing or other minor compiler options). +For more information about how the driver works, see the [rustc guide]. +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/rustc-driver.html diff --git a/src/librustc_trans/README.md b/src/librustc_trans/README.md index b69d632a6a0df..d1868ba2abb17 100644 --- a/src/librustc_trans/README.md +++ b/src/librustc_trans/README.md @@ -1,7 +1,7 @@ -NB: This crate is part of the Rust compiler. For an overview of the -compiler as a whole, see -[the README.md file found in `librustc`](../librustc/README.md). - The `trans` crate contains the code to convert from MIR into LLVM IR, and then from LLVM IR into machine code. In general it contains code that runs towards the end of the compilation process. + +For more information about how trans works, see the [rustc guide]. + +[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html diff --git a/src/libsyntax/README.md b/src/libsyntax/README.md index 3bf735ee86803..7214203830e74 100644 --- a/src/libsyntax/README.md +++ b/src/libsyntax/README.md @@ -1,7 +1,9 @@ -NB: This crate is part of the Rust compiler. For an overview of the -compiler as a whole, see -[the README.md file found in `librustc`](../librustc/README.md). - The `syntax` crate contains those things concerned purely with syntax – that is, the AST ("abstract syntax tree"), parser, pretty-printer, lexer, macro expander, and utilities for traversing ASTs. + +For more information about how these things work in rustc, see the +rustc guide: + +- [Parsing](https://rust-lang-nursery.github.io/rustc-guide/the-parser.html) +- [Macro Expansion](https://rust-lang-nursery.github.io/rustc-guide/macro-expansion.html) From b910d6b93cdbe075b157621432d271e6afcaa20f Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Sat, 17 Mar 2018 09:45:03 +0900 Subject: [PATCH 11/41] Use associated consts for GenericRadix base and prefix --- src/libcore/fmt/num.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 2992e7cf8db34..6378358c2ddcf 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -49,15 +49,13 @@ doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } #[doc(hidden)] trait GenericRadix { /// The number of digits. - fn base(&self) -> u8; + const BASE: u8; /// A radix-specific prefix string. - fn prefix(&self) -> &'static str { - "" - } + const PREFIX: &'static str; /// Converts an integer to corresponding radix digit. - fn digit(&self, x: u8) -> u8; + fn digit(x: u8) -> u8; /// Format an integer using the radix using a formatter. fn fmt_int(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result { @@ -67,14 +65,14 @@ trait GenericRadix { let is_nonnegative = x >= zero; let mut buf = [0; 128]; let mut curr = buf.len(); - let base = T::from_u8(self.base()); + let base = T::from_u8(Self::BASE); if is_nonnegative { // Accumulate each digit of the number from the least significant // to the most significant figure. for byte in buf.iter_mut().rev() { - let n = x % base; // Get the current place value. - x = x / base; // Deaccumulate the number. - *byte = self.digit(n.to_u8()); // Store the digit in the buffer. + let n = x % base; // Get the current place value. + x = x / base; // Deaccumulate the number. + *byte = Self::digit(n.to_u8()); // Store the digit in the buffer. curr -= 1; if x == zero { // No more digits left to accumulate. @@ -84,9 +82,9 @@ trait GenericRadix { } else { // Do the same as above, but accounting for two's complement. for byte in buf.iter_mut().rev() { - let n = zero - (x % base); // Get the current place value. - x = x / base; // Deaccumulate the number. - *byte = self.digit(n.to_u8()); // Store the digit in the buffer. + let n = zero - (x % base); // Get the current place value. + x = x / base; // Deaccumulate the number. + *byte = Self::digit(n.to_u8()); // Store the digit in the buffer. curr -= 1; if x == zero { // No more digits left to accumulate. @@ -95,7 +93,7 @@ trait GenericRadix { } } let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) }; - f.pad_integral(is_nonnegative, self.prefix(), buf) + f.pad_integral(is_nonnegative, Self::PREFIX, buf) } } @@ -122,12 +120,12 @@ struct UpperHex; macro_rules! radix { ($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => { impl GenericRadix for $T { - fn base(&self) -> u8 { $base } - fn prefix(&self) -> &'static str { $prefix } - fn digit(&self, x: u8) -> u8 { + const BASE: u8 = $base; + const PREFIX: &'static str = $prefix; + fn digit(x: u8) -> u8 { match x { $($x => $conv,)+ - x => panic!("number not in the range 0..{}: {}", self.base() - 1, x), + x => panic!("number not in the range 0..{}: {}", Self::BASE - 1, x), } } } From 5bef034b198c58fd02a9e8a584a24fd516dc969c Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Sat, 17 Mar 2018 14:05:24 +0100 Subject: [PATCH 12/41] Bring back the phrase 'borrowing as' for what Borrow does. --- src/libcore/borrow.rs | 47 ++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index c0f1989f87944..0014bddb55cd7 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -12,7 +12,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -/// A trait identifying how borrowed data behaves. +/// A trait for borrowing data. /// /// In Rust, it is common to provide different representations of a type for /// different use cases. For instance, storage location and management for a @@ -24,40 +24,37 @@ /// [`str`]. This requires keeping additional information unnecessary for a /// simple, immutable string. /// -/// These types signal that they are a specialized representation of a basic -/// type `T` by implementing `Borrow`. The method `borrow` provides a way -/// to convert a reference to the type into a reference to this basic type -/// `T`. +/// These types provide access to the underlying data through references +/// to the type of that data. They are said to be ‘borrowed as’ that type. +/// For instance, a [`Box`] can be borrowed as `T` while a [`String`] +/// can be borrowed as `str`. +/// +/// Types express that they can be borrowed as some type `T` by implementing +/// `Borrow`, providing a reference to a `T` in the trait’s +/// [`borrow`] method. A type is free to borrow as several different types. +/// If it wishes to mutably borrow as the type – allowing the underlying data +/// to be modified, it can additionally implement [`BorrowMut`]. /// /// Further, when providing implementations for additional traits, it needs /// to be considered whether they should behave identical to those of the /// underlying type as a consequence of acting as a representation of that -/// underlying type. -/// -/// Generic code typically uses `Borrow` when it not only needs access -/// to a reference of the underlying type but relies on the identical -/// behavior of these additional trait implementations. These traits are -/// likely to appear as additional trait bounds. +/// underlying type. Generic code typically uses `Borrow` when it relies +/// on the identical behavior of these additional trait implementations. +/// These traits will likely appear as additional trait bounds. /// /// If generic code merely needs to work for all types that can /// provide a reference to related type `T`, it is often better to use /// [`AsRef`] as more types can safely implement it. /// -/// If a type implementing `Borrow` also wishes to allow mutable access -/// to the underlying type `T`, it can do so by implementing the companion -/// trait [`BorrowMut`]. -/// -/// Note also that it is perfectly fine for a single type to have multiple -/// implementations of `Borrow` for different `T`s. In fact, a blanket -/// implementation lets every type be at least a borrow of itself. -/// /// [`AsRef`]: ../../std/convert/trait.AsRef.html -/// [`BorrowMut`]: trait.BorrowMut.html +/// [`BorrowMut`]: trait.BorrowMut.html /// [`Box`]: ../../std/boxed/struct.Box.html /// [`Mutex`]: ../../std/sync/struct.Mutex.html /// [`Rc`]: ../../std/rc/struct.Rc.html /// [`str`]: ../../std/primitive.str.html /// [`String`]: ../../std/string/struct.String.html +/// [`borrow`]: #tymethod.borrow +/// /// /// # Examples /// @@ -113,10 +110,10 @@ /// `str` is available. /// /// Instead, the `get` method is generic over the type of the underlying key -/// data, called `Q` in the method signature above. It states that `K` is a -/// representation of `Q` by requiring that `K: Borrow`. By additionally -/// requiring `Q: Hash + Eq`, it demands that `K` and `Q` have -/// implementations of the `Hash` and `Eq` traits that produce identical +/// data, called `Q` in the method signature above. It states that `K` +/// borrows as a `Q` by requiring that `K: Borrow`. By additionally +/// requiring `Q: Hash + Eq`, it signals the requirement that `K` and `Q` +/// have implementations of the `Hash` and `Eq` traits that produce identical /// results. /// /// The implementation of `get` relies in particular on identical @@ -141,7 +138,7 @@ /// ``` /// /// Because two equal values need to produce the same hash value, the -/// implementation of `Hash` needs to reflect that, too: +/// implementation of `Hash` needs to ignore ASCII case, too: /// /// ``` /// # use std::hash::{Hash, Hasher}; From d664b8954e83e74870a90b871161942d6e827aa6 Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Sat, 17 Mar 2018 14:09:45 +0100 Subject: [PATCH 13/41] Rewrite the documentation for BorrowMut. --- src/libcore/borrow.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 0014bddb55cd7..7470512e2b2d7 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -191,7 +191,11 @@ pub trait Borrow { /// A trait for mutably borrowing data. /// -/// Similar to `Borrow`, but for mutable borrows. +/// As a companion to [`Borrow`] this trait allows a type to borrow as +/// an underlying type by providing a mutable reference. See [`Borrow`] +/// for more information on borrowing as another type. +/// +/// [`Borrow`]: trait.Borrow.html #[stable(feature = "rust1", since = "1.0.0")] pub trait BorrowMut : Borrow { /// Mutably borrows from an owned value. From 9f5a356c1d01e971b1fe33f7afb2b81d0eec2b1c Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Sat, 17 Mar 2018 13:46:45 +0800 Subject: [PATCH 14/41] improve attribute trailing semicolon error --- src/libsyntax/parse/attr.rs | 11 +---------- src/test/ui/issue-49040.rs | 12 ++++++++++++ src/test/ui/issue-49040.stderr | 8 ++++++++ 3 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/issue-49040.rs create mode 100644 src/test/ui/issue-49040.stderr diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 053746b579dcb..4c3f42d9c6b7d 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -90,7 +90,7 @@ impl<'a> Parser<'a> { debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}", inner_parse_policy, self.token); - let (span, path, tokens, mut style) = match self.token { + let (span, path, tokens, style) = match self.token { token::Pound => { let lo = self.span; self.bump(); @@ -129,15 +129,6 @@ impl<'a> Parser<'a> { } }; - if inner_parse_policy == InnerAttributeParsePolicy::Permitted && - self.token == token::Semi { - self.bump(); - self.span_warn(span, - "this inner attribute syntax is deprecated. The new syntax is \ - `#![foo]`, with a bang and no semicolon"); - style = ast::AttrStyle::Inner; - } - Ok(ast::Attribute { id: attr::mk_attr_id(), style, diff --git a/src/test/ui/issue-49040.rs b/src/test/ui/issue-49040.rs new file mode 100644 index 0000000000000..866ecd9e1d951 --- /dev/null +++ b/src/test/ui/issue-49040.rs @@ -0,0 +1,12 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unused_variables)]; //~ ERROR expected item, found `;` +fn main() {} diff --git a/src/test/ui/issue-49040.stderr b/src/test/ui/issue-49040.stderr new file mode 100644 index 0000000000000..b6f624dac7db6 --- /dev/null +++ b/src/test/ui/issue-49040.stderr @@ -0,0 +1,8 @@ +error: expected item, found `;` + --> $DIR/issue-49040.rs:11:28 + | +LL | #![allow(unused_variables)]; //~ ERROR expected item, found `;` + | ^ help: consider removing this semicolon + +error: aborting due to previous error + From fab7020bd95c695be4f3c06dce236fada0dabb8e Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Fri, 9 Feb 2018 19:04:12 +0100 Subject: [PATCH 15/41] Add span_suggestion while removing TyRefs based on the snippet String. --- src/librustc/traits/error_reporting.rs | 87 ++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 7e5dc02798dff..c90a6d0709db6 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -575,6 +575,44 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { = self.on_unimplemented_note(trait_ref, obligation); let have_alt_message = message.is_some() || label.is_some(); + // { + // let ty::Binder(trait_ref) = trait_ref; + // println!("TraitRef: {:?}", trait_ref); + // println!("TraitRef: id:{:?}; subst:{:?}", trait_ref.def_id, trait_ref.substs); + + // if let ty::Predicate::Trait(trait_predicate_binder) = + // trait_ref.to_predicate() { + // let trait_predicate = trait_predicate_binder.skip_binder(); + // println!("TraitPredicateBinder: {:?}", trait_predicate_binder); + // println!("TraitPredicate: {:?}", trait_predicate); + + // let trait_ty = trait_ref.self_ty(); + // println!("TraitPredicateTy: {:?}", trait_ty); + // println!("TraitPredicateTy: sty:{:?}; flags{:?}", trait_ty.sty, trait_ty.flags); + // } + + // for in_ty in trait_ref.input_types() { + // println!("\t- {:?}", in_ty); + // println!("\t\t- sty:{:?}; flags:{:?}", in_ty.sty, in_ty.flags); + // } + + // println!("Message: {:?}", message); + // println!("Label: {:?}", label); + // println!("Obligation: {:?}", obligation); + // println!("Span: {:?}", self.tcx.sess.codemap().span_to_string(span)); + + // let body_id = obligation.cause.body_id; + // println!("BodyId: {:?}", body_id); + // println!("BodyIdSpan: {:?}", self.tcx.hir.span(body_id)); + + // match self.tcx.hir.find(body_id) { + // Some(node) => println!("Node: {:?}", node), + // None => println!("Node not found."), + // } + + // println!("=------------------------------="); + // } + let mut err = struct_span_err!( self.tcx.sess, span, @@ -606,6 +644,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err); + self.suggest_remove_reference(&obligation, &mut err, &trait_ref); // Try to report a help message if !trait_ref.has_infer_types() && @@ -844,6 +883,54 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } + fn suggest_remove_reference(&self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>) { + let ty::Binder(trait_ref) = trait_ref; + + let span = obligation.cause.span; + let mut snippet = match self.tcx.sess.codemap().span_to_snippet(span) { + Ok(s) => s, + Err(_) => String::from(""), + }; + + let mut refs_number = 0; + + for c in snippet.chars() { + if c == '&' { + refs_number += 1; + } + } + + let mut refs_remaining = refs_number; + let mut trait_type = trait_ref.self_ty(); + let mut selcx = SelectionContext::new(self); + + while refs_remaining > 0 { + if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) = + trait_type.sty { + trait_type = t_type; + refs_remaining -= 1; + + let substs = self.tcx.mk_substs_trait(trait_type, &[]); + let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs); + let new_obligation = Obligation::new(ObligationCause::dummy(), + obligation.param_env, + new_trait_ref.to_predicate()); + + if selcx.evaluate_obligation(&new_obligation) { + for i in 0..refs_number { + snippet.remove(i); + } + err.span_suggestion(span, "consider removing `&`s like", format!("{}", snippet)); + } + } else { + break; + } + } + } + /// Given some node representing a fn-like thing in the HIR map, /// returns a span and `ArgKind` information that describes the /// arguments it expects. This can be supplied to From 1e73c1d39f0734d2ae687b9cad5f5bde2f96d0b8 Mon Sep 17 00:00:00 2001 From: Maxim Nazarenko Date: Sun, 18 Mar 2018 03:05:00 +0200 Subject: [PATCH 16/41] rustbuild: Ship libsynchronization Ship libsynchronization from MinGW --- src/bootstrap/dist.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index dcb572416594e..eca06eac7f307 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -221,6 +221,7 @@ fn make_win_dist( "libsecur32.a", "libsetupapi.a", "libshell32.a", + "libsynchronization.a", "libuser32.a", "libuserenv.a", "libuuid.a", From 13d94d666e037162808174f0bedbd5db9d65c7fe Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Sun, 18 Mar 2018 13:05:00 +0100 Subject: [PATCH 17/41] Fix formatting. --- src/libcore/borrow.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs index 7470512e2b2d7..f45a32d4b94ac 100644 --- a/src/libcore/borrow.rs +++ b/src/libcore/borrow.rs @@ -55,7 +55,6 @@ /// [`String`]: ../../std/string/struct.String.html /// [`borrow`]: #tymethod.borrow /// -/// /// # Examples /// /// As a data collection, [`HashMap`] owns both keys and values. If @@ -163,7 +162,6 @@ /// [`HashMap`]: ../../std/collections/struct.HashMap.html /// [`String`]: ../../std/string/struct.String.html /// [`str`]: ../../std/primitive.str.html -/// #[stable(feature = "rust1", since = "1.0.0")] pub trait Borrow { /// Immutably borrows from an owned value. From 55116243e708201918f4f8bc20182754b00f32fa Mon Sep 17 00:00:00 2001 From: csmoe <35686186+csmoe@users.noreply.github.com> Date: Thu, 15 Mar 2018 18:39:44 +0800 Subject: [PATCH 18/41] remove unneeded where clause --- src/librustc_mir/util/borrowck_errors.rs | 40 +++--------------------- 1 file changed, 4 insertions(+), 36 deletions(-) diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index bcd7a3e7cd347..5e15348de5e71 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -52,19 +52,17 @@ impl Origin { } } -pub trait BorrowckErrors<'cx> { +pub trait BorrowckErrors<'cx>: Sized + Copy { fn struct_span_err_with_code>(self, sp: S, msg: &str, code: DiagnosticId) - -> DiagnosticBuilder<'cx> - where Self: Sized + Copy; + -> DiagnosticBuilder<'cx>; fn struct_span_err>(self, sp: S, msg: &str) - -> DiagnosticBuilder<'cx> - where Self: Sized + Copy; + -> DiagnosticBuilder<'cx>; /// Cancels the given error if we shouldn't emit errors for a given /// origin in the current mode. @@ -74,12 +72,10 @@ pub trait BorrowckErrors<'cx> { fn cancel_if_wrong_origin(self, diag: DiagnosticBuilder<'cx>, o: Origin) - -> DiagnosticBuilder<'cx> - where Self: Sized + Copy; + -> DiagnosticBuilder<'cx>; fn cannot_move_when_borrowed(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let err = struct_span_err!(self, span, E0505, "cannot move out of `{}` because it is borrowed{OGN}", @@ -94,7 +90,6 @@ pub trait BorrowckErrors<'cx> { borrow_desc: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, span, E0503, "cannot use `{}` because it was mutably borrowed{OGN}", @@ -112,7 +107,6 @@ pub trait BorrowckErrors<'cx> { desc: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let err = struct_span_err!(self, span, E0381, "{} of possibly uninitialized variable: `{}`{OGN}", @@ -129,7 +123,6 @@ pub trait BorrowckErrors<'cx> { old_load_end_span: Option, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, new_loan_span, E0499, "cannot borrow `{}`{} as mutable more than once at a time{OGN}", @@ -162,7 +155,6 @@ pub trait BorrowckErrors<'cx> { old_load_end_span: Option, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, new_loan_span, E0524, "two closures require unique access to `{}` at the same time{OGN}", @@ -191,7 +183,6 @@ pub trait BorrowckErrors<'cx> { previous_end_span: Option, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, new_loan_span, E0500, "closure requires unique access to `{}` but {} is already borrowed{}{OGN}", @@ -216,7 +207,6 @@ pub trait BorrowckErrors<'cx> { previous_end_span: Option, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, new_loan_span, E0501, "cannot borrow `{}`{} as {} because previous closure \ @@ -244,7 +234,6 @@ pub trait BorrowckErrors<'cx> { old_load_end_span: Option, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, span, E0502, "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}", @@ -259,7 +248,6 @@ pub trait BorrowckErrors<'cx> { fn cannot_assign_to_borrowed(self, span: Span, borrow_span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, span, E0506, "cannot assign to `{}` because it is borrowed{OGN}", @@ -273,7 +261,6 @@ pub trait BorrowckErrors<'cx> { fn cannot_move_into_closure(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let err = struct_span_err!(self, span, E0504, "cannot move `{}` into closure because it is borrowed{OGN}", @@ -284,7 +271,6 @@ pub trait BorrowckErrors<'cx> { fn cannot_reassign_immutable(self, span: Span, desc: &str, is_arg: bool, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let msg = if is_arg { "to immutable argument" @@ -299,7 +285,6 @@ pub trait BorrowckErrors<'cx> { } fn cannot_assign(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let err = struct_span_err!(self, span, E0594, "cannot assign to {}{OGN}", @@ -309,14 +294,12 @@ pub trait BorrowckErrors<'cx> { fn cannot_assign_static(self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { self.cannot_assign(span, &format!("immutable static item `{}`", desc), o) } fn cannot_move_out_of(self, move_from_span: Span, move_from_desc: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, move_from_span, E0507, "cannot move out of {}{OGN}", @@ -334,7 +317,6 @@ pub trait BorrowckErrors<'cx> { is_index: bool, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let type_name = match (&ty.sty, is_index) { (&ty::TyArray(_, _), true) => "array", @@ -355,7 +337,6 @@ pub trait BorrowckErrors<'cx> { container_ty: ty::Ty, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, move_from_span, E0509, "cannot move out of type `{}`, \ @@ -373,7 +354,6 @@ pub trait BorrowckErrors<'cx> { moved_path: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let err = struct_span_err!(self, use_span, E0382, "{} of {}moved value: `{}`{OGN}", @@ -387,7 +367,6 @@ pub trait BorrowckErrors<'cx> { uninit_path: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let err = struct_span_err!(self, span, @@ -403,7 +382,6 @@ pub trait BorrowckErrors<'cx> { descr: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}", descr, OGN=o); @@ -416,7 +394,6 @@ pub trait BorrowckErrors<'cx> { path: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}", path, OGN=o); @@ -429,7 +406,6 @@ pub trait BorrowckErrors<'cx> { yield_span: Span, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, span, @@ -446,7 +422,6 @@ pub trait BorrowckErrors<'cx> { path: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}", path, OGN=o); @@ -459,7 +434,6 @@ pub trait BorrowckErrors<'cx> { path: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let err = struct_span_err!(self, span, E0598, "lifetime of {} is too short to guarantee \ @@ -475,7 +449,6 @@ pub trait BorrowckErrors<'cx> { help: (Span, &str), o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let (help_span, help_msg) = help; let mut err = struct_span_err!(self, span, E0387, @@ -491,7 +464,6 @@ pub trait BorrowckErrors<'cx> { bad_thing: &str, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}", bad_thing, OGN=o); @@ -506,7 +478,6 @@ pub trait BorrowckErrors<'cx> { capture_span: Span, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { let mut err = struct_span_err!(self, closure_span, E0373, "closure may outlive the current function, \ @@ -526,7 +497,6 @@ impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> { msg: &str, code: DiagnosticId) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { self.sess.struct_span_err_with_code(sp, msg, code) } @@ -535,7 +505,6 @@ impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> { sp: S, msg: &str) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { self.sess.struct_span_err(sp, msg) } @@ -544,7 +513,6 @@ impl<'cx, 'gcx, 'tcx> BorrowckErrors<'cx> for TyCtxt<'cx, 'gcx, 'tcx> { mut diag: DiagnosticBuilder<'cx>, o: Origin) -> DiagnosticBuilder<'cx> - where Self: Sized + Copy { if !o.should_emit_errors(self.borrowck_mode()) { self.sess.diagnostic().cancel(&mut diag); From 5581aa8eebba270cde4e95d2e2b7f08163ae7319 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 18 Mar 2018 16:32:41 +0100 Subject: [PATCH 19/41] Fix events handling in rustdoc --- src/librustdoc/html/static/main.js | 73 ++++++++++++++++-------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 28d39cb174a10..21c1d9d670d65 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -239,52 +239,59 @@ } } - function handleShortcut(ev) { - if (document.activeElement.tagName === "INPUT" && - hasClass(document.getElementById('main'), "hidden")) { - return; + function handleEscape(ev, help) { + hideModal(); + var search = document.getElementById("search"); + if (!hasClass(help, "hidden")) { + displayHelp(false, ev); + } else if (!hasClass(search, "hidden")) { + ev.preventDefault(); + addClass(search, "hidden"); + removeClass(document.getElementById("main"), "hidden"); } + defocusSearchBar(); + } + function handleShortcut(ev) { // Don't interfere with browser shortcuts if (ev.ctrlKey || ev.altKey || ev.metaKey) { return; } var help = document.getElementById("help"); - switch (getVirtualKey(ev)) { - case "Escape": - hideModal(); - var search = document.getElementById("search"); - if (!hasClass(help, "hidden")) { - displayHelp(false, ev); - } else if (!hasClass(search, "hidden")) { - ev.preventDefault(); - addClass(search, "hidden"); - removeClass(document.getElementById("main"), "hidden"); + if (document.activeElement.tagName === "INPUT") { + switch (getVirtualKey(ev)) { + case "Escape": + handleEscape(ev, help); + break; } - defocusSearchBar(); - break; + } else { + switch (getVirtualKey(ev)) { + case "Escape": + handleEscape(ev, help); + break; - case "s": - case "S": - displayHelp(false, ev); - hideModal(); - ev.preventDefault(); - focusSearchBar(); - break; + case "s": + case "S": + displayHelp(false, ev); + hideModal(); + ev.preventDefault(); + focusSearchBar(); + break; - case "+": - case "-": - ev.preventDefault(); - toggleAllDocs(); - break; + case "+": + case "-": + ev.preventDefault(); + toggleAllDocs(); + break; - case "?": - if (ev.shiftKey) { - hideModal(); - displayHelp(true, ev); + case "?": + if (ev.shiftKey) { + hideModal(); + displayHelp(true, ev); + } + break; } - break; } } From 16da5d4bb2d65a4d533d1da2a4e0d288d3a474c5 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 18 Mar 2018 09:18:18 -0700 Subject: [PATCH 20/41] Add BufReader::buffer This subsumes the need for an explicit is_empty function, and provides access to the buffered data itself which has been requested from time to time. --- src/libstd/io/buffered.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 9250c1c437b2a..ccaa19acc8379 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -168,8 +168,36 @@ impl BufReader { /// # } /// ``` #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")] + #[rustc_deprecated(since = "1.26.0", reason = "use .buffer().is_empty() instead")] pub fn is_empty(&self) -> bool { - self.pos == self.cap + self.buffer().is_empty() + } + + /// Returns a reference to the internally buffered data. + /// + /// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty. + /// + /// # Examples + /// + /// ``` + /// # #![feature(bufreader_buffer)] + /// use std::io::{BufReader, BufRead}; + /// use std::fs::File; + /// + /// # fn foo() -> std::io::Result<()> { + /// let f = File::open("log.txt")?; + /// let mut reader = BufReader::new(f); + /// assert!(reader.buffer().is_empty()); + /// + /// if reader.fill_buf()?.len() > 0 { + /// assert!(!reader.buffer().is_empty()); + /// } + /// # Ok(()) + /// # } + /// ``` + #[unstable(feature = "bufreader_buffer", issue = "45323")] + pub fn buffer(&self) -> &[u8] { + &self.buf[self.pos..self.cap] } /// Unwraps this `BufReader`, returning the underlying reader. From 4dd45069feda95e06cf8287629caea9c64d9d481 Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Sun, 11 Mar 2018 02:21:38 -0300 Subject: [PATCH 21/41] Refactored with high-order functions. --- src/librustc/traits/error_reporting.rs | 42 +++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c90a6d0709db6..5bfeff89e355a 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -888,28 +888,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err: &mut DiagnosticBuilder<'tcx>, trait_ref: &ty::Binder>) { let ty::Binder(trait_ref) = trait_ref; - let span = obligation.cause.span; - let mut snippet = match self.tcx.sess.codemap().span_to_snippet(span) { - Ok(s) => s, - Err(_) => String::from(""), - }; - let mut refs_number = 0; + if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) { + let refs_number = snippet.chars() + .filter(|c| !c.is_whitespace()) + .take_while(|c| *c == '&') + .count(); - for c in snippet.chars() { - if c == '&' { - refs_number += 1; - } - } + let mut refs_remaining = refs_number; + let mut trait_type = trait_ref.self_ty(); + let mut selcx = SelectionContext::new(self); - let mut refs_remaining = refs_number; - let mut trait_type = trait_ref.self_ty(); - let mut selcx = SelectionContext::new(self); + while refs_remaining > 0 { + if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) = + trait_type.sty { - while refs_remaining > 0 { - if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) = - trait_type.sty { trait_type = t_type; refs_remaining -= 1; @@ -920,14 +914,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { new_trait_ref.to_predicate()); if selcx.evaluate_obligation(&new_obligation) { - for i in 0..refs_number { - snippet.remove(i); - } - err.span_suggestion(span, "consider removing `&`s like", format!("{}", snippet)); + let suggest_snippet = snippet.chars() + .skip(refs_number) + .collect::(); + + err.span_suggestion(span, + "consider removing `&`s like", + format!("{}", suggest_snippet)); + + break; } } else { break; } + } } } From e0fb0132c12cc291a866c0ca72334751d3b5a677 Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Mon, 12 Mar 2018 23:40:55 -0300 Subject: [PATCH 22/41] Test added. --- src/test/ui/suggest-remove-refs.rs | 18 ++++++++++++++++++ src/test/ui/suggest-remove-refs.stderr | 15 +++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/test/ui/suggest-remove-refs.rs create mode 100644 src/test/ui/suggest-remove-refs.stderr diff --git a/src/test/ui/suggest-remove-refs.rs b/src/test/ui/suggest-remove-refs.rs new file mode 100644 index 0000000000000..0f19c48337b1e --- /dev/null +++ b/src/test/ui/suggest-remove-refs.rs @@ -0,0 +1,18 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, n) in &v.iter().enumerate() { + //~^ ERROR the trait bound + println!("{}", i); + } +} diff --git a/src/test/ui/suggest-remove-refs.stderr b/src/test/ui/suggest-remove-refs.stderr new file mode 100644 index 0000000000000..d81166e55797a --- /dev/null +++ b/src/test/ui/suggest-remove-refs.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `&std::iter::Enumerate>: std::iter::Iterator` is not satisfied + --> $DIR/suggest-remove-refs.rs:14:19 + | +LL | for (i, n) in &v.iter().enumerate() { + | ^^^^^^^^^^^^^^^^^^^^^ + | | + | `&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method + | help: consider removing `&`s like: `v.iter().enumerate()` + | + = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate>` + = note: required by `std::iter::IntoIterator::into_iter` + +error: aborting due to previous error + +If you want more information on this error, try using "rustc --explain E0277" From f44b945e0ed73c6d108a40655d3bed14133ec7db Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Tue, 13 Mar 2018 01:05:46 -0300 Subject: [PATCH 23/41] New test added. --- ...remove-refs.rs => suggest-remove-refs-1.rs} | 0 ...efs.stderr => suggest-remove-refs-1.stderr} | 4 ++-- src/test/ui/suggest-remove-refs-2.rs | 18 ++++++++++++++++++ src/test/ui/suggest-remove-refs-2.stderr | 15 +++++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) rename src/test/ui/{suggest-remove-refs.rs => suggest-remove-refs-1.rs} (100%) rename src/test/ui/{suggest-remove-refs.stderr => suggest-remove-refs-1.stderr} (84%) create mode 100644 src/test/ui/suggest-remove-refs-2.rs create mode 100644 src/test/ui/suggest-remove-refs-2.stderr diff --git a/src/test/ui/suggest-remove-refs.rs b/src/test/ui/suggest-remove-refs-1.rs similarity index 100% rename from src/test/ui/suggest-remove-refs.rs rename to src/test/ui/suggest-remove-refs-1.rs diff --git a/src/test/ui/suggest-remove-refs.stderr b/src/test/ui/suggest-remove-refs-1.stderr similarity index 84% rename from src/test/ui/suggest-remove-refs.stderr rename to src/test/ui/suggest-remove-refs-1.stderr index d81166e55797a..154b67219f679 100644 --- a/src/test/ui/suggest-remove-refs.stderr +++ b/src/test/ui/suggest-remove-refs-1.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `&std::iter::Enumerate>: std::iter::Iterator` is not satisfied - --> $DIR/suggest-remove-refs.rs:14:19 + --> $DIR/suggest-remove-refs-1.rs:14:19 | LL | for (i, n) in &v.iter().enumerate() { | ^^^^^^^^^^^^^^^^^^^^^ | | | `&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method - | help: consider removing `&`s like: `v.iter().enumerate()` + | help: consider removing 1 references `&`: `v.iter().enumerate()` | = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate>` = note: required by `std::iter::IntoIterator::into_iter` diff --git a/src/test/ui/suggest-remove-refs-2.rs b/src/test/ui/suggest-remove-refs-2.rs new file mode 100644 index 0000000000000..c427f697ae1ef --- /dev/null +++ b/src/test/ui/suggest-remove-refs-2.rs @@ -0,0 +1,18 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, n) in & & & & &v.iter().enumerate() { + //~^ ERROR the trait bound + println!("{}", i); + } +} diff --git a/src/test/ui/suggest-remove-refs-2.stderr b/src/test/ui/suggest-remove-refs-2.stderr new file mode 100644 index 0000000000000..f394344275aaf --- /dev/null +++ b/src/test/ui/suggest-remove-refs-2.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `&&&&&std::iter::Enumerate>: std::iter::Iterator` is not satisfied + --> $DIR/suggest-remove-refs-2.rs:14:19 + | +LL | for (i, n) in & & & & &v.iter().enumerate() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `&&&&&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method + | help: consider removing 5 references `&`: `v.iter().enumerate()` + | + = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate>` + = note: required by `std::iter::IntoIterator::into_iter` + +error: aborting due to previous error + +If you want more information on this error, try using "rustc --explain E0277" From 97b66d2987522d28bb69994e8908a5bb789bff37 Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Tue, 13 Mar 2018 01:06:04 -0300 Subject: [PATCH 24/41] Review fixes. - `suggest_snippet` handling space between refs; - Suggest message changing according to the number of refs that should be removed. --- src/librustc/traits/error_reporting.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 5bfeff89e355a..31c8cb25c521a 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -883,6 +883,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } + /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`, + /// suggest removing these references until we reach a type that implements the trait. fn suggest_remove_reference(&self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -896,16 +898,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .take_while(|c| *c == '&') .count(); - let mut refs_remaining = refs_number; let mut trait_type = trait_ref.self_ty(); let mut selcx = SelectionContext::new(self); - while refs_remaining > 0 { + for refs_remaining in 0..refs_number { if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) = trait_type.sty { trait_type = t_type; - refs_remaining -= 1; let substs = self.tcx.mk_substs_trait(trait_type, &[]); let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs); @@ -914,12 +914,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { new_trait_ref.to_predicate()); if selcx.evaluate_obligation(&new_obligation) { + let remove_refs = refs_remaining + 1; + let suggest_snippet = snippet.chars() - .skip(refs_number) + .filter(|c| !c.is_whitespace()) + .skip(remove_refs) .collect::(); err.span_suggestion(span, - "consider removing `&`s like", + &format!("consider removing {} references `&`", + remove_refs), format!("{}", suggest_snippet)); break; From f41dc775a3ae1f002c24fdff6b2f7c4b68ceca66 Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Wed, 14 Mar 2018 06:41:05 -0300 Subject: [PATCH 25/41] Keeping code formatting. Suggesting snippet without changing the original formatting of the code. --- src/librustc/traits/error_reporting.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 31c8cb25c521a..1bbd24de6ae46 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -914,11 +914,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { new_trait_ref.to_predicate()); if selcx.evaluate_obligation(&new_obligation) { - let remove_refs = refs_remaining + 1; + let mut remove_refs = refs_remaining + 1; let suggest_snippet = snippet.chars() - .filter(|c| !c.is_whitespace()) - .skip(remove_refs) + .skip_while(|c| c.is_whitespace() || { + if *c == '&' && remove_refs > 0 { + true + } else { + false + } + }) .collect::(); err.span_suggestion(span, From 52cd07aef79223b89109fe392addb905d491de18 Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Wed, 14 Mar 2018 06:42:27 -0300 Subject: [PATCH 26/41] Created multiple line test. --- src/test/ui/suggest-remove-refs-3.rs | 21 +++++++++++++++++++++ src/test/ui/suggest-remove-refs-3.stderr | 22 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/test/ui/suggest-remove-refs-3.rs create mode 100644 src/test/ui/suggest-remove-refs-3.stderr diff --git a/src/test/ui/suggest-remove-refs-3.rs b/src/test/ui/suggest-remove-refs-3.rs new file mode 100644 index 0000000000000..f54ae30caebca --- /dev/null +++ b/src/test/ui/suggest-remove-refs-3.rs @@ -0,0 +1,21 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let v = vec![0, 1, 2, 3]; + + for (i, n) in & & & + & &v + .iter() + .enumerate() { + //~^^^^ ERROR the trait bound + println!("{}", i); + } +} diff --git a/src/test/ui/suggest-remove-refs-3.stderr b/src/test/ui/suggest-remove-refs-3.stderr new file mode 100644 index 0000000000000..7add72adf4d3d --- /dev/null +++ b/src/test/ui/suggest-remove-refs-3.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `&&&&&std::iter::Enumerate>: std::iter::Iterator` is not satisfied + --> $DIR/suggest-remove-refs-3.rs:14:19 + | +LL | for (i, n) in & & & + | ___________________^ +LL | | & &v +LL | | .iter() +LL | | .enumerate() { + | |____________________^ `&&&&&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method + | + = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate>` + = note: required by `std::iter::IntoIterator::into_iter` +help: consider removing 5 references `&` + | +LL | for (i, n) in v +LL | .iter() +LL | .enumerate() { + | + +error: aborting due to previous error + +If you want more information on this error, try using "rustc --explain E0277" From f6bffd16d15672557e7d9c32b0cca08639a32251 Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Wed, 14 Mar 2018 12:49:06 -0300 Subject: [PATCH 27/41] Rebased with master. --- src/librustc_traits/normalize_projection_ty.rs | 2 +- src/librustc_typeck/check/dropck.rs | 2 +- src/test/ui/suggest-remove-refs-1.stderr | 2 +- src/test/ui/suggest-remove-refs-2.stderr | 2 +- src/test/ui/suggest-remove-refs-3.stderr | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs index 55785d9586cc3..171bc1bd2d6d4 100644 --- a/src/librustc_traits/normalize_projection_ty.rs +++ b/src/librustc_traits/normalize_projection_ty.rs @@ -36,7 +36,7 @@ crate fn normalize_projection_ty<'tcx>( ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal); let fulfill_cx = &mut FulfillmentContext::new(); let selcx = &mut SelectionContext::new(infcx); - let cause = ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID); + let cause = ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID, DUMMY_NODE_ID); let Normalized { value: answer, obligations, diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 596381d7ea676..4943560d68be0 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -298,7 +298,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>( }; let parent_scope = rcx.tcx.mk_region(ty::ReScope(parent_scope)); let origin = || infer::SubregionOrigin::SafeDestructor(span); - let cause = &ObligationCause::misc(span, body_id); + let cause = &ObligationCause::misc(span, body_id, body_id); let infer_ok = rcx.infcx.at(cause, rcx.fcx.param_env).dropck_outlives(ty); debug!("dropck_outlives = {:#?}", infer_ok); let kinds = rcx.fcx.register_infer_ok_obligations(infer_ok); diff --git a/src/test/ui/suggest-remove-refs-1.stderr b/src/test/ui/suggest-remove-refs-1.stderr index 154b67219f679..fe4ab2c4ee052 100644 --- a/src/test/ui/suggest-remove-refs-1.stderr +++ b/src/test/ui/suggest-remove-refs-1.stderr @@ -12,4 +12,4 @@ LL | for (i, n) in &v.iter().enumerate() { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggest-remove-refs-2.stderr b/src/test/ui/suggest-remove-refs-2.stderr index f394344275aaf..243ddcfe125e2 100644 --- a/src/test/ui/suggest-remove-refs-2.stderr +++ b/src/test/ui/suggest-remove-refs-2.stderr @@ -12,4 +12,4 @@ LL | for (i, n) in & & & & &v.iter().enumerate() { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggest-remove-refs-3.stderr b/src/test/ui/suggest-remove-refs-3.stderr index 7add72adf4d3d..83f3826642b2b 100644 --- a/src/test/ui/suggest-remove-refs-3.stderr +++ b/src/test/ui/suggest-remove-refs-3.stderr @@ -19,4 +19,4 @@ LL | .enumerate() { error: aborting due to previous error -If you want more information on this error, try using "rustc --explain E0277" +For more information about this error, try `rustc --explain E0277`. From c1ba5ac62c14ab5e231edcce914fd33f0e32c2d1 Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Fri, 16 Mar 2018 17:58:11 -0300 Subject: [PATCH 28/41] Reporting with `span_suggestion_short`. --- src/librustc/traits/error_reporting.rs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 1bbd24de6ae46..267d84cc53141 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -914,22 +914,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { new_trait_ref.to_predicate()); if selcx.evaluate_obligation(&new_obligation) { - let mut remove_refs = refs_remaining + 1; - - let suggest_snippet = snippet.chars() - .skip_while(|c| c.is_whitespace() || { - if *c == '&' && remove_refs > 0 { - true - } else { - false - } - }) - .collect::(); + let remove_refs = refs_remaining + 1; - err.span_suggestion(span, - &format!("consider removing {} references `&`", - remove_refs), - format!("{}", suggest_snippet)); + err.span_suggestion_short(span, + &format!("consider removing {} leading `&`-references", + remove_refs), + String::from("")); break; } From 74a4928ed49d000dee9827c21f68148ad3aa271e Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Sat, 17 Mar 2018 15:41:46 -0300 Subject: [PATCH 29/41] Review fixes. - `span_suggestion` changed to `span_suggestion_short`; - `Span` used changed to contain only `&` refs; - Tests passing. --- src/librustc/traits/error_reporting.rs | 11 ++++++----- src/libsyntax/codemap.rs | 16 ++++++++++++++++ src/test/ui/suggest-remove-refs-1.stderr | 4 ++-- src/test/ui/suggest-remove-refs-2.stderr | 4 ++-- src/test/ui/suggest-remove-refs-3.stderr | 21 +++++++++------------ 5 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 267d84cc53141..9b01f8899b52b 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -914,13 +914,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { new_trait_ref.to_predicate()); if selcx.evaluate_obligation(&new_obligation) { - let remove_refs = refs_remaining + 1; + let sp = self.tcx.sess.codemap() + .span_take_while(span, |c| c.is_whitespace() || *c == '&'); - err.span_suggestion_short(span, - &format!("consider removing {} leading `&`-references", - remove_refs), - String::from("")); + let remove_refs = refs_remaining + 1; + let format_str = format!("consider removing {} leading `&`-references", + remove_refs); + err.span_suggestion_short(sp, &format_str, String::from("")); break; } } else { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index a1aec05208859..324d57c119452 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -697,6 +697,22 @@ impl CodeMap { sp } + /// Given a `Span`, get a shorter one until `predicate` yields false. + pub fn span_take_while

(&self, sp: Span, predicate: P) -> Span + where P: for <'r> FnMut(&'r char) -> bool + { + if let Ok(snippet) = self.span_to_snippet(sp) { + let offset = snippet.chars() + .take_while(predicate) + .map(|c| c.len_utf8()) + .sum::(); + + sp.with_hi(BytePos(sp.lo().0 + (offset as u32))) + } else { + sp + } + } + pub fn def_span(&self, sp: Span) -> Span { self.span_until_char(sp, '{') } diff --git a/src/test/ui/suggest-remove-refs-1.stderr b/src/test/ui/suggest-remove-refs-1.stderr index fe4ab2c4ee052..c47b4d283d7cd 100644 --- a/src/test/ui/suggest-remove-refs-1.stderr +++ b/src/test/ui/suggest-remove-refs-1.stderr @@ -2,10 +2,10 @@ error[E0277]: the trait bound `&std::iter::Enumerate $DIR/suggest-remove-refs-1.rs:14:19 | LL | for (i, n) in &v.iter().enumerate() { - | ^^^^^^^^^^^^^^^^^^^^^ + | -^^^^^^^^^^^^^^^^^^^^ | | | `&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method - | help: consider removing 1 references `&`: `v.iter().enumerate()` + | help: consider removing 1 leading `&`-references | = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate>` = note: required by `std::iter::IntoIterator::into_iter` diff --git a/src/test/ui/suggest-remove-refs-2.stderr b/src/test/ui/suggest-remove-refs-2.stderr index 243ddcfe125e2..fdd654ea3923f 100644 --- a/src/test/ui/suggest-remove-refs-2.stderr +++ b/src/test/ui/suggest-remove-refs-2.stderr @@ -2,10 +2,10 @@ error[E0277]: the trait bound `&&&&&std::iter::Enumerate $DIR/suggest-remove-refs-2.rs:14:19 | LL | for (i, n) in & & & & &v.iter().enumerate() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ---------^^^^^^^^^^^^^^^^^^^^ | | | `&&&&&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method - | help: consider removing 5 references `&`: `v.iter().enumerate()` + | help: consider removing 5 leading `&`-references | = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate>` = note: required by `std::iter::IntoIterator::into_iter` diff --git a/src/test/ui/suggest-remove-refs-3.stderr b/src/test/ui/suggest-remove-refs-3.stderr index 83f3826642b2b..b0920a0fa523e 100644 --- a/src/test/ui/suggest-remove-refs-3.stderr +++ b/src/test/ui/suggest-remove-refs-3.stderr @@ -1,21 +1,18 @@ error[E0277]: the trait bound `&&&&&std::iter::Enumerate>: std::iter::Iterator` is not satisfied --> $DIR/suggest-remove-refs-3.rs:14:19 | -LL | for (i, n) in & & & - | ___________________^ -LL | | & &v -LL | | .iter() -LL | | .enumerate() { - | |____________________^ `&&&&&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method +LL | for (i, n) in & & & + | ___________________^ + | |___________________| + | || +LL | || & &v + | ||___________- help: consider removing 5 leading `&`-references +LL | | .iter() +LL | | .enumerate() { + | |_____________________^ `&&&&&std::iter::Enumerate>` is not an iterator; maybe try calling `.iter()` or a similar method | = help: the trait `std::iter::Iterator` is not implemented for `&&&&&std::iter::Enumerate>` = note: required by `std::iter::IntoIterator::into_iter` -help: consider removing 5 references `&` - | -LL | for (i, n) in v -LL | .iter() -LL | .enumerate() { - | error: aborting due to previous error From 0b36b20651704cf7051f468aeb3b84babf940e63 Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Sun, 18 Mar 2018 10:05:20 -0300 Subject: [PATCH 30/41] CodeMap functions refactored. - Using `span_take_while` to implement others. --- src/libsyntax/codemap.rs | 88 +++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 50 deletions(-) diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 324d57c119452..73924c4270e66 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -597,21 +597,6 @@ impl CodeMap { self.span_to_source(sp, |src, start_index, _| src[..start_index].to_string()) } - /// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char` - pub fn span_until_char(&self, sp: Span, c: char) -> Span { - match self.span_to_snippet(sp) { - Ok(snippet) => { - let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right(); - if !snippet.is_empty() && !snippet.contains('\n') { - sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32)) - } else { - sp - } - } - _ => sp, - } - } - /// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span /// if no character could be found or if an error occurred while retrieving the code snippet. pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span { @@ -646,26 +631,50 @@ impl CodeMap { sp } + /// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char` + pub fn span_until_char(&self, sp: Span, c: char) -> Span { + match self.span_to_snippet(sp) { + Ok(snippet) => { + let snippet = snippet.split(c).nth(0).unwrap_or("").trim_right(); + if !snippet.is_empty() && !snippet.contains('\n') { + sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32)) + } else { + sp + } + } + _ => sp, + } + } + + /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char` + /// `c`. + pub fn span_through_char(&self, sp: Span, c: char) -> Span { + if let Ok(snippet) = self.span_to_snippet(sp) { + if let Some(offset) = snippet.find(c) { + return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32)); + } + } + sp + } + /// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or /// the original `Span`. /// /// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned. pub fn span_until_non_whitespace(&self, sp: Span) -> Span { - if let Ok(snippet) = self.span_to_snippet(sp) { - let mut offset = 0; - // get the bytes width of all the non-whitespace characters - for c in snippet.chars().take_while(|c| !c.is_whitespace()) { - offset += c.len_utf8(); - } - // get the bytes width of all the whitespace characters after that - for c in snippet[offset..].chars().take_while(|c| c.is_whitespace()) { - offset += c.len_utf8(); + let mut whitespace_found = false; + + self.span_take_while(sp, |c| { + if !whitespace_found && c.is_whitespace() { + whitespace_found = true; } - if offset > 1 { - return sp.with_hi(BytePos(sp.lo().0 + offset as u32)); + + if whitespace_found && !c.is_whitespace() { + false + } else { + true } - } - sp + }) } /// Given a `Span`, get a new `Span` covering the first token without its trailing whitespace or @@ -673,28 +682,7 @@ impl CodeMap { /// /// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned. pub fn span_until_whitespace(&self, sp: Span) -> Span { - if let Ok(snippet) = self.span_to_snippet(sp) { - let mut offset = 0; - // Get the bytes width of all the non-whitespace characters - for c in snippet.chars().take_while(|c| !c.is_whitespace()) { - offset += c.len_utf8(); - } - if offset > 1 { - return sp.with_hi(BytePos(sp.lo().0 + offset as u32)); - } - } - sp - } - - /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char` - /// `c`. - pub fn span_through_char(&self, sp: Span, c: char) -> Span { - if let Ok(snippet) = self.span_to_snippet(sp) { - if let Some(offset) = snippet.find(c) { - return sp.with_hi(BytePos(sp.lo().0 + (offset + c.len_utf8()) as u32)); - } - } - sp + self.span_take_while(sp, |c| !c.is_whitespace()) } /// Given a `Span`, get a shorter one until `predicate` yields false. From 736ba433ac2f0d2f6604a64f744f86a311a56be4 Mon Sep 17 00:00:00 2001 From: Yukio Siraichi Date: Sun, 18 Mar 2018 20:58:56 -0300 Subject: [PATCH 31/41] Cleaned comments and extras s. --- src/librustc/traits/error_reporting.rs | 38 ------------------- .../normalize_projection_ty.rs | 2 +- src/librustc_typeck/check/dropck.rs | 2 +- 3 files changed, 2 insertions(+), 40 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 9b01f8899b52b..ab3c619dcdcd0 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -575,44 +575,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { = self.on_unimplemented_note(trait_ref, obligation); let have_alt_message = message.is_some() || label.is_some(); - // { - // let ty::Binder(trait_ref) = trait_ref; - // println!("TraitRef: {:?}", trait_ref); - // println!("TraitRef: id:{:?}; subst:{:?}", trait_ref.def_id, trait_ref.substs); - - // if let ty::Predicate::Trait(trait_predicate_binder) = - // trait_ref.to_predicate() { - // let trait_predicate = trait_predicate_binder.skip_binder(); - // println!("TraitPredicateBinder: {:?}", trait_predicate_binder); - // println!("TraitPredicate: {:?}", trait_predicate); - - // let trait_ty = trait_ref.self_ty(); - // println!("TraitPredicateTy: {:?}", trait_ty); - // println!("TraitPredicateTy: sty:{:?}; flags{:?}", trait_ty.sty, trait_ty.flags); - // } - - // for in_ty in trait_ref.input_types() { - // println!("\t- {:?}", in_ty); - // println!("\t\t- sty:{:?}; flags:{:?}", in_ty.sty, in_ty.flags); - // } - - // println!("Message: {:?}", message); - // println!("Label: {:?}", label); - // println!("Obligation: {:?}", obligation); - // println!("Span: {:?}", self.tcx.sess.codemap().span_to_string(span)); - - // let body_id = obligation.cause.body_id; - // println!("BodyId: {:?}", body_id); - // println!("BodyIdSpan: {:?}", self.tcx.hir.span(body_id)); - - // match self.tcx.hir.find(body_id) { - // Some(node) => println!("Node: {:?}", node), - // None => println!("Node not found."), - // } - - // println!("=------------------------------="); - // } - let mut err = struct_span_err!( self.tcx.sess, span, diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs index 171bc1bd2d6d4..55785d9586cc3 100644 --- a/src/librustc_traits/normalize_projection_ty.rs +++ b/src/librustc_traits/normalize_projection_ty.rs @@ -36,7 +36,7 @@ crate fn normalize_projection_ty<'tcx>( ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal); let fulfill_cx = &mut FulfillmentContext::new(); let selcx = &mut SelectionContext::new(infcx); - let cause = ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID, DUMMY_NODE_ID); + let cause = ObligationCause::misc(DUMMY_SP, DUMMY_NODE_ID); let Normalized { value: answer, obligations, diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 4943560d68be0..596381d7ea676 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -298,7 +298,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>( }; let parent_scope = rcx.tcx.mk_region(ty::ReScope(parent_scope)); let origin = || infer::SubregionOrigin::SafeDestructor(span); - let cause = &ObligationCause::misc(span, body_id, body_id); + let cause = &ObligationCause::misc(span, body_id); let infer_ok = rcx.infcx.at(cause, rcx.fcx.param_env).dropck_outlives(ty); debug!("dropck_outlives = {:#?}", infer_ok); let kinds = rcx.fcx.register_infer_ok_obligations(infer_ok); From 612c4a95bce4c4dc0cddc5ab374fcb262039aede Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Tue, 6 Mar 2018 23:17:49 -0500 Subject: [PATCH 32/41] Impl Integer methods for Wrapping Wrapping now implements: count_ones, count_zeros, leading_zeros, trailing_zeros, rotate_left, rotate_right, swap_bytes, from_be, from_le, to_be, to_le, and pow where T is: u8, u16, u32, u64, usize, i8, i16, i32, i64, or isize. Docs were written for all these methods, as well as examples. The examples mirror the ones on u8, u16, etc... for consistency. Closes #32463 --- src/libcore/num/wrapping.rs | 299 ++++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index ae1b0b3ce11b2..6c110aa052311 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -317,11 +317,307 @@ macro_rules! wrapping_impl { } forward_ref_unop! { impl Neg, neg for Wrapping<$t>, #[stable(feature = "wrapping_ref", since = "1.14.0")] } + )*) } wrapping_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } +macro_rules! wrapping_int_impl { + ($($t:ty)*) => ($( + impl Wrapping<$t> { + /// Returns the number of ones in the binary representation of + /// `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(-0b1000_0000); + /// + /// assert_eq!(n.count_ones(), 1); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn count_ones(self) -> u32 { + self.0.count_ones() + } + + /// Returns the number of zeros in the binary representation of + /// `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(-0b1000_0000); + /// + /// assert_eq!(n.count_zeros(), 7); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn count_zeros(self) -> u32 { + self.0.count_zeros() + } + + /// Returns the number of leading zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(-1); + /// + /// assert_eq!(n.leading_zeros(), 0); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn leading_zeros(self) -> u32 { + self.0.leading_zeros() + } + + /// Returns the number of trailing zeros in the binary representation + /// of `self`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(-4); + /// + /// assert_eq!(n.trailing_zeros(), 2); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn trailing_zeros(self) -> u32 { + self.0.trailing_zeros() + } + + /// Shifts the bits to the left by a specified amount, `n`, + /// wrapping the truncated bits to the end of the resulting + /// integer. + /// + /// Please note this isn't the same operation as `>>`! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// let m: Wrapping = Wrapping(-0x76543210FEDCBA99); + /// + /// assert_eq!(n.rotate_left(32), m); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn rotate_left(self, n: u32) -> Self { + Wrapping(self.0.rotate_left(n)) + } + + /// Shifts the bits to the right by a specified amount, `n`, + /// wrapping the truncated bits to the beginning of the resulting + /// integer. + /// + /// Please note this isn't the same operation as `<<`! + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// let m: Wrapping = Wrapping(-0xFEDCBA987654322); + /// + /// assert_eq!(n.rotate_right(4), m); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn rotate_right(self, n: u32) -> Self { + Wrapping(self.0.rotate_right(n)) + } + + /// Reverses the byte order of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0b0000000_01010101); + /// assert_eq!(n, Wrapping(85)); + /// + /// let m = n.swap_bytes(); + /// + /// assert_eq!(m, Wrapping(0b01010101_00000000)); + /// assert_eq!(m, Wrapping(21760)); + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn swap_bytes(self) -> Self { + Wrapping(self.0.swap_bytes()) + } + + /// Converts an integer from big endian to the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(Wrapping::::from_be(n), n); + /// } else { + /// assert_eq!(Wrapping::::from_be(n), n.swap_bytes()); + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn from_be(x: Self) -> Self { + Wrapping(<$t>::from_be(x.0)) + } + + /// Converts an integer from little endian to the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(Wrapping::::from_le(n), n); + /// } else { + /// assert_eq!(Wrapping::::from_le(n), n.swap_bytes()); + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn from_le(x: Self) -> Self { + Wrapping(<$t>::from_le(x.0)) + } + + /// Converts `self` to big endian from the target's endianness. + /// + /// On big endian this is a no-op. On little endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// + /// if cfg!(target_endian = "big") { + /// assert_eq!(n.to_be(), n); + /// } else { + /// assert_eq!(n.to_be(), n.swap_bytes()); + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn to_be(self) -> Self { + Wrapping(self.0.to_be()) + } + + /// Converts `self` to little endian from the target's endianness. + /// + /// On little endian this is a no-op. On big endian the bytes are + /// swapped. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); + /// + /// if cfg!(target_endian = "little") { + /// assert_eq!(n.to_le(), n); + /// } else { + /// assert_eq!(n.to_le(), n.swap_bytes()); + /// } + /// ``` + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn to_le(self) -> Self { + Wrapping(self.0.to_le()) + } + + /// Raises self to the power of `exp`, using exponentiation by + /// squaring. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// let x: Wrapping = Wrapping(2); // or any other integer type + /// + /// assert_eq!(x.pow(4), Wrapping(16)); + #[inline] + #[unstable(feature = "wrapping_int_impl", issue = "32463")] + pub fn pow(self, exp: u32) -> Self { + Wrapping(self.0.pow(exp)) + } + } + )*) +} + +wrapping_int_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } + + mod shift_max { #![allow(non_upper_case_globals)] @@ -355,3 +651,6 @@ mod shift_max { pub const u64: u32 = i64; pub use self::platform::usize; } + + + From 5258af398aced119ad5ac40192fa131a2f2827d4 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Thu, 8 Mar 2018 02:31:15 -0500 Subject: [PATCH 33/41] Make Wrapping::pow use wrapping_pow, add example --- src/libcore/num/wrapping.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 6c110aa052311..fb79ddd095172 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -606,10 +606,23 @@ macro_rules! wrapping_int_impl { /// let x: Wrapping = Wrapping(2); // or any other integer type /// /// assert_eq!(x.pow(4), Wrapping(16)); + /// ``` + /// + /// Results that are too large are wrapped: + /// + /// ``` + /// #![feature(wrapping_int_impl)] + /// use std::num::Wrapping; + /// + /// // 5 ^ 4 = 625, which is too big for a u8 + /// let x: Wrapping = Wrapping(5); + /// + /// assert_eq!(x.pow(4).0, 113); + /// ``` #[inline] #[unstable(feature = "wrapping_int_impl", issue = "32463")] pub fn pow(self, exp: u32) -> Self { - Wrapping(self.0.pow(exp)) + Wrapping(self.0.wrapping_pow(exp)) } } )*) @@ -651,6 +664,3 @@ mod shift_max { pub const u64: u32 = i64; pub use self::platform::usize; } - - - From bf101a5759fd0ddab7c9cbb1dc93d22d35f54722 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Thu, 8 Mar 2018 03:30:55 -0500 Subject: [PATCH 34/41] Fix trailing whitespace --- src/libcore/num/wrapping.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index fb79ddd095172..826883fdc3f01 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -525,7 +525,7 @@ macro_rules! wrapping_int_impl { /// use std::num::Wrapping; /// /// let n: Wrapping = Wrapping(0x0123456789ABCDEF); - /// + /// /// if cfg!(target_endian = "little") { /// assert_eq!(Wrapping::::from_le(n), n); /// } else { From 741d7a5598739f864f0f842d21665fa1e5809b41 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 19 Mar 2018 07:37:59 +0100 Subject: [PATCH 35/41] Docs: fix incorrect copy-paste for new `X?` in formatting strings --- src/liballoc/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 2c4cdef03b0f7..90043e1c716b6 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -114,7 +114,7 @@ //! * *nothing* ⇒ [`Display`] //! * `?` ⇒ [`Debug`] //! * `x?` ⇒ [`Debug`] with lower-case hexadecimal integers -//! * `X?` ⇒ [`Debug`] with lower-case hexadecimal integers +//! * `X?` ⇒ [`Debug`] with upper-case hexadecimal integers //! * `o` ⇒ [`Octal`](trait.Octal.html) //! * `x` ⇒ [`LowerHex`](trait.LowerHex.html) //! * `X` ⇒ [`UpperHex`](trait.UpperHex.html) From 3799866063d3d6646f20f5a99292f633dce789cb Mon Sep 17 00:00:00 2001 From: Dileep Bapat Date: Mon, 19 Mar 2018 16:44:58 +0530 Subject: [PATCH 36/41] #49133 - Reworded the Error message: "`pub` not needed here" message --- src/librustc_passes/ast_validation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 4215bf306a4fd..e5157a071bf0a 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -67,7 +67,7 @@ impl<'a> AstValidator<'a> { E0449, "unnecessary visibility qualifier"); if vis.node == VisibilityKind::Public { - err.span_label(vis.span, "`pub` not needed here"); + err.span_label(vis.span, "`pub` not permitted here because it's implied"); } if let Some(note) = note { err.note(note); From a8f59aaef916849155157b11089dd209062eecc4 Mon Sep 17 00:00:00 2001 From: Dileep Bapat Date: Mon, 19 Mar 2018 16:44:58 +0530 Subject: [PATCH 37/41] #49133 - Reworded the Error message: "`pub` not needed here" message --- src/test/ui/error-codes/E0449.stderr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/error-codes/E0449.stderr b/src/test/ui/error-codes/E0449.stderr index 480d8c40022d5..df3b09ba7c9f3 100644 --- a/src/test/ui/error-codes/E0449.stderr +++ b/src/test/ui/error-codes/E0449.stderr @@ -2,7 +2,7 @@ error[E0449]: unnecessary visibility qualifier --> $DIR/E0449.rs:17:1 | LL | pub impl Bar {} //~ ERROR E0449 - | ^^^ `pub` not needed here + | ^^^ `pub` not permitted here because it's implied | = note: place qualifiers on individual impl items instead @@ -10,13 +10,13 @@ error[E0449]: unnecessary visibility qualifier --> $DIR/E0449.rs:19:1 | LL | pub impl Foo for Bar { //~ ERROR E0449 - | ^^^ `pub` not needed here + | ^^^ `pub` not permitted here because it's implied error[E0449]: unnecessary visibility qualifier --> $DIR/E0449.rs:20:5 | LL | pub fn foo() {} //~ ERROR E0449 - | ^^^ `pub` not needed here + | ^^^ `pub` not permitted here because it's implied error: aborting due to 3 previous errors From 253ade5b31c8841f0351298c0f393fb0aba2cd24 Mon Sep 17 00:00:00 2001 From: Alan Du Date: Mon, 19 Mar 2018 10:14:13 -0400 Subject: [PATCH 38/41] Update rustfmt to 0.4.1 --- src/Cargo.lock | 139 ++++++++++++++++------------------------------ src/tools/rustfmt | 2 +- 2 files changed, 48 insertions(+), 93 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index c82588e41125c..26508dec4bba2 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -236,18 +236,6 @@ dependencies = [ "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "cargo_metadata" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cargo_metadata" version = "0.5.3" @@ -588,15 +576,6 @@ dependencies = [ "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "env_logger" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "env_logger" version = "0.5.5" @@ -1490,7 +1469,7 @@ dependencies = [ "rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.4.1", "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1585,7 +1564,7 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "29.0.0" +version = "67.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1594,57 +1573,62 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_data_structures" -version = "29.0.0" +version = "67.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "29.0.0" +version = "67.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-serialize" -version = "29.0.0" +version = "67.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "29.0.0" +version = "67.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "29.0.0" +version = "67.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2066,52 +2050,26 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.3.8" +version = "0.4.1" dependencies = [ - "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustfmt-nightly" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "derive-new 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.39 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2146,15 +2104,6 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "semver" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "semver" version = "0.9.0" @@ -2424,6 +2373,15 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "term" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termcolor" version = "0.3.5" @@ -2737,7 +2695,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" "checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" "checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b" -"checksum cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20d6fb2b5574726329c85cdba0df0347fddfec3cf9c8b588f9931708280f5643" "checksum cargo_metadata 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b5caae26de3704081ef638f87f05a6891b04f2b7d5ce9429a3de21095528ae22" "checksum cc 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fedf677519ac9e865c4ff43ef8f930773b37ed6e6ea61b6b83b400a7b5787f49" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" @@ -2764,7 +2721,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" -"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum env_logger 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0628f04f7c26ebccf40d7fc2c1cf92236c05ec88cf2132641cc956812312f0f" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82" @@ -2858,21 +2814,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb" -"checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524" -"checksum rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c0d65325492aba7db72899e3edbab34d39af98c42ab7c7e450c9a288ffe4ad" -"checksum rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4ab2e06a671b5b5c5b0359dac346f164c99d059dce6a22feb08f2f56bd182" -"checksum rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0745fa445ff41c4b6699936cf35ce3ca49502377dd7b3929c829594772c3a7b" -"checksum rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82efedabe30f393161e11214a9130edfa01ad476372d1c6f3fec1f8d30488c9d" -"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0" +"checksum rustc-ap-rustc_cratesio_shim 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "adc16e4a6e50a4ffbd4633d737aedbdfcb565bdf658159e0544266908180a919" +"checksum rustc-ap-rustc_data_structures 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ec5f0a018fbec07f64b689ac20f7343ed77939055ca07d2aceb37c832245b1b" +"checksum rustc-ap-rustc_errors 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8301221cc07002666eed552a089b15000bc954c94b14a460c0653363a7f42f4c" +"checksum rustc-ap-serialize 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5212ee40fc332d791cacf202ae5fb99197341857c0a14bcdf60541fea7dfc5ed" +"checksum rustc-ap-syntax 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "168571b3878c6c61aef4bacef95c86d30fa61fb1cff04395d9535c80c196e559" +"checksum rustc-ap-syntax_pos 67.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd7a0486f56db583caa665c8b4ff02c4774fe279db1741509437bc8a84c53361" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustfmt-nightly 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "554256054eae37ead2f799ffa9cf8be8249496c6c3cf005c28b7cfa55f4efaa5" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" "checksum schannel 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fbaffce35eb61c5b00846e73128b0cd62717e7c0ec46abbec132370d013975b4" "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4" "checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4763b773978e495252615e814d2ad04773b2c1f85421c7913869a537f35cb406" @@ -2896,6 +2850,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tar 0.4.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1605d3388ceb50252952ffebab4b5dc43017ead7e4481b175961c283bb951195" "checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" +"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "56c456352e44f9f91f774ddeeed27c1ec60a2455ed66d692059acfb1d731bda1" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 346238f49740d..87180d9065e7c 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 346238f49740d6c98102a6a59811b1625c73a9d7 +Subproject commit 87180d9065e7c8070c0ba46eb48ddf8779ef89ac From 7dd943866228bb1037c7b9efd5e01f91862703e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 19 Mar 2018 15:14:19 +0100 Subject: [PATCH 39/41] config.toml.example: thinlto bootstrap was removed in ff227c4a2d8a2fad5abf322f6f1391ae6779197f so remove the option. --- config.toml.example | 5 ----- 1 file changed, 5 deletions(-) diff --git a/config.toml.example b/config.toml.example index b47f9163c0dac..f8cc67aee91a3 100644 --- a/config.toml.example +++ b/config.toml.example @@ -239,11 +239,6 @@ # compiler. #codegen-units = 1 -# Whether to enable ThinLTO (and increase the codegen units to either a default -# or the configured value). On by default. If we want the fastest possible -# compiler, we should disable this. -#thinlto = true - # Whether or not debug assertions are enabled for the compiler and standard # library. Also enables compilation of debug! and trace! logging macros. #debug-assertions = false From 1b8f1fc2d9a387840fbd9b04eb80e6b9a42ea198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 18 Mar 2018 18:18:35 -0700 Subject: [PATCH 40/41] Do not suggest `.into()` in `const`s --- src/librustc_typeck/check/demand.rs | 15 ++++++++++++- .../ui/suggestions/const-type-mismatch.rs | 21 +++++++++++++++++++ .../ui/suggestions/const-type-mismatch.stderr | 15 +++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/suggestions/const-type-mismatch.rs create mode 100644 src/test/ui/suggestions/const-type-mismatch.stderr diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 634a7ee569917..701b896b9057b 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -18,8 +18,9 @@ use syntax::ast; use syntax::util::parser::PREC_POSTFIX; use syntax_pos::{self, Span}; use rustc::hir; -use rustc::hir::print; use rustc::hir::def::Def; +use rustc::hir::map::NodeItem; +use rustc::hir::{Item, ItemConst, print}; use rustc::ty::{self, Ty, AssociatedItem}; use errors::{DiagnosticBuilder, CodeMapper}; @@ -318,6 +319,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { checked_ty: Ty<'tcx>, expected_ty: Ty<'tcx>) -> bool { + let parent_id = self.tcx.hir.get_parent_node(expr.id); + match self.tcx.hir.find(parent_id) { + Some(parent) => { + // Shouldn't suggest `.into()` on `const`s. + if let NodeItem(Item { node: ItemConst(_, _), .. }) = parent { + // FIXME(estebank): modify once we decide to suggest `as` casts + return false; + } + } + None => {} + }; + let will_truncate = "will truncate the source value"; let depending_on_isize = "will truncate or zero-extend depending on the bit width of \ `isize`"; diff --git a/src/test/ui/suggestions/const-type-mismatch.rs b/src/test/ui/suggestions/const-type-mismatch.rs new file mode 100644 index 0000000000000..ddad4e79cfdaa --- /dev/null +++ b/src/test/ui/suggestions/const-type-mismatch.rs @@ -0,0 +1,21 @@ +// Copyright 2018 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. + +// `const`s shouldn't suggest `.into()` + +const TEN: u8 = 10; +const TWELVE: u16 = TEN + 2; +//~^ ERROR mismatched types [E0308] + +fn main() { + const TEN: u8 = 10; + const ALSO_TEN: u16 = TEN; + //~^ ERROR mismatched types [E0308] +} diff --git a/src/test/ui/suggestions/const-type-mismatch.stderr b/src/test/ui/suggestions/const-type-mismatch.stderr new file mode 100644 index 0000000000000..965995f82c53a --- /dev/null +++ b/src/test/ui/suggestions/const-type-mismatch.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/const-type-mismatch.rs:14:21 + | +LL | const TWELVE: u16 = TEN + 2; + | ^^^^^^^ expected u16, found u8 + +error[E0308]: mismatched types + --> $DIR/const-type-mismatch.rs:19:27 + | +LL | const ALSO_TEN: u16 = TEN; + | ^^^ expected u16, found u8 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 57c74c39813c4668d3be5a0c244758f59ab32d9a Mon Sep 17 00:00:00 2001 From: Bryan Drewery Date: Mon, 19 Mar 2018 12:40:42 -0700 Subject: [PATCH 41/41] Update beta to version with fixed FreeBSD support from #49023. Fixes #42681 --- src/stage0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stage0.txt b/src/stage0.txt index b9578386ce5bc..96ec1e6834dff 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2018-02-20 +date: 2018-03-18 rustc: beta cargo: beta