From 05c1e6b1db11d3be8c5d554bbc4ce06574ddcf36 Mon Sep 17 00:00:00 2001 From: Gibby Free Date: Wed, 1 Mar 2023 18:56:29 -0800 Subject: [PATCH 01/32] stabilize debugger visualizer attribute --- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/active.rs | 2 -- compiler/rustc_feature/src/builtin_attrs.rs | 12 ++++++------ .../dependency-with-embedded-visualizers.rs | 2 +- tests/debuginfo/embedded-visualizer.rs | 2 +- .../feature-gate-debugger-visualizer.rs | 3 --- .../feature-gate-debugger-visualizer.stderr | 12 ------------ .../ui/invalid/invalid-debugger-visualizer-option.rs | 2 +- .../ui/invalid/invalid-debugger-visualizer-target.rs | 2 +- 9 files changed, 12 insertions(+), 27 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-debugger-visualizer.rs delete mode 100644 tests/ui/feature-gates/feature-gate-debugger-visualizer.stderr diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 761f1ebdbacae..8a442c310c8c8 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -130,6 +130,8 @@ declare_features! ( (accepted, copy_closures, "1.26.0", Some(44490), None), /// Allows `crate` in paths. (accepted, crate_in_paths, "1.30.0", Some(45477), None), + /// Allows using `#[debugger_visualizer]` attribute. + (accepted, debugger_visualizer, "CURRENT_RUSTC_VERSION", Some(95939), None), /// Allows rustc to inject a default alloc_error_handler (accepted, default_alloc_error_handler, "1.68.0", Some(66741), None), /// Allows using assigning a default type to type parameters in algebraic data type definitions. diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index adc06d9aa108a..ebb96c4a28cc7 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -364,8 +364,6 @@ declare_features! ( (active, custom_inner_attributes, "1.30.0", Some(54726), None), /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`. (active, custom_test_frameworks, "1.30.0", Some(50297), None), - /// Allows using `#[debugger_visualizer]`. - (active, debugger_visualizer, "1.62.0", Some(95939), None), /// Allows declarative macros 2.0 (`macro`). (active, decl_macro, "1.17.0", Some(39412), None), /// Allows default type parameters to influence type inference. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 493a9cd89e3b6..fc919daeeca07 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -403,16 +403,16 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk ), + // Debugging + ungated!( + debugger_visualizer, Normal, + template!(List: r#"natvis_file = "...", gdb_script_file = "...""#), DuplicatesOk + ), + // ========================================================================== // Unstable attributes: // ========================================================================== - // RFC #3191: #[debugger_visualizer] support - gated!( - debugger_visualizer, Normal, template!(List: r#"natvis_file = "...", gdb_script_file = "...""#), - DuplicatesOk, experimental!(debugger_visualizer) - ), - // Linking: gated!( naked, Normal, template!(Word), WarnFollowing, @only_local: true, diff --git a/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.rs b/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.rs index 327515b10afd1..4082d98593fd4 100644 --- a/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.rs +++ b/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.rs @@ -2,7 +2,7 @@ // ignore-lldb // no-prefer-dynamic -#![feature(debugger_visualizer)] +#![cfg_attr(bootstrap, feature(debugger_visualizer))] #![debugger_visualizer(natvis_file = "dependency-with-embedded-visualizers.natvis")] #![debugger_visualizer(gdb_script_file = "dependency-with-embedded-visualizers.py")] #![crate_type = "rlib"] diff --git a/tests/debuginfo/embedded-visualizer.rs b/tests/debuginfo/embedded-visualizer.rs index 2898e75e0ee36..b6500aec49355 100644 --- a/tests/debuginfo/embedded-visualizer.rs +++ b/tests/debuginfo/embedded-visualizer.rs @@ -60,7 +60,7 @@ // gdb-check:$4 = "Person A" is 10 years old. #![allow(unused_variables)] -#![feature(debugger_visualizer)] +#![cfg_attr(bootstrap, feature(debugger_visualizer))] #![debugger_visualizer(natvis_file = "embedded-visualizer.natvis")] #![debugger_visualizer(gdb_script_file = "embedded-visualizer.py")] diff --git a/tests/ui/feature-gates/feature-gate-debugger-visualizer.rs b/tests/ui/feature-gates/feature-gate-debugger-visualizer.rs deleted file mode 100644 index 4c4dc450d18bc..0000000000000 --- a/tests/ui/feature-gates/feature-gate-debugger-visualizer.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![debugger_visualizer(natvis_file = "auxiliary/debugger-visualizer.natvis")] //~ ERROR the `#[debugger_visualizer]` attribute is an experimental feature - -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-debugger-visualizer.stderr b/tests/ui/feature-gates/feature-gate-debugger-visualizer.stderr deleted file mode 100644 index e9367fbc6c96c..0000000000000 --- a/tests/ui/feature-gates/feature-gate-debugger-visualizer.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: the `#[debugger_visualizer]` attribute is an experimental feature - --> $DIR/feature-gate-debugger-visualizer.rs:1:1 - | -LL | #![debugger_visualizer(natvis_file = "auxiliary/debugger-visualizer.natvis")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #95939 for more information - = help: add `#![feature(debugger_visualizer)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/invalid/invalid-debugger-visualizer-option.rs b/tests/ui/invalid/invalid-debugger-visualizer-option.rs index 5645a30ccee7d..bf549cbe9624d 100644 --- a/tests/ui/invalid/invalid-debugger-visualizer-option.rs +++ b/tests/ui/invalid/invalid-debugger-visualizer-option.rs @@ -1,7 +1,7 @@ // normalize-stderr-test: "foo.random:.*\(" -> "foo.random: $$FILE_NOT_FOUND_MSG (" // normalize-stderr-test: "os error \d+" -> "os error $$FILE_NOT_FOUND_CODE" -#![feature(debugger_visualizer)] +#![cfg_attr(bootstrap, feature(debugger_visualizer))] #![debugger_visualizer(random_file = "../foo.random")] //~ ERROR invalid argument #![debugger_visualizer(natvis_file = "../foo.random")] //~ ERROR fn main() {} diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.rs b/tests/ui/invalid/invalid-debugger-visualizer-target.rs index f0aba6a75c4cb..44378872b68ec 100644 --- a/tests/ui/invalid/invalid-debugger-visualizer-target.rs +++ b/tests/ui/invalid/invalid-debugger-visualizer-target.rs @@ -1,4 +1,4 @@ -#![feature(debugger_visualizer)] +#![cfg_attr(bootstrap, feature(debugger_visualizer))] #[debugger_visualizer(natvis_file = "../foo.natvis")] //~ ERROR attribute should be applied to a module fn main() {} From 5c34f7788fbfb3ab281f93d09a4599c2e8cd7b8e Mon Sep 17 00:00:00 2001 From: Gibby Free Date: Thu, 2 Mar 2023 10:41:08 -0800 Subject: [PATCH 02/32] whitespace, delete unstable book page --- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- .../language-features/debugger-visualizer.md | 27 ------------------- 2 files changed, 1 insertion(+), 28 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/debugger-visualizer.md diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index fc919daeeca07..34c9af2ac6bc2 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -405,7 +405,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Debugging ungated!( - debugger_visualizer, Normal, + debugger_visualizer, Normal, template!(List: r#"natvis_file = "...", gdb_script_file = "...""#), DuplicatesOk ), diff --git a/src/doc/unstable-book/src/language-features/debugger-visualizer.md b/src/doc/unstable-book/src/language-features/debugger-visualizer.md deleted file mode 100644 index c7a0414b67602..0000000000000 --- a/src/doc/unstable-book/src/language-features/debugger-visualizer.md +++ /dev/null @@ -1,27 +0,0 @@ -# `debugger_visualizer` - -The tracking issue for this feature is: [#95939] - -[#95939]: https://github.com/rust-lang/rust/issues/95939 - ------------------------- - -The `debugger_visualizer` attribute can be used to instruct the compiler -to embed a debugger visualizer file into the PDB/ELF generated by `rustc`. - -## Examples - -``` rust,ignore (partial-example) -#![feature(debugger_visualizer)] -#![debugger_visualizer(natvis_file = "foo.natvis")] -#![debugger_visualizer(gdb_script_file = "foo.py")] -struct Foo { - -} -``` - -## Limitations - -Currently, this feature only supports embedding Natvis files on `-windows-msvc` -targets via the `natvis_file` meta item. `-windows-gnu` targets are not currently -supported. From 45104397e5541b76e281ed9b72cb0a89a4c850eb Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Tue, 29 Nov 2022 21:02:11 +0100 Subject: [PATCH 03/32] Refactor core::char::EscapeDefault and co. structures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change core::char::{EscapeUnicode, EscapeDefault and EscapeDebug} structures from using a state machine to computing escaped sequence upfront and during iteration just going through the characters. This is arguably simpler since it’s easier to think about having a buffer and start..end range to iterate over rather than thinking about a state machine. This also harmonises implementation of aforementioned iterators and core::ascii::EscapeDefault struct. This is done by introducing a new helper EscapeIterInner struct which holds the buffer and offers simple methods for iterating over range. As a side effect, this probably optimises Display implementation for those types since rather than calling write_char repeatedly, write_str is invoked once. On 64-bit platforms, it also reduces size of some of the structs: | Struct | Before | After | |----------------------------+--------+-------+ | core::char::EscapeUnicode | 16 | 12 | | core::char::EscapeDefault | 16 | 12 | | core::char::EscapeDebug | 16 | 16 | My ulterior motive and reason why I started looking into this is addition of as_str method to the iterators. With this change this will became trivial. It’s also going to be trivial to implement DoubleEndedIterator if that’s ever desired. --- library/core/src/ascii.rs | 71 +++++---- library/core/src/char/methods.rs | 57 +++---- library/core/src/char/mod.rs | 251 ++++++++++++++----------------- library/core/src/escape.rs | 97 ++++++++++++ library/core/src/lib.rs | 1 + 5 files changed, 271 insertions(+), 206 deletions(-) create mode 100644 library/core/src/escape.rs diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index 8a4cb78cc7f92..065f1b3e70e68 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -9,10 +9,10 @@ #![stable(feature = "core_ascii", since = "1.26.0")] +use crate::escape; use crate::fmt; use crate::iter::FusedIterator; -use crate::ops::Range; -use crate::str::from_utf8_unchecked; +use crate::num::NonZeroUsize; /// An iterator over the escaped version of a byte. /// @@ -21,10 +21,7 @@ use crate::str::from_utf8_unchecked; #[must_use = "iterators are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] -pub struct EscapeDefault { - range: Range, - data: [u8; 4], -} +pub struct EscapeDefault(escape::EscapeIterInner<4>); /// Returns an iterator that produces an escaped version of a `u8`. /// @@ -90,21 +87,9 @@ pub struct EscapeDefault { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn escape_default(c: u8) -> EscapeDefault { - let (data, len) = match c { - b'\t' => ([b'\\', b't', 0, 0], 2), - b'\r' => ([b'\\', b'r', 0, 0], 2), - b'\n' => ([b'\\', b'n', 0, 0], 2), - b'\\' => ([b'\\', b'\\', 0, 0], 2), - b'\'' => ([b'\\', b'\'', 0, 0], 2), - b'"' => ([b'\\', b'"', 0, 0], 2), - b'\x20'..=b'\x7e' => ([c, 0, 0, 0], 1), - _ => { - let hex_digits: &[u8; 16] = b"0123456789abcdef"; - ([b'\\', b'x', hex_digits[(c >> 4) as usize], hex_digits[(c & 0xf) as usize]], 4) - } - }; - - return EscapeDefault { range: 0..len, data }; + let mut data = [0; 4]; + let range = escape::escape_ascii_into(&mut data, c); + EscapeDefault(escape::EscapeIterInner::new(data, range)) } #[stable(feature = "rust1", since = "1.0.0")] @@ -113,33 +98,59 @@ impl Iterator for EscapeDefault { #[inline] fn next(&mut self) -> Option { - self.range.next().map(|i| self.data[i as usize]) + self.0.next() } + + #[inline] fn size_hint(&self) -> (usize, Option) { - self.range.size_hint() + let n = self.0.len(); + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.0.len() } + + #[inline] fn last(mut self) -> Option { - self.next_back() + self.0.next_back() + } + + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.0.advance_by(n) } } + #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for EscapeDefault { + #[inline] fn next_back(&mut self) -> Option { - self.range.next_back().map(|i| self.data[i as usize]) + self.0.next_back() + } + + #[inline] + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.0.advance_back_by(n) } } + #[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for EscapeDefault {} +impl ExactSizeIterator for EscapeDefault { + #[inline] + fn len(&self) -> usize { + self.0.len() + } +} + #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDefault {} #[stable(feature = "ascii_escape_display", since = "1.39.0")] impl fmt::Display for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // SAFETY: ok because `escape_default` created only valid utf-8 data - f.write_str(unsafe { - from_utf8_unchecked(&self.data[(self.range.start as usize)..(self.range.end as usize)]) - }) + f.write_str(self.0.as_str()) } } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 9bc97ea0bff18..8f149a9ece2ae 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -380,20 +380,7 @@ impl char { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn escape_unicode(self) -> EscapeUnicode { - let c = self as u32; - - // or-ing 1 ensures that for c==0 the code computes that one - // digit should be printed and (which is the same) avoids the - // (31 - 32) underflow - let msb = 31 - (c | 1).leading_zeros(); - - // the index of the most significant hex digit - let ms_hex_digit = msb / 4; - EscapeUnicode { - c: self, - state: EscapeUnicodeState::Backslash, - hex_digit_idx: ms_hex_digit as usize, - } + EscapeUnicode::new(self) } /// An extended version of `escape_debug` that optionally permits escaping @@ -403,21 +390,20 @@ impl char { /// characters, and double quotes in strings. #[inline] pub(crate) fn escape_debug_ext(self, args: EscapeDebugExtArgs) -> EscapeDebug { - let init_state = match self { - '\0' => EscapeDefaultState::Backslash('0'), - '\t' => EscapeDefaultState::Backslash('t'), - '\r' => EscapeDefaultState::Backslash('r'), - '\n' => EscapeDefaultState::Backslash('n'), - '\\' => EscapeDefaultState::Backslash(self), - '"' if args.escape_double_quote => EscapeDefaultState::Backslash(self), - '\'' if args.escape_single_quote => EscapeDefaultState::Backslash(self), + match self { + '\0' => EscapeDebug::backslash(b'0'), + '\t' => EscapeDebug::backslash(b't'), + '\r' => EscapeDebug::backslash(b'r'), + '\n' => EscapeDebug::backslash(b'n'), + '\\' => EscapeDebug::backslash(self as u8), + '"' if args.escape_double_quote => EscapeDebug::backslash(self as u8), + '\'' if args.escape_single_quote => EscapeDebug::backslash(self as u8), _ if args.escape_grapheme_extended && self.is_grapheme_extended() => { - EscapeDefaultState::Unicode(self.escape_unicode()) + EscapeDebug::from_unicode(self.escape_unicode()) } - _ if is_printable(self) => EscapeDefaultState::Char(self), - _ => EscapeDefaultState::Unicode(self.escape_unicode()), - }; - EscapeDebug(EscapeDefault { state: init_state }) + _ if is_printable(self) => EscapeDebug::printable(self), + _ => EscapeDebug::from_unicode(self.escape_unicode()), + } } /// Returns an iterator that yields the literal escape code of a character @@ -515,15 +501,14 @@ impl char { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn escape_default(self) -> EscapeDefault { - let init_state = match self { - '\t' => EscapeDefaultState::Backslash('t'), - '\r' => EscapeDefaultState::Backslash('r'), - '\n' => EscapeDefaultState::Backslash('n'), - '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self), - '\x20'..='\x7e' => EscapeDefaultState::Char(self), - _ => EscapeDefaultState::Unicode(self.escape_unicode()), - }; - EscapeDefault { state: init_state } + match self { + '\t' => EscapeDefault::backslash(b't'), + '\r' => EscapeDefault::backslash(b'r'), + '\n' => EscapeDefault::backslash(b'n'), + '\\' | '\'' | '"' => EscapeDefault::backslash(self as u8), + '\x20'..='\x7e' => EscapeDefault::printable(self as u8), + _ => EscapeDefault::from_unicode(self.escape_unicode()), + } } /// Returns the number of bytes this `char` would need if encoded in UTF-8. diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 8ec78e88733cf..6383a5b5ca960 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -39,8 +39,10 @@ pub use self::methods::encode_utf16_raw; pub use self::methods::encode_utf8_raw; use crate::error::Error; +use crate::escape; use crate::fmt::{self, Write}; use crate::iter::FusedIterator; +use crate::num::NonZeroUsize; pub(crate) use self::methods::EscapeDebugExtArgs; @@ -146,86 +148,44 @@ pub const fn from_digit(num: u32, radix: u32) -> Option { /// [`escape_unicode`]: char::escape_unicode #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct EscapeUnicode { - c: char, - state: EscapeUnicodeState, - - // The index of the next hex digit to be printed (0 if none), - // i.e., the number of remaining hex digits to be printed; - // increasing from the least significant digit: 0x543210 - hex_digit_idx: usize, -} +pub struct EscapeUnicode(escape::EscapeIterInner<10>); -// The enum values are ordered so that their representation is the -// same as the remaining length (besides the hexadecimal digits). This -// likely makes `len()` a single load from memory) and inline-worth. -#[derive(Clone, Debug)] -enum EscapeUnicodeState { - Done, - RightBrace, - Value, - LeftBrace, - Type, - Backslash, +impl EscapeUnicode { + fn new(chr: char) -> Self { + let mut data = [0; 10]; + let range = escape::escape_unicode_into(&mut data, chr); + Self(escape::EscapeIterInner::new(data, range)) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for EscapeUnicode { type Item = char; + #[inline] fn next(&mut self) -> Option { - match self.state { - EscapeUnicodeState::Backslash => { - self.state = EscapeUnicodeState::Type; - Some('\\') - } - EscapeUnicodeState::Type => { - self.state = EscapeUnicodeState::LeftBrace; - Some('u') - } - EscapeUnicodeState::LeftBrace => { - self.state = EscapeUnicodeState::Value; - Some('{') - } - EscapeUnicodeState::Value => { - let hex_digit = ((self.c as u32) >> (self.hex_digit_idx * 4)) & 0xf; - let c = char::from_digit(hex_digit, 16).unwrap(); - if self.hex_digit_idx == 0 { - self.state = EscapeUnicodeState::RightBrace; - } else { - self.hex_digit_idx -= 1; - } - Some(c) - } - EscapeUnicodeState::RightBrace => { - self.state = EscapeUnicodeState::Done; - Some('}') - } - EscapeUnicodeState::Done => None, - } + self.0.next().map(char::from) } #[inline] fn size_hint(&self) -> (usize, Option) { - let n = self.len(); + let n = self.0.len(); (n, Some(n)) } #[inline] fn count(self) -> usize { - self.len() + self.0.len() } - fn last(self) -> Option { - match self.state { - EscapeUnicodeState::Done => None, + #[inline] + fn last(mut self) -> Option { + self.0.next_back().map(char::from) + } - EscapeUnicodeState::RightBrace - | EscapeUnicodeState::Value - | EscapeUnicodeState::LeftBrace - | EscapeUnicodeState::Type - | EscapeUnicodeState::Backslash => Some('}'), - } + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.0.advance_by(n) } } @@ -233,16 +193,7 @@ impl Iterator for EscapeUnicode { impl ExactSizeIterator for EscapeUnicode { #[inline] fn len(&self) -> usize { - // The match is a single memory access with no branching - self.hex_digit_idx - + match self.state { - EscapeUnicodeState::Done => 0, - EscapeUnicodeState::RightBrace => 1, - EscapeUnicodeState::Value => 2, - EscapeUnicodeState::LeftBrace => 3, - EscapeUnicodeState::Type => 4, - EscapeUnicodeState::Backslash => 5, - } + self.0.len() } } @@ -252,10 +203,7 @@ impl FusedIterator for EscapeUnicode {} #[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for EscapeUnicode { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for c in self.clone() { - f.write_char(c)?; - } - Ok(()) + f.write_str(self.0.as_str()) } } @@ -267,90 +215,60 @@ impl fmt::Display for EscapeUnicode { /// [`escape_default`]: char::escape_default #[derive(Clone, Debug)] #[stable(feature = "rust1", since = "1.0.0")] -pub struct EscapeDefault { - state: EscapeDefaultState, -} +pub struct EscapeDefault(escape::EscapeIterInner<10>); -#[derive(Clone, Debug)] -enum EscapeDefaultState { - Done, - Char(char), - Backslash(char), - Unicode(EscapeUnicode), +impl EscapeDefault { + fn printable(chr: u8) -> Self { + let data = [chr, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + Self(escape::EscapeIterInner::new(data, 0..1)) + } + + fn backslash(chr: u8) -> Self { + let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0]; + Self(escape::EscapeIterInner::new(data, 0..2)) + } + + fn from_unicode(esc: EscapeUnicode) -> Self { + Self(esc.0) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for EscapeDefault { type Item = char; + #[inline] fn next(&mut self) -> Option { - match self.state { - EscapeDefaultState::Backslash(c) => { - self.state = EscapeDefaultState::Char(c); - Some('\\') - } - EscapeDefaultState::Char(c) => { - self.state = EscapeDefaultState::Done; - Some(c) - } - EscapeDefaultState::Done => None, - EscapeDefaultState::Unicode(ref mut iter) => iter.next(), - } + self.0.next().map(char::from) } #[inline] fn size_hint(&self) -> (usize, Option) { - let n = self.len(); + let n = self.0.len(); (n, Some(n)) } #[inline] fn count(self) -> usize { - self.len() + self.0.len() } - fn nth(&mut self, n: usize) -> Option { - match self.state { - EscapeDefaultState::Backslash(c) if n == 0 => { - self.state = EscapeDefaultState::Char(c); - Some('\\') - } - EscapeDefaultState::Backslash(c) if n == 1 => { - self.state = EscapeDefaultState::Done; - Some(c) - } - EscapeDefaultState::Backslash(_) => { - self.state = EscapeDefaultState::Done; - None - } - EscapeDefaultState::Char(c) => { - self.state = EscapeDefaultState::Done; - - if n == 0 { Some(c) } else { None } - } - EscapeDefaultState::Done => None, - EscapeDefaultState::Unicode(ref mut i) => i.nth(n), - } + #[inline] + fn last(mut self) -> Option { + self.0.next_back().map(char::from) } - fn last(self) -> Option { - match self.state { - EscapeDefaultState::Unicode(iter) => iter.last(), - EscapeDefaultState::Done => None, - EscapeDefaultState::Backslash(c) | EscapeDefaultState::Char(c) => Some(c), - } + #[inline] + fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.0.advance_by(n) } } #[stable(feature = "exact_size_escape", since = "1.11.0")] impl ExactSizeIterator for EscapeDefault { + #[inline] fn len(&self) -> usize { - match self.state { - EscapeDefaultState::Done => 0, - EscapeDefaultState::Char(_) => 1, - EscapeDefaultState::Backslash(_) => 2, - EscapeDefaultState::Unicode(ref iter) => iter.len(), - } + self.0.len() } } @@ -360,10 +278,7 @@ impl FusedIterator for EscapeDefault {} #[stable(feature = "char_struct_display", since = "1.16.0")] impl fmt::Display for EscapeDefault { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for c in self.clone() { - f.write_char(c)?; - } - Ok(()) + f.write_str(self.0.as_str()) } } @@ -375,21 +290,74 @@ impl fmt::Display for EscapeDefault { /// [`escape_debug`]: char::escape_debug #[stable(feature = "char_escape_debug", since = "1.20.0")] #[derive(Clone, Debug)] -pub struct EscapeDebug(EscapeDefault); +pub struct EscapeDebug(EscapeDebugInner); + +#[derive(Clone, Debug)] +enum EscapeDebugInner { + Bytes(escape::EscapeIterInner<10>), + Char(char), +} + +impl EscapeDebug { + fn printable(chr: char) -> Self { + // Note: It’s possible to manually encode the EscapeDebugInner inside of + // EscapeIterInner (e.g. with alive=254..255 indicating that data[0..4] + // holds a char) which would likely result in a more optimised code. + // For now we use the option easier to implement. + Self(EscapeDebugInner::Char(chr)) + } + + fn backslash(chr: u8) -> Self { + let data = [b'\\', chr, 0, 0, 0, 0, 0, 0, 0, 0]; + let iter = escape::EscapeIterInner::new(data, 0..2); + Self(EscapeDebugInner::Bytes(iter)) + } + + fn from_unicode(esc: EscapeUnicode) -> Self { + Self(EscapeDebugInner::Bytes(esc.0)) + } + + fn clear(&mut self) { + let bytes = escape::EscapeIterInner::new([0; 10], 0..0); + self.0 = EscapeDebugInner::Bytes(bytes); + } +} #[stable(feature = "char_escape_debug", since = "1.20.0")] impl Iterator for EscapeDebug { type Item = char; + + #[inline] fn next(&mut self) -> Option { - self.0.next() + match self.0 { + EscapeDebugInner::Bytes(ref mut bytes) => bytes.next().map(char::from), + EscapeDebugInner::Char(chr) => { + self.clear(); + Some(chr) + } + } } + fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() + let n = self.len(); + (n, Some(n)) + } + + #[inline] + fn count(self) -> usize { + self.len() } } #[stable(feature = "char_escape_debug", since = "1.20.0")] -impl ExactSizeIterator for EscapeDebug {} +impl ExactSizeIterator for EscapeDebug { + fn len(&self) -> usize { + match &self.0 { + EscapeDebugInner::Bytes(bytes) => bytes.len(), + EscapeDebugInner::Char(_) => 1, + } + } +} #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDebug {} @@ -397,7 +365,10 @@ impl FusedIterator for EscapeDebug {} #[stable(feature = "char_escape_debug", since = "1.20.0")] impl fmt::Display for EscapeDebug { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.0, f) + match &self.0 { + EscapeDebugInner::Bytes(bytes) => f.write_str(bytes.as_str()), + EscapeDebugInner::Char(chr) => f.write_char(*chr), + } } } diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs new file mode 100644 index 0000000000000..66faa0316d1e5 --- /dev/null +++ b/library/core/src/escape.rs @@ -0,0 +1,97 @@ +//! Helper code for character escaping. + +use crate::num::NonZeroUsize; +use crate::ops::Range; + +const HEX_DIGITS: [u8; 16] = *b"0123456789abcdef"; + +/// Escapes a byte into provided buffer; returns length of escaped +/// representation. +pub(super) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range { + let (data, len) = match byte { + b'\t' => ([b'\\', b't', 0, 0], 2), + b'\r' => ([b'\\', b'r', 0, 0], 2), + b'\n' => ([b'\\', b'n', 0, 0], 2), + b'\\' => ([b'\\', b'\\', 0, 0], 2), + b'\'' => ([b'\\', b'\'', 0, 0], 2), + b'"' => ([b'\\', b'"', 0, 0], 2), + b'\x20'..=b'\x7e' => ([byte, 0, 0, 0], 1), + _ => { + ([b'\\', b'x', HEX_DIGITS[(byte >> 4) as usize], HEX_DIGITS[(byte & 0xf) as usize]], 4) + } + }; + *output = data; + 0..(len as u8) +} + +/// Escapes a character into provided buffer using `\u{NNNN}` representation. +pub(super) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range { + let ch = (ch as u32) & 0x1f_ffff; + + output[9] = b'}'; + + output[3] = HEX_DIGITS[((ch >> 20) & 15) as usize]; + output[4] = HEX_DIGITS[((ch >> 16) & 15) as usize]; + output[5] = HEX_DIGITS[((ch >> 12) & 15) as usize]; + output[6] = HEX_DIGITS[((ch >> 8) & 15) as usize]; + output[7] = HEX_DIGITS[((ch >> 4) & 15) as usize]; + output[8] = HEX_DIGITS[((ch >> 0) & 15) as usize]; + + // or-ing 1 ensures that for ch==0 the code computes that one digit should + // be printed. + let start = (ch | 1).leading_zeros() as usize / 4 - 2; + output[start..start + 3].copy_from_slice(b"\\u{"); + + (start as u8)..10 +} + +/// An iterator over an fixed-size array. +/// +/// This is essentially equivalent to array’s IntoIter except that indexes are +/// limited to u8 to reduce size of the structure. +#[derive(Clone, Debug)] +pub(super) struct EscapeIterInner { + // Invariant: data[alive] is all ASCII. + pub(super) data: [u8; N], + + // Invariant: alive.start <= alive.end <= N. + pub(super) alive: Range, +} + +impl EscapeIterInner { + pub fn new(data: [u8; N], alive: Range) -> Self { + debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}"); + let this = Self { data, alive }; + debug_assert!(this.as_bytes().is_ascii(), "Expected ASCII, got {:?}", this.as_bytes()); + this + } + + fn as_bytes(&self) -> &[u8] { + &self.data[(self.alive.start as usize)..(self.alive.end as usize)] + } + + pub fn as_str(&self) -> &str { + // SAFETY: self.data[self.alive] is all ASCII characters. + unsafe { crate::str::from_utf8_unchecked(self.as_bytes()) } + } + + pub fn len(&self) -> usize { + usize::from(self.alive.end - self.alive.start) + } + + pub fn next(&mut self) -> Option { + self.alive.next().map(|i| self.data[usize::from(i)]) + } + + pub fn next_back(&mut self) -> Option { + self.alive.next_back().map(|i| self.data[usize::from(i)]) + } + + pub fn advance_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.alive.advance_by(n) + } + + pub fn advance_back_by(&mut self, n: usize) -> Result<(), NonZeroUsize> { + self.alive.advance_back_by(n) + } +} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index a6b9acb576eb4..8842f92459bb3 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -381,6 +381,7 @@ pub mod alloc; // note: does not need to be public mod bool; +mod escape; mod tuple; mod unit; From be413ae527c7b9da1669538abc429fd41f7c57ba Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Thu, 27 Apr 2023 18:21:14 +0530 Subject: [PATCH 04/32] Remove all in target_thread_local cfg I think it was left there by mistake after previous refactoring. Signed-off-by: Ayush Singh --- library/std/src/sys/common/thread_local/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/common/thread_local/mod.rs b/library/std/src/sys/common/thread_local/mod.rs index a7528c06c9de2..951d509ec9533 100644 --- a/library/std/src/sys/common/thread_local/mod.rs +++ b/library/std/src/sys/common/thread_local/mod.rs @@ -6,7 +6,7 @@ cfg_if::cfg_if! { mod static_local; #[doc(hidden)] pub use static_local::{Key, thread_local_inner}; - } else if #[cfg(all(target_thread_local))] { + } else if #[cfg(target_thread_local)] { #[doc(hidden)] mod fast_local; #[doc(hidden)] From 518d348f873ac5df4ca43b36145e5556138adad3 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 17 Feb 2023 13:43:38 +0000 Subject: [PATCH 05/32] Implement `StructuralEq` for integers, `bool` and `char` (how did this work before??) --- library/core/src/marker.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index e85c0c0a68890..1d33236c269e5 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -214,6 +214,35 @@ pub trait StructuralEq { // Empty. } +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for usize {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for u8 {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for u16 {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for u32 {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for u64 {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for u128 {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for isize {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for i8 {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for i16 {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for i32 {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for i64 {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for i128 {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for bool {} +#[unstable(feature = "structural_match", issue = "31434")] +impl StructuralEq for char {} + /// Types whose values can be duplicated simply by copying bits. /// /// By default, variable bindings have 'move semantics.' In other From 9a716dafbe3deb97091c5e511c2d893e1f325b07 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 17 Feb 2023 13:44:35 +0000 Subject: [PATCH 06/32] Add a `ConstParamTy` trait --- compiler/rustc_hir/src/lang_items.rs | 2 + compiler/rustc_hir_analysis/messages.ftl | 4 + .../src/coherence/builtin.rs | 255 ++++++++++-------- compiler/rustc_hir_analysis/src/errors.rs | 8 + compiler/rustc_span/src/symbol.rs | 1 + .../rustc_trait_selection/src/traits/misc.rs | 94 +++++-- library/core/src/marker.rs | 34 +++ .../const_patam_ty_impl_bad_field.rs | 12 + .../const_patam_ty_impl_bad_field.stderr | 12 + 9 files changed, 300 insertions(+), 122 deletions(-) create mode 100644 tests/ui/const-generics/const_patam_ty_impl_bad_field.rs create mode 100644 tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 8f91a96f964ab..e1c030d3e198a 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -293,6 +293,8 @@ language_item_table! { PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0); + ConstParamTy, sym::const_param_ty, const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0); + Poll, sym::Poll, poll, Target::Enum, GenericRequirement::None; PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None; PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None; diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 1d7965ff5f66e..bda9879b5db1a 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -35,6 +35,10 @@ hir_analysis_field_already_declared = hir_analysis_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` +hir_analysis_const_param_ty_impl_on_non_adt = + the trait `ConstParamTy` may not be implemented for this type + .label = type is not a structure or enumeration + hir_analysis_ambiguous_lifetime_bound = ambiguous lifetime bound, explicit lifetime bound required diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 611ce13b739c2..0f450ae67b7a6 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -1,9 +1,11 @@ //! Check properties that are required by built-in traits and set //! up data structures required by type-checking/codegen. -use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem}; +use crate::errors::{ + ConstParamTyImplOnNonAdt, CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem, +}; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, MultiSpan}; +use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; @@ -14,9 +16,11 @@ use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt}; use rustc_infer::traits::Obligation; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt}; +use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::misc::{ - type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason, + type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy, + ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason, }; use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; @@ -27,6 +31,7 @@ pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) { Checker { tcx, trait_def_id } .check(lang_items.drop_trait(), visit_implementation_of_drop) .check(lang_items.copy_trait(), visit_implementation_of_copy) + .check(lang_items.const_param_ty_trait(), visit_implementation_of_const_param_ty) .check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized) .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn); } @@ -83,110 +88,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) { Ok(()) => {} Err(CopyImplementationError::InfringingFields(fields)) => { - let mut err = struct_span_err!( - tcx.sess, - span, - E0204, - "the trait `Copy` cannot be implemented for this type" - ); - - // We'll try to suggest constraining type parameters to fulfill the requirements of - // their `Copy` implementation. - let mut errors: BTreeMap<_, Vec<_>> = Default::default(); - let mut bounds = vec![]; - - let mut seen_tys = FxHashSet::default(); - - for (field, ty, reason) in fields { - // Only report an error once per type. - if !seen_tys.insert(ty) { - continue; - } - - let field_span = tcx.def_span(field.did); - err.span_label(field_span, "this field does not implement `Copy`"); - - match reason { - InfringingFieldsReason::Fulfill(fulfillment_errors) => { - for error in fulfillment_errors { - let error_predicate = error.obligation.predicate; - // Only note if it's not the root obligation, otherwise it's trivial and - // should be self-explanatory (i.e. a field literally doesn't implement Copy). - - // FIXME: This error could be more descriptive, especially if the error_predicate - // contains a foreign type or if it's a deeply nested type... - if error_predicate != error.root_obligation.predicate { - errors - .entry((ty.to_string(), error_predicate.to_string())) - .or_default() - .push(error.obligation.cause.span); - } - if let ty::PredicateKind::Clause(ty::Clause::Trait( - ty::TraitPredicate { - trait_ref, - polarity: ty::ImplPolarity::Positive, - .. - }, - )) = error_predicate.kind().skip_binder() - { - let ty = trait_ref.self_ty(); - if let ty::Param(_) = ty.kind() { - bounds.push(( - format!("{ty}"), - trait_ref.print_only_trait_path().to_string(), - Some(trait_ref.def_id), - )); - } - } - } - } - InfringingFieldsReason::Regions(region_errors) => { - for error in region_errors { - let ty = ty.to_string(); - match error { - RegionResolutionError::ConcreteFailure(origin, a, b) => { - let predicate = format!("{b}: {a}"); - errors - .entry((ty.clone(), predicate.clone())) - .or_default() - .push(origin.span()); - if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() { - bounds.push((b.to_string(), a.to_string(), None)); - } - } - RegionResolutionError::GenericBoundFailure(origin, a, b) => { - let predicate = format!("{a}: {b}"); - errors - .entry((ty.clone(), predicate.clone())) - .or_default() - .push(origin.span()); - if let infer::region_constraints::GenericKind::Param(_) = a { - bounds.push((a.to_string(), b.to_string(), None)); - } - } - _ => continue, - } - } - } - } - } - for ((ty, error_predicate), spans) in errors { - let span: MultiSpan = spans.into(); - err.span_note( - span, - &format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate), - ); - } - suggest_constraining_type_params( - tcx, - tcx.hir().get_generics(impl_did).expect("impls always have generics"), - &mut err, - bounds.iter().map(|(param, constraint, def_id)| { - (param.as_str(), constraint.as_str(), *def_id) - }), - None, - ); - err.emit(); + infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span); } Err(CopyImplementationError::NotAnAdt) => { tcx.sess.emit_err(CopyImplOnNonAdt { span }); @@ -197,6 +99,29 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { } } +fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId) { + let self_type = tcx.type_of(impl_did).subst_identity(); + assert!(!self_type.has_escaping_bound_vars()); + + let param_env = tcx.param_env(impl_did); + + let span = match tcx.hir().expect_item(impl_did).expect_impl() { + hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return, + impl_ => impl_.self_ty.span, + }; + + let cause = traits::ObligationCause::misc(span, impl_did); + match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) { + Ok(()) => {} + Err(ConstParamTyImplementationError::InfrigingFields(fields)) => { + infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span); + } + Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => { + tcx.sess.emit_err(ConstParamTyImplOnNonAdt { span }); + } + } +} + fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'_>, impl_did: LocalDefId) { debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did); @@ -593,3 +518,119 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe CoerceUnsizedInfo { custom_kind: kind } } + +fn infringing_fields_error( + tcx: TyCtxt<'_>, + fields: Vec<(&ty::FieldDef, Ty<'_>, InfringingFieldsReason<'_>)>, + lang_item: LangItem, + impl_did: LocalDefId, + impl_span: Span, +) -> ErrorGuaranteed { + let trait_did = tcx.require_lang_item(lang_item, Some(impl_span)); + + let trait_name = tcx.def_path_str(trait_did); + + let mut err = struct_span_err!( + tcx.sess, + impl_span, + E0204, + "the trait `{trait_name}` cannot be implemented for this type" + ); + + // We'll try to suggest constraining type parameters to fulfill the requirements of + // their `Copy` implementation. + let mut errors: BTreeMap<_, Vec<_>> = Default::default(); + let mut bounds = vec![]; + + let mut seen_tys = FxHashSet::default(); + + for (field, ty, reason) in fields { + // Only report an error once per type. + if !seen_tys.insert(ty) { + continue; + } + + let field_span = tcx.def_span(field.did); + err.span_label(field_span, format!("this field does not implement `{trait_name}`")); + + match reason { + InfringingFieldsReason::Fulfill(fulfillment_errors) => { + for error in fulfillment_errors { + let error_predicate = error.obligation.predicate; + // Only note if it's not the root obligation, otherwise it's trivial and + // should be self-explanatory (i.e. a field literally doesn't implement Copy). + + // FIXME: This error could be more descriptive, especially if the error_predicate + // contains a foreign type or if it's a deeply nested type... + if error_predicate != error.root_obligation.predicate { + errors + .entry((ty.to_string(), error_predicate.to_string())) + .or_default() + .push(error.obligation.cause.span); + } + if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate { + trait_ref, + polarity: ty::ImplPolarity::Positive, + .. + })) = error_predicate.kind().skip_binder() + { + let ty = trait_ref.self_ty(); + if let ty::Param(_) = ty.kind() { + bounds.push(( + format!("{ty}"), + trait_ref.print_only_trait_path().to_string(), + Some(trait_ref.def_id), + )); + } + } + } + } + InfringingFieldsReason::Regions(region_errors) => { + for error in region_errors { + let ty = ty.to_string(); + match error { + RegionResolutionError::ConcreteFailure(origin, a, b) => { + let predicate = format!("{b}: {a}"); + errors + .entry((ty.clone(), predicate.clone())) + .or_default() + .push(origin.span()); + if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() { + bounds.push((b.to_string(), a.to_string(), None)); + } + } + RegionResolutionError::GenericBoundFailure(origin, a, b) => { + let predicate = format!("{a}: {b}"); + errors + .entry((ty.clone(), predicate.clone())) + .or_default() + .push(origin.span()); + if let infer::region_constraints::GenericKind::Param(_) = a { + bounds.push((a.to_string(), b.to_string(), None)); + } + } + _ => continue, + } + } + } + } + } + for ((ty, error_predicate), spans) in errors { + let span: MultiSpan = spans.into(); + err.span_note( + span, + format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"), + ); + } + suggest_constraining_type_params( + tcx, + tcx.hir().get_generics(impl_did).expect("impls always have generics"), + &mut err, + bounds + .iter() + .map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)), + None, + ); + + err.emit() +} diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 2a3a683489ddd..8dcf3b1670dc9 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -107,6 +107,14 @@ pub struct CopyImplOnNonAdt { pub span: Span, } +#[derive(Diagnostic)] +#[diag(hir_analysis_const_param_ty_impl_on_non_adt)] +pub struct ConstParamTyImplOnNonAdt { + #[primary_span] + #[label] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")] pub struct TraitObjectDeclaredWithNoTraits { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 70b9088de5064..d2e23f845144f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -531,6 +531,7 @@ symbols! { const_mut_refs, const_panic, const_panic_fmt, + const_param_ty, const_precise_live_drops, const_raw_ptr_deref, const_raw_ptr_to_usize_cast, diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 63949843aedcd..3c43758e50daa 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -2,13 +2,14 @@ use crate::traits::{self, ObligationCause, ObligationCtxt}; +use hir::LangItem; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::query::NoSolution; use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError}; -use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, AdtDef, GenericArg, List, ParamEnv, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::DUMMY_SP; use super::outlives_bounds::InferCtxtExt; @@ -19,6 +20,11 @@ pub enum CopyImplementationError<'tcx> { HasDestructor, } +pub enum ConstParamTyImplementationError<'tcx> { + InfrigingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>), + NotAnAdtOrBuiltinAllowed, +} + pub enum InfringingFieldsReason<'tcx> { Fulfill(Vec>), Regions(Vec>), @@ -27,7 +33,10 @@ pub enum InfringingFieldsReason<'tcx> { /// Checks that the fields of the type (an ADT) all implement copy. /// /// If fields don't implement copy, return an error containing a list of -/// those violating fields. If it's not an ADT, returns `Err(NotAnAdt)`. +/// those violating fields. +/// +/// If it's not an ADT, int ty, `bool`, float ty, `char`, raw pointer, `!`, +/// a reference or an array returns `Err(NotAnAdt)`. pub fn type_allowed_to_implement_copy<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -47,12 +56,75 @@ pub fn type_allowed_to_implement_copy<'tcx>( | ty::Ref(_, _, hir::Mutability::Not) | ty::Array(..) => return Ok(()), - ty::Adt(adt, substs) => (adt, substs), + &ty::Adt(adt, substs) => (adt, substs), _ => return Err(CopyImplementationError::NotAnAdt), }; - let copy_def_id = tcx.require_lang_item(hir::LangItem::Copy, Some(parent_cause.span)); + all_fields_implement_trait( + tcx, + param_env, + self_type, + adt, + substs, + parent_cause, + hir::LangItem::Copy, + ) + .map_err(CopyImplementationError::InfringingFields)?; + + if adt.has_dtor(tcx) { + return Err(CopyImplementationError::HasDestructor); + } + + Ok(()) +} + +/// Checks that the fields of the type (an ADT) all implement `ConstParamTy`. +/// +/// If fields don't implement `ConstParamTy`, return an error containing a list of +/// those violating fields. +/// +/// If it's not an ADT, int ty, `bool` or `char`, returns `Err(NotAnAdtOrBuiltinAllowed)`. +pub fn type_allowed_to_implement_const_param_ty<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + self_type: Ty<'tcx>, + parent_cause: ObligationCause<'tcx>, +) -> Result<(), ConstParamTyImplementationError<'tcx>> { + let (adt, substs) = match self_type.kind() { + // `core` provides these impls. + ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => return Ok(()), + + &ty::Adt(adt, substs) => (adt, substs), + + _ => return Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed), + }; + + all_fields_implement_trait( + tcx, + param_env, + self_type, + adt, + substs, + parent_cause, + hir::LangItem::Copy, + ) + .map_err(ConstParamTyImplementationError::InfrigingFields)?; + + Ok(()) +} + +/// Check that all fields of a given `adt` implement `lang_item` trait. +pub fn all_fields_implement_trait<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + self_type: Ty<'tcx>, + adt: AdtDef<'tcx>, + substs: &'tcx List>, + parent_cause: ObligationCause<'tcx>, + lang_item: LangItem, +) -> Result<(), Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>> { + let trait_def_id = tcx.require_lang_item(lang_item, Some(parent_cause.span)); let mut infringing = Vec::new(); for variant in adt.variants() { @@ -93,7 +165,7 @@ pub fn type_allowed_to_implement_copy<'tcx>( // between expected and found const-generic types. Don't report an // additional copy error here, since it's not typically useful. if !normalization_errors.is_empty() || ty.references_error() { - tcx.sess.delay_span_bug(field_span, format!("couldn't normalize struct field `{unnormalized_ty}` when checking Copy implementation")); + tcx.sess.delay_span_bug(field_span, format!("couldn't normalize struct field `{unnormalized_ty}` when checking {tr} implementation", tr = tcx.def_path_str(trait_def_id))); continue; } @@ -101,7 +173,7 @@ pub fn type_allowed_to_implement_copy<'tcx>( ObligationCause::dummy_with_span(field_ty_span), param_env, ty, - copy_def_id, + trait_def_id, ); let errors = ocx.select_all_or_error(); if !errors.is_empty() { @@ -124,15 +196,7 @@ pub fn type_allowed_to_implement_copy<'tcx>( } } - if !infringing.is_empty() { - return Err(CopyImplementationError::InfringingFields(infringing)); - } - - if adt.has_dtor(tcx) { - return Err(CopyImplementationError::HasDestructor); - } - - Ok(()) + if infringing.is_empty() { Ok(()) } else { Err(infringing) } } pub fn check_tys_might_be_eq<'tcx>( diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 1d33236c269e5..ff8653c08204a 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -912,6 +912,40 @@ pub trait Tuple {} )] pub trait PointerLike {} +/// A marker for types which can be used as types of `const` generic parameters. +#[cfg_attr(not(bootstrap), lang = "const_param_ty")] +#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] +pub trait ConstParamTy: StructuralEq {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for usize {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for u8 {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for u16 {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for u32 {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for u64 {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for u128 {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for isize {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for i8 {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for i16 {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for i32 {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for i64 {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for i128 {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for bool {} +#[unstable(feature = "const_param_ty_trait", issue = "none")] +impl ConstParamTy for char {} + /// Implementations of `Copy` for primitive types. /// /// Implementations that cannot be described in Rust diff --git a/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs b/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs new file mode 100644 index 0000000000000..37cfa1aa7f537 --- /dev/null +++ b/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs @@ -0,0 +1,12 @@ +#![feature(const_param_ty_trait)] + +#[derive(PartialEq)] +struct NotParam; + +#[derive(PartialEq)] +struct CantParam(NotParam); + +impl std::marker::ConstParamTy for CantParam {} +//~^ error: the trait `ConstParamTy` may not be implemented for this type + +fn main() {} diff --git a/tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr b/tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr new file mode 100644 index 0000000000000..dd150deffc2de --- /dev/null +++ b/tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr @@ -0,0 +1,12 @@ +error[E0204]: the trait `ConstParamTy` may not be implemented for this type + --> $DIR/const_patam_ty_impl_bad_field.rs:9:36 + | +LL | struct CantParam(NotParam); + | -------- this field does not implement `ConstParamTy` +LL | +LL | impl std::marker::ConstParamTy for CantParam {} + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0204`. From c8844e1337f1304d06417a712110abbd3a2beb95 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 22 Feb 2023 17:57:52 +0000 Subject: [PATCH 07/32] `derive(Eq)` in a test --- tests/ui/const-generics/const_patam_ty_impl_bad_field.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs b/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs index 37cfa1aa7f537..2cfccb68b0e90 100644 --- a/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs +++ b/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs @@ -1,9 +1,9 @@ #![feature(const_param_ty_trait)] -#[derive(PartialEq)] +#[derive(PartialEq, Eq)] struct NotParam; -#[derive(PartialEq)] +#[derive(PartialEq, Eq)] struct CantParam(NotParam); impl std::marker::ConstParamTy for CantParam {} From 81a2b856c8e6336f01831108924004f582ad59d0 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 22 Feb 2023 17:59:49 +0000 Subject: [PATCH 08/32] Remove `feature(const_param_ty_trait)`, use `adt_const_params` instead --- library/core/src/marker.rs | 30 +++++++++---------- .../const_patam_ty_impl_bad_field.rs | 3 +- .../const_patam_ty_impl_bad_field.stderr | 2 +- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index ff8653c08204a..24e95aed27ec2 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -914,36 +914,36 @@ pub trait PointerLike {} /// A marker for types which can be used as types of `const` generic parameters. #[cfg_attr(not(bootstrap), lang = "const_param_ty")] -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] pub trait ConstParamTy: StructuralEq {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for usize {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for u8 {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for u16 {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for u32 {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for u64 {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for u128 {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for isize {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for i8 {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for i16 {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for i32 {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for i64 {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for i128 {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for bool {} -#[unstable(feature = "const_param_ty_trait", issue = "none")] +#[unstable(feature = "adt_const_params", issue = "95174")] impl ConstParamTy for char {} /// Implementations of `Copy` for primitive types. diff --git a/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs b/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs index 2cfccb68b0e90..3d2d99b9d38ca 100644 --- a/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs +++ b/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs @@ -1,4 +1,5 @@ -#![feature(const_param_ty_trait)] +#![allow(incomplete_features)] +#![feature(adt_const_params)] #[derive(PartialEq, Eq)] struct NotParam; diff --git a/tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr b/tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr index dd150deffc2de..273845b1668fb 100644 --- a/tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr +++ b/tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `ConstParamTy` may not be implemented for this type - --> $DIR/const_patam_ty_impl_bad_field.rs:9:36 + --> $DIR/const_patam_ty_impl_bad_field.rs:10:36 | LL | struct CantParam(NotParam); | -------- this field does not implement `ConstParamTy` From c45c4f2cb13968722ae15f76c70fe598c73698fb Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 22 Feb 2023 18:11:47 +0000 Subject: [PATCH 09/32] Rename/move a test --- .../const_param_ty_impl_bad_field.rs} | 0 .../const_param_ty_impl_bad_field.stderr} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/ui/const-generics/{const_patam_ty_impl_bad_field.rs => adt_const_params/const_param_ty_impl_bad_field.rs} (100%) rename tests/ui/const-generics/{const_patam_ty_impl_bad_field.stderr => adt_const_params/const_param_ty_impl_bad_field.stderr} (89%) diff --git a/tests/ui/const-generics/const_patam_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs similarity index 100% rename from tests/ui/const-generics/const_patam_ty_impl_bad_field.rs rename to tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs diff --git a/tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr similarity index 89% rename from tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr rename to tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr index 273845b1668fb..5cd5cae6d79dd 100644 --- a/tests/ui/const-generics/const_patam_ty_impl_bad_field.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `ConstParamTy` may not be implemented for this type - --> $DIR/const_patam_ty_impl_bad_field.rs:10:36 + --> $DIR/const_param_ty_impl_bad_field.rs:10:36 | LL | struct CantParam(NotParam); | -------- this field does not implement `ConstParamTy` From 1c544108b1e10124b3a9f45a68c1cb36c1c45e90 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 23 Feb 2023 11:54:09 +0000 Subject: [PATCH 10/32] Check the correct trait when checking `ConstParamTy` impls --- compiler/rustc_trait_selection/src/traits/misc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 3c43758e50daa..cb8f64dd2e8cf 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -107,7 +107,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>( adt, substs, parent_cause, - hir::LangItem::Copy, + hir::LangItem::ConstParamTy, ) .map_err(ConstParamTyImplementationError::InfrigingFields)?; From 7234d63ea4880c62fa2ed0078c465cc07bbbb289 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 23 Feb 2023 12:00:34 +0000 Subject: [PATCH 11/32] Add `!StructuralEq` test for `ConstParamTy` --- .../const_param_ty_impl_no_structural_eq.rs | 17 +++++++++++++++++ .../const_param_ty_impl_no_structural_eq.stderr | 12 ++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs create mode 100644 tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs new file mode 100644 index 0000000000000..17ef396164efd --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs @@ -0,0 +1,17 @@ +#![allow(incomplete_features)] +#![feature(adt_const_params)] + +#[derive(PartialEq, Eq)] +struct ImplementsConstParamTy; +impl std::marker::ConstParamTy for ImplementsConstParamTy {} + +struct CantParam(ImplementsConstParamTy); + +impl std::marker::ConstParamTy for CantParam {} +//~^ error: the type `CantParam` does not `#[derive(Eq)]` + +fn check() {} + +fn main() { + check::(); +} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr new file mode 100644 index 0000000000000..ca5abf5e25420 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr @@ -0,0 +1,12 @@ +error[E0277]: the type `CantParam` does not `#[derive(Eq)]` + --> $DIR/const_param_ty_impl_no_structural_eq.rs:10:36 + | +LL | impl std::marker::ConstParamTy for CantParam {} + | ^^^^^^^^^ the trait `StructuralEq` is not implemented for `CantParam` + | +note: required by a bound in `ConstParamTy` + --> $SRC_DIR/core/src/marker.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 2205c3fa5ffdb8794917d541e580742f527be8f1 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 3 Mar 2023 11:29:21 +0000 Subject: [PATCH 12/32] Add a macro to conveniently implement marker traits --- library/core/src/lib.rs | 1 + library/core/src/marker.rs | 221 +++++++++++++++++++------------------ 2 files changed, 114 insertions(+), 108 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 24a9d81d03784..b269a3bcb000e 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -162,6 +162,7 @@ #![feature(const_waker)] #![feature(core_panic)] #![feature(duration_consts_float)] +#![feature(internal_impls_macro)] #![feature(ip)] #![feature(is_ascii_octdigit)] #![feature(maybe_uninit_uninit_array)] diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 24e95aed27ec2..8c240661b2b44 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -12,6 +12,60 @@ use crate::fmt::Debug; use crate::hash::Hash; use crate::hash::Hasher; +/// Implements a given marker trait for multiple types at the same time. +/// +/// The basic syntax looks like this: +/// ```ignore private macro +/// marker_impls! { MarkerTrait for u8, i8 } +/// ``` +/// You can also implement `unsafe` traits +/// ```ignore private macro +/// marker_impls! { unsafe MarkerTrait for u8, i8 } +/// ``` +/// Add attributes to all impls: +/// ```ignore private macro +/// marker_impls! { +/// #[allow(lint)] +/// #[unstable(feature = "marker_trait", issue = "none")] +/// MarkerTrait for u8, i8 +/// } +/// ``` +/// And use generics: +/// ```ignore private macro +/// marker_impls! { +/// MarkerTrait for +/// u8, i8, +/// {T: ?Sized} *const T, +/// {T: ?Sized} *mut T, +/// {T: MarkerTrait} PhantomData, +/// u32, +/// } +/// ``` +#[unstable(feature = "internal_impls_macro", issue = "none")] +macro marker_impls { + ( $(#[$($meta:tt)*])* $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => { + // This inner macro is needed because... idk macros are weird. + // It allows repeating `meta` on all impls. + #[unstable(feature = "internal_impls_macro", issue = "none")] + macro _impl { + ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => { + $(#[$($meta)*])* impl<$$($$($$bounds_)*)?> $Trait for $$T_ {} + } + } + $( _impl! { $({$($bounds)*})? $T } )+ + }, + ( $(#[$($meta:tt)*])* unsafe $Trait:ident for $( $({$($bounds:tt)*})? $T:ty ),+ $(,)?) => { + #[unstable(feature = "internal_impls_macro", issue = "none")] + macro _impl { + ( $$({$$($$bounds_:tt)*})? $$T_:ty ) => { + $(#[$($meta)*])* unsafe impl<$$($$($$bounds_)*)?> $Trait for $$T_ {} + } + } + + $( _impl! { $({$($bounds)*})? $T } )+ + }, +} + /// Types that can be transferred across thread boundaries. /// /// This trait is automatically implemented when the compiler determines it's @@ -214,34 +268,14 @@ pub trait StructuralEq { // Empty. } -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for usize {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for u8 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for u16 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for u32 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for u64 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for u128 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for isize {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for i8 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for i16 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for i32 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for i64 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for i128 {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for bool {} -#[unstable(feature = "structural_match", issue = "31434")] -impl StructuralEq for char {} +marker_impls! { + #[unstable(feature = "structural_match", issue = "31434")] + StructuralEq for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + bool, + char, +} /// Types whose values can be duplicated simply by copying bits. /// @@ -430,6 +464,30 @@ pub macro Copy($item:item) { /* compiler built-in */ } +// Implementations of `Copy` for primitive types. +// +// Implementations that cannot be described in Rust +// are implemented in `traits::SelectionContext::copy_clone_conditions()` +// in `rustc_trait_selection`. +marker_impls! { + #[stable(feature = "rust1", since = "1.0.0")] + Copy for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + f32, f64, + bool, char, + {T: ?Sized} *const T, + {T: ?Sized} *mut T, + +} + +#[unstable(feature = "never_type", issue = "35121")] +impl Copy for ! {} + +/// Shared references can be copied, but mutable references *cannot*! +#[stable(feature = "rust1", since = "1.0.0")] +impl Copy for &T {} + /// Types for which it is safe to share references between threads. /// /// This trait is automatically implemented when the compiler determines @@ -802,11 +860,14 @@ pub trait DiscriminantKind { pub(crate) unsafe auto trait Freeze {} impl !Freeze for UnsafeCell {} -unsafe impl Freeze for PhantomData {} -unsafe impl Freeze for *const T {} -unsafe impl Freeze for *mut T {} -unsafe impl Freeze for &T {} -unsafe impl Freeze for &mut T {} +marker_impls! { + unsafe Freeze for + {T: ?Sized} PhantomData, + {T: ?Sized} *const T, + {T: ?Sized} *mut T, + {T: ?Sized} &T, + {T: ?Sized} &mut T, +} /// Types that can be safely moved after being pinned. /// @@ -867,17 +928,19 @@ pub struct PhantomPinned; #[stable(feature = "pin", since = "1.33.0")] impl !Unpin for PhantomPinned {} -#[stable(feature = "pin", since = "1.33.0")] -impl<'a, T: ?Sized + 'a> Unpin for &'a T {} - -#[stable(feature = "pin", since = "1.33.0")] -impl<'a, T: ?Sized + 'a> Unpin for &'a mut T {} - -#[stable(feature = "pin_raw", since = "1.38.0")] -impl Unpin for *const T {} +marker_impls! { + #[stable(feature = "pin", since = "1.33.0")] + Unpin for + {T: ?Sized} &T, + {T: ?Sized} &mut T, +} -#[stable(feature = "pin_raw", since = "1.38.0")] -impl Unpin for *mut T {} +marker_impls! { + #[stable(feature = "pin_raw", since = "1.38.0")] + Unpin for + {T: ?Sized} *const T, + {T: ?Sized} *mut T, +} /// A marker for types that can be dropped. /// @@ -917,72 +980,14 @@ pub trait PointerLike {} #[unstable(feature = "adt_const_params", issue = "95174")] #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] pub trait ConstParamTy: StructuralEq {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for usize {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for u8 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for u16 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for u32 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for u64 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for u128 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for isize {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for i8 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for i16 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for i32 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for i64 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for i128 {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for bool {} -#[unstable(feature = "adt_const_params", issue = "95174")] -impl ConstParamTy for char {} - -/// Implementations of `Copy` for primitive types. -/// -/// Implementations that cannot be described in Rust -/// are implemented in `traits::SelectionContext::copy_clone_conditions()` -/// in `rustc_trait_selection`. -mod copy_impls { - - use super::Copy; - - macro_rules! impl_copy { - ($($t:ty)*) => { - $( - #[stable(feature = "rust1", since = "1.0.0")] - impl Copy for $t {} - )* - } - } - impl_copy! { - usize u8 u16 u32 u64 u128 - isize i8 i16 i32 i64 i128 - f32 f64 - bool char - } - - #[unstable(feature = "never_type", issue = "35121")] - impl Copy for ! {} - - #[stable(feature = "rust1", since = "1.0.0")] - impl Copy for *const T {} - - #[stable(feature = "rust1", since = "1.0.0")] - impl Copy for *mut T {} - - /// Shared references can be copied, but mutable references *cannot*! - #[stable(feature = "rust1", since = "1.0.0")] - impl Copy for &T {} +marker_impls! { + #[unstable(feature = "adt_const_params", issue = "95174")] + ConstParamTy for + usize, u8, u16, u32, u64, u128, + isize, i8, i16, i32, i64, i128, + bool, + char, } /// A common trait implemented by all function pointers. From 1bf6bbb1bd199956d1be3d8988f0d8b6036cd2e3 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 3 Mar 2023 18:02:11 +0000 Subject: [PATCH 13/32] Impl `StructuralEq` & `ConstParamTy` for `str`, `&T`, `[T; N]` and `[T]` --- compiler/rustc_trait_selection/src/traits/misc.rs | 9 ++++++++- library/core/src/marker.rs | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index cb8f64dd2e8cf..2210ef975e6c8 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -93,7 +93,14 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>( ) -> Result<(), ConstParamTyImplementationError<'tcx>> { let (adt, substs) = match self_type.kind() { // `core` provides these impls. - ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => return Ok(()), + ty::Uint(_) + | ty::Int(_) + | ty::Bool + | ty::Char + | ty::Str + | ty::Array(..) + | ty::Slice(_) + | ty::Ref(.., hir::Mutability::Not) => return Ok(()), &ty::Adt(adt, substs) => (adt, substs), diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 8c240661b2b44..2f9138c56f21f 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -268,6 +268,7 @@ pub trait StructuralEq { // Empty. } +// FIXME: Remove special cases of these types from the compiler pattern checking code and always check `T: StructuralEq` instead marker_impls! { #[unstable(feature = "structural_match", issue = "31434")] StructuralEq for @@ -275,6 +276,10 @@ marker_impls! { isize, i8, i16, i32, i64, i128, bool, char, + str /* Technically requires `[u8]: StructuralEq` */, + {T: ConstParamTy, const N: usize} [T; N], + {T: ConstParamTy} [T], + {T: ConstParamTy} &T, } /// Types whose values can be duplicated simply by copying bits. @@ -988,6 +993,10 @@ marker_impls! { isize, i8, i16, i32, i64, i128, bool, char, + str /* Technically requires `[u8]: ConstParamTy` */, + {T: ConstParamTy, const N: usize} [T; N], + {T: ConstParamTy} [T], + {T: ConstParamTy} &T, } /// A common trait implemented by all function pointers. From 2c5e7160f30a13f1f32c7d41075515ffbc6012cf Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 3 Mar 2023 18:09:49 +0000 Subject: [PATCH 14/32] Add FIXMEs --- library/core/src/marker.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 2f9138c56f21f..47b431e93b03e 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -986,6 +986,8 @@ pub trait PointerLike {} #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")] pub trait ConstParamTy: StructuralEq {} +// FIXME(generic_const_parameter_types): handle `ty::FnDef`/`ty::Closure` +// FIXME(generic_const_parameter_types): handle `ty::Tuple` marker_impls! { #[unstable(feature = "adt_const_params", issue = "95174")] ConstParamTy for From 51355ad92b6a98a38e72f4e1c168abd494b59160 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 3 Mar 2023 18:20:17 +0000 Subject: [PATCH 15/32] Add a test for `[NotParam; 0]: ConstParamTy` (not holding) --- .../const_param_ty_bad_empty_array.rs | 12 ++++++++++++ .../const_param_ty_bad_empty_array.stderr | 16 ++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.rs create mode 100644 tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.rs new file mode 100644 index 0000000000000..b0e3b13cc1ef9 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.rs @@ -0,0 +1,12 @@ +#![allow(incomplete_features)] +#![feature(adt_const_params)] + +#[derive(PartialEq, Eq)] +struct NotParam; + +fn check() {} + +fn main() { + check::<[NotParam; 0]>(); + //~^ error: `NotParam` can't be used as a const parameter type +} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr new file mode 100644 index 0000000000000..ef55242df8742 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad_empty_array.stderr @@ -0,0 +1,16 @@ +error[E0277]: `NotParam` can't be used as a const parameter type + --> $DIR/const_param_ty_bad_empty_array.rs:10:13 + | +LL | check::<[NotParam; 0]>(); + | ^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | + = note: required for `[NotParam; 0]` to implement `ConstParamTy` +note: required by a bound in `check` + --> $DIR/const_param_ty_bad_empty_array.rs:7:13 + | +LL | fn check() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From bdb5502aa862e22cec579eb845df4bfe42612cfd Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 3 Mar 2023 18:35:57 +0000 Subject: [PATCH 16/32] Fix some marker impls --- library/core/src/marker.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 47b431e93b03e..a1cad6e9992d1 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -277,9 +277,9 @@ marker_impls! { bool, char, str /* Technically requires `[u8]: StructuralEq` */, - {T: ConstParamTy, const N: usize} [T; N], - {T: ConstParamTy} [T], - {T: ConstParamTy} &T, + {T: StructuralEq, const N: usize} [T; N], + {T: StructuralEq} [T], + {T: ?Sized + StructuralEq} &T, } /// Types whose values can be duplicated simply by copying bits. @@ -998,7 +998,7 @@ marker_impls! { str /* Technically requires `[u8]: ConstParamTy` */, {T: ConstParamTy, const N: usize} [T; N], {T: ConstParamTy} [T], - {T: ConstParamTy} &T, + {T: ?Sized + ConstParamTy} &T, } /// A common trait implemented by all function pointers. From 26417a85e7551115146f98c64ea4e433453b9b4b Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 3 Mar 2023 18:52:49 +0000 Subject: [PATCH 17/32] Add `ConstParamTy` tests --- .../adt_const_params/const_param_ty_bad.rs | 13 +++ .../const_param_ty_bad.stderr | 87 +++++++++++++++++++ ...nst_param_ty_generic_bounds_do_not_hold.rs | 13 +++ ...param_ty_generic_bounds_do_not_hold.stderr | 42 +++++++++ .../adt_const_params/const_param_ty_good.rs | 43 +++++++++ 5 files changed, 198 insertions(+) create mode 100644 tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs create mode 100644 tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr create mode 100644 tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs create mode 100644 tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr create mode 100644 tests/ui/const-generics/adt_const_params/const_param_ty_good.rs diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs new file mode 100644 index 0000000000000..a9ade9d838c98 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs @@ -0,0 +1,13 @@ +#![allow(incomplete_features)] +#![feature(adt_const_params)] + +fn check(_: impl std::marker::ConstParamTy) {} + +fn main() { + check(main); //~ error: `fn() {main}` can't be used as a const parameter type + check(|| {}); //~ error: `[closure@fake-test-src-base/const-generics/adt_const_params/const_param_ty_bad.rs:8:11: 8:13]` can't be used as a const parameter type + check(main as fn()); //~ error: `fn()` can't be used as a const parameter type + check(&mut ()); //~ error: `&mut ()` can't be used as a const parameter type + check(&mut () as *mut ()); //~ error: `*mut ()` can't be used as a const parameter type + check(&() as *const ()); //~ error: `*const ()` can't be used as a const parameter type +} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr new file mode 100644 index 0000000000000..de5704ee429ed --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr @@ -0,0 +1,87 @@ +error[E0277]: `fn() {main}` can't be used as a const parameter type + --> $DIR/const_param_ty_bad.rs:7:11 + | +LL | check(main); + | ----- ^^^^ the trait `ConstParamTy` is not implemented for fn item `fn() {main}` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/const_param_ty_bad.rs:4:18 + | +LL | fn check(_: impl std::marker::ConstParamTy) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: `[closure@$DIR/const_param_ty_bad.rs:8:11: 8:13]` can't be used as a const parameter type + --> $DIR/const_param_ty_bad.rs:8:11 + | +LL | check(|| {}); + | ----- ^^^^^ the trait `ConstParamTy` is not implemented for closure `[closure@$DIR/const_param_ty_bad.rs:8:11: 8:13]` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/const_param_ty_bad.rs:4:18 + | +LL | fn check(_: impl std::marker::ConstParamTy) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: `fn()` can't be used as a const parameter type + --> $DIR/const_param_ty_bad.rs:9:11 + | +LL | check(main as fn()); + | ----- ^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `fn()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/const_param_ty_bad.rs:4:18 + | +LL | fn check(_: impl std::marker::ConstParamTy) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: `&mut ()` can't be used as a const parameter type + --> $DIR/const_param_ty_bad.rs:10:11 + | +LL | check(&mut ()); + | ----- ^^^^^^^ the trait `ConstParamTy` is not implemented for `&mut ()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/const_param_ty_bad.rs:4:18 + | +LL | fn check(_: impl std::marker::ConstParamTy) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: `*mut ()` can't be used as a const parameter type + --> $DIR/const_param_ty_bad.rs:11:11 + | +LL | check(&mut () as *mut ()); + | ----- ^^^^^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `*mut ()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/const_param_ty_bad.rs:4:18 + | +LL | fn check(_: impl std::marker::ConstParamTy) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: `*const ()` can't be used as a const parameter type + --> $DIR/const_param_ty_bad.rs:12:11 + | +LL | check(&() as *const ()); + | ----- ^^^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `*const ()` + | | + | required by a bound introduced by this call + | +note: required by a bound in `check` + --> $DIR/const_param_ty_bad.rs:4:18 + | +LL | fn check(_: impl std::marker::ConstParamTy) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs new file mode 100644 index 0000000000000..e4dc76703a2d8 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.rs @@ -0,0 +1,13 @@ +#![allow(incomplete_features)] +#![feature(adt_const_params)] + +#[derive(PartialEq, Eq)] +struct NotParam; + +fn check() {} + +fn main() { + check::<&NotParam>(); //~ error: `NotParam` can't be used as a const parameter type + check::<[NotParam]>(); //~ error: `NotParam` can't be used as a const parameter type + check::<[NotParam; 17]>(); //~ error: `NotParam` can't be used as a const parameter type +} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr new file mode 100644 index 0000000000000..86d1c94e87f96 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_generic_bounds_do_not_hold.stderr @@ -0,0 +1,42 @@ +error[E0277]: `NotParam` can't be used as a const parameter type + --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:10:13 + | +LL | check::<&NotParam>(); + | ^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | + = note: required for `&NotParam` to implement `ConstParamTy` +note: required by a bound in `check` + --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13 + | +LL | fn check() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: `NotParam` can't be used as a const parameter type + --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:11:13 + | +LL | check::<[NotParam]>(); + | ^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | + = note: required for `[NotParam]` to implement `ConstParamTy` +note: required by a bound in `check` + --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13 + | +LL | fn check() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error[E0277]: `NotParam` can't be used as a const parameter type + --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:12:13 + | +LL | check::<[NotParam; 17]>(); + | ^^^^^^^^^^^^^^ the trait `ConstParamTy` is not implemented for `NotParam` + | + = note: required for `[NotParam; 17]` to implement `ConstParamTy` +note: required by a bound in `check` + --> $DIR/const_param_ty_generic_bounds_do_not_hold.rs:7:13 + | +LL | fn check() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs new file mode 100644 index 0000000000000..a1b711a3024e3 --- /dev/null +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_good.rs @@ -0,0 +1,43 @@ +// check-pass +#![allow(incomplete_features)] +#![feature(adt_const_params)] +use std::marker::ConstParamTy; + +#[derive(PartialEq, Eq)] +struct S { + field: u8, + gen: T, +} + +impl ConstParamTy for S {} + +fn check() {} + +fn main() { + check::(); + check::(); + check::(); + check::(); + check::(); + + check::(); + check::(); + check::(); + check::(); + check::(); + + check::(); + check::(); + check::(); + + check::<&u8>(); + check::<&str>(); + check::<[usize]>(); + check::<[u16; 0]>(); + check::<[u8; 42]>(); + + check::>(); + check::>(); + + // FIXME: test tuples +} From 2f70d02df46916a56f15ef52b13a99c3a69fbd5b Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 27 Apr 2023 17:25:51 +0000 Subject: [PATCH 18/32] Fix compile test so it normalizes (un)expected error messages --- src/tools/compiletest/src/runtest.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6597c729387e..514b96ce85203 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1384,7 +1384,9 @@ impl<'test> TestCx<'test> { let actual_errors = json::parse_output(&diagnostic_file_name, &proc_res.stderr, proc_res); let mut unexpected = Vec::new(); let mut found = vec![false; expected_errors.len()]; - for actual_error in &actual_errors { + for mut actual_error in actual_errors { + actual_error.msg = self.normalize_output(&actual_error.msg, &[]); + let opt_index = expected_errors.iter().enumerate().position(|(index, expected_error)| { !found[index] @@ -1403,7 +1405,8 @@ impl<'test> TestCx<'test> { None => { // If the test is a known bug, don't require that the error is annotated - if self.is_unexpected_compiler_message(actual_error, expect_help, expect_note) { + if self.is_unexpected_compiler_message(&actual_error, expect_help, expect_note) + { self.error(&format!( "{}:{}: unexpected {}: '{}'", file_name, From 1f44a24e725bd2fdeccfb91b0daa51788ac761f1 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 27 Apr 2023 17:26:59 +0000 Subject: [PATCH 19/32] --bless `ConstParamTy` ui tests --- tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs | 2 +- .../adt_const_params/const_param_ty_impl_bad_field.rs | 2 +- .../adt_const_params/const_param_ty_impl_bad_field.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs index a9ade9d838c98..0da68ae757351 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.rs @@ -5,7 +5,7 @@ fn check(_: impl std::marker::ConstParamTy) {} fn main() { check(main); //~ error: `fn() {main}` can't be used as a const parameter type - check(|| {}); //~ error: `[closure@fake-test-src-base/const-generics/adt_const_params/const_param_ty_bad.rs:8:11: 8:13]` can't be used as a const parameter type + check(|| {}); //~ error: `[closure@$DIR/const_param_ty_bad.rs:8:11: 8:13]` can't be used as a const parameter type check(main as fn()); //~ error: `fn()` can't be used as a const parameter type check(&mut ()); //~ error: `&mut ()` can't be used as a const parameter type check(&mut () as *mut ()); //~ error: `*mut ()` can't be used as a const parameter type diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs index 3d2d99b9d38ca..07fd243737e2a 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs @@ -8,6 +8,6 @@ struct NotParam; struct CantParam(NotParam); impl std::marker::ConstParamTy for CantParam {} -//~^ error: the trait `ConstParamTy` may not be implemented for this type +//~^ error: the trait `ConstParamTy` cannot be implemented for this type fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr index 5cd5cae6d79dd..c8e065848b1e0 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr @@ -1,4 +1,4 @@ -error[E0204]: the trait `ConstParamTy` may not be implemented for this type +error[E0204]: the trait `ConstParamTy` cannot be implemented for this type --> $DIR/const_param_ty_impl_bad_field.rs:10:36 | LL | struct CantParam(NotParam); From 182eee298c05b7259c98209a3d9a87ecac484040 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 28 Apr 2023 11:56:02 +0000 Subject: [PATCH 20/32] fixup tests wrt new normalization --- tests/ui/const-generics/nested-type.rs | 6 +++++- tests/ui/fmt/format-string-error.rs | 2 +- tests/ui/parser/issues/issue-62913.rs | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/ui/const-generics/nested-type.rs b/tests/ui/const-generics/nested-type.rs index 5240f5c3b0b64..ff95018065a84 100644 --- a/tests/ui/const-generics/nested-type.rs +++ b/tests/ui/const-generics/nested-type.rs @@ -3,7 +3,7 @@ #![cfg_attr(full, feature(adt_const_params))] #![cfg_attr(full, allow(incomplete_features))] -struct Foo; impl Foo { @@ -15,5 +15,9 @@ struct Foo::value() //~^ ERROR cannot call non-const fn }]>; +//[min]~^^^^^^^^^^^^ ERROR `[u8; { + +// N.B. it is important that the comment above is not inside the array length, +// otherwise it may check for itself, instead of the actual error fn main() {} diff --git a/tests/ui/fmt/format-string-error.rs b/tests/ui/fmt/format-string-error.rs index eae4f3cb5479f..9b436e2c479f2 100644 --- a/tests/ui/fmt/format-string-error.rs +++ b/tests/ui/fmt/format-string-error.rs @@ -17,7 +17,7 @@ fn main() { let _ = format!("}"); //~^ ERROR invalid format string: unmatched `}` found let _ = format!("{\\}"); - //~^ ERROR invalid format string: expected `'}'`, found `'\\'` + //~^ ERROR invalid format string: expected `'}'`, found `'\'` let _ = format!("\n\n\n{\n\n\n"); //~^ ERROR invalid format string let _ = format!(r###" diff --git a/tests/ui/parser/issues/issue-62913.rs b/tests/ui/parser/issues/issue-62913.rs index 0db06f636c3ec..a55ef5ac71030 100644 --- a/tests/ui/parser/issues/issue-62913.rs +++ b/tests/ui/parser/issues/issue-62913.rs @@ -1,4 +1,4 @@ "\u\\" //~^ ERROR incorrect unicode escape sequence //~| ERROR invalid trailing slash in literal -//~| ERROR expected item, found `"\u\\"` +//~| ERROR expected item, found `"\u\"` From 5c99175a9efcaa3d65712c119f361add22e3a859 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 28 Apr 2023 17:17:46 +0000 Subject: [PATCH 21/32] uplift `clippy::clone_double_ref` as `suspicious_double_ref_op` --- compiler/rustc_codegen_ssa/src/back/link.rs | 7 +- compiler/rustc_lint/messages.ftl | 3 + compiler/rustc_lint/src/lints.rs | 8 ++ compiler/rustc_lint/src/noop_method_call.rs | 81 ++++++++++++---- .../clippy/clippy_lints/src/declared_lints.rs | 1 - .../clippy_lints/src/methods/clone_on_copy.rs | 40 +------- .../clippy/clippy_lints/src/methods/mod.rs | 24 ----- .../clippy/clippy_lints/src/renamed_lints.rs | 1 + .../tests/ui/explicit_deref_methods.fixed | 2 +- .../clippy/tests/ui/explicit_deref_methods.rs | 2 +- src/tools/clippy/tests/ui/rename.fixed | 2 + src/tools/clippy/tests/ui/rename.rs | 2 + src/tools/clippy/tests/ui/rename.stderr | 92 ++++++++++--------- .../clippy/tests/ui/unnecessary_clone.rs | 13 --- .../clippy/tests/ui/unnecessary_clone.stderr | 52 +---------- tests/ui/lint/noop-method-call.rs | 8 +- tests/ui/lint/noop-method-call.stderr | 26 +++++- tests/ui/lint/suspicious-double-ref-op.rs | 30 ++++++ tests/ui/lint/suspicious-double-ref-op.stderr | 35 +++++++ 19 files changed, 230 insertions(+), 199 deletions(-) create mode 100644 tests/ui/lint/suspicious-double-ref-op.rs create mode 100644 tests/ui/lint/suspicious-double-ref-op.stderr diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 02e21e74fadc8..802e99a5e0e61 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -40,7 +40,6 @@ use regex::Regex; use tempfile::Builder as TempFileBuilder; use itertools::Itertools; -use std::borrow::Borrow; use std::cell::OnceCell; use std::collections::BTreeSet; use std::ffi::OsString; @@ -573,17 +572,17 @@ fn link_dwarf_object<'a>( impl ThorinSession { fn alloc_mmap(&self, data: Mmap) -> &Mmap { - (*self.arena_mmap.alloc(data)).borrow() + &*self.arena_mmap.alloc(data) } } impl thorin::Session for ThorinSession { fn alloc_data(&self, data: Vec) -> &[u8] { - (*self.arena_data.alloc(data)).borrow() + &*self.arena_data.alloc(data) } fn alloc_relocation(&self, data: Relocations) -> &Relocations { - (*self.arena_relocations.alloc(data)).borrow() + &*self.arena_relocations.alloc(data) } fn read_input(&self, path: &Path) -> std::io::Result<&[u8]> { diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 3c6dbb466db7a..0cef6a44b0776 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -50,6 +50,9 @@ lint_deprecated_lint_name = lint_renamed_or_removed_lint = {$msg} .suggestion = use the new name +lint_suspicious_double_ref_op = + using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op} the inner type + lint_unknown_lint = unknown lint: `{$name}` .suggestion = did you mean diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 848f6a9ecb532..d7bacc6485f15 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1150,6 +1150,14 @@ pub struct NoopMethodCallDiag<'a> { pub label: Span, } +#[derive(LintDiagnostic)] +#[diag(lint_suspicious_double_ref_op)] +pub struct SuspiciousDoubleRefDiag<'a> { + pub call: Symbol, + pub ty: Ty<'a>, + pub op: &'static str, +} + // pass_by_value.rs #[derive(LintDiagnostic)] #[diag(lint_pass_by_value)] diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index d67a00619dd09..648c0c26404c1 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -1,10 +1,11 @@ use crate::context::LintContext; -use crate::lints::NoopMethodCallDiag; +use crate::lints::{NoopMethodCallDiag, SuspiciousDoubleRefDiag}; use crate::LateContext; use crate::LateLintPass; use rustc_hir::def::DefKind; use rustc_hir::{Expr, ExprKind}; use rustc_middle::ty; +use rustc_middle::ty::adjustment::Adjust; use rustc_span::symbol::sym; declare_lint! { @@ -35,14 +36,44 @@ declare_lint! { "detects the use of well-known noop methods" } -declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL]); +declare_lint! { + /// The `suspicious_double_ref_op` lint checks for usage of `.clone()`/`.borrow()`/`.deref()` + /// on an `&&T` when `T: !Deref/Borrow/Clone`, which means the call will return the inner `&T`, + /// instead of performing the operation on the underlying `T` and can be confusing. + /// + /// ### Example + /// + /// ```rust + /// # #![allow(unused)] + /// struct Foo; + /// let foo = &&Foo; + /// let clone: &Foo = foo.clone(); + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Since `Foo` doesn't implement `Clone`, running `.clone()` only dereferences the double + /// reference, instead of cloning the inner type which should be what was intended. + pub SUSPICIOUS_DOUBLE_REF_OP, + Warn, + "suspicious call of trait method on `&&T`" +} + +declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL, SUSPICIOUS_DOUBLE_REF_OP]); impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { // We only care about method calls. - let ExprKind::MethodCall(call, receiver, ..) = &expr.kind else { - return + let ExprKind::MethodCall(call, receiver, _, call_span) = &expr.kind else { + return; }; + + if call_span.from_expansion() { + return; + } + // We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow` // traits and ignore any other method call. let did = match cx.typeck_results().type_dependent_def(expr.hir_id) { @@ -70,25 +101,39 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { }; // (Re)check that it implements the noop diagnostic. let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return }; - if !matches!( - name, - sym::noop_method_borrow | sym::noop_method_clone | sym::noop_method_deref - ) { - return; - } + + let op = match name { + sym::noop_method_borrow => "borrowing", + sym::noop_method_clone => "cloning", + sym::noop_method_deref => "dereferencing", + _ => return, + }; + let receiver_ty = cx.typeck_results().expr_ty(receiver); let expr_ty = cx.typeck_results().expr_ty_adjusted(expr); - if receiver_ty != expr_ty { - // This lint will only trigger if the receiver type and resulting expression \ - // type are the same, implying that the method call is unnecessary. + let arg_adjustments = cx.typeck_results().expr_adjustments(receiver); + + // If there is any user defined auto-deref step, then we don't want to warn. + // https://github.com/rust-lang/rust-clippy/issues/9272 + if arg_adjustments.iter().any(|adj| matches!(adj.kind, Adjust::Deref(Some(_)))) { return; } + let expr_span = expr.span; let span = expr_span.with_lo(receiver.span.hi()); - cx.emit_spanned_lint( - NOOP_METHOD_CALL, - span, - NoopMethodCallDiag { method: call.ident.name, receiver_ty, label: span }, - ); + + if receiver_ty == expr_ty { + cx.emit_spanned_lint( + NOOP_METHOD_CALL, + span, + NoopMethodCallDiag { method: call.ident.name, receiver_ty, label: span }, + ); + } else { + cx.emit_spanned_lint( + SUSPICIOUS_DOUBLE_REF_OP, + span, + SuspiciousDoubleRefDiag { call: call.ident.name, ty: expr_ty, op }, + ) + } } } diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs index 0c66d36a1d630..fa726a649370e 100644 --- a/src/tools/clippy/clippy_lints/src/declared_lints.rs +++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs @@ -313,7 +313,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::methods::CHARS_NEXT_CMP_INFO, crate::methods::CLEAR_WITH_DRAIN_INFO, crate::methods::CLONED_INSTEAD_OF_COPIED_INFO, - crate::methods::CLONE_DOUBLE_REF_INFO, crate::methods::CLONE_ON_COPY_INFO, crate::methods::CLONE_ON_REF_PTR_INFO, crate::methods::COLLAPSIBLE_STR_REPLACE_INFO, diff --git a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs index 3795c0ec25098..65fd50dff5846 100644 --- a/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs +++ b/src/tools/clippy/clippy_lints/src/methods/clone_on_copy.rs @@ -1,7 +1,6 @@ -use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; +use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_node; use clippy_utils::source::snippet_with_context; -use clippy_utils::sugg; use clippy_utils::ty::is_copy; use rustc_errors::Applicability; use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, MatchSource, Node, PatKind, QPath}; @@ -9,7 +8,6 @@ use rustc_lint::LateContext; use rustc_middle::ty::{self, adjustment::Adjust, print::with_forced_trimmed_paths}; use rustc_span::symbol::{sym, Symbol}; -use super::CLONE_DOUBLE_REF; use super::CLONE_ON_COPY; /// Checks for the `CLONE_ON_COPY` lint. @@ -42,41 +40,7 @@ pub(super) fn check( let ty = cx.typeck_results().expr_ty(expr); if let ty::Ref(_, inner, _) = arg_ty.kind() { - if let ty::Ref(_, innermost, _) = inner.kind() { - span_lint_and_then( - cx, - CLONE_DOUBLE_REF, - expr.span, - &with_forced_trimmed_paths!(format!( - "using `clone` on a double-reference; \ - this will copy the reference of type `{ty}` instead of cloning the inner type" - )), - |diag| { - if let Some(snip) = sugg::Sugg::hir_opt(cx, arg) { - let mut ty = innermost; - let mut n = 0; - while let ty::Ref(_, inner, _) = ty.kind() { - ty = inner; - n += 1; - } - let refs = "&".repeat(n + 1); - let derefs = "*".repeat(n); - let explicit = with_forced_trimmed_paths!(format!("<{refs}{ty}>::clone({snip})")); - diag.span_suggestion( - expr.span, - "try dereferencing it", - with_forced_trimmed_paths!(format!("{refs}({derefs}{}).clone()", snip.deref())), - Applicability::MaybeIncorrect, - ); - diag.span_suggestion( - expr.span, - "or try being explicit if you are sure, that you want to clone a reference", - explicit, - Applicability::MaybeIncorrect, - ); - } - }, - ); + if let ty::Ref(..) = inner.kind() { return; // don't report clone_on_copy } } diff --git a/src/tools/clippy/clippy_lints/src/methods/mod.rs b/src/tools/clippy/clippy_lints/src/methods/mod.rs index 9cafbc2e5f5a6..e4a659d3ce73c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/mod.rs +++ b/src/tools/clippy/clippy_lints/src/methods/mod.rs @@ -984,29 +984,6 @@ declare_clippy_lint! { "using 'clone' on a ref-counted pointer" } -declare_clippy_lint! { - /// ### What it does - /// Checks for usage of `.clone()` on an `&&T`. - /// - /// ### Why is this bad? - /// Cloning an `&&T` copies the inner `&T`, instead of - /// cloning the underlying `T`. - /// - /// ### Example - /// ```rust - /// fn main() { - /// let x = vec![1]; - /// let y = &&x; - /// let z = y.clone(); - /// println!("{:p} {:p}", *y, z); // prints out the same pointer - /// } - /// ``` - #[clippy::version = "pre 1.29.0"] - pub CLONE_DOUBLE_REF, - correctness, - "using `clone` on `&&T`" -} - declare_clippy_lint! { /// ### What it does /// Checks for usage of `.to_string()` on an `&&T` where @@ -3258,7 +3235,6 @@ impl_lint_pass!(Methods => [ CHARS_LAST_CMP, CLONE_ON_COPY, CLONE_ON_REF_PTR, - CLONE_DOUBLE_REF, COLLAPSIBLE_STR_REPLACE, ITER_OVEREAGER_CLONED, CLONED_INSTEAD_OF_COPIED, diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs index 9f487dedb8cb6..5e81a01a461ab 100644 --- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs +++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs @@ -30,6 +30,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[ ("clippy::stutter", "clippy::module_name_repetitions"), ("clippy::to_string_in_display", "clippy::recursive_format_impl"), ("clippy::zero_width_space", "clippy::invisible_characters"), + ("clippy::clone_double_ref", "suspicious_double_ref_op"), ("clippy::drop_bounds", "drop_bounds"), ("clippy::for_loop_over_option", "for_loops_over_fallibles"), ("clippy::for_loop_over_result", "for_loops_over_fallibles"), diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed index 77e9f5fc1fdf1..60482c66da7c4 100644 --- a/src/tools/clippy/tests/ui/explicit_deref_methods.fixed +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.fixed @@ -3,7 +3,7 @@ #![allow(unused_variables)] #![allow( clippy::borrow_deref_ref, - clippy::clone_double_ref, + suspicious_double_ref_op, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::uninlined_format_args diff --git a/src/tools/clippy/tests/ui/explicit_deref_methods.rs b/src/tools/clippy/tests/ui/explicit_deref_methods.rs index 0c2cc7c2c3a6a..e3613e216bb22 100644 --- a/src/tools/clippy/tests/ui/explicit_deref_methods.rs +++ b/src/tools/clippy/tests/ui/explicit_deref_methods.rs @@ -3,7 +3,7 @@ #![allow(unused_variables)] #![allow( clippy::borrow_deref_ref, - clippy::clone_double_ref, + suspicious_double_ref_op, clippy::explicit_auto_deref, clippy::needless_borrow, clippy::uninlined_format_args diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed index e8a00a9e7f712..ff19a042825d8 100644 --- a/src/tools/clippy/tests/ui/rename.fixed +++ b/src/tools/clippy/tests/ui/rename.fixed @@ -36,6 +36,7 @@ #![allow(enum_intrinsics_non_enums)] #![allow(non_fmt_panics)] #![allow(named_arguments_used_positionally)] +#![allow(suspicious_double_ref_op)] #![allow(temporary_cstring_as_ptr)] #![allow(unknown_lints)] #![allow(unused_labels)] @@ -67,6 +68,7 @@ #![warn(clippy::module_name_repetitions)] #![warn(clippy::recursive_format_impl)] #![warn(clippy::invisible_characters)] +#![warn(suspicious_double_ref_op)] #![warn(drop_bounds)] #![warn(for_loops_over_fallibles)] #![warn(for_loops_over_fallibles)] diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs index c8ea70c2bcb1d..38b1647c0cca0 100644 --- a/src/tools/clippy/tests/ui/rename.rs +++ b/src/tools/clippy/tests/ui/rename.rs @@ -36,6 +36,7 @@ #![allow(enum_intrinsics_non_enums)] #![allow(non_fmt_panics)] #![allow(named_arguments_used_positionally)] +#![allow(suspicious_double_ref_op)] #![allow(temporary_cstring_as_ptr)] #![allow(unknown_lints)] #![allow(unused_labels)] @@ -67,6 +68,7 @@ #![warn(clippy::stutter)] #![warn(clippy::to_string_in_display)] #![warn(clippy::zero_width_space)] +#![warn(clippy::clone_double_ref)] #![warn(clippy::drop_bounds)] #![warn(clippy::for_loop_over_option)] #![warn(clippy::for_loop_over_result)] diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr index 27a0263292ef1..70d15408b9fc1 100644 --- a/src/tools/clippy/tests/ui/rename.stderr +++ b/src/tools/clippy/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range` - --> $DIR/rename.rs:42:9 + --> $DIR/rename.rs:43:9 | LL | #![warn(clippy::almost_complete_letter_range)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range` @@ -7,250 +7,256 @@ LL | #![warn(clippy::almost_complete_letter_range)] = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names` - --> $DIR/rename.rs:43:9 + --> $DIR/rename.rs:44:9 | LL | #![warn(clippy::blacklisted_name)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names` error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:44:9 + --> $DIR/rename.rs:45:9 | LL | #![warn(clippy::block_in_if_condition_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions` - --> $DIR/rename.rs:45:9 + --> $DIR/rename.rs:46:9 | LL | #![warn(clippy::block_in_if_condition_stmt)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions` error: lint `clippy::box_vec` has been renamed to `clippy::box_collection` - --> $DIR/rename.rs:46:9 + --> $DIR/rename.rs:47:9 | LL | #![warn(clippy::box_vec)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:47:9 + --> $DIR/rename.rs:48:9 | LL | #![warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> $DIR/rename.rs:48:9 + --> $DIR/rename.rs:49:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq` - --> $DIR/rename.rs:49:9 + --> $DIR/rename.rs:50:9 | LL | #![warn(clippy::derive_hash_xor_eq)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq` error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods` - --> $DIR/rename.rs:50:9 + --> $DIR/rename.rs:51:9 | LL | #![warn(clippy::disallowed_method)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods` error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types` - --> $DIR/rename.rs:51:9 + --> $DIR/rename.rs:52:9 | LL | #![warn(clippy::disallowed_type)] | ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types` error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression` - --> $DIR/rename.rs:52:9 + --> $DIR/rename.rs:53:9 | LL | #![warn(clippy::eval_order_dependence)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression` error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion` - --> $DIR/rename.rs:53:9 + --> $DIR/rename.rs:54:9 | LL | #![warn(clippy::identity_conversion)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion` error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok` - --> $DIR/rename.rs:54:9 + --> $DIR/rename.rs:55:9 | LL | #![warn(clippy::if_let_some_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok` error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr` - --> $DIR/rename.rs:55:9 + --> $DIR/rename.rs:56:9 | LL | #![warn(clippy::logic_bug)] | ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> $DIR/rename.rs:56:9 + --> $DIR/rename.rs:57:9 | LL | #![warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map` - --> $DIR/rename.rs:57:9 + --> $DIR/rename.rs:58:9 | LL | #![warn(clippy::option_and_then_some)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map` error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:58:9 + --> $DIR/rename.rs:59:9 | LL | #![warn(clippy::option_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:59:9 + --> $DIR/rename.rs:60:9 | LL | #![warn(clippy::option_map_unwrap_or)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:60:9 + --> $DIR/rename.rs:61:9 | LL | #![warn(clippy::option_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:61:9 + --> $DIR/rename.rs:62:9 | LL | #![warn(clippy::option_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow` - --> $DIR/rename.rs:62:9 + --> $DIR/rename.rs:63:9 | LL | #![warn(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow` error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used` - --> $DIR/rename.rs:63:9 + --> $DIR/rename.rs:64:9 | LL | #![warn(clippy::result_expect_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used` error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or` - --> $DIR/rename.rs:64:9 + --> $DIR/rename.rs:65:9 | LL | #![warn(clippy::result_map_unwrap_or_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or` error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used` - --> $DIR/rename.rs:65:9 + --> $DIR/rename.rs:66:9 | LL | #![warn(clippy::result_unwrap_used)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used` error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str` - --> $DIR/rename.rs:66:9 + --> $DIR/rename.rs:67:9 | LL | #![warn(clippy::single_char_push_str)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> $DIR/rename.rs:67:9 + --> $DIR/rename.rs:68:9 | LL | #![warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl` - --> $DIR/rename.rs:68:9 + --> $DIR/rename.rs:69:9 | LL | #![warn(clippy::to_string_in_display)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl` error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters` - --> $DIR/rename.rs:69:9 + --> $DIR/rename.rs:70:9 | LL | #![warn(clippy::zero_width_space)] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters` +error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op` + --> $DIR/rename.rs:71:9 + | +LL | #![warn(clippy::clone_double_ref)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op` + error: lint `clippy::drop_bounds` has been renamed to `drop_bounds` - --> $DIR/rename.rs:70:9 + --> $DIR/rename.rs:72:9 | LL | #![warn(clippy::drop_bounds)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds` error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:71:9 + --> $DIR/rename.rs:73:9 | LL | #![warn(clippy::for_loop_over_option)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:72:9 + --> $DIR/rename.rs:74:9 | LL | #![warn(clippy::for_loop_over_result)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles` - --> $DIR/rename.rs:73:9 + --> $DIR/rename.rs:75:9 | LL | #![warn(clippy::for_loops_over_fallibles)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles` error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter` - --> $DIR/rename.rs:74:9 + --> $DIR/rename.rs:76:9 | LL | #![warn(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter` error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering` - --> $DIR/rename.rs:75:9 + --> $DIR/rename.rs:77:9 | LL | #![warn(clippy::invalid_atomic_ordering)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering` error: lint `clippy::invalid_ref` has been renamed to `invalid_value` - --> $DIR/rename.rs:76:9 + --> $DIR/rename.rs:78:9 | LL | #![warn(clippy::invalid_ref)] | ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value` error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop` - --> $DIR/rename.rs:77:9 + --> $DIR/rename.rs:79:9 | LL | #![warn(clippy::let_underscore_drop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop` error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums` - --> $DIR/rename.rs:78:9 + --> $DIR/rename.rs:80:9 | LL | #![warn(clippy::mem_discriminant_non_enum)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums` error: lint `clippy::panic_params` has been renamed to `non_fmt_panics` - --> $DIR/rename.rs:79:9 + --> $DIR/rename.rs:81:9 | LL | #![warn(clippy::panic_params)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics` error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally` - --> $DIR/rename.rs:80:9 + --> $DIR/rename.rs:82:9 | LL | #![warn(clippy::positional_named_format_parameters)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally` error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr` - --> $DIR/rename.rs:81:9 + --> $DIR/rename.rs:83:9 | LL | #![warn(clippy::temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr` error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints` - --> $DIR/rename.rs:82:9 + --> $DIR/rename.rs:84:9 | LL | #![warn(clippy::unknown_clippy_lints)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints` error: lint `clippy::unused_label` has been renamed to `unused_labels` - --> $DIR/rename.rs:83:9 + --> $DIR/rename.rs:85:9 | LL | #![warn(clippy::unused_label)] | ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels` -error: aborting due to 42 previous errors +error: aborting due to 43 previous errors diff --git a/src/tools/clippy/tests/ui/unnecessary_clone.rs b/src/tools/clippy/tests/ui/unnecessary_clone.rs index 8b1629b19a769..7ceed3c75fd85 100644 --- a/src/tools/clippy/tests/ui/unnecessary_clone.rs +++ b/src/tools/clippy/tests/ui/unnecessary_clone.rs @@ -42,14 +42,6 @@ fn clone_on_copy_generic(t: T) { Some(t).clone(); } -fn clone_on_double_ref() { - let x = vec![1]; - let y = &&x; - let z: &Vec<_> = y.clone(); - - println!("{:p} {:p}", *y, z); -} - mod many_derefs { struct A; struct B; @@ -84,11 +76,6 @@ mod many_derefs { let _: E = a.clone(); let _: E = *****a; } - - fn check(mut encoded: &[u8]) { - let _ = &mut encoded.clone(); - let _ = &encoded.clone(); - } } mod issue2076 { diff --git a/src/tools/clippy/tests/ui/unnecessary_clone.stderr b/src/tools/clippy/tests/ui/unnecessary_clone.stderr index 6022d9fa4c5c3..5686ab6b4531e 100644 --- a/src/tools/clippy/tests/ui/unnecessary_clone.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_clone.stderr @@ -44,63 +44,17 @@ error: using `clone` on type `Option` which implements the `Copy` trait LL | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` -error: using `clone` on a double-reference; this will copy the reference of type `&Vec` instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:48:22 - | -LL | let z: &Vec<_> = y.clone(); - | ^^^^^^^^^ - | - = note: `#[deny(clippy::clone_double_ref)]` on by default -help: try dereferencing it - | -LL | let z: &Vec<_> = &(*y).clone(); - | ~~~~~~~~~~~~~ -help: or try being explicit if you are sure, that you want to clone a reference - | -LL | let z: &Vec<_> = <&Vec>::clone(y); - | ~~~~~~~~~~~~~~~~~~~~~ - error: using `clone` on type `E` which implements the `Copy` trait - --> $DIR/unnecessary_clone.rs:84:20 + --> $DIR/unnecessary_clone.rs:76:20 | LL | let _: E = a.clone(); | ^^^^^^^^^ help: try dereferencing it: `*****a` -error: using `clone` on a double-reference; this will copy the reference of type `&[u8]` instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:89:22 - | -LL | let _ = &mut encoded.clone(); - | ^^^^^^^^^^^^^^^ - | -help: try dereferencing it - | -LL | let _ = &mut &(*encoded).clone(); - | ~~~~~~~~~~~~~~~~~~~ -help: or try being explicit if you are sure, that you want to clone a reference - | -LL | let _ = &mut <&[u8]>::clone(encoded); - | ~~~~~~~~~~~~~~~~~~~~~~~ - -error: using `clone` on a double-reference; this will copy the reference of type `&[u8]` instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:90:18 - | -LL | let _ = &encoded.clone(); - | ^^^^^^^^^^^^^^^ - | -help: try dereferencing it - | -LL | let _ = &&(*encoded).clone(); - | ~~~~~~~~~~~~~~~~~~~ -help: or try being explicit if you are sure, that you want to clone a reference - | -LL | let _ = &<&[u8]>::clone(encoded); - | ~~~~~~~~~~~~~~~~~~~~~~~ - error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:108:14 + --> $DIR/unnecessary_clone.rs:95:14 | LL | Some(try_opt!(Some(rc)).clone()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `Rc::::clone(&try_opt!(Some(rc)))` -error: aborting due to 12 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/lint/noop-method-call.rs b/tests/ui/lint/noop-method-call.rs index 89b2966359542..dbcf2a5131b5b 100644 --- a/tests/ui/lint/noop-method-call.rs +++ b/tests/ui/lint/noop-method-call.rs @@ -19,18 +19,17 @@ fn main() { let clone_type_ref = &CloneType(1u32); let clone_type_ref_clone: CloneType = clone_type_ref.clone(); - // Calling clone on a double reference doesn't warn since the method call itself - // peels the outer reference off let clone_type_ref = &&CloneType(1u32); let clone_type_ref_clone: &CloneType = clone_type_ref.clone(); + //~^ WARNING using `.clone()` on a double reference, which returns `&CloneType` let non_deref_type = &PlainType(1u32); let non_deref_type_deref: &PlainType = non_deref_type.deref(); //~^ WARNING call to `.deref()` on a reference in this situation does nothing - // Dereferencing a &&T does not warn since it has collapsed the double reference let non_deref_type = &&PlainType(1u32); let non_deref_type_deref: &PlainType = non_deref_type.deref(); + //~^ WARNING using `.deref()` on a double reference, which returns `&PlainType` let non_borrow_type = &PlainType(1u32); let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); @@ -41,7 +40,8 @@ fn main() { let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); let xs = ["a", "b", "c"]; - let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // ok, but could use `*x` instead + let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead + //~^ WARNING using `.clone()` on a double reference, which returns `&str` } fn generic(non_clone_type: &PlainType) { diff --git a/tests/ui/lint/noop-method-call.stderr b/tests/ui/lint/noop-method-call.stderr index 6a904d01abc8e..37cd1a0fc18ea 100644 --- a/tests/ui/lint/noop-method-call.stderr +++ b/tests/ui/lint/noop-method-call.stderr @@ -11,22 +11,42 @@ note: the lint level is defined here LL | #![warn(noop_method_call)] | ^^^^^^^^^^^^^^^^ +warning: using `.clone()` on a double reference, which returns `&CloneType` instead of cloning the inner type + --> $DIR/noop-method-call.rs:23:63 + | +LL | let clone_type_ref_clone: &CloneType = clone_type_ref.clone(); + | ^^^^^^^^ + | + = note: `#[warn(suspicious_double_ref_op)]` on by default + warning: call to `.deref()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:28:63 + --> $DIR/noop-method-call.rs:27:63 | LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); | ^^^^^^^^ unnecessary method call | = note: the type `&PlainType` which `deref` is being called on is the same as the type returned from `deref`, so the method call does not do anything and can be removed +warning: using `.deref()` on a double reference, which returns `&PlainType` instead of dereferencing the inner type + --> $DIR/noop-method-call.rs:31:63 + | +LL | let non_deref_type_deref: &PlainType = non_deref_type.deref(); + | ^^^^^^^^ + warning: call to `.borrow()` on a reference in this situation does nothing - --> $DIR/noop-method-call.rs:36:66 + --> $DIR/noop-method-call.rs:35:66 | LL | let non_borrow_type_borrow: &PlainType = non_borrow_type.borrow(); | ^^^^^^^^^ unnecessary method call | = note: the type `&PlainType` which `borrow` is being called on is the same as the type returned from `borrow`, so the method call does not do anything and can be removed +warning: using `.clone()` on a double reference, which returns `&str` instead of cloning the inner type + --> $DIR/noop-method-call.rs:43:44 + | +LL | let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead + | ^^^^^^^^ + warning: call to `.clone()` on a reference in this situation does nothing --> $DIR/noop-method-call.rs:48:19 | @@ -43,5 +63,5 @@ LL | non_clone_type.clone(); | = note: the type `&PlainType` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed -warning: 5 warnings emitted +warning: 8 warnings emitted diff --git a/tests/ui/lint/suspicious-double-ref-op.rs b/tests/ui/lint/suspicious-double-ref-op.rs new file mode 100644 index 0000000000000..b9bcd31c2a8b0 --- /dev/null +++ b/tests/ui/lint/suspicious-double-ref-op.rs @@ -0,0 +1,30 @@ +#![feature(lazy_cell)] +#![deny(suspicious_double_ref_op, noop_method_call)] + +pub fn clone_on_double_ref() { + let x = vec![1]; + let y = &&x; + let z: &Vec<_> = y.clone(); + //~^ ERROR using `.clone()` on a double reference, which returns `&Vec` + + println!("{:p} {:p}", *y, z); +} + +use std::sync::LazyLock; + +pub static STRS: LazyLock<&str> = LazyLock::new(|| "First"); + +// https://github.com/rust-lang/rust-clippy/issues/9272 +fn rust_clippy_issue_9272() { + let str = STRS.clone(); + println!("{str}") +} + +fn check(mut encoded: &[u8]) { + let _ = &mut encoded.clone(); + //~^ ERROR call to `.clone()` on a reference in this situation does nothing + let _ = &encoded.clone(); + //~^ ERROR call to `.clone()` on a reference in this situation does nothing +} + +fn main() {} diff --git a/tests/ui/lint/suspicious-double-ref-op.stderr b/tests/ui/lint/suspicious-double-ref-op.stderr new file mode 100644 index 0000000000000..d15487ca23865 --- /dev/null +++ b/tests/ui/lint/suspicious-double-ref-op.stderr @@ -0,0 +1,35 @@ +error: using `.clone()` on a double reference, which returns `&Vec` instead of cloning the inner type + --> $DIR/suspicious-double-ref-op.rs:7:23 + | +LL | let z: &Vec<_> = y.clone(); + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/suspicious-double-ref-op.rs:2:9 + | +LL | #![deny(suspicious_double_ref_op, noop_method_call)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: call to `.clone()` on a reference in this situation does nothing + --> $DIR/suspicious-double-ref-op.rs:24:25 + | +LL | let _ = &mut encoded.clone(); + | ^^^^^^^^ unnecessary method call + | + = note: the type `&[u8]` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed +note: the lint level is defined here + --> $DIR/suspicious-double-ref-op.rs:2:35 + | +LL | #![deny(suspicious_double_ref_op, noop_method_call)] + | ^^^^^^^^^^^^^^^^ + +error: call to `.clone()` on a reference in this situation does nothing + --> $DIR/suspicious-double-ref-op.rs:26:21 + | +LL | let _ = &encoded.clone(); + | ^^^^^^^^ unnecessary method call + | + = note: the type `&[u8]` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed + +error: aborting due to 3 previous errors + From e92806704b088471a3ced0a7dcc2aa46c99e1366 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 29 Apr 2023 06:58:36 +0000 Subject: [PATCH 22/32] fix rustdoc and core test --- library/core/tests/clone.rs | 1 + src/librustdoc/html/format.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/tests/clone.rs b/library/core/tests/clone.rs index 33ca9f2c6a3a1..aafe5ced2e97f 100644 --- a/library/core/tests/clone.rs +++ b/library/core/tests/clone.rs @@ -1,4 +1,5 @@ #[test] +#[cfg_attr(not(bootstrap), allow(suspicious_double_ref_op))] fn test_borrowed_clone() { let x = 5; let y: &i32 = &x; diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 1b445b8981e1a..297120da284b9 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -167,7 +167,7 @@ pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>( display_fn(move |f| { let mut bounds_dup = FxHashSet::default(); - for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(b.clone())).enumerate() { + for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(*b)).enumerate() { if i > 0 { f.write_str(" + ")?; } From 475378f0c6fb6261fd73b54a902a2d7d55ee47cb Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 29 Apr 2023 15:47:23 +0000 Subject: [PATCH 23/32] add match to diagnostic messages --- compiler/rustc_lint/messages.ftl | 7 ++++++- compiler/rustc_lint/src/noop_method_call.rs | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 0cef6a44b0776..71cf644eb5019 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -51,7 +51,12 @@ lint_renamed_or_removed_lint = {$msg} .suggestion = use the new name lint_suspicious_double_ref_op = - using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op} the inner type + using `.{$call}()` on a double reference, which returns `{$ty}` instead of {$op -> + *[should_not_happen] [{$op}] + [deref] dereferencing + [borrow] borrowing + [clone] cloning + } the inner type lint_unknown_lint = unknown lint: `{$name}` diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 648c0c26404c1..d054966459d85 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -103,9 +103,9 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall { let Some(name) = cx.tcx.get_diagnostic_name(i.def_id()) else { return }; let op = match name { - sym::noop_method_borrow => "borrowing", - sym::noop_method_clone => "cloning", - sym::noop_method_deref => "dereferencing", + sym::noop_method_borrow => "borrow", + sym::noop_method_clone => "clone", + sym::noop_method_deref => "deref", _ => return, }; From 4d0f7e2f393937afac76c97d33e0d96c50160510 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sun, 30 Apr 2023 03:59:11 +0200 Subject: [PATCH 24/32] review --- library/core/src/char/methods.rs | 6 +++--- library/core/src/char/mod.rs | 8 ++++---- library/core/src/escape.rs | 16 ++++++++-------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 8f149a9ece2ae..2408f17807554 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -395,9 +395,9 @@ impl char { '\t' => EscapeDebug::backslash(b't'), '\r' => EscapeDebug::backslash(b'r'), '\n' => EscapeDebug::backslash(b'n'), - '\\' => EscapeDebug::backslash(self as u8), - '"' if args.escape_double_quote => EscapeDebug::backslash(self as u8), - '\'' if args.escape_single_quote => EscapeDebug::backslash(self as u8), + '\\' => EscapeDebug::backslash(b'\\'), + '"' if args.escape_double_quote => EscapeDebug::backslash(b'"'), + '\'' if args.escape_single_quote => EscapeDebug::backslash(b'\''), _ if args.escape_grapheme_extended && self.is_grapheme_extended() => { EscapeDebug::from_unicode(self.escape_unicode()) } diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index 6383a5b5ca960..e186db7052cd0 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -293,6 +293,10 @@ impl fmt::Display for EscapeDefault { pub struct EscapeDebug(EscapeDebugInner); #[derive(Clone, Debug)] +// Note: It’s possible to manually encode the EscapeDebugInner inside of +// EscapeIterInner (e.g. with alive=254..255 indicating that data[0..4] holds +// a char) which would likely result in a more optimised code. For now we use +// the option easier to implement. enum EscapeDebugInner { Bytes(escape::EscapeIterInner<10>), Char(char), @@ -300,10 +304,6 @@ enum EscapeDebugInner { impl EscapeDebug { fn printable(chr: char) -> Self { - // Note: It’s possible to manually encode the EscapeDebugInner inside of - // EscapeIterInner (e.g. with alive=254..255 indicating that data[0..4] - // holds a char) which would likely result in a more optimised code. - // For now we use the option easier to implement. Self(EscapeDebugInner::Char(chr)) } diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index 66faa0316d1e5..c52c1fa870ed3 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -7,7 +7,7 @@ const HEX_DIGITS: [u8; 16] = *b"0123456789abcdef"; /// Escapes a byte into provided buffer; returns length of escaped /// representation. -pub(super) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range { +pub(crate) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range { let (data, len) = match byte { b'\t' => ([b'\\', b't', 0, 0], 2), b'\r' => ([b'\\', b'r', 0, 0], 2), @@ -25,11 +25,10 @@ pub(super) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range { } /// Escapes a character into provided buffer using `\u{NNNN}` representation. -pub(super) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range { - let ch = (ch as u32) & 0x1f_ffff; - +pub(crate) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range { output[9] = b'}'; + let ch = ch as u32; output[3] = HEX_DIGITS[((ch >> 20) & 15) as usize]; output[4] = HEX_DIGITS[((ch >> 16) & 15) as usize]; output[5] = HEX_DIGITS[((ch >> 12) & 15) as usize]; @@ -50,16 +49,17 @@ pub(super) fn escape_unicode_into(output: &mut [u8; 10], ch: char) -> Range /// This is essentially equivalent to array’s IntoIter except that indexes are /// limited to u8 to reduce size of the structure. #[derive(Clone, Debug)] -pub(super) struct EscapeIterInner { +pub(crate) struct EscapeIterInner { // Invariant: data[alive] is all ASCII. - pub(super) data: [u8; N], + pub(crate) data: [u8; N], // Invariant: alive.start <= alive.end <= N. - pub(super) alive: Range, + pub(crate) alive: Range, } impl EscapeIterInner { pub fn new(data: [u8; N], alive: Range) -> Self { + const { assert!(N < 256) }; debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}"); let this = Self { data, alive }; debug_assert!(this.as_bytes().is_ascii(), "Expected ASCII, got {:?}", this.as_bytes()); @@ -67,7 +67,7 @@ impl EscapeIterInner { } fn as_bytes(&self) -> &[u8] { - &self.data[(self.alive.start as usize)..(self.alive.end as usize)] + &self.data[usize::from(self.alive.start)..usize::from(self.alive.end)] } pub fn as_str(&self) -> &str { From 76c99470244777da83fa4e1fef480d6d13af2a80 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Sun, 30 Apr 2023 15:40:54 +0200 Subject: [PATCH 25/32] a bit more usize::from --- library/core/src/escape.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index c52c1fa870ed3..20ac3cf027f87 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -17,7 +17,9 @@ pub(crate) fn escape_ascii_into(output: &mut [u8; 4], byte: u8) -> Range { b'"' => ([b'\\', b'"', 0, 0], 2), b'\x20'..=b'\x7e' => ([byte, 0, 0, 0], 1), _ => { - ([b'\\', b'x', HEX_DIGITS[(byte >> 4) as usize], HEX_DIGITS[(byte & 0xf) as usize]], 4) + let hi = HEX_DIGITS[usize::from(byte >> 4)]; + let lo = HEX_DIGITS[usize::from(byte & 0xf)]; + ([b'\\', b'x', hi, lo], 4) } }; *output = data; From c31754651da17b207fa7fb94c2f3ba2c188aa0b1 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 1 May 2023 11:45:51 +0000 Subject: [PATCH 26/32] Fix `StructuralEq` impls for `&T`, `[T]` and `[T; N]` (`StructuralEq` is shallow for some reason...) --- library/core/src/marker.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index a1cad6e9992d1..2ebe42aef21d7 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -277,9 +277,9 @@ marker_impls! { bool, char, str /* Technically requires `[u8]: StructuralEq` */, - {T: StructuralEq, const N: usize} [T; N], - {T: StructuralEq} [T], - {T: ?Sized + StructuralEq} &T, + {T, const N: usize} [T; N], + {T} [T], + {T: ?Sized} &T, } /// Types whose values can be duplicated simply by copying bits. From 0bcfff48a532f1ab974dff495ce006ec0604300a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 18 Apr 2023 20:57:16 +0000 Subject: [PATCH 27/32] Simplify type_parameter_bounds_in_generics --- .../rustc_hir_analysis/src/astconv/mod.rs | 17 ++--- .../src/collect/predicates_of.rs | 70 ++++++++----------- 2 files changed, 34 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 709dea43d84aa..40c689537881a 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1007,7 +1007,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], ) -> Bounds<'tcx> { - self.compute_bounds_inner(param_ty, ast_bounds) + let mut bounds = Bounds::default(); + self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty()); + debug!(?bounds); + + bounds } /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type @@ -1029,17 +1033,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - self.compute_bounds_inner(param_ty, &result) - } - - fn compute_bounds_inner( - &self, - param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], - ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); - - self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty()); + self.add_bounds(param_ty, result.iter(), &mut bounds, ty::List::empty()); debug!(?bounds); bounds diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 8c414521b7653..935b561945ca2 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -774,32 +774,34 @@ impl<'tcx> ItemCtxt<'tcx> { only_self_bounds: OnlySelfBounds, assoc_name: Option, ) -> Vec<(ty::Predicate<'tcx>, Span)> { - ast_generics - .predicates - .iter() - .filter_map(|wp| match wp { - hir::WherePredicate::BoundPredicate(bp) => Some(bp), - _ => None, - }) - .flat_map(|bp| { - let bt = if bp.is_param_bound(param_def_id.to_def_id()) { - Some(ty) - } else if !only_self_bounds.0 { - Some(self.to_ty(bp.bounded_ty)) - } else { - None - }; - let bvars = self.tcx.late_bound_vars(bp.hir_id); - - bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter( - |(_, b, _)| match assoc_name { - Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), - None => true, - }, - ) - }) - .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars)) - .collect() + let mut bounds = Bounds::default(); + + for predicate in ast_generics.predicates { + let hir::WherePredicate::BoundPredicate(predicate) = predicate else { + continue; + }; + + let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) { + ty + } else if !only_self_bounds.0 { + self.to_ty(predicate.bounded_ty) + } else { + continue; + }; + + let bound_vars = self.tcx.late_bound_vars(predicate.hir_id); + self.astconv().add_bounds( + bound_ty, + predicate.bounds.iter().filter(|bound| { + assoc_name + .map_or(true, |assoc_name| self.bound_defines_assoc_item(bound, assoc_name)) + }), + &mut bounds, + bound_vars, + ); + } + + bounds.predicates().collect() } #[instrument(level = "trace", skip(self))] @@ -817,19 +819,3 @@ impl<'tcx> ItemCtxt<'tcx> { } } } - -/// Converts a specific `GenericBound` from the AST into a set of -/// predicates that apply to the self type. A vector is returned -/// because this can be anywhere from zero predicates (`T: ?Sized` adds no -/// predicates) to one (`T: Foo`) to many (`T: Bar` adds `T: Bar` -/// and `::X == i32`). -fn predicates_from_bound<'tcx>( - astconv: &dyn AstConv<'tcx>, - param_ty: Ty<'tcx>, - bound: &'tcx hir::GenericBound<'tcx>, - bound_vars: &'tcx ty::List, -) -> Vec<(ty::Predicate<'tcx>, Span)> { - let mut bounds = Bounds::default(); - astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars); - bounds.predicates().collect() -} From 8ea71f264e384877bc1f991ad232141b1b7808a5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 18 Apr 2023 23:55:05 +0000 Subject: [PATCH 28/32] Do not consider associated type bounds for super_predicates_that_define_assoc_type --- .../rustc_hir_analysis/src/astconv/mod.rs | 57 +++++++++++++++++-- .../src/collect/item_bounds.rs | 6 +- .../src/collect/predicates_of.rs | 18 +++--- compiler/rustc_hir_analysis/src/lib.rs | 3 +- .../supertrait-defines-ty.rs | 26 +++++++++ 5 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 tests/ui/associated-type-bounds/supertrait-defines-ty.rs diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 40c689537881a..6cb008bc5f8a0 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -56,6 +56,9 @@ use std::slice; #[derive(Debug)] pub struct PathSeg(pub DefId, pub usize); +#[derive(Copy, Clone, Debug)] +pub struct OnlySelfBounds(pub bool); + pub trait AstConv<'tcx> { fn tcx(&self) -> TyCtxt<'tcx>; @@ -670,6 +673,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args: &GenericArgs<'_>, infer_args: bool, self_ty: Ty<'tcx>, + only_self_bounds: OnlySelfBounds, ) -> GenericArgCountResult { let (substs, arg_count) = self.create_substs_for_ast_path( trait_ref_span, @@ -706,6 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &mut dup_bindings, binding_span.unwrap_or(binding.span), constness, + only_self_bounds, ); // Okay to ignore `Err` because of `ErrorGuaranteed` (see above). } @@ -741,6 +746,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, + only_self_bounds: OnlySelfBounds, ) -> GenericArgCountResult { let hir_id = trait_ref.hir_ref_id; let binding_span = None; @@ -766,6 +772,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, self_ty, + only_self_bounds, ) } @@ -777,6 +784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args: &GenericArgs<'_>, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, + only_self_bounds: OnlySelfBounds, ) { let binding_span = Some(span); let constness = ty::BoundConstness::NotConst; @@ -799,6 +807,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, self_ty, + only_self_bounds, ); } @@ -947,6 +956,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ast_bounds: I, bounds: &mut Bounds<'tcx>, bound_vars: &'tcx ty::List, + only_self_bounds: OnlySelfBounds, ) { for ast_bound in ast_bounds { match ast_bound { @@ -964,11 +974,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { param_ty, bounds, false, + only_self_bounds, ); } &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { self.instantiate_lang_item_trait_ref( - lang_item, span, hir_id, args, param_ty, bounds, + lang_item, + span, + hir_id, + args, + param_ty, + bounds, + only_self_bounds, ); } hir::GenericBound::Outlives(lifetime) => { @@ -1006,9 +1023,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], + only_self_bounds: OnlySelfBounds, ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); - self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty()); + self.add_bounds( + param_ty, + ast_bounds.iter(), + &mut bounds, + ty::List::empty(), + only_self_bounds, + ); debug!(?bounds); bounds @@ -1034,7 +1058,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } let mut bounds = Bounds::default(); - self.add_bounds(param_ty, result.iter(), &mut bounds, ty::List::empty()); + self.add_bounds( + param_ty, + result.iter(), + &mut bounds, + ty::List::empty(), + OnlySelfBounds(true), + ); debug!(?bounds); bounds @@ -1057,6 +1087,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dup_bindings: &mut FxHashMap, path_span: Span, constness: ty::BoundConstness, + only_self_bounds: OnlySelfBounds, ) -> Result<(), ErrorGuaranteed> { // Given something like `U: SomeTrait`, we want to produce a // predicate like `::T = X`. This is somewhat @@ -1356,8 +1387,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // parameter to have a skipped binder. - let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder()); - self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars()); + // + // NOTE: If `only_self_bounds` is true, do NOT expand this associated + // type bound into a trait predicate, since we only want to add predicates + // for the `Self` type. + if !only_self_bounds.0 { + let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder()); + self.add_bounds( + param_ty, + ast_bounds.iter(), + bounds, + projection_ty.bound_vars(), + only_self_bounds, + ); + } } } Ok(()) @@ -1398,6 +1441,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dummy_self, &mut bounds, false, + // FIXME: This should be `true`, but we don't really handle + // associated type bounds or type aliases in objects in a way + // that makes this meaningful, I think. + OnlySelfBounds(false), ) { potential_assoc_types.extend(cur_potential_assoc_types); } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 80d6bc7db9e8f..948b903e509ad 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -1,5 +1,5 @@ use super::ItemCtxt; -use crate::astconv::AstConv; +use crate::astconv::{AstConv, OnlySelfBounds}; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::subst::InternalSubsts; @@ -26,7 +26,7 @@ fn associated_type_bounds<'tcx>( ); let icx = ItemCtxt::new(tcx, assoc_item_def_id); - let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds); + let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false)); // Associated types are implicitly sized unless a `?Sized` bound is found icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); @@ -67,7 +67,7 @@ fn opaque_type_bounds<'tcx>( ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { ty::print::with_no_queries!({ let icx = ItemCtxt::new(tcx, opaque_def_id); - let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds); + let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false)); // Opaque types are implicitly sized unless a `?Sized` bound is found icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); debug!(?bounds); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 935b561945ca2..b142e4ae1a651 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1,4 +1,4 @@ -use crate::astconv::AstConv; +use crate::astconv::{AstConv, OnlySelfBounds}; use crate::bounds::Bounds; use crate::collect::ItemCtxt; use crate::constrained_generic_params as cgp; @@ -14,9 +14,6 @@ use rustc_middle::ty::{GenericPredicates, ToPredicate}; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; -#[derive(Debug)] -struct OnlySelfBounds(bool); - /// Returns a list of all type predicates (explicit and implicit) for the definition with /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus /// `Self: Trait` predicates for traits. @@ -225,7 +222,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } let mut bounds = Bounds::default(); - icx.astconv().add_bounds(ty, bound_pred.bounds.iter(), &mut bounds, bound_vars); + icx.astconv().add_bounds( + ty, + bound_pred.bounds.iter(), + &mut bounds, + bound_vars, + OnlySelfBounds(false), + ); predicates.extend(bounds.predicates()); } @@ -608,7 +611,7 @@ pub(super) fn implied_predicates_with_filter( let (superbounds, where_bounds_that_match) = match filter { PredicateFilter::All => ( // Convert the bounds that follow the colon (or equal in trait aliases) - icx.astconv().compute_bounds(self_param_ty, bounds), + icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)), // Also include all where clause bounds icx.type_parameter_bounds_in_generics( generics, @@ -620,7 +623,7 @@ pub(super) fn implied_predicates_with_filter( ), PredicateFilter::SelfOnly => ( // Convert the bounds that follow the colon (or equal in trait aliases) - icx.astconv().compute_bounds(self_param_ty, bounds), + icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)), // Include where clause bounds for `Self` icx.type_parameter_bounds_in_generics( generics, @@ -798,6 +801,7 @@ impl<'tcx> ItemCtxt<'tcx> { }), &mut bounds, bound_vars, + only_self_bounds, ); } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index a4b797f77f7fe..961457b75794a 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -116,7 +116,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, use std::ops::Not; -use astconv::AstConv; +use astconv::{AstConv, OnlySelfBounds}; use bounds::Bounds; fluent_messages! { "../messages.ftl" } @@ -531,6 +531,7 @@ pub fn hir_trait_to_predicates<'tcx>( self_ty, &mut bounds, true, + OnlySelfBounds(false), ); bounds diff --git a/tests/ui/associated-type-bounds/supertrait-defines-ty.rs b/tests/ui/associated-type-bounds/supertrait-defines-ty.rs new file mode 100644 index 0000000000000..b6f37cb908e4e --- /dev/null +++ b/tests/ui/associated-type-bounds/supertrait-defines-ty.rs @@ -0,0 +1,26 @@ +// check-pass + +// Make sure that we don't look into associated type bounds when looking for +// supertraits that define an associated type. Fixes #76593. + +#![feature(associated_type_bounds)] + +trait Load: Sized { + type Blob; +} + +trait Primitive: Load {} + +trait BlobPtr: Primitive {} + +trait CleanPtr: Load { + fn to_blob(&self) -> Self::Blob; +} + +impl Load for () { + type Blob = Self; +} +impl Primitive for () {} +impl BlobPtr for () {} + +fn main() {} From bec7193072649d7493091de1191fd739645037d6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 19 Apr 2023 00:13:53 +0000 Subject: [PATCH 29/32] Don't use implied trait predicates in gather_explicit_predicates_of --- .../src/collect/predicates_of.rs | 17 +- tests/rustdoc-ui/issues/issue-105742.rs | 8 + tests/rustdoc-ui/issues/issue-105742.stderr | 198 ++++++++++++++---- tests/ui/associated-type-bounds/duplicate.rs | 3 + .../associated-type-bounds/duplicate.stderr | 60 ++++-- .../assoc_const_eq_diagnostic.rs | 1 + .../assoc_const_eq_diagnostic.stderr | 16 +- tests/ui/error-codes/E0719.rs | 1 + tests/ui/error-codes/E0719.stderr | 12 +- .../super-traits-fail-2.nn.stderr | 8 +- .../super-traits-fail-2.ny.stderr | 8 +- .../super-traits-fail-2.rs | 1 + .../super-traits-fail-2.yn.stderr | 4 +- .../super-traits-fail-2.yy.stderr | 4 +- .../super-traits-fail-3.nn.stderr | 10 +- .../super-traits-fail-3.ny.stderr | 8 +- .../super-traits-fail-3.rs | 1 + .../super-traits-fail-3.yn.stderr | 2 +- tests/ui/traits/issue-38404.rs | 1 + tests/ui/traits/issue-38404.stderr | 16 +- .../typeck-builtin-bound-type-parameters.rs | 1 + ...ypeck-builtin-bound-type-parameters.stderr | 18 +- 22 files changed, 319 insertions(+), 79 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index b142e4ae1a651..83470342a7660 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -96,8 +96,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen | ItemKind::Struct(_, generics) | ItemKind::Union(_, generics) => generics, - ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => { - is_trait = Some(ty::TraitRef::identity(tcx, def_id.to_def_id())); + ItemKind::Trait(_, _, generics, self_bounds, ..) + | ItemKind::TraitAlias(generics, self_bounds) => { + is_trait = Some(self_bounds); generics } ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics, @@ -119,10 +120,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // Below we'll consider the bounds on the type parameters (including `Self`) // and the explicit where-clauses, but to get the full set of predicates - // on a trait we need to add in the supertrait bounds and bounds found on - // associated types. - if let Some(_trait_ref) = is_trait { - predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned()); + // on a trait we must also consider the bounds that follow the trait's name, + // like `trait Foo: A + B + C`. + if let Some(self_bounds) = is_trait { + predicates.extend( + icx.astconv() + .compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false)) + .predicates(), + ); } // In default impls, we can assume that the self type implements diff --git a/tests/rustdoc-ui/issues/issue-105742.rs b/tests/rustdoc-ui/issues/issue-105742.rs index 8f4172c0cbbbf..1fbb70c7808ee 100644 --- a/tests/rustdoc-ui/issues/issue-105742.rs +++ b/tests/rustdoc-ui/issues/issue-105742.rs @@ -19,6 +19,8 @@ pub trait SVec: Index< //~| missing generics for associated type `SVec::Item` //~| missing generics for associated type `SVec::Item` //~| missing generics for associated type `SVec::Item` + //~| missing generics for associated type `SVec::Item` + //~| missing generics for associated type `SVec::Item` Output = ::Item, //~^ expected 1 lifetime argument //~| expected 1 generic argument @@ -26,6 +28,8 @@ pub trait SVec: Index< //~| missing generics for associated type `SVec::Item` //~| missing generics for associated type `SVec::Item` //~| missing generics for associated type `SVec::Item` + //~| missing generics for associated type `SVec::Item` + //~| missing generics for associated type `SVec::Item` Output = ::Item> as SVec>::Item, //~^ expected 1 lifetime argument //~| expected 1 generic argument @@ -34,11 +38,15 @@ pub trait SVec: Index< //~| missing generics for associated type `SVec::Item` //~| missing generics for associated type `SVec::Item` //~| missing generics for associated type `SVec::Item` + //~| missing generics for associated type `SVec::Item` + //~| missing generics for associated type `SVec::Item` //~| expected 1 generic argument //~| missing generics for associated type `SVec::Item` //~| missing generics for associated type `SVec::Item` //~| missing generics for associated type `SVec::Item` //~| missing generics for associated type `SVec::Item` + //~| missing generics for associated type `SVec::Item` + //~| missing generics for associated type `SVec::Item` > { type Item<'a, T>; diff --git a/tests/rustdoc-ui/issues/issue-105742.stderr b/tests/rustdoc-ui/issues/issue-105742.stderr index cd53762ef9b2d..b63176c914905 100644 --- a/tests/rustdoc-ui/issues/issue-105742.stderr +++ b/tests/rustdoc-ui/issues/issue-105742.stderr @@ -5,7 +5,7 @@ LL | ::Item, | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ -- @@ -21,7 +21,7 @@ LL | ::Item, | ^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ - @@ -31,13 +31,13 @@ LL | ::Item, | +++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:22:37 + --> $DIR/issue-105742.rs:24:37 | LL | Output = ::Item, | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ -- @@ -47,13 +47,13 @@ LL | Output = ::Item<'a>, | ++++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:22:37 + --> $DIR/issue-105742.rs:24:37 | LL | Output = ::Item, | ^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ - @@ -63,13 +63,13 @@ LL | Output = ::Item, | +++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:29:30 + --> $DIR/issue-105742.rs:33:30 | LL | Output = ::Item> as SVec>::Item, | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ -- @@ -79,13 +79,13 @@ LL | Output = ::Item<'a>> as SVec>::Item, | ++++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:29:30 + --> $DIR/issue-105742.rs:33:30 | LL | Output = ::Item> as SVec>::Item, | ^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ - @@ -95,13 +95,13 @@ LL | Output = ::Item> as SVec>::Item, | +++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:29:46 + --> $DIR/issue-105742.rs:33:46 | LL | Output = ::Item> as SVec>::Item, | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ -- @@ -111,13 +111,13 @@ LL | Output = ::Item> as SVec>::Item<'a>, | ++++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:29:46 + --> $DIR/issue-105742.rs:33:46 | LL | Output = ::Item> as SVec>::Item, | ^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ - @@ -133,7 +133,7 @@ LL | pub fn next<'a, T>(s: &'a mut dyn SVec) { | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ -- @@ -149,7 +149,7 @@ LL | pub fn next<'a, T>(s: &'a mut dyn SVec) { | ^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ - @@ -165,7 +165,7 @@ LL | ::Item, | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ -- @@ -181,7 +181,7 @@ LL | ::Item, | ^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ - @@ -191,13 +191,13 @@ LL | ::Item, | +++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:22:37 + --> $DIR/issue-105742.rs:24:37 | LL | Output = ::Item, | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ -- @@ -207,13 +207,13 @@ LL | Output = ::Item<'a>, | ++++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:22:37 + --> $DIR/issue-105742.rs:24:37 | LL | Output = ::Item, | ^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ - @@ -223,13 +223,13 @@ LL | Output = ::Item, | +++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:29:30 + --> $DIR/issue-105742.rs:33:30 | LL | Output = ::Item> as SVec>::Item, | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ -- @@ -239,13 +239,13 @@ LL | Output = ::Item<'a>> as SVec>::Item, | ++++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:29:30 + --> $DIR/issue-105742.rs:33:30 | LL | Output = ::Item> as SVec>::Item, | ^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ - @@ -255,13 +255,13 @@ LL | Output = ::Item> as SVec>::Item, | +++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:29:46 + --> $DIR/issue-105742.rs:33:46 | LL | Output = ::Item> as SVec>::Item, | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ -- @@ -271,13 +271,13 @@ LL | Output = ::Item> as SVec>::Item<'a>, | ++++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:29:46 + --> $DIR/issue-105742.rs:33:46 | LL | Output = ::Item> as SVec>::Item, | ^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ - @@ -317,13 +317,141 @@ LL | | > { | |__^ ...because it uses `Self` as a type parameter error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:45:38 + --> $DIR/issue-105742.rs:15:21 + | +LL | ::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:51:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | ::Item<'a>, + | ++++ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:15:21 + | +LL | ::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:51:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | ::Item, + | +++ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:24:37 + | +LL | Output = ::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:51:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = ::Item<'a>, + | ++++ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:24:37 + | +LL | Output = ::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:51:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = ::Item, + | +++ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:33:30 + | +LL | Output = ::Item> as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:51:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = ::Item<'a>> as SVec>::Item, + | ++++ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:33:30 + | +LL | Output = ::Item> as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:51:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = ::Item> as SVec>::Item, + | +++ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:33:46 + | +LL | Output = ::Item> as SVec>::Item, + | ^^^^ expected 1 lifetime argument + | +note: associated type defined here, with 1 lifetime parameter: `'a` + --> $DIR/issue-105742.rs:51:10 + | +LL | type Item<'a, T>; + | ^^^^ -- +help: add missing lifetime argument + | +LL | Output = ::Item> as SVec>::Item<'a>, + | ++++ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:33:46 + | +LL | Output = ::Item> as SVec>::Item, + | ^^^^ expected 1 generic argument + | +note: associated type defined here, with 1 generic parameter: `T` + --> $DIR/issue-105742.rs:51:10 + | +LL | type Item<'a, T>; + | ^^^^ - +help: add missing generic argument + | +LL | Output = ::Item> as SVec>::Item, + | +++ + +error[E0107]: missing generics for associated type `SVec::Item` + --> $DIR/issue-105742.rs:53:38 | LL | fn len(&self) -> ::Item; | ^^^^ expected 1 lifetime argument | note: associated type defined here, with 1 lifetime parameter: `'a` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ -- @@ -333,13 +461,13 @@ LL | fn len(&self) -> ::Item<'_>; | ++++ error[E0107]: missing generics for associated type `SVec::Item` - --> $DIR/issue-105742.rs:45:38 + --> $DIR/issue-105742.rs:53:38 | LL | fn len(&self) -> ::Item; | ^^^^ expected 1 generic argument | note: associated type defined here, with 1 generic parameter: `T` - --> $DIR/issue-105742.rs:43:10 + --> $DIR/issue-105742.rs:51:10 | LL | type Item<'a, T>; | ^^^^ - @@ -348,7 +476,7 @@ help: add missing generic argument LL | fn len(&self) -> ::Item; | +++ -error: aborting due to 21 previous errors +error: aborting due to 29 previous errors Some errors have detailed explanations: E0038, E0107. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/associated-type-bounds/duplicate.rs b/tests/ui/associated-type-bounds/duplicate.rs index f67410986e559..4b8bf52c37492 100644 --- a/tests/ui/associated-type-bounds/duplicate.rs +++ b/tests/ui/associated-type-bounds/duplicate.rs @@ -193,10 +193,13 @@ trait TRI3> {} //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] trait TRS1: Iterator {} //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +//~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] trait TRS2: Iterator {} //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +//~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] trait TRS3: Iterator {} //~^ ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] +//~| ERROR the value of the associated type `Item` (from trait `Iterator`) is already specified [E0719] trait TRW1 where T: Iterator, diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr index c3061327f566e..08721eff7b0ce 100644 --- a/tests/ui/associated-type-bounds/duplicate.stderr +++ b/tests/ui/associated-type-bounds/duplicate.stderr @@ -367,7 +367,23 @@ LL | trait TRS1: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:196:34 + --> $DIR/duplicate.rs:194:34 + | +LL | trait TRS1: Iterator {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:197:34 + | +LL | trait TRS2: Iterator {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:197:34 | LL | trait TRS2: Iterator {} | ---------- ^^^^^^^^^^ re-bound here @@ -375,7 +391,15 @@ LL | trait TRS2: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:198:37 + --> $DIR/duplicate.rs:200:37 + | +LL | trait TRS3: Iterator {} + | ------------- ^^^^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/duplicate.rs:200:37 | LL | trait TRS3: Iterator {} | ------------- ^^^^^^^^^^^^^ re-bound here @@ -383,7 +407,7 @@ LL | trait TRS3: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:202:29 + --> $DIR/duplicate.rs:205:29 | LL | T: Iterator, | ---------- ^^^^^^^^^^ re-bound here @@ -391,7 +415,7 @@ LL | T: Iterator, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:208:29 + --> $DIR/duplicate.rs:211:29 | LL | T: Iterator, | ---------- ^^^^^^^^^^ re-bound here @@ -399,7 +423,7 @@ LL | T: Iterator, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:214:32 + --> $DIR/duplicate.rs:217:32 | LL | T: Iterator, | ------------- ^^^^^^^^^^^^^ re-bound here @@ -407,7 +431,7 @@ LL | T: Iterator, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:220:32 + --> $DIR/duplicate.rs:223:32 | LL | Self: Iterator, | ---------- ^^^^^^^^^^ re-bound here @@ -415,7 +439,7 @@ LL | Self: Iterator, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:220:32 + --> $DIR/duplicate.rs:223:32 | LL | Self: Iterator, | ---------- ^^^^^^^^^^ re-bound here @@ -423,7 +447,7 @@ LL | Self: Iterator, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:227:32 + --> $DIR/duplicate.rs:230:32 | LL | Self: Iterator, | ---------- ^^^^^^^^^^ re-bound here @@ -431,7 +455,7 @@ LL | Self: Iterator, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:227:32 + --> $DIR/duplicate.rs:230:32 | LL | Self: Iterator, | ---------- ^^^^^^^^^^ re-bound here @@ -439,7 +463,7 @@ LL | Self: Iterator, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:234:35 + --> $DIR/duplicate.rs:237:35 | LL | Self: Iterator, | ------------- ^^^^^^^^^^^^^ re-bound here @@ -447,7 +471,7 @@ LL | Self: Iterator, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:234:35 + --> $DIR/duplicate.rs:237:35 | LL | Self: Iterator, | ------------- ^^^^^^^^^^^^^ re-bound here @@ -455,7 +479,7 @@ LL | Self: Iterator, | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:252:40 + --> $DIR/duplicate.rs:255:40 | LL | type TADyn1 = dyn Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -463,7 +487,7 @@ LL | type TADyn1 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:254:44 + --> $DIR/duplicate.rs:257:44 | LL | type TADyn2 = Box>; | ---------- ^^^^^^^^^^ re-bound here @@ -471,7 +495,7 @@ LL | type TADyn2 = Box>; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:256:43 + --> $DIR/duplicate.rs:259:43 | LL | type TADyn3 = dyn Iterator; | ------------- ^^^^^^^^^^^^^ re-bound here @@ -479,7 +503,7 @@ LL | type TADyn3 = dyn Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:240:34 + --> $DIR/duplicate.rs:243:34 | LL | type A: Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -487,7 +511,7 @@ LL | type A: Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:244:34 + --> $DIR/duplicate.rs:247:34 | LL | type A: Iterator; | ---------- ^^^^^^^^^^ re-bound here @@ -495,13 +519,13 @@ LL | type A: Iterator; | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/duplicate.rs:248:37 + --> $DIR/duplicate.rs:251:37 | LL | type A: Iterator; | ------------- ^^^^^^^^^^^^^ re-bound here | | | `Item` bound here first -error: aborting due to 63 previous errors +error: aborting due to 66 previous errors For more information about this error, try `rustc --explain E0719`. diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.rs b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs index 4d0aaf88e403b..bf8202ac15267 100644 --- a/tests/ui/const-generics/assoc_const_eq_diagnostic.rs +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs @@ -10,6 +10,7 @@ pub trait Parse { pub trait CoolStuff: Parse {} //~^ ERROR expected associated constant bound +//~| ERROR expected associated constant bound //~| ERROR expected type fn no_help() -> Mode::Cool {} diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr index ba727ee0ea308..d7e5e50cba82d 100644 --- a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr @@ -8,7 +8,7 @@ LL | pub trait CoolStuff: Parse {} | help: try using the variant's enum: `Mode` error[E0573]: expected type, found variant `Mode::Cool` - --> $DIR/assoc_const_eq_diagnostic.rs:15:17 + --> $DIR/assoc_const_eq_diagnostic.rs:16:17 | LL | fn no_help() -> Mode::Cool {} | ^^^^^^^^^^ @@ -28,6 +28,18 @@ note: associated constant defined here LL | const MODE: Mode; | ^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: expected associated constant bound, found type + --> $DIR/assoc_const_eq_diagnostic.rs:11:28 + | +LL | pub trait CoolStuff: Parse {} + | ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }` + | +note: associated constant defined here + --> $DIR/assoc_const_eq_diagnostic.rs:8:5 + | +LL | const MODE: Mode; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0573`. diff --git a/tests/ui/error-codes/E0719.rs b/tests/ui/error-codes/E0719.rs index 3311e190937cc..cbf1bb219a07b 100644 --- a/tests/ui/error-codes/E0719.rs +++ b/tests/ui/error-codes/E0719.rs @@ -1,5 +1,6 @@ trait Foo: Iterator {} //~^ ERROR is already specified +//~| ERROR is already specified type Unit = (); diff --git a/tests/ui/error-codes/E0719.stderr b/tests/ui/error-codes/E0719.stderr index b342d634334d0..e302f406d02b0 100644 --- a/tests/ui/error-codes/E0719.stderr +++ b/tests/ui/error-codes/E0719.stderr @@ -7,13 +7,21 @@ LL | trait Foo: Iterator {} | `Item` bound here first error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified - --> $DIR/E0719.rs:6:42 + --> $DIR/E0719.rs:1:33 + | +LL | trait Foo: Iterator {} + | ---------- ^^^^^^^^^^ re-bound here + | | + | `Item` bound here first + +error[E0719]: the value of the associated type `Item` (from trait `Iterator`) is already specified + --> $DIR/E0719.rs:7:42 | LL | fn test() -> Box> { | --------- ^^^^^^^^^^^ re-bound here | | | `Item` bound here first -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0719`. diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr index d4f42b787e4da..97f346e8c1dba 100644 --- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.nn.stderr @@ -4,5 +4,11 @@ error: ~const can only be applied to `#[const_trait]` traits LL | trait Bar: ~const Foo {} | ^^^ -error: aborting due to previous error +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-2.rs:11:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr index d4f42b787e4da..97f346e8c1dba 100644 --- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.ny.stderr @@ -4,5 +4,11 @@ error: ~const can only be applied to `#[const_trait]` traits LL | trait Bar: ~const Foo {} | ^^^ -error: aborting due to previous error +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-2.rs:11:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs index d183efde2df1f..ecb06271cd9b4 100644 --- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.rs @@ -10,6 +10,7 @@ trait Foo { #[cfg_attr(any(yy, ny), const_trait)] trait Bar: ~const Foo {} //[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` +//[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]` const fn foo(x: &T) { x.a(); diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr index 13fc719f28c5c..c9fa1955498d4 100644 --- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yn.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:15:7 + --> $DIR/super-traits-fail-2.rs:16:7 | LL | x.a(); | ^ the trait `~const Foo` is not implemented for `T` | note: the trait `Foo` is implemented for `T`, but that implementation is not `const` - --> $DIR/super-traits-fail-2.rs:15:5 + --> $DIR/super-traits-fail-2.rs:16:5 | LL | x.a(); | ^ diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr index 13fc719f28c5c..c9fa1955498d4 100644 --- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-2.yy.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: ~const Foo` is not satisfied - --> $DIR/super-traits-fail-2.rs:15:7 + --> $DIR/super-traits-fail-2.rs:16:7 | LL | x.a(); | ^ the trait `~const Foo` is not implemented for `T` | note: the trait `Foo` is implemented for `T`, but that implementation is not `const` - --> $DIR/super-traits-fail-2.rs:15:5 + --> $DIR/super-traits-fail-2.rs:16:5 | LL | x.a(); | ^ diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr index d433e1cfa698a..fdc6b805889ed 100644 --- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.nn.stderr @@ -5,10 +5,16 @@ LL | trait Bar: ~const Foo {} | ^^^ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:15:24 + --> $DIR/super-traits-fail-3.rs:12:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:16:24 | LL | const fn foo(x: &T) { | ^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr index 2a7e8e00bc78c..7375b8c819ca7 100644 --- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.ny.stderr @@ -4,5 +4,11 @@ error: ~const can only be applied to `#[const_trait]` traits LL | trait Bar: ~const Foo {} | ^^^ -error: aborting due to previous error +error: ~const can only be applied to `#[const_trait]` traits + --> $DIR/super-traits-fail-3.rs:12:19 + | +LL | trait Bar: ~const Foo {} + | ^^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs index 70d2936d3b259..8cf64944ac1c3 100644 --- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.rs @@ -11,6 +11,7 @@ trait Foo { #[cfg_attr(any(yy, ny), const_trait)] trait Bar: ~const Foo {} //[ny,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` +//[ny,nn]~| ERROR: ~const can only be applied to `#[const_trait]` const fn foo(x: &T) { //[yn,nn]~^ ERROR: ~const can only be applied to `#[const_trait]` diff --git a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr index e5978c12a0981..7a152914b6964 100644 --- a/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr +++ b/tests/ui/rfc-2632-const-trait-impl/super-traits-fail-3.yn.stderr @@ -1,5 +1,5 @@ error: ~const can only be applied to `#[const_trait]` traits - --> $DIR/super-traits-fail-3.rs:15:24 + --> $DIR/super-traits-fail-3.rs:16:24 | LL | const fn foo(x: &T) { | ^^^ diff --git a/tests/ui/traits/issue-38404.rs b/tests/ui/traits/issue-38404.rs index 1a92acc34042b..05921b2c36e46 100644 --- a/tests/ui/traits/issue-38404.rs +++ b/tests/ui/traits/issue-38404.rs @@ -2,5 +2,6 @@ trait A: std::ops::Add + Sized {} trait B: A {} trait C: A> {} //~^ ERROR the trait `B` cannot be made into an object +//~| ERROR the trait `B` cannot be made into an object fn main() {} diff --git a/tests/ui/traits/issue-38404.stderr b/tests/ui/traits/issue-38404.stderr index d7721d7e69cd4..f8625f53b78fa 100644 --- a/tests/ui/traits/issue-38404.stderr +++ b/tests/ui/traits/issue-38404.stderr @@ -12,6 +12,20 @@ LL | trait A: std::ops::Add + Sized {} LL | trait B: A {} | - this trait cannot be made into an object... -error: aborting due to previous error +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/issue-38404.rs:3:15 + | +LL | trait C: A> {} + | ^^^^^^^^^^^^^^^^^^^^^^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/issue-38404.rs:1:13 + | +LL | trait A: std::ops::Add + Sized {} + | ^^^^^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter +LL | trait B: A {} + | - this trait cannot be made into an object... + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs b/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs index 7ff9199f63c5c..e7e62c077394e 100644 --- a/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs +++ b/tests/ui/typeck/typeck-builtin-bound-type-parameters.rs @@ -3,6 +3,7 @@ fn foo1, U>(x: T) {} trait Trait: Copy {} //~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied +//~| ERROR trait takes 0 generic arguments but 1 generic argument was supplied struct MyStruct1>; //~^ ERROR trait takes 0 generic arguments but 1 generic argument was supplied diff --git a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr index a71fd95365820..a3517af877cc7 100644 --- a/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr +++ b/tests/ui/typeck/typeck-builtin-bound-type-parameters.stderr @@ -15,7 +15,15 @@ LL | trait Trait: Copy {} | expected 0 generic arguments error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/typeck-builtin-bound-type-parameters.rs:7:21 + --> $DIR/typeck-builtin-bound-type-parameters.rs:4:14 + | +LL | trait Trait: Copy {} + | ^^^^---------- help: remove these generics + | | + | expected 0 generic arguments + +error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied + --> $DIR/typeck-builtin-bound-type-parameters.rs:8:21 | LL | struct MyStruct1>; | ^^^^--- help: remove these generics @@ -23,7 +31,7 @@ LL | struct MyStruct1>; | expected 0 generic arguments error[E0107]: trait takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/typeck-builtin-bound-type-parameters.rs:10:25 + --> $DIR/typeck-builtin-bound-type-parameters.rs:11:25 | LL | struct MyStruct2<'a, T: Copy<'a>>; | ^^^^---- help: remove these generics @@ -31,7 +39,7 @@ LL | struct MyStruct2<'a, T: Copy<'a>>; | expected 0 lifetime arguments error[E0107]: trait takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15 + --> $DIR/typeck-builtin-bound-type-parameters.rs:14:15 | LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {} | ^^^^ -- help: remove this lifetime argument @@ -39,13 +47,13 @@ LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {} | expected 0 lifetime arguments error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/typeck-builtin-bound-type-parameters.rs:13:15 + --> $DIR/typeck-builtin-bound-type-parameters.rs:14:15 | LL | fn foo2<'a, T:Copy<'a, U>, U>(x: T) {} | ^^^^ - help: remove this generic argument | | | expected 0 generic arguments -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0107`. From b00e5f37f3bbc583332319b9fddd96449c18b120 Mon Sep 17 00:00:00 2001 From: Gibby Free Date: Mon, 6 Mar 2023 11:46:40 -0800 Subject: [PATCH 30/32] remove bootstrap from tests --- .../debuginfo/auxiliary/dependency-with-embedded-visualizers.rs | 1 - tests/debuginfo/embedded-visualizer.rs | 1 - tests/ui/invalid/invalid-debugger-visualizer-option.rs | 1 - tests/ui/invalid/invalid-debugger-visualizer-target.rs | 2 -- 4 files changed, 5 deletions(-) diff --git a/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.rs b/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.rs index 4082d98593fd4..c187df637fdc7 100644 --- a/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.rs +++ b/tests/debuginfo/auxiliary/dependency-with-embedded-visualizers.rs @@ -2,7 +2,6 @@ // ignore-lldb // no-prefer-dynamic -#![cfg_attr(bootstrap, feature(debugger_visualizer))] #![debugger_visualizer(natvis_file = "dependency-with-embedded-visualizers.natvis")] #![debugger_visualizer(gdb_script_file = "dependency-with-embedded-visualizers.py")] #![crate_type = "rlib"] diff --git a/tests/debuginfo/embedded-visualizer.rs b/tests/debuginfo/embedded-visualizer.rs index b6500aec49355..ac421092839f4 100644 --- a/tests/debuginfo/embedded-visualizer.rs +++ b/tests/debuginfo/embedded-visualizer.rs @@ -60,7 +60,6 @@ // gdb-check:$4 = "Person A" is 10 years old. #![allow(unused_variables)] -#![cfg_attr(bootstrap, feature(debugger_visualizer))] #![debugger_visualizer(natvis_file = "embedded-visualizer.natvis")] #![debugger_visualizer(gdb_script_file = "embedded-visualizer.py")] diff --git a/tests/ui/invalid/invalid-debugger-visualizer-option.rs b/tests/ui/invalid/invalid-debugger-visualizer-option.rs index bf549cbe9624d..150723898bd78 100644 --- a/tests/ui/invalid/invalid-debugger-visualizer-option.rs +++ b/tests/ui/invalid/invalid-debugger-visualizer-option.rs @@ -1,7 +1,6 @@ // normalize-stderr-test: "foo.random:.*\(" -> "foo.random: $$FILE_NOT_FOUND_MSG (" // normalize-stderr-test: "os error \d+" -> "os error $$FILE_NOT_FOUND_CODE" -#![cfg_attr(bootstrap, feature(debugger_visualizer))] #![debugger_visualizer(random_file = "../foo.random")] //~ ERROR invalid argument #![debugger_visualizer(natvis_file = "../foo.random")] //~ ERROR fn main() {} diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.rs b/tests/ui/invalid/invalid-debugger-visualizer-target.rs index 44378872b68ec..f9dd20dbfed1d 100644 --- a/tests/ui/invalid/invalid-debugger-visualizer-target.rs +++ b/tests/ui/invalid/invalid-debugger-visualizer-target.rs @@ -1,4 +1,2 @@ -#![cfg_attr(bootstrap, feature(debugger_visualizer))] - #[debugger_visualizer(natvis_file = "../foo.natvis")] //~ ERROR attribute should be applied to a module fn main() {} From c9653a6b0b5ab0a2bd7a6d525c234a15ef1d9a70 Mon Sep 17 00:00:00 2001 From: Gibby Free Date: Mon, 6 Mar 2023 12:06:34 -0800 Subject: [PATCH 31/32] fix stderrs --- tests/ui/invalid/invalid-debugger-visualizer-option.stderr | 4 ++-- tests/ui/invalid/invalid-debugger-visualizer-target.stderr | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/invalid/invalid-debugger-visualizer-option.stderr b/tests/ui/invalid/invalid-debugger-visualizer-option.stderr index afb8d16ee960a..6fbb4d641e6f6 100644 --- a/tests/ui/invalid/invalid-debugger-visualizer-option.stderr +++ b/tests/ui/invalid/invalid-debugger-visualizer-option.stderr @@ -1,5 +1,5 @@ error: invalid argument - --> $DIR/invalid-debugger-visualizer-option.rs:5:24 + --> $DIR/invalid-debugger-visualizer-option.rs:4:24 | LL | #![debugger_visualizer(random_file = "../foo.random")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | #![debugger_visualizer(random_file = "../foo.random")] = note: expected: `gdb_script_file = "..."` error: couldn't read $DIR/../foo.random: $FILE_NOT_FOUND_MSG (os error $FILE_NOT_FOUND_CODE) - --> $DIR/invalid-debugger-visualizer-option.rs:6:24 + --> $DIR/invalid-debugger-visualizer-option.rs:5:24 | LL | #![debugger_visualizer(natvis_file = "../foo.random")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr index 3555bbb169b1c..7944f7518593c 100644 --- a/tests/ui/invalid/invalid-debugger-visualizer-target.stderr +++ b/tests/ui/invalid/invalid-debugger-visualizer-target.stderr @@ -1,5 +1,5 @@ error: attribute should be applied to a module - --> $DIR/invalid-debugger-visualizer-target.rs:3:1 + --> $DIR/invalid-debugger-visualizer-target.rs:1:1 | LL | #[debugger_visualizer(natvis_file = "../foo.natvis")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 7411468ff817884cdb1239e85b5ab785cc65e36d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 1 May 2023 05:29:36 +0000 Subject: [PATCH 32/32] Mark RPITIT and AFIT as no longer incomplete --- compiler/rustc_feature/src/active.rs | 4 ++-- .../bad-inputs-and-output.rs | 1 - .../bad-inputs-and-output.stderr | 20 ++++++------------- .../return-type-notation/basic.rs | 1 - .../return-type-notation/basic.with.stderr | 10 +--------- .../return-type-notation/basic.without.stderr | 16 ++++----------- .../return-type-notation/equality.rs | 1 - .../return-type-notation/equality.stderr | 12 ++--------- .../return-type-notation/missing.rs | 1 - .../return-type-notation/missing.stderr | 12 ++--------- ...async-default-fn-overridden.current.stderr | 11 ---------- .../async-default-fn-overridden.next.stderr | 11 ---------- .../in-trait/async-default-fn-overridden.rs | 1 - .../in-trait/bad-signatures.current.stderr | 15 +++----------- .../in-trait/bad-signatures.next.stderr | 15 +++----------- .../ui/async-await/in-trait/bad-signatures.rs | 1 - ...to-specializable-projection.current.stderr | 11 +--------- ...ct-to-specializable-projection.next.stderr | 11 +--------- .../in-trait/lifetime-mismatch.current.stderr | 13 ++---------- .../in-trait/lifetime-mismatch.next.stderr | 13 ++---------- .../async-await/in-trait/lifetime-mismatch.rs | 1 - .../missing-send-bound.current.stderr | 17 ++++------------ .../in-trait/missing-send-bound.next.stderr | 17 ++++------------ .../in-trait/missing-send-bound.rs | 1 - .../in-trait/object-safety.current.stderr | 15 +++----------- .../in-trait/object-safety.next.stderr | 15 +++----------- .../ui/async-await/in-trait/object-safety.rs | 1 - .../return-type-suggestion.current.stderr | 13 ++---------- .../return-type-suggestion.next.stderr | 13 ++---------- .../in-trait/return-type-suggestion.rs | 1 - .../issue-110963-early.stderr | 10 +--------- .../return-type-notation/issue-110963-late.rs | 1 - .../issue-110963-late.stderr | 10 +--------- ...ature-gate-return_type_notation.cfg.stderr | 17 ++++------------ ...eature-gate-return_type_notation.no.stderr | 13 ++---------- .../feature-gate-return_type_notation.rs | 1 - .../box-coerce-span-in-default.current.stderr | 11 ---------- .../box-coerce-span-in-default.next.stderr | 11 ---------- .../in-trait/box-coerce-span-in-default.rs | 1 - ...ault-method-binder-shifting.current.stderr | 11 ---------- ...default-method-binder-shifting.next.stderr | 11 ---------- .../default-method-binder-shifting.rs | 1 - .../default-method-constraint.current.stderr | 11 ---------- .../default-method-constraint.next.stderr | 11 ---------- .../in-trait/default-method-constraint.rs | 1 - ...ect-to-rpitit-with-no-value.current.stderr | 13 ++---------- ...roject-to-rpitit-with-no-value.next.stderr | 13 ++---------- .../dont-project-to-rpitit-with-no-value.rs | 1 - 48 files changed, 59 insertions(+), 363 deletions(-) delete mode 100644 tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr delete mode 100644 tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr delete mode 100644 tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr delete mode 100644 tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr delete mode 100644 tests/ui/impl-trait/in-trait/default-method-binder-shifting.current.stderr delete mode 100644 tests/ui/impl-trait/in-trait/default-method-binder-shifting.next.stderr delete mode 100644 tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr delete mode 100644 tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index f046022b84275..bafb83740ca85 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -310,7 +310,7 @@ declare_features! ( /// Allows `async || body` closures. (active, async_closure, "1.37.0", Some(62290), None), /// Allows async functions to be declared, implemented, and used in traits. - (incomplete, async_fn_in_trait, "1.66.0", Some(91611), None), + (active, async_fn_in_trait, "1.66.0", Some(91611), None), /// Treat `extern "C"` function as nounwind. (active, c_unwind, "1.52.0", Some(74990), None), /// Allows using C-variadics. @@ -496,7 +496,7 @@ declare_features! ( /// Allows `repr(simd)` and importing the various simd intrinsics. (active, repr_simd, "1.4.0", Some(27731), None), /// Allows return-position `impl Trait` in traits. - (incomplete, return_position_impl_trait_in_trait, "1.65.0", Some(91611), None), + (active, return_position_impl_trait_in_trait, "1.65.0", Some(91611), None), /// Allows bounding the return type of AFIT/RPITIT. (incomplete, return_type_notation, "1.70.0", Some(109417), None), /// Allows `extern "rust-cold"`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs index 79cee55177ba0..58ce41d1a8933 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs @@ -2,7 +2,6 @@ #![feature(return_type_notation, async_fn_in_trait)] //~^ WARN the feature `return_type_notation` is incomplete -//~| WARN the feature `async_fn_in_trait` is incomplete trait Trait { async fn method() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr index b23e0f791eae4..95ef7d82fcab8 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr @@ -1,11 +1,11 @@ error: return type notation uses `()` instead of `(..)` for elided arguments - --> $DIR/bad-inputs-and-output.rs:19:24 + --> $DIR/bad-inputs-and-output.rs:18:24 | LL | fn baz>() {} | ^^ help: remove the `..` error[E0658]: associated type bounds are unstable - --> $DIR/bad-inputs-and-output.rs:11:17 + --> $DIR/bad-inputs-and-output.rs:10:17 | LL | fn foo>() {} | ^^^^^^^^^^^^^^^^^ @@ -14,7 +14,7 @@ LL | fn foo>() {} = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable error[E0658]: associated type bounds are unstable - --> $DIR/bad-inputs-and-output.rs:15:17 + --> $DIR/bad-inputs-and-output.rs:14:17 | LL | fn bar (): Send>>() {} | ^^^^^^^^^^^^^^^^^^^^ @@ -31,26 +31,18 @@ LL | #![feature(return_type_notation, async_fn_in_trait)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bad-inputs-and-output.rs:3:34 - | -LL | #![feature(return_type_notation, async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - error: argument types not allowed with return type notation - --> $DIR/bad-inputs-and-output.rs:11:23 + --> $DIR/bad-inputs-and-output.rs:10:23 | LL | fn foo>() {} | ^^^^^ help: remove the input types: `()` error: return type not allowed with return type notation - --> $DIR/bad-inputs-and-output.rs:15:25 + --> $DIR/bad-inputs-and-output.rs:14:25 | LL | fn bar (): Send>>() {} | ^^^^^^ help: remove the return type -error: aborting due to 5 previous errors; 2 warnings emitted +error: aborting due to 5 previous errors; 1 warning emitted For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.rs b/tests/ui/associated-type-bounds/return-type-notation/basic.rs index 0b7530b65d758..edc6a8e4caf0a 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.rs @@ -4,7 +4,6 @@ #![feature(return_type_notation, async_fn_in_trait)] //~^ WARN the feature `return_type_notation` is incomplete -//~| WARN the feature `async_fn_in_trait` is incomplete trait Foo { async fn method() -> Result<(), ()>; diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.with.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.with.stderr index 722c774cb3394..9962f4706b314 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.with.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.with.stderr @@ -7,13 +7,5 @@ LL | #![feature(return_type_notation, async_fn_in_trait)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/basic.rs:5:34 - | -LL | #![feature(return_type_notation, async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr index 1645d8c26502a..c2da4f57696f5 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/basic.without.stderr @@ -7,31 +7,23 @@ LL | #![feature(return_type_notation, async_fn_in_trait)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/basic.rs:5:34 - | -LL | #![feature(return_type_notation, async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - error: future cannot be sent between threads safely - --> $DIR/basic.rs:24:13 + --> $DIR/basic.rs:23:13 | LL | is_send(foo::()); | ^^^^^^^^^^ future returned by `foo` is not `Send` | = help: within `impl Future>`, the trait `Send` is not implemented for `impl Future>` note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/basic.rs:14:5 + --> $DIR/basic.rs:13:5 | LL | T::method().await?; | ^^^^^^^^^^^ await occurs here on type `impl Future>`, which is not `Send` note: required by a bound in `is_send` - --> $DIR/basic.rs:18:20 + --> $DIR/basic.rs:17:20 | LL | fn is_send(_: impl Send) {} | ^^^^ required by this bound in `is_send` -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.rs b/tests/ui/associated-type-bounds/return-type-notation/equality.rs index 75f757e90259b..6884305d7b37b 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/equality.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/equality.rs @@ -2,7 +2,6 @@ #![feature(return_type_notation, async_fn_in_trait)] //~^ WARN the feature `return_type_notation` is incomplete -//~| WARN the feature `async_fn_in_trait` is incomplete use std::future::Future; diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.stderr index c5b2e5710d4a7..490bfdc4c3c60 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/equality.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/equality.stderr @@ -7,19 +7,11 @@ LL | #![feature(return_type_notation, async_fn_in_trait)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/equality.rs:3:34 - | -LL | #![feature(return_type_notation, async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - error: return type notation is not allowed to use type equality - --> $DIR/equality.rs:13:18 + --> $DIR/equality.rs:12:18 | LL | fn test>>>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.rs b/tests/ui/associated-type-bounds/return-type-notation/missing.rs index 7b98a5cdafdd3..b84b5a717b72d 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/missing.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/missing.rs @@ -2,7 +2,6 @@ #![feature(return_type_notation, async_fn_in_trait)] //~^ WARN the feature `return_type_notation` is incomplete -//~| WARN the feature `async_fn_in_trait` is incomplete trait Trait { async fn method() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr index 34f5bda884d4c..954d9f74767a7 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr @@ -7,19 +7,11 @@ LL | #![feature(return_type_notation, async_fn_in_trait)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/missing.rs:3:34 - | -LL | #![feature(return_type_notation, async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - error: cannot find associated function `methid` in trait `Trait` - --> $DIR/missing.rs:11:17 + --> $DIR/missing.rs:10:17 | LL | fn bar>() {} | ^^^^^^^^^^^^^^ -error: aborting due to previous error; 2 warnings emitted +error: aborting due to previous error; 1 warning emitted diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr b/tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr deleted file mode 100644 index 2142ee232ca5c..0000000000000 --- a/tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/async-default-fn-overridden.rs:6:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr b/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr deleted file mode 100644 index 2142ee232ca5c..0000000000000 --- a/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/async-default-fn-overridden.rs:6:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs index dd1af93d706c4..99c3ba6a3c20e 100644 --- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs +++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs @@ -4,7 +4,6 @@ // revisions: current next #![feature(async_fn_in_trait)] -//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use use std::future::Future; diff --git a/tests/ui/async-await/in-trait/bad-signatures.current.stderr b/tests/ui/async-await/in-trait/bad-signatures.current.stderr index 5a05b080c3e57..ae590fb057f3b 100644 --- a/tests/ui/async-await/in-trait/bad-signatures.current.stderr +++ b/tests/ui/async-await/in-trait/bad-signatures.current.stderr @@ -1,11 +1,11 @@ error: expected identifier, found keyword `self` - --> $DIR/bad-signatures.rs:9:23 + --> $DIR/bad-signatures.rs:8:23 | LL | async fn bar(&abc self); | ^^^^ expected identifier, found keyword error: expected one of `:`, `@`, or `|`, found keyword `self` - --> $DIR/bad-signatures.rs:9:23 + --> $DIR/bad-signatures.rs:8:23 | LL | async fn bar(&abc self); | -----^^^^ @@ -13,14 +13,5 @@ LL | async fn bar(&abc self); | | expected one of `:`, `@`, or `|` | help: declare the type after the parameter binding: `: ` -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bad-signatures.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/in-trait/bad-signatures.next.stderr b/tests/ui/async-await/in-trait/bad-signatures.next.stderr index 5a05b080c3e57..ae590fb057f3b 100644 --- a/tests/ui/async-await/in-trait/bad-signatures.next.stderr +++ b/tests/ui/async-await/in-trait/bad-signatures.next.stderr @@ -1,11 +1,11 @@ error: expected identifier, found keyword `self` - --> $DIR/bad-signatures.rs:9:23 + --> $DIR/bad-signatures.rs:8:23 | LL | async fn bar(&abc self); | ^^^^ expected identifier, found keyword error: expected one of `:`, `@`, or `|`, found keyword `self` - --> $DIR/bad-signatures.rs:9:23 + --> $DIR/bad-signatures.rs:8:23 | LL | async fn bar(&abc self); | -----^^^^ @@ -13,14 +13,5 @@ LL | async fn bar(&abc self); | | expected one of `:`, `@`, or `|` | help: declare the type after the parameter binding: `: ` -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/bad-signatures.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors diff --git a/tests/ui/async-await/in-trait/bad-signatures.rs b/tests/ui/async-await/in-trait/bad-signatures.rs index e0093be8cb33f..4baddd8ccb835 100644 --- a/tests/ui/async-await/in-trait/bad-signatures.rs +++ b/tests/ui/async-await/in-trait/bad-signatures.rs @@ -3,7 +3,6 @@ // revisions: current next #![feature(async_fn_in_trait)] -//~^ WARN the feature `async_fn_in_trait` is incomplete trait MyTrait { async fn bar(&abc self); diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.current.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.current.stderr index 1e67cdca248d4..eec5ab065397c 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.current.stderr +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.current.stderr @@ -1,12 +1,3 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/dont-project-to-specializable-projection.rs:6:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error: async associated function in trait cannot be specialized --> $DIR/dont-project-to-specializable-projection.rs:16:5 | @@ -15,5 +6,5 @@ LL | default async fn foo(_: T) -> &'static str { | = note: specialization behaves in inconsistent and surprising ways with `#![feature(async_fn_in_trait)]`, and for now is disallowed -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.next.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.next.stderr index fa89c6b77e0b9..25a7f3bb56a50 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.next.stderr +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.next.stderr @@ -1,12 +1,3 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/dont-project-to-specializable-projection.rs:6:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0053]: method `foo` has an incompatible type for trait --> $DIR/dont-project-to-specializable-projection.rs:16:35 | @@ -29,6 +20,6 @@ LL | default async fn foo(_: T) -> &'static str { | = note: specialization behaves in inconsistent and surprising ways with `#![feature(async_fn_in_trait)]`, and for now is disallowed -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.current.stderr b/tests/ui/async-await/in-trait/lifetime-mismatch.current.stderr index 0e9477544a4a6..69e7c65ee3e70 100644 --- a/tests/ui/async-await/in-trait/lifetime-mismatch.current.stderr +++ b/tests/ui/async-await/in-trait/lifetime-mismatch.current.stderr @@ -1,14 +1,5 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/lifetime-mismatch.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration - --> $DIR/lifetime-mismatch.rs:14:17 + --> $DIR/lifetime-mismatch.rs:13:17 | LL | async fn foo<'a>(&self); | ---- lifetimes in impl do not match this method in trait @@ -16,6 +7,6 @@ LL | async fn foo<'a>(&self); LL | async fn foo(&self) {} | ^ lifetimes do not match method in trait -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.next.stderr b/tests/ui/async-await/in-trait/lifetime-mismatch.next.stderr index 0e9477544a4a6..69e7c65ee3e70 100644 --- a/tests/ui/async-await/in-trait/lifetime-mismatch.next.stderr +++ b/tests/ui/async-await/in-trait/lifetime-mismatch.next.stderr @@ -1,14 +1,5 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/lifetime-mismatch.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration - --> $DIR/lifetime-mismatch.rs:14:17 + --> $DIR/lifetime-mismatch.rs:13:17 | LL | async fn foo<'a>(&self); | ---- lifetimes in impl do not match this method in trait @@ -16,6 +7,6 @@ LL | async fn foo<'a>(&self); LL | async fn foo(&self) {} | ^ lifetimes do not match method in trait -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0195`. diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.rs b/tests/ui/async-await/in-trait/lifetime-mismatch.rs index 5ff5a01a1ee03..46183f72bce68 100644 --- a/tests/ui/async-await/in-trait/lifetime-mismatch.rs +++ b/tests/ui/async-await/in-trait/lifetime-mismatch.rs @@ -3,7 +3,6 @@ // revisions: current next #![feature(async_fn_in_trait)] -//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes trait MyTrait { async fn foo<'a>(&self); diff --git a/tests/ui/async-await/in-trait/missing-send-bound.current.stderr b/tests/ui/async-await/in-trait/missing-send-bound.current.stderr index 319ed582e2719..9aa37f7437e4e 100644 --- a/tests/ui/async-await/in-trait/missing-send-bound.current.stderr +++ b/tests/ui/async-await/in-trait/missing-send-bound.current.stderr @@ -1,29 +1,20 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/missing-send-bound.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error: future cannot be sent between threads safely - --> $DIR/missing-send-bound.rs:17:20 + --> $DIR/missing-send-bound.rs:16:20 | LL | assert_is_send(test::()); | ^^^^^^^^^^^ future returned by `test` is not `Send` | = help: within `impl Future`, the trait `Send` is not implemented for `impl Future` note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/missing-send-bound.rs:13:5 + --> $DIR/missing-send-bound.rs:12:5 | LL | T::bar().await; | ^^^^^^^^ await occurs here on type `impl Future`, which is not `Send` note: required by a bound in `assert_is_send` - --> $DIR/missing-send-bound.rs:21:27 + --> $DIR/missing-send-bound.rs:20:27 | LL | fn assert_is_send(_: impl Send) {} | ^^^^ required by this bound in `assert_is_send` -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error diff --git a/tests/ui/async-await/in-trait/missing-send-bound.next.stderr b/tests/ui/async-await/in-trait/missing-send-bound.next.stderr index 319ed582e2719..9aa37f7437e4e 100644 --- a/tests/ui/async-await/in-trait/missing-send-bound.next.stderr +++ b/tests/ui/async-await/in-trait/missing-send-bound.next.stderr @@ -1,29 +1,20 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/missing-send-bound.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error: future cannot be sent between threads safely - --> $DIR/missing-send-bound.rs:17:20 + --> $DIR/missing-send-bound.rs:16:20 | LL | assert_is_send(test::()); | ^^^^^^^^^^^ future returned by `test` is not `Send` | = help: within `impl Future`, the trait `Send` is not implemented for `impl Future` note: future is not `Send` as it awaits another future which is not `Send` - --> $DIR/missing-send-bound.rs:13:5 + --> $DIR/missing-send-bound.rs:12:5 | LL | T::bar().await; | ^^^^^^^^ await occurs here on type `impl Future`, which is not `Send` note: required by a bound in `assert_is_send` - --> $DIR/missing-send-bound.rs:21:27 + --> $DIR/missing-send-bound.rs:20:27 | LL | fn assert_is_send(_: impl Send) {} | ^^^^ required by this bound in `assert_is_send` -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error diff --git a/tests/ui/async-await/in-trait/missing-send-bound.rs b/tests/ui/async-await/in-trait/missing-send-bound.rs index 705fcf322f9ea..b602865cbb12d 100644 --- a/tests/ui/async-await/in-trait/missing-send-bound.rs +++ b/tests/ui/async-await/in-trait/missing-send-bound.rs @@ -3,7 +3,6 @@ // revisions: current next #![feature(async_fn_in_trait)] -//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes trait Foo { async fn bar(); diff --git a/tests/ui/async-await/in-trait/object-safety.current.stderr b/tests/ui/async-await/in-trait/object-safety.current.stderr index 90e049a99606f..7f7ec39142cdf 100644 --- a/tests/ui/async-await/in-trait/object-safety.current.stderr +++ b/tests/ui/async-await/in-trait/object-safety.current.stderr @@ -1,20 +1,11 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/object-safety.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:13:12 + --> $DIR/object-safety.rs:12:12 | LL | let x: &dyn Foo = todo!(); | ^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:9:14 + --> $DIR/object-safety.rs:8:14 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -22,6 +13,6 @@ LL | async fn foo(&self); | ^^^ ...because method `foo` is `async` = help: consider moving `foo` to another trait -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/in-trait/object-safety.next.stderr b/tests/ui/async-await/in-trait/object-safety.next.stderr index 90e049a99606f..7f7ec39142cdf 100644 --- a/tests/ui/async-await/in-trait/object-safety.next.stderr +++ b/tests/ui/async-await/in-trait/object-safety.next.stderr @@ -1,20 +1,11 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/object-safety.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:13:12 + --> $DIR/object-safety.rs:12:12 | LL | let x: &dyn Foo = todo!(); | ^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:9:14 + --> $DIR/object-safety.rs:8:14 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -22,6 +13,6 @@ LL | async fn foo(&self); | ^^^ ...because method `foo` is `async` = help: consider moving `foo` to another trait -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/async-await/in-trait/object-safety.rs b/tests/ui/async-await/in-trait/object-safety.rs index f67286a20a244..4edad1512e93a 100644 --- a/tests/ui/async-await/in-trait/object-safety.rs +++ b/tests/ui/async-await/in-trait/object-safety.rs @@ -3,7 +3,6 @@ // revisions: current next #![feature(async_fn_in_trait)] -//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes trait Foo { async fn foo(&self); diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.current.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.current.stderr index a5efc75715656..6a107d7beb8fd 100644 --- a/tests/ui/async-await/in-trait/return-type-suggestion.current.stderr +++ b/tests/ui/async-await/in-trait/return-type-suggestion.current.stderr @@ -1,14 +1,5 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/return-type-suggestion.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0308]: mismatched types - --> $DIR/return-type-suggestion.rs:10:9 + --> $DIR/return-type-suggestion.rs:9:9 | LL | Ok(()) | ^^^^^^- help: consider using a semicolon here: `;` @@ -18,6 +9,6 @@ LL | Ok(()) = note: expected unit type `()` found enum `Result<(), _>` -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.next.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.next.stderr index a5efc75715656..6a107d7beb8fd 100644 --- a/tests/ui/async-await/in-trait/return-type-suggestion.next.stderr +++ b/tests/ui/async-await/in-trait/return-type-suggestion.next.stderr @@ -1,14 +1,5 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/return-type-suggestion.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0308]: mismatched types - --> $DIR/return-type-suggestion.rs:10:9 + --> $DIR/return-type-suggestion.rs:9:9 | LL | Ok(()) | ^^^^^^- help: consider using a semicolon here: `;` @@ -18,6 +9,6 @@ LL | Ok(()) = note: expected unit type `()` found enum `Result<(), _>` -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.rs b/tests/ui/async-await/in-trait/return-type-suggestion.rs index 3de66306d9ab8..d63bccefa9fdc 100644 --- a/tests/ui/async-await/in-trait/return-type-suggestion.rs +++ b/tests/ui/async-await/in-trait/return-type-suggestion.rs @@ -3,7 +3,6 @@ // revisions: current next #![feature(async_fn_in_trait)] -//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes trait A { async fn e() { diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr index b4a3924d8dab9..33e22dec3f7b2 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr @@ -7,14 +7,6 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-110963-early.rs:5:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - error: higher-ranked lifetime error --> $DIR/issue-110963-early.rs:15:5 | @@ -41,5 +33,5 @@ LL | | }); | = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send` -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.rs b/tests/ui/async-await/return-type-notation/issue-110963-late.rs index 2a35922eaa1b5..17b5d775d4479 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-late.rs +++ b/tests/ui/async-await/return-type-notation/issue-110963-late.rs @@ -4,7 +4,6 @@ #![feature(return_type_notation)] //~^ WARN the feature `return_type_notation` is incomplete #![feature(async_fn_in_trait)] -//~^ WARN the feature `async_fn_in_trait` is incomplete trait HealthCheck { async fn check(&mut self) -> bool; diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.stderr b/tests/ui/async-await/return-type-notation/issue-110963-late.stderr index 36ef3ad0a4c82..9c6966537a73a 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-late.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-late.stderr @@ -7,13 +7,5 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 for more information = note: `#[warn(incomplete_features)]` on by default -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/issue-110963-late.rs:6:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr index c3a371e25e896..1bdb2574eadc3 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr @@ -1,5 +1,5 @@ error[E0658]: return type notation is experimental - --> $DIR/feature-gate-return_type_notation.rs:15:17 + --> $DIR/feature-gate-return_type_notation.rs:14:17 | LL | fn foo>() {} | ^^^^^^^^^ @@ -7,17 +7,8 @@ LL | fn foo>() {} = note: see issue #109417 for more information = help: add `#![feature(return_type_notation)]` to the crate attributes to enable -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/feature-gate-return_type_notation.rs:7:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error: parenthesized generic arguments cannot be used in associated type constraints - --> $DIR/feature-gate-return_type_notation.rs:15:17 + --> $DIR/feature-gate-return_type_notation.rs:14:17 | LL | fn foo>() {} | ^-- @@ -25,12 +16,12 @@ LL | fn foo>() {} | help: remove these parentheses error[E0220]: associated type `m` not found for `Trait` - --> $DIR/feature-gate-return_type_notation.rs:15:17 + --> $DIR/feature-gate-return_type_notation.rs:14:17 | LL | fn foo>() {} | ^ associated type `m` not found -error: aborting due to 3 previous errors; 1 warning emitted +error: aborting due to 3 previous errors Some errors have detailed explanations: E0220, E0658. For more information about an error, try `rustc --explain E0220`. diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr index 52c90c1565cff..dd6ebb6103862 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.no.stderr @@ -1,14 +1,5 @@ -warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/feature-gate-return_type_notation.rs:7:12 - | -LL | #![feature(async_fn_in_trait)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - warning: return type notation is experimental - --> $DIR/feature-gate-return_type_notation.rs:15:17 + --> $DIR/feature-gate-return_type_notation.rs:14:17 | LL | fn foo>() {} | ^^^^^^^^^ @@ -18,5 +9,5 @@ LL | fn foo>() {} = warning: unstable syntax can change at any point in the future, causing a hard error! = note: for more information, see issue #65860 -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs index 5028b9ec9e3de..d9bcb65feba9a 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs @@ -5,7 +5,6 @@ // Since we're not adding new syntax, `cfg`'d out RTN must pass. #![feature(async_fn_in_trait)] -//~^ WARN the feature `async_fn_in_trait` is incomplete trait Trait { async fn m(); diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr deleted file mode 100644 index 05c025cc169ff..0000000000000 --- a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/box-coerce-span-in-default.rs:5:12 - | -LL | #![feature(return_position_impl_trait_in_trait)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr deleted file mode 100644 index 05c025cc169ff..0000000000000 --- a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/box-coerce-span-in-default.rs:5:12 - | -LL | #![feature(return_position_impl_trait_in_trait)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs index 163bb4fcf773d..f5290a5f4af8f 100644 --- a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs +++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs @@ -3,7 +3,6 @@ // revisions: current next #![feature(return_position_impl_trait_in_trait)] -//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete struct TestA {} struct TestB {} diff --git a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.current.stderr b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.current.stderr deleted file mode 100644 index a0c0589b9a1c0..0000000000000 --- a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.current.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/default-method-binder-shifting.rs:5:12 - | -LL | #![feature(return_position_impl_trait_in_trait)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.next.stderr b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.next.stderr deleted file mode 100644 index a0c0589b9a1c0..0000000000000 --- a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.next.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/default-method-binder-shifting.rs:5:12 - | -LL | #![feature(return_position_impl_trait_in_trait)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs index de82544f29338..187039f449c8d 100644 --- a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs +++ b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs @@ -3,7 +3,6 @@ // revisions: current next #![feature(return_position_impl_trait_in_trait)] -//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete trait Trait { type Type; diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr b/tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr deleted file mode 100644 index 7bb79911f56f8..0000000000000 --- a/tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/default-method-constraint.rs:7:12 - | -LL | #![feature(return_position_impl_trait_in_trait)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr b/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr deleted file mode 100644 index 7bb79911f56f8..0000000000000 --- a/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr +++ /dev/null @@ -1,11 +0,0 @@ -warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/default-method-constraint.rs:7:12 - | -LL | #![feature(return_position_impl_trait_in_trait)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.rs b/tests/ui/impl-trait/in-trait/default-method-constraint.rs index e85fe3c8626f4..4f0bf2e7dfe16 100644 --- a/tests/ui/impl-trait/in-trait/default-method-constraint.rs +++ b/tests/ui/impl-trait/in-trait/default-method-constraint.rs @@ -5,7 +5,6 @@ // This didn't work in the previous default RPITIT method hack attempt #![feature(return_position_impl_trait_in_trait)] -//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete trait Foo { fn bar(x: bool) -> impl Sized { diff --git a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.current.stderr b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.current.stderr index b8a793e1a7bb5..d4d0124a6599c 100644 --- a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.current.stderr +++ b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.current.stderr @@ -1,14 +1,5 @@ -warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/dont-project-to-rpitit-with-no-value.rs:4:12 - | -LL | #![feature(return_position_impl_trait_in_trait)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0046]: not all trait items implemented, missing: `foo` - --> $DIR/dont-project-to-rpitit-with-no-value.rs:12:1 + --> $DIR/dont-project-to-rpitit-with-no-value.rs:11:1 | LL | fn foo(&self) -> impl Sized; | ---------------------------- `foo` from trait @@ -16,6 +7,6 @@ LL | fn foo(&self) -> impl Sized; LL | impl MyTrait for i32 { | ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.next.stderr b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.next.stderr index b8a793e1a7bb5..d4d0124a6599c 100644 --- a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.next.stderr +++ b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.next.stderr @@ -1,14 +1,5 @@ -warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes - --> $DIR/dont-project-to-rpitit-with-no-value.rs:4:12 - | -LL | #![feature(return_position_impl_trait_in_trait)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #91611 for more information - = note: `#[warn(incomplete_features)]` on by default - error[E0046]: not all trait items implemented, missing: `foo` - --> $DIR/dont-project-to-rpitit-with-no-value.rs:12:1 + --> $DIR/dont-project-to-rpitit-with-no-value.rs:11:1 | LL | fn foo(&self) -> impl Sized; | ---------------------------- `foo` from trait @@ -16,6 +7,6 @@ LL | fn foo(&self) -> impl Sized; LL | impl MyTrait for i32 { | ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to previous error; 1 warning emitted +error: aborting due to previous error For more information about this error, try `rustc --explain E0046`. diff --git a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs index 8329ce1f835d0..4d50b8c927870 100644 --- a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs +++ b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs @@ -2,7 +2,6 @@ // revisions: current next #![feature(return_position_impl_trait_in_trait)] -//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete trait MyTrait { fn foo(&self) -> impl Sized;