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

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

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.

@craterbot
Copy link
Collaborator

🎉 Experiment pr-124214 is completed!
📊 106 regressed and 118 fixed (447503 total)
📰 Open the full report.

⚠️ If you notice any spurious failure please add them to the blacklist!
ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more

@craterbot craterbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-crater Status: Waiting on a crater run to be completed. labels May 17, 2024
@carbotaniuman
Copy link
Contributor Author

Looking at the crater results, it appears like there's no regressions from this change.

@bors
Copy link
Contributor

bors commented May 20, 2024

☔ The latest upstream changes (presumably #125331) 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.

@bors
Copy link
Contributor

bors commented May 22, 2024

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

@michaelwoerister
Copy link
Member

Looking at the crater results, it appears like there's no regressions from this change.

I agree. I can't find anything that looks related this PR.

Copy link
Member

@michaelwoerister michaelwoerister left a comment

Choose a reason for hiding this comment

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

The PR looks good to merge now. Please expand the comment mentioned below. After that I'm happy to approve.

@@ -360,7 +367,8 @@ impl MetaItem {
_ => path.span.hi(),
};
let span = path.span.with_hi(hi);
Some(MetaItem { path, kind, span })
// FIX THIS LATER
Copy link
Member

Choose a reason for hiding this comment

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

Can you expand this comment to give more information on what needs to be fixed?

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've put a proper FIXME here. I expect I'll tackle this in a subsequent PR, so I'd prefer not having to block on this.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks, yes that works me.

@michaelwoerister
Copy link
Member

Actually, @carbotaniuman, let's also make #[ffi_const] and #[ffi_pure] unsafe too. Those definitely fit the bill. Not sure about #[naked] yet.

@michaelwoerister
Copy link
Member

@traviscross, let me know if you'd like me to hold off on approving the PR until the lang-team has reviewed the set of attributes.

@RalfJung
Copy link
Member

#[naked] seems very unsafe, doesn't it? Cc @Amanieu

@michaelwoerister
Copy link
Member

michaelwoerister commented May 22, 2024

#[naked] seems very unsafe, doesn't it? Cc @Amanieu

I agree but it might be a similar case to #[link_name] because either the naked function itself has to be unsafe or its entire body must be wrapped inside an unsafe block. But maybe that's a kind of unsafety of a different category?

@pnkfelix
Copy link
Member

pnkfelix commented May 22, 2024

@traviscross, let me know if you'd like me to hold off on approving the PR until the lang-team has reviewed the set of attributes.

I'm doing that review now, thanks @michaelwoerister

click to see review table
attribute already unsafe in PR #124214 should be unsafe stay safe removed from lang
link covered by coupling with (unsafe) extern {...}
link_ordinal covered by coupling with (unsafe) extern {...}
link_args replace with -C link-arg or #![feature(link_arg_attribute]and #[link(kind="link-arg", ...] (thus see above)
link_name covered by coupling with (unsafe) extern {...}
repr believed safe (apart from packed; see below)
repr(packed) checked for error at use sites
export_name done
link_section done
no_mangle done
used believed safe
ffi_const suggested in mw review
ffi_pure suggested in mw review
naked covered by unsafe for naked function itself

@michaelwoerister
Copy link
Member

michaelwoerister commented May 28, 2024

@pnkfelix, can I interpret your message as "the current set of attributes is approved for this PR"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-lang-nominated The issue / PR has been nominated for discussion during a lang team meeting. 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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants