Skip to content

Commit cbc0d97

Browse files
committed
fix bugs in inline/force_inline and diagnostics of all attr parsers
1 parent 5d8fa68 commit cbc0d97

33 files changed

+580
-238
lines changed

compiler/rustc_attr_data_structures/src/lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ pub struct AttributeLint<Id> {
1111
#[derive(Clone, Debug, HashStable_Generic)]
1212
pub enum AttributeLintKind {
1313
UnusedDuplicate { this: Span, other: Span, warning: bool },
14+
IllFormedAttributeInput { suggestions: Vec<String> },
1415
}

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ attr_parsing_expects_feature_list =
2323
attr_parsing_expects_features =
2424
`{$name}` expects feature names
2525
26+
attr_parsing_ill_formed_attribute_input = {$num_suggestions ->
27+
[1] attribute must be of the form {$suggestions}
28+
*[other] valid forms for the attribute are {$suggestions}
29+
}
2630
attr_parsing_incorrect_meta_item = expected a quoted string literal
2731
attr_parsing_incorrect_meta_item_suggestion = consider surrounding this with quotes
2832
@@ -136,6 +140,7 @@ attr_parsing_unused_duplicate =
136140
.suggestion = remove this attribute
137141
.note = attribute also specified here
138142
.warn = {-passes_previously_accepted}
143+
139144
attr_parsing_unused_multiple =
140145
multiple `{$name}` attributes
141146
.suggestion = remove this attribute

compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::iter;
22

33
use rustc_attr_data_structures::AttributeKind;
4+
use rustc_feature::{AttributeTemplate, template};
45
use rustc_span::{Span, Symbol, sym};
56

67
use super::{CombineAttributeParser, ConvertFn};
@@ -13,6 +14,7 @@ impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
1314
const PATH: &[Symbol] = &[sym::allow_internal_unstable];
1415
type Item = (Symbol, Span);
1516
const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowInternalUnstable;
17+
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
1618

1719
fn extend<'c>(
1820
cx: &'c mut AcceptContext<'_, '_, S>,
@@ -29,6 +31,7 @@ impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
2931
const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable];
3032
type Item = Symbol;
3133
const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowConstFnUnstable;
34+
const TEMPLATE: AttributeTemplate = template!(Word, List: "feat1, feat2, ...");
3235

3336
fn extend<'c>(
3437
cx: &'c mut AcceptContext<'_, '_, S>,

compiler/rustc_attr_parsing/src/attributes/confusables.rs

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_attr_data_structures::AttributeKind;
2+
use rustc_feature::template;
23
use rustc_span::{Span, Symbol, sym};
34
use thin_vec::ThinVec;
45

@@ -13,37 +14,41 @@ pub(crate) struct ConfusablesParser {
1314
}
1415

