Skip to content

Commit f84347a

Browse files
Rollup merge of #156791 - obi1kenobi:unsafe-kept-in-help-text, r=JonathanBrouwer,Kivooeo
Unsafe kept in help text Currently when encountering a malformed attribute, the compiler will suggest removing unsafe in the well-formed template even when unsafe is required. This PR preserves whatever unsafe (or lack) exists in the user's code. r? @jdonszelmann
2 parents 8162cf5 + 970cb15 commit f84347a

7 files changed

Lines changed: 43 additions & 17 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4010,6 +4010,7 @@ dependencies = [
40104010
name = "rustc_feature"
40114011
version = "0.0.0"
40124012
dependencies = [
4013+
"rustc_ast",
40134014
"rustc_data_structures",
40144015
"rustc_hir",
40154016
"rustc_span",

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+
cfg_attr.get_normal_item().unsafety,
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+
cfg_attr.get_normal_item().unsafety,
369+
sym::cfg_attr,
370+
),
365371
),
366372
});
367373
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 6 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: Safety,
362+
360363
/// The name of the attribute we're currently accepting.
361364
pub(crate) attr_path: AttrPath,
362365
}
@@ -873,7 +876,7 @@ 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(style, self.attr_safety, &self.attr_path)
877880
}
878881
}
879882

@@ -1064,7 +1067,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {
10641067
ParsedDescription::Macro => AttrSuggestionStyle::Macro,
10651068
};
10661069

1067-
self.template.suggestions(style, &self.attr_path)
1070+
self.template.suggestions(style, self.attr_safety, &self.attr_path)
10681071
}
10691072
/// Error that a string literal was expected.
10701073
/// 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/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2024"
55

66
[dependencies]
77
# tidy-alphabetical-start
8+
rustc_ast = { path = "../rustc_ast" }
89
rustc_data_structures = { path = "../rustc_data_structures" }
910
rustc_hir = { path = "../rustc_hir" }
1011
rustc_span = { path = "../rustc_span" }

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::sync::LazyLock;
44

55
use AttributeGate::*;
6+
use rustc_ast::ast::Safety;
67
use rustc_data_structures::fx::FxHashMap;
78
use rustc_hir::AttrStyle;
89
use rustc_span::{Symbol, sym};
@@ -113,6 +114,7 @@ impl AttributeTemplate {
113114
pub fn suggestions(
114115
&self,
115116
style: AttrSuggestionStyle,
117+
safety: Safety,
116118
name: impl std::fmt::Display,
117119
) -> Vec<String> {
118120
let (start, macro_call, end) = match style {
@@ -124,20 +126,32 @@ impl AttributeTemplate {
124126

125127
let mut suggestions = vec![];
126128

129+
let (safety_start, safety_end) = match safety {
130+
Safety::Unsafe(_) => ("unsafe(", ")"),
131+
_ => ("", ""),
132+
};
133+
127134
if self.word {
128135
debug_assert!(macro_call.is_empty(), "Macro suggestions use list style");
129-
suggestions.push(format!("{start}{name}{end}"));
136+
suggestions.push(format!("{start}{safety_start}{name}{safety_end}{end}"));
130137
}
131138
if let Some(descr) = self.list {
132139
for descr in descr {
133-
suggestions.push(format!("{start}{name}{macro_call}({descr}){end}"));
140+
suggestions.push(format!(
141+
"{start}{safety_start}{name}{macro_call}({descr}){safety_end}{end}"
142+
));
134143
}
135144
}
136-
suggestions.extend(self.one_of.iter().map(|&word| format!("{start}{name}({word}){end}")));
145+
suggestions.extend(
146+
self.one_of
147+
.iter()
148+
.map(|&word| format!("{start}{safety_start}{name}({word}){safety_end}{end}")),
149+
);
137150
if let Some(descr) = self.name_value_str {
138151
debug_assert!(macro_call.is_empty(), "Macro suggestions use list style");
139152
for descr in descr {
140-
suggestions.push(format!("{start}{name} = \"{descr}\"{end}"));
153+
suggestions
154+
.push(format!("{start}{safety_start}{name} = \"{descr}\"{safety_end}{end}"));
141155
}
142156
}
143157
suggestions.sort();

tests/ui/attributes/malformed-attrs.stderr

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,8 @@ LL | #[unsafe(export_name)]
159159
|
160160
help: must be of the form
161161
|
162-
LL - #[unsafe(export_name)]
163-
LL + #[export_name = "name"]
164-
|
162+
LL | #[unsafe(export_name = "name")]
163+
| ++++++++
165164

166165
error: `rustc_allow_const_fn_unstable` expects a list of feature names
167166
--> $DIR/malformed-attrs.rs:31:1
@@ -330,7 +329,7 @@ LL | #[unsafe(naked())]
330329
help: must be of the form
331330
|
332331
LL - #[unsafe(naked())]
333-
LL + #[naked]
332+
LL + #[unsafe(naked)]
334333
|
335334

336335
error[E0565]: malformed `track_caller` attribute input
@@ -651,7 +650,7 @@ LL | #[unsafe(ffi_pure = 1)]
651650
help: must be of the form
652651
|
653652
LL - #[unsafe(ffi_pure = 1)]
654-
LL + #[ffi_pure]
653+
LL + #[unsafe(ffi_pure)]
655654
|
656655

657656
error[E0539]: malformed `link_ordinal` attribute input
@@ -677,7 +676,7 @@ LL | #[unsafe(ffi_const = 1)]
677676
help: must be of the form
678677
|
679678
LL - #[unsafe(ffi_const = 1)]
680-
LL + #[ffi_const]
679+
LL + #[unsafe(ffi_const)]
681680
|
682681

683682
error[E0539]: malformed `linkage` attribute input

0 commit comments

Comments
 (0)