Skip to content

Commit

Permalink
Add toggle for parse_meta_item unsafe parsing
Browse files Browse the repository at this point in the history
This makes it possible for the `unsafe(...)` syntax to only be
valid at the top level, and the `NestedMetaItem`s will automatically
reject `unsafe(...)`.
  • Loading branch information
carbotaniuman committed Jul 10, 2024
1 parent 7e15ea0 commit bd94a21
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 38 deletions.
3 changes: 0 additions & 3 deletions compiler/rustc_builtin_macros/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,6 @@ builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept a
builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
.suggestion = remove the value
builtin_macros_derive_unsafe_path = traits in `#[derive(...)]` don't accept `unsafe(...)`
.suggestion = remove the `unsafe(...)`
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
.custom = use `std::env::var({$var_expr})` to read the variable at run time
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_builtin_macros/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn parse_cfg<'a>(cx: &ExtCtxt<'a>, span: Span, tts: TokenStream) -> PResult<'a,
return Err(cx.dcx().create_err(errors::RequiresCfgPattern { span }));
}

let cfg = p.parse_meta_item()?;
let cfg = p.parse_meta_item(true)?;

let _ = p.eat(&token::Comma);

Expand Down
13 changes: 1 addition & 12 deletions compiler/rustc_builtin_macros/src/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::cfg_eval::cfg_eval;
use crate::errors;

use rustc_ast as ast;
use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, Safety, StmtKind};
use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
use rustc_expand::base::{
Annotatable, DeriveResolution, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier,
};
Expand Down Expand Up @@ -62,7 +62,6 @@ impl MultiItemModifier for Expander {
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the
// paths.
report_path_args(sess, meta);
report_unsafe_args(sess, meta);
meta.path.clone()
})
.map(|path| DeriveResolution {
Expand Down Expand Up @@ -162,13 +161,3 @@ fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
}
}
}

fn report_unsafe_args(sess: &Session, meta: &ast::MetaItem) {
match meta.unsafety {
Safety::Unsafe(span) => {
sess.dcx().emit_err(errors::DeriveUnsafePath { span });
}
Safety::Default => {}
Safety::Safe(_) => unreachable!(),
}
}
7 changes: 0 additions & 7 deletions compiler/rustc_builtin_macros/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,13 +295,6 @@ pub(crate) struct DerivePathArgsValue {
pub(crate) span: Span,
}

#[derive(Diagnostic)]
#[diag(builtin_macros_derive_unsafe_path)]
pub(crate) struct DeriveUnsafePath {
#[primary_span]
pub(crate) span: Span,
}

#[derive(Diagnostic)]
#[diag(builtin_macros_no_default_variant)]
#[help]
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
}