1516
impl<S: Stage> AttributeParser<S> for ConfusablesParser {
16-
const ATTRIBUTES: AcceptMapping<Self, S> = &[(&[sym::rustc_confusables], |this, cx, args| {
17-
let Some(list) = args.list() else {
18-
// FIXME(jdonszelmann): error when not a list? Bring validation code here.
19-
// NOTE: currently subsequent attributes are silently ignored using
20-
// tcx.get_attr().
21-
return;
22-
};
23-
24-
if list.is_empty() {
25-
cx.emit_err(session_diagnostics::EmptyConfusables { span: cx.attr_span });
26-
}
27-
28-
for param in list.mixed() {
29-
let span = param.span();
30-
31-
let Some(lit) = param.lit() else {
32-
cx.emit_err(session_diagnostics::IncorrectMetaItem {
33-
span,
34-
suggestion: Some(session_diagnostics::IncorrectMetaItemSuggestion {
35-
lo: span.shrink_to_lo(),
36-
hi: span.shrink_to_hi(),
37-
}),
38-
});
39-
continue;
17+
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
18+
&[sym::rustc_confusables],
19+
template!(List: r#""name1", "name2", ..."#),
20+
|this, cx, args| {
21+
let Some(list) = args.list() else {
22+
// FIXME(jdonszelmann): error when not a list? Bring validation code here.
23+
// NOTE: currently subsequent attributes are silently ignored using
24+
// tcx.get_attr().
25+
return;
4026
};
4127

42-
this.confusables.push(lit.symbol);
43-
}
44-
45-
this.first_span.get_or_insert(cx.attr_span);
46-
})];
28+
if list.is_empty() {
29+
cx.emit_err(session_diagnostics::EmptyConfusables { span: cx.attr_span });
30+
}
31+
32+
for param in list.mixed() {
33+
let span = param.span();
34+
35+
let Some(lit) = param.lit() else {
36+
cx.emit_err(session_diagnostics::IncorrectMetaItem {
37+
span,
38+
suggestion: Some(session_diagnostics::IncorrectMetaItemSuggestion {
39+
lo: span.shrink_to_lo(),
40+
hi: span.shrink_to_hi(),
41+
}),
42+
});
43+
continue;
44+
};
45+
46+
this.confusables.push(lit.symbol);
47+
}
48+
49+
this.first_span.get_or_insert(cx.attr_span);
50+
},
51+
)];
4752

4853
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
4954
if self.confusables.is_empty() {

compiler/rustc_attr_parsing/src/attributes/deprecation.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_attr_data_structures::{AttributeKind, DeprecatedSince, Deprecation};
2+
use rustc_feature::{AttributeTemplate, template};
23
use rustc_span::{Span, Symbol, sym};
34

45
use super::util::parse_version;
@@ -45,6 +46,11 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
4546
const PATH: &[Symbol] = &[sym::deprecated];
4647
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
4748
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
49+
const TEMPLATE: AttributeTemplate = template!(
50+
Word,
51+
List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#,
52+
NameValueStr: "reason"
53+
);
4854

4955
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
5056
let features = cx.features();

compiler/rustc_attr_parsing/src/attributes/inline.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use super::{AcceptContext, AttributeOrder, OnDuplicate};
1111
use crate::attributes::SingleAttributeParser;
1212
use crate::context::Stage;
1313
use crate::parser::ArgParser;
14-
use crate::session_diagnostics::IncorrectMetaItem;
1514

1615
pub(crate) struct InlineParser;
1716

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use std::marker::PhantomData;
1818

1919
use rustc_attr_data_structures::AttributeKind;
2020
use rustc_attr_data_structures::lints::AttributeLintKind;
21+
use rustc_feature::AttributeTemplate;
2122
use rustc_span::{Span, Symbol};
2223
use thin_vec::ThinVec;
2324

@@ -36,7 +37,7 @@ pub(crate) mod transparency;
3637
pub(crate) mod util;
3738

3839
type AcceptFn<T, S> = for<'sess> fn(&mut T, &mut AcceptContext<'_, 'sess, S>, &ArgParser<'_>);
39-
type AcceptMapping<T, S> = &'static [(&'static [Symbol], AcceptFn<T, S>)];
40+
type AcceptMapping<T, S> = &'static [(&'static [Symbol], AttributeTemplate, AcceptFn<T, S>)];
4041

4142
/// An [`AttributeParser`] is a type which searches for syntactic attributes.
4243
///
@@ -79,6 +80,9 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
7980
const ATTRIBUTE_ORDER: AttributeOrder;
8081
const ON_DUPLICATE: OnDuplicate<S>;
8182

83+
/// The template this attribute parser should implement. Used for diagnostics.
84+
const TEMPLATE: AttributeTemplate;
85+
8286
/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
8387
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
8488
}
@@ -95,8 +99,10 @@ impl<T: SingleAttributeParser<S>, S: Stage> Default for Single<T, S> {
9599
}
96100

97101
impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S> {
98-
const ATTRIBUTES: AcceptMapping<Self, S> =
99-
&[(T::PATH, |group: &mut Single<T, S>, cx, args| {
102+
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
103+
T::PATH,
104+
<T as SingleAttributeParser<S>>::TEMPLATE,
105+
|group: &mut Single<T, S>, cx, args| {
100106
if let Some(pa) = T::convert(cx, args) {
101107
match T::ATTRIBUTE_ORDER {
102108
// keep the first and report immediately. ignore this attribute
@@ -117,7 +123,8 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
117123

118124
group.1 = Some((pa, cx.attr_span));
119125
}
120-
})];
126+
},
127+
)];
121128

