Skip to content

Commit 8ce5fde

Browse files
committed
Auto merge of #155511 - jhpratt:rollup-49I3hDK, r=jhpratt
Rollup of 10 pull requests Successful merges: - #155370 (Add regression test for dead code elimination with drop + panic) - #154823 (Replace the spdx-rs dependency with a minimal in-tree SPDX tag-value parser) - #155294 (Add test for coalescing of diagnostic attribute duplicates) - #155352 (triagebot.toml: Sync `assign.owners` with `autolabel."T-compiler"`) - #155431 (Add temporary scope to assert_matches) - #152995 (ACP Implementation of PermissionsExt for Windows ) - #153873 (deprecate `std::char` constants and functions) - #154865 (libtest: use binary search for --exact test filtering) - #154979 (add #[must_use] macros for floats) - #155504 (Remove `AttributeLintKind` variants - part 2)
2 parents ec2d669 + baef609 commit 8ce5fde

39 files changed

Lines changed: 876 additions & 431 deletions

File tree

Cargo.lock

Lines changed: 41 additions & 108 deletions
Large diffs are not rendered by default.

compiler/rustc_attr_parsing/src/attributes/doc.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use thin_vec::ThinVec;
1313
use super::prelude::{ALL_TARGETS, AllowedTargets};
1414
use super::{AcceptMapping, AttributeParser};
1515
use crate::context::{AcceptContext, FinalizeContext, Stage};
16+
use crate::errors::{DocAliasDuplicated, DocAutoCfgExpectsHideOrShow, IllFormedAttributeInput};
1617
use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser};
1718
use crate::session_diagnostics::{
1819
DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel,
@@ -255,9 +256,9 @@ impl DocParser {
255256
}
256257

257258
if let Some(first_definition) = self.attribute.aliases.get(&alias).copied() {
258-
cx.emit_lint(
259+
cx.emit_dyn_lint(
259260
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
260-
AttributeLintKind::DuplicateDocAlias { first_definition },
261+
move |dcx, level| DocAliasDuplicated { first_definition }.into_diag(dcx, level),
261262
span,
262263
);
263264
}
@@ -343,9 +344,9 @@ impl DocParser {
343344
ArgParser::List(list) => {
344345
for meta in list.mixed() {
345346
let MetaItemOrLitParser::MetaItemParser(item) = meta else {
346-
cx.emit_lint(
347+
cx.emit_dyn_lint(
347348
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
348-
AttributeLintKind::DocAutoCfgExpectsHideOrShow,
349+
|dcx, level| DocAutoCfgExpectsHideOrShow.into_diag(dcx, level),
349350
meta.span(),
350351
);
351352
continue;
@@ -354,9 +355,9 @@ impl DocParser {
354355
Some(sym::hide) => (HideOrShow::Hide, sym::hide),
355356
Some(sym::show) => (HideOrShow::Show, sym::show),
356357
_ => {
357-
cx.emit_lint(
358+
cx.emit_dyn_lint(
358359
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
359-
AttributeLintKind::DocAutoCfgExpectsHideOrShow,
360+
|dcx, level| DocAutoCfgExpectsHideOrShow.into_diag(dcx, level),
360361
item.span(),
361362
);
362363
continue;
@@ -666,12 +667,10 @@ impl DocParser {
666667
ArgParser::NoArgs => {
667668
let suggestions = cx.adcx().suggestions();
668669
let span = cx.attr_span;
669-
cx.emit_lint(
670+
cx.emit_dyn_lint(
670671
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
671-
AttributeLintKind::IllFormedAttributeInput {
672-
suggestions,
673-
docs: None,
674-
help: None,
672+
move |dcx, level| {
673+
IllFormedAttributeInput::new(&suggestions, None, None).into_diag(dcx, level)
675674
},
676675
span,
677676
);

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -897,11 +897,18 @@ where
897897
}
898898

899899
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
900-
let attr_path = self.attr_path.clone().to_string();
900+
let attr_path = self.attr_path.to_string();
901901
let valid_without_list = self.template.word;
902-
self.emit_lint(
902+
self.emit_dyn_lint(
903903
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
904-
AttributeLintKind::EmptyAttribute { first_span: span, attr_path, valid_without_list },
904+
move |dcx, level| {
905+
crate::errors::EmptyAttributeList {
906+
attr_span: span,
907+
attr_path: &attr_path,
908+
valid_without_list,
909+
}
910+
.into_diag(dcx, level)
911+
},
905912
span,
906913
);
907914
}
@@ -916,9 +923,12 @@ where
916923
) {
917924
let suggestions = self.suggestions();
918925
let span = self.attr_span;
919-
self.emit_lint(
926+
self.emit_dyn_lint(
920927
lint,
921-
AttributeLintKind::IllFormedAttributeInput { suggestions, docs: None, help },
928+
move |dcx, level| {
929+
crate::errors::IllFormedAttributeInput::new(&suggestions, None, help.as_deref())
930+
.into_diag(dcx, level)
931+
},
922932
span,
923933
);
924934
}

compiler/rustc_attr_parsing/src/errors.rs

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_errors::MultiSpan;
1+
use rustc_errors::{DiagArgValue, MultiSpan};
22
use rustc_macros::{Diagnostic, Subdiagnostic};
33
use rustc_span::{Span, Symbol};
44

@@ -66,3 +66,114 @@ pub(crate) struct UnsafeAttrOutsideUnsafeLint {
6666
#[subdiagnostic]
6767
pub suggestion: Option<crate::session_diagnostics::UnsafeAttrOutsideUnsafeSuggestion>,
6868
}
69+
70+
#[derive(Diagnostic)]
71+
#[diag(
72+
"{$num_suggestions ->
73+
[1] attribute must be of the form {$suggestions}
74+
*[other] valid forms for the attribute are {$suggestions}
75+
}"
76+
)]
77+
pub(crate) struct IllFormedAttributeInput {
78+
pub num_suggestions: usize,
79+
pub suggestions: DiagArgValue,
80+
#[note("for more information, visit <{$docs}>")]
81+
pub has_docs: bool,
82+
pub docs: &'static str,
83+
#[subdiagnostic]
84+
help: Option<IllFormedAttributeInputHelp>,
85+
}
86+
87+
impl IllFormedAttributeInput {
88+
pub(crate) fn new(
89+
suggestions: &[String],
90+
docs: Option<&'static str>,
91+
help: Option<&str>,
92+
) -> Self {
93+
Self {
94+
num_suggestions: suggestions.len(),
95+
suggestions: DiagArgValue::StrListSepByAnd(
96+
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),
97+
),
98+
has_docs: docs.is_some(),
99+
docs: docs.unwrap_or(""),
100+
help: help.map(|h| IllFormedAttributeInputHelp { lint: h.to_string() }),
101+
}
102+
}
103+
}
104+
105+
#[derive(Subdiagnostic)]
106+
#[help(
107+
"if you meant to silence a warning, consider using #![allow({$lint})] or #![expect({$lint})]"
108+
)]
109+
struct IllFormedAttributeInputHelp {
110+
pub lint: String,
111+
}
112+
113+
#[derive(Diagnostic)]
114+
#[diag("unused attribute")]
115+
#[note(
116+
"{$valid_without_list ->
117+
[true] using `{$attr_path}` with an empty list is equivalent to not using a list at all
118+
*[other] using `{$attr_path}` with an empty list has no effect
119+
}"
120+
)]
121+
pub(crate) struct EmptyAttributeList<'a> {
122+
#[suggestion(
123+
"{$valid_without_list ->
124+
[true] remove these parentheses
125+
*[other] remove this attribute
126+
}",
127+
code = "",
128+
applicability = "machine-applicable"
129+
)]
130+
pub attr_span: Span,
131+
pub attr_path: &'a str,
132+
pub valid_without_list: bool,
133+
}
134+
135+
#[derive(Diagnostic)]
136+
#[diag("`#[{$name}]` attribute cannot be used on {$target}")]
137+
#[warning(
138+
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
139+
)]
140+
#[help("`#[{$name}]` can {$only}be applied to {$applied}")]
141+
pub(crate) struct InvalidTargetLint {
142+
pub name: String,
143+
pub target: &'static str,
144+
pub applied: DiagArgValue,
145+
pub only: &'static str,
146+
#[suggestion(
147+
"remove the attribute",
148+
code = "",
149+
applicability = "machine-applicable",
150+
style = "tool-only"
151+
)]
152+
pub attr_span: Span,
153+
}
154+
155+
#[derive(Diagnostic)]
156+
#[diag(
157+
"{$is_used_as_inner ->
158+
[false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]`
159+
*[other] the `#![{$name}]` attribute can only be used at the crate root
160+
}"
161+
)]
162+
pub(crate) struct InvalidAttrStyle<'a> {
163+
pub name: &'a str,
164+
pub is_used_as_inner: bool,
165+
#[note("this attribute does not have an `!`, which means it is applied to this {$target}")]
166+
pub target_span: Option<Span>,
167+
pub target: &'static str,
168+
}
169+
170+
#[derive(Diagnostic)]
171+
#[diag("doc alias is duplicated")]
172+
pub(crate) struct DocAliasDuplicated {
173+
#[label("first defined here")]
174+
pub first_definition: Span,
175+
}
176+
177+
#[derive(Diagnostic)]
178+
#[diag("only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]`")]
179+
pub(crate) struct DocAutoCfgExpectsHideOrShow;

