Skip to content

Commit 835004a

Browse files
committed
Make attr template suggestions preserve attribute safety.
1 parent 5ea817c commit 835004a

4 files changed

Lines changed: 40 additions & 11 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,11 @@ pub fn parse_cfg_attr(
327327
}) {
328328
Ok(r) => return Some(r),
329329
Err(e) => {
330-
let suggestions = CFG_ATTR_TEMPLATE
331-
.suggestions(AttrSuggestionStyle::Attribute(cfg_attr.style), sym::cfg_attr);
330+
let suggestions = CFG_ATTR_TEMPLATE.suggestions(
331+
AttrSuggestionStyle::Attribute(cfg_attr.style),
332+
matches!(cfg_attr.get_normal_item().unsafety, rustc_ast::Safety::Unsafe(_)),
333+
sym::cfg_attr,
334+
);
332335
e.with_span_suggestions(
333336
cfg_attr.span,
334337
"must be of the form",
@@ -360,8 +363,11 @@ pub fn parse_cfg_attr(
360363
description: ParsedDescription::Attribute,
361364
reason,
362365
suggestions: session_diagnostics::AttributeParseErrorSuggestions::CreatedByTemplate(
363-
CFG_ATTR_TEMPLATE
364-
.suggestions(AttrSuggestionStyle::Attribute(cfg_attr.style), sym::cfg_attr),
366+
CFG_ATTR_TEMPLATE.suggestions(
367+
AttrSuggestionStyle::Attribute(cfg_attr.style),
368+
matches!(cfg_attr.get_normal_item().unsafety, rustc_ast::Safety::Unsafe(_)),
369+
sym::cfg_attr,
370+
),
365371
),
366372
});
367373
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::mem;
55
use std::ops::{Deref, DerefMut};
66
use std::sync::LazyLock;
77

8-
use rustc_ast::{AttrStyle, MetaItemLit};
8+
use rustc_ast::{AttrStyle, MetaItemLit, Safety};
99
use rustc_data_structures::sync::{DynSend, DynSync};
1010
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan};
1111
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate};
@@ -357,6 +357,9 @@ pub struct AcceptContext<'f, 'sess> {
357357
/// Used in reporting errors to give a hint to users what the attribute *should* look like.
358358
pub(crate) template: &'f AttributeTemplate,
359359

360+
/// The safety attribute (if any) applied to the attribute.
361+
pub(crate) attr_safety: rustc_ast::Safety,
362+
360363
/// The name of the attribute we're currently accepting.
361364
pub(crate) attr_path: AttrPath,
362365
}
@@ -873,7 +876,11 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {
873876
ParsedDescription::Macro => AttrSuggestionStyle::Macro,
874877
};
875878

876-
self.template.suggestions(style, &self.attr_path)
879+
self.template.suggestions(
880+
style,
881+
matches!(self.attr_safety, rustc_ast::Safety::Unsafe(_)),
882+
&self.attr_path,
883+
)
877884
}
878885
}
879886

@@ -1064,7 +1071,11 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {
10641071
ParsedDescription::Macro => AttrSuggestionStyle::Macro,
10651072
};
10661073

1067-
self.template.suggestions(style, &self.attr_path)
1074+
self.template.suggestions(
1075+
style,
1076+
matches!(self.attr_safety, Safety::Unsafe(_)),
1077+
&self.attr_path,
1078+
)
10681079
}
10691080
/// Error that a string literal was expected.
10701081
/// You can optionally give the literal you did find (which you found not to be a string literal)

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ impl<'sess> AttributeParser<'sess> {
234234
attr_style,
235235
parsed_description,
236236
template,
237+
attr_safety: attr_safety.unwrap_or(Safety::Default),
237238
attr_path,
238239
};
239240
parse_fn(&mut cx, args)
@@ -404,6 +405,7 @@ impl<'sess> AttributeParser<'sess> {
404405
attr_style: attr.style,
405406
parsed_description: ParsedDescription::Attribute,
406407
template: &accept.template,
408+
attr_safety: n.item.unsafety,
407409
attr_path: attr_path.clone(),
408410
};
409411

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ impl AttributeTemplate {
118118
pub fn suggestions(
119119
&self,
120120
style: AttrSuggestionStyle,
121+
wrap_with_unsafe: bool,
121122
name: impl std::fmt::Display,
122123
) -> Vec<String> {
123124
let (start, macro_call, end) = match style {
@@ -129,20 +130,29 @@ impl AttributeTemplate {
129130

130131
let mut suggestions = vec![];
131132

133+
let (maybe_unsafe_start, maybe_unsafe_end) =
134+
if wrap_with_unsafe { ("unsafe(", ")") } else { ("", "") };
135+
132136
if self.word {
133137
debug_assert!(macro_call.is_empty(), "Macro suggestions use list style");
134-
suggestions.push(format!("{start}{name}{end}"));
138+
suggestions.push(format!("{maybe_unsafe_start}{start}{name}{end}{maybe_unsafe_end}"));
135139
}
136140
if let Some(descr) = self.list {
137141
for descr in descr {
138-
suggestions.push(format!("{start}{name}{macro_call}({descr}){end}"));
142+
suggestions.push(format!(
143+
"{maybe_unsafe_start}{start}{name}{macro_call}({descr}){end}{maybe_unsafe_end}"
144+
));
139145
}
140146
}
141-
suggestions.extend(self.one_of.iter().map(|&word| format!("{start}{name}({word}){end}")));
147+
suggestions.extend(self.one_of.iter().map(|&word| {
148+
format!("{maybe_unsafe_start}{start}{name}({word}){end}{maybe_unsafe_end}")
149+
}));
142150
if let Some(descr) = self.name_value_str {
143151
debug_assert!(macro_call.is_empty(), "Macro suggestions use list style");
144152
for descr in descr {
145-
suggestions.push(format!("{start}{name} = \"{descr}\"{end}"));
153+
suggestions.push(format!(
154+
"{maybe_unsafe_start}{start}{name} = \"{descr}\"{end}{maybe_unsafe_end}"
155+
));
146156
}
147157
}
148158
suggestions.sort();

0 commit comments

Comments
 (0)