122129
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
123130
Some(self.1?.0)
@@ -214,6 +221,9 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
214221
type Item;
215222
const CONVERT: ConvertFn<Self::Item>;
216223

224+
/// The template this attribute parser should implement. Used for diagnostics.
225+
const TEMPLATE: AttributeTemplate;
226+
217227
/// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
218228
fn extend<'c>(
219229
cx: &'c mut AcceptContext<'_, '_, S>,
@@ -233,8 +243,11 @@ impl<T: CombineAttributeParser<S>, S: Stage> Default for Combine<T, S> {
233243
}
234244

235245
impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S> {
236-
const ATTRIBUTES: AcceptMapping<Self, S> =
237-
&[(T::PATH, |group: &mut Combine<T, S>, cx, args| group.1.extend(T::extend(cx, args)))];
246+
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
247+
T::PATH,
248+
<T as CombineAttributeParser<S>>::TEMPLATE,
249+
|group: &mut Combine<T, S>, cx, args| group.1.extend(T::extend(cx, args)),
250+
)];
238251

239252
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
240253
if self.1.is_empty() { None } else { Some(T::CONVERT(self.1)) }

compiler/rustc_attr_parsing/src/attributes/repr.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_abi::Align;
22
use rustc_ast::{IntTy, LitIntType, LitKind, UintTy};
33
use rustc_attr_data_structures::{AttributeKind, IntType, ReprAttr};
4+
use rustc_feature::{AttributeTemplate, template};
45
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
56

