Skip to content

Commit 6e534c7

Browse files
authored
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.
2 parents 0acb5b8 + f9104f0 commit 6e534c7

36 files changed

+357
-34
lines changed

compiler/rustc_ast/src/ast.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,7 @@ pub struct Crate {
488488
/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
489489
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
490490
pub struct MetaItem {
491+
pub unsafety: Safety,
491492
pub path: Path,
492493
pub kind: MetaItemKind,
493494
pub span: Span,
@@ -2823,14 +2824,20 @@ pub struct NormalAttr {
28232824
impl NormalAttr {
28242825
pub fn from_ident(ident: Ident) -> Self {
28252826
Self {
2826-
item: AttrItem { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None },
2827+
item: AttrItem {
2828+
unsafety: Safety::Default,
2829+
path: Path::from_ident(ident),
2830+
args: AttrArgs::Empty,
2831+
tokens: None,
2832+
},
28272833
tokens: None,
28282834
}
28292835
}
28302836
}
28312837

28322838
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
28332839
pub struct AttrItem {
2840+
pub unsafety: Safety,
28342841
pub path: Path,
28352842
pub args: AttrArgs,
28362843
// Tokens for the meta item, e.g. just the `foo` within `#[foo]` or `#![foo]`.

compiler/rustc_ast/src/attr/mod.rs

+27-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, Safety,
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};
@@ -238,7 +240,12 @@ impl AttrItem {
238240
}
239241

240242
pub fn meta(&self, span: Span) -> Option<MetaItem> {
241-
Some(MetaItem { path: self.path.clone(), kind: self.meta_kind()?, span })
243+
Some(MetaItem {
244+
unsafety: Safety::Default,
245+
path: self.path.clone(),
246+
kind: self.meta_kind()?,
247+
span,
248+
})
242249
}
243250

244251
pub fn meta_kind(&self) -> Option<MetaItemKind> {
@@ -371,7 +378,10 @@ impl MetaItem {
371378
_ => path.span.hi(),
372379
};
373380
let span = path.span.with_hi(hi);
374-
Some(MetaItem { path, kind, span })
381+
// FIXME: This parses `unsafe()` not as unsafe attribute syntax in `MetaItem`,
382+
// but as a parenthesized list. This (and likely `MetaItem`) should be changed in
383+
// such a way that builtin macros don't accept extraneous `unsafe()`.
384+
Some(MetaItem { unsafety: Safety::Default, path, kind, span })
375385
}
376386
}
377387

@@ -555,11 +565,12 @@ pub fn mk_doc_comment(
555565
pub fn mk_attr(
556566
g: &AttrIdGenerator,
557567
style: AttrStyle,
568+
unsafety: Safety,
558569
path: Path,
559570
args: AttrArgs,
560571
span: Span,
561572
) -> Attribute {
562-
mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
573+
mk_attr_from_item(g, AttrItem { unsafety, path, args, tokens: None }, None, style, span)
563574
}
564575

565576
pub fn mk_attr_from_item(
@@ -577,15 +588,22 @@ pub fn mk_attr_from_item(
577588
}
578589
}
579590

580-
pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
591+
pub fn mk_attr_word(
592+
g: &AttrIdGenerator,
593+
style: AttrStyle,
594+
unsafety: Safety,
595+
name: Symbol,
596+
span: Span,
597+
) -> Attribute {
581598
let path = Path::from_ident(Ident::new(name, span));
582599
let args = AttrArgs::Empty;
583-
mk_attr(g, style, path, args, span)
600+
mk_attr(g, style, unsafety, path, args, span)
584601
}
585602

586603
pub fn mk_attr_nested_word(
587604
g: &AttrIdGenerator,
588605
style: AttrStyle,
606+
unsafety: Safety,
589607
outer: Symbol,
590608
inner: Symbol,
591609
span: Span,
@@ -601,12 +619,13 @@ pub fn mk_attr_nested_word(
601619
delim: Delimiter::Parenthesis,
602620
tokens: inner_tokens,
603621
});
604-
mk_attr(g, style, path, attr_args, span)
622+
mk_attr(g, style, unsafety, path, attr_args, span)
605623
}
606624

607625
pub fn mk_attr_name_value_str(
608626
g: &AttrIdGenerator,
609627
style: AttrStyle,
628+
unsafety: Safety,
610629
name: Symbol,
611630
val: Symbol,
612631
span: Span,
@@ -621,7 +640,7 @@ pub fn mk_attr_name_value_str(
621640
});
622641
let path = Path::from_ident(Ident::new(name, span));
623642
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
624-
mk_attr(g, style, path, args, span)
643+
mk_attr(g, style, unsafety, path, args, span)
625644
}
626645

627646
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)),
@@ -840,7 +842,7 @@ fn visit_nonterminal<T: MutVisitor>(nt: &mut token::Nonterminal, vis: &mut T) {
840842
token::NtTy(ty) => vis.visit_ty(ty),
841843
token::NtLiteral(expr) => vis.visit_expr(expr),
842844
token::NtMeta(item) => {
843-
let AttrItem { path, args, tokens } = item.deref_mut();
845+
let AttrItem { unsafety: _, path, args, tokens } = item.deref_mut();
844846
vis.visit_path(path);
845847
visit_attr_args(args, vis);
846848
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+
Safety::Default,
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
@@ -561,6 +561,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
561561
gate_all!(mut_ref, "mutable by-reference bindings are experimental");
562562
gate_all!(precise_capturing, "precise captures on `impl Trait` are experimental");
563563
gate_all!(global_registration, "global registration is experimental");
564+
gate_all!(unsafe_attributes, "`#[unsafe()]` markers for attributes are experimental");
564565

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

compiler/rustc_ast_pretty/src/pprust/state.rs

+9-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, Safety};
2020
use rustc_ast::{attr, BindingMode, ByRef, DelimArgs, RangeEnd, RangeSyntax, Term};
2121
use rustc_ast::{GenericArg, GenericBound, SelfKind};
2222
use rustc_ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
@@ -249,6 +249,7 @@ pub fn print_crate<'a>(
249249
let fake_attr = attr::mk_attr_nested_word(
250250
g,
251251
ast::AttrStyle::Inner,
252+
Safety::Default,
252253
sym::feature,
253254
sym::prelude_import,
254255
DUMMY_SP,
@@ -259,7 +260,13 @@ pub fn print_crate<'a>(
259260
// root, so this is not needed, and actually breaks things.
260261
if edition.is_rust_2015() {
261262
// `#![no_std]`
262-
let fake_attr = attr::mk_attr_word(g, ast::AttrStyle::Inner, sym::no_std, DUMMY_SP);
263+
let fake_attr = attr::mk_attr_word(
264+
g,
265+
ast::AttrStyle::Inner,
266+
Safety::Default,
267+
sym::no_std,
268+
DUMMY_SP,
269+
);
263270
s.print_attribute(&fake_attr);
264271
}
265272
}

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
@@ -17,7 +17,7 @@ pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) {
1717
));
1818

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

