Skip to content

Move logic for emitting UNSAFE_CODE for unsafe attributes to attr parsing - #157201

Merged
rust-bors[bot] merged 6 commits into
rust-lang:mainfrom
JonathanBrouwer:unsafe-code-attribute
Jun 13, 2026
Merged

Move logic for emitting UNSAFE_CODE for unsafe attributes to attr parsing#157201
rust-bors[bot] merged 6 commits into
rust-lang:mainfrom
JonathanBrouwer:unsafe-code-attribute

Conversation

@JonathanBrouwer

@JonathanBrouwer JonathanBrouwer commented May 31, 2026

Copy link
Copy Markdown
Member

View all comments

Fixes #131801

This moves the emitting of UNSAFE_CODE for unsafe attributes to attr parsing.
Because it is now implemented generically for all unsafe attributes, we don't have to manually list all attributes anymore, and we can't miss adding support for new unsafe attributes in the future.

This adds support for detecting UNSAFE_CODE for the following attributes:

  • #[naked] (stable attribute!)
  • #[ffi_pure]
  • #[ffi_const]
  • #[force_target_feature]

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 31, 2026
@JonathanBrouwer
JonathanBrouwer marked this pull request as ready for review May 31, 2026 15:02
@rustbot

rustbot commented May 31, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 31, 2026
@rustbot

rustbot commented May 31, 2026

Copy link
Copy Markdown
Collaborator

r? @mati865

rustbot has assigned @mati865.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 73 candidates
  • Random selection from 16 candidates

@JonathanBrouwer JonathanBrouwer added T-lang Relevant to the language team needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. I-lang-nominated Nominated for discussion during a lang team meeting. S-waiting-on-t-lang Status: Awaiting decision from T-lang labels May 31, 2026
@JonathanBrouwer

JonathanBrouwer commented May 31, 2026

Copy link
Copy Markdown
Member Author

@rustbot label +I-lang-nominated
@rust-lang/lang

Previously, the UNSAFE_CODE lint emitted a lint for the usage of the following unstable attributes:

  • #[no_mangle]
  • #[link_section]
  • #[export_name]

This PR extends the lint to emit a lint for all unsafe attributes, which adds the following currently unsafe attributes:

  • #[naked] (stable attribute!)
  • #[ffi_pure] (unstable attribute)
  • #[ffi_const] (unstable attribute)
  • #[force_target_feature] (unstable attribute)

@rust-lang rust-lang deleted a comment from rustbot May 31, 2026
@rust-log-analyzer

This comment has been minimized.

@traviscross traviscross added the P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang label May 31, 2026
@JonathanBrouwer
JonathanBrouwer force-pushed the unsafe-code-attribute branch from 810b455 to bd1b6d1 Compare May 31, 2026 15:42
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@JonathanBrouwer
JonathanBrouwer force-pushed the unsafe-code-attribute branch from bb9c4da to b79a79e Compare May 31, 2026 17:54
@traviscross traviscross added the waived-reference-pr This language change does not need a Reference PR. label May 31, 2026
@traviscross

Copy link
Copy Markdown
Contributor

Makes sense to me. Thanks @JonathanBrouwer for pushing this forward. I propose we do it:

@rfcbot fcp merge lang

One thing I'll mention is that we do use unsafe both to create and to discharge safety obligations. So far, all the unsafe attributes discharge obligations. If we both 1) ever wanted to create a safety obligation with an unsafe attribute and 2) rethink whether unsafe_code should apply to creating safety obligations (e.g., #148651, which we discussed without resolution in our meeting on 2026-01-14), then maybe this would need to get a bit more complicated. Not a problem today.

@rust-rfcbot

rust-rfcbot commented May 31, 2026

Copy link
Copy Markdown
Collaborator

Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns.
See this document for info about what commands tagged team members can give me.

@rust-rfcbot rust-rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels May 31, 2026
Comment thread compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs Outdated
Comment thread compiler/rustc_attr_parsing/src/attributes/mod.rs Outdated
@JonathanBrouwer
JonathanBrouwer force-pushed the unsafe-code-attribute branch from b79a79e to d7bad7f Compare June 1, 2026 05:59
@rust-bors

This comment has been minimized.

@rust-rfcbot rust-rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting labels Jun 13, 2026
@rust-rfcbot

Copy link
Copy Markdown
Collaborator

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

@JonathanBrouwer
JonathanBrouwer force-pushed the unsafe-code-attribute branch from d7bad7f to 5681079 Compare June 13, 2026 16:27
@rustbot

