Skip to content

Commit faa502e

Browse files
committed
Add runtime check to avoid overwrite arg easily in diag and store and restore snapshot when set subdiag arg
Signed-off-by: xizheyin <[email protected]>
1 parent 2fcf177 commit faa502e

File tree

22 files changed

+119
-39
lines changed

22 files changed

+119
-39
lines changed

compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1254,8 +1254,14 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
12541254
&& !spans.is_empty()
12551255
{
12561256
let mut span: MultiSpan = spans.clone().into();
1257+
err.arg("ty", param_ty.to_string());
1258+
let msg = err.dcx.eagerly_translate_to_string(
1259+
fluent::borrowck_moved_a_fn_once_in_call_def,
1260+
err.args.iter(),
1261+
);
1262+
err.remove_arg("ty");
12571263
for sp in spans {
1258-
span.push_span_label(sp, fluent::borrowck_moved_a_fn_once_in_call_def);
1264+
span.push_span_label(sp, msg.clone());
12591265
}
12601266
span.push_span_label(
12611267
fn_call_span,

compiler/rustc_builtin_macros/src/errors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ impl Subdiagnostic for FormatUnusedArg {
672672
fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
673673
diag.arg("named", self.named);
674674
let msg = diag.eagerly_translate(crate::fluent_generated::builtin_macros_format_unused_arg);
675+
diag.remove_arg("named");
675676
diag.span_label(self.span, msg);
676677
}
677678
}

compiler/rustc_const_eval/src/errors.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ impl Subdiagnostic for FrameNote {
293293
span.push_span_label(self.span, fluent::const_eval_frame_note_last);
294294
}
295295
let msg = diag.eagerly_translate(fluent::const_eval_frame_note);
296+
diag.remove_arg("times");
297+
diag.remove_arg("where_");
298+
diag.remove_arg("instance");
296299
diag.span_note(span, msg);
297300
}
298301
}

compiler/rustc_errors/src/diagnostic.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ pub struct DiagInner {
289289
pub suggestions: Suggestions,
290290
pub args: DiagArgMap,
291291

292+
// This is used to store args and restore them after a subdiagnostic is rendered.
293+
pub reserved_args: DiagArgMap,
294+
292295
/// This is not used for highlighting or rendering any error message. Rather, it can be used
293296
/// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of
294297
/// `span` if there is one. Otherwise, it is `DUMMY_SP`.
@@ -319,6 +322,7 @@ impl DiagInner {
319322
children: vec![],
320323
suggestions: Suggestions::Enabled(vec![]),
321324
args: Default::default(),
325+
reserved_args: Default::default(),
322326
sort_span: DUMMY_SP,
323327
is_lint: None,
324328
long_ty_path: None,
@@ -390,7 +394,28 @@ impl DiagInner {
390394
}
391395

392396
pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
393-
self.args.insert(name.into(), arg.into_diag_arg(&mut self.long_ty_path));
397+
let name = name.into();
398+
let value = arg.into_diag_arg(&mut self.long_ty_path);
399+
// This assertion is to avoid subdiagnostics overwriting an existing diagnostic arg.
400+
debug_assert!(
401+
!self.args.contains_key(&name) || self.args.get(&name) == Some(&value),
402+
"arg {} already exists",
403+
name
404+
);
405+
self.args.insert(name, value);
406+
}
407+
408+
pub fn remove_arg(&mut self, name: &str) {
409+
self.args.swap_remove(name);
410+
}
411+
412+
pub fn store_args(&mut self) {
413+
self.reserved_args = self.args.clone();
414+
}
415+
416+
pub fn restore_args(&mut self) {
417+
self.args = self.reserved_args.clone();
418+
self.reserved_args.clear();
394419
}
395420

396421
/// Fields used for Hash, and PartialEq trait.
@@ -1423,6 +1448,12 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
14231448
self.downgrade_to_delayed_bug();
14241449
self.emit()
14251450
}
1451+
1452+
pub fn remove_arg(&mut self, name: &str) {
1453+
if let Some(diag) = self.diag.as_mut() {
1454+
diag.remove_arg(name);
1455+
}
1456+
}
14261457
}
14271458

14281459
/// Destructor bomb: every `Diag` must be consumed (emitted, cancelled, etc.)

compiler/rustc_hir_analysis/src/errors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ pub(crate) enum AssocItemNotFoundSugg<'a> {
127127
SimilarInOtherTrait {
128128
#[primary_span]
129129
span: Span,
130+
trait_name: &'a str,
130131
assoc_kind: &'static str,
131132
suggested_name: Symbol,
132133
},

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
309309
// change the associated item.
310310
err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait {
311311
span: assoc_ident.span,
312+
trait_name: &trait_name,
312313
assoc_kind: assoc_kind_str,
313314
suggested_name,
314315
});