67
use super::{CombineAttributeParser, ConvertFn};
@@ -23,6 +24,8 @@ impl<S: Stage> CombineAttributeParser<S> for ReprParser {
2324
type Item = (ReprAttr, Span);
2425
const PATH: &[Symbol] = &[sym::repr];
2526
const CONVERT: ConvertFn<Self::Item> = AttributeKind::Repr;
27+
// FIXME(jdonszelmann): never used
28+
const TEMPLATE: AttributeTemplate = template!(List: "C");
2629

2730
fn extend<'c>(
2831
cx: &'c mut AcceptContext<'_, '_, S>,

compiler/rustc_attr_parsing/src/attributes/stability.rs

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_attr_data_structures::{
55
StableSince, UnstableReason, VERSION_PLACEHOLDER,
66
};
77
use rustc_errors::ErrorGuaranteed;
8+
use rustc_feature::{AttributeTemplate, template};
89
use rustc_span::{Span, Symbol, sym};
910

1011
use super::util::parse_version;
@@ -43,26 +44,39 @@ impl StabilityParser {
4344

4445
impl<S: Stage> AttributeParser<S> for StabilityParser {
4546
const ATTRIBUTES: AcceptMapping<Self, S> = &[
46-
(&[sym::stable], |this, cx, args| {
47-
reject_outside_std!(cx);
48-
if !this.check_duplicate(cx)
49-
&& let Some((feature, level)) = parse_stability(cx, args)
50-
{
51-
this.stability = Some((Stability { level, feature }, cx.attr_span));
52-
}
53-
}),
54-
(&[sym::unstable], |this, cx, args| {
55-
reject_outside_std!(cx);
56-
if !this.check_duplicate(cx)
57-
&& let Some((feature, level)) = parse_unstability(cx, args)
58-
{
59-
this.stability = Some((Stability { level, feature }, cx.attr_span));
60-
}
61-
}),
62-
(&[sym::rustc_allowed_through_unstable_modules], |this, cx, args| {
63-
reject_outside_std!(cx);
64-
this.allowed_through_unstable_modules = args.name_value().and_then(|i| i.value_as_str())
65-
}),
47+
(
48+
&[sym::stable],
49+
template!(List: r#"feature = "name", since = "version""#),
50+
|this, cx, args| {
51+
reject_outside_std!(cx);
52+
if !this.check_duplicate(cx)
53+
&& let Some((feature, level)) = parse_stability(cx, args)
54+
{
55+
this.stability = Some((Stability { level, feature }, cx.attr_span));
56+
}
57+
},
58+
),
59+
(
60+
&[sym::unstable],
61+
template!(List: r#"feature = "name", reason = "...", issue = "N""#),
62+
|this, cx, args| {
63+
reject_outside_std!(cx);
64+
if !this.check_duplicate(cx)
65+
&& let Some((feature, level)) = parse_unstability(cx, args)
66+
{
67+
this.stability = Some((Stability { level, feature }, cx.attr_span));
68+
}
69+
},
70+
),
71+
(
72+
&[sym::rustc_allowed_through_unstable_modules],
73+
template!(NameValueStr: "deprecation message"),
74+
|this, cx, args| {
75+
reject_outside_std!(cx);
76+
this.allowed_through_unstable_modules =
77+
args.name_value().and_then(|i| i.value_as_str())
78+
},
79+
),
6680
];
6781

6882
fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
@@ -96,16 +110,19 @@ pub(crate) struct BodyStabilityParser {
96110
}
97111

98112
impl<S: Stage> AttributeParser<S> for BodyStabilityParser {
99-
const ATTRIBUTES: AcceptMapping<Self, S> =
100-
&[(&[sym::rustc_default_body_unstable], |this, cx, args| {
113+
const ATTRIBUTES: AcceptMapping<Self, S> = &[(
114+
&[sym::rustc_default_body_unstable],
115+
template!(List: r#"feature = "name", reason = "...", issue = "N""#),
116+
|this, cx, args| {
101117
reject_outside_std!(cx);
102118
if this.stability.is_some() {
103119
cx.dcx()
104120
.emit_err(session_diagnostics::MultipleStabilityLevels { span: cx.attr_span });
105121
} else if let Some((feature, level)) = parse_unstability(cx, args) {
106122
this.stability = Some((DefaultBodyStability { level, feature }, cx.attr_span));
107123
}
108-
})];
124+
},
125+
)];
109126

110127
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
111128
let (stability, span) = self.stability?;
@@ -120,6 +137,7 @@ impl<S: Stage> SingleAttributeParser<S> for ConstStabilityIndirectParser {
120137
const PATH: &[Symbol] = &[sym::rustc_const_stable_indirect];
121138
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
122139
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
140+
const TEMPLATE: AttributeTemplate = template!(Word);
123141

124142
fn convert(_cx: &mut AcceptContext<'_, '_, S>, _args: &ArgParser<'_>) -> Option<AttributeKind> {
125143
Some(AttributeKind::ConstStabilityIndirect)
@@ -146,7 +164,7 @@ impl ConstStabilityParser {
146164

147165
impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
148166
const ATTRIBUTES: AcceptMapping<Self, S> = &[
149-
(&[sym::rustc_const_stable], |this, cx, args| {
167+
(&[sym::rustc_const_stable], template!(List: r#"feature = "name""#), |this, cx, args| {
150168
reject_outside_std!(cx);
151169

152170
if !this.check_duplicate(cx)
@@ -158,7 +176,7 @@ impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
158176
));
159177
}
160178
}),
161-
(&[sym::rustc_const_unstable], |this, cx, args| {
179+
(&[sym::rustc_const_unstable], template!(List: r#"feature = "name""#), |this, cx, args| {
162180
reject_outside_std!(cx);
163181
if !this.check_duplicate(cx)
164182
&& let Some((feature, level)) = parse_unstability(cx, args)
@@ -169,7 +187,7 @@ impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
169187
));
170188
}
171189
}),
172-
(&[sym::rustc_promotable], |this, cx, _| {
190+
(&[sym::rustc_promotable], template!(Word), |this, cx, _| {
173191
reject_outside_std!(cx);
174192
this.promotable = true;
175193
}),

compiler/rustc_attr_parsing/src/attributes/transparency.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_attr_data_structures::AttributeKind;
2+
use rustc_feature::{AttributeTemplate, template};
23
use rustc_span::hygiene::Transparency;
34
use rustc_span::{Symbol, sym};
45

@@ -17,6 +18,8 @@ impl<S: Stage> SingleAttributeParser<S> for TransparencyParser {
1718
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Custom(|cx, used, unused| {
1819
cx.dcx().span_err(vec![used, unused], "multiple macro transparency attributes");
1920
});
21+
const TEMPLATE: AttributeTemplate =
22+
template!(NameValueStr: "transparent|semitransparent|opaque");
2023

2124
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
2225
match args.name_value().and_then(|nv| nv.value_as_str()) {

0 commit comments

Comments
 (0)