Skip to content

Commit 1c130a6

Browse files
committed
stash
1 parent 557f5e3 commit 1c130a6

3 files changed

Lines changed: 27 additions & 8 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/lint.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ impl<S: Stage> AttributeParser<S> for AllowParser {
2424
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
2525
),
2626
|this, cx, args| {
27-
validate_lint_attr(cx, args, &mut this.lint_ids, &mut this.errored, &mut this.reason);
27+
validate_lint_attr(cx, args, &mut this.lint_ids, &mut this.errored, &mut this.reason, sym::allow);
2828
},
2929
)];
3030

3131
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
32-
if !self.lint_ids.is_empty() && !self.errored {
32+
if !self.errored {
3333
Some(AttributeKind::Allow { lint_ids: self.lint_ids, reason: self.reason })
3434
} else {
3535
None
@@ -52,12 +52,12 @@ impl<S: Stage> AttributeParser<S> for DenyParser {
5252
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
5353
),
5454
|this, cx, args| {
55-
validate_lint_attr(cx, args, &mut this.lint_ids, &mut this.errored, &mut this.reason);
55+
validate_lint_attr(cx, args, &mut this.lint_ids, &mut this.errored, &mut this.reason, sym::deny);
5656
},
5757
)];
5858

5959
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
60-
if !self.lint_ids.is_empty() && !self.errored {
60+
if !self.errored {
6161
Some(AttributeKind::Deny { lint_ids: self.lint_ids, reason: self.reason })
6262
} else {
6363
None
@@ -74,20 +74,21 @@ fn validate_lint_attr<S: Stage>(
7474
lint_ids: &mut ThinVec<(Symbol, Span)>,
7575
errored: &mut bool,
7676
reason: &mut Option<Symbol>,
77+
attr_name: Symbol,
7778
) {
7879

7980
let Some(list) = args.list().map(MetaItemListParser::mixed) else {
8081
cx.expected_list(cx.inner_span, args);
8182
return;
8283
};
83-
8484
let mut list = list.peekable();
8585

86+
let mut skip_empty_check = false;
8687
while let Some(item) = list.next() {
8788
let Some(meta_item) = item.meta_item() else {
8889
cx.expected_string_literal(item.span(), item.lit());
8990
*errored = true;
90-
return;
91+
continue;
9192
};
9293
if let Some(args) = meta_item.word_is(sym::reason) {
9394
let ArgParser::NameValue(nv) = args else {
@@ -96,7 +97,7 @@ fn validate_lint_attr<S: Stage>(
9697
continue;
9798
};
9899
if list.peek().is_some() {
99-
// TODO: proper error
100+
cx.expected_nv_as_last_argument(nv.args_span(), attr_name, sym::reason);
100101
*errored = true;
101102
continue;
102103
}
@@ -126,9 +127,16 @@ fn validate_lint_attr<S: Stage>(
126127

127128
if let Some(ids) = check_lint(cx, &name, tool_name, tool_span, meta_item.span()) {
128129
lint_ids.extend(ids);
130+
} else {
131+
// Since external tool lints aren't directly checked by rustc, we don't store these ids
132+
// inside the parsed attr, but this still means that something *does* exist in it, so we shouldn't warn
133+
skip_empty_check = true;
129134
}
130135
}
131136
}
137+
if !skip_empty_check && lint_ids.is_empty() {
138+
cx.warn_empty_attribute(cx.attr_span);
139+
}
132140
}
133141

134142
fn check_lint<S: Stage>(
@@ -148,7 +156,6 @@ fn check_lint<S: Stage>(
148156
lint_ids.push((Symbol::intern(&id.to_string()), meta_item_span));
149157
}
150158
}
151-
// TODO fix tools
152159
CheckLintNameResult::Tool(ids, new_lint_name) => {
153160
let _name = match new_lint_name {
154161
None => {

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,10 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
629629
)
630630
}
631631

632+
pub(crate) fn expected_nv_as_last_argument(&self, span: Span,attr_name: Symbol, name_value_key: Symbol) -> ErrorGuaranteed {
633+
self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValueAsLastArgument {span,attr_name, name_value_key})
634+
}
635+
632636
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
633637
let attr_path = self.attr_path.clone().to_string();
634638
let valid_without_list = self.template.word;

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,11 @@ pub(crate) enum AttributeParseErrorReason<'a> {
570570
list: bool,
571571
},
572572
ExpectedIdentifier,
573+
ExpectedNameValueAsLastArgument {
574+
span: Span,
575+
attr_name: Symbol,
576+
name_value_key: Symbol,
577+
},
573578
}
574579

575580
/// A description of a thing that can be parsed using an attribute parser.
@@ -750,6 +755,9 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> {
750755
AttributeParseErrorReason::ExpectedIdentifier => {
751756
diag.span_label(self.span, "expected a valid identifier here");
752757
}
758+
AttributeParseErrorReason::ExpectedNameValueAsLastArgument { span, attr_name, name_value_key } => {
759+
diag.span_label(span, format!("the name value key `{name_value_key}` must come last in `#[{attr_name}]`"));
760+
}
753761
}
754762

755763
if let Some(link) = self.template.docs {

0 commit comments

Comments
 (0)