Skip to content

Commit d747e47

Browse files
authored
Unrolled build for #148000
Rollup merge of #148000 - JonathanBrouwer:wipnew2, r=jdonszelmann Improvements to attribute suggestions Changes in commit 1: - Add `AcceptContext::suggestions`, which retrieves the suggestions for the currently parsing attribute - This happens to fix a bug in the way `#[macro_export`]. Closes #147987 Changes in commit 2: - Add a check to the suggestions function so the suggestions for attributes in cfg_attr are nicer. Fixes #147693 This is also part (but not all) of the changes needed to unblock #147945 r? `@jdonszelmann`
2 parents 79966ae + 24502dd commit d747e47

File tree

14 files changed

+84
-73
lines changed

14 files changed

+84
-73
lines changed

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ pub fn parse_cfg_attr(
326326
}) {
327327
Ok(r) => return Some(r),
328328
Err(e) => {
329-
let suggestions = CFG_ATTR_TEMPLATE.suggestions(cfg_attr.style, sym::cfg_attr);
329+
let suggestions =
330+
CFG_ATTR_TEMPLATE.suggestions(Some(cfg_attr.style), sym::cfg_attr);
330331
e.with_span_suggestions(
331332
cfg_attr.span,
332333
"must be of the form",
@@ -356,7 +357,7 @@ pub fn parse_cfg_attr(
356357
template: CFG_ATTR_TEMPLATE,
357358
attribute: AttrPath::from_ast(&cfg_attr.get_normal_item().path),
358359
reason,
359-
attr_style: cfg_attr.style,
360+
suggestions: CFG_ATTR_TEMPLATE.suggestions(Some(cfg_attr.style), sym::cfg_attr),
360361
});
361362
}
362363
}
@@ -388,6 +389,7 @@ fn parse_cfg_attr_internal<'a>(
388389
let cfg_predicate = AttributeParser::parse_single_args(
389390
sess,
390391
attribute.span,
392+
attribute.get_normal_item().span(),
391393
attribute.style,
392394
AttrPath {
393395
segments: attribute

compiler/rustc_attr_parsing/src/attributes/inline.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ impl<S: Stage> SingleAttributeParser<S> for InlineParser {
5656
}
5757
}
5858
ArgParser::NameValue(_) => {
59-
let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
60-
.suggestions(cx.attr_style, "inline");
59+
let suggestions = cx.suggestions();
6160
let span = cx.attr_span;
6261
cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
6362
return None;

compiler/rustc_attr_parsing/src/attributes/link_attrs.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ impl<S: Stage> CombineAttributeParser<S> for LinkParser {
7171
// Specifically `#[link = "dl"]` is accepted with a FCW
7272
// For more information, see https://github.com/rust-lang/rust/pull/143193
7373
ArgParser::NameValue(nv) if nv.value_as_str().is_some_and(|v| v == sym::dl) => {
74-
let suggestions = <Self as CombineAttributeParser<S>>::TEMPLATE
75-
.suggestions(cx.attr_style, "link");
74+
let suggestions = cx.suggestions();
7675
let span = cx.attr_span;
7776
cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
7877
return None;

compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use rustc_ast::AttrStyle;
21
use rustc_errors::DiagArgValue;
32
use rustc_hir::attrs::MacroUseArgs;
43

@@ -102,7 +101,7 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser {
102101
}
103102
}
104103
ArgParser::NameValue(_) => {
105-
let suggestions = MACRO_USE_TEMPLATE.suggestions(cx.attr_style, sym::macro_use);
104+
let suggestions = cx.suggestions();
106105
cx.emit_err(IllFormedAttributeInputLint {
107106
num_suggestions: suggestions.len(),
108107
suggestions: DiagArgValue::StrListSepByAnd(
@@ -149,19 +148,14 @@ impl<S: Stage> SingleAttributeParser<S> for MacroExportParser {
149148
]);
150149

151150
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
152-
let suggestions = || {
153-
<Self as SingleAttributeParser<S>>::TEMPLATE
154-
.suggestions(AttrStyle::Inner, "macro_export")
155-
};
156151
let local_inner_macros = match args {
157152
ArgParser::NoArgs => false,
158153
ArgParser::List(list) => {
159154
let Some(l) = list.single() else {
160155
let span = cx.attr_span;
156+
let suggestions = cx.suggestions();
161157
cx.emit_lint(
162-
AttributeLintKind::InvalidMacroExportArguments {
163-
suggestions: suggestions(),
164-
},
158+
AttributeLintKind::InvalidMacroExportArguments { suggestions },
165159
span,
166160
);
167161
return None;
@@ -170,10 +164,9 @@ impl<S: Stage> SingleAttributeParser<S> for MacroExportParser {
170164
Some(sym::local_inner_macros) => true,
171165
_ => {
172166
let span = cx.attr_span;
167+
let suggestions = cx.suggestions();
173168
cx.emit_lint(
174-
AttributeLintKind::InvalidMacroExportArguments {
175-
suggestions: suggestions(),
176-
},
169+
AttributeLintKind::InvalidMacroExportArguments { suggestions },
177170
span,
178171
);
179172
return None;
@@ -182,7 +175,7 @@ impl<S: Stage> SingleAttributeParser<S> for MacroExportParser {
182175
}
183176
ArgParser::NameValue(_) => {
184177
let span = cx.attr_span;
185-
let suggestions = suggestions();
178+
let suggestions = cx.suggestions();
186179
cx.emit_err(IllFormedAttributeInputLint {
187180
num_suggestions: suggestions.len(),
188181
suggestions: DiagArgValue::StrListSepByAnd(

compiler/rustc_attr_parsing/src/attributes/must_use.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
4545
Some(value_str)
4646
}
4747
ArgParser::List(_) => {
48-
let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
49-
.suggestions(cx.attr_style, "must_use");
48+
let suggestions = cx.suggestions();
5049
cx.emit_err(IllFormedAttributeInputLint {
5150
num_suggestions: suggestions.len(),
5251
suggestions: DiagArgValue::StrListSepByAnd(

compiler/rustc_attr_parsing/src/attributes/test_attrs.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
2020
ArgParser::NoArgs => None,
2121
ArgParser::NameValue(name_value) => {
2222
let Some(str_value) = name_value.value_as_str() else {
23-
let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
24-
.suggestions(cx.attr_style, "ignore");
23+
let suggestions = cx.suggestions();
2524
let span = cx.attr_span;
2625
cx.emit_lint(
2726
AttributeLintKind::IllFormedAttributeInput { suggestions },
@@ -32,8 +31,7 @@ impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {
3231
Some(str_value)
3332
}
3433
ArgParser::List(_) => {
35-
let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
36-
.suggestions(cx.attr_style, "ignore");
34+
let suggestions = cx.suggestions();
3735
let span = cx.attr_span;
3836
cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span);
3937
return None;

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,16 @@ pub struct Late;
337337
/// Gives [`AttributeParser`]s enough information to create errors, for example.
338338
pub struct AcceptContext<'f, 'sess, S: Stage> {
339339
pub(crate) shared: SharedContext<'f, 'sess, S>,
340-
/// The span of the attribute currently being parsed
340+
341+
/// The outer span of the attribute currently being parsed
342+
/// #[attribute(...)]
343+
/// ^^^^^^^^^^^^^^^^^ outer span
344+
/// For attributes in `cfg_attr`, the outer span and inner spans are equal.
341345
pub(crate) attr_span: Span,
346+
/// The inner span of the attribute currently being parsed
347+
/// #[attribute(...)]
348+
/// ^^^^^^^^^^^^^^ inner span
349+
pub(crate) inner_span: Span,
342350

343351
/// Whether it is an inner or outer attribute
344352
pub(crate) attr_style: AttrStyle,
@@ -427,7 +435,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
427435
i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
428436
}),
429437
},
430-
attr_style: self.attr_style,
438+
suggestions: self.suggestions(),
431439
})
432440
}
433441

@@ -438,7 +446,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
438446
template: self.template.clone(),
439447
attribute: self.attr_path.clone(),
440448
reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
441-
attr_style: self.attr_style,
449+
suggestions: self.suggestions(),
442450
})
443451
}
444452

@@ -449,7 +457,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
449457
template: self.template.clone(),
450458
attribute: self.attr_path.clone(),
451459
reason: AttributeParseErrorReason::ExpectedList,
452-
attr_style: self.attr_style,
460+
suggestions: self.suggestions(),
453461
})
454462
}
455463

@@ -460,7 +468,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
460468
template: self.template.clone(),
461469
attribute: self.attr_path.clone(),
462470
reason: AttributeParseErrorReason::ExpectedNoArgs,
463-
attr_style: self.attr_style,
471+
suggestions: self.suggestions(),
464472
})
465473
}
466474

@@ -472,7 +480,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
472480
template: self.template.clone(),
473481
attribute: self.attr_path.clone(),
474482
reason: AttributeParseErrorReason::ExpectedIdentifier,
475-
attr_style: self.attr_style,
483+
suggestions: self.suggestions(),
476484
})
477485
}
478486

@@ -485,7 +493,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
485493
template: self.template.clone(),
486494
attribute: self.attr_path.clone(),
487495
reason: AttributeParseErrorReason::ExpectedNameValue(name),
488-
attr_style: self.attr_style,
496+
suggestions: self.suggestions(),
489497
})
490498
}
491499

@@ -497,7 +505,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
497505
template: self.template.clone(),
498506
attribute: self.attr_path.clone(),
499507
reason: AttributeParseErrorReason::DuplicateKey(key),
500-
attr_style: self.attr_style,
508+
suggestions: self.suggestions(),
501509
})
502510
}
503511

