From e77b14e2acc1efbd649990873a8db678cf2086fa Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 1 May 2023 17:17:05 +0000 Subject: [PATCH 01/41] Relax implicit `R: Sized` bound on `BufReader` --- library/std/src/io/buffered/bufreader.rs | 27 +++++++++++++----------- library/std/src/io/mod.rs | 2 +- library/std/src/sys/unix/kernel_copy.rs | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 4f339a18a480..3edf9d747ce8 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -47,9 +47,9 @@ use buffer::Buffer; /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub struct BufReader { - inner: R, +pub struct BufReader { buf: Buffer, + inner: R, } impl BufReader { @@ -95,7 +95,7 @@ impl BufReader { } } -impl BufReader { +impl BufReader { /// Gets a reference to the underlying reader. /// /// It is inadvisable to directly read from the underlying reader. @@ -213,7 +213,10 @@ impl BufReader { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_inner(self) -> R { + pub fn into_inner(self) -> R + where + R: Sized, + { self.inner } @@ -226,13 +229,13 @@ impl BufReader { // This is only used by a test which asserts that the initialization-tracking is correct. #[cfg(test)] -impl BufReader { +impl BufReader { pub fn initialized(&self) -> usize { self.buf.initialized() } } -impl BufReader { +impl BufReader { /// Seeks relative to the current position. If the new position lies within the buffer, /// the buffer will not be flushed, allowing for more efficient seeks. /// This method does not return the location of the underlying reader, so the caller @@ -257,7 +260,7 @@ impl BufReader { } #[stable(feature = "rust1", since = "1.0.0")] -impl Read for BufReader { +impl Read for BufReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { // If we don't have any buffered data and we're doing a massive read // (larger than our internal buffer), bypass our internal buffer @@ -371,7 +374,7 @@ impl Read for BufReader { } #[stable(feature = "rust1", since = "1.0.0")] -impl BufRead for BufReader { +impl BufRead for BufReader { fn fill_buf(&mut self) -> io::Result<&[u8]> { self.buf.fill_buf(&mut self.inner) } @@ -384,11 +387,11 @@ impl BufRead for BufReader { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for BufReader where - R: fmt::Debug, + R: ?Sized + fmt::Debug, { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("BufReader") - .field("reader", &self.inner) + .field("reader", &&self.inner) .field( "buffer", &format_args!("{}/{}", self.buf.filled() - self.buf.pos(), self.capacity()), @@ -398,7 +401,7 @@ where } #[stable(feature = "rust1", since = "1.0.0")] -impl Seek for BufReader { +impl Seek for BufReader { /// Seek to an offset, in bytes, in the underlying reader. /// /// The position used for seeking with [SeekFrom::Current]\(_) is the @@ -491,7 +494,7 @@ impl Seek for BufReader { } } -impl SizeHint for BufReader { +impl SizeHint for BufReader { #[inline] fn lower_bound(&self) -> usize { SizeHint::lower_bound(self.get_ref()) + self.buffer().len() diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 9e09ce337bc0..bb329dc2446b 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2753,7 +2753,7 @@ trait SizeHint { } } -impl SizeHint for T { +impl SizeHint for T { #[inline] default fn lower_bound(&self) -> usize { 0 diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index 16c8e0c0ebfc..81b081e0070e 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -466,7 +466,7 @@ impl CopyRead for Take { } } -impl CopyRead for BufReader { +impl CopyRead for BufReader { fn drain_to(&mut self, writer: &mut W, outer_limit: u64) -> Result { let buf = self.buffer(); let buf = &buf[0..min(buf.len(), outer_limit.try_into().unwrap_or(usize::MAX))]; From a49753373be6a4c23635d92c5fcebb60379d734f Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 1 May 2023 17:52:28 +0000 Subject: [PATCH 02/41] Relax implicit `W: Sized` bound on `BufWriter` --- library/std/src/io/buffered/bufwriter.rs | 138 ++++++++++++----------- library/std/src/io/copy.rs | 2 +- library/std/src/sys/unix/kernel_copy.rs | 2 +- 3 files changed, 72 insertions(+), 70 deletions(-) diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs index 14c455d4fa3c..0e2450655e5b 100644 --- a/library/std/src/io/buffered/bufwriter.rs +++ b/library/std/src/io/buffered/bufwriter.rs @@ -67,8 +67,7 @@ use crate::ptr; /// [`TcpStream`]: crate::net::TcpStream /// [`flush`]: BufWriter::flush #[stable(feature = "rust1", since = "1.0.0")] -pub struct BufWriter { - inner: W, +pub struct BufWriter { // The buffer. Avoid using this like a normal `Vec` in common code paths. // That is, don't use `buf.push`, `buf.extend_from_slice`, or any other // methods that require bounds checking or the like. This makes an enormous @@ -78,6 +77,7 @@ pub struct BufWriter { // write the buffered data a second time in BufWriter's destructor. This // flag tells the Drop impl if it should skip the flush. panicked: bool, + inner: W, } impl BufWriter { @@ -115,6 +115,69 @@ impl BufWriter { BufWriter { inner, buf: Vec::with_capacity(capacity), panicked: false } } + /// Unwraps this `BufWriter`, returning the underlying writer. + /// + /// The buffer is written out before returning the writer. + /// + /// # Errors + /// + /// An [`Err`] will be returned if an error occurs while flushing the buffer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufWriter; + /// use std::net::TcpStream; + /// + /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); + /// + /// // unwrap the TcpStream and flush the buffer + /// let stream = buffer.into_inner().unwrap(); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_inner(mut self) -> Result>> { + match self.flush_buf() { + Err(e) => Err(IntoInnerError::new(self, e)), + Ok(()) => Ok(self.into_parts().0), + } + } + + /// Disassembles this `BufWriter`, returning the underlying writer, and any buffered but + /// unwritten data. + /// + /// If the underlying writer panicked, it is not known what portion of the data was written. + /// In this case, we return `WriterPanicked` for the buffered data (from which the buffer + /// contents can still be recovered). + /// + /// `into_parts` makes no attempt to flush data and cannot fail. + /// + /// # Examples + /// + /// ``` + /// use std::io::{BufWriter, Write}; + /// + /// let mut buffer = [0u8; 10]; + /// let mut stream = BufWriter::new(buffer.as_mut()); + /// write!(stream, "too much data").unwrap(); + /// stream.flush().expect_err("it doesn't fit"); + /// let (recovered_writer, buffered_data) = stream.into_parts(); + /// assert_eq!(recovered_writer.len(), 0); + /// assert_eq!(&buffered_data.unwrap(), b"ata"); + /// ``` + #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] + pub fn into_parts(mut self) -> (W, Result, WriterPanicked>) { + let buf = mem::take(&mut self.buf); + let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; + + // SAFETY: forget(self) prevents double dropping inner + let inner = unsafe { ptr::read(&self.inner) }; + mem::forget(self); + + (inner, buf) + } +} + +impl BufWriter { /// Send data in our local buffer into the inner writer, looping as /// necessary until either it's all been sent or an error occurs. /// @@ -284,67 +347,6 @@ impl BufWriter { self.buf.capacity() } - /// Unwraps this `BufWriter`, returning the underlying writer. - /// - /// The buffer is written out before returning the writer. - /// - /// # Errors - /// - /// An [`Err`] will be returned if an error occurs while flushing the buffer. - /// - /// # Examples - /// - /// ```no_run - /// use std::io::BufWriter; - /// use std::net::TcpStream; - /// - /// let mut buffer = BufWriter::new(TcpStream::connect("127.0.0.1:34254").unwrap()); - /// - /// // unwrap the TcpStream and flush the buffer - /// let stream = buffer.into_inner().unwrap(); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn into_inner(mut self) -> Result>> { - match self.flush_buf() { - Err(e) => Err(IntoInnerError::new(self, e)), - Ok(()) => Ok(self.into_parts().0), - } - } - - /// Disassembles this `BufWriter`, returning the underlying writer, and any buffered but - /// unwritten data. - /// - /// If the underlying writer panicked, it is not known what portion of the data was written. - /// In this case, we return `WriterPanicked` for the buffered data (from which the buffer - /// contents can still be recovered). - /// - /// `into_parts` makes no attempt to flush data and cannot fail. - /// - /// # Examples - /// - /// ``` - /// use std::io::{BufWriter, Write}; - /// - /// let mut buffer = [0u8; 10]; - /// let mut stream = BufWriter::new(buffer.as_mut()); - /// write!(stream, "too much data").unwrap(); - /// stream.flush().expect_err("it doesn't fit"); - /// let (recovered_writer, buffered_data) = stream.into_parts(); - /// assert_eq!(recovered_writer.len(), 0); - /// assert_eq!(&buffered_data.unwrap(), b"ata"); - /// ``` - #[stable(feature = "bufwriter_into_parts", since = "1.56.0")] - pub fn into_parts(mut self) -> (W, Result, WriterPanicked>) { - let buf = mem::take(&mut self.buf); - let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) }; - - // SAFETY: forget(self) prevents double dropping inner - let inner = unsafe { ptr::read(&self.inner) }; - mem::forget(self); - - (inner, buf) - } - // Ensure this function does not get inlined into `write`, so that it // remains inlineable and its common path remains as short as possible. // If this function ends up being called frequently relative to `write`, @@ -511,7 +513,7 @@ impl fmt::Debug for WriterPanicked { } #[stable(feature = "rust1", since = "1.0.0")] -impl Write for BufWriter { +impl Write for BufWriter { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { // Use < instead of <= to avoid a needless trip through the buffer in some cases. @@ -640,20 +642,20 @@ impl Write for BufWriter { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for BufWriter +impl fmt::Debug for BufWriter where W: fmt::Debug, { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.debug_struct("BufWriter") - .field("writer", &self.inner) + .field("writer", &&self.inner) .field("buffer", &format_args!("{}/{}", self.buf.len(), self.buf.capacity())) .finish() } } #[stable(feature = "rust1", since = "1.0.0")] -impl Seek for BufWriter { +impl Seek for BufWriter { /// Seek to the offset, in bytes, in the underlying writer. /// /// Seeking always writes out the internal buffer before seeking. @@ -664,7 +666,7 @@ impl Seek for BufWriter { } #[stable(feature = "rust1", since = "1.0.0")] -impl Drop for BufWriter { +impl Drop for BufWriter { fn drop(&mut self) { if !self.panicked { // dtors should not panic, so we ignore a failed flush diff --git a/library/std/src/io/copy.rs b/library/std/src/io/copy.rs index 38b98afffa16..7c2a772774c1 100644 --- a/library/std/src/io/copy.rs +++ b/library/std/src/io/copy.rs @@ -86,7 +86,7 @@ impl BufferedCopySpec for W { } } -impl BufferedCopySpec for BufWriter { +impl BufferedCopySpec for BufWriter { fn copy_to(reader: &mut R, writer: &mut Self) -> Result { if writer.capacity() < DEFAULT_BUF_SIZE { return stack_buffer_copy(reader, writer); diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs index 81b081e0070e..7d49bbdcbe06 100644 --- a/library/std/src/sys/unix/kernel_copy.rs +++ b/library/std/src/sys/unix/kernel_copy.rs @@ -495,7 +495,7 @@ impl CopyRead for BufReader { } } -impl CopyWrite for BufWriter { +impl CopyWrite for BufWriter { fn properties(&self) -> CopyParams { self.get_ref().properties() } From 29302a204c1f5a1ac1c114cbdb17c32a24da8367 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 1 May 2023 18:01:04 +0000 Subject: [PATCH 03/41] Relax implicit `W: Sized` bound on `LineWriter` --- library/std/src/io/buffered/linewriter.rs | 50 ++++++++++--------- library/std/src/io/buffered/linewritershim.rs | 6 +-- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/library/std/src/io/buffered/linewriter.rs b/library/std/src/io/buffered/linewriter.rs index a26a4ab330e7..3d4ae7041932 100644 --- a/library/std/src/io/buffered/linewriter.rs +++ b/library/std/src/io/buffered/linewriter.rs @@ -64,7 +64,7 @@ use crate::io::{self, buffered::LineWriterShim, BufWriter, IntoInnerError, IoSli /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub struct LineWriter { +pub struct LineWriter { inner: BufWriter, } @@ -109,27 +109,6 @@ impl LineWriter { LineWriter { inner: BufWriter::with_capacity(capacity, inner) } } - /// Gets a reference to the underlying writer. - /// - /// # Examples - /// - /// ```no_run - /// use std::fs::File; - /// use std::io::LineWriter; - /// - /// fn main() -> std::io::Result<()> { - /// let file = File::create("poem.txt")?; - /// let file = LineWriter::new(file); - /// - /// let reference = file.get_ref(); - /// Ok(()) - /// } - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn get_ref(&self) -> &W { - self.inner.get_ref() - } - /// Gets a mutable reference to the underlying writer. /// /// Caution must be taken when calling methods on the mutable reference @@ -184,8 +163,31 @@ impl LineWriter { } } +impl LineWriter { + /// Gets a reference to the underlying writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs::File; + /// use std::io::LineWriter; + /// + /// fn main() -> std::io::Result<()> { + /// let file = File::create("poem.txt")?; + /// let file = LineWriter::new(file); + /// + /// let reference = file.get_ref(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get_ref(&self) -> &W { + self.inner.get_ref() + } +} + #[stable(feature = "rust1", since = "1.0.0")] -impl Write for LineWriter { +impl Write for LineWriter { fn write(&mut self, buf: &[u8]) -> io::Result { LineWriterShim::new(&mut self.inner).write(buf) } @@ -216,7 +218,7 @@ impl Write for LineWriter { } #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for LineWriter +impl fmt::Debug for LineWriter where W: fmt::Debug, { diff --git a/library/std/src/io/buffered/linewritershim.rs b/library/std/src/io/buffered/linewritershim.rs index 0175d2693e89..f2a55da05b22 100644 --- a/library/std/src/io/buffered/linewritershim.rs +++ b/library/std/src/io/buffered/linewritershim.rs @@ -11,11 +11,11 @@ use crate::sys_common::memchr; /// `BufWriters` to be temporarily given line-buffering logic; this is what /// enables Stdout to be alternately in line-buffered or block-buffered mode. #[derive(Debug)] -pub struct LineWriterShim<'a, W: Write> { +pub struct LineWriterShim<'a, W: ?Sized + Write> { buffer: &'a mut BufWriter, } -impl<'a, W: Write> LineWriterShim<'a, W> { +impl<'a, W: ?Sized + Write> LineWriterShim<'a, W> { pub fn new(buffer: &'a mut BufWriter) -> Self { Self { buffer } } @@ -49,7 +49,7 @@ impl<'a, W: Write> LineWriterShim<'a, W> { } } -impl<'a, W: Write> Write for LineWriterShim<'a, W> { +impl<'a, W: ?Sized + Write> Write for LineWriterShim<'a, W> { /// Write some data into this BufReader with line buffering. This means /// that, if any newlines are present in the data, the data up to the last /// newline is sent directly to the underlying writer, and data after it From 741d210c44bc637a30dd1e4675848c1c2aae5952 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 22 Apr 2023 16:00:20 +0200 Subject: [PATCH 04/41] Add search result item types after their name --- src/librustdoc/html/static/css/rustdoc.css | 4 +- src/librustdoc/html/static/js/search.js | 43 +++++++++++++++++----- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 054cfe7597ea..b487cfa5c255 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -213,7 +213,7 @@ a.anchor, h1 a, .search-results a, .stab, -.result-name .primitive > i, .result-name .keyword > i { +.result-name i { color: var(--main-color); } @@ -887,7 +887,7 @@ so that we can apply CSS-filters to change the arrow color in themes */ .search-results .result-name span.alias { color: var(--search-results-alias-color); } -.search-results .result-name span.grey { +.search-results .result-name .grey { color: var(--search-results-grey-color); } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index 62afe40bb315..f65d39151241 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -35,6 +35,35 @@ const itemTypes = [ "traitalias", ]; +const longItemTypes = [ + "module", + "extern crate", + "re-export", + "struct", + "enum", + "function", + "type alias", + "static", + "trait", + "", + "trait method", + "method", + "struct field", + "enum variant", + "macro", + "primitive type", + "associated type", + "constant", + "associated constant", + "union", + "foreign type", + "keyword", + "existential type", + "attribute macro", + "derive macro", + "trait alias", +]; + // used for special search precedence const TY_PRIMITIVE = itemTypes.indexOf("primitive"); const TY_KEYWORD = itemTypes.indexOf("keyword"); @@ -1836,16 +1865,11 @@ function initSearch(rawSearchIndex) { array.forEach(item => { const name = item.name; const type = itemTypes[item.ty]; + const longType = longItemTypes[item.ty]; + let extra = longType.length !== 0 ? ` (${longType})` : ""; length += 1; - let extra = ""; - if (type === "primitive") { - extra = " (primitive type)"; - } else if (type === "keyword") { - extra = " (keyword)"; - } - const link = document.createElement("a"); link.className = "result-" + type; link.href = item.href; @@ -1854,6 +1878,7 @@ function initSearch(rawSearchIndex) { resultName.className = "result-name"; if (item.is_alias) { + extra = ""; const alias = document.createElement("span"); alias.className = "alias"; @@ -1863,13 +1888,13 @@ function initSearch(rawSearchIndex) { alias.insertAdjacentHTML( "beforeend", - " - see "); + " - see "); resultName.appendChild(alias); } resultName.insertAdjacentHTML( "beforeend", - item.displayPath + "" + name + extra + ""); + item.displayPath + "" + name + "" + extra); link.appendChild(resultName); const description = document.createElement("div"); From 7a09a688de6f1565fe1608eaaaee5ff4fe0c3a6d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 22 Apr 2023 16:00:29 +0200 Subject: [PATCH 05/41] Update rustdoc tests and add more checks for type kind colors --- tests/rustdoc-gui/search-reexport.goml | 2 +- tests/rustdoc-gui/search-result-color.goml | 14 +++++++++++--- tests/rustdoc-gui/search-result-keyword.goml | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/tests/rustdoc-gui/search-reexport.goml b/tests/rustdoc-gui/search-reexport.goml index fd817b58990c..06a0dc949c4e 100644 --- a/tests/rustdoc-gui/search-reexport.goml +++ b/tests/rustdoc-gui/search-reexport.goml @@ -14,7 +14,7 @@ assert-attribute: ( "//a[@class='result-import']", {"href": "../test_docs/index.html#reexport.TheStdReexport"}, ) -assert-text: ("//a[@class='result-import']", "test_docs::TheStdReexport") +assert-text: ("//a[@class='result-import']", "test_docs::TheStdReexport (re-export)") click: "//a[@class='result-import']" // We check that it has the background modified thanks to the focus. wait-for-css: ("//*[@id='reexport.TheStdReexport']", {"background-color": "rgb(73, 74, 61)"}) diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index 90f7160b7249..b0d236ce1e5d 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -5,6 +5,7 @@ define-function: ( (result_kind, color, hover_color), block { assert-css: (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL) + assert-css: (".result-" + |result_kind| + " i", {"color": |default_color|}) assert-css: ( ".result-" + |result_kind|, {"color": |entry_color|, "background-color": |background_color|}, @@ -18,6 +19,7 @@ define-function: ( ".result-" + |result_kind| + ":hover ." + |result_kind|, {"color": |hover_color|}, ) + assert-css: (".result-" + |result_kind| + ":hover i", {"color": |default_color|}) move-cursor-to: ".search-input" focus: ".result-" + |result_kind| assert-css: ( @@ -65,10 +67,12 @@ assert-css: ( {"border-bottom-color": "#aaa3"} ) +store-value: (default_color, "rgb(197, 197, 197)") + // Checking the color of "keyword" text. assert-css: ( "//*[@class='result-name']//*[text()='(keyword)']", - {"color": "#788797"}, + {"color": |default_color|}, ) store-value: (entry_color, "#0096cf") // color of the search entry @@ -182,10 +186,12 @@ assert-css: ( {"border-bottom-color": "#aaa3"} ) +store-value: (default_color, "rgb(221, 221, 221)") + // Checking the color for "keyword" text. assert-css: ( "//*[@class='result-name']//*[text()='(keyword)']", - {"color": "#ddd"}, + {"color": |default_color|}, ) store-value: (entry_color, "#ddd") // color of the search entry @@ -284,10 +290,12 @@ assert-css: ( {"border-bottom-color": "#aaa3"} ) +store-value: (default_color, "rgb(0, 0, 0)") + // Checking the color for "keyword" text. assert-css: ( "//*[@class='result-name']//*[text()='(keyword)']", - {"color": "#000"}, + {"color": |default_color|}, ) store-value: (entry_color, "#000") // color of the search entry diff --git a/tests/rustdoc-gui/search-result-keyword.goml b/tests/rustdoc-gui/search-result-keyword.goml index 5d56e9d9cd42..8d6478e28a5b 100644 --- a/tests/rustdoc-gui/search-result-keyword.goml +++ b/tests/rustdoc-gui/search-result-keyword.goml @@ -9,5 +9,5 @@ wait-for: "#search-tabs" // less good. // // Checking that the CSS is displaying " (keyword)" in italic. -assert-text: (".result-name span.keyword > i", "(keyword)") -assert-text: (".result-name span.keyword", "CookieMonster (keyword)") +assert-text: (".result-keyword span.keyword + i", "(keyword)") +assert-text: (".result-keyword .result-name", "CookieMonster (keyword)") From 8a35cc3ddc5b18303d67d0455fa1a8fa88ca0af8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 18 May 2023 16:16:13 +0200 Subject: [PATCH 06/41] Move item kind before the item name --- src/librustdoc/html/static/css/rustdoc.css | 5 ++++ src/librustdoc/html/static/js/search.js | 11 +++++--- tests/rustdoc-gui/search-reexport.goml | 5 ++-- tests/rustdoc-gui/search-result-color.goml | 28 ++------------------ tests/rustdoc-gui/search-result-display.goml | 4 +-- tests/rustdoc-gui/search-result-keyword.goml | 4 +-- 6 files changed, 22 insertions(+), 35 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index b487cfa5c255..d469b397dcfc 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -190,6 +190,7 @@ h1, h2, h3, h4, h5, h6, .mobile-topbar, .search-input, .search-results .result-name, +.search-results .type-kind, .item-name > a, .out-of-band, span.since, @@ -870,6 +871,10 @@ so that we can apply CSS-filters to change the arrow color in themes */ } .search-results > a > div { + flex: 3; +} + +.search-results > a > div.type-kind { flex: 1; } diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index f65d39151241..c25c36994fa4 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1866,7 +1866,7 @@ function initSearch(rawSearchIndex) { const name = item.name; const type = itemTypes[item.ty]; const longType = longItemTypes[item.ty]; - let extra = longType.length !== 0 ? ` (${longType})` : ""; + const typeName = longType.length !== 0 ? `${longType}` : "?"; length += 1; @@ -1878,7 +1878,6 @@ function initSearch(rawSearchIndex) { resultName.className = "result-name"; if (item.is_alias) { - extra = ""; const alias = document.createElement("span"); alias.className = "alias"; @@ -1892,9 +1891,15 @@ function initSearch(rawSearchIndex) { resultName.appendChild(alias); } + + const typeDisplay = document.createElement("div"); + typeDisplay.innerText = typeName; + typeDisplay.className = "type-kind"; + link.appendChild(typeDisplay); + resultName.insertAdjacentHTML( "beforeend", - item.displayPath + "" + name + "" + extra); + item.displayPath + "" + name + ""); link.appendChild(resultName); const description = document.createElement("div"); diff --git a/tests/rustdoc-gui/search-reexport.goml b/tests/rustdoc-gui/search-reexport.goml index 06a0dc949c4e..4f3ccd715994 100644 --- a/tests/rustdoc-gui/search-reexport.goml +++ b/tests/rustdoc-gui/search-reexport.goml @@ -14,7 +14,8 @@ assert-attribute: ( "//a[@class='result-import']", {"href": "../test_docs/index.html#reexport.TheStdReexport"}, ) -assert-text: ("//a[@class='result-import']", "test_docs::TheStdReexport (re-export)") +assert-text: ("a.result-import .result-name", "test_docs::TheStdReexport") +assert-text: ("a.result-import .type-kind", "re-export") click: "//a[@class='result-import']" // We check that it has the background modified thanks to the focus. wait-for-css: ("//*[@id='reexport.TheStdReexport']", {"background-color": "rgb(73, 74, 61)"}) @@ -25,7 +26,7 @@ press-key: 'Enter' write: (".search-input", "AliasForTheStdReexport") wait-for: "//a[@class='result-import']" assert-text: ( - "//a[@class='result-import']", + "a.result-import .result-name", "AliasForTheStdReexport - see test_docs::TheStdReexport", ) // Same thing again, we click on it to ensure the background is once again set as expected. diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index b0d236ce1e5d..5ae3125a7f18 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -5,7 +5,7 @@ define-function: ( (result_kind, color, hover_color), block { assert-css: (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL) - assert-css: (".result-" + |result_kind| + " i", {"color": |default_color|}) + assert-css: (".result-" + |result_kind| + " .type-kind", {"color": |entry_color|}) assert-css: ( ".result-" + |result_kind|, {"color": |entry_color|, "background-color": |background_color|}, @@ -19,7 +19,7 @@ define-function: ( ".result-" + |result_kind| + ":hover ." + |result_kind|, {"color": |hover_color|}, ) - assert-css: (".result-" + |result_kind| + ":hover i", {"color": |default_color|}) + assert-css: (".result-" + |result_kind| + ":hover .type-kind", {"color": |hover_entry_color|}) move-cursor-to: ".search-input" focus: ".result-" + |result_kind| assert-css: ( @@ -67,14 +67,6 @@ assert-css: ( {"border-bottom-color": "#aaa3"} ) -store-value: (default_color, "rgb(197, 197, 197)") - -// Checking the color of "keyword" text. -assert-css: ( - "//*[@class='result-name']//*[text()='(keyword)']", - {"color": |default_color|}, -) - store-value: (entry_color, "#0096cf") // color of the search entry store-value: (hover_entry_color, "#fff") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color @@ -186,14 +178,6 @@ assert-css: ( {"border-bottom-color": "#aaa3"} ) -store-value: (default_color, "rgb(221, 221, 221)") - -// Checking the color for "keyword" text. -assert-css: ( - "//*[@class='result-name']//*[text()='(keyword)']", - {"color": |default_color|}, -) - store-value: (entry_color, "#ddd") // color of the search entry store-value: (hover_entry_color, "#ddd") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color @@ -290,14 +274,6 @@ assert-css: ( {"border-bottom-color": "#aaa3"} ) -store-value: (default_color, "rgb(0, 0, 0)") - -// Checking the color for "keyword" text. -assert-css: ( - "//*[@class='result-name']//*[text()='(keyword)']", - {"color": |default_color|}, -) - store-value: (entry_color, "#000") // color of the search entry store-value: (hover_entry_color, "#000") // color of the hovered/focused search entry store-value: (background_color, "transparent") // background color diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml index bf096f62c483..08c43b4899cd 100644 --- a/tests/rustdoc-gui/search-result-display.goml +++ b/tests/rustdoc-gui/search-result-display.goml @@ -7,11 +7,11 @@ press-key: 'Enter' wait-for: "#crate-search" // The width is returned by "getComputedStyle" which returns the exact number instead of the // CSS rule which is "50%"... -assert-css: (".search-results div.desc", {"width": "310px"}) +assert-size: (".search-results div.desc", {"width": 259}) set-window-size: (600, 100) // As counter-intuitive as it may seem, in this width, the width is "100%", which is why // when computed it's larger. -assert-css: (".search-results div.desc", {"width": "566px"}) +assert-size: (".search-results div.desc", {"width": 566}) // The result set is all on one line. assert-css: (".search-results .result-name > span", {"display": "inline"}) diff --git a/tests/rustdoc-gui/search-result-keyword.goml b/tests/rustdoc-gui/search-result-keyword.goml index 8d6478e28a5b..3326f5b72f4d 100644 --- a/tests/rustdoc-gui/search-result-keyword.goml +++ b/tests/rustdoc-gui/search-result-keyword.goml @@ -9,5 +9,5 @@ wait-for: "#search-tabs" // less good. // // Checking that the CSS is displaying " (keyword)" in italic. -assert-text: (".result-keyword span.keyword + i", "(keyword)") -assert-text: (".result-keyword .result-name", "CookieMonster (keyword)") +assert-text: (".result-keyword .type-kind", "keyword") +assert-text: (".result-keyword .result-name", "CookieMonster") From f92cd677114d76d78c73177d21184c83a087a6b6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 23 May 2023 13:41:59 +0200 Subject: [PATCH 07/41] Improve new search result display on mobile --- src/librustdoc/html/static/css/rustdoc.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d469b397dcfc..167319ba9bd7 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1722,6 +1722,14 @@ in source-script.js display: block; } + .search-results > a > .type-kind { + display: inline-block; + } + .search-results > a > .result-name { + display: inline-block; + margin-left: 7px; + } + /* Display an alternating layout on tablets and phones */ .search-results > a { padding: 5px 0px; From de85f7ff363a80ab0eefc6909edc24b5c99880c4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 3 Jun 2023 16:22:19 +0200 Subject: [PATCH 08/41] Move type name directly into the same DOM element --- src/librustdoc/html/static/css/rustdoc.css | 13 ------------- src/librustdoc/html/static/js/search.js | 7 +------ tests/rustdoc-gui/search-reexport.goml | 5 ++--- tests/rustdoc-gui/search-result-color.goml | 2 -- tests/rustdoc-gui/search-result-display.goml | 2 +- tests/rustdoc-gui/search-result-keyword.goml | 7 +------ 6 files changed, 5 insertions(+), 31 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 167319ba9bd7..b487cfa5c255 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -190,7 +190,6 @@ h1, h2, h3, h4, h5, h6, .mobile-topbar, .search-input, .search-results .result-name, -.search-results .type-kind, .item-name > a, .out-of-band, span.since, @@ -871,10 +870,6 @@ so that we can apply CSS-filters to change the arrow color in themes */ } .search-results > a > div { - flex: 3; -} - -.search-results > a > div.type-kind { flex: 1; } @@ -1722,14 +1717,6 @@ in source-script.js display: block; } - .search-results > a > .type-kind { - display: inline-block; - } - .search-results > a > .result-name { - display: inline-block; - margin-left: 7px; - } - /* Display an alternating layout on tablets and phones */ .search-results > a { padding: 5px 0px; diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js index c25c36994fa4..eff8aa79caf9 100644 --- a/src/librustdoc/html/static/js/search.js +++ b/src/librustdoc/html/static/js/search.js @@ -1892,14 +1892,9 @@ function initSearch(rawSearchIndex) { resultName.appendChild(alias); } - const typeDisplay = document.createElement("div"); - typeDisplay.innerText = typeName; - typeDisplay.className = "type-kind"; - link.appendChild(typeDisplay); - resultName.insertAdjacentHTML( "beforeend", - item.displayPath + "" + name + ""); + `${typeName} ${item.displayPath}${name}`); link.appendChild(resultName); const description = document.createElement("div"); diff --git a/tests/rustdoc-gui/search-reexport.goml b/tests/rustdoc-gui/search-reexport.goml index 4f3ccd715994..0ce4e99339fb 100644 --- a/tests/rustdoc-gui/search-reexport.goml +++ b/tests/rustdoc-gui/search-reexport.goml @@ -14,8 +14,7 @@ assert-attribute: ( "//a[@class='result-import']", {"href": "../test_docs/index.html#reexport.TheStdReexport"}, ) -assert-text: ("a.result-import .result-name", "test_docs::TheStdReexport") -assert-text: ("a.result-import .type-kind", "re-export") +assert-text: ("a.result-import .result-name", "re-export test_docs::TheStdReexport") click: "//a[@class='result-import']" // We check that it has the background modified thanks to the focus. wait-for-css: ("//*[@id='reexport.TheStdReexport']", {"background-color": "rgb(73, 74, 61)"}) @@ -27,7 +26,7 @@ write: (".search-input", "AliasForTheStdReexport") wait-for: "//a[@class='result-import']" assert-text: ( "a.result-import .result-name", - "AliasForTheStdReexport - see test_docs::TheStdReexport", + "AliasForTheStdReexport - see re-export test_docs::TheStdReexport", ) // Same thing again, we click on it to ensure the background is once again set as expected. click: "//a[@class='result-import']" diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index 5ae3125a7f18..c75e4141434e 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -5,7 +5,6 @@ define-function: ( (result_kind, color, hover_color), block { assert-css: (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL) - assert-css: (".result-" + |result_kind| + " .type-kind", {"color": |entry_color|}) assert-css: ( ".result-" + |result_kind|, {"color": |entry_color|, "background-color": |background_color|}, @@ -19,7 +18,6 @@ define-function: ( ".result-" + |result_kind| + ":hover ." + |result_kind|, {"color": |hover_color|}, ) - assert-css: (".result-" + |result_kind| + ":hover .type-kind", {"color": |hover_entry_color|}) move-cursor-to: ".search-input" focus: ".result-" + |result_kind| assert-css: ( diff --git a/tests/rustdoc-gui/search-result-display.goml b/tests/rustdoc-gui/search-result-display.goml index 08c43b4899cd..afb3a44be303 100644 --- a/tests/rustdoc-gui/search-result-display.goml +++ b/tests/rustdoc-gui/search-result-display.goml @@ -7,7 +7,7 @@ press-key: 'Enter' wait-for: "#crate-search" // The width is returned by "getComputedStyle" which returns the exact number instead of the // CSS rule which is "50%"... -assert-size: (".search-results div.desc", {"width": 259}) +assert-size: (".search-results div.desc", {"width": 310}) set-window-size: (600, 100) // As counter-intuitive as it may seem, in this width, the width is "100%", which is why // when computed it's larger. diff --git a/tests/rustdoc-gui/search-result-keyword.goml b/tests/rustdoc-gui/search-result-keyword.goml index 3326f5b72f4d..1b2be6d4e3e2 100644 --- a/tests/rustdoc-gui/search-result-keyword.goml +++ b/tests/rustdoc-gui/search-result-keyword.goml @@ -5,9 +5,4 @@ write: (".search-input", "CookieMonster") press-key: 'Enter' // Waiting for the search results to appear... wait-for: "#search-tabs" -// Note: The two next assert commands could be merged as one but readability would be -// less good. -// -// Checking that the CSS is displaying " (keyword)" in italic. -assert-text: (".result-keyword .type-kind", "keyword") -assert-text: (".result-keyword .result-name", "CookieMonster") +assert-text: (".result-keyword .result-name", "keyword CookieMonster") From 25b3751fd1585e3ce8d9806cc197f6c60f95b367 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 2 Jun 2023 22:18:11 +0100 Subject: [PATCH 09/41] std: available_parallelism using native netbsd api first before falling back to existing code paths like FreeBSD does. --- library/std/src/sys/unix/thread.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 878af5088d9f..010015667f7a 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -344,6 +344,29 @@ pub fn available_parallelism() -> io::Result { } } + #[cfg(target_os = "netbsd")] + { + unsafe { + let set = libc::_cpuset_create(); + if !set.is_null() { + let mut count: usize = 0; + if libc::pthread_getaffinity_np(libc::pthread_self(), libc::_cpuset_size(set), set) == 0 { + for i in 0..u64::MAX { + match libc::_cpuset_isset(i, set) { + -1 => break, + 0 => continue, + _ => count = count + 1, + } + } + } + libc::_cpuset_destroy(set); + if let Some(count) = NonZeroUsize::new(count) { + return Ok(count); + } + } + } + } + let mut cpus: libc::c_uint = 0; let mut cpus_size = crate::mem::size_of_val(&cpus); From e3b499fd655083dcbe02a3504cddf1b913327418 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 Jun 2023 03:47:56 +0000 Subject: [PATCH 10/41] Instantiate closure synthetic substs in root universe --- compiler/rustc_hir_typeck/src/closure.rs | 4 ++-- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 4 ++++ tests/ui/traits/new-solver/closure-substs-ambiguity.rs | 7 +++++++ 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/new-solver/closure-substs-ambiguity.rs diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 9659a0ec13d4..dce426ca2db6 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -98,7 +98,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.typeck_root_def_id(expr_def_id.to_def_id()), ); - let tupled_upvars_ty = self.next_ty_var(TypeVariableOrigin { + let tupled_upvars_ty = self.next_root_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::ClosureSynthetic, span: self.tcx.def_span(expr_def_id), }); @@ -143,7 +143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Create a type variable (for now) to represent the closure kind. // It will be unified during the upvar inference phase (`upvar.rs`) - None => self.next_ty_var(TypeVariableOrigin { + None => self.next_root_ty_var(TypeVariableOrigin { // FIXME(eddyb) distinguish closure kind inference variables from the rest. kind: TypeVariableOriginKind::ClosureSynthetic, span: expr_span, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 67f45f9aa3f0..630878bbf0c6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -189,6 +189,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn errors_reported_since_creation(&self) -> bool { self.tcx.sess.err_count() > self.err_count_on_creation } + + pub fn next_root_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { + self.tcx.mk_ty_var(self.next_ty_var_id_in_universe(origin, ty::UniverseIndex::ROOT)) + } } impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { diff --git a/tests/ui/traits/new-solver/closure-substs-ambiguity.rs b/tests/ui/traits/new-solver/closure-substs-ambiguity.rs new file mode 100644 index 000000000000..48432f4020f8 --- /dev/null +++ b/tests/ui/traits/new-solver/closure-substs-ambiguity.rs @@ -0,0 +1,7 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +fn main() { + let mut x: Vec<_> = vec![]; + x.extend(Some(1i32).into_iter().map(|x| x)); +} From 204bfb6a8c1f9aaa9b5c04d72a47f7fd8772a4bb Mon Sep 17 00:00:00 2001 From: DonoughLiu Date: Sat, 10 Jun 2023 03:21:39 +0800 Subject: [PATCH 11/41] Support 128-bit enum variant in debuginfo codegen --- compiler/rustc_codegen_gcc/src/common.rs | 6 +++++- compiler/rustc_codegen_llvm/src/common.rs | 4 ++++ compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | 2 +- .../src/debuginfo/metadata/enums/native.rs | 8 +------- compiler/rustc_codegen_ssa/src/traits/consts.rs | 1 + 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index bad87db47323..b62f4676f70b 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -108,6 +108,10 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { self.const_uint(self.type_u64(), i) } + fn const_u128(&self, i: u128) -> RValue<'gcc> { + self.const_uint_big(self.type_u128(), i) + } + fn const_usize(&self, i: u64) -> RValue<'gcc> { let bit_size = self.data_layout().pointer_size.bits(); if bit_size < 64 { @@ -254,7 +258,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // SIMD builtins require a constant value. self.bitcast_if_needed(value, typ) } - + fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value { self.context.new_array_access(None, base_addr, self.const_usize(offset.bytes())).get_address(None) } diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index a3910fef9549..a2db59bd6c47 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -168,6 +168,10 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { self.const_uint(self.type_i64(), i) } + fn const_u128(&self, i: u128) -> &'ll Value { + self.const_uint_big(self.type_i128(), i) + } + fn const_usize(&self, i: u64) -> &'ll Value { let bit_size = self.data_layout().pointer_size.bits(); if bit_size < 64 { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 166454d3ae74..bede63373b1b 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -429,7 +429,7 @@ pub fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll D return existing_di_node; } - debug!("type_di_node: {:?}", t); + debug!("type_di_node: {:?} kind: {:?}", t, t.kind()); let DINodeCreationResult { di_node, already_stored_in_typemap } = match *t.kind() { ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs index 978141917c6b..666b9762f5a7 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs @@ -412,13 +412,7 @@ fn build_enum_variant_member_di_node<'ll, 'tcx>( enum_type_and_layout.size.bits(), enum_type_and_layout.align.abi.bits() as u32, Size::ZERO.bits(), - discr_value.opt_single_val().map(|value| { - // NOTE(eddyb) do *NOT* remove this assert, until - // we pass the full 128-bit value to LLVM, otherwise - // truncation will be silent and remain undetected. - assert_eq!(value as u64 as u128, value); - cx.const_u64(value as u64) - }), + discr_value.opt_single_val().map(|value| cx.const_u128(value)), DIFlags::FlagZero, variant_member_info.variant_struct_type_di_node, ) diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index dc2fc3964801..d6e9bfce1a4f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -15,6 +15,7 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_i32(&self, i: i32) -> Self::Value; fn const_u32(&self, i: u32) -> Self::Value; fn const_u64(&self, i: u64) -> Self::Value; + fn const_u128(&self, i: u128) -> Self::Value; fn const_usize(&self, i: u64) -> Self::Value; fn const_u8(&self, i: u8) -> Self::Value; fn const_real(&self, t: Self::Type, val: f64) -> Self::Value; From 859bac7af8705f610ae8aa5c7df17398a46c0cdf Mon Sep 17 00:00:00 2001 From: ldm0 Date: Sat, 10 Jun 2023 08:31:06 +0000 Subject: [PATCH 12/41] Fix codegen tests --- tests/codegen/enum-debug-niche-2.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/codegen/enum-debug-niche-2.rs b/tests/codegen/enum-debug-niche-2.rs index 9c72ad9d248a..4b607d505745 100644 --- a/tests/codegen/enum-debug-niche-2.rs +++ b/tests/codegen/enum-debug-niche-2.rs @@ -7,8 +7,8 @@ // compile-flags: -g -C no-prepopulate-passes // CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}size: 32,{{.*}} -// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Placeholder",{{.*}}extraData: i64 4294967295{{[,)].*}} -// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i64 0{{[,)].*}} +// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Placeholder",{{.*}}extraData: i128 4294967295{{[,)].*}} +// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i128 0{{[,)].*}} #![feature(never_type)] From ea19243d15de0d15bdeee6f82c27366477d7a043 Mon Sep 17 00:00:00 2001 From: ldm0 Date: Sat, 10 Jun 2023 16:58:51 +0000 Subject: [PATCH 13/41] Add test --- tests/codegen/enum-u128.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/codegen/enum-u128.rs diff --git a/tests/codegen/enum-u128.rs b/tests/codegen/enum-u128.rs new file mode 100644 index 000000000000..f50d360ac9f3 --- /dev/null +++ b/tests/codegen/enum-u128.rs @@ -0,0 +1,27 @@ +// This tests that debug info for "c-like" 128bit enums is properly emitted. +// This is ignored for the fallback mode on MSVC due to problems with PDB. + +// +// ignore-msvc + +// compile-flags: -g -C no-prepopulate-passes + +// CHECK-LABEL: @main +// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_enumeration_type,{{.*}}name: "Foo",{{.*}}flags: DIFlagEnumClass,{{.*}} +// CHECK: {{.*}}DIEnumerator{{.*}}name: "Lo",{{.*}}value: 0,{{.*}} +// CHECK: {{.*}}DIEnumerator{{.*}}name: "Hi",{{.*}}value: 18446744073709551616,{{.*}} +// CHECK: {{.*}}DIEnumerator{{.*}}name: "Bar",{{.*}}value: 18446745000000000123,{{.*}} + +#![allow(incomplete_features)] +#![feature(repr128)] + +#[repr(u128)] +pub enum Foo { + Lo, + Hi = 1 << 64, + Bar = 18_446_745_000_000_000_123, +} + +pub fn main() { + let foo = Foo::Bar; +} From 3b9b4e5e3d6b45be6d355f0685eb70d99c3ab50a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 11 Jun 2023 22:15:46 +0200 Subject: [PATCH 14/41] reorder attributes to make miri-test-libstd work again --- library/alloc/src/lib.rs | 10 +++++----- library/std/src/lib.rs | 13 +++++++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 59fa91c1066d..967ad3a0e690 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -56,6 +56,11 @@ //! [`Rc`]: rc //! [`RefCell`]: core::cell +// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be +// able to "empty" this crate. See . +// rustc itself never sets the feature, so this line has no affect there. +#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] +// #![allow(unused_attributes)] #![stable(feature = "alloc", since = "1.36.0")] #![doc( @@ -75,11 +80,6 @@ ))] #![no_std] #![needs_allocator] -// To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be -// able to "empty" this crate. See . -// rustc itself never sets the feature, so this line has no affect there. -#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] -// // Lints: #![deny(unsafe_op_in_unsafe_fn)] #![deny(fuzzy_provenance_casts)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d53f1a2b2fff..da08c018d0e3 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -188,6 +188,13 @@ //! [array]: prim@array //! [slice]: prim@slice +// To run std tests without x.py without ending up with two copies of std, Miri needs to be +// able to "empty" this crate. See . +// rustc itself never sets the feature, so this line has no affect there. +#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] +// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies. +#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))] +// #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))] #![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))] #![doc( @@ -202,12 +209,6 @@ no_global_oom_handling, not(no_global_oom_handling) ))] -// To run std tests without x.py without ending up with two copies of std, Miri needs to be -// able to "empty" this crate. See . -// rustc itself never sets the feature, so this line has no affect there. -#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))] -// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies. -#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))] // Don't link to std. We are std. #![no_std] // Tell the compiler to link to either panic_abort or panic_unwind From 696b0dd472d42c7e71c992bd2e3def2d40fadebb Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 7 Jun 2023 19:20:39 -0400 Subject: [PATCH 15/41] Publish docs as github artifacts during CI This PR saves library docs as github artifacts so they can be easily viewed for review. Discussed in --- .github/workflows/ci.yml | 36 ++++++++++++++++ .../docker/host-x86_64/mingw-check/Dockerfile | 3 ++ src/ci/github-actions/ci.yml | 16 +++++++ src/ci/scripts/create-doc-artifacts.sh | 42 +++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100755 src/ci/scripts/create-doc-artifacts.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 210ec72a11e0..ecc30901c7a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,7 @@ jobs: env: CI_JOB_NAME: "${{ matrix.name }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" SCCACHE_BUCKET: rust-lang-ci-sccache2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" CACHE_DOMAIN: ci-caches.rust-lang.org @@ -143,6 +144,17 @@ jobs: AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" if: success() && !env.SKIP_JOB + - name: create github artifacts + run: src/ci/scripts/create-doc-artifacts.sh + if: success() && !env.SKIP_JOB + - name: upload artifacts to github + uses: actions/upload-artifact@v3 + with: + name: "${{ env.DOC_ARTIFACT_NAME }}" + path: obj/artifacts/doc + if-no-files-found: ignore + retention-days: 5 + if: success() && !env.SKIP_JOB - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh env: @@ -156,6 +168,7 @@ jobs: env: CI_JOB_NAME: "${{ matrix.name }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" SCCACHE_BUCKET: rust-lang-ci-sccache2 DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" @@ -567,6 +580,17 @@ jobs: AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" if: success() && !env.SKIP_JOB + - name: create github artifacts + run: src/ci/scripts/create-doc-artifacts.sh + if: success() && !env.SKIP_JOB + - name: upload artifacts to github + uses: actions/upload-artifact@v3 + with: + name: "${{ env.DOC_ARTIFACT_NAME }}" + path: obj/artifacts/doc + if-no-files-found: ignore + retention-days: 5 + if: success() && !env.SKIP_JOB - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh env: @@ -581,6 +605,7 @@ jobs: DIST_TRY_BUILD: 1 CI_JOB_NAME: "${{ matrix.name }}" CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + HEAD_SHA: "${{ github.event.pull_request.head.sha || github.sha }}" SCCACHE_BUCKET: rust-lang-ci-sccache2 DEPLOY_BUCKET: rust-lang-ci2 TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" @@ -682,6 +707,17 @@ jobs: AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}" TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}" if: success() && !env.SKIP_JOB + - name: create github artifacts + run: src/ci/scripts/create-doc-artifacts.sh + if: success() && !env.SKIP_JOB + - name: upload artifacts to github + uses: actions/upload-artifact@v3 + with: + name: "${{ env.DOC_ARTIFACT_NAME }}" + path: obj/artifacts/doc + if-no-files-found: ignore + retention-days: 5 + if: success() && !env.SKIP_JOB - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh env: diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile index 515890aef8df..85a9a5d33752 100644 --- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile +++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile @@ -45,6 +45,9 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \ python3 ../x.py test --stage 0 src/tools/compiletest && \ python3 ../x.py test --stage 0 core alloc std test proc_macro && \ # Build both public and internal documentation. + RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library && \ + mkdir -p /checkout/obj/staging/doc && \ + cp -r build/x86_64-unknown-linux-gnu/doc /checkout/obj/staging && \ RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 compiler && \ RUSTDOCFLAGS=\"--document-private-items --document-hidden-items\" python3 ../x.py doc --stage 0 library/test && \ /scripts/validate-toolstate.sh && \ diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index d3cb6b6ed522..f8986bbc108c 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -34,6 +34,8 @@ x--expand-yaml-anchors--remove: - &shared-ci-variables CI_JOB_NAME: ${{ matrix.name }} CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + # commit of PR sha or commit sha. `GITHUB_SHA` is not accurate for PRs. + HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }} - &public-variables SCCACHE_BUCKET: rust-lang-ci-sccache2 @@ -229,6 +231,20 @@ x--expand-yaml-anchors--remove: TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }} <<: *step + - name: create github artifacts + run: src/ci/scripts/create-doc-artifacts.sh + <<: *step + + - name: upload artifacts to github + uses: actions/upload-artifact@v3 + with: + # name is set in previous step + name: ${{ env.DOC_ARTIFACT_NAME }} + path: obj/artifacts/doc + if-no-files-found: ignore + retention-days: 5 + <<: *step + - name: upload artifacts to S3 run: src/ci/scripts/upload-artifacts.sh env: diff --git a/src/ci/scripts/create-doc-artifacts.sh b/src/ci/scripts/create-doc-artifacts.sh new file mode 100755 index 000000000000..2516b0d85059 --- /dev/null +++ b/src/ci/scripts/create-doc-artifacts.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Compress doc artifacts and name them based on the commit, or the date if +# commit is not available. + +set -euox pipefail + +# Try to get short commit hash, fallback to date +if [ -n "$HEAD_SHA" ]; then + short_rev=$(echo "${HEAD_SHA}" | cut -c1-8) +else + short_rev=$(git rev-parse --short HEAD || date -u +'%Y-%m-%dT%H%M%SZ') +fi + +# Try to get branch, fallback to none +branch=$(git branch --show-current || echo) + +if [ -n "$branch" ]; then + branch="${branch}-" +fi + +if [ "${GITHUB_EVENT_NAME:=none}" = "pull_request" ]; then + pr_num=$(echo "$GITHUB_REF_NAME" | cut -d'/' -f1) + name="doc-${pr_num}-${short_rev}" +else + name="doc-${branch}${short_rev}" +fi + + +if [ -d "obj/staging/doc" ]; then + mkdir -p obj/artifacts/doc + + # Level 12 seems to give a good tradeoff of time vs. space savings + ZSTD_CLEVEL=12 ZSTD_NBTHREADS=4 \ + tar --zstd -cf "obj/artifacts/doc/${name}.tar.zst" -C obj/staging/doc . + + ls -lh obj/artifacts/doc +fi + +# Set this environment variable for future use if running in CI +if [ -n "$GITHUB_ENV" ]; then + echo "DOC_ARTIFACT_NAME=${name}" >> "$GITHUB_ENV" +fi From 513f28db0a540725bc41f080a0f52973af67c3db Mon Sep 17 00:00:00 2001 From: MikaelUrankar Date: Tue, 13 Jun 2023 13:14:06 +0200 Subject: [PATCH 16/41] Fix building the documentation on FreeBSD. It fixes the following error: error[E0412]: cannot find type `sockcred2` in module `libc` --> library/std/src/os/unix/net/ancillary.rs:211:29 | 211 | pub struct SocketCred(libc::sockcred2); | ^^^^^^^^^ not found in `libc` --- library/std/src/os/unix/net/ancillary.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 7565fbc0d099..814f1c7c2838 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -17,6 +17,7 @@ mod libc { pub use libc::c_int; pub struct ucred; pub struct cmsghdr; + pub struct sockcred2; pub type pid_t = i32; pub type gid_t = u32; pub type uid_t = u32; From 01377e8064a5b3d987b177c16e18da4bffec03a4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 13 Jun 2023 22:10:51 +0000 Subject: [PATCH 17/41] opportunistically resolve regions --- compiler/rustc_middle/src/infer/canonical.rs | 41 +++++++++++++++---- .../src/solve/canonicalize.rs | 21 +++++++++- .../src/solve/eval_ctxt.rs | 5 ++- .../opportunistic-region-resolve.rs | 19 +++++++++ 4 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 tests/ui/traits/new-solver/opportunistic-region-resolve.rs diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 29dae67bfca7..1b19ed9ad148 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -82,15 +82,40 @@ impl CanonicalVarValues<'_> { } pub fn is_identity_modulo_regions(&self) -> bool { - self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() { - ty::GenericArgKind::Lifetime(_) => true, - ty::GenericArgKind::Type(ty) => { - matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv) + let mut var = ty::BoundVar::from_u32(0); + for arg in self.var_values { + match arg.unpack() { + ty::GenericArgKind::Lifetime(r) => { + if let ty::ReLateBound(ty::INNERMOST, br) = *r + && var == br.var + { + var = var + 1; + } else { + // It's ok if this region var isn't unique + } + }, + ty::GenericArgKind::Type(ty) => { + if let ty::Bound(ty::INNERMOST, bt) = *ty.kind() + && var == bt.var + { + var = var + 1; + } else { + return false; + } + } + ty::GenericArgKind::Const(ct) => { + if let ty::ConstKind::Bound(ty::INNERMOST, bc) = ct.kind() + && var == bc + { + var = var + 1; + } else { + return false; + } + } } - ty::GenericArgKind::Const(ct) => { - matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv) - } - }) + } + + true } } diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index 29bdb5ff67da..05248cb9d178 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -208,8 +208,25 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { t } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - let r = self.infcx.shallow_resolve(r); + fn fold_region(&mut self, mut r: ty::Region<'tcx>) -> ty::Region<'tcx> { + match self.canonicalize_mode { + CanonicalizeMode::Input => { + // Don't resolve infer vars in input, since it affects + // caching and may cause trait selection bugs which rely + // on regions to be equal. + } + CanonicalizeMode::Response { .. } => { + if let ty::ReVar(vid) = *r { + r = self + .infcx + .inner + .borrow_mut() + .unwrap_region_constraints() + .opportunistic_resolve_var(self.infcx.tcx, vid); + } + } + } + let kind = match *r { ty::ReLateBound(..) => return r, diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs index e01187bcd3c2..35fe38c5317d 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt.rs @@ -263,7 +263,10 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> { let (_orig_values, canonical_goal) = self.canonicalize_goal(goal); let new_canonical_response = EvalCtxt::evaluate_canonical_goal(self.tcx(), self.search_graph, canonical_goal)?; - if !new_canonical_response.value.var_values.is_identity() { + // We only check for modulo regions as we convert all regions in + // the input to new existentials, even if they're expected to be + // `'static` or a placeholder region. + if !new_canonical_response.value.var_values.is_identity_modulo_regions() { bug!( "unstable result: re-canonicalized goal={canonical_goal:#?} \ first_response={canonical_response:#?} \ diff --git a/tests/ui/traits/new-solver/opportunistic-region-resolve.rs b/tests/ui/traits/new-solver/opportunistic-region-resolve.rs new file mode 100644 index 000000000000..2610789cd485 --- /dev/null +++ b/tests/ui/traits/new-solver/opportunistic-region-resolve.rs @@ -0,0 +1,19 @@ +// compile-flags: -Ztrait-solver=next +// check-pass + +#![feature(rustc_attrs)] + +#[rustc_coinductive] +trait Trait {} + +#[rustc_coinductive] +trait Indirect {} +impl Indirect for T {} + +impl<'a> Trait for &'a () where &'a (): Indirect {} + +fn impls_trait() {} + +fn main() { + impls_trait::<&'static ()>(); +} From 7e07271eaf6f8ae1f3b2c3ffeb46bf1c13f36bc1 Mon Sep 17 00:00:00 2001 From: danakj Date: Wed, 14 Jun 2023 10:44:00 -0400 Subject: [PATCH 18/41] Avoid absolute sysroot paths in the MSVC linker command line When the `--sysroot` is specified as relative to the current working directory, the sysroot's rlibs should also be specified as relative paths. Otherwise, the current working directory ends up in the absolute paths, and in the linker command line. And the entire linker command line appears in the PDB file generated by the MSVC linker. When adding an rlib to the linker command line, if the rlib's canonical path is in the sysroot's canonical path, then use the current sysroot path + filename instead of the full absolute path to the rlib. This means that when `--sysroot=foo` is specified, the linker command line will contain `foo/rustlib/target/lib/lib*.rlib` instead of the full absolute path to the same. This addresses https://github.com/rust-lang/rust/issues/112586 --- compiler/rustc_codegen_ssa/src/back/link.rs | 29 +++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8d346c8c0d0d..9c53e5c05313 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_errors::{ErrorGuaranteed, Handler}; -use rustc_fs_util::fix_windows_verbatim_for_gcc; +use rustc_fs_util::{fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{copy_to_stdout, emit_wrapper_file, METADATA_FILENAME}; @@ -2682,6 +2682,31 @@ fn add_upstream_native_libraries( } } +// Rehome sysroot lib paths to be relative to the sysroot, which may be a relative +// path specified by the user. If the sysroot is a relative path, and the sysroot rlibs +// are specified as an absolute path, the linker command line can be non-deterministic +// due to the paths including the current working directory. The linker command line +// needs to be deterministic since it appears inside the PDB file generated by the MSVC +// linker. See https://github.com/rust-lang/rust/issues/112586. +// +// Note that the `susroot_lib_path` returned by `target_filesearch().get_lib_path()` has +// already had `fix_windows_verbatim_for_gcc()` applied if needed. +fn rehome_sysroot_rlib_path<'a>(sess: &'a Session, rlib_path: PathBuf) -> PathBuf { + let sysroot_lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); + let canonical_sysroot_lib_path = + { try_canonicalize(&sysroot_lib_path).unwrap_or_else(|_| sysroot_lib_path.clone()) }; + + let mut canonical_rlib_dir = try_canonicalize(&rlib_path).unwrap_or_else(|_| rlib_path.clone()); + canonical_rlib_dir.pop(); + + if canonical_rlib_dir == canonical_sysroot_lib_path { + sysroot_lib_path + .join(rlib_path.file_name().expect("rlib path has no file name path component")) + } else { + rlib_path + } +} + // Adds the static "rlib" versions of all crates to the command line. // There's a bit of magic which happens here specifically related to LTO, // namely that we remove upstream object files. @@ -2713,7 +2738,7 @@ fn add_static_crate<'a>( let cratepath = &src.rlib.as_ref().unwrap().0; let mut link_upstream = |path: &Path| { - cmd.link_rlib(&fix_windows_verbatim_for_gcc(path)); + cmd.link_rlib(&rehome_sysroot_rlib_path(sess, fix_windows_verbatim_for_gcc(path))); }; if !are_upstream_rust_objects_already_included(sess) From 4b83156a5c503174e7b4ce130edbe348fcd82817 Mon Sep 17 00:00:00 2001 From: danakj Date: Wed, 14 Jun 2023 10:58:08 -0400 Subject: [PATCH 19/41] Move the comment on fixing paths to where it belongs --- compiler/rustc_codegen_ssa/src/back/link.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 9c53e5c05313..6369116ece3a 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2688,9 +2688,6 @@ fn add_upstream_native_libraries( // due to the paths including the current working directory. The linker command line // needs to be deterministic since it appears inside the PDB file generated by the MSVC // linker. See https://github.com/rust-lang/rust/issues/112586. -// -// Note that the `susroot_lib_path` returned by `target_filesearch().get_lib_path()` has -// already had `fix_windows_verbatim_for_gcc()` applied if needed. fn rehome_sysroot_rlib_path<'a>(sess: &'a Session, rlib_path: PathBuf) -> PathBuf { let sysroot_lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); let canonical_sysroot_lib_path = @@ -2700,6 +2697,8 @@ fn rehome_sysroot_rlib_path<'a>(sess: &'a Session, rlib_path: PathBuf) -> PathBu canonical_rlib_dir.pop(); if canonical_rlib_dir == canonical_sysroot_lib_path { + // The `susroot_lib_path` returned by `target_filesearch().get_lib_path()` has + // already had `fix_windows_verbatim_for_gcc()` applied if needed. sysroot_lib_path .join(rlib_path.file_name().expect("rlib path has no file name path component")) } else { From 9d7295f0be2c90a98b6a7ce5f24ddef96dea10b7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Jun 2023 09:37:36 +1000 Subject: [PATCH 20/41] Move dead CGU marking code out of `partition`. The other major steps in `partition` have their own function, so it's nice for this one to be likewise. --- .../rustc_monomorphize/src/partitioning.rs | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index ebcc3b039997..2a314727744f 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -197,34 +197,8 @@ where let instrument_dead_code = tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions(); - if instrument_dead_code { - assert!( - codegen_units.len() > 0, - "There must be at least one CGU that code coverage data can be generated in." - ); - - // Find the smallest CGU that has exported symbols and put the dead - // function stubs in that CGU. We look for exported symbols to increase - // the likelihood the linker won't throw away the dead functions. - // FIXME(#92165): In order to truly resolve this, we need to make sure - // the object file (CGU) containing the dead function stubs is included - // in the final binary. This will probably require forcing these - // function symbols to be included via `-u` or `/include` linker args. - let mut cgus: Vec<_> = codegen_units.iter_mut().collect(); - cgus.sort_by_key(|cgu| cgu.size_estimate()); - - let dead_code_cgu = - if let Some(cgu) = cgus.into_iter().rev().find(|cgu| { - cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External) - }) { - cgu - } else { - // If there are no CGUs that have externally linked items, - // then we just pick the first CGU as a fallback. - &mut codegen_units[0] - }; - dead_code_cgu.make_code_coverage_dead_code_cgu(); + mark_code_coverage_dead_code_cgu(&mut codegen_units); } // Ensure CGUs are sorted by name, so that we get deterministic results. @@ -545,6 +519,33 @@ fn internalize_symbols<'tcx>( } } +fn mark_code_coverage_dead_code_cgu<'tcx>(codegen_units: &mut [CodegenUnit<'tcx>]) { + assert!(!codegen_units.is_empty()); + + // Find the smallest CGU that has exported symbols and put the dead + // function stubs in that CGU. We look for exported symbols to increase + // the likelihood the linker won't throw away the dead functions. + // FIXME(#92165): In order to truly resolve this, we need to make sure + // the object file (CGU) containing the dead function stubs is included + // in the final binary. This will probably require forcing these + // function symbols to be included via `-u` or `/include` linker args. + let mut cgus: Vec<&mut CodegenUnit<'tcx>> = codegen_units.iter_mut().collect(); + cgus.sort_by_key(|cgu| cgu.size_estimate()); + + let dead_code_cgu = if let Some(cgu) = cgus + .into_iter() + .rev() + .find(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)) + { + cgu + } else { + // If there are no CGUs that have externally linked items, + // then we just pick the first CGU as a fallback. + &mut codegen_units[0] + }; + dead_code_cgu.make_code_coverage_dead_code_cgu(); +} + fn characteristic_def_id_of_mono_item<'tcx>( tcx: TyCtxt<'tcx>, mono_item: MonoItem<'tcx>, From 57a7c8f577abd12ef4bb404448c42d794a76c690 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Jun 2023 09:50:48 +1000 Subject: [PATCH 21/41] Fix bug in `mark_code_coverage_dead_code_cgus`. The comment says "Find the smallest CGU that has exported symbols and put the dead function stubs in that CGU". But the code sorts the CGUs by size (smallest first) and then searches them in reverse order, which means it will find the *largest* CGU that has exported symbols. The erroneous code was introduced in #92142. This commit changes it to use a simpler search, avoiding the sort, and fixes the bug in the process. --- .../rustc_monomorphize/src/partitioning.rs | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 2a314727744f..de57992beac3 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -529,20 +529,15 @@ fn mark_code_coverage_dead_code_cgu<'tcx>(codegen_units: &mut [CodegenUnit<'tcx> // the object file (CGU) containing the dead function stubs is included // in the final binary. This will probably require forcing these // function symbols to be included via `-u` or `/include` linker args. - let mut cgus: Vec<&mut CodegenUnit<'tcx>> = codegen_units.iter_mut().collect(); - cgus.sort_by_key(|cgu| cgu.size_estimate()); + let dead_code_cgu = codegen_units + .iter_mut() + .filter(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)) + .min_by_key(|cgu| cgu.size_estimate()); + + // If there are no CGUs that have externally linked items, then we just + // pick the first CGU as a fallback. + let dead_code_cgu = if let Some(cgu) = dead_code_cgu { cgu } else { &mut codegen_units[0] }; - let dead_code_cgu = if let Some(cgu) = cgus - .into_iter() - .rev() - .find(|cgu| cgu.items().iter().any(|(_, (linkage, _))| *linkage == Linkage::External)) - { - cgu - } else { - // If there are no CGUs that have externally linked items, - // then we just pick the first CGU as a fallback. - &mut codegen_units[0] - }; dead_code_cgu.make_code_coverage_dead_code_cgu(); } From e414d25e94b8cfc29ee2ad44af10e2fd6644d36b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Jun 2023 10:00:55 +1000 Subject: [PATCH 22/41] Make `partition` more consistent. Always put the `create_size_estimate` calls and `debug_dump` calls within a timed scopes. This makes the four main steps look more similar to each other. --- .../rustc_monomorphize/src/partitioning.rs | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index de57992beac3..a74ba8e4a4be 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -155,15 +155,17 @@ where // functions and statics defined in the local crate. let PlacedRootMonoItems { mut codegen_units, internalization_candidates, unique_inlined_stats } = { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots"); - place_root_mono_items(cx, mono_items) + let mut placed = place_root_mono_items(cx, mono_items); + + for cgu in &mut placed.codegen_units { + cgu.create_size_estimate(tcx); + } + + debug_dump(tcx, "ROOTS", &placed.codegen_units, placed.unique_inlined_stats); + + placed }; - for cgu in &mut codegen_units { - cgu.create_size_estimate(tcx); - } - - debug_dump(tcx, "ROOTS", &codegen_units, unique_inlined_stats); - // Merge until we have at most `max_cgu_count` codegen units. // `merge_codegen_units` is responsible for updating the CGU size // estimates. @@ -179,22 +181,25 @@ where // local functions the definition of which is marked with `#[inline]`. { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items"); - place_inlined_mono_items(cx, &mut codegen_units) - }; + place_inlined_mono_items(cx, &mut codegen_units); - for cgu in &mut codegen_units { - cgu.create_size_estimate(tcx); + for cgu in &mut codegen_units { + cgu.create_size_estimate(tcx); + } + + debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats); } - debug_dump(tcx, "INLINE", &codegen_units, unique_inlined_stats); - // Next we try to make as many symbols "internal" as possible, so LLVM has // more freedom to optimize. if !tcx.sess.link_dead_code() { let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols"); internalize_symbols(cx, &mut codegen_units, internalization_candidates); + + debug_dump(tcx, "INTERNALIZE", &codegen_units, unique_inlined_stats); } + // Mark one CGU for dead code, if necessary. let instrument_dead_code = tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions(); if instrument_dead_code { @@ -204,8 +209,6 @@ where // Ensure CGUs are sorted by name, so that we get deterministic results. assert!(codegen_units.is_sorted_by(|a, b| Some(a.name().as_str().cmp(b.name().as_str())))); - debug_dump(tcx, "FINAL", &codegen_units, unique_inlined_stats); - codegen_units } From 9ef580fa6f2b5019b35e6a9cf979f6f13d21de00 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Jun 2023 01:55:30 +0000 Subject: [PATCH 23/41] Handle interpolated literal errors --- compiler/rustc_parse/src/parser/expr.rs | 9 +++------ tests/ui/parser/lit-err-in-macro.rs | 10 ++++++++++ tests/ui/parser/lit-err-in-macro.stderr | 8 ++++++++ 3 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 tests/ui/parser/lit-err-in-macro.rs create mode 100644 tests/ui/parser/lit-err-in-macro.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index cea2a71c9882..f00bc54589a7 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2023,17 +2023,14 @@ impl<'a> Parser<'a> { let recovered = self.recover_after_dot(); let token = recovered.as_ref().unwrap_or(&self.token); match token::Lit::from_token(token) { - Some(token_lit) => { - match MetaItemLit::from_token_lit(token_lit, token.span) { + Some(lit) => { + match MetaItemLit::from_token_lit(lit, token.span) { Ok(lit) => { self.bump(); Some(lit) } Err(err) => { - let span = token.span; - let token::Literal(lit) = token.kind else { - unreachable!(); - }; + let span = token.uninterpolated_span(); self.bump(); report_lit_error(&self.sess, err, lit, span); // Pack possible quotes and prefixes from the original literal into diff --git a/tests/ui/parser/lit-err-in-macro.rs b/tests/ui/parser/lit-err-in-macro.rs new file mode 100644 index 000000000000..cff8ee6b40ca --- /dev/null +++ b/tests/ui/parser/lit-err-in-macro.rs @@ -0,0 +1,10 @@ +macro_rules! f { + ($abi:literal) => { + extern $abi fn f() {} + } +} + +f!("Foo"__); +//~^ ERROR suffixes on string literals are invalid + +fn main() {} diff --git a/tests/ui/parser/lit-err-in-macro.stderr b/tests/ui/parser/lit-err-in-macro.stderr new file mode 100644 index 000000000000..a61fb5c85d49 --- /dev/null +++ b/tests/ui/parser/lit-err-in-macro.stderr @@ -0,0 +1,8 @@ +error: suffixes on string literals are invalid + --> $DIR/lit-err-in-macro.rs:7:4 + | +LL | f!("Foo"__); + | ^^^^^^^ invalid suffix `__` + +error: aborting due to previous error + From 2af5f2276d0cc2b34f2304415b1fbd6ccd42bc49 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Jun 2023 18:58:23 +1000 Subject: [PATCH 24/41] Merge CGUs in a nicer way. --- compiler/rustc_monomorphize/src/partitioning.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index a74ba8e4a4be..531644f0b849 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -340,9 +340,7 @@ fn merge_codegen_units<'tcx>( // Move the mono-items from `smallest` to `second_smallest` second_smallest.modify_size_estimate(smallest.size_estimate()); - for (k, v) in smallest.items_mut().drain() { - second_smallest.items_mut().insert(k, v); - } + second_smallest.items_mut().extend(smallest.items_mut().drain()); // Record that `second_smallest` now contains all the stuff that was // in `smallest` before. From c340325ebf348914c67fc62e868db8833845eeb9 Mon Sep 17 00:00:00 2001 From: danakj Date: Thu, 15 Jun 2023 11:13:03 -0400 Subject: [PATCH 25/41] Remap dylib paths into the sysroot to be relative to the sysroot Like for rlibs, the paths on the linker command line need to be relative paths if the sysroot was specified by the user to be a relative path. Dylibs put the path in /LIBPATH instead of into the file path of the library itself, so we rehome the libpath and adjust the rehoming function to be able to support both use cases, rlibs and dylibs. --- compiler/rustc_codegen_ssa/src/back/link.rs | 38 ++++++++++++--------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 6369116ece3a..557b120b2c8f 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2682,27 +2682,27 @@ fn add_upstream_native_libraries( } } -// Rehome sysroot lib paths to be relative to the sysroot, which may be a relative -// path specified by the user. If the sysroot is a relative path, and the sysroot rlibs -// are specified as an absolute path, the linker command line can be non-deterministic -// due to the paths including the current working directory. The linker command line -// needs to be deterministic since it appears inside the PDB file generated by the MSVC -// linker. See https://github.com/rust-lang/rust/issues/112586. -fn rehome_sysroot_rlib_path<'a>(sess: &'a Session, rlib_path: PathBuf) -> PathBuf { +// Rehome lib paths (which exclude the library file name) that point into the sysroot lib directory +// to be relative to the sysroot directory, which may be a relative path specified by the user. +// +// If the sysroot is a relative path, and the sysroot libs are specified as an absolute path, the +// linker command line can be non-deterministic due to the paths including the current working +// directory. The linker command line needs to be deterministic since it appears inside the PDB +// file generated by the MSVC linker. See https://github.com/rust-lang/rust/issues/112586. +// +// The returned path will always have `fix_windows_verbatim_for_gcc()` applied to it. +fn rehome_sysroot_lib_dir<'a>(sess: &'a Session, lib_dir: &Path) -> PathBuf { let sysroot_lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); let canonical_sysroot_lib_path = { try_canonicalize(&sysroot_lib_path).unwrap_or_else(|_| sysroot_lib_path.clone()) }; - let mut canonical_rlib_dir = try_canonicalize(&rlib_path).unwrap_or_else(|_| rlib_path.clone()); - canonical_rlib_dir.pop(); - - if canonical_rlib_dir == canonical_sysroot_lib_path { - // The `susroot_lib_path` returned by `target_filesearch().get_lib_path()` has + let canonical_lib_dir = try_canonicalize(lib_dir).unwrap_or_else(|_| lib_dir.to_path_buf()); + if canonical_lib_dir == canonical_sysroot_lib_path { + // This path, returned by `target_filesearch().get_lib_path()`, has // already had `fix_windows_verbatim_for_gcc()` applied if needed. sysroot_lib_path - .join(rlib_path.file_name().expect("rlib path has no file name path component")) } else { - rlib_path + fix_windows_verbatim_for_gcc(&lib_dir) } } @@ -2737,7 +2737,13 @@ fn add_static_crate<'a>( let cratepath = &src.rlib.as_ref().unwrap().0; let mut link_upstream = |path: &Path| { - cmd.link_rlib(&rehome_sysroot_rlib_path(sess, fix_windows_verbatim_for_gcc(path))); + let rlib_path = if let Some(dir) = path.parent() { + let file_name = path.file_name().expect("rlib path has no file name path component"); + rehome_sysroot_lib_dir(sess, &dir).join(file_name) + } else { + fix_windows_verbatim_for_gcc(path) + }; + cmd.link_rlib(&rlib_path); }; if !are_upstream_rust_objects_already_included(sess) @@ -2806,7 +2812,7 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) { // what its name is let parent = cratepath.parent(); if let Some(dir) = parent { - cmd.include_path(&fix_windows_verbatim_for_gcc(dir)); + cmd.include_path(&rehome_sysroot_lib_dir(sess, dir)); } let stem = cratepath.file_stem().unwrap().to_str().unwrap(); // Convert library file-stem into a cc -l argument. From b4ba7c4f93c1279c55271404937f064a78355e2f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Jun 2023 16:18:38 +0000 Subject: [PATCH 26/41] Make assumption functions in new solver take clause --- compiler/rustc_middle/src/ty/mod.rs | 66 +++++++++++++++++++ .../src/solve/assembly/mod.rs | 40 ++++++----- .../src/solve/project_goals.rs | 8 +-- .../src/solve/trait_goals.rs | 10 +-- 4 files changed, 98 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 72341e656e29..ff5d99794f1e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -586,6 +586,24 @@ pub enum Clause<'tcx> { ConstArgHasType(Const<'tcx>, Ty<'tcx>), } +impl<'tcx> Binder<'tcx, Clause<'tcx>> { + pub fn as_trait_clause(self) -> Option>> { + if let ty::Clause::Trait(trait_clause) = self.skip_binder() { + Some(self.rebind(trait_clause)) + } else { + None + } + } + + pub fn as_projection_clause(self) -> Option>> { + if let ty::Clause::Projection(projection_clause) = self.skip_binder() { + Some(self.rebind(projection_clause)) + } else { + None + } + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] pub enum PredicateKind<'tcx> { @@ -1203,6 +1221,17 @@ impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for TraitRef<'tcx> { + #[inline(always)] + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + Binder::dummy(Clause::Trait(TraitPredicate { + trait_ref: self, + constness: ty::BoundConstness::NotConst, + polarity: ty::ImplPolarity::Positive, + })) + } +} + impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { @@ -1211,6 +1240,14 @@ impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for Binder<'tcx, TraitRef<'tcx>> { + #[inline(always)] + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx); + pred.to_predicate(tcx) + } +} + impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> { #[inline(always)] fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> { @@ -1240,6 +1277,12 @@ impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for PolyTraitPredicate<'tcx> { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + self.map_bound(|p| Clause::Trait(p)) + } +} + impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(|p| PredicateKind::Clause(Clause::RegionOutlives(p))).to_predicate(tcx) @@ -1258,6 +1301,12 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { } } +impl<'tcx> ToPredicate<'tcx, Binder<'tcx, Clause<'tcx>>> for PolyProjectionPredicate<'tcx> { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Binder<'tcx, Clause<'tcx>> { + self.map_bound(|p| Clause::Projection(p)) + } +} + impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { PredicateKind::Clause(Clause::Trait(self)).to_predicate(tcx) @@ -1327,6 +1376,23 @@ impl<'tcx> Predicate<'tcx> { | PredicateKind::TypeWellFormedFromEnv(..) => None, } } + + pub fn as_clause(self) -> Option>> { + let predicate = self.kind(); + match predicate.skip_binder() { + PredicateKind::Clause(clause) => Some(predicate.rebind(clause)), + PredicateKind::AliasRelate(..) + | PredicateKind::Subtype(..) + | PredicateKind::Coerce(..) + | PredicateKind::WellFormed(..) + | PredicateKind::ObjectSafe(..) + | PredicateKind::ClosureKind(..) + | PredicateKind::ConstEvaluatable(..) + | PredicateKind::ConstEquate(..) + | PredicateKind::Ambiguous + | PredicateKind::TypeWellFormedFromEnv(..) => None, + } + } } /// Represents the bounds declared on a particular set of type diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 1b749b9c854c..e6eddf24844c 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -105,7 +105,7 @@ pub(super) trait GoalKind<'tcx>: fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx>; @@ -115,7 +115,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_implied_clause( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, requirements: impl IntoIterator>>, ) -> QueryResult<'tcx> { Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { @@ -131,7 +131,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_alias_bound_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, ) -> QueryResult<'tcx> { Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { ecx.validate_alias_bound_self_from_param_env(goal) @@ -144,7 +144,7 @@ pub(super) trait GoalKind<'tcx>: fn consider_object_bound_candidate( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, ) -> QueryResult<'tcx> { Self::probe_and_match_goal_against_assumption(ecx, goal, assumption, |ecx| { let tcx = ecx.tcx(); @@ -467,11 +467,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates: &mut Vec>, ) { for (i, assumption) in goal.param_env.caller_bounds().iter().enumerate() { - match G::consider_implied_clause(self, goal, assumption, []) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result }) + if let Some(clause) = assumption.as_clause() { + match G::consider_implied_clause(self, goal, clause, []) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::ParamEnv(i), result }) + } + Err(NoSolution) => (), } - Err(NoSolution) => (), } } } @@ -517,11 +519,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { for assumption in self.tcx().item_bounds(alias_ty.def_id).subst(self.tcx(), alias_ty.substs) { - match G::consider_alias_bound_candidate(self, goal, assumption) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::AliasBound, result }) + if let Some(clause) = assumption.as_clause() { + match G::consider_alias_bound_candidate(self, goal, clause) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::AliasBound, result }) + } + Err(NoSolution) => (), } - Err(NoSolution) => (), } } } @@ -675,18 +679,20 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // projection predicates that we reach by elaborating the principal trait ref, // since that'll cause ambiguity. // - // We can remove this when we have implemented intersections in responses. + // We can remove this when we have implemented lifetime intersections in responses. if assumption.to_opt_poly_projection_pred().is_some() && !own_bounds.contains(&assumption) { continue; } - match G::consider_object_bound_candidate(self, goal, assumption) { - Ok(result) => { - candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) + if let Some(clause) = assumption.as_clause() { + match G::consider_object_bound_candidate(self, goal, clause) { + Ok(result) => { + candidates.push(Candidate { source: CandidateSource::BuiltinImpl, result }) + } + Err(NoSolution) => (), } - Err(NoSolution) => (), } } } diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 242f9ba87473..8303bab4c36f 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -105,15 +105,15 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx> { - if let Some(poly_projection_pred) = assumption.to_opt_poly_projection_pred() - && poly_projection_pred.projection_def_id() == goal.predicate.def_id() + if let Some(projection_pred) = assumption.as_projection_clause() + && projection_pred.projection_def_id() == goal.predicate.def_id() { ecx.probe(|ecx| { let assumption_projection_pred = - ecx.instantiate_binder_with_infer(poly_projection_pred); + ecx.instantiate_binder_with_infer(projection_pred); ecx.eq( goal.param_env, goal.predicate.projection_ty, diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index f722f281314e..60cf386a289f 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -81,17 +81,17 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { fn probe_and_match_goal_against_assumption( ecx: &mut EvalCtxt<'_, 'tcx>, goal: Goal<'tcx, Self>, - assumption: ty::Predicate<'tcx>, + assumption: ty::Binder<'tcx, ty::Clause<'tcx>>, then: impl FnOnce(&mut EvalCtxt<'_, 'tcx>) -> QueryResult<'tcx>, ) -> QueryResult<'tcx> { - if let Some(poly_trait_pred) = assumption.to_opt_poly_trait_pred() - && poly_trait_pred.def_id() == goal.predicate.def_id() - && poly_trait_pred.polarity() == goal.predicate.polarity + if let Some(trait_clause) = assumption.as_trait_clause() + && trait_clause.def_id() == goal.predicate.def_id() + && trait_clause.polarity() == goal.predicate.polarity { // FIXME: Constness ecx.probe(|ecx| { let assumption_trait_pred = - ecx.instantiate_binder_with_infer(poly_trait_pred); + ecx.instantiate_binder_with_infer(trait_clause); ecx.eq( goal.param_env, goal.predicate.trait_ref, From b7921981d5c53097329cd5ff77a4721626433fe1 Mon Sep 17 00:00:00 2001 From: bohan Date: Fri, 2 Jun 2023 09:22:57 +0800 Subject: [PATCH 27/41] fix: inline `predicate_may_hold_fatal` --- .../src/traits/coherence.rs | 7 ++++- .../src/traits/select/mod.rs | 13 --------- tests/ui/traits/issue-105231.rs | 9 ++++++ tests/ui/traits/issue-105231.stderr | 29 +++++++++++++++++++ 4 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 tests/ui/traits/issue-105231.rs create mode 100644 tests/ui/traits/issue-105231.stderr diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 190a78f6a8ec..3193d00e11b2 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -292,7 +292,12 @@ fn impl_intersection_has_impossible_obligation<'cx, 'tcx>( Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, predicate) }) .chain(obligations) - .find(|o| !selcx.predicate_may_hold_fatal(o)); + .find(|o| { + selcx.evaluate_root_obligation(o).map_or( + false, // Overflow has occurred, and treat the obligation as possibly holding. + |result| !result.may_apply(), + ) + }); if let Some(failing_obligation) = opt_failing_obligation { debug!("overlap: obligation unsatisfiable {:?}", failing_obligation); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 5acd7b573dd9..4c5a794bc815 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -518,19 +518,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // The result is "true" if the obligation *may* hold and "false" if // we can be sure it does not. - /// Evaluates whether the obligation `obligation` can be satisfied (by any means). - pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool { - debug!(?obligation, "predicate_may_hold_fatal"); - - // This fatal query is a stopgap that should only be used in standard mode, - // where we do not expect overflow to be propagated. - assert!(self.query_mode == TraitQueryMode::Standard); - - self.evaluate_root_obligation(obligation) - .expect("Overflow should be caught earlier in standard query mode") - .may_apply() - } - /// Evaluates whether the obligation `obligation` can be satisfied /// and returns an `EvaluationResult`. This is meant for the /// *initial* call. diff --git a/tests/ui/traits/issue-105231.rs b/tests/ui/traits/issue-105231.rs new file mode 100644 index 000000000000..74c7afd6b9ed --- /dev/null +++ b/tests/ui/traits/issue-105231.rs @@ -0,0 +1,9 @@ +//~ ERROR overflow evaluating the requirement `A>>>>>>: Send` +struct A(B); +//~^ ERROR recursive types `A` and `B` have infinite size +struct B(A>); +trait Foo {} +impl Foo for T where T: Send {} +impl Foo for B {} + +fn main() {} diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr new file mode 100644 index 000000000000..fe20c47c57a8 --- /dev/null +++ b/tests/ui/traits/issue-105231.stderr @@ -0,0 +1,29 @@ +error[E0072]: recursive types `A` and `B` have infinite size + --> $DIR/issue-105231.rs:2:1 + | +LL | struct A(B); + | ^^^^^^^^^^^ ---- recursive without indirection +LL | +LL | struct B(A>); + | ^^^^^^^^^^^ ------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle + | +LL ~ struct A(Box>); +LL | +LL ~ struct B(Box>>); + | + +error[E0275]: overflow evaluating the requirement `A>>>>>>: Send` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_105231`) +note: required because it appears within the type `B>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/issue-105231.rs:4:8 + | +LL | struct B(A>); + | ^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0072, E0275. +For more information about an error, try `rustc --explain E0072`. From c54672e25f41b8ef41d0ff94da8c9a06fd6ed0b5 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 15 Jun 2023 18:02:55 -0400 Subject: [PATCH 28/41] Disable alignment checks on i686-pc-windows-msvc --- .../src/check_alignment.rs | 3 +++ tests/ui/mir/mir_alignment_check.rs | 1 + ...ir_alignment_check_i686-pc-windows-msvc.rs | 21 +++++++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index ef64f70fdf34..3987614f951e 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -15,6 +15,9 @@ pub struct CheckAlignment; impl<'tcx> MirPass<'tcx> for CheckAlignment { fn is_enabled(&self, sess: &Session) -> bool { + if sess.target.llvm_target == "i686-pc-windows-msvc" { + return false; + } sess.opts.debug_assertions } diff --git a/tests/ui/mir/mir_alignment_check.rs b/tests/ui/mir/mir_alignment_check.rs index 68a5384b30d7..d1bf3d46a7c7 100644 --- a/tests/ui/mir/mir_alignment_check.rs +++ b/tests/ui/mir/mir_alignment_check.rs @@ -1,5 +1,6 @@ // run-fail // ignore-wasm32-bare: No panic messages +// ignore-i686-pc-windows-msvc: #112480 // compile-flags: -C debug-assertions // error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is diff --git a/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs b/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs new file mode 100644 index 000000000000..56388c1047e9 --- /dev/null +++ b/tests/ui/mir/mir_alignment_check_i686-pc-windows-msvc.rs @@ -0,0 +1,21 @@ +// run-pass +// only-i686-pc-windows-msvc +// compile-flags: -Copt-level=0 -Cdebug-assertions=yes + +// MSVC isn't sure if on 32-bit Windows its u64 type is 8-byte-aligned or 4-byte-aligned. +// So this test ensures that on i686-pc-windows-msvc, we do not insert a runtime check +// that will fail on dereferencing of a pointer to u64 which is not 8-byte-aligned but is +// 4-byte-aligned. + +#![feature(strict_provenance)] + +fn main() { + let mut x = [0u64; 2]; + let ptr: *mut u8 = x.as_mut_ptr().cast::(); + unsafe { + let misaligned = ptr.add(4).cast::(); + assert!(misaligned.addr() % 8 != 0); + assert!(misaligned.addr() % 4 == 0); + *misaligned = 42; + } +} From dc3e91c6c2e3d5ae2287fd8332ecb6b7b7cee743 Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Thu, 15 Jun 2023 17:43:23 +0200 Subject: [PATCH 29/41] `#[lang_item]` for `core::ptr::Unique` --- compiler/rustc_hir/src/lang_items.rs | 2 ++ compiler/rustc_span/src/symbol.rs | 1 + library/core/src/ptr/unique.rs | 2 ++ 3 files changed, 5 insertions(+) diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 4b3bc816b953..4e23a28b3716 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -260,6 +260,8 @@ language_item_table! { EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None; OwnedBox, sym::owned_box, owned_box, Target::Struct, GenericRequirement::Minimum(1); + // Experimental language item for Miri + PtrUnique, sym::ptr_unique, ptr_unique, Target::Struct, GenericRequirement::Exact(1); PhantomData, sym::phantom_data, phantom_data, Target::Struct, GenericRequirement::Exact(1); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index c5ce2575fff0..19d986a3152b 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1156,6 +1156,7 @@ symbols! { ptr_null_mut, ptr_offset_from, ptr_offset_from_unsigned, + ptr_unique, pub_macro_rules, pub_restricted, public, diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs index a853f15edb7e..ff7e91d3ec30 100644 --- a/library/core/src/ptr/unique.rs +++ b/library/core/src/ptr/unique.rs @@ -32,6 +32,8 @@ use crate::ptr::NonNull; )] #[doc(hidden)] #[repr(transparent)] +// Lang item used experimentally by Miri to define the semantics of `Unique`. +#[cfg_attr(not(bootstrap), lang = "ptr_unique")] pub struct Unique { pointer: NonNull, // NOTE: this marker has no consequences for variance, but is necessary From 73c5c97de793c7202bcb0a3eb822c928309c14e5 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Fri, 16 Jun 2023 13:45:48 +0000 Subject: [PATCH 30/41] Add `SyntaxContext::is_root` --- compiler/rustc_expand/src/mbe/quoted.rs | 4 ++-- compiler/rustc_middle/src/mir/spanview.rs | 4 ++-- compiler/rustc_span/src/hygiene.rs | 13 +++++++++---- compiler/rustc_span/src/lib.rs | 14 +++++++------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index b2bdf9c7e6db..40bfa3715be7 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -9,7 +9,7 @@ use rustc_session::parse::{feature_err, ParseSess}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::edition::Edition; -use rustc_span::{Span, SyntaxContext}; +use rustc_span::Span; const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \ @@ -72,7 +72,7 @@ pub(super) fn parse( // `SyntaxContext::root()` from a foreign crate will // have the edition of that crate (which we manually // retrieve via the `edition` parameter). - if span.ctxt() == SyntaxContext::root() { + if span.ctxt().is_root() { edition } else { span.edition() diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 2165403da267..6b0361943818 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -3,7 +3,7 @@ use rustc_middle::hir; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use rustc_session::config::MirSpanview; -use rustc_span::{BytePos, Pos, Span, SyntaxContext}; +use rustc_span::{BytePos, Pos, Span}; use std::cmp; use std::io::{self, Write}; @@ -327,7 +327,7 @@ fn compute_block_span(data: &BasicBlockData<'_>, body_span: Span) -> Span { let mut span = data.terminator().source_info.span; for statement_span in data.statements.iter().map(|statement| statement.source_info.span) { // Only combine Spans from the root context, and within the function's body_span. - if statement_span.ctxt() == SyntaxContext::root() && body_span.contains(statement_span) { + if statement_span.ctxt().is_root() && body_span.contains(statement_span) { span = span.to(statement_span); } } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 0c7e36b3bef7..9f2ff4378425 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -507,7 +507,7 @@ impl HygieneData { self.normalize_to_macro_rules(call_site_ctxt) }; - if call_site_ctxt == SyntaxContext::root() { + if call_site_ctxt.is_root() { return self.apply_mark_internal(ctxt, expn_id, transparency); } @@ -671,12 +671,17 @@ impl SyntaxContext { } #[inline] - pub(crate) fn as_u32(self) -> u32 { + pub const fn is_root(self) -> bool { + self.0 == SyntaxContext::root().as_u32() + } + + #[inline] + pub(crate) const fn as_u32(self) -> u32 { self.0 } #[inline] - pub(crate) fn from_u32(raw: u32) -> SyntaxContext { + pub(crate) const fn from_u32(raw: u32) -> SyntaxContext { SyntaxContext(raw) } @@ -1500,7 +1505,7 @@ impl HashStable for SyntaxContext { const TAG_EXPANSION: u8 = 0; const TAG_NO_EXPANSION: u8 = 1; - if *self == SyntaxContext::root() { + if self.is_root() { TAG_NO_EXPANSION.hash_stable(ctx, hasher); } else { TAG_EXPANSION.hash_stable(ctx, hasher); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index eae3f0fa041d..e7a53c63e83b 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -826,9 +826,9 @@ impl Span { // Return the macro span on its own to avoid weird diagnostic output. It is preferable to // have an incomplete span than a completely nonsensical one. if span_data.ctxt != end_data.ctxt { - if span_data.ctxt == SyntaxContext::root() { + if span_data.ctxt.is_root() { return end; - } else if end_data.ctxt == SyntaxContext::root() { + } else if end_data.ctxt.is_root() { return self; } // Both spans fall within a macro. @@ -837,7 +837,7 @@ impl Span { Span::new( cmp::min(span_data.lo, end_data.lo), cmp::max(span_data.hi, end_data.hi), - if span_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, + if span_data.ctxt.is_root() { end_data.ctxt } else { span_data.ctxt }, if span_data.parent == end_data.parent { span_data.parent } else { None }, ) } @@ -855,7 +855,7 @@ impl Span { Span::new( span.hi, end.lo, - if end.ctxt == SyntaxContext::root() { end.ctxt } else { span.ctxt }, + if end.ctxt.is_root() { end.ctxt } else { span.ctxt }, if span.parent == end.parent { span.parent } else { None }, ) } @@ -879,9 +879,9 @@ impl Span { // Return the macro span on its own to avoid weird diagnostic output. It is preferable to // have an incomplete span than a completely nonsensical one. if span_data.ctxt != end_data.ctxt { - if span_data.ctxt == SyntaxContext::root() { + if span_data.ctxt.is_root() { return end; - } else if end_data.ctxt == SyntaxContext::root() { + } else if end_data.ctxt.is_root() { return self; } // Both spans fall within a macro. @@ -890,7 +890,7 @@ impl Span { Span::new( span_data.lo, end_data.lo, - if end_data.ctxt == SyntaxContext::root() { end_data.ctxt } else { span_data.ctxt }, + if end_data.ctxt.is_root() { end_data.ctxt } else { span_data.ctxt }, if span_data.parent == end_data.parent { span_data.parent } else { None }, ) } From 4ef316f397956fda8a478a2233ebc4392a1f7203 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 16 Jun 2023 09:55:23 -0400 Subject: [PATCH 31/41] Update compiler/rustc_mir_transform/src/check_alignment.rs --- compiler/rustc_mir_transform/src/check_alignment.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 3987614f951e..fd349c07040f 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -15,6 +15,7 @@ pub struct CheckAlignment; impl<'tcx> MirPass<'tcx> for CheckAlignment { fn is_enabled(&self, sess: &Session) -> bool { + // FIXME(#112480) MSVC and rustc disagree on minimum stack alignment on x86 Windows if sess.target.llvm_target == "i686-pc-windows-msvc" { return false; } From c153f3a356b0e7917c91d3a804b93fadffb778b0 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 4 Jun 2023 20:21:00 -0400 Subject: [PATCH 32/41] Ignore the always part of #[inline(always)] in MIR inlining --- compiler/rustc_mir_transform/src/inline.rs | 9 +- .../miri/tests/fail/terminate-terminator.rs | 2 +- tests/mir-opt/inline/asm_unwind.rs | 3 +- tests/mir-opt/inline/cycle.rs | 1 + tests/mir-opt/inline/inline_diverging.rs | 1 + ...ine_generator.main.Inline.panic-abort.diff | 30 ++-- ...ne_generator.main.Inline.panic-unwind.diff | 30 ++-- tests/mir-opt/inline/inline_generator.rs | 5 +- ...nto_box_place.main.Inline.panic-abort.diff | 149 +++++++++++++++- ...to_box_place.main.Inline.panic-unwind.diff | 159 +++++++++++++++++- tests/mir-opt/inline/inline_into_box_place.rs | 2 +- ...l_unsigned_smaller.Inline.panic-abort.diff | 112 +----------- ..._unsigned_smaller.Inline.panic-unwind.diff | 112 +----------- ...d_smaller.PreCodegen.after.panic-abort.mir | 111 +----------- ..._smaller.PreCodegen.after.panic-unwind.mir | 111 +----------- ...shr_signed_smaller.Inline.panic-abort.diff | 112 +----------- ...hr_signed_smaller.Inline.panic-unwind.diff | 112 +----------- ...d_smaller.PreCodegen.after.panic-abort.mir | 111 +----------- ..._smaller.PreCodegen.after.panic-unwind.mir | 111 +----------- 19 files changed, 349 insertions(+), 934 deletions(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 5487b5987e00..b28fed7159f1 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -479,11 +479,12 @@ impl<'tcx> Inliner<'tcx> { // Abort if type validation found anything fishy. checker.validation?; + // N.B. We still apply our cost threshold to #[inline(always)] functions. + // That attribute is often applied to very large functions that exceed LLVM's (very + // generous) inlining threshold. Such functions are very poor MIR inlining candidates. + // Always inlining #[inline(always)] functions in MIR, on net, slows down the compiler. let cost = checker.cost; - if let InlineAttr::Always = callee_attrs.inline { - debug!("INLINING {:?} because inline(always) [cost={}]", callsite, cost); - Ok(()) - } else if cost <= threshold { + if cost <= threshold { debug!("INLINING {:?} [cost={} <= threshold={}]", callsite, cost, threshold); Ok(()) } else { diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs index b9199cff079e..bd6cd69215ae 100644 --- a/src/tools/miri/tests/fail/terminate-terminator.rs +++ b/src/tools/miri/tests/fail/terminate-terminator.rs @@ -1,4 +1,4 @@ -//@compile-flags: -Zmir-opt-level=3 +//@compile-flags: -Zmir-opt-level=3 -Zinline-mir-hint-threshold=1000 // Enable MIR inlining to ensure that `TerminatorKind::Terminate` is generated // instead of just `UnwindAction::Terminate`. diff --git a/tests/mir-opt/inline/asm_unwind.rs b/tests/mir-opt/inline/asm_unwind.rs index a977ebf1bb7b..573ae1ba68d4 100644 --- a/tests/mir-opt/inline/asm_unwind.rs +++ b/tests/mir-opt/inline/asm_unwind.rs @@ -2,6 +2,7 @@ // // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // needs-asm-support +// compile-flags: -Zinline-mir-hint-threshold=1000 #![feature(asm_unwind)] struct D; @@ -10,7 +11,7 @@ impl Drop for D { fn drop(&mut self) {} } -#[inline(always)] +#[inline] fn foo() { let _d = D; unsafe { std::arch::asm!("", options(may_unwind)) }; diff --git a/tests/mir-opt/inline/cycle.rs b/tests/mir-opt/inline/cycle.rs index af2ca895cc63..1b74d818451e 100644 --- a/tests/mir-opt/inline/cycle.rs +++ b/tests/mir-opt/inline/cycle.rs @@ -1,4 +1,5 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// compile-flags: -Zinline-mir-hint-threshold=1000 // EMIT_MIR cycle.f.Inline.diff #[inline(always)] diff --git a/tests/mir-opt/inline/inline_diverging.rs b/tests/mir-opt/inline/inline_diverging.rs index febf1a8a6bf5..e01c4c1dd021 100644 --- a/tests/mir-opt/inline/inline_diverging.rs +++ b/tests/mir-opt/inline/inline_diverging.rs @@ -1,6 +1,7 @@ // Tests inlining of diverging calls. // // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// compile-flags: -Zinline-mir-hint-threshold=1000 #![crate_type = "lib"] // EMIT_MIR inline_diverging.f.Inline.diff diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff index fa48c56d185d..e05c605a4e47 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff @@ -4,30 +4,30 @@ fn main() -> () { let mut _0: (); let _1: std::ops::GeneratorState; - let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>; - let mut _3: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; - let mut _4: [generator@$DIR/inline_generator.rs:15:5: 15:8]; + let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>; + let mut _3: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _4: [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { + } -+ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new) { ++ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new) { + debug pointer => _3; + scope 4 { -+ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new_unchecked) { ++ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new_unchecked) { + debug pointer => _3; + } + } + } + scope 6 (inlined g::{closure#0}) { + debug a => _5; -+ let mut _6: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; ++ let mut _6: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _7: u32; + let mut _8: i32; -+ let mut _9: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; -+ let mut _10: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; ++ let mut _9: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; ++ let mut _10: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + } bb0: { @@ -39,18 +39,18 @@ - } - - bb1: { -+ _4 = [generator@$DIR/inline_generator.rs:15:5: 15:8 (#0)]; ++ _4 = [generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)]; _3 = &mut _4; -- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind unreachable]; +- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new(move _3) -> [return: bb2, unwind unreachable]; - } - - bb2: { -+ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]> { pointer: move _3 }; ++ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]> { pointer: move _3 }; StorageDead(_3); -- _1 = <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; +- _1 = <[generator@$DIR/inline_generator.rs:16:5: 16:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; + StorageLive(_5); + _5 = const false; -+ _6 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _6 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb2, 1: bb6, 3: bb7, otherwise: bb8]; } @@ -82,7 +82,7 @@ + + bb5: { + _1 = GeneratorState::::Yielded(move _8); -+ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + discriminant((*_9)) = 3; + goto -> bb1; + } @@ -95,7 +95,7 @@ + StorageLive(_8); + StorageDead(_8); + _1 = GeneratorState::::Complete(_5); -+ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + discriminant((*_10)) = 1; + goto -> bb1; + } diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff index 63f70ccc3b52..588f04048d67 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff @@ -4,30 +4,30 @@ fn main() -> () { let mut _0: (); let _1: std::ops::GeneratorState; - let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>; - let mut _3: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; - let mut _4: [generator@$DIR/inline_generator.rs:15:5: 15:8]; + let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>; + let mut _3: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _4: [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _5: bool; scope 1 { debug _r => _1; } + scope 2 (inlined g) { + } -+ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new) { ++ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new) { + debug pointer => _3; + scope 4 { -+ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new_unchecked) { ++ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new_unchecked) { + debug pointer => _3; + } + } + } + scope 6 (inlined g::{closure#0}) { + debug a => _5; -+ let mut _6: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; ++ let mut _6: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + let mut _7: u32; + let mut _8: i32; -+ let mut _9: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; -+ let mut _10: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; ++ let mut _9: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; ++ let mut _10: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]; + } bb0: { @@ -39,18 +39,18 @@ - } - - bb1: { -+ _4 = [generator@$DIR/inline_generator.rs:15:5: 15:8 (#0)]; ++ _4 = [generator@$DIR/inline_generator.rs:16:5: 16:8 (#0)]; _3 = &mut _4; -- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; +- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]>::new(move _3) -> [return: bb2, unwind: bb4]; - } - - bb2: { -+ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]> { pointer: move _3 }; ++ _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:16:5: 16:8]> { pointer: move _3 }; StorageDead(_3); -- _1 = <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; +- _1 = <[generator@$DIR/inline_generator.rs:16:5: 16:8] as Generator>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; + StorageLive(_5); + _5 = const false; -+ _6 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _6 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; } @@ -87,7 +87,7 @@ + + bb6: { + _1 = GeneratorState::::Yielded(move _8); -+ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _9 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + discriminant((*_9)) = 3; + goto -> bb1; + } @@ -100,7 +100,7 @@ + StorageLive(_8); + StorageDead(_8); + _1 = GeneratorState::::Complete(_5); -+ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); ++ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:16:5: 16:8]); + discriminant((*_10)) = 1; + goto -> bb1; + } diff --git a/tests/mir-opt/inline/inline_generator.rs b/tests/mir-opt/inline/inline_generator.rs index 61f1da897bd1..2d71458c1741 100644 --- a/tests/mir-opt/inline/inline_generator.rs +++ b/tests/mir-opt/inline/inline_generator.rs @@ -1,4 +1,5 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// compile-flags: -Zinline-mir-hint-threshold=1000 #![feature(generators, generator_trait)] use std::ops::Generator; @@ -9,8 +10,8 @@ fn main() { let _r = Pin::new(&mut g()).resume(false); } -#[inline(always)] +#[inline] pub fn g() -> impl Generator { - #[inline(always)] + #[inline] |a| { yield if a { 7 } else { 13 } } } diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff index b186a701f65b..f3a6923415a1 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-abort.diff @@ -18,6 +18,99 @@ + let mut _6: *mut u8; + let mut _7: *const std::vec::Vec; + scope 4 { ++ scope 5 (inlined alloc::alloc::exchange_malloc) { ++ debug size => _4; ++ debug align => _5; ++ let _8: std::alloc::Layout; ++ let mut _9: std::result::Result, std::alloc::AllocError>; ++ let mut _10: isize; ++ let mut _12: !; ++ scope 6 { ++ debug layout => _8; ++ let _11: std::ptr::NonNull<[u8]>; ++ let mut _13: &std::alloc::Global; ++ scope 8 { ++ debug ptr => _11; ++ scope 18 (inlined NonNull::<[u8]>::as_mut_ptr) { ++ debug self => _11; ++ let mut _15: std::ptr::NonNull; ++ scope 19 (inlined NonNull::<[u8]>::as_non_null_ptr) { ++ debug self => _11; ++ let mut _16: *mut u8; ++ let mut _17: *mut [u8]; ++ scope 20 { ++ scope 21 (inlined NonNull::<[u8]>::as_ptr) { ++ debug self => _11; ++ let mut _18: *const [u8]; ++ } ++ scope 22 (inlined ptr::mut_ptr::::as_mut_ptr) { ++ debug self => _17; ++ } ++ scope 23 (inlined NonNull::::new_unchecked) { ++ debug ptr => _16; ++ let mut _19: *const u8; ++ scope 24 { ++ scope 25 (inlined NonNull::::new_unchecked::runtime::) { ++ debug ptr => _16; ++ scope 26 (inlined ptr::mut_ptr::::is_null) { ++ debug self => _16; ++ let mut _20: *mut u8; ++ scope 27 { ++ scope 28 (inlined ptr::mut_ptr::::is_null::runtime_impl) { ++ debug ptr => _20; ++ scope 29 (inlined ptr::mut_ptr::::addr) { ++ debug self => _20; ++ scope 30 { ++ scope 31 (inlined ptr::mut_ptr::::cast::<()>) { ++ debug self => _20; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ scope 32 (inlined NonNull::::as_ptr) { ++ debug self => _15; ++ let mut _21: *const u8; ++ } ++ } ++ } ++ scope 17 (inlined ::allocate) { ++ debug self => const _; ++ debug layout => _8; ++ } ++ } ++ scope 7 { ++ scope 9 (inlined Layout::from_size_align_unchecked) { ++ debug size => _4; ++ debug align => _5; ++ let mut _14: std::ptr::Alignment; ++ scope 10 { ++ scope 11 (inlined std::ptr::Alignment::new_unchecked) { ++ debug align => _5; ++ scope 12 { ++ scope 14 (inlined std::ptr::Alignment::new_unchecked::runtime) { ++ debug align => _5; ++ scope 15 (inlined core::num::::is_power_of_two) { ++ debug self => _5; ++ scope 16 (inlined core::num::::count_ones) { ++ debug self => _5; ++ } ++ } ++ } ++ } ++ scope 13 { ++ } ++ } ++ } ++ } ++ } ++ } + } + } @@ -31,7 +124,17 @@ + StorageDead(_3); + _4 = SizeOf(std::vec::Vec); + _5 = AlignOf(std::vec::Vec); -+ _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> [return: bb2, unwind unreachable]; ++ StorageLive(_8); ++ StorageLive(_11); ++ StorageLive(_12); ++ StorageLive(_13); ++ StorageLive(_14); ++ _14 = _5 as std::ptr::Alignment (Transmute); ++ _8 = Layout { size: _4, align: move _14 }; ++ StorageDead(_14); ++ StorageLive(_9); ++ _13 = const _; ++ _9 = std::alloc::Global::alloc_impl(_13, _8, const false) -> [return: bb5, unwind unreachable]; } bb1: { @@ -41,18 +144,56 @@ } bb2: { ++ _12 = handle_alloc_error(_8) -> unwind unreachable; ++ } ++ ++ bb3: { ++ unreachable; ++ } ++ ++ bb4: { ++ _11 = ((_9 as Ok).0: std::ptr::NonNull<[u8]>); ++ StorageLive(_15); ++ StorageLive(_16); ++ StorageLive(_17); ++ StorageLive(_18); ++ _18 = (_11.0: *const [u8]); ++ _17 = move _18 as *mut [u8] (PtrToPtr); ++ StorageDead(_18); ++ _16 = _17 as *mut u8 (PtrToPtr); ++ StorageDead(_17); ++ StorageLive(_19); ++ StorageLive(_20); ++ _19 = _16 as *const u8 (Pointer(MutToConstPointer)); ++ _15 = NonNull:: { pointer: _19 }; ++ StorageDead(_20); ++ StorageDead(_19); ++ StorageDead(_16); ++ StorageLive(_21); ++ _21 = (_15.0: *const u8); ++ _6 = move _21 as *mut u8 (PtrToPtr); ++ StorageDead(_21); ++ StorageDead(_15); ++ StorageDead(_9); ++ StorageDead(_13); ++ StorageDead(_12); ++ StorageDead(_11); ++ StorageDead(_8); + _1 = ShallowInitBox(move _6, std::vec::Vec); + _7 = (((_1.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); + (*_7) = move _2; StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind unreachable]; -- } -- ++ drop(_1) -> [return: bb1, unwind unreachable]; + } + - bb3: { - StorageDead(_1); - return; -+ drop(_1) -> [return: bb1, unwind unreachable]; ++ bb5: { ++ _10 = discriminant(_9); ++ switchInt(move _10) -> [0: bb4, 1: bb2, otherwise: bb3]; } } diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff index a789f9933b4b..4615a3f98267 100644 --- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.panic-unwind.diff @@ -18,6 +18,99 @@ + let mut _6: *mut u8; + let mut _7: *const std::vec::Vec; + scope 4 { ++ scope 5 (inlined alloc::alloc::exchange_malloc) { ++ debug size => _4; ++ debug align => _5; ++ let _8: std::alloc::Layout; ++ let mut _9: std::result::Result, std::alloc::AllocError>; ++ let mut _10: isize; ++ let mut _12: !; ++ scope 6 { ++ debug layout => _8; ++ let _11: std::ptr::NonNull<[u8]>; ++ let mut _13: &std::alloc::Global; ++ scope 8 { ++ debug ptr => _11; ++ scope 18 (inlined NonNull::<[u8]>::as_mut_ptr) { ++ debug self => _11; ++ let mut _15: std::ptr::NonNull; ++ scope 19 (inlined NonNull::<[u8]>::as_non_null_ptr) { ++ debug self => _11; ++ let mut _16: *mut u8; ++ let mut _17: *mut [u8]; ++ scope 20 { ++ scope 21 (inlined NonNull::<[u8]>::as_ptr) { ++ debug self => _11; ++ let mut _18: *const [u8]; ++ } ++ scope 22 (inlined ptr::mut_ptr::::as_mut_ptr) { ++ debug self => _17; ++ } ++ scope 23 (inlined NonNull::::new_unchecked) { ++ debug ptr => _16; ++ let mut _19: *const u8; ++ scope 24 { ++ scope 25 (inlined NonNull::::new_unchecked::runtime::) { ++ debug ptr => _16; ++ scope 26 (inlined ptr::mut_ptr::::is_null) { ++ debug self => _16; ++ let mut _20: *mut u8; ++ scope 27 { ++ scope 28 (inlined ptr::mut_ptr::::is_null::runtime_impl) { ++ debug ptr => _20; ++ scope 29 (inlined ptr::mut_ptr::::addr) { ++ debug self => _20; ++ scope 30 { ++ scope 31 (inlined ptr::mut_ptr::::cast::<()>) { ++ debug self => _20; ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ } ++ scope 32 (inlined NonNull::::as_ptr) { ++ debug self => _15; ++ let mut _21: *const u8; ++ } ++ } ++ } ++ scope 17 (inlined ::allocate) { ++ debug self => const _; ++ debug layout => _8; ++ } ++ } ++ scope 7 { ++ scope 9 (inlined Layout::from_size_align_unchecked) { ++ debug size => _4; ++ debug align => _5; ++ let mut _14: std::ptr::Alignment; ++ scope 10 { ++ scope 11 (inlined std::ptr::Alignment::new_unchecked) { ++ debug align => _5; ++ scope 12 { ++ scope 14 (inlined std::ptr::Alignment::new_unchecked::runtime) { ++ debug align => _5; ++ scope 15 (inlined core::num::::is_power_of_two) { ++ debug self => _5; ++ scope 16 (inlined core::num::::count_ones) { ++ debug self => _5; ++ } ++ } ++ } ++ } ++ scope 13 { ++ } ++ } ++ } ++ } ++ } ++ } + } + } @@ -31,7 +124,17 @@ + StorageDead(_3); + _4 = SizeOf(std::vec::Vec); + _5 = AlignOf(std::vec::Vec); -+ _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> [return: bb3, unwind: bb4]; ++ StorageLive(_8); ++ StorageLive(_11); ++ StorageLive(_12); ++ StorageLive(_13); ++ StorageLive(_14); ++ _14 = _5 as std::ptr::Alignment (Transmute); ++ _8 = Layout { size: _4, align: move _14 }; ++ StorageDead(_14); ++ StorageLive(_9); ++ _13 = const _; ++ _9 = std::alloc::Global::alloc_impl(_13, _8, const false) -> [return: bb7, unwind: bb3]; } bb1: { @@ -48,20 +151,62 @@ + resume; } - bb3: { +- bb3: { - StorageDead(_1); - return; ++ bb3 (cleanup): { ++ drop(_2) -> [return: bb2, unwind terminate]; + } + +- bb4 (cleanup): { +- resume; ++ bb4: { ++ _12 = handle_alloc_error(_8) -> bb3; ++ } ++ ++ bb5: { ++ unreachable; ++ } ++ ++ bb6: { ++ _11 = ((_9 as Ok).0: std::ptr::NonNull<[u8]>); ++ StorageLive(_15); ++ StorageLive(_16); ++ StorageLive(_17); ++ StorageLive(_18); ++ _18 = (_11.0: *const [u8]); ++ _17 = move _18 as *mut [u8] (PtrToPtr); ++ StorageDead(_18); ++ _16 = _17 as *mut u8 (PtrToPtr); ++ StorageDead(_17); ++ StorageLive(_19); ++ StorageLive(_20); ++ _19 = _16 as *const u8 (Pointer(MutToConstPointer)); ++ _15 = NonNull:: { pointer: _19 }; ++ StorageDead(_20); ++ StorageDead(_19); ++ StorageDead(_16); ++ StorageLive(_21); ++ _21 = (_15.0: *const u8); ++ _6 = move _21 as *mut u8 (PtrToPtr); ++ StorageDead(_21); ++ StorageDead(_15); ++ StorageDead(_9); ++ StorageDead(_13); ++ StorageDead(_12); ++ StorageDead(_11); ++ StorageDead(_8); + _1 = ShallowInitBox(move _6, std::vec::Vec); + _7 = (((_1.0: std::ptr::Unique>).0: std::ptr::NonNull>).0: *const std::vec::Vec); + (*_7) = move _2; + StorageDead(_2); + _0 = const (); + drop(_1) -> [return: bb1, unwind: bb2]; - } - - bb4 (cleanup): { -- resume; -+ drop(_2) -> [return: bb2, unwind terminate]; ++ } ++ ++ bb7: { ++ _10 = discriminant(_9); ++ switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; } } diff --git a/tests/mir-opt/inline/inline_into_box_place.rs b/tests/mir-opt/inline/inline_into_box_place.rs index bc578ec90e84..56f174e515b3 100644 --- a/tests/mir-opt/inline/inline_into_box_place.rs +++ b/tests/mir-opt/inline/inline_into_box_place.rs @@ -1,7 +1,7 @@ // ignore-endian-big // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // ignore-debug MIR alignment checks in std alter the diff, breaking the test -// compile-flags: -Z mir-opt-level=4 +// compile-flags: -Zmir-opt-level=4 -Zinline-mir-hint-threshold=200 // EMIT_MIR inline_into_box_place.main.Inline.diff fn main() { diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff index 890d9b109fb4..093925b8e4fa 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-abort.diff @@ -7,129 +7,19 @@ let mut _0: u16; let mut _3: u16; let mut _4: u32; -+ scope 1 (inlined core::num::::unchecked_shl) { -+ debug self => _3; -+ debug rhs => _4; -+ let mut _5: u16; -+ scope 2 { -+ scope 3 (inlined core::num::::unchecked_shl::conv) { -+ debug x => _4; -+ let mut _6: std::option::Option; -+ let mut _7: std::result::Result; -+ scope 4 { -+ scope 5 (inlined >::try_into) { -+ debug self => _4; -+ scope 6 (inlined convert::num:: for u16>::try_from) { -+ debug u => _4; -+ let mut _8: bool; -+ let mut _9: u32; -+ let mut _10: u16; -+ } -+ } -+ scope 7 (inlined Result::::ok) { -+ debug self => _7; -+ let mut _11: isize; -+ let _12: u16; -+ scope 8 { -+ debug x => _12; -+ } -+ } -+ scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { -+ debug self => _6; -+ let mut _13: &std::option::Option; -+ let mut _14: isize; -+ scope 10 { -+ debug val => _5; -+ } -+ scope 11 { -+ scope 13 (inlined unreachable_unchecked) { -+ scope 14 { -+ scope 15 (inlined unreachable_unchecked::runtime) { -+ } -+ } -+ } -+ } -+ scope 12 (inlined Option::::is_some) { -+ debug self => _13; -+ } -+ } -+ } -+ } -+ } -+ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable]; -+ StorageLive(_5); -+ StorageLive(_6); -+ StorageLive(_7); -+ StorageLive(_8); -+ StorageLive(_9); -+ _9 = const 65535_u32; -+ _8 = Gt(_4, move _9); -+ StorageDead(_9); -+ switchInt(move _8) -> [0: bb3, otherwise: bb2]; + _0 = core::num::::unchecked_shl(move _3, move _4) -> [return: bb1, unwind unreachable]; } bb1: { -+ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; -+ } -+ -+ bb2: { -+ _7 = Result::::Err(const TryFromIntError(())); -+ goto -> bb4; -+ } -+ -+ bb3: { -+ StorageLive(_10); -+ _10 = _4 as u16 (IntToInt); -+ _7 = Result::::Ok(move _10); -+ StorageDead(_10); -+ goto -> bb4; -+ } -+ -+ bb4: { -+ StorageDead(_8); -+ StorageLive(_12); -+ _11 = discriminant(_7); -+ switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; -+ } -+ -+ bb5: { -+ _6 = Option::::None; -+ goto -> bb8; -+ } -+ -+ bb6: { -+ unreachable; -+ } -+ -+ bb7: { -+ _12 = move ((_7 as Ok).0: u16); -+ _6 = Option::::Some(move _12); -+ goto -> bb8; -+ } -+ -+ bb8: { -+ StorageDead(_12); -+ StorageDead(_7); -+ StorageLive(_13); -+ _14 = discriminant(_6); -+ switchInt(move _14) -> [1: bb9, otherwise: bb6]; -+ } -+ -+ bb9: { -+ _5 = move ((_6 as Some).0: u16); -+ StorageDead(_13); -+ StorageDead(_6); -+ _0 = unchecked_shl::(_3, move _5) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff index 118e601b136c..50934e0439a3 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.panic-unwind.diff @@ -7,129 +7,19 @@ let mut _0: u16; let mut _3: u16; let mut _4: u32; -+ scope 1 (inlined core::num::::unchecked_shl) { -+ debug self => _3; -+ debug rhs => _4; -+ let mut _5: u16; -+ scope 2 { -+ scope 3 (inlined core::num::::unchecked_shl::conv) { -+ debug x => _4; -+ let mut _6: std::option::Option; -+ let mut _7: std::result::Result; -+ scope 4 { -+ scope 5 (inlined >::try_into) { -+ debug self => _4; -+ scope 6 (inlined convert::num:: for u16>::try_from) { -+ debug u => _4; -+ let mut _8: bool; -+ let mut _9: u32; -+ let mut _10: u16; -+ } -+ } -+ scope 7 (inlined Result::::ok) { -+ debug self => _7; -+ let mut _11: isize; -+ let _12: u16; -+ scope 8 { -+ debug x => _12; -+ } -+ } -+ scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { -+ debug self => _6; -+ let mut _13: &std::option::Option; -+ let mut _14: isize; -+ scope 10 { -+ debug val => _5; -+ } -+ scope 11 { -+ scope 13 (inlined unreachable_unchecked) { -+ scope 14 { -+ scope 15 (inlined unreachable_unchecked::runtime) { -+ } -+ } -+ } -+ } -+ scope 12 (inlined Option::::is_some) { -+ debug self => _13; -+ } -+ } -+ } -+ } -+ } -+ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shl(move _3, move _4) -> bb1; -+ StorageLive(_5); -+ StorageLive(_6); -+ StorageLive(_7); -+ StorageLive(_8); -+ StorageLive(_9); -+ _9 = const 65535_u32; -+ _8 = Gt(_4, move _9); -+ StorageDead(_9); -+ switchInt(move _8) -> [0: bb3, otherwise: bb2]; + _0 = core::num::::unchecked_shl(move _3, move _4) -> bb1; } bb1: { -+ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; -+ } -+ -+ bb2: { -+ _7 = Result::::Err(const TryFromIntError(())); -+ goto -> bb4; -+ } -+ -+ bb3: { -+ StorageLive(_10); -+ _10 = _4 as u16 (IntToInt); -+ _7 = Result::::Ok(move _10); -+ StorageDead(_10); -+ goto -> bb4; -+ } -+ -+ bb4: { -+ StorageDead(_8); -+ StorageLive(_12); -+ _11 = discriminant(_7); -+ switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; -+ } -+ -+ bb5: { -+ _6 = Option::::None; -+ goto -> bb8; -+ } -+ -+ bb6: { -+ unreachable; -+ } -+ -+ bb7: { -+ _12 = move ((_7 as Ok).0: u16); -+ _6 = Option::::Some(move _12); -+ goto -> bb8; -+ } -+ -+ bb8: { -+ StorageDead(_12); -+ StorageDead(_7); -+ StorageLive(_13); -+ _14 = discriminant(_6); -+ switchInt(move _14) -> [1: bb9, otherwise: bb6]; -+ } -+ -+ bb9: { -+ _5 = move ((_6 as Some).0: u16); -+ StorageDead(_13); -+ StorageDead(_6); -+ _0 = unchecked_shl::(_3, move _5) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir index 0d692251051e..46f3511b14ca 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-abort.mir @@ -4,121 +4,12 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { debug a => _1; debug b => _2; let mut _0: u16; - scope 1 (inlined core::num::::unchecked_shl) { - debug self => _1; - debug rhs => _2; - let mut _11: u16; - scope 2 { - scope 3 (inlined core::num::::unchecked_shl::conv) { - debug x => _2; - let mut _6: std::result::Result; - let mut _9: std::option::Option; - scope 4 { - scope 5 (inlined >::try_into) { - debug self => _2; - scope 6 (inlined convert::num:: for u16>::try_from) { - debug u => _2; - let mut _3: u32; - let mut _4: bool; - let mut _5: u16; - } - } - scope 7 (inlined Result::::ok) { - debug self => _6; - let mut _7: isize; - let _8: u16; - scope 8 { - debug x => _8; - } - } - scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { - debug self => _9; - let mut _10: isize; - let mut _12: &std::option::Option; - scope 10 { - debug val => _11; - } - scope 11 { - scope 13 (inlined unreachable_unchecked) { - scope 14 { - scope 15 (inlined unreachable_unchecked::runtime) { - } - } - } - } - scope 12 (inlined Option::::is_some) { - debug self => _12; - } - } - } - } - } - } bb0: { - StorageLive(_11); - StorageLive(_9); - StorageLive(_6); - StorageLive(_4); - StorageLive(_3); - _3 = const 65535_u32; - _4 = Gt(_2, move _3); - StorageDead(_3); - switchInt(move _4) -> [0: bb1, otherwise: bb2]; + _0 = core::num::::unchecked_shl(_1, _2) -> [return: bb1, unwind unreachable]; } bb1: { - StorageLive(_5); - _5 = _2 as u16 (IntToInt); - _6 = Result::::Ok(move _5); - StorageDead(_5); - goto -> bb3; - } - - bb2: { - _6 = Result::::Err(const TryFromIntError(())); - goto -> bb3; - } - - bb3: { - StorageDead(_4); - StorageLive(_8); - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb9]; - } - - bb4: { - _8 = move ((_6 as Ok).0: u16); - _9 = Option::::Some(move _8); - goto -> bb6; - } - - bb5: { - _9 = Option::::None; - goto -> bb6; - } - - bb6: { - StorageDead(_8); - StorageDead(_6); - StorageLive(_12); - _10 = discriminant(_9); - switchInt(move _10) -> [1: bb7, otherwise: bb9]; - } - - bb7: { - _11 = move ((_9 as Some).0: u16); - StorageDead(_12); - StorageDead(_9); - _0 = unchecked_shl::(_1, move _11) -> [return: bb8, unwind unreachable]; - } - - bb8: { - StorageDead(_11); return; } - - bb9: { - unreachable; - } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir index 0d692251051e..35fee449c35c 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.panic-unwind.mir @@ -4,121 +4,12 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 { debug a => _1; debug b => _2; let mut _0: u16; - scope 1 (inlined core::num::::unchecked_shl) { - debug self => _1; - debug rhs => _2; - let mut _11: u16; - scope 2 { - scope 3 (inlined core::num::::unchecked_shl::conv) { - debug x => _2; - let mut _6: std::result::Result; - let mut _9: std::option::Option; - scope 4 { - scope 5 (inlined >::try_into) { - debug self => _2; - scope 6 (inlined convert::num:: for u16>::try_from) { - debug u => _2; - let mut _3: u32; - let mut _4: bool; - let mut _5: u16; - } - } - scope 7 (inlined Result::::ok) { - debug self => _6; - let mut _7: isize; - let _8: u16; - scope 8 { - debug x => _8; - } - } - scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { - debug self => _9; - let mut _10: isize; - let mut _12: &std::option::Option; - scope 10 { - debug val => _11; - } - scope 11 { - scope 13 (inlined unreachable_unchecked) { - scope 14 { - scope 15 (inlined unreachable_unchecked::runtime) { - } - } - } - } - scope 12 (inlined Option::::is_some) { - debug self => _12; - } - } - } - } - } - } bb0: { - StorageLive(_11); - StorageLive(_9); - StorageLive(_6); - StorageLive(_4); - StorageLive(_3); - _3 = const 65535_u32; - _4 = Gt(_2, move _3); - StorageDead(_3); - switchInt(move _4) -> [0: bb1, otherwise: bb2]; + _0 = core::num::::unchecked_shl(_1, _2) -> bb1; } bb1: { - StorageLive(_5); - _5 = _2 as u16 (IntToInt); - _6 = Result::::Ok(move _5); - StorageDead(_5); - goto -> bb3; - } - - bb2: { - _6 = Result::::Err(const TryFromIntError(())); - goto -> bb3; - } - - bb3: { - StorageDead(_4); - StorageLive(_8); - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb9]; - } - - bb4: { - _8 = move ((_6 as Ok).0: u16); - _9 = Option::::Some(move _8); - goto -> bb6; - } - - bb5: { - _9 = Option::::None; - goto -> bb6; - } - - bb6: { - StorageDead(_8); - StorageDead(_6); - StorageLive(_12); - _10 = discriminant(_9); - switchInt(move _10) -> [1: bb7, otherwise: bb9]; - } - - bb7: { - _11 = move ((_9 as Some).0: u16); - StorageDead(_12); - StorageDead(_9); - _0 = unchecked_shl::(_1, move _11) -> [return: bb8, unwind unreachable]; - } - - bb8: { - StorageDead(_11); return; } - - bb9: { - unreachable; - } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff index 61155f5078ff..1659a51b090d 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-abort.diff @@ -7,129 +7,19 @@ let mut _0: i16; let mut _3: i16; let mut _4: u32; -+ scope 1 (inlined core::num::::unchecked_shr) { -+ debug self => _3; -+ debug rhs => _4; -+ let mut _5: i16; -+ scope 2 { -+ scope 3 (inlined core::num::::unchecked_shr::conv) { -+ debug x => _4; -+ let mut _6: std::option::Option; -+ let mut _7: std::result::Result; -+ scope 4 { -+ scope 5 (inlined >::try_into) { -+ debug self => _4; -+ scope 6 (inlined convert::num:: for i16>::try_from) { -+ debug u => _4; -+ let mut _8: bool; -+ let mut _9: u32; -+ let mut _10: i16; -+ } -+ } -+ scope 7 (inlined Result::::ok) { -+ debug self => _7; -+ let mut _11: isize; -+ let _12: i16; -+ scope 8 { -+ debug x => _12; -+ } -+ } -+ scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { -+ debug self => _6; -+ let mut _13: &std::option::Option; -+ let mut _14: isize; -+ scope 10 { -+ debug val => _5; -+ } -+ scope 11 { -+ scope 13 (inlined unreachable_unchecked) { -+ scope 14 { -+ scope 15 (inlined unreachable_unchecked::runtime) { -+ } -+ } -+ } -+ } -+ scope 12 (inlined Option::::is_some) { -+ debug self => _13; -+ } -+ } -+ } -+ } -+ } -+ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable]; -+ StorageLive(_5); -+ StorageLive(_6); -+ StorageLive(_7); -+ StorageLive(_8); -+ StorageLive(_9); -+ _9 = const 32767_u32; -+ _8 = Gt(_4, move _9); -+ StorageDead(_9); -+ switchInt(move _8) -> [0: bb3, otherwise: bb2]; + _0 = core::num::::unchecked_shr(move _3, move _4) -> [return: bb1, unwind unreachable]; } bb1: { -+ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; -+ } -+ -+ bb2: { -+ _7 = Result::::Err(const TryFromIntError(())); -+ goto -> bb4; -+ } -+ -+ bb3: { -+ StorageLive(_10); -+ _10 = _4 as i16 (IntToInt); -+ _7 = Result::::Ok(move _10); -+ StorageDead(_10); -+ goto -> bb4; -+ } -+ -+ bb4: { -+ StorageDead(_8); -+ StorageLive(_12); -+ _11 = discriminant(_7); -+ switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; -+ } -+ -+ bb5: { -+ _6 = Option::::None; -+ goto -> bb8; -+ } -+ -+ bb6: { -+ unreachable; -+ } -+ -+ bb7: { -+ _12 = move ((_7 as Ok).0: i16); -+ _6 = Option::::Some(move _12); -+ goto -> bb8; -+ } -+ -+ bb8: { -+ StorageDead(_12); -+ StorageDead(_7); -+ StorageLive(_13); -+ _14 = discriminant(_6); -+ switchInt(move _14) -> [1: bb9, otherwise: bb6]; -+ } -+ -+ bb9: { -+ _5 = move ((_6 as Some).0: i16); -+ StorageDead(_13); -+ StorageDead(_6); -+ _0 = unchecked_shr::(_3, move _5) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff index 181a423164b2..cb5ec37feb36 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.panic-unwind.diff @@ -7,129 +7,19 @@ let mut _0: i16; let mut _3: i16; let mut _4: u32; -+ scope 1 (inlined core::num::::unchecked_shr) { -+ debug self => _3; -+ debug rhs => _4; -+ let mut _5: i16; -+ scope 2 { -+ scope 3 (inlined core::num::::unchecked_shr::conv) { -+ debug x => _4; -+ let mut _6: std::option::Option; -+ let mut _7: std::result::Result; -+ scope 4 { -+ scope 5 (inlined >::try_into) { -+ debug self => _4; -+ scope 6 (inlined convert::num:: for i16>::try_from) { -+ debug u => _4; -+ let mut _8: bool; -+ let mut _9: u32; -+ let mut _10: i16; -+ } -+ } -+ scope 7 (inlined Result::::ok) { -+ debug self => _7; -+ let mut _11: isize; -+ let _12: i16; -+ scope 8 { -+ debug x => _12; -+ } -+ } -+ scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { -+ debug self => _6; -+ let mut _13: &std::option::Option; -+ let mut _14: isize; -+ scope 10 { -+ debug val => _5; -+ } -+ scope 11 { -+ scope 13 (inlined unreachable_unchecked) { -+ scope 14 { -+ scope 15 (inlined unreachable_unchecked::runtime) { -+ } -+ } -+ } -+ } -+ scope 12 (inlined Option::::is_some) { -+ debug self => _13; -+ } -+ } -+ } -+ } -+ } -+ } bb0: { StorageLive(_3); _3 = _1; StorageLive(_4); _4 = _2; -- _0 = core::num::::unchecked_shr(move _3, move _4) -> bb1; -+ StorageLive(_5); -+ StorageLive(_6); -+ StorageLive(_7); -+ StorageLive(_8); -+ StorageLive(_9); -+ _9 = const 32767_u32; -+ _8 = Gt(_4, move _9); -+ StorageDead(_9); -+ switchInt(move _8) -> [0: bb3, otherwise: bb2]; + _0 = core::num::::unchecked_shr(move _3, move _4) -> bb1; } bb1: { -+ StorageDead(_5); StorageDead(_4); StorageDead(_3); return; -+ } -+ -+ bb2: { -+ _7 = Result::::Err(const TryFromIntError(())); -+ goto -> bb4; -+ } -+ -+ bb3: { -+ StorageLive(_10); -+ _10 = _4 as i16 (IntToInt); -+ _7 = Result::::Ok(move _10); -+ StorageDead(_10); -+ goto -> bb4; -+ } -+ -+ bb4: { -+ StorageDead(_8); -+ StorageLive(_12); -+ _11 = discriminant(_7); -+ switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; -+ } -+ -+ bb5: { -+ _6 = Option::::None; -+ goto -> bb8; -+ } -+ -+ bb6: { -+ unreachable; -+ } -+ -+ bb7: { -+ _12 = move ((_7 as Ok).0: i16); -+ _6 = Option::::Some(move _12); -+ goto -> bb8; -+ } -+ -+ bb8: { -+ StorageDead(_12); -+ StorageDead(_7); -+ StorageLive(_13); -+ _14 = discriminant(_6); -+ switchInt(move _14) -> [1: bb9, otherwise: bb6]; -+ } -+ -+ bb9: { -+ _5 = move ((_6 as Some).0: i16); -+ StorageDead(_13); -+ StorageDead(_6); -+ _0 = unchecked_shr::(_3, move _5) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir index 66936df380bc..9f2f40002a32 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-abort.mir @@ -4,121 +4,12 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 { debug a => _1; debug b => _2; let mut _0: i16; - scope 1 (inlined core::num::::unchecked_shr) { - debug self => _1; - debug rhs => _2; - let mut _11: i16; - scope 2 { - scope 3 (inlined core::num::::unchecked_shr::conv) { - debug x => _2; - let mut _6: std::result::Result; - let mut _9: std::option::Option; - scope 4 { - scope 5 (inlined >::try_into) { - debug self => _2; - scope 6 (inlined convert::num:: for i16>::try_from) { - debug u => _2; - let mut _3: u32; - let mut _4: bool; - let mut _5: i16; - } - } - scope 7 (inlined Result::::ok) { - debug self => _6; - let mut _7: isize; - let _8: i16; - scope 8 { - debug x => _8; - } - } - scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { - debug self => _9; - let mut _10: isize; - let mut _12: &std::option::Option; - scope 10 { - debug val => _11; - } - scope 11 { - scope 13 (inlined unreachable_unchecked) { - scope 14 { - scope 15 (inlined unreachable_unchecked::runtime) { - } - } - } - } - scope 12 (inlined Option::::is_some) { - debug self => _12; - } - } - } - } - } - } bb0: { - StorageLive(_11); - StorageLive(_9); - StorageLive(_6); - StorageLive(_4); - StorageLive(_3); - _3 = const 32767_u32; - _4 = Gt(_2, move _3); - StorageDead(_3); - switchInt(move _4) -> [0: bb1, otherwise: bb2]; + _0 = core::num::::unchecked_shr(_1, _2) -> [return: bb1, unwind unreachable]; } bb1: { - StorageLive(_5); - _5 = _2 as i16 (IntToInt); - _6 = Result::::Ok(move _5); - StorageDead(_5); - goto -> bb3; - } - - bb2: { - _6 = Result::::Err(const TryFromIntError(())); - goto -> bb3; - } - - bb3: { - StorageDead(_4); - StorageLive(_8); - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb9]; - } - - bb4: { - _8 = move ((_6 as Ok).0: i16); - _9 = Option::::Some(move _8); - goto -> bb6; - } - - bb5: { - _9 = Option::::None; - goto -> bb6; - } - - bb6: { - StorageDead(_8); - StorageDead(_6); - StorageLive(_12); - _10 = discriminant(_9); - switchInt(move _10) -> [1: bb7, otherwise: bb9]; - } - - bb7: { - _11 = move ((_9 as Some).0: i16); - StorageDead(_12); - StorageDead(_9); - _0 = unchecked_shr::(_1, move _11) -> [return: bb8, unwind unreachable]; - } - - bb8: { - StorageDead(_11); return; } - - bb9: { - unreachable; - } } diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir index 66936df380bc..aaf3bb62e8a3 100644 --- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.panic-unwind.mir @@ -4,121 +4,12 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 { debug a => _1; debug b => _2; let mut _0: i16; - scope 1 (inlined core::num::::unchecked_shr) { - debug self => _1; - debug rhs => _2; - let mut _11: i16; - scope 2 { - scope 3 (inlined core::num::::unchecked_shr::conv) { - debug x => _2; - let mut _6: std::result::Result; - let mut _9: std::option::Option; - scope 4 { - scope 5 (inlined >::try_into) { - debug self => _2; - scope 6 (inlined convert::num:: for i16>::try_from) { - debug u => _2; - let mut _3: u32; - let mut _4: bool; - let mut _5: i16; - } - } - scope 7 (inlined Result::::ok) { - debug self => _6; - let mut _7: isize; - let _8: i16; - scope 8 { - debug x => _8; - } - } - scope 9 (inlined #[track_caller] Option::::unwrap_unchecked) { - debug self => _9; - let mut _10: isize; - let mut _12: &std::option::Option; - scope 10 { - debug val => _11; - } - scope 11 { - scope 13 (inlined unreachable_unchecked) { - scope 14 { - scope 15 (inlined unreachable_unchecked::runtime) { - } - } - } - } - scope 12 (inlined Option::::is_some) { - debug self => _12; - } - } - } - } - } - } bb0: { - StorageLive(_11); - StorageLive(_9); - StorageLive(_6); - StorageLive(_4); - StorageLive(_3); - _3 = const 32767_u32; - _4 = Gt(_2, move _3); - StorageDead(_3); - switchInt(move _4) -> [0: bb1, otherwise: bb2]; + _0 = core::num::::unchecked_shr(_1, _2) -> bb1; } bb1: { - StorageLive(_5); - _5 = _2 as i16 (IntToInt); - _6 = Result::::Ok(move _5); - StorageDead(_5); - goto -> bb3; - } - - bb2: { - _6 = Result::::Err(const TryFromIntError(())); - goto -> bb3; - } - - bb3: { - StorageDead(_4); - StorageLive(_8); - _7 = discriminant(_6); - switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb9]; - } - - bb4: { - _8 = move ((_6 as Ok).0: i16); - _9 = Option::::Some(move _8); - goto -> bb6; - } - - bb5: { - _9 = Option::::None; - goto -> bb6; - } - - bb6: { - StorageDead(_8); - StorageDead(_6); - StorageLive(_12); - _10 = discriminant(_9); - switchInt(move _10) -> [1: bb7, otherwise: bb9]; - } - - bb7: { - _11 = move ((_9 as Some).0: i16); - StorageDead(_12); - StorageDead(_9); - _0 = unchecked_shr::(_1, move _11) -> [return: bb8, unwind unreachable]; - } - - bb8: { - StorageDead(_11); return; } - - bb9: { - unreachable; - } } From 4fdd07fe88c8965daea60c5109913095e3042c9c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 13 Mar 2023 13:33:39 +0000 Subject: [PATCH 33/41] Merge the orphan logic for all alias kinds --- .../src/coherence/orphan.rs | 52 ++++++++----------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 23beacd2a8c2..c270bebd6789 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -200,35 +200,29 @@ fn do_orphan_check_impl<'tcx>( NonlocalImpl::DisallowOther, ), - // trait Id { type This: ?Sized; } - // impl Id for T { - // type This = T; - // } - // impl AutoTrait for ::This {} - ty::Alias(AliasKind::Projection, _) => ( - LocalImpl::Disallow { problematic_kind: "associated type" }, - NonlocalImpl::DisallowOther, - ), - - // ``` - // struct S(T); - // impl S { - // type This = T; - // } - // impl AutoTrait for S::This {} - // ``` - // FIXME(inherent_associated_types): The example code above currently leads to a cycle - ty::Alias(AliasKind::Inherent, _) => ( - LocalImpl::Disallow { problematic_kind: "associated type" }, - NonlocalImpl::DisallowOther, - ), - - // type Opaque = impl Trait; - // impl AutoTrait for Opaque {} - ty::Alias(AliasKind::Opaque, _) => ( - LocalImpl::Disallow { problematic_kind: "opaque type" }, - NonlocalImpl::DisallowOther, - ), + ty::Alias(kind, _) => { + let problematic_kind = match kind { + // trait Id { type This: ?Sized; } + // impl Id for T { + // type This = T; + // } + // impl AutoTrait for ::This {} + AliasKind::Projection => "associated type", + // type Opaque = impl Trait; + // impl AutoTrait for Opaque {} + AliasKind::Opaque => "opaque type", + // ``` + // struct S(T); + // impl S { + // type This = T; + // } + // impl AutoTrait for S::This {} + // ``` + // FIXME(inherent_associated_types): The example code above currently leads to a cycle + AliasKind::Inherent => "associated type", + }; + (LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther) + } ty::Bool | ty::Char From f3b7dd6388503ef555f4dbf027d6075ee5c8b3ee Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 7 Mar 2023 12:03:11 +0000 Subject: [PATCH 34/41] Add `AliasKind::Weak` for type aliases. Only use it when the type alias contains an opaque type. Also does wf-checking on such type aliases. --- .../rustc_const_eval/src/util/type_name.rs | 1 + .../rustc_hir_analysis/src/astconv/mod.rs | 14 ++++++- .../rustc_hir_analysis/src/check/wfcheck.rs | 40 ++++++++++++++----- .../src/coherence/orphan.rs | 3 ++ .../src/collect/item_bounds.rs | 1 + .../rustc_hir_analysis/src/hir_wf_check.rs | 4 +- .../src/infer/error_reporting/mod.rs | 1 + compiler/rustc_lint/src/builtin.rs | 4 +- compiler/rustc_lint/src/types.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 10 +++++ compiler/rustc_middle/src/traits/mod.rs | 3 ++ compiler/rustc_middle/src/ty/context.rs | 1 + compiler/rustc_middle/src/ty/error.rs | 1 + compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/relate.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 1 + compiler/rustc_privacy/src/lib.rs | 3 ++ compiler/rustc_symbol_mangling/src/v0.rs | 1 + .../src/solve/assembly/mod.rs | 3 +- .../src/solve/assembly/structural_traits.rs | 2 +- .../rustc_trait_selection/src/solve/mod.rs | 1 + .../src/solve/project_goals.rs | 1 + .../src/solve/trait_goals.rs | 2 +- .../src/solve/weak_types.rs | 19 +++++++++ .../src/traits/coherence.rs | 4 +- .../src/traits/error_reporting/mod.rs | 13 +++--- .../src/traits/error_reporting/suggestions.rs | 23 +++++++++++ .../src/traits/outlives_bounds.rs | 2 +- .../src/traits/project.rs | 27 ++++++++++++- .../src/traits/query/normalize.rs | 3 +- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/confirmation.rs | 2 +- .../src/traits/select/mod.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 5 +++ compiler/rustc_traits/src/chalk/lowering.rs | 1 + .../src/normalize_projection_ty.rs | 34 +++++++++++++++- compiler/rustc_type_ir/src/sty.rs | 8 ++++ src/librustdoc/clean/mod.rs | 5 +++ .../clippy/clippy_lints/src/dereference.rs | 1 + .../clippy/tests/ui/from_over_into.fixed | 6 --- src/tools/clippy/tests/ui/from_over_into.rs | 6 --- .../tests/ui/from_over_into_unfixable.rs | 6 +++ .../tests/ui/from_over_into_unfixable.stderr | 33 ++++----------- src/tools/clippy/tests/ui/new_ret_no_self.rs | 22 ---------- .../clippy/tests/ui/new_ret_no_self.stderr | 18 +-------- .../tests/ui/new_ret_no_self_overflow.rs | 26 ++++++++++++ .../tests/ui/new_ret_no_self_overflow.stderr | 9 +++++ .../nested-return-type2-tait.stderr | 4 -- .../nested-return-type3-tait.stderr | 4 -- .../nested-return-type3-tait2.stderr | 4 -- ...ias-impl-trait-declaration-too-subtle-2.rs | 3 +- ...impl-trait-declaration-too-subtle-2.stderr | 15 ------- ...s-impl-trait-declaration-too-subtle.stderr | 5 +++ ...rsive-type-alias-impl-trait-declaration.rs | 3 +- ...e-type-alias-impl-trait-declaration.stderr | 15 +++++++ tests/ui/lint/lint-ctypes-73249-2.rs | 8 ++-- tests/ui/lint/lint-ctypes-73249-2.stderr | 6 +-- tests/ui/lint/lint-ctypes-73251-1.rs | 6 +-- tests/ui/lint/lint-ctypes-73251-1.stderr | 6 +-- tests/ui/lint/lint-ctypes-73251-2.rs | 2 +- tests/ui/lint/lint-ctypes-73251-2.stderr | 6 +-- tests/ui/lint/lint-ctypes-73251.rs | 4 +- tests/ui/lint/opaque-ty-ffi-unsafe.rs | 4 +- tests/ui/lint/opaque-ty-ffi-unsafe.stderr | 6 +-- .../auto-trait-leakage.rs | 4 +- .../bounds-are-checked3.rs | 16 ++++++++ .../bounds-are-checked3.stderr | 20 ++++++++++ tests/ui/type-alias-impl-trait/bounds.rs | 16 ++++++++ .../ui/type-alias-impl-trait/coherence.stderr | 2 +- .../defining-use-submodule.rs | 6 +-- .../generic_underconstrained.stderr | 4 +- .../generic_underconstrained2.stderr | 8 ++-- .../impl_for_weak_alias.rs | 14 +++++++ .../impl_for_weak_alias.stderr | 11 +++++ .../issue-53398-cyclic-types.rs | 3 +- .../issue-53398-cyclic-types.stderr | 12 ------ .../type-alias-impl-trait/obligation_ice.rs | 17 ++++++++ tests/ui/type-alias-impl-trait/privacy.rs | 8 ++++ tests/ui/type-alias-impl-trait/privacy.stderr | 11 +++++ .../self-referential-3.rs | 2 +- .../self-referential-3.stderr | 15 +++++++ .../type-alias-impl-trait/self-referential.rs | 2 +- .../self-referential.stderr | 6 +-- .../type-alias-impl-trait-fns.rs | 8 ++-- .../unnameable_type.stderr | 5 +++ 86 files changed, 474 insertions(+), 199 deletions(-) create mode 100644 compiler/rustc_trait_selection/src/solve/weak_types.rs create mode 100644 src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs create mode 100644 src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr delete mode 100644 tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr create mode 100644 tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr create mode 100644 tests/ui/type-alias-impl-trait/bounds-are-checked3.rs create mode 100644 tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr create mode 100644 tests/ui/type-alias-impl-trait/bounds.rs create mode 100644 tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs create mode 100644 tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr delete mode 100644 tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr create mode 100644 tests/ui/type-alias-impl-trait/obligation_ice.rs create mode 100644 tests/ui/type-alias-impl-trait/privacy.rs create mode 100644 tests/ui/type-alias-impl-trait/privacy.stderr create mode 100644 tests/ui/type-alias-impl-trait/self-referential-3.stderr diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 11ad5b49df2e..4f01e0a24a5d 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -63,6 +63,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), + ty::Alias(ty::Weak, _) => bug!("type_name: unexpected weak projection"), ty::Alias(ty::Inherent, _) => bug!("type_name: unexpected inherent projection"), ty::GeneratorWitness(_) => bug!("type_name: unexpected `GeneratorWitness`"), ty::GeneratorWitnessMIR(..) => bug!("type_name: unexpected `GeneratorWitnessMIR`"), diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 1037a49acdf3..8afa0a46d32f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1458,7 +1458,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment: &hir::PathSegment<'_>, ) -> Ty<'tcx> { let substs = self.ast_path_substs_for_ty(span, did, item_segment); - self.tcx().at(span).type_of(did).subst(self.tcx(), substs) + let ty = self.tcx().at(span).type_of(did); + + if matches!(self.tcx().def_kind(did), DefKind::TyAlias) + && ty.skip_binder().has_opaque_types() + { + // Type aliases referring to types that contain opaque types (but aren't just directly + // referencing a single opaque type) get encoded as a type alias that normalization will + // then actually instantiate the where bounds of. + let alias_ty = self.tcx().mk_alias_ty(did, substs); + self.tcx().mk_alias(ty::Weak, alias_ty) + } else { + ty.subst(self.tcx(), substs) + } } fn conv_object_ty_poly_trait_ref( diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4554d167080b..f93f395caed6 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -217,10 +217,10 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { check_item_fn(tcx, def_id, item.ident, item.span, sig.decl); } hir::ItemKind::Static(ty, ..) => { - check_item_type(tcx, def_id, ty.span, false); + check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid); } hir::ItemKind::Const(ty, ..) => { - check_item_type(tcx, def_id, ty.span, false); + check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid); } hir::ItemKind::Struct(_, ast_generics) => { check_type_defn(tcx, item, false); @@ -242,6 +242,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { } // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => {} + hir::ItemKind::TyAlias(hir_ty, ..) => { + if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() { + // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);` + check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow); + } + } _ => {} } } @@ -258,7 +264,9 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { hir::ForeignItemKind::Fn(decl, ..) => { check_item_fn(tcx, def_id, item.ident, item.span, decl) } - hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true), + hir::ForeignItemKind::Static(ty, ..) => { + check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail) + } hir::ForeignItemKind::Type => (), } } @@ -1100,20 +1108,32 @@ fn check_item_fn( }) } -fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_foreign_ty: bool) { +enum UnsizedHandling { + Forbid, + Allow, + AllowIfForeignTail, +} + +fn check_item_type( + tcx: TyCtxt<'_>, + item_id: LocalDefId, + ty_span: Span, + unsized_handling: UnsizedHandling, +) { debug!("check_item_type: {:?}", item_id); enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| { let ty = tcx.type_of(item_id).subst_identity(); let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty); - let mut forbid_unsized = true; - if allow_foreign_ty { - let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env); - if let ty::Foreign(_) = tail.kind() { - forbid_unsized = false; + let forbid_unsized = match unsized_handling { + UnsizedHandling::Forbid => true, + UnsizedHandling::Allow => false, + UnsizedHandling::AllowIfForeignTail => { + let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env); + !matches!(tail.kind(), ty::Foreign(_)) } - } + }; wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into()); if forbid_unsized { diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index c270bebd6789..eb299a1ea799 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -208,6 +208,9 @@ fn do_orphan_check_impl<'tcx>( // } // impl AutoTrait for ::This {} AliasKind::Projection => "associated type", + // type Foo = (impl Sized, bool) + // impl AutoTrait for Foo {} + AliasKind::Weak => "type alias", // type Opaque = impl Trait; // impl AutoTrait for Opaque {} AliasKind::Opaque => "opaque type", diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index b92d561fb86a..90e8e523ea3e 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -122,6 +122,7 @@ pub(super) fn explicit_item_bounds( }; opaque_type_bounds(tcx, def_id, bounds, item_ty, *span) } + hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[], _ => bug!("item_bounds called on {:?}", def_id), }; ty::EarlyBinder::bind(bounds) diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index e4c6e6e391a1..a653a6522313 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -128,7 +128,9 @@ fn diagnostic_hir_wf_check<'tcx>( ref item => bug!("Unexpected TraitItem {:?}", item), }, hir::Node::Item(item) => match item.kind { - hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => vec![ty], + hir::ItemKind::TyAlias(ty, _) + | hir::ItemKind::Static(ty, _, _) + | hir::ItemKind::Const(ty, _) => vec![ty], hir::ItemKind::Impl(impl_) => match &impl_.of_trait { Some(t) => t .path diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 3e4812e7ca99..fc1f90fdc13f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2375,6 +2375,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ty::AliasKind::Projection | ty::AliasKind::Inherent => { format!("the associated type `{}`", p) } + ty::AliasKind::Weak => format!("the type alias `{}`", p), ty::AliasKind::Opaque => format!("the opaque type `{}`", p), }, }; diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 7b05bff51514..f02f3668dc1f 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1465,8 +1465,8 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { let hir::ItemKind::TyAlias(ty, type_alias_generics) = &item.kind else { return }; - if let hir::TyKind::OpaqueDef(..) = ty.kind { - // Bounds are respected for `type X = impl Trait` + if cx.tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() { + // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);` return; } if cx.tcx.type_of(item.owner_id).skip_binder().has_inherent_projections() { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index ec9e7c7fdae8..9a2d45ccd663 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1255,7 +1255,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } ty::Param(..) - | ty::Alias(ty::Projection | ty::Inherent, ..) + | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Infer(..) | ty::Bound(..) | ty::Error(_) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a6c8d41e925f..132b11b29eb3 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1903,6 +1903,16 @@ rustc_queries! { desc { "normalizing `{}`", goal.value.value } } + /// Do not call this query directly: invoke `normalize` instead. + query normalize_weak_ty( + goal: CanonicalProjectionGoal<'tcx> + ) -> Result< + &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, + NoSolution, + > { + desc { "normalizing `{}`", goal.value.value } + } + /// Do not call this query directly: invoke `normalize` instead. query normalize_inherent_projection_ty( goal: CanonicalProjectionGoal<'tcx> diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index bf3872e81d4a..b63e049a520c 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -448,6 +448,9 @@ pub enum ObligationCauseCode<'tcx> { /// Requirement for a `const N: Ty` to implement `Ty: ConstParamTy` ConstParam(Ty<'tcx>), + + /// Obligations emitted during the normalization of a weak type alias. + TypeAlias(InternedObligationCauseCode<'tcx>, Span, DefId), } /// The 'location' at which we try to perform HIR-based wf checking. diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4ee543bbfb6d..449129b84188 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2012,6 +2012,7 @@ impl<'tcx> TyCtxt<'tcx> { (ty::Opaque, DefKind::OpaqueTy) | (ty::Projection | ty::Inherent, DefKind::AssocTy) | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder) + | (ty::Weak, DefKind::TyAlias) ); self.mk_ty_from_kind(Alias(kind, alias_ty)) } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 66293f19eef6..c794c3faded1 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -300,6 +300,7 @@ impl<'tcx> Ty<'tcx> { ty::Placeholder(..) => "higher-ranked type".into(), ty::Bound(..) => "bound type variable".into(), ty::Alias(ty::Projection | ty::Inherent, _) => "associated type".into(), + ty::Alias(ty::Weak, _) => "type alias".into(), ty::Param(_) => "type parameter".into(), ty::Alias(ty::Opaque, ..) => "opaque type".into(), } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index d64875a9f00e..9cce9d64d5d2 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -178,7 +178,7 @@ impl FlagComputation { &ty::Alias(kind, data) => { self.add_flags(match kind { - ty::Projection => TypeFlags::HAS_TY_PROJECTION, + ty::Weak | ty::Projection => TypeFlags::HAS_TY_PROJECTION, ty::Inherent => TypeFlags::HAS_TY_INHERENT, ty::Opaque => TypeFlags::HAS_TY_OPAQUE, }); diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6156fdf7eac2..f36b8ad8df6c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -731,7 +731,7 @@ pub trait PrettyPrinter<'tcx>: ty::Foreign(def_id) => { p!(print_def_path(def_id, &[])); } - ty::Alias(ty::Projection | ty::Inherent, ref data) => { + ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ref data) => { if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get())) && self.tcx().is_impl_trait_in_trait(data.def_id) { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 8bcae3d9ab7c..74a3bddf2fae 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -391,13 +391,13 @@ impl<'tcx> Relate<'tcx> for Ty<'tcx> { /// Relates `a` and `b` structurally, calling the relation for all nested values. /// Any semantic equality, e.g. of projections, and inference variables have to be /// handled by the caller. +#[instrument(level = "trace", skip(relation), ret)] pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( relation: &mut R, a: Ty<'tcx>, b: Ty<'tcx>, ) -> RelateResult<'tcx, Ty<'tcx>> { let tcx = relation.tcx(); - debug!("structurally_relate_tys: a={:?} b={:?}", a, b); match (a.kind(), b.kind()) { (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { // The caller should handle these cases! diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index d19a7bcde79b..5f2f241bc0dc 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1231,6 +1231,7 @@ impl<'tcx> AliasTy<'tcx> { DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent, DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection, DefKind::OpaqueTy => ty::Opaque, + DefKind::TyAlias => ty::Weak, kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index a51a1c9a8a43..5ef11acadced 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -242,6 +242,9 @@ where } } } + ty::Alias(ty::Weak, alias) => { + self.def_id_visitor.visit_def_id(alias.def_id, "type alias", &ty); + } ty::Alias(ty::Projection, proj) => { if self.def_id_visitor.skip_assoc_tys() { // Visitors searching for minimal visibility/reachability want to diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 0a805e2422d4..5dc00e317863 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -483,6 +483,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { } ty::Alias(ty::Inherent, _) => bug!("symbol_names: unexpected inherent projection"), + ty::Alias(ty::Weak, _) => bug!("symbol_names: unexpected weak projection"), ty::GeneratorWitness(_) => bug!("symbol_names: unexpected `GeneratorWitness`"), ty::GeneratorWitnessMIR(..) => bug!("symbol_names: unexpected `GeneratorWitnessMIR`"), } diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index 1b749b9c854c..7ada389edbe6 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -508,10 +508,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::Placeholder(..) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Alias(ty::Inherent, _) + | ty::Alias(ty::Weak, _) | ty::Error(_) => return, ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) | ty::Bound(..) => bug!("unexpected self type for `{goal:?}`"), - // Excluding IATs here as they don't have meaningful item bounds. + // Excluding IATs and type aliases here as they don't have meaningful item bounds. ty::Alias(ty::Projection | ty::Opaque, alias_ty) => alias_ty, }; diff --git a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs index 0f3f8f1ac2cb..97b86a06c8ca 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/structural_traits.rs @@ -33,7 +33,7 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>( ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) - | ty::Alias(ty::Projection | ty::Inherent, ..) + | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => { diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index f4c29c837b88..a30a14df80b0 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -29,6 +29,7 @@ mod opaques; mod project_goals; mod search_graph; mod trait_goals; +mod weak_types; pub use eval_ctxt::{EvalCtxt, InferCtxtEvalExt}; pub use fulfill::FulfillmentCtxt; diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index 242f9ba87473..17f3404268d7 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -57,6 +57,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } DefKind::AnonConst => self.normalize_anon_const(goal), DefKind::OpaqueTy => self.normalize_opaque_type(goal), + DefKind::TyAlias => self.normalize_weak_type(goal), kind => bug!("unknown DefKind {} in projection goal: {goal:#?}", kind.descr(def_id)), } } diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index f722f281314e..a212cc9453aa 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -618,7 +618,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) - | ty::Alias(ty::Projection | ty::Inherent, ..) + | ty::Alias(ty::Projection | ty::Weak | ty::Inherent, ..) | ty::Placeholder(..) => Some(Err(NoSolution)), ty::Infer(_) | ty::Bound(_, _) => bug!("unexpected type `{self_ty}`"), diff --git a/compiler/rustc_trait_selection/src/solve/weak_types.rs b/compiler/rustc_trait_selection/src/solve/weak_types.rs new file mode 100644 index 000000000000..b095b54c554f --- /dev/null +++ b/compiler/rustc_trait_selection/src/solve/weak_types.rs @@ -0,0 +1,19 @@ +use rustc_middle::traits::solve::{Certainty, Goal, QueryResult}; +use rustc_middle::ty; + +use super::EvalCtxt; + +impl<'tcx> EvalCtxt<'_, 'tcx> { + pub(super) fn normalize_weak_type( + &mut self, + goal: Goal<'tcx, ty::ProjectionPredicate<'tcx>>, + ) -> QueryResult<'tcx> { + let tcx = self.tcx(); + let weak_ty = goal.predicate.projection_ty; + let expected = goal.predicate.term.ty().expect("no such thing as a const alias"); + + let actual = tcx.type_of(weak_ty.def_id).subst(tcx, weak_ty.substs); + self.eq(goal.param_env, expected, actual)?; + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } +} diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 3193d00e11b2..0065c7fc253b 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -695,7 +695,9 @@ impl<'tcx> TypeVisitor> for OrphanChecker<'tcx> { | ty::RawPtr(..) | ty::Never | ty::Tuple(..) - | ty::Alias(ty::Projection | ty::Inherent, ..) => self.found_non_local_ty(ty), + | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) => { + self.found_non_local_ty(ty) + } ty::Param(..) => self.found_param_ty(ty), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 1bc4599377aa..ffbe2888bf84 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1824,12 +1824,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ty::Alias(ty::Projection, ..) => Some(12), ty::Alias(ty::Inherent, ..) => Some(13), ty::Alias(ty::Opaque, ..) => Some(14), - ty::Never => Some(15), - ty::Adt(..) => Some(16), - ty::Generator(..) => Some(17), - ty::Foreign(..) => Some(18), - ty::GeneratorWitness(..) => Some(19), - ty::GeneratorWitnessMIR(..) => Some(20), + ty::Alias(ty::Weak, ..) => Some(15), + ty::Never => Some(16), + ty::Adt(..) => Some(17), + ty::Generator(..) => Some(18), + ty::Foreign(..) => Some(19), + ty::GeneratorWitness(..) => Some(20), + ty::GeneratorWitnessMIR(..) => Some(21), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error(_) => None, } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 5783383e93e3..fcf813e3a393 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -3198,6 +3198,29 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) }); } + ObligationCauseCode::TypeAlias(ref nested, span, def_id) => { + // #74711: avoid a stack overflow + ensure_sufficient_stack(|| { + self.note_obligation_cause_code( + body_id, + err, + predicate, + param_env, + nested, + obligated_types, + seen_requirements, + ) + }); + let mut multispan = MultiSpan::from(span); + multispan.push_span_label(span, "required by this bound"); + err.span_note( + multispan, + format!( + "required by a bound on the type alias `{}`", + self.infcx.tcx.item_name(def_id) + ), + ); + } ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, call_hir_id, diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs index f8d056e321e6..ff55eaf13ad5 100644 --- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs +++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs @@ -9,7 +9,7 @@ use rustc_span::def_id::LocalDefId; pub use rustc_middle::traits::query::OutlivesBound; -type Bounds<'a, 'tcx: 'a> = impl Iterator> + 'a; +pub type Bounds<'a, 'tcx: 'a> = impl Iterator> + 'a; pub trait InferCtxtExt<'a, 'tcx> { fn implied_outlives_bounds( &self, diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 0a1e971f268e..8466b3fc9545 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -31,6 +31,7 @@ use rustc_infer::infer::at::At; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::ImplSourceBuiltinData; +use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt}; @@ -621,6 +622,30 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx ); normalized_ty } + ty::Weak => { + let infcx = self.selcx.infcx; + self.obligations.extend( + infcx + .tcx + .predicates_of(data.def_id) + .instantiate_own(infcx.tcx, data.substs) + .map(|(mut predicate, span)| { + if data.has_escaping_bound_vars() { + (predicate, ..) = BoundVarReplacer::replace_bound_vars( + infcx, + &mut self.universes, + predicate, + ); + } + let mut cause = self.cause.clone(); + cause.map_code(|code| { + ObligationCauseCode::TypeAlias(code, span, data.def_id) + }); + Obligation::new(infcx.tcx, cause, self.param_env, predicate) + }), + ); + infcx.tcx.type_of(data.def_id).subst(infcx.tcx, data.substs).fold_with(self) + } ty::Inherent if !data.has_escaping_bound_vars() => { // This branch is *mostly* just an optimization: when we don't @@ -1545,7 +1570,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( // Check whether the self-type is itself a projection. // If so, extract what we know from the trait and try to come up with a good answer. let bounds = match *obligation.predicate.self_ty().kind() { - // Excluding IATs here as they don't have meaningful item bounds. + // Excluding IATs and type aliases here as they don't have meaningful item bounds. ty::Alias(ty::Projection | ty::Opaque, ref data) => { tcx.item_bounds(data.def_id).subst(tcx, data.substs) } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 8bf934cb78ae..2d97a8082258 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -257,7 +257,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> ty::Opaque => ty.try_super_fold_with(self)?, - ty::Projection | ty::Inherent => { + ty::Projection | ty::Inherent | ty::Weak => { // See note in `rustc_trait_selection::traits::project` let infcx = self.infcx; @@ -282,6 +282,7 @@ impl<'cx, 'tcx> FallibleTypeFolder> for QueryNormalizer<'cx, 'tcx> debug!("QueryNormalizer: orig_values = {:#?}", orig_values); let result = match kind { ty::Projection => tcx.normalize_projection_ty(c_data), + ty::Weak => tcx.normalize_weak_ty(c_data), ty::Inherent => tcx.normalize_inherent_projection_ty(c_data), _ => unreachable!(), }?; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 3c223db5a0b7..f2dfa6921f41 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -143,7 +143,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Before we go into the whole placeholder thing, just // quickly check if the self-type is a projection at all. match obligation.predicate.skip_binder().trait_ref.self_ty().kind() { - // Excluding IATs here as they don't have meaningful item bounds. + // Excluding IATs and type aliases here as they don't have meaningful item bounds. ty::Alias(ty::Projection | ty::Opaque, _) => {} ty::Infer(ty::TyVar(_)) => { span_bug!( diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 7853af959ad5..d2c2cadd617b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -163,7 +163,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); let (def_id, substs) = match *placeholder_self_ty.kind() { - // Excluding IATs here as they don't have meaningful item bounds. + // Excluding IATs and type aliases here as they don't have meaningful item bounds. ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { (def_id, substs) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4c5a794bc815..e72d3ca97d7c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2314,7 +2314,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) - | ty::Alias(ty::Projection | ty::Inherent, ..) + | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..) | ty::Bound(..) | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { bug!("asked to assemble constituent types of unexpected type: {:?}", t); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 086ab32b5200..92d899b0f138 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -731,6 +731,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } + ty::Alias(ty::Weak, ty::AliasTy { def_id, substs, .. }) => { + let obligations = self.nominal_obligations(def_id, substs); + self.out.extend(obligations); + } + ty::Dynamic(data, r, _) => { // WfObject // diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index e6c6e0f13df3..f9a7c8c386ae 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -372,6 +372,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { substitution: substs.lower_into(interner), })) } + ty::Alias(ty::Weak, ty::AliasTy { .. }) => unimplemented!(), ty::Alias(ty::Inherent, _) => unimplemented!(), ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => { chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index b552ba41acd3..83828f177bc8 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -10,7 +10,12 @@ use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext}; use std::sync::atomic::Ordering; pub(crate) fn provide(p: &mut Providers) { - *p = Providers { normalize_projection_ty, normalize_inherent_projection_ty, ..*p }; + *p = Providers { + normalize_projection_ty, + normalize_weak_ty, + normalize_inherent_projection_ty, + ..*p + }; } fn normalize_projection_ty<'tcx>( @@ -43,6 +48,33 @@ fn normalize_projection_ty<'tcx>( ) } +fn normalize_weak_ty<'tcx>( + tcx: TyCtxt<'tcx>, + goal: CanonicalProjectionGoal<'tcx>, +) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> { + debug!("normalize_provider(goal={:#?})", goal); + + tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed); + tcx.infer_ctxt().enter_canonical_trait_query( + &goal, + |ocx, ParamEnvAnd { param_env, value: goal }| { + let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.substs).map( + |(predicate, span)| { + traits::Obligation::new( + tcx, + ObligationCause::dummy_with_span(span), + param_env, + predicate, + ) + }, + ); + ocx.register_obligations(obligations); + let normalized_ty = tcx.type_of(goal.def_id).subst(tcx, goal.substs); + Ok(NormalizationResult { normalized_ty }) + }, + ) +} + fn normalize_inherent_projection_ty<'tcx>( tcx: TyCtxt<'tcx>, goal: CanonicalProjectionGoal<'tcx>, diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index fa18f921ee4b..f621673f1d6f 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -36,9 +36,17 @@ pub enum DynKind { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable_Generic)] pub enum AliasKind { + /// A projection `::AssocType`. + /// Can get normalized away if monomorphic enough. Projection, Inherent, + /// An opaque type (usually from `impl Trait` in type aliases or function return types) + /// Can only be normalized away in RevealAll mode Opaque, + /// A type alias that actually checks its trait bounds. + /// Currently only used if the type alias references opaque types. + /// Can always be normalized away. + Weak, } /// Defines the kinds of types used by the type system. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0c7950bfd3dd..9f698a3b6bf9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2052,6 +2052,11 @@ pub(crate) fn clean_middle_ty<'tcx>( })) } + ty::Alias(ty::Weak, data) => { + let ty = cx.tcx.type_of(data.def_id).subst(cx.tcx, data.substs); + clean_middle_ty(bound_ty.rebind(ty), cx, None, None) + } + ty::Param(ref p) => { if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) { ImplTrait(bounds) diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index a1d2147cb496..dbaf6aaa853c 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1424,6 +1424,7 @@ fn ty_auto_deref_stability<'tcx>( continue; }, ty::Param(_) => TyPosition::new_deref_stable_for_result(precedence, ty), + ty::Alias(ty::Weak, _) => unreachable!("should have been normalized away above"), ty::Alias(ty::Inherent, _) => unreachable!("inherent projection should have been normalized away above"), ty::Alias(ty::Projection, _) if ty.has_non_region_param() => { TyPosition::new_deref_stable_for_result(precedence, ty) diff --git a/src/tools/clippy/tests/ui/from_over_into.fixed b/src/tools/clippy/tests/ui/from_over_into.fixed index d18f93875658..204019130ede 100644 --- a/src/tools/clippy/tests/ui/from_over_into.fixed +++ b/src/tools/clippy/tests/ui/from_over_into.fixed @@ -82,10 +82,4 @@ fn msrv_1_41() { } } -type Opaque = impl Sized; -struct IntoOpaque; -impl Into for IntoOpaque { - fn into(self) -> Opaque {} -} - fn main() {} diff --git a/src/tools/clippy/tests/ui/from_over_into.rs b/src/tools/clippy/tests/ui/from_over_into.rs index de8ff0b06bdc..46e02847e308 100644 --- a/src/tools/clippy/tests/ui/from_over_into.rs +++ b/src/tools/clippy/tests/ui/from_over_into.rs @@ -82,10 +82,4 @@ fn msrv_1_41() { } } -type Opaque = impl Sized; -struct IntoOpaque; -impl Into for IntoOpaque { - fn into(self) -> Opaque {} -} - fn main() {} diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs index 3b280b7488ae..bd62c655216e 100644 --- a/src/tools/clippy/tests/ui/from_over_into_unfixable.rs +++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.rs @@ -32,4 +32,10 @@ impl Into for ContainsVal { } } +type Opaque = impl Sized; +struct IntoOpaque; +impl Into for IntoOpaque { + fn into(self) -> Opaque {} +} + fn main() {} diff --git a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr index 251f1d84e74e..bb966af4b0ff 100644 --- a/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr +++ b/src/tools/clippy/tests/ui/from_over_into_unfixable.stderr @@ -1,29 +1,12 @@ -error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into_unfixable.rs:11:1 +error[E0658]: `impl Trait` in type aliases is unstable + --> $DIR/from_over_into_unfixable.rs:35:15 | -LL | impl Into for String { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | type Opaque = impl Sized; + | ^^^^^^^^^^ | - = help: replace the `Into` implementation with `From` - = note: `-D clippy::from-over-into` implied by `-D warnings` + = note: see issue #63063 for more information + = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable -error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into_unfixable.rs:19:1 - | -LL | impl Into for &'static [u8] { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: replace the `Into` implementation with `From<&'static [u8]>` - -error: an implementation of `From` is preferred since it gives you `Into<_>` for free where the reverse isn't true - --> $DIR/from_over_into_unfixable.rs:28:1 - | -LL | impl Into for ContainsVal { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: `impl From for Foreign` is allowed by the orphan rules, for more information see - https://doc.rust-lang.org/reference/items/implementations.html#trait-implementation-coherence - = help: replace the `Into` implementation with `From` - -error: aborting due to 3 previous errors +error: aborting due to previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.rs b/src/tools/clippy/tests/ui/new_ret_no_self.rs index a2a30c8b931c..4eff62b85ff6 100644 --- a/src/tools/clippy/tests/ui/new_ret_no_self.rs +++ b/src/tools/clippy/tests/ui/new_ret_no_self.rs @@ -401,25 +401,3 @@ mod issue7344 { } } } - -mod issue10041 { - struct Bomb; - - impl Bomb { - // Hidden default generic parameter. - pub fn new() -> impl PartialOrd { - 0i32 - } - } - - // TAIT with self-referencing bounds - type X = impl std::ops::Add; - - struct Bomb2; - - impl Bomb2 { - pub fn new() -> X { - 0i32 - } - } -} diff --git a/src/tools/clippy/tests/ui/new_ret_no_self.stderr b/src/tools/clippy/tests/ui/new_ret_no_self.stderr index 2eaebfb5cac5..2b053b462b16 100644 --- a/src/tools/clippy/tests/ui/new_ret_no_self.stderr +++ b/src/tools/clippy/tests/ui/new_ret_no_self.stderr @@ -92,21 +92,5 @@ LL | | unimplemented!() LL | | } | |_________^ -error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:410:9 - | -LL | / pub fn new() -> impl PartialOrd { -LL | | 0i32 -LL | | } - | |_________^ - -error: methods called `new` usually return `Self` - --> $DIR/new_ret_no_self.rs:421:9 - | -LL | / pub fn new() -> X { -LL | | 0i32 -LL | | } - | |_________^ - -error: aborting due to 14 previous errors +error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs new file mode 100644 index 000000000000..7bc6fec10ba6 --- /dev/null +++ b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs @@ -0,0 +1,26 @@ +#![feature(type_alias_impl_trait)] +#![warn(clippy::new_ret_no_self)] + +mod issue10041 { + struct Bomb; + + impl Bomb { + // Hidden default generic parameter. + pub fn new() -> impl PartialOrd { + 0i32 + } + } + + // TAIT with self-referencing bounds + type X = impl std::ops::Add; + + struct Bomb2; + + impl Bomb2 { + pub fn new() -> X { + 0i32 + } + } +} + +fn main() {} diff --git a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr new file mode 100644 index 000000000000..babb634fdcd1 --- /dev/null +++ b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Output == issue10041::X` + --> $DIR/new_ret_no_self_overflow.rs:20:25 + | +LL | pub fn new() -> X { + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/impl-trait/nested-return-type2-tait.stderr b/tests/ui/impl-trait/nested-return-type2-tait.stderr index a8eb69cfcb73..4383e8ab3a0c 100644 --- a/tests/ui/impl-trait/nested-return-type2-tait.stderr +++ b/tests/ui/impl-trait/nested-return-type2-tait.stderr @@ -8,10 +8,6 @@ LL | fn foo() -> impl Trait { | ^^^^^^^^^^^^^^^^ | = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -help: add this bound - | -LL | type Sendable = impl Send + Duh; - | +++++ warning: 1 warning emitted diff --git a/tests/ui/impl-trait/nested-return-type3-tait.stderr b/tests/ui/impl-trait/nested-return-type3-tait.stderr index 5f58c8dca4ad..d32944a0d721 100644 --- a/tests/ui/impl-trait/nested-return-type3-tait.stderr +++ b/tests/ui/impl-trait/nested-return-type3-tait.stderr @@ -8,10 +8,6 @@ LL | fn foo() -> impl Trait { | ^^^^^^^^^^^^^^^^ | = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -help: add this bound - | -LL | type Sendable = impl Send + Duh; - | +++++ warning: 1 warning emitted diff --git a/tests/ui/impl-trait/nested-return-type3-tait2.stderr b/tests/ui/impl-trait/nested-return-type3-tait2.stderr index c07f6ead7502..a2eddd116653 100644 --- a/tests/ui/impl-trait/nested-return-type3-tait2.stderr +++ b/tests/ui/impl-trait/nested-return-type3-tait2.stderr @@ -8,10 +8,6 @@ LL | type Traitable = impl Trait; | ^^^^^^^^^^^^^^^^ | = note: `#[warn(opaque_hidden_inferred_bound)]` on by default -help: add this bound - | -LL | type Sendable = impl Send + Duh; - | +++++ warning: 1 warning emitted diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs index af9dfe25bb4c..01c933473ea7 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs @@ -1,5 +1,7 @@ #![feature(type_alias_impl_trait)] +// check-pass + type Foo = impl PartialEq<(Foo, i32)>; struct Bar; @@ -11,7 +13,6 @@ impl PartialEq<(Foo, i32)> for Bar { } fn foo() -> Foo { - //~^ ERROR can't compare `Bar` with `(Bar, i32)` Bar } diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr deleted file mode 100644 index 7b63a3d0b9f1..000000000000 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0277]: can't compare `Bar` with `(Bar, i32)` - --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs:13:13 - | -LL | fn foo() -> Foo { - | ^^^ no implementation for `Bar == (Bar, i32)` -LL | -LL | Bar - | --- return type was inferred to be `Bar` here - | - = help: the trait `PartialEq<(Bar, i32)>` is not implemented for `Bar` - = help: the trait `PartialEq<(Foo, i32)>` is implemented for `Bar` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index fe62a8f32888..bbd60d4398b7 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -20,6 +20,11 @@ LL | fn eq(&self, _other: &(Foo, i32)) -> bool { | = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _` found signature `fn(&a::Bar, &(a::Foo, i32)) -> _` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:9 + | +LL | fn eq(&self, _other: &(Foo, i32)) -> bool { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unconstrained opaque type --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16 diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs index ad0a003e8794..aab10be2de27 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs @@ -1,5 +1,3 @@ -// check-pass - #![feature(type_alias_impl_trait)] type Foo = impl PartialEq<(Foo, i32)>; @@ -13,6 +11,7 @@ impl PartialEq<(Bar, i32)> for Bar { } fn foo() -> Foo { + //~^ ERROR can't compare `Bar` with `(Foo, i32)` Bar } diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr new file mode 100644 index 000000000000..b98b859a99bf --- /dev/null +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr @@ -0,0 +1,15 @@ +error[E0277]: can't compare `Bar` with `(Foo, i32)` + --> $DIR/recursive-type-alias-impl-trait-declaration.rs:13:13 + | +LL | fn foo() -> Foo { + | ^^^ no implementation for `Bar == (Foo, i32)` +LL | +LL | Bar + | --- return type was inferred to be `Bar` here + | + = help: the trait `PartialEq<(Foo, i32)>` is not implemented for `Bar` + = help: the trait `PartialEq<(Bar, i32)>` is implemented for `Bar` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/lint/lint-ctypes-73249-2.rs b/tests/ui/lint/lint-ctypes-73249-2.rs index 691047c8a405..f30377d6c16e 100644 --- a/tests/ui/lint/lint-ctypes-73249-2.rs +++ b/tests/ui/lint/lint-ctypes-73249-2.rs @@ -1,7 +1,7 @@ #![feature(type_alias_impl_trait)] #![deny(improper_ctypes)] -pub trait Baz {} +trait Baz {} impl Baz for () {} @@ -9,7 +9,7 @@ type Qux = impl Baz; fn assign() -> Qux {} -pub trait Foo { +trait Foo { type Assoc: 'static; } @@ -18,12 +18,12 @@ impl Foo for () { } #[repr(transparent)] -pub struct A { +struct A { x: &'static ::Assoc, } extern "C" { - pub fn lint_me() -> A<()>; //~ ERROR: uses type `Qux` + fn lint_me() -> A<()>; //~ ERROR: uses type `Qux` } fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73249-2.stderr b/tests/ui/lint/lint-ctypes-73249-2.stderr index 8073c33dd463..49fa54114b21 100644 --- a/tests/ui/lint/lint-ctypes-73249-2.stderr +++ b/tests/ui/lint/lint-ctypes-73249-2.stderr @@ -1,8 +1,8 @@ error: `extern` block uses type `Qux`, which is not FFI-safe - --> $DIR/lint-ctypes-73249-2.rs:26:25 + --> $DIR/lint-ctypes-73249-2.rs:26:21 | -LL | pub fn lint_me() -> A<()>; - | ^^^^^ not FFI-safe +LL | fn lint_me() -> A<()>; + | ^^^^^ not FFI-safe | = note: opaque types have no C equivalent note: the lint level is defined here diff --git a/tests/ui/lint/lint-ctypes-73251-1.rs b/tests/ui/lint/lint-ctypes-73251-1.rs index 145ba784f7c6..fc11f23a1049 100644 --- a/tests/ui/lint/lint-ctypes-73251-1.rs +++ b/tests/ui/lint/lint-ctypes-73251-1.rs @@ -1,13 +1,13 @@ #![feature(type_alias_impl_trait)] #![deny(improper_ctypes)] -pub trait Baz {} +trait Baz {} impl Baz for u32 {} type Qux = impl Baz; -pub trait Foo { +trait Foo { type Assoc; } @@ -20,7 +20,7 @@ fn assign() -> Qux { } extern "C" { - pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `Qux` + fn lint_me() -> ::Assoc; //~ ERROR: uses type `Qux` } fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73251-1.stderr b/tests/ui/lint/lint-ctypes-73251-1.stderr index 9f43576ad735..b4eb921b97e2 100644 --- a/tests/ui/lint/lint-ctypes-73251-1.stderr +++ b/tests/ui/lint/lint-ctypes-73251-1.stderr @@ -1,8 +1,8 @@ error: `extern` block uses type `Qux`, which is not FFI-safe - --> $DIR/lint-ctypes-73251-1.rs:23:25 + --> $DIR/lint-ctypes-73251-1.rs:23:21 | -LL | pub fn lint_me() -> ::Assoc; - | ^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: opaque types have no C equivalent note: the lint level is defined here diff --git a/tests/ui/lint/lint-ctypes-73251-2.rs b/tests/ui/lint/lint-ctypes-73251-2.rs index df71a9457962..fbe0a58f3b5b 100644 --- a/tests/ui/lint/lint-ctypes-73251-2.rs +++ b/tests/ui/lint/lint-ctypes-73251-2.rs @@ -33,7 +33,7 @@ fn use_of_b() -> AliasB { } extern "C" { - pub fn lint_me() -> ::Assoc; //~ ERROR: uses type `AliasA` + fn lint_me() -> ::Assoc; //~ ERROR: uses type `AliasA` } fn main() {} diff --git a/tests/ui/lint/lint-ctypes-73251-2.stderr b/tests/ui/lint/lint-ctypes-73251-2.stderr index 0b3de379c19d..e44cd45bd30f 100644 --- a/tests/ui/lint/lint-ctypes-73251-2.stderr +++ b/tests/ui/lint/lint-ctypes-73251-2.stderr @@ -1,8 +1,8 @@ error: `extern` block uses type `AliasA`, which is not FFI-safe - --> $DIR/lint-ctypes-73251-2.rs:36:25 + --> $DIR/lint-ctypes-73251-2.rs:36:21 | -LL | pub fn lint_me() -> ::Assoc; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe +LL | fn lint_me() -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe | = note: opaque types have no C equivalent note: the lint level is defined here diff --git a/tests/ui/lint/lint-ctypes-73251.rs b/tests/ui/lint/lint-ctypes-73251.rs index ebc2ca77b67a..a00d1a75aec2 100644 --- a/tests/ui/lint/lint-ctypes-73251.rs +++ b/tests/ui/lint/lint-ctypes-73251.rs @@ -3,7 +3,7 @@ #![feature(type_alias_impl_trait)] #![deny(improper_ctypes)] -pub trait Foo { +trait Foo { type Assoc; } @@ -16,7 +16,7 @@ type Bar = impl Foo; fn assign() -> Bar {} extern "C" { - pub fn lint_me() -> ::Assoc; + fn lint_me() -> ::Assoc; } fn main() {} diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.rs b/tests/ui/lint/opaque-ty-ffi-unsafe.rs index b7cc38e99fc3..5faeac9ed4c3 100644 --- a/tests/ui/lint/opaque-ty-ffi-unsafe.rs +++ b/tests/ui/lint/opaque-ty-ffi-unsafe.rs @@ -3,12 +3,12 @@ type A = impl Fn(); -pub fn ret_closure() -> A { +pub(crate) fn ret_closure() -> A { || {} } extern "C" { - pub fn a(_: A); + pub(crate) fn a(_: A); //~^ ERROR `extern` block uses type `A`, which is not FFI-safe [improper_ctypes] } diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr index 33aa95854e30..ba9e18bcce5c 100644 --- a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr +++ b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr @@ -1,8 +1,8 @@ error: `extern` block uses type `A`, which is not FFI-safe - --> $DIR/opaque-ty-ffi-unsafe.rs:11:17 + --> $DIR/opaque-ty-ffi-unsafe.rs:11:24 | -LL | pub fn a(_: A); - | ^ not FFI-safe +LL | pub(crate) fn a(_: A); + | ^ not FFI-safe | = note: opaque types have no C equivalent note: the lint level is defined here diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs index a1584581e6c4..d9f7c7809b98 100644 --- a/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs +++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs @@ -4,9 +4,9 @@ #![allow(dead_code)] mod m { - type Foo = impl std::fmt::Debug; + pub(crate) type Foo = impl std::fmt::Debug; - pub fn foo() -> Foo { + pub(crate) fn foo() -> Foo { 22_u32 } } diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs new file mode 100644 index 000000000000..5a9e87c09196 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +use std::fmt::{Debug, Display}; + +struct Struct(Option); + +// Make sure that, in contrast to type aliases without opaque types, +// we actually do a wf check for the aliased type. +type Foo = (impl Debug, Struct); +//~^ ERROR: `T` doesn't implement `std::fmt::Display` + +fn foo() -> Foo { + (Vec::::new(), Struct(None)) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr new file mode 100644 index 000000000000..a845cba77163 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.stderr @@ -0,0 +1,20 @@ +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/bounds-are-checked3.rs:9:35 + | +LL | type Foo = (impl Debug, Struct); + | ^^^^^^^^^ `T` cannot be formatted with the default formatter + | + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +note: required by a bound in `Struct` + --> $DIR/bounds-are-checked3.rs:5:18 + | +LL | struct Struct(Option); + | ^^^^^^^ required by this bound in `Struct` +help: consider further restricting this bound + | +LL | type Foo = (impl Debug, Struct); + | +++++++++++++++++++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/bounds.rs b/tests/ui/type-alias-impl-trait/bounds.rs new file mode 100644 index 000000000000..dc05b70c5cc9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/bounds.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +use std::fmt::Debug; + +// No need to report the `type_alias_bounds` lint, as +// the moment an opaque type is mentioned, we actually do check +// type alias bounds. +type Foo = (impl Debug, usize); + +fn foo() -> Foo { + (Vec::::new(), 1234) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.stderr index 00b0dbbb583f..c923eb08ab31 100644 --- a/tests/ui/type-alias-impl-trait/coherence.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.stderr @@ -4,7 +4,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar LL | impl foreign_crate::ForeignTrait for AliasOfForeignType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------- | | | - | | type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate + | | `AliasOfForeignType` is not defined in the current crate | impl doesn't use only types from inside the current crate | = note: define and implement a trait or new type instead diff --git a/tests/ui/type-alias-impl-trait/defining-use-submodule.rs b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs index 8b51f55715e9..4d84b2cbbe9a 100644 --- a/tests/ui/type-alias-impl-trait/defining-use-submodule.rs +++ b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs @@ -11,12 +11,12 @@ type Foo = impl std::fmt::Display; type Bar = impl std::fmt::Display; mod foo { - pub fn foo() -> super::Foo { + pub(crate) fn foo() -> super::Foo { "foo" } - pub mod bar { - pub fn bar() -> crate::Bar { + pub(crate) mod bar { + pub(crate) fn bar() -> crate::Bar { 1 } } diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr index c73288329b01..bc9280127acc 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr @@ -4,11 +4,11 @@ error[E0277]: the trait bound `T: Trait` is not satisfied LL | fn underconstrain(_: T) -> Underconstrained { | ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` | -note: required by a bound in `Underconstrained` +note: required by a bound on the type alias `Underconstrained` --> $DIR/generic_underconstrained.rs:6:26 | LL | type Underconstrained = impl Send; - | ^^^^^ required by this bound in `Underconstrained` + | ^^^^^ required by this bound help: consider restricting type parameter `T` | LL | fn underconstrain(_: T) -> Underconstrained { diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr index d77d978aa444..fdc9ec090dbe 100644 --- a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr @@ -4,11 +4,11 @@ error[E0277]: `U` doesn't implement `Debug` LL | fn underconstrained(_: U) -> Underconstrained { | ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` | -note: required by a bound in `Underconstrained` +note: required by a bound on the type alias `Underconstrained` --> $DIR/generic_underconstrained2.rs:5:26 | LL | type Underconstrained = impl Send; - | ^^^^^^^^^^^^^^^ required by this bound in `Underconstrained` + | ^^^^^^^^^^^^^^^ required by this bound help: consider restricting type parameter `U` | LL | fn underconstrained(_: U) -> Underconstrained { @@ -20,11 +20,11 @@ error[E0277]: `V` doesn't implement `Debug` LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { | ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug` | -note: required by a bound in `Underconstrained2` +note: required by a bound on the type alias `Underconstrained2` --> $DIR/generic_underconstrained2.rs:13:27 | LL | type Underconstrained2 = impl Send; - | ^^^^^^^^^^^^^^^ required by this bound in `Underconstrained2` + | ^^^^^^^^^^^^^^^ required by this bound help: consider restricting type parameter `V` | LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { diff --git a/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs new file mode 100644 index 000000000000..00d1a1a226d2 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs @@ -0,0 +1,14 @@ +#![feature(type_alias_impl_trait)] +#![feature(auto_traits)] + +type Alias = (impl Sized, u8); + +auto trait Trait {} +impl Trait for Alias {} +//~^ ERROR traits with a default impl, like `Trait`, cannot be implemented for type alias `Alias` + +fn _def() -> Alias { + (42, 42) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr new file mode 100644 index 000000000000..c312ee7dece8 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.stderr @@ -0,0 +1,11 @@ +error[E0321]: traits with a default impl, like `Trait`, cannot be implemented for type alias `Alias` + --> $DIR/impl_for_weak_alias.rs:7:1 + | +LL | impl Trait for Alias {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: a trait object implements `Trait` if and only if `Trait` is one of the trait object's trait bounds + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0321`. diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs index 4a11bb5020e6..b89c3e4590f2 100644 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs +++ b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.rs @@ -1,9 +1,10 @@ #![feature(type_alias_impl_trait)] +// check-pass + type Foo = impl Fn() -> Foo; fn foo() -> Foo { -//~^ ERROR: overflow evaluating the requirement foo } diff --git a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr b/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr deleted file mode 100644 index 0a34e8486a55..000000000000 --- a/tests/ui/type-alias-impl-trait/issue-53398-cyclic-types.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0275]: overflow evaluating the requirement `Foo: Sized` - --> $DIR/issue-53398-cyclic-types.rs:5:13 - | -LL | fn foo() -> Foo { - | ^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_53398_cyclic_types`) - = note: required because it appears within the type `fn() -> Foo {foo}` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/type-alias-impl-trait/obligation_ice.rs b/tests/ui/type-alias-impl-trait/obligation_ice.rs new file mode 100644 index 000000000000..5aef04ff19c0 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/obligation_ice.rs @@ -0,0 +1,17 @@ +#![feature(type_alias_impl_trait)] +// check-pass + +use std::iter::{once, Chain}; + +trait Trait<'a, 'b: 'a> {} + +impl<'a, 'b: 'a, T> Trait<'a, 'b> for std::iter::Cloned {} + +type I<'a, 'b: 'a, A: Trait<'a, 'b>> = Chain>; +fn test2<'a, 'b, A: Trait<'a, 'b> + Iterator>(x: A) -> I<'a, 'b, A> { + x.chain(once("5")) +} + +fn main() { + assert_eq!(vec!["1", "3", "5"], test2(["1", "3"].iter().cloned()).collect::>()); +} diff --git a/tests/ui/type-alias-impl-trait/privacy.rs b/tests/ui/type-alias-impl-trait/privacy.rs new file mode 100644 index 000000000000..aa092f6f8ecc --- /dev/null +++ b/tests/ui/type-alias-impl-trait/privacy.rs @@ -0,0 +1,8 @@ +#![feature(type_alias_impl_trait)] + +type Foo = (impl Sized, u8); +pub fn foo() -> Foo { + //~^ ERROR private type alias `Foo` in public interface + (42, 42) +} +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/privacy.stderr b/tests/ui/type-alias-impl-trait/privacy.stderr new file mode 100644 index 000000000000..e8c6039cdc84 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/privacy.stderr @@ -0,0 +1,11 @@ +error[E0446]: private type alias `Foo` in public interface + --> $DIR/privacy.rs:4:1 + | +LL | type Foo = (impl Sized, u8); + | -------- `Foo` declared as private +LL | pub fn foo() -> Foo { + | ^^^^^^^^^^^^^^^^^^^ can't leak private type alias + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.rs b/tests/ui/type-alias-impl-trait/self-referential-3.rs index d40715717d49..18f09b548675 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-3.rs +++ b/tests/ui/type-alias-impl-trait/self-referential-3.rs @@ -1,9 +1,9 @@ -// run-pass #![feature(type_alias_impl_trait)] type Bar<'a, 'b> = impl PartialEq> + std::fmt::Debug; fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + //~^ ERROR can't compare `&i32` with `Bar<'a, 'b>` i } diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.stderr b/tests/ui/type-alias-impl-trait/self-referential-3.stderr new file mode 100644 index 000000000000..4155a114b4f9 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/self-referential-3.stderr @@ -0,0 +1,15 @@ +error[E0277]: can't compare `&i32` with `Bar<'a, 'b>` + --> $DIR/self-referential-3.rs:5:31 + | +LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { + | ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>` +LL | +LL | i + | - return type was inferred to be `&i32` here + | + = help: the trait `PartialEq>` is not implemented for `&i32` + = help: the trait `PartialEq` is implemented for `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/self-referential.rs b/tests/ui/type-alias-impl-trait/self-referential.rs index 3ff5406a3827..34b7c24df9f6 100644 --- a/tests/ui/type-alias-impl-trait/self-referential.rs +++ b/tests/ui/type-alias-impl-trait/self-referential.rs @@ -10,7 +10,7 @@ fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> { type Foo<'a, 'b> = (i32, impl PartialEq> + std::fmt::Debug); fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { - //~^ ERROR can't compare `&i32` with `(i32, &i32)` + //~^ ERROR can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})` (42, i) } diff --git a/tests/ui/type-alias-impl-trait/self-referential.stderr b/tests/ui/type-alias-impl-trait/self-referential.stderr index aff489d70e38..9a17d495b629 100644 --- a/tests/ui/type-alias-impl-trait/self-referential.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential.stderr @@ -10,16 +10,16 @@ LL | i = help: the trait `PartialEq>` is not implemented for `&i32` = help: the trait `PartialEq` is implemented for `i32` -error[E0277]: can't compare `&i32` with `(i32, &i32)` +error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0})` --> $DIR/self-referential.rs:12:31 | LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> { - | ^^^^^^^^^^^ no implementation for `&i32 == (i32, &i32)` + | ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0})` LL | LL | (42, i) | ------- return type was inferred to be `(i32, &i32)` here | - = help: the trait `PartialEq<(i32, &i32)>` is not implemented for `&i32` + = help: the trait `PartialEq<(i32, Foo<'a, 'b>::{opaque#0})>` is not implemented for `&i32` = help: the trait `PartialEq` is implemented for `i32` error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0})` diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs index 07c891f0638c..4e7388517a5e 100644 --- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs +++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs @@ -4,20 +4,20 @@ // Regression test for issue #61863 -pub trait MyTrait {} +trait MyTrait {} #[derive(Debug)] -pub struct MyStruct { +struct MyStruct { v: u64, } impl MyTrait for MyStruct {} -pub fn bla() -> TE { +fn bla() -> TE { return MyStruct { v: 1 }; } -pub fn bla2() -> TE { +fn bla2() -> TE { bla() } diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr index e9032433494a..24f5cc8c7339 100644 --- a/tests/ui/type-alias-impl-trait/unnameable_type.stderr +++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr @@ -25,6 +25,11 @@ LL | fn dont_define_this(_private: Private) {} | ^^^^^^^ = note: expected signature `fn(Private)` found signature `fn(MyPrivate)` +note: this item must have the opaque type in its signature in order to be able to register hidden types + --> $DIR/unnameable_type.rs:20:5 + | +LL | fn dont_define_this(_private: MyPrivate) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors From 79c2c986a29faf7be042a5ab40975b9b8f1c2575 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 16 Jun 2023 16:54:51 +0000 Subject: [PATCH 35/41] Pacify tidy --- .../rustc_hir_analysis/src/astconv/lint.rs | 124 ++++++++++++++++++ .../rustc_hir_analysis/src/astconv/mod.rs | 120 +---------------- 2 files changed, 128 insertions(+), 116 deletions(-) create mode 100644 compiler/rustc_hir_analysis/src/astconv/lint.rs diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs new file mode 100644 index 000000000000..05a3ab63d5cf --- /dev/null +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -0,0 +1,124 @@ +use rustc_ast::TraitObjectSyntax; +use rustc_errors::{Diagnostic, StashKey}; +use rustc_hir as hir; +use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability}; +use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName; + +use super::AstConv; + +impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { + /// Make sure that we are in the condition to suggest the blanket implementation. + pub(super) fn maybe_lint_blanket_trait_impl( + &self, + self_ty: &hir::Ty<'_>, + diag: &mut Diagnostic, + ) { + let tcx = self.tcx(); + let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; + if let hir::Node::Item(hir::Item { + kind: + hir::ItemKind::Impl(hir::Impl { + self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, .. + }), + .. + }) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id + { + if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) { + return; + } + let of_trait_span = of_trait_ref.path.span; + // make sure that we are not calling unwrap to abort during the compilation + let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; }; + let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; }; + // check if the trait has generics, to make a correct suggestion + let param_name = generics.params.next_type_param_name(None); + + let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { + (span, format!(", {}: {}", param_name, impl_trait_name)) + } else { + (generics.span, format!("<{}: {}>", param_name, impl_trait_name)) + }; + diag.multipart_suggestion( + format!("alternatively use a blanket \ + implementation to implement `{of_trait_name}` for \ + all types that also implement `{impl_trait_name}`"), + vec![ + (self_ty.span, param_name), + add_generic_sugg, + ], + Applicability::MaybeIncorrect, + ); + } + } + + pub(super) fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { + let tcx = self.tcx(); + if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = + self_ty.kind + { + let needs_bracket = in_path + && !tcx + .sess + .source_map() + .span_to_prev_source(self_ty.span) + .ok() + .is_some_and(|s| s.trim_end().ends_with('<')); + + let is_global = poly_trait_ref.trait_ref.path.is_global(); + + let mut sugg = Vec::from_iter([( + self_ty.span.shrink_to_lo(), + format!( + "{}dyn {}", + if needs_bracket { "<" } else { "" }, + if is_global { "(" } else { "" }, + ), + )]); + + if is_global || needs_bracket { + sugg.push(( + self_ty.span.shrink_to_hi(), + format!( + "{}{}", + if is_global { ")" } else { "" }, + if needs_bracket { ">" } else { "" }, + ), + )); + } + + if self_ty.span.edition().rust_2021() { + let msg = "trait objects must include the `dyn` keyword"; + let label = "add `dyn` keyword before this trait"; + let mut diag = + rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg); + if self_ty.span.can_be_used_for_suggestions() { + diag.multipart_suggestion_verbose( + label, + sugg, + Applicability::MachineApplicable, + ); + } + // check if the impl trait that we are considering is a impl of a local trait + self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag); + diag.stash(self_ty.span, StashKey::TraitMissingMethod); + } else { + let msg = "trait objects without an explicit `dyn` are deprecated"; + tcx.struct_span_lint_hir( + BARE_TRAIT_OBJECTS, + self_ty.hir_id, + self_ty.span, + msg, + |lint| { + lint.multipart_suggestion_verbose( + "use `dyn`", + sugg, + Applicability::MachineApplicable, + ); + self.maybe_lint_blanket_trait_impl(&self_ty, lint); + lint + }, + ); + } + } + } +} diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 8afa0a46d32f..221c7ce4f6ff 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -4,6 +4,7 @@ mod errors; pub mod generics; +mod lint; use crate::astconv::errors::prohibit_assoc_ty_binding; use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args}; @@ -19,7 +20,7 @@ use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError, - MultiSpan, StashKey, + MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; @@ -33,14 +34,12 @@ use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{DynKind, ToPredicate}; -use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS}; +use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{sym, Span, DUMMY_SP}; use rustc_target::spec::abi; -use rustc_trait_selection::traits::error_reporting::{ - report_object_safety_error, suggestions::NextTypeParamName, -}; +use rustc_trait_selection::traits::error_reporting::report_object_safety_error; use rustc_trait_selection::traits::wf::object_region_bounds; use rustc_trait_selection::traits::{ self, astconv_object_safety_violations, NormalizeExt, ObligationCtxt, @@ -3715,115 +3714,4 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } Some(r) } - - /// Make sure that we are in the condition to suggest the blanket implementation. - fn maybe_lint_blanket_trait_impl(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) { - let tcx = self.tcx(); - let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; - if let hir::Node::Item(hir::Item { - kind: - hir::ItemKind::Impl(hir::Impl { - self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, .. - }), - .. - }) = tcx.hir().get_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id - { - if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) { - return; - } - let of_trait_span = of_trait_ref.path.span; - // make sure that we are not calling unwrap to abort during the compilation - let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; }; - let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; }; - // check if the trait has generics, to make a correct suggestion - let param_name = generics.params.next_type_param_name(None); - - let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { - (span, format!(", {}: {}", param_name, impl_trait_name)) - } else { - (generics.span, format!("<{}: {}>", param_name, impl_trait_name)) - }; - diag.multipart_suggestion( - format!("alternatively use a blanket \ - implementation to implement `{of_trait_name}` for \ - all types that also implement `{impl_trait_name}`"), - vec![ - (self_ty.span, param_name), - add_generic_sugg, - ], - Applicability::MaybeIncorrect, - ); - } - } - - fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { - let tcx = self.tcx(); - if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = - self_ty.kind - { - let needs_bracket = in_path - && !tcx - .sess - .source_map() - .span_to_prev_source(self_ty.span) - .ok() - .is_some_and(|s| s.trim_end().ends_with('<')); - - let is_global = poly_trait_ref.trait_ref.path.is_global(); - - let mut sugg = Vec::from_iter([( - self_ty.span.shrink_to_lo(), - format!( - "{}dyn {}", - if needs_bracket { "<" } else { "" }, - if is_global { "(" } else { "" }, - ), - )]); - - if is_global || needs_bracket { - sugg.push(( - self_ty.span.shrink_to_hi(), - format!( - "{}{}", - if is_global { ")" } else { "" }, - if needs_bracket { ">" } else { "" }, - ), - )); - } - - if self_ty.span.edition().rust_2021() { - let msg = "trait objects must include the `dyn` keyword"; - let label = "add `dyn` keyword before this trait"; - let mut diag = - rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg); - if self_ty.span.can_be_used_for_suggestions() { - diag.multipart_suggestion_verbose( - label, - sugg, - Applicability::MachineApplicable, - ); - } - // check if the impl trait that we are considering is a impl of a local trait - self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag); - diag.stash(self_ty.span, StashKey::TraitMissingMethod); - } else { - let msg = "trait objects without an explicit `dyn` are deprecated"; - tcx.struct_span_lint_hir( - BARE_TRAIT_OBJECTS, - self_ty.hir_id, - self_ty.span, - msg, - |lint| { - lint.multipart_suggestion_verbose( - "use `dyn`", - sugg, - Applicability::MachineApplicable, - ); - self.maybe_lint_blanket_trait_impl(&self_ty, lint); - lint - }, - ); - } - } - } } From 1704481bfa782409e77307149c59c87356b5a262 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 16 Jun 2023 00:23:20 +0000 Subject: [PATCH 36/41] Remove some ImplSource candidates --- compiler/rustc_middle/src/traits/mod.rs | 29 +++++------------- .../src/traits/structural_impls.rs | 12 ++------ .../src/traits/project.rs | 5 ++-- .../src/traits/select/confirmation.rs | 30 +++++++++---------- 4 files changed, 26 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index b63e049a520c..a9d85ca506c5 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -662,10 +662,10 @@ pub enum ImplSource<'tcx, N> { Object(ImplSourceObjectData<'tcx, N>), /// Successful resolution for a builtin trait. - Builtin(ImplSourceBuiltinData), + Builtin(Vec), /// ImplSource for trait upcasting coercion - TraitUpcasting(ImplSourceTraitUpcastingData<'tcx, N>), + TraitUpcasting(ImplSourceTraitUpcastingData), /// ImplSource automatically generated for a closure. The `DefId` is the ID /// of the closure expression. This is an `ImplSource::UserDefined` in spirit, but the @@ -692,8 +692,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn nested_obligations(self) -> Vec { match self { ImplSource::UserDefined(i) => i.nested, - ImplSource::Param(n, _) => n, - ImplSource::Builtin(i) => i.nested, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, ImplSource::AutoImpl(d) => d.nested, ImplSource::Closure(c) => c.nested, ImplSource::Generator(c) => c.nested, @@ -709,8 +708,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn borrow_nested_obligations(&self) -> &[N] { match self { ImplSource::UserDefined(i) => &i.nested, - ImplSource::Param(n, _) => n, - ImplSource::Builtin(i) => &i.nested, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, ImplSource::AutoImpl(d) => &d.nested, ImplSource::Closure(c) => &c.nested, ImplSource::Generator(c) => &c.nested, @@ -726,8 +724,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] { match self { ImplSource::UserDefined(i) => &mut i.nested, - ImplSource::Param(n, _) => n, - ImplSource::Builtin(i) => &mut i.nested, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, ImplSource::AutoImpl(d) => &mut d.nested, ImplSource::Closure(c) => &mut c.nested, ImplSource::Generator(c) => &mut c.nested, @@ -751,9 +748,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { nested: i.nested.into_iter().map(f).collect(), }), ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct), - ImplSource::Builtin(i) => ImplSource::Builtin(ImplSourceBuiltinData { - nested: i.nested.into_iter().map(f).collect(), - }), + ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()), ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData { upcast_trait_ref: o.upcast_trait_ref, vtable_base: o.vtable_base, @@ -789,7 +784,6 @@ impl<'tcx, N> ImplSource<'tcx, N> { }), ImplSource::TraitUpcasting(d) => { ImplSource::TraitUpcasting(ImplSourceTraitUpcastingData { - upcast_trait_ref: d.upcast_trait_ref, vtable_vptr_slot: d.vtable_vptr_slot, nested: d.nested.into_iter().map(f).collect(), }) @@ -860,10 +854,7 @@ pub struct ImplSourceAutoImplData { #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceTraitUpcastingData<'tcx, N> { - /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. - pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, - +pub struct ImplSourceTraitUpcastingData { /// The vtable is formed by concatenating together the method lists of /// the base object trait and all supertraits, pointers to supertrait vtable will /// be provided when necessary; this is the position of `upcast_trait_ref`'s vtable @@ -873,12 +864,6 @@ pub struct ImplSourceTraitUpcastingData<'tcx, N> { pub nested: Vec, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceBuiltinData { - pub nested: Vec, -} - #[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceObjectData<'tcx, N> { diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index 6acb7745d654..311d3d1f1e8e 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -76,18 +76,12 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceClosureData<'tcx, N> } } -impl fmt::Debug for traits::ImplSourceBuiltinData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ImplSourceBuiltinData(nested={:?})", self.nested) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitUpcastingData<'tcx, N> { +impl fmt::Debug for traits::ImplSourceTraitUpcastingData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "ImplSourceTraitUpcastingData(upcast={:?}, vtable_vptr_slot={:?}, nested={:?})", - self.upcast_trait_ref, self.vtable_vptr_slot, self.nested + "ImplSourceTraitUpcastingData(vtable_vptr_slot={:?}, nested={:?})", + self.vtable_vptr_slot, self.nested ) } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 8466b3fc9545..dd2bd45c07da 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -30,7 +30,6 @@ use rustc_hir::lang_items::LangItem; use rustc_infer::infer::at::At; use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::infer::DefineOpaqueTypes; -use rustc_infer::traits::ImplSourceBuiltinData; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; @@ -2106,7 +2105,7 @@ fn confirm_future_candidate<'cx, 'tcx>( fn confirm_builtin_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - data: ImplSourceBuiltinData>, + data: Vec>, ) -> Progress<'tcx> { let tcx = selcx.tcx(); let self_ty = obligation.predicate.self_ty(); @@ -2154,7 +2153,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false) .with_addl_obligations(obligations) - .with_addl_obligations(data.nested) + .with_addl_obligations(data) } fn confirm_fn_pointer_candidate<'cx, 'tcx>( diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index d2c2cadd617b..277367fe2757 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -27,12 +27,11 @@ use crate::traits::vtable::{ }; use crate::traits::{ BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource, - ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData, - ImplSourceConstDestructData, ImplSourceFnPointerData, ImplSourceFutureData, - ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData, - ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, Obligation, - ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError, - TraitNotObjectSafe, TraitObligation, Unimplemented, + ImplSourceAutoImplData, ImplSourceClosureData, ImplSourceConstDestructData, + ImplSourceFnPointerData, ImplSourceFutureData, ImplSourceGeneratorData, ImplSourceObjectData, + ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, + Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, + SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, }; use super::BuiltinImplConditions; @@ -114,7 +113,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // This indicates something like `Trait + Send: Send`. In this case, we know that // this holds because that's what the object type is telling us, and there's really // no additional obligations to prove and no types in particular to unify, etc. - ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst) + ImplSource::Builtin(Vec::new()) } BuiltinUnsizeCandidate => { @@ -244,7 +243,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, has_nested: bool, - ) -> ImplSourceBuiltinData> { + ) -> Vec> { debug!(?obligation, ?has_nested, "confirm_builtin_candidate"); let lang_items = self.tcx().lang_items(); @@ -277,14 +276,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?obligations); - ImplSourceBuiltinData { nested: obligations } + obligations } #[instrument(level = "debug", skip(self))] fn confirm_transmutability_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { use rustc_transmute::{Answer, Condition}; #[instrument(level = "debug", skip(tcx, obligation, predicate))] fn flatten_answer_tree<'tcx>( @@ -369,7 +368,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; debug!(?fully_flattened); - Ok(ImplSourceBuiltinData { nested: fully_flattened }) + Ok(fully_flattened) } /// This handles the case where an `auto trait Foo` impl is being used. @@ -912,8 +911,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, idx: usize, - ) -> Result>, SelectionError<'tcx>> - { + ) -> Result>, SelectionError<'tcx>> { let tcx = self.tcx(); // `assemble_candidates_for_unsizing` should ensure there are no late-bound @@ -1010,13 +1008,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let vtable_vptr_slot = prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback).unwrap(); - Ok(ImplSourceTraitUpcastingData { upcast_trait_ref, vtable_vptr_slot, nested }) + Ok(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested }) } fn confirm_builtin_unsize_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { let tcx = self.tcx(); // `assemble_candidates_for_unsizing` should ensure there are no late-bound @@ -1217,7 +1215,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { _ => bug!("source: {source}, target: {target}"), }; - Ok(ImplSourceBuiltinData { nested }) + Ok(nested) } fn confirm_const_destruct_candidate( From 9e68b6f50515ef2e402c7b945bc2041d5cbaa5ca Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 16 Jun 2023 00:43:16 +0000 Subject: [PATCH 37/41] Simplify some impl source candidates --- .../src/transform/check_consts/qualifs.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 37 ------------------- .../src/traits/structural_impls.rs | 20 ---------- .../src/traits/project.rs | 8 +--- .../src/traits/select/confirmation.rs | 26 ++++++------- compiler/rustc_ty_utils/src/instance.rs | 6 +-- 6 files changed, 18 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 1da20579021a..a2d23425f3bc 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -172,7 +172,7 @@ impl Qualif for NeedsNonConstDrop { if !matches!( impl_src, - ImplSource::ConstDestruct(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) + ImplSource::Builtin(_) | ImplSource::Param(_, ty::BoundConstness::ConstIfConst) ) { // If our const destruct candidate is not ConstDestruct or implied by the param env, // then it's bad diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index a9d85ca506c5..adc63aa6addd 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -646,12 +646,6 @@ pub enum ImplSource<'tcx, N> { /// ImplSource identifying a particular impl. UserDefined(ImplSourceUserDefinedData<'tcx, N>), - /// ImplSource for auto trait implementations. - /// This carries the information and nested obligations with regards - /// to an auto implementation for a trait `Trait`. The nested obligations - /// ensure the trait implementation holds for all the constituent types. - AutoImpl(ImplSourceAutoImplData), - /// Successful resolution to an obligation provided by the caller /// for some type parameter. The `Vec` represents the /// obligations incurred from normalizing the where-clause (if @@ -683,9 +677,6 @@ pub enum ImplSource<'tcx, N> { /// ImplSource for a trait alias. TraitAlias(ImplSourceTraitAliasData<'tcx, N>), - - /// ImplSource for a `const Drop` implementation. - ConstDestruct(ImplSourceConstDestructData), } impl<'tcx, N> ImplSource<'tcx, N> { @@ -693,7 +684,6 @@ impl<'tcx, N> ImplSource<'tcx, N> { match self { ImplSource::UserDefined(i) => i.nested, ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, - ImplSource::AutoImpl(d) => d.nested, ImplSource::Closure(c) => c.nested, ImplSource::Generator(c) => c.nested, ImplSource::Future(c) => c.nested, @@ -701,7 +691,6 @@ impl<'tcx, N> ImplSource<'tcx, N> { ImplSource::FnPointer(d) => d.nested, ImplSource::TraitAlias(d) => d.nested, ImplSource::TraitUpcasting(d) => d.nested, - ImplSource::ConstDestruct(i) => i.nested, } } @@ -709,7 +698,6 @@ impl<'tcx, N> ImplSource<'tcx, N> { match self { ImplSource::UserDefined(i) => &i.nested, ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, - ImplSource::AutoImpl(d) => &d.nested, ImplSource::Closure(c) => &c.nested, ImplSource::Generator(c) => &c.nested, ImplSource::Future(c) => &c.nested, @@ -717,7 +705,6 @@ impl<'tcx, N> ImplSource<'tcx, N> { ImplSource::FnPointer(d) => &d.nested, ImplSource::TraitAlias(d) => &d.nested, ImplSource::TraitUpcasting(d) => &d.nested, - ImplSource::ConstDestruct(i) => &i.nested, } } @@ -725,7 +712,6 @@ impl<'tcx, N> ImplSource<'tcx, N> { match self { ImplSource::UserDefined(i) => &mut i.nested, ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, - ImplSource::AutoImpl(d) => &mut d.nested, ImplSource::Closure(c) => &mut c.nested, ImplSource::Generator(c) => &mut c.nested, ImplSource::Future(c) => &mut c.nested, @@ -733,7 +719,6 @@ impl<'tcx, N> ImplSource<'tcx, N> { ImplSource::FnPointer(d) => &mut d.nested, ImplSource::TraitAlias(d) => &mut d.nested, ImplSource::TraitUpcasting(d) => &mut d.nested, - ImplSource::ConstDestruct(i) => &mut i.nested, } } @@ -754,10 +739,6 @@ impl<'tcx, N> ImplSource<'tcx, N> { vtable_base: o.vtable_base, nested: o.nested.into_iter().map(f).collect(), }), - ImplSource::AutoImpl(d) => ImplSource::AutoImpl(ImplSourceAutoImplData { - trait_def_id: d.trait_def_id, - nested: d.nested.into_iter().map(f).collect(), - }), ImplSource::Closure(c) => ImplSource::Closure(ImplSourceClosureData { closure_def_id: c.closure_def_id, substs: c.substs, @@ -788,11 +769,6 @@ impl<'tcx, N> ImplSource<'tcx, N> { nested: d.nested.into_iter().map(f).collect(), }) } - ImplSource::ConstDestruct(i) => { - ImplSource::ConstDestruct(ImplSourceConstDestructData { - nested: i.nested.into_iter().map(f).collect(), - }) - } } } } @@ -845,13 +821,6 @@ pub struct ImplSourceClosureData<'tcx, N> { pub nested: Vec, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceAutoImplData { - pub trait_def_id: DefId, - pub nested: Vec, -} - #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceTraitUpcastingData { @@ -886,12 +855,6 @@ pub struct ImplSourceFnPointerData<'tcx, N> { pub nested: Vec, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceConstDestructData { - pub nested: Vec, -} - #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceTraitAliasData<'tcx, N> { diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index 311d3d1f1e8e..9cc732acefa0 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -9,8 +9,6 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { match *self { super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v), - super::ImplSource::AutoImpl(ref t) => write!(f, "{:?}", t), - super::ImplSource::Closure(ref d) => write!(f, "{:?}", d), super::ImplSource::Generator(ref d) => write!(f, "{:?}", d), @@ -30,8 +28,6 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d), super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d), - - super::ImplSource::ConstDestruct(ref d) => write!(f, "{:?}", d), } } } @@ -86,16 +82,6 @@ impl fmt::Debug for traits::ImplSourceTraitUpcastingData { } } -impl fmt::Debug for traits::ImplSourceAutoImplData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceAutoImplData(trait_def_id={:?}, nested={:?})", - self.trait_def_id, self.nested - ) - } -} - impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceObjectData<'tcx, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( @@ -121,9 +107,3 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx, ) } } - -impl fmt::Debug for traits::ImplSourceConstDestructData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ImplSourceConstDestructData(nested={:?})", self.nested) - } -} diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index dd2bd45c07da..f82885252b73 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1929,9 +1929,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // why we special case object types. false } - super::ImplSource::AutoImpl(..) - | super::ImplSource::TraitUpcasting(_) - | super::ImplSource::ConstDestruct(_) => { + | super::ImplSource::TraitUpcasting(_) => { // These traits have no associated types. selcx.tcx().sess.delay_span_bug( obligation.cause.span, @@ -2001,11 +1999,9 @@ fn confirm_select_candidate<'cx, 'tcx>( super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data), super::ImplSource::Builtin(data) => confirm_builtin_candidate(selcx, obligation, data), super::ImplSource::Object(_) - | super::ImplSource::AutoImpl(..) | super::ImplSource::Param(..) | super::ImplSource::TraitUpcasting(_) - | super::ImplSource::TraitAlias(..) - | super::ImplSource::ConstDestruct(_) => { + | super::ImplSource::TraitAlias(..) => { // we don't create Select candidates with this kind of resolution span_bug!( obligation.cause.span, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 277367fe2757..ea451a3736e7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -27,11 +27,11 @@ use crate::traits::vtable::{ }; use crate::traits::{ BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource, - ImplSourceAutoImplData, ImplSourceClosureData, ImplSourceConstDestructData, - ImplSourceFnPointerData, ImplSourceFutureData, ImplSourceGeneratorData, ImplSourceObjectData, - ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, - Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, - SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, + ImplSourceClosureData, ImplSourceFnPointerData, ImplSourceFutureData, ImplSourceGeneratorData, + ImplSourceObjectData, ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, + ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, + OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError, + TraitNotObjectSafe, TraitObligation, Unimplemented, }; use super::BuiltinImplConditions; @@ -71,7 +71,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { AutoImplCandidate => { let data = self.confirm_auto_impl_candidate(obligation); - ImplSource::AutoImpl(data) + ImplSource::Builtin(data) } ProjectionCandidate(idx, constness) => { @@ -128,7 +128,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ConstDestructCandidate(def_id) => { let data = self.confirm_const_destruct_candidate(obligation, def_id)?; - ImplSource::ConstDestruct(data) + ImplSource::Builtin(data) } }; @@ -379,7 +379,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_auto_impl_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> ImplSourceAutoImplData> { + ) -> Vec> { debug!(?obligation, "confirm_auto_impl_candidate"); let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty()); @@ -393,7 +393,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &TraitObligation<'tcx>, trait_def_id: DefId, nested: ty::Binder<'tcx, Vec>>, - ) -> ImplSourceAutoImplData> { + ) -> Vec> { debug!(?nested, "vtable_auto_impl"); ensure_sufficient_stack(|| { let cause = obligation.derived_cause(BuiltinDerivedObligation); @@ -423,7 +423,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?obligations, "vtable_auto_impl"); - ImplSourceAutoImplData { trait_def_id, nested: obligations } + obligations }) } @@ -1222,10 +1222,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, impl_def_id: Option, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { // `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop` if !obligation.is_const() { - return Ok(ImplSourceConstDestructData { nested: vec![] }); + return Ok(vec![]); } let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None); @@ -1379,6 +1379,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } - Ok(ImplSourceConstDestructData { nested }) + Ok(nested) } } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index dd911239ac45..81ad883903f3 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -312,11 +312,9 @@ fn resolve_associated_item<'tcx>( None } } - traits::ImplSource::AutoImpl(..) - | traits::ImplSource::Param(..) + traits::ImplSource::Param(..) | traits::ImplSource::TraitAlias(..) - | traits::ImplSource::TraitUpcasting(_) - | traits::ImplSource::ConstDestruct(_) => None, + | traits::ImplSource::TraitUpcasting(_) => None, }) } From 1311bb56f3946fcdcf8dd54fecf245ef408e6d04 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 16 Jun 2023 00:48:29 +0000 Subject: [PATCH 38/41] Simplify an ObjectData field --- compiler/rustc_middle/src/traits/mod.rs | 8 ++++---- compiler/rustc_middle/src/traits/structural_impls.rs | 4 ++-- .../src/traits/select/confirmation.rs | 8 ++++++-- compiler/rustc_trait_selection/src/traits/util.rs | 4 ++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index adc63aa6addd..a39f3ae7b4d6 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -653,7 +653,7 @@ pub enum ImplSource<'tcx, N> { Param(Vec, ty::BoundConstness), /// Virtual calls through an object. - Object(ImplSourceObjectData<'tcx, N>), + Object(ImplSourceObjectData), /// Successful resolution for a builtin trait. Builtin(Vec), @@ -735,7 +735,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { ImplSource::Param(n, ct) => ImplSource::Param(n.into_iter().map(f).collect(), ct), ImplSource::Builtin(n) => ImplSource::Builtin(n.into_iter().map(f).collect()), ImplSource::Object(o) => ImplSource::Object(ImplSourceObjectData { - upcast_trait_ref: o.upcast_trait_ref, + upcast_trait_def_id: o.upcast_trait_def_id, vtable_base: o.vtable_base, nested: o.nested.into_iter().map(f).collect(), }), @@ -835,9 +835,9 @@ pub struct ImplSourceTraitUpcastingData { #[derive(PartialEq, Eq, Clone, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceObjectData<'tcx, N> { +pub struct ImplSourceObjectData { /// `Foo` upcast to the obligation trait. This will be some supertrait of `Foo`. - pub upcast_trait_ref: ty::PolyTraitRef<'tcx>, + pub upcast_trait_def_id: DefId, /// The vtable is formed by concatenating together the method lists of /// the base object trait and all supertraits, pointers to supertrait vtable will diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index 9cc732acefa0..3e7ed4dabe97 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -82,12 +82,12 @@ impl fmt::Debug for traits::ImplSourceTraitUpcastingData { } } -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceObjectData<'tcx, N> { +impl fmt::Debug for traits::ImplSourceObjectData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "ImplSourceObjectData(upcast={:?}, vtable_base={}, nested={:?})", - self.upcast_trait_ref, self.vtable_base, self.nested + self.upcast_trait_def_id, self.vtable_base, self.nested ) } } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ea451a3736e7..bf37cc68b8c0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -486,7 +486,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, index: usize, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { let tcx = self.tcx(); debug!(?obligation, ?index, "confirm_object_candidate"); @@ -653,7 +653,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)), ); - Ok(ImplSourceObjectData { upcast_trait_ref, vtable_base, nested }) + Ok(ImplSourceObjectData { + upcast_trait_def_id: upcast_trait_ref.def_id(), + vtable_base, + nested, + }) } fn confirm_fn_pointer_candidate( diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 537405b7eb91..906c357e8ca7 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -243,12 +243,12 @@ pub fn upcast_choices<'tcx>( /// `object.upcast_trait_ref`) within the vtable for `object`. pub fn get_vtable_index_of_object_method<'tcx, N>( tcx: TyCtxt<'tcx>, - object: &super::ImplSourceObjectData<'tcx, N>, + object: &super::ImplSourceObjectData, method_def_id: DefId, ) -> Option { // Count number of methods preceding the one we are selecting and // add them to the total offset. - tcx.own_existential_vtable_entries(object.upcast_trait_ref.def_id()) + tcx.own_existential_vtable_entries(object.upcast_trait_def_id) .iter() .copied() .position(|def_id| def_id == method_def_id) From 2835d9d1d3ab3f09f0117cad8f0a6e0abe142282 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 16 Jun 2023 01:16:40 +0000 Subject: [PATCH 39/41] Simplify even more candidates --- .../src/transform/check_consts/check.rs | 9 +- compiler/rustc_middle/src/traits/mod.rs | 101 +++++------------- .../src/traits/structural_impls.rs | 36 ------- .../src/traits/project.rs | 44 +++++--- .../src/traits/select/confirmation.rs | 19 ++-- compiler/rustc_ty_utils/src/instance.rs | 40 ++++--- 6 files changed, 88 insertions(+), 161 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 57d939747aab..d4cde7e2c652 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -781,8 +781,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { ); return; } - Ok(Some(ImplSource::Closure(data))) => { - if !tcx.is_const_fn_raw(data.closure_def_id) { + Ok(Some(ImplSource::Closure(_))) => { + let ty::Closure(closure_def_id, substs) = + *poly_trait_pred.self_ty().no_bound_vars().unwrap().kind() + else { + unreachable!() + }; + if !tcx.is_const_fn_raw(closure_def_id) { self.check_op(ops::FnCallNonConst { caller, callee, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index a39f3ae7b4d6..98179c0f933d 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -664,16 +664,16 @@ pub enum ImplSource<'tcx, N> { /// ImplSource automatically generated for a closure. The `DefId` is the ID /// of the closure expression. This is an `ImplSource::UserDefined` in spirit, but the /// impl is generated by the compiler and does not appear in the source. - Closure(ImplSourceClosureData<'tcx, N>), + Closure(Vec), /// Same as above, but for a function pointer type with the given signature. - FnPointer(ImplSourceFnPointerData<'tcx, N>), + FnPointer(Vec), /// ImplSource automatically generated for a generator. - Generator(ImplSourceGeneratorData<'tcx, N>), + Generator(Vec), /// ImplSource automatically generated for a generator backing an async future. - Future(ImplSourceFutureData<'tcx, N>), + Future(Vec), /// ImplSource for a trait alias. TraitAlias(ImplSourceTraitAliasData<'tcx, N>), @@ -683,12 +683,13 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn nested_obligations(self) -> Vec { match self { ImplSource::UserDefined(i) => i.nested, - ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, - ImplSource::Closure(c) => c.nested, - ImplSource::Generator(c) => c.nested, - ImplSource::Future(c) => c.nested, + ImplSource::Param(n, _) + | ImplSource::Builtin(n) + | ImplSource::FnPointer(n) + | ImplSource::Closure(n) + | ImplSource::Generator(n) + | ImplSource::Future(n) => n, ImplSource::Object(d) => d.nested, - ImplSource::FnPointer(d) => d.nested, ImplSource::TraitAlias(d) => d.nested, ImplSource::TraitUpcasting(d) => d.nested, } @@ -697,12 +698,13 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn borrow_nested_obligations(&self) -> &[N] { match self { ImplSource::UserDefined(i) => &i.nested, - ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, - ImplSource::Closure(c) => &c.nested, - ImplSource::Generator(c) => &c.nested, - ImplSource::Future(c) => &c.nested, + ImplSource::Param(n, _) + | ImplSource::Builtin(n) + | ImplSource::FnPointer(n) + | ImplSource::Closure(n) + | ImplSource::Generator(n) + | ImplSource::Future(n) => &n, ImplSource::Object(d) => &d.nested, - ImplSource::FnPointer(d) => &d.nested, ImplSource::TraitAlias(d) => &d.nested, ImplSource::TraitUpcasting(d) => &d.nested, } @@ -711,12 +713,13 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] { match self { ImplSource::UserDefined(i) => &mut i.nested, - ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, - ImplSource::Closure(c) => &mut c.nested, - ImplSource::Generator(c) => &mut c.nested, - ImplSource::Future(c) => &mut c.nested, + ImplSource::Param(n, _) + | ImplSource::Builtin(n) + | ImplSource::FnPointer(n) + | ImplSource::Closure(n) + | ImplSource::Generator(n) + | ImplSource::Future(n) => n, ImplSource::Object(d) => &mut d.nested, - ImplSource::FnPointer(d) => &mut d.nested, ImplSource::TraitAlias(d) => &mut d.nested, ImplSource::TraitUpcasting(d) => &mut d.nested, } @@ -739,25 +742,10 @@ impl<'tcx, N> ImplSource<'tcx, N> { vtable_base: o.vtable_base, nested: o.nested.into_iter().map(f).collect(), }), - ImplSource::Closure(c) => ImplSource::Closure(ImplSourceClosureData { - closure_def_id: c.closure_def_id, - substs: c.substs, - nested: c.nested.into_iter().map(f).collect(), - }), - ImplSource::Generator(c) => ImplSource::Generator(ImplSourceGeneratorData { - generator_def_id: c.generator_def_id, - substs: c.substs, - nested: c.nested.into_iter().map(f).collect(), - }), - ImplSource::Future(c) => ImplSource::Future(ImplSourceFutureData { - generator_def_id: c.generator_def_id, - substs: c.substs, - nested: c.nested.into_iter().map(f).collect(), - }), - ImplSource::FnPointer(p) => ImplSource::FnPointer(ImplSourceFnPointerData { - fn_ty: p.fn_ty, - nested: p.nested.into_iter().map(f).collect(), - }), + ImplSource::Closure(n) => ImplSource::Closure(n.into_iter().map(f).collect()), + ImplSource::Generator(n) => ImplSource::Generator(n.into_iter().map(f).collect()), + ImplSource::Future(n) => ImplSource::Future(n.into_iter().map(f).collect()), + ImplSource::FnPointer(n) => ImplSource::FnPointer(n.into_iter().map(f).collect()), ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData { alias_def_id: d.alias_def_id, substs: d.substs, @@ -791,36 +779,6 @@ pub struct ImplSourceUserDefinedData<'tcx, N> { pub nested: Vec, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceGeneratorData<'tcx, N> { - pub generator_def_id: DefId, - pub substs: SubstsRef<'tcx>, - /// Nested obligations. This can be non-empty if the generator - /// signature contains associated types. - pub nested: Vec, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceFutureData<'tcx, N> { - pub generator_def_id: DefId, - pub substs: SubstsRef<'tcx>, - /// Nested obligations. This can be non-empty if the generator - /// signature contains associated types. - pub nested: Vec, -} - -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceClosureData<'tcx, N> { - pub closure_def_id: DefId, - pub substs: SubstsRef<'tcx>, - /// Nested obligations. This can be non-empty if the closure - /// signature contains associated types. - pub nested: Vec, -} - #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceTraitUpcastingData { @@ -848,13 +806,6 @@ pub struct ImplSourceObjectData { pub nested: Vec, } -#[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] -#[derive(TypeFoldable, TypeVisitable)] -pub struct ImplSourceFnPointerData<'tcx, N> { - pub fn_ty: Ty<'tcx>, - pub nested: Vec, -} - #[derive(Clone, PartialEq, Eq, TyEncodable, TyDecodable, HashStable, Lift)] #[derive(TypeFoldable, TypeVisitable)] pub struct ImplSourceTraitAliasData<'tcx, N> { diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index 3e7ed4dabe97..bc0e656a656c 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -42,36 +42,6 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceUserDefinedData<'tcx, } } -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceGeneratorData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceGeneratorData(generator_def_id={:?}, substs={:?}, nested={:?})", - self.generator_def_id, self.substs, self.nested - ) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFutureData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceFutureData(generator_def_id={:?}, substs={:?}, nested={:?})", - self.generator_def_id, self.substs, self.nested - ) - } -} - -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceClosureData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "ImplSourceClosureData(closure_def_id={:?}, substs={:?}, nested={:?})", - self.closure_def_id, self.substs, self.nested - ) - } -} - impl fmt::Debug for traits::ImplSourceTraitUpcastingData { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( @@ -92,12 +62,6 @@ impl fmt::Debug for traits::ImplSourceObjectData { } } -impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceFnPointerData<'tcx, N> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ImplSourceFnPointerData(fn_ty={:?}, nested={:?})", self.fn_ty, self.nested) - } -} - impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSourceTraitAliasData<'tcx, N> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index f82885252b73..1477c8957f6e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -3,6 +3,7 @@ use super::specialization_graph; use super::translate_substs; use super::util; +use super::ImplSourceUserDefinedData; use super::MismatchedProjectionTypes; use super::Obligation; use super::ObligationCause; @@ -10,10 +11,6 @@ use super::PredicateObligation; use super::Selection; use super::SelectionContext; use super::SelectionError; -use super::{ - ImplSourceClosureData, ImplSourceFnPointerData, ImplSourceFutureData, ImplSourceGeneratorData, - ImplSourceUserDefinedData, -}; use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey}; use crate::errors::InherentProjectionNormalizationOverflow; @@ -2015,9 +2012,14 @@ fn confirm_select_candidate<'cx, 'tcx>( fn confirm_generator_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - impl_source: ImplSourceGeneratorData<'tcx, PredicateObligation<'tcx>>, + nested: Vec>, ) -> Progress<'tcx> { - let gen_sig = impl_source.substs.as_generator().poly_sig(); + let ty::Generator(_, substs, _) = + selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() + else { + unreachable!() + }; + let gen_sig = substs.as_generator().poly_sig(); let Normalized { value: gen_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -2055,16 +2057,21 @@ fn confirm_generator_candidate<'cx, 'tcx>( }); confirm_param_env_candidate(selcx, obligation, predicate, false) - .with_addl_obligations(impl_source.nested) + .with_addl_obligations(nested) .with_addl_obligations(obligations) } fn confirm_future_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - impl_source: ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>, + nested: Vec>, ) -> Progress<'tcx> { - let gen_sig = impl_source.substs.as_generator().poly_sig(); + let ty::Generator(_, substs, _) = + selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() + else { + unreachable!() + }; + let gen_sig = substs.as_generator().poly_sig(); let Normalized { value: gen_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -2094,7 +2101,7 @@ fn confirm_future_candidate<'cx, 'tcx>( }); confirm_param_env_candidate(selcx, obligation, predicate, false) - .with_addl_obligations(impl_source.nested) + .with_addl_obligations(nested) .with_addl_obligations(obligations) } @@ -2155,9 +2162,9 @@ fn confirm_builtin_candidate<'cx, 'tcx>( fn confirm_fn_pointer_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - fn_pointer_impl_source: ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, + nested: Vec>, ) -> Progress<'tcx> { - let fn_type = selcx.infcx.shallow_resolve(fn_pointer_impl_source.fn_ty); + let fn_type = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let sig = fn_type.fn_sig(selcx.tcx()); let Normalized { value: sig, obligations } = normalize_with_depth( selcx, @@ -2168,16 +2175,21 @@ fn confirm_fn_pointer_candidate<'cx, 'tcx>( ); confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes) - .with_addl_obligations(fn_pointer_impl_source.nested) + .with_addl_obligations(nested) .with_addl_obligations(obligations) } fn confirm_closure_candidate<'cx, 'tcx>( selcx: &mut SelectionContext<'cx, 'tcx>, obligation: &ProjectionTyObligation<'tcx>, - impl_source: ImplSourceClosureData<'tcx, PredicateObligation<'tcx>>, + nested: Vec>, ) -> Progress<'tcx> { - let closure_sig = impl_source.substs.as_closure().sig(); + let ty::Closure(_, substs) = + selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind() + else { + unreachable!() + }; + let closure_sig = substs.as_closure().sig(); let Normalized { value: closure_sig, obligations } = normalize_with_depth( selcx, obligation.param_env, @@ -2189,7 +2201,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( debug!(?obligation, ?closure_sig, ?obligations, "confirm_closure_candidate"); confirm_callable_candidate(selcx, obligation, closure_sig, util::TupleArgumentsFlag::No) - .with_addl_obligations(impl_source.nested) + .with_addl_obligations(nested) .with_addl_obligations(obligations) } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index bf37cc68b8c0..d369a087c9b8 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -27,7 +27,6 @@ use crate::traits::vtable::{ }; use crate::traits::{ BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource, - ImplSourceClosureData, ImplSourceFnPointerData, ImplSourceFutureData, ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError, @@ -664,8 +663,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, is_const: bool, - ) -> Result>, SelectionError<'tcx>> - { + ) -> Result>, SelectionError<'tcx>> { debug!(?obligation, "confirm_fn_pointer_candidate"); let tcx = self.tcx(); @@ -717,7 +715,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let tr = ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [output_ty]); nested.push(Obligation::new(self.infcx.tcx, cause, obligation.param_env, tr)); - Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested }) + Ok(nested) } fn confirm_trait_alias_candidate( @@ -749,8 +747,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn confirm_generator_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> - { + ) -> Result>, SelectionError<'tcx>> { // Okay to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope // type/region parameters. @@ -783,13 +780,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; debug!(?trait_ref, ?nested, "generator candidate obligations"); - Ok(ImplSourceGeneratorData { generator_def_id, substs, nested }) + Ok(nested) } fn confirm_future_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { // Okay to skip binder because the substs on generator types never // touch bound regions, they just capture the in-scope // type/region parameters. @@ -813,14 +810,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?; debug!(?trait_ref, ?nested, "future candidate obligations"); - Ok(ImplSourceFutureData { generator_def_id, substs, nested }) + Ok(nested) } #[instrument(skip(self), level = "debug")] fn confirm_closure_candidate( &mut self, obligation: &TraitObligation<'tcx>, - ) -> Result>, SelectionError<'tcx>> { + ) -> Result>, SelectionError<'tcx>> { let kind = self .tcx() .fn_trait_kind_from_def_id(obligation.predicate.def_id()) @@ -847,7 +844,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { )); } - Ok(ImplSourceClosureData { closure_def_id, substs, nested }) + Ok(nested) } /// In the case of closure types and fn pointers, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 81ad883903f3..cc7700f378a0 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -177,30 +177,30 @@ fn resolve_associated_item<'tcx>( Some(ty::Instance::new(leaf_def.item.def_id, substs)) } - traits::ImplSource::Generator(generator_data) => { + traits::ImplSource::Generator(_) => { + let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else { + unreachable!() + }; if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume { // For compiler developers who'd like to add new items to `Generator`, // you either need to generate a shim body, or perhaps return // `InstanceDef::Item` pointing to a trait default method body if // it is given a default implementation by the trait. span_bug!( - tcx.def_span(generator_data.generator_def_id), + tcx.def_span(generator_def_id), "no definition for `{trait_ref}::{}` for built-in generator type", tcx.item_name(trait_item_id) ) } - Some(Instance { - def: ty::InstanceDef::Item(generator_data.generator_def_id), - substs: generator_data.substs, - }) + Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs }) } - traits::ImplSource::Future(future_data) => { + traits::ImplSource::Future(_) => { + let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else { + unreachable!() + }; if Some(trait_item_id) == tcx.lang_items().future_poll_fn() { // `Future::poll` is generated by the compiler. - Some(Instance { - def: ty::InstanceDef::Item(future_data.generator_def_id), - substs: future_data.substs, - }) + Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs: substs }) } else { // All other methods are default methods of the `Future` trait. // (this assumes that `ImplSource::Future` is only used for methods on `Future`) @@ -208,7 +208,10 @@ fn resolve_associated_item<'tcx>( Some(Instance::new(trait_item_id, rcvr_substs)) } } - traits::ImplSource::Closure(closure_data) => { + traits::ImplSource::Closure(_) => { + let ty::Closure(closure_def_id, substs) = *rcvr_substs.type_at(0).kind() else { + unreachable!() + }; if cfg!(debug_assertions) && ![sym::call, sym::call_mut, sym::call_once] .contains(&tcx.item_name(trait_item_id)) @@ -218,20 +221,15 @@ fn resolve_associated_item<'tcx>( // `InstanceDef::Item` pointing to a trait default method body if // it is given a default implementation by the trait. span_bug!( - tcx.def_span(closure_data.closure_def_id), + tcx.def_span(closure_def_id), "no definition for `{trait_ref}::{}` for built-in closure type", tcx.item_name(trait_item_id) ) } let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap(); - Instance::resolve_closure( - tcx, - closure_data.closure_def_id, - closure_data.substs, - trait_closure_kind, - ) + Instance::resolve_closure(tcx, closure_def_id, substs, trait_closure_kind) } - traits::ImplSource::FnPointer(ref data) => match data.fn_ty.kind() { + traits::ImplSource::FnPointer(_) => match rcvr_substs.type_at(0).kind() { ty::FnDef(..) | ty::FnPtr(..) => { if cfg!(debug_assertions) && ![sym::call, sym::call_mut, sym::call_once] @@ -247,7 +245,7 @@ fn resolve_associated_item<'tcx>( ) } Some(Instance { - def: ty::InstanceDef::FnPtrShim(trait_item_id, data.fn_ty), + def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_substs.type_at(0)), substs: rcvr_substs, }) } From d97d4ebecc502bcb5eda2cdaa513e0e7922a377e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 16 Jun 2023 02:10:10 +0000 Subject: [PATCH 40/41] Remove even more redundant builtin candidates --- .../src/transform/check_consts/check.rs | 6 +- compiler/rustc_middle/src/traits/mod.rs | 39 +---- .../src/traits/structural_impls.rs | 10 +- .../src/traits/project.rs | 34 +++-- .../src/traits/select/confirmation.rs | 8 +- compiler/rustc_ty_utils/src/instance.rs | 137 ++++++++---------- 6 files changed, 96 insertions(+), 138 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index d4cde7e2c652..106cf1114749 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -781,7 +781,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { ); return; } - Ok(Some(ImplSource::Closure(_))) => { + // Closure: Fn{Once|Mut} + Ok(Some(ImplSource::Builtin(_))) + if poly_trait_pred.self_ty().skip_binder().is_closure() + && tcx.fn_trait_kind_from_def_id(trait_id).is_some() => + { let ty::Closure(closure_def_id, substs) = *poly_trait_pred.self_ty().no_bound_vars().unwrap().kind() else { diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 98179c0f933d..492b7228488f 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -661,20 +661,6 @@ pub enum ImplSource<'tcx, N> { /// ImplSource for trait upcasting coercion TraitUpcasting(ImplSourceTraitUpcastingData), - /// ImplSource automatically generated for a closure. The `DefId` is the ID - /// of the closure expression. This is an `ImplSource::UserDefined` in spirit, but the - /// impl is generated by the compiler and does not appear in the source. - Closure(Vec), - - /// Same as above, but for a function pointer type with the given signature. - FnPointer(Vec), - - /// ImplSource automatically generated for a generator. - Generator(Vec), - - /// ImplSource automatically generated for a generator backing an async future. - Future(Vec), - /// ImplSource for a trait alias. TraitAlias(ImplSourceTraitAliasData<'tcx, N>), } @@ -683,12 +669,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn nested_obligations(self) -> Vec { match self { ImplSource::UserDefined(i) => i.nested, - ImplSource::Param(n, _) - | ImplSource::Builtin(n) - | ImplSource::FnPointer(n) - | ImplSource::Closure(n) - | ImplSource::Generator(n) - | ImplSource::Future(n) => n, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, ImplSource::Object(d) => d.nested, ImplSource::TraitAlias(d) => d.nested, ImplSource::TraitUpcasting(d) => d.nested, @@ -698,12 +679,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn borrow_nested_obligations(&self) -> &[N] { match self { ImplSource::UserDefined(i) => &i.nested, - ImplSource::Param(n, _) - | ImplSource::Builtin(n) - | ImplSource::FnPointer(n) - | ImplSource::Closure(n) - | ImplSource::Generator(n) - | ImplSource::Future(n) => &n, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => &n, ImplSource::Object(d) => &d.nested, ImplSource::TraitAlias(d) => &d.nested, ImplSource::TraitUpcasting(d) => &d.nested, @@ -713,12 +689,7 @@ impl<'tcx, N> ImplSource<'tcx, N> { pub fn borrow_nested_obligations_mut(&mut self) -> &mut [N] { match self { ImplSource::UserDefined(i) => &mut i.nested, - ImplSource::Param(n, _) - | ImplSource::Builtin(n) - | ImplSource::FnPointer(n) - | ImplSource::Closure(n) - | ImplSource::Generator(n) - | ImplSource::Future(n) => n, + ImplSource::Param(n, _) | ImplSource::Builtin(n) => n, ImplSource::Object(d) => &mut d.nested, ImplSource::TraitAlias(d) => &mut d.nested, ImplSource::TraitUpcasting(d) => &mut d.nested, @@ -742,10 +713,6 @@ impl<'tcx, N> ImplSource<'tcx, N> { vtable_base: o.vtable_base, nested: o.nested.into_iter().map(f).collect(), }), - ImplSource::Closure(n) => ImplSource::Closure(n.into_iter().map(f).collect()), - ImplSource::Generator(n) => ImplSource::Generator(n.into_iter().map(f).collect()), - ImplSource::Future(n) => ImplSource::Future(n.into_iter().map(f).collect()), - ImplSource::FnPointer(n) => ImplSource::FnPointer(n.into_iter().map(f).collect()), ImplSource::TraitAlias(d) => ImplSource::TraitAlias(ImplSourceTraitAliasData { alias_def_id: d.alias_def_id, substs: d.substs, diff --git a/compiler/rustc_middle/src/traits/structural_impls.rs b/compiler/rustc_middle/src/traits/structural_impls.rs index bc0e656a656c..ac02d6ed62f2 100644 --- a/compiler/rustc_middle/src/traits/structural_impls.rs +++ b/compiler/rustc_middle/src/traits/structural_impls.rs @@ -9,13 +9,7 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { match *self { super::ImplSource::UserDefined(ref v) => write!(f, "{:?}", v), - super::ImplSource::Closure(ref d) => write!(f, "{:?}", d), - - super::ImplSource::Generator(ref d) => write!(f, "{:?}", d), - - super::ImplSource::Future(ref d) => write!(f, "{:?}", d), - - super::ImplSource::FnPointer(ref d) => write!(f, "({:?})", d), + super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d), super::ImplSource::Object(ref d) => write!(f, "{:?}", d), @@ -23,8 +17,6 @@ impl<'tcx, N: fmt::Debug> fmt::Debug for traits::ImplSource<'tcx, N> { write!(f, "ImplSourceParamData({:?}, {:?})", n, ct) } - super::ImplSource::Builtin(ref d) => write!(f, "{:?}", d), - super::ImplSource::TraitAlias(ref d) => write!(f, "{:?}", d), super::ImplSource::TraitUpcasting(ref d) => write!(f, "{:?}", d), diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 1477c8957f6e..8399fbfc5be6 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1717,11 +1717,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( }; let eligible = match &impl_source { - super::ImplSource::Closure(_) - | super::ImplSource::Generator(_) - | super::ImplSource::Future(_) - | super::ImplSource::FnPointer(_) - | super::ImplSource::TraitAlias(_) => true, + super::ImplSource::TraitAlias(_) => true, super::ImplSource::UserDefined(impl_data) => { // We have to be careful when projecting out of an // impl because of specialization. If we are not in @@ -1779,7 +1775,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( let self_ty = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()); let lang_items = selcx.tcx().lang_items(); - if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) { + if [lang_items.gen_trait(), lang_items.future_trait()].contains(&Some(poly_trait_ref.def_id())) + || selcx.tcx().fn_trait_kind_from_def_id(poly_trait_ref.def_id()).is_some() + { + true + } else if lang_items.discriminant_kind_trait() == Some(poly_trait_ref.def_id()) { match self_ty.kind() { ty::Bool | ty::Char @@ -1990,11 +1990,23 @@ fn confirm_select_candidate<'cx, 'tcx>( ) -> Progress<'tcx> { match impl_source { super::ImplSource::UserDefined(data) => confirm_impl_candidate(selcx, obligation, data), - super::ImplSource::Generator(data) => confirm_generator_candidate(selcx, obligation, data), - super::ImplSource::Future(data) => confirm_future_candidate(selcx, obligation, data), - super::ImplSource::Closure(data) => confirm_closure_candidate(selcx, obligation, data), - super::ImplSource::FnPointer(data) => confirm_fn_pointer_candidate(selcx, obligation, data), - super::ImplSource::Builtin(data) => confirm_builtin_candidate(selcx, obligation, data), + super::ImplSource::Builtin(data) => { + let trait_def_id = obligation.predicate.trait_def_id(selcx.tcx()); + let lang_items = selcx.tcx().lang_items(); + if lang_items.gen_trait() == Some(trait_def_id) { + confirm_generator_candidate(selcx, obligation, data) + } else if lang_items.future_trait() == Some(trait_def_id) { + confirm_future_candidate(selcx, obligation, data) + } else if selcx.tcx().fn_trait_kind_from_def_id(trait_def_id).is_some() { + if obligation.predicate.self_ty().is_closure() { + confirm_closure_candidate(selcx, obligation, data) + } else { + confirm_fn_pointer_candidate(selcx, obligation, data) + } + } else { + confirm_builtin_candidate(selcx, obligation, data) + } + } super::ImplSource::Object(_) | super::ImplSource::Param(..) | super::ImplSource::TraitUpcasting(_) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index d369a087c9b8..3c356978d5ca 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -85,22 +85,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ClosureCandidate { .. } => { let vtable_closure = self.confirm_closure_candidate(obligation)?; - ImplSource::Closure(vtable_closure) + ImplSource::Builtin(vtable_closure) } GeneratorCandidate => { let vtable_generator = self.confirm_generator_candidate(obligation)?; - ImplSource::Generator(vtable_generator) + ImplSource::Builtin(vtable_generator) } FutureCandidate => { let vtable_future = self.confirm_future_candidate(obligation)?; - ImplSource::Future(vtable_future) + ImplSource::Builtin(vtable_future) } FnPointerCandidate { is_const } => { let data = self.confirm_fn_pointer_candidate(obligation, is_const)?; - ImplSource::FnPointer(data) + ImplSource::Builtin(data) } TraitAliasCandidate => { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index cc7700f378a0..45b1075b6023 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -177,83 +177,6 @@ fn resolve_associated_item<'tcx>( Some(ty::Instance::new(leaf_def.item.def_id, substs)) } - traits::ImplSource::Generator(_) => { - let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else { - unreachable!() - }; - if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume { - // For compiler developers who'd like to add new items to `Generator`, - // you either need to generate a shim body, or perhaps return - // `InstanceDef::Item` pointing to a trait default method body if - // it is given a default implementation by the trait. - span_bug!( - tcx.def_span(generator_def_id), - "no definition for `{trait_ref}::{}` for built-in generator type", - tcx.item_name(trait_item_id) - ) - } - Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs }) - } - traits::ImplSource::Future(_) => { - let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else { - unreachable!() - }; - if Some(trait_item_id) == tcx.lang_items().future_poll_fn() { - // `Future::poll` is generated by the compiler. - Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs: substs }) - } else { - // All other methods are default methods of the `Future` trait. - // (this assumes that `ImplSource::Future` is only used for methods on `Future`) - debug_assert!(tcx.defaultness(trait_item_id).has_value()); - Some(Instance::new(trait_item_id, rcvr_substs)) - } - } - traits::ImplSource::Closure(_) => { - let ty::Closure(closure_def_id, substs) = *rcvr_substs.type_at(0).kind() else { - unreachable!() - }; - if cfg!(debug_assertions) - && ![sym::call, sym::call_mut, sym::call_once] - .contains(&tcx.item_name(trait_item_id)) - { - // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`, - // you either need to generate a shim body, or perhaps return - // `InstanceDef::Item` pointing to a trait default method body if - // it is given a default implementation by the trait. - span_bug!( - tcx.def_span(closure_def_id), - "no definition for `{trait_ref}::{}` for built-in closure type", - tcx.item_name(trait_item_id) - ) - } - let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap(); - Instance::resolve_closure(tcx, closure_def_id, substs, trait_closure_kind) - } - traits::ImplSource::FnPointer(_) => match rcvr_substs.type_at(0).kind() { - ty::FnDef(..) | ty::FnPtr(..) => { - if cfg!(debug_assertions) - && ![sym::call, sym::call_mut, sym::call_once] - .contains(&tcx.item_name(trait_item_id)) - { - // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`, - // you either need to generate a shim body, or perhaps return - // `InstanceDef::Item` pointing to a trait default method body if - // it is given a default implementation by the trait. - bug!( - "no definition for `{trait_ref}::{}` for built-in fn type", - tcx.item_name(trait_item_id) - ) - } - Some(Instance { - def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_substs.type_at(0)), - substs: rcvr_substs, - }) - } - _ => bug!( - "no built-in definition for `{trait_ref}::{}` for non-fn type", - tcx.item_name(trait_item_id) - ), - }, traits::ImplSource::Object(ref data) => { traits::get_vtable_index_of_object_method(tcx, data, trait_item_id).map(|index| { Instance { @@ -306,6 +229,66 @@ fn resolve_associated_item<'tcx>( span: tcx.def_span(trait_item_id), }) } + } else if Some(trait_ref.def_id) == lang_items.future_trait() { + let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else { + bug!() + }; + if Some(trait_item_id) == tcx.lang_items().future_poll_fn() { + // `Future::poll` is generated by the compiler. + Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs: substs }) + } else { + // All other methods are default methods of the `Future` trait. + // (this assumes that `ImplSource::Builtin` is only used for methods on `Future`) + debug_assert!(tcx.defaultness(trait_item_id).has_value()); + Some(Instance::new(trait_item_id, rcvr_substs)) + } + } else if Some(trait_ref.def_id) == lang_items.gen_trait() { + let ty::Generator(generator_def_id, substs, _) = *rcvr_substs.type_at(0).kind() else { + bug!() + }; + if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume { + // For compiler developers who'd like to add new items to `Generator`, + // you either need to generate a shim body, or perhaps return + // `InstanceDef::Item` pointing to a trait default method body if + // it is given a default implementation by the trait. + span_bug!( + tcx.def_span(generator_def_id), + "no definition for `{trait_ref}::{}` for built-in generator type", + tcx.item_name(trait_item_id) + ) + } + Some(Instance { def: ty::InstanceDef::Item(generator_def_id), substs }) + } else if tcx.fn_trait_kind_from_def_id(trait_ref.def_id).is_some() { + // FIXME: This doesn't check for malformed libcore that defines, e.g., + // `trait Fn { fn call_once(&self) { .. } }`. This is mostly for extension + // methods. + if cfg!(debug_assertions) + && ![sym::call, sym::call_mut, sym::call_once] + .contains(&tcx.item_name(trait_item_id)) + { + // For compiler developers who'd like to add new items to `Fn`/`FnMut`/`FnOnce`, + // you either need to generate a shim body, or perhaps return + // `InstanceDef::Item` pointing to a trait default method body if + // it is given a default implementation by the trait. + bug!( + "no definition for `{trait_ref}::{}` for built-in callable type", + tcx.item_name(trait_item_id) + ) + } + match *rcvr_substs.type_at(0).kind() { + ty::Closure(closure_def_id, substs) => { + let trait_closure_kind = tcx.fn_trait_kind_from_def_id(trait_id).unwrap(); + Instance::resolve_closure(tcx, closure_def_id, substs, trait_closure_kind) + } + ty::FnDef(..) | ty::FnPtr(..) => Some(Instance { + def: ty::InstanceDef::FnPtrShim(trait_item_id, rcvr_substs.type_at(0)), + substs: rcvr_substs, + }), + _ => bug!( + "no built-in definition for `{trait_ref}::{}` for non-fn type", + tcx.item_name(trait_item_id) + ), + } } else { None } From b866113d1918e64140bf15647850373d5a3bbe62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Wed, 21 Jun 2023 21:53:55 +0200 Subject: [PATCH 41/41] rustdoc: render the assoc ty body before the where-clause --- src/librustdoc/html/render/mod.rs | 3 ++- tests/rustdoc/generic-associated-types/gats.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 5bd9389a400a..322ab7a4af3f 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -800,10 +800,11 @@ fn assoc_type( if !bounds.is_empty() { write!(w, ": {}", print_generic_bounds(bounds, cx)) } - write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline)); + // Render the default before the where-clause which aligns with the new recommended style. See #89122. if let Some(default) = default { write!(w, " = {}", default.print(cx)) } + write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline)); } fn assoc_method( diff --git a/tests/rustdoc/generic-associated-types/gats.rs b/tests/rustdoc/generic-associated-types/gats.rs index 7ab82bb58296..605176e5feaf 100644 --- a/tests/rustdoc/generic-associated-types/gats.rs +++ b/tests/rustdoc/generic-associated-types/gats.rs @@ -23,9 +23,9 @@ impl LendingIterator for () { pub struct Infinite(T); // @has foo/trait.LendingIterator.html -// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> where Self: 'a = &'a T" +// @has - '//*[@id="associatedtype.Item-2"]//h4[@class="code-header"]' "type Item<'a> = &'a T where Self: 'a" impl LendingIterator for Infinite { - type Item<'a> where Self: 'a = &'a T; + type Item<'a> = &'a T where Self: 'a; fn next<'a>(&'a self) -> Self::Item<'a> { &self.0