Skip to content

Commit 9735524

Browse files
Add AcceptContext::suggestions
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
1 parent f5e2df7 commit 9735524

File tree

12 files changed

+61
-64
lines changed

12 files changed

+61
-64
lines changed

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 3 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
}

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: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
427427
i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
428428
}),
429429
},
430-
attr_style: self.attr_style,
430+
suggestions: self.suggestions(),
431431
})
432432
}
433433

@@ -438,7 +438,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
438438
template: self.template.clone(),
439439
attribute: self.attr_path.clone(),
440440
reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
441-
attr_style: self.attr_style,
441+
suggestions: self.suggestions(),
442442
})
443443
}
444444

@@ -449,7 +449,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
449449
template: self.template.clone(),
450450
attribute: self.attr_path.clone(),
451451
reason: AttributeParseErrorReason::ExpectedList,
452-
attr_style: self.attr_style,
452+
suggestions: self.suggestions(),
453453
})
454454
}
455455

@@ -460,7 +460,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
460460
template: self.template.clone(),
461461
attribute: self.attr_path.clone(),
462462
reason: AttributeParseErrorReason::ExpectedNoArgs,
463-
attr_style: self.attr_style,
463+
suggestions: self.suggestions(),
464464
})
465465
}
466466

@@ -472,7 +472,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
472472
template: self.template.clone(),
473473
attribute: self.attr_path.clone(),
474474
reason: AttributeParseErrorReason::ExpectedIdentifier,
475-
attr_style: self.attr_style,
475+
suggestions: self.suggestions(),
476476
})
477477
}
478478

@@ -485,7 +485,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
485485
template: self.template.clone(),
486486
attribute: self.attr_path.clone(),
487487
reason: AttributeParseErrorReason::ExpectedNameValue(name),
488-
attr_style: self.attr_style,
488+
suggestions: self.suggestions(),
489489
})
490490
}
491491

@@ -497,7 +497,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
497497
template: self.template.clone(),
498498
attribute: self.attr_path.clone(),
499499
reason: AttributeParseErrorReason::DuplicateKey(key),
500-
attr_style: self.attr_style,
500+
suggestions: self.suggestions(),
501501
})
502502
}
503503

@@ -510,7 +510,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
510510
template: self.template.clone(),
511511
attribute: self.attr_path.clone(),
512512
reason: AttributeParseErrorReason::UnexpectedLiteral,
513-
attr_style: self.attr_style,
513+
suggestions: self.suggestions(),
514514
})
515515
}
516516

@@ -521,7 +521,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
521521
template: self.template.clone(),
522522
attribute: self.attr_path.clone(),
523523
reason: AttributeParseErrorReason::ExpectedSingleArgument,
524-
attr_style: self.attr_style,
524+
suggestions: self.suggestions(),
525525
})
526526
}
527527

@@ -532,7 +532,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
532532
template: self.template.clone(),
533533
attribute: self.attr_path.clone(),
534534
reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
535-
attr_style: self.attr_style,
535+
suggestions: self.suggestions(),
536536
})
537537
}
538538

@@ -552,7 +552,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
552552
strings: false,
553553
list: false,
554554
},
555-
attr_style: self.attr_style,
555+
suggestions: self.suggestions(),
556556
})
557557
}
558558

@@ -573,7 +573,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
573573
strings: false,
574574
list: true,
575575
},
576-
attr_style: self.attr_style,
576+
suggestions: self.suggestions(),
577577
})
578578
}
579579

@@ -593,7 +593,7 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
593593
strings: true,
594594
list: false,
595595
},
596-
attr_style: self.attr_style,
596+
suggestions: self.suggestions(),
597597
})
598598
}
599599

@@ -605,6 +605,10 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
605605
span,
606606
);
607607
}
608+
609+
pub(crate) fn suggestions(&self) -> Vec<String> {
610+
self.template.suggestions(Some(self.attr_style), &self.attr_path)
611+
}
608612
}
609613

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

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();

tests/ui/attributes/invalid_macro_export_argument.allow.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Future incompatibility report: Future breakage diagnostic:
2-
warning: valid forms for the attribute are `#![macro_export(local_inner_macros)]` and `#![macro_export]`
2+
warning: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]`
33
--> $DIR/invalid_macro_export_argument.rs:7:1
44
|
55
LL | #[macro_export(hello, world)]
@@ -9,7 +9,7 @@ LL | #[macro_export(hello, world)]
99
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
1010

1111
Future breakage diagnostic:
12-
warning: valid forms for the attribute are `#![macro_export(local_inner_macros)]` and `#![macro_export]`
12+
warning: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]`
1313
--> $DIR/invalid_macro_export_argument.rs:14:1
1414
|
1515
LL | #[macro_export(not_local_inner_macros)]
@@ -19,7 +19,7 @@ LL | #[macro_export(not_local_inner_macros)]
1919
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
2020

2121
Future breakage diagnostic:
22-
warning: valid forms for the attribute are `#![macro_export(local_inner_macros)]` and `#![macro_export]`
22+
warning: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]`
2323
--> $DIR/invalid_macro_export_argument.rs:31:1
2424
|
2525
LL | #[macro_export()]
@@ -29,7 +29,7 @@ LL | #[macro_export()]
2929
= note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
3030

3131
Future breakage diagnostic:
32-
warning: valid forms for the attribute are `#![macro_export(local_inner_macros)]` and `#![macro_export]`
32+
warning: valid forms for the attribute are `#[macro_export(local_inner_macros)]` and `#[macro_export]`
3333
--> $DIR/invalid_macro_export_argument.rs:38:1
3434
|
3535
LL | #[macro_export("blah")]

0 commit comments

Comments
 (0)