compiler/rustc_lint/src/levels.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,8 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
482482
let name = lint_name.as_str();
483483
let suggestion = RenamedLintSuggestion::WithoutSpan { replace };
484484
let requested_level = RequestedLevel { level, lint_name };
485-
let lint = RenamedLintFromCommandLine { name, suggestion, requested_level };
485+
let lint =
486+
RenamedLintFromCommandLine { name, replace, suggestion, requested_level };
486487
self.emit_lint(RENAMED_AND_REMOVED_LINTS, lint);
487488
}
488489
CheckLintNameResult::Removed(ref reason) => {
@@ -824,7 +825,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
824825
RenamedLintSuggestion::WithSpan { suggestion: sp, replace };
825826
let name =
826827
tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
827-
let lint = RenamedLint { name: name.as_str(), suggestion };
828+
let lint = RenamedLint { name: name.as_str(), replace, suggestion };
828829
self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
829830
}
830831

compiler/rustc_lint/src/lifetime_syntax.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,12 +422,12 @@ fn build_mismatch_suggestion(
422422
lifetime_name: &str,
423423
infos: &[&Info<'_>],
424424
) -> lints::MismatchedLifetimeSyntaxesSuggestion {
425-
let lifetime_name = lifetime_name.to_owned();
425+
let lifetime_name_sugg = lifetime_name.to_owned();
426426

427427
let suggestions = infos.iter().map(|info| info.suggestion(&lifetime_name)).collect();
428428

429429
lints::MismatchedLifetimeSyntaxesSuggestion::Explicit {
430-
lifetime_name,
430+
lifetime_name_sugg,
431431
suggestions,
432432
tool_only: false,
433433
}

compiler/rustc_lint/src/lints.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,7 @@ pub(crate) struct DeprecatedLintNameFromCommandLine<'a> {
10891089
#[diag(lint_renamed_lint)]
10901090
pub(crate) struct RenamedLint<'a> {
10911091
pub name: &'a str,
1092+
pub replace: &'a str,
10921093
#[subdiagnostic]
10931094
pub suggestion: RenamedLintSuggestion<'a>,
10941095
}
@@ -1109,6 +1110,7 @@ pub(crate) enum RenamedLintSuggestion<'a> {
11091110
#[diag(lint_renamed_lint)]
11101111
pub(crate) struct RenamedLintFromCommandLine<'a> {
11111112
pub name: &'a str,
1113+
pub replace: &'a str,
11121114
#[subdiagnostic]
11131115
pub suggestion: RenamedLintSuggestion<'a>,
11141116
#[subdiagnostic]
@@ -3227,7 +3229,7 @@ pub(crate) enum MismatchedLifetimeSyntaxesSuggestion {
32273229
},
32283230

32293231
Explicit {
3230-
lifetime_name: String,
3232+
lifetime_name_sugg: String,
32313233
suggestions: Vec<(Span, String)>,
32323234
tool_only: bool,
32333235
},
@@ -3281,13 +3283,12 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion {
32813283
);
32823284
}
32833285

