Auto merge of #75715 - tmandry:rollup-18atkj4, r=tmandry

Rollup of 7 pull requests

Successful merges:

 - #75069 (move const param structural match checks to wfcheck)
 - #75587 (mir building: fix some comments)
 - #75593 (Adjust installation place for compiler docs)
 - #75648 (Make OnceCell<T> transparent to dropck)
 - #75649 (Fix intra-doc links for inherent impls that are both lang items and not the default impl)
 - #75674 (Move to intra doc links for std::io)
 - #75696 (Remove `#[cfg(miri)]` from OnceCell tests)

Failed merges:

r? @ghost
This commit is contained in:
bors 2020-08-19 18:13:03 +00:00
commit 9900178cba
54 changed files with 608 additions and 759 deletions

View File

@ -4106,6 +4106,7 @@ dependencies = [
"rustc-rayon",
"serde",
"serde_json",
"smallvec 1.4.2",
"tempfile",
]

View File

@ -122,3 +122,12 @@ fn reentrant_init() {
});
eprintln!("use after free: {:?}", dangling_ref.get().unwrap());
}
#[test]
fn dropck() {
let cell = OnceCell::new();
{
let s = String::new();
cell.set(&s).unwrap();
}
}

View File

@ -21,17 +21,16 @@ use crate::memchr;
/// *repeated* read calls to the same file or network socket. It does not
/// help when reading very large amounts at once, or reading just one or a few
/// times. It also provides no advantage when reading from a source that is
/// already in memory, like a `Vec<u8>`.
/// already in memory, like a [`Vec`]`<u8>`.
///
/// When the `BufReader<R>` is dropped, the contents of its buffer will be
/// discarded. Creating multiple instances of a `BufReader<R>` on the same
/// stream can cause data loss. Reading from the underlying reader after
/// unwrapping the `BufReader<R>` with `BufReader::into_inner` can also cause
/// unwrapping the `BufReader<R>` with [`BufReader::into_inner`] can also cause
/// data loss.
///
/// [`Read`]: ../../std/io/trait.Read.html
/// [`TcpStream::read`]: ../../std/net/struct.TcpStream.html#method.read
/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
/// [`TcpStream::read`]: Read::read
/// [`TcpStream`]: crate::net::TcpStream
///
/// # Examples
///
@ -155,7 +154,9 @@ impl<R> BufReader<R> {
/// Returns a reference to the internally buffered data.
///
/// Unlike `fill_buf`, this will not attempt to fill the buffer if it is empty.
/// Unlike [`fill_buf`], this will not attempt to fill the buffer if it is empty.
///
/// [`fill_buf`]: BufRead::fill_buf
///
/// # Examples
///
@ -338,27 +339,26 @@ where
impl<R: Seek> Seek for BufReader<R> {
/// Seek to an offset, in bytes, in the underlying reader.
///
/// The position used for seeking with `SeekFrom::Current(_)` is the
/// The position used for seeking with [`SeekFrom::Current`]`(_)` is the
/// position the underlying reader would be at if the `BufReader<R>` had no
/// internal buffer.
///
/// Seeking always discards the internal buffer, even if the seek position
/// would otherwise fall within it. This guarantees that calling
/// `.into_inner()` immediately after a seek yields the underlying reader
/// [`BufReader::into_inner()`] immediately after a seek yields the underlying reader
/// at the same position.
///
/// To seek without discarding the internal buffer, use [`BufReader::seek_relative`].
///
/// See [`std::io::Seek`] for more details.
///
/// Note: In the edge case where you're seeking with `SeekFrom::Current(n)`
/// Note: In the edge case where you're seeking with [`SeekFrom::Current`]`(n)`
/// where `n` minus the internal buffer length overflows an `i64`, two
/// seeks will be performed instead of one. If the second seek returns
/// `Err`, the underlying reader will be left at the same position it would
/// have if you called `seek` with `SeekFrom::Current(0)`.
/// [`Err`], the underlying reader will be left at the same position it would
/// have if you called `seek` with [`SeekFrom::Current`]`(0)`.
///
/// [`BufReader::seek_relative`]: struct.BufReader.html#method.seek_relative
/// [`std::io::Seek`]: trait.Seek.html
/// [`std::io::Seek`]: Seek
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
let result: u64;
if let SeekFrom::Current(n) = pos {
@ -397,7 +397,7 @@ impl<R: Seek> Seek for BufReader<R> {
/// *repeated* write calls to the same file or network socket. It does not
/// help when writing very large amounts at once, or writing just one or a few
/// times. It also provides no advantage when writing to a destination that is
/// in memory, like a `Vec<u8>`.
/// in memory, like a [`Vec`]<u8>`.
///
/// It is critical to call [`flush`] before `BufWriter<W>` is dropped. Though
/// dropping will attempt to flush the contents of the buffer, any errors
@ -441,10 +441,9 @@ impl<R: Seek> Seek for BufReader<R> {
/// together by the buffer and will all be written out in one system call when
/// the `stream` is flushed.
///
/// [`Write`]: ../../std/io/trait.Write.html
/// [`TcpStream::write`]: ../../std/net/struct.TcpStream.html#method.write
/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
/// [`flush`]: #method.flush
/// [`TcpStream::write`]: Write::write
/// [`TcpStream`]: crate::net::TcpStream
/// [`flush`]: Write::flush
#[stable(feature = "rust1", since = "1.0.0")]
pub struct BufWriter<W: Write> {
inner: Option<W>,
@ -455,7 +454,7 @@ pub struct BufWriter<W: Write> {
panicked: bool,
}
/// An error returned by `into_inner` which combines an error that
/// An error returned by [`BufWriter::into_inner`] which combines an error that
/// happened while writing out the buffer, and the buffered writer object
/// which may be used to recover from the condition.
///
@ -629,7 +628,7 @@ impl<W: Write> BufWriter<W> {
///
/// # Errors
///
/// An `Err` will be returned if an error occurs while flushing the buffer.
/// An [`Err`] will be returned if an error occurs while flushing the buffer.
///
/// # Examples
///
@ -725,7 +724,8 @@ impl<W: Write> Drop for BufWriter<W> {
}
impl<W> IntoInnerError<W> {
/// Returns the error which caused the call to `into_inner()` to fail.
/// Returns the error which caused the call to [`BufWriter::into_inner()`]
/// to fail.
///
/// This error was returned when attempting to write the internal buffer.
///
@ -819,17 +819,15 @@ impl<W> fmt::Display for IntoInnerError<W> {
/// Wraps a writer and buffers output to it, flushing whenever a newline
/// (`0x0a`, `'\n'`) is detected.
///
/// The [`BufWriter`][bufwriter] struct wraps a writer and buffers its output.
/// The [`BufWriter`] struct wraps a writer and buffers its output.
/// But it only does this batched write when it goes out of scope, or when the
/// internal buffer is full. Sometimes, you'd prefer to write each line as it's
/// completed, rather than the entire buffer at once. Enter `LineWriter`. It
/// does exactly that.
///
/// Like [`BufWriter`][bufwriter], a `LineWriter`s buffer will also be flushed when the
/// Like [`BufWriter`], a `LineWriter`s buffer will also be flushed when the
/// `LineWriter` goes out of scope or when its internal buffer is full.
///
/// [bufwriter]: struct.BufWriter.html
///
/// If there's still a partial line in the buffer when the `LineWriter` is
/// dropped, it will flush those contents.
///
@ -979,7 +977,7 @@ impl<W: Write> LineWriter<W> {
///
/// # Errors
///
/// An `Err` will be returned if an error occurs while flushing the buffer.
/// An [`Err`] will be returned if an error occurs while flushing the buffer.
///
/// # Examples
///

View File

@ -9,7 +9,7 @@ use core::convert::TryInto;
/// [`Seek`] implementation.
///
/// `Cursor`s are used with in-memory buffers, anything implementing
/// `AsRef<[u8]>`, to allow them to implement [`Read`] and/or [`Write`],
/// [`AsRef`]`<[u8]>`, to allow them to implement [`Read`] and/or [`Write`],
/// allowing these buffers to be used anywhere you might use a reader or writer
/// that does actual I/O.
///
@ -23,12 +23,8 @@ use core::convert::TryInto;
/// code, but use an in-memory buffer in our tests. We can do this with
/// `Cursor`:
///
/// [`Seek`]: trait.Seek.html
/// [`Read`]: ../../std/io/trait.Read.html
/// [`Write`]: ../../std/io/trait.Write.html
/// [`Vec`]: ../../std/vec/struct.Vec.html
/// [bytes]: ../../std/primitive.slice.html
/// [`File`]: ../fs/struct.File.html
/// [bytes]: crate::slice
/// [`File`]: crate::fs::File
///
/// ```no_run
/// use std::io::prelude::*;
@ -81,8 +77,8 @@ pub struct Cursor<T> {
impl<T> Cursor<T> {
/// Creates a new cursor wrapping the provided underlying in-memory buffer.
///
/// Cursor initial position is `0` even if underlying buffer (e.g., `Vec`)
/// is not empty. So writing to cursor starts with overwriting `Vec`
/// Cursor initial position is `0` even if underlying buffer (e.g., [`Vec`])
/// is not empty. So writing to cursor starts with overwriting [`Vec`]
/// content, not with appending to it.
///
/// # Examples

View File

@ -4,8 +4,7 @@ use crate::fmt;
use crate::result;
use crate::sys;
/// A specialized [`Result`](../result/enum.Result.html) type for I/O
/// operations.
/// A specialized [`Result`] type for I/O operations.
///
/// This type is broadly used across [`std::io`] for any operation which may
/// produce an error.
@ -16,12 +15,13 @@ use crate::sys;
/// While usual Rust style is to import types directly, aliases of [`Result`]
/// often are not, to make it easier to distinguish between them. [`Result`] is
/// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias
/// will generally use `io::Result` instead of shadowing the prelude's import
/// will generally use `io::Result` instead of shadowing the [prelude]'s import
/// of [`std::result::Result`][`Result`].
///
/// [`std::io`]: ../io/index.html
/// [`io::Error`]: ../io/struct.Error.html
/// [`Result`]: ../result/enum.Result.html
/// [`std::io`]: crate::io
/// [`io::Error`]: Error
/// [`Result`]: crate::result::Result
/// [prelude]: crate::prelude
///
/// # Examples
///
@ -48,10 +48,9 @@ pub type Result<T> = result::Result<T, Error>;
/// `Error` can be created with crafted error messages and a particular value of
/// [`ErrorKind`].
///
/// [`Read`]: ../io/trait.Read.html
/// [`Write`]: ../io/trait.Write.html
/// [`Seek`]: ../io/trait.Seek.html
/// [`ErrorKind`]: enum.ErrorKind.html
/// [`Read`]: crate::io::Read
/// [`Write`]: crate::io::Write
/// [`Seek`]: crate::io::Seek
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Error {
repr: Repr,
@ -83,7 +82,7 @@ struct Custom {
///
/// It is used with the [`io::Error`] type.
///
/// [`io::Error`]: struct.Error.html
/// [`io::Error`]: Error
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(deprecated)]
@ -137,7 +136,7 @@ pub enum ErrorKind {
/// For example, a function that reads a file into a string will error with
/// `InvalidData` if the file's contents are not valid UTF-8.
///
/// [`InvalidInput`]: #variant.InvalidInput
/// [`InvalidInput`]: ErrorKind::InvalidInput
#[stable(feature = "io_invalid_data", since = "1.2.0")]
InvalidData,
/// The I/O operation's timeout expired, causing it to be canceled.
@ -150,8 +149,8 @@ pub enum ErrorKind {
/// particular number of bytes but only a smaller number of bytes could be
/// written.
///
/// [`write`]: ../../std/io/trait.Write.html#tymethod.write
/// [`Ok(0)`]: ../../std/io/type.Result.html
/// [`write`]: crate::io::Write::write
/// [`Ok(0)`]: Ok
#[stable(feature = "rust1", since = "1.0.0")]
WriteZero,
/// This operation was interrupted.
@ -220,9 +219,6 @@ impl From<ErrorKind> for Error {
/// let error = Error::from(not_found);
/// assert_eq!("entity not found", format!("{}", error));
/// ```
///
/// [`ErrorKind`]: ../../std/io/enum.ErrorKind.html
/// [`Error`]: ../../std/io/struct.Error.html
#[inline]
fn from(kind: ErrorKind) -> Error {
Error { repr: Repr::Simple(kind) }
@ -235,7 +231,7 @@ impl Error {
///
/// This function is used to generically create I/O errors which do not
/// originate from the OS itself. The `error` argument is an arbitrary
/// payload which will be contained in this `Error`.
/// payload which will be contained in this [`Error`].
///
/// # Examples
///
@ -264,7 +260,7 @@ impl Error {
///
/// This function reads the value of `errno` for the target platform (e.g.
/// `GetLastError` on Windows) and will return a corresponding instance of
/// `Error` for the error code.
/// [`Error`] for the error code.
///
/// # Examples
///
@ -278,7 +274,7 @@ impl Error {
Error::from_raw_os_error(sys::os::errno() as i32)
}
/// Creates a new instance of an `Error` from a particular OS error code.
/// Creates a new instance of an [`Error`] from a particular OS error code.
///
/// # Examples
///
@ -310,9 +306,12 @@ impl Error {
/// Returns the OS error that this error represents (if any).
///
/// If this `Error` was constructed via `last_os_error` or
/// `from_raw_os_error`, then this function will return `Some`, otherwise
/// it will return `None`.
/// If this [`Error`] was constructed via [`last_os_error`] or
/// [`from_raw_os_error`], then this function will return [`Some`], otherwise
/// it will return [`None`].
///
/// [`last_os_error`]: Error::last_os_error
/// [`from_raw_os_error`]: Error::from_raw_os_error
///
/// # Examples
///
@ -345,8 +344,10 @@ impl Error {
/// Returns a reference to the inner error wrapped by this error (if any).
///
/// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`.
/// If this [`Error`] was constructed via [`new`] then this function will
/// return [`Some`], otherwise it will return [`None`].
///
/// [`new`]: Error::new
///
/// # Examples
///
@ -380,8 +381,10 @@ impl Error {
/// Returns a mutable reference to the inner error wrapped by this error
/// (if any).
///
/// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`.
/// If this [`Error`] was constructed via [`new`] then this function will
/// return [`Some`], otherwise it will return [`None`].
///
/// [`new`]: Error::new
///
/// # Examples
///
@ -448,8 +451,10 @@ impl Error {
/// Consumes the `Error`, returning its inner error (if any).
///
/// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`.
/// If this [`Error`] was constructed via [`new`] then this function will
/// return [`Some`], otherwise it will return [`None`].
///
/// [`new`]: Error::new
///
/// # Examples
///
@ -480,7 +485,7 @@ impl Error {
}
}
/// Returns the corresponding `ErrorKind` for this error.
/// Returns the corresponding [`ErrorKind`] for this error.
///
/// # Examples
///

View File

@ -240,9 +240,9 @@
//!
//! [`File`]: crate::fs::File
//! [`TcpStream`]: crate::net::TcpStream
//! [`Vec<T>`]: crate::vec::Vec
//! [`Vec<T>`]: Vec
//! [`io::stdout`]: stdout
//! [`io::Result`]: crate::io::Result
//! [`io::Result`]: self::Result
//! [`?` operator]: ../../book/appendix-02-operators.html
//! [`Result`]: crate::result::Result
//! [`.unwrap()`]: crate::result::Result::unwrap
@ -671,15 +671,15 @@ pub trait Read {
/// If the data in this stream is *not* valid UTF-8 then an error is
/// returned and `buf` is unchanged.
///
/// See [`read_to_end`][readtoend] for other error semantics.
/// See [`read_to_end`] for other error semantics.
///
/// [readtoend]: Self::read_to_end
/// [`read_to_end`]: Read::read_to_end
///
/// # Examples
///
/// [`File`][file]s implement `Read`:
/// [`File`]s implement `Read`:
///
/// [file]: crate::fs::File
/// [`File`]: crate::fs::File
///
/// ```no_run
/// use std::io;
@ -790,9 +790,9 @@ pub trait Read {
///
/// # Examples
///
/// [`File`][file]s implement `Read`:
/// [`File`]s implement `Read`:
///
/// [file]: crate::fs::File
/// [`File`]: crate::fs::File
///
/// ```no_run
/// use std::io;
@ -834,10 +834,9 @@ pub trait Read {
///
/// # Examples
///
/// [`File`][file]s implement `Read`:
/// [`File`]s implement `Read`:
///
/// [file]: crate::fs::File
/// [`Iterator`]: crate::iter::Iterator
/// [`File`]: crate::fs::File
/// [`Result`]: crate::result::Result
/// [`io::Error`]: self::Error
///
@ -871,9 +870,9 @@ pub trait Read {
///
/// # Examples
///
/// [`File`][file]s implement `Read`:
/// [`File`]s implement `Read`:
///
/// [file]: crate::fs::File
/// [`File`]: crate::fs::File
///
/// ```no_run
/// use std::io;
@ -1210,8 +1209,8 @@ impl Initializer {
/// throughout [`std::io`] take and provide types which implement the `Write`
/// trait.
///
/// [`write`]: Self::write
/// [`flush`]: Self::flush
/// [`write`]: Write::write
/// [`flush`]: Write::flush
/// [`std::io`]: self
///
/// # Examples
@ -1237,7 +1236,7 @@ impl Initializer {
/// The trait also provides convenience methods like [`write_all`], which calls
/// `write` in a loop until its entire input has been written.
///
/// [`write_all`]: Self::write_all
/// [`write_all`]: Write::write_all
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(spotlight)]
pub trait Write {
@ -1283,30 +1282,36 @@ pub trait Write {
/// Ok(())
/// }
/// ```
///
/// [`Ok(n)`]: Ok
#[stable(feature = "rust1", since = "1.0.0")]
fn write(&mut self, buf: &[u8]) -> Result<usize>;
/// Like `write`, except that it writes from a slice of buffers.
/// Like [`write`], except that it writes from a slice of buffers.
///
/// Data is copied from each buffer in order, with the final buffer
/// read from possibly being only partially consumed. This method must
/// behave as a call to `write` with the buffers concatenated would.
/// behave as a call to [`write`] with the buffers concatenated would.
///
/// The default implementation calls `write` with either the first nonempty
/// The default implementation calls [`write`] with either the first nonempty
/// buffer provided, or an empty one if none exists.
///
/// [`write`]: Write::write
#[stable(feature = "iovec", since = "1.36.0")]
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
default_write_vectored(|b| self.write(b), bufs)
}
/// Determines if this `Write`er has an efficient `write_vectored`
/// Determines if this `Write`er has an efficient [`write_vectored`]
/// implementation.
///
/// If a `Write`er does not override the default `write_vectored`
/// If a `Write`er does not override the default [`write_vectored`]
/// implementation, code using it may want to avoid the method all together
/// and coalesce writes into a single buffer for higher performance.
///
/// The default implementation returns `false`.
///
/// [`write_vectored`]: Write::write_vectored
#[unstable(feature = "can_vector", issue = "69941")]
fn is_write_vectored(&self) -> bool {
false
@ -1354,7 +1359,7 @@ pub trait Write {
/// This function will return the first error of
/// non-[`ErrorKind::Interrupted`] kind that [`write`] returns.
///
/// [`write`]: Self::write
/// [`write`]: Write::write
///
/// # Examples
///
@ -1395,22 +1400,21 @@ pub trait Write {
///
/// If the buffer contains no data, this will never call [`write_vectored`].
///
/// [`write_vectored`]: Self::write_vectored
///
/// # Notes
///
///
/// Unlike `io::Write::write_vectored`, this takes a *mutable* reference to
/// a slice of `IoSlice`s, not an immutable one. That's because we need to
/// Unlike [`write_vectored`], this takes a *mutable* reference to
/// a slice of [`IoSlice`]s, not an immutable one. That's because we need to
/// modify the slice to keep track of the bytes already written.
///
/// Once this function returns, the contents of `bufs` are unspecified, as
/// this depends on how many calls to `write_vectored` were necessary. It is
/// this depends on how many calls to [`write_vectored`] were necessary. It is
/// best to understand this function as taking ownership of `bufs` and to
/// not use `bufs` afterwards. The underlying buffers, to which the
/// `IoSlice`s point (but not the `IoSlice`s themselves), are unchanged and
/// [`IoSlice`]s point (but not the [`IoSlice`]s themselves), are unchanged and
/// can be reused.
///
/// [`write_vectored`]: Write::write_vectored
///
/// # Examples
///
/// ```
@ -1458,12 +1462,12 @@ pub trait Write {
/// explicitly be called. The [`write!()`] macro should be favored to
/// invoke this method instead.
///
/// This function internally uses the [`write_all`][writeall] method on
/// This function internally uses the [`write_all`] method on
/// this trait and hence will continuously write data so long as no errors
/// are received. This also means that partial writes are not indicated in
/// this signature.
///
/// [writeall]: Self::write_all
/// [`write_all`]: Write::write_all
///
/// # Errors
///
@ -1558,9 +1562,9 @@ pub trait Write {
///
/// # Examples
///
/// [`File`][file]s implement `Seek`:
/// [`File`]s implement `Seek`:
///
/// [file]: crate::fs::File
/// [`File`]: crate::fs::File
///
/// ```no_run
/// use std::io;
@ -1610,7 +1614,6 @@ pub trait Seek {
/// data is appended to a file). So calling this method multiple times does
/// not necessarily return the same length each time.
///
///
/// # Example
///
/// ```no_run
@ -1646,7 +1649,6 @@ pub trait Seek {
///
/// This is equivalent to `self.seek(SeekFrom::Current(0))`.
///
///
/// # Example
///
/// ```no_run
@ -1756,8 +1758,8 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R
/// [`BufReader`] to the rescue!
///
/// [`File`]: crate::fs::File
/// [`read_line`]: Self::read_line
/// [`lines`]: Self::lines
/// [`read_line`]: BufRead::read_line
/// [`lines`]: BufRead::lines
///
/// ```no_run
/// use std::io::{self, BufReader};
@ -1775,7 +1777,6 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R
/// Ok(())
/// }
/// ```
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BufRead: Read {
/// Returns the contents of the internal buffer, filling it with more data
@ -1788,7 +1789,7 @@ pub trait BufRead: Read {
/// be called with the number of bytes that are consumed from this buffer to
/// ensure that the bytes are never returned twice.
///
/// [`consume`]: Self::consume
/// [`consume`]: BufRead::consume
///
/// An empty buffer returned indicates that the stream has reached EOF.
///
@ -1838,7 +1839,7 @@ pub trait BufRead: Read {
/// Since `consume()` is meant to be used with [`fill_buf`],
/// that method's example includes an example of `consume()`.
///
/// [`fill_buf`]: Self::fill_buf
/// [`fill_buf`]: BufRead::fill_buf
#[stable(feature = "rust1", since = "1.0.0")]
fn consume(&mut self, amt: usize);
@ -1862,7 +1863,7 @@ pub trait BufRead: Read {
/// If an I/O error is encountered then all bytes read so far will be
/// present in `buf` and its length will have been adjusted appropriately.
///
/// [`fill_buf`]: Self::fill_buf
/// [`fill_buf`]: BufRead::fill_buf
///
/// # Examples
///
@ -1901,22 +1902,24 @@ pub trait BufRead: Read {
read_until(self, byte, buf)
}
/// Read all bytes until a newline (the 0xA byte) is reached, and append
/// Read all bytes until a newline (the `0xA` byte) is reached, and append
/// them to the provided buffer.
///
/// This function will read bytes from the underlying stream until the
/// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes
/// newline delimiter (the `0xA` byte) or EOF is found. Once found, all bytes
/// up to, and including, the delimiter (if found) will be appended to
/// `buf`.
///
/// If successful, this function will return the total number of bytes read.
///
/// If this function returns `Ok(0)`, the stream has reached EOF.
/// If this function returns [`Ok(0)`], the stream has reached EOF.
///
/// This function is blocking and should be used carefully: it is possible for
/// an attacker to continuously send bytes without ever sending a newline
/// or EOF.
///
/// [`Ok(0)`]: Ok
///
/// # Errors
///
/// This function has the same error semantics as [`read_until`] and will
@ -1924,7 +1927,7 @@ pub trait BufRead: Read {
/// error is encountered then `buf` may contain some bytes already read in
/// the event that all data read so far was valid UTF-8.
///
/// [`read_until`]: Self::read_until
/// [`read_until`]: BufRead::read_until
///
/// # Examples
///
@ -1976,8 +1979,8 @@ pub trait BufRead: Read {
/// also yielded an error.
///
/// [`io::Result`]: self::Result
/// [`Vec<u8>`]: crate::vec::Vec
/// [`read_until`]: Self::read_until
/// [`Vec<u8>`]: Vec
/// [`read_until`]: BufRead::read_until
///
/// # Examples
///
@ -2008,7 +2011,7 @@ pub trait BufRead: Read {
///
/// The iterator returned from this function will yield instances of
/// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
/// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
/// byte (the `0xA` byte) or `CRLF` (`0xD`, `0xA` bytes) at the end.
///
/// [`io::Result`]: self::Result
///

View File

@ -252,8 +252,7 @@ fn handle_ebadf<T>(r: io::Result<T>, default: T) -> io::Result<T> {
///
/// Created by the [`io::stdin`] method.
///
/// [`io::stdin`]: fn.stdin.html
/// [`BufRead`]: trait.BufRead.html
/// [`io::stdin`]: stdin
///
/// ### Note: Windows Portability Consideration
///
@ -283,10 +282,6 @@ pub struct Stdin {
/// This handle implements both the [`Read`] and [`BufRead`] traits, and
/// is constructed via the [`Stdin::lock`] method.
///
/// [`Read`]: trait.Read.html
/// [`BufRead`]: trait.BufRead.html
/// [`Stdin::lock`]: struct.Stdin.html#method.lock
///
/// ### Note: Windows Portability Consideration
///
/// When operating in a console, the Windows implementation of this stream does not support
@ -319,8 +314,6 @@ pub struct StdinLock<'a> {
/// is synchronized via a mutex. If you need more explicit control over
/// locking, see the [`Stdin::lock`] method.
///
/// [`Stdin::lock`]: struct.Stdin.html#method.lock
///
/// ### Note: Windows Portability Consideration
/// When operating in a console, the Windows implementation of this stream does not support
/// non-UTF-8 byte sequences. Attempting to read bytes that are not valid UTF-8 will return
@ -380,9 +373,6 @@ impl Stdin {
/// returned guard also implements the [`Read`] and [`BufRead`] traits for
/// accessing the underlying data.
///
/// [`Read`]: trait.Read.html
/// [`BufRead`]: trait.BufRead.html
///
/// # Examples
///
/// ```no_run
@ -407,8 +397,6 @@ impl Stdin {
/// For detailed semantics of this method, see the documentation on
/// [`BufRead::read_line`].
///
/// [`BufRead::read_line`]: trait.BufRead.html#method.read_line
///
/// # Examples
///
/// ```no_run
@ -542,8 +530,8 @@ impl fmt::Debug for StdinLock<'_> {
/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
/// an error.
///
/// [`lock`]: #method.lock
/// [`io::stdout`]: fn.stdout.html
/// [`lock`]: Stdout::lock
/// [`io::stdout`]: stdout
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stdout {
// FIXME: this should be LineWriter or BufWriter depending on the state of
@ -561,9 +549,6 @@ pub struct Stdout {
/// When operating in a console, the Windows implementation of this stream does not support
/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
/// an error.
///
/// [`Write`]: trait.Write.html
/// [`Stdout::lock`]: struct.Stdout.html#method.lock
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdoutLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<Maybe<StdoutRaw>>>>,
@ -575,8 +560,6 @@ pub struct StdoutLock<'a> {
/// is synchronized via a mutex. If you need more explicit control over
/// locking, see the [`Stdout::lock`] method.
///
/// [`Stdout::lock`]: struct.Stdout.html#method.lock
///
/// ### Note: Windows Portability Consideration
/// When operating in a console, the Windows implementation of this stream does not support
/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
@ -724,7 +707,7 @@ impl fmt::Debug for StdoutLock<'_> {
///
/// For more information, see the [`io::stderr`] method.
///
/// [`io::stderr`]: fn.stderr.html
/// [`io::stderr`]: stderr
///
/// ### Note: Windows Portability Consideration
/// When operating in a console, the Windows implementation of this stream does not support
@ -740,8 +723,6 @@ pub struct Stderr {
/// This handle implements the `Write` trait and is constructed via
/// the [`Stderr::lock`] method.
///
/// [`Stderr::lock`]: struct.Stderr.html#method.lock
///
/// ### Note: Windows Portability Consideration
/// When operating in a console, the Windows implementation of this stream does not support
/// non-UTF-8 byte sequences. Attempting to write bytes that are not valid UTF-8 will return
@ -819,7 +800,7 @@ impl Stderr {
/// guard.
///
/// The lock is released when the returned lock goes out of scope. The
/// returned guard also implements the `Write` trait for writing data.
/// returned guard also implements the [`Write`] trait for writing data.
///
/// # Examples
///

View File

@ -16,14 +16,17 @@ use crate::mem::MaybeUninit;
/// If youre wanting to copy the contents of one file to another and youre
/// working with filesystem paths, see the [`fs::copy`] function.
///
/// [`fs::copy`]: ../fs/fn.copy.html
/// [`fs::copy`]: crate::fs::copy
///
/// # Errors
///
/// This function will return an error immediately if any call to `read` or
/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
/// This function will return an error immediately if any call to [`read`] or
/// [`write`] returns an error. All instances of [`ErrorKind::Interrupted`] are
/// handled by this function and the underlying operation is retried.
///
/// [`read`]: Read::read
/// [`write`]: Write::write
///
/// # Examples
///
/// ```
@ -70,10 +73,8 @@ where
/// A reader which is always at EOF.
///
/// This struct is generally created by calling [`empty`]. Please see
/// the documentation of [`empty()`][`empty`] for more details.
///
/// [`empty`]: fn.empty.html
/// This struct is generally created by calling [`empty()`]. Please see
/// the documentation of [`empty()`] for more details.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Empty {
_priv: (),
@ -83,8 +84,6 @@ pub struct Empty {
///
/// All reads from the returned reader will return [`Ok`]`(0)`.
///
/// [`Ok`]: ../result/enum.Result.html#variant.Ok
///
/// # Examples
///
/// A slightly sad example of not reading anything into a buffer:
@ -132,10 +131,8 @@ impl fmt::Debug for Empty {
/// A reader which yields one byte over and over and over and over and over and...
///
/// This struct is generally created by calling [`repeat`][repeat]. Please
/// see the documentation of `repeat()` for more details.
///
/// [repeat]: fn.repeat.html
/// This struct is generally created by calling [`repeat()`]. Please
/// see the documentation of [`repeat()`] for more details.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Repeat {
byte: u8,
@ -199,10 +196,8 @@ impl fmt::Debug for Repeat {
/// A writer which will move data into the void.
///
/// This struct is generally created by calling [`sink`][sink]. Please
/// see the documentation of `sink()` for more details.
///
/// [sink]: fn.sink.html
/// This struct is generally created by calling [`sink`]. Please
/// see the documentation of [`sink()`] for more details.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Sink {
_priv: (),
@ -210,9 +205,11 @@ pub struct Sink {
/// Creates an instance of a writer which will successfully consume all data.
///
/// All calls to `write` on the returned instance will return `Ok(buf.len())`
/// All calls to [`write`] on the returned instance will return `Ok(buf.len())`
/// and the contents of the buffer will not be inspected.
///
/// [`write`]: Write::write
///
/// # Examples
///
/// ```rust

View File

@ -386,9 +386,10 @@ impl<T> SyncOnceCell<T> {
}
}
impl<T> Drop for SyncOnceCell<T> {
unsafe impl<#[may_dangle] T> Drop for SyncOnceCell<T> {
fn drop(&mut self) {
// Safety: The cell is being dropped, so it can't be accessed again
// Safety: The cell is being dropped, so it can't be accessed again.
// We also don't touch the `T`, which validates our usage of #[may_dangle].
unsafe { self.take_inner() };
}
}
@ -516,6 +517,7 @@ mod tests {
mpsc::channel,
Mutex,
},
thread,
};
#[test]
@ -552,26 +554,8 @@ mod tests {
}
}
// miri doesn't support threads
#[cfg(not(miri))]
fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
crate::thread::spawn(f).join().unwrap()
}
#[cfg(not(miri))]
fn spawn(f: impl FnOnce() + Send + 'static) {
let _ = crate::thread::spawn(f);
}
// "stub threads" for Miri
#[cfg(miri)]
fn spawn_and_wait<R: Send + 'static>(f: impl FnOnce() -> R + Send + 'static) -> R {
f(())
}
#[cfg(miri)]
fn spawn(f: impl FnOnce() + Send + 'static) {
f(())
thread::spawn(f).join().unwrap()
}
#[test]
@ -734,7 +718,6 @@ mod tests {
}
#[test]
#[cfg_attr(miri, ignore)] // leaks memory
fn static_sync_lazy() {
static XS: SyncLazy<Vec<i32>> = SyncLazy::new(|| {
let mut xs = Vec::new();
@ -752,7 +735,6 @@ mod tests {
}
#[test]
#[cfg_attr(miri, ignore)] // leaks memory
fn static_sync_lazy_via_fn() {
fn xs() -> &'static Vec<i32> {
static XS: SyncOnceCell<Vec<i32>> = SyncOnceCell::new();
@ -811,7 +793,6 @@ mod tests {
}
#[test]
#[cfg_attr(miri, ignore)] // deadlocks without real threads
fn sync_once_cell_does_not_leak_partially_constructed_boxes() {
static ONCE_CELL: SyncOnceCell<String> = SyncOnceCell::new();
@ -823,7 +804,7 @@ mod tests {
for _ in 0..n_readers {
let tx = tx.clone();
spawn(move || {
thread::spawn(move || {
loop {
if let Some(msg) = ONCE_CELL.get() {
tx.send(msg).unwrap();
@ -835,7 +816,7 @@ mod tests {
});
}
for _ in 0..n_writers {
spawn(move || {
thread::spawn(move || {
let _ = ONCE_CELL.set(MSG.to_owned());
});
}
@ -845,4 +826,13 @@ mod tests {
assert_eq!(msg, MSG);
}
}
#[test]
fn dropck() {
let cell = SyncOnceCell::new();
{
let s = String::new();
cell.set(&s).unwrap();
}
}
}

View File

@ -162,7 +162,7 @@ impl Step for RustcDocs {
let image = tmpdir(builder).join(format!("{}-{}-image", name, host.triple));
let _ = fs::remove_dir_all(&image);
let dst = image.join("share/doc/rust/html");
let dst = image.join("share/doc/rust/html/rustc");
t!(fs::create_dir_all(&dst));
let src = builder.compiler_doc_out(host);
builder.cp_r(&src, &dst);
@ -181,7 +181,7 @@ impl Step for RustcDocs {
.arg(format!("--package-name={}-{}", name, host.triple))
.arg("--component-name=rustc-docs")
.arg("--legacy-manifest-dirs=rustlib,cargo")
.arg("--bulk-dirs=share/doc/rust/html");
.arg("--bulk-dirs=share/doc/rust/html/rustc");
builder.info(&format!("Dist compiler docs ({})", host));
let _time = timeit(builder);

View File

@ -321,6 +321,7 @@ fn mir_validated(
// Ensure that we compute the `mir_const_qualif` for constants at
// this point, before we steal the mir-const result.
// Also this means promotion can rely on all const checks having been done.
let _ = tcx.mir_const_qualif_opt_const_arg(def);
let mut body = tcx.mir_const(def).steal();
@ -336,7 +337,7 @@ fn mir_validated(
let promote: &[&dyn MirPass<'tcx>] = &[
// What we need to run borrowck etc.
&promote_pass,
&simplify::SimplifyCfg::new("qualify-consts"),
&simplify::SimplifyCfg::new("promote-consts"),
];
let opt_coverage: &[&dyn MirPass<'tcx>] = if tcx.sess.opts.debugging_opts.instrument_coverage {

View File

@ -6,9 +6,12 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit as hir_visit;
use rustc_hir::intravisit::Visitor;
use rustc_hir::itemlikevisit::ParItemLikeVisitor;
use rustc_hir::lang_items;
use rustc_hir::ItemKind;
use rustc_middle::hir::map as hir_map;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
@ -275,6 +278,107 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: LocalDefId) {
check_associated_item(tcx, impl_item.hir_id, impl_item.span, method_sig);
}
fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
match param.kind {
// We currently only check wf of const params here.
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => (),
// Const parameters are well formed if their
// type is structural match.
hir::GenericParamKind::Const { ty: hir_ty } => {
let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id));
let err_ty_str;
let mut is_ptr = true;
let err = if tcx.features().min_const_generics {
match ty.kind {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None,
ty::FnPtr(_) => Some("function pointers"),
ty::RawPtr(_) => Some("raw pointers"),
_ => {
is_ptr = false;
err_ty_str = format!("`{}`", ty);
Some(err_ty_str.as_str())
}
}
} else {
match ty.peel_refs().kind {
ty::FnPtr(_) => Some("function pointers"),
ty::RawPtr(_) => Some("raw pointers"),
_ => None,
}
};
if let Some(unsupported_type) = err {
if is_ptr {
tcx.sess.span_err(
hir_ty.span,
&format!(
"using {} as const generic parameters is forbidden",
unsupported_type
),
)
} else {
tcx.sess
.struct_span_err(
hir_ty.span,
&format!(
"{} is forbidden as the type of a const generic parameter",
unsupported_type
),
)
.note("the only supported types are integers, `bool` and `char`")
.note("more complex types are supported with `#[feature(const_generics)]`")
.emit()
}
};
if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
.is_some()
{
// We use the same error code in both branches, because this is really the same
// issue: we just special-case the message for type parameters to make it
// clearer.
if let ty::Param(_) = ty.peel_refs().kind {
// Const parameters may not have type parameters as their types,
// because we cannot be sure that the type parameter derives `PartialEq`
// and `Eq` (just implementing them is not enough for `structural_match`).
struct_span_err!(
tcx.sess,
hir_ty.span,
E0741,
"`{}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
used as the type of a const parameter",
ty,
)
.span_label(
hir_ty.span,
format!("`{}` may not derive both `PartialEq` and `Eq`", ty),
)
.note(
"it is not currently possible to use a type parameter as the type of a \
const parameter",
)
.emit();
} else {
struct_span_err!(
tcx.sess,
hir_ty.span,
E0741,
"`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
the type of a const parameter",
ty,
)
.span_label(
hir_ty.span,
format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty),
)
.emit();
}
}
}
}
}
fn check_associated_item(
tcx: TyCtxt<'_>,
item_id: hir::HirId,
@ -1282,6 +1386,7 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) {
fcx.select_all_obligations_or_error();
}
#[derive(Clone, Copy)]
pub struct CheckTypeWellFormedVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
}
@ -1294,21 +1399,49 @@ impl CheckTypeWellFormedVisitor<'tcx> {
impl ParItemLikeVisitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
fn visit_item(&self, i: &'tcx hir::Item<'tcx>) {
debug!("visit_item: {:?}", i);
let def_id = self.tcx.hir().local_def_id(i.hir_id);
self.tcx.ensure().check_item_well_formed(def_id);
Visitor::visit_item(&mut self.clone(), i);
}
fn visit_trait_item(&self, trait_item: &'tcx hir::TraitItem<'tcx>) {
debug!("visit_trait_item: {:?}", trait_item);
let def_id = self.tcx.hir().local_def_id(trait_item.hir_id);
self.tcx.ensure().check_trait_item_well_formed(def_id);
Visitor::visit_trait_item(&mut self.clone(), trait_item);
}
fn visit_impl_item(&self, impl_item: &'tcx hir::ImplItem<'tcx>) {
Visitor::visit_impl_item(&mut self.clone(), impl_item);
}
}
impl Visitor<'tcx> for CheckTypeWellFormedVisitor<'tcx> {
type Map = hir_map::Map<'tcx>;
fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
hir_visit::NestedVisitorMap::OnlyBodies(self.tcx.hir())
}
fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) {
debug!("visit_item: {:?}", i);
let def_id = self.tcx.hir().local_def_id(i.hir_id);
self.tcx.ensure().check_item_well_formed(def_id);
hir_visit::walk_item(self, i);
}
fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
debug!("visit_trait_item: {:?}", trait_item);
let def_id = self.tcx.hir().local_def_id(trait_item.hir_id);
self.tcx.ensure().check_trait_item_well_formed(def_id);
hir_visit::walk_trait_item(self, trait_item);
}
fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
debug!("visit_impl_item: {:?}", impl_item);
let def_id = self.tcx.hir().local_def_id(impl_item.hir_id);
self.tcx.ensure().check_impl_item_well_formed(def_id);
hir_visit::walk_impl_item(self, impl_item);
}
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
check_param_wf(self.tcx, p);
hir_visit::walk_generic_param(self, p);
}
}

View File

@ -12,7 +12,6 @@ use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
use rustc_span::symbol::Ident;
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::traits;
use super::ItemCtxt;
use super::{bad_placeholder_type, is_suggestable_infer_ty};
@ -323,88 +322,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
}
Node::GenericParam(param) => match &param.kind {
GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
GenericParamKind::Const { ty: ref hir_ty, .. } => {
let ty = icx.to_ty(hir_ty);
let err_ty_str;
let err = if tcx.features().min_const_generics {
match ty.kind {
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None,
ty::FnPtr(_) => Some("function pointers"),
ty::RawPtr(_) => Some("raw pointers"),
_ => {
err_ty_str = format!("`{}`", ty);
Some(err_ty_str.as_str())
}
}
} else {
match ty.peel_refs().kind {
ty::FnPtr(_) => Some("function pointers"),
ty::RawPtr(_) => Some("raw pointers"),
_ => None,
}
};
if let Some(unsupported_type) = err {
let mut err = tcx.sess.struct_span_err(
hir_ty.span,
&format!(
"using {} as const generic parameters is forbidden",
unsupported_type
),
);
if tcx.features().min_const_generics {
err.note("the only supported types are integers, `bool` and `char`")
.note("more complex types are supported with `#[feature(const_generics)]`").emit()
} else {
err.emit();
}
};
if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
.is_some()
{
// We use the same error code in both branches, because this is really the same
// issue: we just special-case the message for type parameters to make it
// clearer.
if let ty::Param(_) = ty.peel_refs().kind {
// Const parameters may not have type parameters as their types,
// because we cannot be sure that the type parameter derives `PartialEq`
// and `Eq` (just implementing them is not enough for `structural_match`).
struct_span_err!(
tcx.sess,
hir_ty.span,
E0741,
"`{}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
used as the type of a const parameter",
ty,
)
.span_label(
hir_ty.span,
format!("`{}` may not derive both `PartialEq` and `Eq`", ty),
)
.note(
"it is not currently possible to use a type parameter as the type of a \
const parameter",
)
.emit();
} else {
struct_span_err!(
tcx.sess,
hir_ty.span,
E0741,
"`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
the type of a const parameter",
ty,
)
.span_label(
hir_ty.span,
format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty),
)
.emit();
}
}
ty
}
GenericParamKind::Type { default: Some(ty), .. }
| GenericParamKind::Const { ty, .. } => icx.to_ty(ty),
x => bug!("unexpected non-type Node::GenericParam: {:?}", x),
},

View File

@ -14,5 +14,6 @@ minifier = "0.0.33"
rayon = { version = "0.3.0", package = "rustc-rayon" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
smallvec = "1.0"
tempfile = "3"
itertools = "0.8"

View File

@ -3,6 +3,7 @@ use std::default::Default;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
use std::lazy::SyncOnceCell as OnceCell;
use std::num::NonZeroU32;
use std::rc::Rc;
use std::sync::Arc;
@ -19,12 +20,14 @@ use rustc_hir::lang_items;
use rustc_hir::Mutability;
use rustc_index::vec::IndexVec;
use rustc_middle::middle::stability;
use rustc_middle::ty::TyCtxt;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{self, FileName};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
use smallvec::{smallvec, SmallVec};
use crate::clean::cfg::Cfg;
use crate::clean::external_path;
@ -1264,6 +1267,86 @@ impl PrimitiveType {
}
}
pub fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
}
pub fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
CELL.get_or_init(move || {
use self::PrimitiveType::*;
/// A macro to create a FxHashMap.
///
/// Example:
///
/// ```
/// let letters = map!{"a" => "b", "c" => "d"};
/// ```
///
/// Trailing commas are allowed.
/// Commas between elements are required (even if the expression is a block).
macro_rules! map {
($( $key: expr => $val: expr ),* $(,)*) => {{
let mut map = ::rustc_data_structures::fx::FxHashMap::default();
$( map.insert($key, $val); )*
map
}}
}
let single = |a: Option<DefId>| a.into_iter().collect();
let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
a.into_iter().chain(b).collect()
};
let lang_items = tcx.lang_items();
map! {
Isize => single(lang_items.isize_impl()),
I8 => single(lang_items.i8_impl()),
I16 => single(lang_items.i16_impl()),
I32 => single(lang_items.i32_impl()),
I64 => single(lang_items.i64_impl()),
I128 => single(lang_items.i128_impl()),
Usize => single(lang_items.usize_impl()),
U8 => single(lang_items.u8_impl()),
U16 => single(lang_items.u16_impl()),
U32 => single(lang_items.u32_impl()),
U64 => single(lang_items.u64_impl()),
U128 => single(lang_items.u128_impl()),
F32 => both(lang_items.f32_impl(), lang_items.f32_runtime_impl()),
F64 => both(lang_items.f64_impl(), lang_items.f64_runtime_impl()),
Char => single(lang_items.char_impl()),
Bool => single(lang_items.bool_impl()),
Str => both(lang_items.str_impl(), lang_items.str_alloc_impl()),
Slice => {
lang_items
.slice_impl()
.into_iter()
.chain(lang_items.slice_u8_impl())
.chain(lang_items.slice_alloc_impl())
.chain(lang_items.slice_u8_alloc_impl())
.collect()
},
Array => single(lang_items.array_impl()),
Tuple => smallvec![],
Unit => smallvec![],
RawPointer => {
lang_items
.const_ptr_impl()
.into_iter()
.chain(lang_items.mut_ptr_impl())
.chain(lang_items.const_slice_ptr_impl())
.chain(lang_items.mut_slice_ptr_impl())
.collect()
},
Reference => smallvec![],
Fn => smallvec![],
Never => smallvec![],
}
})
}
pub fn to_url_str(&self) -> &'static str {
self.as_str()
}

View File

@ -351,7 +351,6 @@ pub fn qpath_to_string(p: &hir::QPath<'_>) -> String {
}
pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut Vec<Item>) {
use self::PrimitiveType::*;
let tcx = cx.tcx;
for item in items {
@ -370,34 +369,7 @@ pub fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut V
None => continue,
},
};
let did = match primitive {
Isize => tcx.lang_items().isize_impl(),
I8 => tcx.lang_items().i8_impl(),
I16 => tcx.lang_items().i16_impl(),
I32 => tcx.lang_items().i32_impl(),
I64 => tcx.lang_items().i64_impl(),
I128 => tcx.lang_items().i128_impl(),
Usize => tcx.lang_items().usize_impl(),
U8 => tcx.lang_items().u8_impl(),
U16 => tcx.lang_items().u16_impl(),
U32 => tcx.lang_items().u32_impl(),
U64 => tcx.lang_items().u64_impl(),
U128 => tcx.lang_items().u128_impl(),
F32 => tcx.lang_items().f32_impl(),
F64 => tcx.lang_items().f64_impl(),
Char => tcx.lang_items().char_impl(),
Bool => tcx.lang_items().bool_impl(),
Str => tcx.lang_items().str_impl(),
Slice => tcx.lang_items().slice_impl(),
Array => tcx.lang_items().array_impl(),
Tuple => None,
Unit => None,
RawPointer => tcx.lang_items().const_ptr_impl(),
Reference => None,
Fn => None,
Never => None,
};
if let Some(did) = did {
for &did in primitive.impls(tcx) {
if !did.is_local() {
inline::build_impl(cx, did, None, ret);
}

View File

@ -12,6 +12,7 @@
#![feature(ptr_offset_from)]
#![feature(crate_visibility_modifier)]
#![feature(never_type)]
#![feature(once_cell)]
#![recursion_limit = "256"]
#[macro_use]

View File

@ -16,6 +16,7 @@ use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::Ident;
use rustc_span::symbol::Symbol;
use rustc_span::DUMMY_SP;
use smallvec::SmallVec;
use std::cell::Cell;
use std::ops::Range;
@ -270,18 +271,26 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
.ok_or(ErrorKind::ResolutionFailure)?;
if let Some((path, prim)) = is_primitive(&path, TypeNS) {
let did = primitive_impl(cx, &path).ok_or(ErrorKind::ResolutionFailure)?;
return cx
.tcx
.associated_items(did)
.filter_by_name_unhygienic(item_name)
.next()
.and_then(|item| match item.kind {
ty::AssocKind::Fn => Some("method"),
_ => None,
})
.map(|out| (prim, Some(format!("{}#{}.{}", path, out, item_name))))
.ok_or(ErrorKind::ResolutionFailure);
for &impl_ in primitive_impl(cx, &path).ok_or(ErrorKind::ResolutionFailure)? {
let link = cx
.tcx
.associated_items(impl_)
.find_by_name_and_namespace(
cx.tcx,
Ident::with_dummy_span(item_name),
ns,
impl_,
)
.and_then(|item| match item.kind {
ty::AssocKind::Fn => Some("method"),
_ => None,
})
.map(|out| (prim, Some(format!("{}#{}.{}", path, out, item_name))));
if let Some(link) = link {
return Ok(link);
}
}
return Err(ErrorKind::ResolutionFailure);
}
let (_, ty_res) = cx
@ -1238,26 +1247,6 @@ fn is_primitive(path_str: &str, ns: Namespace) -> Option<(&'static str, Res)> {
}
}
fn primitive_impl(cx: &DocContext<'_>, path_str: &str) -> Option<DefId> {
let tcx = cx.tcx;
match path_str {
"u8" => tcx.lang_items().u8_impl(),
"u16" => tcx.lang_items().u16_impl(),
"u32" => tcx.lang_items().u32_impl(),
"u64" => tcx.lang_items().u64_impl(),
"u128" => tcx.lang_items().u128_impl(),
"usize" => tcx.lang_items().usize_impl(),
"i8" => tcx.lang_items().i8_impl(),
"i16" => tcx.lang_items().i16_impl(),
"i32" => tcx.lang_items().i32_impl(),
"i64" => tcx.lang_items().i64_impl(),
"i128" => tcx.lang_items().i128_impl(),
"isize" => tcx.lang_items().isize_impl(),
"f32" => tcx.lang_items().f32_impl(),
"f64" => tcx.lang_items().f64_impl(),
"str" => tcx.lang_items().str_impl(),
"bool" => tcx.lang_items().bool_impl(),
"char" => tcx.lang_items().char_impl(),
_ => None,
}
fn primitive_impl(cx: &DocContext<'_>, path_str: &str) -> Option<&'static SmallVec<[DefId; 4]>> {
Some(PrimitiveType::from_symbol(Symbol::intern(path_str))?.impls(cx.tcx))
}

View File

@ -34,40 +34,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate {
}
// Also try to inline primitive impls from other crates.
let lang_items = cx.tcx.lang_items();
let primitive_impls = [
lang_items.isize_impl(),
lang_items.i8_impl(),
lang_items.i16_impl(),
lang_items.i32_impl(),
lang_items.i64_impl(),
lang_items.i128_impl(),
lang_items.usize_impl(),
lang_items.u8_impl(),
lang_items.u16_impl(),
lang_items.u32_impl(),
lang_items.u64_impl(),
lang_items.u128_impl(),
lang_items.f32_impl(),
lang_items.f64_impl(),
lang_items.f32_runtime_impl(),
lang_items.f64_runtime_impl(),
lang_items.bool_impl(),
lang_items.char_impl(),
lang_items.str_impl(),
lang_items.array_impl(),
lang_items.slice_impl(),
lang_items.slice_u8_impl(),
lang_items.str_alloc_impl(),
lang_items.slice_alloc_impl(),
lang_items.slice_u8_alloc_impl(),
lang_items.const_ptr_impl(),
lang_items.mut_ptr_impl(),
lang_items.const_slice_ptr_impl(),
lang_items.mut_slice_ptr_impl(),
];
for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
for &def_id in PrimitiveType::all_impls(cx.tcx).values().flatten() {
if !def_id.is_local() {
inline::build_impl(cx, def_id, None, &mut new_items);

View File

@ -14,7 +14,7 @@ trait Foo {
}
// EMIT_MIR_FOR_EACH_BIT_WIDTH
// EMIT_MIR issue_41697.{{impl}}-{{constant}}.SimplifyCfg-qualify-consts.after.mir
// EMIT_MIR issue_41697.{{impl}}-{{constant}}.SimplifyCfg-promote-consts.after.mir
impl Foo for [u8; 1+1] {
fn get(&self) -> [u8; 2] {
*self

View File

@ -1,4 +1,4 @@
// MIR for `<impl at $DIR/issue-41697.rs:18:1: 22:2>::{{constant}}#0` after SimplifyCfg-qualify-consts
// MIR for `<impl at $DIR/issue-41697.rs:18:1: 22:2>::{{constant}}#0` after SimplifyCfg-promote-consts
<impl at $DIR/issue-41697.rs:18:1: 22:2>::{{constant}}#0: usize = {
let mut _0: usize; // return place in scope 0 at $DIR/issue-41697.rs:18:19: 18:22

View File

@ -1,4 +1,4 @@
// MIR for `<impl at $DIR/issue-41697.rs:18:1: 22:2>::{{constant}}#0` after SimplifyCfg-qualify-consts
// MIR for `<impl at $DIR/issue-41697.rs:18:1: 22:2>::{{constant}}#0` after SimplifyCfg-promote-consts
<impl at $DIR/issue-41697.rs:18:1: 22:2>::{{constant}}#0: usize = {
let mut _0: usize; // return place in scope 0 at $DIR/issue-41697.rs:18:19: 18:22

View File

@ -1,4 +1,4 @@
// MIR for `main` after SimplifyCfg-qualify-consts
// MIR for `main` after SimplifyCfg-promote-consts
fn main() -> () {
let mut _0: (); // return place in scope 0 at $DIR/loop_test.rs:6:11: 6:11

View File

@ -2,7 +2,7 @@
// Tests to make sure we correctly generate falseUnwind edges in loops
// EMIT_MIR loop_test.main.SimplifyCfg-qualify-consts.after.mir
// EMIT_MIR loop_test.main.SimplifyCfg-promote-consts.after.mir
fn main() {
// Exit early at runtime. Since only care about the generated MIR
// and not the runtime behavior (which is exercised by other tests)

View File

@ -0,0 +1,32 @@
#![deny(broken_intra_doc_links)]
// ignore-tidy-linelength
// @has intra_link_primitive_non_default_impl/fn.str_methods.html
/// [`str::trim`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.trim"]' 'str::trim'
/// [`str::to_lowercase`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase"]' 'str::to_lowercase'
/// [`str::into_boxed_bytes`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.into_boxed_bytes"]' 'str::into_boxed_bytes'
/// [`str::replace`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.str.html#method.replace"]' 'str::replace'
pub fn str_methods() {}
// @has intra_link_primitive_non_default_impl/fn.f32_methods.html
/// [f32::powi]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.powi"]' 'f32::powi'
/// [f32::sqrt]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.sqrt"]' 'f32::sqrt'
/// [f32::mul_add]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f32.html#method.mul_add"]' 'f32::mul_add'
pub fn f32_methods() {}
// @has intra_link_primitive_non_default_impl/fn.f64_methods.html
/// [`f64::powi`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.powi"]' 'f64::powi'
/// [`f64::sqrt`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.sqrt"]' 'f64::sqrt'
/// [`f64::mul_add`]
// @has - '//*[@href="https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.mul_add"]' 'f64::mul_add'
pub fn f64_methods() {}

View File

@ -14,7 +14,7 @@ LL | arr: [u8; CFG.arr_size],
|
= help: it is currently only allowed to use either `CFG` or `{ CFG }` as generic constants
error: using `Config` as const generic parameters is forbidden
error: `Config` is forbidden as the type of a const generic parameter
--> $DIR/array-size-in-generic-struct-param.rs:18:21
|
LL | struct B<const CFG: Config> {

View File

@ -16,7 +16,7 @@ struct Config {
}
struct B<const CFG: Config> {
//[min]~^ ERROR using `Config` as const generic parameters is forbidden
//[min]~^ ERROR `Config` is forbidden
arr: [u8; CFG.arr_size],
//[full]~^ ERROR constant expression depends on a generic parameter
//[min]~^^ ERROR generic parameters must not be used inside of non trivial

View File

@ -28,7 +28,7 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
LL | fn bar<const N: &u8>() {}
| ^ explicit lifetime name needed here
error: using `&'static u8` as const generic parameters is forbidden
error: `&'static u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:11:19
|
LL | struct A<const N: &u8>;
@ -37,7 +37,7 @@ LL | struct A<const N: &u8>;
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `&'static u8` as const generic parameters is forbidden
error: `&'static u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:16:15
|
LL | impl<const N: &u8> A<N> {
@ -46,7 +46,7 @@ LL | impl<const N: &u8> A<N> {
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `&'static u8` as const generic parameters is forbidden
error: `&'static u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:24:15
|
LL | impl<const N: &u8> B for A<N> {}
@ -55,7 +55,7 @@ LL | impl<const N: &u8> B for A<N> {}
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `&'static u8` as const generic parameters is forbidden
error: `&'static u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:28:17
|
LL | fn bar<const N: &u8>() {}
@ -64,7 +64,7 @@ LL | fn bar<const N: &u8>() {}
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `&'static u8` as const generic parameters is forbidden
error: `&'static u8` is forbidden as the type of a const generic parameter
--> $DIR/const-param-elided-lifetime.rs:19:21
|
LL | fn foo<const M: &u8>(&self) {}

View File

@ -10,23 +10,23 @@
struct A<const N: &u8>;
//~^ ERROR `&` without an explicit lifetime name cannot be used here
//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
//[min]~^^ ERROR `&'static u8` is forbidden
trait B {}
impl<const N: &u8> A<N> {
//~^ ERROR `&` without an explicit lifetime name cannot be used here
//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
//[min]~^^ ERROR `&'static u8` is forbidden
fn foo<const M: &u8>(&self) {}
//~^ ERROR `&` without an explicit lifetime name cannot be used here
//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
//[min]~^^ ERROR `&'static u8` is forbidden
}
impl<const N: &u8> B for A<N> {}
//~^ ERROR `&` without an explicit lifetime name cannot be used here
//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
//[min]~^^ ERROR `&'static u8` is forbidden
fn bar<const N: &u8>() {}
//~^ ERROR `&` without an explicit lifetime name cannot be used here
//[min]~^^ ERROR using `&'static u8` as const generic parameters is forbidden
//[min]~^^ ERROR `&'static u8` is forbidden
fn main() {}

View File

@ -10,7 +10,7 @@ error[E0770]: the type of const parameters must not depend on other generic para
LL | pub struct SelfDependent<const N: [u8; N]>;
| ^ the type must not depend on the parameter `N`
error: using `[u8; _]` as const generic parameters is forbidden
error: `[u8; _]` is forbidden as the type of a const generic parameter
--> $DIR/const-param-type-depends-on-const-param.rs:12:47
|
LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
@ -19,7 +19,7 @@ LL | pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `[u8; _]` as const generic parameters is forbidden
error: `[u8; _]` is forbidden as the type of a const generic parameter
--> $DIR/const-param-type-depends-on-const-param.rs:16:35
|
LL | pub struct SelfDependent<const N: [u8; N]>;

View File

@ -11,10 +11,10 @@
pub struct Dependent<const N: usize, const X: [u8; N]>([(); N]);
//~^ ERROR: the type of const parameters must not depend on other generic parameters
//[min]~^^ ERROR using `[u8; _]` as const generic parameters is forbidden
//[min]~^^ ERROR `[u8; _]` is forbidden
pub struct SelfDependent<const N: [u8; N]>;
//~^ ERROR: the type of const parameters must not depend on other generic parameters
//[min]~^^ ERROR using `[u8; _]` as const generic parameters is forbidden
//[min]~^^ ERROR `[u8; _]` is forbidden
fn main() {}

View File

@ -1,4 +1,4 @@
error: using `[usize; 1]` as const generic parameters is forbidden
error: `[usize; 1]` is forbidden as the type of a const generic parameter
--> $DIR/different_byref.rs:8:23
|
LL | struct Const<const V: [usize; 1]> {}

View File

@ -6,7 +6,7 @@
#![cfg_attr(min, feature(min_const_generics))]
struct Const<const V: [usize; 1]> {}
//[min]~^ using `[usize; 1]` as const generic parameters is forbidden
//[min]~^ ERROR `[usize; 1]` is forbidden
fn main() {
let mut x = Const::<{ [3] }> {};

View File

@ -3,18 +3,12 @@ error: using function pointers as const generic parameters is forbidden
|
LL | struct Wrapper<const F: fn() -> u32>;
| ^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using function pointers as const generic parameters is forbidden
--> $DIR/fn-const-param-call.rs:14:15
|
LL | impl<const F: fn() -> u32> Wrapper<F> {
| ^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: aborting due to 2 previous errors

View File

@ -3,9 +3,6 @@ error: using function pointers as const generic parameters is forbidden
|
LL | struct Checked<const F: fn(usize) -> bool>;
| ^^^^^^^^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: aborting due to previous error

View File

@ -1,4 +1,4 @@
error: using `A` as const generic parameters is forbidden
error: `A` is forbidden as the type of a const generic parameter
--> $DIR/forbid-non-structural_match-types.rs:10:19
|
LL | struct B<const X: A>; // ok
@ -7,7 +7,7 @@ LL | struct B<const X: A>; // ok
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `C` as const generic parameters is forbidden
error: `C` is forbidden as the type of a const generic parameter
--> $DIR/forbid-non-structural_match-types.rs:15:19
|
LL | struct D<const X: C>;

View File

@ -8,11 +8,11 @@
struct A;
struct B<const X: A>; // ok
//[min]~^ ERROR using `A` as const generic parameters is forbidden
//[min]~^ ERROR `A` is forbidden
struct C;
struct D<const X: C>; //~ ERROR `C` must be annotated with `#[derive(PartialEq, Eq)]`
//[min]~^ ERROR using `C` as const generic parameters is forbidden
//[min]~^ ERROR `C` is forbidden
fn main() {}

View File

@ -1,4 +1,4 @@
error: using `&'static str` as const generic parameters is forbidden
error: `&'static str` is forbidden as the type of a const generic parameter
--> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:9:25
|
LL | trait Trait<const NAME: &'static str> {

View File

@ -7,7 +7,7 @@
trait Trait<const NAME: &'static str> {
//[min]~^ ERROR using `&'static str` as const generic parameters is forbidden
//[min]~^ ERROR `&'static str` is forbidden
type Assoc;
}

View File

@ -6,15 +6,6 @@ LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
|
= note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052>
error: using `&'static str` as const generic parameters is forbidden
--> $DIR/issue-56445.rs:9:25
|
LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
| ^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: aborting due to 2 previous errors
error: aborting due to previous error
For more information about this error, try `rustc --explain E0771`.

View File

@ -8,6 +8,5 @@ use std::marker::PhantomData;
struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
//~^ ERROR: use of non-static lifetime `'a` in const generic
//[min]~| ERROR: using `&'static str` as const
impl Bug<'_, ""> {}

View File

@ -0,0 +1,47 @@
error: `Inner` is forbidden as the type of a const generic parameter
--> $DIR/issue-74950.rs:18:23
|
LL | struct Outer<const I: Inner>;
| ^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: `Inner` is forbidden as the type of a const generic parameter
--> $DIR/issue-74950.rs:18:23
|
LL | struct Outer<const I: Inner>;
| ^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: `Inner` is forbidden as the type of a const generic parameter
--> $DIR/issue-74950.rs:18:23
|
LL | struct Outer<const I: Inner>;
| ^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: `Inner` is forbidden as the type of a const generic parameter
--> $DIR/issue-74950.rs:18:23
|
LL | struct Outer<const I: Inner>;
| ^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: `Inner` is forbidden as the type of a const generic parameter
--> $DIR/issue-74950.rs:18:23
|
LL | struct Outer<const I: Inner>;
| ^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: aborting due to 5 previous errors

View File

@ -0,0 +1,25 @@
// [full] build-pass
// revisions: full min
#![cfg_attr(full, feature(const_generics))]
#![cfg_attr(full, allow(incomplete_features))]
#![cfg_attr(min, feature(min_const_generics))]
#[derive(PartialEq, Eq)]
struct Inner;
// Note: We emit the error 5 times if we don't deduplicate:
// - struct definition
// - impl PartialEq
// - impl Eq
// - impl StructuralPartialEq
// - impl StructuralEq
#[derive(PartialEq, Eq)]
struct Outer<const I: Inner>;
//[min]~^ `Inner` is forbidden
//[min]~| `Inner` is forbidden
//[min]~| `Inner` is forbidden
//[min]~| `Inner` is forbidden
//[min]~| `Inner` is forbidden
fn main() {}

View File

@ -0,0 +1,15 @@
// check-pass
#![feature(const_generics)]
#![allow(incomplete_features)]
struct Bar<T>(T);
impl<T> Bar<T> {
const fn value() -> usize {
42
}
}
struct Foo<const N: [u8; Bar::<u32>::value()]>;
fn main() {}

View File

@ -1,18 +1,17 @@
#![feature(min_const_generics)]
struct Foo<const N: [u8; 0]>;
//~^ ERROR using `[u8; 0]` as const generic parameters is forbidden
//~^ ERROR `[u8; 0]` is forbidden
struct Bar<const N: ()>;
//~^ ERROR using `()` as const generic parameters is forbidden
//~^ ERROR `()` is forbidden
#[derive(PartialEq, Eq)]
struct No;
struct Fez<const N: No>;
//~^ ERROR using `No` as const generic parameters is forbidden
//~^ ERROR `No` is forbidden
struct Faz<const N: &'static u8>;
//~^ ERROR using `&'static u8` as const generic parameters is forbidden
//~^ ERROR `&'static u8` is forbidden
fn main() {}

View File

@ -1,4 +1,4 @@
error: using `[u8; 0]` as const generic parameters is forbidden
error: `[u8; 0]` is forbidden as the type of a const generic parameter
--> $DIR/complex-types.rs:3:21
|
LL | struct Foo<const N: [u8; 0]>;
@ -7,7 +7,7 @@ LL | struct Foo<const N: [u8; 0]>;
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `()` as const generic parameters is forbidden
error: `()` is forbidden as the type of a const generic parameter
--> $DIR/complex-types.rs:6:21
|
LL | struct Bar<const N: ()>;
@ -16,8 +16,8 @@ LL | struct Bar<const N: ()>;
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `No` as const generic parameters is forbidden
--> $DIR/complex-types.rs:12:21
error: `No` is forbidden as the type of a const generic parameter
--> $DIR/complex-types.rs:11:21
|
LL | struct Fez<const N: No>;
| ^^
@ -25,8 +25,8 @@ LL | struct Fez<const N: No>;
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `&'static u8` as const generic parameters is forbidden
--> $DIR/complex-types.rs:15:21
error: `&'static u8` is forbidden as the type of a const generic parameter
--> $DIR/complex-types.rs:14:21
|
LL | struct Faz<const N: &'static u8>;
| ^^^^^^^^^^^

View File

@ -1,159 +1,16 @@
error[E0391]: cycle detected when computing type of `Foo`
--> $DIR/nested-type.rs:7:1
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> $DIR/nested-type.rs:16:5
|
LL | struct Foo<const N: [u8; {
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires computing type of `Foo::N`...
--> $DIR/nested-type.rs:7:18
|
LL | struct Foo<const N: [u8; {
| ^
note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires const-evaluating `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires type-checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
--> $DIR/nested-type.rs:11:5
|
LL | struct Foo<const N: usize>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing the variances for items in this crate...
= note: ...which again requires computing type of `Foo`, completing the cycle
note: cycle used when collecting item types in top-level module
--> $DIR/nested-type.rs:3:1
|
LL | / #![cfg_attr(full, feature(const_generics))]
LL | | #![cfg_attr(full, allow(incomplete_features))]
LL | | #![cfg_attr(min, feature(min_const_generics))]
LL | |
... |
LL | |
LL | | fn main() {}
| |____________^
LL | Foo::<17>::value()
| ^^^^^^^^^^^^^^^^^^
error[E0391]: cycle detected when computing type of `Foo`
--> $DIR/nested-type.rs:7:1
error[E0080]: evaluation of constant value failed
--> $DIR/nested-type.rs:16:5
|
LL | struct Foo<const N: [u8; {
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires computing type of `Foo::N`...
--> $DIR/nested-type.rs:7:18
|
LL | struct Foo<const N: [u8; {
| ^
note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires const-evaluating `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires type-checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
--> $DIR/nested-type.rs:11:5
|
LL | struct Foo<const N: usize>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing the variances for items in this crate...
= note: ...which again requires computing type of `Foo`, completing the cycle
note: cycle used when collecting item types in top-level module
--> $DIR/nested-type.rs:3:1
|
LL | / #![cfg_attr(full, feature(const_generics))]
LL | | #![cfg_attr(full, allow(incomplete_features))]
LL | | #![cfg_attr(min, feature(min_const_generics))]
LL | |
... |
LL | |
LL | | fn main() {}
| |____________^
LL | Foo::<17>::value()
| ^^^^^^^^^^^^^^^^^^ calling non-const function `Foo::{{constant}}#0::Foo::<17_usize>::value`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0391`.
Some errors have detailed explanations: E0015, E0080.
For more information about an error, try `rustc --explain E0015`.

View File

@ -1,175 +1,32 @@
error: using `[u8; _]` as const generic parameters is forbidden
error: `[u8; _]` is forbidden as the type of a const generic parameter
--> $DIR/nested-type.rs:7:21
|
LL | struct Foo<const N: [u8; {
| _____________________^
LL | | struct Foo<const N: usize>;
LL | |
LL | |
LL | |
LL | | impl<const N: usize> Foo<N> {
... |
LL | | Foo::<17>::value()
LL | |
LL | | }]>;
| |__^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error[E0391]: cycle detected when computing type of `Foo`
--> $DIR/nested-type.rs:7:1
error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
--> $DIR/nested-type.rs:16:5
|
LL | struct Foo<const N: [u8; {
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires computing type of `Foo::N`...
--> $DIR/nested-type.rs:7:18
|
LL | struct Foo<const N: [u8; {
| ^
note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires const-evaluating `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires type-checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
--> $DIR/nested-type.rs:11:5
|
LL | struct Foo<const N: usize>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing the variances for items in this crate...
= note: ...which again requires computing type of `Foo`, completing the cycle
note: cycle used when collecting item types in top-level module
--> $DIR/nested-type.rs:3:1
|
LL | / #![cfg_attr(full, feature(const_generics))]
LL | | #![cfg_attr(full, allow(incomplete_features))]
LL | | #![cfg_attr(min, feature(min_const_generics))]
LL | |
... |
LL | |
LL | | fn main() {}
| |____________^
LL | Foo::<17>::value()
| ^^^^^^^^^^^^^^^^^^
error[E0391]: cycle detected when computing type of `Foo`
--> $DIR/nested-type.rs:7:1
error[E0080]: evaluation of constant value failed
--> $DIR/nested-type.rs:16:5
|
LL | struct Foo<const N: [u8; {
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires computing type of `Foo::N`...
--> $DIR/nested-type.rs:7:18
|
LL | struct Foo<const N: [u8; {
| ^
note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires const-evaluating + checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires const-evaluating `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires type-checking `Foo::{{constant}}#0`...
--> $DIR/nested-type.rs:7:26
|
LL | struct Foo<const N: [u8; {
| __________________________^
LL | |
LL | |
LL | |
... |
LL | | Foo::<17>::value()
LL | | }]>;
| |_^
note: ...which requires computing the variances of `Foo::{{constant}}#0::Foo`...
--> $DIR/nested-type.rs:11:5
|
LL | struct Foo<const N: usize>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which requires computing the variances for items in this crate...
= note: ...which again requires computing type of `Foo`, completing the cycle
note: cycle used when collecting item types in top-level module
--> $DIR/nested-type.rs:3:1
|
LL | / #![cfg_attr(full, feature(const_generics))]
LL | | #![cfg_attr(full, allow(incomplete_features))]
LL | | #![cfg_attr(min, feature(min_const_generics))]
LL | |
... |
LL | |
LL | | fn main() {}
| |____________^
LL | Foo::<17>::value()
| ^^^^^^^^^^^^^^^^^^ calling non-const function `Foo::{{constant}}#0::Foo::<17_usize>::value`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0391`.
Some errors have detailed explanations: E0015, E0080.
For more information about an error, try `rustc --explain E0015`.

View File

@ -4,10 +4,7 @@
#![cfg_attr(full, allow(incomplete_features))]
#![cfg_attr(min, feature(min_const_generics))]
struct Foo<const N: [u8; {
//~^ ERROR cycle detected
//~| ERROR cycle detected
//[min]~| ERROR using `[u8; _]` as const generic
struct Foo<const N: [u8; { //[min]~ ERROR `[u8; _]` is forbidden
struct Foo<const N: usize>;
impl<const N: usize> Foo<N> {
@ -17,6 +14,8 @@ struct Foo<const N: [u8; {
}
Foo::<17>::value()
//~^ ERROR calls in constants are limited to constant functions
//~| ERROR evaluation of constant value failed
}]>;
fn main() {}

View File

@ -3,18 +3,12 @@ error: using raw pointers as const generic parameters is forbidden
|
LL | struct Const<const P: *const u32>;
| ^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using raw pointers as const generic parameters is forbidden
--> $DIR/raw-ptr-const-param-deref.rs:12:15
|
LL | impl<const P: *const u32> Const<P> {
| ^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: aborting due to 2 previous errors

View File

@ -3,9 +3,6 @@ error: using raw pointers as const generic parameters is forbidden
|
LL | struct Const<const P: *const u32>;
| ^^^^^^^^^^
|
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: aborting due to previous error

View File

@ -1,4 +1,4 @@
error: using `&'static str` as const generic parameters is forbidden
error: `&'static str` is forbidden as the type of a const generic parameter
--> $DIR/slice-const-param-mismatch.rs:8:29
|
LL | struct ConstString<const T: &'static str>;
@ -7,7 +7,7 @@ LL | struct ConstString<const T: &'static str>;
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `&'static [u8]` as const generic parameters is forbidden
error: `&'static [u8]` is forbidden as the type of a const generic parameter
--> $DIR/slice-const-param-mismatch.rs:10:28
|
LL | struct ConstBytes<const T: &'static [u8]>;

View File

@ -1,4 +1,4 @@
error: using `&'static str` as const generic parameters is forbidden
error: `&'static str` is forbidden as the type of a const generic parameter
--> $DIR/slice-const-param.rs:8:40
|
LL | pub fn function_with_str<const STRING: &'static str>() -> &'static str {
@ -7,7 +7,7 @@ LL | pub fn function_with_str<const STRING: &'static str>() -> &'static str {
= note: the only supported types are integers, `bool` and `char`
= note: more complex types are supported with `#[feature(const_generics)]`
error: using `&'static [u8]` as const generic parameters is forbidden
error: `&'static [u8]` is forbidden as the type of a const generic parameter
--> $DIR/slice-const-param.rs:13:41
|
LL | pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {

View File

@ -6,12 +6,12 @@
#![cfg_attr(min, feature(min_const_generics))]
pub fn function_with_str<const STRING: &'static str>() -> &'static str {
//[min]~^ ERROR using `&'static str` as const
//[min]~^ ERROR `&'static str` is forbidden
STRING
}
pub fn function_with_bytes<const BYTES: &'static [u8]>() -> &'static [u8] {
//[min]~^ ERROR using `&'static [u8]` as const
//[min]~^ ERROR `&'static [u8]` is forbidden
BYTES
}