Skip to content

Commit 73c500b

Browse files
authored
Rollup merge of #127591 - compiler-errors:label-after-primary, r=lcnr
Make sure that labels are defined after the primary span in diagnostics Putting a `#[label]` before a `#[primary_span]` results in that label being overwritten, due to the semantics of `Diagnostic::span` and the fact that labels are stored in the `MultiSpan` of the diagnostic. This isn't possible to fix in general, since a lot of code actually *relies* in this overwriting behavior (e.g. `rustc_on_unimplemented`). However, it's useful to enforce this for derive-diagnostics, since this is certainly never what you intend to do in a derived diagnostic, where all the fields are meaningful parts of the diagnostic being rendered. This only matters for `#[label]`, since those are the ones stored in the `MultiSpan` of the error. We could also make this "just work" by sorting the attrs or processing the primary span attr first, however I think it's kinda pointless to do. There was 1 case where this mattered, but we literally didn't have a test exercising that diagnostic 🙃
2 parents 380c787 + 12ae282 commit 73c500b

File tree

4 files changed

+24
-1
lines changed

4 files changed

+24
-1
lines changed

compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs

+9
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ impl DiagnosticDeriveVariantBuilder {
269269
let field_binding = &binding_info.binding;
270270

271271
let inner_ty = FieldInnerTy::from_type(&field.ty);
272+
let mut seen_label = false;
272273

273274
field
274275
.attrs
@@ -280,6 +281,14 @@ impl DiagnosticDeriveVariantBuilder {
280281
}
281282

282283
let name = attr.path().segments.last().unwrap().ident.to_string();
284+
285+
if name == "primary_span" && seen_label {
286+
span_err(attr.span().unwrap(), format!("`#[primary_span]` must be placed before labels, since it overwrites the span of the diagnostic")).emit();
287+
}
288+
if name == "label" {
289+
seen_label = true;
290+
}
291+
283292
let needs_clone =
284293
name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
285294
let (binding, needs_destructure) = if needs_clone {

compiler/rustc_resolve/src/errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1089,8 +1089,8 @@ pub(crate) struct ToolWasAlreadyRegistered {
10891089
#[derive(Diagnostic)]
10901090
#[diag(resolve_tool_only_accepts_identifiers)]
10911091
pub(crate) struct ToolOnlyAcceptsIdentifiers {
1092-
#[label]
10931092
#[primary_span]
1093+
#[label]
10941094
pub(crate) span: Span,
10951095
pub(crate) tool: Symbol,
10961096
}
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(register_tool)]
2+
3+
#![register_tool(1)]
4+
//~^ ERROR `register_tool` only accepts identifiers
5+
6+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: `register_tool` only accepts identifiers
2+
--> $DIR/invalid-tool.rs:3:18
3+
|
4+
LL | #![register_tool(1)]
5+
| ^ not an identifier
6+
7+
error: aborting due to 1 previous error
8+

0 commit comments

Comments
 (0)