Skip to content

Commit 54bfda8

Browse files
committed
Auto merge of rust-lang#124214 - carbotaniuman:parse_unsafe_attrs, r=<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.
2 parents 5ce96b1 + aadc436 commit 54bfda8

File tree

26 files changed

+223
-28
lines changed

26 files changed

+223
-28
lines changed

compiler/rustc_ast/src/ast.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,7 @@ pub struct Crate {
489489
/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
490490
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
491491
pub struct MetaItem {
492+
pub unsafety: Unsafe,
492493
pub path: Path,
493494
pub kind: MetaItemKind,
494495
pub span: Span,
@@ -2799,14 +2800,20 @@ pub struct NormalAttr {
27992800
impl NormalAttr {
28002801
pub fn from_ident(ident: Ident) -> Self {
28012802
Self {
2802-
item: AttrItem { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None },
2803+
item: AttrItem {
2804+
unsafety: Unsafe::No,
2805+
path: Path::from_ident(ident),
2806+
args: AttrArgs::Empty,
2807+
tokens: None,
2808+
},
28032809
tokens: None,
28042810
}
28052811
}
28062812
}
28072813

28082814
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
28092815
pub struct AttrItem {
2816+
pub unsafety: Unsafe,
28102817
pub path: Path,
28112818
pub args: AttrArgs,
28122819
// Tokens for the meta item, e.g. just the `foo` within `#[foo]` or `#![foo]`.

compiler/rustc_ast/src/attr/mod.rs

+25-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Functions dealing with attributes and meta items.
22
3-
use crate::ast::{AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute};
3+
use crate::ast::{
4+
AttrArgs, AttrArgsEq, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, Unsafe,
5+
};
46
use crate::ast::{DelimArgs, Expr, ExprKind, LitKind, MetaItemLit};
57
use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem, NormalAttr};
68
use crate::ast::{Path, PathSegment, DUMMY_NODE_ID};
@@ -227,7 +229,12 @@ impl AttrItem {
227229
}
228230

229231
pub fn meta(&self, span: Span) -> Option<MetaItem> {
230-
Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
232+
Some(MetaItem {
233+
unsafety: Unsafe::No,
234+
path: self.path.clone(),
235+
kind: self.meta_kind()?,
236+
span,
237+
})
231238
}
232239

233240
pub fn meta_kind(&self) -> Option<MetaItemKind> {
@@ -360,7 +367,8 @@ impl MetaItem {
360367
_ => path.span.hi(),
361368
};
362369
let span = path.span.with_hi(hi);
363-
Some(MetaItem { path, kind, span })
370+
// FIX THIS LATER
371+
Some(MetaItem { unsafety: Unsafe::No, path, kind, span })
364372
}
365373
}
366374

@@ -544,11 +552,12 @@ pub fn mk_doc_comment(
544552
pub fn mk_attr(
545553
g: &AttrIdGenerator,
546554
style: AttrStyle,
555+
unsafety: Unsafe,
547556
path: Path,
548557
args: AttrArgs,
549558
span: Span,
550559
) -> Attribute {
551-
mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
560+
mk_attr_from_item(g, AttrItem { unsafety, path, args, tokens: None }, None, style, span)
552561
}
553562

554563
pub fn mk_attr_from_item(
@@ -566,15 +575,22 @@ pub fn mk_attr_from_item(
566575
}
567576
}
568577

569-
pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
578+
pub fn mk_attr_word(
579+
g: &AttrIdGenerator,
580+
style: AttrStyle,
581+
unsafety: Unsafe,
582+
name: Symbol,
583+
span: Span,
584+
) -> Attribute {
570585
let path = Path::from_ident(Ident::new(name, span));
571586
let args = AttrArgs::Empty;
572-
mk_attr(g, style, path, args, span)
587+
mk_attr(g, style, unsafety, path, args, span)
573588
}
574589

575590
pub fn mk_attr_nested_word(
576591
g: &AttrIdGenerator,
577592
style: AttrStyle,
593+
unsafety: Unsafe,
578594
outer: Symbol,
579595
inner: Symbol,
580596
span: Span,
@@ -590,12 +606,13 @@ pub fn mk_attr_nested_word(
590606
delim: Delimiter::Parenthesis,
591607
tokens: inner_tokens,
592608
});
593-
mk_attr(g, style, path, attr_args, span)
609+
mk_attr(g, style, unsafety, path, attr_args, span)
594610
}
595611

596612
pub fn mk_attr_name_value_str(
597613
g: &AttrIdGenerator,
598614
style: AttrStyle,
615+
unsafety: Unsafe,
599616
name: Symbol,
600617
val: Symbol,
601618
span: Span,
@@ -610,7 +627,7 @@ pub fn mk_attr_name_value_str(
610627
});
611628
let path = Path::from_ident(Ident::new(name, span));
612629
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
613-
mk_attr(g, style, path, args, span)
630+
mk_attr(g, style, unsafety, path, args, span)
614631
}
615632

616633
pub fn filter_by_name(attrs: &[Attribute], name: Symbol) -> impl Iterator<Item = &Attribute> {

compiler/rustc_ast/src/mut_visit.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -647,8 +647,10 @@ fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
647647
let Attribute { kind, id: _, style: _, span } = attr;
648648
match kind {
649649
AttrKind::Normal(normal) => {
650-
let NormalAttr { item: AttrItem { path, args, tokens }, tokens: attr_tokens } =
651-
&mut **normal;
650+
let NormalAttr {
651+
item: AttrItem { unsafety: _, path, args, tokens },
652+
tokens: attr_tokens,
653+
} = &mut **normal;
652654
vis.visit_path(path);
653655
visit_attr_args(args, vis);
654656
visit_lazy_tts(tokens, vis);
@@ -678,7 +680,7 @@ fn noop_visit_meta_list_item<T: MutVisitor>(li: &mut NestedMetaItem, vis: &mut T
678680
}
679681

680682
fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
681-
let MetaItem { path: _, kind, span } = mi;
683+
let MetaItem { unsafety: _, path: _, kind, span } = mi;
682684
match kind {
683685
MetaItemKind::Word => {}
684686
MetaItemKind::List(mis) => visit_thin_vec(mis, |mi| vis.visit_meta_list_item(mi)),
@@ -838,7 +840,7 @@ fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
838840
token::NtLifetime(ident) => vis.visit_ident(ident),
839841
token::NtLiteral(expr) => vis.visit_expr(expr),
840842
token::NtMeta(item) => {
841-
let AttrItem { path, args, tokens } = item.deref_mut();
843+
let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut();
842844
vis.visit_path(path);
843845
visit_attr_args(args, vis);
844846
visit_lazy_tts(tokens, vis);

compiler/rustc_ast_lowering/src/expr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1805,6 +1805,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
18051805
let attr = attr::mk_attr_nested_word(
18061806
&self.tcx.sess.psess.attr_id_generator,
18071807
AttrStyle::Outer,
1808+
Unsafe::No,
18081809
sym::allow,
18091810
sym::unreachable_code,
18101811
self.lower_span(span),

compiler/rustc_ast_lowering/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
905905
let kind = match attr.kind {
906906
AttrKind::Normal(ref normal) => AttrKind::Normal(P(NormalAttr {
907907
item: AttrItem {
908+
unsafety: normal.item.unsafety,
908909
path: normal.item.path.clone(),
909910
args: self.lower_attr_args(&normal.item.args),
910911
tokens: None,

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
560560
gate_all!(postfix_match, "postfix match is experimental");
561561
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
562562
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
563+
gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental");
563564

564565
if !visitor.features.never_patterns {
565566
if let Some(spans) = spans.get(&sym::never_patterns) {

compiler/rustc_ast_pretty/src/pprust/state.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, To
1616
use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
1717
use rustc_ast::util::classify;
1818
use rustc_ast::util::comments::{Comment, CommentStyle};
19-
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind};
19+
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, BlockCheckMode, PatKind, Unsafe};
2020
use rustc_ast::{attr, BindingMode, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
2121
use rustc_ast::{GenericArg, GenericBound, SelfKind};
2222
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
@@ -245,6 +245,7 @@ pub fn print_crate<'a>(
245245
let fake_attr = attr::mk_attr_nested_word(
246246
g,
247247
ast::AttrStyle::Inner,
248+
Unsafe::No,
248249
sym::feature,
249250
sym::prelude_import,
250251
DUMMY_SP,
@@ -255,7 +256,8 @@ pub fn print_crate<'a>(
255256
// root, so this is not needed, and actually breaks things.
256257
if edition.is_rust_2015() {
257258
// `#![no_std]`
258-
let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
259+
let fake_attr =
260+
attr::mk_attr_word(g, ast::AttrStyle::Inner, Unsafe::No, sym::no_std, DUMMY_SP);
259261
s.print_attribute(&fake_attr);
260262
}
261263
}

compiler/rustc_builtin_macros/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ builtin_macros_derive_path_args_list = traits in `#[derive(...)]` don't accept a
110110
builtin_macros_derive_path_args_value = traits in `#[derive(...)]` don't accept values
111111
.suggestion = remove the value
112112
113+
builtin_macros_derive_unsafe_path = traits in `#[derive(...)]` don't accept `unsafe(...)`
114+
.suggestion = remove the `unsafe(...)`
115+
113116
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
114117
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
115118
.custom = use `std::env::var({$var_expr})` to read the variable at run time

compiler/rustc_builtin_macros/src/cmdline_attrs.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
1616
);
1717

1818
let start_span = parser.token.span;
19-
let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item(false) {
19+
let AttrItem { unsafety, path, args, tokens: _ } = match parser.parse_attr_item(false) {
2020
Ok(ai) => ai,
2121
Err(err) => {
2222
err.emit();
@@ -32,6 +32,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
3232
krate.attrs.push(mk_attr(
3333
&psess.attr_id_generator,
3434
AttrStyle::Inner,
35+
unsafety,
3536
path,
3637
args,
3738
start_span.to(end_span),

compiler/rustc_builtin_macros/src/derive.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::cfg_eval::cfg_eval;
22
use crate::errors;
33

44
use rustc_ast as ast;
5-
use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
5+
use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind, Unsafe};
66
use rustc_expand::base::{
77
Annotatable, DeriveResolution, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier,
88
};
@@ -60,6 +60,7 @@ impl MultiItemModifier for Expander {
6060
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the
6161
// paths.
6262
report_path_args(sess, meta);
63+
report_unsafe_args(sess, meta);
6364
meta.path.clone()
6465
})
6566
.map(|path| DeriveResolution {
@@ -159,3 +160,12 @@ fn report_path_args(sess: &Session, meta: &ast::MetaItem) {
159160
}
160161
}
161162
}
163+
164+
fn report_unsafe_args(sess: &Session, meta: &ast::MetaItem) {
165+
match meta.unsafety {
166+
Unsafe::Yes(span) => {
167+
sess.dcx().emit_err(errors::DeriveUnsafePath { span });
168+
}
169+
Unsafe::No => {}
170+
}
171+
}

compiler/rustc_builtin_macros/src/errors.rs

+7
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,13 @@ pub(crate) struct DerivePathArgsValue {
295295
pub(crate) span: Span,
296296
}
297297

298+
#[derive(Diagnostic)]
299+
#[diag(builtin_macros_derive_unsafe_path)]
300+
pub(crate) struct DeriveUnsafePath {
301+
#[primary_span]
302+
pub(crate) span: Span,
303+
}
304+
298305
#[derive(Diagnostic)]
299306
#[diag(builtin_macros_no_default_variant)]
300307
#[help]

compiler/rustc_builtin_macros/src/test_harness.rs

+1
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
202202
let allow_dead_code = attr::mk_attr_nested_word(
203203
&self.sess.psess.attr_id_generator,
204204
ast::AttrStyle::Outer,
205+
ast::Unsafe::No,
205206
sym::allow,
206207
sym::dead_code,
207208
self.def_site,

compiler/rustc_expand/src/build.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -663,20 +663,20 @@ impl<'a> ExtCtxt<'a> {
663663
// Builds `#[name]`.
664664
pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
665665
let g = &self.sess.psess.attr_id_generator;
666-
attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span)
666+
attr::mk_attr_word(g, ast::AttrStyle::Outer, ast::Unsafe::No, name, span)
667667
}
668668

669669
// Builds `#[name = val]`.
670670
//
671671
// Note: `span` is used for both the identifier and the value.
672672
pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
673673
let g = &self.sess.psess.attr_id_generator;
674-
attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span)
674+
attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, ast::Unsafe::No, name, val, span)
675675
}
676676

677677
// Builds `#[outer(inner)]`.
678678
pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
679679
let g = &self.sess.psess.attr_id_generator;
680-
attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span)
680+
attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, ast::Unsafe::No, outer, inner, span)
681681
}
682682
}

compiler/rustc_expand/src/expand.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
778778
if let SyntaxExtensionKind::Derive(..) = ext {
779779
self.gate_proc_macro_input(&item);
780780
}
781-
let meta = ast::MetaItem { kind: MetaItemKind::Word, span, path };
781+
// The `MetaItem` representing the trait to derive can't
782+
// have an unsafe around it (as of now).
783+
let meta = ast::MetaItem {
784+
unsafety: ast::Unsafe::No,
785+
kind: MetaItemKind::Word,
786+
span,
787+
path,
788+
};
782789
let items = match expander.expand(self.cx, span, &meta, item, is_const) {
783790
ExpandResult::Ready(items) => items,
784791
ExpandResult::Retry(item) => {

0 commit comments

Comments
 (0)