Auto merge of #151339 - JonathanBrouwer:rollup-DYrRtnq, r=JonathanBrouwer

Rollup of 3 pull requests

Successful merges:

 - rust-lang/rust#151287 (Reorganizing `tests/ui/issues` 15 tests [2/N] )
 - rust-lang/rust#151309 (fix: thread creation failed on the wasm32-wasip1-threads target.)
 - rust-lang/rust#151335 (Port rustc allocator attributes to attribute parser)

r? @ghost
This commit is contained in:
bors 2026-01-18 21:30:40 +00:00
commit 9b37157ece
39 changed files with 163 additions and 41 deletions

View file

@ -58,6 +58,7 @@ pub(crate) mod pin_v2;
pub(crate) mod proc_macro_attrs;
pub(crate) mod prototype;
pub(crate) mod repr;
pub(crate) mod rustc_allocator;
pub(crate) mod rustc_dump;
pub(crate) mod rustc_internal;
pub(crate) mod semantics;

View file

@ -0,0 +1,60 @@
use super::prelude::*;
pub(crate) struct RustcAllocatorParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcAllocatorParser {
const PATH: &[Symbol] = &[sym::rustc_allocator];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAllocator;
}
pub(crate) struct RustcAllocatorZeroedParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcAllocatorZeroedParser {
const PATH: &[Symbol] = &[sym::rustc_allocator_zeroed];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcAllocatorZeroed;
}
pub(crate) struct RustcAllocatorZeroedVariantParser;
impl<S: Stage> SingleAttributeParser<S> for RustcAllocatorZeroedVariantParser {
const PATH: &[Symbol] = &[sym::rustc_allocator_zeroed_variant];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "function");
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(name) = args.name_value().and_then(NameValueParser::value_as_str) else {
cx.expected_name_value(cx.attr_span, None);
return None;
};
Some(AttributeKind::RustcAllocatorZeroedVariant { name })
}
}
pub(crate) struct RustcDeallocatorParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcDeallocatorParser {
const PATH: &[Symbol] = &[sym::rustc_deallocator];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDeallocator;
}
pub(crate) struct RustcReallocatorParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcReallocatorParser {
const PATH: &[Symbol] = &[sym::rustc_reallocator];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::ForeignFn)]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcReallocator;
}

View file

