Auto merge of #143645 - matthiaskrgr:rollup-d2a3leo, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang/rust#143402 (Port several linking (linkage?) related attributes the new attribute system )
 - rust-lang/rust#143555 (Don't mark `#[target_feature]` safe fns as unsafe in rustdoc JSON.)
 - rust-lang/rust#143593 (Port #[rustc_dummy])
 - rust-lang/rust#143600 (Update intro blurb in `wasm32-wasip1` docs)
 - rust-lang/rust#143603 (Clarify the meaning of `AttributeOrder::KeepFirst` and `AttributeOrder::KeepLast`)
 - rust-lang/rust#143620 (fix: Remove newline from multiple crate versions note)
 - rust-lang/rust#143622 (Add target maintainer information for mips64-unknown-linux-muslabi64)

Failed merges:

 - rust-lang/rust#143403 (Port several trait/coherence-related attributes the new attribute system)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-07-08 17:31:40 +00:00
commit ab68b0fb26
18 changed files with 266 additions and 68 deletions

View file

@ -240,6 +240,9 @@ pub enum AttributeKind {
/// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol },
/// Represents `#[rustc_dummy]`.
Dummy,
/// Represents [`#[export_name]`](https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute).
ExportName {
/// The name to export this item with.
@ -248,6 +251,15 @@ pub enum AttributeKind {
span: Span,
},
/// Represents `#[export_stable]`.
ExportStable,
/// Represents `#[ffi_const]`.
FfiConst(Span),
/// Represents `#[ffi_pure]`.
FfiPure(Span),
/// Represents `#[ignore]`
Ignore {
span: Span,
@ -326,6 +338,9 @@ pub enum AttributeKind {
span: Span,
},
/// Represents `#[rustc_std_internal_symbol]`.
StdInternalSymbol(Span),
/// Represents `#[target_feature(enable = "...")]`
TargetFeature(ThinVec<(Symbol, Span)>, Span),

View file

@ -25,7 +25,11 @@ impl AttributeKind {
ConstStabilityIndirect => No,
Deprecation { .. } => Yes,
DocComment { .. } => Yes,
Dummy => No,
ExportName { .. } => Yes,
ExportStable => No,
FfiConst(..) => No,
FfiPure(..) => No,
Ignore { .. } => No,
Inline(..) => No,
LinkName { .. } => Yes,
@ -48,6 +52,7 @@ impl AttributeKind {
RustcObjectLifetimeDefault => No,
SkipDuringMethodDispatch { .. } => No,
Stability { .. } => Yes,
StdInternalSymbol(..) => No,
TargetFeature(..) => No,
TrackCaller(..) => Yes,
Used { .. } => No,

View file

@ -0,0 +1,19 @@
use rustc_attr_data_structures::AttributeKind;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Symbol, sym};
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
pub(crate) struct DummyParser;
impl<S: Stage> SingleAttributeParser<S> for DummyParser {
const PATH: &[Symbol] = &[sym::rustc_dummy];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really
fn convert(_: &mut AcceptContext<'_, '_, S>, _: &ArgParser<'_>) -> Option<AttributeKind> {
Some(AttributeKind::Dummy)
}
}

View file

@ -1,9 +1,11 @@
use rustc_attr_data_structures::AttributeKind;
use rustc_attr_data_structures::AttributeKind::{LinkName, LinkSection};
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Symbol, sym};
use rustc_span::{Span, Symbol, sym};
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics::NullOnLinkSection;
@ -57,3 +59,31 @@ impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
Some(LinkSection { name, span: cx.attr_span })
}
}
pub(crate) struct ExportStableParser;
impl<S: Stage> NoArgsAttributeParser<S> for ExportStableParser {
const PATH: &[Symbol] = &[sym::export_stable];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ExportStable;
}
pub(crate) struct FfiConstParser;
impl<S: Stage> NoArgsAttributeParser<S> for FfiConstParser {
const PATH: &[Symbol] = &[sym::ffi_const];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiConst;
}
pub(crate) struct FfiPureParser;
impl<S: Stage> NoArgsAttributeParser<S> for FfiPureParser {
const PATH: &[Symbol] = &[sym::ffi_pure];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;
}
pub(crate) struct StdInternalSymbolParser;
impl<S: Stage> NoArgsAttributeParser<S> for StdInternalSymbolParser {
const PATH: &[Symbol] = &[sym::rustc_std_internal_symbol];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::StdInternalSymbol;
}

View file

@ -30,6 +30,7 @@ pub(crate) mod cfg;
pub(crate) mod codegen_attrs;
pub(crate) mod confusables;
pub(crate) mod deprecation;
pub(crate) mod dummy;
pub(crate) mod inline;
pub(crate) mod link_attrs;
pub(crate) mod lint_helpers;
@ -217,7 +218,14 @@ impl<S: Stage> OnDuplicate<S> {
// them will be merged in another PR
#[allow(unused)]
pub(crate) enum AttributeOrder {
/// Duplicates after the first attribute will be an error.
/// Duplicates after the first attribute will be an error. I.e. only keep the lowest attribute.
///
/// Attributes are processed from bottom to top, so this raises an error on all the attributes
/// further above the lowest one:
/// ```
/// #[stable(since="1.0")] //~ WARNING duplicated attribute
/// #[stable(since="2.0")]
/// ```
///
/// This should be used where duplicates would be ignored, but carry extra
/// meaning that could cause confusion. For example, `#[stable(since="1.0")]
@ -227,6 +235,13 @@ pub(crate) enum AttributeOrder {
/// Duplicates preceding the last instance of the attribute will be a
/// warning, with a note that this will be an error in the future.
///
/// Attributes are processed from bottom to top, so this raises a warning on all the attributes
/// below the higher one:
/// ```
/// #[path="foo.rs"]
/// #[path="bar.rs"] //~ WARNING duplicated attribute
/// ```
///
/// This is the same as `FutureWarnFollowing`, except the last attribute is
/// the one that is "used". Ideally these can eventually migrate to
/// `ErrorPreceding`.

View file

@ -21,8 +21,12 @@ use crate::attributes::codegen_attrs::{
};
use crate::attributes::confusables::ConfusablesParser;
use crate::attributes::deprecation::DeprecationParser;
use crate::attributes::dummy::DummyParser;
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
use crate::attributes::link_attrs::{LinkNameParser, LinkSectionParser};
use crate::attributes::link_attrs::{
ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkSectionParser,
StdInternalSymbolParser,
};
use crate::attributes::lint_helpers::{AsPtrParser, PassByValueParser, PubTransparentParser};
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
use crate::attributes::must_use::MustUseParser;
@ -127,6 +131,7 @@ attribute_parsers!(
// tidy-alphabetical-start
Single<DeprecationParser>,
Single<DummyParser>,
Single<ExportNameParser>,
Single<IgnoreParser>,
Single<InlineParser>,
@ -145,6 +150,9 @@ attribute_parsers!(
Single<WithoutArgs<ColdParser>>,
Single<WithoutArgs<ConstContinueParser>>,
Single<WithoutArgs<ConstStabilityIndirectParser>>,
Single<WithoutArgs<ExportStableParser>>,
Single<WithoutArgs<FfiConstParser>>,
Single<WithoutArgs<FfiPureParser>>,
Single<WithoutArgs<LoopMatchParser>>,
Single<WithoutArgs<MayDangleParser>>,
Single<WithoutArgs<NoImplicitPreludeParser>>,
@ -152,6 +160,7 @@ attribute_parsers!(
Single<WithoutArgs<NonExhaustiveParser>>,
Single<WithoutArgs<PassByValueParser>>,
Single<WithoutArgs<PubTransparentParser>>,
Single<WithoutArgs<StdInternalSymbolParser>>,
Single<WithoutArgs<TrackCallerParser>>,
// tidy-alphabetical-end
];

View file

@ -203,6 +203,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
UsedBy::Compiler => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER,
UsedBy::Linker => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER,
},
AttributeKind::FfiConst(_) => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST
}
AttributeKind::FfiPure(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE,
AttributeKind::StdInternalSymbol(_) => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
}
_ => {}
}
}
@ -213,17 +220,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
match name {
sym::rustc_allocator => codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR,
sym::ffi_pure => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE,
sym::ffi_const => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST,
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::rustc_std_internal_symbol => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
}
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
sym::linkage => {
if let Some(val) = attr.value_str() {

View file

@ -271,6 +271,10 @@ pub fn check_builtin_meta_item(
if matches!(
name,
sym::inline
| sym::export_stable
| sym::ffi_const
| sym::ffi_pure
| sym::rustc_std_internal_symbol
| sym::may_dangle
| sym::rustc_as_ptr
| sym::rustc_pub_transparent

View file

@ -204,10 +204,20 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::RustcLayoutScalarValidRangeStart(_num, attr_span)
| AttributeKind::RustcLayoutScalarValidRangeEnd(_num, attr_span),
) => self.check_rustc_layout_scalar_valid_range(*attr_span, span, target),
Attribute::Parsed(AttributeKind::ExportStable) => {
// handled in `check_export`
}
&Attribute::Parsed(AttributeKind::FfiConst(attr_span)) => {
self.check_ffi_const(attr_span, target)
}
&Attribute::Parsed(AttributeKind::FfiPure(attr_span)) => {
self.check_ffi_pure(attr_span, attrs, target)
}
Attribute::Parsed(
AttributeKind::BodyStability { .. }
| AttributeKind::ConstStabilityIndirect
| AttributeKind::MacroTransparency(_),
| AttributeKind::MacroTransparency(_)
| AttributeKind::Dummy,
) => { /* do nothing */ }
Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => {
self.check_applied_to_fn_or_method(hir_id, *attr_span, span, target)
@ -233,6 +243,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
&Attribute::Parsed(AttributeKind::PassByValue(attr_span)) => {
self.check_pass_by_value(attr_span, span, target)
}
&Attribute::Parsed(AttributeKind::StdInternalSymbol(attr_span)) => {
self.check_rustc_std_internal_symbol(attr_span, span, target)
}
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
match attr.path().as_slice() {
@ -258,9 +271,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
),
[sym::no_link, ..] => self.check_no_link(hir_id, attr, span, target),
[sym::debugger_visualizer, ..] => self.check_debugger_visualizer(attr, target),
[sym::rustc_std_internal_symbol, ..] => {
self.check_rustc_std_internal_symbol(attr, span, target)
}
[sym::rustc_no_implicit_autorefs, ..] => {
self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target)
}
@ -300,8 +310,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::rustc_has_incoherent_inherent_impls, ..] => {
self.check_has_incoherent_inherent_impls(attr, span, target)
}
[sym::ffi_pure, ..] => self.check_ffi_pure(attr.span(), attrs, target),
[sym::ffi_const, ..] => self.check_ffi_const(attr.span(), target),
[sym::link_ordinal, ..] => self.check_link_ordinal(attr, span, target),
[sym::link, ..] => self.check_link(hir_id, attr, span, target),
[sym::macro_use, ..] | [sym::macro_escape, ..] => {
@ -346,7 +354,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::cfg_attr
| sym::cfg_trace
| sym::cfg_attr_trace
| sym::export_stable // handled in `check_export`
// need to be fixed
| sym::cfi_encoding // FIXME(cfi_encoding)
| sym::pointee // FIXME(derive_coerce_pointee)
@ -1507,7 +1514,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.dcx().emit_err(errors::FfiPureInvalidTarget { attr_span });
return;
}
if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
if find_attr!(attrs, AttributeKind::FfiConst(_)) {
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
self.dcx().emit_err(errors::BothFfiConstAndPure { attr_span });
}
@ -2214,13 +2221,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_rustc_std_internal_symbol(&self, attr: &Attribute, span: Span, target: Target) {
fn check_rustc_std_internal_symbol(&self, attr_span: Span, span: Span, target: Target) {
match target {
Target::Fn | Target::Static | Target::ForeignFn | Target::ForeignStatic => {}
_ => {
self.tcx
.dcx()
.emit_err(errors::RustcStdInternalSymbol { attr_span: attr.span(), span });
self.tcx.dcx().emit_err(errors::RustcStdInternalSymbol { attr_span, span });
}
}
}

View file

@ -2,6 +2,7 @@ use std::iter;
use std::ops::ControlFlow;
use rustc_abi::ExternAbi;
use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
@ -14,7 +15,7 @@ use rustc_middle::ty::{
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, Visibility,
};
use rustc_session::config::CrateType;
use rustc_span::{Span, sym};
use rustc_span::Span;
use crate::errors::UnexportableItem;
@ -44,7 +45,7 @@ impl<'tcx> ExportableItemCollector<'tcx> {
}
fn item_is_exportable(&self, def_id: LocalDefId) -> bool {
let has_attr = self.tcx.has_attr(def_id, sym::export_stable);
let has_attr = find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::ExportStable);
if !self.in_exportable_mod && !has_attr {
return false;
}
@ -80,7 +81,7 @@ impl<'tcx> ExportableItemCollector<'tcx> {
fn walk_item_with_mod(&mut self, item: &'tcx hir::Item<'tcx>) {
let def_id = item.hir_id().owner.def_id;
let old_exportable_mod = self.in_exportable_mod;
if self.tcx.get_attr(def_id, sym::export_stable).is_some() {
if find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::ExportStable) {
self.in_exportable_mod = true;
}
let old_seen_exportable_in_mod = std::mem::replace(&mut self.seen_exportable_in_mod, false);

View file

@ -1933,7 +1933,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
StringPart::highlighted("multiple different versions".to_string()),
StringPart::normal(" of crate `".to_string()),
StringPart::highlighted(format!("{crate_name}")),
StringPart::normal("` in the dependency graph\n".to_string()),
StringPart::normal("` in the dependency graph".to_string()),
],
);
if points_at_type {

View file

@ -83,6 +83,7 @@
- [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)
- [m68k-unknown-none-elf](platform-support/m68k-unknown-none-elf.md)
- [mips64-openwrt-linux-musl](platform-support/mips64-openwrt-linux-musl.md)
- [mips64-unknown-linux-muslabi64](platform-support/mips64-unknown-linux-muslabi64.md)
- [mipsel-sony-psx](platform-support/mipsel-sony-psx.md)
- [mipsel-unknown-linux-gnu](platform-support/mipsel-unknown-linux-gnu.md)
- [mips\*-mti-none-elf](platform-support/mips-mti-none-elf.md)

View file

@ -333,7 +333,7 @@ target | std | host | notes
`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc
[`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? | | MIPS64 for OpenWrt Linux musl 1.2.3
`mips64-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 Linux, N64 ABI (kernel 4.4, glibc 2.23)
`mips64-unknown-linux-muslabi64` | ✓ | | MIPS64 Linux, N64 ABI, musl 1.2.3
[`mips64-unknown-linux-muslabi64`](platform-support/mips64-unknown-linux-muslabi64.md) | ✓ | ✓ | MIPS64 Linux, N64 ABI, musl 1.2.3
`mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 (little endian) Linux, N64 ABI (kernel 4.4, glibc 2.23)
`mips64el-unknown-linux-muslabi64` | ✓ | | MIPS64 (little endian) Linux, N64 ABI, musl 1.2.3
`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP)

View file

@ -0,0 +1,49 @@
# mips64-unknown-linux-muslabi64
**Tier: 3**
Target for 64-bit big endian MIPS Linux programs using musl libc and the N64 ABI.
## Target maintainers
[@Gelbpunkt](https://github.com/Gelbpunkt)
## Requirements
Building the target itself requires a 64-bit big endian MIPS compiler that is
supported by `cc-rs`.
## Building the target
The target can be built by enabling it for a `rustc` build.
```toml
[build]
target = ["mips64-unknown-linux-muslabi64"]
```
Make sure your C compiler is included in `$PATH`, then add it to the
`bootstrap.toml`:
```toml
[target.mips64-unknown-linux-muslabi64]
cc = "mips64-linux-musl-gcc"
cxx = "mips64-linux-musl-g++"
ar = "mips64-linux-musl-ar"
linker = "mips64-linux-musl-gcc"
```
## Building Rust programs
Rust does not yet ship pre-compiled artifacts for this target. To compile for
this target, you will first need to build Rust with the target enabled (see
"Building the target" above).
## Cross-compilation
This target can be cross-compiled from any host.
## Testing
This target can be tested as normal with `x.py` on a 64-bit big endian MIPS
host or via QEMU emulation.

View file

@ -4,37 +4,35 @@
The `wasm32-wasip1` target is a WebAssembly compilation target which
assumes that the [WASIp1] (aka "WASI preview1") set of "syscalls" are available
for use in the standard library. Historically this target in the Rust compiler
was one of the first for WebAssembly where Rust and C code are explicitly
intended to interoperate as well.
for use in the standard library. This target explicitly supports interop with
non-Rust code such as C and C++.
There's a bit of history to the target and current development which is also
worth explaining before going much further. Historically this target was
originally called `wasm32-wasi` in both rustc and Clang. This was first added
to Rust in 2019. In the intervening years leading up to 2024 the WASI standard
continued to be developed and was eventually "rebased" on top of the [Component
Model]. This was a large change to the WASI specification and was released as
0.2.0 ("WASIp2" colloquially) in January 2024. The previous target's name in
rustc, `wasm32-wasi`, was then renamed to `wasm32-wasip1`, to avoid
confusion with this new target to be added to rustc as `wasm32-wasip2`.
Some more context can be found in these MCPs:
The [WASIp1] set of syscalls is standard insofar as it was written down once by
a set of folks and has not changed since then. Additionally the [WASIp1]
syscalls have been adapted and adopted into a number of runtimes and embeddings.
It is not standard in the sense that there are no formal semantics for each
syscall and APIs are no longer receiving any maintenance (e.g. no new APIs, no
new documentation, etc). After [WASIp1] was originally developed in 2019 the
WASI standard effort has since been "rebased" on top of the [Component Model].
This was a large change to the WASI specification and was released as 0.2.0
("WASIp2" colloquially) in January 2024. Current standardization efforts are
focused on the Component Model-based definition of WASI. At this point the
`wasm32-wasip1` Rust target is intended for historical compatibility with
[WASIp1] set of syscalls.
* [Rename wasm32-wasi target to wasm32-wasip1](https://github.com/rust-lang/compiler-team/issues/607)
* [Smooth the renaming transition of wasm32-wasi](https://github.com/rust-lang/compiler-team/issues/695)
At this point the `wasm32-wasip1` target is intended for historical
compatibility with the first version of the WASI standard. As of now (January
2024) the 0.2.0 target of WASI ("WASIp2") is relatively new. The state of
WASI will likely change in few years after which point this documentation will
probably receive another update.
[WASI Preview1]: https://github.com/WebAssembly/WASI/tree/main/legacy/preview1
[WASIp1]: https://github.com/WebAssembly/WASI/tree/main/legacy/preview1
[Component Model]: https://github.com/webassembly/component-model
Today the `wasm32-wasip1` target will generate core WebAssembly modules
which will import functions from the `wasi_snapshot_preview1` module for
OS-related functionality (e.g. printing).
> **Note**: Prior to March 2024 this target was known as `wasm32-wasi` with some
> historical context found in old MCPs:
>
> * [Rename wasm32-wasi target to wasm32-wasip1](https://github.com/rust-lang/compiler-team/issues/607)
> * [Smooth the renaming transition of wasm32-wasi](https://github.com/rust-lang/compiler-team/issues/695)
## Target maintainers
When this target was added to the compiler platform-specific documentation here

View file

@ -7,6 +7,7 @@ use rustc_ast::ast;
use rustc_attr_data_structures::{self as attrs, DeprecatedSince};
use rustc_hir::def::CtorKind;
use rustc_hir::def_id::DefId;
use rustc_hir::{HeaderSafety, Safety};
use rustc_metadata::rendered_const;
use rustc_middle::{bug, ty};
use rustc_span::{Pos, kw, sym};
@ -381,10 +382,22 @@ impl FromClean<clean::Union> for Union {
impl FromClean<rustc_hir::FnHeader> for FunctionHeader {
fn from_clean(header: &rustc_hir::FnHeader, renderer: &JsonRenderer<'_>) -> Self {
let is_unsafe = match header.safety {
HeaderSafety::SafeTargetFeatures => {
// The type system's internal implementation details consider
// safe functions with the `#[target_feature]` attribute to be analogous
// to unsafe functions: `header.is_unsafe()` returns `true` for them.
// For rustdoc, this isn't the right decision, so we explicitly return `false`.
// Context: https://github.com/rust-lang/rust/issues/142655
false
}
HeaderSafety::Normal(Safety::Safe) => false,
HeaderSafety::Normal(Safety::Unsafe) => true,
};
FunctionHeader {
is_async: header.is_async(),
is_const: header.is_const(),
is_unsafe: header.is_unsafe(),
is_unsafe,
abi: header.abi.into_json(renderer),
}
}

View file

@ -1,17 +1,40 @@
//@ only-x86_64
//@ is "$.index[?(@.name=='test1')].attrs" '["#[target_feature(enable=\"avx\")]"]'
//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
#[target_feature(enable = "avx")]
pub fn test1() {}
//@ is "$.index[?(@.name=='test2')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\")]"]'
//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
#[target_feature(enable = "avx,avx2")]
pub fn test2() {}
//@ is "$.index[?(@.name=='test3')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\")]"]'
//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
#[target_feature(enable = "avx", enable = "avx2")]
pub fn test3() {}
//@ is "$.index[?(@.name=='test4')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\", enable=\"avx512f\")]"]'
//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
#[target_feature(enable = "avx", enable = "avx2,avx512f")]
pub fn test4() {}
//@ is "$.index[?(@.name=='test_unsafe_fn')].attrs" '["#[target_feature(enable=\"avx\")]"]'
//@ is "$.index[?(@.name=='test_unsafe_fn')].inner.function.header.is_unsafe" true
#[target_feature(enable = "avx")]
pub unsafe fn test_unsafe_fn() {}
pub struct Example;
impl Example {
//@ is "$.index[?(@.name=='safe_assoc_fn')].attrs" '["#[target_feature(enable=\"avx\")]"]'
//@ is "$.index[?(@.name=='safe_assoc_fn')].inner.function.header.is_unsafe" false
#[target_feature(enable = "avx")]
pub fn safe_assoc_fn() {}
//@ is "$.index[?(@.name=='unsafe_assoc_fn')].attrs" '["#[target_feature(enable=\"avx\")]"]'
//@ is "$.index[?(@.name=='unsafe_assoc_fn')].inner.function.header.is_unsafe" true
#[target_feature(enable = "avx")]
pub unsafe fn unsafe_assoc_fn() {}
}

View file

@ -40,12 +40,6 @@ error: malformed `crate_name` attribute input
LL | #[crate_name]
| ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]`
error: malformed `export_stable` attribute input
--> $DIR/malformed-attrs.rs:81:1
|
LL | #[export_stable = 1]
| ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[export_stable]`
error: malformed `coverage` attribute input
--> $DIR/malformed-attrs.rs:90:1
|
@ -140,24 +134,12 @@ error: malformed `fundamental` attribute input
LL | #[fundamental()]
| ^^^^^^^^^^^^^^^^ help: must be of the form: `#[fundamental]`
error: malformed `ffi_pure` attribute input
--> $DIR/malformed-attrs.rs:165:5
|
LL | #[unsafe(ffi_pure = 1)]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[ffi_pure]`
error: malformed `link_ordinal` attribute input
--> $DIR/malformed-attrs.rs:167:5
|
LL | #[link_ordinal]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_ordinal(ordinal)]`
error: malformed `ffi_const` attribute input
--> $DIR/malformed-attrs.rs:171:5
|
LL | #[unsafe(ffi_const = 1)]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[ffi_const]`
error: malformed `linkage` attribute input
--> $DIR/malformed-attrs.rs:173:5
|
@ -481,6 +463,15 @@ LL | #[target_feature]
| expected this to be a list
| help: must be of the form: `#[target_feature(enable = "feat1, feat2")]`
error[E0565]: malformed `export_stable` attribute input
--> $DIR/malformed-attrs.rs:81:1
|
LL | #[export_stable = 1]
| ^^^^^^^^^^^^^^^^---^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[export_stable]`
error[E0539]: malformed `link_name` attribute input
--> $DIR/malformed-attrs.rs:86:1
|
@ -537,6 +528,24 @@ LL | #[rustc_layout_scalar_valid_range_end]
| expected this to be a list
| help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]`
error[E0565]: malformed `ffi_pure` attribute input
--> $DIR/malformed-attrs.rs:165:5
|
LL | #[unsafe(ffi_pure = 1)]
| ^^^^^^^^^^^^^^^^^^---^^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[ffi_pure]`
error[E0565]: malformed `ffi_const` attribute input
--> $DIR/malformed-attrs.rs:171:5
|
LL | #[unsafe(ffi_const = 1)]
| ^^^^^^^^^^^^^^^^^^^---^^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[ffi_const]`
error[E0565]: malformed `non_exhaustive` attribute input
--> $DIR/malformed-attrs.rs:197:1
|