Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse unsafe attributes #124214

Merged
merged 14 commits into from
Jun 7, 2024
Merged

Conversation

carbotaniuman
Copy link
Contributor

Initial parse implementation for #123757

This is the initial work to parse unsafe attributes, which is represented as an extra unsafety field in MetaItem and AttrItem. There's two areas in the code where it appears that parsing is done manually and not using the parser stuff, and I'm not sure how I'm supposed to thread the change there.

@rustbot
Copy link
Collaborator

rustbot commented Apr 21, 2024

r? @michaelwoerister

rustbot has assigned @michaelwoerister.
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

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 21, 2024
@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Apr 21, 2024

☔ The latest upstream changes (presumably #124208) made this pull request unmergeable. Please resolve the merge conflicts.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@bors
Copy link
Contributor

bors commented Apr 25, 2024

☔ The latest upstream changes (presumably #124360) made this pull request unmergeable. Please resolve the merge conflicts.

@michaelwoerister
Copy link
Member

Thanks for the PR, @carbotaniuman!

Would you mind also adding a test case where using unsafe(..) works as expected and one where it is used in a nested context, like #[cfg_attr(foo, unsafe(no_mangle)]?

@carbotaniuman carbotaniuman force-pushed the parse_unsafe_attrs branch 2 times, most recently from c91ab4f to eb16919 Compare April 25, 2024 16:39
@bors
Copy link
Contributor

bors commented Apr 27, 2024

☔ The latest upstream changes (presumably #124424) made this pull request unmergeable. Please resolve the merge conflicts.

@carbotaniuman
Copy link
Contributor Author

I've added stuff to handle the $meta matcher in macro_rules!. I'm not sure if it's needed, but it's technically breaking, and RFC 3531 suggests I do.

@@ -911,7 +912,7 @@ impl NonterminalKind {
sym::ident => NonterminalKind::Ident,
sym::lifetime => NonterminalKind::Lifetime,
sym::literal => NonterminalKind::Literal,
sym::meta => NonterminalKind::Meta,
sym::meta => NonterminalKind::Meta2021,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this actually needed? The grammar doesn't change, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure...

https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=5ccbe0db996ad629df3df4dc2119e2cd

#[cfg_attr(not(debug), unsafe(Foo))]
struct Foo;

The above is a parse error right now as it expects a path and not a keyword. There were 2 implementations strategies I considered, one of which was defining a macro unsafe that created the Attribute with the proper unsafety, but given that I would still need syntax changes (to deal with the unsafe), I opted to instead change the core AttrItem itself to have an unsafety field. So I'm not really sure if a) this is the right way of doing things and b) if I need to make the macro changes.

ast::Unsafe::No
};

let path = this.parse_path(PathStyle::Mod)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect this to result in a slightly weird error message when doing something like #[unsafe(unsafe(no_mangle))]. Can we add a test case for that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error: expected identifier, found keyword `unsafe`
  --> /home/quydx/code/rust/tests/ui/attributes/unsafe/double-unsafe-in-attribute.rs:1:10
   |
LL | #[unsafe(unsafe(no_mangle))]
   |          ^^^^^^ expected identifier, found keyword
   |
help: escape `unsafe` to use it as an identifier
   |
LL | #[unsafe(r#unsafe(no_mangle))]
   |          ++

error: cannot find attribute `r#unsafe` in this scope
  --> /home/quydx/code/rust/tests/ui/attributes/unsafe/double-unsafe-in-attribute.rs:1:10
   |
LL | #[unsafe(unsafe(no_mangle))]
   |          ^^^^^^

The error is basically just what we have now. I can probably add a note saying that unsafe(...) doesn't nest.

@@ -170,6 +175,7 @@ impl<'a> Parser<'a> {
NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?))
}
NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(true)?)),
NonterminalKind::Meta2021 => NtMeta(P(self.parse_attr_item_no_unsafe(true)?)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I'm not sure this is necessary because using unsafe(...) currently fails to parse (see playground example). So I think this should fall under the following paragraph from RFC 3531:

In cases where we’re adding new syntax and updating the grammar to include that new syntax, if we can update the corresponding fragment specifier simultaneously to match the new grammar in such a way that we do not risk changing the behavior of existing macros (i.e., because the new syntax previously would have failed parsing), then we will do that so as to prevent or minimize divergence between the fragment specifier and the new grammar.

I.e. the question is: Can the addition of unsafe(..) change the behavior of any currently valid macros / macro invocations?

@michaelwoerister
Copy link
Member

I think we need some expert input. There are two main questions:

  • The PR's current implementation strategy for unsafe attributes is to add an unsafety field to AttrItem and MetaItem and handled that during parsing. I.e. #[unsafe(Something)] will end up as a flat Something AttrItem as opposed to an unsafe AttrItem with Something nested as an argument. Given that the RFC says that unsafe attributes cannot be nested or complex, that implementation strategy makes sense to me. But I'm no parsing/macros expert so it would be good to get additional opinions here.

  • The PR currently introduces a new meta_2021 fragment specifier to account for the unsafe attributes changes (see RFC 3531 - Macro matcher fragment specifiers edition policy). However, I think that is not necessary since #[unsafe(something)] does not currently parse (see playground example). Therefore starting to allow it for the existing meta fragment specifier should not be a breaking change and does not need to happen on an edition boundary. Does this reasoning overlook something?

@rustbot ping parser

@rustbot
Copy link
Collaborator

rustbot commented May 2, 2024

Error: This team (parser) cannot be pinged via this command; it may need to be added to triagebot.toml on the default branch.

Please file an issue on GitHub at triagebot if there's a problem with this bot, or reach out on #t-infra on Zulip.

@michaelwoerister
Copy link
Member

It looks like rustbot does not allow pinging adhoc groups, so pinging manually regarding the questions in the comment above: @compiler-errors @davidtwco @estebank @nnethercote @petrochenkov @spastorino

@petrochenkov
Copy link
Contributor

The PR's current implementation strategy for unsafe attributes is to add an unsafety field to AttrItem and MetaItem and handled that during parsing. I.e. #[unsafe(Something)] will end up as a flat Something AttrItem as opposed to an unsafe AttrItem with Something nested as an argument.

This is the right strategy.
It would be more clear if the syntax was different, like #[unsafe my_attr].
The confusing parenthesized syntax was selected in the end, but it doesn't change the semantics.

@petrochenkov
Copy link
Contributor

Macro matcher fragment specifiers edition policy](https://rust-lang.github.io/rfcs/3531-macro-fragment-policy.html)). However, I think that is not necessary since #[unsafe(something)] does not currently parse (see playground example).

It would be good if unsafe could fit into the existing meta matcher.

There may be some issues with ambiguities between macro arms in cases similar to

macro_rules! m {
    (unsafe) => { 1 }
    ($meta:meta) => { 2 }
}

m!(unsafe(no_mangle));

This needs some testing.

@michaelwoerister
Copy link
Member

This is the right strategy.

Thanks for the feedback!

It would be more clear if the syntax was different, like #[unsafe my_attr].
The confusing parenthesized syntax was selected in the end, but it doesn't change the semantics.

Yes, I read through the RFC discussion thread today. I'm going to stay neutral regarding the choice 🙂
From a grammar point of view #[unsafe my_attr] would indeed be clearer.

@rust-log-analyzer

This comment has been minimized.

@michaelwoerister
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Jun 7, 2024

📌 Commit f9104f0 has been approved by michaelwoerister

It is now in the queue for this repository.

@bors bors 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 7, 2024
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jun 7, 2024
…r=michaelwoerister

Parse unsafe attributes

Initial parse implementation for rust-lang#123757

This is the initial work to parse unsafe attributes, which is represented as an extra `unsafety` field in `MetaItem` and `AttrItem`. There's two areas in the code where it appears that parsing is done manually and not using the parser stuff, and I'm not sure how I'm supposed to thread the change there.
bors added a commit to rust-lang-ci/rust that referenced this pull request Jun 7, 2024
…iaskrgr

Rollup of 11 pull requests

Successful merges:

 - rust-lang#116088 (Stabilise `c_unwind`)
 - rust-lang#124012 (Stabilize `binary_heap_as_slice`)
 - rust-lang#124214 (Parse unsafe attributes)
 - rust-lang#125572 (Detect pub structs never constructed and unused associated constants)
 - rust-lang#125781 (prefer `compile::stream_cargo` for building tools)
 - rust-lang#126030 (Update `./x fmt` command in library/std/src/sys/pal/windows/c/README.md)
 - rust-lang#126047 (Simplify the rayon calls in the installer)
 - rust-lang#126070 (Enable f16 in assembly on aarch64 platforms that support it)
 - rust-lang#126089 (Stabilize Option::take_if)
 - rust-lang#126112 (Clean up source root in run-make tests)
 - rust-lang#126119 (Improve docs for using custom paths with `--emit`)

r? `@ghost`
`@rustbot` modify labels: rollup
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jun 7, 2024
…r=michaelwoerister

Parse unsafe attributes

Initial parse implementation for rust-lang#123757

This is the initial work to parse unsafe attributes, which is represented as an extra `unsafety` field in `MetaItem` and `AttrItem`. There's two areas in the code where it appears that parsing is done manually and not using the parser stuff, and I'm not sure how I'm supposed to thread the change there.
bors added a commit to rust-lang-ci/rust that referenced this pull request Jun 7, 2024
…iaskrgr

Rollup of 10 pull requests

Successful merges:

 - rust-lang#116088 (Stabilise `c_unwind`)
 - rust-lang#124012 (Stabilize `binary_heap_as_slice`)
 - rust-lang#124214 (Parse unsafe attributes)
 - rust-lang#125572 (Detect pub structs never constructed and unused associated constants)
 - rust-lang#125781 (prefer `compile::stream_cargo` for building tools)
 - rust-lang#126030 (Update `./x fmt` command in library/std/src/sys/pal/windows/c/README.md)
 - rust-lang#126047 (Simplify the rayon calls in the installer)
 - rust-lang#126089 (Stabilize Option::take_if)
 - rust-lang#126112 (Clean up source root in run-make tests)
 - rust-lang#126119 (Improve docs for using custom paths with `--emit`)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Jun 7, 2024
…iaskrgr

Rollup of 11 pull requests

Successful merges:

 - rust-lang#124012 (Stabilize `binary_heap_as_slice`)
 - rust-lang#124214 (Parse unsafe attributes)
 - rust-lang#125572 (Detect pub structs never constructed and unused associated constants)
 - rust-lang#125781 (prefer `compile::stream_cargo` for building tools)
 - rust-lang#126030 (Update `./x fmt` command in library/std/src/sys/pal/windows/c/README.md)
 - rust-lang#126047 (Simplify the rayon calls in the installer)
 - rust-lang#126052 (More `rustc_parse` cleanups)
 - rust-lang#126077 (Revert "Use the HIR instead of mir_keys for determining whether something will have a MIR body.")
 - rust-lang#126089 (Stabilize Option::take_if)
 - rust-lang#126112 (Clean up source root in run-make tests)
 - rust-lang#126119 (Improve docs for using custom paths with `--emit`)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 6e534c7 into rust-lang:master Jun 7, 2024
6 checks passed
@rustbot rustbot added this to the 1.80.0 milestone Jun 7, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Jun 7, 2024
Rollup merge of rust-lang#124214 - carbotaniuman:parse_unsafe_attrs, r=michaelwoerister

Parse unsafe attributes

Initial parse implementation for rust-lang#123757

This is the initial work to parse unsafe attributes, which is represented as an extra `unsafety` field in `MetaItem` and `AttrItem`. There's two areas in the code where it appears that parsing is done manually and not using the parser stuff, and I'm not sure how I'm supposed to thread the change there.
@carbotaniuman carbotaniuman deleted the parse_unsafe_attrs branch June 7, 2024 23:14
tgross35 added a commit to tgross35/rust that referenced this pull request Aug 17, 2024
…r, r=nnethercote

Stabilize `unsafe_attributes`

# Stabilization report

## Summary

This is a tracking issue for the RFC 3325: unsafe attributes

We are stabilizing `#![feature(unsafe_attributes)]`,  which makes certain attributes considered 'unsafe', meaning that they must be surrounded by an `unsafe(...)`, as in `#[unsafe(no_mangle)]`.

RFC: rust-lang/rfcs#3325
Tracking issue: rust-lang#123757

## What is stabilized

### Summary of stabilization

Certain attributes will now be designated as unsafe attributes, namely, `no_mangle`, `export_name`, and `link_section` (stable only), and these attributes will need to be called by surrounding them in `unsafe(...)` syntax. On editions prior to 2024, this is simply an edition lint, but it will become a hard error in 2024. This also works in `cfg_attr`, but `unsafe` is not allowed for any other attributes, including proc-macros ones.

```rust
#[unsafe(no_mangle)]
fn a() {}

#[cfg_attr(any(), unsafe(export_name = "c"))]
fn b() {}
```

For a table showing the attributes that were considered to be included in the list to require unsafe, and subsequent reasoning about why each such attribute was or was not included, see [this comment here](rust-lang#124214 (comment))

## Tests

The relevant tests are in `tests/ui/rust-2024/unsafe-attributes` and `tests/ui/attributes/unsafe`.
bors added a commit to rust-lang-ci/rust that referenced this pull request Aug 17, 2024
… r=nnethercote

Stabilize `unsafe_attributes`

# Stabilization report

## Summary

This is a tracking issue for the RFC 3325: unsafe attributes

We are stabilizing `#![feature(unsafe_attributes)]`,  which makes certain attributes considered 'unsafe', meaning that they must be surrounded by an `unsafe(...)`, as in `#[unsafe(no_mangle)]`.

RFC: rust-lang/rfcs#3325
Tracking issue: rust-lang#123757

## What is stabilized

### Summary of stabilization

Certain attributes will now be designated as unsafe attributes, namely, `no_mangle`, `export_name`, and `link_section` (stable only), and these attributes will need to be called by surrounding them in `unsafe(...)` syntax. On editions prior to 2024, this is simply an edition lint, but it will become a hard error in 2024. This also works in `cfg_attr`, but `unsafe` is not allowed for any other attributes, including proc-macros ones.

```rust
#[unsafe(no_mangle)]
fn a() {}

#[cfg_attr(any(), unsafe(export_name = "c"))]
fn b() {}
```

For a table showing the attributes that were considered to be included in the list to require unsafe, and subsequent reasoning about why each such attribute was or was not included, see [this comment here](rust-lang#124214 (comment))

## Tests

The relevant tests are in `tests/ui/rust-2024/unsafe-attributes` and `tests/ui/attributes/unsafe`.
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Aug 20, 2024
…rcote

Stabilize `unsafe_attributes`

# Stabilization report

## Summary

This is a tracking issue for the RFC 3325: unsafe attributes

We are stabilizing `#![feature(unsafe_attributes)]`,  which makes certain attributes considered 'unsafe', meaning that they must be surrounded by an `unsafe(...)`, as in `#[unsafe(no_mangle)]`.

RFC: rust-lang/rfcs#3325
Tracking issue: #123757

## What is stabilized

### Summary of stabilization

Certain attributes will now be designated as unsafe attributes, namely, `no_mangle`, `export_name`, and `link_section` (stable only), and these attributes will need to be called by surrounding them in `unsafe(...)` syntax. On editions prior to 2024, this is simply an edition lint, but it will become a hard error in 2024. This also works in `cfg_attr`, but `unsafe` is not allowed for any other attributes, including proc-macros ones.

```rust
#[unsafe(no_mangle)]
fn a() {}

#[cfg_attr(any(), unsafe(export_name = "c"))]
fn b() {}
```

For a table showing the attributes that were considered to be included in the list to require unsafe, and subsequent reasoning about why each such attribute was or was not included, see [this comment here](rust-lang/rust#124214 (comment))

## Tests

The relevant tests are in `tests/ui/rust-2024/unsafe-attributes` and `tests/ui/attributes/unsafe`.
lnicola pushed a commit to lnicola/rust-analyzer that referenced this pull request Aug 29, 2024
…rcote

Stabilize `unsafe_attributes`

# Stabilization report

## Summary

This is a tracking issue for the RFC 3325: unsafe attributes

We are stabilizing `#![feature(unsafe_attributes)]`,  which makes certain attributes considered 'unsafe', meaning that they must be surrounded by an `unsafe(...)`, as in `#[unsafe(no_mangle)]`.

RFC: rust-lang/rfcs#3325
Tracking issue: #123757

## What is stabilized

### Summary of stabilization

Certain attributes will now be designated as unsafe attributes, namely, `no_mangle`, `export_name`, and `link_section` (stable only), and these attributes will need to be called by surrounding them in `unsafe(...)` syntax. On editions prior to 2024, this is simply an edition lint, but it will become a hard error in 2024. This also works in `cfg_attr`, but `unsafe` is not allowed for any other attributes, including proc-macros ones.

```rust
#[unsafe(no_mangle)]
fn a() {}

#[cfg_attr(any(), unsafe(export_name = "c"))]
fn b() {}
```

For a table showing the attributes that were considered to be included in the list to require unsafe, and subsequent reasoning about why each such attribute was or was not included, see [this comment here](rust-lang/rust#124214 (comment))

## Tests

The relevant tests are in `tests/ui/rust-2024/unsafe-attributes` and `tests/ui/attributes/unsafe`.
github-actions bot pushed a commit to ytmimi/rustfmt that referenced this pull request Sep 10, 2024
…rcote

Stabilize `unsafe_attributes`

# Stabilization report

## Summary

This is a tracking issue for the RFC 3325: unsafe attributes

We are stabilizing `#![feature(unsafe_attributes)]`,  which makes certain attributes considered 'unsafe', meaning that they must be surrounded by an `unsafe(...)`, as in `#[unsafe(no_mangle)]`.

RFC: rust-lang/rfcs#3325
Tracking issue: #123757

## What is stabilized

### Summary of stabilization

Certain attributes will now be designated as unsafe attributes, namely, `no_mangle`, `export_name`, and `link_section` (stable only), and these attributes will need to be called by surrounding them in `unsafe(...)` syntax. On editions prior to 2024, this is simply an edition lint, but it will become a hard error in 2024. This also works in `cfg_attr`, but `unsafe` is not allowed for any other attributes, including proc-macros ones.

```rust
#[unsafe(no_mangle)]
fn a() {}

#[cfg_attr(any(), unsafe(export_name = "c"))]
fn b() {}
```

For a table showing the attributes that were considered to be included in the list to require unsafe, and subsequent reasoning about why each such attribute was or was not included, see [this comment here](rust-lang/rust#124214 (comment))

## Tests

The relevant tests are in `tests/ui/rust-2024/unsafe-attributes` and `tests/ui/attributes/unsafe`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants