Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit eb3a8e5

Browse filesBrowse files
committed
Make attribute safety validation logic more obvious
1 parent 622ac04 commit eb3a8e5
Copy full SHA for eb3a8e5

File tree

Expand file treeCollapse file tree

5 files changed

+91
-15
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+91
-15
lines changed

‎compiler/rustc_expand/src/config.rs

Copy file name to clipboardExpand all lines: compiler/rustc_expand/src/config.rs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ impl<'a> StripUnconfigured<'a> {
276276
pub(crate) fn expand_cfg_attr(&self, cfg_attr: &Attribute, recursive: bool) -> Vec<Attribute> {
277277
validate_attr::check_attribute_safety(
278278
&self.sess.psess,
279-
AttributeSafety::Normal,
279+
Some(AttributeSafety::Normal),
280280
&cfg_attr,
281281
ast::CRATE_NODE_ID,
282282
);

‎compiler/rustc_parse/src/validate_attr.rs

Copy file name to clipboardExpand all lines: compiler/rustc_parse/src/validate_attr.rs
+47-14Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute, id: NodeId) {
2222
return;
2323
}
2424

25-
let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
26-
let attr_item = attr.get_normal_item();
25+
let builtin_attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
2726

28-
// All non-builtin attributes are considered safe
29-
let safety = attr_info.map(|x| x.safety).unwrap_or(AttributeSafety::Normal);
30-
check_attribute_safety(psess, safety, attr, id);
27+
let builtin_attr_safety = builtin_attr_info.map(|x| x.safety);
28+
check_attribute_safety(psess, builtin_attr_safety, attr, id);
3129

3230
// Check input tokens for built-in and key-value attributes.
33-
match attr_info {
31+
match builtin_attr_info {
3432
// `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
3533
Some(BuiltinAttribute { name, template, .. }) if *name != sym::rustc_dummy => {
3634
match parse_meta(psess, attr) {
@@ -44,6 +42,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute, id: NodeId) {
4442
}
4543
}
4644
_ => {
45+
let attr_item = attr.get_normal_item();
4746
if let AttrArgs::Eq { .. } = attr_item.args {
4847
// All key-value attributes are restricted to meta-item syntax.
4948
match parse_meta(psess, attr) {
@@ -157,14 +156,21 @@ fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaIte
157156

158157
pub fn check_attribute_safety(
159158
psess: &ParseSess,
160-
safety: AttributeSafety,
159+
builtin_attr_safety: Option<AttributeSafety>,
161160
attr: &Attribute,
162161
id: NodeId,
163162
) {
164163
let attr_item = attr.get_normal_item();
164+
match (builtin_attr_safety, attr_item.unsafety) {
165+
// - Unsafe builtin attribute
166+
// - User wrote `#[unsafe(..)]`, which is permitted on any edition
167+
(Some(AttributeSafety::Unsafe { .. }), Safety::Unsafe(..)) => {
168+
// OK
169+
}
165170

166-
if let AttributeSafety::Unsafe { unsafe_since } = safety {
167-
if let ast::Safety::Default = attr_item.unsafety {
171+
// - Unsafe builtin attribute
172+
// - User did not write `#[unsafe(..)]`
173+
(Some(AttributeSafety::Unsafe { unsafe_since }), Safety::Default) => {
168174
let path_span = attr_item.path.span;
169175

170176
// If the `attr_item`'s span is not from a macro, then just suggest
@@ -199,11 +205,38 @@ pub fn check_attribute_safety(
199205
);
200206
}
201207
}
202-
} else if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
203-
psess.dcx().emit_err(errors::InvalidAttrUnsafe {
204-
span: unsafe_span,
205-
name: attr_item.path.clone(),
206-
});
208+
209+
// - Normal builtin attribute, or any non-builtin attribute
210+
// - All non-builtin attributes are currently considered safe; writing `#[unsafe(..)]` is
211+
// not permitted on non-builtin attributes or normal builtin attributes
212+
(Some(AttributeSafety::Normal) | None, Safety::Unsafe(unsafe_span)) => {
213+
psess.dcx().emit_err(errors::InvalidAttrUnsafe {
214+
span: unsafe_span,
215+
name: attr_item.path.clone(),
216+
});
217+
}
218+
219+
// - Normal builtin attribute
220+
// - No explicit `#[unsafe(..)]` written.
221+
(Some(AttributeSafety::Normal), Safety::Default) => {
222+
// OK
223+
}
224+
225+
// - Non-builtin attribute
226+
// - No explicit `#[unsafe(..)]` written.
227+
(None, Safety::Default) => {
228+
// OK
229+
}
230+
231+
(
232+
Some(AttributeSafety::Unsafe { .. } | AttributeSafety::Normal) | None,
233+
Safety::Safe(..),
234+
) => {
235+
psess.dcx().span_delayed_bug(
236+
attr_item.span(),
237+
"`check_attribute_safety` does not expect `Safety::Safe` on attributes",
238+
);
239+
}
207240
}
208241
}
209242

+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extern crate proc_macro;
2+
use proc_macro::TokenStream;
3+
4+
#[proc_macro_attribute]
5+
pub fn safe(_attr: TokenStream, item: TokenStream) -> TokenStream {
6+
item
7+
}
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//! Anti-regression test for `#[safe]` proc-macro attribute.
2+
3+
//@ revisions: unknown_attr proc_macro_attr
4+
//@[proc_macro_attr] proc-macro: safe_attr.rs
5+
//@[proc_macro_attr] check-pass
6+
7+
#![warn(unsafe_attr_outside_unsafe)]
8+
9+
#[cfg(proc_macro_attr)]
10+
extern crate safe_attr;
11+
#[cfg(proc_macro_attr)]
12+
use safe_attr::safe;
13+
14+
#[safe]
15+
//[unknown_attr]~^ ERROR cannot find attribute `safe` in this scope
16+
fn foo() {}
17+
18+
#[safe(no_mangle)]
19+
//[unknown_attr]~^ ERROR cannot find attribute `safe` in this scope
20+
fn bar() {}
21+
22+
fn main() {}
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: cannot find attribute `safe` in this scope
2+
--> $DIR/safe-proc-macro-attribute.rs:18:3
3+
|
4+
LL | #[safe(no_mangle)]
5+
| ^^^^
6+
7+
error: cannot find attribute `safe` in this scope
8+
--> $DIR/safe-proc-macro-attribute.rs:14:3
9+
|
10+
LL | #[safe]
11+
| ^^^^
12+
13+
error: aborting due to 2 previous errors
14+

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.