rustbot commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@JonathanBrouwer

Copy link
Copy Markdown
Member Author

@bors r=mati865 rollup

@rust-bors

rust-bors Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

📋 This PR cannot be approved because it currently has the following labels: proposed-final-comment-period, needs-fcp, S-waiting-on-t-lang.

@JonathanBrouwer JonathanBrouwer removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. S-waiting-on-t-lang Status: Awaiting decision from T-lang labels Jun 13, 2026
@JonathanBrouwer

Copy link
Copy Markdown
Member Author

@bors r=mati865 rollup

@rust-bors

rust-bors Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

📌 Commit 5681079 has been approved by mati865

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 13, 2026
@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job x86_64-gnu-tools failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
...............................F.................. (50/144)
.................................................. (100/144)
............................................       (144/144)

======== tests/rustdoc-gui/go-to-collapsed-elem.goml ========

[ERROR] line 40
    at `tests/rustdoc-gui/go-to-collapsed-elem.goml` line 21: Error: Node is detached from document: for command `click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"`
    at <file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/doc/test_docs/struct.Foo.html?search=t_use>


<= doc-ui tests done: 143 succeeded, 1 failed, 0 filtered out

Error: ()

@JonathanBrouwer

Copy link
Copy Markdown
Member Author

(spurious)

rust-bors Bot pushed a commit that referenced this pull request Jun 13, 2026
…uwer

Rollup of 3 pull requests

Successful merges:

 - #157201 (Move logic for emitting UNSAFE_CODE for unsafe attributes to attr parsing)
 - #157613 (Improve invalid cfg predicate error)
 - #157838 (rustdoc: Don't strip hidden items in `AliasedNonLocalStripper`)
@rust-bors
rust-bors Bot merged commit a20b9df into rust-lang:main Jun 13, 2026
9 of 13 checks passed
@rustbot rustbot added this to the 1.98.0 milestone Jun 13, 2026
rust-timer added a commit that referenced this pull request Jun 13, 2026
Rollup merge of #157201 - JonathanBrouwer:unsafe-code-attribute, r=mati865

Move logic for emitting UNSAFE_CODE for unsafe attributes to attr parsing

Fixes #131801

This moves the emitting of `UNSAFE_CODE` for unsafe attributes to attr parsing.
Because it is now implemented generically for all unsafe attributes, we don't have to manually list all attributes anymore, and we can't miss adding support for new unsafe attributes in the future.