3284-
Explicit { lifetime_name, suggestions, tool_only } => {
3285-
diag.arg("lifetime_name", lifetime_name);
3286-
3286+
Explicit { lifetime_name_sugg, suggestions, tool_only } => {
3287+
diag.arg("lifetime_name_sugg", lifetime_name_sugg);
32873288
let msg = diag.eagerly_translate(
32883289
fluent::lint_mismatched_lifetime_syntaxes_suggestion_explicit,
32893290
);
3290-
3291+
diag.remove_arg("lifetime_name_sugg");
32913292
diag.multipart_suggestion_with_style(
32923293
msg,
32933294
suggestions,

compiler/rustc_macros/src/diagnostics/subdiagnostic.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
220220
}
221221

222222
/// Generates the code for a field with no attributes.
223-
fn generate_field_arg(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream {
223+
fn generate_field_arg(&mut self, binding_info: &BindingInfo<'_>) -> (TokenStream, TokenStream) {
224224
let diag = &self.parent.diag;
225225

226226
let field = binding_info.ast();
@@ -230,12 +230,16 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
230230
let ident = field.ident.as_ref().unwrap();
231231
let ident = format_ident!("{}", ident); // strip `r#` prefix, if present
232232

233-
quote! {
233+
let args = quote! {
234234
#diag.arg(
235235
stringify!(#ident),
236236
#field_binding
237237
);
238-
}
238+
};
239+
let remove_args = quote! {
240+
#diag.remove_arg(stringify!(#ident));
241+
};
242+
(args, remove_args)
239243
}
240244

241245
/// Generates the necessary code for all attributes on a field.
@@ -600,8 +604,13 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
600604

601605
calls.extend(call);
602606
}
603-
604-
let plain_args: TokenStream = self
607+
let store_args = quote! {
608+
#diag.store_args();
609+
};
610+
let restore_args = quote! {
611+
#diag.restore_args();
612+
};
613+
let (plain_args, remove_args): (TokenStream, TokenStream) = self
605614
.variant
606615
.bindings()
607616
.iter()
@@ -610,12 +619,23 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
610619
.collect();
611620

612621
let formatting_init = &self.formatting_init;
622+
623+
// For #[derive(Subdiagnostic)]
624+
//
625+
// - Store args of the main diagnostic for later restore.
626+
// - add args of subdiagnostic.
627+
// - Generate the calls, such as note, label, etc.
628+
// - Remove the arguments for allowing Vec<Subdiagnostic> to be used.
629+
// - Restore the arguments for allowing main and subdiagnostic share the same fields.
613630
Ok(quote! {
614631
#init
615632
#formatting_init
616633
#attr_args
634+
#store_args
617635
#plain_args
618636
#calls
637+
#remove_args
638+
#restore_args
619639
})
620640
}
621641
}

compiler/rustc_metadata/src/dependency_format.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ fn add_library(
314314
crate_name: tcx.crate_name(cnum),
315315
non_static_deps: unavailable_as_static
316316
.drain(..)
317-
.map(|cnum| NonStaticCrateDep { crate_name: tcx.crate_name(cnum) })
317+
.map(|cnum| NonStaticCrateDep { crate_name_: tcx.crate_name(cnum) })
318318
.collect(),
319319
rustc_driver_help: linking_to_rustc_driver.then_some(RustcDriverHelp),
320320
});

