From e3fc97be2b90add55bbe48362cba902c6a0675be Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Tue, 23 Apr 2024 22:16:29 +0200 Subject: [PATCH 01/48] Inline `EscapeDebug::size_hint`. --- library/core/src/char/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index a860c7c6aaadc..bf9f633eef370 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -339,6 +339,7 @@ impl Iterator for EscapeDebug { } } + #[inline] fn size_hint(&self) -> (usize, Option) { let n = self.len(); (n, Some(n)) From 16981ba40607ba87bc3767c0e810622455dc0d85 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Thu, 25 Apr 2024 01:26:32 +0200 Subject: [PATCH 02/48] Avoid panicking branch in `EscapeIterInner`. --- library/core/src/ascii.rs | 14 +-- library/core/src/char/methods.rs | 8 +- library/core/src/char/mod.rs | 48 +++++----- library/core/src/escape.rs | 148 ++++++++++++++++++++----------- 4 files changed, 137 insertions(+), 81 deletions(-) diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index c29e5565d514a..17fbb19d0397a 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -91,17 +91,21 @@ pub struct EscapeDefault(escape::EscapeIterInner<4>); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn escape_default(c: u8) -> EscapeDefault { - let mut data = [Char::Null; 4]; - let range = escape::escape_ascii_into(&mut data, c); - EscapeDefault(escape::EscapeIterInner::new(data, range)) + EscapeDefault::new(c) } impl EscapeDefault { + #[inline] + pub(crate) const fn new(c: u8) -> Self { + Self(escape::EscapeIterInner::ascii(c)) + } + + #[inline] pub(crate) fn empty() -> Self { - let data = [Char::Null; 4]; - EscapeDefault(escape::EscapeIterInner::new(data, 0..0)) + EscapeDefault(escape::EscapeIterInner::empty()) } + #[inline] pub(crate) fn as_str(&self) -> &str { self.0.as_str() } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index a93b94867ce4c..458be49fb152a 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -449,10 +449,10 @@ impl char { '\"' if args.escape_double_quote => EscapeDebug::backslash(ascii::Char::QuotationMark), '\'' if args.escape_single_quote => EscapeDebug::backslash(ascii::Char::Apostrophe), _ if args.escape_grapheme_extended && self.is_grapheme_extended() => { - EscapeDebug::from_unicode(self.escape_unicode()) + EscapeDebug::unicode(self) } _ if is_printable(self) => EscapeDebug::printable(self), - _ => EscapeDebug::from_unicode(self.escape_unicode()), + _ => EscapeDebug::unicode(self), } } @@ -555,9 +555,9 @@ impl char { '\t' => EscapeDefault::backslash(ascii::Char::SmallT), '\r' => EscapeDefault::backslash(ascii::Char::SmallR), '\n' => EscapeDefault::backslash(ascii::Char::SmallN), - '\\' | '\'' | '"' => EscapeDefault::backslash(self.as_ascii().unwrap()), + '\\' | '\'' | '\"' => EscapeDefault::backslash(self.as_ascii().unwrap()), '\x20'..='\x7e' => EscapeDefault::printable(self.as_ascii().unwrap()), - _ => EscapeDefault::from_unicode(self.escape_unicode()), + _ => EscapeDefault::unicode(self), } } diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index bf9f633eef370..d99ac226da005 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -152,10 +152,9 @@ pub const fn from_digit(num: u32, radix: u32) -> Option { pub struct EscapeUnicode(escape::EscapeIterInner<10>); impl EscapeUnicode { - fn new(chr: char) -> Self { - let mut data = [ascii::Char::Null; 10]; - let range = escape::escape_unicode_into(&mut data, chr); - Self(escape::EscapeIterInner::new(data, range)) + #[inline] + const fn new(c: char) -> Self { + Self(escape::EscapeIterInner::unicode(c)) } } @@ -219,18 +218,24 @@ impl fmt::Display for EscapeUnicode { pub struct EscapeDefault(escape::EscapeIterInner<10>); impl EscapeDefault { - fn printable(chr: ascii::Char) -> Self { - let data = [chr]; - Self(escape::EscapeIterInner::from_array(data)) + #[inline] + const fn printable(c: ascii::Char) -> Self { + Self::ascii(c.to_u8()) } - fn backslash(chr: ascii::Char) -> Self { - let data = [ascii::Char::ReverseSolidus, chr]; - Self(escape::EscapeIterInner::from_array(data)) + #[inline] + const fn backslash(c: ascii::Char) -> Self { + Self(escape::EscapeIterInner::backslash(c)) } - fn from_unicode(esc: EscapeUnicode) -> Self { - Self(esc.0) + #[inline] + const fn ascii(c: u8) -> Self { + Self(escape::EscapeIterInner::ascii(c)) + } + + #[inline] + const fn unicode(c: char) -> Self { + Self(escape::EscapeIterInner::unicode(c)) } } @@ -304,23 +309,24 @@ enum EscapeDebugInner { } impl EscapeDebug { - fn printable(chr: char) -> Self { + #[inline] + const fn printable(chr: char) -> Self { Self(EscapeDebugInner::Char(chr)) } - fn backslash(chr: ascii::Char) -> Self { - let data = [ascii::Char::ReverseSolidus, chr]; - let iter = escape::EscapeIterInner::from_array(data); - Self(EscapeDebugInner::Bytes(iter)) + #[inline] + const fn backslash(c: ascii::Char) -> Self { + Self(EscapeDebugInner::Bytes(escape::EscapeIterInner::backslash(c))) } - fn from_unicode(esc: EscapeUnicode) -> Self { - Self(EscapeDebugInner::Bytes(esc.0)) + #[inline] + const fn unicode(c: char) -> Self { + Self(EscapeDebugInner::Bytes(escape::EscapeIterInner::unicode(c))) } + #[inline] fn clear(&mut self) { - let bytes = escape::EscapeIterInner::from_array([]); - self.0 = EscapeDebugInner::Bytes(bytes); + self.0 = EscapeDebugInner::Bytes(escape::EscapeIterInner::empty()); } } diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index 143e277283e2c..a71fe59e50a13 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -6,56 +6,85 @@ use crate::ops::Range; const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap(); -/// Escapes a byte into provided buffer; returns length of escaped -/// representation. -pub(crate) fn escape_ascii_into(output: &mut [ascii::Char; 4], byte: u8) -> Range { - #[inline] - fn backslash(a: ascii::Char) -> ([ascii::Char; 4], u8) { - ([ascii::Char::ReverseSolidus, a, ascii::Char::Null, ascii::Char::Null], 2) - } +#[inline] +const fn backslash(a: ascii::Char) -> ([ascii::Char; N], u8) { + const { assert!(N >= 2) }; + + let mut output = [ascii::Char::Null; N]; + + output[0] = ascii::Char::ReverseSolidus; + output[1] = a; + + (output, 2) +} + +/// Escapes an ASCII character. +/// +/// Returns a buffer and the length of the escaped representation. +const fn escape_ascii(byte: u8) -> ([ascii::Char; N], u8) { + const { assert!(N >= 4) }; - let (data, len) = match byte { + match byte { b'\t' => backslash(ascii::Char::SmallT), b'\r' => backslash(ascii::Char::SmallR), b'\n' => backslash(ascii::Char::SmallN), b'\\' => backslash(ascii::Char::ReverseSolidus), b'\'' => backslash(ascii::Char::Apostrophe), b'\"' => backslash(ascii::Char::QuotationMark), - _ => { - if let Some(a) = byte.as_ascii() + byte => { + let mut output = [ascii::Char::Null; N]; + + if let Some(c) = byte.as_ascii() && !byte.is_ascii_control() { - ([a, ascii::Char::Null, ascii::Char::Null, ascii::Char::Null], 1) + output[0] = c; + (output, 1) } else { - let hi = HEX_DIGITS[usize::from(byte >> 4)]; - let lo = HEX_DIGITS[usize::from(byte & 0xf)]; - ([ascii::Char::ReverseSolidus, ascii::Char::SmallX, hi, lo], 4) + let hi = HEX_DIGITS[(byte >> 4) as usize]; + let lo = HEX_DIGITS[(byte & 0xf) as usize]; + + output[0] = ascii::Char::ReverseSolidus; + output[1] = ascii::Char::SmallX; + output[2] = hi; + output[3] = lo; + + (output, 4) } } - }; - *output = data; - 0..len + } } -/// Escapes a character into provided buffer using `\u{NNNN}` representation. -pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> Range { - output[9] = ascii::Char::RightCurlyBracket; - - 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]; - 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; - const UNICODE_ESCAPE_PREFIX: &[ascii::Char; 3] = b"\\u{".as_ascii().unwrap(); - output[start..][..3].copy_from_slice(UNICODE_ESCAPE_PREFIX); - - (start as u8)..10 +/// Escapes a character `\u{NNNN}` representation. +/// +/// Returns a buffer and the length of the escaped representation. +const fn escape_unicode(c: char) -> ([ascii::Char; N], u8) { + const { assert!(N >= 10) }; + + let c = c as u32; + + // OR-ing `1` ensures that for `c == 0` the code computes that + // one digit should be printed. + let u_len = (8 - (c | 1).leading_zeros() / 4) as usize; + + let closing_paren_offset = 3 + u_len; + + let mut output = [ascii::Char::Null; N]; + + output[0] = ascii::Char::ReverseSolidus; + output[1] = ascii::Char::SmallU; + output[2] = ascii::Char::LeftCurlyBracket; + + output[3 + u_len.saturating_sub(6)] = HEX_DIGITS[((c >> 20) & 0x0f) as usize]; + output[3 + u_len.saturating_sub(5)] = HEX_DIGITS[((c >> 16) & 0x0f) as usize]; + output[3 + u_len.saturating_sub(4)] = HEX_DIGITS[((c >> 12) & 0x0f) as usize]; + output[3 + u_len.saturating_sub(3)] = HEX_DIGITS[((c >> 8) & 0x0f) as usize]; + output[3 + u_len.saturating_sub(2)] = HEX_DIGITS[((c >> 4) & 0x0f) as usize]; + output[3 + u_len.saturating_sub(1)] = HEX_DIGITS[((c >> 0) & 0x0f) as usize]; + + output[closing_paren_offset] = ascii::Char::RightCurlyBracket; + + let len = (closing_paren_offset + 1) as u8; + (output, len) } /// An iterator over an fixed-size array. @@ -65,45 +94,62 @@ pub(crate) fn escape_unicode_into(output: &mut [ascii::Char; 10], ch: char) -> R #[derive(Clone, Debug)] pub(crate) struct EscapeIterInner { // The element type ensures this is always ASCII, and thus also valid UTF-8. - pub(crate) data: [ascii::Char; N], + data: [ascii::Char; N], - // Invariant: alive.start <= alive.end <= N. - pub(crate) alive: Range, + // Invariant: `alive.start <= alive.end <= N` + alive: Range, } impl EscapeIterInner { - pub fn new(data: [ascii::Char; N], alive: Range) -> Self { - const { assert!(N < 256) }; - debug_assert!(alive.start <= alive.end && usize::from(alive.end) <= N, "{alive:?}"); - Self { data, alive } + pub const fn backslash(c: ascii::Char) -> Self { + let (data, len) = backslash(c); + Self { data, alive: 0..len } } - pub fn from_array(array: [ascii::Char; M]) -> Self { - const { assert!(M <= N) }; + pub const fn ascii(c: u8) -> Self { + let (data, len) = escape_ascii(c); + Self { data, alive: 0..len } + } - let mut data = [ascii::Char::Null; N]; - data[..M].copy_from_slice(&array); - Self::new(data, 0..M as u8) + pub const fn unicode(c: char) -> Self { + let (data, len) = escape_unicode(c); + Self { data, alive: 0..len } + } + + #[inline] + pub const fn empty() -> Self { + Self { data: [ascii::Char::Null; N], alive: 0..0 } } pub fn as_ascii(&self) -> &[ascii::Char] { - &self.data[usize::from(self.alive.start)..usize::from(self.alive.end)] + // SAFETY: `self.alive` is guaranteed to be a valid range for indexing `self.data`. + unsafe { + self.data.get_unchecked(usize::from(self.alive.start)..usize::from(self.alive.end)) + } } + #[inline] pub fn as_str(&self) -> &str { self.as_ascii().as_str() } + #[inline] 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)].to_u8()) + let i = self.alive.next()?; + + // SAFETY: `i` is guaranteed to be a valid index for `self.data`. + unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) } } pub fn next_back(&mut self) -> Option { - self.alive.next_back().map(|i| self.data[usize::from(i)].to_u8()) + let i = self.alive.next_back()?; + + // SAFETY: `i` is guaranteed to be a valid index for `self.data`. + unsafe { Some(self.data.get_unchecked(usize::from(i)).to_u8()) } } pub fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { From 4edf12d33e0aa67a82e6587e94469f3761cb1f53 Mon Sep 17 00:00:00 2001 From: Markus Reiter Date: Wed, 1 May 2024 16:14:37 +0200 Subject: [PATCH 03/48] Improve escape methods. --- library/core/src/ascii.rs | 2 +- library/core/src/char/mod.rs | 7 +---- library/core/src/escape.rs | 61 +++++++++++++++++------------------- 3 files changed, 30 insertions(+), 40 deletions(-) diff --git a/library/core/src/ascii.rs b/library/core/src/ascii.rs index 17fbb19d0397a..e9f4d0f93ed49 100644 --- a/library/core/src/ascii.rs +++ b/library/core/src/ascii.rs @@ -102,7 +102,7 @@ impl EscapeDefault { #[inline] pub(crate) fn empty() -> Self { - EscapeDefault(escape::EscapeIterInner::empty()) + Self(escape::EscapeIterInner::empty()) } #[inline] diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs index d99ac226da005..f3683fe3f9c83 100644 --- a/library/core/src/char/mod.rs +++ b/library/core/src/char/mod.rs @@ -220,7 +220,7 @@ pub struct EscapeDefault(escape::EscapeIterInner<10>); impl EscapeDefault { #[inline] const fn printable(c: ascii::Char) -> Self { - Self::ascii(c.to_u8()) + Self(escape::EscapeIterInner::ascii(c.to_u8())) } #[inline] @@ -228,11 +228,6 @@ impl EscapeDefault { Self(escape::EscapeIterInner::backslash(c)) } - #[inline] - const fn ascii(c: u8) -> Self { - Self(escape::EscapeIterInner::ascii(c)) - } - #[inline] const fn unicode(c: char) -> Self { Self(escape::EscapeIterInner::unicode(c)) diff --git a/library/core/src/escape.rs b/library/core/src/escape.rs index a71fe59e50a13..f6ec30b9f793a 100644 --- a/library/core/src/escape.rs +++ b/library/core/src/escape.rs @@ -7,7 +7,7 @@ use crate::ops::Range; const HEX_DIGITS: [ascii::Char; 16] = *b"0123456789abcdef".as_ascii().unwrap(); #[inline] -const fn backslash(a: ascii::Char) -> ([ascii::Char; N], u8) { +const fn backslash(a: ascii::Char) -> ([ascii::Char; N], Range) { const { assert!(N >= 2) }; let mut output = [ascii::Char::Null; N]; @@ -15,13 +15,13 @@ const fn backslash(a: ascii::Char) -> ([ascii::Char; N], u8) { output[0] = ascii::Char::ReverseSolidus; output[1] = a; - (output, 2) + (output, 0..2) } /// Escapes an ASCII character. /// /// Returns a buffer and the length of the escaped representation. -const fn escape_ascii(byte: u8) -> ([ascii::Char; N], u8) { +const fn escape_ascii(byte: u8) -> ([ascii::Char; N], Range) { const { assert!(N >= 4) }; match byte { @@ -38,7 +38,7 @@ const fn escape_ascii(byte: u8) -> ([ascii::Char; N], u8) { && !byte.is_ascii_control() { output[0] = c; - (output, 1) + (output, 0..1) } else { let hi = HEX_DIGITS[(byte >> 4) as usize]; let lo = HEX_DIGITS[(byte & 0xf) as usize]; @@ -48,7 +48,7 @@ const fn escape_ascii(byte: u8) -> ([ascii::Char; N], u8) { output[2] = hi; output[3] = lo; - (output, 4) + (output, 0..4) } } } @@ -57,34 +57,28 @@ const fn escape_ascii(byte: u8) -> ([ascii::Char; N], u8) { /// Escapes a character `\u{NNNN}` representation. /// /// Returns a buffer and the length of the escaped representation. -const fn escape_unicode(c: char) -> ([ascii::Char; N], u8) { - const { assert!(N >= 10) }; +const fn escape_unicode(c: char) -> ([ascii::Char; N], Range) { + const { assert!(N >= 10 && N < u8::MAX as usize) }; - let c = c as u32; + let c = u32::from(c); // OR-ing `1` ensures that for `c == 0` the code computes that // one digit should be printed. - let u_len = (8 - (c | 1).leading_zeros() / 4) as usize; - - let closing_paren_offset = 3 + u_len; + let start = (c | 1).leading_zeros() as usize / 4 - 2; let mut output = [ascii::Char::Null; N]; - - output[0] = ascii::Char::ReverseSolidus; - output[1] = ascii::Char::SmallU; - output[2] = ascii::Char::LeftCurlyBracket; - - output[3 + u_len.saturating_sub(6)] = HEX_DIGITS[((c >> 20) & 0x0f) as usize]; - output[3 + u_len.saturating_sub(5)] = HEX_DIGITS[((c >> 16) & 0x0f) as usize]; - output[3 + u_len.saturating_sub(4)] = HEX_DIGITS[((c >> 12) & 0x0f) as usize]; - output[3 + u_len.saturating_sub(3)] = HEX_DIGITS[((c >> 8) & 0x0f) as usize]; - output[3 + u_len.saturating_sub(2)] = HEX_DIGITS[((c >> 4) & 0x0f) as usize]; - output[3 + u_len.saturating_sub(1)] = HEX_DIGITS[((c >> 0) & 0x0f) as usize]; - - output[closing_paren_offset] = ascii::Char::RightCurlyBracket; - - let len = (closing_paren_offset + 1) as u8; - (output, len) + output[3] = HEX_DIGITS[((c >> 20) & 15) as usize]; + output[4] = HEX_DIGITS[((c >> 16) & 15) as usize]; + output[5] = HEX_DIGITS[((c >> 12) & 15) as usize]; + output[6] = HEX_DIGITS[((c >> 8) & 15) as usize]; + output[7] = HEX_DIGITS[((c >> 4) & 15) as usize]; + output[8] = HEX_DIGITS[((c >> 0) & 15) as usize]; + output[9] = ascii::Char::RightCurlyBracket; + output[start + 0] = ascii::Char::ReverseSolidus; + output[start + 1] = ascii::Char::SmallU; + output[start + 2] = ascii::Char::LeftCurlyBracket; + + (output, (start as u8)..(N as u8)) } /// An iterator over an fixed-size array. @@ -102,18 +96,18 @@ pub(crate) struct EscapeIterInner { impl EscapeIterInner { pub const fn backslash(c: ascii::Char) -> Self { - let (data, len) = backslash(c); - Self { data, alive: 0..len } + let (data, range) = backslash(c); + Self { data, alive: range } } pub const fn ascii(c: u8) -> Self { - let (data, len) = escape_ascii(c); - Self { data, alive: 0..len } + let (data, range) = escape_ascii(c); + Self { data, alive: range } } pub const fn unicode(c: char) -> Self { - let (data, len) = escape_unicode(c); - Self { data, alive: 0..len } + let (data, range) = escape_unicode(c); + Self { data, alive: range } } #[inline] @@ -121,6 +115,7 @@ impl EscapeIterInner { Self { data: [ascii::Char::Null; N], alive: 0..0 } } + #[inline] pub fn as_ascii(&self) -> &[ascii::Char] { // SAFETY: `self.alive` is guaranteed to be a valid range for indexing `self.data`. unsafe { From fa5964fa9198e5c23e457821aa88bef34833b571 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 10 May 2024 11:57:10 -0700 Subject: [PATCH 04/48] s/MetaVarExpr::Length/MetaVarExpr::Len/ --- compiler/rustc_expand/src/mbe/metavar_expr.rs | 10 +++++----- compiler/rustc_expand/src/mbe/quoted.rs | 2 +- compiler/rustc_expand/src/mbe/transcribe.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 8239cfd46cbfe..128e9f48ff573 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -23,7 +23,7 @@ pub(crate) enum MetaVarExpr { /// The length of the repetition at a particular depth, where 0 is the inner-most /// repetition. The `usize` is the depth. - Length(usize), + Len(usize), } impl MetaVarExpr { @@ -48,13 +48,13 @@ impl MetaVarExpr { MetaVarExpr::Ignore(parse_ident(&mut iter, psess, ident.span)?) } "index" => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?), - "length" => MetaVarExpr::Length(parse_depth(&mut iter, psess, ident.span)?), + "len" => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?), _ => { let err_msg = "unrecognized meta-variable expression"; let mut err = psess.dcx.struct_span_err(ident.span, err_msg); err.span_suggestion( ident.span, - "supported expressions are count, ignore, index and length", + "supported expressions are count, ignore, index and len", "", Applicability::MachineApplicable, ); @@ -68,7 +68,7 @@ impl MetaVarExpr { pub(crate) fn ident(&self) -> Option { match *self { MetaVarExpr::Count(ident, _) | MetaVarExpr::Ignore(ident) => Some(ident), - MetaVarExpr::Index(..) | MetaVarExpr::Length(..) => None, + MetaVarExpr::Index(..) | MetaVarExpr::Len(..) => None, } } } @@ -111,7 +111,7 @@ fn parse_count<'psess>( Ok(MetaVarExpr::Count(ident, depth)) } -/// Parses the depth used by index(depth) and length(depth). +/// Parses the depth used by index(depth) and len(depth). fn parse_depth<'psess>( iter: &mut RefTokenTreeCursor<'_>, psess: &'psess ParseSess, diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 06c1612ddbaea..2e5596f51c35d 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -357,7 +357,7 @@ fn parse_sep_and_kleene_op<'a>( // `$$` or a meta-variable is the lhs of a macro but shouldn't. // -// For example, `macro_rules! foo { ( ${length()} ) => {} }` +// For example, `macro_rules! foo { ( ${len()} ) => {} }` fn span_dollar_dollar_or_metavar_in_the_lhs_err(sess: &Session, token: &Token) { sess.dcx() .span_err(token.span, format!("unexpected token: {}", pprust::token_to_string(token))); diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 011aa95c8a116..139d58b3a7688 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -675,14 +675,14 @@ fn transcribe_metavar_expr<'a>( } None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "index")), }, - MetaVarExpr::Length(depth) => match repeats.iter().nth_back(depth) { + MetaVarExpr::Len(depth) => match repeats.iter().nth_back(depth) { Some((_, length)) => { result.push(TokenTree::token_alone( TokenKind::lit(token::Integer, sym::integer(*length), None), visited_span(), )); } - None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "length")), + None => return Err(out_of_bounds_err(cx, repeats.len(), sp.entire(), "len")), }, } Ok(()) From 6e74155b0bbcf67b8319dd292ac793abcbf16ee7 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Fri, 10 May 2024 12:12:39 -0700 Subject: [PATCH 05/48] fix tests after s/${length()}/${len()}/ --- .../meta-variable-depth-outside-repeat.rs | 4 +- .../meta-variable-depth-outside-repeat.stderr | 6 +- .../count-and-length-are-distinct.rs | 108 +++++++++------- .../feature-gate-macro_metavar_expr.rs | 11 +- .../rfc-3086-metavar-expr/macro-expansion.rs | 10 +- .../out-of-bounds-arguments.rs | 6 +- .../out-of-bounds-arguments.stderr | 6 +- .../rfc-3086-metavar-expr/required-feature.rs | 7 +- .../required-feature.stderr | 6 +- .../rfc-3086-metavar-expr/syntax-errors.rs | 9 +- .../syntax-errors.stderr | 122 +++++++++--------- 11 files changed, 155 insertions(+), 140 deletions(-) diff --git a/tests/ui/macros/meta-variable-depth-outside-repeat.rs b/tests/ui/macros/meta-variable-depth-outside-repeat.rs index b7fb947854f04..89b4706360617 100644 --- a/tests/ui/macros/meta-variable-depth-outside-repeat.rs +++ b/tests/ui/macros/meta-variable-depth-outside-repeat.rs @@ -2,8 +2,8 @@ macro_rules! metavar { ( $i:expr ) => { - ${length(0)} - //~^ ERROR meta-variable expression `length` with depth parameter must be called inside of a macro repetition + ${len(0)} + //~^ ERROR meta-variable expression `len` with depth parameter must be called inside of a macro repetition }; } diff --git a/tests/ui/macros/meta-variable-depth-outside-repeat.stderr b/tests/ui/macros/meta-variable-depth-outside-repeat.stderr index 49b5053a023cc..4299ca9842483 100644 --- a/tests/ui/macros/meta-variable-depth-outside-repeat.stderr +++ b/tests/ui/macros/meta-variable-depth-outside-repeat.stderr @@ -1,8 +1,8 @@ -error: meta-variable expression `length` with depth parameter must be called inside of a macro repetition +error: meta-variable expression `len` with depth parameter must be called inside of a macro repetition --> $DIR/meta-variable-depth-outside-repeat.rs:5:10 | -LL | ${length(0)} - | ^^^^^^^^^^^ +LL | ${len(0)} + | ^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs b/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs index 3a14e0c64fd1d..131d4166de04a 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs +++ b/tests/ui/macros/rfc-3086-metavar-expr/count-and-length-are-distinct.rs @@ -3,60 +3,55 @@ #![feature(macro_metavar_expr)] fn main() { - macro_rules! one_nested_count_and_length { + macro_rules! one_nested_count_and_len { ( $( [ $( $l:literal ),* ] ),* ) => { [ // outer-most repetition $( // inner-most repetition $( - ${ignore($l)} ${index()}, ${length()}, + ${ignore($l)} ${index()}, ${len()}, )* - ${count($l)}, ${index()}, ${length()}, + ${count($l)}, ${index()}, ${len()}, )* ${count($l)}, ] }; } assert_eq!( - one_nested_count_and_length!(["foo"], ["bar", "baz"]), + one_nested_count_and_len!(["foo"], ["bar", "baz"]), [ // # ["foo"] // ## inner-most repetition (first iteration) // // `index` is 0 because this is the first inner-most iteration. - // `length` is 1 because there is only one inner-most repetition, "foo". + // `len` is 1 because there is only one inner-most repetition, "foo". 0, 1, - // ## outer-most repetition (first iteration) // // `count` is 1 because of "foo", i,e, `$l` has only one repetition, // `index` is 0 because this is the first outer-most iteration. - // `length` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"] + // `len` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"] 1, 0, 2, - // # ["bar", "baz"] // ## inner-most repetition (first iteration) // // `index` is 0 because this is the first inner-most iteration - // `length` is 2 because there are repetitions, "bar" and "baz" + // `len` is 2 because there are repetitions, "bar" and "baz" 0, 2, - // ## inner-most repetition (second iteration) // // `index` is 1 because this is the second inner-most iteration - // `length` is 2 because there are repetitions, "bar" and "baz" + // `len` is 2 because there are repetitions, "bar" and "baz" 1, 2, - // ## outer-most repetition (second iteration) // // `count` is 2 because of "bar" and "baz", i,e, `$l` has two repetitions, // `index` is 1 because this is the second outer-most iteration - // `length` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"] + // `len` is 2 because there are 2 outer-most repetitions, ["foo"] and ["bar", "baz"] 2, 1, 2, - // # last count // Because there are a total of 3 repetitions of `$l`, "foo", "bar" and "baz" @@ -131,7 +126,6 @@ fn main() { &[2][..], // t u v w x y z &[7][..], - // (a b c) (d e f) &[6, 2][..], // (g h) (i j k l m) @@ -142,7 +136,6 @@ fn main() { &[5, 3][..], // (t u v w x y z) &[7, 1][..], - // [ (a b c) (d e f) ] // [ (g h) (i j k l m) ] // [ (n) ] @@ -150,7 +143,6 @@ fn main() { // [ (o) (p q) (r s) ] // [ (t u v w x y z) ] &[12, 4, 2][..], - // { // [ (a b c) (d e f) ] // [ (g h) (i j k l m) ] @@ -165,43 +157,43 @@ fn main() { ); // Grouped from the outer-most to the inner-most - macro_rules! three_nested_length { + macro_rules! three_nested_len { ( $( { $( [ $( ( $( $i:ident )* ) )* ] )* } )* ) => { &[ $( $( $( $( &[ - ${ignore($i)} ${length(3)}, - ${ignore($i)} ${length(2)}, - ${ignore($i)} ${length(1)}, - ${ignore($i)} ${length(0)}, + ${ignore($i)} ${len(3)}, + ${ignore($i)} ${len(2)}, + ${ignore($i)} ${len(1)}, + ${ignore($i)} ${len(0)}, ][..], )* )* )* )* $( $( $( &[ - ${ignore($i)} ${length(2)}, - ${ignore($i)} ${length(1)}, - ${ignore($i)} ${length(0)}, + ${ignore($i)} ${len(2)}, + ${ignore($i)} ${len(1)}, + ${ignore($i)} ${len(0)}, ][..], )* )* )* $( $( &[ - ${ignore($i)} ${length(1)}, - ${ignore($i)} ${length(0)}, + ${ignore($i)} ${len(1)}, + ${ignore($i)} ${len(0)}, ][..], )* )* $( &[ - ${ignore($i)} ${length(0)}, + ${ignore($i)} ${len(0)}, ][..], )* ][..] } } assert_eq!( - three_nested_length!( + three_nested_len!( { [ (a b c) (d e f) ] [ (g h) (i j k l m) ] @@ -214,45 +206,64 @@ fn main() { ), &[ // a b c - &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], + &[2, 3, 2, 3][..], + &[2, 3, 2, 3][..], + &[2, 3, 2, 3][..], // d e f - &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], &[2, 3, 2, 3][..], + &[2, 3, 2, 3][..], + &[2, 3, 2, 3][..], + &[2, 3, 2, 3][..], // g h - &[2, 3, 2, 2][..], &[2, 3, 2, 2][..], + &[2, 3, 2, 2][..], + &[2, 3, 2, 2][..], // i j k l m - &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], + &[2, 3, 2, 5][..], + &[2, 3, 2, 5][..], + &[2, 3, 2, 5][..], + &[2, 3, 2, 5][..], &[2, 3, 2, 5][..], // n &[2, 3, 1, 1][..], // o &[2, 2, 3, 1][..], // p q - &[2, 2, 3, 2][..], &[2, 2, 3, 2][..], + &[2, 2, 3, 2][..], + &[2, 2, 3, 2][..], // r s - &[2, 2, 3, 2][..], &[2, 2, 3, 2][..], + &[2, 2, 3, 2][..], + &[2, 2, 3, 2][..], // t u v w x y z - &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], - &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], &[2, 2, 1, 7][..], - + &[2, 2, 1, 7][..], + &[2, 2, 1, 7][..], + &[2, 2, 1, 7][..], + &[2, 2, 1, 7][..], + &[2, 2, 1, 7][..], + &[2, 2, 1, 7][..], + &[2, 2, 1, 7][..], // (a b c) (d e f) - &[2, 3, 2][..], &[2, 3, 2][..], + &[2, 3, 2][..], + &[2, 3, 2][..], // (g h) (i j k l m) - &[2, 3, 2][..], &[2, 3, 2][..], + &[2, 3, 2][..], + &[2, 3, 2][..], // (n) &[2, 3, 1][..], // (o) (p q) (r s) - &[2, 2, 3][..], &[2, 2, 3][..], &[2, 2, 3][..], + &[2, 2, 3][..], + &[2, 2, 3][..], + &[2, 2, 3][..], // (t u v w x y z) &[2, 2, 1][..], - // [ (a b c) (d e f) ] // [ (g h) (i j k l m) ] // [ (n) ] - &[2, 3][..], &[2, 3][..], &[2, 3,][..], + &[2, 3][..], + &[2, 3][..], + &[2, 3,][..], // [ (o) (p q) (r s) ] // [ (t u v w x y z) ] - &[2, 2][..], &[2, 2][..], - + &[2, 2][..], + &[2, 2][..], // { // [ (a b c) (d e f) ] // [ (g h) (i j k l m) ] @@ -262,10 +273,11 @@ fn main() { // [ (o) (p q) (r s) ] // [ (t u v w x y z) ] // } - &[2][..], &[2][..] + &[2][..], + &[2][..] ][..] ); - // It is possible to say, to some degree, that count is an "amalgamation" of length (see - // each length line result and compare them with the count results) + // It is possible to say, to some degree, that count is an "amalgamation" of len (see + // each len line result and compare them with the count results) } diff --git a/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs b/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs index 6464fd6f2fd2f..51445221c57b4 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs +++ b/tests/ui/macros/rfc-3086-metavar-expr/feature-gate-macro_metavar_expr.rs @@ -37,17 +37,17 @@ macro_rules! count_depth_limits { }; } -/// Produce (index, length) pairs for literals in a macro repetition. +/// Produce (index, len) pairs for literals in a macro repetition. /// The literal is not included in the output, so this macro uses the /// `ignore` meta-variable expression to create a non-expanding /// repetition binding. macro_rules! enumerate_literals { ( $( ($l:stmt) ),* ) => { - [$( ${ignore($l)} (${index()}, ${length()}) ),*] + [$( ${ignore($l)} (${index()}, ${len()}) ),*] }; } -/// Produce index and length tuples for literals in a 2-dimensional +/// Produce index and len tuples for literals in a 2-dimensional /// macro repetition. macro_rules! enumerate_literals_2 { ( $( [ $( ($l:literal) ),* ] ),* ) => { @@ -56,9 +56,9 @@ macro_rules! enumerate_literals_2 { $( ( ${index(1)}, - ${length(1)}, + ${len(1)}, ${index(0)}, - ${length(0)}, + ${len(0)}, $l ), )* @@ -134,7 +134,6 @@ fn main() { (0, 2, 0, 3, "foo"), (0, 2, 1, 3, "bar"), (0, 2, 2, 3, "baz"), - (1, 2, 0, 4, "qux"), (1, 2, 1, 4, "quux"), (1, 2, 2, 4, "quuz"), diff --git a/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs b/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs index 787b927c449b3..1d34275874bc1 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs +++ b/tests/ui/macros/rfc-3086-metavar-expr/macro-expansion.rs @@ -17,20 +17,20 @@ macro_rules! example { _nested: vec![ $( Example { - _indexes: &[(${index()}, ${length()})], + _indexes: &[(${index()}, ${len()})], _counts: &[${count($x, 0)}, ${count($x, 1)}], _nested: vec![ $( Example { - _indexes: &[(${index(1)}, ${length(1)}), (${index()}, ${length()})], + _indexes: &[(${index(1)}, ${len(1)}), (${index()}, ${len()})], _counts: &[${count($x)}], _nested: vec![ $( Example { _indexes: &[ - (${index(2)}, ${length(2)}), - (${index(1)}, ${length(1)}), - (${index()}, ${length()}) + (${index(2)}, ${len(2)}), + (${index(1)}, ${len(1)}), + (${index()}, ${len()}) ], _counts: &[], _nested: vec![], diff --git a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs index d195506af3612..0caa3ea89e4d6 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs +++ b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.rs @@ -28,9 +28,9 @@ macro_rules! c { ( $( $( ${ignore($foo)} - ${length(0)} - ${length(10)} - //~^ ERROR depth parameter of meta-variable expression `length` must be less than 2 + ${len(0)} + ${len(10)} + //~^ ERROR depth parameter of meta-variable expression `len` must be less than 2 )* )* ) }; diff --git a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr index f757b8af219fd..0b441cad083fc 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr +++ b/tests/ui/macros/rfc-3086-metavar-expr/out-of-bounds-arguments.stderr @@ -10,11 +10,11 @@ error: depth parameter of meta-variable expression `index` must be less than 3 LL | ${index(10)}, | ^^^^^^^^^^^ -error: depth parameter of meta-variable expression `length` must be less than 2 +error: depth parameter of meta-variable expression `len` must be less than 2 --> $DIR/out-of-bounds-arguments.rs:32:18 | -LL | ${length(10)} - | ^^^^^^^^^^^^ +LL | ${len(10)} + | ^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs index 53d045700f9fe..77c165e385593 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs +++ b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.rs @@ -32,13 +32,12 @@ macro_rules! ignore { }}; } -macro_rules! length { +macro_rules! len { ( $( $e:stmt ),* ) => { - $( ${ignore($e)} ${length()} )* + $( ${ignore($e)} ${len()} )* //~^ ERROR meta-variable expressions are unstable //~| ERROR meta-variable expressions are unstable }; } -fn main() { -} +fn main() {} diff --git a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr index 7f4adb728c0b6..f28f822a05883 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr +++ b/tests/ui/macros/rfc-3086-metavar-expr/required-feature.stderr @@ -81,7 +81,7 @@ LL | 0 $( + 1 ${ignore($i)} )* error[E0658]: meta-variable expressions are unstable --> $DIR/required-feature.rs:37:13 | -LL | $( ${ignore($e)} ${length()} )* +LL | $( ${ignore($e)} ${len()} )* | ^^^^^^^^^^^^ | = note: see issue #83527 for more information @@ -91,8 +91,8 @@ LL | $( ${ignore($e)} ${length()} )* error[E0658]: meta-variable expressions are unstable --> $DIR/required-feature.rs:37:27 | -LL | $( ${ignore($e)} ${length()} )* - | ^^^^^^^^^^ +LL | $( ${ignore($e)} ${len()} )* + | ^^^^^^^ | = note: see issue #83527 for more information = help: add `#![feature(macro_metavar_expr)]` to the crate attributes to enable diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs index 05c65fe869073..9fec546ecd65e 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs +++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.rs @@ -18,23 +18,27 @@ macro_rules! curly__rhs_dollar__no_round { //~^ ERROR `count` can not be placed inside the inner-most repetition } +#[rustfmt::skip] // autoformatters can break a few of the error traces macro_rules! no_curly__no_rhs_dollar__round { ( $( $i:ident ),* ) => { count(i) }; //~^ ERROR cannot find function `count` in this scope //~| ERROR cannot find value `i` in this scope } +#[rustfmt::skip] // autoformatters can break a few of the error traces macro_rules! no_curly__no_rhs_dollar__no_round { ( $i:ident ) => { count(i) }; //~^ ERROR cannot find function `count` in this scope //~| ERROR cannot find value `i` in this scope } +#[rustfmt::skip] // autoformatters can break a few of the error traces macro_rules! no_curly__rhs_dollar__round { ( $( $i:ident ),* ) => { count($i) }; //~^ ERROR variable 'i' is still repeating at this depth } +#[rustfmt::skip] // autoformatters can break a few of the error traces macro_rules! no_curly__rhs_dollar__no_round { ( $i:ident ) => { count($i) }; //~^ ERROR cannot find function `count` in this scope @@ -44,7 +48,7 @@ macro_rules! no_curly__rhs_dollar__no_round { macro_rules! dollar_dollar_in_the_lhs { ( $$ $a:ident ) => { - //~^ ERROR unexpected token: $ + //~^ ERROR unexpected token: $ }; } @@ -85,7 +89,7 @@ macro_rules! metavar_depth_is_not_literal { } macro_rules! metavar_in_the_lhs { - ( ${ length() } ) => { + ( ${ len() } ) => { //~^ ERROR unexpected token: { //~| ERROR expected one of: `*`, `+`, or `?` }; @@ -109,6 +113,7 @@ macro_rules! metavar_without_parens { //~| ERROR expected expression, found `$` } +#[rustfmt::skip] macro_rules! open_brackets_without_tokens { ( $( $i:ident ),* ) => { ${ {} } }; //~^ ERROR expected expression, found `$` diff --git a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr index 0dda38290ab6b..e9cef5ec6cc96 100644 --- a/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr +++ b/tests/ui/macros/rfc-3086-metavar-expr/syntax-errors.stderr @@ -1,200 +1,200 @@ error: unexpected token: $ - --> $DIR/syntax-errors.rs:46:8 + --> $DIR/syntax-errors.rs:50:8 | LL | ( $$ $a:ident ) => { | ^ note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions - --> $DIR/syntax-errors.rs:46:8 + --> $DIR/syntax-errors.rs:50:8 | LL | ( $$ $a:ident ) => { | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:53:19 + --> $DIR/syntax-errors.rs:57:19 | LL | ${count() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:53:19 + --> $DIR/syntax-errors.rs:57:19 | LL | ${count() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:56:20 + --> $DIR/syntax-errors.rs:60:20 | LL | ${count($i a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:56:20 + --> $DIR/syntax-errors.rs:60:20 | LL | ${count($i a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:58:23 + --> $DIR/syntax-errors.rs:62:23 | LL | ${count($i, 1 a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:58:23 + --> $DIR/syntax-errors.rs:62:23 | LL | ${count($i, 1 a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:60:21 + --> $DIR/syntax-errors.rs:64:21 | LL | ${count($i) a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:60:21 + --> $DIR/syntax-errors.rs:64:21 | LL | ${count($i) a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:63:22 + --> $DIR/syntax-errors.rs:67:22 | LL | ${ignore($i) a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:63:22 + --> $DIR/syntax-errors.rs:67:22 | LL | ${ignore($i) a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:65:21 + --> $DIR/syntax-errors.rs:69:21 | LL | ${ignore($i a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:65:21 + --> $DIR/syntax-errors.rs:69:21 | LL | ${ignore($i a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:68:19 + --> $DIR/syntax-errors.rs:72:19 | LL | ${index() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:68:19 + --> $DIR/syntax-errors.rs:72:19 | LL | ${index() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:70:19 + --> $DIR/syntax-errors.rs:74:19 | LL | ${index(1 a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:70:19 + --> $DIR/syntax-errors.rs:74:19 | LL | ${index(1 a b c)} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:73:19 + --> $DIR/syntax-errors.rs:77:19 | LL | ${index() a b c} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:73:19 + --> $DIR/syntax-errors.rs:77:19 | LL | ${index() a b c} | ^ error: unexpected token: a - --> $DIR/syntax-errors.rs:75:19 + --> $DIR/syntax-errors.rs:79:19 | LL | ${index(1 a b c)} | ^ | note: meta-variable expression must not have trailing tokens - --> $DIR/syntax-errors.rs:75:19 + --> $DIR/syntax-errors.rs:79:19 | LL | ${index(1 a b c)} | ^ error: meta-variable expression depth must be a literal - --> $DIR/syntax-errors.rs:82:33 + --> $DIR/syntax-errors.rs:86:33 | LL | ( $( $i:ident ),* ) => { ${ index(IDX) } }; | ^^^^^ error: unexpected token: { - --> $DIR/syntax-errors.rs:88:8 + --> $DIR/syntax-errors.rs:92:8 | -LL | ( ${ length() } ) => { - | ^^^^^^^^^^^^ +LL | ( ${ len() } ) => { + | ^^^^^^^^^ note: `$$` and meta-variable expressions are not allowed inside macro parameter definitions - --> $DIR/syntax-errors.rs:88:8 + --> $DIR/syntax-errors.rs:92:8 | -LL | ( ${ length() } ) => { - | ^^^^^^^^^^^^ +LL | ( ${ len() } ) => { + | ^^^^^^^^^ error: expected one of: `*`, `+`, or `?` - --> $DIR/syntax-errors.rs:88:8 + --> $DIR/syntax-errors.rs:92:8 | -LL | ( ${ length() } ) => { - | ^^^^^^^^^^^^ +LL | ( ${ len() } ) => { + | ^^^^^^^^^ error: meta-variables within meta-variable expressions must be referenced using a dollar sign - --> $DIR/syntax-errors.rs:95:33 + --> $DIR/syntax-errors.rs:99:33 | LL | ( $( $i:ident ),* ) => { ${ ignore() } }; | ^^^^^^ error: only unsuffixes integer literals are supported in meta-variable expressions - --> $DIR/syntax-errors.rs:101:33 + --> $DIR/syntax-errors.rs:105:33 | LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; | ^^^^^ error: meta-variable expression parameter must be wrapped in parentheses - --> $DIR/syntax-errors.rs:107:33 + --> $DIR/syntax-errors.rs:111:33 | LL | ( $( $i:ident ),* ) => { ${ count{i} } }; | ^^^^^ -error: expected identifier - --> $DIR/syntax-errors.rs:113:31 - | -LL | ( $( $i:ident ),* ) => { ${ {} } }; - | ^^^^^^ - error: meta-variables within meta-variable expressions must be referenced using a dollar sign - --> $DIR/syntax-errors.rs:120:11 + --> $DIR/syntax-errors.rs:125:11 | LL | ${count(foo)} | ^^^^^ error: meta-variables within meta-variable expressions must be referenced using a dollar sign - --> $DIR/syntax-errors.rs:128:11 + --> $DIR/syntax-errors.rs:133:11 | LL | ${ignore(bar)} | ^^^^^^ error: unrecognized meta-variable expression - --> $DIR/syntax-errors.rs:135:33 + --> $DIR/syntax-errors.rs:140:33 | LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; - | ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and length + | ^^^^^^^^^^^^^^ help: supported expressions are count, ignore, index and len + +error: expected identifier + --> $DIR/syntax-errors.rs:118:31 + | +LL | ( $( $i:ident ),* ) => { ${ {} } }; + | ^^^^^^ error: `count` can not be placed inside the inner-most repetition --> $DIR/syntax-errors.rs:12:24 @@ -209,13 +209,13 @@ LL | ( $i:ident ) => { ${ count($i) } }; | ^^^^^^^^^^^^^ error: variable 'i' is still repeating at this depth - --> $DIR/syntax-errors.rs:34:36 + --> $DIR/syntax-errors.rs:37:36 | LL | ( $( $i:ident ),* ) => { count($i) }; | ^^ error: expected expression, found `$` - --> $DIR/syntax-errors.rs:53:9 + --> $DIR/syntax-errors.rs:57:9 | LL | ${count() a b c} | ^ expected expression @@ -226,7 +226,7 @@ LL | extra_garbage_after_metavar!(a); = note: this error originates in the macro `extra_garbage_after_metavar` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected expression, found `$` - --> $DIR/syntax-errors.rs:82:30 + --> $DIR/syntax-errors.rs:86:30 | LL | ( $( $i:ident ),* ) => { ${ index(IDX) } }; | ^ expected expression @@ -237,7 +237,7 @@ LL | metavar_depth_is_not_literal!(a); = note: this error originates in the macro `metavar_depth_is_not_literal` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected expression, found `$` - --> $DIR/syntax-errors.rs:95:30 + --> $DIR/syntax-errors.rs:99:30 | LL | ( $( $i:ident ),* ) => { ${ ignore() } }; | ^ expected expression @@ -248,7 +248,7 @@ LL | metavar_token_without_ident!(a); = note: this error originates in the macro `metavar_token_without_ident` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected expression, found `$` - --> $DIR/syntax-errors.rs:101:30 + --> $DIR/syntax-errors.rs:105:30 | LL | ( $( $i:ident ),* ) => { ${ index(1u32) } }; | ^ expected expression @@ -259,7 +259,7 @@ LL | metavar_with_literal_suffix!(a); = note: this error originates in the macro `metavar_with_literal_suffix` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected expression, found `$` - --> $DIR/syntax-errors.rs:107:30 + --> $DIR/syntax-errors.rs:111:30 | LL | ( $( $i:ident ),* ) => { ${ count{i} } }; | ^ expected expression @@ -270,7 +270,7 @@ LL | metavar_without_parens!(a); = note: this error originates in the macro `metavar_without_parens` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected expression, found `$` - --> $DIR/syntax-errors.rs:113:30 + --> $DIR/syntax-errors.rs:118:30 | LL | ( $( $i:ident ),* ) => { ${ {} } }; | ^ expected expression @@ -281,7 +281,7 @@ LL | open_brackets_without_tokens!(a); = note: this error originates in the macro `open_brackets_without_tokens` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected expression, found `$` - --> $DIR/syntax-errors.rs:120:9 + --> $DIR/syntax-errors.rs:125:9 | LL | ${count(foo)} | ^ expected expression @@ -292,7 +292,7 @@ LL | unknown_count_ident!(a); = note: this error originates in the macro `unknown_count_ident` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected expression, found `$` - --> $DIR/syntax-errors.rs:128:9 + --> $DIR/syntax-errors.rs:133:9 | LL | ${ignore(bar)} | ^ expected expression @@ -303,7 +303,7 @@ LL | unknown_ignore_ident!(a); = note: this error originates in the macro `unknown_ignore_ident` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected expression, found `$` - --> $DIR/syntax-errors.rs:135:30 + --> $DIR/syntax-errors.rs:140:30 | LL | ( $( $i:ident ),* ) => { ${ aaaaaaaaaaaaaa(i) } }; | ^ expected expression @@ -314,7 +314,7 @@ LL | unknown_metavar!(a); = note: this error originates in the macro `unknown_metavar` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `i` in this scope - --> $DIR/syntax-errors.rs:22:36 + --> $DIR/syntax-errors.rs:23:36 | LL | ( $( $i:ident ),* ) => { count(i) }; | ^ not found in this scope @@ -325,7 +325,7 @@ LL | no_curly__no_rhs_dollar__round!(a, b, c); = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `i` in this scope - --> $DIR/syntax-errors.rs:28:29 + --> $DIR/syntax-errors.rs:30:29 | LL | ( $i:ident ) => { count(i) }; | ^ not found in this scope @@ -336,13 +336,13 @@ LL | no_curly__no_rhs_dollar__no_round!(a); = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `a` in this scope - --> $DIR/syntax-errors.rs:147:37 + --> $DIR/syntax-errors.rs:152:37 | LL | no_curly__rhs_dollar__no_round!(a); | ^ not found in this scope error[E0425]: cannot find function `count` in this scope - --> $DIR/syntax-errors.rs:22:30 + --> $DIR/syntax-errors.rs:23:30 | LL | ( $( $i:ident ),* ) => { count(i) }; | ^^^^^ not found in this scope @@ -353,7 +353,7 @@ LL | no_curly__no_rhs_dollar__round!(a, b, c); = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find function `count` in this scope - --> $DIR/syntax-errors.rs:28:23 + --> $DIR/syntax-errors.rs:30:23 | LL | ( $i:ident ) => { count(i) }; | ^^^^^ not found in this scope @@ -364,7 +364,7 @@ LL | no_curly__no_rhs_dollar__no_round!(a); = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find function `count` in this scope - --> $DIR/syntax-errors.rs:39:23 + --> $DIR/syntax-errors.rs:43:23 | LL | ( $i:ident ) => { count($i) }; | ^^^^^ not found in this scope From 35a5be2833a555b15a11280e9ed80f9d90fc0809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 11 May 2024 00:39:42 +0200 Subject: [PATCH 06/48] Also expand weak alias tys inside consts inside `expand_weak_alias_tys` --- compiler/rustc_middle/src/ty/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index f5e973f85da12..6d9d0f232d6bf 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1130,7 +1130,7 @@ impl<'tcx> TypeFolder> for WeakAliasTypeExpander<'tcx> { } fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - if !ct.ty().has_type_flags(ty::TypeFlags::HAS_TY_WEAK) { + if !ct.has_type_flags(ty::TypeFlags::HAS_TY_WEAK) { return ct; } ct.super_fold_with(self) From 848f3c2c6e65c799bb87e5f0308ad7556f7e7fcb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 11 May 2024 19:49:18 -0400 Subject: [PATCH 07/48] Make crashes dump mir to build dir --- src/tools/compiletest/src/runtest.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 1d69ed598591f..02c9d384ab7e4 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2478,6 +2478,15 @@ impl<'test> TestCx<'test> { } } + let set_mir_dump_dir = |rustc: &mut Command| { + let mir_dump_dir = self.get_mir_dump_dir(); + remove_and_create_dir_all(&mir_dump_dir); + let mut dir_opt = "-Zdump-mir-dir=".to_string(); + dir_opt.push_str(mir_dump_dir.to_str().unwrap()); + debug!("dir_opt: {:?}", dir_opt); + rustc.arg(dir_opt); + }; + match self.config.mode { Incremental => { // If we are extracting and matching errors in the new @@ -2532,13 +2541,7 @@ impl<'test> TestCx<'test> { ]); } - let mir_dump_dir = self.get_mir_dump_dir(); - remove_and_create_dir_all(&mir_dump_dir); - let mut dir_opt = "-Zdump-mir-dir=".to_string(); - dir_opt.push_str(mir_dump_dir.to_str().unwrap()); - debug!("dir_opt: {:?}", dir_opt); - - rustc.arg(dir_opt); + set_mir_dump_dir(&mut rustc); } CoverageMap => { rustc.arg("-Cinstrument-coverage"); @@ -2560,8 +2563,11 @@ impl<'test> TestCx<'test> { Assembly | Codegen => { rustc.arg("-Cdebug-assertions=no"); } + Crashes => { + set_mir_dump_dir(&mut rustc); + } RunPassValgrind | Pretty | DebugInfo | Rustdoc | RustdocJson | RunMake - | CodegenUnits | JsDocTest | Crashes => { + | CodegenUnits | JsDocTest => { // do not use JSON output } } From 7fde7308bf751315e0f4fabe32258916b166e34e Mon Sep 17 00:00:00 2001 From: ivan-shrimp <70307174+ivan-shrimp@users.noreply.github.com> Date: Sun, 12 May 2024 11:29:24 +0800 Subject: [PATCH 08/48] reverse condition in `uN::checked_sub` --- library/core/src/num/uint_macros.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 48a96c5792c64..446d0658c1262 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -584,11 +584,11 @@ macro_rules! uint_impl { // Thus, rather than using `overflowing_sub` that produces a wrapping // subtraction, check it ourself so we can use an unchecked one. - if self >= rhs { + if self < rhs { + None + } else { // SAFETY: just checked this can't overflow Some(unsafe { intrinsics::unchecked_sub(self, rhs) }) - } else { - None } } From f2de5fb2ae0f69d403a06ff4f963e63d95406591 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Sun, 12 May 2024 14:00:09 -0400 Subject: [PATCH 09/48] rewrite issue-14500 to rmake --- src/tools/run-make-support/src/rustc.rs | 14 +++++++++ .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/issue-14500/Makefile | 15 --------- tests/run-make/issue-14500/rmake.rs | 31 +++++++++++++++++++ 4 files changed, 45 insertions(+), 16 deletions(-) delete mode 100644 tests/run-make/issue-14500/Makefile create mode 100644 tests/run-make/issue-14500/rmake.rs diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index de773d688ef00..c92e9f9b11f4c 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -150,6 +150,20 @@ impl Rustc { self } + /// Pass a codegen option. + pub fn codegen_option(&mut self, option: &str) -> &mut Self { + self.cmd.arg("-C"); + self.cmd.arg(option); + self + } + + /// Add a directory to the library search path. + pub fn library_search_path>(&mut self, path: P) -> &mut Self { + self.cmd.arg("-L"); + self.cmd.arg(path.as_ref()); + self + } + /// Specify the edition year. pub fn edition(&mut self, edition: &str) -> &mut Self { self.cmd.arg("--edition"); diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index e87950b36d9df..a358bc89e1385 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -99,7 +99,6 @@ run-make/issue-107094/Makefile run-make/issue-10971-temps-dir/Makefile run-make/issue-109934-lto-debuginfo/Makefile run-make/issue-11908/Makefile -run-make/issue-14500/Makefile run-make/issue-14698/Makefile run-make/issue-15460/Makefile run-make/issue-18943/Makefile diff --git a/tests/run-make/issue-14500/Makefile b/tests/run-make/issue-14500/Makefile deleted file mode 100644 index eeab48de3b950..0000000000000 --- a/tests/run-make/issue-14500/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -include ../tools.mk - -# ignore-cross-compile - -# Test to make sure that reachable extern fns are always available in final -# productcs, including when LTO is used. In this test, the `foo` crate has a -# reahable symbol, and is a dependency of the `bar` crate. When the `bar` crate -# is compiled with LTO, it shouldn't strip the symbol from `foo`, and that's the -# only way that `foo.c` will successfully compile. - -all: - $(RUSTC) foo.rs --crate-type=rlib - $(RUSTC) bar.rs --crate-type=staticlib -C lto -L. -o $(TMPDIR)/libbar.a - $(CC) foo.c $(TMPDIR)/libbar.a $(EXTRACFLAGS) $(call OUT_EXE,foo) - $(call RUN,foo) diff --git a/tests/run-make/issue-14500/rmake.rs b/tests/run-make/issue-14500/rmake.rs new file mode 100644 index 0000000000000..58c6bc9ebb3a4 --- /dev/null +++ b/tests/run-make/issue-14500/rmake.rs @@ -0,0 +1,31 @@ +// Test to make sure that reachable extern fns are always available in final +// productcs, including when LTO is used. + +// In this test, the `foo` crate has a reahable symbol, +// and is a dependency of the `bar` crate. When the `bar` crate +// is compiled with LTO, it shouldn't strip the symbol from `foo`, and that's the +// only way that `foo.c` will successfully compile. +// See https://github.com/rust-lang/rust/issues/14500 + +//@ ignore-cross-compile + +use run_make_support::{cc, extra_c_flags, run, rustc}; + +fn main() { + let libbar_path = tmp_dir().join("libbar.a"); + rustc().input("foo.rs") + .crate_type("rlib") + .run(); + rustc().input("bar.rs") + .static_lib("staticlib") + .codegen_option("lto") + .library_search_path(".") + .output(&libbar_path) + .run(); + cc().input("foo.c") + .input(libbar_path) + .args(&extra_c_flags()) + .out_exe("foo") + .run(); + run("foo"); +} From a1b5ea0cc220d11b831f49a92c2e37b31ae928d3 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Sun, 12 May 2024 14:13:02 -0400 Subject: [PATCH 10/48] make tidy happy --- tests/run-make/issue-14500/rmake.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/run-make/issue-14500/rmake.rs b/tests/run-make/issue-14500/rmake.rs index 58c6bc9ebb3a4..956d66ba88f22 100644 --- a/tests/run-make/issue-14500/rmake.rs +++ b/tests/run-make/issue-14500/rmake.rs @@ -13,19 +13,14 @@ use run_make_support::{cc, extra_c_flags, run, rustc}; fn main() { let libbar_path = tmp_dir().join("libbar.a"); - rustc().input("foo.rs") - .crate_type("rlib") - .run(); - rustc().input("bar.rs") + rustc().input("foo.rs").crate_type("rlib").run(); + rustc() + .input("bar.rs") .static_lib("staticlib") .codegen_option("lto") .library_search_path(".") .output(&libbar_path) .run(); - cc().input("foo.c") - .input(libbar_path) - .args(&extra_c_flags()) - .out_exe("foo") - .run(); + cc().input("foo.c").input(libbar_path).args(&extra_c_flags()).out_exe("foo").run(); run("foo"); } From 71fd2cf5b44441c91673e90414d1e445d8de1922 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Sun, 12 May 2024 15:02:22 -0400 Subject: [PATCH 11/48] fix function call and import --- tests/run-make/issue-14500/rmake.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/run-make/issue-14500/rmake.rs b/tests/run-make/issue-14500/rmake.rs index 956d66ba88f22..58f632e590938 100644 --- a/tests/run-make/issue-14500/rmake.rs +++ b/tests/run-make/issue-14500/rmake.rs @@ -9,14 +9,14 @@ //@ ignore-cross-compile -use run_make_support::{cc, extra_c_flags, run, rustc}; +use run_make_support::{cc, extra_c_flags, run, rustc, tmp_dir}; fn main() { let libbar_path = tmp_dir().join("libbar.a"); rustc().input("foo.rs").crate_type("rlib").run(); rustc() .input("bar.rs") - .static_lib("staticlib") + .crate_type("staticlib") .codegen_option("lto") .library_search_path(".") .output(&libbar_path) From 4db00fe229f08b06feeee552ae53af9f49c25048 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 10 May 2024 16:38:19 +0200 Subject: [PATCH 12/48] Use an helper to move the files In case the source is not in the same filesystem. --- src/bootstrap/src/core/build_steps/dist.rs | 6 ++++-- src/bootstrap/src/core/download.rs | 6 +++--- src/bootstrap/src/utils/helpers.rs | 15 +++++++++++++++ src/bootstrap/src/utils/tarball.rs | 4 ++-- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 5bc9d7615e2bc..1f006e1453f4b 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -26,7 +26,9 @@ use crate::core::build_steps::tool::{self, Tool}; use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::channel::{self, Info}; -use crate::utils::helpers::{exe, is_dylib, output, t, target_supports_cranelift_backend, timeit}; +use crate::utils::helpers::{ + exe, is_dylib, move_file, output, t, target_supports_cranelift_backend, timeit, +}; use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball}; use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS}; @@ -2024,7 +2026,7 @@ impl Step for Extended { builder.run(&mut cmd); if !builder.config.dry_run() { - t!(fs::rename(exe.join(&filename), distdir(builder).join(&filename))); + t!(move_file(exe.join(&filename), distdir(builder).join(&filename))); } } } diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index a074d53aa36e6..60f48c5923e1c 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -12,7 +12,7 @@ use build_helper::ci::CiEnv; use build_helper::stage0_parser::VersionMetadata; use xz2::bufread::XzDecoder; -use crate::utils::helpers::{check_run, exe, program_out_of_date}; +use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date}; use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode}; use crate::{t, Config}; @@ -209,7 +209,7 @@ impl Config { None => panic!("no protocol in {url}"), } t!( - std::fs::rename(&tempfile, dest_path), + move_file(&tempfile, dest_path), format!("failed to rename {tempfile:?} to {dest_path:?}") ); } @@ -313,7 +313,7 @@ impl Config { if src_path.is_dir() && dst_path.exists() { continue; } - t!(fs::rename(src_path, dst_path)); + t!(move_file(src_path, dst_path)); } let dst_dir = dst.join(directory_prefix); if dst_dir.exists() { diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs index 0d2ff4f951b61..278359cb08e39 100644 --- a/src/bootstrap/src/utils/helpers.rs +++ b/src/bootstrap/src/utils/helpers.rs @@ -150,6 +150,21 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result< } } +/// Rename a file if from and to are in the same filesystem or +/// copy and remove the file otherwise +pub fn move_file, Q: AsRef>(from: P, to: Q) -> io::Result<()> { + match fs::rename(&from, &to) { + // FIXME: Once `ErrorKind::CrossesDevices` is stabilized use + // if e.kind() == io::ErrorKind::CrossesDevices { + #[cfg(unix)] + Err(e) if e.raw_os_error() == Some(libc::EXDEV) => { + std::fs::copy(&from, &to)?; + std::fs::remove_file(&from) + } + r => r, + } +} + pub fn forcing_clang_based_tests() -> bool { if let Some(var) = env::var_os("RUSTBUILD_FORCE_CLANG_BASED_TESTS") { match &var.to_string_lossy().to_lowercase()[..] { diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs index 2a950e669b923..57cdf7473a191 100644 --- a/src/bootstrap/src/utils/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -13,7 +13,7 @@ use std::{ use crate::core::builder::Builder; use crate::core::{build_steps::dist::distdir, builder::Kind}; use crate::utils::channel; -use crate::utils::helpers::t; +use crate::utils::helpers::{move_file, t}; #[derive(Copy, Clone)] pub(crate) enum OverlayKind { @@ -284,7 +284,7 @@ impl<'a> Tarball<'a> { // name, not "image". We rename the image directory just before passing // into rust-installer. let dest = self.temp_dir.join(self.package_name()); - t!(std::fs::rename(&self.image_dir, &dest)); + t!(move_file(&self.image_dir, &dest)); self.run(|this, cmd| { let distdir = distdir(this.builder); From fe8f66e4bcbe36e7e4b21943661ff23b5369c64b Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Mon, 13 May 2024 13:32:31 -0400 Subject: [PATCH 13/48] `rustc_hir_typeck`: Account for `skipped_ref_pats` in `expr_use_visitor` Fixes #125058 --- .../rustc_hir_typeck/src/expr_use_visitor.rs | 12 +++++++++- .../pattern/skipped-ref-pats-issue-125058.rs | 18 ++++++++++++++ .../skipped-ref-pats-issue-125058.stderr | 24 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/ui/pattern/skipped-ref-pats-issue-125058.rs create mode 100644 tests/ui/pattern/skipped-ref-pats-issue-125058.stderr diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 1864c7e6ef82d..89f62577506fd 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -18,12 +18,12 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, Res}; use rustc_hir::def_id::LocalDefId; use rustc_hir::{HirId, PatKind}; -use rustc_middle::{bug, span_bug}; use rustc_middle::hir::place::ProjectionKind; use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::{ self, adjustment, AdtKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt as _, }; +use rustc_middle::{bug, span_bug}; use rustc_span::{ErrorGuaranteed, Span}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_trait_selection::infer::InferCtxtExt; @@ -1181,6 +1181,10 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx debug!("pat_ty(pat={:?}) found adjusted ty `{:?}`", pat, first_ty); return Ok(*first_ty); } + } else if let PatKind::Ref(subpat, _) = pat.kind + && self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id) + { + return self.pat_ty_adjusted(subpat); } self.pat_ty_unadjusted(pat) @@ -1712,6 +1716,12 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx self.cat_pattern(place_with_id, subpat, op)?; } + PatKind::Ref(subpat, _) + if self.cx.typeck_results().skipped_ref_pats().contains(pat.hir_id) => + { + self.cat_pattern(place_with_id, subpat, op)?; + } + PatKind::Box(subpat) | PatKind::Ref(subpat, _) => { // box p1, &p1, &mut p1. we can ignore the mutability of // PatKind::Ref since that information is already contained diff --git a/tests/ui/pattern/skipped-ref-pats-issue-125058.rs b/tests/ui/pattern/skipped-ref-pats-issue-125058.rs new file mode 100644 index 0000000000000..b733e5fda0a26 --- /dev/null +++ b/tests/ui/pattern/skipped-ref-pats-issue-125058.rs @@ -0,0 +1,18 @@ +//@ run-pass +//@ edition: 2024 +//@ compile-flags: -Zunstable-options + +#![allow(incomplete_features)] +#![feature(ref_pat_eat_one_layer_2024)] + +struct Foo; +//~^ WARN struct `Foo` is never constructed + +fn main() { + || { + //~^ WARN unused closure that must be used + if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { + let _: u32 = x; + } + }; +} diff --git a/tests/ui/pattern/skipped-ref-pats-issue-125058.stderr b/tests/ui/pattern/skipped-ref-pats-issue-125058.stderr new file mode 100644 index 0000000000000..cee1cc673c7e6 --- /dev/null +++ b/tests/ui/pattern/skipped-ref-pats-issue-125058.stderr @@ -0,0 +1,24 @@ +warning: struct `Foo` is never constructed + --> $DIR/skipped-ref-pats-issue-125058.rs:8:8 + | +LL | struct Foo; + | ^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: unused closure that must be used + --> $DIR/skipped-ref-pats-issue-125058.rs:12:5 + | +LL | / || { +LL | | +LL | | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { +LL | | let _: u32 = x; +LL | | } +LL | | }; + | |_____^ + | + = note: closures are lazy and do nothing unless called + = note: `#[warn(unused_must_use)]` on by default + +warning: 2 warnings emitted + From 2e4c90c3f7c11c745a5d787809ad36c49970a25b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 13 May 2024 22:05:11 -0400 Subject: [PATCH 14/48] Don't do post-method-probe error reporting steps if we're in a suggestion --- compiler/rustc_hir_typeck/src/demand.rs | 4 ++-- compiler/rustc_hir_typeck/src/expr.rs | 9 ++++++-- .../src/fn_ctxt/suggestions.rs | 3 ++- compiler/rustc_hir_typeck/src/method/mod.rs | 4 ++-- compiler/rustc_hir_typeck/src/method/probe.rs | 23 ++++++++++++++++++- .../rustc_hir_typeck/src/method/suggest.rs | 3 ++- 6 files changed, 37 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 706f6f875bf64..6da5adc7a6e9b 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -938,14 +938,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - pub fn get_conversion_methods( + pub fn get_conversion_methods_for_diagnostic( &self, span: Span, expected: Ty<'tcx>, checked_ty: Ty<'tcx>, hir_id: hir::HirId, ) -> Vec { - let methods = self.probe_for_return_type( + let methods = self.probe_for_return_type_for_diagnostic( span, probe::Mode::MethodCall, expected, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index f283c0138052e..5a9eab1ffeaf1 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2414,7 +2414,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let guar = if field.name == kw::Empty { self.dcx().span_delayed_bug(field.span, "field name with no name") - } else if self.method_exists(field, base_ty, expr.hir_id, expected.only_has_type(self)) { + } else if self.method_exists_for_diagnostic( + field, + base_ty, + expr.hir_id, + expected.only_has_type(self), + ) { self.ban_take_value_of_method(expr, base_ty, field) } else if !base_ty.is_primitive_ty() { self.ban_nonexisting_field(field, base, expr, base_ty) @@ -2600,7 +2605,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut err = self.private_field_err(field, base_did); // Also check if an accessible method exists, which is often what is meant. - if self.method_exists(field, expr_t, expr.hir_id, return_ty) + if self.method_exists_for_diagnostic(field, expr_t, expr.hir_id, return_ty) && !self.expr_in_place(expr.hir_id) { self.suggest_method_call( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 11f288391c3bd..fe0dd4e393fc8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -290,7 +290,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>, ) -> bool { let expr = expr.peel_blocks(); - let methods = self.get_conversion_methods(expr.span, expected, found, expr.hir_id); + let methods = + self.get_conversion_methods_for_diagnostic(expr.span, expected, found, expr.hir_id); if let Some((suggestion, msg, applicability, verbose, annotation)) = self.suggest_deref_or_ref(expr, found, expected) diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index f82182fa0583c..a40fa600c19e2 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -91,7 +91,7 @@ pub enum CandidateSource { impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Determines whether the type `self_ty` supports a visible method named `method_name` or not. #[instrument(level = "debug", skip(self))] - pub fn method_exists( + pub fn method_exists_for_diagnostic( &self, method_name: Ident, self_ty: Ty<'tcx>, @@ -102,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { probe::Mode::MethodCall, method_name, return_type, - IsSuggestion(false), + IsSuggestion(true), self_ty, call_expr_id, ProbeScope::TraitsInScope, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 81e179c90900c..6cfdacf6a24d2 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -90,6 +90,11 @@ pub(crate) struct ProbeContext<'a, 'tcx> { >, scope_expr_id: HirId, + + /// Is this probe being done for a diagnostic? This will skip some error reporting + /// machinery, since we don't particularly care about, for example, similarly named + /// candidates if we're *reporting* similarly named candidates. + is_suggestion: IsSuggestion, } impl<'a, 'tcx> Deref for ProbeContext<'a, 'tcx> { @@ -220,7 +225,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// would use to decide if a method is a plausible fit for /// ambiguity purposes). #[instrument(level = "debug", skip(self, candidate_filter))] - pub fn probe_for_return_type( + pub fn probe_for_return_type_for_diagnostic( &self, span: Span, mode: Mode, @@ -459,6 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &orig_values, steps.steps, scope_expr_id, + is_suggestion, ); probe_cx.assemble_inherent_candidates(); @@ -553,6 +559,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { orig_steps_var_values: &'a OriginalQueryValues<'tcx>, steps: &'tcx [CandidateStep<'tcx>], scope_expr_id: HirId, + is_suggestion: IsSuggestion, ) -> ProbeContext<'a, 'tcx> { ProbeContext { fcx, @@ -570,6 +577,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { static_candidates: RefCell::new(Vec::new()), unsatisfied_predicates: RefCell::new(Vec::new()), scope_expr_id, + is_suggestion, } } @@ -944,6 +952,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { return r; } + // If it's a `lookup_probe_for_diagnostic`, then quit early. No need to + // probe for other candidates. + if self.is_suggestion.0 { + return Err(MethodError::NoMatch(NoMatchData { + static_candidates: vec![], + unsatisfied_predicates: vec![], + out_of_scope_traits: vec![], + similar_candidate: None, + mode: self.mode, + })); + } + debug!("pick: actual search failed, assemble diagnostics"); let static_candidates = std::mem::take(self.static_candidates.get_mut()); @@ -1631,6 +1651,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.orig_steps_var_values, self.steps, self.scope_expr_id, + IsSuggestion(true), ); pcx.allow_similar_names = true; pcx.assemble_inherent_candidates(); diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index d50e99433842a..c1cbe05f6bdbb 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2814,7 +2814,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(output_ty) => self.resolve_vars_if_possible(output_ty), _ => return, }; - let method_exists = self.method_exists(item_name, output_ty, call.hir_id, return_type); + let method_exists = + self.method_exists_for_diagnostic(item_name, output_ty, call.hir_id, return_type); debug!("suggest_await_before_method: is_method_exist={}", method_exists); if method_exists { err.span_suggestion_verbose( From 1ad28a6f534d7673664e8f26c632bc71490c33a6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 13 May 2024 12:40:08 -0400 Subject: [PATCH 15/48] Uplift AliasTy --- compiler/rustc_errors/src/diagnostic_impls.rs | 6 + compiler/rustc_middle/src/ty/consts.rs | 18 +- compiler/rustc_middle/src/ty/consts/kind.rs | 30 +- compiler/rustc_middle/src/ty/context.rs | 76 +++- compiler/rustc_middle/src/ty/mod.rs | 16 +- compiler/rustc_middle/src/ty/predicate.rs | 1 + compiler/rustc_middle/src/ty/print/pretty.rs | 54 +-- .../rustc_middle/src/ty/structural_impls.rs | 36 +- compiler/rustc_middle/src/ty/sty.rs | 388 +----------------- compiler/rustc_type_ir/src/const_kind.rs | 41 ++ compiler/rustc_type_ir/src/inherent.rs | 29 +- compiler/rustc_type_ir/src/interner.rs | 25 +- compiler/rustc_type_ir/src/ir_print.rs | 6 +- compiler/rustc_type_ir/src/predicate.rs | 234 +++++++++-- compiler/rustc_type_ir/src/ty_kind.rs | 158 ++++++- 15 files changed, 584 insertions(+), 534 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 2cc0167dbaa6e..d9add1c9b3b52 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -106,6 +106,12 @@ impl IntoDiagArg for rustc_type_ir::ExistentialTrait } } +impl IntoDiagArg for rustc_type_ir::UnevaluatedConst { + fn into_diag_arg(self) -> rustc_errors::DiagArgValue { + format!("{self:?}").into_diag_arg() + } +} + into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize); impl IntoDiagArg for bool { diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 329d5f34a2123..27a4abaa0b695 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -7,8 +7,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_macros::{HashStable, TyDecodable, TyEncodable}; -use rustc_type_ir::ConstKind as IrConstKind; -use rustc_type_ir::{TypeFlags, WithCachedTypeInfo}; +use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; mod int; mod kind; @@ -20,7 +19,8 @@ use rustc_span::Span; use rustc_span::DUMMY_SP; pub use valtree::*; -pub type ConstKind<'tcx> = IrConstKind>; +pub type ConstKind<'tcx> = ir::ConstKind>; +pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst>; #[cfg(target_pointer_width = "64")] rustc_data_structures::static_assert_size!(ConstKind<'_>, 32); @@ -184,9 +184,21 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { Const::new_bound(tcx, debruijn, var, ty) } + fn new_unevaluated( + interner: TyCtxt<'tcx>, + uv: ty::UnevaluatedConst<'tcx>, + ty: Ty<'tcx>, + ) -> Self { + Const::new_unevaluated(interner, uv, ty) + } + fn ty(self) -> Ty<'tcx> { self.ty() } + + fn into_term(self) -> ty::Term<'tcx> { + self.into() + } } impl<'tcx> Const<'tcx> { diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 7e49b0ac915c6..d7ae050ed4d02 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,30 +1,15 @@ use super::Const; use crate::mir; use crate::ty::abstract_const::CastKind; -use crate::ty::GenericArgsRef; use crate::ty::{self, visit::TypeVisitableExt as _, List, Ty, TyCtxt}; -use rustc_hir::def_id::DefId; -use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_macros::{extension, HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; -/// An unevaluated (potentially generic) constant used in the type-system. -#[derive(Copy, Clone, Eq, PartialEq, TyEncodable, TyDecodable)] -#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] -pub struct UnevaluatedConst<'tcx> { - pub def: DefId, - pub args: GenericArgsRef<'tcx>, -} - -impl rustc_errors::IntoDiagArg for UnevaluatedConst<'_> { - fn into_diag_arg(self) -> rustc_errors::DiagArgValue { - format!("{self:?}").into_diag_arg() - } -} - -impl<'tcx> UnevaluatedConst<'tcx> { +#[extension(pub(crate) trait UnevaluatedConstEvalExt<'tcx>)] +impl<'tcx> ty::UnevaluatedConst<'tcx> { /// FIXME(RalfJung): I cannot explain what this does or why it makes sense, but not doing this /// hurts performance. #[inline] - pub(crate) fn prepare_for_eval( + fn prepare_for_eval( self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -55,13 +40,6 @@ impl<'tcx> UnevaluatedConst<'tcx> { } } -impl<'tcx> UnevaluatedConst<'tcx> { - #[inline] - pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> { - UnevaluatedConst { def, args } - } -} - #[derive(Copy, Clone, Eq, PartialEq, Hash)] #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)] pub enum Expr<'tcx> { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e831db1a41bf8..d7e185dd5e107 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -76,6 +76,7 @@ use rustc_type_ir::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; use rustc_type_ir::{CollectAndApply, Interner, TypeFlags}; +use std::assert_matches::assert_matches; use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt; @@ -91,67 +92,124 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type DefiningOpaqueTypes = &'tcx ty::List; type AdtDef = ty::AdtDef<'tcx>; type GenericArgs = ty::GenericArgsRef<'tcx>; + type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; type GenericArg = ty::GenericArg<'tcx>; - type Term = ty::Term<'tcx>; + type Term = ty::Term<'tcx>; type Binder>> = Binder<'tcx, T>; type BoundVars = &'tcx List; type BoundVar = ty::BoundVariableKind; - type CanonicalVars = CanonicalVarInfos<'tcx>; + type CanonicalVars = CanonicalVarInfos<'tcx>; type Ty = Ty<'tcx>; type Tys = &'tcx List>; - type AliasTy = ty::AliasTy<'tcx>; type ParamTy = ParamTy; type BoundTy = ty::BoundTy; type PlaceholderTy = ty::PlaceholderType; - type ErrorGuaranteed = ErrorGuaranteed; + type ErrorGuaranteed = ErrorGuaranteed; type BoundExistentialPredicates = &'tcx List>; type PolyFnSig = PolyFnSig<'tcx>; type AllocId = crate::mir::interpret::AllocId; - type Pat = Pattern<'tcx>; + type Pat = Pattern<'tcx>; type Const = ty::Const<'tcx>; type AliasConst = ty::UnevaluatedConst<'tcx>; type PlaceholderConst = ty::PlaceholderConst; type ParamConst = ty::ParamConst; type BoundConst = ty::BoundVar; type ValueConst = ty::ValTree<'tcx>; - type ExprConst = ty::Expr<'tcx>; + type ExprConst = ty::Expr<'tcx>; type Region = Region<'tcx>; type EarlyParamRegion = ty::EarlyParamRegion; type LateParamRegion = ty::LateParamRegion; type BoundRegion = ty::BoundRegion; type InferRegion = ty::RegionVid; - type PlaceholderRegion = ty::PlaceholderRegion; + type PlaceholderRegion = ty::PlaceholderRegion; type Predicate = Predicate<'tcx>; type TraitPredicate = ty::TraitPredicate<'tcx>; type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>; type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>; type ProjectionPredicate = ty::ProjectionPredicate<'tcx>; - type AliasTerm = ty::AliasTerm<'tcx>; type NormalizesTo = ty::NormalizesTo<'tcx>; type SubtypePredicate = ty::SubtypePredicate<'tcx>; type CoercePredicate = ty::CoercePredicate<'tcx>; type ClosureKind = ty::ClosureKind; - type Clauses = ty::Clauses<'tcx>; + type Clauses = ty::Clauses<'tcx>; fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo]) -> Self::CanonicalVars { self.mk_canonical_var_infos(infos) } type GenericsOf = &'tcx ty::Generics; + fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics { self.generics_of(def_id) } + fn type_of_instantiated(self, def_id: DefId, args: ty::GenericArgsRef<'tcx>) -> Ty<'tcx> { + self.type_of(def_id).instantiate(self, args) + } + + fn alias_ty_kind(self, alias: ty::AliasTy<'tcx>) -> ty::AliasTyKind { + match self.def_kind(alias.def_id) { + DefKind::AssocTy => { + if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) + { + ty::Inherent + } else { + ty::Projection + } + } + DefKind::OpaqueTy => ty::Opaque, + DefKind::TyAlias => ty::Weak, + kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), + } + } + + fn alias_term_kind(self, alias: ty::AliasTerm<'tcx>) -> ty::AliasTermKind { + match self.def_kind(alias.def_id) { + DefKind::AssocTy => { + if let DefKind::Impl { of_trait: false } = self.def_kind(self.parent(alias.def_id)) + { + ty::AliasTermKind::InherentTy + } else { + ty::AliasTermKind::ProjectionTy + } + } + DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy, + DefKind::TyAlias => ty::AliasTermKind::WeakTy, + DefKind::AssocConst => ty::AliasTermKind::ProjectionConst, + DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst, + kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), + } + } + + fn trait_ref_and_own_args_for_alias( + self, + def_id: Self::DefId, + args: Self::GenericArgs, + ) -> (rustc_type_ir::TraitRef, Self::GenericArgsSlice) { + assert_matches!(self.def_kind(def_id), DefKind::AssocTy | DefKind::AssocConst); + let trait_def_id = self.parent(def_id); + assert_matches!(self.def_kind(trait_def_id), DefKind::Trait); + let trait_generics = self.generics_of(trait_def_id); + ( + ty::TraitRef::new(self, trait_def_id, args.truncate_to(self, trait_generics)), + &args[trait_generics.count()..], + ) + } + fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs { self.mk_args(args) } + fn mk_args_from_iter(self, args: impl Iterator) -> Self::GenericArgs { + self.mk_args_from_iter(args) + } + fn check_and_mk_args( self, def_id: DefId, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index dc5e881843a54..93ccc0a7de420 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -96,9 +96,9 @@ pub use self::list::{List, ListWithCachedTypeInfo}; pub use self::parameterized::ParameterizedOverTcx; pub use self::pattern::{Pattern, PatternKind}; pub use self::predicate::{ - Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialPredicateStableCmpExt, - ExistentialProjection, ExistentialTraitRef, NormalizesTo, OutlivesPredicate, - PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection, + AliasTerm, Clause, ClauseKind, CoercePredicate, ExistentialPredicate, + ExistentialPredicateStableCmpExt, ExistentialProjection, ExistentialTraitRef, NormalizesTo, + OutlivesPredicate, PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, @@ -110,11 +110,11 @@ pub use self::region::{ }; pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::{ - AliasTerm, AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, - CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, - CoroutineClosureArgs, CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, - InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, - UpvarArgs, VarianceDiagInfo, + AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, + ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs, + CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs, + InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, + VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index e78856517b217..16ca098853eea 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -13,6 +13,7 @@ use crate::ty::{ }; pub type TraitRef<'tcx> = ir::TraitRef>; +pub type AliasTerm<'tcx> = ir::AliasTerm>; pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate>; pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate>; pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef>; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 8d8ed70a7574d..3577db7234d90 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3038,6 +3038,33 @@ define_print! { p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path())) } + ty::AliasTy<'tcx> { + let alias_term: ty::AliasTerm<'tcx> = (*self).into(); + p!(print(alias_term)) + } + + ty::AliasTerm<'tcx> { + match self.kind(cx.tcx()) { + ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)), + ty::AliasTermKind::ProjectionTy + | ty::AliasTermKind::WeakTy + | ty::AliasTermKind::OpaqueTy + | ty::AliasTermKind::UnevaluatedConst + | ty::AliasTermKind::ProjectionConst => { + // If we're printing verbosely, or don't want to invoke queries + // (`is_impl_trait_in_trait`), then fall back to printing the def path. + // This is likely what you want if you're debugging the compiler anyways. + if !(cx.should_print_verbose() || with_reduced_queries()) + && cx.tcx().is_impl_trait_in_trait(self.def_id) + { + return cx.pretty_print_opaque_impl_type(self.def_id, self.args); + } else { + p!(print_def_path(self.def_id, self.args)); + } + } + } + } + ty::TraitPredicate<'tcx> { p!(print(self.trait_ref.self_ty()), ": "); p!(pretty_print_bound_constness(self.trait_ref)); @@ -3205,33 +3232,6 @@ define_print_and_forward_display! { } } - ty::AliasTy<'tcx> { - let alias_term: ty::AliasTerm<'tcx> = (*self).into(); - p!(print(alias_term)) - } - - ty::AliasTerm<'tcx> { - match self.kind(cx.tcx()) { - ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)), - ty::AliasTermKind::ProjectionTy - | ty::AliasTermKind::WeakTy - | ty::AliasTermKind::OpaqueTy - | ty::AliasTermKind::UnevaluatedConst - | ty::AliasTermKind::ProjectionConst => { - // If we're printing verbosely, or don't want to invoke queries - // (`is_impl_trait_in_trait`), then fall back to printing the def path. - // This is likely what you want if you're debugging the compiler anyways. - if !(cx.should_print_verbose() || with_reduced_queries()) - && cx.tcx().is_impl_trait_in_trait(self.def_id) - { - return cx.pretty_print_opaque_impl_type(self.def_id, self.args); - } else { - p!(print_def_path(self.def_id, self.args)); - } - } - } - } - ty::Predicate<'tcx> { p!(print(self.kind())) } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 6abd685343b3a..7523cd1532070 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -7,7 +7,7 @@ use crate::mir::interpret; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; -use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; +use crate::ty::{self, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_ast_ir::try_visit; use rustc_ast_ir::visit::VisitorResult; use rustc_hir::def::Namespace; @@ -164,23 +164,6 @@ impl<'tcx> fmt::Debug for ty::Clause<'tcx> { } } -impl<'tcx> fmt::Debug for AliasTy<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - WithInfcx::with_no_infcx(self).fmt(f) - } -} -impl<'tcx> DebugWithInfcx> for AliasTy<'tcx> { - fn fmt>>( - this: WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { - f.debug_struct("AliasTy") - .field("args", &this.map(|data| data.args)) - .field("def_id", &this.data.def_id) - .finish() - } -} - impl<'tcx> DebugWithInfcx> for Pattern<'tcx> { fn fmt>>( this: WithInfcx<'_, Infcx, &Self>, @@ -230,23 +213,6 @@ impl<'tcx> DebugWithInfcx> for ty::consts::Expr<'tcx> { } } -impl<'tcx> fmt::Debug for ty::UnevaluatedConst<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - WithInfcx::with_no_infcx(self).fmt(f) - } -} -impl<'tcx> DebugWithInfcx> for ty::UnevaluatedConst<'tcx> { - fn fmt>>( - this: WithInfcx<'_, Infcx, &Self>, - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { - f.debug_struct("UnevaluatedConst") - .field("def", &this.data.def) - .field("args", &this.wrap(this.data.args)) - .finish() - } -} - impl<'tcx> fmt::Debug for ty::Const<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { WithInfcx::with_no_infcx(self).fmt(f) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 163016332475e..e4396c6f20ba2 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -28,20 +28,17 @@ use std::iter; use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; -use rustc_type_ir::BoundVar; -use rustc_type_ir::CollectAndApply; -use rustc_type_ir::DynKind; -use rustc_type_ir::TyKind as IrTyKind; use rustc_type_ir::TyKind::*; -use rustc_type_ir::TypeAndMut as IrTypeAndMut; +use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind}; use super::fold::FnMutDelegate; use super::GenericParamDefKind; // Re-export and re-parameterize some `I = TyCtxt<'tcx>` types here #[rustc_diagnostic_item = "TyKind"] -pub type TyKind<'tcx> = IrTyKind>; -pub type TypeAndMut<'tcx> = IrTypeAndMut>; +pub type TyKind<'tcx> = ir::TyKind>; +pub type TypeAndMut<'tcx> = ir::TypeAndMut>; +pub type AliasTy<'tcx> = ir::AliasTy>; pub trait Article { fn article(&self) -> &'static str; @@ -1105,371 +1102,6 @@ where } } -/// Represents the unprojected term of a projection goal. -/// -/// * For a projection, this would be `>::N<...>`. -/// * For an inherent projection, this would be `Ty::N<...>`. -/// * For an opaque type, there is no explicit syntax. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct AliasTerm<'tcx> { - /// The parameters of the associated or opaque item. - /// - /// For a projection, these are the generic parameters for the trait and the - /// GAT parameters, if there are any. - /// - /// For an inherent projection, they consist of the self type and the GAT parameters, - /// if there are any. - /// - /// For RPIT the generic parameters are for the generics of the function, - /// while for TAIT it is used for the generic parameters of the alias. - pub args: GenericArgsRef<'tcx>, - - /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether - /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if - /// this is an opaque. - /// - /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the - /// underlying type if the type is an opaque. - /// - /// Note that if this is an associated type, this is not the `DefId` of the - /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`, - /// aka. `tcx.parent(def_id)`. - pub def_id: DefId, - - /// This field exists to prevent the creation of `AliasTerm` without using - /// [AliasTerm::new]. - _use_alias_term_new_instead: (), -} - -// FIXME: Remove these when we uplift `AliasTerm` -use crate::ty::{DebugWithInfcx, InferCtxtLike, WithInfcx}; -impl<'tcx> std::fmt::Debug for AliasTerm<'tcx> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - WithInfcx::with_no_infcx(self).fmt(f) - } -} -impl<'tcx> DebugWithInfcx> for AliasTerm<'tcx> { - fn fmt>>( - this: WithInfcx<'_, Infcx, &Self>, - f: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - f.debug_struct("AliasTerm") - .field("args", &this.map(|data| data.args)) - .field("def_id", &this.data.def_id) - .finish() - } -} - -impl<'tcx> rustc_type_ir::inherent::AliasTerm> for AliasTerm<'tcx> { - fn new( - interner: TyCtxt<'tcx>, - trait_def_id: DefId, - args: impl IntoIterator>>, - ) -> Self { - AliasTerm::new(interner, trait_def_id, args) - } - - fn def_id(self) -> DefId { - self.def_id - } - - fn args(self) -> ty::GenericArgsRef<'tcx> { - self.args - } - - fn trait_def_id(self, interner: TyCtxt<'tcx>) -> DefId { - self.trait_def_id(interner) - } - - fn self_ty(self) -> Ty<'tcx> { - self.self_ty() - } - - fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - self.with_self_ty(tcx, self_ty) - } -} - -impl<'tcx> AliasTerm<'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - def_id: DefId, - args: impl IntoIterator>>, - ) -> AliasTerm<'tcx> { - let args = tcx.check_and_mk_args(def_id, args); - AliasTerm { def_id, args, _use_alias_term_new_instead: () } - } - - pub fn expect_ty(self, tcx: TyCtxt<'tcx>) -> AliasTy<'tcx> { - match self.kind(tcx) { - ty::AliasTermKind::ProjectionTy - | ty::AliasTermKind::InherentTy - | ty::AliasTermKind::OpaqueTy - | ty::AliasTermKind::WeakTy => {} - ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => { - bug!("Cannot turn `UnevaluatedConst` into `AliasTy`") - } - } - ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () } - } - - pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTermKind { - match tcx.def_kind(self.def_id) { - DefKind::AssocTy => { - if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) { - ty::AliasTermKind::InherentTy - } else { - ty::AliasTermKind::ProjectionTy - } - } - DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy, - DefKind::TyAlias => ty::AliasTermKind::WeakTy, - DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst, - DefKind::AssocConst => ty::AliasTermKind::ProjectionConst, - kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), - } - } -} - -/// The following methods work only with (trait) associated item projections. -impl<'tcx> AliasTerm<'tcx> { - pub fn self_ty(self) -> Ty<'tcx> { - self.args.type_at(0) - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - AliasTerm::new( - tcx, - self.def_id, - [self_ty.into()].into_iter().chain(self.args.iter().skip(1)), - ) - } - - pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { - match tcx.def_kind(self.def_id) { - DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id), - kind => bug!("expected a projection AliasTy; found {kind:?}"), - } - } - - /// Extracts the underlying trait reference from this projection. - /// For example, if this is a projection of `::Item`, - /// then this function would return a `T: Iterator` trait reference. - /// - /// NOTE: This will drop the args for generic associated types - /// consider calling [Self::trait_ref_and_own_args] to get those - /// as well. - pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { - let def_id = self.trait_def_id(tcx); - ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id))) - } - - /// Extracts the underlying trait reference and own args from this projection. - /// For example, if this is a projection of `::Item<'a>`, - /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args - pub fn trait_ref_and_own_args( - self, - tcx: TyCtxt<'tcx>, - ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { - let trait_def_id = self.trait_def_id(tcx); - let trait_generics = tcx.generics_of(trait_def_id); - ( - ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)), - &self.args[trait_generics.count()..], - ) - } - - pub fn to_term(self, tcx: TyCtxt<'tcx>) -> ty::Term<'tcx> { - match self.kind(tcx) { - ty::AliasTermKind::ProjectionTy => Ty::new_alias( - tcx, - ty::Projection, - AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, - ) - .into(), - ty::AliasTermKind::InherentTy => Ty::new_alias( - tcx, - ty::Inherent, - AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, - ) - .into(), - ty::AliasTermKind::OpaqueTy => Ty::new_alias( - tcx, - ty::Opaque, - AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, - ) - .into(), - ty::AliasTermKind::WeakTy => Ty::new_alias( - tcx, - ty::Weak, - AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, - ) - .into(), - ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => { - ty::Const::new_unevaluated( - tcx, - ty::UnevaluatedConst::new(self.def_id, self.args), - tcx.type_of(self.def_id).instantiate(tcx, self.args), - ) - .into() - } - } - } -} - -impl<'tcx> From> for AliasTerm<'tcx> { - fn from(ty: AliasTy<'tcx>) -> Self { - AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () } - } -} - -impl<'tcx> From> for AliasTerm<'tcx> { - fn from(ct: ty::UnevaluatedConst<'tcx>) -> Self { - AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () } - } -} - -/// Represents the projection of an associated, opaque, or lazy-type-alias type. -/// -/// * For a projection, this would be `>::N<...>`. -/// * For an inherent projection, this would be `Ty::N<...>`. -/// * For an opaque type, there is no explicit syntax. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct AliasTy<'tcx> { - /// The parameters of the associated or opaque type. - /// - /// For a projection, these are the generic parameters for the trait and the - /// GAT parameters, if there are any. - /// - /// For an inherent projection, they consist of the self type and the GAT parameters, - /// if there are any. - /// - /// For RPIT the generic parameters are for the generics of the function, - /// while for TAIT it is used for the generic parameters of the alias. - pub args: GenericArgsRef<'tcx>, - - /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether - /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if - /// this is an opaque. - /// - /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the - /// underlying type if the type is an opaque. - /// - /// Note that if this is an associated type, this is not the `DefId` of the - /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`, - /// aka. `tcx.parent(def_id)`. - pub def_id: DefId, - - /// This field exists to prevent the creation of `AliasT` without using - /// [AliasTy::new]. - _use_alias_ty_new_instead: (), -} - -impl<'tcx> AliasTy<'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - def_id: DefId, - args: impl IntoIterator>>, - ) -> ty::AliasTy<'tcx> { - let args = tcx.check_and_mk_args(def_id, args); - ty::AliasTy { def_id, args, _use_alias_ty_new_instead: () } - } - - pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTyKind { - match tcx.def_kind(self.def_id) { - DefKind::AssocTy - if let DefKind::Impl { of_trait: false } = - tcx.def_kind(tcx.parent(self.def_id)) => - { - ty::Inherent - } - DefKind::AssocTy => ty::Projection, - DefKind::OpaqueTy => ty::Opaque, - DefKind::TyAlias => ty::Weak, - kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), - } - } - - /// Whether this alias type is an opaque. - pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool { - matches!(self.kind(tcx), ty::Opaque) - } - - pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - Ty::new_alias(tcx, self.kind(tcx), self) - } -} - -/// The following methods work only with (trait) associated type projections. -impl<'tcx> AliasTy<'tcx> { - pub fn self_ty(self) -> Ty<'tcx> { - self.args.type_at(0) - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { - AliasTy::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1))) - } - - pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { - match tcx.def_kind(self.def_id) { - DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id), - kind => bug!("expected a projection AliasTy; found {kind:?}"), - } - } - - /// Extracts the underlying trait reference and own args from this projection. - /// For example, if this is a projection of `::Item<'a>`, - /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args - pub fn trait_ref_and_own_args( - self, - tcx: TyCtxt<'tcx>, - ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { - let trait_def_id = self.trait_def_id(tcx); - let trait_generics = tcx.generics_of(trait_def_id); - ( - ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)), - &self.args[trait_generics.count()..], - ) - } - - /// Extracts the underlying trait reference from this projection. - /// For example, if this is a projection of `::Item`, - /// then this function would return a `T: Iterator` trait reference. - /// - /// WARNING: This will drop the args for generic associated types - /// consider calling [Self::trait_ref_and_own_args] to get those - /// as well. - pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { - let def_id = self.trait_def_id(tcx); - ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id))) - } -} - -/// The following methods work only with inherent associated type projections. -impl<'tcx> AliasTy<'tcx> { - /// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that. - /// - /// Does the following transformation: - /// - /// ```text - /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m] - /// - /// I_i impl args - /// P_j GAT args - /// ``` - pub fn rebase_inherent_args_onto_impl( - self, - impl_args: ty::GenericArgsRef<'tcx>, - tcx: TyCtxt<'tcx>, - ) -> ty::GenericArgsRef<'tcx> { - debug_assert_eq!(self.kind(tcx), ty::Inherent); - - tcx.mk_args_from_iter(impl_args.into_iter().chain(self.args.into_iter().skip(1))) - } -} - #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)] pub struct GenSig<'tcx> { pub resume_ty: Ty<'tcx>, @@ -2020,6 +1652,18 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon }) } + + fn new_alias( + interner: TyCtxt<'tcx>, + kind: ty::AliasTyKind, + alias_ty: ty::AliasTy<'tcx>, + ) -> Self { + Ty::new_alias(interner, kind, alias_ty) + } + + fn into_term(self) -> ty::Term<'tcx> { + self.into() + } } /// Type utilities diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index c748cdf6ed278..af07e9ff96bf8 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -2,6 +2,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use std::fmt; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx}; @@ -86,6 +87,46 @@ impl DebugWithInfcx for ConstKind { } } +/// An unevaluated (potentially generic) constant used in the type-system. +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub struct UnevaluatedConst { + pub def: I::DefId, + pub args: I::GenericArgs, +} + +impl UnevaluatedConst { + #[inline] + pub fn new(def: I::DefId, args: I::GenericArgs) -> UnevaluatedConst { + UnevaluatedConst { def, args } + } +} + +impl fmt::Debug for UnevaluatedConst { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + WithInfcx::with_no_infcx(self).fmt(f) + } +} +impl DebugWithInfcx for UnevaluatedConst { + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("UnevaluatedConst") + .field("def", &this.data.def) + .field("args", &this.wrap(this.data.args)) + .finish() + } +} + rustc_index::newtype_index! { /// A **`const`** **v**ariable **ID**. #[encodable] diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 5e98163643893..0a964801ce7f2 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -5,7 +5,8 @@ use std::ops::Deref; use crate::fold::TypeSuperFoldable; use crate::visit::{Flags, TypeSuperVisitable}; use crate::{ - BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind, TyKind, UniverseIndex, + AliasTy, AliasTyKind, BoundVar, ConstKind, DebruijnIndex, DebugWithInfcx, Interner, RegionKind, + TyKind, UnevaluatedConst, UniverseIndex, }; pub trait Ty>: @@ -20,6 +21,10 @@ pub trait Ty>: + Flags { fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self; + + fn new_alias(interner: I, kind: AliasTyKind, alias_ty: AliasTy) -> Self; + + fn into_term(self) -> I::Term; } pub trait Region>: @@ -43,7 +48,11 @@ pub trait Const>: { fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self; + fn new_unevaluated(interner: I, uv: UnevaluatedConst, ty: I::Ty) -> Self; + fn ty(self) -> I::Ty; + + fn into_term(self) -> I::Term; } pub trait GenericsOf> { @@ -89,21 +98,3 @@ pub trait BoundVars { fn has_no_bound_vars(&self) -> bool; } - -pub trait AliasTerm: Copy + DebugWithInfcx + Hash + Eq + Sized { - fn new( - interner: I, - trait_def_id: I::DefId, - args: impl IntoIterator>, - ) -> Self; - - fn def_id(self) -> I::DefId; - - fn args(self) -> I::GenericArgs; - - fn trait_def_id(self, interner: I) -> I::DefId; - - fn self_ty(self) -> I::Ty; - - fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self; -} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index af0e833b9e983..d6680977168ec 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -6,13 +6,16 @@ use crate::inherent::*; use crate::ir_print::IrPrint; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{ - CanonicalVarInfo, CoercePredicate, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, - NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, + AliasTerm, AliasTermKind, AliasTy, AliasTyKind, CanonicalVarInfo, CoercePredicate, + DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, NormalizesTo, ProjectionPredicate, + SubtypePredicate, TraitPredicate, TraitRef, }; pub trait Interner: Sized + Copy + + IrPrint> + + IrPrint> + IrPrint> + IrPrint> + IrPrint> @@ -27,6 +30,7 @@ pub trait Interner: type AdtDef: Copy + Debug + Hash + Eq; type GenericArgs: GenericArgs; + type GenericArgsSlice: Copy + Debug + Hash + Eq; type GenericArg: Copy + DebugWithInfcx + Hash + Eq; type Term: Copy + Debug + Hash + Eq; @@ -39,7 +43,6 @@ pub trait Interner: // Kinds of tys type Ty: Ty; type Tys: Copy + Debug + Hash + Eq + IntoIterator; - type AliasTy: Copy + DebugWithInfcx + Hash + Eq + Sized; type ParamTy: Copy + Debug + Hash + Eq; type BoundTy: Copy + Debug + Hash + Eq; type PlaceholderTy: PlaceholderLike; @@ -74,7 +77,6 @@ pub trait Interner: type RegionOutlivesPredicate: Copy + Debug + Hash + Eq; type TypeOutlivesPredicate: Copy + Debug + Hash + Eq; type ProjectionPredicate: Copy + Debug + Hash + Eq; - type AliasTerm: AliasTerm; type NormalizesTo: Copy + Debug + Hash + Eq; type SubtypePredicate: Copy + Debug + Hash + Eq; type CoercePredicate: Copy + Debug + Hash + Eq; @@ -86,8 +88,23 @@ pub trait Interner: type GenericsOf: GenericsOf; fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf; + // FIXME: Remove after uplifting `EarlyBinder` + fn type_of_instantiated(self, def_id: Self::DefId, args: Self::GenericArgs) -> Self::Ty; + + fn alias_ty_kind(self, alias: AliasTy) -> AliasTyKind; + + fn alias_term_kind(self, alias: AliasTerm) -> AliasTermKind; + + fn trait_ref_and_own_args_for_alias( + self, + def_id: Self::DefId, + args: Self::GenericArgs, + ) -> (TraitRef, Self::GenericArgsSlice); + fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs; + fn mk_args_from_iter(self, args: impl Iterator) -> Self::GenericArgs; + fn check_and_mk_args( self, def_id: Self::DefId, diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs index 5885139754afe..2a766d0bc09c9 100644 --- a/compiler/rustc_type_ir/src/ir_print.rs +++ b/compiler/rustc_type_ir/src/ir_print.rs @@ -1,8 +1,8 @@ use std::fmt; use crate::{ - CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner, NormalizesTo, - ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, + AliasTerm, AliasTy, CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner, + NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, }; pub trait IrPrint { @@ -43,6 +43,8 @@ define_display_via_print!( NormalizesTo, SubtypePredicate, CoercePredicate, + AliasTy, + AliasTerm, ); define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection); diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 71f198d2b8e84..1ec237d7cd555 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -6,7 +6,9 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen use crate::inherent::*; use crate::visit::TypeVisitableExt as _; -use crate::{DebugWithInfcx, Interner}; +use crate::{ + AliasTy, AliasTyKind, DebugWithInfcx, InferCtxtLike, Interner, UnevaluatedConst, WithInfcx, +}; /// A complete reference to a trait. These take numerous guises in syntax, /// but perhaps the most recognizable form is in a where-clause: @@ -272,20 +274,20 @@ impl ExistentialProjection { /// For example, if this is a projection of `exists T. ::Item == X`, /// then this function would return an `exists T. T: Iterator` existential trait /// reference. - pub fn trait_ref(&self, tcx: I) -> ExistentialTraitRef { - let def_id = tcx.parent(self.def_id); - let args_count = tcx.generics_of(def_id).count() - 1; - let args = tcx.mk_args(&self.args[..args_count]); + pub fn trait_ref(&self, interner: I) -> ExistentialTraitRef { + let def_id = interner.parent(self.def_id); + let args_count = interner.generics_of(def_id).count() - 1; + let args = interner.mk_args(&self.args[..args_count]); ExistentialTraitRef { def_id, args } } - pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate { + pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate { // otherwise the escaping regions would be captured by the binders debug_assert!(!self_ty.has_escaping_bound_vars()); ProjectionPredicate { - projection_term: I::AliasTerm::new( - tcx, + projection_term: AliasTerm::new( + interner, self.def_id, [self_ty.into()].into_iter().chain(self.args), ), @@ -293,13 +295,13 @@ impl ExistentialProjection { } } - pub fn erase_self_ty(tcx: I, projection_predicate: ProjectionPredicate) -> Self { + pub fn erase_self_ty(interner: I, projection_predicate: ProjectionPredicate) -> Self { // Assert there is a Self. - projection_predicate.projection_term.args().type_at(0); + projection_predicate.projection_term.args.type_at(0); Self { - def_id: projection_predicate.projection_term.def_id(), - args: tcx.mk_args(&projection_predicate.projection_term.args()[1..]), + def_id: projection_predicate.projection_term.def_id, + args: interner.mk_args(&projection_predicate.projection_term.args[1..]), term: projection_predicate.term, } } @@ -339,6 +341,190 @@ impl AliasTermKind { } } +/// Represents the unprojected term of a projection goal. +/// +/// * For a projection, this would be `>::N<...>`. +/// * For an inherent projection, this would be `Ty::N<...>`. +/// * For an opaque type, there is no explicit syntax. +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub struct AliasTerm { + /// The parameters of the associated or opaque item. + /// + /// For a projection, these are the generic parameters for the trait and the + /// GAT parameters, if there are any. + /// + /// For an inherent projection, they consist of the self type and the GAT parameters, + /// if there are any. + /// + /// For RPIT the generic parameters are for the generics of the function, + /// while for TAIT it is used for the generic parameters of the alias. + pub args: I::GenericArgs, + + /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether + /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if + /// this is an opaque. + /// + /// During codegen, `interner.type_of(def_id)` can be used to get the type of the + /// underlying type if the type is an opaque. + /// + /// Note that if this is an associated type, this is not the `DefId` of the + /// `TraitRef` containing this associated type, which is in `interner.associated_item(def_id).container`, + /// aka. `interner.parent(def_id)`. + pub def_id: I::DefId, + + /// This field exists to prevent the creation of `AliasTerm` without using + /// [AliasTerm::new]. + _use_alias_term_new_instead: (), +} + +impl std::fmt::Debug for AliasTerm { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + WithInfcx::with_no_infcx(self).fmt(f) + } +} +impl DebugWithInfcx for AliasTerm { + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + f.debug_struct("AliasTerm") + .field("args", &this.map(|data| data.args)) + .field("def_id", &this.data.def_id) + .finish() + } +} + +impl AliasTerm { + pub fn new( + interner: I, + def_id: I::DefId, + args: impl IntoIterator>, + ) -> AliasTerm { + let args = interner.check_and_mk_args(def_id, args); + AliasTerm { def_id, args, _use_alias_term_new_instead: () } + } + + pub fn expect_ty(self, interner: I) -> AliasTy { + match self.kind(interner) { + AliasTermKind::ProjectionTy + | AliasTermKind::InherentTy + | AliasTermKind::OpaqueTy + | AliasTermKind::WeakTy => {} + AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => { + panic!("Cannot turn `UnevaluatedConst` into `AliasTy`") + } + } + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () } + } + + pub fn kind(self, interner: I) -> AliasTermKind { + interner.alias_term_kind(self) + } + + pub fn to_term(self, interner: I) -> I::Term { + match self.kind(interner) { + AliasTermKind::ProjectionTy => Ty::new_alias( + interner, + AliasTyKind::Projection, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into_term(), + AliasTermKind::InherentTy => Ty::new_alias( + interner, + AliasTyKind::Inherent, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into_term(), + AliasTermKind::OpaqueTy => Ty::new_alias( + interner, + AliasTyKind::Opaque, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into_term(), + AliasTermKind::WeakTy => Ty::new_alias( + interner, + AliasTyKind::Weak, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into_term(), + AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => { + I::Const::new_unevaluated( + interner, + UnevaluatedConst::new(self.def_id, self.args), + interner.type_of_instantiated(self.def_id, self.args), + ) + .into_term() + } + } + } +} + +/// The following methods work only with (trait) associated type projections. +impl AliasTerm { + pub fn self_ty(self) -> I::Ty { + self.args.type_at(0) + } + + pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + AliasTerm::new( + interner, + self.def_id, + [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)), + ) + } + + pub fn trait_def_id(self, interner: I) -> I::DefId { + assert!( + matches!( + self.kind(interner), + AliasTermKind::ProjectionTy | AliasTermKind::ProjectionConst + ), + "expected a projection" + ); + interner.parent(self.def_id) + } + + /// Extracts the underlying trait reference and own args from this projection. + /// For example, if this is a projection of `::Item<'a>`, + /// then this function would return a `T: StreamingIterator` trait reference and + /// `['a]` as the own args. + pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef, I::GenericArgsSlice) { + interner.trait_ref_and_own_args_for_alias(self.def_id, self.args) + } + + /// Extracts the underlying trait reference from this projection. + /// For example, if this is a projection of `::Item`, + /// then this function would return a `T: Iterator` trait reference. + /// + /// WARNING: This will drop the args for generic associated types + /// consider calling [Self::trait_ref_and_own_args] to get those + /// as well. + pub fn trait_ref(self, interner: I) -> TraitRef { + self.trait_ref_and_own_args(interner).0 + } +} + +impl From> for AliasTerm { + fn from(ty: AliasTy) -> Self { + AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () } + } +} + +impl From> for AliasTerm { + fn from(ct: UnevaluatedConst) -> Self { + AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () } + } +} + /// This kind of predicate has no *direct* correspondent in the /// syntax, but it roughly corresponds to the syntactic forms: /// @@ -362,7 +548,7 @@ impl AliasTermKind { #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct ProjectionPredicate { - pub projection_term: I::AliasTerm, + pub projection_term: AliasTerm, pub term: I::Term, } @@ -371,16 +557,16 @@ impl ProjectionPredicate { self.projection_term.self_ty() } - pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate { - Self { projection_term: self.projection_term.with_self_ty(tcx, self_ty), ..self } + pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPredicate { + Self { projection_term: self.projection_term.with_self_ty(interner, self_ty), ..self } } - pub fn trait_def_id(self, tcx: I) -> I::DefId { - self.projection_term.trait_def_id(tcx) + pub fn trait_def_id(self, interner: I) -> I::DefId { + self.projection_term.trait_def_id(interner) } pub fn def_id(self) -> I::DefId { - self.projection_term.def_id() + self.projection_term.def_id } } @@ -403,7 +589,7 @@ impl fmt::Debug for ProjectionPredicate { #[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct NormalizesTo { - pub alias: I::AliasTerm, + pub alias: AliasTerm, pub term: I::Term, } @@ -412,16 +598,16 @@ impl NormalizesTo { self.alias.self_ty() } - pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> NormalizesTo { - Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self } + pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo { + Self { alias: self.alias.with_self_ty(interner, self_ty), ..self } } - pub fn trait_def_id(self, tcx: I) -> I::DefId { - self.alias.trait_def_id(tcx) + pub fn trait_def_id(self, interner: I) -> I::DefId { + self.alias.trait_def_id(interner) } pub fn def_id(self) -> I::DefId { - self.alias.def_id() + self.alias.def_id } } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 6e544d0e6ace4..672c890f94edb 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -4,11 +4,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; -use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; +use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; use std::fmt; -use crate::Interner; -use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx}; +use crate::inherent::*; +use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, TraitRef, WithInfcx}; use self::TyKind::*; @@ -88,7 +88,7 @@ pub enum TyKind { /// for `struct List` and the args `[i32]`. /// /// Note that generic parameters in fields only get lazily instantiated - /// by using something like `adt_def.all_fields().map(|field| field.ty(tcx, args))`. + /// by using something like `adt_def.all_fields().map(|field| field.ty(interner, args))`. Adt(I::AdtDef, I::GenericArgs), /// An unsized FFI type that is opaque to Rust. Written as `extern type T`. @@ -201,7 +201,7 @@ pub enum TyKind { /// A projection, opaque type, weak type alias, or inherent associated type. /// All of these types are represented as pairs of def-id and args, and can /// be normalized, so they are grouped conceptually. - Alias(AliasTyKind, I::AliasTy), + Alias(AliasTyKind, AliasTy), /// A type parameter; for example, `T` in `fn f(x: T) {}`. Param(I::ParamTy), @@ -422,6 +422,154 @@ impl fmt::Debug for TyKind { } } +/// Represents the projection of an associated, opaque, or lazy-type-alias type. +/// +/// * For a projection, this would be `>::N<...>`. +/// * For an inherent projection, this would be `Ty::N<...>`. +/// * For an opaque type, there is no explicit syntax. +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub struct AliasTy { + /// The parameters of the associated or opaque type. + /// + /// For a projection, these are the generic parameters for the trait and the + /// GAT parameters, if there are any. + /// + /// For an inherent projection, they consist of the self type and the GAT parameters, + /// if there are any. + /// + /// For RPIT the generic parameters are for the generics of the function, + /// while for TAIT it is used for the generic parameters of the alias. + pub args: I::GenericArgs, + + /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether + /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if + /// this is an opaque. + /// + /// During codegen, `interner.type_of(def_id)` can be used to get the type of the + /// underlying type if the type is an opaque. + /// + /// Note that if this is an associated type, this is not the `DefId` of the + /// `TraitRef` containing this associated type, which is in `interner.associated_item(def_id).container`, + /// aka. `interner.parent(def_id)`. + pub def_id: I::DefId, + + /// This field exists to prevent the creation of `AliasTy` without using + /// [AliasTy::new]. + pub(crate) _use_alias_ty_new_instead: (), +} + +impl AliasTy { + pub fn new( + interner: I, + def_id: I::DefId, + args: impl IntoIterator>, + ) -> AliasTy { + let args = interner.check_and_mk_args(def_id, args); + AliasTy { def_id, args, _use_alias_ty_new_instead: () } + } + + pub fn kind(self, interner: I) -> AliasTyKind { + interner.alias_ty_kind(self) + } + + /// Whether this alias type is an opaque. + pub fn is_opaque(self, interner: I) -> bool { + matches!(self.kind(interner), AliasTyKind::Opaque) + } + + pub fn to_ty(self, interner: I) -> I::Ty { + Ty::new_alias(interner, self.kind(interner), self) + } +} + +/// The following methods work only with (trait) associated type projections. +impl AliasTy { + pub fn self_ty(self) -> I::Ty { + self.args.type_at(0) + } + + pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self { + AliasTy::new( + interner, + self.def_id, + [self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)), + ) + } + + pub fn trait_def_id(self, interner: I) -> I::DefId { + assert_eq!(self.kind(interner), AliasTyKind::Projection, "expected a projection"); + interner.parent(self.def_id) + } + + /// Extracts the underlying trait reference and own args from this projection. + /// For example, if this is a projection of `::Item<'a>`, + /// then this function would return a `T: StreamingIterator` trait reference and + /// `['a]` as the own args. + pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef, I::GenericArgsSlice) { + debug_assert_eq!(self.kind(interner), AliasTyKind::Projection); + interner.trait_ref_and_own_args_for_alias(self.def_id, self.args) + } + + /// Extracts the underlying trait reference from this projection. + /// For example, if this is a projection of `::Item`, + /// then this function would return a `T: Iterator` trait reference. + /// + /// WARNING: This will drop the args for generic associated types + /// consider calling [Self::trait_ref_and_own_args] to get those + /// as well. + pub fn trait_ref(self, interner: I) -> TraitRef { + self.trait_ref_and_own_args(interner).0 + } +} + +/// The following methods work only with inherent associated type projections. +impl AliasTy { + /// Transform the generic parameters to have the given `impl` args as the base and the GAT args on top of that. + /// + /// Does the following transformation: + /// + /// ```text + /// [Self, P_0...P_m] -> [I_0...I_n, P_0...P_m] + /// + /// I_i impl args + /// P_j GAT args + /// ``` + pub fn rebase_inherent_args_onto_impl( + self, + impl_args: I::GenericArgs, + interner: I, + ) -> I::GenericArgs { + debug_assert_eq!(self.kind(interner), AliasTyKind::Inherent); + interner.mk_args_from_iter(impl_args.into_iter().chain(self.args.into_iter().skip(1))) + } +} + +impl fmt::Debug for AliasTy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + WithInfcx::with_no_infcx(self).fmt(f) + } +} +impl DebugWithInfcx for AliasTy { + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, + f: &mut core::fmt::Formatter<'_>, + ) -> core::fmt::Result { + f.debug_struct("AliasTy") + .field("args", &this.map(|data| data.args)) + .field("def_id", &this.data.def_id) + .finish() + } +} + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))] pub enum IntTy { From 9f8cdb286ec2660c7abe65f687bb29cb0b207fa5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 13 May 2024 15:22:47 -0400 Subject: [PATCH 16/48] Remove to_term --- compiler/rustc_middle/src/ty/consts.rs | 4 ---- compiler/rustc_middle/src/ty/sty.rs | 4 ---- compiler/rustc_type_ir/src/inherent.rs | 6 ++---- compiler/rustc_type_ir/src/predicate.rs | 10 +++++----- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 27a4abaa0b695..9dc30447f0e57 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -195,10 +195,6 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { fn ty(self) -> Ty<'tcx> { self.ty() } - - fn into_term(self) -> ty::Term<'tcx> { - self.into() - } } impl<'tcx> Const<'tcx> { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e4396c6f20ba2..74b03d6db66db 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1660,10 +1660,6 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { ) -> Self { Ty::new_alias(interner, kind, alias_ty) } - - fn into_term(self) -> ty::Term<'tcx> { - self.into() - } } /// Type utilities diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 0a964801ce7f2..92b1e08ab0a36 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -15,6 +15,7 @@ pub trait Ty>: + Hash + Eq + Into + + Into + IntoKind> + TypeSuperVisitable + TypeSuperFoldable @@ -23,8 +24,6 @@ pub trait Ty>: fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self; fn new_alias(interner: I, kind: AliasTyKind, alias_ty: AliasTy) -> Self; - - fn into_term(self) -> I::Term; } pub trait Region>: @@ -41,6 +40,7 @@ pub trait Const>: + Hash + Eq + Into + + Into + IntoKind> + TypeSuperVisitable + TypeSuperFoldable @@ -51,8 +51,6 @@ pub trait Const>: fn new_unevaluated(interner: I, uv: UnevaluatedConst, ty: I::Ty) -> Self; fn ty(self) -> I::Ty; - - fn into_term(self) -> I::Term; } pub trait GenericsOf> { diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 1ec237d7cd555..b6c7c2c348cca 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -437,32 +437,32 @@ impl AliasTerm { AliasTyKind::Projection, AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, ) - .into_term(), + .into(), AliasTermKind::InherentTy => Ty::new_alias( interner, AliasTyKind::Inherent, AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, ) - .into_term(), + .into(), AliasTermKind::OpaqueTy => Ty::new_alias( interner, AliasTyKind::Opaque, AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, ) - .into_term(), + .into(), AliasTermKind::WeakTy => Ty::new_alias( interner, AliasTyKind::Weak, AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, ) - .into_term(), + .into(), AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => { I::Const::new_unevaluated( interner, UnevaluatedConst::new(self.def_id, self.args), interner.type_of_instantiated(self.def_id, self.args), ) - .into_term() + .into() } } } From 45b50d303c52a11785469364c82e083cbe14140b Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 13 May 2024 22:56:21 -0400 Subject: [PATCH 17/48] lto function, static_library call, rename --- src/tools/run-make-support/src/rustc.rs | 7 +++---- .../bar.rs | 0 .../foo.c | 0 .../foo.rs | 0 .../rmake.rs | 8 ++++---- 5 files changed, 7 insertions(+), 8 deletions(-) rename tests/run-make/{issue-14500 => reachable-extern-fn-available-lto}/bar.rs (100%) rename tests/run-make/{issue-14500 => reachable-extern-fn-available-lto}/foo.c (100%) rename tests/run-make/{issue-14500 => reachable-extern-fn-available-lto}/foo.rs (100%) rename tests/run-make/{issue-14500 => reachable-extern-fn-available-lto}/rmake.rs (78%) diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index c92e9f9b11f4c..0de5a38c0c486 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -150,10 +150,9 @@ impl Rustc { self } - /// Pass a codegen option. - pub fn codegen_option(&mut self, option: &str) -> &mut Self { - self.cmd.arg("-C"); - self.cmd.arg(option); + /// Enables link time optimizations in rustc. Equivalent to `-Clto``. + pub fn lto(&mut self) -> &mut Self { + self.cmd.arg("-Clto"); self } diff --git a/tests/run-make/issue-14500/bar.rs b/tests/run-make/reachable-extern-fn-available-lto/bar.rs similarity index 100% rename from tests/run-make/issue-14500/bar.rs rename to tests/run-make/reachable-extern-fn-available-lto/bar.rs diff --git a/tests/run-make/issue-14500/foo.c b/tests/run-make/reachable-extern-fn-available-lto/foo.c similarity index 100% rename from tests/run-make/issue-14500/foo.c rename to tests/run-make/reachable-extern-fn-available-lto/foo.c diff --git a/tests/run-make/issue-14500/foo.rs b/tests/run-make/reachable-extern-fn-available-lto/foo.rs similarity index 100% rename from tests/run-make/issue-14500/foo.rs rename to tests/run-make/reachable-extern-fn-available-lto/foo.rs diff --git a/tests/run-make/issue-14500/rmake.rs b/tests/run-make/reachable-extern-fn-available-lto/rmake.rs similarity index 78% rename from tests/run-make/issue-14500/rmake.rs rename to tests/run-make/reachable-extern-fn-available-lto/rmake.rs index 58f632e590938..3e38b92b2b87d 100644 --- a/tests/run-make/issue-14500/rmake.rs +++ b/tests/run-make/reachable-extern-fn-available-lto/rmake.rs @@ -1,5 +1,5 @@ // Test to make sure that reachable extern fns are always available in final -// productcs, including when LTO is used. +// productcs, including when link time optimizations (LTO) are used. // In this test, the `foo` crate has a reahable symbol, // and is a dependency of the `bar` crate. When the `bar` crate @@ -9,15 +9,15 @@ //@ ignore-cross-compile -use run_make_support::{cc, extra_c_flags, run, rustc, tmp_dir}; +use run_make_support::{cc, extra_c_flags, run, rustc, static_lib, tmp_dir}; fn main() { - let libbar_path = tmp_dir().join("libbar.a"); + let libbar_path = static_lib("bar"); rustc().input("foo.rs").crate_type("rlib").run(); rustc() .input("bar.rs") .crate_type("staticlib") - .codegen_option("lto") + .lto() .library_search_path(".") .output(&libbar_path) .run(); From 8f97a2588caa808b4d46dc3224de5d40bbbcd94b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 13 May 2024 22:36:48 -0400 Subject: [PATCH 18/48] Add test to make sure suggestions are still quick --- ...obe-for-diagnostic-doesnt-do-extra-work.rs | 163 ++++++++++++++++++ ...for-diagnostic-doesnt-do-extra-work.stderr | 84 +++++++++ 2 files changed, 247 insertions(+) create mode 100644 tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.rs create mode 100644 tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.stderr diff --git a/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.rs b/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.rs new file mode 100644 index 0000000000000..b6bc450dcc764 --- /dev/null +++ b/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.rs @@ -0,0 +1,163 @@ +#![allow(non_snake_case)] + +// Ensures that we don't spend an unnecessary amount of compiler time building +// suggestions for mistyped methods. This used to happen because when we had method +// lookup failures, we would do subsequent method lookups, and those would themselves +// do extra work that was unnecessary for the purposes of suggestions. +// Fixed by #125100. + +macro_rules! traits { + ($($name:ident),*) => { + $( + trait $name { + fn $name(&self); + } + )* + } +} + +traits!( + A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, + A21, A22, A23, A24, A25, A26, A27, A28, A29, A30, A31, A32, A33, A34, A35, A36, A37, A38, A39, + A40, A41, A42, A43, A44, A45, A46, A47, A48, A49, A50, A51, A52, A53, A54, A55, A56, A57, A58, + A59, A60, A61, A62, A63, A64, A65, A66, A67, A68, A69, A70, A71, A72, A73, A74, A75, A76, A77, + A78, A79, A80, A81, A82, A83, A84, A85, A86, A87, A88, A89, A90, A91, A92, A93, A94, A95, A96, + A97, A98, A99, A100, A101, A102, A103, A104, A105, A106, A107, A108, A109, A110, A111, A112, + A113, A114, A115, A116, A117, A118, A119, A120, A121, A122, A123, A124, A125, A126, A127, A128, + A129, A130, A131, A132, A133, A134, A135, A136, A137, A138, A139, A140, A141, A142, A143, A144, + A145, A146, A147, A148, A149, A150, A151, A152, A153, A154, A155, A156, A157, A158, A159, A160, + A161, A162, A163, A164, A165, A166, A167, A168, A169, A170, A171, A172, A173, A174, A175, A176, + A177, A178, A179, A180, A181, A182, A183, A184, A185, A186, A187, A188, A189, A190, A191, A192, + A193, A194, A195, A196, A197, A198, A199, A200, A201, A202, A203, A204, A205, A206, A207, A208, + A209, A210, A211, A212, A213, A214, A215, A216, A217, A218, A219, A220, A221, A222, A223, A224, + A225, A226, A227, A228, A229, A230, A231, A232, A233, A234, A235, A236, A237, A238, A239, A240, + A241, A242, A243, A244, A245, A246, A247, A248, A249, A250, A251, A252, A253, A254, A255, A256, + A257, A258, A259, A260, A261, A262, A263, A264, A265, A266, A267, A268, A269, A270, A271, A272, + A273, A274, A275, A276, A277, A278, A279, A280, A281, A282, A283, A284, A285, A286, A287, A288, + A289, A290, A291, A292, A293, A294, A295, A296, A297, A298, A299, A300, A301, A302, A303, A304, + A305, A306, A307, A308, A309, A310, A311, A312, A313, A314, A315, A316, A317, A318, A319, A320, + A321, A322, A323, A324, A325, A326, A327, A328, A329, A330, A331, A332, A333, A334, A335, A336, + A337, A338, A339, A340, A341, A342, A343, A344, A345, A346, A347, A348, A349, A350, A351, A352, + A353, A354, A355, A356, A357, A358, A359, A360, A361, A362, A363, A364, A365, A366, A367, A368, + A369, A370, A371, A372, A373, A374, A375, A376, A377, A378, A379, A380, A381, A382, A383, A384, + A385, A386, A387, A388, A389, A390, A391, A392, A393, A394, A395, A396, A397, A398, A399, A400, + A401, A402, A403, A404, A405, A406, A407, A408, A409, A410, A411, A412, A413, A414, A415, A416, + A417, A418, A419, A420, A421, A422, A423, A424, A425, A426, A427, A428, A429, A430, A431, A432, + A433, A434, A435, A436, A437, A438, A439, A440, A441, A442, A443, A444, A445, A446, A447, A448, + A449, A450, A451, A452, A453, A454, A455, A456, A457, A458, A459, A460, A461, A462, A463, A464, + A465, A466, A467, A468, A469, A470, A471, A472, A473, A474, A475, A476, A477, A478, A479, A480, + A481, A482, A483, A484, A485, A486, A487, A488, A489, A490, A491, A492, A493, A494, A495, A496, + A497, A498, A499, A500, A501, A502, A503, A504, A505, A506, A507, A508, A509, A510, A511, A512, + A513, A514, A515, A516, A517, A518, A519, A520, A521, A522, A523, A524, A525, A526, A527, A528, + A529, A530, A531, A532, A533, A534, A535, A536, A537, A538, A539, A540, A541, A542, A543, A544, + A545, A546, A547, A548, A549, A550, A551, A552, A553, A554, A555, A556, A557, A558, A559, A560, + A561, A562, A563, A564, A565, A566, A567, A568, A569, A570, A571, A572, A573, A574, A575, A576, + A577, A578, A579, A580, A581, A582, A583, A584, A585, A586, A587, A588, A589, A590, A591, A592, + A593, A594, A595, A596, A597, A598, A599, A600, A601, A602, A603, A604, A605, A606, A607, A608, + A609, A610, A611, A612, A613, A614, A615, A616, A617, A618, A619, A620, A621, A622, A623, A624, + A625, A626, A627, A628, A629, A630, A631, A632, A633, A634, A635, A636, A637, A638, A639, A640, + A641, A642, A643, A644, A645, A646, A647, A648, A649, A650, A651, A652, A653, A654, A655, A656, + A657, A658, A659, A660, A661, A662, A663, A664, A665, A666, A667, A668, A669, A670, A671, A672, + A673, A674, A675, A676, A677, A678, A679, A680, A681, A682, A683, A684, A685, A686, A687, A688, + A689, A690, A691, A692, A693, A694, A695, A696, A697, A698, A699, A700, A701, A702, A703, A704, + A705, A706, A707, A708, A709, A710, A711, A712, A713, A714, A715, A716, A717, A718, A719, A720, + A721, A722, A723, A724, A725, A726, A727, A728, A729, A730, A731, A732, A733, A734, A735, A736, + A737, A738, A739, A740, A741, A742, A743, A744, A745, A746, A747, A748, A749, A750, A751, A752, + A753, A754, A755, A756, A757, A758, A759, A760, A761, A762, A763, A764, A765, A766, A767, A768, + A769, A770, A771, A772, A773, A774, A775, A776, A777, A778, A779, A780, A781, A782, A783, A784, + A785, A786, A787, A788, A789, A790, A791, A792, A793, A794, A795, A796, A797, A798, A799, A800, + A801, A802, A803, A804, A805, A806, A807, A808, A809, A810, A811, A812, A813, A814, A815, A816, + A817, A818, A819, A820, A821, A822, A823, A824, A825, A826, A827, A828, A829, A830, A831, A832, + A833, A834, A835, A836, A837, A838, A839, A840, A841, A842, A843, A844, A845, A846, A847, A848, + A849, A850, A851, A852, A853, A854, A855, A856, A857, A858, A859, A860, A861, A862, A863, A864, + A865, A866, A867, A868, A869, A870, A871, A872, A873, A874, A875, A876, A877, A878, A879, A880, + A881, A882, A883, A884, A885, A886, A887, A888, A889, A890, A891, A892, A893, A894, A895, A896, + A897, A898, A899, A900, A901, A902, A903, A904, A905, A906, A907, A908, A909, A910, A911, A912, + A913, A914, A915, A916, A917, A918, A919, A920, A921, A922, A923, A924, A925, A926, A927, A928, + A929, A930, A931, A932, A933, A934, A935, A936, A937, A938, A939, A940, A941, A942, A943, A944, + A945, A946, A947, A948, A949, A950, A951, A952, A953, A954, A955, A956, A957, A958, A959, A960, + A961, A962, A963, A964, A965, A966, A967, A968, A969, A970, A971, A972, A973, A974, A975, A976, + A977, A978, A979, A980, A981, A982, A983, A984, A985, A986, A987, A988, A989, A990, A991, A992, + A993, A994, A995, A996, A997, A998, A999 +); + +#[derive(Default)] +struct M0 { + m1: M1, + m2: M1, + m3: M1, + m4: M1, + m5: M1, + m6: M1, + m7: M1, + m8: M1, + m9: M1, + m10: M1, + m11: M1, + m12: M1, + m13: M1, + m14: M1, + m15: M1, +} + +#[derive(Default)] +struct M1 { + m1: M2, + m2: M2, + m3: M2, + m4: M2, + m5: M2, + m6: M2, + m7: M2, + m8: M2, + m9: M2, + m10: M2, + m11: M2, + m12: M2, + m13: M2, + m14: M2, + m15: M2, +} + +#[derive(Default)] +struct M2 { + m1: M3, + m2: M3, + m3: M3, + m4: M3, + m5: M3, + m6: M3, + m7: M3, + m8: M3, + m9: M3, + m10: M3, + m11: M3, + m12: M3, + m13: M3, + m14: M3, + m15: M3, +} + +#[derive(Default)] +struct M3 {} + +fn main() { + M0::default().Au(); + //~^ ERROR no method named `Au` found for struct `M0` in the current scope + M0::default().Au(); + //~^ ERROR no method named `Au` found for struct `M0` in the current scope + M0::default().Au(); + //~^ ERROR no method named `Au` found for struct `M0` in the current scope + M0::default().Au(); + //~^ ERROR no method named `Au` found for struct `M0` in the current scope + M0::default().Au(); + //~^ ERROR no method named `Au` found for struct `M0` in the current scope + M0::default().Au(); + //~^ ERROR no method named `Au` found for struct `M0` in the current scope + M0::default().Au(); + //~^ ERROR no method named `Au` found for struct `M0` in the current scope + M0::default().Au(); + //~^ ERROR no method named `Au` found for struct `M0` in the current scope + M0::default().Au(); + //~^ ERROR no method named `Au` found for struct `M0` in the current scope +} diff --git a/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.stderr b/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.stderr new file mode 100644 index 0000000000000..f5c01ef8fe03b --- /dev/null +++ b/tests/ui/methods/probe-for-diagnostic-doesnt-do-extra-work.stderr @@ -0,0 +1,84 @@ +error[E0599]: no method named `Au` found for struct `M0` in the current scope + --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:145:19 + | +LL | struct M0 { + | --------- method `Au` not found for this struct +... +LL | M0::default().Au(); + | ^^ method not found in `M0` + +error[E0599]: no method named `Au` found for struct `M0` in the current scope + --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:147:19 + | +LL | struct M0 { + | --------- method `Au` not found for this struct +... +LL | M0::default().Au(); + | ^^ method not found in `M0` + +error[E0599]: no method named `Au` found for struct `M0` in the current scope + --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:149:19 + | +LL | struct M0 { + | --------- method `Au` not found for this struct +... +LL | M0::default().Au(); + | ^^ method not found in `M0` + +error[E0599]: no method named `Au` found for struct `M0` in the current scope + --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:151:19 + | +LL | struct M0 { + | --------- method `Au` not found for this struct +... +LL | M0::default().Au(); + | ^^ method not found in `M0` + +error[E0599]: no method named `Au` found for struct `M0` in the current scope + --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:153:19 + | +LL | struct M0 { + | --------- method `Au` not found for this struct +... +LL | M0::default().Au(); + | ^^ method not found in `M0` + +error[E0599]: no method named `Au` found for struct `M0` in the current scope + --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:155:19 + | +LL | struct M0 { + | --------- method `Au` not found for this struct +... +LL | M0::default().Au(); + | ^^ method not found in `M0` + +error[E0599]: no method named `Au` found for struct `M0` in the current scope + --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:157:19 + | +LL | struct M0 { + | --------- method `Au` not found for this struct +... +LL | M0::default().Au(); + | ^^ method not found in `M0` + +error[E0599]: no method named `Au` found for struct `M0` in the current scope + --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:159:19 + | +LL | struct M0 { + | --------- method `Au` not found for this struct +... +LL | M0::default().Au(); + | ^^ method not found in `M0` + +error[E0599]: no method named `Au` found for struct `M0` in the current scope + --> $DIR/probe-for-diagnostic-doesnt-do-extra-work.rs:161:19 + | +LL | struct M0 { + | --------- method `Au` not found for this struct +... +LL | M0::default().Au(); + | ^^ method not found in `M0` + +error: aborting due to 9 previous errors + +For more information about this error, try `rustc --explain E0599`. From dbd2ca6478dca81dc4ed64f9dec09fb216d34f1a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 7 May 2024 11:09:21 -0400 Subject: [PATCH 19/48] Use a proper probe for shadowing impl --- .../rustc_middle/src/traits/solve/inspect.rs | 2 ++ .../src/traits/solve/inspect/format.rs | 3 ++ .../src/solve/assembly/mod.rs | 19 +++++------ .../src/solve/eval_ctxt/select.rs | 3 +- .../src/solve/inspect/analyse.rs | 34 +++++++++++++------ 5 files changed, 39 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/traits/solve/inspect.rs b/compiler/rustc_middle/src/traits/solve/inspect.rs index 2ddcb8aab2530..9e94489902674 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect.rs @@ -153,6 +153,8 @@ pub enum ProbeKind<'tcx> { /// do a probe to find out what projection type(s) may be used to prove that /// the source type upholds all of the target type's object bounds. UpcastProjectionCompatibility, + /// Looking for param-env candidates that satisfy the trait ref for a projection. + ShadowedEnvProbing, /// Try to unify an opaque type with an existing key in the storage. OpaqueTypeStorageLookup { result: QueryResult<'tcx> }, } diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs index e652f0586c4ea..5b3c50cb97323 100644 --- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs +++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs @@ -118,6 +118,9 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> { ProbeKind::TraitCandidate { source, result } => { write!(self.f, "CANDIDATE {source:?}: {result:?}") } + ProbeKind::ShadowedEnvProbing => { + write!(self.f, "PROBING FOR IMPLS SHADOWED BY PARAM-ENV CANDIDATE:") + } }?; self.nested(|this| { diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 9a027d7f937ec..97bea28f06a3a 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -1,7 +1,7 @@ //! Code shared by trait and projection goals for candidate assembly. use crate::solve::GoalSource; -use crate::solve::{inspect, EvalCtxt, SolverMode}; +use crate::solve::{EvalCtxt, SolverMode}; use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; use rustc_middle::bug; @@ -16,7 +16,6 @@ use rustc_middle::ty::{fast_reject, TypeFoldable}; use rustc_middle::ty::{ToPredicate, TypeVisitableExt}; use rustc_span::{ErrorGuaranteed, DUMMY_SP}; use std::fmt::Debug; -use std::mem; pub(super) mod structural_traits; @@ -792,17 +791,16 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { goal: Goal<'tcx, G>, candidates: &mut Vec>, ) { - // HACK: We temporarily remove the `ProofTreeBuilder` to - // avoid adding `Trait` candidates to the candidates used - // to prove the current goal. - let inspect = mem::replace(&mut self.inspect, inspect::ProofTreeBuilder::new_noop()); - let tcx = self.tcx(); let trait_goal: Goal<'tcx, ty::TraitPredicate<'tcx>> = goal.with(tcx, goal.predicate.trait_ref(tcx)); - let mut trait_candidates_from_env = Vec::new(); - self.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env); - self.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env); + + let mut trait_candidates_from_env = vec![]; + self.probe(|_| ProbeKind::ShadowedEnvProbing).enter(|ecx| { + ecx.assemble_param_env_candidates(trait_goal, &mut trait_candidates_from_env); + ecx.assemble_alias_bound_candidates(trait_goal, &mut trait_candidates_from_env); + }); + if !trait_candidates_from_env.is_empty() { let trait_env_result = self.merge_candidates(trait_candidates_from_env); match trait_env_result.unwrap().value.certainty { @@ -831,7 +829,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } } - self.inspect = inspect; } /// If there are multiple ways to prove a trait or projection goal, we have diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 6fda5f4af25e7..68c0c8bf09eac 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -176,7 +176,8 @@ fn to_selection<'tcx>( | ProbeKind::UnsizeAssembly | ProbeKind::UpcastProjectionCompatibility | ProbeKind::OpaqueTypeStorageLookup { result: _ } - | ProbeKind::Root { result: _ } => { + | ProbeKind::Root { result: _ } + | ProbeKind::ShadowedEnvProbing => { span_bug!(span, "didn't expect to assemble trait candidate from {:#?}", cand.kind()) } }) diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index fd36b7ffd4eb4..b71a1b339cb81 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -18,8 +18,8 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{inspect, QueryResult}; use rustc_middle::traits::solve::{Certainty, Goal}; use rustc_middle::traits::ObligationCause; -use rustc_middle::ty; use rustc_middle::ty::TypeFoldable; +use rustc_middle::{bug, ty}; use rustc_span::{Span, DUMMY_SP}; use crate::solve::eval_ctxt::canonical; @@ -290,12 +290,25 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { match *step { inspect::ProbeStep::AddGoal(source, goal) => nested_goals.push((source, goal)), inspect::ProbeStep::NestedProbe(ref probe) => { - // Nested probes have to prove goals added in their parent - // but do not leak them, so we truncate the added goals - // afterwards. - let num_goals = nested_goals.len(); - self.candidates_recur(candidates, nested_goals, probe); - nested_goals.truncate(num_goals); + match probe.kind { + // These never assemble candidates for the goal we're trying to solve. + inspect::ProbeKind::UpcastProjectionCompatibility + | inspect::ProbeKind::ShadowedEnvProbing => continue, + + inspect::ProbeKind::NormalizedSelfTyAssembly + | inspect::ProbeKind::UnsizeAssembly + | inspect::ProbeKind::Root { .. } + | inspect::ProbeKind::TryNormalizeNonRigid { .. } + | inspect::ProbeKind::TraitCandidate { .. } + | inspect::ProbeKind::OpaqueTypeStorageLookup { .. } => { + // Nested probes have to prove goals added in their parent + // but do not leak them, so we truncate the added goals + // afterwards. + let num_goals = nested_goals.len(); + self.candidates_recur(candidates, nested_goals, probe); + nested_goals.truncate(num_goals); + } + } } inspect::ProbeStep::MakeCanonicalResponse { shallow_certainty: c } => { assert_eq!(shallow_certainty.replace(c), None); @@ -308,9 +321,10 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { } match probe.kind { - inspect::ProbeKind::NormalizedSelfTyAssembly - | inspect::ProbeKind::UnsizeAssembly - | inspect::ProbeKind::UpcastProjectionCompatibility => (), + inspect::ProbeKind::UpcastProjectionCompatibility + | inspect::ProbeKind::ShadowedEnvProbing => bug!(), + + inspect::ProbeKind::NormalizedSelfTyAssembly | inspect::ProbeKind::UnsizeAssembly => {} // We add a candidate even for the root evaluation if there // is only one way to prove a given goal, e.g. for `WellFormed`. From 57c32a193fee197f7ad034210de005db338a64ec Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 10 Jan 2024 19:30:22 -0800 Subject: [PATCH 20/48] style-guide: When breaking binops handle multi-line first operand better Use the indentation of the *last* line of the first operand, not the first. Fixes https://github.com/rust-lang/style-team/issues/189 --- src/doc/style-guide/src/editions.md | 2 ++ src/doc/style-guide/src/expressions.md | 31 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md index 9d593f8081025..74e873e35ff38 100644 --- a/src/doc/style-guide/src/editions.md +++ b/src/doc/style-guide/src/editions.md @@ -40,6 +40,8 @@ include: of a delimited expression, delimited expressions are generally combinable, regardless of the number of members. Previously only applied with exactly one member (except for closures with explicit blocks). +- When line-breaking a binary operator, if the first operand spans multiple + lines, use the base indentation of the last line. - Miscellaneous `rustfmt` bugfixes. - Use version-sort (sort `x8`, `x16`, `x32`, `x64`, `x128` in that order). - Change "ASCIIbetical" sort to Unicode-aware "non-lowercase before lowercase". diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 171a24cd89d73..597f8fcaf404e 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -328,6 +328,37 @@ foo_bar Prefer line-breaking at an assignment operator (either `=` or `+=`, etc.) rather than at other binary operators. +If line-breaking a binary operator (including assignment operators) where the +first operand spans multiple lines, use the base indentation of the *last* +line of the first , and indent relative to that: + +```rust +impl SomeType { + fn method(&mut self) { + self.array[array_index as usize] + .as_mut() + .expect("thing must exist") + .extra_info = + long_long_long_long_long_long_long_long_long_long_long_long_long_long_long; + + self.array[array_index as usize] + .as_mut() + .expect("thing must exist") + .extra_info + + long_long_long_long_long_long_long_long_long_long_long_long_long_long_long; + + self.array[array_index as usize] + .as_mut() + .expect("thing must exist") + .extra_info = Some(ExtraInfo { + parent, + count: count as u16, + children: children.into_boxed_slice(), + }); + } +} +``` + ### Casts (`as`) Format `as` casts like a binary operator. In particular, always include spaces From e2d9c0d938a057dfe745dea4a38eb397b6feb3c1 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 20 Jan 2024 13:26:01 -0800 Subject: [PATCH 21/48] Fix missing word Co-authored-by: Caleb Cartwright --- src/doc/style-guide/src/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 597f8fcaf404e..221cb3fbcc38c 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -330,7 +330,7 @@ than at other binary operators. If line-breaking a binary operator (including assignment operators) where the first operand spans multiple lines, use the base indentation of the *last* -line of the first , and indent relative to that: +line of the first operand, and indent relative to that: ```rust impl SomeType { From e098eb14ae9576593b38d4179c981fb7af7bee89 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sat, 20 Jan 2024 13:26:26 -0800 Subject: [PATCH 22/48] Wording improvement Co-authored-by: Caleb Cartwright --- src/doc/style-guide/src/expressions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 221cb3fbcc38c..3bb0ee6d5ff6c 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -328,7 +328,7 @@ foo_bar Prefer line-breaking at an assignment operator (either `=` or `+=`, etc.) rather than at other binary operators. -If line-breaking a binary operator (including assignment operators) where the +If line-breaking at a binary operator (including assignment operators) where the first operand spans multiple lines, use the base indentation of the *last* line of the first operand, and indent relative to that: From bfadc3a9b9cb4bbfacddf6e73adff23a3557852b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 30 Apr 2024 23:36:08 +1000 Subject: [PATCH 23/48] coverage: `CoverageIdsInfo::mcdc_bitmap_bytes` is never needed This code for recalculating `mcdc_bitmap_bytes` doesn't provide any benefit, because its result won't have changed from the value in `FunctionCoverageInfo` that was computed during the MIR instrumentation pass. --- compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs | 7 +------ compiler/rustc_middle/src/mir/query.rs | 4 ---- compiler/rustc_mir_transform/src/coverage/query.rs | 12 +----------- 3 files changed, 2 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index c51a7744a30a3..26ea95f0f0d50 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -207,13 +207,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { let cond_bitmap = coverage_context .try_get_mcdc_condition_bitmap(&instance, decision_depth) .expect("mcdc cond bitmap should have been allocated for merging into the global bitmap"); - let bitmap_bytes = bx.tcx().coverage_ids_info(instance.def).mcdc_bitmap_bytes; + let bitmap_bytes = function_coverage_info.mcdc_bitmap_bytes; assert!(bitmap_idx < bitmap_bytes, "bitmap index of the decision out of range"); - assert!( - bitmap_bytes <= function_coverage_info.mcdc_bitmap_bytes, - "bitmap length disagreement: query says {bitmap_bytes} but function info only has {}", - function_coverage_info.mcdc_bitmap_bytes - ); let fn_name = bx.get_pgo_func_name_var(instance); let hash = bx.const_u64(function_coverage_info.function_source_hash); diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 9a7af6135e46f..9d70231be3b0c 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -362,8 +362,4 @@ pub struct CoverageIdsInfo { /// InstrumentCoverage MIR pass, if the highest-numbered counter increments /// were removed by MIR optimizations. pub max_counter_id: mir::coverage::CounterId, - - /// Coverage codegen for mcdc needs to know the size of the global bitmap so that it can - /// set the `bytemap-bytes` argument of the `llvm.instrprof.mcdc.tvbitmap.update` intrinsic. - pub mcdc_bitmap_bytes: u32, } diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index f77ee63d02c20..65715253647a8 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -61,17 +61,7 @@ fn coverage_ids_info<'tcx>( .max() .unwrap_or(CounterId::ZERO); - let mcdc_bitmap_bytes = mir_body - .coverage_branch_info - .as_deref() - .map(|info| { - info.mcdc_decision_spans - .iter() - .fold(0, |acc, decision| acc + (1_u32 << decision.conditions_num).div_ceil(8)) - }) - .unwrap_or_default(); - - CoverageIdsInfo { max_counter_id, mcdc_bitmap_bytes } + CoverageIdsInfo { max_counter_id } } fn all_coverage_in_mir_body<'a, 'tcx>( From c81be68fb49cf5798fe44cedd56cb91bdc61d011 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 1 May 2024 11:19:52 +1000 Subject: [PATCH 24/48] coverage: Remove confusing comments from `CoverageKind` These comments appear to be inspired by the similar comments on `CounterIncrement` and `ExpressionUsed`. But those comments refer to specific simplification steps performed during coverage codegen, and there is no corresponding step for the MC/DC coverage statements. If these statements do not survive optimization, they will simply not participate in code generation, just like any other statement. --- compiler/rustc_middle/src/mir/coverage.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 477303e2434f4..7f9a5a366d74e 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -129,17 +129,11 @@ pub enum CoverageKind { /// Marks the point in MIR control flow represented by a evaluated condition. /// /// This is eventually lowered to `llvm.instrprof.mcdc.condbitmap.update` in LLVM IR. - /// - /// If this statement does not survive MIR optimizations, the condition would never be - /// taken as evaluated. CondBitmapUpdate { id: ConditionId, value: bool, decision_depth: u16 }, /// Marks the point in MIR control flow represented by a evaluated decision. /// /// This is eventually lowered to `llvm.instrprof.mcdc.tvbitmap.update` in LLVM IR. - /// - /// If this statement does not survive MIR optimizations, the decision would never be - /// taken as evaluated. TestVectorBitmapUpdate { bitmap_idx: u32, decision_depth: u16 }, } From f97d9151733ae29aa7d530a385003282b549dafc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 14 May 2024 13:39:40 +0200 Subject: [PATCH 25/48] Use new utility functions/methods in run-make tests --- tests/run-make/doctests-keep-binaries/rmake.rs | 9 +++------ tests/run-make/doctests-runtool/rmake.rs | 3 +-- tests/run-make/rustdoc-map-file/rmake.rs | 6 ++---- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/tests/run-make/doctests-keep-binaries/rmake.rs b/tests/run-make/doctests-keep-binaries/rmake.rs index ad0c2764df7aa..0613ef4839b14 100644 --- a/tests/run-make/doctests-keep-binaries/rmake.rs +++ b/tests/run-make/doctests-keep-binaries/rmake.rs @@ -26,8 +26,7 @@ fn main() { .arg("--test") .arg("--persist-doctests") .arg(out_dir) - .arg("--extern") - .arg(format!("t={}", extern_path.display())) + .extern_("t", extern_path) .run(); check_generated_binaries(); }); @@ -38,8 +37,7 @@ fn main() { .arg("--test") .arg("--persist-doctests") .arg(out_dir) - .arg("--extern") - .arg(format!("t={}", extern_path.display())) + .extern_("t", extern_path) .arg("--no-run") .run(); check_generated_binaries(); @@ -59,8 +57,7 @@ fn main() { .arg("doctests") .arg("--test-run-directory") .arg(run_dir) - .arg("--extern") - .arg("t=libt.rlib") + .extern_("t", "libt.rlib") .run(); remove_dir_all(run_dir_path); diff --git a/tests/run-make/doctests-runtool/rmake.rs b/tests/run-make/doctests-runtool/rmake.rs index 6f89bf23b47c4..6cc7c6bbdafd2 100644 --- a/tests/run-make/doctests-runtool/rmake.rs +++ b/tests/run-make/doctests-runtool/rmake.rs @@ -29,8 +29,7 @@ fn main() { .arg(run_dir_name) .arg("--runtool") .arg(&run_tool_binary) - .arg("--extern") - .arg("t=libt.rlib") + .extern_("t", "libt.rlib") .current_dir(tmp_dir()) .run(); diff --git a/tests/run-make/rustdoc-map-file/rmake.rs b/tests/run-make/rustdoc-map-file/rmake.rs index aaa7fea0b6b78..d017b41bcdd29 100644 --- a/tests/run-make/rustdoc-map-file/rmake.rs +++ b/tests/run-make/rustdoc-map-file/rmake.rs @@ -1,5 +1,4 @@ -use run_make_support::{rustdoc, tmp_dir}; -use std::process::Command; +use run_make_support::{python_command, rustdoc, tmp_dir}; fn main() { let out_dir = tmp_dir().join("out"); @@ -10,6 +9,5 @@ fn main() { .output(&out_dir) .run(); // FIXME (GuillaumeGomez): Port the python script to Rust as well. - let python = std::env::var("PYTHON").unwrap_or("python".into()); - assert!(Command::new(python).arg("validate_json.py").arg(&out_dir).status().unwrap().success()); + assert!(python_command().arg("validate_json.py").arg(&out_dir).status().unwrap().success()); } From ade33b02f237d484bef950ebf550bc12d49313d1 Mon Sep 17 00:00:00 2001 From: bohan Date: Mon, 13 May 2024 22:57:44 +0800 Subject: [PATCH 26/48] only find segs chain for missing methods when no available candidates --- .../rustc_hir_typeck/src/method/suggest.rs | 39 ++++++++++++++++--- tests/ui/const-generics/lookup-method.rs | 19 +++++++++ tests/ui/const-generics/lookup-method.stderr | 15 +++++++ 3 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 tests/ui/const-generics/lookup-method.rs create mode 100644 tests/ui/const-generics/lookup-method.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index d50e99433842a..5b15b3c8cce01 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1143,7 +1143,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - let label_span_not_found = |err: &mut Diag<'_>| { + let mut find_candidate_for_method = false; + + let mut label_span_not_found = |err: &mut Diag<'_>| { if unsatisfied_predicates.is_empty() { err.span_label(span, format!("{item_kind} not found in `{ty_str}`")); let is_string_or_ref_str = match rcvr_ty.kind() { @@ -1219,6 +1221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.note(format!( "the {item_kind} was found for\n{type_candidates}{additional_types}" )); + find_candidate_for_method = mode == Mode::MethodCall; } } } else { @@ -1371,9 +1374,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } - // If an appropriate error source is not found, check method chain for possible candiates - if unsatisfied_predicates.is_empty() - && let Mode::MethodCall = mode + + if !find_candidate_for_method { + self.lookup_segments_chain_for_no_match_method( + &mut err, + item_name, + item_kind, + source, + no_match_data, + ); + } + + self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected); + Some(err) + } + + /// If an appropriate error source is not found, check method chain for possible candidates + fn lookup_segments_chain_for_no_match_method( + &self, + err: &mut Diag<'_>, + item_name: Ident, + item_kind: &str, + source: SelfSource<'tcx>, + no_match_data: &NoMatchData<'tcx>, + ) { + if no_match_data.unsatisfied_predicates.is_empty() + && let Mode::MethodCall = no_match_data.mode && let SelfSource::MethodCall(mut source_expr) = source { let mut stack_methods = vec![]; @@ -1394,6 +1420,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .unwrap_or(Ty::new_misc_error(self.tcx)), ); + // FIXME: `probe_for_name_many` searches for methods in inherent implementations, + // so it may return a candidate that doesn't belong to this `revr_ty`. We need to + // check whether the instantiated type matches the received one. for _matched_method in self.probe_for_name_many( Mode::MethodCall, item_name, @@ -1416,8 +1445,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } - self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected); - Some(err) } fn find_likely_intended_associated_item( diff --git a/tests/ui/const-generics/lookup-method.rs b/tests/ui/const-generics/lookup-method.rs new file mode 100644 index 0000000000000..915935c94a55a --- /dev/null +++ b/tests/ui/const-generics/lookup-method.rs @@ -0,0 +1,19 @@ +// https://github.com/rust-lang/rust/issues/124946 + +struct Builder; + +impl Builder { + fn cast(self) -> Builder { + Builder + } +} + +impl Builder { + fn build(self) {} +} + +fn main() { + let b = Builder::; + b.cast().build(); + //~^ ERROR: no method named `build` found for struct `Builder` in the current scope +} diff --git a/tests/ui/const-generics/lookup-method.stderr b/tests/ui/const-generics/lookup-method.stderr new file mode 100644 index 0000000000000..4cbd1e17c7bea --- /dev/null +++ b/tests/ui/const-generics/lookup-method.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `build` found for struct `Builder` in the current scope + --> $DIR/lookup-method.rs:17:14 + | +LL | struct Builder; + | -------------------------------------------- method `build` not found for this struct +... +LL | b.cast().build(); + | ^^^^^ method not found in `Builder` + | + = note: the method was found for + - `Builder` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From 5cc020d3df393ff0ba3a209a3f791f8823abf5cf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 14 May 2024 19:32:11 +0200 Subject: [PATCH 27/48] avoid using aligned_alloc; posix_memalign is better-behaved --- library/std/src/sys/pal/unix/alloc.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs index 9938c0bac25b0..d1e19329025e5 100644 --- a/library/std/src/sys/pal/unix/alloc.rs +++ b/library/std/src/sys/pal/unix/alloc.rs @@ -89,21 +89,18 @@ cfg_if::cfg_if! { // /memory/aligned_memory.cc libc::memalign(layout.align(), layout.size()) as *mut u8 } - } else if #[cfg(target_os = "wasi")] { - #[inline] - unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { - // C11 aligned_alloc requires that the size be a multiple of the alignment. - // Layout already checks that the size rounded up doesn't overflow isize::MAX. - let align = layout.align(); - let size = layout.size().next_multiple_of(align); - libc::aligned_alloc(align, size) as *mut u8 - } } else { #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { let mut out = ptr::null_mut(); - // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`. - // Since these are all powers of 2, we can just use max. + // We prefer posix_memalign over aligned_malloc since with aligned_malloc, + // implementations are making almost arbitrary choices for which alignments are + // "supported", making it hard to use. For instance, some implementations require the + // size to be a multiple of the alignment (wasi emmalloc), while others require the + // alignment to be at least the pointer size (Illumos, macOS) -- which may or may not be + // standards-compliant, but that does not help us. + // posix_memalign only has one, clear requirement: that the alignment be a multiple of + // `sizeof(void*)`. Since these are all powers of 2, we can just use max. let align = layout.align().max(crate::mem::size_of::()); let ret = libc::posix_memalign(&mut out, align, layout.size()); if ret != 0 { ptr::null_mut() } else { out as *mut u8 } From c3c9783de2f6cbfaaaeaea91e603238b386b3f2e Mon Sep 17 00:00:00 2001 From: Bernardo Meurer Costa Date: Wed, 10 Apr 2024 18:49:55 +0000 Subject: [PATCH 28/48] feat(tools/opt-dist): allow local builds to specify a rustc-perf checkout --- src/tools/opt-dist/src/main.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index ffb01210e0455..bd0a3815855d5 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -69,6 +69,10 @@ enum EnvironmentCmd { #[arg(long, default_value = "opt-artifacts")] artifact_dir: Utf8PathBuf, + /// Checkout directory of `rustc-perf`, it will be fetched automatically if unspecified. + #[arg(long)] + rustc_perf_checkout_dir: Option, + /// Is LLVM for `rustc` built in shared library mode? #[arg(long, default_value_t = true)] llvm_shared: bool, @@ -109,6 +113,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> llvm_dir, python, artifact_dir, + rustc_perf_checkout_dir, llvm_shared, use_bolt, skipped_tests, @@ -121,6 +126,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .host_llvm_dir(llvm_dir) .artifact_dir(artifact_dir) .build_dir(checkout_dir) + .prebuilt_rustc_perf(rustc_perf_checkout_dir) .shared_llvm(llvm_shared) .use_bolt(use_bolt) .skipped_tests(skipped_tests) From 1f5837ae2506d5439b31195b7fcf784b9ee90d2b Mon Sep 17 00:00:00 2001 From: Oneirical Date: Sat, 11 May 2024 17:20:31 -0400 Subject: [PATCH 29/48] rewrite c-link-to-rust-staticlib --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../c-link-to-rust-staticlib/Makefile | 16 --------------- .../c-link-to-rust-staticlib/rmake.rs | 20 +++++++++++++++++++ 3 files changed, 20 insertions(+), 17 deletions(-) delete mode 100644 tests/run-make/c-link-to-rust-staticlib/Makefile create mode 100644 tests/run-make/c-link-to-rust-staticlib/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 5f68f779c4eb0..37acd768593eb 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -8,7 +8,6 @@ run-make/branch-protection-check-IBT/Makefile run-make/c-dynamic-dylib/Makefile run-make/c-dynamic-rlib/Makefile run-make/c-link-to-rust-dylib/Makefile -run-make/c-link-to-rust-staticlib/Makefile run-make/c-static-dylib/Makefile run-make/c-static-rlib/Makefile run-make/c-unwind-abi-catch-lib-panic/Makefile diff --git a/tests/run-make/c-link-to-rust-staticlib/Makefile b/tests/run-make/c-link-to-rust-staticlib/Makefile deleted file mode 100644 index d36cc421c468a..0000000000000 --- a/tests/run-make/c-link-to-rust-staticlib/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# This test checks that C linking with Rust does not encounter any errors, with static libraries. -# See https://github.com/rust-lang/rust/issues/10434 - -# ignore-cross-compile -include ../tools.mk - -# ignore-freebsd -# FIXME - -all: - $(RUSTC) foo.rs - $(CC) bar.c $(call STATICLIB,foo) $(call OUT_EXE,bar) \ - $(EXTRACFLAGS) $(EXTRACXXFLAGS) - $(call RUN,bar) - rm $(call STATICLIB,foo) - $(call RUN,bar) diff --git a/tests/run-make/c-link-to-rust-staticlib/rmake.rs b/tests/run-make/c-link-to-rust-staticlib/rmake.rs new file mode 100644 index 0000000000000..d73ca413777d2 --- /dev/null +++ b/tests/run-make/c-link-to-rust-staticlib/rmake.rs @@ -0,0 +1,20 @@ +// This test checks that C linking with Rust does not encounter any errors, with a static library. +// See https://github.com/rust-lang/rust/issues/10434 + +//@ ignore-cross-compile + +use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib}; +use std::fs; + +fn main() { + rustc().input("foo.rs").run(); + cc().input("bar.c") + .input(static_lib("foo")) + .out_exe("bar") + .args(&extra_c_flags()) + .args(&extra_cxx_flags()) + .run(); + run("bar"); + fs::remove_file(static_lib("foo")); + run("bar"); +} From b1e5e5161a2ef27852aab40cf3472187bdda5fee Mon Sep 17 00:00:00 2001 From: Julien <96022417+Oneirical@users.noreply.github.com> Date: Tue, 14 May 2024 16:43:39 -0400 Subject: [PATCH 30/48] remove cxx_flags --- tests/run-make/c-link-to-rust-staticlib/rmake.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/run-make/c-link-to-rust-staticlib/rmake.rs b/tests/run-make/c-link-to-rust-staticlib/rmake.rs index d73ca413777d2..762d7953a9a0f 100644 --- a/tests/run-make/c-link-to-rust-staticlib/rmake.rs +++ b/tests/run-make/c-link-to-rust-staticlib/rmake.rs @@ -3,7 +3,7 @@ //@ ignore-cross-compile -use run_make_support::{cc, extra_c_flags, extra_cxx_flags, run, rustc, static_lib}; +use run_make_support::{cc, extra_c_flags, run, rustc, static_lib}; use std::fs; fn main() { @@ -12,7 +12,6 @@ fn main() { .input(static_lib("foo")) .out_exe("bar") .args(&extra_c_flags()) - .args(&extra_cxx_flags()) .run(); run("bar"); fs::remove_file(static_lib("foo")); From 1f61cc3078ce6bcca8095778310f73fc45f7193e Mon Sep 17 00:00:00 2001 From: Oneirical Date: Mon, 13 May 2024 23:30:50 -0400 Subject: [PATCH 31/48] port no-cdylib-as-rdylib test --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/no-cdylib-as-rdylib/Makefile | 16 ---------------- tests/run-make/no-cdylib-as-rdylib/rmake.rs | 16 ++++++++++++++++ 3 files changed, 16 insertions(+), 17 deletions(-) delete mode 100644 tests/run-make/no-cdylib-as-rdylib/Makefile create mode 100644 tests/run-make/no-cdylib-as-rdylib/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index d742368292035..fc2ba589d2442 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -185,7 +185,6 @@ run-make/native-link-modifier-whole-archive/Makefile run-make/no-alloc-shim/Makefile run-make/no-builtins-attribute/Makefile run-make/no-builtins-lto/Makefile -run-make/no-cdylib-as-rdylib/Makefile run-make/no-duplicate-libs/Makefile run-make/no-intermediate-extras/Makefile run-make/obey-crate-type-flag/Makefile diff --git a/tests/run-make/no-cdylib-as-rdylib/Makefile b/tests/run-make/no-cdylib-as-rdylib/Makefile deleted file mode 100644 index 4d2be0aea913d..0000000000000 --- a/tests/run-make/no-cdylib-as-rdylib/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -# Test that rustc will not attempt to link against a cdylib as if -# it is a rust dylib when an rlib for the same crate is available. -# Previously rustc didn't actually check if any further formats of -# a crate which has been loaded are of the same version and if -# they are actually valid. This caused a cdylib to be interpreted -# as rust dylib as soon as the corresponding rlib was loaded. As -# cdylibs don't export any rust symbols, linking would fail if -# rustc decides to link against the cdylib rather than the rlib. - -all: - $(RUSTC) bar.rs --crate-type=rlib --crate-type=cdylib - $(RUSTC) foo.rs -C prefer-dynamic - $(call RUN,foo) diff --git a/tests/run-make/no-cdylib-as-rdylib/rmake.rs b/tests/run-make/no-cdylib-as-rdylib/rmake.rs new file mode 100644 index 0000000000000..42e89df6c2b61 --- /dev/null +++ b/tests/run-make/no-cdylib-as-rdylib/rmake.rs @@ -0,0 +1,16 @@ +// This test produces an rlib and a cdylib from bar.rs. +// Then, foo.rs attempts to link to the bar library. +// If the test passes, that means rustc favored the rlib and ignored the cdylib. +// If the test fails, that is because the cdylib was picked, which does not export +// any Rust symbols. +// See https://github.com/rust-lang/rust/pull/113695 + +//@ ignore-cross-compile + +use run_make_support::{run, rustc}; + +fn main() { + rustc().input("bar.rs").crate_type("rlib").crate_type("cdylib").run(); + rustc().input("foo.rs").arg("-Cprefer-dynamic").run(); + run("foo"); +} From 81f7e54962efc456a630746e7b73d1a97188d5d8 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Sat, 11 May 2024 19:34:19 -0400 Subject: [PATCH 32/48] Port issue-11908 to rmake --- src/tools/run-make-support/src/lib.rs | 51 +++++++++++++++++-- src/tools/run-make-support/src/rustc.rs | 10 +--- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/issue-11908/Makefile | 22 -------- .../rmake.rs | 4 +- .../bar.rs | 0 .../foo.rs | 0 .../same-lib-two-locations-no-panic/rmake.rs | 28 ++++++++++ 8 files changed, 79 insertions(+), 37 deletions(-) delete mode 100644 tests/run-make/issue-11908/Makefile rename tests/run-make/{issue-11908 => same-lib-two-locations-no-panic}/bar.rs (100%) rename tests/run-make/{issue-11908 => same-lib-two-locations-no-panic}/foo.rs (100%) create mode 100644 tests/run-make/same-lib-two-locations-no-panic/rmake.rs diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index cc81d23a8ff01..446afa1f82ec3 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -40,12 +40,17 @@ pub fn target() -> String { /// Check if target is windows-like. pub fn is_windows() -> bool { - env::var_os("IS_WINDOWS").is_some() + target().contains("windows") } /// Check if target uses msvc. pub fn is_msvc() -> bool { - env::var_os("IS_MSVC").is_some() + target().contains("msvc") +} + +/// Check if target uses macOS. +pub fn is_darwin() -> bool { + target().contains("darwin") } /// Construct a path to a static library under `$TMPDIR` given the library name. This will return a @@ -82,9 +87,47 @@ pub fn static_lib_name(name: &str) -> String { // endif // endif // ``` - assert!(!name.contains(char::is_whitespace), "name cannot contain whitespace"); + assert!(!name.contains(char::is_whitespace), "static library name cannot contain whitespace"); + + if is_msvc() { format!("{name}.lib") } else { format!("lib{name}.a") } +} + +/// Construct a path to a dynamic library under `$TMPDIR` given the library name. This will return a +/// path with `$TMPDIR` joined with platform-and-compiler-specific library name. +pub fn dynamic_lib(name: &str) -> PathBuf { + tmp_dir().join(dynamic_lib_name(name)) +} + +/// Construct the dynamic library name based on the platform. +pub fn dynamic_lib_name(name: &str) -> String { + // See tools.mk (irrelevant lines omitted): + // + // ```makefile + // ifeq ($(UNAME),Darwin) + // DYLIB = $(TMPDIR)/lib$(1).dylib + // else + // ifdef IS_WINDOWS + // DYLIB = $(TMPDIR)/$(1).dll + // else + // DYLIB = $(TMPDIR)/lib$(1).so + // endif + // endif + // ``` + assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace"); + + if is_darwin() { + format!("lib{name}.dylib") + } else if is_windows() { + format!("{name}.dll") + } else { + format!("lib{name}.so") + } +} - if target().contains("msvc") { format!("{name}.lib") } else { format!("lib{name}.a") } +/// Construct a path to a rust library (rlib) under `$TMPDIR` given the library name. This will return a +/// path with `$TMPDIR` joined with the library name. +pub fn rust_lib(name: &str) -> PathBuf { + tmp_dir().join(format!("lib{name}.rlib")) } /// Construct the binary name based on platform. diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index 7d239ff2e0a3a..d034826a830b4 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -91,7 +91,7 @@ impl Rustc { self } - /// Specify path to the output file. + /// Specify path to the output file. Equivalent to `-o`` in rustc. pub fn output>(&mut self, path: P) -> &mut Self { self.cmd.arg("-o"); self.cmd.arg(path.as_ref()); @@ -150,13 +150,7 @@ impl Rustc { self } - /// Enables link time optimizations in rustc. Equivalent to `-Clto``. - pub fn lto(&mut self) -> &mut Self { - self.cmd.arg("-Clto"); - self - } - - /// Add a directory to the library search path. + /// Add a directory to the library search path. Equivalent to `-L`` in rustc. pub fn library_search_path>(&mut self, path: P) -> &mut Self { self.cmd.arg("-L"); self.cmd.arg(path.as_ref()); diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 5f68f779c4eb0..c2358eff61799 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -94,7 +94,6 @@ run-make/invalid-staticlib/Makefile run-make/issue-107094/Makefile run-make/issue-10971-temps-dir/Makefile run-make/issue-109934-lto-debuginfo/Makefile -run-make/issue-11908/Makefile run-make/issue-14698/Makefile run-make/issue-15460/Makefile run-make/issue-18943/Makefile diff --git a/tests/run-make/issue-11908/Makefile b/tests/run-make/issue-11908/Makefile deleted file mode 100644 index 38586662fc75b..0000000000000 --- a/tests/run-make/issue-11908/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# ignore-cross-compile -# This test ensures that if you have the same rlib or dylib at two locations -# in the same path that you don't hit an assertion in the compiler. -# -# Note that this relies on `liburl` to be in the path somewhere else, -# and then our aux-built libraries will collide with liburl (they have -# the same version listed) - -include ../tools.mk - -all: - mkdir $(TMPDIR)/other - $(RUSTC) foo.rs --crate-type=dylib -C prefer-dynamic - mv $(call DYLIB,foo) $(TMPDIR)/other - $(RUSTC) foo.rs --crate-type=dylib -C prefer-dynamic - $(RUSTC) bar.rs -L $(TMPDIR)/other - rm -rf $(TMPDIR) - mkdir -p $(TMPDIR)/other - $(RUSTC) foo.rs --crate-type=rlib - mv $(TMPDIR)/libfoo.rlib $(TMPDIR)/other - $(RUSTC) foo.rs --crate-type=rlib - $(RUSTC) bar.rs -L $(TMPDIR)/other diff --git a/tests/run-make/reachable-extern-fn-available-lto/rmake.rs b/tests/run-make/reachable-extern-fn-available-lto/rmake.rs index 3e38b92b2b87d..c7262b9461b3a 100644 --- a/tests/run-make/reachable-extern-fn-available-lto/rmake.rs +++ b/tests/run-make/reachable-extern-fn-available-lto/rmake.rs @@ -9,7 +9,7 @@ //@ ignore-cross-compile -use run_make_support::{cc, extra_c_flags, run, rustc, static_lib, tmp_dir}; +use run_make_support::{cc, extra_c_flags, run, rustc, static_lib}; fn main() { let libbar_path = static_lib("bar"); @@ -17,7 +17,7 @@ fn main() { rustc() .input("bar.rs") .crate_type("staticlib") - .lto() + .arg("-Clto") .library_search_path(".") .output(&libbar_path) .run(); diff --git a/tests/run-make/issue-11908/bar.rs b/tests/run-make/same-lib-two-locations-no-panic/bar.rs similarity index 100% rename from tests/run-make/issue-11908/bar.rs rename to tests/run-make/same-lib-two-locations-no-panic/bar.rs diff --git a/tests/run-make/issue-11908/foo.rs b/tests/run-make/same-lib-two-locations-no-panic/foo.rs similarity index 100% rename from tests/run-make/issue-11908/foo.rs rename to tests/run-make/same-lib-two-locations-no-panic/foo.rs diff --git a/tests/run-make/same-lib-two-locations-no-panic/rmake.rs b/tests/run-make/same-lib-two-locations-no-panic/rmake.rs new file mode 100644 index 0000000000000..2900c3c8b749c --- /dev/null +++ b/tests/run-make/same-lib-two-locations-no-panic/rmake.rs @@ -0,0 +1,28 @@ +// A path which contains the same rlib or dylib in two locations +// should not cause an assertion panic in the compiler. +// This test tries to replicate the linked issue and checks +// if the bugged error makes a resurgence. + +// See https://github.com/rust-lang/rust/issues/11908 + +//@ ignore-cross-compile + +use run_make_support::{dynamic_lib, rust_lib, rustc, tmp_dir}; +use std::fs; + +fn main() { + let tmp_dir_other = tmp_dir().join("other"); + + fs::create_dir(&tmp_dir_other); + rustc().input("foo.rs").crate_type("dylib").arg("-Cprefer-dynamic").run(); + fs::rename(dynamic_lib("foo"), &tmp_dir_other); + rustc().input("foo.rs").crate_type("dylib").arg("-Cprefer-dynamic").run(); + rustc().input("bar.rs").library_search_path(&tmp_dir_other).run(); + fs::remove_dir_all(tmp_dir()); + + fs::create_dir_all(&tmp_dir_other); + rustc().input("foo.rs").crate_type("rlib").run(); + fs::rename(rust_lib("foo"), &tmp_dir_other); + rustc().input("foo.rs").crate_type("rlib").run(); + rustc().input("bar.rs").library_search_path(tmp_dir_other).run(); +} From 18d7411719c954fdd72307ce96fc9b3bf891bc7f Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Wed, 15 May 2024 00:49:33 +0200 Subject: [PATCH 33/48] Add `on_unimplemented" typo suggestions --- .../rustc_lint/src/context/diagnostics.rs | 8 ++++ compiler/rustc_lint_defs/src/lib.rs | 4 ++ compiler/rustc_resolve/src/macros.rs | 20 +++++++--- .../ui/diagnostic_namespace/suggest_typos.rs | 18 +++++++++ .../diagnostic_namespace/suggest_typos.stderr | 40 +++++++++++++++++++ 5 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 tests/ui/diagnostic_namespace/suggest_typos.rs create mode 100644 tests/ui/diagnostic_namespace/suggest_typos.stderr diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 8458b53933537..5ad3ff71a6d4a 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -347,5 +347,13 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di "reduce the glob import's visibility or increase visibility of imported items", ); } + BuiltinLintDiag::MaybeTypo { span, name } => { + diag.span_suggestion_verbose( + span, + "an attribute with a similar name exists", + name, + Applicability::MachineApplicable, + ); + } } } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index ed165188787a5..e06e3e9b805f7 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -663,6 +663,10 @@ pub enum BuiltinLintDiag { span: Span, max_vis: String, }, + MaybeTypo { + span: Span, + name: Symbol, + }, } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 35bf3f761df39..e3cfe6a6e05a5 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -29,6 +29,7 @@ use rustc_session::lint::builtin::{LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE}; use rustc_session::lint::builtin::{UNUSED_MACROS, UNUSED_MACRO_RULES}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::parse::feature_err; +use rustc_span::edit_distance::edit_distance; use rustc_span::edition::Edition; use rustc_span::hygiene::{self, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::hygiene::{AstPass, MacroKind}; @@ -568,15 +569,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if res == Res::NonMacroAttr(NonMacroAttrKind::Tool) - && path.segments.len() >= 2 - && path.segments[0].ident.name == sym::diagnostic - && path.segments[1].ident.name != sym::on_unimplemented + && let [namespace, attribute, ..] = &*path.segments + && namespace.ident.name == sym::diagnostic + && attribute.ident.name != sym::on_unimplemented { - self.tcx.sess.psess.buffer_lint( + let distance = + edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5); + + let help = if distance.is_some() { + BuiltinLintDiag::MaybeTypo { span: attribute.span(), name: sym::on_unimplemented } + } else { + BuiltinLintDiag::Normal + }; + self.tcx.sess.psess.buffer_lint_with_diagnostic( UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, - path.segments[1].span(), + attribute.span(), node_id, "unknown diagnostic attribute", + help, ); } diff --git a/tests/ui/diagnostic_namespace/suggest_typos.rs b/tests/ui/diagnostic_namespace/suggest_typos.rs new file mode 100644 index 0000000000000..b25f097a8adc1 --- /dev/null +++ b/tests/ui/diagnostic_namespace/suggest_typos.rs @@ -0,0 +1,18 @@ +#![deny(unknown_or_malformed_diagnostic_attributes)] + +#[diagnostic::onunimplemented] +//~^ERROR unknown diagnostic attribute +//~^^HELP an attribute with a similar name exists +trait X{} + +#[diagnostic::un_onimplemented] +//~^ERROR unknown diagnostic attribute +//~^^HELP an attribute with a similar name exists +trait Y{} + +#[diagnostic::on_implemented] +//~^ERROR unknown diagnostic attribute +//~^^HELP an attribute with a similar name exists +trait Z{} + +fn main(){} diff --git a/tests/ui/diagnostic_namespace/suggest_typos.stderr b/tests/ui/diagnostic_namespace/suggest_typos.stderr new file mode 100644 index 0000000000000..307311258f274 --- /dev/null +++ b/tests/ui/diagnostic_namespace/suggest_typos.stderr @@ -0,0 +1,40 @@ +error: unknown diagnostic attribute + --> $DIR/suggest_typos.rs:3:15 + | +LL | #[diagnostic::onunimplemented] + | ^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/suggest_typos.rs:1:9 + | +LL | #![deny(unknown_or_malformed_diagnostic_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: an attribute with a similar name exists + | +LL | #[diagnostic::on_unimplemented] + | ~~~~~~~~~~~~~~~~ + +error: unknown diagnostic attribute + --> $DIR/suggest_typos.rs:8:15 + | +LL | #[diagnostic::un_onimplemented] + | ^^^^^^^^^^^^^^^^ + | +help: an attribute with a similar name exists + | +LL | #[diagnostic::on_unimplemented] + | ~~~~~~~~~~~~~~~~ + +error: unknown diagnostic attribute + --> $DIR/suggest_typos.rs:13:15 + | +LL | #[diagnostic::on_implemented] + | ^^^^^^^^^^^^^^ + | +help: an attribute with a similar name exists + | +LL | #[diagnostic::on_unimplemented] + | ~~~~~~~~~~~~~~~~ + +error: aborting due to 3 previous errors + From c30b41012d474586d407392a6b154e7f19c38b2c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 15 Mar 2024 14:21:03 +0300 Subject: [PATCH 34/48] delegation: Implement list delegation ```rust reuse prefix::{a, b, c} ``` --- compiler/rustc_ast/src/ast.rs | 27 +++- compiler/rustc_ast/src/mut_visit.rs | 26 ++++ compiler/rustc_ast/src/visit.rs | 26 ++++ compiler/rustc_ast_lowering/src/item.rs | 20 ++- .../rustc_ast_pretty/src/pprust/state/item.rs | 74 ++++++++--- compiler/rustc_expand/messages.ftl | 3 + compiler/rustc_expand/src/errors.rs | 7 ++ compiler/rustc_expand/src/expand.rs | 117 +++++++++++++++++- compiler/rustc_parse/src/parser/item.rs | 31 +++-- compiler/rustc_parse/src/parser/path.rs | 7 +- compiler/rustc_passes/src/hir_stats.rs | 5 +- compiler/rustc_passes/src/lang_items.rs | 8 +- .../rustc_resolve/src/build_reduced_graph.rs | 6 +- compiler/rustc_resolve/src/def_collector.rs | 2 + .../src/effective_visibilities.rs | 2 +- compiler/rustc_resolve/src/late.rs | 15 ++- .../rustc_resolve/src/late/diagnostics.rs | 4 +- src/tools/rustfmt/src/items.rs | 4 +- src/tools/rustfmt/src/visitor.rs | 2 +- tests/ui/delegation/bad-resolve.rs | 4 + tests/ui/delegation/bad-resolve.stderr | 16 ++- tests/ui/delegation/body-identity-list.rs | 32 +++++ tests/ui/delegation/empty-list.rs | 8 ++ tests/ui/delegation/empty-list.stderr | 8 ++ tests/ui/delegation/inner-attr.rs | 8 ++ tests/ui/delegation/inner-attr.stderr | 18 +++ tests/ui/delegation/list.rs | 46 +++++++ tests/ui/delegation/macro-inside-list.rs | 26 ++++ tests/ui/delegation/rename.rs | 15 ++- 29 files changed, 509 insertions(+), 58 deletions(-) create mode 100644 tests/ui/delegation/body-identity-list.rs create mode 100644 tests/ui/delegation/empty-list.rs create mode 100644 tests/ui/delegation/empty-list.stderr create mode 100644 tests/ui/delegation/inner-attr.rs create mode 100644 tests/ui/delegation/inner-attr.stderr create mode 100644 tests/ui/delegation/list.rs create mode 100644 tests/ui/delegation/macro-inside-list.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 7951b7e7b75a0..6d3ee2bb54b62 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2961,6 +2961,7 @@ impl Item { | ItemKind::GlobalAsm(_) | ItemKind::MacCall(_) | ItemKind::Delegation(_) + | ItemKind::DelegationMac(_) | ItemKind::MacroDef(_) => None, ItemKind::Static(_) => None, ItemKind::Const(i) => Some(&i.generics), @@ -3123,8 +3124,16 @@ pub struct Delegation { /// Path resolution id. pub id: NodeId, pub qself: Option>, - pub rename: Option, pub path: Path, + pub rename: Option, + pub body: Option>, +} + +#[derive(Clone, Encodable, Decodable, Debug)] +pub struct DelegationMac { + pub qself: Option>, + pub prefix: Path, + pub suffixes: ThinVec<(Ident, Option)>, pub body: Option>, } @@ -3243,10 +3252,13 @@ pub enum ItemKind { /// A macro definition. MacroDef(MacroDef), - /// A delegation item (`reuse`). + /// A single delegation item (`reuse`). /// /// E.g. `reuse ::name { target_expr_template }`. Delegation(Box), + /// A list delegation item (`reuse prefix::{a, b, c}`). + /// Treated similarly to a macro call and expanded early. + DelegationMac(Box), } impl ItemKind { @@ -3255,7 +3267,7 @@ impl ItemKind { match self { Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..) | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) - | Delegation(..) => "a", + | Delegation(..) | DelegationMac(..) => "a", ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an", } } @@ -3280,6 +3292,7 @@ impl ItemKind { ItemKind::MacroDef(..) => "macro definition", ItemKind::Impl { .. } => "implementation", ItemKind::Delegation(..) => "delegated function", + ItemKind::DelegationMac(..) => "delegation", } } @@ -3323,6 +3336,8 @@ pub enum AssocItemKind { MacCall(P), /// An associated delegation item. Delegation(Box), + /// An associated delegation item list. + DelegationMac(Box), } impl AssocItemKind { @@ -3331,7 +3346,9 @@ impl AssocItemKind { Self::Const(box ConstItem { defaultness, .. }) | Self::Fn(box Fn { defaultness, .. }) | Self::Type(box TyAlias { defaultness, .. }) => defaultness, - Self::MacCall(..) | Self::Delegation(..) => Defaultness::Final, + Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => { + Defaultness::Final + } } } } @@ -3344,6 +3361,7 @@ impl From for ItemKind { AssocItemKind::Type(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), AssocItemKind::MacCall(a) => ItemKind::MacCall(a), AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation), + AssocItemKind::DelegationMac(delegation) => ItemKind::DelegationMac(delegation), } } } @@ -3358,6 +3376,7 @@ impl TryFrom for AssocItemKind { ItemKind::TyAlias(ty_kind) => AssocItemKind::Type(ty_kind), ItemKind::MacCall(a) => AssocItemKind::MacCall(a), ItemKind::Delegation(d) => AssocItemKind::Delegation(d), + ItemKind::DelegationMac(d) => AssocItemKind::DelegationMac(d), _ => return Err(item_kind), }) } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 5c4162295bbc1..1cfb8972a6280 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1170,6 +1170,19 @@ impl NoopVisitItemKind for ItemKind { vis.visit_block(body); } } + ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { + vis.visit_qself(qself); + vis.visit_path(prefix); + for (ident, rename) in suffixes { + vis.visit_ident(ident); + if let Some(rename) = rename { + vis.visit_ident(rename); + } + } + if let Some(body) = body { + vis.visit_block(body); + } + } } } } @@ -1213,6 +1226,19 @@ impl NoopVisitItemKind for AssocItemKind { visitor.visit_block(body); } } + AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { + visitor.visit_qself(qself); + visitor.visit_path(prefix); + for (ident, rename) in suffixes { + visitor.visit_ident(ident); + if let Some(rename) = rename { + visitor.visit_ident(rename); + } + } + if let Some(body) = body { + visitor.visit_block(body); + } + } } } } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index d36193ef7b0ab..7794edc350519 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -403,6 +403,19 @@ impl WalkItemKind for ItemKind { visit_opt!(visitor, visit_ident, *rename); visit_opt!(visitor, visit_block, body); } + ItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { + if let Some(qself) = qself { + try_visit!(visitor.visit_ty(&qself.ty)); + } + try_visit!(visitor.visit_path(prefix, item.id)); + for (ident, rename) in suffixes { + visitor.visit_ident(*ident); + if let Some(rename) = rename { + visitor.visit_ident(*rename); + } + } + visit_opt!(visitor, visit_block, body); + } } V::Result::output() } @@ -815,6 +828,19 @@ impl WalkItemKind for AssocItemKind { visit_opt!(visitor, visit_ident, *rename); visit_opt!(visitor, visit_block, body); } + AssocItemKind::DelegationMac(box DelegationMac { qself, prefix, suffixes, body }) => { + if let Some(qself) = qself { + try_visit!(visitor.visit_ty(&qself.ty)); + } + try_visit!(visitor.visit_path(prefix, item.id)); + for (ident, rename) in suffixes { + visitor.visit_ident(*ident); + if let Some(rename) = rename { + visitor.visit_ident(*rename); + } + } + visit_opt!(visitor, visit_block, body); + } } V::Result::output() } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 61fb5c16ad612..1255c1bba0876 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -460,8 +460,8 @@ impl<'hir> LoweringContext<'_, 'hir> { delegation_results.body_id, ) } - ItemKind::MacCall(..) => { - panic!("`TyMac` should have been expanded by now") + ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => { + panic!("macros should have been expanded by now") } } } @@ -845,7 +845,9 @@ impl<'hir> LoweringContext<'_, 'hir> { ); (delegation_results.generics, item_kind, true) } - AssocItemKind::MacCall(..) => panic!("macro item shouldn't exist at this point"), + AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { + panic!("macros should have been expanded by now") + } }; let item = hir::TraitItem { @@ -869,7 +871,9 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn { has_self: self.delegation_has_self(i.id, delegation.id, i.span), }, - AssocItemKind::MacCall(..) => unimplemented!(), + AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { + panic!("macros should have been expanded by now") + } }; let id = hir::TraitItemId { owner_id: hir::OwnerId { def_id: self.local_def_id(i.id) } }; hir::TraitItemRef { @@ -964,7 +968,9 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ImplItemKind::Fn(delegation_results.sig, delegation_results.body_id), ) } - AssocItemKind::MacCall(..) => panic!("`TyMac` should have been expanded by now"), + AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { + panic!("macros should have been expanded by now") + } }; let item = hir::ImplItem { @@ -993,7 +999,9 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Delegation(box delegation) => hir::AssocItemKind::Fn { has_self: self.delegation_has_self(i.id, delegation.id, i.span), }, - AssocItemKind::MacCall(..) => unimplemented!(), + AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { + panic!("macros should have been expanded by now") + } }, trait_item_def_id: self .resolver diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 09f9ca53a7ac0..16c3ee948a480 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -5,6 +5,7 @@ use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT}; use ast::StaticItem; use itertools::{Itertools, Position}; use rustc_ast as ast; +use rustc_ast::ptr::P; use rustc_ast::ModKind; use rustc_span::symbol::Ident; @@ -374,9 +375,22 @@ impl<'a> State<'a> { state.print_visibility(&item.vis) }); } - ast::ItemKind::Delegation(box delegation) => { - self.print_delegation(delegation, &item.vis, &item.attrs) - } + ast::ItemKind::Delegation(deleg) => self.print_delegation( + &item.attrs, + &item.vis, + &deleg.qself, + &deleg.path, + None, + &deleg.body, + ), + ast::ItemKind::DelegationMac(deleg) => self.print_delegation( + &item.attrs, + &item.vis, + &deleg.qself, + &deleg.prefix, + Some(&deleg.suffixes), + &deleg.body, + ), } self.ann.post(self, AnnNode::Item(item)) } @@ -553,31 +567,63 @@ impl<'a> State<'a> { self.word(";"); } } - ast::AssocItemKind::Delegation(box delegation) => { - self.print_delegation(delegation, vis, &item.attrs) - } + ast::AssocItemKind::Delegation(deleg) => self.print_delegation( + &item.attrs, + vis, + &deleg.qself, + &deleg.path, + None, + &deleg.body, + ), + ast::AssocItemKind::DelegationMac(deleg) => self.print_delegation( + &item.attrs, + vis, + &deleg.qself, + &deleg.prefix, + Some(&deleg.suffixes), + &deleg.body, + ), } self.ann.post(self, AnnNode::SubItem(id)) } pub(crate) fn print_delegation( &mut self, - delegation: &ast::Delegation, - vis: &ast::Visibility, attrs: &[ast::Attribute], + vis: &ast::Visibility, + qself: &Option>, + path: &ast::Path, + suffixes: Option<&[(Ident, Option)]>, + body: &Option>, ) { - if delegation.body.is_some() { + if body.is_some() { self.head(""); } self.print_visibility(vis); - self.word_space("reuse"); + self.word_nbsp("reuse"); - if let Some(qself) = &delegation.qself { - self.print_qpath(&delegation.path, qself, false); + if let Some(qself) = qself { + self.print_qpath(path, qself, false); } else { - self.print_path(&delegation.path, false, 0); + self.print_path(path, false, 0); + } + if let Some(suffixes) = suffixes { + self.word("::"); + self.word("{"); + for (i, (ident, rename)) in suffixes.iter().enumerate() { + self.print_ident(*ident); + if let Some(rename) = rename { + self.nbsp(); + self.word_nbsp("as"); + self.print_ident(*rename); + } + if i != suffixes.len() - 1 { + self.word_space(","); + } + } + self.word("}"); } - if let Some(body) = &delegation.body { + if let Some(body) = body { self.nbsp(); self.print_block_with_attrs(body, attrs); } else { diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index b7aae2af9ef97..7ae988a5be6c8 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -30,6 +30,9 @@ expand_duplicate_matcher_binding = duplicate matcher binding .label = duplicate binding .label2 = previous binding +expand_empty_delegation_list = + empty list delegation is not supported + expand_expected_paren_or_brace = expected `(` or `{"{"}`, found `{$token}` diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index b0563bfdea749..a5fc9e9d89c1e 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -433,3 +433,10 @@ pub struct ExpectedParenOrBrace<'a> { pub span: Span, pub token: Cow<'a, str>, } + +#[derive(Diagnostic)] +#[diag(expand_empty_delegation_list)] +pub(crate) struct EmptyDelegationList { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index ddf7b1a007a8e..a049ac251e1e7 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1,8 +1,8 @@ use crate::base::*; use crate::config::StripUnconfigured; use crate::errors::{ - IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, - UnsupportedKeyValue, WrongFragmentKind, + EmptyDelegationList, IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, + RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind, }; use crate::mbe::diagnostics::annotate_err_with_kind; use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod}; @@ -1041,6 +1041,7 @@ enum AddSemicolon { trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { type OutputTy = SmallVec<[Self; 1]>; type AttrsTy: Deref = ast::AttrVec; + type ItemKind = ItemKind; const KIND: AstFragmentKind; fn to_annotatable(self) -> Annotatable; fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy; @@ -1059,6 +1060,18 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized { fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { unreachable!() } + fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item)> { + None + } + fn delegation_item_kind(_deleg: Box) -> Self::ItemKind { + unreachable!() + } + fn from_item(_item: ast::Item) -> Self { + unreachable!() + } + fn flatten_outputs(_outputs: impl Iterator) -> Self::OutputTy { + unreachable!() + } fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {} fn post_flat_map_node_collect_bang(_output: &mut Self::OutputTy, _add_semicolon: AddSemicolon) { } @@ -1106,6 +1119,21 @@ impl InvocationCollectorNode for P { _ => unreachable!(), } } + fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item)> { + match &self.kind { + ItemKind::DelegationMac(deleg) => Some((deleg, self)), + _ => None, + } + } + fn delegation_item_kind(deleg: Box) -> Self::ItemKind { + ItemKind::Delegation(deleg) + } + fn from_item(item: ast::Item) -> Self { + P(item) + } + fn flatten_outputs(items: impl Iterator) -> Self::OutputTy { + items.flatten().collect() + } fn wrap_flat_map_node_noop_flat_map( mut node: Self, collector: &mut InvocationCollector<'_, '_>, @@ -1214,6 +1242,7 @@ impl InvocationCollectorNode for P { struct TraitItemTag; impl InvocationCollectorNode for AstNodeWrapper, TraitItemTag> { type OutputTy = SmallVec<[P; 1]>; + type ItemKind = AssocItemKind; const KIND: AstFragmentKind = AstFragmentKind::TraitItems; fn to_annotatable(self) -> Annotatable { Annotatable::TraitItem(self.wrapped) @@ -1234,11 +1263,27 @@ impl InvocationCollectorNode for AstNodeWrapper, TraitItemTag> _ => unreachable!(), } } + fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item)> { + match &self.wrapped.kind { + AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)), + _ => None, + } + } + fn delegation_item_kind(deleg: Box) -> Self::ItemKind { + AssocItemKind::Delegation(deleg) + } + fn from_item(item: ast::Item) -> Self { + AstNodeWrapper::new(P(item), TraitItemTag) + } + fn flatten_outputs(items: impl Iterator) -> Self::OutputTy { + items.flatten().collect() + } } struct ImplItemTag; impl InvocationCollectorNode for AstNodeWrapper, ImplItemTag> { type OutputTy = SmallVec<[P; 1]>; + type ItemKind = AssocItemKind; const KIND: AstFragmentKind = AstFragmentKind::ImplItems; fn to_annotatable(self) -> Annotatable { Annotatable::ImplItem(self.wrapped) @@ -1259,6 +1304,21 @@ impl InvocationCollectorNode for AstNodeWrapper, ImplItemTag> _ => unreachable!(), } } + fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item)> { + match &self.wrapped.kind { + AssocItemKind::DelegationMac(deleg) => Some((deleg, &self.wrapped)), + _ => None, + } + } + fn delegation_item_kind(deleg: Box) -> Self::ItemKind { + AssocItemKind::Delegation(deleg) + } + fn from_item(item: ast::Item) -> Self { + AstNodeWrapper::new(P(item), ImplItemTag) + } + fn flatten_outputs(items: impl Iterator) -> Self::OutputTy { + items.flatten().collect() + } } impl InvocationCollectorNode for P { @@ -1420,6 +1480,24 @@ impl InvocationCollectorNode for ast::Stmt { }; (mac, attrs, if add_semicolon { AddSemicolon::Yes } else { AddSemicolon::No }) } + fn delegation_list(&self) -> Option<(&ast::DelegationMac, &ast::Item)> { + match &self.kind { + StmtKind::Item(item) => match &item.kind { + ItemKind::DelegationMac(deleg) => Some((deleg, item)), + _ => None, + }, + _ => None, + } + } + fn delegation_item_kind(deleg: Box) -> Self::ItemKind { + ItemKind::Delegation(deleg) + } + fn from_item(item: ast::Item) -> Self { + ast::Stmt { id: ast::DUMMY_NODE_ID, span: item.span, kind: StmtKind::Item(P(item)) } + } + fn flatten_outputs(items: impl Iterator) -> Self::OutputTy { + items.flatten().collect() + } fn post_flat_map_node_collect_bang(stmts: &mut Self::OutputTy, add_semicolon: AddSemicolon) { // If this is a macro invocation with a semicolon, then apply that // semicolon to the final statement produced by expansion. @@ -1818,6 +1896,40 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { Node::post_flat_map_node_collect_bang(&mut res, add_semicolon); res } + None if let Some((deleg, item)) = node.delegation_list() => { + if deleg.suffixes.is_empty() { + // Report an error for now, to avoid keeping stem for resolution and + // stability checks. + self.cx.dcx().emit_err(EmptyDelegationList { span: item.span }); + } + + Node::flatten_outputs(deleg.suffixes.iter().map(|&(ident, rename)| { + let mut path = deleg.prefix.clone(); + path.segments.push(ast::PathSegment { + ident, + id: ast::DUMMY_NODE_ID, + args: None, + }); + + let mut item = Node::from_item(ast::Item { + attrs: item.attrs.clone(), + id: ast::DUMMY_NODE_ID, + span: ident.span, + vis: item.vis.clone(), + ident: rename.unwrap_or(ident), + kind: Node::delegation_item_kind(Box::new(ast::Delegation { + id: ast::DUMMY_NODE_ID, + qself: deleg.qself.clone(), + path, + rename, + body: deleg.body.clone(), + })), + tokens: None, + }); + + assign_id!(self, item.node_id_mut(), || item.noop_flat_map(self)) + })) + } None => { match Node::wrap_flat_map_node_noop_flat_map(node, self, |mut node, this| { assign_id!(this, node.node_id_mut(), || node.noop_flat_map(this)) @@ -1866,6 +1978,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { self.collect_bang(mac, Node::KIND).make_ast::() }) } + None if node.delegation_list().is_some() => unreachable!(), None => { assign_id!(self, node.node_id_mut(), || node.noop_visit(self)) } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 29957bd2f71ea..5a3bfb8372520 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -685,20 +685,35 @@ impl<'a> Parser<'a> { (None, self.parse_path(PathStyle::Expr)?) }; - let rename = if self.eat_keyword(kw::As) { Some(self.parse_ident()?) } else { None }; + let rename = |this: &mut Self| { + Ok(if this.eat_keyword(kw::As) { Some(this.parse_ident()?) } else { None }) + }; + let body = |this: &mut Self| { + Ok(if this.check(&token::OpenDelim(Delimiter::Brace)) { + Some(this.parse_block()?) + } else { + this.expect(&token::Semi)?; + None + }) + }; - let body = if self.check(&token::OpenDelim(Delimiter::Brace)) { - Some(self.parse_block()?) + let (ident, item_kind) = if self.eat(&token::PathSep) { + let (suffixes, _) = self.parse_delim_comma_seq(Delimiter::Brace, |p| { + Ok((p.parse_path_segment_ident()?, rename(p)?)) + })?; + let deleg = DelegationMac { qself, prefix: path, suffixes, body: body(self)? }; + (Ident::empty(), ItemKind::DelegationMac(Box::new(deleg))) } else { - self.expect(&token::Semi)?; - None + let rename = rename(self)?; + let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident); + let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body: body(self)? }; + (ident, ItemKind::Delegation(Box::new(deleg))) }; + let span = span.to(self.prev_token.span); self.psess.gated_spans.gate(sym::fn_delegation, span); - let ident = rename.unwrap_or_else(|| path.segments.last().unwrap().ident); - let deleg = Delegation { id: DUMMY_NODE_ID, qself, path, rename, body }; - Ok((ident, ItemKind::Delegation(Box::new(deleg)))) + Ok((ident, item_kind)) } fn parse_item_list( diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index c37d3f0441d0b..d845e8ab90d51 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -95,12 +95,15 @@ impl<'a> Parser<'a> { debug!("parse_qpath: (decrement) count={:?}", self.unmatched_angle_bracket_count); } - if !self.recover_colon_before_qpath_proj() { + let is_import_coupler = self.is_import_coupler(); + if !is_import_coupler && !self.recover_colon_before_qpath_proj() { self.expect(&token::PathSep)?; } let qself = P(QSelf { ty, path_span, position: path.segments.len() }); - self.parse_path_segments(&mut path.segments, style, None)?; + if !is_import_coupler { + self.parse_path_segments(&mut path.segments, style, None)?; + } Ok(( qself, diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index d7664d1c1fff7..a980d5dcaba4b 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -522,7 +522,8 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { Impl, MacCall, MacroDef, - Delegation + Delegation, + DelegationMac ] ); ast_visit::walk_item(self, i) @@ -650,7 +651,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_assoc_item(&mut self, i: &'v ast::AssocItem, ctxt: ast_visit::AssocCtxt) { record_variants!( (self, i, i.kind, Id::None, ast, AssocItem, AssocItemKind), - [Const, Fn, Type, MacCall, Delegation] + [Const, Fn, Type, MacCall, Delegation, DelegationMac] ); ast_visit::walk_assoc_item(self, i, ctxt); } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index c1da8928f3021..a5fa94faeadcd 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -285,7 +285,9 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { ast::ItemKind::TraitAlias(_, _) => Target::TraitAlias, ast::ItemKind::Impl(_) => Target::Impl, ast::ItemKind::MacroDef(_) => Target::MacroDef, - ast::ItemKind::MacCall(_) => unreachable!("macros should have been expanded"), + ast::ItemKind::MacCall(_) | ast::ItemKind::DelegationMac(_) => { + unreachable!("macros should have been expanded") + } }; self.check_for_lang( @@ -340,7 +342,9 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { } ast::AssocItemKind::Const(ct) => (Target::AssocConst, Some(&ct.generics)), ast::AssocItemKind::Type(ty) => (Target::AssocTy, Some(&ty.generics)), - ast::AssocItemKind::MacCall(_) => unreachable!("macros should have been expanded"), + ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(_) => { + unreachable!("macros should have been expanded") + } }; self.check_for_lang( diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 3467f1c3edfda..3e9aa3e0a6f21 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -825,7 +825,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {} - ItemKind::MacroDef(..) | ItemKind::MacCall(_) => unreachable!(), + ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => { + unreachable!() + } } } @@ -1381,7 +1383,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { | AssocItemKind::Delegation(..) | AssocItemKind::Fn(..) => ValueNS, AssocItemKind::Type(..) => TypeNS, - AssocItemKind::MacCall(_) => bug!(), // handled above + AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => bug!(), // handled above }; let parent = self.parent_scope.module; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index a27a6bceda335..741a650da55e0 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -139,6 +139,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, ItemKind::Use(..) => return visit::walk_item(self, i), ItemKind::MacCall(..) => return self.visit_macro_invoc(i.id), + ItemKind::DelegationMac(..) => unreachable!(), }; let def_id = self.create_def(i.id, i.ident.name, def_kind, i.span); @@ -278,6 +279,7 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { AssocItemKind::Const(..) => DefKind::AssocConst, AssocItemKind::Type(..) => DefKind::AssocTy, AssocItemKind::MacCall(..) => return self.visit_macro_invoc(i.id), + AssocItemKind::DelegationMac(..) => unreachable!(), }; let def = self.create_def(i.id, i.ident.name, def_kind, i.span); diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 3443bbe6e1158..074bf810eaf4b 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -236,7 +236,7 @@ impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 't ast::ItemKind::Impl(..) => return, // Should be unreachable at this stage - ast::ItemKind::MacCall(..) => panic!( + ast::ItemKind::MacCall(..) | ast::ItemKind::DelegationMac(..) => panic!( "ast::ItemKind::MacCall encountered, this should not anymore appear at this stage" ), diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5dd95a1896bb1..322f2922f9253 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2561,7 +2561,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ItemKind::ExternCrate(..) => {} - ItemKind::MacCall(_) => panic!("unexpanded macro in resolve!"), + ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => { + panic!("unexpanded macro in resolve!") + } } } @@ -2849,7 +2851,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { walk_assoc_item(this, generics, LifetimeBinderKind::Item, item) }), - AssocItemKind::MacCall(_) => { + AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => { panic!("unexpanded macro in resolve!") } }; @@ -3116,7 +3118,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }, ); } - AssocItemKind::MacCall(_) => { + AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => { panic!("unexpanded macro in resolve!") } } @@ -3218,7 +3220,9 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { AssocItemKind::Fn(..) => (E0324, "method"), AssocItemKind::Type(..) => (E0325, "type"), AssocItemKind::Delegation(..) => (E0324, "method"), - AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"), + AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => { + span_bug!(span, "unexpanded macro") + } }; let trait_path = path_names_to_string(path); self.report_error( @@ -4790,7 +4794,8 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { | ItemKind::ExternCrate(..) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(..) - | ItemKind::MacCall(..) => {} + | ItemKind::MacCall(..) + | ItemKind::DelegationMac(..) => {} ItemKind::Delegation(..) => { // Delegated functions have lifetimes, their count is not necessarily zero. // But skipping the delegation items here doesn't mean that the count will be considered zero, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 64451030adf0f..12815291c1d1c 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2045,7 +2045,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { AssocSuggestion::MethodWithSelf { called } } ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called }, - ast::AssocItemKind::MacCall(_) => continue, + ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(..) => { + continue; + } }); } } diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index e196d1817f34a..90e9e58ef9ca4 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -739,8 +739,8 @@ impl<'a> FmtVisitor<'a> { (_, Const(..)) => Ordering::Greater, (MacCall(..), _) => Ordering::Less, (_, MacCall(..)) => Ordering::Greater, - (Delegation(..), _) => Ordering::Less, - (_, Delegation(..)) => Ordering::Greater, + (Delegation(..), _) | (DelegationMac(..), _) => Ordering::Less, + (_, Delegation(..)) | (_, DelegationMac(..)) => Ordering::Greater, }); let mut prev_kind = None; for (buf, item) in buffer { diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 6209b37004bf1..e1c7dc35087b2 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -586,7 +586,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { ); self.push_rewrite(item.span, rewrite); } - ast::ItemKind::Delegation(..) => { + ast::ItemKind::Delegation(..) | ast::ItemKind::DelegationMac(..) => { // TODO: rewrite delegation items once syntax is established. // For now, leave the contents of the Span unformatted. self.push_rewrite(item.span, None) diff --git a/tests/ui/delegation/bad-resolve.rs b/tests/ui/delegation/bad-resolve.rs index d2723dc32e043..f378e05304b29 100644 --- a/tests/ui/delegation/bad-resolve.rs +++ b/tests/ui/delegation/bad-resolve.rs @@ -36,4 +36,8 @@ impl Trait for S { //~^ ERROR cannot find function `foo` in this scope } +mod prefix {} +reuse unresolved_prefix::{a, b, c}; //~ ERROR use of undeclared crate or module `unresolved_prefix` +reuse prefix::{self, super, crate}; //~ ERROR `crate` in paths can only be used in start position + fn main() {} diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr index f669ac3730e26..883ff523bcfea 100644 --- a/tests/ui/delegation/bad-resolve.stderr +++ b/tests/ui/delegation/bad-resolve.stderr @@ -63,7 +63,19 @@ LL | type Type; LL | impl Trait for S { | ^^^^^^^^^^^^^^^^ missing `Type` in implementation -error: aborting due to 8 previous errors +error[E0433]: failed to resolve: use of undeclared crate or module `unresolved_prefix` + --> $DIR/bad-resolve.rs:40:7 + | +LL | reuse unresolved_prefix::{a, b, c}; + | ^^^^^^^^^^^^^^^^^ use of undeclared crate or module `unresolved_prefix` + +error[E0433]: failed to resolve: `crate` in paths can only be used in start position + --> $DIR/bad-resolve.rs:41:29 + | +LL | reuse prefix::{self, super, crate}; + | ^^^^^ `crate` in paths can only be used in start position + +error: aborting due to 10 previous errors -Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0575, E0576. +Some errors have detailed explanations: E0046, E0324, E0407, E0423, E0425, E0433, E0575, E0576. For more information about an error, try `rustc --explain E0046`. diff --git a/tests/ui/delegation/body-identity-list.rs b/tests/ui/delegation/body-identity-list.rs new file mode 100644 index 0000000000000..1f08ab4e1a4c2 --- /dev/null +++ b/tests/ui/delegation/body-identity-list.rs @@ -0,0 +1,32 @@ +//@ check-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Trait { + fn foo(&self) {} + fn bar(&self) {} +} + +impl Trait for u8 {} + +struct S(u8); + +mod to_import { + pub fn check(arg: &u8) -> &u8 { arg } +} + +impl Trait for S { + reuse Trait::{foo, bar} { + use to_import::check; + + let _arr = Some(self.0).map(|x| [x * 2; 3]); + check(&self.0) + } +} + +fn main() { + let s = S(0); + s.foo(); + s.bar(); +} diff --git a/tests/ui/delegation/empty-list.rs b/tests/ui/delegation/empty-list.rs new file mode 100644 index 0000000000000..e0697f42283ec --- /dev/null +++ b/tests/ui/delegation/empty-list.rs @@ -0,0 +1,8 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +mod m {} + +reuse m::{}; //~ ERROR empty list delegation is not supported + +fn main() {} diff --git a/tests/ui/delegation/empty-list.stderr b/tests/ui/delegation/empty-list.stderr new file mode 100644 index 0000000000000..50d3c0eee223c --- /dev/null +++ b/tests/ui/delegation/empty-list.stderr @@ -0,0 +1,8 @@ +error: empty list delegation is not supported + --> $DIR/empty-list.rs:6:1 + | +LL | reuse m::{}; + | ^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/delegation/inner-attr.rs b/tests/ui/delegation/inner-attr.rs new file mode 100644 index 0000000000000..6c996807d6ba8 --- /dev/null +++ b/tests/ui/delegation/inner-attr.rs @@ -0,0 +1,8 @@ +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +fn a() {} + +reuse a as b { #![rustc_dummy] self } //~ ERROR an inner attribute is not permitted in this context + +fn main() {} diff --git a/tests/ui/delegation/inner-attr.stderr b/tests/ui/delegation/inner-attr.stderr new file mode 100644 index 0000000000000..f3b53e331ad88 --- /dev/null +++ b/tests/ui/delegation/inner-attr.stderr @@ -0,0 +1,18 @@ +error: an inner attribute is not permitted in this context + --> $DIR/inner-attr.rs:6:16 + | +LL | reuse a as b { #![rustc_dummy] self } + | ^^^^^^^^^^^^^^^ +LL | +LL | fn main() {} + | ------------ the inner attribute doesn't annotate this function + | + = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files +help: to annotate the function, change the attribute from inner to outer style + | +LL - reuse a as b { #![rustc_dummy] self } +LL + reuse a as b { #[rustc_dummy] self } + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/delegation/list.rs b/tests/ui/delegation/list.rs new file mode 100644 index 0000000000000..208b14816797a --- /dev/null +++ b/tests/ui/delegation/list.rs @@ -0,0 +1,46 @@ +//@ check-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Trait { + fn foo(&self) -> u8 { 0 } + fn bar(&self) -> u8 { 1 } +} + +impl Trait for u8 {} + +struct S(u8); +struct Z(u8); + +impl Trait for S { + reuse Trait::{foo, bar} { &self.0 } +} + +impl Trait for Z { + reuse ::{foo, bar} { &self.0 } +} + +trait Trait2 where Self: Trait { + reuse Trait::{foo, bar}; +} + +mod to_reuse { + pub fn a() {} + pub fn b() {} +} + +reuse to_reuse::{a, b}; + +fn main() { + let s = S(2); + s.foo(); + s.bar(); + + let z = Z(3); + z.foo(); + z.bar(); + + a(); + b(); +} diff --git a/tests/ui/delegation/macro-inside-list.rs b/tests/ui/delegation/macro-inside-list.rs new file mode 100644 index 0000000000000..16c74d396ef00 --- /dev/null +++ b/tests/ui/delegation/macro-inside-list.rs @@ -0,0 +1,26 @@ +//@ check-pass + +#![feature(fn_delegation)] +#![allow(incomplete_features)] + +trait Trait { + fn foo(&self) -> u8 { 0 } + fn bar(&self) -> u8 { 1 } +} + +impl Trait for u8 {} + +struct S(u8); + +// Macro expansion works inside delegation items. +macro_rules! u8 { () => { u8 } } +macro_rules! self_0 { () => { &self.0 } } +impl Trait for S { + reuse ::{foo, bar} { self_0!() } +} + +fn main() { + let s = S(2); + s.foo(); + s.bar(); +} diff --git a/tests/ui/delegation/rename.rs b/tests/ui/delegation/rename.rs index f4b3da76c56c7..80b8724a5bf9e 100644 --- a/tests/ui/delegation/rename.rs +++ b/tests/ui/delegation/rename.rs @@ -5,16 +5,23 @@ mod to_reuse { pub fn a() {} + pub fn b() {} } -reuse to_reuse::a as b; +reuse to_reuse::a as x; +reuse to_reuse::{a as y, b as z}; struct S; impl S { - reuse to_reuse::a as b; + reuse to_reuse::a as x; + reuse to_reuse::{a as y, b as z}; } fn main() { - b(); - S::b(); + x(); + y(); + z(); + S::x(); + S::y(); + S::z(); } From 91a3f04a3f9d6927e09c5ca6e57d337255cf1886 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 14 May 2024 20:06:23 -0400 Subject: [PATCH 35/48] fix the test --- tests/run-make/c-link-to-rust-staticlib/rmake.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/run-make/c-link-to-rust-staticlib/rmake.rs b/tests/run-make/c-link-to-rust-staticlib/rmake.rs index 762d7953a9a0f..63d5eb78c6987 100644 --- a/tests/run-make/c-link-to-rust-staticlib/rmake.rs +++ b/tests/run-make/c-link-to-rust-staticlib/rmake.rs @@ -8,11 +8,7 @@ use std::fs; fn main() { rustc().input("foo.rs").run(); - cc().input("bar.c") - .input(static_lib("foo")) - .out_exe("bar") - .args(&extra_c_flags()) - .run(); + cc().input("bar.c").input(static_lib("foo")).out_exe("bar").args(&extra_c_flags()).run(); run("bar"); fs::remove_file(static_lib("foo")); run("bar"); From 8994840f7e61c1e90db35e7d966d0271880d905c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 14 May 2024 20:40:47 -0400 Subject: [PATCH 36/48] rustdoc: Negative impls are not notable --- src/librustdoc/html/render/mod.rs | 8 +++++++ .../doc-notable_trait-negative.negative.html | 1 + .../doc-notable_trait-negative.positive.html | 1 + .../doc-notable_trait-negative.rs | 22 +++++++++++++++++++ 4 files changed, 32 insertions(+) create mode 100644 tests/rustdoc/notable-trait/doc-notable_trait-negative.negative.html create mode 100644 tests/rustdoc/notable-trait/doc-notable_trait-negative.positive.html create mode 100644 tests/rustdoc/notable-trait/doc-notable_trait-negative.rs diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index b4e62e39d8d6b..18323e0b8adaa 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1424,6 +1424,10 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> O if let Some(impls) = cx.cache().impls.get(&did) { for i in impls { let impl_ = i.inner_impl(); + if impl_.polarity != ty::ImplPolarity::Positive { + continue; + } + if !ty.is_doc_subtype_of(&impl_.for_, cx.cache()) { // Two different types might have the same did, // without actually being the same. @@ -1459,6 +1463,10 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) { for i in impls { let impl_ = i.inner_impl(); + if impl_.polarity != ty::ImplPolarity::Positive { + continue; + } + if !ty.is_doc_subtype_of(&impl_.for_, cx.cache()) { // Two different types might have the same did, // without actually being the same. diff --git a/tests/rustdoc/notable-trait/doc-notable_trait-negative.negative.html b/tests/rustdoc/notable-trait/doc-notable_trait-negative.negative.html new file mode 100644 index 0000000000000..6f19558cc1543 --- /dev/null +++ b/tests/rustdoc/notable-trait/doc-notable_trait-negative.negative.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/rustdoc/notable-trait/doc-notable_trait-negative.positive.html b/tests/rustdoc/notable-trait/doc-notable_trait-negative.positive.html new file mode 100644 index 0000000000000..a3d0fedaaf47e --- /dev/null +++ b/tests/rustdoc/notable-trait/doc-notable_trait-negative.positive.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/rustdoc/notable-trait/doc-notable_trait-negative.rs b/tests/rustdoc/notable-trait/doc-notable_trait-negative.rs new file mode 100644 index 0000000000000..2bbe0a3ef8c40 --- /dev/null +++ b/tests/rustdoc/notable-trait/doc-notable_trait-negative.rs @@ -0,0 +1,22 @@ +#![feature(doc_notable_trait, negative_impls)] + +#[doc(notable_trait)] +pub trait SomeTrait {} + +pub struct Positive; +impl SomeTrait for Positive {} + +pub struct Negative; +impl !SomeTrait for Negative {} + +// @has doc_notable_trait_negative/fn.positive.html +// @snapshot positive - '//script[@id="notable-traits-data"]' +pub fn positive() -> Positive { + todo!() +} + +// @has doc_notable_trait_negative/fn.negative.html +// @count - '//script[@id="notable-traits-data"]' 0 +pub fn negative() -> Negative { + &[] +} From 75895f59b0742126a7b5abeb86b35df2dfa8ee59 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 15 May 2024 10:26:07 +0800 Subject: [PATCH 37/48] Fix the dedup error because of spans from suggestion --- compiler/rustc_errors/src/diagnostic.rs | 2 +- tests/ui/macros/macro-span-issue-116502.rs | 16 ++++++++++ .../ui/macros/macro-span-issue-116502.stderr | 30 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/ui/macros/macro-span-issue-116502.rs create mode 100644 tests/ui/macros/macro-span-issue-116502.stderr diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 1610135a0efad..18bb71bd99f73 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -896,7 +896,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { style: SuggestionStyle, ) -> &mut Self { suggestion.sort_unstable(); - suggestion.dedup(); + suggestion.dedup_by(|(s1, m1), (s2, m2)| s1.source_equal(*s2) && m1 == m2); let parts = suggestion .into_iter() diff --git a/tests/ui/macros/macro-span-issue-116502.rs b/tests/ui/macros/macro-span-issue-116502.rs new file mode 100644 index 0000000000000..4c254289ee684 --- /dev/null +++ b/tests/ui/macros/macro-span-issue-116502.rs @@ -0,0 +1,16 @@ +#![allow(dead_code)] +#![allow(unused_variables)] + +fn bug() { + macro_rules! m { + () => { + _ //~ ERROR the placeholder `_` is not allowed within types on item signatures for structs + }; + } + struct S(m!(), T) + where + T: Trait; +} +trait Trait {} + +fn main() {} diff --git a/tests/ui/macros/macro-span-issue-116502.stderr b/tests/ui/macros/macro-span-issue-116502.stderr new file mode 100644 index 0000000000000..da02855660a4f --- /dev/null +++ b/tests/ui/macros/macro-span-issue-116502.stderr @@ -0,0 +1,30 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs + --> $DIR/macro-span-issue-116502.rs:7:13 + | +LL | _ + | ^ + | | + | not allowed in type signatures + | not allowed in type signatures + | not allowed in type signatures +... +LL | struct S(m!(), T) + | ---- ---- in this macro invocation + | | + | in this macro invocation +LL | where +LL | T: Trait; + | ---- in this macro invocation + | + = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use type parameters instead + | +LL ~ U +LL | }; +LL | } +LL ~ struct S(m!(), T) + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0121`. From 0afd50e8524aee0e9f23d4881bc7cac687c23ddf Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 15 May 2024 08:22:53 +0200 Subject: [PATCH 38/48] MIR operators: clarify Shl/Shr handling of negative offsets --- compiler/rustc_middle/src/mir/syntax.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 4278ce823d0e0..e124b478f4193 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1480,13 +1480,17 @@ pub enum BinOp { BitOr, /// The `<<` operator (shift left) /// - /// The offset is truncated to the size of the first operand and made unsigned before shifting. + /// The offset is (uniquely) determined as follows: + /// - it is "equal modulo LHS::BITS" to the RHS + /// - it is in the range `0..LHS::BITS` Shl, /// Like `Shl`, but is UB if the RHS >= LHS::BITS or RHS < 0 ShlUnchecked, /// The `>>` operator (shift right) /// - /// The offset is truncated to the size of the first operand and made unsigned before shifting. + /// The offset is (uniquely) determined as follows: + /// - it is "equal modulo LHS::BITS" to the RHS + /// - it is in the range `0..LHS::BITS` /// /// This is an arithmetic shift if the LHS is signed /// and a logical shift if the LHS is unsigned. From c87ae947ebdc868825f9ba23f45ec1a4878be996 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 May 2024 11:46:04 +0200 Subject: [PATCH 39/48] Add new `htmldocck` function to `run-make-support` --- src/tools/run-make-support/src/lib.rs | 6 ++++++ .../run-make/rustdoc-scrape-examples-ordering/rmake.rs | 10 ++-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index cc81d23a8ff01..5295388d02cab 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -59,6 +59,12 @@ pub fn python_command() -> Command { Command::new(python_path) } +pub fn htmldocck() -> Command { + let mut python = python_command(); + python.arg(source_path().join("/src/etc/htmldocck.py")); + python +} + pub fn source_path() -> PathBuf { std::env::var("S").expect("S variable does not exist").into() } diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs index edcf3406d47f8..08ca9ce5de817 100644 --- a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs @@ -1,4 +1,4 @@ -use run_make_support::{python_command, rustc, rustdoc, source_path, tmp_dir}; +use run_make_support::{htmldocck, rustc, rustdoc, source_path, tmp_dir}; use std::fs::read_dir; use std::path::Path; @@ -45,11 +45,5 @@ fn main() { } rustdoc.run(); - python_command() - .arg(source_path().join("/src/etc/htmldocck.py")) - .arg(out_dir) - .arg("src/lib.rs") - .status() - .unwrap() - .success(); + htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success(); } From c765480efedc191736587b3b890c362b8faa7fa7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 15 May 2024 11:46:25 +0200 Subject: [PATCH 40/48] Migrate `run-make/rustdoc-themes` to new rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/rustdoc-themes/Makefile | 11 ------- tests/run-make/rustdoc-themes/rmake.rs | 31 +++++++++++++++++++ 3 files changed, 31 insertions(+), 12 deletions(-) delete mode 100644 tests/run-make/rustdoc-themes/Makefile create mode 100644 tests/run-make/rustdoc-themes/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 5f68f779c4eb0..74aa8fe5949b8 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -246,7 +246,6 @@ run-make/rustdoc-scrape-examples-multiple/Makefile run-make/rustdoc-scrape-examples-remap/Makefile run-make/rustdoc-scrape-examples-test/Makefile run-make/rustdoc-scrape-examples-whitespace/Makefile -run-make/rustdoc-themes/Makefile run-make/rustdoc-verify-output-files/Makefile run-make/rustdoc-with-out-dir-option/Makefile run-make/rustdoc-with-output-option/Makefile diff --git a/tests/run-make/rustdoc-themes/Makefile b/tests/run-make/rustdoc-themes/Makefile deleted file mode 100644 index a4980eb0b3e4d..0000000000000 --- a/tests/run-make/rustdoc-themes/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -include ../tools.mk - -# Test that rustdoc will properly load in a theme file and display it in the theme selector. - -OUTPUT_DIR := "$(TMPDIR)/rustdoc-themes" - -all: - awk '/Begin theme: light/ {in_theme=1;next} /End theme:/ {in_theme=0} { if (in_theme) print }' \ - < '$(S)/src/librustdoc/html/static/css/noscript.css' > '$(TMPDIR)/test.css' - $(RUSTDOC) -o $(OUTPUT_DIR) foo.rs --theme $(TMPDIR)/test.css - $(HTMLDOCCK) $(OUTPUT_DIR) foo.rs diff --git a/tests/run-make/rustdoc-themes/rmake.rs b/tests/run-make/rustdoc-themes/rmake.rs new file mode 100644 index 0000000000000..1d7dfe6bb2a09 --- /dev/null +++ b/tests/run-make/rustdoc-themes/rmake.rs @@ -0,0 +1,31 @@ +// Test that rustdoc will properly load in a theme file and display it in the theme selector. + +use run_make_support::{htmldocck, rustdoc, source_path, tmp_dir}; + +fn main() { + let out_dir = tmp_dir().join("rustdoc-themes"); + let test_css = out_dir.join("test.css"); + + let no_script = + std::fs::read_to_string(source_path().join("src/librustdoc/html/static/css/noscript.css")) + .unwrap(); + + let mut test_content = String::new(); + let mut found_begin_light = false; + for line in no_script.split('\n') { + if line == "/* Begin theme: light */" { + found_begin_light = true; + } else if line == "/* End theme: light */" { + break; + } else if found_begin_light { + test_content.push_str(line); + test_content.push('\n'); + } + } + assert!(!test_content.is_empty()); + std::fs::create_dir_all(&out_dir).unwrap(); + std::fs::write(&test_css, test_content).unwrap(); + + rustdoc().output(&out_dir).input("foo.rs").arg("--theme").arg(&test_css).run(); + htmldocck().arg(out_dir).arg("foo.rs").status().unwrap().success(); +} From cae17ff42b711d0de6f5c70b90bd44b76c3d10c4 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 15 May 2024 09:58:47 -0400 Subject: [PATCH 41/48] rewrite panic-impl-transitive --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/panic-impl-transitive/Makefile | 7 ------- tests/run-make/panic-impl-transitive/rmake.rs | 14 ++++++++++++++ 3 files changed, 14 insertions(+), 8 deletions(-) delete mode 100644 tests/run-make/panic-impl-transitive/Makefile create mode 100644 tests/run-make/panic-impl-transitive/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index c2358eff61799..cf72a85218e1b 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -192,7 +192,6 @@ run-make/output-with-hyphens/Makefile run-make/override-aliased-flags/Makefile run-make/overwrite-input/Makefile run-make/panic-abort-eh_frame/Makefile -run-make/panic-impl-transitive/Makefile run-make/pass-linker-flags-flavor/Makefile run-make/pass-linker-flags-from-dep/Makefile run-make/pass-linker-flags/Makefile diff --git a/tests/run-make/panic-impl-transitive/Makefile b/tests/run-make/panic-impl-transitive/Makefile deleted file mode 100644 index 9a271a22e10dd..0000000000000 --- a/tests/run-make/panic-impl-transitive/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -include ../tools.mk - -# NOTE we use --emit=llvm-ir to avoid running the linker (linking will fail because there's no main -# in this crate) -all: - $(RUSTC) panic-impl-provider.rs - $(RUSTC) panic-impl-consumer.rs -C panic=abort --emit=llvm-ir -L $(TMPDIR) diff --git a/tests/run-make/panic-impl-transitive/rmake.rs b/tests/run-make/panic-impl-transitive/rmake.rs new file mode 100644 index 0000000000000..4e25f2410e8cc --- /dev/null +++ b/tests/run-make/panic-impl-transitive/rmake.rs @@ -0,0 +1,14 @@ +// In Rust programs where the standard library is unavailable (#![no_std]), we may be interested +// in customizing how panics are handled. Here, the provider specifies that panics should be handled +// by entering an infinite loop. This test checks that this panic implementation can be transitively +// provided by an external crate. +// --emit=llvm-ir is used to avoid running the linker, as linking will fail due to the lack of main +// function in the crate. +// See https://github.com/rust-lang/rust/pull/50338 + +use run_make_support::{rustc, tmp_dir}; + +fn main() { + rustc().input("panic-impl-provider.rs").run(); + rustc().input("panic-impl-consumer.rs").panic("abort").emit("llvm-ir").library_search_path(tmp_dir()).run(); +} From a7484d2e49e8bec4e6b4c2442f07fdc77bf70966 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 15 May 2024 10:09:19 -0400 Subject: [PATCH 42/48] fix tidy --- tests/run-make/panic-impl-transitive/rmake.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/run-make/panic-impl-transitive/rmake.rs b/tests/run-make/panic-impl-transitive/rmake.rs index 4e25f2410e8cc..86308f593b314 100644 --- a/tests/run-make/panic-impl-transitive/rmake.rs +++ b/tests/run-make/panic-impl-transitive/rmake.rs @@ -10,5 +10,10 @@ use run_make_support::{rustc, tmp_dir}; fn main() { rustc().input("panic-impl-provider.rs").run(); - rustc().input("panic-impl-consumer.rs").panic("abort").emit("llvm-ir").library_search_path(tmp_dir()).run(); + rustc() + .input("panic-impl-consumer.rs") + .panic("abort") + .emit("llvm-ir") + .library_search_path(tmp_dir()) + .run(); } From 72a48fc68c23afd94607a5c5eca3921116d0f434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 15 May 2024 20:19:52 +0200 Subject: [PATCH 43/48] Allow unauthenticated users to modify `L-*`, `PG-*` and `-Z*` labels --- triagebot.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 499ba6e470cda..38f3db2be3f9e 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -9,11 +9,14 @@ allow-unauthenticated = [ "E-*", "F-*", "I-*", + "L-*", "NLL-*", "O-*", + "PG-*", "S-*", "T-*", "WG-*", + "-Z*", "beta-nominated", "const-hack", "llvm-*", From 257d222e4b7243b7555e0033e75b308ea85af7e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kostrubiec?= Date: Tue, 14 May 2024 22:33:19 +0200 Subject: [PATCH 44/48] Improved the documentation of the FnAbi struct --- compiler/rustc_target/src/abi/call/mod.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 919fa2140d5be..fc79c9232d1bd 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -779,16 +779,21 @@ impl RiscvInterruptKind { /// Metadata describing how the arguments to a native function /// should be passed in order to respect the native ABI. /// +/// The signature represented by this type may not match the MIR function signature. +/// Certain attributes, like `#[track_caller]` can introduce additional arguments, which are present in [`FnAbi`], but not in `FnSig`. +/// While this difference is rarely relevant, it should still be kept in mind. +/// /// I will do my best to describe this structure, but these /// comments are reverse-engineered and may be inaccurate. -NDM #[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)] pub struct FnAbi<'a, Ty> { - /// The LLVM types of each argument. + /// The type, layout, and information about how each argument is passed. pub args: Box<[ArgAbi<'a, Ty>]>, - /// LLVM return type. + /// The layout, type, and the way a value is returned from this function. pub ret: ArgAbi<'a, Ty>, + /// Marks this function as variadic (accepting a variable number of arguments). pub c_variadic: bool, /// The count of non-variadic arguments. @@ -796,9 +801,9 @@ pub struct FnAbi<'a, Ty> { /// Should only be different from args.len() when c_variadic is true. /// This can be used to know whether an argument is variadic or not. pub fixed_count: u32, - + /// The calling convention of this function. pub conv: Conv, - + /// Indicates if an unwind may happen across a call to this function. pub can_unwind: bool, } From 887151ad93b0541ae19c6589f4aeb3f07bbc60a1 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 1 Apr 2024 13:16:15 -0700 Subject: [PATCH 45/48] Set `debuginfo-level = "line-tables-only"` for compiler profile This profile has only undergone minimal tweaks since it was originally drafted. I asked a number of compiler contributors and they said they set rust.debug explicitly. This was even true for one contributor that set `rust.debug` = false! Almost everyone seems slightly surprised that `rust.debug = true` is not the default. However, adding full debuginfo at this level costs multiple gigabytes! We can still get much better debuginfo by setting "line-tables-only" at the cost of only 150~200 MB. --- src/bootstrap/defaults/config.compiler.toml | 2 ++ src/bootstrap/src/utils/change_tracker.rs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml index d93c5fd25a150..fd2da24699086 100644 --- a/src/bootstrap/defaults/config.compiler.toml +++ b/src/bootstrap/defaults/config.compiler.toml @@ -8,6 +8,8 @@ compiler-docs = true # where adding `debug!()` appears to do nothing. # However, it makes running the compiler slightly slower. debug-logging = true +# Get actually-useful information from backtraces, profiling, etc. with minimal added bytes +debuginfo-level = "line-tables-only" # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. incremental = true # Print backtrace on internal compiler errors during bootstrap diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index c3a03693f714f..a1c9ddebb5d96 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -180,4 +180,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "New option `build.lldb` that will override the default lldb binary path used in debuginfo tests", }, + ChangeInfo { + change_id: 123337, + severity: ChangeSeverity::Info, + summary: r#"The compiler profile now defaults to rust.debuginfo-level = "line-tables-only""#, + }, ]; From 8124a5e74d3f4ac1723628a87ad178ed268663f4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 16 May 2024 15:17:00 +0200 Subject: [PATCH 46/48] Migrate `run-make/rustdoc-with-out-dir-option` to new `rmake.rs` --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/rustdoc-with-out-dir-option/Makefile | 8 -------- tests/run-make/rustdoc-with-out-dir-option/rmake.rs | 7 +++++++ 3 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 tests/run-make/rustdoc-with-out-dir-option/Makefile create mode 100644 tests/run-make/rustdoc-with-out-dir-option/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 44c9616dbb172..1a3d6f8d81360 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -243,7 +243,6 @@ run-make/rustdoc-scrape-examples-remap/Makefile run-make/rustdoc-scrape-examples-test/Makefile run-make/rustdoc-scrape-examples-whitespace/Makefile run-make/rustdoc-verify-output-files/Makefile -run-make/rustdoc-with-out-dir-option/Makefile run-make/rustdoc-with-output-option/Makefile run-make/rustdoc-with-short-out-dir-option/Makefile run-make/sanitizer-cdylib-link/Makefile diff --git a/tests/run-make/rustdoc-with-out-dir-option/Makefile b/tests/run-make/rustdoc-with-out-dir-option/Makefile deleted file mode 100644 index f5d5060ed1303..0000000000000 --- a/tests/run-make/rustdoc-with-out-dir-option/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -include ../tools.mk - -OUTPUT_DIR := "$(TMPDIR)/rustdoc" - -all: - $(RUSTDOC) src/lib.rs --crate-name foobar --crate-type lib --out-dir $(OUTPUT_DIR) - - $(HTMLDOCCK) $(OUTPUT_DIR) src/lib.rs diff --git a/tests/run-make/rustdoc-with-out-dir-option/rmake.rs b/tests/run-make/rustdoc-with-out-dir-option/rmake.rs new file mode 100644 index 0000000000000..86471093834fc --- /dev/null +++ b/tests/run-make/rustdoc-with-out-dir-option/rmake.rs @@ -0,0 +1,7 @@ +use run_make_support::{htmldocck, rustdoc, tmp_dir}; + +fn main() { + let out_dir = tmp_dir().join("rustdoc"); + rustdoc().input("src/lib.rs").crate_name("foobar").crate_type("lib").output(&out_dir).run(); + assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success()); +} From d594c9ceea99d5f48747aa9102586ddb0f95ea8a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 May 2024 00:47:18 +0200 Subject: [PATCH 47/48] Add missing assert! calls --- tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs | 2 +- tests/run-make/rustdoc-themes/rmake.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs index 08ca9ce5de817..1bc23ec88817f 100644 --- a/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs +++ b/tests/run-make/rustdoc-scrape-examples-ordering/rmake.rs @@ -45,5 +45,5 @@ fn main() { } rustdoc.run(); - htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success(); + assert!(htmldocck().arg(out_dir).arg("src/lib.rs").status().unwrap().success()); } diff --git a/tests/run-make/rustdoc-themes/rmake.rs b/tests/run-make/rustdoc-themes/rmake.rs index 1d7dfe6bb2a09..e9da4e2594007 100644 --- a/tests/run-make/rustdoc-themes/rmake.rs +++ b/tests/run-make/rustdoc-themes/rmake.rs @@ -27,5 +27,5 @@ fn main() { std::fs::write(&test_css, test_content).unwrap(); rustdoc().output(&out_dir).input("foo.rs").arg("--theme").arg(&test_css).run(); - htmldocck().arg(out_dir).arg("foo.rs").status().unwrap().success(); + assert!(htmldocck().arg(out_dir).arg("foo.rs").status().unwrap().success()); } From 61d4f5c53bc87665c425f10e663eedf8858b032f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 17 May 2024 00:50:11 +0200 Subject: [PATCH 48/48] Fix `htmldocck` function --- src/tools/run-make-support/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 03b1a7efaaddf..9854d91e19e33 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -66,7 +66,7 @@ pub fn python_command() -> Command { pub fn htmldocck() -> Command { let mut python = python_command(); - python.arg(source_path().join("/src/etc/htmldocck.py")); + python.arg(source_path().join("src/etc/htmldocck.py")); python }