Auto merge of #75692 - JohnTitor:rollup-8gr04ah, r=JohnTitor
Rollup of 9 pull requests Successful merges: - #75038 (See also X-Link mem::{swap, take, replace}) - #75049 (docs(marker/copy): provide example for `&T` being `Copy`) - #75499 (Fix documentation error) - #75554 (Fix clashing_extern_declarations stack overflow for recursive types.) - #75646 (Move to intra doc links for keyword documentation) - #75652 (Resolve true and false as booleans) - #75658 (Don't emit "is not a logical operator" error outside of associative expressions) - #75665 (Add doc examples coverage) - #75685 (Switch to intra-doc links in /src/sys/unix/ext/*.rs) Failed merges: r? @ghost
This commit is contained in:
commit
5b04bbfcbb
32 changed files with 553 additions and 446 deletions
|
@ -291,6 +291,7 @@ pub trait StructuralEq {
|
|||
///
|
||||
/// ```
|
||||
/// # #[allow(dead_code)]
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// struct Point {
|
||||
/// x: i32,
|
||||
/// y: i32,
|
||||
|
@ -315,6 +316,20 @@ pub trait StructuralEq {
|
|||
/// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy`
|
||||
/// ```
|
||||
///
|
||||
/// Shared references (`&T`) are also `Copy`, so a type can be `Copy`, even when it holds
|
||||
/// shared references of types `T` that are *not* `Copy`. Consider the following struct,
|
||||
/// which can implement `Copy`, because it only holds a *shared reference* to our non-`Copy`
|
||||
/// type `PointList` from above:
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(dead_code)]
|
||||
/// # struct PointList;
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// struct PointListWrapper<'a> {
|
||||
/// point_list_ref: &'a PointList,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## When *can't* my type be `Copy`?
|
||||
///
|
||||
/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased
|
||||
|
|
|
@ -670,6 +670,9 @@ pub unsafe fn uninitialized<T>() -> T {
|
|||
|
||||
/// Swaps the values at two mutable locations, without deinitializing either one.
|
||||
///
|
||||
/// * If you want to swap with a default or dummy value, see [`take`].
|
||||
/// * If you want to swap with a passed value, returning the old value, see [`replace`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -683,6 +686,9 @@ pub unsafe fn uninitialized<T>() -> T {
|
|||
/// assert_eq!(42, x);
|
||||
/// assert_eq!(5, y);
|
||||
/// ```
|
||||
///
|
||||
/// [`replace`]: fn.replace.html
|
||||
/// [`take`]: fn.take.html
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn swap<T>(x: &mut T, y: &mut T) {
|
||||
|
@ -695,6 +701,9 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
|
|||
|
||||
/// Replaces `dest` with the default value of `T`, returning the previous `dest` value.
|
||||
///
|
||||
/// * If you want to replace the values of two variables, see [`swap`].
|
||||
/// * If you want to replace with a passed value instead of the default value, see [`replace`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A simple example:
|
||||
|
@ -747,6 +756,8 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
|
|||
/// ```
|
||||
///
|
||||
/// [`Clone`]: ../../std/clone/trait.Clone.html
|
||||
/// [`replace`]: fn.replace.html
|
||||
/// [`swap`]: fn.swap.html
|
||||
#[inline]
|
||||
#[stable(feature = "mem_take", since = "1.40.0")]
|
||||
pub fn take<T: Default>(dest: &mut T) -> T {
|
||||
|
@ -757,6 +768,9 @@ pub fn take<T: Default>(dest: &mut T) -> T {
|
|||
///
|
||||
/// Neither value is dropped.
|
||||
///
|
||||
/// * If you want to replace the values of two variables, see [`swap`].
|
||||
/// * If you want to replace with a default value, see [`take`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A simple example:
|
||||
|
@ -810,6 +824,8 @@ pub fn take<T: Default>(dest: &mut T) -> T {
|
|||
/// ```
|
||||
///
|
||||
/// [`Clone`]: ../../std/clone/trait.Clone.html
|
||||
/// [`swap`]: fn.swap.html
|
||||
/// [`take`]: fn.take.html
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "if you don't need the old value, you can just assign the new value directly"]
|
||||
|
|
|
@ -2031,7 +2031,7 @@ mod traits {
|
|||
/// # Panics
|
||||
///
|
||||
/// Panics if `begin` does not point to the starting byte offset of
|
||||
/// a character (as defined by `is_char_boundary`), or if `begin >= len`.
|
||||
/// a character (as defined by `is_char_boundary`), or if `begin > len`.
|
||||
#[stable(feature = "str_checked_slicing", since = "1.20.0")]
|
||||
unsafe impl SliceIndex<str> for ops::RangeFrom<usize> {
|
||||
type Output = str;
|
||||
|
|
|
@ -98,7 +98,6 @@ mod as_keyword {}
|
|||
/// [Reference on "break expression"]: ../reference/expressions/loop-expr.html#break-expressions
|
||||
/// [Reference on "break and loop values"]:
|
||||
/// ../reference/expressions/loop-expr.html#break-and-loop-values
|
||||
///
|
||||
mod break_keyword {}
|
||||
|
||||
#[doc(keyword = "const")]
|
||||
|
@ -336,7 +335,6 @@ mod else_keyword {}
|
|||
/// For more information, take a look at the [Rust Book] or the [Reference]
|
||||
///
|
||||
/// [ADT]: https://en.wikipedia.org/wiki/Algebraic_data_type
|
||||
/// [`Option`]: option/enum.Option.html
|
||||
/// [Rust Book]: ../book/ch06-01-defining-an-enum.html
|
||||
/// [Reference]: ../reference/items/enumerations.html
|
||||
mod enum_keyword {}
|
||||
|
@ -534,7 +532,6 @@ mod fn_keyword {}
|
|||
/// [`in`]: keyword.in.html
|
||||
/// [`impl`]: keyword.impl.html
|
||||
/// [higher-ranked trait bounds]: ../reference/trait-bounds.html#higher-ranked-trait-bounds
|
||||
/// [`IntoIterator`]: iter/trait.IntoIterator.html
|
||||
/// [Rust book]:
|
||||
/// ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
|
||||
/// [Reference]: ../reference/expressions/loop-expr.html#iterator-loops
|
||||
|
@ -993,7 +990,6 @@ mod mod_keyword {}
|
|||
/// For more information on the `move` keyword, see the [closure]'s section
|
||||
/// of the Rust book or the [threads] section
|
||||
///
|
||||
/// [`Fn` trait]: ../std/ops/trait.Fn.html
|
||||
/// [closure]: ../book/ch13-01-closures.html
|
||||
/// [threads]: ../book/ch16-01-threads.html#using-move-closures-with-threads
|
||||
mod move_keyword {}
|
||||
|
@ -1413,9 +1409,7 @@ mod self_upper_keyword {}
|
|||
/// [`extern`]: keyword.extern.html
|
||||
/// [`mut`]: keyword.mut.html
|
||||
/// [`unsafe`]: keyword.unsafe.html
|
||||
/// [`drop`]: mem/fn.drop.html
|
||||
/// [`Sync`]: marker/trait.Sync.html
|
||||
/// [`RefCell`]: cell/struct.RefCell.html
|
||||
/// [`RefCell`]: cell::RefCell
|
||||
/// [Reference]: ../reference/items/static-items.html
|
||||
mod static_keyword {}
|
||||
|
||||
|
@ -1522,7 +1516,7 @@ mod static_keyword {}
|
|||
/// For more information on structs, take a look at the [Rust Book][book] or the
|
||||
/// [Reference][reference].
|
||||
///
|
||||
/// [`PhantomData`]: marker/struct.PhantomData.html
|
||||
/// [`PhantomData`]: marker::PhantomData
|
||||
/// [book]: ../book/ch05-01-defining-structs.html
|
||||
/// [reference]: ../reference/items/structs.html
|
||||
mod struct_keyword {}
|
||||
|
@ -1733,8 +1727,6 @@ mod super_keyword {}
|
|||
/// [`for`]: keyword.for.html
|
||||
/// [`impl`]: keyword.impl.html
|
||||
/// [`unsafe`]: keyword.unsafe.html
|
||||
/// [`Send`]: marker/trait.Send.html
|
||||
/// [`Sync`]: marker/trait.Sync.html
|
||||
/// [Ref-Traits]: ../reference/items/traits.html
|
||||
/// [Ref-Trait-Objects]: ../reference/types/trait-object.html
|
||||
mod trait_keyword {}
|
||||
|
@ -1764,7 +1756,6 @@ mod trait_keyword {}
|
|||
/// [`while`]: keyword.while.html
|
||||
/// [`match`]: ../reference/expressions/match-expr.html#match-guards
|
||||
/// [`false`]: keyword.false.html
|
||||
/// [`bool`]: primitive.bool.html
|
||||
mod true_keyword {}
|
||||
|
||||
#[doc(keyword = "type")]
|
||||
|
@ -1986,9 +1977,6 @@ mod type_keyword {}
|
|||
/// [`static`]: keyword.static.html
|
||||
/// [`union`]: keyword.union.html
|
||||
/// [`impl`]: keyword.impl.html
|
||||
/// [Send]: marker/trait.Send.html
|
||||
/// [Sync]: marker/trait.Sync.html
|
||||
/// [`Vec::set_len`]: vec/struct.Vec.html#method.set_len
|
||||
/// [raw pointers]: ../reference/types/pointer.html
|
||||
/// [memory safety]: ../book/ch19-01-unsafe-rust.html
|
||||
/// [Rustnomicon]: ../nomicon/index.html
|
||||
|
@ -2178,7 +2166,7 @@ mod where_keyword {}
|
|||
///
|
||||
/// It is available for use in stable rust from version 1.39 onwards.
|
||||
///
|
||||
/// [`Future`]: ./future/trait.Future.html
|
||||
/// [`Future`]: future::Future
|
||||
/// [async book]: https://rust-lang.github.io/async-book/
|
||||
mod async_keyword {}
|
||||
|
||||
|
@ -2197,7 +2185,7 @@ mod async_keyword {}
|
|||
///
|
||||
/// It is available for use in stable rust from version 1.39 onwards.
|
||||
///
|
||||
/// [`Future`]: ./future/trait.Future.html
|
||||
/// [`Future`]: future::Future
|
||||
/// [async book]: https://rust-lang.github.io/async-book/
|
||||
mod await_keyword {}
|
||||
|
||||
|
|
|
@ -9,9 +9,7 @@ use crate::sys;
|
|||
use crate::sys::platform::fs::MetadataExt as UnixMetadataExt;
|
||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
|
||||
|
||||
/// Unix-specific extensions to [`File`].
|
||||
///
|
||||
/// [`File`]: ../../../../std/fs/struct.File.html
|
||||
/// Unix-specific extensions to [`fs::File`].
|
||||
#[stable(feature = "file_offset", since = "1.15.0")]
|
||||
pub trait FileExt {
|
||||
/// Reads a number of bytes starting from a given offset.
|
||||
|
@ -55,19 +53,18 @@ pub trait FileExt {
|
|||
///
|
||||
/// The current file cursor is not affected by this function.
|
||||
///
|
||||
/// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
|
||||
/// Similar to [`io::Read::read_exact`] but uses [`read_at`] instead of `read`.
|
||||
///
|
||||
/// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
|
||||
/// [`read_at`]: #tymethod.read_at
|
||||
/// [`read_at`]: FileExt::read_at
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If this function encounters an error of the kind
|
||||
/// [`ErrorKind::Interrupted`] then the error is ignored and the operation
|
||||
/// [`io::ErrorKind::Interrupted`] then the error is ignored and the operation
|
||||
/// will continue.
|
||||
///
|
||||
/// If this function encounters an "end of file" before completely filling
|
||||
/// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
|
||||
/// the buffer, it returns an error of the kind [`io::ErrorKind::UnexpectedEof`].
|
||||
/// The contents of `buf` are unspecified in this case.
|
||||
///
|
||||
/// If any other read error is encountered then this function immediately
|
||||
|
@ -77,9 +74,6 @@ pub trait FileExt {
|
|||
/// has read, but it will never read more than would be necessary to
|
||||
/// completely fill the buffer.
|
||||
///
|
||||
/// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
|
||||
/// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
|
@ -161,19 +155,18 @@ pub trait FileExt {
|
|||
/// The current file cursor is not affected by this function.
|
||||
///
|
||||
/// This method will continuously call [`write_at`] until there is no more data
|
||||
/// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
|
||||
/// to be written or an error of non-[`io::ErrorKind::Interrupted`] kind is
|
||||
/// returned. This method will not return until the entire buffer has been
|
||||
/// successfully written or such an error occurs. The first error that is
|
||||
/// not of [`ErrorKind::Interrupted`] kind generated from this method will be
|
||||
/// not of [`io::ErrorKind::Interrupted`] kind generated from this method will be
|
||||
/// returned.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return the first error of
|
||||
/// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
|
||||
/// non-[`io::ErrorKind::Interrupted`] kind that [`write_at`] returns.
|
||||
///
|
||||
/// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
|
||||
/// [`write_at`]: #tymethod.write_at
|
||||
/// [`write_at`]: FileExt::write_at
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -223,8 +216,6 @@ impl FileExt for fs::File {
|
|||
}
|
||||
|
||||
/// Unix-specific extensions to [`fs::Permissions`].
|
||||
///
|
||||
/// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
|
||||
#[stable(feature = "fs_ext", since = "1.1.0")]
|
||||
pub trait PermissionsExt {
|
||||
/// Returns the underlying raw `st_mode` bits that contain the standard
|
||||
|
@ -302,8 +293,6 @@ impl PermissionsExt for Permissions {
|
|||
}
|
||||
|
||||
/// Unix-specific extensions to [`fs::OpenOptions`].
|
||||
///
|
||||
/// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
|
||||
#[stable(feature = "fs_ext", since = "1.1.0")]
|
||||
pub trait OpenOptionsExt {
|
||||
/// Sets the mode bits that a new file will be created with.
|
||||
|
@ -372,8 +361,6 @@ impl OpenOptionsExt for OpenOptions {
|
|||
}
|
||||
|
||||
/// Unix-specific extensions to [`fs::Metadata`].
|
||||
///
|
||||
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
|
||||
#[stable(feature = "metadata_ext", since = "1.1.0")]
|
||||
pub trait MetadataExt {
|
||||
/// Returns the ID of the device containing the file.
|
||||
|
@ -535,7 +522,7 @@ pub trait MetadataExt {
|
|||
fn atime(&self) -> i64;
|
||||
/// Returns the last access time of the file, in nanoseconds since [`atime`].
|
||||
///
|
||||
/// [`atime`]: #tymethod.atime
|
||||
/// [`atime`]: MetadataExt::atime
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -571,7 +558,7 @@ pub trait MetadataExt {
|
|||
fn mtime(&self) -> i64;
|
||||
/// Returns the last modification time of the file, in nanoseconds since [`mtime`].
|
||||
///
|
||||
/// [`mtime`]: #tymethod.mtime
|
||||
/// [`mtime`]: MetadataExt::mtime
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -607,7 +594,7 @@ pub trait MetadataExt {
|
|||
fn ctime(&self) -> i64;
|
||||
/// Returns the last status change time of the file, in nanoseconds since [`ctime`].
|
||||
///
|
||||
/// [`ctime`]: #tymethod.ctime
|
||||
/// [`ctime`]: MetadataExt::ctime
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -714,12 +701,10 @@ impl MetadataExt for fs::Metadata {
|
|||
}
|
||||
}
|
||||
|
||||
/// Unix-specific extensions for [`FileType`].
|
||||
/// Unix-specific extensions for [`fs::FileType`].
|
||||
///
|
||||
/// Adds support for special Unix file types such as block/character devices,
|
||||
/// pipes, and sockets.
|
||||
///
|
||||
/// [`FileType`]: ../../../../std/fs/struct.FileType.html
|
||||
#[stable(feature = "file_type_ext", since = "1.5.0")]
|
||||
pub trait FileTypeExt {
|
||||
/// Returns `true` if this file type is a block device.
|
||||
|
@ -813,8 +798,6 @@ impl FileTypeExt for fs::FileType {
|
|||
}
|
||||
|
||||
/// Unix-specific extension methods for [`fs::DirEntry`].
|
||||
///
|
||||
/// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
|
||||
#[stable(feature = "dir_entry_ext", since = "1.1.0")]
|
||||
pub trait DirEntryExt {
|
||||
/// Returns the underlying `d_ino` field in the contained `dirent`
|
||||
|
@ -875,8 +858,6 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
|
|||
}
|
||||
|
||||
/// Unix-specific extensions to [`fs::DirBuilder`].
|
||||
///
|
||||
/// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
|
||||
#[stable(feature = "dir_builder", since = "1.6.0")]
|
||||
pub trait DirBuilderExt {
|
||||
/// Sets the mode to create new directories with. This option defaults to
|
||||
|
|
|
@ -408,10 +408,7 @@ impl UnixStream {
|
|||
/// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
|
||||
/// method.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
|
||||
/// [`read`]: ../../../../std/io/trait.Read.html#tymethod.read
|
||||
/// [`Duration`]: ../../../../std/time/struct.Duration.html
|
||||
/// [`read`]: io::Read::read
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -453,10 +450,7 @@ impl UnixStream {
|
|||
/// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
|
||||
/// passed to this method.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
|
||||
/// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write
|
||||
/// [`Duration`]: ../../../../std/time/struct.Duration.html
|
||||
/// [`read`]: io::Read::read
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -581,8 +575,6 @@ impl UnixStream {
|
|||
/// specified portions to immediately return with an appropriate value
|
||||
/// (see the documentation of [`Shutdown`]).
|
||||
///
|
||||
/// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
|
@ -852,7 +844,7 @@ impl UnixListener {
|
|||
/// is established. When established, the corresponding [`UnixStream`] and
|
||||
/// the remote peer's address will be returned.
|
||||
///
|
||||
/// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html
|
||||
/// [`UnixStream`]: crate::os::unix::net::UnixStream
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -937,8 +929,6 @@ impl UnixListener {
|
|||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`io::ErrorKind::WouldBlock`]: ../../../io/enum.ErrorKind.html#variant.WouldBlock
|
||||
#[stable(feature = "unix_socket", since = "1.10.0")]
|
||||
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||
self.0.set_nonblocking(nonblocking)
|
||||
|
@ -973,9 +963,6 @@ impl UnixListener {
|
|||
/// The iterator will never return [`None`] and will also not yield the
|
||||
/// peer's [`SocketAddr`] structure.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`SocketAddr`]: struct.SocketAddr.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
|
@ -1043,9 +1030,6 @@ impl<'a> IntoIterator for &'a UnixListener {
|
|||
///
|
||||
/// It will never return [`None`].
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`UnixListener`]: struct.UnixListener.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
|
@ -1205,9 +1189,9 @@ impl UnixDatagram {
|
|||
/// The [`send`] method may be used to send data to the specified address.
|
||||
/// [`recv`] and [`recv_from`] will only receive data from that address.
|
||||
///
|
||||
/// [`send`]: #method.send
|
||||
/// [`recv`]: #method.recv
|
||||
/// [`recv_from`]: #method.recv_from
|
||||
/// [`send`]: UnixDatagram::send
|
||||
/// [`recv`]: UnixDatagram::recv
|
||||
/// [`recv_from`]: UnixDatagram::recv_from
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1284,7 +1268,7 @@ impl UnixDatagram {
|
|||
///
|
||||
/// The [`connect`] method will connect the socket to a peer.
|
||||
///
|
||||
/// [`connect`]: #method.connect
|
||||
/// [`connect`]: UnixDatagram::connect
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1432,11 +1416,8 @@ impl UnixDatagram {
|
|||
/// block indefinitely. An [`Err`] is returned if the zero [`Duration`]
|
||||
/// is passed to this method.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`Err`]: ../../../../std/result/enum.Result.html#variant.Err
|
||||
/// [`recv`]: #method.recv
|
||||
/// [`recv_from`]: #method.recv_from
|
||||
/// [`Duration`]: ../../../../std/time/struct.Duration.html
|
||||
/// [`recv`]: UnixDatagram::recv
|
||||
/// [`recv_from`]: UnixDatagram::recv_from
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1479,10 +1460,8 @@ impl UnixDatagram {
|
|||
/// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
|
||||
/// method.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`send`]: #method.send
|
||||
/// [`send_to`]: #method.send_to
|
||||
/// [`Duration`]: ../../../../std/time/struct.Duration.html
|
||||
/// [`send`]: UnixDatagram::send
|
||||
/// [`send_to`]: UnixDatagram::send_to
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1605,8 +1584,6 @@ impl UnixDatagram {
|
|||
/// specified portions to immediately return with an appropriate value
|
||||
/// (see the documentation of [`Shutdown`]).
|
||||
///
|
||||
/// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::os::unix::net::UnixDatagram;
|
||||
/// use std::net::Shutdown;
|
||||
|
|
|
@ -10,8 +10,6 @@ use crate::sys;
|
|||
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||
|
||||
/// Unix-specific extensions to the [`process::Command`] builder.
|
||||
///
|
||||
/// [`process::Command`]: ../../../../std/process/struct.Command.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait CommandExt {
|
||||
/// Sets the child process's user ID. This translates to a
|
||||
|
@ -65,7 +63,7 @@ pub trait CommandExt {
|
|||
/// This method is stable and usable, but it should be unsafe. To fix
|
||||
/// that, it got deprecated in favor of the unsafe [`pre_exec`].
|
||||
///
|
||||
/// [`pre_exec`]: #tymethod.pre_exec
|
||||
/// [`pre_exec`]: CommandExt::pre_exec
|
||||
#[stable(feature = "process_exec", since = "1.15.0")]
|
||||
#[rustc_deprecated(since = "1.37.0", reason = "should be unsafe, use `pre_exec` instead")]
|
||||
fn before_exec<F>(&mut self, f: F) -> &mut process::Command
|
||||
|
@ -94,8 +92,6 @@ pub trait CommandExt {
|
|||
/// a new child. Like spawn, however, the default behavior for the stdio
|
||||
/// descriptors will be to inherited from the current process.
|
||||
///
|
||||
/// [`process::exit`]: ../../../process/fn.exit.html
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The process may be in a "broken state" if this function returns in
|
||||
|
@ -151,8 +147,6 @@ impl CommandExt for process::Command {
|
|||
}
|
||||
|
||||
/// Unix-specific extensions to [`process::ExitStatus`].
|
||||
///
|
||||
/// [`process::ExitStatus`]: ../../../../std/process/struct.ExitStatus.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait ExitStatusExt {
|
||||
/// Creates a new `ExitStatus` from the raw underlying `i32` return value of
|
||||
|
|
|
@ -11,9 +11,7 @@ use crate::thread::JoinHandle;
|
|||
#[allow(deprecated)]
|
||||
pub type RawPthread = pthread_t;
|
||||
|
||||
/// Unix-specific extensions to [`thread::JoinHandle`].
|
||||
///
|
||||
/// [`thread::JoinHandle`]: ../../../../std/thread/struct.JoinHandle.html
|
||||
/// Unix-specific extensions to [`JoinHandle`].
|
||||
#[stable(feature = "thread_extensions", since = "1.9.0")]
|
||||
pub trait JoinHandleExt {
|
||||
/// Extracts the raw pthread_t without taking ownership
|
||||
|
|
|
@ -29,6 +29,7 @@ use rustc_ast::visit::{FnCtxt, FnKind};
|
|||
use rustc_ast::{self as ast, *};
|
||||
use rustc_ast_pretty::pprust::{self, expr_to_string};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
|
||||
use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType};
|
||||
use rustc_feature::{GateIssue, Stability};
|
||||
|
@ -2153,44 +2154,58 @@ impl ClashingExternDeclarations {
|
|||
b: Ty<'tcx>,
|
||||
ckind: CItemKind,
|
||||
) -> bool {
|
||||
debug!("structurally_same_type(cx, a = {:?}, b = {:?})", a, b);
|
||||
let tcx = cx.tcx;
|
||||
if a == b || rustc_middle::ty::TyS::same_type(a, b) {
|
||||
// All nominally-same types are structurally same, too.
|
||||
true
|
||||
} else {
|
||||
// Do a full, depth-first comparison between the two.
|
||||
use rustc_middle::ty::TyKind::*;
|
||||
let a_kind = &a.kind;
|
||||
let b_kind = &b.kind;
|
||||
fn structurally_same_type_impl<'tcx>(
|
||||
seen_types: &mut FxHashSet<(Ty<'tcx>, Ty<'tcx>)>,
|
||||
cx: &LateContext<'tcx>,
|
||||
a: Ty<'tcx>,
|
||||
b: Ty<'tcx>,
|
||||
ckind: CItemKind,
|
||||
) -> bool {
|
||||
debug!("structurally_same_type_impl(cx, a = {:?}, b = {:?})", a, b);
|
||||
if !seen_types.insert((a, b)) {
|
||||
// We've encountered a cycle. There's no point going any further -- the types are
|
||||
// structurally the same.
|
||||
return true;
|
||||
}
|
||||
let tcx = cx.tcx;
|
||||
if a == b || rustc_middle::ty::TyS::same_type(a, b) {
|
||||
// All nominally-same types are structurally same, too.
|
||||
true
|
||||
} else {
|
||||
// Do a full, depth-first comparison between the two.
|
||||
use rustc_middle::ty::TyKind::*;
|
||||
let a_kind = &a.kind;
|
||||
let b_kind = &b.kind;
|
||||
|
||||
let compare_layouts = |a, b| -> bool {
|
||||
let a_layout = &cx.layout_of(a).unwrap().layout.abi;
|
||||
let b_layout = &cx.layout_of(b).unwrap().layout.abi;
|
||||
debug!("{:?} == {:?} = {}", a_layout, b_layout, a_layout == b_layout);
|
||||
a_layout == b_layout
|
||||
};
|
||||
let compare_layouts = |a, b| -> bool {
|
||||
let a_layout = &cx.layout_of(a).unwrap().layout.abi;
|
||||
let b_layout = &cx.layout_of(b).unwrap().layout.abi;
|
||||
debug!("{:?} == {:?} = {}", a_layout, b_layout, a_layout == b_layout);
|
||||
a_layout == b_layout
|
||||
};
|
||||
|
||||
#[allow(rustc::usage_of_ty_tykind)]
|
||||
let is_primitive_or_pointer =
|
||||
|kind: &ty::TyKind<'_>| kind.is_primitive() || matches!(kind, RawPtr(..));
|
||||
#[allow(rustc::usage_of_ty_tykind)]
|
||||
let is_primitive_or_pointer = |kind: &ty::TyKind<'_>| {
|
||||
kind.is_primitive() || matches!(kind, RawPtr(..) | Ref(..))
|
||||
};
|
||||
|
||||
match (a_kind, b_kind) {
|
||||
(Adt(_, a_substs), Adt(_, b_substs)) => {
|
||||
let a = a.subst(cx.tcx, a_substs);
|
||||
let b = b.subst(cx.tcx, b_substs);
|
||||
debug!("Comparing {:?} and {:?}", a, b);
|
||||
ensure_sufficient_stack(|| {
|
||||
match (a_kind, b_kind) {
|
||||
(Adt(a_def, a_substs), Adt(b_def, b_substs)) => {
|
||||
let a = a.subst(cx.tcx, a_substs);
|
||||
let b = b.subst(cx.tcx, b_substs);
|
||||
debug!("Comparing {:?} and {:?}", a, b);
|
||||
|
||||
if let (Adt(a_def, ..), Adt(b_def, ..)) = (&a.kind, &b.kind) {
|
||||
// Grab a flattened representation of all fields.
|
||||
let a_fields = a_def.variants.iter().flat_map(|v| v.fields.iter());
|
||||
let b_fields = b_def.variants.iter().flat_map(|v| v.fields.iter());
|
||||
compare_layouts(a, b)
|
||||
// Grab a flattened representation of all fields.
|
||||
let a_fields = a_def.variants.iter().flat_map(|v| v.fields.iter());
|
||||
let b_fields = b_def.variants.iter().flat_map(|v| v.fields.iter());
|
||||
compare_layouts(a, b)
|
||||
&& a_fields.eq_by(
|
||||
b_fields,
|
||||
|&ty::FieldDef { did: a_did, .. },
|
||||
&ty::FieldDef { did: b_did, .. }| {
|
||||
Self::structurally_same_type(
|
||||
structurally_same_type_impl(
|
||||
seen_types,
|
||||
cx,
|
||||
tcx.type_of(a_did),
|
||||
tcx.type_of(b_did),
|
||||
|
@ -2198,78 +2213,93 @@ impl ClashingExternDeclarations {
|
|||
)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
(Array(a_ty, a_const), Array(b_ty, b_const)) => {
|
||||
// For arrays, we also check the constness of the type.
|
||||
a_const.val == b_const.val
|
||||
&& structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
|
||||
}
|
||||
(Slice(a_ty), Slice(b_ty)) => {
|
||||
structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
|
||||
}
|
||||
(RawPtr(a_tymut), RawPtr(b_tymut)) => {
|
||||
a_tymut.mutbl == b_tymut.mutbl
|
||||
&& structurally_same_type_impl(
|
||||
seen_types,
|
||||
cx,
|
||||
&a_tymut.ty,
|
||||
&b_tymut.ty,
|
||||
ckind,
|
||||
)
|
||||
}
|
||||
(Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => {
|
||||
// For structural sameness, we don't need the region to be same.
|
||||
a_mut == b_mut
|
||||
&& structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
|
||||
}
|
||||
(FnDef(..), FnDef(..)) => {
|
||||
let a_poly_sig = a.fn_sig(tcx);
|
||||
let b_poly_sig = b.fn_sig(tcx);
|
||||
|
||||
// As we don't compare regions, skip_binder is fine.
|
||||
let a_sig = a_poly_sig.skip_binder();
|
||||
let b_sig = b_poly_sig.skip_binder();
|
||||
|
||||
(a_sig.abi, a_sig.unsafety, a_sig.c_variadic)
|
||||
== (b_sig.abi, b_sig.unsafety, b_sig.c_variadic)
|
||||
&& a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {
|
||||
structurally_same_type_impl(seen_types, cx, a, b, ckind)
|
||||
})
|
||||
&& structurally_same_type_impl(
|
||||
seen_types,
|
||||
cx,
|
||||
a_sig.output(),
|
||||
b_sig.output(),
|
||||
ckind,
|
||||
)
|
||||
}
|
||||
(Tuple(a_substs), Tuple(b_substs)) => {
|
||||
a_substs.types().eq_by(b_substs.types(), |a_ty, b_ty| {
|
||||
structurally_same_type_impl(seen_types, cx, a_ty, b_ty, ckind)
|
||||
})
|
||||
}
|
||||
// For these, it's not quite as easy to define structural-sameness quite so easily.
|
||||
// For the purposes of this lint, take the conservative approach and mark them as
|
||||
// not structurally same.
|
||||
(Dynamic(..), Dynamic(..))
|
||||
| (Error(..), Error(..))
|
||||
| (Closure(..), Closure(..))
|
||||
| (Generator(..), Generator(..))
|
||||
| (GeneratorWitness(..), GeneratorWitness(..))
|
||||
| (Projection(..), Projection(..))
|
||||
| (Opaque(..), Opaque(..)) => false,
|
||||
|
||||
// These definitely should have been caught above.
|
||||
(Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
|
||||
|
||||
// An Adt and a primitive or pointer type. This can be FFI-safe if non-null
|
||||
// enum layout optimisation is being applied.
|
||||
(Adt(..), other_kind) | (other_kind, Adt(..))
|
||||
if is_primitive_or_pointer(other_kind) =>
|
||||
{
|
||||
let (primitive, adt) =
|
||||
if is_primitive_or_pointer(&a.kind) { (a, b) } else { (b, a) };
|
||||
if let Some(ty) = crate::types::repr_nullable_ptr(cx, adt, ckind) {
|
||||
ty == primitive
|
||||
} else {
|
||||
compare_layouts(a, b)
|
||||
}
|
||||
}
|
||||
// Otherwise, just compare the layouts. This may fail to lint for some
|
||||
// incompatible types, but at the very least, will stop reads into
|
||||
// uninitialised memory.
|
||||
_ => compare_layouts(a, b),
|
||||
}
|
||||
}
|
||||
(Array(a_ty, a_const), Array(b_ty, b_const)) => {
|
||||
// For arrays, we also check the constness of the type.
|
||||
a_const.val == b_const.val
|
||||
&& Self::structurally_same_type(cx, a_const.ty, b_const.ty, ckind)
|
||||
&& Self::structurally_same_type(cx, a_ty, b_ty, ckind)
|
||||
}
|
||||
(Slice(a_ty), Slice(b_ty)) => Self::structurally_same_type(cx, a_ty, b_ty, ckind),
|
||||
(RawPtr(a_tymut), RawPtr(b_tymut)) => {
|
||||
a_tymut.mutbl == b_tymut.mutbl
|
||||
&& Self::structurally_same_type(cx, &a_tymut.ty, &b_tymut.ty, ckind)
|
||||
}
|
||||
(Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => {
|
||||
// For structural sameness, we don't need the region to be same.
|
||||
a_mut == b_mut && Self::structurally_same_type(cx, a_ty, b_ty, ckind)
|
||||
}
|
||||
(FnDef(..), FnDef(..)) => {
|
||||
let a_poly_sig = a.fn_sig(tcx);
|
||||
let b_poly_sig = b.fn_sig(tcx);
|
||||
|
||||
// As we don't compare regions, skip_binder is fine.
|
||||
let a_sig = a_poly_sig.skip_binder();
|
||||
let b_sig = b_poly_sig.skip_binder();
|
||||
|
||||
(a_sig.abi, a_sig.unsafety, a_sig.c_variadic)
|
||||
== (b_sig.abi, b_sig.unsafety, b_sig.c_variadic)
|
||||
&& a_sig.inputs().iter().eq_by(b_sig.inputs().iter(), |a, b| {
|
||||
Self::structurally_same_type(cx, a, b, ckind)
|
||||
})
|
||||
&& Self::structurally_same_type(cx, a_sig.output(), b_sig.output(), ckind)
|
||||
}
|
||||
(Tuple(a_substs), Tuple(b_substs)) => {
|
||||
a_substs.types().eq_by(b_substs.types(), |a_ty, b_ty| {
|
||||
Self::structurally_same_type(cx, a_ty, b_ty, ckind)
|
||||
})
|
||||
}
|
||||
// For these, it's not quite as easy to define structural-sameness quite so easily.
|
||||
// For the purposes of this lint, take the conservative approach and mark them as
|
||||
// not structurally same.
|
||||
(Dynamic(..), Dynamic(..))
|
||||
| (Error(..), Error(..))
|
||||
| (Closure(..), Closure(..))
|
||||
| (Generator(..), Generator(..))
|
||||
| (GeneratorWitness(..), GeneratorWitness(..))
|
||||
| (Projection(..), Projection(..))
|
||||
| (Opaque(..), Opaque(..)) => false,
|
||||
|
||||
// These definitely should have been caught above.
|
||||
(Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
|
||||
|
||||
// An Adt and a primitive type. This can be FFI-safe is the ADT is an enum with a
|
||||
// non-null field.
|
||||
(Adt(..), other_kind) | (other_kind, Adt(..))
|
||||
if is_primitive_or_pointer(other_kind) =>
|
||||
{
|
||||
let (primitive, adt) =
|
||||
if is_primitive_or_pointer(&a.kind) { (a, b) } else { (b, a) };
|
||||
if let Some(ty) = crate::types::repr_nullable_ptr(cx, adt, ckind) {
|
||||
ty == primitive
|
||||
} else {
|
||||
compare_layouts(a, b)
|
||||
}
|
||||
}
|
||||
// Otherwise, just compare the layouts. This may fail to lint for some
|
||||
// incompatible types, but at the very least, will stop reads into
|
||||
// uninitialised memory.
|
||||
_ => compare_layouts(a, b),
|
||||
})
|
||||
}
|
||||
}
|
||||
let mut seen_types = FxHashSet::default();
|
||||
structurally_same_type_impl(&mut seen_types, cx, a, b, ckind)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -308,7 +308,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool {
|
||||
match (self.expr_is_complete(lhs), self.check_assoc_op().map(|op| op.node)) {
|
||||
match (self.expr_is_complete(lhs), AssocOp::from_token(&self.token)) {
|
||||
// Semi-statement forms are odd:
|
||||
// See https://github.com/rust-lang/rust/issues/29071
|
||||
(true, None) => false,
|
||||
|
|
|
@ -200,10 +200,12 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option
|
|||
match *clean_type {
|
||||
clean::ResolvedPath { ref path, .. } => {
|
||||
let segments = &path.segments;
|
||||
let path_segment = segments.iter().last().unwrap_or_else(|| panic!(
|
||||
let path_segment = segments.iter().last().unwrap_or_else(|| {
|
||||
panic!(
|
||||
"get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path",
|
||||
clean_type, accept_generic
|
||||
));
|
||||
)
|
||||
});
|
||||
Some(path_segment.name.clone())
|
||||
}
|
||||
clean::Generic(ref s) if accept_generic => Some(s.clone()),
|
||||
|
|
|
@ -2,8 +2,9 @@ use crate::clean;
|
|||
use crate::config::OutputFormat;
|
||||
use crate::core::DocContext;
|
||||
use crate::fold::{self, DocFolder};
|
||||
use crate::html::markdown::{find_testable_code, ErrorCodes};
|
||||
use crate::passes::doc_test_lints::Tests;
|
||||
use crate::passes::Pass;
|
||||
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::FileName;
|
||||
use serde::Serialize;
|
||||
|
@ -30,15 +31,19 @@ fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::C
|
|||
struct ItemCount {
|
||||
total: u64,
|
||||
with_docs: u64,
|
||||
with_examples: u64,
|
||||
}
|
||||
|
||||
impl ItemCount {
|
||||
fn count_item(&mut self, has_docs: bool) {
|
||||
fn count_item(&mut self, has_docs: bool, has_doc_example: bool) {
|
||||
self.total += 1;
|
||||
|
||||
if has_docs {
|
||||
self.with_docs += 1;
|
||||
}
|
||||
if has_doc_example {
|
||||
self.with_examples += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn percentage(&self) -> Option<f64> {
|
||||
|
@ -48,13 +53,25 @@ impl ItemCount {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn examples_percentage(&self) -> Option<f64> {
|
||||
if self.total > 0 {
|
||||
Some((self.with_examples as f64 * 100.0) / self.total as f64)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Sub for ItemCount {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self {
|
||||
ItemCount { total: self.total - rhs.total, with_docs: self.with_docs - rhs.with_docs }
|
||||
ItemCount {
|
||||
total: self.total - rhs.total,
|
||||
with_docs: self.with_docs - rhs.with_docs,
|
||||
with_examples: self.with_examples - rhs.with_examples,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +79,7 @@ impl ops::AddAssign for ItemCount {
|
|||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.total += rhs.total;
|
||||
self.with_docs += rhs.with_docs;
|
||||
self.with_examples += rhs.with_examples;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,33 +121,55 @@ impl CoverageCalculator {
|
|||
let mut total = ItemCount::default();
|
||||
|
||||
fn print_table_line() {
|
||||
println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
|
||||
println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
|
||||
}
|
||||
|
||||
fn print_table_record(name: &str, count: ItemCount, percentage: f64) {
|
||||
fn print_table_record(
|
||||
name: &str,
|
||||
count: ItemCount,
|
||||
percentage: f64,
|
||||
examples_percentage: f64,
|
||||
) {
|
||||
println!(
|
||||
"| {:<35} | {:>10} | {:>10} | {:>9.1}% |",
|
||||
name, count.with_docs, count.total, percentage
|
||||
"| {:<35} | {:>10} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |",
|
||||
name,
|
||||
count.with_docs,
|
||||
count.total,
|
||||
percentage,
|
||||
count.with_examples,
|
||||
examples_percentage,
|
||||
);
|
||||
}
|
||||
|
||||
print_table_line();
|
||||
println!(
|
||||
"| {:<35} | {:>10} | {:>10} | {:>10} |",
|
||||
"File", "Documented", "Total", "Percentage"
|
||||
"| {:<35} | {:>10} | {:>10} | {:>10} | {:>10} | {:>10} |",
|
||||
"File", "Documented", "Total", "Percentage", "Examples", "Percentage",
|
||||
);
|
||||
print_table_line();
|
||||
|
||||
for (file, &count) in &self.items {
|
||||
if let Some(percentage) = count.percentage() {
|
||||
print_table_record(&limit_filename_len(file.to_string()), count, percentage);
|
||||
if let (Some(percentage), Some(examples_percentage)) =
|
||||
(count.percentage(), count.examples_percentage())
|
||||
{
|
||||
print_table_record(
|
||||
&limit_filename_len(file.to_string()),
|
||||
count,
|
||||
percentage,
|
||||
examples_percentage,
|
||||
);
|
||||
|
||||
total += count;
|
||||
}
|
||||
}
|
||||
|
||||
print_table_line();
|
||||
print_table_record("Total", total, total.percentage().unwrap_or(0.0));
|
||||
print_table_record(
|
||||
"Total",
|
||||
total,
|
||||
total.percentage().unwrap_or(0.0),
|
||||
total.examples_percentage().unwrap_or(0.0),
|
||||
);
|
||||
print_table_line();
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +177,17 @@ impl CoverageCalculator {
|
|||
impl fold::DocFolder for CoverageCalculator {
|
||||
fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
|
||||
let has_docs = !i.attrs.doc_strings.is_empty();
|
||||
let mut tests = Tests { found_tests: 0 };
|
||||
|
||||
find_testable_code(
|
||||
&i.attrs.doc_strings.iter().map(|d| d.as_str()).collect::<Vec<_>>().join("\n"),
|
||||
&mut tests,
|
||||
ErrorCodes::No,
|
||||
false,
|
||||
None,
|
||||
);
|
||||
|
||||
let has_doc_example = tests.found_tests != 0;
|
||||
|
||||
match i.inner {
|
||||
_ if !i.def_id.is_local() => {
|
||||
|
@ -187,7 +238,10 @@ impl fold::DocFolder for CoverageCalculator {
|
|||
}
|
||||
_ => {
|
||||
debug!("counting {:?} {:?} in {}", i.type_(), i.name, i.source.filename);
|
||||
self.items.entry(i.source.filename.clone()).or_default().count_item(has_docs);
|
||||
self.items
|
||||
.entry(i.source.filename.clone())
|
||||
.or_default()
|
||||
.count_item(has_docs, has_doc_example);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -222,11 +222,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
disambiguator,
|
||||
None | Some(Disambiguator::Namespace(Namespace::TypeNS))
|
||||
) {
|
||||
if let Some(prim) = is_primitive(path_str, ns) {
|
||||
if let Some((path, prim)) = is_primitive(path_str, ns) {
|
||||
if extra_fragment.is_some() {
|
||||
return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive));
|
||||
}
|
||||
return Ok((prim, Some(path_str.to_owned())));
|
||||
return Ok((prim, Some(path.to_owned())));
|
||||
}
|
||||
}
|
||||
return Ok((res, extra_fragment.clone()));
|
||||
|
@ -239,11 +239,11 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
if value != (ns == ValueNS) {
|
||||
return Err(ErrorKind::ResolutionFailure);
|
||||
}
|
||||
} else if let Some(prim) = is_primitive(path_str, ns) {
|
||||
} else if let Some((path, prim)) = is_primitive(path_str, ns) {
|
||||
if extra_fragment.is_some() {
|
||||
return Err(ErrorKind::AnchorFailure(AnchorFailure::Primitive));
|
||||
}
|
||||
return Ok((prim, Some(path_str.to_owned())));
|
||||
return Ok((prim, Some(path.to_owned())));
|
||||
} else {
|
||||
// If resolution failed, it may still be a method
|
||||
// because methods are not handled by the resolver
|
||||
|
@ -269,7 +269,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
|
|||
})
|
||||
.ok_or(ErrorKind::ResolutionFailure)?;
|
||||
|
||||
if let Some(prim) = is_primitive(&path, TypeNS) {
|
||||
if let Some((path, prim)) = is_primitive(&path, TypeNS) {
|
||||
let did = primitive_impl(cx, &path).ok_or(ErrorKind::ResolutionFailure)?;
|
||||
return cx
|
||||
.tcx
|
||||
|
@ -1220,11 +1220,22 @@ const PRIMITIVES: &[(&str, Res)] = &[
|
|||
("f64", Res::PrimTy(hir::PrimTy::Float(rustc_ast::FloatTy::F64))),
|
||||
("str", Res::PrimTy(hir::PrimTy::Str)),
|
||||
("bool", Res::PrimTy(hir::PrimTy::Bool)),
|
||||
("true", Res::PrimTy(hir::PrimTy::Bool)),
|
||||
("false", Res::PrimTy(hir::PrimTy::Bool)),
|
||||
("char", Res::PrimTy(hir::PrimTy::Char)),
|
||||
];
|
||||
|
||||
fn is_primitive(path_str: &str, ns: Namespace) -> Option<Res> {
|
||||
if ns == TypeNS { PRIMITIVES.iter().find(|x| x.0 == path_str).map(|x| x.1) } else { None }
|
||||
fn is_primitive(path_str: &str, ns: Namespace) -> Option<(&'static str, Res)> {
|
||||
if ns == TypeNS {
|
||||
PRIMITIVES
|
||||
.iter()
|
||||
.filter(|x| x.0 == path_str)
|
||||
.copied()
|
||||
.map(|x| if x.0 == "true" || x.0 == "false" { ("bool", x.1) } else { x })
|
||||
.next()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn primitive_impl(cx: &DocContext<'_>, path_str: &str) -> Option<DefId> {
|
||||
|
|
|
@ -43,6 +43,22 @@ impl<'a, 'tcx> DocFolder for PrivateItemDocTestLinter<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct Tests {
|
||||
pub(crate) found_tests: usize,
|
||||
}
|
||||
|
||||
impl Tests {
|
||||
pub(crate) fn new() -> Tests {
|
||||
Tests { found_tests: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::test::Tester for Tests {
|
||||
fn add_test(&mut self, _: String, _: LangString, _: usize) {
|
||||
self.found_tests += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
|
||||
let hir_id = match cx.as_local_hir_id(item.def_id) {
|
||||
Some(hir_id) => hir_id,
|
||||
|
@ -52,17 +68,7 @@ pub fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
|
|||
}
|
||||
};
|
||||
|
||||
struct Tests {
|
||||
found_tests: usize,
|
||||
}
|
||||
|
||||
impl crate::test::Tester for Tests {
|
||||
fn add_test(&mut self, _: String, _: LangString, _: usize) {
|
||||
self.found_tests += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let mut tests = Tests { found_tests: 0 };
|
||||
let mut tests = Tests::new();
|
||||
|
||||
find_testable_code(&dox, &mut tests, ErrorCodes::No, false, None);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...est/rustdoc-ui/coverage/basic.rs | 7 | 14 | 50.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 7 | 14 | 50.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage | Examples | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| ...est/rustdoc-ui/coverage/basic.rs | 7 | 14 | 50.0% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| Total | 7 | 14 | 50.0% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
|
|
27
src/test/rustdoc-ui/coverage/doc-examples.rs
Normal file
27
src/test/rustdoc-ui/coverage/doc-examples.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
// compile-flags:-Z unstable-options --show-coverage
|
||||
// check-pass
|
||||
|
||||
//! This test ensure that only rust code examples are counted.
|
||||
|
||||
/// Doc
|
||||
///
|
||||
/// ```
|
||||
/// let x = 2;
|
||||
/// ```
|
||||
pub struct Foo;
|
||||
|
||||
/// Doc
|
||||
///
|
||||
/// ```text
|
||||
/// yolo
|
||||
/// ```
|
||||
pub trait Bar {}
|
||||
|
||||
/// Doc
|
||||
///
|
||||
/// ```ignore (just for the sake of this test)
|
||||
/// let x = 2;
|
||||
/// ```
|
||||
pub fn foo<T: Bar, D: ::std::fmt::Debug>(a: Foo, b: u32, c: T, d: D) -> u32 {
|
||||
0
|
||||
}
|
7
src/test/rustdoc-ui/coverage/doc-examples.stdout
Normal file
7
src/test/rustdoc-ui/coverage/doc-examples.stdout
Normal file
|
@ -0,0 +1,7 @@
|
|||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage | Examples | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| ...tdoc-ui/coverage/doc-examples.rs | 4 | 4 | 100.0% | 2 | 50.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| Total | 4 | 4 | 100.0% | 2 | 50.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
|
@ -1,7 +1,7 @@
|
|||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...est/rustdoc-ui/coverage/empty.rs | 0 | 1 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 0 | 1 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage | Examples | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| ...est/rustdoc-ui/coverage/empty.rs | 0 | 1 | 0.0% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| Total | 0 | 1 | 0.0% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...est/rustdoc-ui/coverage/enums.rs | 6 | 8 | 75.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 6 | 8 | 75.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage | Examples | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| ...est/rustdoc-ui/coverage/enums.rs | 6 | 8 | 75.0% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| Total | 6 | 8 | 75.0% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...st/rustdoc-ui/coverage/exotic.rs | 1 | 1 | 100.0% |
|
||||
| <anon> | 2 | 2 | 100.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 3 | 3 | 100.0% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage | Examples | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| ...st/rustdoc-ui/coverage/exotic.rs | 1 | 1 | 100.0% | 0 | 0.0% |
|
||||
| <anon> | 2 | 2 | 100.0% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| Total | 3 | 3 | 100.0% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"$DIR/json.rs":{"total":13,"with_docs":7}}
|
||||
{"$DIR/json.rs":{"total":13,"with_docs":7,"with_examples":0}}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...t/rustdoc-ui/coverage/private.rs | 4 | 7 | 57.1% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 4 | 7 | 57.1% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage | Examples | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| ...t/rustdoc-ui/coverage/private.rs | 4 | 7 | 57.1% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| Total | 4 | 7 | 57.1% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...oc-ui/coverage/statics-consts.rs | 6 | 7 | 85.7% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 6 | 7 | 85.7% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage | Examples | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| ...oc-ui/coverage/statics-consts.rs | 6 | 7 | 85.7% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| Total | 6 | 7 | 85.7% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
+-------------------------------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| ...st/rustdoc-ui/coverage/traits.rs | 6 | 7 | 85.7% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
| Total | 6 | 7 | 85.7% |
|
||||
+-------------------------------------+------------+------------+------------+
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| File | Documented | Total | Percentage | Examples | Percentage |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| ...st/rustdoc-ui/coverage/traits.rs | 6 | 7 | 85.7% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
| Total | 6 | 7 | 85.7% | 0 | 0.0% |
|
||||
+-------------------------------------+------------+------------+------------+------------+------------+
|
||||
|
|
10
src/test/rustdoc/intra-doc-link-true-false.rs
Normal file
10
src/test/rustdoc/intra-doc-link-true-false.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
#![deny(broken_intra_doc_links)]
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// ignore-tidy-linelength
|
||||
|
||||
// @has foo/index.html
|
||||
// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'true'
|
||||
// @has - '//*[@id="main"]//a[@href="https://doc.rust-lang.org/nightly/std/primitive.bool.html"]' 'false'
|
||||
|
||||
//! A `bool` is either [`true`] or [`false`].
|
|
@ -5,10 +5,8 @@ fn test_and() {
|
|||
let b = false;
|
||||
|
||||
let _ = a and b; //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
|
||||
if a and b { //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
|
||||
|
@ -20,10 +18,8 @@ fn test_or() {
|
|||
let b = false;
|
||||
|
||||
let _ = a or b; //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
|
||||
if a or b { //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +28,6 @@ fn test_and_par() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
if (a and b) { //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +36,6 @@ fn test_or_par() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
if (a or b) { //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +44,6 @@ fn test_while_and() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
while a and b { //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +52,6 @@ fn test_while_or() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
while a or b { //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,23 +7,7 @@ LL | let _ = a and b;
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:7:15
|
||||
|
|
||||
LL | let _ = a and b;
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:10:10
|
||||
|
|
||||
LL | if a and b {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:10:10
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:9:10
|
||||
|
|
||||
LL | if a and b {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
@ -31,7 +15,7 @@ LL | if a and b {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:22:15
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:20:15
|
||||
|
|
||||
LL | let _ = a or b;
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
@ -39,23 +23,7 @@ LL | let _ = a or b;
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:22:15
|
||||
|
|
||||
LL | let _ = a or b;
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:25:10
|
||||
|
|
||||
LL | if a or b {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:25:10
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:22:10
|
||||
|
|
||||
LL | if a or b {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
@ -63,15 +31,7 @@ LL | if a or b {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:34:11
|
||||
|
|
||||
LL | if (a and b) {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:34:11
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:30:11
|
||||
|
|
||||
LL | if (a and b) {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
@ -79,15 +39,7 @@ LL | if (a and b) {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:43:11
|
||||
|
|
||||
LL | if (a or b) {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:43:11
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:38:11
|
||||
|
|
||||
LL | if (a or b) {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
@ -95,15 +47,7 @@ LL | if (a or b) {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:52:13
|
||||
|
|
||||
LL | while a and b {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:52:13
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:46:13
|
||||
|
|
||||
LL | while a and b {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
@ -111,15 +55,7 @@ LL | while a and b {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:61:13
|
||||
|
|
||||
LL | while a or b {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:61:13
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:54:13
|
||||
|
|
||||
LL | while a or b {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
@ -127,13 +63,13 @@ LL | while a or b {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:15:33
|
||||
--> $DIR/issue-54109-and_instead_of_ampersands.rs:13:33
|
||||
|
|
||||
LL | let _recovery_witness: () = 0;
|
||||
| -- ^ expected `()`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -11,10 +11,8 @@ fn test_and() {
|
|||
let b = false;
|
||||
|
||||
let _ = a && b; //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
|
||||
if a && b { //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +22,8 @@ fn test_or() {
|
|||
let b = false;
|
||||
|
||||
let _ = a || b; //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
|
||||
if a || b { //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +32,6 @@ fn test_and_par() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
if (a && b) { //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +40,6 @@ fn test_or_par() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
if (a || b) { //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +48,6 @@ fn test_while_and() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
while a && b { //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +56,6 @@ fn test_while_or() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
while a || b { //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,8 @@ fn test_and() {
|
|||
let b = false;
|
||||
|
||||
let _ = a and b; //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
|
||||
if a and b { //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +22,8 @@ fn test_or() {
|
|||
let b = false;
|
||||
|
||||
let _ = a or b; //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
|
||||
if a or b { //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +32,6 @@ fn test_and_par() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
if (a and b) { //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +40,6 @@ fn test_or_par() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
if (a or b) { //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +48,6 @@ fn test_while_and() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
while a and b { //~ ERROR `and` is not a logical operator
|
||||
//~| ERROR `and` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +56,6 @@ fn test_while_or() {
|
|||
let a = true;
|
||||
let b = false;
|
||||
while a or b { //~ ERROR `or` is not a logical operator
|
||||
//~| ERROR `or` is not a logical operator
|
||||
println!("both");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,23 +7,7 @@ LL | let _ = a and b;
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:13:15
|
||||
|
|
||||
LL | let _ = a and b;
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:16:10
|
||||
|
|
||||
LL | if a and b {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:16:10
|
||||
--> $DIR/issue-54109-without-witness.rs:15:10
|
||||
|
|
||||
LL | if a and b {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
@ -31,7 +15,7 @@ LL | if a and b {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:26:15
|
||||
--> $DIR/issue-54109-without-witness.rs:24:15
|
||||
|
|
||||
LL | let _ = a or b;
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
@ -39,23 +23,7 @@ LL | let _ = a or b;
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:26:15
|
||||
|
|
||||
LL | let _ = a or b;
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:29:10
|
||||
|
|
||||
LL | if a or b {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:29:10
|
||||
--> $DIR/issue-54109-without-witness.rs:26:10
|
||||
|
|
||||
LL | if a or b {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
@ -63,15 +31,7 @@ LL | if a or b {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:38:11
|
||||
|
|
||||
LL | if (a and b) {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:38:11
|
||||
--> $DIR/issue-54109-without-witness.rs:34:11
|
||||
|
|
||||
LL | if (a and b) {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
@ -79,15 +39,7 @@ LL | if (a and b) {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:47:11
|
||||
|
|
||||
LL | if (a or b) {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:47:11
|
||||
--> $DIR/issue-54109-without-witness.rs:42:11
|
||||
|
|
||||
LL | if (a or b) {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
@ -95,15 +47,7 @@ LL | if (a or b) {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:56:13
|
||||
|
|
||||
LL | while a and b {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `and` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:56:13
|
||||
--> $DIR/issue-54109-without-witness.rs:50:13
|
||||
|
|
||||
LL | while a and b {
|
||||
| ^^^ help: use `&&` to perform logical conjunction
|
||||
|
@ -111,20 +55,12 @@ LL | while a and b {
|
|||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:65:13
|
||||
--> $DIR/issue-54109-without-witness.rs:58:13
|
||||
|
|
||||
LL | while a or b {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: `or` is not a logical operator
|
||||
--> $DIR/issue-54109-without-witness.rs:65:13
|
||||
|
|
||||
LL | while a or b {
|
||||
| ^^ help: use `||` to perform logical disjunction
|
||||
|
|
||||
= note: unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
|
||||
|
||||
error: aborting due to 16 previous errors
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
|
24
src/test/ui/issues/issue-75599.rs
Normal file
24
src/test/ui/issues/issue-75599.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
// check-pass
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
const or: usize = 1;
|
||||
const and: usize = 2;
|
||||
|
||||
mod or {
|
||||
pub const X: usize = 3;
|
||||
}
|
||||
|
||||
mod and {
|
||||
pub const X: usize = 4;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match 0 {
|
||||
0 => {}
|
||||
or => {}
|
||||
and => {}
|
||||
or::X => {}
|
||||
and::X => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
119
src/test/ui/lint/clashing-extern-fn-recursion.rs
Normal file
119
src/test/ui/lint/clashing-extern-fn-recursion.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
// check-pass
|
||||
//
|
||||
// This tests checks that clashing_extern_declarations handles types that are recursive through a
|
||||
// pointer or ref argument. See #75512.
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
mod raw_ptr_recursion {
|
||||
mod a {
|
||||
#[repr(C)]
|
||||
struct Pointy {
|
||||
pointy: *const Pointy,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn run_pointy(pointy: Pointy);
|
||||
}
|
||||
}
|
||||
mod b {
|
||||
#[repr(C)]
|
||||
struct Pointy {
|
||||
pointy: *const Pointy,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn run_pointy(pointy: Pointy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod raw_ptr_recursion_once_removed {
|
||||
mod a {
|
||||
#[repr(C)]
|
||||
struct Pointy1 {
|
||||
pointy_two: *const Pointy2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct Pointy2 {
|
||||
pointy_one: *const Pointy1,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn run_pointy2(pointy: Pointy2);
|
||||
}
|
||||
}
|
||||
|
||||
mod b {
|
||||
#[repr(C)]
|
||||
struct Pointy1 {
|
||||
pointy_two: *const Pointy2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct Pointy2 {
|
||||
pointy_one: *const Pointy1,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn run_pointy2(pointy: Pointy2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod ref_recursion {
|
||||
mod a {
|
||||
#[repr(C)]
|
||||
struct Reffy<'a> {
|
||||
reffy: &'a Reffy<'a>,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn reffy_recursion(reffy: Reffy);
|
||||
}
|
||||
}
|
||||
mod b {
|
||||
#[repr(C)]
|
||||
struct Reffy<'a> {
|
||||
reffy: &'a Reffy<'a>,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn reffy_recursion(reffy: Reffy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod ref_recursion_once_removed {
|
||||
mod a {
|
||||
#[repr(C)]
|
||||
struct Reffy1<'a> {
|
||||
reffy: &'a Reffy2<'a>,
|
||||
}
|
||||
|
||||
struct Reffy2<'a> {
|
||||
reffy: &'a Reffy1<'a>,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[allow(improper_ctypes)]
|
||||
fn reffy_once_removed(reffy: Reffy1);
|
||||
}
|
||||
}
|
||||
mod b {
|
||||
#[repr(C)]
|
||||
struct Reffy1<'a> {
|
||||
reffy: &'a Reffy2<'a>,
|
||||
}
|
||||
|
||||
struct Reffy2<'a> {
|
||||
reffy: &'a Reffy1<'a>,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[allow(improper_ctypes)]
|
||||
fn reffy_once_removed(reffy: Reffy1);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue