Auto merge of #146468 - Zalathar:rollup-6u3s44d, r=Zalathar

Rollup of 15 pull requests

Successful merges:

 - rust-lang/rust#144549 (match clang's `va_arg` assembly on arm targets)
 - rust-lang/rust#145895 (thread parking: fix docs and examples)
 - rust-lang/rust#146308 (support integer literals in `${concat()}`)
 - rust-lang/rust#146323 (check before test for hardware capabilites in bits 32~63 of usize)
 - rust-lang/rust#146332 (tidy: make behavior of extra-checks more uniform)
 - rust-lang/rust#146374 (Update `browser-ui-test` version to `0.22.2`)
 - rust-lang/rust#146413 (Improve suggestion in case a bare URL is surrounded by brackets)
 - rust-lang/rust#146426 (Bump miow to 0.60.1)
 - rust-lang/rust#146432 (Implement `Socket::take_error` for Hermit)
 - rust-lang/rust#146433 (rwlock tests: fix miri macos test regression)
 - rust-lang/rust#146435 (Change the default value of `gcc.download-ci-gcc` to `true`)
 - rust-lang/rust#146439 (fix cfg for poison test macro)
 - rust-lang/rust#146448 ([rustdoc] Correctly handle literal search on paths)
 - rust-lang/rust#146449 (Fix `libgccjit` symlink when we build GCC locally)
 - rust-lang/rust#146455 (test: remove an outdated normalization for rustc versions)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-09-12 11:27:07 +00:00
commit 408eacfb95
38 changed files with 503 additions and 205 deletions

View file

@ -2347,11 +2347,11 @@ dependencies = [
[[package]]
name = "miow"
version = "0.6.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "359f76430b20a79f9e20e115b3428614e654f04fab314482fc0fda0ebd3c6044"
checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08"
dependencies = [
"windows-sys 0.48.0",
"windows-sys 0.60.2",
]
[[package]]
@ -6314,15 +6314,6 @@ dependencies = [
"windows-link",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
@ -6350,21 +6341,6 @@ dependencies = [
"windows-targets 0.53.3",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
@ -6407,12 +6383,6 @@ dependencies = [
"windows-link",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
@ -6425,12 +6395,6 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
@ -6443,12 +6407,6 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
@ -6473,12 +6431,6 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
@ -6491,12 +6443,6 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
@ -6509,12 +6455,6 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
@ -6527,12 +6467,6 @@ version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"

View file

@ -908,6 +908,21 @@ pub(super) fn emit_va_arg<'ll, 'tcx>(
)
}
"aarch64" => emit_aapcs_va_arg(bx, addr, target_ty),
"arm" => {
// Types wider than 16 bytes are not currently supported. Clang has special logic for
// such types, but `VaArgSafe` is not implemented for any type that is this large.
assert!(bx.cx.size_of(target_ty).bytes() <= 16);
emit_ptr_va_arg(
bx,
addr,
target_ty,
PassMode::Direct,
SlotSize::Bytes4,
AllowHigherAlign::Yes,
ForceRightAdjust::No,
)
}
"s390x" => emit_s390x_va_arg(bx, addr, target_ty),
"powerpc" => emit_powerpc_va_arg(bx, addr, target_ty),
"powerpc64" | "powerpc64le" => emit_ptr_va_arg(

View file

@ -520,7 +520,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
LocalRef::Place(va_list) => {
bx.va_end(va_list.val.llval);
// Explicitly end the lifetime of the `va_list`, this matters for LLVM.
// Explicitly end the lifetime of the `va_list`, improves LLVM codegen.
bx.lifetime_end(va_list.val.llval, va_list.layout.size);
}
_ => bug!("C-variadic function must have a `VaList` place"),

View file

@ -438,6 +438,10 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
if fx.fn_abi.c_variadic && arg_index == fx.fn_abi.args.len() {
let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty));
// Explicitly start the lifetime of the `va_list`, improves LLVM codegen.
bx.lifetime_start(va_list.val.llval, va_list.layout.size);
bx.va_start(va_list.val.llval);
return LocalRef::Place(va_list);

View file

@ -940,11 +940,27 @@ fn extract_symbol_from_pnr<'a>(
{
Ok(*symbol)
}
ParseNtResult::Literal(expr)
if let ExprKind::Lit(lit @ Lit { kind: LitKind::Integer, symbol, suffix }) =
&expr.kind =>
{
if lit.is_semantic_float() {
Err(dcx
.struct_err("floats are not supported as metavariables of `${concat(..)}`")
.with_span(span_err))
} else if suffix.is_none() {
Ok(*symbol)
} else {
Err(dcx
.struct_err("integer metavariables of `${concat(..)}` must not be suffixed")
.with_span(span_err))
}
}
_ => Err(dcx
.struct_err(
"metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`",
)
.with_note("currently only string literals are supported")
.with_note("currently only string and integer literals are supported")
.with_span(span_err)),
}
}

View file

@ -304,7 +304,8 @@ impl Socket {
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
unimplemented!()
let raw: c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_ERROR)?;
if raw == 0 { Ok(None) } else { Ok(Some(io::Error::from_raw_os_error(raw as i32))) }
}
// This is used by sys_common code to abstract over Windows and Unix.

View file

