Skip to content

Commit f3f7d41

Browse files
committed
Parse unsafe attributes
1 parent f6e4703 commit f3f7d41

File tree

19 files changed

+173
-27
lines changed

19 files changed

+173
-27
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 8 additions & 1 deletion
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,
@@ -2810,14 +2811,20 @@ pub struct NormalAttr {
28102811
impl NormalAttr {
28112812
pub fn from_ident(ident: Ident) -> Self {
28122813
Self {
2813-
item: AttrItem { path: Path::from_ident(ident), args: AttrArgs::Empty, tokens: None },
2814+
item: AttrItem {
2815+
unsafety: Unsafe::No,
2816+
path: Path::from_ident(ident),
2817+
args: AttrArgs::Empty,
2818+
tokens: None,
2819+
},
28142820
tokens: None,
28152821
}
28162822
}
28172823
}
28182824

28192825
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
28202826
pub struct AttrItem {
2827+
pub unsafety: Unsafe,
28212828
pub path: Path,
28222829
pub args: AttrArgs,
28232830
// Tokens for the meta item, e.g. just the `foo` within `#[foo]` or `#![foo]`.

compiler/rustc_ast/src/attr/mod.rs

Lines changed: 25 additions & 8 deletions
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};
@@ -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: Unsafe::No,
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,8 @@ impl MetaItem {
371378
_ => path.span.hi(),
372379
};
373380
let span = path.span.with_hi(hi);
374-
Some(MetaItem { path, kind, span })
381+
// FIX THIS LATER
382+
Some(MetaItem { unsafety: Unsafe::No, path, kind, span })
375383
}
376384
}
377385

@@ -555,11 +563,12 @@ pub fn mk_doc_comment(
555563
pub fn mk_attr(
556564
g: &AttrIdGenerator,
557565
style: AttrStyle,
566+
unsafety: Unsafe,
558567
path: Path,
559568
args: AttrArgs,
560569
span: Span,
561570
) -> Attribute {
562-
mk_attr_from_item(g, AttrItem { path, args, tokens: None }, None, style, span)
571+
mk_attr_from_item(g, AttrItem { unsafety, path, args, tokens: None }, None, style, span)
563572
}
564573

565574
pub fn mk_attr_from_item(
@@ -577,15 +586,22 @@ pub fn mk_attr_from_item(
577586
}
578587
}
579588

580-
pub fn mk_attr_word(g: &AttrIdGenerator, style: AttrStyle, name: Symbol, span: Span) -> Attribute {
589+
pub fn mk_attr_word(
590+
g: &AttrIdGenerator,
591+
style: AttrStyle,
592+
unsafety: Unsafe,
593+
name: Symbol,
594+
span: Span,
595+
) -> Attribute {
581596
let path = Path::from_ident(Ident::new(name, span));
582597
let args = AttrArgs::Empty;
583-
mk_attr(g, style, path, args, span)
598+
mk_attr(g, style, unsafety, path, args, span)
584599
}
585600

586601
pub fn mk_attr_nested_word(
587602
g: &AttrIdGenerator,
588603
style: AttrStyle,
604+
unsafety: Unsafe,
589605
outer: Symbol,
590606
inner: Symbol,
591607
span: Span,
@@ -601,12 +617,13 @@ pub fn mk_attr_nested_word(
601617
delim: Delimiter::Parenthesis,
602618
tokens: inner_tokens,
603619
});
604-
mk_attr(g, style, path, attr_args, span)
620+
mk_attr(g, style, unsafety, path, attr_args, span)
605621
}
606622

607623
pub fn mk_attr_name_value_str(
608624
g: &AttrIdGenerator,
609625
style: AttrStyle,
626+
unsafety: Unsafe,
610627
name: Symbol,
611628
val: Symbol,
612629
span: Span,
@@ -621,7 +638,7 @@ pub fn mk_attr_name_value_str(
621638
});
622639
let path = Path::from_ident(Ident::new(name, span));
623640
let args = AttrArgs::Eq(span, AttrArgsEq::Ast(expr));
624-
mk_attr(g, style, path, args, span)
641+
mk_attr(g, style, unsafety, path, args, span)
625642
}
626643

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

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 6 additions & 4 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 4 additions & 2 deletions
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};
@@ -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+
Unsafe::No,
252253
sym::feature,
253254
sym::prelude_import,
254255
DUMMY_SP,
@@ -259,7 +260,8 @@ 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 =
264+
attr::mk_attr_word(g, ast::AttrStyle::Inner, Unsafe::No, sym::no_std, DUMMY_SP);
263265
s.print_attribute(&fake_attr);
264266
}
265267
}

compiler/rustc_builtin_macros/src/cmdline_attrs.rs

Lines changed: 2 additions & 1 deletion
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/test_harness.rs

Lines changed: 1 addition & 0 deletions
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::Unsafe::No,
206207
sym::allow,
207208
sym::dead_code,
208209
self.def_site,

compiler/rustc_expand/src/build.rs