This adds support for detecting `UNSAFE_CODE` for the following attributes:
* `#[naked]` **(stable attribute!)**
* `#[ffi_pure]`
* `#[ffi_const]`
* `#[force_target_feature]`
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Aug 21, 2026
This MR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [rust](https://github.com/rust-lang/rust) | tools | minor | `1.97.1` → `1.98.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>rust-lang/rust (rust)</summary>

### [`v1.98.0`](https://github.com/rust-lang/rust/blob/HEAD/RELEASES.md#Version-1980-2026-08-20)

[Compare Source](rust-lang/rust@1.97.1...1.98.0)

\==========================

<a id="1.98.0-Language"></a>

## Language

- [Allow shortening lifetime of `&mut` when unsize-coercing, even in an invariant position.](rust-lang/rust#149219) For example, you can now coerce a `Cell<&'long mut i32>` to a `Cell<&'short mut dyn Send>`. Such shortenings were already previously allowed when coercing a `&mut` to a `&`, or coercing a `&` to a `&`.
- [Add deny-by-default `invalid_runtime_symbol_definitions` lint and warn-by-default `suspicious_runtime_symbol_definitions` lint](rust-lang/rust#155521)
  - The lints currently specifically targets `core` runtime symbols like `memcmp`, `memset`, `strlen`, ... and is planned to be expanded in the next few releases.
- [Add warn-by-default `c_void_returns` lint to check `core::ffi::c_void` as a return type](rust-lang/rust#156379)

<a id="1.98.0-Platform-Support"></a>

## Platform Support

- [Add `powerpc64-unknown-linux-gnuelfv2` as Tier 3](rust-lang/rust#144220)
- [Add `aarch64-unknown-linux-pauthtest` as Tier 3 target](rust-lang/rust#155722)
- [Promote `thumbv7a-none-eabi` to Tier 2](rust-lang/rust#155763)
- [Promote `thumbv7a-none-eabihf` to Tier 2](rust-lang/rust#155763)
- [Promote `thumbv7r-none-eabi` to Tier 2](rust-lang/rust#155763)
- [Promote `thumbv7r-none-eabihf` to Tier 2](rust-lang/rust#155763)
- [Promote `thumbv8r-none-eabihf` to Tier 2](rust-lang/rust#155763)

Refer to Rust's [platform support page][platform-support-doc]
for more information on Rust's tiered platform support.

[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html

<a id="1.98.0-Libraries"></a>

## Libraries

- [Change `Location<'_>` lifetime to `'static` in `Panic[Hook]Info`](rust-lang/rust#146561)
- [Document panic in `RangeInclusive::from(legacy::RangeInclusive)`](rust-lang/rust#155421)
- [Document that `ManuallyDrop`'s `Box` interaction has been fixed](rust-lang/rust#155750)
- [Stabilize LoongArch CRC Intrinsics](rust-lang/rust#156908)
- [The `derive` macro is available at `{core,std}::derive`.](rust-lang/rust#154645) This was previously [unintentionally stabilized in 1.96](rust-lang/rust#159856), but is now [explicitly accepted](rust-lang/rust#154645) as a stabilized API.
  - Please note that the MSRV for `{core,std}::derive` will be 1.96, and not 1.98.

<a id="1.98.0-Stabilized-APIs"></a>

## Stabilized APIs

- [`str::substr_range`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.substr_range)
- [`[T]::subslice_range`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.subslice_range)
- [`core::fmt::NumBuffer`](https://doc.rust-lang.org/stable/core/fmt/struct.NumBuffer.html)
- [`<{integer}>::format_into`](https://doc.rust-lang.org/stable/core/primitive.usize.html#method.format_into)
- [`Send/Sync for std::process::CommandArgs`](https://doc.rust-lang.org/stable/std/process/struct.CommandArgs.html#impl-Send-for-CommandArgs%3C'a%3E)
- [`{fN}::algebraic_add`](https://doc.rust-lang.org/stable/core/primitive.f32.html#method.algebraic_add)
- [`{fN}::algebraic_sub`](https://doc.rust-lang.org/stable/core/primitive.f32.html#method.algebraic_sub)
- [`{fN}::algebraic_mul`](https://doc.rust-lang.org/stable/core/primitive.f32.html#method.algebraic_mul)
- [`{fN}::algebraic_div`](https://doc.rust-lang.org/stable/core/primitive.f32.html#method.algebraic_div)
- [`{fN}::algebraic_rem`](https://doc.rust-lang.org/stable/core/primitive.f32.html#method.algebraic_rem)
- [`NonZero<{integer}>::from_str_radix`](https://doc.rust-lang.org/stable/core/num/struct.NonZero.html#method.from_str_radix-4)
- [`String::from_utf16le`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf16le)
- [`String::from_utf16le_lossy`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf16le_lossy)
- [`String::from_utf16be`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf16be)
- [`String::from_utf16be_lossy`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf16be_lossy)
- [`[T]::strip_circumfix`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.strip_circumfix)
- [`str::strip_circumfix`](https://doc.rust-lang.org/stable/core/primitive.str.html#method.strip_circumfix)
- [`Atomic<T>::from_mut`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.Atomic.html#method.from_mut)
- [`Atomic<T>::get_mut_slice`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.Atomic.html#method.get_mut_slice)
- [`Atomic<T>::from_mut_slice`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.Atomic.html#method.from_mut_slice)
- [`std::range::legacy`](https://doc.rust-lang.org/stable/std/range/legacy/index.html)

<a id="1.98.0-Compatibility-Notes"></a>

## Compatibility Notes

- [If fully elided, lifetime bounds of trait object types may now resolve differently or even get rejected in very specific niche scenarios](rust-lang/rust#129543)
- [Error in more cases of ambiguous imports](rust-lang/rust#145108)
- [Switch the destructors implementation for thread locals on Windows to use Fiber Local Storage (FLS)](rust-lang/rust#148799)
- [Convert some cases of the `ambiguous_glob_imports` lint into a hard error](rust-lang/rust#149195)
- [Where-bounds of the form `Type = Type` and `Type == Type` are no longer syntactically allowed](rust-lang/rust#153513)
- [Ensure Send/Sync is not implemented for std::env::Vars{,Os}](rust-lang/rust#155153)
- [Fix that in some attributes, arguments were not properly rejected](rust-lang/rust#155193)
- [`repr(transparent)` is now more strict about which fields have "trivial" layout and hence can be ignored: `repr(C)` types, types with private fields, and `#[non_exhaustive]` types are no longer considered "trivial"](rust-lang/rust#155299)
- [Correctly check whether types have equal size in `transmute()` when some `repr` attributes are involved.](rust-lang/rust#155418)
- [More characters are escaped when printing strings and chars](rust-lang/rust#155527)
- [Implement fast path for `derive(PartialOrd)` when deriving `Ord`](rust-lang/rust#155598)
  This can break crates in practice where a type's PartialOrd and Ord impls were inconsistent with each other.
- [Add temporary scope to `assert_eq` and `assert_ne`](rust-lang/rust#155739)
- Closed a hole in the pattern matching [structural equality](https://doc.rust-lang.org/reference/patterns.html#constant-patterns) check, preventing cases where a match of a constant would be allowed, despite disagreeing with a manually written `PartialEq` implementation, when a `derive(PartialEq)` implementation for that type also exists.
- [On Emscripten the WASM exception handling ABI is now unconditionally used](rust-lang/rust#156928) The `-Zemscripten-wasm-eh=false` flag to switch back to JS exceptions has been removed.
- [The UNSAFE\_CODE lint is now consistently emitted for all unsafe attributes](rust-lang/rust#157201)
- [Solaris: remove `File::lock` implementation, it has the wrong semantics (return "unsupported" instead)](rust-lang/rust#157509)
- [Windows-gnu targets now specify baseline tools versions](rust-lang/rust#158020)
- [rustfmt now discovers module files that are defined in `cfg_select!`](rust-lang/rust#158372)
  This may cause more code to be formatted which was previously ignored.

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yODguMCIsInVwZGF0ZWRJblZlciI6IjQzLjI4OC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6bWlub3IiXX0=-->
andrico21 added a commit to andrico21/rmcp-server-kit that referenced this pull request Aug 21, 2026
Audit RUST_GUIDELINES.md against Rust/Cargo/Clippy 1.98.0 (2026-08-20).

Three 1.98 changes conflicted with rules the document already gave:

- derive(PartialOrd) fast path (rust-lang/rust#155598) plus the closed
  pattern-matching structural-equality hole make a manual PartialEq
  alongside a derived Ord observably inconsistent. The existing "destructure
  structs in trait impls" example did exactly this (ignoring `timestamp`),
  so it shipped the trap with the technique. New rule: comparison traits are
  all-manual or all-derived, `a == b` iff `cmp == Equal`, and manual-PartialEq
  types must not appear in constant patterns.
- UNSAFE_CODE now fires on unsafe attributes (rust-lang/rust#157201).
  `unsafe_code = "forbid"` cannot be locally overridden, so crates using
  #[unsafe(no_mangle)] / #[unsafe(link_section)] / #[unsafe(export_name)] /
  #[unsafe(naked)] break on upgrade. Firmware targets must use "deny" plus a
  justified per-item #[allow].
- repr(transparent) is stricter (rust-lang/rust#155299): repr(C),
  private-field, and #[non_exhaustive] types are no longer "trivial" layout,
  which collides with the newtype and exhaustive_structs guidance.

Also added: algebraic float non-determinism rule; Clippy 1.98 lint tables
(5 lints auto-covered by all = "deny"; with_capacity_zero and
unused_async_trait_impl are pedantic and need a decision -- documented as a
per-impl #[expect(reason)] matching 80c3586, not a crate-wide allow);
rustc runtime-symbol lint table with warnings-group membership; rustfmt now
discovering cfg_select! modules and the fmt-gate churn that implies;
Debug-is-not-a-wire-format and assert_eq! temporary-scope test rules; and
1.98 API idioms (bool::ok_or, NonZero::from_str_radix, format_into +
NumBuffer, substr_range/subslice_range, Atomic::from_mut, strip_circumfix,
String::from_utf16{le,be}).

Corrected drift against the enforced config: expect_used and
clone_on_ref_ptr to "deny", removed the deprecated string_to_string lint,
added the mandatory priority = -1 on [lints.clippy] group entries, documented
the clippy.toml thresholds, marked the pointer lints as moot under
unsafe_code = "forbid", and made the Miri requirement conditional on the
crate actually containing unsafe. Fixed a GOOD example that violated the
document's own unwrap_used and indexing_slicing rules.

Cargo 1.98 needs no changes: its stable Added and Changed sections are empty.

ESP32/embassy guidance is retained and refreshed in place rather than
removed, including NumBuffer as the core-not-alloc integer formatting path
and algebraic_* fenced off from values reported over MQTT or persisted to NVS.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team to-announce Announce this issue on triage meeting waived-reference-pr This language change does not need a Reference PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

We have two independent checks for "is this attribute unsafe"

10 participants