compiler/rustc_builtin_macros/src/derive.rs

+12-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, Safety, StmtKind};
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,13 @@ 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+
Safety::Unsafe(span) => {
167+
sess.dcx().emit_err(errors::DeriveUnsafePath { span });
168+
}
169+
Safety::Default => {}
170+
Safety::Safe(_) => unreachable!(),
171+
}
172+
}

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
@@ -203,6 +203,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
203203
let allow_dead_code = attr::mk_attr_nested_word(
204204
&self.sess.psess.attr_id_generator,
205205
ast::AttrStyle::Outer,
206+
ast::Safety::Default,
206207
sym::allow,
207208
sym::dead_code,
208209
self.def_site,

compiler/rustc_expand/src/build.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -666,20 +666,34 @@ impl<'a> ExtCtxt<'a> {
666666
// Builds `#[name]`.
667667
pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
668668
let g = &self.sess.psess.attr_id_generator;
669-
attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span)
669+
attr::mk_attr_word(g, ast::AttrStyle::Outer, ast::Safety::Default, name, span)
670670
}
671671

672672
// Builds `#[name = val]`.
673673
//
674674
// Note: `span` is used for both the identifier and the value.
675675
pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
676676
let g = &self.sess.psess.attr_id_generator;
677-
attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span)
677+
attr::mk_attr_name_value_str(
678+
g,
679+
ast::AttrStyle::Outer,
680+
ast::Safety::Default,
681+
name,
682+
val,
683+
span,
684+
)
678685
}
679686

680687
// Builds `#[outer(inner)]`.
681688
pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
682689
let g = &self.sess.psess.attr_id_generator;
683-
attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span)
690+
attr::mk_attr_nested_word(
691+
g,
692+
ast::AttrStyle::Outer,
693+
ast::Safety::Default,
694+
outer,
695+
inner,
696+
span,
697+
)
684698
}
685699
}

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::Safety::Default,
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)