@ -3,7 +3,7 @@ use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
use crate::sys::unsupported;
use crate::{fmt, io, str};
use crate::{fmt, io};
pub fn errno() -> i32 {
unsafe { hermit_abi::get_errno() }

View file

@ -276,7 +276,9 @@ fn wait(
// If the managing thread happens to signal and unpark us before we
// can park ourselves, the result could be this thread never gets
// unparked. Luckily `park` comes with the guarantee that if it got
// an `unpark` just before on an unparked thread it does not park.
// an `unpark` just before on an unparked thread it does not park. Crucially, we know
// the `unpark` must have happened between the `compare_exchange_weak` above and here,
// and there's no other `park` in that code that could steal our token.
// SAFETY: we retrieved this handle on the current thread above.
unsafe { node.thread.park() }
}

View file

@ -1021,13 +1021,23 @@ impl Drop for PanicGuard {
/// specifying a maximum time to block the thread for.
///
/// * The [`unpark`] method on a [`Thread`] atomically makes the token available
/// if it wasn't already. Because the token is initially absent, [`unpark`]
/// followed by [`park`] will result in the second call returning immediately.
/// if it wasn't already. Because the token can be held by a thread even if it is currently not
/// parked, [`unpark`] followed by [`park`] will result in the second call returning immediately.
/// However, note that to rely on this guarantee, you need to make sure that your `unpark` happens
/// after all `park` that may be done by other data structures!
///
/// The API is typically used by acquiring a handle to the current thread,
/// placing that handle in a shared data structure so that other threads can
/// find it, and then `park`ing in a loop. When some desired condition is met, another
/// thread calls [`unpark`] on the handle.
/// The API is typically used by acquiring a handle to the current thread, placing that handle in a
/// shared data structure so that other threads can find it, and then `park`ing in a loop. When some
/// desired condition is met, another thread calls [`unpark`] on the handle. The last bullet point
/// above guarantees that even if the `unpark` occurs before the thread is finished `park`ing, it
/// will be woken up properly.
///
/// Note that the coordination via the shared data structure is crucial: If you `unpark` a thread
/// without first establishing that it is about to be `park`ing within your code, that `unpark` may
/// get consumed by a *different* `park` in the same thread, leading to a deadlock. This also means
/// you must not call unknown code between setting up for parking and calling `park`; for instance,
/// if you invoke `println!`, that may itself call `park` and thus consume your `unpark` and cause a
/// deadlock.
///
/// The motivation for this design is twofold:
///
@ -1058,21 +1068,24 @@ impl Drop for PanicGuard {
///
/// ```
/// use std::thread;
/// use std::sync::{Arc, atomic::{Ordering, AtomicBool}};
/// use std::sync::atomic::{Ordering, AtomicBool};
/// use std::time::Duration;
///
/// let flag = Arc::new(AtomicBool::new(false));
/// let flag2 = Arc::clone(&flag);
/// static QUEUED: AtomicBool = AtomicBool::new(false);
/// static FLAG: AtomicBool = AtomicBool::new(false);
///
/// let parked_thread = thread::spawn(move || {
/// println!("Thread spawned");
/// // Signal that we are going to `park`. Between this store and our `park`, there may
/// // be no other `park`, or else that `park` could consume our `unpark` token!
/// QUEUED.store(true, Ordering::Release);
/// // We want to wait until the flag is set. We *could* just spin, but using
/// // park/unpark is more efficient.
/// while !flag2.load(Ordering::Relaxed) {
/// println!("Parking thread");
/// while !FLAG.load(Ordering::Acquire) {
/// // We can *not* use `println!` here since that could use thread parking internally.
/// thread::park();
/// // We *could* get here spuriously, i.e., way before the 10ms below are over!
/// // But that is no problem, we are in a loop until the flag is set anyway.
/// println!("Thread unparked");
/// }
/// println!("Flag received");
/// });
@ -1080,11 +1093,22 @@ impl Drop for PanicGuard {
/// // Let some time pass for the thread to be spawned.
/// thread::sleep(Duration::from_millis(10));
///
/// // Ensure the thread is about to park.
/// // This is crucial! It guarantees that the `unpark` below is not consumed
/// // by some other code in the parked thread (e.g. inside `println!`).
/// while !QUEUED.load(Ordering::Acquire) {
/// // Spinning is of course inefficient; in practice, this would more likely be
/// // a dequeue where we have no work to do if there's nobody queued.
/// std::hint::spin_loop();
/// }
///
/// // Set the flag, and let the thread wake up.
/// // There is no race condition here, if `unpark`
/// // There is no race condition here: if `unpark`
/// // happens first, `park` will return immediately.
/// // There is also no other `park` that could consume this token,
/// // since we waited until the other thread got queued.
/// // Hence there is no risk of a deadlock.
/// flag.store(true, Ordering::Relaxed);
/// FLAG.store(true, Ordering::Release);
/// println!("Unpark the thread");
/// parked_thread.thread().unpark();
///
@ -1494,10 +1518,14 @@ impl Thread {
/// ```
/// use std::thread;
/// use std::time::Duration;
/// use std::sync::atomic::{AtomicBool, Ordering};
///
/// static QUEUED: AtomicBool = AtomicBool::new(false);
///
/// let parked_thread = thread::Builder::new()
/// .spawn(|| {
/// println!("Parking thread");
/// QUEUED.store(true, Ordering::Release);
/// thread::park();
/// println!("Thread unparked");
/// })
@ -1506,6 +1534,15 @@ impl Thread {
/// // Let some time pass for the thread to be spawned.
/// thread::sleep(Duration::from_millis(10));
///
/// // Wait until the other thread is queued.
/// // This is crucial! It guarantees that the `unpark` below is not consumed
/// // by some other code in the parked thread (e.g. inside `println!`).
/// while !QUEUED.load(Ordering::Acquire) {
/// // Spinning is of course inefficient; in practice, this would more likely be
/// // a dequeue where we have no work to do if there's nobody queued.
/// std::hint::spin_loop();
/// }
///
/// println!("Unpark the thread");
/// parked_thread.thread().unpark();
///

View file

@ -287,6 +287,8 @@ fn test_park_unpark_called_other_thread() {
for _ in 0..10 {
let th = thread::current();
// Here we rely on `thread::spawn` (specifically the part that runs after spawning
// the thread) to not consume the parking token.
let _guard = thread::spawn(move || {
super::sleep(Duration::from_millis(50));
th.unpark();
@ -316,6 +318,8 @@ fn test_park_timeout_unpark_called_other_thread() {
for _ in 0..10 {
let th = thread::current();
// Here we rely on `thread::spawn` (specifically the part that runs after spawning
// the thread) to not consume the parking token.
let _guard = thread::spawn(move || {
super::sleep(Duration::from_millis(50));
th.unpark();

View file

@ -17,7 +17,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
nonpoison_and_poison_unwrap_test!(
name: notify_one,
test_body: {
@ -38,7 +38,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
nonpoison_and_poison_unwrap_test!(
name: notify_all,
test_body: {
@ -79,7 +79,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
nonpoison_and_poison_unwrap_test!(
name: test_mutex_arc_condvar,
test_body: {
@ -116,7 +116,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
nonpoison_and_poison_unwrap_test!(
name: wait_while,
test_body: {
@ -141,7 +141,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
nonpoison_and_poison_unwrap_test!(
name: wait_timeout_wait,
test_body: {
@ -164,7 +164,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
nonpoison_and_poison_unwrap_test!(
name: wait_timeout_while_wait,
test_body: {
@ -180,7 +180,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
nonpoison_and_poison_unwrap_test!(
name: wait_timeout_while_instant_satisfy,
test_body: {
@ -197,7 +197,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
nonpoison_and_poison_unwrap_test!(
name: wait_timeout_while_wake,
test_body: {
@ -226,7 +226,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
#[cfg(not(any(target_os = "emscripten", target_os = "wasi")))] // No threads.
nonpoison_and_poison_unwrap_test!(
name: wait_timeout_wake,
test_body: {

View file

@ -58,6 +58,9 @@ fn result_unwrap<T, E: std::fmt::Debug>(x: Result<T, E>) -> T {
/// a no-op (the identity function).
///
/// The test names will be prefiex with `poison_` or `nonpoison_`.
///
/// Important: most attributes (except `cfg`) will not work properly! (They are only applied to the first test.)
/// See <https://github.com/rust-lang/rust/pull/146433> for more information.
macro_rules! nonpoison_and_poison_unwrap_test {
(
name: $name:ident,

View file

@ -266,7 +266,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
#[cfg(panic = "unwind")] // Requires unwinding support.
nonpoison_and_poison_unwrap_test!(
name: test_panics,
test_body: {
@ -297,7 +297,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
#[cfg(panic = "unwind")] // Requires unwinding support.
nonpoison_and_poison_unwrap_test!(
name: test_mutex_arc_access_in_unwind,
test_body: {

View file

@ -50,7 +50,7 @@ nonpoison_and_poison_unwrap_test!(
// FIXME: On macOS we use a provenance-incorrect implementation and Miri
// catches that issue with a chance of around 1/1000.
// See <https://github.com/rust-lang/rust/issues/121950> for details.
#[cfg_attr(all(miri, target_os = "macos"), ignore)]
#[cfg(not(all(miri, target_os = "macos")))]
nonpoison_and_poison_unwrap_test!(
name: frob,
test_body: {
@ -124,7 +124,7 @@ nonpoison_and_poison_unwrap_test!(
}
);
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
#[cfg(panic = "unwind")] // Requires unwinding support.
nonpoison_and_poison_unwrap_test!(
name: test_rw_arc_access_in_unwind,
test_body: {
@ -315,7 +315,7 @@ nonpoison_and_poison_unwrap_test!(
// FIXME: On macOS we use a provenance-incorrect implementation and Miri catches that issue.
// See <https://github.com/rust-lang/rust/issues/121950> for details.
#[cfg_attr(all(miri, target_os = "macos"), ignore)]
#[cfg(not(all(miri, target_os = "macos")))]
nonpoison_and_poison_unwrap_test!(
name: test_downgrade_observe,
test_body: {
@ -362,7 +362,7 @@ nonpoison_and_poison_unwrap_test!(
// FIXME: On macOS we use a provenance-incorrect implementation and Miri catches that issue.
// See <https://github.com/rust-lang/rust/issues/121950> for details.
#[cfg_attr(all(miri, target_os = "macos"), ignore)]
#[cfg(not(all(miri, target_os = "macos")))]
nonpoison_and_poison_unwrap_test!(
name: test_downgrade_atomic,
test_body: {

View file

@ -140,7 +140,7 @@ struct AtHwcap {
impl From<auxvec::AuxVec> for AtHwcap {
/// Reads AtHwcap from the auxiliary vector.
fn from(auxv: auxvec::AuxVec) -> Self {
AtHwcap {
let mut cap = AtHwcap {
fp: bit::test(auxv.hwcap, 0),
asimd: bit::test(auxv.hwcap, 1),
// evtstrm: bit::test(auxv.hwcap, 2),
@ -207,39 +207,50 @@ impl From<auxvec::AuxVec> for AtHwcap {
// smef32f32: bit::test(auxv.hwcap2, 29),
smefa64: bit::test(auxv.hwcap2, 30),
wfxt: bit::test(auxv.hwcap2, 31),
// ebf16: bit::test(auxv.hwcap2, 32),
// sveebf16: bit::test(auxv.hwcap2, 33),
cssc: bit::test(auxv.hwcap2, 34),
// rprfm: bit::test(auxv.hwcap2, 35),
sve2p1: bit::test(auxv.hwcap2, 36),
sme2: bit::test(auxv.hwcap2, 37),
sme2p1: bit::test(auxv.hwcap2, 38),
// smei16i32: bit::test(auxv.hwcap2, 39),
// smebi32i32: bit::test(auxv.hwcap2, 40),
smeb16b16: bit::test(auxv.hwcap2, 41),
smef16f16: bit::test(auxv.hwcap2, 42),
mops: bit::test(auxv.hwcap2, 43),
hbc: bit::test(auxv.hwcap2, 44),
sveb16b16: bit::test(auxv.hwcap2, 45),
lrcpc3: bit::test(auxv.hwcap2, 46),
lse128: bit::test(auxv.hwcap2, 47),
fpmr: bit::test(auxv.hwcap2, 48),
lut: bit::test(auxv.hwcap2, 49),
faminmax: bit::test(auxv.hwcap2, 50),
f8cvt: bit::test(auxv.hwcap2, 51),
f8fma: bit::test(auxv.hwcap2, 52),
f8dp4: bit::test(auxv.hwcap2, 53),
f8dp2: bit::test(auxv.hwcap2, 54),
f8e4m3: bit::test(auxv.hwcap2, 55),
f8e5m2: bit::test(auxv.hwcap2, 56),
smelutv2: bit::test(auxv.hwcap2, 57),
smef8f16: bit::test(auxv.hwcap2, 58),
smef8f32: bit::test(auxv.hwcap2, 59),
smesf8fma: bit::test(auxv.hwcap2, 60),
smesf8dp4: bit::test(auxv.hwcap2, 61),
smesf8dp2: bit::test(auxv.hwcap2, 62),
// pauthlr: bit::test(auxv.hwcap2, ??),
..Default::default()
};
// Hardware capabilities from bits 32 to 63 should only
// be tested on LP64 targets with 64 bits `usize`.
// On ILP32 targets like `aarch64-unknown-linux-gnu_ilp32`,
// these hardware capabilities will default to `false`.
// https://github.com/rust-lang/rust/issues/146230
#[cfg(target_pointer_width = "64")]
{
// cap.ebf16: bit::test(auxv.hwcap2, 32);
// cap.sveebf16: bit::test(auxv.hwcap2, 33);
cap.cssc = bit::test(auxv.hwcap2, 34);
// cap.rprfm: bit::test(auxv.hwcap2, 35);
cap.sve2p1 = bit::test(auxv.hwcap2, 36);
cap.sme2 = bit::test(auxv.hwcap2, 37);
cap.sme2p1 = bit::test(auxv.hwcap2, 38);
// cap.smei16i32 = bit::test(auxv.hwcap2, 39);
// cap.smebi32i32 = bit::test(auxv.hwcap2, 40);
cap.smeb16b16 = bit::test(auxv.hwcap2, 41);
cap.smef16f16 = bit::test(auxv.hwcap2, 42);
cap.mops = bit::test(auxv.hwcap2, 43);
cap.hbc = bit::test(auxv.hwcap2, 44);
cap.sveb16b16 = bit::test(auxv.hwcap2, 45);
cap.lrcpc3 = bit::test(auxv.hwcap2, 46);
cap.lse128 = bit::test(auxv.hwcap2, 47);
cap.fpmr = bit::test(auxv.hwcap2, 48);
cap.lut = bit::test(auxv.hwcap2, 49);
cap.faminmax = bit::test(auxv.hwcap2, 50);
cap.f8cvt = bit::test(auxv.hwcap2, 51);
cap.f8fma = bit::test(auxv.hwcap2, 52);
cap.f8dp4 = bit::test(auxv.hwcap2, 53);
cap.f8dp2 = bit::test(auxv.hwcap2, 54);
cap.f8e4m3 = bit::test(auxv.hwcap2, 55);
cap.f8e5m2 = bit::test(auxv.hwcap2, 56);
cap.smelutv2 = bit::test(auxv.hwcap2, 57);
cap.smef8f16 = bit::test(auxv.hwcap2, 58);
cap.smef8f32 = bit::test(auxv.hwcap2, 59);
cap.smesf8fma = bit::test(auxv.hwcap2, 60);
cap.smesf8dp4 = bit::test(auxv.hwcap2, 61);
cap.smesf8dp2 = bit::test(auxv.hwcap2, 62);
// cap.pauthlr = bit::test(auxv.hwcap2, ??);
}
cap
}
}

8
package-lock.json generated
View file

@ -5,7 +5,7 @@
"packages": {
"": {
"dependencies": {
"browser-ui-test": "^0.22.0",
"browser-ui-test": "^0.22.2",
"es-check": "^6.2.1",
"eslint": "^8.57.1",
"eslint-js": "github:eslint/js",
@ -485,9 +485,9 @@
}
},
"node_modules/browser-ui-test": {
"version": "0.22.0",
"resolved": "https://registry.npmjs.org/browser-ui-test/-/browser-ui-test-0.22.0.tgz",
"integrity": "sha512-p/C02TMybTDKsAjpGOdnyNC0Q25KDae/fKMnvHaqcJ0tXRqNKwndW2Ltq7HTmin5xqg8GGOmysEgWTZkXu6pfA==",
"version": "0.22.2",
"resolved": "https://registry.npmjs.org/browser-ui-test/-/browser-ui-test-0.22.2.tgz",
"integrity": "sha512-eNB/PN2yDGe5n5IwE3ld/N6A39jM1oRzJmT5nOVQqrvoZEtcd9JSggDQPNVUnMEyuGcD4OEOWMsEa4oJppAmDQ==",
"license": "MIT",
"dependencies": {
"css-unit-converter": "^1.1.2",

View file

@ -1,6 +1,6 @@
{
"dependencies": {
"browser-ui-test": "^0.22.0",
"browser-ui-test": "^0.22.2",
"es-check": "^6.2.1",
"eslint": "^8.57.1",
"eslint-js": "github:eslint/js",

View file

@ -14,6 +14,10 @@ compiletest-use-stage0-libtest = false
[llvm]
download-ci-llvm = false
# Most users installing from source want to build all parts of the project from source.
[gcc]
download-ci-gcc = false
[rust]
# We have several defaults in bootstrap that depend on whether the channel is `dev` (e.g. `omit-git-hash` and `download-ci-llvm`).
# Make sure they don't get set when installing from source.

View file

@ -32,6 +32,10 @@ pub struct GccOutput {
impl GccOutput {
/// Install the required libgccjit library file(s) to the specified `path`.
pub fn install_to(&self, builder: &Builder<'_>, directory: &Path) {
if builder.config.dry_run() {
return;
}
// At build time, cg_gcc has to link to libgccjit.so (the unversioned symbol).
// However, at runtime, it will by default look for libgccjit.so.0.
// So when we install the built libgccjit.so file to the target `directory`, we add it there
@ -39,8 +43,16 @@ impl GccOutput {
let mut target_filename = self.libgccjit.file_name().unwrap().to_str().unwrap().to_string();
target_filename.push_str(".0");
// If we build libgccjit ourselves, then `self.libgccjit` can actually be a symlink.
// In that case, we have to resolve it first, otherwise we'd create a symlink to a symlink,
// which wouldn't work.
let actual_libgccjit_path = t!(
self.libgccjit.canonicalize(),
format!("Cannot find libgccjit at {}", self.libgccjit.display())
);
let dst = directory.join(target_filename);
builder.copy_link(&self.libgccjit, &dst, FileType::NativeLibrary);
builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary);
}
}

View file

@ -422,10 +422,10 @@ impl std::str::FromStr for RustcLto {
#[derive(Default, Clone)]
pub enum GccCiMode {
/// Build GCC from the local `src/gcc` submodule.
#[default]
BuildLocally,
/// Try to download GCC from CI.
/// If it is not available on CI, it will be built locally instead.
#[default]
DownloadFromCi,
}

View file

@ -541,4 +541,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Info,
summary: "Added a new option `rust.break-on-ice` to control if internal compiler errors cause a debug break on Windows.",
},
ChangeInfo {
change_id: 146435,
severity: ChangeSeverity::Info,
summary: "The default value of the `gcc.download-ci-gcc` option has been changed to `true`.",
},
];

View file

@ -3639,7 +3639,7 @@ class DocSearch {
if (contains.length === 0) {
return 0;
}
const maxPathEditDistance = Math.floor(
const maxPathEditDistance = parsedQuery.literalSearch ? 0 : Math.floor(
contains.reduce((acc, next) => acc + next.length, 0) / 3,
);
let ret_dist = maxPathEditDistance + 1;
@ -3650,7 +3650,9 @@ class DocSearch {
let dist_total = 0;
for (let x = 0; x < clength; ++x) {
const [p, c] = [path[i + x], contains[x]];
if (Math.floor((p.length - c.length) / 3) <= maxPathEditDistance &&
if (parsedQuery.literalSearch && p !== c) {
continue pathiter;
} else if (Math.floor((p.length - c.length) / 3) <= maxPathEditDistance &&
p.indexOf(c) !== -1
) {
// discount distance on substring match

View file

@ -17,7 +17,10 @@ use crate::core::DocContext;
use crate::html::markdown::main_body_opts;
pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) {
let report_diag = |cx: &DocContext<'_>, msg: &'static str, range: Range<usize>| {
let report_diag = |cx: &DocContext<'_>,
msg: &'static str,
range: Range<usize>,
without_brackets: Option<&str>| {
let maybe_sp = source_span_for_markdown_range(cx.tcx, dox, &range, &item.attrs.doc_strings)
.map(|(sp, _)| sp);
let sp = maybe_sp.unwrap_or_else(|| item.attr_span(cx.tcx));
@ -27,14 +30,22 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
// The fallback of using the attribute span is suitable for
// highlighting where the error is, but not for placing the < and >
if let Some(sp) = maybe_sp {
lint.multipart_suggestion(
"use an automatic link instead",
vec![
(sp.shrink_to_lo(), "<".to_string()),
(sp.shrink_to_hi(), ">".to_string()),
],
Applicability::MachineApplicable,
);
if let Some(without_brackets) = without_brackets {
lint.multipart_suggestion(
"use an automatic link instead",
vec![(sp, format!("<{without_brackets}>"))],
Applicability::MachineApplicable,
);
} else {
lint.multipart_suggestion(
"use an automatic link instead",
vec![
(sp.shrink_to_lo(), "<".to_string()),
(sp.shrink_to_hi(), ">".to_string()),
],
Applicability::MachineApplicable,
);
}
}
});
};
@ -43,7 +54,7 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
while let Some((event, range)) = p.next() {
match event {
Event::Text(s) => find_raw_urls(cx, &s, range, &report_diag),
Event::Text(s) => find_raw_urls(cx, dox, &s, range, &report_diag),
// We don't want to check the text inside code blocks or links.
Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => {
for (event, _) in p.by_ref() {
@ -67,25 +78,35 @@ static URL_REGEX: LazyLock<Regex> = LazyLock::new(|| {
r"https?://", // url scheme
r"([-a-zA-Z0-9@:%._\+~#=]{2,256}\.)+", // one or more subdomains
r"[a-zA-Z]{2,63}", // root domain
r"\b([-a-zA-Z0-9@:%_\+.~#?&/=]*)" // optional query or url fragments
r"\b([-a-zA-Z0-9@:%_\+.~#?&/=]*)", // optional query or url fragments
))
.expect("failed to build regex")
});
fn find_raw_urls(
cx: &DocContext<'_>,
dox: &str,
text: &str,
range: Range<usize>,
f: &impl Fn(&DocContext<'_>, &'static str, Range<usize>),
f: &impl Fn(&DocContext<'_>, &'static str, Range<usize>, Option<&str>),
) {
trace!("looking for raw urls in {text}");
// For now, we only check "full" URLs (meaning, starting with "http://" or "https://").
for match_ in URL_REGEX.find_iter(text) {
let url_range = match_.range();
f(
cx,
"this URL is not a hyperlink",
Range { start: range.start + url_range.start, end: range.start + url_range.end },
);
let mut url_range = match_.range();
url_range.start += range.start;
url_range.end += range.start;
let mut without_brackets = None;
// If the link is contained inside `[]`, then we need to replace the brackets and
// not just add `<>`.
if dox[..url_range.start].ends_with('[')
&& url_range.end <= dox.len()
&& dox[url_range.end..].starts_with(']')
{
url_range.start -= 1;
url_range.end += 1;
without_brackets = Some(match_.as_str());
}
f(cx, "this URL is not a hyperlink", url_range, without_brackets);
}
}

View file

@ -606,6 +606,7 @@ Definite bugs found:
* [A bug in the new `RwLock::downgrade` implementation](https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/Miri.20error.20library.20test) (caught by Miri before it landed in the Rust repo)
* [Mockall reading uninitialized memory when mocking `std::io::Read::read`, even if all expectations are satisfied](https://github.com/asomers/mockall/issues/647) (caught by Miri running Tokio's test suite)
* [`ReentrantLock` not correctly dealing with reuse of addresses for TLS storage of different threads](https://github.com/rust-lang/rust/pull/141248)
* [Rare Deadlock in the thread (un)parking example code](https://github.com/rust-lang/rust/issues/145816)
Violations of [Stacked Borrows] found that are likely bugs (but Stacked Borrows is currently just an experiment):

View file

@ -124,6 +124,12 @@ fn check_impl(
};
}
let rerun_with_bless = |mode: &str, action: &str| {
if !bless {
eprintln!("rerun tidy with `--extra-checks={mode} --bless` to {action}");
}
};
let python_lint = extra_check!(Py, Lint);
let python_fmt = extra_check!(Py, Fmt);
let shell_lint = extra_check!(Shell, Lint);
@ -147,14 +153,21 @@ fn check_impl(
}
if python_lint {
eprintln!("linting python files");
let py_path = py_path.as_ref().unwrap();
let res = run_ruff(root_path, outdir, py_path, &cfg_args, &file_args, &["check".as_ref()]);
let args: &[&OsStr] = if bless {
eprintln!("linting python files and applying suggestions");
&["check".as_ref(), "--fix".as_ref()]
} else {
eprintln!("linting python files");
&["check".as_ref()]
};
if res.is_err() && show_diff {
let res = run_ruff(root_path, outdir, py_path, &cfg_args, &file_args, args);
if res.is_err() && show_diff && !bless {
eprintln!("\npython linting failed! Printing diff suggestions:");
let _ = run_ruff(
let diff_res = run_ruff(
root_path,
outdir,
py_path,
@ -162,6 +175,10 @@ fn check_impl(
&file_args,
&["check".as_ref(), "--diff".as_ref()],
);
// `ruff check --diff` will return status 0 if there are no suggestions.
if diff_res.is_err() {
rerun_with_bless("py:lint", "apply ruff suggestions");
}
}
// Rethrow error
res?;
@ -192,7 +209,7 @@ fn check_impl(
&["format".as_ref(), "--diff".as_ref()],
);
}
eprintln!("rerun tidy with `--extra-checks=py:fmt --bless` to reformat Python code");
rerun_with_bless("py:fmt", "reformat Python code");
}
// Rethrow error
@ -225,7 +242,7 @@ fn check_impl(
let args = merge_args(&cfg_args_clang_format, &file_args_clang_format);
let res = py_runner(py_path.as_ref().unwrap(), false, None, "clang-format", &args);
if res.is_err() && show_diff {
if res.is_err() && show_diff && !bless {
eprintln!("\nclang-format linting failed! Printing diff suggestions:");
let mut cfg_args_clang_format_diff = cfg_args.clone();
@ -265,6 +282,7 @@ fn check_impl(
);
}
}
rerun_with_bless("cpp:fmt", "reformat C++ code");
}
// Rethrow error
res?;
@ -290,12 +308,16 @@ fn check_impl(
args.extend_from_slice(SPELLCHECK_DIRS);
if bless {
eprintln!("spellcheck files and fix");
eprintln!("spellchecking files and fixing typos");
args.push("--write-changes");
} else {
eprintln!("spellcheck files");
eprintln!("spellchecking files");
}
spellcheck_runner(root_path, &outdir, &cargo, &args)?;
let res = spellcheck_runner(root_path, &outdir, &cargo, &args);
if res.is_err() {
rerun_with_bless("spellcheck", "fix typos");
}
res?;
}
if js_lint || js_typecheck {
@ -303,11 +325,21 @@ fn check_impl(
}
if js_lint {
rustdoc_js::lint(outdir, librustdoc_path, tools_path, bless)?;
if bless {
eprintln!("linting javascript files");
} else {
eprintln!("linting javascript files and applying suggestions");
}
let res = rustdoc_js::lint(outdir, librustdoc_path, tools_path, bless);
if res.is_err() {
rerun_with_bless("js:lint", "apply eslint suggestions");
}
res?;
rustdoc_js::es_check(outdir, librustdoc_path)?;
}
if js_typecheck {
eprintln!("typechecking javascript files");
rustdoc_js::typecheck(outdir, librustdoc_path)?;
}

View file

@ -57,7 +57,7 @@ fn run_eslint(
if exit_status.success() {
return Ok(());
}
Err(super::Error::FailedCheck("eslint command failed"))
Err(super::Error::FailedCheck("eslint"))
}
Err(error) => Err(super::Error::Generic(format!("eslint command failed: {error:?}"))),
}
@ -94,7 +94,7 @@ pub(super) fn typecheck(outdir: &Path, librustdoc_path: &Path) -> Result<(), sup
if exit_status.success() {
return Ok(());
}
Err(super::Error::FailedCheck("tsc command failed"))
Err(super::Error::FailedCheck("tsc"))
}
Err(error) => Err(super::Error::Generic(format!("tsc command failed: {error:?}"))),
}
@ -112,7 +112,7 @@ pub(super) fn es_check(outdir: &Path, librustdoc_path: &Path) -> Result<(), supe
if exit_status.success() {
return Ok(());
}
Err(super::Error::FailedCheck("es-check command failed"))
Err(super::Error::FailedCheck("es-check"))
}
Err(error) => Err(super::Error::Generic(format!("es-check command failed: {error:?}"))),
}

View file

@ -0,0 +1,26 @@
//@ assembly-output: emit-asm
//@ compile-flags: -Copt-level=3
//@ only-arm
//@ ignore-thumb
//@ ignore-android
#![no_std]
#![crate_type = "lib"]
#![feature(c_variadic)]
// Check that the assembly that rustc generates matches what clang emits.
#[unsafe(no_mangle)]
unsafe extern "C" fn variadic(a: f64, mut args: ...) -> f64 {
// CHECK-LABEL: variadic
// CHECK: sub sp, sp
// CHECK: vldr
// CHECK: vadd.f64
// CHECK: vldr
// CHECK: vadd.f64
let b = args.arg::<f64>();
let c = args.arg::<f64>();
a + b + c
// CHECK: add sp, sp
}

View file

@ -0,0 +1,21 @@
//@ add-core-stubs
//@ compile-flags: -Copt-level=3
#![feature(c_variadic)]
#![crate_type = "lib"]
// Check that `%args` explicitly has its lifetime start and end. Being explicit can improve
// instruction and register selection, see e.g. https://github.com/rust-lang/rust/pull/144549
#[unsafe(no_mangle)]
unsafe extern "C" fn variadic(a: f64, mut args: ...) -> f64 {
// CHECK: call void @llvm.lifetime.start.p0(i64 {{[0-9]+}}, ptr nonnull %args)
// CHECK: call void @llvm.va_start.p0(ptr nonnull %args)
let b = args.arg::<f64>();
let c = args.arg::<f64>();
a + b + c
// CHECK: call void @llvm.va_end.p0(ptr nonnull %args)
// CHECK: call void @llvm.lifetime.end.p0(i64 {{[0-9]+}}, ptr nonnull %args)
}

View file

@ -0,0 +1,23 @@
// exact-check
// This test ensures that literal search is always applied on elements of the path.
const EXPECTED = [
{
'query': '"some::path"',
'others': [
{ 'path': 'literal_path::some', 'name': 'Path' },
],
},
{
'query': '"somea::path"',
'others': [
{ 'path': 'literal_path::somea', 'name': 'Path' },
],
},
{
'query': '"soma::path"',
'others': [
],
},
];

View file

@ -0,0 +1,7 @@
pub mod some {
pub struct Path;
}
pub mod somea {
pub struct Path;
}

View file

@ -68,3 +68,17 @@ pub mod foo {
/// https://somewhere.com/a?hello=12&bye=11#xyz
pub fn bar() {}
}
/// <https://bloob.blob>
//~^ ERROR this URL is not a hyperlink
/// [ <https://bloob.blob> ]
//~^ ERROR this URL is not a hyperlink
/// [ <https://bloob.blob>]
//~^ ERROR this URL is not a hyperlink
/// [<https://bloob.blob> ]
//~^ ERROR this URL is not a hyperlink
/// [<https://bloob.blob>
//~^ ERROR this URL is not a hyperlink
/// <https://bloob.blob>]
//~^ ERROR this URL is not a hyperlink
pub fn lint_with_brackets() {}

View file

@ -68,3 +68,17 @@ pub mod foo {
/// https://somewhere.com/a?hello=12&bye=11#xyz
pub fn bar() {}
}
/// [https://bloob.blob]
//~^ ERROR this URL is not a hyperlink
/// [ https://bloob.blob ]
//~^ ERROR this URL is not a hyperlink
/// [ https://bloob.blob]
//~^ ERROR this URL is not a hyperlink
/// [https://bloob.blob ]
//~^ ERROR this URL is not a hyperlink
/// [https://bloob.blob
//~^ ERROR this URL is not a hyperlink
/// https://bloob.blob]
//~^ ERROR this URL is not a hyperlink
pub fn lint_with_brackets() {}

View file

@ -243,5 +243,73 @@ help: use an automatic link instead
LL | #[doc = "<https://example.com/raw>"]
| + +
error: aborting due to 20 previous errors
error: this URL is not a hyperlink
--> $DIR/bare-urls.rs:72:5
|
LL | /// [https://bloob.blob]
| ^^^^^^^^^^^^^^^^^^^^ help: use an automatic link instead: `<https://bloob.blob>`
|
= note: bare URLs are not automatically turned into clickable links
error: this URL is not a hyperlink
--> $DIR/bare-urls.rs:74:7
|
LL | /// [ https://bloob.blob ]
| ^^^^^^^^^^^^^^^^^^
|
= note: bare URLs are not automatically turned into clickable links
help: use an automatic link instead
|
LL | /// [ <https://bloob.blob> ]
| + +
error: this URL is not a hyperlink
--> $DIR/bare-urls.rs:76:7
|
LL | /// [ https://bloob.blob]
| ^^^^^^^^^^^^^^^^^^
|
= note: bare URLs are not automatically turned into clickable links
help: use an automatic link instead
|
LL | /// [ <https://bloob.blob>]
| + +
error: this URL is not a hyperlink
--> $DIR/bare-urls.rs:78:6
|
LL | /// [https://bloob.blob ]
| ^^^^^^^^^^^^^^^^^^
|
= note: bare URLs are not automatically turned into clickable links
help: use an automatic link instead
|
LL | /// [<https://bloob.blob> ]
| + +
error: this URL is not a hyperlink
--> $DIR/bare-urls.rs:80:6
|
LL | /// [https://bloob.blob
| ^^^^^^^^^^^^^^^^^^
|
= note: bare URLs are not automatically turned into clickable links
help: use an automatic link instead
|
LL | /// [<https://bloob.blob>
| + +
error: this URL is not a hyperlink
--> $DIR/bare-urls.rs:82:5
|
LL | /// https://bloob.blob]
| ^^^^^^^^^^^^^^^^^^
|
= note: bare URLs are not automatically turned into clickable links
help: use an automatic link instead
|
LL | /// <https://bloob.blob>]
| + +
error: aborting due to 26 previous errors

View file

@ -1,4 +1,3 @@
//@ normalize-stderr: "you are using [0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?( \([^)]*\))?" -> "you are using $$RUSTC_VERSION"
#![feature(no_sanitize)] //~ ERROR feature has been removed
#[sanitize(address = "on")]

View file

@ -1,5 +1,5 @@
error[E0557]: feature has been removed
--> $DIR/feature-gate-sanitize.rs:2:12
--> $DIR/feature-gate-sanitize.rs:1:12
|
LL | #![feature(no_sanitize)]
| ^^^^^^^^^^^ feature has been removed
@ -8,7 +8,7 @@ LL | #![feature(no_sanitize)]
= note: renamed to sanitize(xyz = "on|off")
error[E0658]: the `#[sanitize]` attribute is an experimental feature
--> $DIR/feature-gate-sanitize.rs:4:1
--> $DIR/feature-gate-sanitize.rs:3:1
|
LL | #[sanitize(address = "on")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -92,6 +92,12 @@ macro_rules! combinations {
}};
}
macro_rules! int_struct {
($n: literal) => {
struct ${concat(E, $n)};
}
}
fn main() {
create_things!(behold);
behold_separated_idents_in_a_fn();
@ -112,4 +118,16 @@ fn main() {
assert_eq!(VAR_123, 2);
combinations!(_hello, "a", b, "b");
int_struct!(1_0);
int_struct!(2);
int_struct!(3___0);
int_struct!(7_);
int_struct!(08);
let _ = E1_0;
let _ = E2;
let _ = E3___0;
let _ = E7_;
let _ = E08;
}

View file

@ -140,7 +140,9 @@ macro_rules! bad_literal_non_string {
//~| ERROR metavariables of `${concat(..)}` must be of type
//~| ERROR metavariables of `${concat(..)}` must be of type
//~| ERROR metavariables of `${concat(..)}` must be of type
//~| ERROR metavariables of `${concat(..)}` must be of type
//~| ERROR floats are not supported as metavariables of `${concat(..)}`
//~| ERROR integer metavariables of `${concat(..)}` must not be suffixed
//~| ERROR integer metavariables of `${concat(..)}` must not be suffixed
}
}
@ -149,7 +151,6 @@ macro_rules! bad_tt_literal {
const ${concat(_foo, $tt)}: () = ();
//~^ ERROR metavariables of `${concat(..)}` must be of type
//~| ERROR metavariables of `${concat(..)}` must be of type
//~| ERROR metavariables of `${concat(..)}` must be of type
}
}
@ -178,13 +179,14 @@ fn main() {
bad_literal_string!("1.0");
bad_literal_string!("'1'");
bad_literal_non_string!(1);
bad_literal_non_string!(-1);
bad_literal_non_string!(1.0);
bad_literal_non_string!('1');
bad_literal_non_string!(false);
bad_literal_non_string!(4f64);
bad_literal_non_string!(5u8);
bad_literal_non_string!(6_u8);
bad_tt_literal!(1);
bad_tt_literal!(1.0);
bad_tt_literal!('1');
}

View file

@ -130,7 +130,7 @@ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `t
LL | ${concat($ex, aaaa)}
| ^^
|
= note: currently only string literals are supported
= note: currently only string and integer literals are supported
error: variable `foo` is not recognized in meta-variable expression
--> $DIR/concat-usage-errors.rs:37:30
@ -276,7 +276,7 @@ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `t
LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^
|
= note: currently only string literals are supported
= note: currently only string and integer literals are supported
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/concat-usage-errors.rs:138:31
@ -284,7 +284,7 @@ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `t
LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^
|
= note: currently only string literals are supported
= note: currently only string and integer literals are supported
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
@ -293,7 +293,7 @@ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `t
LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^
|
= note: currently only string literals are supported
= note: currently only string and integer literals are supported
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
@ -302,43 +302,45 @@ error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `t
LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^
|
= note: currently only string literals are supported
= note: currently only string and integer literals are supported
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
error: floats are not supported as metavariables of `${concat(..)}`
--> $DIR/concat-usage-errors.rs:138:31
|
LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^
error: integer metavariables of `${concat(..)}` must not be suffixed
--> $DIR/concat-usage-errors.rs:138:31
|
LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^
error: integer metavariables of `${concat(..)}` must not be suffixed
--> $DIR/concat-usage-errors.rs:138:31
|
LL | const ${concat(_foo, $literal)}: () = ();
| ^^^^^^^
|
= note: currently only string literals are supported
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/concat-usage-errors.rs:149:31
--> $DIR/concat-usage-errors.rs:151:31
|
LL | const ${concat(_foo, $tt)}: () = ();
| ^^
|
= note: currently only string literals are supported
= note: currently only string and integer literals are supported
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/concat-usage-errors.rs:149:31
--> $DIR/concat-usage-errors.rs:151:31
|
LL | const ${concat(_foo, $tt)}: () = ();
| ^^
|
= note: currently only string literals are supported
= note: currently only string and integer literals are supported
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`
--> $DIR/concat-usage-errors.rs:149:31
|
LL | const ${concat(_foo, $tt)}: () = ();
| ^^
|
= note: currently only string literals are supported
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 43 previous errors
error: aborting due to 44 previous errors