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
base: master
Are you sure you want to change the base?
Parse unsafe attributes #124214
Conversation
rustbot has assigned @michaelwoerister. Use |
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #124208) made this pull request unmergeable. Please resolve the merge conflicts. |
0702557
to
6ebb485
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #124360) made this pull request unmergeable. Please resolve the merge conflicts. |
@@ -628,6 +628,7 @@ declare_features! ( | |||
/// Allows unnamed fields of struct and union type | |||
(incomplete, unnamed_fields, "1.74.0", Some(49804)), | |||
/// Allows unsized fn parameters. | |||
(unstable, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc comment needs an update too.
Thanks for the PR, @carbotaniuman! Would you mind also adding a test case where using |
c91ab4f
to
eb16919
Compare
☔ The latest upstream changes (presumably #124424) made this pull request unmergeable. Please resolve the merge conflicts. |
eb16919
to
5562e99
Compare
I've added stuff to handle the |
compiler/rustc_ast/src/token.rs
Outdated
@@ -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, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure...
#[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)?; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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)?)), |
There was a problem hiding this comment.
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?
I think we need some expert input. There are two main questions:
@rustbot ping parser |
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 |
This is the right strategy. |
It would be good if 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. |
Thanks for the feedback!
Yes, I read through the RFC discussion thread today. I'm going to stay neutral regarding the choice 🙂 |
Let's try to make that work then.
To clarify, the above test case would be an example where the current and the new Do you mean a case like the following where currently fn main() {
macro_rules! foo {
($l:meta) => { 1 };
(unsafe($x:ident)) => { 2 };
}
let x = foo!(unsafe(no_mangle));
println!("{x}");
} |
Yeah, that |
@carbotaniuman, can you bring this PR in a state where we don't introduce a separate @rustbot author |
Alright, I've reverted those commits. @rustbot ready |
Thanks, @carbotaniuman! Let's do a try build for the crater run. I guess we'll need a build-and-test run since the difference in parsing does not necessarily result in a compile time error. |
…<try> 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.
A code search on github does not yield anything that looks problematic: |
☀️ Try build successful - checks-actions |
@craterbot run mode=build-and-test |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
Initial parse implementation for #123757
This is the initial work to parse unsafe attributes, which is represented as an extra
unsafety
field inMetaItem
andAttrItem
. 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.