compiler/rustc_attr_parsing/src/target_checking.rs

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
use std::borrow::Cow;
22

33
use rustc_ast::AttrStyle;
4-
use rustc_errors::{DiagArgValue, MultiSpan, StashKey};
4+
use rustc_errors::{DiagArgValue, Diagnostic, MultiSpan, StashKey};
55
use rustc_feature::Features;
66
use rustc_hir::attrs::AttributeKind;
7-
use rustc_hir::lints::AttributeLintKind;
87
use rustc_hir::{AttrItem, Attribute, MethodKind, Target};
98
use rustc_span::{BytePos, Span, Symbol, sym};
109

1110
use crate::AttributeParser;
1211
use crate::context::{AcceptContext, Stage};
1312
use crate::errors::{
14-
InvalidAttrAtCrateLevel, ItemFollowingInnerAttr, UnsupportedAttributesInWhere,
13+
InvalidAttrAtCrateLevel, InvalidTargetLint, ItemFollowingInnerAttr,
14+
UnsupportedAttributesInWhere,
1515
};
1616
use crate::session_diagnostics::InvalidTarget;
1717
use crate::target_checking::Policy::Allow;
@@ -142,14 +142,19 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
142142
};
143143

144144
let attr_span = cx.attr_span;
145-
cx.emit_lint(
145+
cx.emit_dyn_lint(
146146
lint,
147-
AttributeLintKind::InvalidTarget {
148-
name: name.to_string(),
149-
target: target.plural_name(),
150-
only: if only { "only " } else { "" },
151-
applied,
152-
attr_span,
147+
move |dcx, level| {
148+
InvalidTargetLint {
149+
name: name.to_string(),
150+
target: target.plural_name(),
151+
only: if only { "only " } else { "" },
152+
applied: DiagArgValue::StrListSepByAnd(
153+
applied.iter().map(|i| Cow::Owned(i.to_string())).collect(),
154+
),
155+
attr_span,
156+
}
157+
.into_diag(dcx, level)
153158
},
154159
attr_span,
155160
);
@@ -176,15 +181,24 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
176181
return;
177182
}
178183

179-
let kind = AttributeLintKind::InvalidStyle {
180-
name: cx.attr_path.to_string(),
181-
is_used_as_inner: cx.attr_style == AttrStyle::Inner,
182-
target: target.name(),
183-
target_span: cx.target_span,
184-
};
184+
let name = cx.attr_path.to_string();
185+
let is_used_as_inner = cx.attr_style == AttrStyle::Inner;
186+
let target_span = cx.target_span;
185187
let attr_span = cx.attr_span;
186188

187-
cx.emit_lint(rustc_session::lint::builtin::UNUSED_ATTRIBUTES, kind, attr_span);
189+
cx.emit_dyn_lint(
190+
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
191+
move |dcx, level| {
192+
crate::errors::InvalidAttrStyle {
193+
name: &name,
194+
is_used_as_inner,
195+
target_span: (!is_used_as_inner).then_some(target_span),
196+
target: target.name(),
197+
}
198+
.into_diag(dcx, level)
199+
},
200+
attr_span,
201+
);
188202
}
189203