match new_parser_from_source_str(&psess, filename, s.to_string()) {
Ok(mut parser) => match parser.parse_meta_item() {
Ok(mut parser) => match parser.parse_meta_item(false) {
Ok(meta_item) if parser.token == token::Eof => {
if meta_item.path.segments.len() != 1 {
error!("argument key must be an identifier");
Expand Down Expand Up @@ -174,7 +174,7 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
}
};

let meta_item = match parser.parse_meta_item() {
let meta_item = match parser.parse_meta_item(true) {
Ok(meta_item) if parser.token == token::Eof => meta_item,
Ok(..) => expected_error(),
Err(err) => {
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_parse/src/parser/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ impl<'a> Parser<'a> {

/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
pub fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> {
let cfg_predicate = self.parse_meta_item()?;
let cfg_predicate = self.parse_meta_item(false)?;
self.expect(&token::Comma)?;

// Presumably, the majority of the time there will only be one attr.
Expand Down Expand Up @@ -373,7 +373,7 @@ impl<'a> Parser<'a> {
/// MetaItem = SimplePath ( '=' UNSUFFIXED_LIT | '(' MetaSeq? ')' )? ;
/// MetaSeq = MetaItemInner (',' MetaItemInner)* ','? ;
/// ```
pub fn parse_meta_item(&mut self) -> PResult<'a, ast::MetaItem> {
pub fn parse_meta_item(&mut self, allow_leading_unsafe: bool) -> PResult<'a, ast::MetaItem> {
// We can't use `maybe_whole` here because it would bump in the `None`
// case, which we don't want.
if let token::Interpolated(nt) = &self.token.kind
Expand All @@ -389,7 +389,7 @@ impl<'a> Parser<'a> {
}

let lo = self.token.span;
let is_unsafe = self.eat_keyword(kw::Unsafe);
let is_unsafe = if allow_leading_unsafe { self.eat_keyword(kw::Unsafe) } else { false };
let unsafety = if is_unsafe {
let unsafe_span = self.prev_token.span;
self.psess.gated_spans.gate(sym::unsafe_attributes, unsafe_span);
Expand Down Expand Up @@ -432,7 +432,7 @@ impl<'a> Parser<'a> {
Err(err) => err.cancel(), // we provide a better error below
}

match self.parse_meta_item() {
match self.parse_meta_item(false) {
Ok(mi) => return Ok(ast::NestedMetaItem::MetaItem(mi)),
Err(err) => err.cancel(), // we provide a better error below
}
Expand Down
8 changes: 7 additions & 1 deletion tests/ui/attributes/unsafe/derive-unsafe-attributes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
#![feature(unsafe_attributes)]

#[derive(unsafe(Debug))] //~ ERROR: traits in `#[derive(...)]` don't accept `unsafe(...)`
#[derive(unsafe(Debug))]
//~^ ERROR: expected identifier, found keyword `unsafe`
//~| ERROR: traits in `#[derive(...)]` don't accept arguments
//~| ERROR: expected identifier, found keyword `unsafe`
//~| ERROR: expected identifier, found keyword `unsafe`
//~| ERROR: cannot find derive macro `r#unsafe` in this scope
//~| ERROR: cannot find derive macro `r#unsafe` in this scope
struct Foo;

#[unsafe(derive(Debug))] //~ ERROR: is not an unsafe attribute
Expand Down
57 changes: 53 additions & 4 deletions tests/ui/attributes/unsafe/derive-unsafe-attributes.stderr
Original file line number Diff line number Diff line change
@@ -1,16 +1,65 @@
error: traits in `#[derive(...)]` don't accept `unsafe(...)`
error: expected identifier, found keyword `unsafe`
--> $DIR/derive-unsafe-attributes.rs:3:10
|
LL | #[derive(unsafe(Debug))]
| ^^^^^^
| ^^^^^^ expected identifier, found keyword
|
help: escape `unsafe` to use it as an identifier
|
LL | #[derive(r#unsafe(Debug))]
| ++

error: traits in `#[derive(...)]` don't accept arguments
--> $DIR/derive-unsafe-attributes.rs:3:16
|
LL | #[derive(unsafe(Debug))]
| ^^^^^^^ help: remove the arguments

error: `derive` is not an unsafe attribute
--> $DIR/derive-unsafe-attributes.rs:6:3
--> $DIR/derive-unsafe-attributes.rs:12:3
|
LL | #[unsafe(derive(Debug))]
| ^^^^^^
|
= note: extraneous unsafe is not allowed in attributes

error: aborting due to 2 previous errors
error: expected identifier, found keyword `unsafe`
--> $DIR/derive-unsafe-attributes.rs:3:10
|
LL | #[derive(unsafe(Debug))]
| ^^^^^^ expected identifier, found keyword
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: escape `unsafe` to use it as an identifier
|
LL | #[derive(r#unsafe(Debug))]
| ++

error: expected identifier, found keyword `unsafe`
--> $DIR/derive-unsafe-attributes.rs:3:10
|
LL | #[derive(unsafe(Debug))]
| ^^^^^^ expected identifier, found keyword
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
help: escape `unsafe` to use it as an identifier
|
LL | #[derive(r#unsafe(Debug))]
| ++

error: cannot find derive macro `r#unsafe` in this scope
--> $DIR/derive-unsafe-attributes.rs:3:10
|
LL | #[derive(unsafe(Debug))]
| ^^^^^^

error: cannot find derive macro `r#unsafe` in this scope
--> $DIR/derive-unsafe-attributes.rs:3:10
|
LL | #[derive(unsafe(Debug))]
| ^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 7 previous errors

10 changes: 10 additions & 0 deletions tests/ui/attributes/unsafe/proc-unsafe-attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub fn b() {}

#[proc_macro_derive(unsafe(Foo))]
//~^ ERROR attribute is only usable with crates of the `proc-macro` crate type
//~| ERROR: expected identifier, found keyword `unsafe`
pub fn c() {}

#[unsafe(proc_macro_attribute)]
Expand All @@ -24,4 +25,13 @@ pub fn d() {}
//~^ ERROR: is not an unsafe attribute
pub fn e() {}

#[unsafe(allow(unsafe(dead_code)))]
//~^ ERROR: is not an unsafe attribute
//~| ERROR: malformed lint attribute input
//~| ERROR: malformed lint attribute input
//~| ERROR: expected identifier, found keyword `unsafe`
//~| ERROR: malformed lint attribute input
//~| ERROR: malformed lint attribute input
pub fn f() {}

fn main() {}
69 changes: 65 additions & 4 deletions tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
error[E0452]: malformed lint attribute input
--> $DIR/proc-unsafe-attributes.rs:28:16
|
LL | #[unsafe(allow(unsafe(dead_code)))]
| ^^^^^^^^^^^^^^^^^ bad attribute argument

error[E0452]: malformed lint attribute input
--> $DIR/proc-unsafe-attributes.rs:28:16
|
LL | #[unsafe(allow(unsafe(dead_code)))]
| ^^^^^^^^^^^^^^^^^ bad attribute argument
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: `proc_macro` is not an unsafe attribute
--> $DIR/proc-unsafe-attributes.rs:3:3
|
Expand All @@ -14,22 +28,52 @@ LL | #[unsafe(proc_macro_derive(Foo))]
|
= note: extraneous unsafe is not allowed in attributes

error: expected identifier, found keyword `unsafe`
--> $DIR/proc-unsafe-attributes.rs:14:21
|
LL | #[proc_macro_derive(unsafe(Foo))]
| ^^^^^^ expected identifier, found keyword
|
help: escape `unsafe` to use it as an identifier
|
LL | #[proc_macro_derive(r#unsafe(Foo))]
| ++

error: `proc_macro_attribute` is not an unsafe attribute
--> $DIR/proc-unsafe-attributes.rs:18:3
--> $DIR/proc-unsafe-attributes.rs:19:3
|
LL | #[unsafe(proc_macro_attribute)]
| ^^^^^^
|
= note: extraneous unsafe is not allowed in attributes

error: `allow` is not an unsafe attribute
--> $DIR/proc-unsafe-attributes.rs:23:3
--> $DIR/proc-unsafe-attributes.rs:24:3
|
LL | #[unsafe(allow(dead_code))]
| ^^^^^^
|
= note: extraneous unsafe is not allowed in attributes

error: `allow` is not an unsafe attribute
--> $DIR/proc-unsafe-attributes.rs:28:3
|
LL | #[unsafe(allow(unsafe(dead_code)))]
| ^^^^^^
|
= note: extraneous unsafe is not allowed in attributes

error: expected identifier, found keyword `unsafe`
--> $DIR/proc-unsafe-attributes.rs:28:16
|
LL | #[unsafe(allow(unsafe(dead_code)))]
| ^^^^^^ expected identifier, found keyword
|
help: escape `unsafe` to use it as an identifier
|
LL | #[unsafe(allow(r#unsafe(dead_code)))]
| ++

error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type
--> $DIR/proc-unsafe-attributes.rs:3:1
|
Expand All @@ -49,10 +93,27 @@ LL | #[proc_macro_derive(unsafe(Foo))]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type
--> $DIR/proc-unsafe-attributes.rs:18:1
--> $DIR/proc-unsafe-attributes.rs:19:1
|
LL | #[unsafe(proc_macro_attribute)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 8 previous errors
error[E0452]: malformed lint attribute input
--> $DIR/proc-unsafe-attributes.rs:28:16
|
LL | #[unsafe(allow(unsafe(dead_code)))]
| ^^^^^^^^^^^^^^^^^ bad attribute argument
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error[E0452]: malformed lint attribute input
--> $DIR/proc-unsafe-attributes.rs:28:16
|
LL | #[unsafe(allow(unsafe(dead_code)))]
| ^^^^^^^^^^^^^^^^^ bad attribute argument
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

error: aborting due to 15 previous errors

For more information about this error, try `rustc --explain E0452`.

0 comments on commit bd94a21

Please sign in to comment.