@ -64,6 +64,10 @@ use crate::attributes::proc_macro_attrs::{
};
use crate::attributes::prototype::CustomMirParser;
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
use crate::attributes::rustc_allocator::{
RustcAllocatorParser, RustcAllocatorZeroedParser, RustcAllocatorZeroedVariantParser,
RustcDeallocatorParser, RustcReallocatorParser,
};
use crate::attributes::rustc_dump::{
RustcDumpDefParents, RustcDumpItemBounds, RustcDumpPredicates, RustcDumpUserArgs,
RustcDumpVtable,
@ -223,6 +227,7 @@ attribute_parsers!(
Single<PatternComplexityLimitParser>,
Single<ProcMacroDeriveParser>,
Single<RecursionLimitParser>,
Single<RustcAllocatorZeroedVariantParser>,
Single<RustcBuiltinMacroParser>,
Single<RustcForceInlineParser>,
Single<RustcLayoutScalarValidRangeEndParser>,
@ -274,7 +279,10 @@ attribute_parsers!(
Single<WithoutArgs<ProcMacroAttributeParser>>,
Single<WithoutArgs<ProcMacroParser>>,
Single<WithoutArgs<PubTransparentParser>>,
Single<WithoutArgs<RustcAllocatorParser>>,
Single<WithoutArgs<RustcAllocatorZeroedParser>>,
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
Single<WithoutArgs<RustcDeallocatorParser>>,
Single<WithoutArgs<RustcDumpDefParents>>,
Single<WithoutArgs<RustcDumpItemBounds>>,
Single<WithoutArgs<RustcDumpPredicates>>,
@ -289,6 +297,7 @@ attribute_parsers!(
Single<WithoutArgs<RustcNeverReturnsNullPointerParser>>,
Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
Single<WithoutArgs<RustcReallocatorParser>>,
Single<WithoutArgs<RustcShouldNotBeCalledOnConstItems>>,
Single<WithoutArgs<SpecializationTraitParser>>,
Single<WithoutArgs<StdInternalSymbolParser>>,

View file

@ -1,6 +1,7 @@
//! Set and unset common attributes on LLVM values.
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr, RtsanSetting};
use rustc_hir::def_id::DefId;
use rustc_hir::find_attr;
use rustc_middle::middle::codegen_fn_attrs::{
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, SanitizerFnAttrs,
};
@ -470,9 +471,7 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
{
to_add.push(create_alloc_family_attr(cx.llcx));
if let Some(instance) = instance
&& let Some(zv) =
tcx.get_attr(instance.def_id(), rustc_span::sym::rustc_allocator_zeroed_variant)
&& let Some(name) = zv.value_str()
&& let Some(name) = find_attr!(tcx.get_all_attrs(instance.def_id()), rustc_hir::attrs::AttributeKind::RustcAllocatorZeroedVariant {name} => name)
{
to_add.push(llvm::CreateAttrStringValue(
cx.llcx,

View file

@ -335,6 +335,18 @@ fn process_builtin_attrs(
AttributeKind::InstructionSet(instruction_set) => {
codegen_fn_attrs.instruction_set = Some(*instruction_set)
}
AttributeKind::RustcAllocator => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR
}
AttributeKind::RustcDeallocator => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR
}
AttributeKind::RustcReallocator => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR
}
AttributeKind::RustcAllocatorZeroed => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
}
_ => {}
}
}
@ -344,13 +356,7 @@ fn process_builtin_attrs(
};
match name {
sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR,
sym::rustc_nounwind => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND,
sym::rustc_reallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR,
sym::rustc_deallocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR,
sym::rustc_allocator_zeroed => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
}
sym::patchable_function_entry => {
codegen_fn_attrs.patchable_function_entry =
parse_patchable_function_entry(tcx, attr);

View file

@ -909,12 +909,24 @@ pub enum AttributeKind {
/// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
/// Represents `#[rustc_allocator]`
RustcAllocator,
/// Represents `#[rustc_allocator_zeroed]`
RustcAllocatorZeroed,
/// Represents `#[rustc_allocator_zeroed_variant]`
RustcAllocatorZeroedVariant { name: Symbol },
/// Represents `#[rustc_builtin_macro]`.
RustcBuiltinMacro { builtin_name: Option<Symbol>, helper_attrs: ThinVec<Symbol>, span: Span },
/// Represents `#[rustc_coherence_is_core]`
RustcCoherenceIsCore(Span),
/// Represents `#[rustc_deallocator]`
RustcDeallocator,
/// Represents `#[rustc_dump_def_parents]`
RustcDumpDefParents,
@ -975,6 +987,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]`
RustcPassIndirectlyInNonRusticAbis(Span),
/// Represents `#[rustc_reallocator]`
RustcReallocator,
/// Represents `#[rustc_scalable_vector(N)]`
RustcScalableVector {
/// The base multiple of lanes that are in a scalable vector, if provided. `element_count`

View file

@ -98,8 +98,12 @@ impl AttributeKind {
PubTransparent(..) => Yes,
RecursionLimit { .. } => No,
Repr { .. } => No,
RustcAllocator => No,
RustcAllocatorZeroed => No,
RustcAllocatorZeroedVariant { .. } => Yes,
RustcBuiltinMacro { .. } => Yes,
RustcCoherenceIsCore(..) => No,
RustcDeallocator => No,
RustcDumpDefParents => No,
RustcDumpItemBounds => No,
RustcDumpPredicates => No,
@ -120,6 +124,7 @@ impl AttributeKind {
RustcNoImplicitAutorefs => Yes,
RustcObjectLifetimeDefault => No,
RustcPassIndirectlyInNonRusticAbis(..) => No,
RustcReallocator => No,
RustcScalableVector { .. } => Yes,
RustcShouldNotBeCalledOnConstItems(..) => Yes,
RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate

View file

@ -317,6 +317,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::RustcDumpDefParents
| AttributeKind::RustcDumpVtable(..)
| AttributeKind::NeedsAllocator
| AttributeKind::RustcAllocator
| AttributeKind::RustcAllocatorZeroed
| AttributeKind::RustcAllocatorZeroedVariant { .. }
| AttributeKind::RustcDeallocator
| AttributeKind::RustcReallocator
) => { /* do nothing */ }
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
@ -361,12 +366,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::rustc_do_not_const_check
| sym::rustc_reservation_impl
| sym::rustc_doc_primitive
| sym::rustc_allocator
| sym::rustc_deallocator
| sym::rustc_reallocator
| sym::rustc_conversion_suggestion
| sym::rustc_allocator_zeroed
| sym::rustc_allocator_zeroed_variant
| sym::rustc_deprecated_safe_2024
| sym::rustc_test_marker
| sym::rustc_abi

View file

@ -49,7 +49,7 @@ impl Thread {
// WASI does not support threading via pthreads. While wasi-libc provides
// pthread stubs, pthread_create returns EAGAIN, which causes confusing
// errors. We return UNSUPPORTED_PLATFORM directly instead.
if cfg!(target_os = "wasi") {
if cfg!(all(target_os = "wasi", not(target_feature = "atomics"))) {
return Err(io::Error::UNSUPPORTED_PLATFORM);
}

View file

@ -1,3 +1,5 @@
//! regression test for <https://github.com/rust-lang/rust/issues/38919>
fn foo<T: Iterator>() {
T::Item; //~ ERROR no associated item named `Item` found
}

View file

@ -1,5 +1,5 @@
error[E0599]: no associated item named `Item` found for type parameter `T` in the current scope
--> $DIR/issue-38919.rs:2:8
--> $DIR/associated-type-as-value.rs:4:8
|
LL | fn foo<T: Iterator>() {
| - associated item `Item` not found for this type parameter

View file

@ -1,3 +1,5 @@
//! regression test for <https://github.com/rust-lang/rust/issues/17441>
fn main() {
let _foo = &[1_usize, 2] as [usize];
//~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]`

View file

@ -1,5 +1,5 @@
error[E0620]: cast to unsized type: `&[usize; 2]` as `[usize]`
--> $DIR/issue-17441.rs:2:16
--> $DIR/cast-to-unsized-type.rs:4:16
|
LL | let _foo = &[1_usize, 2] as [usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^
@ -10,7 +10,7 @@ LL | let _foo = &[1_usize, 2] as &[usize];
| +
error[E0620]: cast to unsized type: `Box<usize>` as `dyn Debug`
--> $DIR/issue-17441.rs:5:16
--> $DIR/cast-to-unsized-type.rs:7:16
|
LL | let _bar = Box::new(1_usize) as dyn std::fmt::Debug;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -21,25 +21,25 @@ LL | let _bar = Box::new(1_usize) as Box<dyn std::fmt::Debug>;
| ++++ +
error[E0620]: cast to unsized type: `usize` as `dyn Debug`
--> $DIR/issue-17441.rs:8:16
--> $DIR/cast-to-unsized-type.rs:10:16
|
LL | let _baz = 1_usize as dyn std::fmt::Debug;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider using a box or reference as appropriate
--> $DIR/issue-17441.rs:8:16
--> $DIR/cast-to-unsized-type.rs:10:16
|
LL | let _baz = 1_usize as dyn std::fmt::Debug;
| ^^^^^^^
error[E0620]: cast to unsized type: `[usize; 2]` as `[usize]`
--> $DIR/issue-17441.rs:11:17
--> $DIR/cast-to-unsized-type.rs:13:17
|
LL | let _quux = [1_usize, 2] as [usize];
| ^^^^^^^^^^^^^^^^^^^^^^^
|
help: consider using a box or reference as appropriate
--> $DIR/issue-17441.rs:11:17
--> $DIR/cast-to-unsized-type.rs:13:17
|
LL | let _quux = [1_usize, 2] as [usize];
| ^^^^^^^^^^^^

View file

@ -1,3 +1,5 @@
//! regression test for <https://github.com/rust-lang/rust/issues/2995>
fn bad (p: *const isize) {
let _q: &isize = p as &isize; //~ ERROR non-primitive cast
}

View file

@ -1,5 +1,5 @@
error[E0605]: non-primitive cast: `*const isize` as `&isize`
--> $DIR/issue-2995.rs:2:22
--> $DIR/non-primitive-isize-ref-cast.rs:4:22
|
LL | let _q: &isize = p as &isize;
| ^^^^^^^^^^^ invalid cast

View file

@ -1,3 +1,5 @@
//! regression test for <https://github.com/rust-lang/rust/issues/19922>
enum Homura {
Akemi { madoka: () }
}

View file

@ -1,5 +1,5 @@
error[E0559]: variant `Homura::Akemi` has no field named `kaname`
--> $DIR/issue-19922.rs:6:34
--> $DIR/enum-nonexisting-field.rs:8:34
|
LL | let homura = Homura::Akemi { kaname: () };
| ^^^^^^ `Homura::Akemi` does not have this field

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/17351>
//@ run-pass
trait Str { fn foo(&self) {} } //~ WARN method `foo` is never used

View file

@ -1,5 +1,5 @@
warning: method `foo` is never used
--> $DIR/issue-17351.rs:3:16
--> $DIR/unused-trait-fn.rs:4:16
|
LL | trait Str { fn foo(&self) {} }
| --- ^^^

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/22599>
#![deny(unused_variables)]
fn f(_: i32) {}

View file

@ -1,11 +1,11 @@
error: unused variable: `a`
--> $DIR/issue-22599.rs:8:19
--> $DIR/unused-var-in-match-arm.rs:9:19
|
LL | v = match 0 { a => 0 };
| ^ help: if this is intentional, prefix it with an underscore: `_a`
|
note: the lint level is defined here
--> $DIR/issue-22599.rs:1:9
--> $DIR/unused-var-in-match-arm.rs:2:9
|
LL | #![deny(unused_variables)]
| ^^^^^^^^^^^^^^^^

View file

@ -1,3 +1,5 @@
//! regression test for <https://github.com/rust-lang/rust/issues/19692>
struct Homura;
fn akemi(homura: Homura) {

View file

@ -1,5 +1,5 @@
error[E0599]: no method named `kaname` found for struct `Homura` in the current scope
--> $DIR/issue-19692.rs:4:40
--> $DIR/method-not-found-on-struct.rs:6:40
|
LL | struct Homura;
| ------------- method `kaname` not found for this struct

View file

@ -1,3 +1,5 @@
//! regression test for <https://github.com/rust-lang/rust/issues/34209>
enum S {
A,
}

View file

@ -1,5 +1,5 @@
error[E0599]: no variant named `B` found for enum `S`
--> $DIR/issue-34209.rs:7:12
--> $DIR/enum-variant-not-found.rs:9:12
|
LL | enum S {
| ------ variant `B` not found here

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/16745>
//@ run-pass
fn main() {
const X: u8 = 0;

View file

@ -1,3 +1,5 @@
//! auxiliary crate for <https://github.com/rust-lang/rust/issues/11680>
enum Foo {
Bar(isize)
}

View file

@ -1,6 +1,7 @@
//@ aux-build:issue-11680.rs
//! regression test for <https://github.com/rust-lang/rust/issues/11680>
//@ aux-build:imported-enum-is-private.rs
extern crate issue_11680 as other;
extern crate imported_enum_is_private as other;
fn main() {
let _b = other::Foo::Bar(1);

View file

@ -1,5 +1,5 @@
error[E0603]: enum `Foo` is private
--> $DIR/issue-11680.rs:6:21
--> $DIR/imported-enum-is-private.rs:7:21
|
LL | let _b = other::Foo::Bar(1);
| ^^^ --- tuple variant `Bar` is not publicly re-exported
@ -7,13 +7,13 @@ LL | let _b = other::Foo::Bar(1);
| private enum
|
note: the enum `Foo` is defined here
--> $DIR/auxiliary/issue-11680.rs:1:1
--> $DIR/auxiliary/imported-enum-is-private.rs:3:1
|
LL | enum Foo {
| ^^^^^^^^
error[E0603]: enum `Foo` is private
--> $DIR/issue-11680.rs:9:27
--> $DIR/imported-enum-is-private.rs:10:27
|
LL | let _b = other::test::Foo::Bar(1);
| ^^^ --- tuple variant `Bar` is not publicly re-exported
@ -21,7 +21,7 @@ LL | let _b = other::test::Foo::Bar(1);
| private enum
|
note: the enum `Foo` is defined here
--> $DIR/auxiliary/issue-11680.rs:6:5
--> $DIR/auxiliary/imported-enum-is-private.rs:8:5
|
LL | enum Foo {
| ^^^^^^^^

View file

@ -1,3 +1,5 @@
//! regression test for <https://github.com/rust-lang/rust/issues/26472>
mod sub {
pub struct S { len: usize }
impl S {

View file

@ -1,5 +1,5 @@
error[E0616]: field `len` of struct `S` is private
--> $DIR/issue-26472.rs:11:15
--> $DIR/private-struct-field-in-module.rs:13:15
|
LL | let v = s.len;
| ^^^ private field
@ -10,7 +10,7 @@ LL | let v = s.len();
| ++
error[E0616]: field `len` of struct `S` is private
--> $DIR/issue-26472.rs:12:7
--> $DIR/private-struct-field-in-module.rs:14:7
|
LL | s.len = v;
| ^^^ private field

View file

@ -1,3 +1,4 @@
//! regression test for <https://github.com/rust-lang/rust/issues/16966>
//@ edition:2015..2021
fn main() {
panic!(std::default::Default::default());

View file

@ -1,5 +1,5 @@
error[E0283]: type annotations needed
--> $DIR/issue-16966.rs:3:12
--> $DIR/panic-with-unspecified-type.rs:4:12
|
LL | panic!(std::default::Default::default());
| -------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-

View file

@ -1,3 +1,5 @@
//! regression test for <https://github.com/rust-lang/rust/issues/25368>
use std::sync::mpsc::channel;
use std::thread::spawn;
use std::marker::PhantomData;

View file

@ -1,5 +1,5 @@
error[E0282]: type annotations needed
--> $DIR/issue-25368.rs:11:27
--> $DIR/send-with-unspecified-type.rs:13:27
|
LL | tx.send(Foo{ foo: PhantomData });
| ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `PhantomData`

View file

@ -1,3 +1,5 @@
//! regression test for <https://github.com/rust-lang/rust/issues/24013>
fn main() {
use std::mem::{transmute, swap};
let a = 1;

View file

@ -1,5 +1,5 @@
error[E0282]: type annotations needed
--> $DIR/issue-24013.rs:5:13
--> $DIR/swap-with-unspecified-type.rs:7:13
|
LL | unsafe {swap::<&mut _>(transmute(&a), transmute(&b))};
| ^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `swap`

View file

@ -1,3 +1,5 @@
//! regression test for <https://github.com/rust-lang/rust/issues/35241>
struct Foo(u32);
fn test() -> Foo { Foo } //~ ERROR mismatched types

View file

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/issue-35241.rs:3:20
--> $DIR/struct-constructor-as-value.rs:5:20
|
LL | struct Foo(u32);
| ---------- `Foo` defines a struct constructor here, which should be called