190204
// FIXME: Fix "Cannot determine resolution" error and remove built-in macros

compiler/rustc_attr_parsing/src/validate_attr.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ use rustc_ast::tokenstream::DelimSpan;
88
use rustc_ast::{
99
self as ast, AttrArgs, Attribute, DelimArgs, MetaItem, MetaItemInner, MetaItemKind, Safety,
1010
};
11-
use rustc_errors::{Applicability, PResult};
11+
use rustc_errors::{Applicability, Diagnostic, PResult};
1212
use rustc_feature::{AttributeTemplate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, template};
1313
use rustc_hir::AttrPath;
14-
use rustc_hir::lints::AttributeLintKind;
1514
use rustc_parse::parse_in;
1615
use rustc_session::errors::report_lit_error;
1716
use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
@@ -210,14 +209,14 @@ pub fn emit_malformed_attribute(
210209
suggestions.clear();
211210
}
212211
if should_warn(name) {
213-
psess.buffer_lint(
212+
let suggestions = suggestions.clone();
213+
psess.dyn_buffer_lint(
214214
ILL_FORMED_ATTRIBUTE_INPUT,
215215
span,
216216
ast::CRATE_NODE_ID,
217-
AttributeLintKind::IllFormedAttributeInput {
218-
suggestions: suggestions.clone(),
219-
docs: template.docs,
220-
help: None,
217+
move |dcx, level| {
218+
crate::errors::IllFormedAttributeInput::new(&suggestions, template.docs, None)
219+
.into_diag(dcx, level)
221220
},
222221
);
223222
} else {

compiler/rustc_builtin_macros/src/test_harness.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> Box<ast::Expr> {
370370
let ecx = &cx.ext_cx;
371371

372372
let mut tests = cx.test_cases.clone();
373+
// Note that this sort is load-bearing: the libtest harness uses binary search to find tests by
374+
// name.
373375
tests.sort_by(|a, b| a.name.as_str().cmp(b.name.as_str()));
374376

375377
ecx.expr_array_ref(

0 commit comments

Comments
 (0)