@@ -510,7 +518,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
510518
template: self.template.clone(),
511519
attribute: self.attr_path.clone(),
512520
reason: AttributeParseErrorReason::UnexpectedLiteral,
513-
attr_style: self.attr_style,
521+
suggestions: self.suggestions(),
514522
})
515523
}
516524

@@ -521,7 +529,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
521529
template: self.template.clone(),
522530
attribute: self.attr_path.clone(),
523531
reason: AttributeParseErrorReason::ExpectedSingleArgument,
524-
attr_style: self.attr_style,
532+
suggestions: self.suggestions(),
525533
})
526534
}
527535

@@ -532,7 +540,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
532540
template: self.template.clone(),
533541
attribute: self.attr_path.clone(),
534542
reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
535-
attr_style: self.attr_style,
543+
suggestions: self.suggestions(),
536544
})
537545
}
538546

@@ -552,7 +560,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
552560
strings: false,
553561
list: false,
554562
},
555-
attr_style: self.attr_style,
563+
suggestions: self.suggestions(),
556564
})
557565
}
558566

@@ -573,7 +581,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
573581
strings: false,
574582
list: true,
575583
},
576-
attr_style: self.attr_style,
584+
suggestions: self.suggestions(),
577585
})
578586
}
579587

@@ -593,7 +601,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
593601
strings: true,
594602
list: false,
595603
},
596-
attr_style: self.attr_style,
604+
suggestions: self.suggestions(),
597605
})
598606
}
599607

