From 95dc353006c23a4493b3d08ba33680e51c2107c8 Mon Sep 17 00:00:00 2001 From: jmaargh Date: Sat, 9 Apr 2022 16:42:26 +0100 Subject: [PATCH 01/28] Fix documentation for with_capacity and reserve families of methods Documentation for the following methods with_capacity with_capacity_in with_capacity_and_hasher reserve reserve_exact try_reserve try_reserve_exact was inconsistent and often not entirely correct where they existed on the following types Vec VecDeque String OsString PathBuf BinaryHeap HashSet HashMap BufWriter LineWriter since the allocator is allowed to allocate more than the requested capacity in all such cases, and will frequently "allocate" much more in the case of zero-sized types (I also checked BufReader, but there the docs appear to be accurate as it appears to actually allocate the exact capacity). Some effort was made to make the documentation more consistent between types as well. Fix with_capacity* methods for Vec Fix *reserve* methods for Vec Fix docs for *reserve* methods of VecDeque Fix docs for String::with_capacity Fix docs for *reserve* methods of String Fix docs for OsString::with_capacity Fix docs for *reserve* methods on OsString Fix docs for with_capacity* methods on HashSet Fix docs for *reserve methods of HashSet Fix docs for with_capacity* methods of HashMap Fix docs for *reserve methods on HashMap Fix expect messages about OOM in doctests Fix docs for BinaryHeap::with_capacity Fix docs for *reserve* methods of BinaryHeap Fix typos Fix docs for with_capacity on BufWriter and LineWriter Fix consistent use of `hasher` between `HashMap` and `HashSet` Fix warning in doc test Add test for capacity of vec with ZST Fix doc test error --- library/alloc/src/collections/binary_heap.rs | 51 ++++++----- .../alloc/src/collections/vec_deque/mod.rs | 16 ++-- library/alloc/src/string.rs | 70 +++++++-------- library/alloc/src/vec/mod.rs | 85 +++++++++++++------ library/alloc/tests/vec.rs | 9 ++ library/std/src/collections/hash/map.rs | 35 +++++--- library/std/src/collections/hash/set.rs | 25 ++++-- library/std/src/ffi/os_str.rs | 22 ++--- library/std/src/io/buffered/bufwriter.rs | 4 +- library/std/src/io/buffered/linewriter.rs | 4 +- 10 files changed, 191 insertions(+), 130 deletions(-) diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 3706300dcfeb7..197e7aaaccf3d 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -374,10 +374,11 @@ impl BinaryHeap { BinaryHeap { data: vec![] } } - /// Creates an empty `BinaryHeap` with a specific capacity. - /// This preallocates enough memory for `capacity` elements, - /// so that the `BinaryHeap` does not have to be reallocated - /// until it contains at least that many values. + /// Creates an empty `BinaryHeap` with at least the specified capacity. + /// + /// The binary heap will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the binary heap will not allocate. /// /// # Examples /// @@ -906,16 +907,18 @@ impl BinaryHeap { self.data.capacity() } - /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the - /// given `BinaryHeap`. Does nothing if the capacity is already sufficient. + /// Reserves the minimum capacity for at least `additional` elements more than + /// the current length. Unlike [`reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional`. Does nothing if the capacity is already + /// sufficient. /// - /// Note that the allocator may give the collection more space than it requests. Therefore - /// capacity can not be relied upon to be precisely minimal. Prefer [`reserve`] if future - /// insertions are expected. + /// [`reserve`]: BinaryHeap::reserve /// /// # Panics /// - /// Panics if the new capacity overflows `usize`. + /// Panics if the new capacity overflows [`usize`]. /// /// # Examples /// @@ -935,12 +938,15 @@ impl BinaryHeap { self.data.reserve_exact(additional); } - /// Reserves capacity for at least `additional` more elements to be inserted in the - /// `BinaryHeap`. The collection may reserve more space to avoid frequent reallocations. + /// Reserves capacity for at least `additional` elements more than the + /// current length. The allocator may reserve more space to speculatively + /// avoid frequent allocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if capacity is already sufficient. /// /// # Panics /// - /// Panics if the new capacity overflows `usize`. + /// Panics if the new capacity overflows [`usize`]. /// /// # Examples /// @@ -958,10 +964,11 @@ impl BinaryHeap { self.data.reserve(additional); } - /// Tries to reserve the minimum capacity for exactly `additional` - /// elements to be inserted in the given `BinaryHeap`. After calling - /// `try_reserve_exact`, capacity will be greater than or equal to - /// `self.len() + additional` if it returns `Ok(())`. + /// Tries to reserve the minimum capacity for at least `additional` elements + /// more than the current length. Unlike [`try_reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `try_reserve_exact`, capacity will be greater than or + /// equal to `self.len() + additional` if it returns `Ok(())`. /// Does nothing if the capacity is already sufficient. /// /// Note that the allocator may give the collection more space than it @@ -999,11 +1006,11 @@ impl BinaryHeap { self.data.try_reserve_exact(additional) } - /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given `BinaryHeap`. The collection may reserve more space to avoid - /// frequent reallocations. After calling `try_reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. + /// Tries to reserve capacity for at least `additional` elements more than the + /// current length. The allocator may reserve more space to speculatively + /// avoid frequent allocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional` if it returns + /// `Ok(())`. Does nothing if capacity is already sufficient. /// /// # Errors /// diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index f92e5759b6f9e..4d895d83745b2 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -688,7 +688,7 @@ impl VecDeque { self.cap() - 1 } - /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the + /// Reserves the minimum capacity for at least `additional` more elements to be inserted in the /// given deque. Does nothing if the capacity is already sufficient. /// /// Note that the allocator may give the collection more space than it requests. Therefore @@ -716,7 +716,7 @@ impl VecDeque { } /// Reserves capacity for at least `additional` more elements to be inserted in the given - /// deque. The collection may reserve more space to avoid frequent reallocations. + /// deque. The collection may reserve more space to speculatively avoid frequent reallocations. /// /// # Panics /// @@ -748,10 +748,10 @@ impl VecDeque { } } - /// Tries to reserve the minimum capacity for exactly `additional` more elements to + /// Tries to reserve the minimum capacity for at least `additional` more elements to /// be inserted in the given deque. After calling `try_reserve_exact`, - /// capacity will be greater than or equal to `self.len() + additional`. - /// Does nothing if the capacity is already sufficient. + /// capacity will be greater than or equal to `self.len() + additional` if + /// it returns `Ok(())`. Does nothing if the capacity is already sufficient. /// /// Note that the allocator may give the collection more space than it /// requests. Therefore, capacity can not be relied upon to be precisely @@ -791,10 +791,10 @@ impl VecDeque { } /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given deque. The collection may reserve more space to avoid + /// in the given deque. The collection may reserve more space to speculatively avoid /// frequent reallocations. After calling `try_reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. + /// greater than or equal to `self.len() + additional` if it returns + /// `Ok(())`. Does nothing if capacity is already sufficient. /// /// # Errors /// diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 668af60611b86..8883880726594 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -455,13 +455,13 @@ impl String { String { vec: Vec::new() } } - /// Creates a new empty `String` with a particular capacity. + /// Creates a new empty `String` with at least the specified capacity. /// /// `String`s have an internal buffer to hold their data. The capacity is /// the length of that buffer, and can be queried with the [`capacity`] /// method. This method creates an empty `String`, but one with an initial - /// buffer that can hold `capacity` bytes. This is useful when you may be - /// appending a bunch of data to the `String`, reducing the number of + /// buffer that can hold at least `capacity` bytes. This is useful when you + /// may be appending a bunch of data to the `String`, reducing the number of /// reallocations it needs to do. /// /// [`capacity`]: String::capacity @@ -979,21 +979,16 @@ impl String { self.vec.capacity() } - /// Ensures that this `String`'s capacity is at least `additional` bytes - /// larger than its length. - /// - /// The capacity may be increased by more than `additional` bytes if it - /// chooses, to prevent frequent reallocations. - /// - /// If you do not want this "at least" behavior, see the [`reserve_exact`] - /// method. + /// Reserves capacity for at least `additional` bytes more than the + /// current length. The allocator may reserve more space to speculatively + /// avoid frequent allocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if capacity is already sufficient. /// /// # Panics /// /// Panics if the new capacity overflows [`usize`]. /// - /// [`reserve_exact`]: String::reserve_exact - /// /// # Examples /// /// Basic usage: @@ -1013,15 +1008,16 @@ impl String { /// s.push('a'); /// s.push('b'); /// - /// // s now has a length of 2 and a capacity of 10 + /// // s now has a length of 2 and a capacity of at least 10 + /// let capacity = s.capacity(); /// assert_eq!(2, s.len()); - /// assert_eq!(10, s.capacity()); + /// assert!(capacity >= 10); /// - /// // Since we already have an extra 8 capacity, calling this... + /// // Since we already have at least an extra 8 capacity, calling this... /// s.reserve(8); /// /// // ... doesn't actually increase. - /// assert_eq!(10, s.capacity()); + /// assert_eq!(capacity, s.capacity()); /// ``` #[cfg(not(no_global_oom_handling))] #[inline] @@ -1030,17 +1026,18 @@ impl String { self.vec.reserve(additional) } - /// Ensures that this `String`'s capacity is `additional` bytes - /// larger than its length. - /// - /// Consider using the [`reserve`] method unless you absolutely know - /// better than the allocator. + /// Reserves the minimum capacity for at least `additional` bytes more than + /// the current length. Unlike [`reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional`. Does nothing if the capacity is already + /// sufficient. /// /// [`reserve`]: String::reserve /// /// # Panics /// - /// Panics if the new capacity overflows `usize`. + /// Panics if the new capacity overflows [`usize`]. /// /// # Examples /// @@ -1061,15 +1058,16 @@ impl String { /// s.push('a'); /// s.push('b'); /// - /// // s now has a length of 2 and a capacity of 10 + /// // s now has a length of 2 and a capacity of at least 10 + /// let capacity = s.capacity(); /// assert_eq!(2, s.len()); - /// assert_eq!(10, s.capacity()); + /// assert!(capacity >= 10); /// - /// // Since we already have an extra 8 capacity, calling this... + /// // Since we already have at least an extra 8 capacity, calling this... /// s.reserve_exact(8); /// /// // ... doesn't actually increase. - /// assert_eq!(10, s.capacity()); + /// assert_eq!(capacity, s.capacity()); /// ``` #[cfg(not(no_global_oom_handling))] #[inline] @@ -1078,11 +1076,11 @@ impl String { self.vec.reserve_exact(additional) } - /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given `String`. The collection may reserve more space to avoid - /// frequent reallocations. After calling `reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. + /// Tries to reserve capacity for at least `additional` bytes more than the + /// current length. The allocator may reserve more space to speculatively + /// avoid frequent allocations. After calling `try_reserve`, capacity will be + /// greater than or equal to `self.len() + additional` if it returns + /// `Ok(())`. Does nothing if capacity is already sufficient. /// /// # Errors /// @@ -1112,9 +1110,11 @@ impl String { self.vec.try_reserve(additional) } - /// Tries to reserve the minimum capacity for exactly `additional` more elements to - /// be inserted in the given `String`. After calling `try_reserve_exact`, - /// capacity will be greater than or equal to `self.len() + additional`. + /// Tries to reserve the minimum capacity for at least `additional` bytes + /// more than the current length. Unlike [`try_reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `try_reserve_exact`, capacity will be greater than or + /// equal to `self.len() + additional` if it returns `Ok(())`. /// Does nothing if the capacity is already sufficient. /// /// Note that the allocator may give the collection more space than it diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 1c0cb6636a134..e25f98d8aa695 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -425,17 +425,25 @@ impl Vec { Vec { buf: RawVec::NEW, len: 0 } } - /// Constructs a new, empty `Vec` with the specified capacity. + /// Constructs a new, empty `Vec` with at least the specified capacity. /// - /// The vector will be able to hold exactly `capacity` elements without - /// reallocating. If `capacity` is 0, the vector will not allocate. + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the vector will not allocate. /// /// It is important to note that although the returned vector has the - /// *capacity* specified, the vector will have a zero *length*. For an - /// explanation of the difference between length and capacity, see + /// minimum *capacity* specified, the vector will have a zero *length*. For + /// an explanation of the difference between length and capacity, see /// *[Capacity and reallocation]*. /// + /// If it is imporant to know the exact allocated capacity of a `Vec`, + /// always use the [`capacity`] method after construction. + /// + /// For `Vec` where `T` is a zero-sized type, there will be no allocation + /// and the capacity will always be `usize::MAX`. + /// /// [Capacity and reallocation]: #capacity-and-reallocation + /// [`capacity`]: Vec::capacity /// /// # Panics /// @@ -448,19 +456,24 @@ impl Vec { /// /// // The vector contains no items, even though it has capacity for more /// assert_eq!(vec.len(), 0); - /// assert_eq!(vec.capacity(), 10); + /// assert!(vec.capacity() >= 10); /// /// // These are all done without reallocating... /// for i in 0..10 { /// vec.push(i); /// } /// assert_eq!(vec.len(), 10); - /// assert_eq!(vec.capacity(), 10); + /// assert!(vec.capacity() >= 10); /// /// // ...but this may make the vector reallocate /// vec.push(11); /// assert_eq!(vec.len(), 11); /// assert!(vec.capacity() >= 11); + /// + /// // A vector of a zero-sized type will always over-allocate, since no + /// // allocation is necessary + /// let vec_units = Vec::<()>::with_capacity(10); + /// assert_eq!(vec_units.capacity(), usize::MAX); /// ``` #[cfg(not(no_global_oom_handling))] #[inline] @@ -566,18 +579,26 @@ impl Vec { Vec { buf: RawVec::new_in(alloc), len: 0 } } - /// Constructs a new, empty `Vec` with the specified capacity with the provided - /// allocator. + /// Constructs a new, empty `Vec` with at least the specified capacity + /// with the provided allocator. /// - /// The vector will be able to hold exactly `capacity` elements without - /// reallocating. If `capacity` is 0, the vector will not allocate. + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the vector will not allocate. /// /// It is important to note that although the returned vector has the - /// *capacity* specified, the vector will have a zero *length*. For an - /// explanation of the difference between length and capacity, see + /// minimum *capacity* specified, the vector will have a zero *length*. For + /// an explanation of the difference between length and capacity, see /// *[Capacity and reallocation]*. /// + /// If it is imporant to know the exact allocated capacity of a `Vec`, + /// always use the [`capacity`] method after construction. + /// + /// For `Vec` where `T` is a zero-sized type, there will be no allocation + /// and the capacity will always be `usize::MAX`. + /// /// [Capacity and reallocation]: #capacity-and-reallocation + /// [`capacity`]: Vec::capacity /// /// # Panics /// @@ -607,6 +628,11 @@ impl Vec { /// vec.push(11); /// assert_eq!(vec.len(), 11); /// assert!(vec.capacity() >= 11); + /// + /// // A vector of a zero-sized type will always over-allocate, since no + /// // allocation is necessary + /// let vec_units = Vec::<(), System>::with_capacity_in(10, System); + /// assert_eq!(vec_units.capacity(), usize::MAX); /// ``` #[cfg(not(no_global_oom_handling))] #[inline] @@ -793,10 +819,10 @@ impl Vec { } /// Reserves capacity for at least `additional` more elements to be inserted - /// in the given `Vec`. The collection may reserve more space to avoid - /// frequent reallocations. After calling `reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. + /// in the given `Vec`. The collection may reserve more space to + /// speculatively avoid frequent reallocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if capacity is already sufficient. /// /// # Panics /// @@ -815,10 +841,12 @@ impl Vec { self.buf.reserve(self.len, additional); } - /// Reserves the minimum capacity for exactly `additional` more elements to - /// be inserted in the given `Vec`. After calling `reserve_exact`, - /// capacity will be greater than or equal to `self.len() + additional`. - /// Does nothing if the capacity is already sufficient. + /// Reserves the minimum capacity for at least `additional` more elements to + /// be inserted in the given `Vec`. Unlike [`reserve`], this will not + /// deliberately over-allocate to speculatively avoid frequent allocations. + /// After calling `reserve_exact`, capacity will be greater than or equal to + /// `self.len() + additional`. Does nothing if the capacity is already + /// sufficient. /// /// Note that the allocator may give the collection more space than it /// requests. Therefore, capacity can not be relied upon to be precisely @@ -844,10 +872,10 @@ impl Vec { } /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given `Vec`. The collection may reserve more space to avoid + /// in the given `Vec`. The collection may reserve more space to speculatively avoid /// frequent reallocations. After calling `try_reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. + /// greater than or equal to `self.len() + additional` if it returns + /// `Ok(())`. Does nothing if capacity is already sufficient. /// /// # Errors /// @@ -879,10 +907,11 @@ impl Vec { self.buf.try_reserve(self.len, additional) } - /// Tries to reserve the minimum capacity for exactly `additional` - /// elements to be inserted in the given `Vec`. After calling - /// `try_reserve_exact`, capacity will be greater than or equal to - /// `self.len() + additional` if it returns `Ok(())`. + /// Tries to reserve the minimum capacity for at least `additional` + /// elements to be inserted in the given `Vec`. Unlike [`try_reserve`], + /// this will not deliberately over-allocate to speculatively avoid frequent + /// allocations. After calling `try_reserve_exact`, capacity will be greater + /// than or equal to `self.len() + additional` if it returns `Ok(())`. /// Does nothing if the capacity is already sufficient. /// /// Note that the allocator may give the collection more space than it diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index cc768c73c0e03..5520f6ebf1904 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -2128,6 +2128,15 @@ fn test_vec_cycle_wrapped() { c3.refs.v[1].set(Some(&c2)); } +#[test] +fn test_zero_sized_capacity() { + for len in [0, 1, 2, 4, 8, 16, 32, 64, 128, 256] { + let v = Vec::<()>::with_capacity(len); + assert_eq!(v.len(), 0); + assert_eq!(v.capacity(), usize::MAX); + } +} + #[test] fn test_zero_sized_vec_push() { const N: usize = 8; diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 192a21f2ffc2d..499c997a36ab2 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -233,10 +233,11 @@ impl HashMap { Default::default() } - /// Creates an empty `HashMap` with the specified capacity. + /// Creates an empty `HashMap` with at least the specified capacity. /// /// The hash map will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash map will not allocate. + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the hash set will not allocate. /// /// # Examples /// @@ -282,18 +283,19 @@ impl HashMap { HashMap { base: base::HashMap::with_hasher(hash_builder) } } - /// Creates an empty `HashMap` with the specified capacity, using `hash_builder` - /// to hash the keys. + /// Creates an empty `HashMap` with at least the specified capacity, using + /// `hasher` to hash the keys. /// /// The hash map will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash map will not allocate. + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the hash map will not allocate. /// - /// Warning: `hash_builder` is normally randomly generated, and + /// Warning: `hasher` is normally randomly generated, and /// is designed to allow HashMaps to be resistant to attacks that /// cause many collisions and very poor performance. Setting it /// manually using this function can expose a DoS attack vector. /// - /// The `hash_builder` passed should implement the [`BuildHasher`] trait for + /// The `hasher` passed should implement the [`BuildHasher`] trait for /// the HashMap to be useful, see its documentation for details. /// /// # Examples @@ -308,8 +310,8 @@ impl HashMap { /// ``` #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] - pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap { - HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder) } + pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashMap { + HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hasher) } } /// Returns the number of elements the map can hold without reallocating. @@ -731,8 +733,10 @@ where S: BuildHasher, { /// Reserves capacity for at least `additional` more elements to be inserted - /// in the `HashMap`. The collection may reserve more space to avoid - /// frequent reallocations. + /// in the `HashMap`. The collection may reserve more space to speculatively + /// avoid frequent reallocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if capacity is already sufficient. /// /// # Panics /// @@ -752,8 +756,11 @@ where } /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given `HashMap`. The collection may reserve more space to avoid - /// frequent reallocations. + /// in the `HashMap`. The collection may reserve more space to speculatively + /// avoid frequent reallocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional` if + /// it returns `Ok(())`. + /// Does nothing if capacity is already sufficient. /// /// # Errors /// @@ -766,7 +773,7 @@ where /// use std::collections::HashMap; /// /// let mut map: HashMap<&str, isize> = HashMap::new(); - /// map.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); + /// map.try_reserve(10).expect("why is the test harness OOMing on a handful of bytes?"); /// ``` #[inline] #[stable(feature = "try_reserve", since = "1.57.0")] diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index fa498a987d6af..abff82788a38d 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -133,10 +133,11 @@ impl HashSet { Default::default() } - /// Creates an empty `HashSet` with the specified capacity. + /// Creates an empty `HashSet` with at least the specified capacity. /// /// The hash set will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash set will not allocate. + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the hash set will not allocate. /// /// # Examples /// @@ -379,11 +380,12 @@ impl HashSet { HashSet { base: base::HashSet::with_hasher(hasher) } } - /// Creates an empty `HashSet` with the specified capacity, using + /// Creates an empty `HashSet` with at least the specified capacity, using /// `hasher` to hash the keys. /// /// The hash set will be able to hold at least `capacity` elements without - /// reallocating. If `capacity` is 0, the hash set will not allocate. + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the hash set will not allocate. /// /// Warning: `hasher` is normally randomly generated, and /// is designed to allow `HashSet`s to be resistant to attacks that @@ -434,8 +436,10 @@ where S: BuildHasher, { /// Reserves capacity for at least `additional` more elements to be inserted - /// in the `HashSet`. The collection may reserve more space to avoid - /// frequent reallocations. + /// in the `HashSet`. The collection may reserve more space to speculatively + /// avoid frequent reallocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional`. + /// Does nothing if capacity is already sufficient. /// /// # Panics /// @@ -456,8 +460,11 @@ where } /// Tries to reserve capacity for at least `additional` more elements to be inserted - /// in the given `HashSet`. The collection may reserve more space to avoid - /// frequent reallocations. + /// in the `HashSet`. The collection may reserve more space to speculatively + /// avoid frequent reallocations. After calling `reserve`, + /// capacity will be greater than or equal to `self.len() + additional` if + /// it returns `Ok(())`. + /// Does nothing if capacity is already sufficient. /// /// # Errors /// @@ -469,7 +476,7 @@ where /// ``` /// use std::collections::HashSet; /// let mut set: HashSet = HashSet::new(); - /// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?"); + /// set.try_reserve(10).expect("why is the test harness OOMing on a handful of bytes?"); /// ``` #[inline] #[stable(feature = "try_reserve", since = "1.57.0")] diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 95d274c3c91e7..f2bbcc85cecda 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -196,10 +196,11 @@ impl OsString { self.inner.push_slice(&s.as_ref().inner) } - /// Creates a new `OsString` with the given capacity. + /// Creates a new `OsString` with at least the given capacity. /// - /// The string will be able to hold exactly `capacity` length units of other - /// OS strings without reallocating. If `capacity` is 0, the string will not + /// The string will be able to hold at least `capacity` length units of other + /// OS strings without reallocating. This method is allowed to allocate for + /// more units than `capacity`. If `capacity` is 0, the string will not /// allocate. /// /// See the main `OsString` documentation information about encoding and capacity units. @@ -263,9 +264,10 @@ impl OsString { } /// Reserves capacity for at least `additional` more capacity to be inserted - /// in the given `OsString`. + /// in the given `OsString`. Does nothing if the capacity is + /// already sufficient. /// - /// The collection may reserve more space to avoid frequent reallocations. + /// The collection may reserve more space to speculatively avoid frequent reallocations. /// /// See the main `OsString` documentation information about encoding and capacity units. /// @@ -285,10 +287,10 @@ impl OsString { } /// Tries to reserve capacity for at least `additional` more length units - /// in the given `OsString`. The string may reserve more space to avoid + /// in the given `OsString`. The string may reserve more space to speculatively avoid /// frequent reallocations. After calling `try_reserve`, capacity will be - /// greater than or equal to `self.len() + additional`. Does nothing if - /// capacity is already sufficient. + /// greater than or equal to `self.len() + additional` if it returns `Ok(())`. + /// Does nothing if capacity is already sufficient. /// /// See the main `OsString` documentation information about encoding and capacity units. /// @@ -322,7 +324,7 @@ impl OsString { self.inner.try_reserve(additional) } - /// Reserves the minimum capacity for exactly `additional` more capacity to + /// Reserves the minimum capacity for at least `additional` more capacity to /// be inserted in the given `OsString`. Does nothing if the capacity is /// already sufficient. /// @@ -349,7 +351,7 @@ impl OsString { self.inner.reserve_exact(additional) } - /// Tries to reserve the minimum capacity for exactly `additional` + /// Tries to reserve the minimum capacity for at least `additional` /// more length units in the given `OsString`. After calling /// `try_reserve_exact`, capacity will be greater than or equal to /// `self.len() + additional` if it returns `Ok(())`. diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 2d3a0f37b4c2a..6acb937e78479 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -97,11 +97,11 @@ impl BufWriter { BufWriter::with_capacity(DEFAULT_BUF_SIZE, inner) } - /// Creates a new `BufWriter` with the specified buffer capacity. + /// Creates a new `BufWriter` with at least the specified buffer capacity. /// /// # Examples /// - /// Creating a buffer with a buffer of a hundred bytes. + /// Creating a buffer with a buffer of at least a hundred bytes. /// /// ```no_run /// use std::io::BufWriter; diff --git a/library/std/src/io/buffered/linewriter.rs b/library/std/src/io/buffered/linewriter.rs index d7b620d6f9177..a26a4ab330e7a 100644 --- a/library/std/src/io/buffered/linewriter.rs +++ b/library/std/src/io/buffered/linewriter.rs @@ -89,8 +89,8 @@ impl LineWriter { LineWriter::with_capacity(1024, inner) } - /// Creates a new `LineWriter` with a specified capacity for the internal - /// buffer. + /// Creates a new `LineWriter` with at least the specified capacity for the + /// internal buffer. /// /// # Examples /// From 1deca0425db3e74a61cb732e729c0777904e549c Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 19 Jun 2022 13:59:36 -0500 Subject: [PATCH 02/28] Greatly improve error reporting for futures and generators in `note_obligation_cause_code` Most futures don't go through this code path, because they're caught by `maybe_note_obligation_cause_for_async_await`. But all generators do, and `maybe_note` is imperfect and doesn't catch all futures. Improve the error message for those it misses. At some point, we may want to consider unifying this with the code for `maybe_note_async_await`, so that `async_await` notes all parent constraints, and `note_obligation` can point to yield points. But both functions are quite complicated, and it's not clear to me how to combine them; this seems like a good incremental improvement. --- .../src/traits/error_reporting/suggestions.rs | 105 ++++++++++++++++-- src/test/ui/async-await/issue-68112.stderr | 30 +++-- ...e-70935-complex-spans.drop_tracking.stderr | 40 +++++++ ...> issue-70935-complex-spans.normal.stderr} | 8 +- .../async-await/issue-70935-complex-spans.rs | 16 ++- .../partial-drop-partial-reinit.rs | 8 ++ .../partial-drop-partial-reinit.stderr | 20 +++- src/test/ui/closures/closure-move-sync.stderr | 16 ++- src/test/ui/generator/issue-68112.rs | 22 +++- src/test/ui/generator/issue-68112.stderr | 41 +++++-- src/test/ui/generator/not-send-sync.stderr | 11 +- .../print/generator-print-verbose-1.stderr | 33 +++++- .../print/generator-print-verbose-2.stderr | 11 +- src/test/ui/impl-trait/auto-trait-leak2.rs | 18 ++- .../ui/impl-trait/auto-trait-leak2.stderr | 32 ++++-- .../interior-mutability.stderr | 6 +- .../ui/kindck/kindck-nonsendable-1.stderr | 6 +- src/test/ui/no-send-res-ports.stderr | 11 +- src/test/ui/not-clone-closure.stderr | 9 +- .../auto-trait-leakage2.rs | 8 +- .../auto-trait-leakage2.stderr | 10 +- 21 files changed, 389 insertions(+), 72 deletions(-) create mode 100644 src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr rename src/test/ui/async-await/{issue-70935-complex-spans.stderr => issue-70935-complex-spans.normal.stderr} (81%) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 09b73b982a0c1..159fcf932a1da 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -8,6 +8,7 @@ use crate::infer::InferCtxt; use crate::traits::normalize_to; use hir::HirId; +use rustc_ast::Movability; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ @@ -2397,24 +2398,104 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { { let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); - let ty = parent_trait_ref.skip_binder().self_ty(); - matches!(ty.kind(), ty::Generator(..)) - || matches!(ty.kind(), ty::Closure(..)) + let nested_ty = parent_trait_ref.skip_binder().self_ty(); + matches!(nested_ty.kind(), ty::Generator(..)) + || matches!(nested_ty.kind(), ty::Closure(..)) } else { false } }; + let future_trait = self.tcx.lang_items().future_trait().unwrap(); + let opaque_ty_is_future = |def_id| { + self.tcx.explicit_item_bounds(def_id).iter().any(|(predicate, _)| { + if let ty::PredicateKind::Trait(trait_predicate) = + predicate.kind().skip_binder() + { + trait_predicate.trait_ref.def_id == future_trait + } else { + false + } + }) + }; + + let from_generator = tcx.lang_items().from_generator_fn().unwrap(); + // Don't print the tuple of capture types - if !is_upvar_tys_infer_tuple { - let msg = format!("required because it appears within the type `{}`", ty); - match ty.kind() { - ty::Adt(def, _) => match self.tcx.opt_item_ident(def.did()) { - Some(ident) => err.span_note(ident.span, &msg), - None => err.note(&msg), - }, - _ => err.note(&msg), - }; + 'print: { + if !is_upvar_tys_infer_tuple { + let msg = format!("required because it appears within the type `{}`", ty); + match ty.kind() { + ty::Adt(def, _) => { + // `gen_future` is used in all async functions; it doesn't add any additional info. + if self.tcx.is_diagnostic_item(sym::gen_future, def.did()) { + break 'print; + } + match self.tcx.opt_item_ident(def.did()) { + Some(ident) => err.span_note(ident.span, &msg), + None => err.note(&msg), + } + } + ty::Opaque(def_id, _) => { + // Avoid printing the future from `core::future::from_generator`, it's not helpful + if tcx.parent(*def_id) == from_generator { + break 'print; + } + + // If the previous type is `from_generator`, this is the future generated by the body of an async function. + // Avoid printing it twice (it was already printed in the `ty::Generator` arm below). + let is_future = opaque_ty_is_future(def_id); + debug!( + ?obligated_types, + ?is_future, + "note_obligation_cause_code: check for async fn" + ); + if opaque_ty_is_future(def_id) + && obligated_types.last().map_or(false, |ty| match ty.kind() { + ty::Opaque(last_def_id, _) => { + tcx.parent(*last_def_id) == from_generator + } + _ => false, + }) + { + break 'print; + } + err.span_note(self.tcx.def_span(def_id), &msg) + } + ty::GeneratorWitness(bound_tys) => { + use std::fmt::Write; + + // FIXME: this is kind of an unusual format for rustc, can we make it more clear? + // Maybe we should just remove this note altogether? + // FIXME: only print types which don't meet the trait requirement + let mut msg = + "required because it captures the following types: ".to_owned(); + for ty in bound_tys.skip_binder() { + write!(msg, "`{}`, ", ty).unwrap(); + } + err.note(msg.trim_end_matches(", ")) + } + ty::Generator(def_id, _, movability) => { + let sp = self.tcx.def_span(def_id); + + // Special-case this to say "async block" instead of `[static generator]`. + let kind = if *movability == Movability::Static { + "async block" + } else { + "generator" + }; + err.span_note( + sp, + &format!("required because it's used within this {}", kind), + ) + } + ty::Closure(def_id, _) => err.span_note( + self.tcx.def_span(def_id), + &format!("required because it's used within this closure"), + ), + _ => err.note(&msg), + }; + } } obligated_types.push(ty); diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr index 28d94b14ac914..b8d3e1540d8a9 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.stderr @@ -42,15 +42,27 @@ LL | require_send(send_fut); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` - = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:47:31: 47:36]` - = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:47:31: 47:36]>` - = note: required because it appears within the type `impl Future>>` - = note: required because it appears within the type `impl Future>>` - = note: required because it appears within the type `impl Future>>` - = note: required because it appears within the type `{ResumeTy, impl Future>>, (), i32, Ready}` - = note: required because it appears within the type `[static generator@$DIR/issue-68112.rs:55:26: 59:6]` - = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/issue-68112.rs:55:26: 59:6]>` - = note: required because it appears within the type `impl Future` +note: required because it's used within this async block + --> $DIR/issue-68112.rs:47:31 + | +LL | async fn ready2(t: T) -> T { t } + | ^^^^^ +note: required because it appears within the type `impl Future>>` + --> $DIR/issue-68112.rs:48:31 + | +LL | fn make_non_send_future2() -> impl Future>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because it captures the following types: `ResumeTy`, `impl Future>>`, `()`, `i32`, `Ready` +note: required because it's used within this async block + --> $DIR/issue-68112.rs:55:26 + | +LL | let send_fut = async { + | __________________________^ +LL | | let non_send_fut = make_non_send_future2(); +LL | | let _ = non_send_fut.await; +LL | | ready(0).await; +LL | | }; + | |_____^ note: required by a bound in `require_send` --> $DIR/issue-68112.rs:11:25 | diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr new file mode 100644 index 0000000000000..19fd5eb7c73fb --- /dev/null +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -0,0 +1,40 @@ +error[E0277]: `Sender` cannot be shared between threads safely + --> $DIR/issue-70935-complex-spans.rs:13:45 + | +LL | fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { + | ^^^^^^^^^^^^^^^^^^ `Sender` cannot be shared between threads safely + | + = help: the trait `Sync` is not implemented for `Sender` + = note: required because of the requirements on the impl of `Send` for `&Sender` +note: required because it's used within this closure + --> $DIR/issue-70935-complex-spans.rs:25:13 + | +LL | baz(|| async{ + | _____________^ +LL | | foo(tx.clone()); +LL | | }).await; + | |_________^ +note: required because it's used within this async block + --> $DIR/issue-70935-complex-spans.rs:9:67 + | +LL | async fn baz(_c: impl FnMut() -> T) where T: Future { + | ___________________________________________________________________^ +LL | | +LL | | } + | |_^ + = note: required because it captures the following types: `ResumeTy`, `impl Future`, `()` +note: required because it's used within this async block + --> $DIR/issue-70935-complex-spans.rs:23:16 + | +LL | async move { + | ________________^ +LL | | +LL | | baz(|| async{ +LL | | foo(tx.clone()); +LL | | }).await; +LL | | } + | |_____^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/issue-70935-complex-spans.stderr b/src/test/ui/async-await/issue-70935-complex-spans.normal.stderr similarity index 81% rename from src/test/ui/async-await/issue-70935-complex-spans.stderr rename to src/test/ui/async-await/issue-70935-complex-spans.normal.stderr index db3099381196b..2174f260a7135 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.normal.stderr @@ -1,12 +1,12 @@ error: future cannot be sent between threads safely - --> $DIR/issue-70935-complex-spans.rs:10:45 + --> $DIR/issue-70935-complex-spans.rs:13:45 | LL | fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { | ^^^^^^^^^^^^^^^^^^ future created by async block is not `Send` | = help: the trait `Sync` is not implemented for `Sender` note: future is not `Send` as this value is used across an await - --> $DIR/issue-70935-complex-spans.rs:15:11 + --> $DIR/issue-70935-complex-spans.rs:27:11 | LL | baz(|| async{ | _____________- @@ -14,9 +14,9 @@ LL | | foo(tx.clone()); LL | | }).await; | | - ^^^^^^ await occurs here, with the value maybe used later | |_________| - | has type `[closure@$DIR/issue-70935-complex-spans.rs:13:13: 15:10]` which is not `Send` + | has type `[closure@$DIR/issue-70935-complex-spans.rs:25:13: 27:10]` which is not `Send` note: the value is later dropped here - --> $DIR/issue-70935-complex-spans.rs:15:17 + --> $DIR/issue-70935-complex-spans.rs:27:17 | LL | }).await; | ^ diff --git a/src/test/ui/async-await/issue-70935-complex-spans.rs b/src/test/ui/async-await/issue-70935-complex-spans.rs index 2965a7e0654a4..4bf94fe342c1d 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.rs +++ b/src/test/ui/async-await/issue-70935-complex-spans.rs @@ -1,16 +1,28 @@ // edition:2018 +// revisions: normal drop_tracking +// [drop_tracking]compile-flags:-Zdrop-tracking // #70935: Check if we do not emit snippet // with newlines which lead complex diagnostics. use std::future::Future; async fn baz(_c: impl FnMut() -> T) where T: Future { +//[drop_tracking]~^ within this async block } fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { - //~^ ERROR: future cannot be sent between threads safely + //[normal]~^ ERROR: future cannot be sent between threads safely + //[drop_tracking]~^^ ERROR: `Sender` cannot be shared + //[drop_tracking]~| NOTE: cannot be shared + //[drop_tracking]~| NOTE: requirements on the impl of `Send` + //[drop_tracking]~| NOTE: captures the following types + //[drop_tracking]~| NOTE: in this expansion + //[drop_tracking]~| NOTE: in this expansion + //[drop_tracking]~| NOTE: in this expansion + //[drop_tracking]~| NOTE: in this expansion async move { - baz(|| async{ + //[drop_tracking]~^ within this async block + baz(|| async{ //[drop_tracking]~ NOTE: used within this closure foo(tx.clone()); }).await; } diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.rs b/src/test/ui/async-await/partial-drop-partial-reinit.rs index 73f0ca8153cb9..4fcfacea3f886 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.rs +++ b/src/test/ui/async-await/partial-drop-partial-reinit.rs @@ -5,9 +5,15 @@ fn main() { gimme_send(foo()); //~^ ERROR cannot be sent between threads safely + //~| NOTE cannot be sent + //~| NOTE bound introduced by + //~| NOTE appears within the type + //~| NOTE captures the following types } fn gimme_send(t: T) { +//~^ NOTE required by this bound +//~| NOTE required by a bound drop(t); } @@ -20,6 +26,8 @@ impl Drop for NotSend { impl !Send for NotSend {} async fn foo() { +//~^ NOTE used within this async block +//~| NOTE within this `impl Future let mut x = (NotSend {},); drop(x.0); x.0 = NotSend {}; diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.stderr index a1c4957e9843a..96d0c71f103fb 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.stderr +++ b/src/test/ui/async-await/partial-drop-partial-reinit.stderr @@ -11,13 +11,21 @@ LL | async fn foo() { | = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` = note: required because it appears within the type `(NotSend,)` - = note: required because it appears within the type `{ResumeTy, (NotSend,), impl Future, ()}` - = note: required because it appears within the type `[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]` - = note: required because it appears within the type `std::future::from_generator::GenFuture<[static generator@$DIR/partial-drop-partial-reinit.rs:22:16: 27:2]>` - = note: required because it appears within the type `impl Future` - = note: required because it appears within the type `impl Future` + = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future`, `()` +note: required because it's used within this async block + --> $DIR/partial-drop-partial-reinit.rs:28:16 + | +LL | async fn foo() { + | ________________^ +LL | | +LL | | +LL | | let mut x = (NotSend {},); +... | +LL | | bar().await; +LL | | } + | |_^ note: required by a bound in `gimme_send` - --> $DIR/partial-drop-partial-reinit.rs:10:18 + --> $DIR/partial-drop-partial-reinit.rs:14:18 | LL | fn gimme_send(t: T) { | ^^^^ required by this bound in `gimme_send` diff --git a/src/test/ui/closures/closure-move-sync.stderr b/src/test/ui/closures/closure-move-sync.stderr index 618c9a172473c..cbc4e2e52315f 100644 --- a/src/test/ui/closures/closure-move-sync.stderr +++ b/src/test/ui/closures/closure-move-sync.stderr @@ -6,7 +6,15 @@ LL | let t = thread::spawn(|| { | = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>` = note: required because of the requirements on the impl of `Send` for `&std::sync::mpsc::Receiver<()>` - = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:6:27: 9:6]` +note: required because it's used within this closure + --> $DIR/closure-move-sync.rs:6:27 + | +LL | let t = thread::spawn(|| { + | ___________________________^ +LL | | recv.recv().unwrap(); +LL | | +LL | | }); + | |_____^ note: required by a bound in `spawn` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL | @@ -21,7 +29,11 @@ LL | thread::spawn(|| tx.send(()).unwrap()); | = help: the trait `Sync` is not implemented for `Sender<()>` = note: required because of the requirements on the impl of `Send` for `&Sender<()>` - = note: required because it appears within the type `[closure@$DIR/closure-move-sync.rs:18:19: 18:42]` +note: required because it's used within this closure + --> $DIR/closure-move-sync.rs:18:19 + | +LL | thread::spawn(|| tx.send(()).unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `spawn` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL | diff --git a/src/test/ui/generator/issue-68112.rs b/src/test/ui/generator/issue-68112.rs index feb07c9bf8802..3fcef773b68ab 100644 --- a/src/test/ui/generator/issue-68112.rs +++ b/src/test/ui/generator/issue-68112.rs @@ -20,6 +20,10 @@ pub fn make_gen1(t: T) -> Ready { } fn require_send(_: impl Send) {} +//~^ NOTE required by a bound +//~| NOTE required by a bound +//~| NOTE required by this bound +//~| NOTE required by this bound fn make_non_send_generator() -> impl Generator>> { make_gen1(Arc::new(RefCell::new(0))) @@ -28,29 +32,39 @@ fn make_non_send_generator() -> impl Generator>> { fn test1() { let send_gen = || { let _non_send_gen = make_non_send_generator(); + //~^ NOTE not `Send` yield; - }; + //~^ NOTE yield occurs here + //~| NOTE value is used across a yield + }; //~ NOTE later dropped here require_send(send_gen); //~^ ERROR generator cannot be sent between threads + //~| NOTE not `Send` } pub fn make_gen2(t: T) -> impl Generator { - || { +//~^ NOTE appears within the type +//~| NOTE expansion of desugaring + || { //~ NOTE used within this generator yield; t } } -fn make_non_send_generator2() -> impl Generator>> { +fn make_non_send_generator2() -> impl Generator>> { //~ NOTE appears within the type +//~^ NOTE expansion of desugaring make_gen2(Arc::new(RefCell::new(0))) } fn test2() { - let send_gen = || { + let send_gen = || { //~ NOTE used within this generator let _non_send_gen = make_non_send_generator2(); yield; }; require_send(send_gen); //~^ ERROR `RefCell` cannot be shared between threads safely + //~| NOTE `RefCell` cannot be shared between threads safely + //~| NOTE requirements on the impl + //~| NOTE captures the following types } fn main() {} diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr index a7d7a73254886..83f068c207643 100644 --- a/src/test/ui/generator/issue-68112.stderr +++ b/src/test/ui/generator/issue-68112.stderr @@ -1,17 +1,19 @@ error: generator cannot be sent between threads safely - --> $DIR/issue-68112.rs:33:5 + --> $DIR/issue-68112.rs:40:5 | LL | require_send(send_gen); | ^^^^^^^^^^^^ generator is not `Send` | = help: the trait `Sync` is not implemented for `RefCell` note: generator is not `Send` as this value is used across a yield - --> $DIR/issue-68112.rs:31:9 + --> $DIR/issue-68112.rs:36:9 | LL | let _non_send_gen = make_non_send_generator(); | ------------- has type `impl Generator>>` which is not `Send` +LL | LL | yield; | ^^^^^ yield occurs here, with `_non_send_gen` maybe used later +... LL | }; | - `_non_send_gen` is later dropped here note: required by a bound in `require_send` @@ -21,18 +23,41 @@ LL | fn require_send(_: impl Send) {} | ^^^^ required by this bound in `require_send` error[E0277]: `RefCell` cannot be shared between threads safely - --> $DIR/issue-68112.rs:52:5 + --> $DIR/issue-68112.rs:63:5 | LL | require_send(send_gen); | ^^^^^^^^^^^^ `RefCell` cannot be shared between threads safely | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` - = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:38:5: 41:6]` - = note: required because it appears within the type `impl Generator>>` - = note: required because it appears within the type `impl Generator>>` - = note: required because it appears within the type `{impl Generator>>, ()}` - = note: required because it appears within the type `[generator@$DIR/issue-68112.rs:48:20: 51:6]` +note: required because it's used within this generator + --> $DIR/issue-68112.rs:48:5 + | +LL | / || { +LL | | yield; +LL | | t +LL | | } + | |_____^ +note: required because it appears within the type `impl Generator>>` + --> $DIR/issue-68112.rs:45:30 + | +LL | pub fn make_gen2(t: T) -> impl Generator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `impl Generator>>` + --> $DIR/issue-68112.rs:53:34 + | +LL | fn make_non_send_generator2() -> impl Generator>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because it captures the following types: `impl Generator>>`, `()` +note: required because it's used within this generator + --> $DIR/issue-68112.rs:59:20 + | +LL | let send_gen = || { + | ____________________^ +LL | | let _non_send_gen = make_non_send_generator2(); +LL | | yield; +LL | | }; + | |_____^ note: required by a bound in `require_send` --> $DIR/issue-68112.rs:22:25 | diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr index 4d2faa198f1af..edf9ee628a2bc 100644 --- a/src/test/ui/generator/not-send-sync.stderr +++ b/src/test/ui/generator/not-send-sync.stderr @@ -6,7 +6,16 @@ LL | assert_send(|| { | = help: the trait `Sync` is not implemented for `Cell` = note: required because of the requirements on the impl of `Send` for `&Cell` - = note: required because it appears within the type `[generator@$DIR/not-send-sync.rs:16:17: 20:6]` +note: required because it's used within this generator + --> $DIR/not-send-sync.rs:16:17 + | +LL | assert_send(|| { + | _________________^ +LL | | +LL | | drop(&a); +LL | | yield; +LL | | }); + | |_____^ note: required by a bound in `assert_send` --> $DIR/not-send-sync.rs:7:23 | diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr index 2f7faf520d969..3ee4c1458bad3 100644 --- a/src/test/ui/generator/print/generator-print-verbose-1.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr @@ -28,11 +28,34 @@ LL | require_send(send_gen); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` - = note: required because it appears within the type `[make_gen2>>::{closure#0} upvar_tys=(Arc>) {()}]` - = note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc>])` - = note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])` - = note: required because it appears within the type `{Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), []), ()}` - = note: required because it appears within the type `[test2::{closure#0} upvar_tys=() {Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), []), ()}]` +note: required because it's used within this generator + --> $DIR/generator-print-verbose-1.rs:42:5 + | +LL | / || { +LL | | yield; +LL | | t +LL | | } + | |_____^ +note: required because it appears within the type `Opaque(DefId(0:39 ~ generator_print_verbose_1[749a]::make_gen2::{opaque#0}), [std::sync::Arc>])` + --> $DIR/generator-print-verbose-1.rs:41:30 + | +LL | pub fn make_gen2(t: T) -> impl Generator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])` + --> $DIR/generator-print-verbose-1.rs:47:34 + | +LL | fn make_non_send_generator2() -> impl Generator>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: required because it captures the following types: `Opaque(DefId(0:42 ~ generator_print_verbose_1[749a]::make_non_send_generator2::{opaque#0}), [])`, `()` +note: required because it's used within this generator + --> $DIR/generator-print-verbose-1.rs:52:20 + | +LL | let send_gen = || { + | ____________________^ +LL | | let _non_send_gen = make_non_send_generator2(); +LL | | yield; +LL | | }; + | |_____^ note: required by a bound in `require_send` --> $DIR/generator-print-verbose-1.rs:26:25 | diff --git a/src/test/ui/generator/print/generator-print-verbose-2.stderr b/src/test/ui/generator/print/generator-print-verbose-2.stderr index fb2a5754dd306..1356fa5f15295 100644 --- a/src/test/ui/generator/print/generator-print-verbose-2.stderr +++ b/src/test/ui/generator/print/generator-print-verbose-2.stderr @@ -6,7 +6,16 @@ LL | assert_send(|| { | = help: the trait `Sync` is not implemented for `Cell` = note: required because of the requirements on the impl of `Send` for `&'_#4r Cell` - = note: required because it appears within the type `[main::{closure#1} upvar_tys=(&'_#4r Cell) _#17t]` +note: required because it's used within this generator + --> $DIR/generator-print-verbose-2.rs:19:17 + | +LL | assert_send(|| { + | _________________^ +LL | | +LL | | drop(&a); +LL | | yield; +LL | | }); + | |_____^ note: required by a bound in `assert_send` --> $DIR/generator-print-verbose-2.rs:10:23 | diff --git a/src/test/ui/impl-trait/auto-trait-leak2.rs b/src/test/ui/impl-trait/auto-trait-leak2.rs index a464f576dc783..09450089adaa8 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.rs +++ b/src/test/ui/impl-trait/auto-trait-leak2.rs @@ -3,23 +3,37 @@ use std::rc::Rc; // Fast path, main can see the concrete type returned. fn before() -> impl Fn(i32) { +//~^ NOTE within this `impl Fn +//~| NOTE within the type `impl Fn +//~| NOTE expansion of desugaring let p = Rc::new(Cell::new(0)); - move |x| p.set(x) + move |x| p.set(x) //~ NOTE used within this closure } fn send(_: T) {} +//~^ NOTE required by a bound +//~| NOTE required by a bound +//~| NOTE required by this bound +//~| NOTE required by this bound fn main() { send(before()); //~^ ERROR `Rc>` cannot be sent between threads safely + //~| NOTE `Rc>` cannot be sent between threads safely + //~| NOTE required by a bound send(after()); //~^ ERROR `Rc>` cannot be sent between threads safely + //~| NOTE `Rc>` cannot be sent between threads safely + //~| NOTE required by a bound } // Deferred path, main has to wait until typeck finishes, // to check if the return type of after is Send. fn after() -> impl Fn(i32) { +//~^ NOTE within this `impl Fn(i32)` +//~| NOTE in this expansion +//~| NOTE appears within the type let p = Rc::new(Cell::new(0)); - move |x| p.set(x) + move |x| p.set(x) //~ NOTE used within this closure } diff --git a/src/test/ui/impl-trait/auto-trait-leak2.stderr b/src/test/ui/impl-trait/auto-trait-leak2.stderr index 37ae3c6802964..d825843492d49 100644 --- a/src/test/ui/impl-trait/auto-trait-leak2.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak2.stderr @@ -1,5 +1,5 @@ error[E0277]: `Rc>` cannot be sent between threads safely - --> $DIR/auto-trait-leak2.rs:13:10 + --> $DIR/auto-trait-leak2.rs:20:10 | LL | fn before() -> impl Fn(i32) { | ------------ within this `impl Fn(i32)` @@ -10,16 +10,24 @@ LL | send(before()); | required by a bound introduced by this call | = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>` - = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:7:5: 7:22]` - = note: required because it appears within the type `impl Fn(i32)` +note: required because it's used within this closure + --> $DIR/auto-trait-leak2.rs:10:5 + | +LL | move |x| p.set(x) + | ^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `impl Fn(i32)` + --> $DIR/auto-trait-leak2.rs:5:16 + | +LL | fn before() -> impl Fn(i32) { + | ^^^^^^^^^^^^ note: required by a bound in `send` - --> $DIR/auto-trait-leak2.rs:10:12 + --> $DIR/auto-trait-leak2.rs:13:12 | LL | fn send(_: T) {} | ^^^^ required by this bound in `send` error[E0277]: `Rc>` cannot be sent between threads safely - --> $DIR/auto-trait-leak2.rs:16:10 + --> $DIR/auto-trait-leak2.rs:25:10 | LL | send(after()); | ---- ^^^^^^^ `Rc>` cannot be sent between threads safely @@ -30,10 +38,18 @@ LL | fn after() -> impl Fn(i32) { | ------------ within this `impl Fn(i32)` | = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc>` - = note: required because it appears within the type `[closure@$DIR/auto-trait-leak2.rs:24:5: 24:22]` - = note: required because it appears within the type `impl Fn(i32)` +note: required because it's used within this closure + --> $DIR/auto-trait-leak2.rs:38:5 + | +LL | move |x| p.set(x) + | ^^^^^^^^^^^^^^^^^ +note: required because it appears within the type `impl Fn(i32)` + --> $DIR/auto-trait-leak2.rs:33:15 + | +LL | fn after() -> impl Fn(i32) { + | ^^^^^^^^^^^^ note: required by a bound in `send` - --> $DIR/auto-trait-leak2.rs:10:12 + --> $DIR/auto-trait-leak2.rs:13:12 | LL | fn send(_: T) {} | ^^^^ required by this bound in `send` diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr index cb22d5adb717d..66fe3c74e2c87 100644 --- a/src/test/ui/interior-mutability/interior-mutability.stderr +++ b/src/test/ui/interior-mutability/interior-mutability.stderr @@ -7,7 +7,11 @@ LL | catch_unwind(|| { x.set(23); }); = help: within `Cell`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell` = note: required because it appears within the type `Cell` = note: required because of the requirements on the impl of `UnwindSafe` for `&Cell` - = note: required because it appears within the type `[closure@$DIR/interior-mutability.rs:5:18: 5:35]` +note: required because it's used within this closure + --> $DIR/interior-mutability.rs:5:18 + | +LL | catch_unwind(|| { x.set(23); }); + | ^^^^^^^^^^^^^^^^^ note: required by a bound in `catch_unwind` --> $SRC_DIR/std/src/panic.rs:LL:COL | diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr index b3ebe7f5c7dc3..727573a0be4ed 100644 --- a/src/test/ui/kindck/kindck-nonsendable-1.stderr +++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr @@ -7,7 +7,11 @@ LL | bar(move|| foo(x)); | `Rc` cannot be sent between threads safely | = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]`, the trait `Send` is not implemented for `Rc` - = note: required because it appears within the type `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:22]` +note: required because it's used within this closure + --> $DIR/kindck-nonsendable-1.rs:9:9 + | +LL | bar(move|| foo(x)); + | ^^^^^^^^^^^^^ note: required by a bound in `bar` --> $DIR/kindck-nonsendable-1.rs:5:21 | diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr index 80708c989fcf7..e4c57c04e7269 100644 --- a/src/test/ui/no-send-res-ports.stderr +++ b/src/test/ui/no-send-res-ports.stderr @@ -22,7 +22,16 @@ note: required because it appears within the type `Foo` | LL | struct Foo { | ^^^ - = note: required because it appears within the type `[closure@$DIR/no-send-res-ports.rs:25:19: 29:6]` +note: required because it's used within this closure + --> $DIR/no-send-res-ports.rs:25:19 + | +LL | thread::spawn(move|| { + | ___________________^ +LL | | +LL | | let y = x; +LL | | println!("{:?}", y); +LL | | }); + | |_____^ note: required by a bound in `spawn` --> $SRC_DIR/std/src/thread/mod.rs:LL:COL | diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr index 78b35569c2162..bebf561b120b5 100644 --- a/src/test/ui/not-clone-closure.stderr +++ b/src/test/ui/not-clone-closure.stderr @@ -10,7 +10,14 @@ LL | LL | let hello = hello.clone(); | ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]`, the trait `Clone` is not implemented for `S` | - = note: required because it appears within the type `[closure@$DIR/not-clone-closure.rs:7:17: 9:6]` +note: required because it's used within this closure + --> $DIR/not-clone-closure.rs:7:17 + | +LL | let hello = move || { + | _________________^ +LL | | println!("Hello {}", a.0); +LL | | }; + | |_____^ help: consider annotating `S` with `#[derive(Clone)]` | LL | #[derive(Clone)] diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs index 745379efa6df9..fc89b0e870e39 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.rs @@ -4,7 +4,9 @@ mod m { use std::rc::Rc; - type Foo = impl std::fmt::Debug; + type Foo = impl std::fmt::Debug; //~ NOTE appears within the type + //~^ within this `Foo` + //~| expansion of desugaring pub fn foo() -> Foo { Rc::new(22_u32) @@ -12,8 +14,12 @@ mod m { } fn is_send(_: T) {} +//~^ required by this bound +//~| required by a bound fn main() { is_send(m::foo()); //~^ ERROR: `Rc` cannot be sent between threads safely [E0277] + //~| NOTE cannot be sent + //~| NOTE required by a bound } diff --git a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr index 0664275b2ad0a..d7247302dd1e0 100644 --- a/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr +++ b/src/test/ui/type-alias-impl-trait/auto-trait-leakage2.stderr @@ -1,5 +1,5 @@ error[E0277]: `Rc` cannot be sent between threads safely - --> $DIR/auto-trait-leakage2.rs:17:13 + --> $DIR/auto-trait-leakage2.rs:21:13 | LL | type Foo = impl std::fmt::Debug; | -------------------- within this `Foo` @@ -10,9 +10,13 @@ LL | is_send(m::foo()); | required by a bound introduced by this call | = help: within `Foo`, the trait `Send` is not implemented for `Rc` - = note: required because it appears within the type `Foo` +note: required because it appears within the type `Foo` + --> $DIR/auto-trait-leakage2.rs:7:16 + | +LL | type Foo = impl std::fmt::Debug; + | ^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `is_send` - --> $DIR/auto-trait-leakage2.rs:14:15 + --> $DIR/auto-trait-leakage2.rs:16:15 | LL | fn is_send(_: T) {} | ^^^^ required by this bound in `is_send` From a33668601b7da85cfbc3fd669c0acdc3a696a8d6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 Jun 2022 20:49:07 -0700 Subject: [PATCH 03/28] Fix trait object reborrow suggestion --- compiler/rustc_middle/src/traits/mod.rs | 2 +- .../src/traits/error_reporting/mod.rs | 7 +++---- .../src/traits/error_reporting/suggestions.rs | 2 +- .../src/traits/select/confirmation.rs | 6 +++--- .../suggest-borrow-to-dyn-object.rs | 16 ++++++++++++++++ .../suggest-borrow-to-dyn-object.stderr | 19 +++++++++++++++++++ 6 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs create mode 100644 src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 912b09eeca861..278e00712e695 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -253,7 +253,7 @@ pub enum ObligationCauseCode<'tcx> { ObjectTypeBound(Ty<'tcx>, ty::Region<'tcx>), /// Obligation incurred due to an object cast. - ObjectCastObligation(/* Object type */ Ty<'tcx>), + ObjectCastObligation(/* Concrete type */ Ty<'tcx>, /* Object type */ Ty<'tcx>), /// Obligation incurred due to a coercion. Coercion { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 2f999f5ffad85..442d463d79d47 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -484,10 +484,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_label(span, explanation); } - if let ObligationCauseCode::ObjectCastObligation(obj_ty) = obligation.cause.code().peel_derives() && - let Some(self_ty) = trait_predicate.self_ty().no_bound_vars() && + if let ObligationCauseCode::ObjectCastObligation(concrete_ty, obj_ty) = obligation.cause.code().peel_derives() && Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { - self.suggest_borrowing_for_object_cast(&mut err, &obligation, self_ty, *obj_ty); + self.suggest_borrowing_for_object_cast(&mut err, &root_obligation, *concrete_ty, *obj_ty); } if trait_predicate.is_const_if_const() && obligation.param_env.is_const() { @@ -1565,7 +1564,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { obligation.cause.code().peel_derives(), ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::BindingObligation(_, _) - | ObligationCauseCode::ObjectCastObligation(_) + | ObligationCauseCode::ObjectCastObligation(..) | ObligationCauseCode::OpaqueType ); if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 09b73b982a0c1..167ecac226d11 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2228,7 +2228,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_note(tcx.def_span(item_def_id), &descr); } } - ObligationCauseCode::ObjectCastObligation(object_ty) => { + ObligationCauseCode::ObjectCastObligation(_, object_ty) => { err.note(&format!( "required for the cast to the object type `{}`", self.ty_to_string(object_ty) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 5942bb79d69e8..e1131140c39e8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -813,7 +813,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - ObjectCastObligation(target), + ObjectCastObligation(source, target), ); let outlives = ty::OutlivesPredicate(r_a, r_b); nested.push(Obligation::with_depth( @@ -910,7 +910,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - ObjectCastObligation(target), + ObjectCastObligation(source, target), ); let outlives = ty::OutlivesPredicate(r_a, r_b); nested.push(Obligation::with_depth( @@ -931,7 +931,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let cause = ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - ObjectCastObligation(target), + ObjectCastObligation(source, target), ); let predicate_to_obligation = |predicate| { diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs new file mode 100644 index 0000000000000..120fc538307a7 --- /dev/null +++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.rs @@ -0,0 +1,16 @@ +use std::ffi::{OsStr, OsString}; +use std::path::Path; + +fn check(p: &dyn AsRef) { + let m = std::fs::metadata(&p); + println!("{:?}", &m); +} + +fn main() { + let s: OsString = ".".into(); + let s: &OsStr = &s; + check(s); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time + //~| HELP within `OsStr`, the trait `Sized` is not implemented for `[u8]` + //~| HELP consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef` +} diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr new file mode 100644 index 0000000000000..8961f4275a283 --- /dev/null +++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr @@ -0,0 +1,19 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/suggest-borrow-to-dyn-object.rs:12:11 + | +LL | check(s); + | ----- ^ doesn't have a size known at compile-time + | | + | required by a bound introduced by this call + | + = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]` + = note: required because it appears within the type `OsStr` + = note: required for the cast to the object type `dyn AsRef` +help: consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef` + | +LL | check(&s); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 448e00b88979eb16d686fb17aa9a68404feab000 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 Jun 2022 21:04:06 -0700 Subject: [PATCH 04/28] Note concrete type being coerced into object --- .../src/traits/error_reporting/suggestions.rs | 5 +++-- .../assoc-type-eq-with-dyn-atb-fail.stderr | 2 +- .../ui/associated-types/associated-types-eq-3.stderr | 2 +- .../associated-types-overridden-binding-2.stderr | 2 +- src/test/ui/associated-types/issue-65774-1.stderr | 2 +- src/test/ui/associated-types/issue-65774-2.stderr | 2 +- .../async-block-control-flow-static-semantics.stderr | 4 ++-- src/test/ui/async-await/issue-86507.stderr | 2 +- .../coerce-issue-49593-box-never.nofallback.stderr | 4 ++-- .../defaults/trait_objects_fail.stderr | 4 ++-- src/test/ui/custom_test_frameworks/mismatch.stderr | 2 +- src/test/ui/dst/dst-bad-coerce1.stderr | 4 ++-- src/test/ui/dst/dst-object-from-unsized-type.stderr | 8 ++++---- .../issue-79422.extended.stderr | 2 +- src/test/ui/issues/issue-14366.stderr | 2 +- src/test/ui/issues/issue-22034.stderr | 2 +- src/test/ui/issues/issue-22872.stderr | 2 +- src/test/ui/issues/issue-7013.stderr | 2 +- src/test/ui/kindck/kindck-impl-type-params.stderr | 12 ++++++------ src/test/ui/mismatched_types/cast-rfc0401.stderr | 4 ++-- .../never_type/fallback-closure-wrap.fallback.stderr | 2 +- .../suggestions/derive-macro-missing-bounds.stderr | 8 ++++---- .../suggestions/suggest-borrow-to-dyn-object.stderr | 2 +- src/test/ui/traits/coercion-generic-bad.stderr | 2 +- src/test/ui/traits/map-types.stderr | 2 +- .../trait-upcasting/type-checking-test-1.stderr | 2 +- .../trait-upcasting/type-checking-test-2.stderr | 4 ++-- src/test/ui/unsized/unsized-fn-param.stderr | 8 ++++---- 28 files changed, 50 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 167ecac226d11..abd49b69e690b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2228,9 +2228,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { err.span_note(tcx.def_span(item_def_id), &descr); } } - ObligationCauseCode::ObjectCastObligation(_, object_ty) => { + ObligationCauseCode::ObjectCastObligation(concrete_ty, object_ty) => { err.note(&format!( - "required for the cast to the object type `{}`", + "required for the cast from `{}` to the object type `{}`", + self.ty_to_string(concrete_ty), self.ty_to_string(object_ty) )); } diff --git a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr index f1dcd34066dbc..f40e6585b38b1 100644 --- a/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr +++ b/src/test/ui/associated-type-bounds/assoc-type-eq-with-dyn-atb-fail.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied LL | Box::new(AssocNoCopy) | ^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | - = note: required for the cast to the object type `dyn Bar::Out::{opaque#0}>` + = note: required for the cast from `AssocNoCopy` to the object type `dyn Bar::Out::{opaque#0}>` error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr index 521907a60445c..bed63a5e6df03 100644 --- a/src/test/ui/associated-types/associated-types-eq-3.stderr +++ b/src/test/ui/associated-types/associated-types-eq-3.stderr @@ -41,7 +41,7 @@ note: expected this to be `Bar` | LL | type A = usize; | ^^^^^ - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `isize` to the object type `dyn Foo` error: aborting due to 3 previous errors diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr index 9f1abf2a6c4b6..dbd9a44ed9774 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -4,7 +4,7 @@ error[E0271]: type mismatch resolving ` as Iterator>::It LL | let _: &dyn I32Iterator = &vec![42].into_iter(); | ^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `u32` | - = note: required for the cast to the object type `dyn Iterator` + = note: required for the cast from `std::vec::IntoIter` to the object type `dyn Iterator` error: aborting due to previous error diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr index e468a1b3ba484..419de689c52da 100644 --- a/src/test/ui/associated-types/issue-65774-1.stderr +++ b/src/test/ui/associated-types/issue-65774-1.stderr @@ -23,7 +23,7 @@ note: required because of the requirements on the impl of `MyDisplay` for `&mut | LL | impl<'a, T: MyDisplay> MyDisplay for &'a mut T { } | ^^^^^^^^^ ^^^^^^^^^ - = note: required for the cast to the object type `dyn MyDisplay` + = note: required for the cast from `&mut T` to the object type `dyn MyDisplay` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-types/issue-65774-2.stderr b/src/test/ui/associated-types/issue-65774-2.stderr index 4cef4db4698a7..c22302cdc2626 100644 --- a/src/test/ui/associated-types/issue-65774-2.stderr +++ b/src/test/ui/associated-types/issue-65774-2.stderr @@ -18,7 +18,7 @@ LL | writer.my_write(valref) | ^^^^^^ the trait `MyDisplay` is not implemented for `T` | = help: the trait `MyDisplay` is implemented for `&'a mut T` - = note: required for the cast to the object type `dyn MyDisplay` + = note: required for the cast from `T` to the object type `dyn MyDisplay` error: aborting due to 2 previous errors diff --git a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr index e0818337d2039..e5887689690e7 100644 --- a/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr +++ b/src/test/ui/async-await/async-block-control-flow-static-semantics.stderr @@ -37,7 +37,7 @@ error[E0271]: type mismatch resolving ` as Future>::Out LL | let _: &dyn Future = █ | ^^^^^^ expected `()`, found `u8` | - = note: required for the cast to the object type `dyn Future` + = note: required for the cast from `impl Future` to the object type `dyn Future` error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:12:43 @@ -53,7 +53,7 @@ error[E0271]: type mismatch resolving ` as Future>::Out LL | let _: &dyn Future = █ | ^^^^^^ expected `()`, found `u8` | - = note: required for the cast to the object type `dyn Future` + = note: required for the cast from `impl Future` to the object type `dyn Future` error[E0308]: mismatched types --> $DIR/async-block-control-flow-static-semantics.rs:47:44 diff --git a/src/test/ui/async-await/issue-86507.stderr b/src/test/ui/async-await/issue-86507.stderr index 5bbc20359c64a..0e21dba980deb 100644 --- a/src/test/ui/async-await/issue-86507.stderr +++ b/src/test/ui/async-await/issue-86507.stderr @@ -13,7 +13,7 @@ note: captured value is not `Send` because `&` references cannot be sent unless | LL | let x = x; | ^ has type `&T` which is not `Send`, because `T` is not `Sync` - = note: required for the cast to the object type `dyn Future + Send` + = note: required for the cast from `impl Future` to the object type `dyn Future + Send` help: consider further restricting this bound | LL | fn bar<'me, 'async_trait, T: Send + std::marker::Sync>(x: &'me T) diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr index fcd2d7f78ff75..322681b97bccb 100644 --- a/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.nofallback.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied LL | /* *mut $0 is coerced to Box here */ Box::<_ /* ! */>::new(x) | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` | - = note: required for the cast to the object type `dyn std::error::Error` + = note: required for the cast from `()` to the object type `dyn std::error::Error` error[E0277]: the trait bound `(): std::error::Error` is not satisfied --> $DIR/coerce-issue-49593-box-never.rs:23:49 @@ -12,7 +12,7 @@ error[E0277]: the trait bound `(): std::error::Error` is not satisfied LL | /* *mut $0 is coerced to *mut Error here */ raw_ptr_box::<_ /* ! */>(x) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `()` | - = note: required for the cast to the object type `(dyn std::error::Error + 'static)` + = note: required for the cast from `()` to the object type `(dyn std::error::Error + 'static)` error: aborting due to 2 previous errors diff --git a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr index 60dc96f675a8b..da85b2059f0a3 100644 --- a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr +++ b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr @@ -7,7 +7,7 @@ LL | foo(&10_u32); | required by a bound introduced by this call | = help: the trait `Trait<2_u8>` is implemented for `u32` - = note: required for the cast to the object type `dyn Trait` + = note: required for the cast from `u32` to the object type `dyn Trait` error[E0277]: the trait bound `bool: Traitor<{_: u8}>` is not satisfied --> $DIR/trait_objects_fail.rs:28:9 @@ -18,7 +18,7 @@ LL | bar(&true); | required by a bound introduced by this call | = help: the trait `Traitor<2_u8, 3_u8>` is implemented for `bool` - = note: required for the cast to the object type `dyn Traitor<{_: u8}>` + = note: required for the cast from `bool` to the object type `dyn Traitor<{_: u8}>` error: aborting due to 2 previous errors diff --git a/src/test/ui/custom_test_frameworks/mismatch.stderr b/src/test/ui/custom_test_frameworks/mismatch.stderr index e848ddc55b7df..61061ae529d12 100644 --- a/src/test/ui/custom_test_frameworks/mismatch.stderr +++ b/src/test/ui/custom_test_frameworks/mismatch.stderr @@ -6,7 +6,7 @@ LL | #[test] LL | fn wrong_kind(){} | ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn` | - = note: required for the cast to the object type `dyn Testable` + = note: required for the cast from `TestDescAndFn` to the object type `dyn Testable` = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/dst/dst-bad-coerce1.stderr b/src/test/ui/dst/dst-bad-coerce1.stderr index 121c76a01a5de..594acff853a0e 100644 --- a/src/test/ui/dst/dst-bad-coerce1.stderr +++ b/src/test/ui/dst/dst-bad-coerce1.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `Foo: Bar` is not satisfied LL | let f3: &Fat = f2; | ^^ the trait `Bar` is not implemented for `Foo` | - = note: required for the cast to the object type `dyn Bar` + = note: required for the cast from `Foo` to the object type `dyn Bar` error[E0308]: mismatched types --> $DIR/dst-bad-coerce1.rs:28:27 @@ -34,7 +34,7 @@ error[E0277]: the trait bound `Foo: Bar` is not satisfied LL | let f3: &(dyn Bar,) = f2; | ^^ the trait `Bar` is not implemented for `Foo` | - = note: required for the cast to the object type `dyn Bar` + = note: required for the cast from `Foo` to the object type `dyn Bar` error: aborting due to 4 previous errors diff --git a/src/test/ui/dst/dst-object-from-unsized-type.stderr b/src/test/ui/dst/dst-object-from-unsized-type.stderr index 5bd47736626da..e24c96ebed633 100644 --- a/src/test/ui/dst/dst-object-from-unsized-type.stderr +++ b/src/test/ui/dst/dst-object-from-unsized-type.stderr @@ -6,7 +6,7 @@ LL | fn test1(t: &T) { LL | let u: &dyn Foo = t; | ^ doesn't have a size known at compile-time | - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `T` to the object type `dyn Foo` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn test1(t: &T) { @@ -21,7 +21,7 @@ LL | fn test2(t: &T) { LL | let v: &dyn Foo = t as &dyn Foo; | ^ doesn't have a size known at compile-time | - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `T` to the object type `dyn Foo` help: consider removing the `?Sized` bound to make the type parameter `Sized` | LL - fn test2(t: &T) { @@ -35,7 +35,7 @@ LL | let _: &[&dyn Foo] = &["hi"]; | ^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `str` to the object type `dyn Foo` error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/dst-object-from-unsized-type.rs:23:23 @@ -44,7 +44,7 @@ LL | let _: &dyn Foo = x as &dyn Foo; | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `[u8]` to the object type `dyn Foo` error: aborting due to 4 previous errors diff --git a/src/test/ui/generic-associated-types/issue-79422.extended.stderr b/src/test/ui/generic-associated-types/issue-79422.extended.stderr index 9478fc8979211..9bcbd74716845 100644 --- a/src/test/ui/generic-associated-types/issue-79422.extended.stderr +++ b/src/test/ui/generic-associated-types/issue-79422.extended.stderr @@ -27,7 +27,7 @@ LL | type VRefCont<'a> = &'a V where Self: 'a; | ^^^^^ = note: expected trait object `(dyn RefCont<'_, u8> + 'static)` found reference `&u8` - = note: required for the cast to the object type `dyn MapLike + 'static)>` + = note: required for the cast from `BTreeMap` to the object type `dyn MapLike + 'static)>` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-14366.stderr b/src/test/ui/issues/issue-14366.stderr index b96b07c91a1fe..10a73b245ac57 100644 --- a/src/test/ui/issues/issue-14366.stderr +++ b/src/test/ui/issues/issue-14366.stderr @@ -5,7 +5,7 @@ LL | let _x = "test" as &dyn (::std::any::Any); | ^^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn Any` + = note: required for the cast from `str` to the object type `dyn Any` help: consider borrowing the value, since `&str` can be coerced into `dyn Any` | LL | let _x = &"test" as &dyn (::std::any::Any); diff --git a/src/test/ui/issues/issue-22034.stderr b/src/test/ui/issues/issue-22034.stderr index edcd21ebd6b9b..b32de5b24b924 100644 --- a/src/test/ui/issues/issue-22034.stderr +++ b/src/test/ui/issues/issue-22034.stderr @@ -6,7 +6,7 @@ LL | &mut *(ptr as *mut dyn Fn()) | = help: the trait `Fn<()>` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` - = note: required for the cast to the object type `dyn Fn()` + = note: required for the cast from `()` to the object type `dyn Fn()` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22872.stderr b/src/test/ui/issues/issue-22872.stderr index cd96646d751f2..a84cb7d8c5922 100644 --- a/src/test/ui/issues/issue-22872.stderr +++ b/src/test/ui/issues/issue-22872.stderr @@ -10,7 +10,7 @@ note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for | LL | impl<'b, P> Wrap<'b> for Wrapper

