diff --git a/library/core/src/os/darwin/objc.rs b/library/core/src/os/darwin/objc.rs index df3aab867e83d..2350bad853452 100644 --- a/library/core/src/os/darwin/objc.rs +++ b/library/core/src/os/darwin/objc.rs @@ -67,7 +67,8 @@ pub type SEL = *mut objc_selector; /// /// # Example /// -/// ```no_run +#[cfg_attr(target_os = "macos", doc = "```no_run")] +#[cfg_attr(not(target_os = "macos"), doc = "```ignore (needs windows)")] /// #![feature(darwin_objc)] /// use core::os::darwin::objc; /// @@ -93,7 +94,8 @@ pub macro class($classname:expr) {{ /// /// # Examples /// -/// ```no_run +#[cfg_attr(target_os = "macos", doc = "```no_run")] +#[cfg_attr(not(target_os = "macos"), doc = "```ignore (needs windows)")] /// #![feature(darwin_objc)] /// use core::os::darwin::objc; /// diff --git a/library/std/src/os/wasi/mod.rs b/library/std/src/os/wasi/mod.rs index 2ee6aa4660094..1db9ec906726f 100644 --- a/library/std/src/os/wasi/mod.rs +++ b/library/std/src/os/wasi/mod.rs @@ -11,7 +11,8 @@ //! //! # Examples //! -//! ```no_run +#![cfg_attr(target_os = "wasi", doc = "```no_run")] +#![cfg_attr(not(target_os = "wasi"), doc = "```ignore (needs wasi)")] //! use std::fs::File; //! use std::os::wasi::prelude::*; //! diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs index ed933975bd5a5..3cda3e25fb544 100644 --- a/library/std/src/os/windows/ffi.rs +++ b/library/std/src/os/windows/ffi.rs @@ -72,7 +72,8 @@ pub impl(self) trait OsStringExt { /// /// # Examples /// - /// ``` + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::ffi::OsString; /// use std::os::windows::prelude::*; /// @@ -104,7 +105,8 @@ pub impl(self) trait OsStrExt { /// /// # Examples /// - /// ``` + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::ffi::OsString; /// use std::os::windows::prelude::*; /// diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index dfa9236a7e428..7b4f5e7a40055 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -31,7 +31,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs::File; /// use std::os::windows::prelude::*; @@ -59,7 +60,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(core_io_borrowed_buf)] /// #![feature(read_buf_at)] /// @@ -104,7 +106,8 @@ pub trait FileExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::fs::File; /// use std::os::windows::prelude::*; /// @@ -151,7 +154,8 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::fs::OpenOptions; /// use std::os::windows::prelude::*; /// @@ -176,7 +180,8 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::fs::OpenOptions; /// use std::os::windows::prelude::*; /// @@ -202,7 +207,8 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// # #![allow(unexpected_cfgs)] /// # #[cfg(for_demonstration_only)] /// extern crate winapi; @@ -240,7 +246,8 @@ pub trait OpenOptionsExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// # #![allow(unexpected_cfgs)] /// # #[cfg(for_demonstration_only)] /// extern crate winapi; @@ -282,7 +289,8 @@ pub trait OpenOptionsExt { /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// # #![allow(unexpected_cfgs)] /// # #[cfg(for_demonstration_only)] /// extern crate winapi; @@ -377,7 +385,8 @@ impl OpenOptionsExt2 for OpenOptions { /// /// # Example /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_permissions_ext)] /// use std::fs::Permissions; /// use std::os::windows::fs::PermissionsExt; @@ -440,7 +449,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs; /// use std::os::windows::prelude::*; @@ -470,7 +480,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs; /// use std::os::windows::prelude::*; @@ -505,7 +516,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs; /// use std::os::windows::prelude::*; @@ -538,7 +550,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs; /// use std::os::windows::prelude::*; @@ -561,7 +574,8 @@ pub trait MetadataExt { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::io; /// use std::fs; /// use std::os::windows::prelude::*; @@ -700,7 +714,8 @@ impl FileTimesExt for fs::FileTimes { /// /// # Examples /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::os::windows::fs; /// /// fn main() -> std::io::Result<()> { @@ -739,7 +754,8 @@ pub fn symlink_file, Q: AsRef>(original: P, link: Q) -> io: /// /// # Examples /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::os::windows::fs; /// /// fn main() -> std::io::Result<()> { diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index e58f94253bdf7..29697bbb5f8fc 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -424,7 +424,8 @@ pub trait AsHandle { /// /// # Example /// - /// ```rust,no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// use std::fs::File; /// # use std::io; /// use std::os::windows::io::{AsHandle, BorrowedHandle}; diff --git a/library/std/src/os/windows/mod.rs b/library/std/src/os/windows/mod.rs index 53c33d17a9f65..a7e032dbf4d4d 100644 --- a/library/std/src/os/windows/mod.rs +++ b/library/std/src/os/windows/mod.rs @@ -8,7 +8,8 @@ //! //! # Examples //! -//! ```no_run +#![cfg_attr(windows, doc = "```no_run")] +#![cfg_attr(not(windows), doc = "```ignore (needs windows)")] //! use std::fs::File; //! use std::os::windows::prelude::*; //! diff --git a/library/std/src/os/windows/net/addr.rs b/library/std/src/os/windows/net/addr.rs index ef2263edcf617..c330432039a8f 100644 --- a/library/std/src/os/windows/net/addr.rs +++ b/library/std/src/os/windows/net/addr.rs @@ -79,7 +79,8 @@ impl SocketAddr { /// /// With a pathname: /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// use std::path::Path; @@ -104,7 +105,8 @@ impl SocketAddr { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::SocketAddr; /// use std::path::Path; @@ -118,7 +120,8 @@ impl SocketAddr { /// /// Creating a `SocketAddr` with a NULL byte results in an error. /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::SocketAddr; /// @@ -151,7 +154,8 @@ impl SocketAddr { /// /// A named address: /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// diff --git a/library/std/src/os/windows/net/listener.rs b/library/std/src/os/windows/net/listener.rs index 345cfe8d22ba9..19f5254e08bf9 100644 --- a/library/std/src/os/windows/net/listener.rs +++ b/library/std/src/os/windows/net/listener.rs @@ -16,7 +16,8 @@ use crate::{fmt, io}; /// /// # Examples /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::thread; /// use std::os::windows::net::{UnixStream, UnixListener}; @@ -61,7 +62,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -84,7 +86,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::{UnixListener}; /// @@ -122,7 +125,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -148,7 +152,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -170,7 +175,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -194,7 +200,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -212,7 +219,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixListener; /// @@ -236,7 +244,8 @@ impl UnixListener { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::thread; /// use std::os::windows::net::{UnixStream, UnixListener}; @@ -272,7 +281,8 @@ impl UnixListener { /// /// # Examples /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::thread; /// use std::os::windows::net::{UnixStream, UnixListener}; diff --git a/library/std/src/os/windows/net/stream.rs b/library/std/src/os/windows/net/stream.rs index f2d0f7c09e9f1..c0f32e75411e9 100644 --- a/library/std/src/os/windows/net/stream.rs +++ b/library/std/src/os/windows/net/stream.rs @@ -21,7 +21,8 @@ use crate::{fmt, io}; /// /// # Examples /// -/// ```no_run +#[cfg_attr(windows, doc = "```no_run")] +#[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::io::prelude::*; @@ -54,7 +55,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -77,7 +79,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::{UnixListener, UnixStream}; /// @@ -112,7 +115,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -130,7 +134,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -148,7 +153,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::time::Duration; @@ -168,7 +174,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -192,7 +199,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::time::Duration; @@ -207,7 +215,8 @@ impl UnixStream { /// An [`Err`] is returned if the zero [`Duration`] is passed to this /// method: /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::io; /// use std::os::windows::net::UnixStream; @@ -235,7 +244,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::time::Duration; @@ -251,7 +261,8 @@ impl UnixStream { /// An [`Err`] is returned if the zero [`Duration`] is passed to this /// method: /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::io; /// use std::os::windows::net::UnixStream; @@ -277,7 +288,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::net::Shutdown; @@ -296,7 +308,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -321,7 +334,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// @@ -339,7 +353,8 @@ impl UnixStream { /// /// # Examples /// - /// ```no_run + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_unix_domain_sockets)] /// use std::os::windows::net::UnixStream; /// use std::time::Duration; diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 3332714ae4bb7..41dcb70c59c9f 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -273,7 +273,8 @@ pub impl(self) trait CommandExt { /// /// # Example /// - /// ``` + #[cfg_attr(windows, doc = "```")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_process_extensions_async_pipes)] /// use std::os::windows::process::CommandExt; /// use std::process::{Command, Stdio}; @@ -304,7 +305,8 @@ pub impl(self) trait CommandExt { /// /// # Example /// - /// ``` + #[cfg_attr(windows, doc = "```")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] /// #![feature(windows_process_extensions_raw_attribute)] /// use std::os::windows::io::AsRawHandle; /// use std::os::windows::process::{CommandExt, ProcThreadAttributeList}; @@ -563,8 +565,9 @@ impl<'a> ProcThreadAttributeListBuilder<'a> { /// /// # Example /// - #[cfg_attr(target_vendor = "win7", doc = "```no_run")] - #[cfg_attr(not(target_vendor = "win7"), doc = "```")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] + #[cfg_attr(all(windows, target_vendor = "win7"), doc = "```no_run")] + #[cfg_attr(all(windows, not(target_vendor = "win7")), doc = "```")] /// #![feature(windows_process_extensions_raw_attribute)] /// use std::ffi::c_void; /// use std::os::windows::process::{CommandExt, ProcThreadAttributeList}; diff --git a/library/stdarch/crates/core_arch/src/amdgpu/mod.rs b/library/stdarch/crates/core_arch/src/amdgpu/mod.rs index 374f582696947..91dfbd1a16c0f 100644 --- a/library/stdarch/crates/core_arch/src/amdgpu/mod.rs +++ b/library/stdarch/crates/core_arch/src/amdgpu/mod.rs @@ -351,13 +351,13 @@ pub unsafe fn sched_barrier() { /// Combining multiple `sched_group_barrier` intrinsics enables an ordering of specific instruction types during instruction scheduling. /// For example, the following enforces a sequence of 1 VMEM read, followed by 1 VALU instruction, followed by 5 MFMA instructions. /// -/// ```rust +/// ```ignore (only available on AMD) /// // 1 VMEM read -/// sched_group_barrier::<32, 1, 0>() +/// sched_group_barrier::<32, 1, 0>(); /// // 1 VALU -/// sched_group_barrier::<2, 1, 0>() +/// sched_group_barrier::<2, 1, 0>(); /// // 5 MFMA -/// sched_group_barrier::<8, 5, 0>() +/// sched_group_barrier::<8, 5, 0>(); /// ``` /// #[doc = include_str!("intrinsic_is_convergent.md")] diff --git a/library/stdarch/crates/core_arch/src/nvptx/mod.rs b/library/stdarch/crates/core_arch/src/nvptx/mod.rs index d22f3a25bf70e..53d53d1e1ef60 100644 --- a/library/stdarch/crates/core_arch/src/nvptx/mod.rs +++ b/library/stdarch/crates/core_arch/src/nvptx/mod.rs @@ -157,10 +157,13 @@ unsafe extern "C" { /// * `format`: A pointer to the format specifier input (uses common `printf` format). /// * `valist`: A pointer to the valist input. /// - /// ``` + /// ```ignore (available only for nvptx) + /// # use std::mem::transmute; /// #[repr(C)] /// struct PrintArgs(f32, f32, f32, i32); /// + /// let a = 0.1f32; + /// let b = 0.2f32; /// vprintf( /// "int(%f + %f) = int(%f) = %d\n".as_ptr(), /// transmute(&PrintArgs(a, b, a + b, (a + b) as i32)), diff --git a/library/stdarch/crates/core_arch/src/x86/mod.rs b/library/stdarch/crates/core_arch/src/x86/mod.rs index fbf1002eab8ba..589efbcf872d5 100644 --- a/library/stdarch/crates/core_arch/src/x86/mod.rs +++ b/library/stdarch/crates/core_arch/src/x86/mod.rs @@ -39,7 +39,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] @@ -82,7 +86,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] @@ -125,7 +133,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] @@ -172,7 +184,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] @@ -215,7 +231,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] @@ -258,7 +278,11 @@ types! { /// /// # Examples /// - /// ``` + #[cfg_attr(any(target_arch = "x86", target_arch = "x86_64"), doc = "```")] + #[cfg_attr( + not(any(target_arch = "x86", target_arch = "x86_64")), + doc = "```ignore (only works on x86 targets)", + )] /// #[cfg(target_arch = "x86")] /// use std::arch::x86::*; /// #[cfg(target_arch = "x86_64")] diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 74a04b4451040..04dd0eaf22899 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -30,7 +30,7 @@ mod tests; // Because `CfgEntry` includes `Span`, we must NEVER use `==`/`!=` operators on `Cfg` and instead // use `is_equivalent_to`. #[cfg_attr(test, derive(PartialEq))] -pub(crate) struct Cfg(CfgEntry); +pub(crate) struct Cfg(pub(crate) CfgEntry); // Similar to `hir::DocCfgHideShow` but allows to handle both `show` and `hide` as with the `except` // field in `Any` variant. @@ -744,7 +744,7 @@ pub(crate) struct CfgInfo { hidden_cfg: FxHashMap, /// Current computed `cfg`. Each time we enter a new item, this field is updated as well while /// taking into account the `hidden_cfg` information. - current_cfg: Cfg, + pub(crate) current_cfg: Cfg, /// Whether the `doc(auto_cfg())` feature is enabled or not at this point. auto_cfg_active: bool, /// If the parent item used `doc(cfg(...))`, then we don't want to overwrite `current_cfg`, diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index d89fb2ae1767b..ebc32e140df4a 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -6,17 +6,18 @@ use std::sync::Arc; use proc_macro2::{TokenStream, TokenTree}; use rustc_attr_parsing::eval_config_entry; -use rustc_hir::attrs::AttributeKind; +use rustc_hir::attrs::{AttributeKind, CfgEntry}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; -use rustc_hir::{self as hir, Attribute, CRATE_HIR_ID, intravisit}; +use rustc_hir::{self as hir, CRATE_HIR_ID, intravisit}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_resolve::rustdoc::span_of_fragments; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span}; +use rustc_span::{BytePos, DUMMY_SP, FileName, Pos, Span, sym}; use super::{DocTestVisitor, ScrapedDocTest}; -use crate::clean::{Attributes, CfgInfo, extract_cfg_from_attrs}; +use crate::clean::cfg::Cfg; +use crate::clean::{Attributes, CfgInfo}; use crate::html::markdown::{self, CodeLineMapping, ErrorCodes, LangString, MdRelLine}; struct RustCollector { @@ -118,58 +119,66 @@ impl HirCollector<'_> { sp: Span, nested: F, ) { - let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id)); - if let Some(ref cfg) = - extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &mut CfgInfo::default()) - && !eval_config_entry(&self.tcx.sess, cfg.inner()).as_bool() - { - return; - } + let hir_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id)); + + let mut cfg_info = CfgInfo::default(); + let mut found_features = 0; let source_map = self.tcx.sess.source_map(); // Try collecting `#[doc(test(attr(...)))]` let old_global_crate_attrs_len = self.collector.global_crate_attrs.len(); - for attr in ast_attrs { - let Attribute::Parsed(AttributeKind::Doc(d)) = attr else { continue }; - for attr_span in &d.test_attrs { - // FIXME: This is ugly, remove when `test_attrs` has been ported to new attribute API. - if let Ok(snippet) = source_map.span_to_snippet(*attr_span) - && let Ok(stream) = TokenStream::from_str(&snippet) - { - let mut iter = stream.into_iter().peekable(); - while let Some(token) = iter.next() { - if let TokenTree::Ident(i) = token { - let i = i.to_string(); - let peek = iter.peek(); - // From this ident, we can have things like: - // - // * Group: `allow(...)` - // * Name/value: `crate_name = "..."` - // * Tokens: `html_no_url` - // - // So we peek next element to know what case we are in. - match peek { - Some(TokenTree::Group(g)) => { - let g = g.to_string(); - iter.next(); - // Add the additional attributes to the global_crate_attrs vector - self.collector.global_crate_attrs.push(format!("{i}{g}")); - } - // If next item is `=`, it means it's a name value so we will need - // to get the value as well. - Some(TokenTree::Punct(p)) if p.as_char() == '=' => { - let p = p.to_string(); - iter.next(); - if let Some(last) = iter.next() { + for attr in hir_attrs.iter() { + let hir::Attribute::Parsed(attr) = attr else { continue }; + if let AttributeKind::TargetFeature { features, .. } = attr { + for (feature, _) in features { + found_features += 1; + cfg_info.current_cfg &= Cfg(CfgEntry::NameValue { + name: sym::target_feature, + value: Some(*feature), + span: DUMMY_SP, + }); + } + } else if let AttributeKind::Doc(d) = attr { + for attr_span in &d.test_attrs { + // FIXME: This is ugly, remove when `test_attrs` has been ported to new attribute API. + if let Ok(snippet) = source_map.span_to_snippet(*attr_span) + && let Ok(stream) = TokenStream::from_str(&snippet) + { + let mut iter = stream.into_iter().peekable(); + while let Some(token) = iter.next() { + if let TokenTree::Ident(i) = token { + let i = i.to_string(); + let peek = iter.peek(); + // From this ident, we can have things like: + // + // * Group: `allow(...)` + // * Name/value: `crate_name = "..."` + // * Tokens: `html_no_url` + // + // So we peek next element to know what case we are in. + match peek { + Some(TokenTree::Group(g)) => { + let g = g.to_string(); + iter.next(); // Add the additional attributes to the global_crate_attrs vector - self.collector - .global_crate_attrs - .push(format!("{i}{p}{last}")); + self.collector.global_crate_attrs.push(format!("{i}{g}")); + } + // If next item is `=`, it means it's a name value so we will need + // to get the value as well. + Some(TokenTree::Punct(p)) if p.as_char() == '=' => { + let p = p.to_string(); + iter.next(); + if let Some(last) = iter.next() { + // Add the additional attributes to the global_crate_attrs vector + self.collector + .global_crate_attrs + .push(format!("{i}{p}{last}")); + } + } + _ => { + // Add the additional attributes to the global_crate_attrs vector + self.collector.global_crate_attrs.push(i.to_string()); } - } - _ => { - // Add the additional attributes to the global_crate_attrs vector - self.collector.global_crate_attrs.push(i.to_string()); } } } @@ -178,6 +187,14 @@ impl HirCollector<'_> { } } + // We only look at the `target_feature` attributes as the `cfg` attributes have already been + // applied at this point, so no need to take them into account again. + if found_features != 0 + && !eval_config_entry(&self.tcx.sess, &cfg_info.current_cfg.inner()).as_bool() + { + return; + } + let mut has_name = false; if let Some(name) = name { self.collector.cur_path.push(name); @@ -186,7 +203,7 @@ impl HirCollector<'_> { // The collapse-docs pass won't combine sugared/raw doc attributes, or included files with // anything else, this will combine them for us. - let attrs = Attributes::from_hir(ast_attrs); + let attrs = Attributes::from_hir(hir_attrs); if let Some(doc) = attrs.opt_doc_value() { let span = span_of_fragments(&attrs.doc_strings).unwrap_or(sp); self.collector.position = if span.edition().at_least_rust_2024() { @@ -194,7 +211,7 @@ impl HirCollector<'_> { } else { // this span affects filesystem path resolution, // so we need to keep it the same as it was previously - ast_attrs + hir_attrs .iter() .find(|attr| attr.doc_str().is_some()) .map(|attr| { diff --git a/tests/run-make/rustdoc-filter-doc_cfg-doctest/file.rs b/tests/run-make/rustdoc-filter-doc_cfg-doctest/file.rs new file mode 100644 index 0000000000000..51d17849fd718 --- /dev/null +++ b/tests/run-make/rustdoc-filter-doc_cfg-doctest/file.rs @@ -0,0 +1,3 @@ +//! ``` +//! let x = 12; +//! ``` diff --git a/tests/run-make/rustdoc-filter-doc_cfg-doctest/foo.rs b/tests/run-make/rustdoc-filter-doc_cfg-doctest/foo.rs new file mode 100644 index 0000000000000..76f9f463f4f4d --- /dev/null +++ b/tests/run-make/rustdoc-filter-doc_cfg-doctest/foo.rs @@ -0,0 +1,15 @@ +#![feature(doc_cfg)] + +/// ``` +/// assert!(true); +/// ``` +#[doc(cfg(spec))] +fn f() {} + +#[doc(cfg(false))] +mod dummy { + /// ``` + /// assert!(true); + /// ``` + fn f2() {} +} diff --git a/tests/run-make/rustdoc-filter-doc_cfg-doctest/rmake.rs b/tests/run-make/rustdoc-filter-doc_cfg-doctest/rmake.rs new file mode 100644 index 0000000000000..942f23964f4d3 --- /dev/null +++ b/tests/run-make/rustdoc-filter-doc_cfg-doctest/rmake.rs @@ -0,0 +1,30 @@ +//! Regression test to ensure that `doc(cfg())` has no impact on the filtered-out doctests. +//! +//! Regression test for . + +//@ ignore-cross-compile + +use run_make_support::rustdoc; + +fn check_rustdoc_test_output(edition: &str) { + let out = rustdoc().input("foo.rs").edition(edition).arg("--test").run().stdout_utf8(); + + // There should be two tests run. + assert!(out.contains("running 2 test"), "Failed with edition {edition}"); + // They should be in `foo.rs`. + assert!(out.contains("test foo.rs - f (line 3) ... ok"), "Failed with edition {edition}"); + assert!( + out.contains("test foo.rs - dummy::f2 (line 11) ... ok"), + "Failed with edition {edition}" + ); + // We double-check that the test was run (successfully). + assert!( + out.contains("test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out;"), + "Failed with edition {edition}", + ); +} + +fn main() { + check_rustdoc_test_output("2015"); + check_rustdoc_test_output("2024"); +}