@@ -605,6 +613,13 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
605613
span,
606614
);
607615
}
616+
617+
pub(crate) fn suggestions(&self) -> Vec<String> {
618+
// If the outer and inner spans are equal, we are parsing an attribute from `cfg_attr`,
619+
// So don't display an attribute style in the suggestions
620+
let style = (self.attr_span != self.inner_span).then_some(self.attr_style);
621+
self.template.suggestions(style, &self.attr_path)
622+
}
608623
}
609624

610625
impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> {

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ impl<'sess> AttributeParser<'sess, Early> {
142142
Self::parse_single_args(
143143
sess,
144144
attr.span,
145+
normal_attr.item.span(),
145146
attr.style,
146147
path.get_attribute_path(),
147148
target_span,
@@ -159,6 +160,7 @@ impl<'sess> AttributeParser<'sess, Early> {
159160
pub fn parse_single_args<T, I>(
160161
sess: &'sess Session,
161162
attr_span: Span,
163+
inner_span: Span,
162164
attr_style: AttrStyle,
163165
attr_path: AttrPath,
164166
target_span: Span,
@@ -186,6 +188,7 @@ impl<'sess> AttributeParser<'sess, Early> {
186188
},
187189
},
188190
attr_span,
191+
inner_span,
189192
attr_style,
190193
template,
191194
attr_path,
@@ -305,6 +308,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
305308
emit_lint: &mut emit_lint,
306309
},
307310
attr_span: lower_span(attr.span),
311+
inner_span: lower_span(attr.get_normal_item().span()),
308312
attr_style: attr.style,
309313
template: &accept.template,
310314
attr_path: path.get_attribute_path(),

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::num::IntErrorKind;
22

3-
use rustc_ast::{self as ast, AttrStyle, Path};
3+
use rustc_ast::{self as ast, Path};
44
use rustc_errors::codes::*;
55
use rustc_errors::{
66
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
@@ -613,10 +613,10 @@ pub(crate) enum AttributeParseErrorReason<'a> {
613613
pub(crate) struct AttributeParseError<'a> {
614614
pub(crate) span: Span,
615615
pub(crate) attr_span: Span,
616-
pub(crate) attr_style: AttrStyle,
617616
pub(crate) template: AttributeTemplate,
618617
pub(crate) attribute: AttrPath,
619618
pub(crate) reason: AttributeParseErrorReason<'a>,
619+
pub(crate) suggestions: Vec<String>,
620620
}
621621

622622
impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
@@ -752,16 +752,15 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
752752
if let Some(link) = self.template.docs {
753753
diag.note(format!("for more information, visit <{link}>"));
754754
}
755-
let suggestions = self.template.suggestions(self.attr_style, &name);
756755

757756
diag.span_suggestions(
758757
self.attr_span,
759-
if suggestions.len() == 1 {
758+
if self.suggestions.len() == 1 {
760759
"must be of the form"
761760
} else {
762761
"try changing it to one of the following valid forms of the attribute"
763762
},
764-
suggestions,
763+
self.suggestions,
765764
Applicability::HasPlaceholders,
766765
);
767766

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,24 +133,29 @@ pub struct AttributeTemplate {
133133
}
134134

135135
impl AttributeTemplate {
136-
pub fn suggestions(&self, style: AttrStyle, name: impl std::fmt::Display) -> Vec<String> {
136+
pub fn suggestions(
137+
&self,
138+
style: Option<AttrStyle>,
139+
name: impl std::fmt::Display,
140+
) -> Vec<String> {
137141
let mut suggestions = vec![];
138-
let inner = match style {
139-
AttrStyle::Outer => "",
140-
AttrStyle::Inner => "!",
142+
let (start, end) = match style {
143+
Some(AttrStyle::Outer) => ("#[", "]"),
144+
Some(AttrStyle::Inner) => ("#![", "]"),
145+
None => ("", ""),
141146
};
142147
if self.word {
143-
suggestions.push(format!("#{inner}[{name}]"));
148+
suggestions.push(format!("{start}{name}{end}"));
144149
}
145150
if let Some(descr) = self.list {
146151
for descr in descr {
147-
suggestions.push(format!("#{inner}[{name}({descr})]"));
152+
suggestions.push(format!("{start}{name}({descr}){end}"));
148153
}
149154
}
150-
suggestions.extend(self.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]")));
155+
suggestions.extend(self.one_of.iter().map(|&word| format!("{start}{name}({word}){end}")));
151156
if let Some(descr) = self.name_value_str {
152157
for descr in descr {
153-
suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
158+
suggestions.push(format!("{start}{name} = \"{descr}\"{end}"));
154159
}
155160
}
156161
suggestions.sort();

0 commit comments

Comments
 (0)