From 741d6ef17e7ee4a77c9fbc73ea92878d2a6e58ab Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Wed, 11 Sep 2024 01:26:55 +0300 Subject: [PATCH 01/13] Stabilize `std::io::ErrorKind::CrossesDevices` --- library/std/src/io/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 6ecd9469c1740..d0b20b344ff8a 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -353,7 +353,7 @@ pub enum ErrorKind { #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] Deadlock, /// Cross-device or cross-filesystem (hard) link or rename. - #[unstable(feature = "io_error_more", issue = "86442")] + #[stable(feature = "io_error_crosses_devices", since = "CURRENT_RUSTC_VERSION")] CrossesDevices, /// Too many (hard) links to the same filesystem object. /// From b2c1c8f13a88be63ebe1907996bf806a91ec5680 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 12 Sep 2024 02:53:12 +0300 Subject: [PATCH 02/13] Stabilize `std::io::ErrorKind::QuotaExceeded` Also drop "Filesystem" from its name --- library/std/src/io/error.rs | 8 ++++---- library/std/src/io/error/repr_bitpacked.rs | 2 +- library/std/src/sys/pal/teeos/mod.rs | 2 +- library/std/src/sys/pal/unix/mod.rs | 2 +- library/std/src/sys/pal/windows/mod.rs | 4 ++-- src/tools/miri/src/shims/io_error.rs | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index f20814dd95cc1..4cb0754de9b29 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -327,9 +327,9 @@ pub enum ErrorKind { /// example, on Unix, a named pipe opened with `File::open`. #[stable(feature = "io_error_a_bit_more", since = "CURRENT_RUSTC_VERSION")] NotSeekable, - /// Filesystem quota was exceeded. - #[unstable(feature = "io_error_more", issue = "86442")] - FilesystemQuotaExceeded, + /// Filesystem quota or some other kind of quota was exceeded. + #[stable(feature = "io_error_quota_exceeded", since = "CURRENT_RUSTC_VERSION")] + QuotaExceeded, /// File larger than allowed or supported. /// /// This might arise from a hard limit of the underlying filesystem or file access API, or from @@ -451,7 +451,7 @@ impl ErrorKind { ExecutableFileBusy => "executable file busy", FileTooLarge => "file too large", FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", - FilesystemQuotaExceeded => "filesystem quota exceeded", + QuotaExceeded => "quota exceeded", HostUnreachable => "host unreachable", Interrupted => "operation interrupted", InProgress => "in progress", diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index a839a2fbac117..f958a93864603 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -335,7 +335,7 @@ fn kind_from_prim(ek: u32) -> Option { WriteZero, StorageFull, NotSeekable, - FilesystemQuotaExceeded, + QuotaExceeded, FileTooLarge, ResourceBusy, ExecutableFileBusy, diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs index 60a227afb84e3..4253fcb7f5be7 100644 --- a/library/std/src/sys/pal/teeos/mod.rs +++ b/library/std/src/sys/pal/teeos/mod.rs @@ -63,7 +63,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::ECONNREFUSED => ConnectionRefused, libc::ECONNRESET => ConnectionReset, libc::EDEADLK => Deadlock, - libc::EDQUOT => FilesystemQuotaExceeded, + libc::EDQUOT => QuotaExceeded, libc::EEXIST => AlreadyExists, libc::EFBIG => FileTooLarge, libc::EHOSTUNREACH => HostUnreachable, diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 4fe18daa2040f..35a6f0ccd74d0 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -253,7 +253,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::ECONNREFUSED => ConnectionRefused, libc::ECONNRESET => ConnectionReset, libc::EDEADLK => Deadlock, - libc::EDQUOT => FilesystemQuotaExceeded, + libc::EDQUOT => QuotaExceeded, libc::EEXIST => AlreadyExists, libc::EFBIG => FileTooLarge, libc::EHOSTUNREACH => HostUnreachable, diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 1ea253e5e5263..b3b26eb858d81 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -113,7 +113,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem, c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull, c::ERROR_SEEK_ON_DEVICE => return NotSeekable, - c::ERROR_DISK_QUOTA_EXCEEDED => return FilesystemQuotaExceeded, + c::ERROR_DISK_QUOTA_EXCEEDED => return QuotaExceeded, c::ERROR_FILE_TOO_LARGE => return FileTooLarge, c::ERROR_BUSY => return ResourceBusy, c::ERROR_POSSIBLE_DEADLOCK => return Deadlock, @@ -138,7 +138,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { c::WSAEHOSTUNREACH => HostUnreachable, c::WSAENETDOWN => NetworkDown, c::WSAENETUNREACH => NetworkUnreachable, - c::WSAEDQUOT => FilesystemQuotaExceeded, + c::WSAEDQUOT => QuotaExceeded, _ => Uncategorized, } diff --git a/src/tools/miri/src/shims/io_error.rs b/src/tools/miri/src/shims/io_error.rs index 38aa181cb4f05..1a95ae1e7d451 100644 --- a/src/tools/miri/src/shims/io_error.rs +++ b/src/tools/miri/src/shims/io_error.rs @@ -43,7 +43,7 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = { ("ECONNREFUSED", ConnectionRefused), ("ECONNRESET", ConnectionReset), ("EDEADLK", Deadlock), - ("EDQUOT", FilesystemQuotaExceeded), + ("EDQUOT", QuotaExceeded), ("EEXIST", AlreadyExists), ("EFBIG", FileTooLarge), ("EHOSTUNREACH", HostUnreachable), From eb5203233a20e15c9f8f0796cd82e9170c6466f9 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 12 Sep 2024 02:58:27 +0300 Subject: [PATCH 03/13] Unbreak tidy --- library/std/src/io/error.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index 4cb0754de9b29..0c76ddec99ed5 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -435,8 +435,8 @@ pub enum ErrorKind { impl ErrorKind { pub(crate) fn as_str(&self) -> &'static str { use ErrorKind::*; - // tidy-alphabetical-start match *self { + // tidy-alphabetical-start AddrInUse => "address in use", AddrNotAvailable => "address not available", AlreadyExists => "entity already exists", @@ -449,12 +449,11 @@ impl ErrorKind { Deadlock => "deadlock", DirectoryNotEmpty => "directory not empty", ExecutableFileBusy => "executable file busy", - FileTooLarge => "file too large", FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)", - QuotaExceeded => "quota exceeded", + FileTooLarge => "file too large", HostUnreachable => "host unreachable", - Interrupted => "operation interrupted", InProgress => "in progress", + Interrupted => "operation interrupted", InvalidData => "invalid data", InvalidFilename => "invalid filename", InvalidInput => "invalid input parameter", @@ -468,6 +467,7 @@ impl ErrorKind { Other => "other error", OutOfMemory => "out of memory", PermissionDenied => "permission denied", + QuotaExceeded => "quota exceeded", ReadOnlyFilesystem => "read-only filesystem or storage medium", ResourceBusy => "resource busy", StaleNetworkFileHandle => "stale network file handle", @@ -479,8 +479,8 @@ impl ErrorKind { Unsupported => "unsupported", WouldBlock => "operation would block", WriteZero => "write zero", + // tidy-alphabetical-end } - // tidy-alphabetical-end } } From 59be878506d38483b49bbd97a11aaa1047cfd76b Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Sat, 26 Oct 2024 17:25:10 +0200 Subject: [PATCH 04/13] Add Extend impls for tuples of arity 1 through 12 --- library/core/src/iter/traits/collect.rs | 248 +++++++++++++----------- 1 file changed, 138 insertions(+), 110 deletions(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 2cf2ea58fd4ee..16211610f0551 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -492,131 +492,159 @@ impl Extend<()> for () { fn extend_one(&mut self, _item: ()) {} } -#[stable(feature = "extend_for_tuple", since = "1.56.0")] -impl Extend<(A, B)> for (ExtendA, ExtendB) -where - ExtendA: Extend, - ExtendB: Extend, -{ - /// Allows to `extend` a tuple of collections that also implement `Extend`. - /// - /// See also: [`Iterator::unzip`] - /// - /// # Examples - /// ``` - /// let mut tuple = (vec![0], vec![1]); - /// tuple.extend([(2, 3), (4, 5), (6, 7)]); - /// assert_eq!(tuple.0, [0, 2, 4, 6]); - /// assert_eq!(tuple.1, [1, 3, 5, 7]); - /// - /// // also allows for arbitrarily nested tuples as elements - /// let mut nested_tuple = (vec![1], (vec![2], vec![3])); - /// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]); - /// - /// let (a, (b, c)) = nested_tuple; - /// assert_eq!(a, [1, 4, 7]); - /// assert_eq!(b, [2, 5, 8]); - /// assert_eq!(c, [3, 6, 9]); - /// ``` - fn extend>(&mut self, into_iter: T) { - let (a, b) = self; - let iter = into_iter.into_iter(); - SpecTupleExtend::extend(iter, a, b); - } +macro_rules! spec_tuple_impl { + ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), ) => { + spec_tuple_impl!($trait_name, $default_fn_name, #[stable(feature = "extend_for_more_tuples", since = "CURRENT_RUSTC_VERSION")] #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long."] => ($ty_name, $var_name, $extend_ty_name, $cnt),); + }; + // Special case (A, B) as this was stabilized earlier + ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), + ($ty_names:ident, $var_names:ident, $extend_ty_names: ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),) => { - fn extend_one(&mut self, item: (A, B)) { - self.0.extend_one(item.0); - self.1.extend_one(item.1); - } + spec_tuple_impl!(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),); + spec_tuple_impl!($trait_name, $default_fn_name, #[stable(feature = "extend_for_tuple", since = "1.56.0")] => ($ty_name, $var_name, $extend_ty_name, $cnt), ($ty_names, $var_names, $extend_ty_names, $cnts),); + }; + ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),)*) => { - fn extend_reserve(&mut self, additional: usize) { - self.0.extend_reserve(additional); - self.1.extend_reserve(additional); - } + spec_tuple_impl!($(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),)*); + spec_tuple_impl!($trait_name, $default_fn_name, #[stable(feature = "extend_for_more_tuples", since = "CURRENT_RUSTC_VERSION")] #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*); + }; + ($trait_name:ident, $default_fn_name:ident, #[$stable:meta] $(#[$meta:meta] $(#[$doctext:meta])?)? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => { + $(#[$meta] + $(#[$doctext])? + )? + #[$stable] + impl<$($ty_names,)* $($extend_ty_names,)*> Extend<($($ty_names,)*)> for ($($extend_ty_names,)*) + where + $($extend_ty_names: Extend<$ty_names>,)* + { + /// Allows to `extend` a tuple of collections that also implement `Extend`. + /// + /// See also: [`Iterator::unzip`] + /// + /// # Examples + /// ``` + /// // Example given for a 2-tuple, but 1- through 12-tuples are supported + /// let mut tuple = (vec![0], vec![1]); + /// tuple.extend([(2, 3), (4, 5), (6, 7)]); + /// assert_eq!(tuple.0, [0, 2, 4, 6]); + /// assert_eq!(tuple.1, [1, 3, 5, 7]); + /// + /// // also allows for arbitrarily nested tuples as elements + /// let mut nested_tuple = (vec![1], (vec![2], vec![3])); + /// nested_tuple.extend([(4, (5, 6)), (7, (8, 9))]); + /// + /// let (a, (b, c)) = nested_tuple; + /// assert_eq!(a, [1, 4, 7]); + /// assert_eq!(b, [2, 5, 8]); + /// assert_eq!(c, [3, 6, 9]); + /// ``` + fn extend>(&mut self, into_iter: T) { + let ($($var_names,)*) = self; + let iter = into_iter.into_iter(); + $trait_name::extend(iter, $($var_names,)*); + } - unsafe fn extend_one_unchecked(&mut self, item: (A, B)) { - // SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`. - unsafe { - self.0.extend_one_unchecked(item.0); - self.1.extend_one_unchecked(item.1); - } - } -} + fn extend_one(&mut self, item: ($($ty_names,)*)) { + $(self.$cnts.extend_one(item.$cnts);)* + } -fn default_extend_tuple( - iter: impl Iterator, - a: &mut ExtendA, - b: &mut ExtendB, -) where - ExtendA: Extend, - ExtendB: Extend, -{ - fn extend<'a, A, B>( - a: &'a mut impl Extend, - b: &'a mut impl Extend, - ) -> impl FnMut((), (A, B)) + 'a { - move |(), (t, u)| { - a.extend_one(t); - b.extend_one(u); + fn extend_reserve(&mut self, additional: usize) { + $(self.$cnts.extend_reserve(additional);)* + } + + unsafe fn extend_one_unchecked(&mut self, item: ($($ty_names,)*)) { + // SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`. + unsafe { + $(self.$cnts.extend_one_unchecked(item.$cnts);)* + } + } } - } - let (lower_bound, _) = iter.size_hint(); - if lower_bound > 0 { - a.extend_reserve(lower_bound); - b.extend_reserve(lower_bound); - } + trait $trait_name<$($ty_names),*> { + fn extend(self, $($var_names: &mut $ty_names,)*); + } - iter.fold((), extend(a, b)); -} + fn $default_fn_name<$($ty_names,)* $($extend_ty_names,)*>( + iter: impl Iterator, + $($var_names: &mut $extend_ty_names,)* + ) where + $($extend_ty_names: Extend<$ty_names>,)* + { + fn extend<'a, $($ty_names,)*>( + $($var_names: &'a mut impl Extend<$ty_names>,)* + ) -> impl FnMut((), ($($ty_names,)*)) + 'a { + #[allow(non_snake_case)] + move |(), ($($extend_ty_names,)*)| { + $($var_names.extend_one($extend_ty_names);)* + } + } -trait SpecTupleExtend { - fn extend(self, a: &mut A, b: &mut B); -} + let (lower_bound, _) = iter.size_hint(); + if lower_bound > 0 { + $($var_names.extend_reserve(lower_bound);)* + } -impl SpecTupleExtend for Iter -where - ExtendA: Extend, - ExtendB: Extend, - Iter: Iterator, -{ - default fn extend(self, a: &mut ExtendA, b: &mut ExtendB) { - default_extend_tuple(self, a, b); - } -} + iter.fold((), extend($($var_names,)*)); + } -impl SpecTupleExtend for Iter -where - ExtendA: Extend, - ExtendB: Extend, - Iter: TrustedLen, -{ - fn extend(self, a: &mut ExtendA, b: &mut ExtendB) { - fn extend<'a, A, B>( - a: &'a mut impl Extend, - b: &'a mut impl Extend, - ) -> impl FnMut((), (A, B)) + 'a { - // SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen` - // so its `size_hint` is exact. - move |(), (t, u)| unsafe { - a.extend_one_unchecked(t); - b.extend_one_unchecked(u); + impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter + where + $($extend_ty_names: Extend<$ty_names>,)* + Iter: Iterator, + { + default fn extend(self, $($var_names: &mut $extend_ty_names),*) { + $default_fn_name(self, $($var_names),*); } } - let (lower_bound, upper_bound) = self.size_hint(); + impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter + where + $($extend_ty_names: Extend<$ty_names>,)* + Iter: TrustedLen, + { + fn extend(self, $($var_names: &mut $extend_ty_names,)*) { + fn extend<'a, $($ty_names,)*>( + $($var_names: &'a mut impl Extend<$ty_names>,)* + ) -> impl FnMut((), ($($ty_names,)*)) + 'a { + #[allow(non_snake_case)] + // SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen` + // so its `size_hint` is exact. + move |(), ($($extend_ty_names,)*)| unsafe { + $($var_names.extend_one_unchecked($extend_ty_names);)* + } + } - if upper_bound.is_none() { - // We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway. - default_extend_tuple(self, a, b); - return; - } + let (lower_bound, upper_bound) = self.size_hint(); - if lower_bound > 0 { - a.extend_reserve(lower_bound); - b.extend_reserve(lower_bound); - } + if upper_bound.is_none() { + // We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway. + $default_fn_name(self, $($var_names,)*); + return; + } - self.fold((), extend(a, b)); + if lower_bound > 0 { + $($var_names.extend_reserve(lower_bound);)* + } + + self.fold((), extend($($var_names,)*)); + } } + + }; } + +spec_tuple_impl!( + (M, m, EM, TraitM, default_extend_tuple_m, 12), + (L, l, EL, TraitL, default_extend_tuple_l, 11), + (K, k, EK, TraitK, default_extend_tuple_k, 10), + (J, j, EJ, TraitJ, default_extend_tuple_j, 9), + (I, i, EI, TraitI, default_extend_tuple_i, 8), + (H, h, EH, TraitH, default_extend_tuple_h, 7), + (G, g, EG, TraitG, default_extend_tuple_g, 6), + (F, f, EF, TraitF, default_extend_tuple_f, 5), + (E, e, EE, TraitE, default_extend_tuple_e, 4), + (D, d, ED, TraitD, default_extend_tuple_d, 3), + (C, c, EC, TraitC, default_extend_tuple_c, 2), + (B, b, EB, TraitB, default_extend_tuple_b, 1), + (A, a, EA, TraitA, default_extend_tuple_a, 0), +); From be0650272d590f14198d64c6c6f256b1804dcb28 Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Sat, 26 Oct 2024 18:58:05 +0200 Subject: [PATCH 05/13] Simplify documentation for Extend impl for tuples --- library/core/src/iter/traits/collect.rs | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 16211610f0551..8e2d7b9b4a6eb 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -494,25 +494,17 @@ impl Extend<()> for () { macro_rules! spec_tuple_impl { ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), ) => { - spec_tuple_impl!($trait_name, $default_fn_name, #[stable(feature = "extend_for_more_tuples", since = "CURRENT_RUSTC_VERSION")] #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long."] => ($ty_name, $var_name, $extend_ty_name, $cnt),); - }; - // Special case (A, B) as this was stabilized earlier - ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), - ($ty_names:ident, $var_names:ident, $extend_ty_names: ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),) => { - - spec_tuple_impl!(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),); - spec_tuple_impl!($trait_name, $default_fn_name, #[stable(feature = "extend_for_tuple", since = "1.56.0")] => ($ty_name, $var_name, $extend_ty_name, $cnt), ($ty_names, $var_names, $extend_ty_names, $cnts),); + spec_tuple_impl!($trait_name, $default_fn_name, #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in RUSTC_CURRENT_VERSION."] => ($ty_name, $var_name, $extend_ty_name, $cnt),); }; ( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),)*) => { spec_tuple_impl!($(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),)*); - spec_tuple_impl!($trait_name, $default_fn_name, #[stable(feature = "extend_for_more_tuples", since = "CURRENT_RUSTC_VERSION")] #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*); + spec_tuple_impl!($trait_name, $default_fn_name, #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*); }; - ($trait_name:ident, $default_fn_name:ident, #[$stable:meta] $(#[$meta:meta] $(#[$doctext:meta])?)? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => { - $(#[$meta] - $(#[$doctext])? - )? - #[$stable] + ($trait_name:ident, $default_fn_name:ident, #[$meta:meta] $(#[$doctext:meta])? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => { + #[$meta] + $(#[$doctext])? + #[stable(feature = "extend_for_tuple", since = "1.56.0")] impl<$($ty_names,)* $($extend_ty_names,)*> Extend<($($ty_names,)*)> for ($($extend_ty_names,)*) where $($extend_ty_names: Extend<$ty_names>,)* From 9cebcbad1846f6b5448e386a6a6647484adf7e8f Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Thu, 31 Oct 2024 01:23:46 +0100 Subject: [PATCH 06/13] Don't impl Extend for 13-tuples --- library/core/src/iter/traits/collect.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index 8e2d7b9b4a6eb..c3c7288e38990 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -626,7 +626,6 @@ macro_rules! spec_tuple_impl { } spec_tuple_impl!( - (M, m, EM, TraitM, default_extend_tuple_m, 12), (L, l, EL, TraitL, default_extend_tuple_l, 11), (K, k, EK, TraitK, default_extend_tuple_k, 10), (J, j, EJ, TraitJ, default_extend_tuple_j, 9), From 27342cbb1fef4ab2a1b7347b38c09c079f7dc838 Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Thu, 31 Oct 2024 01:48:37 +0100 Subject: [PATCH 07/13] Add a `collect_into` tuple test case --- library/core/tests/iter/traits/iterator.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/library/core/tests/iter/traits/iterator.rs b/library/core/tests/iter/traits/iterator.rs index 93ef9c0812b16..76f1e3319d42e 100644 --- a/library/core/tests/iter/traits/iterator.rs +++ b/library/core/tests/iter/traits/iterator.rs @@ -617,6 +617,19 @@ fn test_next_chunk() { assert_eq!(it.next_chunk::<0>().unwrap(), []); } +#[test] +fn test_collect_into_tuples() { + let a = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)]; + let b = vec![1, 4, 7]; + let c = vec![2, 5, 8]; + let d = vec![3, 6, 9]; + let mut e = (Vec::new(), Vec::new(), Vec::new()); + a.iter().cloned().collect_into(&mut e); + assert!(e.0 == b); + assert!(e.1 == c); + assert!(e.2 == d); +} + // just tests by whether or not this compiles fn _empty_impl_all_auto_traits() { use std::panic::{RefUnwindSafe, UnwindSafe}; From a122dde217459c1decbce3452323807154763206 Mon Sep 17 00:00:00 2001 From: Jack Wrenn Date: Thu, 5 Dec 2024 20:15:08 +0000 Subject: [PATCH 08/13] do not implement unsafe auto traits for types with unsafe fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a type has unsafe fields, its safety invariants are not simply the conjunction of its field types' safety invariants. Consequently, it's invalid to reason about the safety properties of these types in a purely structural manner — i.e., the manner in which `auto` traits are implemented. Makes progress towards #132922. --- compiler/rustc_middle/src/ty/context.rs | 4 +++ compiler/rustc_middle/src/ty/sty.rs | 8 ++++++ .../src/solve/trait_goals.rs | 8 ++++++ .../src/traits/select/candidate_assembly.rs | 9 +++++++ compiler/rustc_type_ir/src/inherent.rs | 3 +++ compiler/rustc_type_ir/src/interner.rs | 3 +++ .../unsafe-fields/auto-traits.current.stderr | 17 ++++++++++++ .../ui/unsafe-fields/auto-traits.next.stderr | 17 ++++++++++++ tests/ui/unsafe-fields/auto-traits.rs | 26 +++++++++++++++++++ .../auxiliary/unsafe-fields-crate-dep.rs | 0 .../unsafe-fields-crate.rs | 0 .../unsafe-fields-crate.stderr | 0 .../unsafe-fields-parse.rs | 0 .../unsafe-fields-parse.stderr | 0 tests/ui/{ => unsafe-fields}/unsafe-fields.rs | 0 .../{ => unsafe-fields}/unsafe-fields.stderr | 0 16 files changed, 95 insertions(+) create mode 100644 tests/ui/unsafe-fields/auto-traits.current.stderr create mode 100644 tests/ui/unsafe-fields/auto-traits.next.stderr create mode 100644 tests/ui/unsafe-fields/auto-traits.rs rename tests/ui/{ => unsafe-fields}/auxiliary/unsafe-fields-crate-dep.rs (100%) rename tests/ui/{ => unsafe-fields}/unsafe-fields-crate.rs (100%) rename tests/ui/{ => unsafe-fields}/unsafe-fields-crate.stderr (100%) rename tests/ui/{ => unsafe-fields}/unsafe-fields-parse.rs (100%) rename tests/ui/{ => unsafe-fields}/unsafe-fields-parse.stderr (100%) rename tests/ui/{ => unsafe-fields}/unsafe-fields.rs (100%) rename tests/ui/{ => unsafe-fields}/unsafe-fields.stderr (100%) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3cbb2a3acf592..d4835bb07f689 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -585,6 +585,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.trait_def(trait_def_id).implement_via_object } + fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool { + self.trait_def(trait_def_id).safety == hir::Safety::Unsafe + } + fn is_impl_trait_in_trait(self, def_id: DefId) -> bool { self.is_impl_trait_in_trait(def_id) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 142db8a17f04f..474062218c97a 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -978,6 +978,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { fn async_destructor_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> { self.async_destructor_ty(interner) } + + fn has_unsafe_fields(self) -> bool { + if let ty::Adt(adt_def, ..) = self.kind() { + adt_def.all_fields().any(|x| x.safety == hir::Safety::Unsafe) + } else { + false + } + } } /// Type utilities diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 6641d2bf92492..12df35d30b8f3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -169,6 +169,14 @@ where return result; } + // Only consider auto impls of unsafe traits when there are no unsafe + // fields. + if ecx.cx().trait_is_unsafe(goal.predicate.def_id()) + && goal.predicate.self_ty().has_unsafe_fields() + { + return Err(NoSolution); + } + // We only look into opaque types during analysis for opaque types // outside of their defining scope. Doing so for opaques in the // defining scope may require calling `typeck` on the same item we're diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 32b4567aba4f0..3e2c8467d3220 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -18,6 +18,7 @@ use rustc_infer::traits::{ use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode}; use rustc_middle::{bug, span_bug}; +use rustc_type_ir::Interner; use tracing::{debug, instrument, trace}; use super::SelectionCandidate::*; @@ -794,6 +795,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Never | ty::Tuple(_) | ty::CoroutineWitness(..) => { + use rustc_type_ir::inherent::*; + + // Only consider auto impls of unsafe traits when there are + // no unsafe fields. + if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() { + return; + } + // Only consider auto impls if there are no manual impls for the root of `self_ty`. // // For example, we only consider auto candidates for `&i32: Auto` if no explicit impl diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index a201f2b1c11f1..f45c94127bd00 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -136,6 +136,9 @@ pub trait Ty>: matches!(self.kind(), ty::FnPtr(..)) } + /// Checks whether this type is an ADT that has unsafe fields. + fn has_unsafe_fields(self) -> bool; + fn fn_sig(self, interner: I) -> ty::Binder> { match self.kind() { ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr), diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 0ae688848ebfc..025ec7ae896dd 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -270,6 +270,9 @@ pub trait Interner: fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool; + /// Returns `true` if this is an `unsafe trait`. + fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool; + fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool; fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed; diff --git a/tests/ui/unsafe-fields/auto-traits.current.stderr b/tests/ui/unsafe-fields/auto-traits.current.stderr new file mode 100644 index 0000000000000..53a97458b7cd7 --- /dev/null +++ b/tests/ui/unsafe-fields/auto-traits.current.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied + --> $DIR/auto-traits.rs:24:22 + | +LL | impl_unsafe_auto(UnsafeEnum::Safe(42)); + | ---------------- ^^^^^^^^^^^^^^^^^^^^ the trait `UnsafeAuto` is not implemented for `UnsafeEnum` + | | + | required by a bound introduced by this call + | +note: required by a bound in `impl_unsafe_auto` + --> $DIR/auto-traits.rs:20:29 + | +LL | fn impl_unsafe_auto(_: impl UnsafeAuto) {} + | ^^^^^^^^^^ required by this bound in `impl_unsafe_auto` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsafe-fields/auto-traits.next.stderr b/tests/ui/unsafe-fields/auto-traits.next.stderr new file mode 100644 index 0000000000000..53a97458b7cd7 --- /dev/null +++ b/tests/ui/unsafe-fields/auto-traits.next.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied + --> $DIR/auto-traits.rs:24:22 + | +LL | impl_unsafe_auto(UnsafeEnum::Safe(42)); + | ---------------- ^^^^^^^^^^^^^^^^^^^^ the trait `UnsafeAuto` is not implemented for `UnsafeEnum` + | | + | required by a bound introduced by this call + | +note: required by a bound in `impl_unsafe_auto` + --> $DIR/auto-traits.rs:20:29 + | +LL | fn impl_unsafe_auto(_: impl UnsafeAuto) {} + | ^^^^^^^^^^ required by this bound in `impl_unsafe_auto` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsafe-fields/auto-traits.rs b/tests/ui/unsafe-fields/auto-traits.rs new file mode 100644 index 0000000000000..e15d0000079ef --- /dev/null +++ b/tests/ui/unsafe-fields/auto-traits.rs @@ -0,0 +1,26 @@ +//@ compile-flags: --crate-type=lib +//@ revisions: current next +//@[next] compile-flags: -Znext-solver + +#![feature(auto_traits)] +#![feature(unsafe_fields)] +#![allow(incomplete_features)] + +enum UnsafeEnum { + Safe(u8), + Unsafe { unsafe field: u8 }, +} + +auto trait SafeAuto {} + +fn impl_safe_auto(_: impl SafeAuto) {} + +unsafe auto trait UnsafeAuto {} + +fn impl_unsafe_auto(_: impl UnsafeAuto) {} + +fn tests() { + impl_safe_auto(UnsafeEnum::Safe(42)); + impl_unsafe_auto(UnsafeEnum::Safe(42)); + //~^ ERROR the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied +} diff --git a/tests/ui/auxiliary/unsafe-fields-crate-dep.rs b/tests/ui/unsafe-fields/auxiliary/unsafe-fields-crate-dep.rs similarity index 100% rename from tests/ui/auxiliary/unsafe-fields-crate-dep.rs rename to tests/ui/unsafe-fields/auxiliary/unsafe-fields-crate-dep.rs diff --git a/tests/ui/unsafe-fields-crate.rs b/tests/ui/unsafe-fields/unsafe-fields-crate.rs similarity index 100% rename from tests/ui/unsafe-fields-crate.rs rename to tests/ui/unsafe-fields/unsafe-fields-crate.rs diff --git a/tests/ui/unsafe-fields-crate.stderr b/tests/ui/unsafe-fields/unsafe-fields-crate.stderr similarity index 100% rename from tests/ui/unsafe-fields-crate.stderr rename to tests/ui/unsafe-fields/unsafe-fields-crate.stderr diff --git a/tests/ui/unsafe-fields-parse.rs b/tests/ui/unsafe-fields/unsafe-fields-parse.rs similarity index 100% rename from tests/ui/unsafe-fields-parse.rs rename to tests/ui/unsafe-fields/unsafe-fields-parse.rs diff --git a/tests/ui/unsafe-fields-parse.stderr b/tests/ui/unsafe-fields/unsafe-fields-parse.stderr similarity index 100% rename from tests/ui/unsafe-fields-parse.stderr rename to tests/ui/unsafe-fields/unsafe-fields-parse.stderr diff --git a/tests/ui/unsafe-fields.rs b/tests/ui/unsafe-fields/unsafe-fields.rs similarity index 100% rename from tests/ui/unsafe-fields.rs rename to tests/ui/unsafe-fields/unsafe-fields.rs diff --git a/tests/ui/unsafe-fields.stderr b/tests/ui/unsafe-fields/unsafe-fields.stderr similarity index 100% rename from tests/ui/unsafe-fields.stderr rename to tests/ui/unsafe-fields/unsafe-fields.stderr From 83909b6b05b38daaf69af523d4c852a45e252d2b Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 5 Dec 2024 00:29:29 +0300 Subject: [PATCH 09/13] skip formatting when `--json-output` is used Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/test.rs | 32 ++++++++++++++-------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 4fa91c1a57144..98bfc40fd7a9b 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -1070,23 +1070,33 @@ impl Step for Tidy { } if builder.config.channel == "dev" || builder.config.channel == "nightly" { - builder.info("fmt check"); - if builder.initial_rustfmt().is_none() { - let inferred_rustfmt_dir = builder.initial_sysroot.join("bin"); - eprintln!( - "\ + if !builder.config.json_output { + builder.info("fmt check"); + if builder.initial_rustfmt().is_none() { + let inferred_rustfmt_dir = builder.initial_sysroot.join("bin"); + eprintln!( + "\ ERROR: no `rustfmt` binary found in {PATH} INFO: `rust.channel` is currently set to \"{CHAN}\" HELP: if you are testing a beta branch, set `rust.channel` to \"beta\" in the `config.toml` file HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to `x.py test`", - PATH = inferred_rustfmt_dir.display(), - CHAN = builder.config.channel, + PATH = inferred_rustfmt_dir.display(), + CHAN = builder.config.channel, + ); + crate::exit!(1); + } + let all = false; + crate::core::build_steps::format::format( + builder, + !builder.config.cmd.bless(), + all, + &[], + ); + } else { + eprintln!( + "WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped" ); - crate::exit!(1); } - let all = false; - crate::core::build_steps::format::format(builder, !builder.config.cmd.bless(), all, &[ - ]); } builder.info("tidy check"); From 31c4057bb8edb92671e632e22eec2c14ef19c556 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 5 Dec 2024 10:17:26 +0000 Subject: [PATCH 10/13] handle `json_output` in `test::run_cargo_test` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/test.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 98bfc40fd7a9b..db246b97515e5 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2634,6 +2634,11 @@ fn prepare_cargo_test( if builder.kind == Kind::Test && !builder.fail_fast { cargo.arg("--no-fail-fast"); } + + if builder.config.json_output { + cargo.arg("--message-format=json"); + } + match builder.doc_tests { DocTests::Only => { cargo.arg("--doc"); From cb72b9bb37c53c495baa726bfafaa893fb81396a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 5 Dec 2024 16:57:30 +0000 Subject: [PATCH 11/13] Silence follow-up errors from `lit_to_const` --- compiler/rustc_mir_build/src/thir/constant.rs | 6 +- tests/crashes/123809.rs | 4 -- .../assoc-const-eq-ambiguity.stderr | 4 +- ...ce-hir-wf-check-anon-const-issue-122989.rs | 4 -- ...ir-wf-check-anon-const-issue-122989.stderr | 71 ++----------------- 5 files changed, 11 insertions(+), 78 deletions(-) delete mode 100644 tests/crashes/123809.rs diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 3fa0e4def82e6..30b6718683b67 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -2,7 +2,7 @@ use rustc_ast as ast; use rustc_hir::LangItem; use rustc_middle::bug; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; -use rustc_middle::ty::{self, ScalarInt, TyCtxt}; +use rustc_middle::ty::{self, ScalarInt, TyCtxt, TypeVisitableExt as _}; use tracing::trace; use crate::build::parse_float_into_scalar; @@ -13,6 +13,10 @@ pub(crate) fn lit_to_const<'tcx>( ) -> Result, LitToConstError> { let LitToConstInput { lit, ty, neg } = lit_input; + if let Err(guar) = ty.error_reported() { + return Ok(ty::Const::new_error(tcx, guar)); + } + let trunc = |n| { let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) { Ok(layout) => layout.size, diff --git a/tests/crashes/123809.rs b/tests/crashes/123809.rs deleted file mode 100644 index 75abe6dc0cd83..0000000000000 --- a/tests/crashes/123809.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #123809 -type Positive = std::pat::pattern_type!(std::pat is 0..); - -pub fn main() {} diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr index ba3a870131606..4517610d8e5d5 100644 --- a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr @@ -30,8 +30,8 @@ LL | fn take1(_: impl Trait1) {} = help: consider introducing a new type parameter `T` and adding `where` constraints: where T: Trait1, - T: Parent2::C = "?", - T: Parent1::C = "?" + T: Parent2::C = {const error}, + T: Parent1::C = {const error} error: aborting due to 2 previous errors diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs index a953f1818c580..997bee1e60081 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs @@ -3,15 +3,11 @@ trait Foo> { //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! //~| ERROR cycle detected when computing type of `Foo::N` - //~| ERROR the trait `Foo` cannot be made into an object - //~| ERROR `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter fn func() {} } trait Bar> {} //~^ WARN trait objects without an explicit `dyn` are deprecated //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! -//~| ERROR the trait `Foo` cannot be made into an object -//~| ERROR `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter fn main() {} diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr index f8905437c6ea6..733b729faf07a 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr @@ -13,7 +13,7 @@ LL | trait Foo> { | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:9:20 | LL | trait Bar> {} | ^^^^^^ @@ -32,7 +32,7 @@ LL | trait Foo> { | ^^^^^^^^^^^^^^^ | note: ...which requires computing type of `Bar::M`... - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:9:11 | LL | trait Bar> {} | ^^^^^^^^^^^^^^^ @@ -44,69 +44,6 @@ LL | trait Foo> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:24 - | -LL | trait Foo> { - | ^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8 - | -LL | trait Foo> { - | --- this trait cannot be made into an object... -... -LL | fn func() {} - | ^^^^ ...because associated function `func` has no `self` parameter -help: consider turning `func` into a method by giving it a `&self` argument - | -LL | fn func(&self) {} - | +++++ -help: alternatively, consider constraining `func` so it does not apply to trait objects - | -LL | fn func() where Self: Sized {} - | +++++++++++++++++ - -error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:20 - | -LL | trait Foo> { - | ^^^^^^ - | - = note: the only supported types are integers, `bool`, and `char` - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 - | -LL | trait Bar> {} - | ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object - | -note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8 - | -LL | trait Foo> { - | --- this trait cannot be made into an object... -... -LL | fn func() {} - | ^^^^ ...because associated function `func` has no `self` parameter -help: consider turning `func` into a method by giving it a `&self` argument - | -LL | fn func(&self) {} - | +++++ -help: alternatively, consider constraining `func` so it does not apply to trait objects - | -LL | fn func() where Self: Sized {} - | +++++++++++++++++ - -error: `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 - | -LL | trait Bar> {} - | ^^^^^^ - | - = note: the only supported types are integers, `bool`, and `char` - -error: aborting due to 5 previous errors; 2 warnings emitted +error: aborting due to 1 previous error; 2 warnings emitted -Some errors have detailed explanations: E0038, E0391. -For more information about an error, try `rustc --explain E0038`. +For more information about this error, try `rustc --explain E0391`. From 060cecba1a049225cd83be0802d1583bc02e7422 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 5 Dec 2024 16:57:30 +0000 Subject: [PATCH 12/13] Hide errors whose suggestions would contain error constants or types --- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 3 +++ tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7ab254e5f4b84..3313339abb313 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -998,6 +998,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_const_arg(ct, FeedConstTy::No).into() } }; + if term.references_error() { + continue; + } // FIXME(#97583): This isn't syntactically well-formed! where_bounds.push(format!( " T: {trait}::{assoc_name} = {term}", diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr index 4517610d8e5d5..aa1db4cb032ef 100644 --- a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr @@ -26,12 +26,6 @@ LL | trait Parent2 { const C: &'static str; } LL | LL | fn take1(_: impl Trait1) {} | ^^^^^^^ ambiguous associated constant `C` - | - = help: consider introducing a new type parameter `T` and adding `where` constraints: - where - T: Trait1, - T: Parent2::C = {const error}, - T: Parent1::C = {const error} error: aborting due to 2 previous errors From 85230741c7232819a01c71d158a7b763c39aeaaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20D=C3=B6nszelmann?= Date: Fri, 6 Dec 2024 14:01:45 +0100 Subject: [PATCH 13/13] remove eq for attributes --- src/librustdoc/clean/types.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 715bf68374a5f..cba947eb833b2 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1241,19 +1241,6 @@ impl Attributes { } } -impl PartialEq for Attributes { - fn eq(&self, rhs: &Self) -> bool { - self.doc_strings == rhs.doc_strings - && self - .other_attrs - .iter() - .map(|attr| attr.id) - .eq(rhs.other_attrs.iter().map(|attr| attr.id)) - } -} - -impl Eq for Attributes {} - #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub(crate) enum GenericBound { TraitBound(PolyTrait, hir::TraitBoundModifiers),