compiler/rustc_metadata/src/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pub struct CrateDepMultiple {
4545
#[derive(Subdiagnostic)]
4646
#[note(metadata_crate_dep_not_static)]
4747
pub struct NonStaticCrateDep {
48-
pub crate_name: Symbol,
48+
pub crate_name_: Symbol,
4949
}
5050

5151
#[derive(Subdiagnostic)]

compiler/rustc_mir_build/src/errors.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -994,14 +994,15 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
994994
pub(crate) uncovered: Uncovered,
995995
#[subdiagnostic]
996996
pub(crate) inform: Option<Inform>,
997-
#[label(mir_build_confused)]
998-
pub(crate) interpreted_as_const: Option<Span>,
999997
#[subdiagnostic]
1000-
pub(crate) interpreted_as_const_sugg: Option<InterpretedAsConst>,
998+
pub(crate) interpreted_as_const: Option<InterpretedAsConst>,
999+
#[subdiagnostic]
1000+
pub(crate) interpreted_as_const_sugg: Option<InterpretedAsConstSugg>,
10011001
#[subdiagnostic]
10021002
pub(crate) adt_defined_here: Option<AdtDefinedHere<'tcx>>,
10031003
#[note(mir_build_privately_uninhabited)]
10041004
pub(crate) witness_1_is_privately_uninhabited: bool,
1005+
pub(crate) witness_1: String,
10051006
#[note(mir_build_pattern_ty)]
10061007
pub(crate) _p: (),
10071008
pub(crate) pattern_ty: Ty<'tcx>,
@@ -1016,6 +1017,14 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
10161017
#[note(mir_build_more_information)]
10171018
pub(crate) struct Inform;
10181019

1020+
#[derive(Subdiagnostic)]
1021+
#[label(mir_build_confused)]
1022+
pub(crate) struct InterpretedAsConst {
1023+
#[primary_span]
1024+
pub(crate) span: Span,
1025+
pub(crate) variable: String,
1026+
}
1027+
10191028
pub(crate) struct AdtDefinedHere<'tcx> {
10201029
pub(crate) adt_def_span: Span,
10211030
pub(crate) ty: Ty<'tcx>,
@@ -1046,7 +1055,7 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
10461055
applicability = "maybe-incorrect",
10471056
style = "verbose"
10481057
)]
1049-
pub(crate) struct InterpretedAsConst {
1058+
pub(crate) struct InterpretedAsConstSugg {
10501059
#[primary_span]
10511060
pub(crate) span: Span,
10521061
pub(crate) variable: String,

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -685,8 +685,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
685685
let span = self.tcx.def_span(def_id);
686686
let variable = self.tcx.item_name(def_id).to_string();
687687
// When we encounter a constant as the binding name, point at the `const` definition.
688-
interpreted_as_const = Some(span);
689-
interpreted_as_const_sugg = Some(InterpretedAsConst { span: pat.span, variable });
688+
interpreted_as_const = Some(InterpretedAsConst { span, variable: variable.clone() });
689+
interpreted_as_const_sugg = Some(InterpretedAsConstSugg { span: pat.span, variable });
690690
} else if let PatKind::Constant { .. } = unpeeled_pat.kind
691691
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
692692
{
@@ -738,6 +738,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
738738
false
739739
};
740740

741+
let witness_1 = cx.print_witness_pat(witnesses.get(0).unwrap());
742+
741743
self.error = Err(self.tcx.dcx().emit_err(PatternNotCovered {
742744
span: pat.span,
743745
origin,
@@ -746,6 +748,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
746748
interpreted_as_const,
747749
interpreted_as_const_sugg,
748750
witness_1_is_privately_uninhabited,
751+
witness_1,
749752
_p: (),
750753
pattern_ty,
751754
let_suggestion,

compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,8 +516,12 @@ struct LocalLabel<'a> {
516516
/// A custom `Subdiagnostic` implementation so that the notes are delivered in a specific order
517517
impl Subdiagnostic for LocalLabel<'_> {
518518
fn add_to_diag<G: rustc_errors::EmissionGuarantee>(self, diag: &mut rustc_errors::Diag<'_, G>) {
519+
// Becuase parent uses this field , we need to remove it delay before adding it.
520+
diag.remove_arg("name");
519521
diag.arg("name", self.name);
522+
diag.remove_arg("is_generated_name");
520523
diag.arg("is_generated_name", self.is_generated_name);
524+
diag.remove_arg("is_dropped_first_edition_2024");
521525
diag.arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024);
522526
let msg = diag.eagerly_translate(crate::fluent_generated::mir_transform_tail_expr_local);
523527
diag.span_label(self.span, msg);

compiler/rustc_passes/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ passes_duplicate_lang_item_crate_depends =
291291
.second_definition_path = second definition in `{$crate_name}` loaded from {$path}
292292
293293
passes_enum_variant_same_name =
294-
it is impossible to refer to the {$descr} `{$dead_name}` because it is shadowed by this enum variant with the same name
294+
it is impossible to refer to the {$dead_descr} `{$dead_name}` because it is shadowed by this enum variant with the same name
295295
296296
passes_export_name =
297297
attribute should be applied to a free function, impl method or static

compiler/rustc_passes/src/dead.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1078,7 +1078,7 @@ impl<'tcx> DeadVisitor<'tcx> {
10781078
maybe_enum.variants().iter().find(|i| i.name == dead_item.name)
10791079
{
10801080
Some(crate::errors::EnumVariantSameName {
1081-
descr: tcx.def_descr(dead_item.def_id.to_def_id()),
1081+
dead_descr: tcx.def_descr(dead_item.def_id.to_def_id()),
10821082
dead_name: dead_item.name,
10831083
variant_span: tcx.def_span(variant.def_id),
10841084
})

compiler/rustc_passes/src/errors.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1509,7 +1509,7 @@ pub(crate) struct EnumVariantSameName<'tcx> {
15091509
#[primary_span]
15101510
pub variant_span: Span,
15111511
pub dead_name: Symbol,
1512-
pub descr: &'tcx str,
1512+
pub dead_descr: &'tcx str,
15131513
}
15141514

15151515
#[derive(Subdiagnostic)]
@@ -1707,6 +1707,7 @@ impl Subdiagnostic for UnusedVariableStringInterp {
17071707
#[derive(LintDiagnostic)]
17081708
#[diag(passes_unused_variable_try_ignore)]
17091709
pub(crate) struct UnusedVarTryIgnore {
1710+
pub name: String,
17101711
#[subdiagnostic]
17111712
pub sugg: UnusedVarTryIgnoreSugg,
17121713
}

compiler/rustc_passes/src/liveness.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,6 +1743,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
17431743
.map(|(_, pat_span, _)| *pat_span)
17441744
.collect::<Vec<_>>(),
17451745
errors::UnusedVarTryIgnore {
1746+
name: name.clone(),
17461747
sugg: errors::UnusedVarTryIgnoreSugg {
17471748
shorthands,
17481749
non_shorthands,

0 commit comments

Comments
 (0)