| ^^^^^^^^ ^^^^^^^^^^ - = note: required for the cast to the object type `dyn for<'b> Wrap<'b>` + = note: required for the cast from `Wrapper

` to the object type `dyn for<'b> Wrap<'b>` help: consider further restricting the associated type | LL | fn push_process

(process: P) where P: Process<'static>,

>::Item: Iterator { diff --git a/src/test/ui/issues/issue-7013.stderr b/src/test/ui/issues/issue-7013.stderr index 98ed67507b1d8..f6cb1cbdc11c6 100644 --- a/src/test/ui/issues/issue-7013.stderr +++ b/src/test/ui/issues/issue-7013.stderr @@ -11,7 +11,7 @@ note: required because it appears within the type `B` | LL | struct B { | ^ - = note: required for the cast to the object type `dyn Foo + Send` + = note: required for the cast from `B` to the object type `dyn Foo + Send` error: aborting due to previous error diff --git a/src/test/ui/kindck/kindck-impl-type-params.stderr b/src/test/ui/kindck/kindck-impl-type-params.stderr index 32759d2fa0ebd..902349135c549 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.stderr @@ -9,7 +9,7 @@ note: required because of the requirements on the impl of `Gettable` for `S Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` help: consider restricting type parameter `T` | LL | fn f(val: T) { @@ -26,7 +26,7 @@ note: required because of the requirements on the impl of `Gettable` for `S Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` help: consider restricting type parameter `T` | LL | fn f(val: T) { @@ -43,7 +43,7 @@ note: required because of the requirements on the impl of `Gettable` for `S Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` help: consider restricting type parameter `T` | LL | fn g(val: T) { @@ -60,7 +60,7 @@ note: required because of the requirements on the impl of `Gettable` for `S Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` help: consider restricting type parameter `T` | LL | fn g(val: T) { @@ -78,7 +78,7 @@ note: required because of the requirements on the impl of `Gettable` for | LL | impl Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` error[E0277]: the trait bound `Foo: Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:43:37 @@ -92,7 +92,7 @@ note: required because of the requirements on the impl of `Gettable` for `S | LL | impl Gettable for S {} | ^^^^^^^^^^^ ^^^^ - = note: required for the cast to the object type `dyn Gettable` + = note: required for the cast from `S` to the object type `dyn Gettable` help: consider annotating `Foo` with `#[derive(Copy)]` | LL | #[derive(Copy)] diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index e63ca6e11de59..eab8e8e80c424 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -220,7 +220,7 @@ LL | let _ = fat_v as *const dyn Foo; | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `[u8]` - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `[u8]` to the object type `dyn Foo` help: consider borrowing the value, since `&[u8]` can be coerced into `dyn Foo` | LL | let _ = &fat_v as *const dyn Foo; @@ -233,7 +233,7 @@ LL | let _ = a as *const dyn Foo; | ^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast from `str` to the object type `dyn Foo` help: consider borrowing the value, since `&str` can be coerced into `dyn Foo` | LL | let _ = &a as *const dyn Foo; diff --git a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr index 78d1a3caf4a30..6b9635d4a60bc 100644 --- a/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr +++ b/src/test/ui/never_type/fallback-closure-wrap.fallback.stderr @@ -10,7 +10,7 @@ LL | | }) as Box); | = note: expected unit type `()` found type `!` - = note: required for the cast to the object type `dyn FnMut()` + = note: required for the cast from `[closure@$DIR/fallback-closure-wrap.rs:18:40: 21:6]` to the object type `dyn FnMut()` error: aborting due to previous error diff --git a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr index 501d083e2bc60..4186dc7cb35ae 100644 --- a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr +++ b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr @@ -33,7 +33,7 @@ LL | impl Debug for Inner { | ^^^^^ ^^^^^^^^ = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Debug` for `&c::Inner` - = note: required for the cast to the object type `dyn Debug` + = note: required for the cast from `&c::Inner` to the object type `dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | @@ -55,7 +55,7 @@ LL | impl Debug for Inner where T: Debug, T: Trait { | ^^^^^ ^^^^^^^^ = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Debug` for `&d::Inner` - = note: required for the cast to the object type `dyn Debug` + = note: required for the cast from `&d::Inner` to the object type `dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | @@ -77,7 +77,7 @@ LL | impl Debug for Inner where T: Debug + Trait { | ^^^^^ ^^^^^^^^ = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Debug` for `&e::Inner` - = note: required for the cast to the object type `dyn Debug` + = note: required for the cast from `&e::Inner` to the object type `dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | @@ -99,7 +99,7 @@ LL | impl Debug for Inner where T: Trait { | ^^^^^ ^^^^^^^^ = note: 1 redundant requirement hidden = note: required because of the requirements on the impl of `Debug` for `&f::Inner` - = note: required for the cast to the object type `dyn Debug` + = note: required for the cast from `&f::Inner` to the object type `dyn Debug` = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider restricting type parameter `T` | diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr index 8961f4275a283..6b6e406130ec2 100644 --- a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr +++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr @@ -8,7 +8,7 @@ LL | check(s); | = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]` = note: required because it appears within the type `OsStr` - = note: required for the cast to the object type `dyn AsRef` + = note: required for the cast from `OsStr` to the object type `dyn AsRef` help: consider borrowing the value, since `&OsStr` can be coerced into `dyn AsRef` | LL | check(&s); diff --git a/src/test/ui/traits/coercion-generic-bad.stderr b/src/test/ui/traits/coercion-generic-bad.stderr index b213ee635df59..93d6770eb47d1 100644 --- a/src/test/ui/traits/coercion-generic-bad.stderr +++ b/src/test/ui/traits/coercion-generic-bad.stderr @@ -5,7 +5,7 @@ LL | let s: Box> = Box::new(Struct { person: "Fred" }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `Struct` | = help: the trait `Trait<&'static str>` is implemented for `Struct` - = note: required for the cast to the object type `dyn Trait` + = note: required for the cast from `Struct` to the object type `dyn Trait` error: aborting due to previous error diff --git a/src/test/ui/traits/map-types.stderr b/src/test/ui/traits/map-types.stderr index a4686edb71757..f685c50b07d5b 100644 --- a/src/test/ui/traits/map-types.stderr +++ b/src/test/ui/traits/map-types.stderr @@ -5,7 +5,7 @@ LL | let y: Box> = Box::new(x); | ^^^^^^^^^^^ the trait `Map` is not implemented for `Box>` | = help: the trait `Map` is implemented for `HashMap` - = note: required for the cast to the object type `dyn Map` + = note: required for the cast from `Box>` to the object type `dyn Map` error: aborting due to previous error diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr index 44f32e0cec91c..3985372119e88 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-1.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied LL | let _ = x as &dyn Bar<_>; // Ambiguous | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` | - = note: required for the cast to the object type `dyn Bar<_>` + = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>` error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr b/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr index 4ae4c8552c161..93c71f54eb53a 100644 --- a/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr +++ b/src/test/ui/traits/trait-upcasting/type-checking-test-2.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `&dyn Foo: Bar` is not satisfied LL | let _ = x as &dyn Bar; // Error | ^ the trait `Bar` is not implemented for `&dyn Foo` | - = note: required for the cast to the object type `dyn Bar` + = note: required for the cast from `&dyn Foo` to the object type `dyn Bar` error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>` --> $DIR/type-checking-test-2.rs:26:13 @@ -34,7 +34,7 @@ error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied LL | let a = x as &dyn Bar<_>; // Ambiguous | ^ the trait `Bar<_>` is not implemented for `&dyn Foo` | - = note: required for the cast to the object type `dyn Bar<_>` + = note: required for the cast from `&dyn Foo` to the object type `dyn Bar<_>` error: aborting due to 4 previous errors diff --git a/src/test/ui/unsized/unsized-fn-param.stderr b/src/test/ui/unsized/unsized-fn-param.stderr index 3eecca0fa09d9..b477260543258 100644 --- a/src/test/ui/unsized/unsized-fn-param.stderr +++ b/src/test/ui/unsized/unsized-fn-param.stderr @@ -5,7 +5,7 @@ LL | foo11("bar", &"baz"); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn AsRef` + = note: required for the cast from `str` to the object type `dyn AsRef` help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` | LL | foo11(&"bar", &"baz"); @@ -18,7 +18,7 @@ LL | foo12(&"bar", "baz"); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn AsRef` + = note: required for the cast from `str` to the object type `dyn AsRef` help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` | LL | foo12(&"bar", &"baz"); @@ -31,7 +31,7 @@ LL | foo21("bar", &"baz"); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn AsRef` + = note: required for the cast from `str` to the object type `dyn AsRef` help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` | LL | foo21(&"bar", &"baz"); @@ -44,7 +44,7 @@ LL | foo22(&"bar", "baz"); | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `str` - = note: required for the cast to the object type `dyn AsRef` + = note: required for the cast from `str` to the object type `dyn AsRef` help: consider borrowing the value, since `&str` can be coerced into `dyn AsRef` | LL | foo22(&"bar", &"baz"); From 1e7ab0bbd772d4dab2a66a72af20f8b207c252ab Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 20 Jun 2022 16:29:05 +0900 Subject: [PATCH 05/28] point at private fields in struct literal --- Cargo.lock | 1 + compiler/rustc_typeck/Cargo.toml | 1 + compiler/rustc_typeck/src/check/expr.rs | 80 ++++++++++++++++--- src/test/ui/issues/issue-76077.rs | 2 +- src/test/ui/issues/issue-76077.stderr | 8 +- src/test/ui/privacy/issue-79593.rs | 2 +- src/test/ui/privacy/issue-79593.stderr | 8 +- ...7872-missing-inaccessible-field-literal.rs | 2 +- ...-missing-inaccessible-field-literal.stderr | 8 +- ...issing-private-fields-in-struct-literal.rs | 18 +++++ ...ng-private-fields-in-struct-literal.stderr | 23 ++++++ 11 files changed, 134 insertions(+), 19 deletions(-) create mode 100644 src/test/ui/typeck/missing-private-fields-in-struct-literal.rs create mode 100644 src/test/ui/typeck/missing-private-fields-in-struct-literal.stderr diff --git a/Cargo.lock b/Cargo.lock index df6f46f26cf0d..cc0f4cc53e656 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4590,6 +4590,7 @@ dependencies = [ name = "rustc_typeck" version = "0.0.0" dependencies = [ + "itertools", "rustc_arena", "rustc_ast", "rustc_attr", diff --git a/compiler/rustc_typeck/Cargo.toml b/compiler/rustc_typeck/Cargo.toml index c08023ee6a70a..b3dd695508094 100644 --- a/compiler/rustc_typeck/Cargo.toml +++ b/compiler/rustc_typeck/Cargo.toml @@ -10,6 +10,7 @@ doctest = false [dependencies] rustc_arena = { path = "../rustc_arena" } tracing = "0.1" +itertools = "0.10.1" rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index dc9d76160c4e9..0a017de80f248 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -23,13 +23,14 @@ use crate::type_error_struct; use super::suggest_call_constructor; use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive}; +use itertools::{Either, Itertools}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::Diagnostic; -use rustc_errors::EmissionGuarantee; -use rustc_errors::ErrorGuaranteed; -use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId}; +use rustc_errors::{ + pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, + EmissionGuarantee, ErrorGuaranteed, MultiSpan, +}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; @@ -1672,12 +1673,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; self.typeck_results.borrow_mut().fru_field_types_mut().insert(expr_id, fru_tys); } else if adt_kind != AdtKind::Union && !remaining_fields.is_empty() { - let inaccessible_remaining_fields = remaining_fields.iter().any(|(_, (_, field))| { - !field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx) - }); + debug!(?remaining_fields); + let private_fields: Vec<&ty::FieldDef> = variant + .fields + .iter() + .filter(|field| { + !field.vis.is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx) + }) + .collect(); - if inaccessible_remaining_fields { - self.report_inaccessible_fields(adt_ty, span); + if !private_fields.is_empty() + && tcx + .visibility(variant.def_id) + .is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx) + { + self.report_private_fields(adt_ty, span, private_fields, ast_fields); } else { self.report_missing_fields( adt_ty, @@ -1801,7 +1811,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Report an error for a struct field expression when there are invisible fields. /// /// ```text - /// error: cannot construct `Foo` with struct literal syntax due to inaccessible fields + /// error: cannot construct `Foo` with struct literal syntax due to private fields /// --> src/main.rs:8:5 /// | /// 8 | foo::Foo {}; @@ -1809,13 +1819,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// /// error: aborting due to previous error /// ``` - fn report_inaccessible_fields(&self, adt_ty: Ty<'tcx>, span: Span) { - self.tcx.sess.span_err( + fn report_private_fields( + &self, + adt_ty: Ty<'tcx>, + span: Span, + private_fields: Vec<&ty::FieldDef>, + used_fields: &'tcx [hir::ExprField<'tcx>], + ) { + let field_names = |fields: Vec, len: usize| match &fields + .iter() + .map(|field| field.to_string()) + .collect::>()[..] + { + _ if len > 6 => String::new(), + [name] => format!("`{name}` "), + [names @ .., last] => { + let names = names.iter().map(|name| format!("`{name}`")).collect::>(); + format!("{} and `{last}` ", names.join(", ")) + } + [] => unreachable!(), + }; + + let mut err = self.tcx.sess.struct_span_err( span, &format!( - "cannot construct `{adt_ty}` with struct literal syntax due to inaccessible fields", + "cannot construct `{adt_ty}` with struct literal syntax due to private fields", ), ); + let (used_private_fields, remaining_private_fields): ( + Vec<(Symbol, Span)>, + Vec<(Symbol, Span)>, + ) = private_fields.iter().partition_map(|field| { + match used_fields.iter().find(|used_field| field.name == used_field.ident.name) { + Some(used_field) => Either::Left((field.name, used_field.span)), + None => Either::Right((field.name, self.tcx.def_span(field.did))), + } + }); + let remaining_private_fields_len = remaining_private_fields.len(); + err.span_labels(used_private_fields.iter().map(|(_, span)| *span), "private field"); + err.span_note( + MultiSpan::from_spans(remaining_private_fields.iter().map(|(_, span)| *span).collect()), + format!( + "missing field{s} {names}{are} private", + s = pluralize!(remaining_private_fields_len), + are = pluralize!("is", remaining_private_fields_len), + names = field_names( + remaining_private_fields.iter().map(|(name, _)| *name).collect(), + remaining_private_fields_len + ) + ), + ); + err.emit(); } fn report_unknown_field( diff --git a/src/test/ui/issues/issue-76077.rs b/src/test/ui/issues/issue-76077.rs index 1ecd37de2e14a..2d29093b01b02 100644 --- a/src/test/ui/issues/issue-76077.rs +++ b/src/test/ui/issues/issue-76077.rs @@ -6,5 +6,5 @@ pub mod foo { fn main() { foo::Foo {}; - //~^ ERROR cannot construct `Foo` with struct literal syntax due to inaccessible fields + //~^ ERROR cannot construct `Foo` with struct literal syntax due to private fields } diff --git a/src/test/ui/issues/issue-76077.stderr b/src/test/ui/issues/issue-76077.stderr index d834ec5e0edd2..c70a928f6475a 100644 --- a/src/test/ui/issues/issue-76077.stderr +++ b/src/test/ui/issues/issue-76077.stderr @@ -1,8 +1,14 @@ -error: cannot construct `Foo` with struct literal syntax due to inaccessible fields +error: cannot construct `Foo` with struct literal syntax due to private fields --> $DIR/issue-76077.rs:8:5 | LL | foo::Foo {}; | ^^^^^^^^ + | +note: missing field `you_cant_use_this_field` is private + --> $DIR/issue-76077.rs:3:9 + | +LL | you_cant_use_this_field: bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/privacy/issue-79593.rs b/src/test/ui/privacy/issue-79593.rs index b94278bfdd221..39c222f7c3414 100644 --- a/src/test/ui/privacy/issue-79593.rs +++ b/src/test/ui/privacy/issue-79593.rs @@ -16,7 +16,7 @@ mod foo { fn correct() { foo::Pub {}; - //~^ ERROR cannot construct `Pub` with struct literal syntax due to inaccessible fields + //~^ ERROR cannot construct `Pub` with struct literal syntax due to private fields } fn wrong() { diff --git a/src/test/ui/privacy/issue-79593.stderr b/src/test/ui/privacy/issue-79593.stderr index b8c7d4f23a28f..435d4cbf73595 100644 --- a/src/test/ui/privacy/issue-79593.stderr +++ b/src/test/ui/privacy/issue-79593.stderr @@ -10,11 +10,17 @@ error[E0063]: missing field `y` in initializer of `Enum` LL | Enum::Variant { x: () }; | ^^^^^^^^^^^^^ missing `y` -error: cannot construct `Pub` with struct literal syntax due to inaccessible fields +error: cannot construct `Pub` with struct literal syntax due to private fields --> $DIR/issue-79593.rs:18:5 | LL | foo::Pub {}; | ^^^^^^^^ + | +note: missing field `private` is private + --> $DIR/issue-79593.rs:2:22 + | +LL | pub struct Pub { private: () } + | ^^^^^^^^^^^ error[E0063]: missing field `y` in initializer of `Enum` --> $DIR/issue-79593.rs:23:5 diff --git a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs index 3176144133760..326e958aaa94f 100644 --- a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs +++ b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.rs @@ -7,5 +7,5 @@ pub mod foo { fn main() { foo::Foo {}; - //~^ ERROR cannot construct `Foo` with struct literal syntax due to inaccessible fields + //~^ ERROR cannot construct `Foo` with struct literal syntax due to private fields } diff --git a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr index 81b73c00e8600..2ade7aea57b3d 100644 --- a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr +++ b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr @@ -1,8 +1,14 @@ -error: cannot construct `Foo` with struct literal syntax due to inaccessible fields +error: cannot construct `Foo` with struct literal syntax due to private fields --> $DIR/issue-87872-missing-inaccessible-field-literal.rs:9:5 | LL | foo::Foo {}; | ^^^^^^^^ + | +note: missing field `you_cant_use_this_field` is private + --> $DIR/issue-87872-missing-inaccessible-field-literal.rs:4:9 + | +LL | you_cant_use_this_field: bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/typeck/missing-private-fields-in-struct-literal.rs b/src/test/ui/typeck/missing-private-fields-in-struct-literal.rs new file mode 100644 index 0000000000000..9f1560bfb8dfe --- /dev/null +++ b/src/test/ui/typeck/missing-private-fields-in-struct-literal.rs @@ -0,0 +1,18 @@ +pub mod m { + pub struct S { + pub visible: bool, + a: (), + b: (), + c: (), + d: (), + e: (), + } +} + +fn main() { + let _ = m::S { //~ ERROR cannot construct `S` with struct literal syntax due to private fields + visible: true, + a: (), + b: (), + }; +} diff --git a/src/test/ui/typeck/missing-private-fields-in-struct-literal.stderr b/src/test/ui/typeck/missing-private-fields-in-struct-literal.stderr new file mode 100644 index 0000000000000..eb5f460f868e1 --- /dev/null +++ b/src/test/ui/typeck/missing-private-fields-in-struct-literal.stderr @@ -0,0 +1,23 @@ +error: cannot construct `S` with struct literal syntax due to private fields + --> $DIR/missing-private-fields-in-struct-literal.rs:13:13 + | +LL | let _ = m::S { + | ^^^^ +LL | visible: true, +LL | a: (), + | ----- private field +LL | b: (), + | ----- private field + | +note: missing fields `c`, `d` and `e` are private + --> $DIR/missing-private-fields-in-struct-literal.rs:6:9 + | +LL | c: (), + | ^^^^^ +LL | d: (), + | ^^^^^ +LL | e: (), + | ^^^^^ + +error: aborting due to previous error + From f00179521d10357d099b419a73a22f50295220f1 Mon Sep 17 00:00:00 2001 From: klensy Date: Mon, 20 Jun 2022 20:42:58 +0300 Subject: [PATCH 06/28] don't alloc error string if no error emitted --- compiler/rustc_typeck/src/astconv/mod.rs | 65 ++++++++++++------------ 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 4641b36aad1d7..1c53618dd7c30 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -2111,14 +2111,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { extend: impl Fn(&mut DiagnosticBuilder<'tcx, ErrorGuaranteed>), ) -> bool { let args = segments.clone().flat_map(|segment| segment.args().args); - let types_and_spans: Vec<_> = segments - .clone() - .flat_map(|segment| { - segment.res.and_then(|res| { - if segment.args().args.is_empty() { - None - } else { - Some(( + + let (lt, ty, ct, inf) = + args.clone().fold((false, false, false, false), |(lt, ty, ct, inf), arg| match arg { + hir::GenericArg::Lifetime(_) => (true, ty, ct, inf), + hir::GenericArg::Type(_) => (lt, true, ct, inf), + hir::GenericArg::Const(_) => (lt, ty, true, inf), + hir::GenericArg::Infer(_) => (lt, ty, ct, true), + }); + let mut emitted = false; + if lt || ty || ct || inf { + let types_and_spans: Vec<_> = segments + .clone() + .flat_map(|segment| { + segment.res.and_then(|res| { + if segment.args().args.is_empty() { + None + } else { + Some(( match res { Res::PrimTy(ty) => format!("{} `{}`", res.descr(), ty.name()), Res::Def(_, def_id) @@ -2130,32 +2140,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }, segment.ident.span, )) - } + } + }) }) - }) - .collect(); - let this_type = match &types_and_spans[..] { - [.., _, (last, _)] => format!( - "{} and {last}", - types_and_spans[..types_and_spans.len() - 1] - .iter() - .map(|(x, _)| x.as_str()) - .intersperse(&", ") - .collect::() - ), - [(only, _)] => only.to_string(), - [] => "this type".to_string(), - }; + .collect(); + let this_type = match &types_and_spans[..] { + [.., _, (last, _)] => format!( + "{} and {last}", + types_and_spans[..types_and_spans.len() - 1] + .iter() + .map(|(x, _)| x.as_str()) + .intersperse(&", ") + .collect::() + ), + [(only, _)] => only.to_string(), + [] => "this type".to_string(), + }; - let (lt, ty, ct, inf) = - args.clone().fold((false, false, false, false), |(lt, ty, ct, inf), arg| match arg { - hir::GenericArg::Lifetime(_) => (true, ty, ct, inf), - hir::GenericArg::Type(_) => (lt, true, ct, inf), - hir::GenericArg::Const(_) => (lt, ty, true, inf), - hir::GenericArg::Infer(_) => (lt, ty, ct, true), - }); - let mut emitted = false; - if lt || ty || ct || inf { let arg_spans: Vec = args.map(|arg| arg.span()).collect(); let mut kinds = Vec::with_capacity(4); From b37a05bd01a4f1fdcdfda77df4a9008d04236528 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Mon, 20 Jun 2022 12:41:11 -0700 Subject: [PATCH 07/28] rustdoc: optimize loading of source sidebar The source sidebar has a setting to remember whether it should be open or closed. Previously, this setting was handled in source-script.js, which is loaded with `defer`, meaning it is often run after the document is rendered. Since CSS renders the source sidebar as closed by default, changing this after the initial render results in a relayout. Instead, handle the setting in storage.js, which is the first script to load and is the only script that blocks render. This avoids a relayout and means navigating between files with the sidebar open is faster. --- src/librustdoc/html/static/css/rustdoc.css | 35 ++++++++++++------- .../html/static/js/source-script.js | 10 ++---- src/librustdoc/html/static/js/storage.js | 11 ++++++ src/test/rustdoc-gui/sidebar-source-code.goml | 10 +++--- src/test/rustdoc-gui/source-code-page.goml | 2 +- 5 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d0229bdb5f23c..b4b7790eebba1 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -387,16 +387,20 @@ nav.sub { overflow-y: hidden; } +.rustdoc.source .sidebar .sidebar-logo { + display: none; +} + .source .sidebar > *:not(#sidebar-toggle) { opacity: 0; visibility: hidden; } -.source .sidebar.expanded { +.source-sidebar-expanded .source .sidebar { overflow-y: auto; } -.source .sidebar.expanded > *:not(#sidebar-toggle) { +.source-sidebar-expanded .source .sidebar > *:not(#sidebar-toggle) { opacity: 1; visibility: visible; } @@ -1682,11 +1686,11 @@ details.rustdoc-toggle[open] > summary.hideme::after { /* When we expand the sidebar on the source code page, we hide the logo on the left of the search bar to have more space. */ - .sidebar.expanded + main .width-limiter .sub-logo-container.rust-logo { + .source-sidebar-expanded .source .sidebar + main .width-limiter .sub-logo-container.rust-logo { display: none; } - .source .sidebar.expanded { + .source-sidebar-expanded .source .sidebar { width: 300px; } } @@ -1766,7 +1770,7 @@ details.rustdoc-toggle[open] > summary.hideme::after { } .sidebar.shown, - .sidebar.expanded, + .source-sidebar-expanded .source .sidebar, .sidebar:focus-within { left: 0; } @@ -1889,11 +1893,7 @@ details.rustdoc-toggle[open] > summary.hideme::after { left: -11px; } - .sidebar.expanded #sidebar-toggle { - font-size: 1.5rem; - } - - .sidebar:not(.expanded) #sidebar-toggle { + #sidebar-toggle { position: fixed; left: 1px; top: 100px; @@ -1910,6 +1910,14 @@ details.rustdoc-toggle[open] > summary.hideme::after { border-left: 0; } + .source-sidebar-expanded #sidebar-toggle { + left: unset; + top: unset; + width: unset; + border-top-right-radius: unset; + border-bottom-right-radius: unset; + } + #source-sidebar { z-index: 11; } @@ -1952,7 +1960,7 @@ details.rustdoc-toggle[open] > summary.hideme::after { padding-left: 2em; } - .source .sidebar.expanded { + .source-sidebar-expanded .source .sidebar { max-width: 100vw; width: 100vw; } @@ -2010,9 +2018,12 @@ details.rustdoc-toggle[open] > summary.hideme::after { width: 35px; } - .sidebar:not(.expanded) #sidebar-toggle { + #sidebar-toggle { top: 10px; } + .source-sidebar-expanded #sidebar-toggle { + top: unset; + } } .method-toggle summary, diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js index 14d8a942977d6..45955c6dd052c 100644 --- a/src/librustdoc/html/static/js/source-script.js +++ b/src/librustdoc/html/static/js/source-script.js @@ -76,14 +76,13 @@ function createDirEntry(elem, parent, fullPath, currentFile, hasFoundFile) { } function toggleSidebar() { - const sidebar = document.querySelector("nav.sidebar"); const child = this.children[0]; if (child.innerText === ">") { - sidebar.classList.add("expanded"); + addClass(document.documentElement, "source-sidebar-expanded"); child.innerText = "<"; updateLocalStorage("source-sidebar-show", "true"); } else { - sidebar.classList.remove("expanded"); + removeClass(document.documentElement, "source-sidebar-expanded"); child.innerText = ">"; updateLocalStorage("source-sidebar-show", "false"); } @@ -119,11 +118,6 @@ function createSourceSidebar() { const sidebar = document.createElement("div"); sidebar.id = "source-sidebar"; - if (getCurrentValue("source-sidebar-show") !== "true") { - container.classList.remove("expanded"); - } else { - container.classList.add("expanded"); - } const currentFile = getCurrentFilePath(); let hasFoundFile = false; diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js index 4fcf049923491..1c4c88344888c 100644 --- a/src/librustdoc/html/static/js/storage.js +++ b/src/librustdoc/html/static/js/storage.js @@ -1,3 +1,8 @@ +// storage.js is loaded in the `` of all rustdoc pages and doesn't +// use `async` or `defer`. That means it blocks further parsing and rendering +// of the page: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script. +// This makes it the correct place to act on settings that affect the display of +// the page, so we don't see major layout changes during the load of the page. "use strict"; const darkThemes = ["dark", "ayu"]; @@ -236,6 +241,12 @@ if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) { switchToSavedTheme(); } +if (getSettingValue("source-sidebar-show") === "true") { + // At this point in page load, `document.body` is not available yet. + // Set a class on the `` element instead. + addClass(document.documentElement, "source-sidebar-expanded"); +} + // If we navigate away (for example to a settings page), and then use the back or // forward button to get back to a page, the theme may have changed in the meantime. // But scripts may not be re-loaded in such a case due to the bfcache diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index 8b4a8bd40dd7e..724520bc399d0 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -8,12 +8,12 @@ assert-css: ("nav.sidebar", {"width": "50px"}) // We now click on the button to expand the sidebar. click: (10, 10) // We wait for the sidebar to be expanded. -wait-for-css: ("nav.sidebar.expanded", {"width": "300px"}) -assert-css: ("nav.sidebar.expanded a", {"font-size": "14px"}) +wait-for-css: (".source-sidebar-expanded nav.sidebar", {"width": "300px"}) +assert-css: (".source-sidebar-expanded nav.sidebar a", {"font-size": "14px"}) // We collapse the sidebar. click: (10, 10) // We ensure that the class has been removed. -wait-for: "nav.sidebar:not(.expanded)" +wait-for: "html:not(.expanded)" assert: "nav.sidebar" // We now switch to mobile mode. @@ -22,11 +22,11 @@ size: (600, 600) assert-css: ("nav.sidebar", {"width": "1px"}) // We expand the sidebar. click: "#sidebar-toggle" -assert-css: ("nav.sidebar.expanded", {"width": "600px"}) +assert-css: (".source-sidebar-expanded nav.sidebar", {"width": "600px"}) // We collapse the sidebar. click: (10, 10) // We ensure that the class has been removed. -assert-false: "nav.sidebar.expanded" +assert-false: ".source-sidebar-expanded" assert: "nav.sidebar" // Check that the topbar is not visible diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index 188b2605f0f13..b45512601f208 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -32,7 +32,7 @@ assert-document-property: ({"URL": "/lib.rs.html"}, ENDS_WITH) // First we "open" it. click: "#sidebar-toggle" -assert: ".sidebar.expanded" +assert: ".source-sidebar-expanded" // We check that the first entry of the sidebar is collapsed (which, for whatever reason, // is number 2 and not 1...). From e900a3549624860a466c33c04742ccfa026bdc6d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 21 Jun 2022 03:47:25 +0000 Subject: [PATCH 08/28] Give name if anonymous region appears in impl signature --- .../src/diagnostics/outlives_suggestion.rs | 3 +- .../src/diagnostics/region_name.rs | 58 +++++++++++++++++-- src/test/ui/nll/issue-98170.rs | 25 ++++++++ src/test/ui/nll/issue-98170.stderr | 44 ++++++++++++++ 4 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/nll/issue-98170.rs create mode 100644 src/test/ui/nll/issue-98170.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index 9d81330745fe2..d359d7efb6268 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -62,7 +62,8 @@ impl OutlivesSuggestionBuilder { | RegionNameSource::AnonRegionFromUpvar(..) | RegionNameSource::AnonRegionFromOutput(..) | RegionNameSource::AnonRegionFromYieldTy(..) - | RegionNameSource::AnonRegionFromAsyncFn(..) => { + | RegionNameSource::AnonRegionFromAsyncFn(..) + | RegionNameSource::AnonRegionFromImplSignature(..) => { debug!("Region {:?} is NOT suggestable", name); false } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index d6b5089712ab4..b5ae85fd042c2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -6,7 +6,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, RegionVid, Ty}; +use rustc_middle::ty::{self, DefIdTree, RegionVid, Ty}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -45,6 +45,8 @@ pub(crate) enum RegionNameSource { AnonRegionFromYieldTy(Span, String), /// An anonymous region from an async fn. AnonRegionFromAsyncFn(Span), + /// An anonymous region from an impl self type or trait + AnonRegionFromImplSignature(Span, &'static str), } /// Describes what to highlight to explain to the user that we're giving an anonymous region a @@ -75,7 +77,8 @@ impl RegionName { | RegionNameSource::AnonRegionFromUpvar(..) | RegionNameSource::AnonRegionFromOutput(..) | RegionNameSource::AnonRegionFromYieldTy(..) - | RegionNameSource::AnonRegionFromAsyncFn(..) => false, + | RegionNameSource::AnonRegionFromAsyncFn(..) + | RegionNameSource::AnonRegionFromImplSignature(..) => false, } } @@ -87,7 +90,8 @@ impl RegionName { | RegionNameSource::SynthesizedFreeEnvRegion(span, _) | RegionNameSource::AnonRegionFromUpvar(span, _) | RegionNameSource::AnonRegionFromYieldTy(span, _) - | RegionNameSource::AnonRegionFromAsyncFn(span) => Some(span), + | RegionNameSource::AnonRegionFromAsyncFn(span) + | RegionNameSource::AnonRegionFromImplSignature(span, _) => Some(span), RegionNameSource::AnonRegionFromArgument(ref highlight) | RegionNameSource::AnonRegionFromOutput(ref highlight, _) => match *highlight { RegionNameHighlight::MatchedHirTy(span) @@ -166,6 +170,12 @@ impl RegionName { RegionNameSource::AnonRegionFromYieldTy(span, type_name) => { diag.span_label(*span, format!("yield type is {type_name}")); } + RegionNameSource::AnonRegionFromImplSignature(span, location) => { + diag.span_label( + *span, + format!("lifetime `{self}` appears in the `impl`'s {location}"), + ); + } RegionNameSource::Static => {} } } @@ -240,7 +250,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr)) .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr)) .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr)); + .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr)); if let Some(ref value) = value { self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone()); @@ -840,4 +851,43 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name), }) } + + fn give_name_if_anonymous_region_appears_in_impl_signature( + &self, + fr: RegionVid, + ) -> Option { + let ty::ReEarlyBound(region) = *self.to_error_region(fr)? else { + return None; + }; + if region.has_name() { + return None; + }; + + let tcx = self.infcx.tcx; + let body_parent_did = tcx.opt_parent(self.mir_def_id().to_def_id())?; + if tcx.parent(region.def_id) != body_parent_did + || tcx.def_kind(body_parent_did) != DefKind::Impl + { + return None; + } + + let mut found = false; + tcx.fold_regions(tcx.type_of(body_parent_did), &mut true, |r: ty::Region<'tcx>, _| { + if *r == ty::ReEarlyBound(region) { + found = true; + } + r + }); + + Some(RegionName { + name: self.synthesize_region_name(), + source: RegionNameSource::AnonRegionFromImplSignature( + tcx.def_span(region.def_id), + // FIXME(compiler-errors): Does this ever actually show up + // anywhere other than the self type? I couldn't create an + // example of a `'_` in the impl's trait being referenceable. + if found { "self type" } else { "header" }, + ), + }) + } } diff --git a/src/test/ui/nll/issue-98170.rs b/src/test/ui/nll/issue-98170.rs new file mode 100644 index 0000000000000..6bb12f52d3f3e --- /dev/null +++ b/src/test/ui/nll/issue-98170.rs @@ -0,0 +1,25 @@ +pub struct MyStruct<'a> { + field: &'a [u32], +} + +impl MyStruct<'_> { + pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> { + Self { field } + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + } +} + +trait Trait<'a> { + fn new(field: &'a [u32]) -> MyStruct<'a>; +} + +impl<'a> Trait<'a> for MyStruct<'_> { + fn new(field: &'a [u32]) -> MyStruct<'a> { + Self { field } + //~^ ERROR lifetime may not live long enough + //~| ERROR lifetime may not live long enough + } +} + +fn main() {} diff --git a/src/test/ui/nll/issue-98170.stderr b/src/test/ui/nll/issue-98170.stderr new file mode 100644 index 0000000000000..0d17365e71b4a --- /dev/null +++ b/src/test/ui/nll/issue-98170.stderr @@ -0,0 +1,44 @@ +error: lifetime may not live long enough + --> $DIR/issue-98170.rs:7:9 + | +LL | impl MyStruct<'_> { + | -- lifetime `'1` appears in the `impl`'s self type +LL | pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> { + | -- lifetime `'a` defined here +LL | Self { field } + | ^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/issue-98170.rs:7:16 + | +LL | impl MyStruct<'_> { + | -- lifetime `'1` appears in the `impl`'s self type +LL | pub fn new<'a>(field: &'a [u32]) -> MyStruct<'a> { + | -- lifetime `'a` defined here +LL | Self { field } + | ^^^^^ this usage requires that `'a` must outlive `'1` + +error: lifetime may not live long enough + --> $DIR/issue-98170.rs:19:9 + | +LL | impl<'a> Trait<'a> for MyStruct<'_> { + | -- -- lifetime `'1` appears in the `impl`'s self type + | | + | lifetime `'a` defined here +LL | fn new(field: &'a [u32]) -> MyStruct<'a> { +LL | Self { field } + | ^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + +error: lifetime may not live long enough + --> $DIR/issue-98170.rs:19:16 + | +LL | impl<'a> Trait<'a> for MyStruct<'_> { + | -- -- lifetime `'1` appears in the `impl`'s self type + | | + | lifetime `'a` defined here +LL | fn new(field: &'a [u32]) -> MyStruct<'a> { +LL | Self { field } + | ^^^^^ this usage requires that `'a` must outlive `'1` + +error: aborting due to 4 previous errors + From f924e74fb1c238b0e6c06c23b51c087f1e6aa0d5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 Jun 2022 18:21:01 -0700 Subject: [PATCH 09/28] Provide a segment res in more cases --- compiler/rustc_resolve/src/ident.rs | 1 + src/test/ui/error-codes/E0109.stderr | 4 +- src/test/ui/error-codes/E0110.stderr | 4 +- .../cannot-infer-closure-circular.rs | 4 +- .../cannot-infer-closure-circular.stderr | 12 +-- .../enum-variant-generic-args.rs | 6 +- .../enum-variant-generic-args.stderr | 12 +-- src/test/ui/type/issue-91268.rs | 2 +- src/test/ui/type/issue-91268.stderr | 4 +- src/test/ui/typeck/prim-with-args.fixed | 44 +++++----- src/test/ui/typeck/prim-with-args.rs | 44 +++++----- src/test/ui/typeck/prim-with-args.stderr | 88 +++++++++---------- src/test/ui/usize-generic-argument-parent.rs | 2 +- .../ui/usize-generic-argument-parent.stderr | 4 +- 14 files changed, 116 insertions(+), 115 deletions(-) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index e934e189f05f3..0cc6d05d1d086 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1502,6 +1502,7 @@ impl<'a> Resolver<'a> { return PathResult::NonModule(PartialRes::new(Res::Err)); } else if opt_ns.is_some() && (is_last || maybe_assoc) { self.lint_if_path_starts_with_module(finalize, path, second_binding); + record_segment_res(self, res); return PathResult::NonModule(PartialRes::with_unresolved_segments( res, path.len() - i - 1, diff --git a/src/test/ui/error-codes/E0109.stderr b/src/test/ui/error-codes/E0109.stderr index da00fdde6bd0a..8f4cb86de99a0 100644 --- a/src/test/ui/error-codes/E0109.stderr +++ b/src/test/ui/error-codes/E0109.stderr @@ -1,10 +1,10 @@ -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `u32` --> $DIR/E0109.rs:1:14 | LL | type X = u32; | --- ^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u32` | help: primitive type `u32` doesn't have generic parameters | diff --git a/src/test/ui/error-codes/E0110.stderr b/src/test/ui/error-codes/E0110.stderr index 5babb5c2961b7..4ce2a0a410ce4 100644 --- a/src/test/ui/error-codes/E0110.stderr +++ b/src/test/ui/error-codes/E0110.stderr @@ -1,10 +1,10 @@ -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `u32` --> $DIR/E0110.rs:1:14 | LL | type X = u32<'static>; | --- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u32` | help: primitive type `u32` doesn't have generic parameters | diff --git a/src/test/ui/inference/cannot-infer-closure-circular.rs b/src/test/ui/inference/cannot-infer-closure-circular.rs index ae879db68ec13..affb481496d02 100644 --- a/src/test/ui/inference/cannot-infer-closure-circular.rs +++ b/src/test/ui/inference/cannot-infer-closure-circular.rs @@ -4,10 +4,10 @@ fn main() { // error handles this gracefully, and in particular doesn't generate an extra // note about the `?` operator in the closure body, which isn't relevant to // the inference. - let x = |r| { + let x = |r| { //~ ERROR type annotations needed for `Result<(), E>` let v = r?; Ok(v) }; - let _ = x(x(Ok(()))); //~ ERROR type annotations needed for `Result<(), E>` + let _ = x(x(Ok(()))); } diff --git a/src/test/ui/inference/cannot-infer-closure-circular.stderr b/src/test/ui/inference/cannot-infer-closure-circular.stderr index 3ad8e3cda16e5..b706cd2bc36e8 100644 --- a/src/test/ui/inference/cannot-infer-closure-circular.stderr +++ b/src/test/ui/inference/cannot-infer-closure-circular.stderr @@ -1,13 +1,13 @@ error[E0282]: type annotations needed for `Result<(), E>` - --> $DIR/cannot-infer-closure-circular.rs:12:9 + --> $DIR/cannot-infer-closure-circular.rs:7:14 | -LL | let _ = x(x(Ok(()))); - | ^ +LL | let x = |r| { + | ^ | -help: consider giving this pattern a type, where the type for type parameter `E` is specified +help: consider giving this closure parameter an explicit type, where the type for type parameter `E` is specified | -LL | let _: Result<(), E> = x(x(Ok(()))); - | +++++++++++++++ +LL | let x = |r: Result<(), E>| { + | +++++++++++++++ error: aborting due to previous error diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs index e6f45036f8514..0031a4665c814 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs +++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.rs @@ -52,7 +52,7 @@ fn main() { // Tuple struct variant Enum::<()>::TSVariant::<()>(()); - //~^ ERROR type arguments are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on tuple variant `TSVariant` [E0109] Alias::TSVariant::<()>(()); //~^ ERROR type arguments are not allowed on this type [E0109] @@ -70,7 +70,7 @@ fn main() { // Struct variant Enum::<()>::SVariant::<()> { v: () }; - //~^ ERROR type arguments are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on variant `SVariant` [E0109] Alias::SVariant::<()> { v: () }; //~^ ERROR type arguments are not allowed on this type [E0109] @@ -88,7 +88,7 @@ fn main() { // Unit variant Enum::<()>::UVariant::<()>; - //~^ ERROR type arguments are not allowed on this type [E0109] + //~^ ERROR type arguments are not allowed on unit variant `UVariant` [E0109] Alias::UVariant::<()>; //~^ ERROR type arguments are not allowed on this type [E0109] diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr index 9601bdce4c503..5467f61bee40f 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr +++ b/src/test/ui/type-alias-enum-variants/enum-variant-generic-args.stderr @@ -272,13 +272,13 @@ LL | Self::<()>::UVariant::<()>; | | | not allowed on this type -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on tuple variant `TSVariant` --> $DIR/enum-variant-generic-args.rs:54:29 | LL | Enum::<()>::TSVariant::<()>(()); | --------- ^^ type argument not allowed | | - | not allowed on this type + | not allowed on tuple variant `TSVariant` error[E0109]: type arguments are not allowed on this type --> $DIR/enum-variant-generic-args.rs:57:24 @@ -340,13 +340,13 @@ LL | AliasFixed::<()>::TSVariant::<()>(()); | | | not allowed on this type -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on variant `SVariant` --> $DIR/enum-variant-generic-args.rs:72:28 | LL | Enum::<()>::SVariant::<()> { v: () }; | -------- ^^ type argument not allowed | | - | not allowed on this type + | not allowed on variant `SVariant` | = note: enum variants can't have type parameters @@ -438,13 +438,13 @@ LL - AliasFixed::<()>::SVariant::<()> { v: () }; LL + AliasFixed::<()>::SVariant { v: () }; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on unit variant `UVariant` --> $DIR/enum-variant-generic-args.rs:90:28 | LL | Enum::<()>::UVariant::<()>; | -------- ^^ type argument not allowed | | - | not allowed on this type + | not allowed on unit variant `UVariant` error[E0109]: type arguments are not allowed on this type --> $DIR/enum-variant-generic-args.rs:93:23 diff --git a/src/test/ui/type/issue-91268.rs b/src/test/ui/type/issue-91268.rs index 01ed9ea9e231f..f1e16bc7bd3c1 100644 --- a/src/test/ui/type/issue-91268.rs +++ b/src/test/ui/type/issue-91268.rs @@ -1,7 +1,7 @@ // error-pattern: this file contains an unclosed delimiter // error-pattern: cannot find type `ţ` in this scope // error-pattern: parenthesized type parameters may only be used with a `Fn` trait -// error-pattern: type arguments are not allowed on this type +// error-pattern: type arguments are not allowed on builtin type `u8` // error-pattern: mismatched types // ignore-tidy-trailing-newlines // `ţ` must be the last character in this file, it cannot be followed by a newline diff --git a/src/test/ui/type/issue-91268.stderr b/src/test/ui/type/issue-91268.stderr index e426f450b11bb..6c9ee9945844d 100644 --- a/src/test/ui/type/issue-91268.stderr +++ b/src/test/ui/type/issue-91268.stderr @@ -35,13 +35,13 @@ help: use angle brackets instead LL | 0: u8<ţ> | ~ + -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `u8` --> $DIR/issue-91268.rs:9:11 | LL | 0: u8(ţ | -- ^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u8` | help: primitive type `u8` doesn't have generic parameters | diff --git a/src/test/ui/typeck/prim-with-args.fixed b/src/test/ui/typeck/prim-with-args.fixed index 1c5fd7508676a..e3f99479a3809 100644 --- a/src/test/ui/typeck/prim-with-args.fixed +++ b/src/test/ui/typeck/prim-with-args.fixed @@ -1,28 +1,28 @@ // run-rustfix fn main() { -let _x: isize; //~ ERROR type arguments are not allowed on this type -let _x: i8; //~ ERROR type arguments are not allowed on this type -let _x: i16; //~ ERROR type arguments are not allowed on this type -let _x: i32; //~ ERROR type arguments are not allowed on this type -let _x: i64; //~ ERROR type arguments are not allowed on this type -let _x: usize; //~ ERROR type arguments are not allowed on this type -let _x: u8; //~ ERROR type arguments are not allowed on this type -let _x: u16; //~ ERROR type arguments are not allowed on this type -let _x: u32; //~ ERROR type arguments are not allowed on this type -let _x: u64; //~ ERROR type arguments are not allowed on this type -let _x: char; //~ ERROR type arguments are not allowed on this type +let _x: isize; //~ ERROR type arguments are not allowed on builtin type +let _x: i8; //~ ERROR type arguments are not allowed on builtin type +let _x: i16; //~ ERROR type arguments are not allowed on builtin type +let _x: i32; //~ ERROR type arguments are not allowed on builtin type +let _x: i64; //~ ERROR type arguments are not allowed on builtin type +let _x: usize; //~ ERROR type arguments are not allowed on builtin type +let _x: u8; //~ ERROR type arguments are not allowed on builtin type +let _x: u16; //~ ERROR type arguments are not allowed on builtin type +let _x: u32; //~ ERROR type arguments are not allowed on builtin type +let _x: u64; //~ ERROR type arguments are not allowed on builtin type +let _x: char; //~ ERROR type arguments are not allowed on builtin type -let _x: isize; //~ ERROR lifetime arguments are not allowed on this type -let _x: i8; //~ ERROR lifetime arguments are not allowed on this type -let _x: i16; //~ ERROR lifetime arguments are not allowed on this type -let _x: i32; //~ ERROR lifetime arguments are not allowed on this type -let _x: i64; //~ ERROR lifetime arguments are not allowed on this type -let _x: usize; //~ ERROR lifetime arguments are not allowed on this type -let _x: u8; //~ ERROR lifetime arguments are not allowed on this type -let _x: u16; //~ ERROR lifetime arguments are not allowed on this type -let _x: u32; //~ ERROR lifetime arguments are not allowed on this type -let _x: u64; //~ ERROR lifetime arguments are not allowed on this type -let _x: char; //~ ERROR lifetime arguments are not allowed on this type +let _x: isize; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i8; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i16; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i32; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i64; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: usize; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u8; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u16; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u32; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u64; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: char; //~ ERROR lifetime arguments are not allowed on builtin type } diff --git a/src/test/ui/typeck/prim-with-args.rs b/src/test/ui/typeck/prim-with-args.rs index b05d6c1cb4e4a..b10471eccee68 100644 --- a/src/test/ui/typeck/prim-with-args.rs +++ b/src/test/ui/typeck/prim-with-args.rs @@ -1,28 +1,28 @@ // run-rustfix fn main() { -let _x: isize; //~ ERROR type arguments are not allowed on this type -let _x: i8; //~ ERROR type arguments are not allowed on this type -let _x: i16; //~ ERROR type arguments are not allowed on this type -let _x: i32; //~ ERROR type arguments are not allowed on this type -let _x: i64; //~ ERROR type arguments are not allowed on this type -let _x: usize; //~ ERROR type arguments are not allowed on this type -let _x: u8; //~ ERROR type arguments are not allowed on this type -let _x: u16; //~ ERROR type arguments are not allowed on this type -let _x: u32; //~ ERROR type arguments are not allowed on this type -let _x: u64; //~ ERROR type arguments are not allowed on this type -let _x: char; //~ ERROR type arguments are not allowed on this type +let _x: isize; //~ ERROR type arguments are not allowed on builtin type +let _x: i8; //~ ERROR type arguments are not allowed on builtin type +let _x: i16; //~ ERROR type arguments are not allowed on builtin type +let _x: i32; //~ ERROR type arguments are not allowed on builtin type +let _x: i64; //~ ERROR type arguments are not allowed on builtin type +let _x: usize; //~ ERROR type arguments are not allowed on builtin type +let _x: u8; //~ ERROR type arguments are not allowed on builtin type +let _x: u16; //~ ERROR type arguments are not allowed on builtin type +let _x: u32; //~ ERROR type arguments are not allowed on builtin type +let _x: u64; //~ ERROR type arguments are not allowed on builtin type +let _x: char; //~ ERROR type arguments are not allowed on builtin type -let _x: isize<'static>; //~ ERROR lifetime arguments are not allowed on this type -let _x: i8<'static>; //~ ERROR lifetime arguments are not allowed on this type -let _x: i16<'static>; //~ ERROR lifetime arguments are not allowed on this type -let _x: i32<'static>; //~ ERROR lifetime arguments are not allowed on this type -let _x: i64<'static>; //~ ERROR lifetime arguments are not allowed on this type -let _x: usize<'static>; //~ ERROR lifetime arguments are not allowed on this type -let _x: u8<'static>; //~ ERROR lifetime arguments are not allowed on this type -let _x: u16<'static>; //~ ERROR lifetime arguments are not allowed on this type -let _x: u32<'static>; //~ ERROR lifetime arguments are not allowed on this type -let _x: u64<'static>; //~ ERROR lifetime arguments are not allowed on this type -let _x: char<'static>; //~ ERROR lifetime arguments are not allowed on this type +let _x: isize<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i8<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i16<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i32<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: i64<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: usize<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u8<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u16<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u32<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: u64<'static>; //~ ERROR lifetime arguments are not allowed on builtin type +let _x: char<'static>; //~ ERROR lifetime arguments are not allowed on builtin type } diff --git a/src/test/ui/typeck/prim-with-args.stderr b/src/test/ui/typeck/prim-with-args.stderr index c45fd00bae9a5..2ddad5ad71e46 100644 --- a/src/test/ui/typeck/prim-with-args.stderr +++ b/src/test/ui/typeck/prim-with-args.stderr @@ -1,10 +1,10 @@ -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `isize` --> $DIR/prim-with-args.rs:4:15 | LL | let _x: isize; | ----- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `isize` | help: primitive type `isize` doesn't have generic parameters | @@ -12,13 +12,13 @@ LL - let _x: isize; LL + let _x: isize; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `i8` --> $DIR/prim-with-args.rs:5:12 | LL | let _x: i8; | -- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `i8` | help: primitive type `i8` doesn't have generic parameters | @@ -26,13 +26,13 @@ LL - let _x: i8; LL + let _x: i8; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `i16` --> $DIR/prim-with-args.rs:6:13 | LL | let _x: i16; | --- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `i16` | help: primitive type `i16` doesn't have generic parameters | @@ -40,13 +40,13 @@ LL - let _x: i16; LL + let _x: i16; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `i32` --> $DIR/prim-with-args.rs:7:13 | LL | let _x: i32; | --- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `i32` | help: primitive type `i32` doesn't have generic parameters | @@ -54,13 +54,13 @@ LL - let _x: i32; LL + let _x: i32; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `i64` --> $DIR/prim-with-args.rs:8:13 | LL | let _x: i64; | --- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `i64` | help: primitive type `i64` doesn't have generic parameters | @@ -68,13 +68,13 @@ LL - let _x: i64; LL + let _x: i64; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `usize` --> $DIR/prim-with-args.rs:9:15 | LL | let _x: usize; | ----- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `usize` | help: primitive type `usize` doesn't have generic parameters | @@ -82,13 +82,13 @@ LL - let _x: usize; LL + let _x: usize; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `u8` --> $DIR/prim-with-args.rs:10:12 | LL | let _x: u8; | -- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u8` | help: primitive type `u8` doesn't have generic parameters | @@ -96,13 +96,13 @@ LL - let _x: u8; LL + let _x: u8; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `u16` --> $DIR/prim-with-args.rs:11:13 | LL | let _x: u16; | --- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u16` | help: primitive type `u16` doesn't have generic parameters | @@ -110,13 +110,13 @@ LL - let _x: u16; LL + let _x: u16; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `u32` --> $DIR/prim-with-args.rs:12:13 | LL | let _x: u32; | --- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u32` | help: primitive type `u32` doesn't have generic parameters | @@ -124,13 +124,13 @@ LL - let _x: u32; LL + let _x: u32; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `u64` --> $DIR/prim-with-args.rs:13:13 | LL | let _x: u64; | --- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u64` | help: primitive type `u64` doesn't have generic parameters | @@ -138,13 +138,13 @@ LL - let _x: u64; LL + let _x: u64; | -error[E0109]: type arguments are not allowed on this type +error[E0109]: type arguments are not allowed on builtin type `char` --> $DIR/prim-with-args.rs:14:14 | LL | let _x: char; | ---- ^^^^^ type argument not allowed | | - | not allowed on this type + | not allowed on builtin type `char` | help: primitive type `char` doesn't have generic parameters | @@ -152,13 +152,13 @@ LL - let _x: char; LL + let _x: char; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `isize` --> $DIR/prim-with-args.rs:16:15 | LL | let _x: isize<'static>; | ----- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `isize` | help: primitive type `isize` doesn't have generic parameters | @@ -166,13 +166,13 @@ LL - let _x: isize<'static>; LL + let _x: isize; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `i8` --> $DIR/prim-with-args.rs:17:12 | LL | let _x: i8<'static>; | -- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `i8` | help: primitive type `i8` doesn't have generic parameters | @@ -180,13 +180,13 @@ LL - let _x: i8<'static>; LL + let _x: i8; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `i16` --> $DIR/prim-with-args.rs:18:13 | LL | let _x: i16<'static>; | --- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `i16` | help: primitive type `i16` doesn't have generic parameters | @@ -194,13 +194,13 @@ LL - let _x: i16<'static>; LL + let _x: i16; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `i32` --> $DIR/prim-with-args.rs:19:13 | LL | let _x: i32<'static>; | --- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `i32` | help: primitive type `i32` doesn't have generic parameters | @@ -208,13 +208,13 @@ LL - let _x: i32<'static>; LL + let _x: i32; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `i64` --> $DIR/prim-with-args.rs:20:13 | LL | let _x: i64<'static>; | --- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `i64` | help: primitive type `i64` doesn't have generic parameters | @@ -222,13 +222,13 @@ LL - let _x: i64<'static>; LL + let _x: i64; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `usize` --> $DIR/prim-with-args.rs:21:15 | LL | let _x: usize<'static>; | ----- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `usize` | help: primitive type `usize` doesn't have generic parameters | @@ -236,13 +236,13 @@ LL - let _x: usize<'static>; LL + let _x: usize; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `u8` --> $DIR/prim-with-args.rs:22:12 | LL | let _x: u8<'static>; | -- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u8` | help: primitive type `u8` doesn't have generic parameters | @@ -250,13 +250,13 @@ LL - let _x: u8<'static>; LL + let _x: u8; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `u16` --> $DIR/prim-with-args.rs:23:13 | LL | let _x: u16<'static>; | --- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u16` | help: primitive type `u16` doesn't have generic parameters | @@ -264,13 +264,13 @@ LL - let _x: u16<'static>; LL + let _x: u16; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `u32` --> $DIR/prim-with-args.rs:24:13 | LL | let _x: u32<'static>; | --- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u32` | help: primitive type `u32` doesn't have generic parameters | @@ -278,13 +278,13 @@ LL - let _x: u32<'static>; LL + let _x: u32; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `u64` --> $DIR/prim-with-args.rs:25:13 | LL | let _x: u64<'static>; | --- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `u64` | help: primitive type `u64` doesn't have generic parameters | @@ -292,13 +292,13 @@ LL - let _x: u64<'static>; LL + let _x: u64; | -error[E0109]: lifetime arguments are not allowed on this type +error[E0109]: lifetime arguments are not allowed on builtin type `char` --> $DIR/prim-with-args.rs:26:14 | LL | let _x: char<'static>; | ---- ^^^^^^^ lifetime argument not allowed | | - | not allowed on this type + | not allowed on builtin type `char` | help: primitive type `char` doesn't have generic parameters | diff --git a/src/test/ui/usize-generic-argument-parent.rs b/src/test/ui/usize-generic-argument-parent.rs index 6d17ba9b5b261..4ab80d944a56f 100644 --- a/src/test/ui/usize-generic-argument-parent.rs +++ b/src/test/ui/usize-generic-argument-parent.rs @@ -1,5 +1,5 @@ fn foo() { - let x: usize; //~ ERROR const arguments are not allowed on this type + let x: usize; //~ ERROR const arguments are not allowed on builtin type `usize` } fn main() {} diff --git a/src/test/ui/usize-generic-argument-parent.stderr b/src/test/ui/usize-generic-argument-parent.stderr index abe8c09b739f7..131c476aa55c0 100644 --- a/src/test/ui/usize-generic-argument-parent.stderr +++ b/src/test/ui/usize-generic-argument-parent.stderr @@ -1,10 +1,10 @@ -error[E0109]: const arguments are not allowed on this type +error[E0109]: const arguments are not allowed on builtin type `usize` --> $DIR/usize-generic-argument-parent.rs:2:18 | LL | let x: usize; | ----- ^^^ const argument not allowed | | - | not allowed on this type + | not allowed on builtin type `usize` | help: primitive type `usize` doesn't have generic parameters | From 761c846a0751ea48c45b246b0b21407e72e906b1 Mon Sep 17 00:00:00 2001 From: beetrees Date: Tue, 21 Jun 2022 18:56:04 +0100 Subject: [PATCH 10/28] Add `create_err` and `emit_err` to `ExtCtxt` --- compiler/rustc_expand/src/base.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 75b6b1cc9195b..245719bff1202 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -14,7 +14,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, MultiSpan, use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::BuiltinLintDiagnostics; use rustc_parse::{self, parser, MACRO_ARGUMENTS}; -use rustc_session::{parse::ParseSess, Limit, Session}; +use rustc_session::{parse::ParseSess, Limit, Session, SessionDiagnostic}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; @@ -1085,6 +1085,17 @@ impl<'a> ExtCtxt<'a> { self.sess.parse_sess.span_diagnostic.struct_span_err(sp, msg) } + pub fn create_err( + &self, + err: impl SessionDiagnostic<'a>, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + self.sess.create_err(err) + } + + pub fn emit_err(&self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed { + self.sess.emit_err(err) + } + /// Emit `msg` attached to `sp`, without immediately stopping /// compilation. /// From d6072e53cd975839ad5e4c2d3ae101ce7ea0c3c0 Mon Sep 17 00:00:00 2001 From: beetrees Date: Tue, 21 Jun 2022 19:28:22 +0100 Subject: [PATCH 11/28] Add UI test for `cfg!(foo, bar)` --- src/test/ui/macros/cfg.rs | 1 + src/test/ui/macros/cfg.stderr | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/ui/macros/cfg.rs b/src/test/ui/macros/cfg.rs index 222161a8183a2..2aac50a9d011a 100644 --- a/src/test/ui/macros/cfg.rs +++ b/src/test/ui/macros/cfg.rs @@ -2,4 +2,5 @@ fn main() { cfg!(); //~ ERROR macro requires a cfg-pattern cfg!(123); //~ ERROR expected identifier cfg!(foo = 123); //~ ERROR literal in `cfg` predicate value must be a string + cfg!(foo, bar); //~ ERROR expected 1 cfg-pattern } diff --git a/src/test/ui/macros/cfg.stderr b/src/test/ui/macros/cfg.stderr index 4785ef9aae482..2633d5f720d70 100644 --- a/src/test/ui/macros/cfg.stderr +++ b/src/test/ui/macros/cfg.stderr @@ -18,6 +18,14 @@ error[E0565]: literal in `cfg` predicate value must be a string LL | cfg!(foo = 123); | ^^^ -error: aborting due to 3 previous errors +error: expected 1 cfg-pattern + --> $DIR/cfg.rs:5:5 + | +LL | cfg!(foo, bar); + | ^^^^^^^^^^^^^^ + | + = note: this error originates in the macro `cfg` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0565`. From 6264ffbfef035448661222ec9baf4648b1d9cb77 Mon Sep 17 00:00:00 2001 From: beetrees Date: Tue, 21 Jun 2022 20:10:31 +0100 Subject: [PATCH 12/28] Migrate `builtin-macros-requires-cfg-pattern` to `SessionDiagnostic` --- Cargo.lock | 1 + compiler/rustc_builtin_macros/Cargo.toml | 1 + compiler/rustc_builtin_macros/src/cfg.rs | 17 ++++++++++++----- .../locales/en-US/builtin_macros.ftl | 3 +++ compiler/rustc_error_messages/src/lib.rs | 1 + 5 files changed, 18 insertions(+), 5 deletions(-) create mode 100644 compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl diff --git a/Cargo.lock b/Cargo.lock index 1ca6ce25ba151..692474f2657b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3669,6 +3669,7 @@ dependencies = [ "rustc_feature", "rustc_lexer", "rustc_lint_defs", + "rustc_macros", "rustc_parse", "rustc_parse_format", "rustc_session", diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml index 9031c3b2ecfbb..7dc947f7d9a14 100644 --- a/compiler/rustc_builtin_macros/Cargo.toml +++ b/compiler/rustc_builtin_macros/Cargo.toml @@ -16,6 +16,7 @@ rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } rustc_lexer = { path = "../rustc_lexer" } rustc_lint_defs = { path = "../rustc_lint_defs" } +rustc_macros = { path = "../rustc_macros" } rustc_parse = { path = "../rustc_parse" } rustc_target = { path = "../rustc_target" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index f5ef4765df64f..2a6adc216643f 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -8,6 +8,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_attr as attr; use rustc_errors::PResult; use rustc_expand::base::{self, *}; +use rustc_macros::SessionDiagnostic; use rustc_span::Span; pub fn expand_cfg( @@ -34,13 +35,19 @@ pub fn expand_cfg( } } -fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> { +#[derive(SessionDiagnostic)] +#[error(slug = "builtin-macros-requires-cfg-pattern")] +struct RequiresCfgPattern { + #[primary_span] + #[label] + span: Span, +} + +fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { - let mut err = cx.struct_span_err(sp, "macro requires a cfg-pattern as an argument"); - err.span_label(sp, "cfg-pattern required"); - return Err(err); + return Err(cx.create_err(RequiresCfgPattern { span })); } let cfg = p.parse_meta_item()?; @@ -48,7 +55,7 @@ fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult<'a let _ = p.eat(&token::Comma); if !p.eat(&token::Eof) { - return Err(cx.struct_span_err(sp, "expected 1 cfg-pattern")); + return Err(cx.struct_span_err(span, "expected 1 cfg-pattern")); } Ok(cfg) diff --git a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl b/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl new file mode 100644 index 0000000000000..89cd9fe579d6b --- /dev/null +++ b/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl @@ -0,0 +1,3 @@ +builtin-macros-requires-cfg-pattern = + macro requires a cfg-pattern as an argument + .label = cfg-pattern required diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index ba7cc4908b80f..7211c05432698 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -33,6 +33,7 @@ pub use unic_langid::{langid, LanguageIdentifier}; fluent_messages! { parser => "../locales/en-US/parser.ftl", typeck => "../locales/en-US/typeck.ftl", + builtin_macros => "../locales/en-US/builtin_macros.ftl", } pub use fluent_generated::{self as fluent, DEFAULT_LOCALE_RESOURCES}; From be5337cde53eabca8a242d7de11f6702a40a1237 Mon Sep 17 00:00:00 2001 From: beetrees Date: Tue, 21 Jun 2022 20:20:00 +0100 Subject: [PATCH 13/28] Migrate `builtin-macros-expected-one-cfg-pattern` to `SessionDiagnostic` --- compiler/rustc_builtin_macros/src/cfg.rs | 9 ++++++++- .../locales/en-US/builtin_macros.ftl | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 2a6adc216643f..c75d83bd0a0e3 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -43,6 +43,13 @@ struct RequiresCfgPattern { span: Span, } +#[derive(SessionDiagnostic)] +#[error(slug = "builtin-macros-expected-one-cfg-pattern")] +struct OneCfgPattern { + #[primary_span] + span: Span, +} + fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a, ast::MetaItem> { let mut p = cx.new_parser_from_tts(tts); @@ -55,7 +62,7 @@ fn parse_cfg<'a>(cx: &mut ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult< let _ = p.eat(&token::Comma); if !p.eat(&token::Eof) { - return Err(cx.struct_span_err(span, "expected 1 cfg-pattern")); + return Err(cx.create_err(OneCfgPattern { span })); } Ok(cfg) diff --git a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl b/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl index 89cd9fe579d6b..1d3e33c81851f 100644 --- a/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl +++ b/compiler/rustc_error_messages/locales/en-US/builtin_macros.ftl @@ -1,3 +1,5 @@ builtin-macros-requires-cfg-pattern = macro requires a cfg-pattern as an argument .label = cfg-pattern required + +builtin-macros-expected-one-cfg-pattern = expected 1 cfg-pattern From 8e09f42042b5644aff05931b08112154c0575d5d Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Tue, 21 Jun 2022 13:19:44 -0700 Subject: [PATCH 14/28] Update Emscripten's no_default_libraries handling --- compiler/rustc_codegen_ssa/src/back/linker.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 8ac5f094cf6ee..b5b63942e2c6e 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1140,7 +1140,7 @@ impl<'a> Linker for EmLinker<'a> { fn no_crt_objects(&mut self) {} fn no_default_libraries(&mut self) { - self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]); + self.cmd.arg("-nodefaultlibs"); } fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { From b052d76586988040c6ae8aef609794ae16cc28dc Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 21 Jun 2022 19:43:46 -0500 Subject: [PATCH 15/28] Address review comments from #98259 It got merged so fast I didn't have time to make changes xD --- compiler/rustc_middle/src/ty/context.rs | 16 +++++++++++- .../src/traits/error_reporting/suggestions.rs | 26 +++---------------- src/test/ui/async-await/issue-68112.stderr | 4 +-- ...e-70935-complex-spans.drop_tracking.stderr | 4 +-- .../async-await/issue-70935-complex-spans.rs | 4 +-- .../partial-drop-partial-reinit.rs | 2 +- .../partial-drop-partial-reinit.stderr | 2 +- 7 files changed, 27 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c43cf07b3ad0a..0765928e9b95c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -74,7 +74,7 @@ use std::mem; use std::ops::{Bound, Deref}; use std::sync::Arc; -use super::RvalueScopes; +use super::{ImplPolarity, RvalueScopes}; pub trait OnDiskCache<'tcx>: rustc_data_structures::sync::Sync { /// Creates a new `OnDiskCache` instance from the serialized data in `data`. @@ -2224,6 +2224,20 @@ impl<'tcx> TyCtxt<'tcx> { }) } + /// Given a `ty`, return whether it's an `impl Future<...>`. + pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool { + let ty::Opaque(def_id, _) = ty.kind() else { return false }; + let future_trait = self.lang_items().future_trait().unwrap(); + + self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| { + let ty::PredicateKind::Trait(trait_predicate) = predicate.kind().skip_binder() else { + return false; + }; + trait_predicate.trait_ref.def_id == future_trait + && trait_predicate.polarity == ImplPolarity::Positive + }) + } + /// Computes the def-ids of the transitive supertraits of `trait_def_id`. This (intentionally) /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used /// to identify which traits may define a given associated type to help avoid cycle errors. diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 159fcf932a1da..19318a85a0125 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -8,7 +8,6 @@ use crate::infer::InferCtxt; use crate::traits::normalize_to; use hir::HirId; -use rustc_ast::Movability; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ @@ -2406,19 +2405,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } }; - let future_trait = self.tcx.lang_items().future_trait().unwrap(); - let opaque_ty_is_future = |def_id| { - self.tcx.explicit_item_bounds(def_id).iter().any(|(predicate, _)| { - if let ty::PredicateKind::Trait(trait_predicate) = - predicate.kind().skip_binder() - { - trait_predicate.trait_ref.def_id == future_trait - } else { - false - } - }) - }; - let from_generator = tcx.lang_items().from_generator_fn().unwrap(); // Don't print the tuple of capture types @@ -2444,13 +2430,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // If the previous type is `from_generator`, this is the future generated by the body of an async function. // Avoid printing it twice (it was already printed in the `ty::Generator` arm below). - let is_future = opaque_ty_is_future(def_id); + let is_future = tcx.ty_is_opaque_future(ty); debug!( ?obligated_types, ?is_future, "note_obligation_cause_code: check for async fn" ); - if opaque_ty_is_future(def_id) + if is_future && obligated_types.last().map_or(false, |ty| match ty.kind() { ty::Opaque(last_def_id, _) => { tcx.parent(*last_def_id) == from_generator @@ -2475,15 +2461,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } err.note(msg.trim_end_matches(", ")) } - ty::Generator(def_id, _, movability) => { + ty::Generator(def_id, _, _) => { let sp = self.tcx.def_span(def_id); // Special-case this to say "async block" instead of `[static generator]`. - let kind = if *movability == Movability::Static { - "async block" - } else { - "generator" - }; + let kind = tcx.generator_kind(def_id).unwrap(); err.span_note( sp, &format!("required because it's used within this {}", kind), diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr index b8d3e1540d8a9..4285fbbeceb60 100644 --- a/src/test/ui/async-await/issue-68112.stderr +++ b/src/test/ui/async-await/issue-68112.stderr @@ -42,7 +42,7 @@ LL | require_send(send_fut); | = help: the trait `Sync` is not implemented for `RefCell` = note: required because of the requirements on the impl of `Send` for `Arc>` -note: required because it's used within this async block +note: required because it's used within this `async fn` body --> $DIR/issue-68112.rs:47:31 | LL | async fn ready2(t: T) -> T { t } @@ -53,7 +53,7 @@ note: required because it appears within the type `impl Future impl Future>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: required because it captures the following types: `ResumeTy`, `impl Future>>`, `()`, `i32`, `Ready` -note: required because it's used within this async block +note: required because it's used within this `async` block --> $DIR/issue-68112.rs:55:26 | LL | let send_fut = async { diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index 19fd5eb7c73fb..43b7cb8cece36 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -14,7 +14,7 @@ LL | baz(|| async{ LL | | foo(tx.clone()); LL | | }).await; | |_________^ -note: required because it's used within this async block +note: required because it's used within this `async fn` body --> $DIR/issue-70935-complex-spans.rs:9:67 | LL | async fn baz(_c: impl FnMut() -> T) where T: Future { @@ -23,7 +23,7 @@ LL | | LL | | } | |_^ = note: required because it captures the following types: `ResumeTy`, `impl Future`, `()` -note: required because it's used within this async block +note: required because it's used within this `async` block --> $DIR/issue-70935-complex-spans.rs:23:16 | LL | async move { diff --git a/src/test/ui/async-await/issue-70935-complex-spans.rs b/src/test/ui/async-await/issue-70935-complex-spans.rs index 4bf94fe342c1d..f45ce1f25efa0 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.rs +++ b/src/test/ui/async-await/issue-70935-complex-spans.rs @@ -7,7 +7,7 @@ use std::future::Future; async fn baz(_c: impl FnMut() -> T) where T: Future { -//[drop_tracking]~^ within this async block +//[drop_tracking]~^ within this `async fn` body } fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { @@ -21,7 +21,7 @@ fn foo(tx: std::sync::mpsc::Sender) -> impl Future + Send { //[drop_tracking]~| NOTE: in this expansion //[drop_tracking]~| NOTE: in this expansion async move { - //[drop_tracking]~^ within this async block + //[drop_tracking]~^ within this `async` block baz(|| async{ //[drop_tracking]~ NOTE: used within this closure foo(tx.clone()); }).await; diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.rs b/src/test/ui/async-await/partial-drop-partial-reinit.rs index 4fcfacea3f886..fe0fce7afd9f9 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.rs +++ b/src/test/ui/async-await/partial-drop-partial-reinit.rs @@ -26,7 +26,7 @@ impl Drop for NotSend { impl !Send for NotSend {} async fn foo() { -//~^ NOTE used within this async block +//~^ NOTE used within this `async fn` body //~| NOTE within this `impl Future let mut x = (NotSend {},); drop(x.0); diff --git a/src/test/ui/async-await/partial-drop-partial-reinit.stderr b/src/test/ui/async-await/partial-drop-partial-reinit.stderr index 96d0c71f103fb..05f5358340a98 100644 --- a/src/test/ui/async-await/partial-drop-partial-reinit.stderr +++ b/src/test/ui/async-await/partial-drop-partial-reinit.stderr @@ -12,7 +12,7 @@ LL | async fn foo() { = help: within `impl Future`, the trait `Send` is not implemented for `NotSend` = note: required because it appears within the type `(NotSend,)` = note: required because it captures the following types: `ResumeTy`, `(NotSend,)`, `impl Future`, `()` -note: required because it's used within this async block +note: required because it's used within this `async fn` body --> $DIR/partial-drop-partial-reinit.rs:28:16 | LL | async fn foo() { From d15fed79b84c621b42699442ccf99563a6bc6881 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 19 Jun 2022 23:11:31 -0700 Subject: [PATCH 16/28] Improve suggestion for calling closure on type mismatch --- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- .../src/check/fn_ctxt/suggestions.rs | 189 +++++++----------- .../suggest-calling-rpit-closure.rs | 12 ++ .../suggest-calling-rpit-closure.stderr | 21 ++ src/test/ui/parser/expr-as-stmt.stderr | 4 + ...truct-literal-restrictions-in-lamda.stderr | 6 + src/test/ui/reify-intrinsic.stderr | 4 - .../disallowed-positions.stderr | 8 + src/test/ui/span/move-closure.stderr | 4 + .../fn-or-tuple-struct-without-args.stderr | 14 +- .../type-alias-impl-trait/issue-63279.stderr | 4 + 11 files changed, 143 insertions(+), 125 deletions(-) create mode 100644 src/test/ui/impl-trait/suggest-calling-rpit-closure.rs create mode 100644 src/test/ui/impl-trait/suggest-calling-rpit-closure.stderr diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 97e5a4983fcd1..3cba6d40e38b1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -856,7 +856,7 @@ pub trait PrettyPrinter<'tcx>: p!(")"); if let Term::Ty(ty) = return_ty.skip_binder() { if !ty.is_unit() { - p!("-> ", print(return_ty)); + p!(" -> ", print(return_ty)); } } p!(write("{}", if paren_needed { ")" } else { "" })); diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs index 03d91435e7712..7195da863db48 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs @@ -8,15 +8,14 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ - Expr, ExprKind, GenericBound, ItemKind, Node, Path, QPath, Stmt, StmtKind, TyKind, - WherePredicate, + Expr, ExprKind, GenericBound, Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate, }; use rustc_infer::infer::{self, TyCtxtInferExt}; use rustc_infer::traits; use rustc_middle::lint::in_external_macro; use rustc_middle::ty::subst::GenericArgKind; -use rustc_middle::ty::{self, Binder, IsSuggestable, ToPredicate, Ty}; -use rustc_span::symbol::{kw, sym}; +use rustc_middle::ty::{self, Binder, IsSuggestable, Subst, ToPredicate, Ty}; +use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; @@ -78,124 +77,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, ) -> bool { - let hir = self.tcx.hir(); - let (def_id, sig) = match *found.kind() { - ty::FnDef(def_id, _) => (def_id, found.fn_sig(self.tcx)), - ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig()), + let (def_id, output, inputs) = match *found.kind() { + ty::FnDef(def_id, _) => { + let fn_sig = found.fn_sig(self.tcx); + (def_id, fn_sig.output(), fn_sig.inputs().skip_binder().len()) + } + ty::Closure(def_id, substs) => { + let fn_sig = substs.as_closure().sig(); + (def_id, fn_sig.output(), fn_sig.inputs().skip_binder().len() - 1) + } + ty::Opaque(def_id, substs) => { + let sig = self.tcx.bound_item_bounds(def_id).subst(self.tcx, substs).iter().find_map(|pred| { + if let ty::PredicateKind::Projection(proj) = pred.kind().skip_binder() + && Some(proj.projection_ty.item_def_id) == self.tcx.lang_items().fn_once_output() + // args tuple will always be substs[1] + && let ty::Tuple(args) = proj.projection_ty.substs.type_at(1).kind() + { + Some(( + pred.kind().rebind(proj.term.ty().unwrap()), + args.len(), + )) + } else { + None + } + }); + if let Some((output, inputs)) = sig { + (def_id, output, inputs) + } else { + return false; + } + } _ => return false, }; - let sig = self.replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, sig); - let sig = self.normalize_associated_types_in(expr.span, sig); - if self.can_coerce(sig.output(), expected) { - let (mut sugg_call, applicability) = if sig.inputs().is_empty() { - (String::new(), Applicability::MachineApplicable) - } else { - ("...".to_string(), Applicability::HasPlaceholders) + let output = self.replace_bound_vars_with_fresh_vars(expr.span, infer::FnCall, output); + let output = self.normalize_associated_types_in(expr.span, output); + if !output.is_ty_var() && self.can_coerce(output, expected) { + let (sugg_call, mut applicability) = match inputs { + 0 => ("".to_string(), Applicability::MachineApplicable), + 1..=4 => ( + (0..inputs).map(|_| "_").collect::>().join(", "), + Applicability::MachineApplicable, + ), + _ => ("...".to_string(), Applicability::HasPlaceholders), }; - let mut msg = "call this function"; - match hir.get_if_local(def_id) { - Some( - Node::Item(hir::Item { kind: ItemKind::Fn(.., body_id), .. }) - | Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(_, body_id), .. - }) - | Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Provided(body_id)), - .. - }), - ) => { - let body = hir.body(*body_id); - sugg_call = body - .params - .iter() - .map(|param| match ¶m.pat.kind { - hir::PatKind::Binding(_, _, ident, None) - if ident.name != kw::SelfLower => - { - ident.to_string() - } - _ => "_".to_string(), - }) - .collect::>() - .join(", "); - } - Some(Node::Expr(hir::Expr { - kind: ExprKind::Closure { body: body_id, .. }, - span: full_closure_span, - .. - })) => { - if *full_closure_span == expr.span { - return false; - } - msg = "call this closure"; - let body = hir.body(*body_id); - sugg_call = body - .params - .iter() - .map(|param| match ¶m.pat.kind { - hir::PatKind::Binding(_, _, ident, None) - if ident.name != kw::SelfLower => - { - ident.to_string() - } - _ => "_".to_string(), - }) - .collect::>() - .join(", "); - } - Some(Node::Ctor(hir::VariantData::Tuple(fields, _))) => { - sugg_call = fields.iter().map(|_| "_").collect::>().join(", "); - match def_id.as_local().map(|def_id| self.tcx.def_kind(def_id)) { - Some(DefKind::Ctor(hir::def::CtorOf::Variant, _)) => { - msg = "instantiate this tuple variant"; - } - Some(DefKind::Ctor(CtorOf::Struct, _)) => { - msg = "instantiate this tuple struct"; - } - _ => {} - } + + let msg = match self.tcx.def_kind(def_id) { + DefKind::Fn => "call this function", + DefKind::Closure | DefKind::OpaqueTy => "call this closure", + DefKind::Ctor(CtorOf::Struct, _) => "instantiate this tuple struct", + DefKind::Ctor(CtorOf::Variant, _) => "instantiate this tuple variant", + _ => "call this function", + }; + + let sugg = match expr.kind { + hir::ExprKind::Call(..) + | hir::ExprKind::Path(..) + | hir::ExprKind::Index(..) + | hir::ExprKind::Lit(..) => { + vec![(expr.span.shrink_to_hi(), format!("({sugg_call})"))] } - Some(Node::ForeignItem(hir::ForeignItem { - kind: hir::ForeignItemKind::Fn(_, idents, _), - .. - })) => { - sugg_call = idents - .iter() - .map(|ident| { - if ident.name != kw::SelfLower { - ident.to_string() - } else { - "_".to_string() - } - }) - .collect::>() - .join(", ") + hir::ExprKind::Closure { .. } => { + // Might be `{ expr } || { bool }` + applicability = Applicability::MaybeIncorrect; + vec![ + (expr.span.shrink_to_lo(), "(".to_string()), + (expr.span.shrink_to_hi(), format!(")({sugg_call})")), + ] } - Some(Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Required(idents)), - .. - })) => { - sugg_call = idents - .iter() - .map(|ident| { - if ident.name != kw::SelfLower { - ident.to_string() - } else { - "_".to_string() - } - }) - .collect::>() - .join(", ") + _ => { + vec![ + (expr.span.shrink_to_lo(), "(".to_string()), + (expr.span.shrink_to_hi(), format!(")({sugg_call})")), + ] } - _ => {} - } - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - &format!("use parentheses to {}", msg), - format!("({})", sugg_call), + }; + + err.multipart_suggestion_verbose( + format!("use parentheses to {msg}"), + sugg, applicability, ); + return true; } false diff --git a/src/test/ui/impl-trait/suggest-calling-rpit-closure.rs b/src/test/ui/impl-trait/suggest-calling-rpit-closure.rs new file mode 100644 index 0000000000000..640156291a38c --- /dev/null +++ b/src/test/ui/impl-trait/suggest-calling-rpit-closure.rs @@ -0,0 +1,12 @@ +fn whatever() -> i32 { + opaque() +//~^ ERROR mismatched types +} + +fn opaque() -> impl Fn() -> i32 { + || 0 +} + +fn main() { + let _ = whatever(); +} diff --git a/src/test/ui/impl-trait/suggest-calling-rpit-closure.stderr b/src/test/ui/impl-trait/suggest-calling-rpit-closure.stderr new file mode 100644 index 0000000000000..2a328a0e6f54d --- /dev/null +++ b/src/test/ui/impl-trait/suggest-calling-rpit-closure.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/suggest-calling-rpit-closure.rs:2:5 + | +LL | fn whatever() -> i32 { + | --- expected `i32` because of return type +LL | opaque() + | ^^^^^^^^ expected `i32`, found opaque type +... +LL | fn opaque() -> impl Fn() -> i32 { + | ---------------- the found opaque type + | + = note: expected type `i32` + found opaque type `impl Fn() -> i32` +help: use parentheses to call this closure + | +LL | opaque()() + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/expr-as-stmt.stderr b/src/test/ui/parser/expr-as-stmt.stderr index 8eb81301bc3e8..d4f64a7de5bcf 100644 --- a/src/test/ui/parser/expr-as-stmt.stderr +++ b/src/test/ui/parser/expr-as-stmt.stderr @@ -201,6 +201,10 @@ LL | { true } || { true } | = note: expected type `bool` found closure `[closure@$DIR/expr-as-stmt.rs:51:14: 51:25]` +help: use parentheses to call this closure + | +LL | { true } (|| { true })() + | + +++ help: parentheses are required to parse this as an expression | LL | ({ true }) || { true } diff --git a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr index b948ab2abb508..e71f15ebfd2e7 100644 --- a/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr +++ b/src/test/ui/parser/struct-literal-restrictions-in-lamda.stderr @@ -25,6 +25,12 @@ LL | | }.hi() { | = note: expected type `bool` found closure `[closure@$DIR/struct-literal-restrictions-in-lamda.rs:12:11: 14:11]` +help: use parentheses to call this closure + | +LL ~ while (|| Foo { +LL | x: 3 +LL ~ }.hi())() { + | error: aborting due to 2 previous errors diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr index 70a64446f6a7d..360557fb5201d 100644 --- a/src/test/ui/reify-intrinsic.stderr +++ b/src/test/ui/reify-intrinsic.stderr @@ -8,10 +8,6 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr | = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(isize) -> usize` found fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` -help: use parentheses to call this function - | -LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::transmute(...); - | +++++ error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid --> $DIR/reify-intrinsic.rs:11:13 diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index dfc7fdc1ed2db..f7f39bd0b9a07 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -1118,6 +1118,10 @@ LL | if let Range { start: F, end } = F..|| true {} | = note: expected type `bool` found closure `[closure@$DIR/disallowed-positions.rs:136:41: 136:48]` +help: use parentheses to call this closure + | +LL | if let Range { start: F, end } = F..(|| true)() {} + | + +++ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:136:8 @@ -1314,6 +1318,10 @@ LL | while let Range { start: F, end } = F..|| true {} | = note: expected type `bool` found closure `[closure@$DIR/disallowed-positions.rs:200:44: 200:51]` +help: use parentheses to call this closure + | +LL | while let Range { start: F, end } = F..(|| true)() {} + | + +++ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:200:11 diff --git a/src/test/ui/span/move-closure.stderr b/src/test/ui/span/move-closure.stderr index ded581dc4968e..3e7041f02b388 100644 --- a/src/test/ui/span/move-closure.stderr +++ b/src/test/ui/span/move-closure.stderr @@ -8,6 +8,10 @@ LL | let x: () = move || (); | = note: expected unit type `()` found closure `[closure@$DIR/move-closure.rs:5:17: 5:27]` +help: use parentheses to call this closure + | +LL | let x: () = (move || ())(); + | + +++ error: aborting due to previous error diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 1ed784e8f5bc9..25ce458f6d813 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -33,7 +33,7 @@ LL | let _: usize = foo; found fn item `fn(usize, usize) -> usize {foo}` help: use parentheses to call this function | -LL | let _: usize = foo(a, b); +LL | let _: usize = foo(_, _); | ++++++ error[E0308]: mismatched types @@ -105,7 +105,7 @@ LL | let _: usize = T::baz; found fn item `fn(usize, usize) -> usize {<_ as T>::baz}` help: use parentheses to call this function | -LL | let _: usize = T::baz(x, y); +LL | let _: usize = T::baz(_, _); | ++++++ error[E0308]: mismatched types @@ -123,7 +123,7 @@ LL | let _: usize = T::bat; found fn item `fn(usize) -> usize {<_ as T>::bat}` help: use parentheses to call this function | -LL | let _: usize = T::bat(x); +LL | let _: usize = T::bat(_); | +++ error[E0308]: mismatched types @@ -159,7 +159,7 @@ LL | let _: usize = X::baz; found fn item `fn(usize, usize) -> usize {::baz}` help: use parentheses to call this function | -LL | let _: usize = X::baz(x, y); +LL | let _: usize = X::baz(_, _); | ++++++ error[E0308]: mismatched types @@ -177,7 +177,7 @@ LL | let _: usize = X::bat; found fn item `fn(usize) -> usize {::bat}` help: use parentheses to call this function | -LL | let _: usize = X::bat(x); +LL | let _: usize = X::bat(_); | +++ error[E0308]: mismatched types @@ -195,7 +195,7 @@ LL | let _: usize = X::bax; found fn item `fn(usize) -> usize {::bax}` help: use parentheses to call this function | -LL | let _: usize = X::bax(x); +LL | let _: usize = X::bax(_); | +++ error[E0308]: mismatched types @@ -213,7 +213,7 @@ LL | let _: usize = X::bach; found fn item `fn(usize) -> usize {::bach}` help: use parentheses to call this function | -LL | let _: usize = X::bach(x); +LL | let _: usize = X::bach(_); | +++ error[E0308]: mismatched types diff --git a/src/test/ui/type-alias-impl-trait/issue-63279.stderr b/src/test/ui/type-alias-impl-trait/issue-63279.stderr index 33f81a77aaf0a..ab39ee74be442 100644 --- a/src/test/ui/type-alias-impl-trait/issue-63279.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-63279.stderr @@ -15,6 +15,10 @@ LL | || -> Closure { || () } | = note: expected unit type `()` found closure `[closure@$DIR/issue-63279.rs:8:21: 8:26]` +help: use parentheses to call this closure + | +LL | || -> Closure { (|| ())() } + | + +++ error[E0308]: mismatched types --> $DIR/issue-63279.rs:8:5 From f847261478de5fa72d7e1d2ec3341e31a794fcaf Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 22 Jun 2022 12:01:41 +0900 Subject: [PATCH 17/28] stop pointing at definitions of missing fields --- Cargo.lock | 1 - compiler/rustc_typeck/Cargo.toml | 1 - compiler/rustc_typeck/src/check/expr.rs | 69 ++++++++----------- src/test/ui/issues/issue-76077.stderr | 6 +- src/test/ui/privacy/issue-79593.stderr | 6 +- ...-missing-inaccessible-field-literal.stderr | 6 +- ...ng-private-fields-in-struct-literal.stderr | 10 +-- 7 files changed, 33 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc0f4cc53e656..df6f46f26cf0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4590,7 +4590,6 @@ dependencies = [ name = "rustc_typeck" version = "0.0.0" dependencies = [ - "itertools", "rustc_arena", "rustc_ast", "rustc_attr", diff --git a/compiler/rustc_typeck/Cargo.toml b/compiler/rustc_typeck/Cargo.toml index b3dd695508094..c08023ee6a70a 100644 --- a/compiler/rustc_typeck/Cargo.toml +++ b/compiler/rustc_typeck/Cargo.toml @@ -10,7 +10,6 @@ doctest = false [dependencies] rustc_arena = { path = "../rustc_arena" } tracing = "0.1" -itertools = "0.10.1" rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 0a017de80f248..e5048fc513217 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -23,13 +23,12 @@ use crate::type_error_struct; use super::suggest_call_constructor; use crate::errors::{AddressOfTemporaryTaken, ReturnStmtOutsideOfFnBody, StructExprNonExhaustive}; -use itertools::{Either, Itertools}; use rustc_ast as ast; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId, - EmissionGuarantee, ErrorGuaranteed, MultiSpan, + EmissionGuarantee, ErrorGuaranteed, }; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -1682,11 +1681,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) .collect(); - if !private_fields.is_empty() - && tcx - .visibility(variant.def_id) - .is_accessible_from(tcx.parent_module(expr_id).to_def_id(), tcx) - { + if !private_fields.is_empty() { self.report_private_fields(adt_ty, span, private_fields, ast_fields); } else { self.report_missing_fields( @@ -1826,12 +1821,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { private_fields: Vec<&ty::FieldDef>, used_fields: &'tcx [hir::ExprField<'tcx>], ) { - let field_names = |fields: Vec, len: usize| match &fields + let mut err = self.tcx.sess.struct_span_err( + span, + &format!( + "cannot construct `{adt_ty}` with struct literal syntax due to private fields", + ), + ); + let (used_private_fields, remaining_private_fields): ( + Vec<(Symbol, Span, bool)>, + Vec<(Symbol, Span, bool)>, + ) = private_fields + .iter() + .map(|field| { + match used_fields.iter().find(|used_field| field.name == used_field.ident.name) { + Some(used_field) => (field.name, used_field.span, true), + None => (field.name, self.tcx.def_span(field.did), false), + } + }) + .partition(|field| field.2); + let remaining_private_fields_len = remaining_private_fields.len(); + let names = match &remaining_private_fields .iter() - .map(|field| field.to_string()) + .map(|(name, _, _)| name.to_string()) .collect::>()[..] { - _ if len > 6 => String::new(), + _ if remaining_private_fields_len > 6 => String::new(), [name] => format!("`{name}` "), [names @ .., last] => { let names = names.iter().map(|name| format!("`{name}`")).collect::>(); @@ -1839,36 +1853,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } [] => unreachable!(), }; - - let mut err = self.tcx.sess.struct_span_err( - span, - &format!( - "cannot construct `{adt_ty}` with struct literal syntax due to private fields", - ), - ); - let (used_private_fields, remaining_private_fields): ( - Vec<(Symbol, Span)>, - Vec<(Symbol, Span)>, - ) = private_fields.iter().partition_map(|field| { - match used_fields.iter().find(|used_field| field.name == used_field.ident.name) { - Some(used_field) => Either::Left((field.name, used_field.span)), - None => Either::Right((field.name, self.tcx.def_span(field.did))), - } - }); - let remaining_private_fields_len = remaining_private_fields.len(); - err.span_labels(used_private_fields.iter().map(|(_, span)| *span), "private field"); - err.span_note( - MultiSpan::from_spans(remaining_private_fields.iter().map(|(_, span)| *span).collect()), - format!( - "missing field{s} {names}{are} private", - s = pluralize!(remaining_private_fields_len), - are = pluralize!("is", remaining_private_fields_len), - names = field_names( - remaining_private_fields.iter().map(|(name, _)| *name).collect(), - remaining_private_fields_len - ) - ), - ); + err.span_labels(used_private_fields.iter().map(|(_, span, _)| *span), "private field"); + err.note(format!( + "... and other private field{s} {names}that were not provided", + s = pluralize!(remaining_private_fields_len), + )); err.emit(); } diff --git a/src/test/ui/issues/issue-76077.stderr b/src/test/ui/issues/issue-76077.stderr index c70a928f6475a..57f7abe3931a4 100644 --- a/src/test/ui/issues/issue-76077.stderr +++ b/src/test/ui/issues/issue-76077.stderr @@ -4,11 +4,7 @@ error: cannot construct `Foo` with struct literal syntax due to private fields LL | foo::Foo {}; | ^^^^^^^^ | -note: missing field `you_cant_use_this_field` is private - --> $DIR/issue-76077.rs:3:9 - | -LL | you_cant_use_this_field: bool, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ... and other private field `you_cant_use_this_field` that were not provided error: aborting due to previous error diff --git a/src/test/ui/privacy/issue-79593.stderr b/src/test/ui/privacy/issue-79593.stderr index 435d4cbf73595..d878e1c023ff1 100644 --- a/src/test/ui/privacy/issue-79593.stderr +++ b/src/test/ui/privacy/issue-79593.stderr @@ -16,11 +16,7 @@ error: cannot construct `Pub` with struct literal syntax due to private fields LL | foo::Pub {}; | ^^^^^^^^ | -note: missing field `private` is private - --> $DIR/issue-79593.rs:2:22 - | -LL | pub struct Pub { private: () } - | ^^^^^^^^^^^ + = note: ... and other private field `private` that were not provided error[E0063]: missing field `y` in initializer of `Enum` --> $DIR/issue-79593.rs:23:5 diff --git a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr index 2ade7aea57b3d..fa1c661ef244e 100644 --- a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr +++ b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr @@ -4,11 +4,7 @@ error: cannot construct `Foo` with struct literal syntax due to private fields LL | foo::Foo {}; | ^^^^^^^^ | -note: missing field `you_cant_use_this_field` is private - --> $DIR/issue-87872-missing-inaccessible-field-literal.rs:4:9 - | -LL | you_cant_use_this_field: bool, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ... and other private field `you_cant_use_this_field` that were not provided error: aborting due to previous error diff --git a/src/test/ui/typeck/missing-private-fields-in-struct-literal.stderr b/src/test/ui/typeck/missing-private-fields-in-struct-literal.stderr index eb5f460f868e1..234110f31f79c 100644 --- a/src/test/ui/typeck/missing-private-fields-in-struct-literal.stderr +++ b/src/test/ui/typeck/missing-private-fields-in-struct-literal.stderr @@ -9,15 +9,7 @@ LL | a: (), LL | b: (), | ----- private field | -note: missing fields `c`, `d` and `e` are private - --> $DIR/missing-private-fields-in-struct-literal.rs:6:9 - | -LL | c: (), - | ^^^^^ -LL | d: (), - | ^^^^^ -LL | e: (), - | ^^^^^ + = note: ... and other private fields `c`, `d` and `e` that were not provided error: aborting due to previous error From 46b2454bad71b844ef5eb40860fb50131b6fe168 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 21 Jun 2022 17:11:28 -0700 Subject: [PATCH 18/28] clarify Arc::clone overflow check comment --- library/alloc/src/sync.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 2670b15982ad9..24e849aab4cce 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1355,15 +1355,16 @@ impl Clone for Arc { // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) let old_size = self.inner().strong.fetch_add(1, Relaxed); - // However we need to guard against massive refcounts in case someone - // is `mem::forget`ing Arcs. If we don't do this the count can overflow - // and users will use-after free. We racily saturate to `isize::MAX` on - // the assumption that there aren't ~2 billion threads incrementing - // the reference count at once. This branch will never be taken in - // any realistic program. + // However we need to guard against massive refcounts in case someone is `mem::forget`ing + // Arcs. If we don't do this the count can overflow and users will use-after free. This + // branch will never be taken in any realistic program. We abort because such a program is + // incredibly degenerate, and we don't care to support it. // - // We abort because such a program is incredibly degenerate, and we - // don't care to support it. + // This check is not 100% water-proof: we error when the refcount grows beyond `isize::MAX`. + // But we do that check *after* having done the increment, so there is a chance here that + // the worst already happened and we actually do overflow the `usize` counter. However, that + // requires the counter to grow from `isize::MAX` to `usize::MAX` between the increment + // above and the `abort` below, which seems exceedingly unlikely. if old_size > MAX_REFCOUNT { abort(); } From 402dceba99bed5efa5774d6238c13dfce4670db1 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Tue, 21 Jun 2022 00:43:20 +0900 Subject: [PATCH 19/28] point to type param definition when not finding variant, method and assoc type use `def_ident_span` , `body_owner_def_id` instead of `in_progress_typeck_results`, `guess_head_span` use `body_id.owner` directly add description to label --- .../rustc_typeck/src/check/method/suggest.rs | 36 +++++++++++-------- .../associated-item-enum.stderr | 6 ++-- .../ui/async-await/pin-needed-to-poll.stderr | 2 +- src/test/ui/bogus-tag.stderr | 2 +- .../issue-18343.stderr | 2 +- .../issue-2392.stderr | 22 ++++++------ .../issue-32128.stderr | 2 +- .../private-field.stderr | 2 +- .../generic_const_exprs/issue-69654.stderr | 2 +- .../generic_const_exprs/issue-80742.stderr | 18 ++++------ .../invalid-const-arg-for-type-param.stderr | 2 +- .../const-needs_drop-monomorphic.stderr | 2 +- src/test/ui/copy-a-resource.stderr | 2 +- .../derives/derive-assoc-type-not-impl.stderr | 4 +-- src/test/ui/derives/issue-91492.stderr | 2 +- src/test/ui/derives/issue-91550.stderr | 6 ++-- src/test/ui/did_you_mean/issue-40006.stderr | 2 +- .../dont-suggest-private-trait-method.stderr | 2 +- src/test/ui/error-codes/E0599.stderr | 2 +- ...hod-unsatified-assoc-type-predicate.stderr | 4 +-- src/test/ui/hrtb/issue-30786.stderr | 8 ++--- ...e-21659-show-relevant-trait-impls-3.stderr | 2 +- .../ui/impl-trait/issues/issue-62742.stderr | 2 +- .../method-suggestion-no-duplication.stderr | 2 +- .../no-method-suggested-traits.stderr | 6 ++-- .../ui/infinite/infinite-autoderef.stderr | 2 +- src/test/ui/issues/issue-19692.stderr | 2 +- src/test/ui/issues/issue-22933-2.stderr | 2 +- src/test/ui/issues/issue-23173.stderr | 8 ++--- src/test/ui/issues/issue-23217.stderr | 2 +- src/test/ui/issues/issue-2823.stderr | 2 +- src/test/ui/issues/issue-28971.stderr | 2 +- src/test/ui/issues/issue-38919.stderr | 2 ++ src/test/ui/issues/issue-41880.stderr | 2 +- src/test/ui/issues/issue-64430.stderr | 2 +- src/test/ui/issues/issue-7950.stderr | 2 +- src/test/ui/lexical-scopes.stderr | 2 ++ .../ui/methods/method-call-err-msg.stderr | 4 +-- ...ethod-not-found-generic-arg-elision.stderr | 14 ++++---- src/test/ui/noncopyable-class.stderr | 2 +- src/test/ui/parser/emoji-identifiers.stderr | 2 +- .../uniform-paths/issue-87932.stderr | 2 +- ...point-at-arbitrary-self-type-method.stderr | 2 +- ...at-arbitrary-self-type-trait-method.stderr | 2 +- src/test/ui/span/issue-7575.stderr | 4 ++- ...pecialization-trait-not-implemented.stderr | 4 +-- .../derive-trait-for-method-call.stderr | 6 ++-- .../dont-wrap-ambiguous-receivers.stderr | 2 +- .../ui/suggestions/field-has-method.stderr | 2 +- ...it-with-missing-trait-bounds-in-arg.stderr | 2 ++ src/test/ui/suggestions/issue-21673.stderr | 2 ++ ...uggest-assoc-fn-call-with-turbofish.stderr | 2 +- .../ui/suggestions/suggest-methods.stderr | 2 +- .../ui/suggestions/suggest-variants.stderr | 6 ++-- .../suggestions/use-placement-typeck.stderr | 2 +- src/test/ui/traits/issue-3973.stderr | 2 +- ...e-65284-suggest-generic-trait-bound.stderr | 2 ++ src/test/ui/traits/issue-95898.stderr | 2 ++ src/test/ui/traits/item-privacy.stderr | 12 +++---- ...licitly-unimplemented-error-message.stderr | 4 +-- .../point-at-type-parameter-definition.rs | 17 +++++++++ .../point-at-type-parameter-definition.stderr | 12 +++++++ .../union-derive-clone.mirunsafeck.stderr | 4 +-- .../union-derive-clone.thirunsafeck.stderr | 4 +-- 64 files changed, 168 insertions(+), 125 deletions(-) create mode 100644 src/test/ui/typeck/point-at-type-parameter-definition.rs create mode 100644 src/test/ui/typeck/point-at-type-parameter-definition.stderr diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 8880049371e58..5684979eab777 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -346,19 +346,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if let Some(def) = actual.ty_adt_def() { - if let Some(full_sp) = tcx.hir().span_if_local(def.did()) { - let def_sp = tcx.sess.source_map().guess_head_span(full_sp); - err.span_label( - def_sp, - format!( - "{} `{}` not found {}", - item_kind, - item_name, - if def.is_enum() && !is_method { "here" } else { "for this" } - ), - ); + let ty_span = match actual.kind() { + ty::Param(param_type) => { + let generics = self.tcx.generics_of(self.body_id.owner.to_def_id()); + let type_param = generics.type_param(param_type, self.tcx); + Some(self.tcx.def_span(type_param.def_id)) + } + ty::Adt(def, _) if def.did().is_local() => { + tcx.def_ident_span(def.did()).map(|span| span) } + _ => None, + }; + + if let Some(span) = ty_span { + err.span_label( + span, + format!( + "{item_kind} `{item_name}` not found for this {}", + actual.prefix_string(self.tcx) + ), + ); } if self.is_fn_ty(rcvr_ty, span) { @@ -1951,9 +1958,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) }; // Obtain the span for `param` and use it for a structured suggestion. - if let (Some(param), Some(table)) = (param_type, self.in_progress_typeck_results) { - let table_owner = table.borrow().hir_owner; - let generics = self.tcx.generics_of(table_owner.to_def_id()); + if let Some(param) = param_type { + let generics = self.tcx.generics_of(self.body_id.owner.to_def_id()); let type_param = generics.type_param(param, self.tcx); let hir = self.tcx.hir(); if let Some(def_id) = type_param.def_id.as_local() { diff --git a/src/test/ui/associated-item/associated-item-enum.stderr b/src/test/ui/associated-item/associated-item-enum.stderr index d52b2b36c7bcc..a09b64aa2f5a5 100644 --- a/src/test/ui/associated-item/associated-item-enum.stderr +++ b/src/test/ui/associated-item/associated-item-enum.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `mispellable` found for enum ` --> $DIR/associated-item-enum.rs:17:11 | LL | enum Enum { Variant } - | --------- variant or associated item `mispellable` not found here + | ---- variant or associated item `mispellable` not found for this enum ... LL | Enum::mispellable(); | ^^^^^^^^^^^ @@ -14,7 +14,7 @@ error[E0599]: no variant or associated item named `mispellable_trait` found for --> $DIR/associated-item-enum.rs:18:11 | LL | enum Enum { Variant } - | --------- variant or associated item `mispellable_trait` not found here + | ---- variant or associated item `mispellable_trait` not found for this enum ... LL | Enum::mispellable_trait(); | ^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ error[E0599]: no variant or associated item named `MISPELLABLE` found for enum ` --> $DIR/associated-item-enum.rs:19:11 | LL | enum Enum { Variant } - | --------- variant or associated item `MISPELLABLE` not found here + | ---- variant or associated item `MISPELLABLE` not found for this enum ... LL | Enum::MISPELLABLE; | ^^^^^^^^^^^ diff --git a/src/test/ui/async-await/pin-needed-to-poll.stderr b/src/test/ui/async-await/pin-needed-to-poll.stderr index c47ec5dddb6e2..ba22b7aaf9828 100644 --- a/src/test/ui/async-await/pin-needed-to-poll.stderr +++ b/src/test/ui/async-await/pin-needed-to-poll.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `poll` found for struct `Sleep` in the current sco --> $DIR/pin-needed-to-poll.rs:42:20 | LL | struct Sleep; - | ------------- method `poll` not found for this + | ----- method `poll` not found for this struct ... LL | self.sleep.poll(cx) | ^^^^ method not found in `Sleep` diff --git a/src/test/ui/bogus-tag.stderr b/src/test/ui/bogus-tag.stderr index cb3199e7c886e..b215adfa593bd 100644 --- a/src/test/ui/bogus-tag.stderr +++ b/src/test/ui/bogus-tag.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `Hsl` found for enum `Color` i --> $DIR/bogus-tag.rs:7:16 | LL | enum Color { Rgb(isize, isize, isize), Rgba(isize, isize, isize, isize), } - | ---------- variant or associated item `Hsl` not found here + | ----- variant or associated item `Hsl` not found for this enum ... LL | Color::Hsl(h, s, l) => { println!("hsl"); } | ^^^ variant or associated item not found in `Color` diff --git a/src/test/ui/confuse-field-and-method/issue-18343.stderr b/src/test/ui/confuse-field-and-method/issue-18343.stderr index 2f67c11ad1f5d..a6d4e80a50c05 100644 --- a/src/test/ui/confuse-field-and-method/issue-18343.stderr +++ b/src/test/ui/confuse-field-and-method/issue-18343.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc --> $DIR/issue-18343.rs:7:7 | LL | struct Obj where F: FnMut() -> u32 { - | ------------------------------------- method `closure` not found for this + | --- method `closure` not found for this struct ... LL | o.closure(); | ^^^^^^^ field, not a method diff --git a/src/test/ui/confuse-field-and-method/issue-2392.stderr b/src/test/ui/confuse-field-and-method/issue-2392.stderr index a37e132d36429..795d0e286b3d3 100644 --- a/src/test/ui/confuse-field-and-method/issue-2392.stderr +++ b/src/test/ui/confuse-field-and-method/issue-2392.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc --> $DIR/issue-2392.rs:36:15 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `closure` not found for this + | --- method `closure` not found for this struct ... LL | o_closure.closure(); | ^^^^^^^ field, not a method @@ -16,7 +16,7 @@ error[E0599]: no method named `not_closure` found for struct `Obj` in the curren --> $DIR/issue-2392.rs:38:15 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `not_closure` not found for this + | --- method `not_closure` not found for this struct ... LL | o_closure.not_closure(); | ^^^^^^^^^^^-- help: remove the arguments @@ -27,7 +27,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc --> $DIR/issue-2392.rs:42:12 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `closure` not found for this + | --- method `closure` not found for this struct ... LL | o_func.closure(); | ^^^^^^^ field, not a method @@ -41,7 +41,7 @@ error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the --> $DIR/issue-2392.rs:45:14 | LL | struct BoxedObj { - | --------------- method `boxed_closure` not found for this + | -------- method `boxed_closure` not found for this struct ... LL | boxed_fn.boxed_closure(); | ^^^^^^^^^^^^^ field, not a method @@ -55,7 +55,7 @@ error[E0599]: no method named `boxed_closure` found for struct `BoxedObj` in the --> $DIR/issue-2392.rs:48:19 | LL | struct BoxedObj { - | --------------- method `boxed_closure` not found for this + | -------- method `boxed_closure` not found for this struct ... LL | boxed_closure.boxed_closure(); | ^^^^^^^^^^^^^ field, not a method @@ -69,7 +69,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc --> $DIR/issue-2392.rs:53:12 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `closure` not found for this + | --- method `closure` not found for this struct ... LL | w.wrap.closure(); | ^^^^^^^ field, not a method @@ -83,7 +83,7 @@ error[E0599]: no method named `not_closure` found for struct `Obj` in the curren --> $DIR/issue-2392.rs:55:12 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `not_closure` not found for this + | --- method `not_closure` not found for this struct ... LL | w.wrap.not_closure(); | ^^^^^^^^^^^-- help: remove the arguments @@ -94,7 +94,7 @@ error[E0599]: no method named `closure` found for struct `Obj` in the current sc --> $DIR/issue-2392.rs:58:24 | LL | struct Obj where F: FnOnce() -> u32 { - | -------------------------------------- method `closure` not found for this + | --- method `closure` not found for this struct ... LL | check_expression().closure(); | ^^^^^^^ field, not a method @@ -108,7 +108,7 @@ error[E0599]: no method named `f1` found for struct `FuncContainer` in the curre --> $DIR/issue-2392.rs:64:31 | LL | struct FuncContainer { - | -------------------- method `f1` not found for this + | ------------- method `f1` not found for this struct ... LL | (*self.container).f1(1); | ^^ field, not a method @@ -122,7 +122,7 @@ error[E0599]: no method named `f2` found for struct `FuncContainer` in the curre --> $DIR/issue-2392.rs:65:31 | LL | struct FuncContainer { - | -------------------- method `f2` not found for this + | ------------- method `f2` not found for this struct ... LL | (*self.container).f2(1); | ^^ field, not a method @@ -136,7 +136,7 @@ error[E0599]: no method named `f3` found for struct `FuncContainer` in the curre --> $DIR/issue-2392.rs:66:31 | LL | struct FuncContainer { - | -------------------- method `f3` not found for this + | ------------- method `f3` not found for this struct ... LL | (*self.container).f3(1); | ^^ field, not a method diff --git a/src/test/ui/confuse-field-and-method/issue-32128.stderr b/src/test/ui/confuse-field-and-method/issue-32128.stderr index 50c6fe1e83308..cad2697b52e92 100644 --- a/src/test/ui/confuse-field-and-method/issue-32128.stderr +++ b/src/test/ui/confuse-field-and-method/issue-32128.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `example` found for struct `Example` in the curren --> $DIR/issue-32128.rs:12:10 | LL | struct Example { - | -------------- method `example` not found for this + | ------- method `example` not found for this struct ... LL | demo.example(1); | ^^^^^^^ field, not a method diff --git a/src/test/ui/confuse-field-and-method/private-field.stderr b/src/test/ui/confuse-field-and-method/private-field.stderr index fd98a864742ee..9e2f245597a45 100644 --- a/src/test/ui/confuse-field-and-method/private-field.stderr +++ b/src/test/ui/confuse-field-and-method/private-field.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `dog_age` found for struct `Dog` in the current sc --> $DIR/private-field.rs:16:23 | LL | pub struct Dog { - | -------------- method `dog_age` not found for this + | --- method `dog_age` not found for this struct ... LL | let dog_age = dog.dog_age(); | ^^^^^^^ private field, not a method diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr index 0ce7640f68577..576d037f3393d 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr @@ -8,7 +8,7 @@ error[E0599]: the function or associated item `foo` exists for struct `Foo<{_: u --> $DIR/issue-69654.rs:17:10 | LL | struct Foo {} - | -------------------------- function or associated item `foo` not found for this + | --- function or associated item `foo` not found for this struct ... LL | Foo::foo(); | ^^^ function or associated item cannot be called on `Foo<{_: usize}>` due to unsatisfied trait bounds diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr index 56cb11bacbe6b..7bfc09387b8a7 100644 --- a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr +++ b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr @@ -15,22 +15,16 @@ LL | [u8; size_of::() + 1]: , error[E0599]: the function or associated item `new` exists for struct `Inline`, but its trait bounds were not satisfied --> $DIR/issue-80742.rs:30:36 | -LL | / struct Inline -LL | | where -LL | | [u8; size_of::() + 1]: , -LL | | { -LL | | _phantom: PhantomData, -LL | | buf: [u8; size_of::() + 1], -LL | | } - | |_- function or associated item `new` not found for this +LL | struct Inline + | ------ function or associated item `new` not found for this struct ... -LL | let dst = Inline::::new(0); - | ^^^ function or associated item cannot be called on `Inline` due to unsatisfied trait bounds +LL | let dst = Inline::::new(0); + | ^^^ function or associated item cannot be called on `Inline` due to unsatisfied trait bounds | ::: $SRC_DIR/core/src/fmt/mod.rs:LL:COL | -LL | pub trait Debug { - | --------------- doesn't satisfy `dyn Debug: Sized` +LL | pub trait Debug { + | --------------- doesn't satisfy `dyn Debug: Sized` | = note: the following trait bounds were not satisfied: `dyn Debug: Sized` diff --git a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr index aa5cebd873e31..ab53d6cf09a74 100644 --- a/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr +++ b/src/test/ui/const-generics/invalid-const-arg-for-type-param.stderr @@ -16,7 +16,7 @@ error[E0599]: no method named `f` found for struct `S` in the current scope --> $DIR/invalid-const-arg-for-type-param.rs:9:7 | LL | struct S; - | --------- method `f` not found for this + | - method `f` not found for this struct ... LL | S.f::<0>(); | ^ method not found in `S` diff --git a/src/test/ui/consts/const-needs_drop-monomorphic.stderr b/src/test/ui/consts/const-needs_drop-monomorphic.stderr index 6e56d20c39d7f..4399db1166562 100644 --- a/src/test/ui/consts/const-needs_drop-monomorphic.stderr +++ b/src/test/ui/consts/const-needs_drop-monomorphic.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `assert` found for struct `Bo --> $DIR/const-needs_drop-monomorphic.rs:11:46 | LL | struct Bool {} - | -------------------------- function or associated item `assert` not found for this + | ---- function or associated item `assert` not found for this struct ... LL | Bool::<{ std::mem::needs_drop::() }>::assert(); | ^^^^^^ function or associated item cannot be called on `Bool<{ std::mem::needs_drop::() }>` due to unsatisfied trait bounds diff --git a/src/test/ui/copy-a-resource.stderr b/src/test/ui/copy-a-resource.stderr index 79095452f9d02..3909862ff1c8b 100644 --- a/src/test/ui/copy-a-resource.stderr +++ b/src/test/ui/copy-a-resource.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for struct `Foo` in the current scop --> $DIR/copy-a-resource.rs:18:16 | LL | struct Foo { - | ---------- method `clone` not found for this + | --- method `clone` not found for this struct ... LL | let _y = x.clone(); | ^^^^^ method not found in `Foo` diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 72dd9c153ab0d..592cc0ae90f7c 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -3,8 +3,8 @@ error[E0599]: the method `clone` exists for struct `Bar`, but its trai | LL | struct Bar { | ------------------ - | | - | method `clone` not found for this + | | | + | | method `clone` not found for this struct | doesn't satisfy `Bar: Clone` ... LL | struct NotClone; diff --git a/src/test/ui/derives/issue-91492.stderr b/src/test/ui/derives/issue-91492.stderr index 73c91154a7bda..e479b539fec2d 100644 --- a/src/test/ui/derives/issue-91492.stderr +++ b/src/test/ui/derives/issue-91492.stderr @@ -37,7 +37,7 @@ LL | pub struct NoDerives; | --------------------- doesn't satisfy `NoDerives: Clone` ... LL | struct Object(T, A); - | -------------------------- method `use_clone` not found for this + | ------ method `use_clone` not found for this struct ... LL | foo.use_clone(); | ^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds diff --git a/src/test/ui/derives/issue-91550.stderr b/src/test/ui/derives/issue-91550.stderr index 1b26d7549844b..e92036c99917e 100644 --- a/src/test/ui/derives/issue-91550.stderr +++ b/src/test/ui/derives/issue-91550.stderr @@ -25,7 +25,7 @@ LL | pub struct NoDerives; | --------------------- doesn't satisfy `NoDerives: Eq` LL | LL | struct Object(T); - | -------------------- method `use_eq` not found for this + | ------ method `use_eq` not found for this struct ... LL | foo.use_eq(); | ^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds @@ -44,7 +44,7 @@ LL | pub struct NoDerives; | --------------------- doesn't satisfy `NoDerives: Ord` LL | LL | struct Object(T); - | -------------------- method `use_ord` not found for this + | ------ method `use_ord` not found for this struct ... LL | foo.use_ord(); | ^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds @@ -66,7 +66,7 @@ LL | pub struct NoDerives; | doesn't satisfy `NoDerives: PartialOrd` LL | LL | struct Object(T); - | -------------------- method `use_ord_and_partial_ord` not found for this + | ------ method `use_ord_and_partial_ord` not found for this struct ... LL | foo.use_ord_and_partial_ord(); | ^^^^^^^^^^^^^^^^^^^^^^^ method cannot be called on `Object` due to unsatisfied trait bounds diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index d5e16e1ff273d..bd5b9f4b49ee3 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -88,7 +88,7 @@ error[E0599]: no method named `hello_method` found for struct `S` in the current --> $DIR/issue-40006.rs:38:7 | LL | struct S; - | --------- method `hello_method` not found for this + | - method `hello_method` not found for this struct ... LL | S.hello_method(); | ^^^^^^^^^^^^ method not found in `S` diff --git a/src/test/ui/dont-suggest-private-trait-method.stderr b/src/test/ui/dont-suggest-private-trait-method.stderr index fd7fdb4f7226c..d85fd526d52b0 100644 --- a/src/test/ui/dont-suggest-private-trait-method.stderr +++ b/src/test/ui/dont-suggest-private-trait-method.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `new` found for struct `T` in --> $DIR/dont-suggest-private-trait-method.rs:4:8 | LL | struct T; - | --------- function or associated item `new` not found for this + | - function or associated item `new` not found for this struct ... LL | T::new(); | ^^^ function or associated item not found in `T` diff --git a/src/test/ui/error-codes/E0599.stderr b/src/test/ui/error-codes/E0599.stderr index a78a003661d6f..49ca1d6353d15 100644 --- a/src/test/ui/error-codes/E0599.stderr +++ b/src/test/ui/error-codes/E0599.stderr @@ -2,7 +2,7 @@ error[E0599]: no associated item named `NotEvenReal` found for struct `Foo` in t --> $DIR/E0599.rs:4:20 | LL | struct Foo; - | ----------- associated item `NotEvenReal` not found for this + | --- associated item `NotEvenReal` not found for this struct ... LL | || if let Foo::NotEvenReal() = Foo {}; | ^^^^^^^^^^^ associated item not found in `Foo` diff --git a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr index 9eeebd80afecb..1322914797b18 100644 --- a/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr +++ b/src/test/ui/generic-associated-types/method-unsatified-assoc-type-predicate.stderr @@ -3,8 +3,8 @@ error[E0599]: the method `f` exists for struct `S`, but its trait bounds were no | LL | struct S; | --------- - | | - | method `f` not found for this + | | | + | | method `f` not found for this struct | doesn't satisfy `::Y = i32` | doesn't satisfy `S: M` ... diff --git a/src/test/ui/hrtb/issue-30786.stderr b/src/test/ui/hrtb/issue-30786.stderr index 1ee549e54a908..5a10a38d08ecd 100644 --- a/src/test/ui/hrtb/issue-30786.stderr +++ b/src/test/ui/hrtb/issue-30786.stderr @@ -3,8 +3,8 @@ error[E0599]: the method `filterx` exists for struct `Map { | -------------------- - | | - | method `filterx` not found for this + | | | + | | method `filterx` not found for this struct | doesn't satisfy `_: StreamExt` ... LL | let filter = map.filterx(|x: &_| true); @@ -28,8 +28,8 @@ error[E0599]: the method `countx` exists for struct `Filter | LL | pub struct Filter { | ----------------------- - | | - | method `countx` not found for this + | | | + | | method `countx` not found for this struct | doesn't satisfy `_: StreamExt` ... LL | let count = filter.countx(); diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index 64cce056a2688..8b671e7dbb3a7 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for struct `Bar` in the current scope --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 | LL | struct Bar; - | ----------- method `foo` not found for this + | --- method `foo` not found for this struct ... LL | f1.foo(1usize); | ^^^ method not found in `Bar` diff --git a/src/test/ui/impl-trait/issues/issue-62742.stderr b/src/test/ui/impl-trait/issues/issue-62742.stderr index 70d693b8bee95..44d775b695ee8 100644 --- a/src/test/ui/impl-trait/issues/issue-62742.stderr +++ b/src/test/ui/impl-trait/issues/issue-62742.stderr @@ -21,7 +21,7 @@ LL | pub struct RawImpl(PhantomData); | -------------------------------------- doesn't satisfy `RawImpl<()>: Raw<()>` ... LL | pub struct SafeImpl>(PhantomData<(A, T)>); - | --------------------------------------------------------------- function or associated item `foo` not found for this + | -------- function or associated item `foo` not found for this struct | = note: the following trait bounds were not satisfied: `RawImpl<()>: Raw<()>` diff --git a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr index f6bb52bf6387c..abd57d12d9e50 100644 --- a/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr +++ b/src/test/ui/impl-trait/method-suggestion-no-duplication.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `is_empty` found for struct `Foo` in the current s --> $DIR/method-suggestion-no-duplication.rs:7:15 | LL | struct Foo; - | ----------- method `is_empty` not found for this + | --- method `is_empty` not found for this struct ... LL | foo(|s| s.is_empty()); | ^^^^^^^^ method not found in `Foo` diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index c8ebed3bfd9ae..1d24f428fb1e1 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -94,7 +94,7 @@ error[E0599]: no method named `method` found for struct `Foo` in the current sco --> $DIR/no-method-suggested-traits.rs:40:9 | LL | struct Foo; - | ----------- method `method` not found for this + | --- method `method` not found for this struct ... LL | Foo.method(); | ^^^^^^ method not found in `Foo` @@ -201,7 +201,7 @@ error[E0599]: no method named `method3` found for struct `Foo` in the current sc --> $DIR/no-method-suggested-traits.rs:59:9 | LL | struct Foo; - | ----------- method `method3` not found for this + | --- method `method3` not found for this struct ... LL | Foo.method3(); | ^^^^^^^ method not found in `Foo` @@ -224,7 +224,7 @@ error[E0599]: no method named `method3` found for enum `Bar` in the current scop --> $DIR/no-method-suggested-traits.rs:63:12 | LL | enum Bar { X } - | -------- method `method3` not found for this + | --- method `method3` not found for this enum ... LL | Bar::X.method3(); | ^^^^^^^ method not found in `Bar` diff --git a/src/test/ui/infinite/infinite-autoderef.stderr b/src/test/ui/infinite/infinite-autoderef.stderr index 2e950dbb8c7f9..edf8a44b7e4a1 100644 --- a/src/test/ui/infinite/infinite-autoderef.stderr +++ b/src/test/ui/infinite/infinite-autoderef.stderr @@ -43,7 +43,7 @@ error[E0599]: no method named `bar` found for struct `Foo` in the current scope --> $DIR/infinite-autoderef.rs:25:9 | LL | struct Foo; - | ----------- method `bar` not found for this + | --- method `bar` not found for this struct ... LL | Foo.bar(); | ^^^ method not found in `Foo` diff --git a/src/test/ui/issues/issue-19692.stderr b/src/test/ui/issues/issue-19692.stderr index b412d7bc70436..7a72a5ff11a45 100644 --- a/src/test/ui/issues/issue-19692.stderr +++ b/src/test/ui/issues/issue-19692.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `kaname` found for struct `Homura` in the current --> $DIR/issue-19692.rs:4:40 | LL | struct Homura; - | -------------- method `kaname` not found for this + | ------ method `kaname` not found for this struct ... LL | let Some(ref madoka) = Some(homura.kaname()); | ^^^^^^ method not found in `Homura` diff --git a/src/test/ui/issues/issue-22933-2.stderr b/src/test/ui/issues/issue-22933-2.stderr index 0bfbf538486de..648912a9690f4 100644 --- a/src/test/ui/issues/issue-22933-2.stderr +++ b/src/test/ui/issues/issue-22933-2.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `PIE` found for enum `Deliciou --> $DIR/issue-22933-2.rs:4:55 | LL | enum Delicious { - | -------------- variant or associated item `PIE` not found here + | --------- variant or associated item `PIE` not found for this enum ... LL | ApplePie = Delicious::Apple as isize | Delicious::PIE as isize, | ^^^ diff --git a/src/test/ui/issues/issue-23173.stderr b/src/test/ui/issues/issue-23173.stderr index 89f70fda786ea..052ccd07d411b 100644 --- a/src/test/ui/issues/issue-23173.stderr +++ b/src/test/ui/issues/issue-23173.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `Homura` found for enum `Token --> $DIR/issue-23173.rs:9:23 | LL | enum Token { LeftParen, RightParen, Plus, Minus, /* etc */ } - | ---------- variant or associated item `Homura` not found here + | ----- variant or associated item `Homura` not found for this enum ... LL | use_token(&Token::Homura); | ^^^^^^ variant or associated item not found in `Token` @@ -11,7 +11,7 @@ error[E0599]: no function or associated item named `method` found for struct `St --> $DIR/issue-23173.rs:10:13 | LL | struct Struct { - | ------------- function or associated item `method` not found for this + | ------ function or associated item `method` not found for this struct ... LL | Struct::method(); | ^^^^^^ function or associated item not found in `Struct` @@ -20,7 +20,7 @@ error[E0599]: no function or associated item named `method` found for struct `St --> $DIR/issue-23173.rs:11:13 | LL | struct Struct { - | ------------- function or associated item `method` not found for this + | ------ function or associated item `method` not found for this struct ... LL | Struct::method; | ^^^^^^ function or associated item not found in `Struct` @@ -29,7 +29,7 @@ error[E0599]: no associated item named `Assoc` found for struct `Struct` in the --> $DIR/issue-23173.rs:12:13 | LL | struct Struct { - | ------------- associated item `Assoc` not found for this + | ------ associated item `Assoc` not found for this struct ... LL | Struct::Assoc; | ^^^^^ associated item not found in `Struct` diff --git a/src/test/ui/issues/issue-23217.stderr b/src/test/ui/issues/issue-23217.stderr index a81b459a34cbe..c5906b8805dfe 100644 --- a/src/test/ui/issues/issue-23217.stderr +++ b/src/test/ui/issues/issue-23217.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `A` found for enum `SomeEnum` --> $DIR/issue-23217.rs:2:19 | LL | pub enum SomeEnum { - | ----------------- variant or associated item `A` not found here + | -------- variant or associated item `A` not found for this enum LL | B = SomeEnum::A, | ^ | | diff --git a/src/test/ui/issues/issue-2823.stderr b/src/test/ui/issues/issue-2823.stderr index b3bc946292f70..fcc007a4a8848 100644 --- a/src/test/ui/issues/issue-2823.stderr +++ b/src/test/ui/issues/issue-2823.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for struct `C` in the current scope --> $DIR/issue-2823.rs:13:16 | LL | struct C { - | -------- method `clone` not found for this + | - method `clone` not found for this struct ... LL | let _d = c.clone(); | ^^^^^ method not found in `C` diff --git a/src/test/ui/issues/issue-28971.stderr b/src/test/ui/issues/issue-28971.stderr index 2736ee881d564..e0a65e33c445e 100644 --- a/src/test/ui/issues/issue-28971.stderr +++ b/src/test/ui/issues/issue-28971.stderr @@ -2,7 +2,7 @@ error[E0599]: no variant or associated item named `Baz` found for enum `Foo` in --> $DIR/issue-28971.rs:7:18 | LL | enum Foo { - | -------- variant or associated item `Baz` not found here + | --- variant or associated item `Baz` not found for this enum ... LL | Foo::Baz(..) => (), | ^^^ diff --git a/src/test/ui/issues/issue-38919.stderr b/src/test/ui/issues/issue-38919.stderr index 0022065a32c3d..f9ab8a5150716 100644 --- a/src/test/ui/issues/issue-38919.stderr +++ b/src/test/ui/issues/issue-38919.stderr @@ -1,6 +1,8 @@ error[E0599]: no associated item named `Item` found for type parameter `T` in the current scope --> $DIR/issue-38919.rs:2:8 | +LL | fn foo() { + | - associated item `Item` not found for this type parameter LL | T::Item; | ^^^^ associated item not found in `T` diff --git a/src/test/ui/issues/issue-41880.stderr b/src/test/ui/issues/issue-41880.stderr index 017dd831f712a..a52dc0c9af0c6 100644 --- a/src/test/ui/issues/issue-41880.stderr +++ b/src/test/ui/issues/issue-41880.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `iter` found for struct `Iterate` in the current s --> $DIR/issue-41880.rs:27:24 | LL | pub struct Iterate { - | ------------------------ method `iter` not found for this + | ------- method `iter` not found for this struct ... LL | println!("{:?}", a.iter().take(10).collect::>()); | ^^^^ method not found in `Iterate<{integer}, [closure@$DIR/issue-41880.rs:26:24: 26:31]>` diff --git a/src/test/ui/issues/issue-64430.stderr b/src/test/ui/issues/issue-64430.stderr index e7a244e9df576..a25b6b8802a9c 100644 --- a/src/test/ui/issues/issue-64430.stderr +++ b/src/test/ui/issues/issue-64430.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `bar` found for struct `Foo` in the current scope --> $DIR/issue-64430.rs:7:9 | LL | pub struct Foo; - | --------------- method `bar` not found for this + | --- method `bar` not found for this struct ... LL | Foo.bar() | ^^^ method not found in `Foo` diff --git a/src/test/ui/issues/issue-7950.stderr b/src/test/ui/issues/issue-7950.stderr index 73e13c65cf37f..2a683c2d55a35 100644 --- a/src/test/ui/issues/issue-7950.stderr +++ b/src/test/ui/issues/issue-7950.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `bar` found for struct `Foo` --> $DIR/issue-7950.rs:6:10 | LL | struct Foo; - | ----------- function or associated item `bar` not found for this + | --- function or associated item `bar` not found for this struct ... LL | Foo::bar(); | ^^^ function or associated item not found in `Foo` diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr index 1e6a35ed479f6..3b2a062c1c254 100644 --- a/src/test/ui/lexical-scopes.stderr +++ b/src/test/ui/lexical-scopes.stderr @@ -7,6 +7,8 @@ LL | let t = T { i: 0 }; error[E0599]: no function or associated item named `f` found for type parameter `Foo` in the current scope --> $DIR/lexical-scopes.rs:10:10 | +LL | fn g() { + | --- function or associated item `f` not found for this type parameter LL | Foo::f(); | ^ function or associated item not found in `Foo` diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index 53e582f7f13a4..03ad6eb03ab53 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -51,8 +51,8 @@ error[E0599]: `Foo` is not an iterator | LL | pub struct Foo; | --------------- - | | - | method `take` not found for this + | | | + | | method `take` not found for this struct | doesn't satisfy `Foo: Iterator` ... LL | .take() diff --git a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr index 1671e5e5e64c8..492d480e13e86 100644 --- a/src/test/ui/methods/method-not-found-generic-arg-elision.stderr +++ b/src/test/ui/methods/method-not-found-generic-arg-elision.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `distance` found for struct `Point` in the cu --> $DIR/method-not-found-generic-arg-elision.rs:82:23 | LL | struct Point { - | --------------- method `distance` not found for this + | ----- method `distance` not found for this struct ... LL | let d = point_i32.distance(); | ^^^^^^^^ method not found in `Point` @@ -14,7 +14,7 @@ error[E0599]: no method named `other` found for struct `Point` in the current sc --> $DIR/method-not-found-generic-arg-elision.rs:84:23 | LL | struct Point { - | --------------- method `other` not found for this + | ----- method `other` not found for this struct ... LL | let d = point_i32.other(); | ^^^^^ method not found in `Point` @@ -29,7 +29,7 @@ error[E0599]: no method named `method` found for struct `Wrapper` in the c --> $DIR/method-not-found-generic-arg-elision.rs:90:13 | LL | struct Wrapper(T); - | --------------------- method `method` not found for this + | ------- method `method` not found for this struct ... LL | wrapper.method(); | ^^^^^^ method not found in `Wrapper` @@ -45,7 +45,7 @@ error[E0599]: no method named `other` found for struct `Wrapper` in the current --> $DIR/method-not-found-generic-arg-elision.rs:92:13 | LL | struct Wrapper(T); - | --------------------- method `other` not found for this + | ------- method `other` not found for this struct ... LL | wrapper.other(); | ^^^^^ method not found in `Wrapper` @@ -54,7 +54,7 @@ error[E0599]: no method named `method` found for struct `Wrapper2<'_, bool, 3_us --> $DIR/method-not-found-generic-arg-elision.rs:96:13 | LL | struct Wrapper2<'a, T, const C: usize> { - | -------------------------------------- method `method` not found for this + | -------- method `method` not found for this struct ... LL | wrapper.method(); | ^^^^^^ method not found in `Wrapper2<'_, bool, 3_usize>` @@ -68,7 +68,7 @@ error[E0599]: no method named `other` found for struct `Wrapper2` in the current --> $DIR/method-not-found-generic-arg-elision.rs:98:13 | LL | struct Wrapper2<'a, T, const C: usize> { - | -------------------------------------- method `other` not found for this + | -------- method `other` not found for this struct ... LL | wrapper.other(); | ^^^^^ method not found in `Wrapper2<'_, bool, 3_usize>` @@ -83,7 +83,7 @@ error[E0599]: the method `method` exists for struct `Struct`, but its trait --> $DIR/method-not-found-generic-arg-elision.rs:104:7 | LL | struct Struct{ - | ---------------- method `method` not found for this + | ------ method `method` not found for this struct ... LL | s.method(); | ^^^^^^ method cannot be called on `Struct` due to unsatisfied trait bounds diff --git a/src/test/ui/noncopyable-class.stderr b/src/test/ui/noncopyable-class.stderr index 4674c16eb433a..88e9cd6a9c088 100644 --- a/src/test/ui/noncopyable-class.stderr +++ b/src/test/ui/noncopyable-class.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for struct `Foo` in the current scop --> $DIR/noncopyable-class.rs:34:16 | LL | struct Foo { - | ---------- method `clone` not found for this + | --- method `clone` not found for this struct ... LL | let _y = x.clone(); | ^^^^^ method not found in `Foo` diff --git a/src/test/ui/parser/emoji-identifiers.stderr b/src/test/ui/parser/emoji-identifiers.stderr index 7dc589e556386..40a85f7f74ca8 100644 --- a/src/test/ui/parser/emoji-identifiers.stderr +++ b/src/test/ui/parser/emoji-identifiers.stderr @@ -77,7 +77,7 @@ error[E0599]: no function or associated item named `full_of✨` found for struct --> $DIR/emoji-identifiers.rs:9:8 | LL | struct 👀; - | ---------- function or associated item `full_of✨` not found for this + | -- function or associated item `full_of✨` not found for this struct ... LL | 👀::full_of✨() | ^^^^^^^^^ diff --git a/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr b/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr index 53272abccbbf0..edbea330a04b6 100644 --- a/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr +++ b/src/test/ui/rust-2018/uniform-paths/issue-87932.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `deserialize` found for struc --> $DIR/issue-87932.rs:13:8 | LL | pub struct A {} - | ------------ function or associated item `deserialize` not found for this + | - function or associated item `deserialize` not found for this struct ... LL | A::deserialize(); | ^^^^^^^^^^^ function or associated item not found in `A` diff --git a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr index a0ef7e3f2cbab..06ccc5b1afeea 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-method.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope --> $DIR/point-at-arbitrary-self-type-method.rs:8:7 | LL | struct A; - | --------- method `foo` not found for this + | - method `foo` not found for this struct ... LL | fn foo(self: Box) {} | --- the method is available for `Box` here diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 440676482835c..bd77f67fb4e9b 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -6,7 +6,7 @@ LL | trait B { fn foo(self: Box); } | | | the method is available for `Box` here LL | struct A; - | --------- method `foo` not found for this + | - method `foo` not found for this struct ... LL | A.foo() | ^^^ method not found in `A` diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr index 783f5aca41746..912618555f4db 100644 --- a/src/test/ui/span/issue-7575.stderr +++ b/src/test/ui/span/issue-7575.stderr @@ -42,7 +42,7 @@ error[E0599]: no method named `fff` found for struct `Myisize` in the current sc --> $DIR/issue-7575.rs:62:30 | LL | struct Myisize(isize); - | ---------------------- method `fff` not found for this + | ------- method `fff` not found for this struct ... LL | u.f8(42) + u.f9(342) + m.fff(42) | --^^^ @@ -60,6 +60,8 @@ LL | fn fff(i: isize) -> isize { error[E0599]: no method named `is_str` found for type parameter `T` in the current scope --> $DIR/issue-7575.rs:70:7 | +LL | fn param_bound(t: T) -> bool { + | - method `is_str` not found for this type parameter LL | t.is_str() | ^^^^^^ this is an associated function, not a method | diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 9894ecc64b518..d2350bc7e4f91 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -13,8 +13,8 @@ error[E0599]: the method `foo_one` exists for struct `MyStruct`, but its trait b | LL | struct MyStruct; | ---------------- - | | - | method `foo_one` not found for this + | | | + | | method `foo_one` not found for this struct | doesn't satisfy `MyStruct: Foo` ... LL | println!("{}", MyStruct.foo_one()); diff --git a/src/test/ui/suggestions/derive-trait-for-method-call.stderr b/src/test/ui/suggestions/derive-trait-for-method-call.stderr index 2af3ba1d5bb9c..65167ce4a29e0 100644 --- a/src/test/ui/suggestions/derive-trait-for-method-call.stderr +++ b/src/test/ui/suggestions/derive-trait-for-method-call.stderr @@ -11,7 +11,7 @@ LL | enum CloneEnum { | -------------- doesn't satisfy `CloneEnum: Default` ... LL | struct Foo (X, Y); - | ------------------------ method `test` not found for this + | --- method `test` not found for this struct ... LL | let y = x.test(); | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds @@ -49,7 +49,7 @@ LL | struct CloneStruct { | ------------------ doesn't satisfy `CloneStruct: Default` ... LL | struct Foo (X, Y); - | ------------------------ method `test` not found for this + | --- method `test` not found for this struct ... LL | let y = x.test(); | ^^^^ method cannot be called on `Foo` due to unsatisfied trait bounds @@ -71,7 +71,7 @@ error[E0599]: the method `test` exists for struct `Foo, Instant>`, but --> $DIR/derive-trait-for-method-call.rs:40:15 | LL | struct Foo (X, Y); - | ------------------------ method `test` not found for this + | --- method `test` not found for this struct ... LL | let y = x.test(); | ^^^^ method cannot be called on `Foo, Instant>` due to unsatisfied trait bounds diff --git a/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr index 8fcadbf4c75f4..d5af89e3547a1 100644 --- a/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr +++ b/src/test/ui/suggestions/dont-wrap-ambiguous-receivers.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `pick` found for struct `Chaenomeles` in the curre --> $DIR/dont-wrap-ambiguous-receivers.rs:18:25 | LL | pub struct Chaenomeles; - | ----------------------- method `pick` not found for this + | ----------- method `pick` not found for this struct ... LL | banana::Chaenomeles.pick() | ^^^^ method not found in `Chaenomeles` diff --git a/src/test/ui/suggestions/field-has-method.stderr b/src/test/ui/suggestions/field-has-method.stderr index 3a57436f200ba..34b6230e19be2 100644 --- a/src/test/ui/suggestions/field-has-method.stderr +++ b/src/test/ui/suggestions/field-has-method.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `kind` found for struct `InferOk` in the current s --> $DIR/field-has-method.rs:19:15 | LL | struct InferOk { - | ----------------- method `kind` not found for this + | ------- method `kind` not found for this struct ... LL | let k = i.kind(); | ^^^^ method not found in `InferOk` diff --git a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr index 8ec7b7bf49658..20f8e65f769a4 100644 --- a/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr +++ b/src/test/ui/suggestions/impl-trait-with-missing-trait-bounds-in-arg.stderr @@ -1,6 +1,8 @@ error[E0599]: no method named `hello` found for type parameter `impl Foo` in the current scope --> $DIR/impl-trait-with-missing-trait-bounds-in-arg.rs:15:9 | +LL | fn test(foo: impl Foo) { + | -------- method `hello` not found for this type parameter LL | foo.hello(); | ^^^^^ method not found in `impl Foo` | diff --git a/src/test/ui/suggestions/issue-21673.stderr b/src/test/ui/suggestions/issue-21673.stderr index 0a4aaa61bc784..523d7a7ccd29c 100644 --- a/src/test/ui/suggestions/issue-21673.stderr +++ b/src/test/ui/suggestions/issue-21673.stderr @@ -13,6 +13,8 @@ LL | fn call_method(x: &T) { error[E0599]: no method named `method` found for type parameter `T` in the current scope --> $DIR/issue-21673.rs:10:7 | +LL | fn call_method_2(x: T) { + | - method `method` not found for this type parameter LL | x.method() | ^^^^^^ method not found in `T` | diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr index f1c0cd6b543e4..3497c31826c5c 100644 --- a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `default_hello` found for struct `GenericAssocMeth --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7 | LL | struct GenericAssocMethod(T); - | -------------------------------- method `default_hello` not found for this + | ------------------ method `default_hello` not found for this struct ... LL | x.default_hello(); | --^^^^^^^^^^^^^ diff --git a/src/test/ui/suggestions/suggest-methods.stderr b/src/test/ui/suggestions/suggest-methods.stderr index 9079e8f2ce7a4..dd9010e32955e 100644 --- a/src/test/ui/suggestions/suggest-methods.stderr +++ b/src/test/ui/suggestions/suggest-methods.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `bat` found for struct `Foo` in the current scope --> $DIR/suggest-methods.rs:18:7 | LL | struct Foo; - | ----------- method `bat` not found for this + | --- method `bat` not found for this struct ... LL | f.bat(1.0); | ^^^ help: there is an associated function with a similar name: `bar` diff --git a/src/test/ui/suggestions/suggest-variants.stderr b/src/test/ui/suggestions/suggest-variants.stderr index 9227baa3e1a5c..cccf9378d4dae 100644 --- a/src/test/ui/suggestions/suggest-variants.stderr +++ b/src/test/ui/suggestions/suggest-variants.stderr @@ -29,7 +29,7 @@ error[E0599]: no variant or associated item named `Squareee` found for enum `Sha --> $DIR/suggest-variants.rs:15:12 | LL | enum Shape { - | ---------- variant or associated item `Squareee` not found here + | ----- variant or associated item `Squareee` not found for this enum ... LL | Shape::Squareee; | ^^^^^^^^ @@ -41,7 +41,7 @@ error[E0599]: no variant or associated item named `Circl` found for enum `Shape` --> $DIR/suggest-variants.rs:16:12 | LL | enum Shape { - | ---------- variant or associated item `Circl` not found here + | ----- variant or associated item `Circl` not found for this enum ... LL | Shape::Circl; | ^^^^^ @@ -53,7 +53,7 @@ error[E0599]: no variant or associated item named `Rombus` found for enum `Shape --> $DIR/suggest-variants.rs:17:12 | LL | enum Shape { - | ---------- variant or associated item `Rombus` not found here + | ----- variant or associated item `Rombus` not found for this enum ... LL | Shape::Rombus; | ^^^^^^ variant or associated item not found in `Shape` diff --git a/src/test/ui/suggestions/use-placement-typeck.stderr b/src/test/ui/suggestions/use-placement-typeck.stderr index 21f22dade2c22..aa9880a60b67c 100644 --- a/src/test/ui/suggestions/use-placement-typeck.stderr +++ b/src/test/ui/suggestions/use-placement-typeck.stderr @@ -8,7 +8,7 @@ LL | fn abc(&self) {} | --- the method is available for `S` here LL | } LL | pub struct S; - | ------------- method `abc` not found for this + | - method `abc` not found for this struct | = help: items from traits can only be used if the trait is in scope help: the following trait is implemented but not in scope; perhaps add a `use` for it: diff --git a/src/test/ui/traits/issue-3973.stderr b/src/test/ui/traits/issue-3973.stderr index 63282e8d86d7b..188125d248d18 100644 --- a/src/test/ui/traits/issue-3973.stderr +++ b/src/test/ui/traits/issue-3973.stderr @@ -11,7 +11,7 @@ error[E0599]: no function or associated item named `new` found for struct `Point --> $DIR/issue-3973.rs:22:20 | LL | struct Point { - | ------------ function or associated item `new` not found for this + | ----- function or associated item `new` not found for this struct ... LL | let p = Point::new(0.0, 0.0); | ^^^ function or associated item not found in `Point` diff --git a/src/test/ui/traits/issue-65284-suggest-generic-trait-bound.stderr b/src/test/ui/traits/issue-65284-suggest-generic-trait-bound.stderr index 35d41c6266761..ae33e61d83b7a 100644 --- a/src/test/ui/traits/issue-65284-suggest-generic-trait-bound.stderr +++ b/src/test/ui/traits/issue-65284-suggest-generic-trait-bound.stderr @@ -1,6 +1,8 @@ error[E0599]: no method named `foo` found for type parameter `T` in the current scope --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7 | +LL | fn do_stuff(t : T) { + | - method `foo` not found for this type parameter LL | t.foo() | ^^^ method not found in `T` | diff --git a/src/test/ui/traits/issue-95898.stderr b/src/test/ui/traits/issue-95898.stderr index 0a58ad4b663eb..ca7bacdbf41ba 100644 --- a/src/test/ui/traits/issue-95898.stderr +++ b/src/test/ui/traits/issue-95898.stderr @@ -1,6 +1,8 @@ error[E0599]: no method named `clone` found for type parameter `T` in the current scope --> $DIR/issue-95898.rs:5:7 | +LL | fn foo(t: T) { + | - method `clone` not found for this type parameter LL | t.clone(); | ^^^^^ method not found in `T` | diff --git a/src/test/ui/traits/item-privacy.stderr b/src/test/ui/traits/item-privacy.stderr index ef5d5cdff8f4b..a7954f7b24595 100644 --- a/src/test/ui/traits/item-privacy.stderr +++ b/src/test/ui/traits/item-privacy.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `a` found for struct `S` in the current scope --> $DIR/item-privacy.rs:67:7 | LL | struct S; - | --------- method `a` not found for this + | - method `a` not found for this struct ... LL | S.a(); | ^ method not found in `S` @@ -18,7 +18,7 @@ error[E0599]: no method named `b` found for struct `S` in the current scope --> $DIR/item-privacy.rs:68:7 | LL | struct S; - | --------- method `b` not found for this + | - method `b` not found for this struct ... LL | fn b(&self) { } | - the method is available for `S` here @@ -45,7 +45,7 @@ error[E0599]: no function or associated item named `a` found for struct `S` in t --> $DIR/item-privacy.rs:78:8 | LL | struct S; - | --------- function or associated item `a` not found for this + | - function or associated item `a` not found for this struct ... LL | S::a(&S); | ^ function or associated item not found in `S` @@ -61,7 +61,7 @@ error[E0599]: no function or associated item named `b` found for struct `S` in t --> $DIR/item-privacy.rs:80:8 | LL | struct S; - | --------- function or associated item `b` not found for this + | - function or associated item `b` not found for this struct ... LL | S::b(&S); | ^ function or associated item not found in `S` @@ -85,7 +85,7 @@ error[E0599]: no associated item named `A` found for struct `S` in the current s --> $DIR/item-privacy.rs:97:8 | LL | struct S; - | --------- associated item `A` not found for this + | - associated item `A` not found for this struct ... LL | S::A; | ^ associated item not found in `S` @@ -101,7 +101,7 @@ error[E0599]: no associated item named `B` found for struct `S` in the current s --> $DIR/item-privacy.rs:98:8 | LL | struct S; - | --------- associated item `B` not found for this + | - associated item `B` not found for this struct ... LL | S::B; | ^ associated item not found in `S` diff --git a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr index c18abf95083da..d8f2f8761ff94 100644 --- a/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr +++ b/src/test/ui/traits/negative-impls/explicitly-unimplemented-error-message.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `clone` found for struct `Qux` in the current scop --> $DIR/explicitly-unimplemented-error-message.rs:34:9 | LL | struct Qux; - | ----------- method `clone` not found for this + | --- method `clone` not found for this struct ... LL | Qux.clone(); | ^^^^^ method not found in `Qux` @@ -23,7 +23,7 @@ error[E0599]: no method named `foo` found for struct `Qux` in the current scope --> $DIR/explicitly-unimplemented-error-message.rs:44:9 | LL | struct Qux; - | ----------- method `foo` not found for this + | --- method `foo` not found for this struct ... LL | Qux.foo(); | ^^^ method not found in `Qux` diff --git a/src/test/ui/typeck/point-at-type-parameter-definition.rs b/src/test/ui/typeck/point-at-type-parameter-definition.rs new file mode 100644 index 0000000000000..856c0db08f79c --- /dev/null +++ b/src/test/ui/typeck/point-at-type-parameter-definition.rs @@ -0,0 +1,17 @@ +trait Trait { + fn do_stuff(&self); +} + +struct Hello; + +impl Hello { + fn method(&self) {} +} + +impl Trait for Vec { + fn do_stuff(&self) { + self[0].method(); //~ ERROR no method named `method` found for type parameter `Hello` in the current scope + } +} + +fn main() {} diff --git a/src/test/ui/typeck/point-at-type-parameter-definition.stderr b/src/test/ui/typeck/point-at-type-parameter-definition.stderr new file mode 100644 index 0000000000000..8a6ab61100d24 --- /dev/null +++ b/src/test/ui/typeck/point-at-type-parameter-definition.stderr @@ -0,0 +1,12 @@ +error[E0599]: no method named `method` found for type parameter `Hello` in the current scope + --> $DIR/point-at-type-parameter-definition.rs:13:17 + | +LL | impl Trait for Vec { + | ----- method `method` not found for this type parameter +LL | fn do_stuff(&self) { +LL | self[0].method(); + | ^^^^^^ method not found in `Hello` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr index c242a7de7abfb..b5c72aa524779 100644 --- a/src/test/ui/union/union-derive-clone.mirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.mirunsafeck.stderr @@ -3,8 +3,8 @@ error[E0599]: the method `clone` exists for union `U5`, but its tra | LL | union U5 { | ----------- - | | - | method `clone` not found for this + | | | + | | method `clone` not found for this union | doesn't satisfy `U5: Clone` ... LL | struct CloneNoCopy; diff --git a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr index c242a7de7abfb..b5c72aa524779 100644 --- a/src/test/ui/union/union-derive-clone.thirunsafeck.stderr +++ b/src/test/ui/union/union-derive-clone.thirunsafeck.stderr @@ -3,8 +3,8 @@ error[E0599]: the method `clone` exists for union `U5`, but its tra | LL | union U5 { | ----------- - | | - | method `clone` not found for this + | | | + | | method `clone` not found for this union | doesn't satisfy `U5: Clone` ... LL | struct CloneNoCopy; From eb86daa1383d5330a18aa4e78270a6ca5b4ea469 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 22 Jun 2022 14:56:40 +0900 Subject: [PATCH 20/28] add "was" to pluralize macro and use it --- compiler/rustc_lint_defs/src/lib.rs | 3 ++ compiler/rustc_typeck/src/check/expr.rs | 39 ++++++++++--------- src/test/ui/issues/issue-76077.stderr | 2 +- src/test/ui/privacy/issue-79593.stderr | 2 +- ...-missing-inaccessible-field-literal.stderr | 2 +- 5 files changed, 27 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index cb1c6f4098767..1cd19c7eaab35 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -26,6 +26,9 @@ macro_rules! pluralize { ("is", $x:expr) => { if $x == 1 { "is" } else { "are" } }; + ("was", $x:expr) => { + if $x == 1 { "was" } else { "were" } + }; ("this", $x:expr) => { if $x == 1 { "this" } else { "these" } }; diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index e5048fc513217..c69de6434539a 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1839,25 +1839,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }) .partition(|field| field.2); - let remaining_private_fields_len = remaining_private_fields.len(); - let names = match &remaining_private_fields - .iter() - .map(|(name, _, _)| name.to_string()) - .collect::>()[..] - { - _ if remaining_private_fields_len > 6 => String::new(), - [name] => format!("`{name}` "), - [names @ .., last] => { - let names = names.iter().map(|name| format!("`{name}`")).collect::>(); - format!("{} and `{last}` ", names.join(", ")) - } - [] => unreachable!(), - }; err.span_labels(used_private_fields.iter().map(|(_, span, _)| *span), "private field"); - err.note(format!( - "... and other private field{s} {names}that were not provided", - s = pluralize!(remaining_private_fields_len), - )); + if !remaining_private_fields.is_empty() { + let remaining_private_fields_len = remaining_private_fields.len(); + let names = match &remaining_private_fields + .iter() + .map(|(name, _, _)| name.to_string()) + .collect::>()[..] + { + _ if remaining_private_fields_len > 6 => String::new(), + [name] => format!("`{name}` "), + [names @ .., last] => { + let names = names.iter().map(|name| format!("`{name}`")).collect::>(); + format!("{} and `{last}` ", names.join(", ")) + } + [] => unreachable!(), + }; + err.note(format!( + "... and other private field{s} {names}that {were} not provided", + s = pluralize!(remaining_private_fields_len), + were = pluralize!("was", remaining_private_fields_len), + )); + } err.emit(); } diff --git a/src/test/ui/issues/issue-76077.stderr b/src/test/ui/issues/issue-76077.stderr index 57f7abe3931a4..197ca8d5a7b25 100644 --- a/src/test/ui/issues/issue-76077.stderr +++ b/src/test/ui/issues/issue-76077.stderr @@ -4,7 +4,7 @@ error: cannot construct `Foo` with struct literal syntax due to private fields LL | foo::Foo {}; | ^^^^^^^^ | - = note: ... and other private field `you_cant_use_this_field` that were not provided + = note: ... and other private field `you_cant_use_this_field` that was not provided error: aborting due to previous error diff --git a/src/test/ui/privacy/issue-79593.stderr b/src/test/ui/privacy/issue-79593.stderr index d878e1c023ff1..21ba760ad0bcc 100644 --- a/src/test/ui/privacy/issue-79593.stderr +++ b/src/test/ui/privacy/issue-79593.stderr @@ -16,7 +16,7 @@ error: cannot construct `Pub` with struct literal syntax due to private fields LL | foo::Pub {}; | ^^^^^^^^ | - = note: ... and other private field `private` that were not provided + = note: ... and other private field `private` that was not provided error[E0063]: missing field `y` in initializer of `Enum` --> $DIR/issue-79593.rs:23:5 diff --git a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr index fa1c661ef244e..f0bd3e0ddf768 100644 --- a/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr +++ b/src/test/ui/typeck/issue-87872-missing-inaccessible-field-literal.stderr @@ -4,7 +4,7 @@ error: cannot construct `Foo` with struct literal syntax due to private fields LL | foo::Foo {}; | ^^^^^^^^ | - = note: ... and other private field `you_cant_use_this_field` that were not provided + = note: ... and other private field `you_cant_use_this_field` that was not provided error: aborting due to previous error From 53481a5a8fde83ed1a5d7e8302be028a4c7d8da5 Mon Sep 17 00:00:00 2001 From: Rose Hudson Date: Wed, 22 Jun 2022 14:06:13 +0100 Subject: [PATCH 21/28] implement `iter_projections` function on `PlaceRef` this makes the api more flexible. the original function now calls the PlaceRef version to avoid duplicating the code. --- compiler/rustc_middle/src/mir/mod.rs | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 4265559cd3197..3f5b16d5ea5f7 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2145,10 +2145,7 @@ impl<'tcx> Place<'tcx> { pub fn iter_projections( self, ) -> impl Iterator, PlaceElem<'tcx>)> + DoubleEndedIterator { - self.projection.iter().enumerate().map(move |(i, proj)| { - let base = PlaceRef { local: self.local, projection: &self.projection[..i] }; - (base, proj) - }) + self.as_ref().iter_projections() } /// Generates a new place by appending `more_projections` to the existing ones @@ -2208,6 +2205,23 @@ impl<'tcx> PlaceRef<'tcx> { None } } + + /// Iterate over the projections in evaluation order, i.e., the first element is the base with + /// its projection and then subsequently more projections are added. + /// As a concrete example, given the place a.b.c, this would yield: + /// - (a, .b) + /// - (a.b, .c) + /// + /// Given a place without projections, the iterator is empty. + #[inline] + pub fn iter_projections( + self, + ) -> impl Iterator, PlaceElem<'tcx>)> + DoubleEndedIterator { + self.projection.iter().enumerate().map(move |(i, proj)| { + let base = PlaceRef { local: self.local, projection: &self.projection[..i] }; + (base, *proj) + }) + } } impl Debug for Place<'_> { From 8e40d936473c41342e935ab323d755210af285e0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Jun 2022 16:26:04 +0200 Subject: [PATCH 22/28] Filter out keyword items in rustdoc JSON output --- src/librustdoc/json/conversions.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 4fde63c99d4b9..c627dcc30d667 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -43,7 +43,7 @@ impl JsonRenderer<'_> { let span = item.span(self.tcx); let clean::Item { name, attrs: _, kind: _, visibility, item_id, cfg: _ } = item; let inner = match *item.kind { - clean::StrippedItem(_) => return None, + clean::StrippedItem(_) | clean::KeywordItem(_) => return None, _ => from_clean_item(item, self.tcx), }; Some(Item { @@ -254,11 +254,8 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { }, // FIXME: do not map to Typedef but to a custom variant AssocTypeItem(t, _) => ItemEnum::Typedef(t.into_tcx(tcx)), - // `convert_item` early returns `None` for striped items - StrippedItem(_) => unreachable!(), - KeywordItem(_) => { - panic!("{:?} is not supported for JSON output", item) - } + // `convert_item` early returns `None` for striped items and keywords. + StrippedItem(_) | KeywordItem(_) => unreachable!(), ExternCrateItem { ref src } => ItemEnum::ExternCrate { name: name.as_ref().unwrap().to_string(), rename: src.map(|x| x.to_string()), @@ -764,7 +761,7 @@ impl FromWithTcx for ItemKind { fn ids(items: impl IntoIterator, tcx: TyCtxt<'_>) -> Vec { items .into_iter() - .filter(|x| !x.is_stripped()) + .filter(|x| !x.is_stripped() && !x.is_keyword()) .map(|i| from_item_id_with_name(i.item_id, tcx, i.name)) .collect() } From 75ad2f7a76170943aaf543c74097927e57a89f32 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 22 Jun 2022 16:26:22 +0200 Subject: [PATCH 23/28] Add test for keywords in rustdoc JSON output --- src/test/rustdoc-json/keyword.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/rustdoc-json/keyword.rs diff --git a/src/test/rustdoc-json/keyword.rs b/src/test/rustdoc-json/keyword.rs new file mode 100644 index 0000000000000..78a843aca7b95 --- /dev/null +++ b/src/test/rustdoc-json/keyword.rs @@ -0,0 +1,21 @@ +// Regression test for . + +// Keywords should not be generated in rustdoc JSON output and this test +// ensures it. + +#![feature(rustdoc_internals)] +#![no_std] + +// @has keyword.json +// @!has - "$.index[*][?(@.name=='match')]" +// @has - "$.index[*][?(@.name=='foo')]" + +#[doc(keyword = "match")] +/// this is a test! +pub mod foo {} + +// @!has - "$.index[*][?(@.name=='hello')]" +// @!has - "$.index[*][?(@.name=='bar')]" +#[doc(keyword = "hello")] +/// hello +mod bar {} From 96cc0c691a0b91e02a3011ecd2cdf8c087ecc470 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 22 Jun 2022 14:01:31 -0700 Subject: [PATCH 24/28] triagebot.toml: Allow applying nominated labels This seems likely to help more than it would hurt; let's see how it goes. --- triagebot.toml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 25e2c384624e9..dbaee7983bbc2 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1,14 +1,12 @@ [relabel] allow-unauthenticated = [ - "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*", + "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*", "I-*", "D-*", "needs-fcp", "relnotes", "requires-nightly", "regression-*", "perf-*", - # I-* without I-*nominated - "I-*", "!I-*nominated", "AsyncAwait-OnDeck", ] From 5cf5a5236f298d701bb59941125acbd953d1ebfb Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 22 Jun 2022 14:02:48 -0700 Subject: [PATCH 25/28] triagebot.toml: Sort and wrap the list of allowed labels --- triagebot.toml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index dbaee7983bbc2..cef78cc3b336e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1,7 +1,16 @@ [relabel] allow-unauthenticated = [ - "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*", "I-*", + "A-*", + "C-*", "D-*", + "E-*", + "F-*", + "I-*", + "NLL-*", + "O-*", + "S-*", + "T-*", + "WG-*", "needs-fcp", "relnotes", "requires-nightly", From 24e0c44eb66fb3c1a2305cc67fea0e042e678b7f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 22 Jun 2022 16:11:10 -0700 Subject: [PATCH 26/28] Update books --- src/doc/book | 2 +- src/doc/embedded-book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/book b/src/doc/book index 396fdb69de7fb..efbafdba36184 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 396fdb69de7fb18f24b15c7ad13491b1c1fa7231 +Subproject commit efbafdba3618487fbc9305318fcab9775132ac15 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index cbb494f96da32..e17dcef5e9634 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit cbb494f96da3268c2925bdadc65ca83d42f2d4ef +Subproject commit e17dcef5e96346ee3d7fa56820ddc7e5c39636bc diff --git a/src/doc/reference b/src/doc/reference index 683bfe5cd64d5..9fce337a55ee4 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 683bfe5cd64d589c6a1645312ab5f93b6385ccbb +Subproject commit 9fce337a55ee4a4629205f6094656195cecad231 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index dbb7e5e2345ee..1095df2a5850f 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit dbb7e5e2345ee26199ffba218156b6009016a20c +Subproject commit 1095df2a5850f2d345fad43a30633133365875ba diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 6e4d6435db89b..048d925f0a955 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 6e4d6435db89bcc027b1bba9742e4f59666f5412 +Subproject commit 048d925f0a955aac601c4160c0e7f05771bcf63b From b96ae9b20442b59c471baec6c4d612e3434d893c Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Wed, 22 Jun 2022 17:43:10 -0700 Subject: [PATCH 27/28] Set no_default_libraries: false in wasm32_emscripten target --- compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs index 975051100b039..6a1a5e7a1d712 100644 --- a/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/wasm32_unknown_emscripten.rs @@ -28,6 +28,7 @@ pub fn target() -> Target { linker: None, is_like_emscripten: true, panic_strategy: PanicStrategy::Unwind, + no_default_libraries: false, post_link_args, families: cvs!["unix", "wasm"], ..options From 137d3c7067a96d45ea96d53f523d482928668619 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Jun 2022 13:04:29 +0200 Subject: [PATCH 28/28] Update browser-ui-test version to 0.9.6 This update provides a better error message when chromium crashes --- .../docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index 03834411d1529..9cf038687f117 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.9.5 \ No newline at end of file +0.9.6 \ No newline at end of file