Lines changed: 3 additions & 3 deletions
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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,13 @@ 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+
// FIX THIS LATER
782+
let meta = ast::MetaItem {
783+
unsafety: ast::Unsafe::No,
784+
kind: MetaItemKind::Word,
785+
span,
786+
path,
787+
};
782788
let items = match expander.expand(self.cx, span, &meta, item, is_const) {
783789
ExpandResult::Ready(items) => items,
784790
ExpandResult::Retry(item) => {

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,17 @@ pub enum AttributeType {
5959
CrateLevel,
6060
}
6161

62+
#[derive(Copy, Clone, PartialEq, Debug)]
63+
#[allow(dead_code)]
64+
pub enum AttributeSafety {
65+
/// Normal attribute that does not need `#[unsafe(...)]`
66+
Normal,
67+
68+
/// Unsafe attribute that requires safety obligations
69+
/// to be discharged
70+
Unsafe,
71+
}
72+
6273
#[derive(Clone, Copy)]
6374
pub enum AttributeGate {
6475
/// Is gated by a given feature gate, reason
@@ -177,6 +188,18 @@ macro_rules! ungated {
177188
name: sym::$attr,
178189
encode_cross_crate: $encode_cross_crate,
179190
type_: $typ,
191+
safety: AttributeSafety::Normal,
192+
template: $tpl,
193+
gate: Ungated,
194+
duplicates: $duplicates,
195+
}
196+
};
197+
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
198+
BuiltinAttribute {
199+
name: sym::$attr,
200+
encode_cross_crate: $encode_cross_crate,
201+
type_: $typ,
202+
safety: AttributeSafety::Unsafe,
180203
template: $tpl,
181204
gate: Ungated,
182205
duplicates: $duplicates,
@@ -190,6 +213,7 @@ macro_rules! gated {
190213
name: sym::$attr,
191214
encode_cross_crate: $encode_cross_crate,
192215
type_: $typ,
216+
safety: AttributeSafety::Normal,
193217
template: $tpl,
194218
duplicates: $duplicates,
195219
gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
@@ -200,6 +224,29 @@ macro_rules! gated {
200224
name: sym::$attr,
201225
encode_cross_crate: $encode_cross_crate,
202226
type_: $typ,
227+
safety: AttributeSafety::Normal,
228+
template: $tpl,
229+
duplicates: $duplicates,
230+
gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
231+
}
232+
};
233+
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $msg:expr $(,)?) => {
234+
BuiltinAttribute {
235+
name: sym::$attr,
236+
encode_cross_crate: $encode_cross_crate,
237+
type_: $typ,
238+
safety: AttributeSafety::Unsafe,
239+
template: $tpl,
240+
duplicates: $duplicates,
241+
gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
242+
}
243+
};
244+
(unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $msg:expr $(,)?) => {
245+
BuiltinAttribute {
246+
name: sym::$attr,
247+
encode_cross_crate: $encode_cross_crate,
248+
type_: $typ,
249+
safety: AttributeSafety::Unsafe,
203250
template: $tpl,
204251
duplicates: $duplicates,
205252
gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
@@ -228,6 +275,7 @@ macro_rules! rustc_attr {
228275
name: sym::$attr,
229276
encode_cross_crate: $encode_cross_crate,
230277
type_: $typ,
278+
safety: AttributeSafety::Normal,
231279
template: $tpl,
232280
duplicates: $duplicates,
233281
gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)),
@@ -258,6 +306,7 @@ pub struct BuiltinAttribute {
258306
/// Otherwise, it can only be used in the local crate.
259307
pub encode_cross_crate: EncodeCrossCrate,
260308
pub type_: AttributeType,
309+
pub safety: AttributeSafety,
261310
pub template: AttributeTemplate,
262311
pub duplicates: AttributeDuplicates,
263312
pub gate: AttributeGate,
@@ -375,9 +424,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
375424
),
376425
ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
377426
ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No),
378-
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
379-
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
380-
ungated!(no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
427+
ungated!(unsafe export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
428+
ungated!(unsafe link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
429+
ungated!(unsafe no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
381430
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No),
382431
ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes),
383432

@@ -844,6 +893,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
844893
// FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
845894
encode_cross_crate: EncodeCrossCrate::Yes,
846895
type_: Normal,
896+
safety: AttributeSafety::Normal,
847897
template: template!(NameValueStr: "name"),
848898
duplicates: ErrorFollowing,
849899
gate: Gated(

compiler/rustc_feature/src/unstable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,7 @@ declare_features! (
627627
/// Allows unnamed fields of struct and union type
628628
(incomplete, unnamed_fields, "1.74.0", Some(49804)),
629629
/// Allows unsized fn parameters.
630+
(unstable, unsafe_attributes, "CURRENT_RUSTC_VERSION", Some(123757)),
630631
(unstable, unsized_fn_params, "1.49.0", Some(48055)),
631632
/// Allows unsized rvalues at arguments and parameters.
632633
(incomplete, unsized_locals, "1.30.0", Some(48055)),

0 commit comments

Comments
 (0)