From ca2fc426a9b30a4fd4442512cec312ce8f8ce870 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 17:35:54 +1100 Subject: [PATCH 01/14] Remove `Clone` impl for `DiagnosticBuilder`. It seems like a bad idea, just asking for diagnostics to be emitted multiple times. --- compiler/rustc_errors/src/diagnostic_builder.rs | 5 ++++- compiler/rustc_errors/src/lib.rs | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index e018c14a4a5cd..fab5affbad1ee 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -42,7 +42,6 @@ where /// access in the methods of `DiagnosticBuilder` here, consider /// extending `DiagCtxtFlags`. #[must_use] -#[derive(Clone)] pub struct DiagnosticBuilder<'a, G: EmissionGuarantee = ErrorGuaranteed> { state: DiagnosticBuilderState<'a>, @@ -55,6 +54,10 @@ pub struct DiagnosticBuilder<'a, G: EmissionGuarantee = ErrorGuaranteed> { _marker: PhantomData, } +// Cloning a `DiagnosticBuilder` is a recipe for a diagnostic being emitted +// twice, which would be bad. +impl !Clone for DiagnosticBuilder<'_, G> {} + #[derive(Clone)] enum DiagnosticBuilderState<'a> { /// Initial state of a `DiagnosticBuilder`, before `.emit()` or `.cancel()`. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 25bec9f766b03..e07a9509383b2 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -10,6 +10,7 @@ #![feature(extract_if)] #![feature(if_let_guard)] #![feature(let_chains)] +#![feature(negative_impls)] #![feature(never_type)] #![feature(rustc_attrs)] #![feature(yeet_expr)] From b1b9278851a9512a0c934c12f9c1800169c336f7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 12:17:35 +1100 Subject: [PATCH 02/14] Make `DiagnosticBuilder::emit` consuming. This works for most of its call sites. This is nice, because `emit` very much makes sense as a consuming operation -- indeed, `DiagnosticBuilderState` exists to ensure no diagnostic is emitted twice, but it uses runtime checks. For the small number of call sites where a consuming emit doesn't work, the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will be removed in subsequent commits.) Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes consuming, while `delay_as_bug_without_consuming` is added (which will also be removed in subsequent commits.) All this requires significant changes to `DiagnosticBuilder`'s chaining methods. Currently `DiagnosticBuilder` method chaining uses a non-consuming `&mut self -> &mut Self` style, which allows chaining to be used when the chain ends in `emit()`, like so: ``` struct_err(msg).span(span).emit(); ``` But it doesn't work when producing a `DiagnosticBuilder` value, requiring this: ``` let mut err = self.struct_err(msg); err.span(span); err ``` This style of chaining won't work with consuming `emit` though. For that, we need to use to a `self -> Self` style. That also would allow `DiagnosticBuilder` production to be chained, e.g.: ``` self.struct_err(msg).span(span) ``` However, removing the `&mut self -> &mut Self` style would require that individual modifications of a `DiagnosticBuilder` go from this: ``` err.span(span); ``` to this: ``` err = err.span(span); ``` There are *many* such places. I have a high tolerance for tedious refactorings, but even I gave up after a long time trying to convert them all. Instead, this commit has it both ways: the existing `&mut self -> Self` chaining methods are kept, and new `self -> Self` chaining methods are added, all of which have a `_mv` suffix (short for "move"). Changes to the existing `forward!` macro lets this happen with very little additional boilerplate code. I chose to add the suffix to the new chaining methods rather than the existing ones, because the number of changes required is much smaller that way. This doubled chainging is a bit clumsy, but I think it is worthwhile because it allows a *lot* of good things to subsequently happen. In this commit, there are many `mut` qualifiers removed in places where diagnostics are emitted without being modified. In subsequent commits: - chaining can be used more, making the code more concise; - more use of chaining also permits the removal of redundant diagnostic APIs like `struct_err_with_code`, which can be replaced easily with `struct_err` + `code_mv`; - `emit_without_diagnostic` can be removed, which simplifies a lot of machinery, removing the need for `DiagnosticBuilderState`. --- compiler/rustc_ast_passes/src/feature_gate.rs | 2 +- .../src/diagnostics/region_errors.rs | 2 +- .../src/region_infer/opaque_types.rs | 2 +- compiler/rustc_builtin_macros/src/asm.rs | 6 +- compiler/rustc_builtin_macros/src/assert.rs | 2 +- compiler/rustc_builtin_macros/src/cfg.rs | 2 +- compiler/rustc_builtin_macros/src/cfg_eval.rs | 2 +- .../rustc_builtin_macros/src/cmdline_attrs.rs | 2 +- compiler/rustc_builtin_macros/src/format.rs | 7 +- .../src/proc_macro_harness.rs | 2 +- .../rustc_builtin_macros/src/source_util.rs | 8 +- compiler/rustc_builtin_macros/src/test.rs | 6 +- .../rustc_builtin_macros/src/type_ascribe.rs | 2 +- .../rustc_codegen_ssa/src/codegen_attrs.rs | 4 +- .../rustc_codegen_ssa/src/target_features.rs | 2 +- .../src/transform/check_consts/check.rs | 2 +- compiler/rustc_driver_impl/src/lib.rs | 2 +- .../rustc_errors/src/diagnostic_builder.rs | 201 ++++++++++-------- compiler/rustc_expand/src/base.rs | 4 +- compiler/rustc_expand/src/config.rs | 2 +- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_expand/src/mbe/macro_parser.rs | 4 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- compiler/rustc_expand/src/mbe/quoted.rs | 4 +- compiler/rustc_expand/src/module.rs | 2 +- compiler/rustc_expand/src/proc_macro.rs | 2 +- .../rustc_expand/src/proc_macro_server.rs | 2 +- .../rustc_hir_analysis/src/astconv/bounds.rs | 2 +- .../rustc_hir_analysis/src/astconv/errors.rs | 6 +- .../src/astconv/generics.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 4 +- .../src/astconv/object_safety.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 22 +- .../src/check/compare_impl_item.rs | 6 +- .../rustc_hir_analysis/src/check/dropck.rs | 4 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 10 +- .../rustc_hir_analysis/src/coherence/mod.rs | 2 +- .../src/coherence/unsafety.rs | 10 +- .../src/collect/resolve_bound_vars.rs | 2 +- compiler/rustc_hir_typeck/src/callee.rs | 2 +- compiler/rustc_hir_typeck/src/cast.rs | 6 +- compiler/rustc_hir_typeck/src/demand.rs | 6 +- compiler/rustc_hir_typeck/src/expr.rs | 4 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 6 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 5 +- compiler/rustc_hir_typeck/src/intrinsicck.rs | 10 +- compiler/rustc_hir_typeck/src/lib.rs | 8 +- compiler/rustc_hir_typeck/src/op.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 30 ++- .../src/infer/error_reporting/mod.rs | 2 +- .../error_reporting/nice_region_error/mod.rs | 2 +- .../src/infer/error_reporting/note.rs | 2 +- compiler/rustc_interface/src/queries.rs | 2 +- compiler/rustc_middle/src/ty/opaque_types.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_parse/src/lexer/tokentrees.rs | 2 +- compiler/rustc_parse/src/lib.rs | 6 +- .../rustc_parse/src/parser/diagnostics.rs | 10 +- compiler/rustc_parse/src/parser/expr.rs | 17 +- compiler/rustc_parse/src/parser/generics.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 35 +-- compiler/rustc_parse/src/parser/mod.rs | 6 +- compiler/rustc_parse/src/parser/pat.rs | 14 +- compiler/rustc_parse/src/parser/path.rs | 4 +- compiler/rustc_parse/src/parser/stmt.rs | 6 +- compiler/rustc_parse/src/parser/ty.rs | 21 +- compiler/rustc_parse/src/validate_attr.rs | 6 +- .../rustc_passes/src/debugger_visualizer.rs | 2 +- compiler/rustc_passes/src/errors.rs | 2 +- .../rustc_query_system/src/query/plumbing.rs | 2 +- .../rustc_resolve/src/build_reduced_graph.rs | 9 +- compiler/rustc_resolve/src/imports.rs | 2 +- compiler/rustc_resolve/src/late.rs | 4 +- compiler/rustc_resolve/src/macros.rs | 6 +- compiler/rustc_session/src/session.rs | 5 +- .../src/traits/const_evaluatable.rs | 4 +- .../src/traits/error_reporting/suggestions.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 5 +- .../src/traits/specialize/mod.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/config.rs | 10 +- .../passes/collect_intra_doc_links.rs | 2 +- src/tools/clippy/clippy_config/src/msrvs.rs | 2 +- src/tools/clippy/clippy_utils/src/attrs.rs | 2 +- src/tools/rustfmt/src/parse/parser.rs | 4 +- 86 files changed, 329 insertions(+), 312 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 2b746789a769f..35b8de64af7ef 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -23,7 +23,7 @@ macro_rules! gate { ($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{ if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) { feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain) - .help($help) + .help_mv($help) .emit(); } }}; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index b3450b09cdf9e..020429c191449 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -348,7 +348,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty); let named_key = self.regioncx.name_regions(self.infcx.tcx, key); let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region); - let mut diag = unexpected_hidden_region_diagnostic( + let diag = unexpected_hidden_region_diagnostic( self.infcx.tcx, span, named_ty, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 093017ecba235..5f427a5ac801c 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -421,7 +421,7 @@ fn check_opaque_type_parameter_valid( return Err(tcx .dcx() .struct_span_err(span, "non-defining opaque type use in defining scope") - .span_note(spans, format!("{descr} used multiple times")) + .span_note_mv(spans, format!("{descr} used multiple times")) .emit()); } } diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index b5801c1b0f168..ac90f4d4084d3 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -458,7 +458,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option template_part, Err(err) => { - if let Some((mut err, _)) = err { + if let Some((err, _)) = err { err.emit(); } return None; @@ -747,7 +747,7 @@ pub(super) fn expand_asm<'cx>( }; MacEager::expr(expr) } - Err(mut err) => { + Err(err) => { err.emit(); DummyResult::any(sp) } @@ -779,7 +779,7 @@ pub(super) fn expand_global_asm<'cx>( DummyResult::any(sp) } } - Err(mut err) => { + Err(err) => { err.emit(); DummyResult::any(sp) } diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 8fa3fe5b3e6cf..501d557f3ab8a 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -22,7 +22,7 @@ pub fn expand_assert<'cx>( ) -> Box { let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) { Ok(assert) => assert, - Err(mut err) => { + Err(err) => { err.emit(); return DummyResult::any(span); } diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 48be680b619f7..1bc2512a7b054 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -28,7 +28,7 @@ pub fn expand_cfg( ); MacEager::expr(cx.expr_bool(sp, matches_cfg)) } - Err(mut err) => { + Err(err) => { err.emit(); DummyResult::any(sp) } diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index ca26b7ed8270d..cfa94b0e78085 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -200,7 +200,7 @@ impl CfgEval<'_, '_> { parser.capture_cfg = true; match parse_annotatable_with(&mut parser) { Ok(a) => annotatable = a, - Err(mut err) => { + Err(err) => { err.emit(); return Some(annotatable); } diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs index 2803ddefba210..d956c096d24a1 100644 --- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs +++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs @@ -18,7 +18,7 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String]) let start_span = parser.token.span; let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item(false) { Ok(ai) => ai, - Err(mut err) => { + Err(err) => { err.emit(); continue; } diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index a668db438eb2c..93381b69fdcc1 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -99,7 +99,7 @@ fn parse_args<'a>(ecx: &mut ExtCtxt<'a>, sp: Span, tts: TokenStream) -> PResult< } match p.expect(&token::Comma) { - Err(mut err) => { + Err(err) => { match token::TokenKind::Comma.similar_tokens() { Some(tks) if tks.contains(&p.token.kind) => { // If a similar token is found, then it may be a typo. We @@ -630,8 +630,7 @@ fn report_missing_placeholders( .collect::>(); if !placeholders.is_empty() { - if let Some(mut new_diag) = report_redundant_format_arguments(ecx, args, used, placeholders) - { + if let Some(new_diag) = report_redundant_format_arguments(ecx, args, used, placeholders) { diag.cancel(); new_diag.emit(); return; @@ -976,7 +975,7 @@ fn expand_format_args_impl<'cx>( MacEager::expr(DummyResult::raw_expr(sp, true)) } } - Err(mut err) => { + Err(err) => { err.emit(); DummyResult::any(sp) } diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 4fddaa8ab6cda..9fb6da6e0121f 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -194,7 +194,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { self.dcx .struct_span_err(attr.span, msg) - .span_label(prev_attr.span, "previous attribute here") + .span_label_mv(prev_attr.span, "previous attribute here") .emit(); return; diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 30f80bb87dd15..caebb12919fc1 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -109,7 +109,7 @@ pub fn expand_include<'cx>( // The file will be added to the code map by the parser let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) { Ok(f) => f, - Err(mut err) => { + Err(err) => { err.emit(); return DummyResult::any(sp); } @@ -146,7 +146,7 @@ pub fn expand_include<'cx>( let mut ret = SmallVec::new(); loop { match self.p.parse_item(ForceCollect::No) { - Err(mut err) => { + Err(err) => { err.emit(); break; } @@ -181,7 +181,7 @@ pub fn expand_include_str( }; let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) { Ok(f) => f, - Err(mut err) => { + Err(err) => { err.emit(); return DummyResult::any(sp); } @@ -215,7 +215,7 @@ pub fn expand_include_bytes( }; let file = match resolve_path(&cx.sess.parse_sess, file.as_str(), sp) { Ok(f) => f, - Err(mut err) => { + Err(err) => { err.emit(); return DummyResult::any(sp); } diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 568f8247b2807..717f5d9c38a25 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -409,8 +409,8 @@ fn not_testable_error(cx: &ExtCtxt<'_>, attr_sp: Span, item: Option<&ast::Item>) ), ); } - err.span_label(attr_sp, "the `#[test]` macro causes a function to be run as a test and has no effect on non-functions") - .span_suggestion(attr_sp, + err.span_label_mv(attr_sp, "the `#[test]` macro causes a function to be run as a test and has no effect on non-functions") + .span_suggestion_mv(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", "#[cfg(test)]", Applicability::MaybeIncorrect) @@ -480,7 +480,7 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { "argument must be of the form: \ `expected = \"error message\"`", ) - .note( + .note_mv( "errors in this attribute were erroneously \ allowed and will become a hard error in a \ future release", diff --git a/compiler/rustc_builtin_macros/src/type_ascribe.rs b/compiler/rustc_builtin_macros/src/type_ascribe.rs index 72b85af148638..564797012ae26 100644 --- a/compiler/rustc_builtin_macros/src/type_ascribe.rs +++ b/compiler/rustc_builtin_macros/src/type_ascribe.rs @@ -12,7 +12,7 @@ pub fn expand_type_ascribe( ) -> Box { let (expr, ty) = match parse_ascribe(cx, tts) { Ok(parsed) => parsed, - Err(mut err) => { + Err(err) => { err.emit(); return DummyResult::any(span); } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 63fd7b42f7ba1..a1ec191f10524 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -477,7 +477,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { InlineAttr::Never } else { struct_span_err!(tcx.dcx(), items[0].span(), E0535, "invalid argument") - .help("valid inline arguments are `always` and `never`") + .help_mv("valid inline arguments are `always` and `never`") .emit(); InlineAttr::None @@ -662,7 +662,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal); tcx.dcx() .struct_span_err(attr.span, msg) - .note("the value may not exceed `u16::MAX`") + .note_mv("the value may not exceed `u16::MAX`") .emit(); None } diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index b6bb1607a09c6..c0ce8a54af573 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -27,7 +27,7 @@ pub fn from_target_feature( let code = "enable = \"..\""; tcx.dcx() .struct_span_err(span, msg) - .span_suggestion(span, "must be of the form", code, Applicability::HasPlaceholders) + .span_suggestion_mv(span, "must be of the form", code, Applicability::HasPlaceholders) .emit(); }; let rust_features = tcx.features(); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 92955c4ed14ca..738c532964a2c 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -338,7 +338,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { return; } - let mut err = op.build_error(self.ccx, span); + let err = op.build_error(self.ccx, span); assert!(err.is_error()); match op.importance() { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index fd925b62702af..da3776ef96a5e 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -716,7 +716,7 @@ fn print_crate_info( let result = parse_crate_attrs(sess); match result { Ok(attrs) => Some(attrs), - Err(mut parse_error) => { + Err(parse_error) => { parse_error.emit(); return Compilation::Stop; } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index fab5affbad1ee..e41acd6447bff 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -198,23 +198,34 @@ impl EmissionGuarantee for rustc_span::fatal_error::FatalError { } } -/// In general, the `DiagnosticBuilder` uses deref to allow access to -/// the fields and methods of the embedded `diagnostic` in a -/// transparent way. *However,* many of the methods are intended to -/// be used in a chained way, and hence ought to return `self`. In -/// that case, we can't just naively forward to the method on the -/// `diagnostic`, because the return type would be a `&Diagnostic` -/// instead of a `&DiagnosticBuilder<'a>`. This `forward!` macro makes -/// it easy to declare such methods on the builder. +/// `DiagnosticBuilder` impls `DerefMut`, which allows access to the fields and +/// methods of the embedded `Diagnostic`. However, that doesn't allow method +/// chaining at the `DiagnosticBuilder` level. Each use of this macro defines +/// two builder methods at that level, both of which wrap the equivalent method +/// in `Diagnostic`. +/// - A `&mut self -> &mut Self` method, with the same name as the underlying +/// `Diagnostic` method. It is mostly to modify existing diagnostics, either +/// in a standalone fashion, e.g. `err.code(code)`, or in a chained fashion +/// to make multiple modifications, e.g. `err.code(code).span(span)`. +/// - A `self -> Self` method, with `_mv` suffix added (short for "move"). +/// It is mostly used in a chained fashion when producing a new diagnostic, +/// e.g. `let err = struct_err(msg).code_mv(code)`, or when emitting a new +/// diagnostic , e.g. `struct_err(msg).code_mv(code).emit()`. +/// +/// Although the latter method can be used to modify an existing diagnostic, +/// e.g. `err = err.code_mv(code)`, this should be avoided because the former +/// method give shorter code, e.g. `err.code(code)`. macro_rules! forward { - // Forward pattern for &mut self -> &mut Self ( - $(#[$attrs:meta])* - pub fn $n:ident(&mut self $(, $name:ident: $ty:ty)* $(,)?) -> &mut Self + ($n:ident, $n_mv:ident)($($name:ident: $ty:ty),* $(,)?) ) => { - $(#[$attrs])* #[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")] - pub fn $n(&mut self $(, $name: $ty)*) -> &mut Self { + pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { + self.diagnostic.$n($($name),*); + self + } + #[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")] + pub fn $n_mv(mut self, $($name: $ty),*) -> Self { self.diagnostic.$n($($name),*); self } @@ -254,11 +265,15 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { } } - /// Emit the diagnostic. Does not consume `self`, which may be surprising, - /// but there are various places that rely on continuing to use `self` - /// after calling `emit`. + /// Emit and consume the diagnostic. #[track_caller] - pub fn emit(&mut self) -> G::EmitResult { + pub fn emit(mut self) -> G::EmitResult { + G::emit_producing_guarantee(&mut self) + } + + /// Emit the diagnostic without consuming it. `emit` should be preferred. + #[track_caller] + pub fn emit_without_consuming(&mut self) -> G::EmitResult { G::emit_producing_guarantee(self) } @@ -267,7 +282,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// /// See `emit` and `delay_as_bug` for details. #[track_caller] - pub fn emit_unless(&mut self, delay: bool) -> G::EmitResult { + pub fn emit_unless(mut self, delay: bool) -> G::EmitResult { if delay { self.downgrade_to_delayed_bug(); } @@ -354,142 +369,142 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. #[track_caller] - pub fn delay_as_bug(&mut self) -> G::EmitResult { + pub fn delay_as_bug(mut self) -> G::EmitResult { self.downgrade_to_delayed_bug(); self.emit() } - forward!(pub fn span_label( - &mut self, + /// Non-consuming variant of `delay_as_bug`. + #[track_caller] + pub fn delay_as_bug_without_consuming(&mut self) -> G::EmitResult { + self.downgrade_to_delayed_bug(); + self.emit_without_consuming() + } + + forward!((span_label, span_label_mv)( span: Span, - label: impl Into - ) -> &mut Self); - forward!(pub fn span_labels( - &mut self, + label: impl Into, + )); + forward!((span_labels, span_labels_mv)( spans: impl IntoIterator, label: &str, - ) -> &mut Self); - forward!(pub fn note_expected_found( - &mut self, + )); + forward!((note_expected_found, note_expected_found_mv)( expected_label: &dyn fmt::Display, expected: DiagnosticStyledString, found_label: &dyn fmt::Display, found: DiagnosticStyledString, - ) -> &mut Self); - forward!(pub fn note_expected_found_extra( - &mut self, + )); + forward!((note_expected_found_extra, note_expected_found_extra_mv)( expected_label: &dyn fmt::Display, expected: DiagnosticStyledString, found_label: &dyn fmt::Display, found: DiagnosticStyledString, expected_extra: &dyn fmt::Display, found_extra: &dyn fmt::Display, - ) -> &mut Self); - forward!(pub fn note(&mut self, msg: impl Into) -> &mut Self); - forward!(pub fn note_once(&mut self, msg: impl Into) -> &mut Self); - forward!(pub fn span_note( - &mut self, + )); + forward!((note, note_mv)( + msg: impl Into, + )); + forward!((note_once, note_once_mv)( + msg: impl Into, + )); + forward!((span_note, span_note_mv)( sp: impl Into, msg: impl Into, - ) -> &mut Self); - forward!(pub fn span_note_once( - &mut self, + )); + forward!((span_note_once, span_note_once_mv)( sp: impl Into, msg: impl Into, - ) -> &mut Self); - forward!(pub fn warn(&mut self, msg: impl Into) -> &mut Self); - forward!(pub fn span_warn( - &mut self, + )); + forward!((warn, warn_mv)( + msg: impl Into, + )); + forward!((span_warn, span_warn_mv)( sp: impl Into, msg: impl Into, - ) -> &mut Self); - forward!(pub fn help(&mut self, msg: impl Into) -> &mut Self); - forward!(pub fn help_once(&mut self, msg: impl Into) -> &mut Self); - forward!(pub fn span_help( - &mut self, + )); + forward!((help, help_mv)( + msg: impl Into, + )); + forward!((help_once, help_once_mv)( + msg: impl Into, + )); + forward!((span_help, span_help_once_mv)( sp: impl Into, msg: impl Into, - ) -> &mut Self); - forward!(pub fn is_lint(&mut self) -> &mut Self); - forward!(pub fn disable_suggestions(&mut self) -> &mut Self); - forward!(pub fn multipart_suggestion( - &mut self, + )); + forward!((multipart_suggestion, multipart_suggestion_mv)( msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, - ) -> &mut Self); - forward!(pub fn multipart_suggestion_verbose( - &mut self, + )); + forward!((multipart_suggestion_verbose, multipart_suggestion_verbose_mv)( msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, - ) -> &mut Self); - forward!(pub fn tool_only_multipart_suggestion( - &mut self, + )); + forward!((tool_only_multipart_suggestion, tool_only_multipart_suggestion_mv)( msg: impl Into, suggestion: Vec<(Span, String)>, applicability: Applicability, - ) -> &mut Self); - forward!(pub fn span_suggestion( - &mut self, + )); + forward!((span_suggestion, span_suggestion_mv)( sp: Span, msg: impl Into, suggestion: impl ToString, applicability: Applicability, - ) -> &mut Self); - forward!(pub fn span_suggestions( - &mut self, + )); + forward!((span_suggestions, span_suggestions_mv)( sp: Span, msg: impl Into, suggestions: impl IntoIterator, applicability: Applicability, - ) -> &mut Self); - forward!(pub fn multipart_suggestions( - &mut self, + )); + forward!((multipart_suggestions, multipart_suggestions_mv)( msg: impl Into, suggestions: impl IntoIterator>, applicability: Applicability, - ) -> &mut Self); - forward!(pub fn span_suggestion_short( - &mut self, + )); + forward!((span_suggestion_short, span_suggestion_short_mv)( sp: Span, msg: impl Into, suggestion: impl ToString, applicability: Applicability, - ) -> &mut Self); - forward!(pub fn span_suggestion_verbose( - &mut self, + )); + forward!((span_suggestion_verbose, span_suggestion_verbose_mv)( sp: Span, msg: impl Into, suggestion: impl ToString, applicability: Applicability, - ) -> &mut Self); - forward!(pub fn span_suggestion_hidden( - &mut self, + )); + forward!((span_suggestion_hidden, span_suggestion_hidden_mv)( sp: Span, msg: impl Into, suggestion: impl ToString, applicability: Applicability, - ) -> &mut Self); - forward!(pub fn tool_only_span_suggestion( - &mut self, + )); + forward!((tool_only_span_suggestion, tool_only_span_suggestion_mv)( sp: Span, msg: impl Into, suggestion: impl ToString, applicability: Applicability, - ) -> &mut Self); - forward!(pub fn primary_message(&mut self, msg: impl Into) -> &mut Self); - forward!(pub fn span(&mut self, sp: impl Into) -> &mut Self); - forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); - forward!(pub fn arg( - &mut self, - name: impl Into>, - arg: impl IntoDiagnosticArg, - ) -> &mut Self); - forward!(pub fn subdiagnostic( - &mut self, - subdiagnostic: impl crate::AddToDiagnostic - ) -> &mut Self); + )); + forward!((primary_message, primary_message_mv)( + msg: impl Into, + )); + forward!((span, span_mv)( + sp: impl Into, + )); + forward!((code, code_mv)( + s: DiagnosticId, + )); + forward!((arg, arg_mv)( + name: impl Into>, arg: impl IntoDiagnosticArg, + )); + forward!((subdiagnostic, subdiagnostic_mv)( + subdiagnostic: impl crate::AddToDiagnostic, + )); } impl Debug for DiagnosticBuilder<'_, G> { diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 8b5a22d191464..e87f2306bc709 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1232,7 +1232,7 @@ pub fn expr_to_string( ) -> Option<(Symbol, ast::StrStyle)> { expr_to_spanned_string(cx, expr, err_msg) .map_err(|err| { - err.map(|(mut err, _)| { + err.map(|(err, _)| { err.emit(); }) }) @@ -1254,7 +1254,7 @@ pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option> { match p.parse_expr() { Ok(e) => return Some(e), - Err(mut err) => { + Err(err) => { err.emit(); } } diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs index 2283a3bfc7606..d015d77996327 100644 --- a/compiler/rustc_expand/src/config.rs +++ b/compiler/rustc_expand/src/config.rs @@ -362,7 +362,7 @@ impl<'a> StripUnconfigured<'a> { pub(crate) fn cfg_true(&self, attr: &Attribute) -> (bool, Option) { let meta_item = match validate_attr::parse_meta(&self.sess.parse_sess, attr) { Ok(meta_item) => meta_item, - Err(mut err) => { + Err(err) => { err.emit(); return (true, None); } diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 5a616e0ffbff3..c39a3dce34e4e 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -735,7 +735,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fragment_kind.expect_from_annotatables(items) } } - Err(mut err) => { + Err(err) => { err.emit(); fragment_kind.dummy(span) } diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index b248a1fe349b3..b86831b8222d9 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -679,8 +679,8 @@ impl TtParser { // We use the span of the metavariable declaration to determine any // edition-specific matching behavior for non-terminals. let nt = match parser.to_mut().parse_nonterminal(kind) { - Err(mut err) => { - let guarantee = err.span_label( + Err(err) => { + let guarantee = err.span_label_mv( span, format!( "while parsing argument for this `{kind}` macro fragment" diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index e9797abcbdf24..68296700987ef 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -215,7 +215,7 @@ fn expand_macro<'cx>( // rhs has holes ( `$id` and `$(...)` that need filled) let tts = match transcribe(cx, &named_matches, rhs, rhs_span, transparency) { Ok(tts) => tts, - Err(mut err) => { + Err(err) => { err.emit(); return DummyResult::any(arm_span); } diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index cd4ba7a9a62b4..c3e4f40c166a0 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -86,7 +86,7 @@ pub(super) fn parse( ); sess.dcx .struct_span_err(span, msg) - .help(VALID_FRAGMENT_NAMES_MSG) + .help_mv(VALID_FRAGMENT_NAMES_MSG) .emit(); token::NonterminalKind::Ident }, @@ -175,7 +175,7 @@ fn parse_tree<'a>( // of a meta-variable expression (e.g. `${count(ident)}`). // Try to parse the meta-variable expression. match MetaVarExpr::parse(tts, delim_span.entire(), sess) { - Err(mut err) => { + Err(err) => { err.emit(); // Returns early the same read `$` to avoid spanning // unrelated diagnostics that could be performed afterwards diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index 60647c3350a31..e979f9a75d4d1 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -282,7 +282,7 @@ impl ModError<'_> { secondary_path: secondary_path.display().to_string(), }) } - ModError::ParserError(mut err) => err.emit(), + ModError::ParserError(err) => err.emit(), } } } diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 73a7d433b5c68..001b3fe44968e 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -171,7 +171,7 @@ impl MultiItemModifier for DeriveProcMacro { items.push(Annotatable::Item(item)); } } - Err(mut err) => { + Err(err) => { err.emit(); break; } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 66695e020f1d1..0053f5503186b 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -537,7 +537,7 @@ impl server::TokenStream for Rustc<'_, '_> { } expr }; - let expr = expr.map_err(|mut err| { + let expr = expr.map_err(|err| { err.emit(); })?; diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index d403f1a850d9c..38184a5dd1824 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -305,7 +305,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { binding.span, format!("{} `{}` is private", assoc_item.kind, binding.item_name), ) - .span_label(binding.span, format!("private {}", assoc_item.kind)) + .span_label_mv(binding.span, format!("private {}", assoc_item.kind)) .emit(); } tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 5e1c29440a50b..24b55461a4277 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -58,13 +58,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if !trait_def.paren_sugar { if trait_segment.args().parenthesized == hir::GenericArgsParentheses::ParenSugar { // For now, require that parenthetical notation be used only with `Fn()` etc. - let mut err = feature_err( + feature_err( &self.tcx().sess.parse_sess, sym::unboxed_closures, span, "parenthetical notation is only stable when used with `Fn`-family traits", - ); - err.emit(); + ) + .emit(); } return; diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 3f0ad6584b65f..257b108471f4d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -70,7 +70,7 @@ fn generic_arg_mismatch_err( Res::Err => { add_braces_suggestion(arg, &mut err); return err - .primary_message("unresolved item provided when a constant was expected") + .primary_message_mv("unresolved item provided when a constant was expected") .emit(); } Res::Def(DefKind::TyParam, src_def_id) => { diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 092df257dbfae..0a924aa3536ee 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1648,8 +1648,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let def_span = tcx.def_span(item); tcx.dcx() .struct_span_err_with_code(span, msg, rustc_errors::error_code!(E0624)) - .span_label(span, format!("private {kind}")) - .span_label(def_span, format!("{kind} defined here")) + .span_label_mv(span, format!("private {kind}")) + .span_label_mv(def_span, format!("{kind} defined here")) .emit(); } tcx.check_stability(item, Some(block), span, None); diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 8a3df79cb2534..ff84a98249527 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -375,7 +375,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_region_to_region(lifetime, None) } else { self.re_infer(None, span).unwrap_or_else(|| { - let mut err = struct_span_err!( + let err = struct_span_err!( tcx.dcx(), span, E0228, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 5ccb7ac389641..544e06879f6f0 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -550,8 +550,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { E0044, "foreign items may not have {kinds} parameters", ) - .span_label(item.span, format!("can't have {kinds} parameters")) - .help( + .span_label_mv(item.span, format!("can't have {kinds} parameters")) + .help_mv( // FIXME: once we start storing spans for type arguments, turn this // into a suggestion. format!( @@ -788,7 +788,7 @@ fn check_impl_items_against_trait<'tcx>( }; tcx.dcx() .struct_span_err(tcx.def_span(def_id), msg) - .note(format!( + .note_mv(format!( "specialization behaves in inconsistent and \ surprising ways with {feature}, \ and for now is disallowed" @@ -830,7 +830,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { let e = fields[FieldIdx::from_u32(0)].ty(tcx, args); if !fields.iter().all(|f| f.ty(tcx, args) == e) { struct_span_err!(tcx.dcx(), sp, E0076, "SIMD vector should be homogeneous") - .span_label(sp, "SIMD elements must have the same type") + .span_label_mv(sp, "SIMD elements must have the same type") .emit(); return; } @@ -1107,7 +1107,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { E0084, "unsupported representation for zero-variant enum" ) - .span_label(tcx.def_span(def_id), "zero-variant enum") + .span_label_mv(tcx.def_span(def_id), "zero-variant enum") .emit(); } } @@ -1140,7 +1140,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { let disr_non_unit = def.variants().iter().any(|var| !is_unit(var) && has_disr(var)); if disr_non_unit || (disr_units && has_non_units) { - let mut err = struct_span_err!( + let err = struct_span_err!( tcx.dcx(), tcx.def_span(def_id), E0732, @@ -1249,7 +1249,7 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) } } - if let Some(mut e) = error { + if let Some(e) = error { e.emit(); } @@ -1294,7 +1294,7 @@ pub(super) fn check_type_params_are_used<'tcx>( { let span = tcx.def_span(param.def_id); struct_span_err!(tcx.dcx(), span, E0091, "type parameter `{}` is unused", param.name,) - .span_label(span, "unused type parameter") + .span_label_mv(span, "unused type parameter") .emit(); } } @@ -1302,9 +1302,9 @@ pub(super) fn check_type_params_are_used<'tcx>( fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed { struct_span_err!(tcx.dcx(), span, E0733, "recursion in an `async fn` requires boxing") - .span_label(span, "recursive `async fn`") - .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`") - .note( + .span_label_mv(span, "recursive `async fn`") + .note_mv("a recursive `async fn` must be rewritten to return a boxed `dyn Future`") + .note_mv( "consider using the `async_recursion` crate: https://crates.io/crates/async_recursion", ) .emit() diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index cc4dc5aca0d9b..f5323fd3bb8df 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -934,12 +934,12 @@ impl<'tcx> ty::FallibleTypeFolder> for RemapHiddenTyRegions<'tcx> { return_span, "return type captures more lifetimes than trait definition", ) - .span_label(self.tcx.def_span(def_id), "this lifetime was captured") - .span_note( + .span_label_mv(self.tcx.def_span(def_id), "this lifetime was captured") + .span_note_mv( self.tcx.def_span(self.def_id), "hidden type must only reference lifetimes captured by this impl trait", ) - .note(format!("hidden type inferred to be `{}`", self.ty)) + .note_mv(format!("hidden type inferred to be `{}`", self.ty)) .emit() } _ => { diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 3492499db686a..ff78d040aca17 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -161,7 +161,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( "`Drop` impl requires `{root_predicate}` \ but the {self_descr} it is implemented for does not", ) - .span_note(item_span, "the implementor must specify the same requirement") + .span_note_mv(item_span, "the implementor must specify the same requirement") .emit(), ); } @@ -193,7 +193,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( "`Drop` impl requires `{outlives}` \ but the {self_descr} it is implemented for does not", ) - .span_note(item_span, "the implementor must specify the same requirement") + .span_note_mv(item_span, "the implementor must specify the same requirement") .emit(), ); } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 632af780ed85c..a5aedeb33ae96 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -30,7 +30,7 @@ fn equate_intrinsic_type<'tcx>( } _ => { struct_span_err!(tcx.dcx(), it.span, E0622, "intrinsic must be a function") - .span_label(it.span, "expected a function") + .span_label_mv(it.span, "expected a function") .emit(); return; } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 5f26da9c87f4d..c53ff56555005 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -838,8 +838,8 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem trait_should_be_self, "associated item referring to unboxed trait object for its own trait", ) - .span_label(trait_name.span, "in this trait") - .multipart_suggestion( + .span_label_mv(trait_name.span, "in this trait") + .multipart_suggestion_mv( "you might have meant to use `Self` to refer to the implementing type", sugg, Applicability::MachineApplicable, @@ -1599,7 +1599,7 @@ fn check_method_receiver<'tcx>( the `arbitrary_self_types` feature", ), ) - .help(HELP_FOR_SELF_TYPE) + .help_mv(HELP_FOR_SELF_TYPE) .emit() } else { // Report error; would not have worked with `arbitrary_self_types`. @@ -1612,8 +1612,8 @@ fn check_method_receiver<'tcx>( fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) -> ErrorGuaranteed { struct_span_err!(tcx.dcx(), span, E0307, "invalid `self` parameter type: {receiver_ty}") - .note("type of `self` must be `Self` or a type that dereferences to it") - .help(HELP_FOR_SELF_TYPE) + .note_mv("type of `self` must be `Self` or a type that dereferences to it") + .help_mv(HELP_FOR_SELF_TYPE) .emit() } diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 5cc9da25d6a53..3d56f8fd44ea2 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -181,7 +181,7 @@ fn check_object_overlap<'tcx>( trait_ref.self_ty(), tcx.def_path_str(trait_def_id) ) - .span_label( + .span_label_mv( span, format!( "`{}` automatically implements trait `{}`", diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index d208c55055b8e..272c13b4c1c8e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -25,7 +25,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "implementing the trait `{}` is not unsafe", trait_ref.print_trait_sugared() ) - .span_suggestion_verbose( + .span_suggestion_verbose_mv( item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)), "remove `unsafe` from this trait implementation", "", @@ -42,13 +42,13 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "the trait `{}` requires an `unsafe impl` declaration", trait_ref.print_trait_sugared() ) - .note(format!( + .note_mv(format!( "the trait `{}` enforces invariants that the compiler can't check. \ Review the trait documentation and make sure this implementation \ upholds those invariants before adding the `unsafe` keyword", trait_ref.print_trait_sugared() )) - .span_suggestion_verbose( + .span_suggestion_verbose_mv( item.span.shrink_to_lo(), "add `unsafe` to this trait implementation", "unsafe ", @@ -65,13 +65,13 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "requires an `unsafe impl` declaration due to `#[{}]` attribute", attr_name ) - .note(format!( + .note_mv(format!( "the trait `{}` enforces invariants that the compiler can't check. \ Review the trait documentation and make sure this implementation \ upholds those invariants before adding the `unsafe` keyword", trait_ref.print_trait_sugared() )) - .span_suggestion_verbose( + .span_suggestion_verbose_mv( item.span.shrink_to_lo(), "add `unsafe` to this trait implementation", "unsafe ", diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 9a28534d7900b..c033cec31550d 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2114,7 +2114,7 @@ pub fn deny_non_region_late_bound( hir::GenericParamKind::Lifetime { .. } => continue, }; - let mut diag = tcx.dcx().struct_span_err( + let diag = tcx.dcx().struct_span_err( param.span, format!("late-bound {what} parameter not allowed on {where_}"), ); diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index de2cb5a6d5c7c..8939c2ddea54e 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -402,7 +402,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_expr.span, format!("evaluate({predicate:?}) = {result:?}"), ) - .span_label(predicate_span, "predicate") + .span_label_mv(predicate_span, "predicate") .emit(); } } diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 631854444793b..0a9f2a27cb83f 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -269,7 +269,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { } CastError::NeedViaInt => { make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx) - .help("cast through an integer first") + .help_mv("cast through an integer first") .emit(); } CastError::IllegalCast => { @@ -277,7 +277,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { } CastError::DifferingKinds => { make_invalid_casting_error(self.span, self.expr_ty, self.cast_ty, fcx) - .note("vtable kinds may not match") + .note_mv("vtable kinds may not match") .emit(); } CastError::CastToBool => { @@ -512,7 +512,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { self.cast_ty, fcx, ) - .note("cannot cast an enum with a non-exhaustive variant when it's defined in another crate") + .note_mv("cannot cast an enum with a non-exhaustive variant when it's defined in another crate") .emit(); } } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index c717319e5072a..9850892bd36af 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -158,7 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Requires that the two types unify, and prints an error message if /// they don't. pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { - if let Some(mut e) = self.demand_suptype_diag(sp, expected, actual) { + if let Some(e) = self.demand_suptype_diag(sp, expected, actual) { e.emit(); } } @@ -189,7 +189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { - if let Some(mut err) = self.demand_eqtype_diag(sp, expected, actual) { + if let Some(err) = self.demand_eqtype_diag(sp, expected, actual) { err.emit(); } } @@ -228,7 +228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let (ty, err) = self.demand_coerce_diag(expr, checked_ty, expected, expected_ty_expr, allow_two_phase); - if let Some(mut err) = err { + if let Some(err) = err { err.emit(); } ty diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 44d9f1ed81846..69a65e8b750b1 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1338,7 +1338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Err(error) => { if segment.ident.name != kw::Empty { - if let Some(mut err) = self.report_method_error( + if let Some(err) = self.report_method_error( span, rcvr_t, segment.ident, @@ -2011,7 +2011,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { != range_def_id { // Suppress any range expr type mismatches - if let Some(mut diag) = + if let Some(diag) = self.dcx().steal_diagnostic(last_expr_field.span, StashKey::MaybeFruTypo) { diag.delay_as_bug(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index cb109a2e02428..a4cd9ccc984e1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -845,7 +845,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .and_then(|r| { // lint bare trait if the method is found in the trait if span.edition().at_least_rust_2021() - && let Some(mut diag) = + && let Some(diag) = self.dcx().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) { diag.emit(); @@ -877,7 +877,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // emit or cancel the diagnostic for bare traits if span.edition().at_least_rust_2021() - && let Some(mut diag) = + && let Some(diag) = self.dcx().steal_diagnostic(qself.span, StashKey::TraitMissingMethod) { if trait_missing_method { @@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if item_name.name != kw::Empty { - if let Some(mut e) = self.report_method_error( + if let Some(e) = self.report_method_error( span, ty.normalized, item_name, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 7b85c492eae5c..9b89169116182 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1384,7 +1384,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "expected struct, variant or union type, found {}", ty.normalized.sort_string(self.tcx) ) - .span_label(path_span, "not a struct") + .span_label_mv(path_span, "not a struct") .emit(), }) } @@ -1459,8 +1459,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let previous_diverges = self.diverges.get(); let else_ty = self.check_block_with_expected(blk, NoExpectation); let cause = self.cause(blk.span, ObligationCauseCode::LetElse); - if let Some(mut err) = - self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty) + if let Some(err) = self.demand_eqtype_with_origin(&cause, self.tcx.types.never, else_ty) { err.emit(); } diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 44d28123fa3fa..a18f486b0d252 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -74,9 +74,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && size_to == Pointer(dl.instruction_address_space).size(&tcx) { struct_span_err!(tcx.dcx(), span, E0591, "can't transmute zero-sized type") - .note(format!("source type: {from}")) - .note(format!("target type: {to}")) - .help("cast with `as` to a pointer instead") + .note_mv(format!("source type: {from}")) + .note_mv(format!("target type: {to}")) + .help_mv("cast with `as` to a pointer instead") .emit(); return; } @@ -125,9 +125,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.note(format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))) .note(format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); if let Err(LayoutError::ReferencesError(_)) = sk_from { - err.delay_as_bug(); + err.delay_as_bug_without_consuming(); } else if let Err(LayoutError::ReferencesError(_)) = sk_to { - err.delay_as_bug(); + err.delay_as_bug_without_consuming(); } } err.emit(); diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 6044b1fdd40af..c3332a4930673 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -366,7 +366,7 @@ fn report_unexpected_variant_res( _ => res.descr(), }; let path_str = rustc_hir_pretty::qpath_to_string(qpath); - let mut err = tcx.dcx().struct_span_err_with_code( + let err = tcx.dcx().struct_span_err_with_code( span, format!("expected {expected}, found {res_descr} `{path_str}`"), DiagnosticId::Error(err_code.into()), @@ -374,10 +374,10 @@ fn report_unexpected_variant_res( match res { Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => { let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html"; - err.span_label(span, "`fn` calls are not allowed in patterns"); - err.help(format!("for more information, visit {patterns_url}")) + err.span_label_mv(span, "`fn` calls are not allowed in patterns") + .help_mv(format!("for more information, visit {patterns_url}")) } - _ => err.span_label(span, format!("not a {expected}")), + _ => err.span_label_mv(span, format!("not a {expected}")), } .emit() } diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 7b49a7cc009db..59cf0d8c8ed63 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -385,7 +385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let hir::ExprKind::Assign(..) = expr.kind { // We defer to the later error produced by `check_lhs_assignable`. - err.delay_as_bug(); + err.delay_as_bug_without_consuming(); } let suggest_deref_binop = diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 02a35110716b5..022213abd6703 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -117,7 +117,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { actual: Ty<'tcx>, ti: TopInfo<'tcx>, ) { - if let Some(mut err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) { + if let Some(err) = self.demand_eqtype_pat_diag(cause_span, expected, actual, ti) { err.emit(); } } @@ -441,7 +441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // then that's equivalent to there existing a LUB. let cause = self.pattern_cause(ti, span); - if let Some(mut err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) { + if let Some(err) = self.demand_suptype_with_origin(&cause, expected, pat_ty) { err.emit_unless( ti.span .filter(|&s| { @@ -1103,7 +1103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Type-check the tuple struct pattern against the expected type. let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, ti); - let had_err = if let Some(mut err) = diag { + let had_err = if let Some(err) = diag { err.emit(); true } else { @@ -1329,9 +1329,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); let element_tys = tcx.mk_type_list_from_iter(element_tys_iter); let pat_ty = Ty::new_tup(tcx, element_tys); - if let Some(mut err) = - self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) - { + if let Some(err) = self.demand_eqtype_pat_diag(span, expected, pat_ty, pat_info.top_info) { let reported = err.emit(); // Walk subpatterns with an expected type of `err` in this case to silence // further errors being emitted when using the bindings. #50333 @@ -1469,8 +1467,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } match (inexistent_fields_err, unmentioned_err) { - (Some(mut i), Some(mut u)) => { - if let Some(mut e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) { + (Some(i), Some(u)) => { + if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) { // We don't want to show the nonexistent fields error when this was // `Foo { a, b }` when it should have been `Foo(a, b)`. i.delay_as_bug(); @@ -1481,19 +1479,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { u.emit(); } } - (None, Some(mut u)) => { - if let Some(mut e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) { + (None, Some(u)) => { + if let Some(e) = self.error_tuple_variant_as_struct_pat(pat, fields, variant) { u.delay_as_bug(); e.emit(); } else { u.emit(); } } - (Some(mut err), None) => { + (Some(err), None) => { err.emit(); } (None, None) - if let Some(mut err) = + if let Some(err) = self.error_tuple_variant_index_shorthand(variant, pat, fields) => { err.emit(); @@ -1571,8 +1569,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "field `{}` bound multiple times in the pattern", ident ) - .span_label(span, format!("multiple uses of `{ident}` in pattern")) - .span_label(other_field, format!("first use of `{ident}`")) + .span_label_mv(span, format!("multiple uses of `{ident}` in pattern")) + .span_label_mv(other_field, format!("first use of `{ident}`")) .emit() } @@ -2237,7 +2235,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pluralize!(min_len), size, ) - .span_label(span, format!("expected {} element{}", size, pluralize!(size))) + .span_label_mv(span, format!("expected {} element{}", size, pluralize!(size))) .emit() } @@ -2256,7 +2254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pluralize!(min_len), size, ) - .span_label( + .span_label_mv( span, format!("pattern cannot match array of {} element{}", size, pluralize!(size),), ) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b5a6374ec4b45..f88fd617c13ee 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -361,7 +361,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( ); } ty::ReError(_) => { - err.delay_as_bug(); + err.delay_as_bug_without_consuming(); } _ => { // Ugh. This is a painful case: the hidden region is not one diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index e13d1d38a89ff..d3e28446ddef1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -60,7 +60,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { pub fn try_report(&self) -> Option { self.try_report_from_nll() - .map(|mut diag| diag.emit()) + .map(|diag| diag.emit()) .or_else(|| self.try_report_impl_not_conforming_to_trait()) .or_else(|| self.try_report_anon_anon_conflict()) .or_else(|| self.try_report_static_impl_trait()) diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index ae30cf53c71e1..e9fa39ad08a27 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -281,7 +281,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } }; if sub.is_error() || sup.is_error() { - err.delay_as_bug(); + err.delay_as_bug_without_consuming(); } err } diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 07bbe78dc2d45..9da806e0779a0 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -108,7 +108,7 @@ impl<'tcx> Queries<'tcx> { pub fn parse(&self) -> Result> { self.parse.compute(|| { - passes::parse(&self.compiler.sess).map_err(|mut parse_error| parse_error.emit()) + passes::parse(&self.compiler.sess).map_err(|parse_error| parse_error.emit()) }) } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index fc4d4c9a3d260..d9bcd8d3ae72c 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -132,7 +132,7 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { .tcx .dcx() .struct_span_err(self.span, "non-defining opaque type use in defining scope") - .span_label( + .span_label_mv( self.span, format!( "lifetime `{r}` is part of concrete type but not used in \ diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 3a6fbaec9fd46..b9c75bd205b24 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -369,7 +369,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some((old_item_id, _)) = dtor_candidate { self.dcx() .struct_span_err(self.def_span(item_id), "multiple drop impls found") - .span_note(self.def_span(old_item_id), "other impl here") + .span_note_mv(self.def_span(old_item_id), "other impl here") .delay_as_bug(); } diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index b6cccd275ee65..72f76cd89756b 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -278,7 +278,7 @@ impl<'a> TokenTreesReader<'a> { } if !diff_errs.is_empty() { errs.iter_mut().for_each(|err| { - err.delay_as_bug(); + err.delay_as_bug_without_consuming(); }); return diff_errs; } diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 579c3cffcfbf5..d7604d7cebcab 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -245,9 +245,9 @@ pub fn parse_cfg_attr( crate::validate_attr::check_cfg_attr_bad_delim(parse_sess, dspan, delim); match parse_in(parse_sess, tokens.clone(), "`cfg_attr` input", |p| p.parse_cfg_attr()) { Ok(r) => return Some(r), - Err(mut e) => { - e.help(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`")) - .note(CFG_ATTR_NOTE_REF) + Err(e) => { + e.help_mv(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`")) + .note_mv(CFG_ATTR_NOTE_REF) .emit(); } } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index aed5e11133bc4..02eab2bac58b5 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -896,7 +896,7 @@ impl<'a> Parser<'a> { let struct_expr = snapshot.parse_expr_struct(None, path, false); let block_tail = self.parse_block_tail(lo, s, AttemptLocalParseRecovery::No); return Some(match (struct_expr, block_tail) { - (Ok(expr), Err(mut err)) => { + (Ok(expr), Err(err)) => { // We have encountered the following: // fn foo() -> Foo { // field: value, @@ -1218,7 +1218,7 @@ impl<'a> Parser<'a> { "::", Applicability::MaybeIncorrect, ) - .emit(); + .emit_without_consuming(); match self.parse_expr() { Ok(_) => { *expr = self.mk_expr_err(expr.span.to(self.prev_token.span)); @@ -2045,7 +2045,7 @@ impl<'a> Parser<'a> { ) -> P { match result { Ok(x) => x, - Err(mut err) => { + Err(err) => { err.emit(); // Recover from parse error, callers expect the closing delim to be consumed. self.consume_block(delim, ConsumeClosingDelim::Yes); @@ -2470,7 +2470,7 @@ impl<'a> Parser<'a> { return Ok(true); // Continue } } - Err(mut err) => { + Err(err) => { args.push(arg); // We will emit a more generic error later. err.delay_as_bug(); @@ -2946,7 +2946,7 @@ impl<'a> Parser<'a> { } pub fn recover_diff_marker(&mut self) { - if let Err(mut err) = self.err_diff_marker() { + if let Err(err) = self.err_diff_marker() { err.emit(); FatalError.raise(); } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 880743ddd3cfb..697c44a9f3e20 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -127,7 +127,7 @@ impl<'a> Parser<'a> { fn parse_expr_catch_underscore(&mut self, restrictions: Restrictions) -> PResult<'a, P> { match self.parse_expr_res(restrictions, None) { Ok(expr) => Ok(expr), - Err(mut err) => match self.token.ident() { + Err(err) => match self.token.ident() { Some((Ident { name: kw::Underscore, .. }, false)) if self.may_recover() && self.look_ahead(1, |t| t == &token::Comma) => { @@ -1333,12 +1333,12 @@ impl<'a> Parser<'a> { .collect(), }, }); - replacement_err.emit(); + replacement_err.emit_without_consuming(); let old_err = mem::replace(err, replacement_err); old_err.cancel(); } else { - err.emit(); + err.emit_without_consuming(); } return Some(self.mk_expr_err(span)); } @@ -1756,9 +1756,8 @@ impl<'a> Parser<'a> { mk_lit_char: impl FnOnce(Symbol, Span) -> L, err: impl FnOnce(&Self) -> DiagnosticBuilder<'a>, ) -> L { - if let Some(mut diag) = self.dcx().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) - { - diag.span_suggestion_verbose( + if let Some(diag) = self.dcx().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) { + diag.span_suggestion_verbose_mv( lifetime.span.shrink_to_hi(), "add `'` to close the char literal", "'", @@ -1767,7 +1766,7 @@ impl<'a> Parser<'a> { .emit(); } else { err(self) - .span_suggestion_verbose( + .span_suggestion_verbose_mv( lifetime.span.shrink_to_hi(), "add `'` to close the char literal", "'", @@ -2903,7 +2902,7 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(Delimiter::Brace) { match self.parse_arm() { Ok(arm) => arms.push(arm), - Err(mut e) => { + Err(e) => { // Recover by skipping to the end of the block. e.emit(); self.recover_stmt(); @@ -3437,7 +3436,7 @@ impl<'a> Parser<'a> { } match self.parse_expr() { Ok(e) => base = ast::StructRest::Base(e), - Err(mut e) if recover => { + Err(e) if recover => { e.emit(); self.recover_stmt(); } diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 7e243c1c32a9f..2a8e220181a44 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -77,7 +77,7 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ); } - err.emit(); + err.emit_without_consuming(); return Err(err); } } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 2ce27ff66e1d4..45aafbd0fdf33 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -739,11 +739,14 @@ impl<'a> Parser<'a> { break; } Ok(Some(item)) => items.extend(item), - Err(mut err) => { + Err(err) => { self.consume_block(Delimiter::Brace, ConsumeClosingDelim::Yes); - err.span_label(open_brace_span, "while parsing this item list starting here") - .span_label(self.prev_token.span, "the item list ends here") - .emit(); + err.span_label_mv( + open_brace_span, + "while parsing this item list starting here", + ) + .span_label_mv(self.prev_token.span, "the item list ends here") + .emit(); break; } } @@ -762,8 +765,8 @@ impl<'a> Parser<'a> { E0584, "found a documentation comment that doesn't document anything", ) - .span_label(self.token.span, "this doc comment doesn't document anything") - .help( + .span_label_mv(self.token.span, "this doc comment doesn't document anything") + .help_mv( "doc comments must come before what they document, if a comment was \ intended use `//`", ) @@ -1106,7 +1109,7 @@ impl<'a> Parser<'a> { && self.token.is_keyword(kw::Unsafe) && self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Brace)) { - let mut err = self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err(); + let err = self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err(); err.emit(); unsafety = Unsafe::Yes(self.token.span); self.eat_keyword(kw::Unsafe); @@ -1198,7 +1201,7 @@ impl<'a> Parser<'a> { defaultness: Defaultness, ) -> PResult<'a, ItemInfo> { let impl_span = self.token.span; - let mut err = self.expected_ident_found_err(); + let err = self.expected_ident_found_err(); // Only try to recover if this is implementing a trait for a type let mut impl_info = match self.parse_item_impl(attrs, defaultness) { @@ -1216,7 +1219,7 @@ impl<'a> Parser<'a> { let before_trait = trai.path.span.shrink_to_lo(); let const_up_to_impl = const_span.with_hi(impl_span.lo()); - err.multipart_suggestion( + err.multipart_suggestion_mv( "you might have meant to write a const trait impl", vec![(const_up_to_impl, "".to_owned()), (before_trait, "const ".to_owned())], Applicability::MaybeIncorrect, @@ -1454,8 +1457,8 @@ impl<'a> Parser<'a> { let ident = this.parse_field_ident("enum", vlo)?; if this.token == token::Not { - if let Err(mut err) = this.unexpected::<()>() { - err.note(fluent::parse_macro_expands_to_enum_variant).emit(); + if let Err(err) = this.unexpected::<()>() { + err.note_mv(fluent::parse_macro_expands_to_enum_variant).emit(); } this.bump(); @@ -1811,7 +1814,7 @@ impl<'a> Parser<'a> { // `check_trailing_angle_brackets` already emitted a nicer error // NOTE(eddyb) this was `.cancel()`, but `err` // gets returned, so we can't fully defuse it. - err.delay_as_bug(); + err.delay_as_bug_without_consuming(); } } } @@ -1828,7 +1831,7 @@ impl<'a> Parser<'a> { ",", Applicability::MachineApplicable, ); - err.emit(); + err.emit_without_consuming(); recovered = true; } @@ -1846,7 +1849,7 @@ impl<'a> Parser<'a> { } fn expect_field_ty_separator(&mut self) -> PResult<'a, ()> { - if let Err(mut err) = self.expect(&token::Colon) { + if let Err(err) = self.expect(&token::Colon) { let sm = self.sess.source_map(); let eq_typo = self.token.kind == token::Eq && self.look_ahead(1, |t| t.is_path_start()); let semi_typo = self.token.kind == token::Semi @@ -1862,7 +1865,7 @@ impl<'a> Parser<'a> { if eq_typo || semi_typo { self.bump(); // Gracefully handle small typos. - err.span_suggestion_short( + err.span_suggestion_short_mv( self.prev_token.span, "field names and their types are separated with `:`", ":", @@ -2598,7 +2601,7 @@ impl<'a> Parser<'a> { let (mut params, _) = self.parse_paren_comma_seq(|p| { p.recover_diff_marker(); let snapshot = p.create_snapshot_for_diagnostic(); - let param = p.parse_param_general(req_name, first_param).or_else(|mut e| { + let param = p.parse_param_general(req_name, first_param).or_else(|e| { e.emit(); let lo = p.prev_token.span; p.restore_snapshot(snapshot); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b201d36455e64..c13adfb0532d3 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -499,7 +499,7 @@ impl<'a> Parser<'a> { let (ident, is_raw) = self.ident_or_err(recover)?; if !is_raw && ident.is_reserved() { - let mut err = self.expected_ident_found_err(); + let err = self.expected_ident_found_err(); if recover { err.emit(); } else { @@ -847,7 +847,7 @@ impl<'a> Parser<'a> { pprust::token_to_string(&self.prev_token) ); expect_err - .span_suggestion_verbose( + .span_suggestion_verbose_mv( self.prev_token.span.shrink_to_hi().until(self.token.span), msg, " @ ", @@ -863,7 +863,7 @@ impl<'a> Parser<'a> { // Parsed successfully, therefore most probably the code only // misses a separator. expect_err - .span_suggestion_short( + .span_suggestion_short_mv( sp, format!("missing `{token_str}`"), token_str, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 7d17b1d4c4d67..e9b68a129ef61 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -144,7 +144,7 @@ impl<'a> Parser<'a> { // Parse the first pattern (`p_0`). let mut first_pat = match self.parse_pat_no_top_alt(expected, syntax_loc) { Ok(pat) => pat, - Err(mut err) + Err(err) if self.token.is_reserved_ident() && !self.token.is_keyword(kw::In) && !self.token.is_keyword(kw::If) => @@ -251,7 +251,7 @@ impl<'a> Parser<'a> { } }); if trailing_vert { - err.delay_as_bug(); + err.delay_as_bug_without_consuming(); } err.emit(); } @@ -1028,7 +1028,7 @@ impl<'a> Parser<'a> { let attrs = match self.parse_outer_attributes() { Ok(attrs) => attrs, Err(err) => { - if let Some(mut delayed) = delayed_err { + if let Some(delayed) = delayed_err { delayed.emit(); } return Err(err); @@ -1040,7 +1040,7 @@ impl<'a> Parser<'a> { if !ate_comma { let mut err = self.dcx().create_err(ExpectedCommaAfterPatternField { span: self.token.span }); - if let Some(mut delayed) = delayed_err { + if let Some(delayed) = delayed_err { delayed.emit(); } self.recover_misplaced_pattern_modifiers(&fields, &mut err); @@ -1113,14 +1113,14 @@ impl<'a> Parser<'a> { // This way we avoid "pattern missing fields" errors afterwards. // We delay this error until the end in order to have a span for a // suggested fix. - if let Some(mut delayed_err) = delayed_err { + if let Some(delayed_err) = delayed_err { delayed_err.emit(); return Err(err); } else { delayed_err = Some(err); } } else { - if let Some(mut err) = delayed_err { + if let Some(err) = delayed_err { err.emit(); } return Err(err); @@ -1132,7 +1132,7 @@ impl<'a> Parser<'a> { let field = match this.parse_pat_field(lo, attrs) { Ok(field) => Ok(field), Err(err) => { - if let Some(mut delayed_err) = delayed_err.take() { + if let Some(delayed_err) = delayed_err.take() { delayed_err.emit(); } return Err(err); diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 4253c0ae421a6..5ad17a30980fb 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -128,7 +128,7 @@ impl<'a> Parser<'a> { self.prev_token.span, "found single colon before projection in qualified path", ) - .span_suggestion( + .span_suggestion_mv( self.prev_token.span, "use double colon", "::", @@ -493,7 +493,7 @@ impl<'a> Parser<'a> { self.angle_bracket_nesting -= 1; Ok(args) } - Err(mut e) if self.angle_bracket_nesting > 10 => { + Err(e) if self.angle_bracket_nesting > 10 => { self.angle_bracket_nesting -= 1; // When encountering severely malformed code where there are several levels of // nested unclosed angle args (`f:: Parser<'a> { /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. // Public for rustfmt usage. pub fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option> { - Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|mut e| { + Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|e| { e.emit(); self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); None @@ -663,7 +663,7 @@ impl<'a> Parser<'a> { match expect_result { // Recover from parser, skip type error to avoid extra errors. Ok(true) => true, - Err(mut e) => { + Err(e) => { if self.recover_colon_as_semi() { // recover_colon_as_semi has already emitted a nicer error. e.delay_as_bug(); @@ -716,7 +716,7 @@ impl<'a> Parser<'a> { _ => {} } - if let Err(mut e) = + if let Err(e) = self.check_mistyped_turbofish_with_multiple_type_params(e, expr) { if recover.no() { diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 4be2c662d0351..61d72857c36b0 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -300,7 +300,7 @@ impl<'a> Parser<'a> { let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus(); let kind = self.parse_remaining_bounds_path(lifetime_defs, path, lo, parse_plus)?; - let mut err = self.dcx().create_err(errors::TransposeDynOrImpl { + let err = self.dcx().create_err(errors::TransposeDynOrImpl { span: kw.span, kw: kw.name.as_str(), sugg: errors::TransposeDynOrImplSugg { @@ -487,7 +487,7 @@ impl<'a> Parser<'a> { fn parse_array_or_slice_ty(&mut self) -> PResult<'a, TyKind> { let elt_ty = match self.parse_ty() { Ok(ty) => ty, - Err(mut err) + Err(err) if self.look_ahead(1, |t| t.kind == token::CloseDelim(Delimiter::Bracket)) | self.look_ahead(1, |t| t.kind == token::Semi) => { @@ -1109,20 +1109,19 @@ impl<'a> Parser<'a> { lifetime_defs.append(&mut generic_params); let generic_args_span = generic_args.span(); - let mut err = self - .dcx() - .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters"); let snippet = format!( "for<{}> ", lifetimes.iter().map(|lt| lt.ident.as_str()).intersperse(", ").collect::(), ); let before_fn_path = fn_path.span.shrink_to_lo(); - err.multipart_suggestion( - "consider using a higher-ranked trait bound instead", - vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)], - Applicability::MaybeIncorrect, - ) - .emit(); + self.dcx() + .struct_span_err(generic_args_span, "`Fn` traits cannot take lifetime parameters") + .multipart_suggestion_mv( + "consider using a higher-ranked trait bound instead", + vec![(generic_args_span, "".to_owned()), (before_fn_path, snippet)], + Applicability::MaybeIncorrect, + ) + .emit(); Ok(()) } diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 4efb1be03bee0..724d574349a8e 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -29,7 +29,7 @@ pub fn check_attr(sess: &ParseSess, attr: &Attribute) { _ if let AttrArgs::Eq(..) = attr.get_normal_item().args => { // All key-value attributes are restricted to meta-item syntax. parse_meta(sess, attr) - .map_err(|mut err| { + .map_err(|err| { err.emit(); }) .ok(); @@ -139,7 +139,7 @@ pub fn check_builtin_attribute( ) { match parse_meta(sess, attr) { Ok(meta) => check_builtin_meta_item(sess, &meta, attr.style, name, template), - Err(mut err) => { + Err(err) => { err.emit(); } } @@ -208,7 +208,7 @@ fn emit_malformed_attribute( } else { sess.dcx .struct_span_err(span, error_msg) - .span_suggestions( + .span_suggestions_mv( span, if suggestions.len() == 1 { "must be of the form" diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index f4cd2fbc91fcb..42e929bde2caa 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -48,7 +48,7 @@ impl DebuggerVisualizerCollector<'_> { let file = match resolve_path(&self.sess.parse_sess, visualizer_path.as_str(), attr.span) { Ok(file) => file, - Err(mut err) => { + Err(err) => { err.emit(); return; } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 9bd9dd41cf691..44c71dfa8d027 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1040,7 +1040,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> { // This error is redundant, we will have already emitted a // suggestion to use the label when `segment` wasn't found // (hence the `Res::Err` check). - diag.delay_as_bug(); + diag.delay_as_bug_without_consuming(); } _ => { diag.span_suggestion( diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index 51842664eeb70..c5715d9385959 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -124,7 +124,7 @@ fn handle_cycle_error( query: Q, qcx: Qcx, cycle_error: &CycleError, - mut error: DiagnosticBuilder<'_>, + error: DiagnosticBuilder<'_>, ) -> Q::Value where Q: QueryConfig, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 4e1fda5479c88..e176b8b4043c6 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -818,7 +818,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r .dcx() .struct_span_err(item.span, "`extern crate self;` requires renaming") - .span_suggestion( + .span_suggestion_mv( item.span, "rename the `self` crate to be able to import it", "extern crate self as name;", @@ -999,7 +999,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let msg = format!("`{name}` is already in scope"); let note = "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)"; - self.r.dcx().struct_span_err(span, msg).note(note).emit(); + self.r.dcx().struct_span_err(span, msg).note_mv(note).emit(); } } @@ -1110,10 +1110,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let msg = "`#[macro_escape]` is a deprecated synonym for `#[macro_use]`"; let mut err = self.r.dcx().struct_span_warn(attr.span, msg); if let ast::AttrStyle::Inner = attr.style { - err.help("try an outer attribute: `#[macro_use]`").emit(); - } else { - err.emit(); + err.help("try an outer attribute: `#[macro_use]`"); } + err.emit(); } else if !attr.has_name(sym::macro_use) { continue; } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 9729766220022..c5bd7ffa038cd 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1233,7 +1233,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ); } else { if ns == TypeNS { - let mut err = if crate_private_reexport { + let err = if crate_private_reexport { self.dcx().create_err(CannotBeReexportedCratePublicNS { span: import.span, ident, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a82f7bdfbf3fd..059ccaebc8208 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2600,7 +2600,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { E0637, "`'_` cannot be used here" ) - .span_label(param.ident.span, "`'_` is a reserved lifetime name") + .span_label_mv(param.ident.span, "`'_` is a reserved lifetime name") .emit(); // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_param(param.id, LifetimeRes::Error); @@ -2615,7 +2615,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { "invalid lifetime parameter name: `{}`", param.ident, ) - .span_label(param.ident.span, "'static is a reserved lifetime name") + .span_label_mv(param.ident.span, "'static is a reserved lifetime name") .emit(); // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_param(param.id, LifetimeRes::Error); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 0f7294cdad09c..32aed6611cfc6 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -128,7 +128,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { let msg = format!("{} `{}` was already registered", "tool", ident); tcx.dcx() .struct_span_err(ident.span, msg) - .span_label(old_ident.span, "already registered here") + .span_label_mv(old_ident.span, "already registered here") .emit(); } } @@ -137,7 +137,7 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools { let span = nested_meta.span(); tcx.dcx() .struct_span_err(span, msg) - .span_label(span, "not an identifier") + .span_label_mv(span, "not an identifier") .emit(); } } @@ -955,7 +955,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { E0773, "attempted to define built-in macro more than once" ) - .span_note(span, "previously defined here") + .span_note_mv(span, "previously defined here") .emit(); } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index ce166ae352fd7..8491d9b4abcb2 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1491,7 +1491,10 @@ impl EarlyDiagCtxt { jobserver::initialize_checked(|err| { #[allow(rustc::untranslatable_diagnostic)] #[allow(rustc::diagnostic_outside_of_impl)] - self.dcx.struct_warn(err).note("the build environment is likely misconfigured").emit() + self.dcx + .struct_warn(err) + .note_mv("the build environment is likely misconfigured") + .emit() }); } } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 451e0823c2522..e119ddeb4c6e4 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -122,8 +122,8 @@ pub fn is_const_evaluatable<'tcx>( if span == rustc_span::DUMMY_SP { tcx.def_span(uv.def) } else { span }, "failed to evaluate generic const expression", ) - .note("the crate this constant originates from uses `#![feature(generic_const_exprs)]`") - .span_suggestion_verbose( + .note_mv("the crate this constant originates from uses `#![feature(generic_const_exprs)]`") + .span_suggestion_verbose_mv( rustc_span::DUMMY_SP, "consider enabling this feature", "#![feature(generic_const_exprs)]\n", diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 58700850a60f8..fb1df4e4e766b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2088,7 +2088,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let ty = self.resolve_vars_if_possible(returned_ty); if ty.references_error() { // don't print out the [type error] here - err.delay_as_bug(); + err.delay_as_bug_without_consuming(); } else { err.span_label(expr.span, format!("this returned value is of type `{ty}`")); } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 54b91ab1d4d81..c1145bc30c912 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -969,7 +969,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().def_span(impl_def_id), "multiple drop impls found", ) - .span_note(self.tcx().def_span(old_impl_def_id), "other impl here") + .span_note_mv( + self.tcx().def_span(old_impl_def_id), + "other impl here", + ) .delay_as_bug(); } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index d43ab0c8e85a7..10329c623b386 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -345,7 +345,7 @@ fn report_negative_positive_conflict<'tcx>( positive_impl_def_id: DefId, sg: &mut specialization_graph::Graph, ) { - let mut err = tcx.dcx().create_err(NegativePositiveConflict { + let err = tcx.dcx().create_err(NegativePositiveConflict { impl_span: tcx.def_span(local_impl_def_id), trait_desc: overlap.trait_ref, self_ty: overlap.self_ty, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1a25d3f799363..0e81b31dd6c41 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3001,7 +3001,7 @@ fn clean_use_statement_inner<'tcx>( E0780, "anonymous imports cannot be inlined" ) - .span_label(import.span, "anonymous import") + .span_label_mv(import.span, "anonymous import") .emit(); } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index f3d63fad71154..614a64d402011 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -577,13 +577,13 @@ impl Options { { if !theme_file.is_file() { dcx.struct_err(format!("invalid argument: \"{theme_s}\"")) - .help("arguments to --theme must be files") + .help_mv("arguments to --theme must be files") .emit(); return Err(1); } if theme_file.extension() != Some(OsStr::new("css")) { dcx.struct_err(format!("invalid argument: \"{theme_s}\"")) - .help("arguments to --theme must have a .css extension") + .help_mv("arguments to --theme must have a .css extension") .emit(); return Err(1); } @@ -595,8 +595,8 @@ impl Options { dcx.struct_warn(format!( "theme file \"{theme_s}\" is missing CSS rules from the default theme", )) - .warn("the theme may appear incorrect when loaded") - .help(format!( + .warn_mv("the theme may appear incorrect when loaded") + .help_mv(format!( "to see what rules are missing, call `rustdoc --check-theme \"{theme_s}\"`", )) .emit(); @@ -809,7 +809,7 @@ fn check_deprecated_options(matches: &getopts::Matches, dcx: &rustc_errors::Diag for &flag in deprecated_flags.iter() { if matches.opt_present(flag) { dcx.struct_warn(format!("the `{flag}` flag is deprecated")) - .note( + .note_mv( "see issue #44136 \ for more information", ) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 506eb56fdc8ff..176494a386341 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1228,7 +1228,7 @@ impl LinkCollector<'_, '_> { span, "linking to associated items of raw pointers is experimental", ) - .note("rustdoc does not allow disambiguating between `*const` and `*mut`, and pointers are unstable until it does") + .note_mv("rustdoc does not allow disambiguating between `*const` and `*mut`, and pointers are unstable until it does") .emit(); } diff --git a/src/tools/clippy/clippy_config/src/msrvs.rs b/src/tools/clippy/clippy_config/src/msrvs.rs index 471ad73e2074d..76f3663f04f27 100644 --- a/src/tools/clippy/clippy_config/src/msrvs.rs +++ b/src/tools/clippy/clippy_config/src/msrvs.rs @@ -109,7 +109,7 @@ impl Msrv { if let Some(duplicate) = msrv_attrs.last() { sess.dcx() .struct_span_err(duplicate.span, "`clippy::msrv` is defined multiple times") - .span_note(msrv_attr.span, "first definition found here") + .span_note_mv(msrv_attr.span, "first definition found here") .emit(); } diff --git a/src/tools/clippy/clippy_utils/src/attrs.rs b/src/tools/clippy/clippy_utils/src/attrs.rs index db80e07ca1c4d..19d38903ade28 100644 --- a/src/tools/clippy/clippy_utils/src/attrs.rs +++ b/src/tools/clippy/clippy_utils/src/attrs.rs @@ -136,7 +136,7 @@ pub fn get_unique_attr<'a>( if let Some(duplicate) = unique_attr { sess.dcx() .struct_span_err(attr.span, format!("`{name}` is defined multiple times")) - .span_note(duplicate.span, "first definition found here") + .span_note_mv(duplicate.span, "first definition found here") .emit(); } else { unique_attr = Some(attr); diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs index 6bc53159b38ba..7045a7dd9ce35 100644 --- a/src/tools/rustfmt/src/parse/parser.rs +++ b/src/tools/rustfmt/src/parse/parser.rs @@ -114,7 +114,7 @@ impl<'a> Parser<'a> { let mut parser = new_parser_from_file(sess.inner(), path, Some(span)); match parser.parse_mod(&TokenKind::Eof) { Ok((a, i, spans)) => Some((a, i, spans.inner_span)), - Err(mut e) => { + Err(e) => { e.emit(); if sess.can_reset_errors() { sess.reset_errors(); @@ -165,7 +165,7 @@ impl<'a> Parser<'a> { match catch_unwind(move || parser.parse_crate_mod()) { Ok(Ok(k)) => Ok(k), - Ok(Err(mut db)) => { + Ok(Err(db)) => { db.emit(); Err(ParserError::ParseError) } From 589591efde6c54baa8b7932ec3be6f45dc9d781f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 16:00:29 +1100 Subject: [PATCH 03/14] Use chaining in `DiagnosticBuilder` construction. To avoid the use of a mutable local variable, and because it reads more nicely. --- .../rustc_attr/src/session_diagnostics.rs | 13 +- .../rustc_borrowck/src/borrowck_errors.rs | 70 +++---- .../src/diagnostics/conflict_errors.rs | 15 +- .../src/diagnostics/move_errors.rs | 31 ++- compiler/rustc_builtin_macros/src/errors.rs | 17 +- compiler/rustc_codegen_llvm/src/errors.rs | 14 +- compiler/rustc_codegen_ssa/src/errors.rs | 180 ++++++------------ .../rustc_errors/src/diagnostic_builder.rs | 4 +- compiler/rustc_errors/src/diagnostic_impls.rs | 63 +++--- compiler/rustc_errors/src/lib.rs | 40 +--- .../rustc_hir_analysis/src/check/wfcheck.rs | 6 +- compiler/rustc_hir_typeck/src/expr.rs | 8 +- .../src/infer/error_reporting/note.rs | 5 +- compiler/rustc_parse/src/lexer/mod.rs | 6 +- compiler/rustc_parse/src/parser/attr.rs | 27 ++- compiler/rustc_parse/src/parser/item.rs | 22 +-- compiler/rustc_parse/src/parser/pat.rs | 7 +- compiler/rustc_resolve/src/diagnostics.rs | 9 +- .../rustc_resolve/src/late/diagnostics.rs | 16 +- compiler/rustc_session/src/errors.rs | 7 +- compiler/rustc_symbol_mangling/src/errors.rs | 4 +- .../error_reporting/type_err_ctxt_ext.rs | 28 ++- 22 files changed, 223 insertions(+), 369 deletions(-) diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index fdb5d66bf62b5..5f61a56c189ac 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -54,13 +54,12 @@ pub(crate) struct UnknownMetaItem<'a> { impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> { fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::>(); - let mut diag = DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item); - diag.span(self.span); - diag.code(error_code!(E0541)); - diag.arg("item", self.item); - diag.arg("expected", expected.join(", ")); - diag.span_label(self.span, fluent::attr_label); - diag + DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item) + .span_mv(self.span) + .code_mv(error_code!(E0541)) + .arg_mv("item", self.item) + .arg_mv("expected", expected.join(", ")) + .span_label_mv(self.span, fluent::attr_label) } } diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 900b789101961..a9fc0a6f415da 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -31,17 +31,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { borrow_span: Span, borrow_desc: &str, ) -> DiagnosticBuilder<'tcx> { - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), span, E0503, "cannot use {} because it was mutably borrowed", desc, - ); - - err.span_label(borrow_span, format!("{borrow_desc} is borrowed here")); - err.span_label(span, format!("use of borrowed {borrow_desc}")); - err + ) + .span_label_mv(borrow_span, format!("{borrow_desc} is borrowed here")) + .span_label_mv(span, format!("use of borrowed {borrow_desc}")) } pub(crate) fn cannot_mutably_borrow_multiply( @@ -238,17 +236,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { borrow_span: Span, desc: &str, ) -> DiagnosticBuilder<'cx> { - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), span, E0506, "cannot assign to {} because it is borrowed", desc, - ); - - err.span_label(borrow_span, format!("{desc} is borrowed here")); - err.span_label(span, format!("{desc} is assigned to here but it was already borrowed")); - err + ) + .span_label_mv(borrow_span, format!("{desc} is borrowed here")) + .span_label_mv(span, format!("{desc} is assigned to here but it was already borrowed")) } pub(crate) fn cannot_reassign_immutable( @@ -287,16 +283,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { (&ty::Slice(_), _) => "slice", _ => span_bug!(move_from_span, "this path should not cause illegal move"), }; - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), move_from_span, E0508, "cannot move out of type `{}`, a non-copy {}", ty, type_name, - ); - err.span_label(move_from_span, "cannot move out of here"); - err + ) + .span_label_mv(move_from_span, "cannot move out of here") } pub(crate) fn cannot_move_out_of_interior_of_drop( @@ -304,15 +299,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { move_from_span: Span, container_ty: Ty<'_>, ) -> DiagnosticBuilder<'cx> { - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), move_from_span, E0509, "cannot move out of type `{}`, which implements the `Drop` trait", container_ty, - ); - err.span_label(move_from_span, "cannot move out of here"); - err + ) + .span_label_mv(move_from_span, "cannot move out of here") } pub(crate) fn cannot_act_on_moved_value( @@ -352,7 +346,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { immutable_section: &str, action: &str, ) -> DiagnosticBuilder<'tcx> { - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), mutate_span, E0510, @@ -360,10 +354,9 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { action, immutable_place, immutable_section, - ); - err.span_label(mutate_span, format!("cannot {action}")); - err.span_label(immutable_span, format!("value is immutable in {immutable_section}")); - err + ) + .span_label_mv(mutate_span, format!("cannot {action}")) + .span_label_mv(immutable_span, format!("value is immutable in {immutable_section}")) } pub(crate) fn cannot_borrow_across_coroutine_yield( @@ -372,14 +365,13 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { yield_span: Span, ) -> DiagnosticBuilder<'tcx> { let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind; - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), span, E0626, "borrow may still be in use when {coroutine_kind:#} yields", - ); - err.span_label(yield_span, "possible yield occurs here"); - err + ) + .span_label_mv(yield_span, "possible yield occurs here") } pub(crate) fn cannot_borrow_across_destructor( @@ -409,7 +401,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { reference_desc: &str, path_desc: &str, ) -> DiagnosticBuilder<'tcx> { - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), span, E0515, @@ -417,14 +409,11 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { RETURN = return_kind, REFERENCE = reference_desc, LOCAL = path_desc, - ); - - err.span_label( + ) + .span_label_mv( span, format!("{return_kind}s a {reference_desc} data owned by the current function"), - ); - - err + ) } pub(crate) fn cannot_capture_in_long_lived_closure( @@ -435,16 +424,15 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { capture_span: Span, scope: &str, ) -> DiagnosticBuilder<'tcx> { - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), closure_span, E0373, "{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \ which is owned by the current {scope}", - ); - err.span_label(capture_span, format!("{borrowed_path} is borrowed here")) - .span_label(closure_span, format!("may outlive borrowed value {borrowed_path}")); - err + ) + .span_label_mv(capture_span, format!("{borrowed_path} is borrowed here")) + .span_label_mv(closure_span, format!("may outlive borrowed value {borrowed_path}")) } pub(crate) fn thread_local_value_does_not_live_long_enough( diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 9ce753134fbcd..5baa108ed3cce 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2218,15 +2218,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { drop_span, borrow_span ); - let mut err = self.thread_local_value_does_not_live_long_enough(borrow_span); - - err.span_label( - borrow_span, - "thread-local variables cannot be borrowed beyond the end of the function", - ); - err.span_label(drop_span, "end of enclosing function is here"); - - err + self.thread_local_value_does_not_live_long_enough(borrow_span) + .span_label_mv( + borrow_span, + "thread-local variables cannot be borrowed beyond the end of the function", + ) + .span_label_mv(drop_span, "end of enclosing function is here") } #[instrument(level = "debug", skip(self))] diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index f3b21d22c1a55..50dde5ce636e7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -329,15 +329,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let PlaceRef { local, projection: [] } = deref_base { let decl = &self.body.local_decls[local]; if decl.is_ref_for_guard() { - let mut err = self.cannot_move_out_of( - span, - &format!("`{}` in pattern guard", self.local_names[local].unwrap()), - ); - err.note( - "variables bound in patterns cannot be moved from \ + return self + .cannot_move_out_of( + span, + &format!("`{}` in pattern guard", self.local_names[local].unwrap()), + ) + .note_mv( + "variables bound in patterns cannot be moved from \ until after the end of the pattern guard", - ); - return err; + ); } else if decl.is_ref_to_static() { return self.report_cannot_move_from_static(move_place, span); } @@ -381,15 +381,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { closure_kind_ty, closure_kind, place_description, ); - let mut diag = self.cannot_move_out_of(span, &place_description); - - diag.span_label(upvar_span, "captured outer variable"); - diag.span_label( - self.infcx.tcx.def_span(def_id), - format!("captured by this `{closure_kind}` closure"), - ); - - diag + self.cannot_move_out_of(span, &place_description) + .span_label_mv(upvar_span, "captured outer variable") + .span_label_mv( + self.infcx.tcx.def_span(def_id), + format!("captured by this `{closure_kind}` closure"), + ) } _ => { let source = self.borrowed_content_source(deref_base); diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index f9ddffcc155d5..13e5a40ca9ee5 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -803,24 +803,23 @@ pub(crate) struct AsmClobberNoReg { impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg { fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { - let mut diag = DiagnosticBuilder::new( - dcx, - level, - crate::fluent_generated::builtin_macros_asm_clobber_no_reg, - ); - diag.span(self.spans.clone()); // eager translation as `span_labels` takes `AsRef` let lbl1 = dcx.eagerly_translate_to_string( crate::fluent_generated::builtin_macros_asm_clobber_abi, [].into_iter(), ); - diag.span_labels(self.clobbers, &lbl1); let lbl2 = dcx.eagerly_translate_to_string( crate::fluent_generated::builtin_macros_asm_clobber_outputs, [].into_iter(), ); - diag.span_labels(self.spans, &lbl2); - diag + DiagnosticBuilder::new( + dcx, + level, + crate::fluent_generated::builtin_macros_asm_clobber_no_reg, + ) + .span_mv(self.spans.clone()) + .span_labels_mv(self.clobbers, &lbl1) + .span_labels_mv(self.spans, &lbl2) } } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 422e8edff5f64..6e2c0dc21ad8a 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -105,10 +105,8 @@ impl IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_ let (message, _) = diag.messages().first().expect("`LlvmError` with no message"); let message = dcx.eagerly_translate_to_string(message.clone(), diag.args()); - let mut diag = - DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config); - diag.arg("error", message); - diag + DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config) + .arg_mv("error", message) } } @@ -204,10 +202,10 @@ impl IntoDiagnostic<'_, G> for WithLlvmError<'_> { PrepareThinLtoModule => fluent::codegen_llvm_prepare_thin_lto_module_with_llvm_err, ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err, }; - let mut diag = self.0.into_diagnostic(dcx, level); - diag.primary_message(msg_with_llvm_err); - diag.arg("llvm_err", self.1); - diag + self.0 + .into_diagnostic(dcx, level) + .primary_message_mv(msg_with_llvm_err) + .arg_mv("llvm_err", self.1) } } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index c1086bebb8d48..7e3b69fa52f49 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -212,192 +212,124 @@ pub struct ThorinErrorWrapper(pub thorin::Error); impl IntoDiagnostic<'_, G> for ThorinErrorWrapper { fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let build = |msg| DiagnosticBuilder::new(dcx, level, msg); - let mut diag; match self.0 { - thorin::Error::ReadInput(_) => { - diag = build(fluent::codegen_ssa_thorin_read_input_failure); - diag - } + thorin::Error::ReadInput(_) => build(fluent::codegen_ssa_thorin_read_input_failure), thorin::Error::ParseFileKind(_) => { - diag = build(fluent::codegen_ssa_thorin_parse_input_file_kind); - diag + build(fluent::codegen_ssa_thorin_parse_input_file_kind) } thorin::Error::ParseObjectFile(_) => { - diag = build(fluent::codegen_ssa_thorin_parse_input_object_file); - diag + build(fluent::codegen_ssa_thorin_parse_input_object_file) } thorin::Error::ParseArchiveFile(_) => { - diag = build(fluent::codegen_ssa_thorin_parse_input_archive_file); - diag + build(fluent::codegen_ssa_thorin_parse_input_archive_file) } thorin::Error::ParseArchiveMember(_) => { - diag = build(fluent::codegen_ssa_thorin_parse_archive_member); - diag - } - thorin::Error::InvalidInputKind => { - diag = build(fluent::codegen_ssa_thorin_invalid_input_kind); - diag - } - thorin::Error::DecompressData(_) => { - diag = build(fluent::codegen_ssa_thorin_decompress_data); - diag + build(fluent::codegen_ssa_thorin_parse_archive_member) } + thorin::Error::InvalidInputKind => build(fluent::codegen_ssa_thorin_invalid_input_kind), + thorin::Error::DecompressData(_) => build(fluent::codegen_ssa_thorin_decompress_data), thorin::Error::NamelessSection(_, offset) => { - diag = build(fluent::codegen_ssa_thorin_section_without_name); - diag.arg("offset", format!("0x{offset:08x}")); - diag + build(fluent::codegen_ssa_thorin_section_without_name) + .arg_mv("offset", format!("0x{offset:08x}")) } thorin::Error::RelocationWithInvalidSymbol(section, offset) => { - diag = build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); - diag.arg("section", section); - diag.arg("offset", format!("0x{offset:08x}")); - diag + build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol) + .arg_mv("section", section) + .arg_mv("offset", format!("0x{offset:08x}")) } thorin::Error::MultipleRelocations(section, offset) => { - diag = build(fluent::codegen_ssa_thorin_multiple_relocations); - diag.arg("section", section); - diag.arg("offset", format!("0x{offset:08x}")); - diag + build(fluent::codegen_ssa_thorin_multiple_relocations) + .arg_mv("section", section) + .arg_mv("offset", format!("0x{offset:08x}")) } thorin::Error::UnsupportedRelocation(section, offset) => { - diag = build(fluent::codegen_ssa_thorin_unsupported_relocation); - diag.arg("section", section); - diag.arg("offset", format!("0x{offset:08x}")); - diag - } - thorin::Error::MissingDwoName(id) => { - diag = build(fluent::codegen_ssa_thorin_missing_dwo_name); - diag.arg("id", format!("0x{id:08x}")); - diag + build(fluent::codegen_ssa_thorin_unsupported_relocation) + .arg_mv("section", section) + .arg_mv("offset", format!("0x{offset:08x}")) } + thorin::Error::MissingDwoName(id) => build(fluent::codegen_ssa_thorin_missing_dwo_name) + .arg_mv("id", format!("0x{id:08x}")), thorin::Error::NoCompilationUnits => { - diag = build(fluent::codegen_ssa_thorin_no_compilation_units); - diag - } - thorin::Error::NoDie => { - diag = build(fluent::codegen_ssa_thorin_no_die); - diag + build(fluent::codegen_ssa_thorin_no_compilation_units) } + thorin::Error::NoDie => build(fluent::codegen_ssa_thorin_no_die), thorin::Error::TopLevelDieNotUnit => { - diag = build(fluent::codegen_ssa_thorin_top_level_die_not_unit); - diag + build(fluent::codegen_ssa_thorin_top_level_die_not_unit) } thorin::Error::MissingRequiredSection(section) => { - diag = build(fluent::codegen_ssa_thorin_missing_required_section); - diag.arg("section", section); - diag + build(fluent::codegen_ssa_thorin_missing_required_section) + .arg_mv("section", section) } thorin::Error::ParseUnitAbbreviations(_) => { - diag = build(fluent::codegen_ssa_thorin_parse_unit_abbreviations); - diag + build(fluent::codegen_ssa_thorin_parse_unit_abbreviations) } thorin::Error::ParseUnitAttribute(_) => { - diag = build(fluent::codegen_ssa_thorin_parse_unit_attribute); - diag + build(fluent::codegen_ssa_thorin_parse_unit_attribute) } thorin::Error::ParseUnitHeader(_) => { - diag = build(fluent::codegen_ssa_thorin_parse_unit_header); - diag - } - thorin::Error::ParseUnit(_) => { - diag = build(fluent::codegen_ssa_thorin_parse_unit); - diag + build(fluent::codegen_ssa_thorin_parse_unit_header) } + thorin::Error::ParseUnit(_) => build(fluent::codegen_ssa_thorin_parse_unit), thorin::Error::IncompatibleIndexVersion(section, format, actual) => { - diag = build(fluent::codegen_ssa_thorin_incompatible_index_version); - diag.arg("section", section); - diag.arg("actual", actual); - diag.arg("format", format); - diag + build(fluent::codegen_ssa_thorin_incompatible_index_version) + .arg_mv("section", section) + .arg_mv("actual", actual) + .arg_mv("format", format) } thorin::Error::OffsetAtIndex(_, index) => { - diag = build(fluent::codegen_ssa_thorin_offset_at_index); - diag.arg("index", index); - diag + build(fluent::codegen_ssa_thorin_offset_at_index).arg_mv("index", index) } thorin::Error::StrAtOffset(_, offset) => { - diag = build(fluent::codegen_ssa_thorin_str_at_offset); - diag.arg("offset", format!("0x{offset:08x}")); - diag + build(fluent::codegen_ssa_thorin_str_at_offset) + .arg_mv("offset", format!("0x{offset:08x}")) } thorin::Error::ParseIndex(_, section) => { - diag = build(fluent::codegen_ssa_thorin_parse_index); - diag.arg("section", section); - diag + build(fluent::codegen_ssa_thorin_parse_index).arg_mv("section", section) } thorin::Error::UnitNotInIndex(unit) => { - diag = build(fluent::codegen_ssa_thorin_unit_not_in_index); - diag.arg("unit", format!("0x{unit:08x}")); - diag + build(fluent::codegen_ssa_thorin_unit_not_in_index) + .arg_mv("unit", format!("0x{unit:08x}")) } thorin::Error::RowNotInIndex(_, row) => { - diag = build(fluent::codegen_ssa_thorin_row_not_in_index); - diag.arg("row", row); - diag - } - thorin::Error::SectionNotInRow => { - diag = build(fluent::codegen_ssa_thorin_section_not_in_row); - diag + build(fluent::codegen_ssa_thorin_row_not_in_index).arg_mv("row", row) } + thorin::Error::SectionNotInRow => build(fluent::codegen_ssa_thorin_section_not_in_row), thorin::Error::EmptyUnit(unit) => { - diag = build(fluent::codegen_ssa_thorin_empty_unit); - diag.arg("unit", format!("0x{unit:08x}")); - diag + build(fluent::codegen_ssa_thorin_empty_unit).arg_mv("unit", format!("0x{unit:08x}")) } thorin::Error::MultipleDebugInfoSection => { - diag = build(fluent::codegen_ssa_thorin_multiple_debug_info_section); - diag + build(fluent::codegen_ssa_thorin_multiple_debug_info_section) } thorin::Error::MultipleDebugTypesSection => { - diag = build(fluent::codegen_ssa_thorin_multiple_debug_types_section); - diag - } - thorin::Error::NotSplitUnit => { - diag = build(fluent::codegen_ssa_thorin_not_split_unit); - diag - } - thorin::Error::DuplicateUnit(unit) => { - diag = build(fluent::codegen_ssa_thorin_duplicate_unit); - diag.arg("unit", format!("0x{unit:08x}")); - diag + build(fluent::codegen_ssa_thorin_multiple_debug_types_section) } + thorin::Error::NotSplitUnit => build(fluent::codegen_ssa_thorin_not_split_unit), + thorin::Error::DuplicateUnit(unit) => build(fluent::codegen_ssa_thorin_duplicate_unit) + .arg_mv("unit", format!("0x{unit:08x}")), thorin::Error::MissingReferencedUnit(unit) => { - diag = build(fluent::codegen_ssa_thorin_missing_referenced_unit); - diag.arg("unit", format!("0x{unit:08x}")); - diag + build(fluent::codegen_ssa_thorin_missing_referenced_unit) + .arg_mv("unit", format!("0x{unit:08x}")) } thorin::Error::NoOutputObjectCreated => { - diag = build(fluent::codegen_ssa_thorin_not_output_object_created); - diag + build(fluent::codegen_ssa_thorin_not_output_object_created) } thorin::Error::MixedInputEncodings => { - diag = build(fluent::codegen_ssa_thorin_mixed_input_encodings); - diag + build(fluent::codegen_ssa_thorin_mixed_input_encodings) } thorin::Error::Io(e) => { - diag = build(fluent::codegen_ssa_thorin_io); - diag.arg("error", format!("{e}")); - diag + build(fluent::codegen_ssa_thorin_io).arg_mv("error", format!("{e}")) } thorin::Error::ObjectRead(e) => { - diag = build(fluent::codegen_ssa_thorin_object_read); - diag.arg("error", format!("{e}")); - diag + build(fluent::codegen_ssa_thorin_object_read).arg_mv("error", format!("{e}")) } thorin::Error::ObjectWrite(e) => { - diag = build(fluent::codegen_ssa_thorin_object_write); - diag.arg("error", format!("{e}")); - diag + build(fluent::codegen_ssa_thorin_object_write).arg_mv("error", format!("{e}")) } thorin::Error::GimliRead(e) => { - diag = build(fluent::codegen_ssa_thorin_gimli_read); - diag.arg("error", format!("{e}")); - diag + build(fluent::codegen_ssa_thorin_gimli_read).arg_mv("error", format!("{e}")) } thorin::Error::GimliWrite(e) => { - diag = build(fluent::codegen_ssa_thorin_gimli_write); - diag.arg("error", format!("{e}")); - diag + build(fluent::codegen_ssa_thorin_gimli_write).arg_mv("error", format!("{e}")) } _ => unimplemented!("Untranslated thorin error"), } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index e41acd6447bff..b3f8a6c244076 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -30,9 +30,7 @@ where G: EmissionGuarantee, { fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { - let mut diag = self.node.into_diagnostic(dcx, level); - diag.span(self.span); - diag + self.node.into_diagnostic(dcx, level).span_mv(self.span) } } diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index de27c6e910b2b..58d4d2caf2ee1 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -249,60 +249,43 @@ impl IntoDiagnosticArg for hir::def::Res { impl IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> { fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { - let mut diag; match self { TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => { - diag = - DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space); - diag.arg("addr_space", addr_space); - diag.arg("cause", cause); - diag.arg("err", err); - diag + DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space) + .arg_mv("addr_space", addr_space) + .arg_mv("cause", cause) + .arg_mv("err", err) } TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { - diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits); - diag.arg("kind", kind); - diag.arg("bit", bit); - diag.arg("cause", cause); - diag.arg("err", err); - diag + DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits) + .arg_mv("kind", kind) + .arg_mv("bit", bit) + .arg_mv("cause", cause) + .arg_mv("err", err) } TargetDataLayoutErrors::MissingAlignment { cause } => { - diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment); - diag.arg("cause", cause); - diag + DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment) + .arg_mv("cause", cause) } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { - diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment); - diag.arg("cause", cause); - diag.arg("err_kind", err.diag_ident()); - diag.arg("align", err.align()); - diag + DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment) + .arg_mv("cause", cause) + .arg_mv("err_kind", err.diag_ident()) + .arg_mv("align", err.align()) } TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { - diag = DiagnosticBuilder::new( - dcx, - level, - fluent::errors_target_inconsistent_architecture, - ); - diag.arg("dl", dl); - diag.arg("target", target); - diag + DiagnosticBuilder::new(dcx, level, fluent::errors_target_inconsistent_architecture) + .arg_mv("dl", dl) + .arg_mv("target", target) } TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { - diag = DiagnosticBuilder::new( - dcx, - level, - fluent::errors_target_inconsistent_pointer_width, - ); - diag.arg("pointer_size", pointer_size); - diag.arg("target", target); - diag + DiagnosticBuilder::new(dcx, level, fluent::errors_target_inconsistent_pointer_width) + .arg_mv("pointer_size", pointer_size) + .arg_mv("target", target) } TargetDataLayoutErrors::InvalidBitsSize { err } => { - diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size); - diag.arg("err", err); - diag + DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size) + .arg_mv("err", err) } } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index e07a9509383b2..a63c32566ca7c 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -729,9 +729,7 @@ impl DiagCtxt { span: impl Into, msg: impl Into, ) -> DiagnosticBuilder<'_, ()> { - let mut result = self.struct_warn(msg); - result.span(span); - result + self.struct_warn(msg).span_mv(span) } /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. @@ -744,9 +742,7 @@ impl DiagCtxt { msg: impl Into, code: DiagnosticId, ) -> DiagnosticBuilder<'_, ()> { - let mut result = self.struct_span_warn(span, msg); - result.code(code); - result + self.struct_span_warn(span, msg).code_mv(code) } /// Construct a builder at the `Warning` level with the `msg`. @@ -786,9 +782,7 @@ impl DiagCtxt { span: impl Into, msg: impl Into, ) -> DiagnosticBuilder<'_> { - let mut result = self.struct_err(msg); - result.span(span); - result + self.struct_err(msg).span_mv(span) } /// Construct a builder at the `Error` level at the given `span`, with the `msg`, and `code`. @@ -800,9 +794,7 @@ impl DiagCtxt { msg: impl Into, code: DiagnosticId, ) -> DiagnosticBuilder<'_> { - let mut result = self.struct_span_err(span, msg); - result.code(code); - result + self.struct_span_err(span, msg).code_mv(code) } /// Construct a builder at the `Error` level with the `msg`. @@ -821,9 +813,7 @@ impl DiagCtxt { msg: impl Into, code: DiagnosticId, ) -> DiagnosticBuilder<'_> { - let mut result = self.struct_err(msg); - result.code(code); - result + self.struct_err(msg).code_mv(code) } /// Construct a builder at the `Warn` level with the `msg` and the `code`. @@ -834,9 +824,7 @@ impl DiagCtxt { msg: impl Into, code: DiagnosticId, ) -> DiagnosticBuilder<'_, ()> { - let mut result = self.struct_warn(msg); - result.code(code); - result + self.struct_warn(msg).code_mv(code) } /// Construct a builder at the `Fatal` level at the given `span` and with the `msg`. @@ -847,9 +835,7 @@ impl DiagCtxt { span: impl Into, msg: impl Into, ) -> DiagnosticBuilder<'_, FatalAbort> { - let mut result = self.struct_fatal(msg); - result.span(span); - result + self.struct_fatal(msg).span_mv(span) } /// Construct a builder at the `Fatal` level at the given `span`, with the `msg`, and `code`. @@ -861,9 +847,7 @@ impl DiagCtxt { msg: impl Into, code: DiagnosticId, ) -> DiagnosticBuilder<'_, FatalAbort> { - let mut result = self.struct_span_fatal(span, msg); - result.code(code); - result + self.struct_span_fatal(span, msg).code_mv(code) } /// Construct a builder at the `Fatal` level with the `msg`. @@ -904,9 +888,7 @@ impl DiagCtxt { span: impl Into, msg: impl Into, ) -> DiagnosticBuilder<'_, BugAbort> { - let mut result = self.struct_bug(msg); - result.span(span); - result + self.struct_bug(msg).span_mv(span) } #[rustc_lint_diagnostics] @@ -1021,9 +1003,7 @@ impl DiagCtxt { span: impl Into, msg: impl Into, ) -> DiagnosticBuilder<'_, ()> { - let mut db = DiagnosticBuilder::new(self, Note, msg); - db.span(span); - db + DiagnosticBuilder::new(self, Note, msg).span_mv(span) } #[rustc_lint_diagnostics] diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index c53ff56555005..4bac124b58bbe 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1921,10 +1921,8 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error } fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> { - let mut err = - struct_span_err!(tcx.dcx(), span, E0392, "parameter `{param_name}` is never used"); - err.span_label(span, "unused parameter"); - err + struct_span_err!(tcx.dcx(), span, E0392, "parameter `{param_name}` is never used") + .span_label_mv(span, "unused parameter") } pub fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 69a65e8b750b1..da9d41a7d72d9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2836,15 +2836,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn private_field_err(&self, field: Ident, base_did: DefId) -> DiagnosticBuilder<'_> { let struct_path = self.tcx().def_path_str(base_did); let kind_name = self.tcx().def_descr(base_did); - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), field.span, E0616, "field `{field}` of {kind_name} `{struct_path}` is private", - ); - err.span_label(field.span, "private field"); - - err + ) + .span_label_mv(field.span, "private field") } pub(crate) fn get_field_candidates_considering_privacy( diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index e9fa39ad08a27..c09646b491c00 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -367,9 +367,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &trace.cause.code().peel_derives() { let span = *span; - let mut err = self.report_concrete_failure(placeholder_origin, sub, sup); - err.span_note(span, "the lifetime requirement is introduced here"); - err + self.report_concrete_failure(placeholder_origin, sub, sup) + .span_note_mv(span, "the lifetime requirement is introduced here") } else { unreachable!( "control flow ensures we have a `BindingObligation` or `ExprBindingObligation` here..." diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 4819ed6021d0d..bc42b1b3ef849 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -249,9 +249,9 @@ impl<'a> StringReader<'a> { let lifetime_name = self.str_from(start); if starts_with_number { let span = self.mk_sp(start, self.pos); - let mut diag = self.dcx().struct_err("lifetimes cannot start with a number"); - diag.span(span); - diag.stash(span, StashKey::LifetimeIsChar); + self.dcx().struct_err("lifetimes cannot start with a number") + .span_mv(span) + .stash(span, StashKey::LifetimeIsChar); } let ident = Symbol::intern(lifetime_name); token::Lifetime(ident) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index c8629069968aa..1f8c368b2a999 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -200,23 +200,22 @@ impl<'a> Parser<'a> { if let InnerAttrPolicy::Forbidden(reason) = policy { let mut diag = match reason.as_ref().copied() { Some(InnerAttrForbiddenReason::AfterOuterDocComment { prev_doc_comment_span }) => { - let mut diag = self.dcx().struct_span_err( - attr_sp, - fluent::parse_inner_attr_not_permitted_after_outer_doc_comment, - ); - diag.span_label(attr_sp, fluent::parse_label_attr) - .span_label(prev_doc_comment_span, fluent::parse_label_prev_doc_comment); - diag + self.dcx() + .struct_span_err( + attr_sp, + fluent::parse_inner_attr_not_permitted_after_outer_doc_comment, + ) + .span_label_mv(attr_sp, fluent::parse_label_attr) + .span_label_mv(prev_doc_comment_span, fluent::parse_label_prev_doc_comment) } - Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => { - let mut diag = self.dcx().struct_span_err( + Some(InnerAttrForbiddenReason::AfterOuterAttribute { prev_outer_attr_sp }) => self + .dcx() + .struct_span_err( attr_sp, fluent::parse_inner_attr_not_permitted_after_outer_attr, - ); - diag.span_label(attr_sp, fluent::parse_label_attr) - .span_label(prev_outer_attr_sp, fluent::parse_label_prev_attr); - diag - } + ) + .span_label_mv(attr_sp, fluent::parse_label_attr) + .span_label_mv(prev_outer_attr_sp, fluent::parse_label_prev_attr), Some(InnerAttrForbiddenReason::InCodeBlock) | None => { self.dcx().struct_span_err(attr_sp, fluent::parse_inner_attr_not_permitted) } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 45aafbd0fdf33..2694dd3c9c612 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1941,15 +1941,14 @@ impl<'a> Parser<'a> { Case::Insensitive, ) { Ok(_) => { - let mut err = self.dcx().struct_span_err( + self.dcx().struct_span_err( lo.to(self.prev_token.span), format!("functions are not allowed in {adt_ty} definitions"), - ); - err.help( + ) + .help_mv( "unlike in C++, Java, and C#, functions are declared in `impl` blocks", - ); - err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information"); - err + ) + .help_mv("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information") } Err(err) => { err.cancel(); @@ -1959,14 +1958,13 @@ impl<'a> Parser<'a> { } } else if self.eat_keyword(kw::Struct) { match self.parse_item_struct() { - Ok((ident, _)) => { - let mut err = self.dcx().struct_span_err( + Ok((ident, _)) => self + .dcx() + .struct_span_err( lo.with_hi(ident.span.hi()), format!("structs are not allowed in {adt_ty} definitions"), - ); - err.help("consider creating a new `struct` definition instead of nesting"); - err - } + ) + .help_mv("consider creating a new `struct` definition instead of nesting"), Err(err) => { err.cancel(); self.restore_snapshot(snapshot); diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index e9b68a129ef61..a6804b992043a 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -460,9 +460,10 @@ impl<'a> Parser<'a> { super::token_descr(&self_.token) ); - let mut err = self_.dcx().struct_span_err(self_.token.span, msg); - err.span_label(self_.token.span, format!("expected {expected}")); - err + self_ + .dcx() + .struct_span_err(self_.token.span, msg) + .span_label_mv(self_.token.span, format!("expected {expected}")) }); PatKind::Lit(self.mk_expr(lo, ExprKind::Lit(lit))) } else { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index c1cb20f6bb091..977a7e796e789 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -944,16 +944,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { trait_item_span, trait_path, } => { - let mut err = self.dcx().struct_span_err_with_code( + self.dcx().struct_span_err_with_code( span, format!( "item `{name}` is an associated {kind}, which doesn't match its trait `{trait_path}`", ), code, - ); - err.span_label(span, "does not match trait"); - err.span_label(trait_item_span, "item in trait"); - err + ) + .span_label_mv(span, "does not match trait") + .span_label_mv(trait_item_span, "item in trait") } ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self .dcx() diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 821aafe2feda5..43608da8ab2a0 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2603,25 +2603,23 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { ) { debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime); let mut err = if let Some(outer) = outer_lifetime_ref { - let mut err = struct_span_err!( + struct_span_err!( self.r.dcx(), lifetime_ref.ident.span, E0401, "can't use generic parameters from outer item", - ); - err.span_label(lifetime_ref.ident.span, "use of generic parameter from outer item"); - err.span_label(outer.span, "lifetime parameter from outer item"); - err + ) + .span_label_mv(lifetime_ref.ident.span, "use of generic parameter from outer item") + .span_label_mv(outer.span, "lifetime parameter from outer item") } else { - let mut err = struct_span_err!( + struct_span_err!( self.r.dcx(), lifetime_ref.ident.span, E0261, "use of undeclared lifetime name `{}`", lifetime_ref.ident - ); - err.span_label(lifetime_ref.ident.span, "undeclared lifetime"); - err + ) + .span_label_mv(lifetime_ref.ident.span, "undeclared lifetime") }; self.suggest_introducing_lifetime( &mut err, diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 758c31224045c..8baa5d892a5c2 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -18,10 +18,9 @@ pub struct FeatureGateError { impl<'a> IntoDiagnostic<'a> for FeatureGateError { #[track_caller] fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> { - let mut diag = DiagnosticBuilder::new(dcx, level, self.explain); - diag.span(self.span); - diag.code(error_code!(E0658)); - diag + DiagnosticBuilder::new(dcx, level, self.explain) + .span_mv(self.span) + .code_mv(error_code!(E0658)) } } diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index 0fa59d2ddfba1..746783ab7e3e2 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -18,9 +18,7 @@ impl IntoDiagnostic<'_, G> for TestOutput { let TestOutput { span, kind, content } = self; #[allow(rustc::untranslatable_diagnostic)] - let mut diag = DiagnosticBuilder::new(dcx, level, format!("{kind}({content})")); - diag.span(span); - diag + DiagnosticBuilder::new(dcx, level, format!("{kind}({content})")).span_mv(span) } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index efc75ee538e89..6bf1307b37f3e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2654,26 +2654,24 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .chain(Some(data.term.into_arg())) .find(|g| g.has_non_region_infer()); if let Some(subst) = subst { - let mut err = self.emit_inference_failure_err( + self.emit_inference_failure_err( obligation.cause.body_id, span, subst, ErrorCode::E0284, true, - ); - err.note(format!("cannot satisfy `{predicate}`")); - err + ) + .note_mv(format!("cannot satisfy `{predicate}`")) } else { // If we can't find a substitution, just print a generic error - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), span, E0284, "type annotations needed: cannot satisfy `{}`", predicate, - ); - err.span_label(span, format!("cannot satisfy `{predicate}`")); - err + ) + .span_label_mv(span, format!("cannot satisfy `{predicate}`")) } } @@ -2693,30 +2691,28 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err } else { // If we can't find a substitution, just print a generic error - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), span, E0284, "type annotations needed: cannot satisfy `{}`", predicate, - ); - err.span_label(span, format!("cannot satisfy `{predicate}`")); - err + ) + .span_label_mv(span, format!("cannot satisfy `{predicate}`")) } } _ => { if self.dcx().has_errors().is_some() || self.tainted_by_errors().is_some() { return; } - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), span, E0284, "type annotations needed: cannot satisfy `{}`", predicate, - ); - err.span_label(span, format!("cannot satisfy `{predicate}`")); - err + ) + .span_label_mv(span, format!("cannot satisfy `{predicate}`")) } }; self.note_obligation_cause(&mut err, obligation); From bd4e623485f383b478fae662a767a3129bb4b989 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 17:03:10 +1100 Subject: [PATCH 04/14] Use chaining for `DiagnosticBuilder` construction and `emit`. To avoid the use of a mutable local variable, and because it reads more nicely. --- compiler/rustc_builtin_macros/src/asm.rs | 15 ++-- .../rustc_codegen_cranelift/src/driver/jit.rs | 7 +- .../rustc_codegen_ssa/src/codegen_attrs.rs | 8 +- .../src/astconv/generics.rs | 6 +- .../src/astconv/object_safety.rs | 10 +-- .../rustc_hir_analysis/src/check/check.rs | 6 +- .../src/check/intrinsicck.rs | 74 +++++++++++-------- .../rustc_hir_analysis/src/check/wfcheck.rs | 53 +++++++------ .../src/coherence/inherent_impls_overlap.rs | 11 ++- .../src/collect/resolve_bound_vars.rs | 8 +- compiler/rustc_hir_typeck/src/expr.rs | 33 +++++---- compiler/rustc_hir_typeck/src/pat.rs | 10 +-- compiler/rustc_hir_typeck/src/place_op.rs | 12 +-- compiler/rustc_middle/src/lint.rs | 1 - compiler/rustc_middle/src/values.rs | 10 +-- .../rustc_parse/src/parser/diagnostics.rs | 19 ++--- compiler/rustc_parse/src/parser/generics.rs | 23 +++--- compiler/rustc_parse/src/parser/item.rs | 3 +- .../rustc_resolve/src/late/diagnostics.rs | 25 ++++--- compiler/rustc_resolve/src/macros.rs | 9 +-- .../error_reporting/type_err_ctxt_ext.rs | 21 +++--- src/librustdoc/core.rs | 12 +-- 22 files changed, 193 insertions(+), 183 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index ac90f4d4084d3..d0e13fa3c0f30 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -693,13 +693,14 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option {} 1 => { let (sp, msg) = unused_operands.into_iter().next().unwrap(); - let mut err = ecx.dcx().struct_span_err(sp, msg); - err.span_label(sp, msg); - err.help(format!( - "if this argument is intentionally unused, \ - consider using it in an asm comment: `\"/*{help_str} */\"`" - )); - err.emit(); + ecx.dcx() + .struct_span_err(sp, msg) + .span_label_mv(sp, msg) + .help_mv(format!( + "if this argument is intentionally unused, \ + consider using it in an asm comment: `\"/*{help_str} */\"`" + )) + .emit(); } _ => { let mut err = ecx.dcx().struct_span_err( diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs index a8d8fb189e2e0..50d9f287e74c9 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs @@ -321,9 +321,10 @@ fn dep_symbol_lookup_fn( Linkage::NotLinked | Linkage::IncludedFromDylib => {} Linkage::Static => { let name = crate_info.crate_name[&cnum]; - let mut err = sess.dcx().struct_err(format!("Can't load static lib {}", name)); - err.note("rustc_codegen_cranelift can only load dylibs in JIT mode."); - err.emit(); + sess.dcx() + .struct_err(format!("Can't load static lib {}", name)) + .note("rustc_codegen_cranelift can only load dylibs in JIT mode.") + .emit(); } Linkage::Dynamic => { dylib_paths.push(src.dylib.as_ref().unwrap().0.clone()); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index a1ec191f10524..f53067d194ac3 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -303,14 +303,14 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { // This exception needs to be kept in sync with allowing // `#[target_feature]` on `main` and `start`. } else if !tcx.features().target_feature_11 { - let mut err = feature_err( + feature_err( &tcx.sess.parse_sess, sym::target_feature_11, attr.span, "`#[target_feature(..)]` can only be applied to `unsafe` functions", - ); - err.span_label(tcx.def_span(did), "not an `unsafe` function"); - err.emit(); + ) + .span_label_mv(tcx.def_span(did), "not an `unsafe` function") + .emit(); } else { check_target_feature_trait_unsafe(tcx, did, attr.span); } diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 257b108471f4d..adc6a9de8086f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -650,9 +650,9 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes( if position == GenericArgPosition::Value && args.num_lifetime_params() != param_counts.lifetimes { - let mut err = struct_span_err!(tcx.dcx(), span, E0794, "{}", msg); - err.span_note(span_late, note); - err.emit(); + struct_span_err!(tcx.dcx(), span, E0794, "{}", msg) + .span_note_mv(span_late, note) + .emit(); } else { let mut multispan = MultiSpan::from_span(span); multispan.push_span_label(span_late, note); diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index ff84a98249527..703e0bdc40edb 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -290,19 +290,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if references_self { let def_id = i.bottom().0.def_id(); - let mut err = struct_span_err!( + struct_span_err!( tcx.dcx(), i.bottom().1, E0038, "the {} `{}` cannot be made into an object", tcx.def_descr(def_id), tcx.item_name(def_id), - ); - err.note( + ) + .note_mv( rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![]) .error_msg(), - ); - err.emit(); + ) + .emit(); } ty::ExistentialTraitRef { def_id: trait_ref.def_id, args } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 544e06879f6f0..4b26a469eb566 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1140,13 +1140,13 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { let disr_non_unit = def.variants().iter().any(|var| !is_unit(var) && has_disr(var)); if disr_non_unit || (disr_units && has_non_units) { - let err = struct_span_err!( + struct_span_err!( tcx.dcx(), tcx.def_span(def_id), E0732, "`#[repr(inttype)]` must be specified" - ); - err.emit(); + ) + .emit(); } } diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index ac18e6de0bac8..1979f52eda948 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -153,12 +153,14 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { }; let Some(asm_ty) = asm_ty else { let msg = format!("cannot use value of type `{ty}` for inline assembly"); - let mut err = self.tcx.dcx().struct_span_err(expr.span, msg); - err.note( - "only integers, floats, SIMD vectors, pointers and function pointers \ - can be used as arguments for inline assembly", - ); - err.emit(); + self.tcx + .dcx() + .struct_span_err(expr.span, msg) + .note_mv( + "only integers, floats, SIMD vectors, pointers and function pointers \ + can be used as arguments for inline assembly", + ) + .emit(); return None; }; @@ -166,9 +168,11 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { // possibly fail is for SIMD types which don't #[derive(Copy)]. if !ty.is_copy_modulo_regions(self.tcx, self.param_env) { let msg = "arguments for inline assembly must be copyable"; - let mut err = self.tcx.dcx().struct_span_err(expr.span, msg); - err.note(format!("`{ty}` does not implement the Copy trait")); - err.emit(); + self.tcx + .dcx() + .struct_span_err(expr.span, msg) + .note_mv(format!("`{ty}` does not implement the Copy trait")) + .emit(); } // Ideally we wouldn't need to do this, but LLVM's register allocator @@ -183,16 +187,17 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Some((in_expr, Some(in_asm_ty))) = tied_input { if in_asm_ty != asm_ty { let msg = "incompatible types for asm inout argument"; - let mut err = self.tcx.dcx().struct_span_err(vec![in_expr.span, expr.span], msg); - let in_expr_ty = (self.get_operand_ty)(in_expr); - err.span_label(in_expr.span, format!("type `{in_expr_ty}`")); - err.span_label(expr.span, format!("type `{ty}`")); - err.note( - "asm inout arguments must have the same type, \ + self.tcx + .dcx() + .struct_span_err(vec![in_expr.span, expr.span], msg) + .span_label_mv(in_expr.span, format!("type `{in_expr_ty}`")) + .span_label_mv(expr.span, format!("type `{ty}`")) + .note_mv( + "asm inout arguments must have the same type, \ unless they are both pointers or integers of the same size", - ); - err.emit(); + ) + .emit(); } // All of the later checks have already been done on the input, so @@ -234,13 +239,15 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Some(feature) = feature { if !target_features.contains(feature) { let msg = format!("`{feature}` target feature is not enabled"); - let mut err = self.tcx.dcx().struct_span_err(expr.span, msg); - err.note(format!( - "this is required to use type `{}` with register class `{}`", - ty, - reg_class.name(), - )); - err.emit(); + self.tcx + .dcx() + .struct_span_err(expr.span, msg) + .note_mv(format!( + "this is required to use type `{}` with register class `{}`", + ty, + reg_class.name(), + )) + .emit(); return Some(asm_ty); } } @@ -449,14 +456,17 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ty::Never | ty::Error(_) => {} ty::FnDef(..) => {} _ => { - let mut err = - self.tcx.dcx().struct_span_err(*op_sp, "invalid `sym` operand"); - err.span_label( - self.tcx.def_span(anon_const.def_id), - format!("is {} `{}`", ty.kind().article(), ty), - ); - err.help("`sym` operands must refer to either a function or a static"); - err.emit(); + self.tcx + .dcx() + .struct_span_err(*op_sp, "invalid `sym` operand") + .span_label_mv( + self.tcx.def_span(anon_const.def_id), + format!("is {} `{}`", ty.kind().article(), ty), + ) + .help_mv( + "`sym` operands must refer to either a function or a static", + ) + .emit(); } }; } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4bac124b58bbe..67ec2c3e5ea82 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -197,11 +197,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() let mut res = Ok(()); if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) { let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span); - let mut err = - tcx.dcx().struct_span_err(sp, "impls of auto traits cannot be default"); - err.span_labels(impl_.defaultness_span, "default because of this"); - err.span_label(sp, "auto trait"); - res = Err(err.emit()); + res = Err(tcx + .dcx() + .struct_span_err(sp, "impls of auto traits cannot be default") + .span_labels_mv(impl_.defaultness_span, "default because of this") + .span_label_mv(sp, "auto trait") + .emit()); } // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. match tcx.impl_polarity(def_id) { @@ -489,35 +490,33 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { if !unsatisfied_bounds.is_empty() { let plural = pluralize!(unsatisfied_bounds.len()); - let mut err = tcx.dcx().struct_span_err( - gat_item_hir.span, - format!("missing required bound{} on `{}`", plural, gat_item_hir.ident), - ); - let suggestion = format!( "{} {}", gat_item_hir.generics.add_where_or_trailing_comma(), unsatisfied_bounds.join(", "), ); - err.span_suggestion( - gat_item_hir.generics.tail_span_for_predicate_suggestion(), - format!("add the required where clause{plural}"), - suggestion, - Applicability::MachineApplicable, - ); - let bound = if unsatisfied_bounds.len() > 1 { "these bounds are" } else { "this bound is" }; - err.note(format!( - "{bound} currently required to ensure that impls have maximum flexibility" - )); - err.note( - "we are soliciting feedback, see issue #87479 \ + tcx.dcx() + .struct_span_err( + gat_item_hir.span, + format!("missing required bound{} on `{}`", plural, gat_item_hir.ident), + ) + .span_suggestion_mv( + gat_item_hir.generics.tail_span_for_predicate_suggestion(), + format!("add the required where clause{plural}"), + suggestion, + Applicability::MachineApplicable, + ) + .note_mv(format!( + "{bound} currently required to ensure that impls have maximum flexibility" + )) + .note_mv( + "we are soliciting feedback, see issue #87479 \ \ for more information", - ); - - err.emit(); + ) + .emit(); } } } @@ -938,8 +937,8 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), }; if may_suggest_feature && tcx.sess.is_nightly_build() { diag.help( - "add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types", - ); + "add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types", + ); } Err(diag.emit()) diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index ec15aa65e7ac2..8f54bf00528cb 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -70,17 +70,16 @@ impl<'tcx> InherentOverlapChecker<'tcx> { match seen_items.entry(norm_ident) { Entry::Occupied(entry) => { let former = entry.get(); - let mut err = struct_span_err!( + struct_span_err!( self.tcx.dcx(), span, E0592, "duplicate definitions with name `{}`", ident, - ); - err.span_label(span, format!("duplicate definitions for `{ident}`")); - err.span_label(*former, format!("other definition for `{ident}`")); - - err.emit(); + ) + .span_label_mv(span, format!("duplicate definitions for `{ident}`")) + .span_label_mv(*former, format!("other definition for `{ident}`")) + .emit(); } Entry::Vacant(entry) => { entry.insert(span); diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index c033cec31550d..61bb4235139db 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -750,12 +750,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { kind: hir::ItemKind::OpaqueTy { .. }, .. }) = self.tcx.hir_node(parent_id) { - let mut err = self.tcx.dcx().struct_span_err( + self.tcx.dcx().struct_span_err( lifetime.ident.span, "higher kinded lifetime bounds on nested opaque types are not supported yet", - ); - err.span_note(self.tcx.def_span(def_id), "lifetime declared here"); - err.emit(); + ) + .span_note_mv(self.tcx.def_span(def_id), "lifetime declared here") + .emit(); self.uninsert_lifetime_on_error(lifetime, def.unwrap()); } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index da9d41a7d72d9..c716391351737 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3183,9 +3183,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.require_type_is_sized(ty, expr.span, traits::InlineAsmSized); if !is_input && !expr.is_syntactic_place_expr() { - let mut err = self.dcx().struct_span_err(expr.span, "invalid asm output"); - err.span_label(expr.span, "cannot assign to this expression"); - err.emit(); + self.dcx() + .struct_span_err(expr.span, "invalid asm output") + .span_label_mv(expr.span, "cannot assign to this expression") + .emit(); } // If this is an input value, we require its type to be fully resolved @@ -3278,27 +3279,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter_enumerated() .find(|(_, v)| v.ident(self.tcx).normalize_to_macros_2_0() == ident) else { - let mut err = type_error_struct!( + type_error_struct!( self.dcx(), ident.span, container, E0599, "no variant named `{ident}` found for enum `{container}`", - ); - err.span_label(field.span, "variant not found"); - err.emit(); + ) + .span_label_mv(field.span, "variant not found") + .emit(); break; }; let Some(&subfield) = fields.next() else { - let mut err = type_error_struct!( + type_error_struct!( self.dcx(), ident.span, container, E0795, "`{ident}` is an enum variant; expected field at end of `offset_of`", - ); - err.span_label(field.span, "enum variant"); - err.emit(); + ) + .span_label_mv(field.span, "enum variant") + .emit(); break; }; let (subident, sub_def_scope) = @@ -3309,16 +3310,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter_enumerated() .find(|(_, f)| f.ident(self.tcx).normalize_to_macros_2_0() == subident) else { - let mut err = type_error_struct!( + type_error_struct!( self.dcx(), ident.span, container, E0609, "no field named `{subfield}` on enum variant `{container}::{ident}`", - ); - err.span_label(field.span, "this enum variant..."); - err.span_label(subident.span, "...does not have this field"); - err.emit(); + ) + .span_label_mv(field.span, "this enum variant...") + .span_label_mv(subident.span, "...does not have this field") + .emit(); break; }; diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 022213abd6703..4ac85cce292f0 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1541,19 +1541,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sp_comma = sm.end_point(pat.span.with_hi(sp_brace.hi())); let sugg = if no_fields || sp_brace != sp_comma { ".. }" } else { ", .. }" }; - let mut err = struct_span_err!( + struct_span_err!( self.dcx(), pat.span, E0638, "`..` required with {descr} marked as non-exhaustive", - ); - err.span_suggestion_verbose( + ) + .span_suggestion_verbose_mv( sp_comma, "add `..` at the end of the field list to ignore all other fields", sugg, Applicability::MachineApplicable, - ); - err.emit(); + ) + .emit(); } fn error_field_already_bound( diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index c3bcdcfa5cd81..3825c513ef3f0 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -332,15 +332,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if inside_union && source.ty_adt_def().is_some_and(|adt| adt.is_manually_drop()) { - let mut err = self.dcx().struct_span_err( + self.dcx().struct_span_err( expr.span, "not automatically applying `DerefMut` on `ManuallyDrop` union field", - ); - err.help( + ) + .help_mv( "writing to this reference calls the destructor for the old value", - ); - err.help("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor"); - err.emit(); + ) + .help_mv("add an explicit `*` if that is desired, or call `ptr::write` to not run the destructor") + .emit(); } } source = adjustment.target; diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index d45ec8e464690..212e831e10614 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -357,7 +357,6 @@ pub fn struct_lint_level( if let Level::Expect(_) = level { let name = lint.name_lower(); err.code(DiagnosticId::Lint { name, has_future_breakage, is_force_warn: false }); - decorate(&mut err); err.emit(); return; diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index b4e45ad568562..b3c05a36a138a 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -190,7 +190,7 @@ pub fn recursive_type_error( } s }; - let mut err = struct_span_err!( + struct_span_err!( tcx.dcx(), err_span, E0072, @@ -198,13 +198,13 @@ pub fn recursive_type_error( pluralize!(cycle_len), items_list, pluralize!("has", cycle_len), - ); - err.multipart_suggestion( + ) + .multipart_suggestion_mv( "insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle", suggestion, Applicability::HasPlaceholders, - ); - err.emit(); + ) + .emit(); } fn find_item_ty_spans( diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 02eab2bac58b5..66d80fa3c5237 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2848,15 +2848,16 @@ impl<'a> Parser<'a> { let label = self.eat_label().expect("just checked if a label exists"); self.bump(); // eat `:` let span = label.ident.span.to(self.prev_token.span); - let mut err = self.dcx().struct_span_err(span, "block label not supported here"); - err.span_label(span, "not supported here"); - err.tool_only_span_suggestion( - label.ident.span.until(self.token.span), - "remove this block label", - "", - Applicability::MachineApplicable, - ); - err.emit(); + self.dcx() + .struct_span_err(span, "block label not supported here") + .span_label_mv(span, "not supported here") + .tool_only_span_suggestion_mv( + label.ident.span.until(self.token.span), + "remove this block label", + "", + Applicability::MachineApplicable, + ) + .emit(); true } diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 2a8e220181a44..7ff72eb5fb3fa 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -141,17 +141,18 @@ impl<'a> Parser<'a> { // Parse optional const generics default value. let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None }; - let mut err = self.dcx().struct_span_err( - mistyped_const_ident.span, - format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()), - ); - err.span_suggestion_verbose( - mistyped_const_ident.span, - "use the `const` keyword", - kw::Const.as_str(), - Applicability::MachineApplicable, - ); - err.emit(); + self.dcx() + .struct_span_err( + mistyped_const_ident.span, + format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()), + ) + .span_suggestion_verbose_mv( + mistyped_const_ident.span, + "use the `const` keyword", + kw::Const.as_str(), + Applicability::MachineApplicable, + ) + .emit(); Ok(GenericParam { ident, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 2694dd3c9c612..381ea21a2446e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1109,8 +1109,7 @@ impl<'a> Parser<'a> { && self.token.is_keyword(kw::Unsafe) && self.look_ahead(1, |t| t.kind == token::OpenDelim(Delimiter::Brace)) { - let err = self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err(); - err.emit(); + self.expect(&token::OpenDelim(Delimiter::Brace)).unwrap_err().emit(); unsafety = Unsafe::Yes(self.token.span); self.eat_keyword(kw::Unsafe); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 43608da8ab2a0..70519af16c580 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3282,16 +3282,16 @@ fn mk_where_bound_predicate( /// Report lifetime/lifetime shadowing as an error. pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) { - let mut err = struct_span_err!( + struct_span_err!( sess.dcx(), shadower.span, E0496, "lifetime name `{}` shadows a lifetime name that is already in scope", orig.name, - ); - err.span_label(orig.span, "first declared here"); - err.span_label(shadower.span, format!("lifetime `{}` already in scope", orig.name)); - err.emit(); + ) + .span_label_mv(orig.span, "first declared here") + .span_label_mv(shadower.span, format!("lifetime `{}` already in scope", orig.name)) + .emit(); } struct LifetimeFinder<'ast> { @@ -3317,11 +3317,12 @@ impl<'ast> Visitor<'ast> for LifetimeFinder<'ast> { pub(super) fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) { let name = shadower.name; let shadower = shadower.span; - let mut err = sess.dcx().struct_span_warn( - shadower, - format!("label name `{name}` shadows a label name that is already in scope"), - ); - err.span_label(orig, "first declared here"); - err.span_label(shadower, format!("label `{name}` already in scope")); - err.emit(); + sess.dcx() + .struct_span_warn( + shadower, + format!("label name `{name}` shadows a label name that is already in scope"), + ) + .span_label_mv(orig, "first declared here") + .span_label_mv(shadower, format!("label `{name}` already in scope")) + .emit(); } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 32aed6611cfc6..fc55481cb0158 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -576,10 +576,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { err.add_as_non_derive = Some(AddAsNonDerive { macro_path: &path_str }); } - let mut err = self.dcx().create_err(err); - err.span_label(path.span, format!("not {article} {expected}")); - - err.emit(); + self.dcx() + .create_err(err) + .span_label_mv(path.span, format!("not {article} {expected}")) + .emit(); return Ok((self.dummy_ext(kind), Res::Err)); } @@ -830,7 +830,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { expected, ident, }); - self.unresolved_macro_suggestions(&mut err, kind, &parent_scope, ident, krate); err.emit(); } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 6bf1307b37f3e..51119c3560e61 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -3544,17 +3544,16 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { span: Span, ) -> Option> { if !self.tcx.features().generic_const_exprs { - let mut err = self - .dcx() - .struct_span_err(span, "constant expression depends on a generic parameter"); - // FIXME(const_generics): we should suggest to the user how they can resolve this - // issue. However, this is currently not actually possible - // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). - // - // Note that with `feature(generic_const_exprs)` this case should not - // be reachable. - err.note("this may fail depending on what value the parameter takes"); - err.emit(); + self.dcx() + .struct_span_err(span, "constant expression depends on a generic parameter") + // FIXME(const_generics): we should suggest to the user how they can resolve this + // issue. However, this is currently not actually possible + // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). + // + // Note that with `feature(generic_const_exprs)` this case should not + // be reachable. + .note_mv("this may fail depending on what value the parameter takes") + .emit(); return None; } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 359d5ec485e3c..40ea4346f9333 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -495,16 +495,16 @@ impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> { .intersperse("::") .collect::() ); - let mut err = rustc_errors::struct_span_err!( + rustc_errors::struct_span_err!( self.tcx.dcx(), path.span, E0433, "failed to resolve: {label}", - ); - err.span_label(path.span, label); - err.note("this error was originally ignored because you are running `rustdoc`"); - err.note("try running again with `rustc` or `cargo check` and you may get a more detailed error"); - err.emit(); + ) + .span_label_mv(path.span, label) + .note_mv("this error was originally ignored because you are running `rustdoc`") + .note_mv("try running again with `rustc` or `cargo check` and you may get a more detailed error") + .emit(); } // We could have an outer resolution that succeeded, // but with generic parameters that failed. From 6682f243dcb9babd67525bbf9798dca302f60588 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 3 Jan 2024 21:50:36 +1100 Subject: [PATCH 05/14] Remove all eight `DiagnosticBuilder::*_with_code` methods. These all have relatively low use, and can be perfectly emulated with a simpler construction method combined with `code` or `code_mv`. --- .../rustc_errors/src/diagnostic_builder.rs | 4 +- compiler/rustc_errors/src/lib.rs | 92 ------------------- .../rustc_hir_analysis/src/astconv/mod.rs | 3 +- .../src/check/compare_impl_item.rs | 4 +- .../wrong_number_of_generic_args.rs | 3 +- compiler/rustc_hir_typeck/src/expr.rs | 8 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 29 +++--- compiler/rustc_hir_typeck/src/lib.rs | 9 +- .../src/infer/error_reporting/mod.rs | 18 ++-- compiler/rustc_parse/src/lexer/mod.rs | 73 +++++++-------- compiler/rustc_parse/src/parser/attr.rs | 9 +- compiler/rustc_resolve/src/diagnostics.rs | 4 +- .../rustc_resolve/src/late/diagnostics.rs | 4 +- .../error_reporting/type_err_ctxt_ext.rs | 4 +- 14 files changed, 84 insertions(+), 180 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index b3f8a6c244076..dcbf60e4847e3 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -538,11 +538,11 @@ impl Drop for DiagnosticBuilder<'_, G> { #[macro_export] macro_rules! struct_span_err { ($dcx:expr, $span:expr, $code:ident, $($message:tt)*) => ({ - $dcx.struct_span_err_with_code( + $dcx.struct_span_err( $span, format!($($message)*), - $crate::error_code!($code), ) + .code_mv($crate::error_code!($code)) }) } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a63c32566ca7c..4710722c77157 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -732,19 +732,6 @@ impl DiagCtxt { self.struct_warn(msg).span_mv(span) } - /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. - /// Also include a code. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_warn_with_code( - &self, - span: impl Into, - msg: impl Into, - code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ()> { - self.struct_span_warn(span, msg).code_mv(code) - } - /// Construct a builder at the `Warning` level with the `msg`. /// /// Attempting to `.emit()` the builder will only emit if either: @@ -785,18 +772,6 @@ impl DiagCtxt { self.struct_err(msg).span_mv(span) } - /// Construct a builder at the `Error` level at the given `span`, with the `msg`, and `code`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_err_with_code( - &self, - span: impl Into, - msg: impl Into, - code: DiagnosticId, - ) -> DiagnosticBuilder<'_> { - self.struct_span_err(span, msg).code_mv(code) - } - /// Construct a builder at the `Error` level with the `msg`. // FIXME: This method should be removed (every error should have an associated error code). #[rustc_lint_diagnostics] @@ -805,28 +780,6 @@ impl DiagCtxt { DiagnosticBuilder::new(self, Error, msg) } - /// Construct a builder at the `Error` level with the `msg` and the `code`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_err_with_code( - &self, - msg: impl Into, - code: DiagnosticId, - ) -> DiagnosticBuilder<'_> { - self.struct_err(msg).code_mv(code) - } - - /// Construct a builder at the `Warn` level with the `msg` and the `code`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_warn_with_code( - &self, - msg: impl Into, - code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ()> { - self.struct_warn(msg).code_mv(code) - } - /// Construct a builder at the `Fatal` level at the given `span` and with the `msg`. #[rustc_lint_diagnostics] #[track_caller] @@ -838,18 +791,6 @@ impl DiagCtxt { self.struct_fatal(msg).span_mv(span) } - /// Construct a builder at the `Fatal` level at the given `span`, with the `msg`, and `code`. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_span_fatal_with_code( - &self, - span: impl Into, - msg: impl Into, - code: DiagnosticId, - ) -> DiagnosticBuilder<'_, FatalAbort> { - self.struct_span_fatal(span, msg).code_mv(code) - } - /// Construct a builder at the `Fatal` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] @@ -897,17 +838,6 @@ impl DiagCtxt { self.struct_span_fatal(span, msg).emit() } - #[rustc_lint_diagnostics] - #[track_caller] - pub fn span_fatal_with_code( - &self, - span: impl Into, - msg: impl Into, - code: DiagnosticId, - ) -> ! { - self.struct_span_fatal_with_code(span, msg, code).emit() - } - #[rustc_lint_diagnostics] #[track_caller] pub fn span_err( @@ -918,34 +848,12 @@ impl DiagCtxt { self.struct_span_err(span, msg).emit() } - #[rustc_lint_diagnostics] - #[track_caller] - pub fn span_err_with_code( - &self, - span: impl Into, - msg: impl Into, - code: DiagnosticId, - ) -> ErrorGuaranteed { - self.struct_span_err_with_code(span, msg, code).emit() - } - #[rustc_lint_diagnostics] #[track_caller] pub fn span_warn(&self, span: impl Into, msg: impl Into) { self.struct_span_warn(span, msg).emit() } - #[rustc_lint_diagnostics] - #[track_caller] - pub fn span_warn_with_code( - &self, - span: impl Into, - msg: impl Into, - code: DiagnosticId, - ) { - self.struct_span_warn_with_code(span, msg, code).emit() - } - pub fn span_bug(&self, span: impl Into, msg: impl Into) -> ! { self.struct_span_bug(span, msg).emit() } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 0a924aa3536ee..eb6a5cc5b217f 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1647,7 +1647,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let msg = format!("{kind} `{name}` is private"); let def_span = tcx.def_span(item); tcx.dcx() - .struct_span_err_with_code(span, msg, rustc_errors::error_code!(E0624)) + .struct_span_err(span, msg) + .code_mv(rustc_errors::error_code!(E0624)) .span_label_mv(span, format!("private {kind}")) .span_label_mv(def_span, format!("{kind} defined here")) .emit(); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index f5323fd3bb8df..46b5c1a94dec9 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1371,7 +1371,7 @@ fn compare_number_of_generics<'tcx>( let spans = arg_spans(impl_.kind, impl_item.generics); let span = spans.first().copied(); - let mut err = tcx.dcx().struct_span_err_with_code( + let mut err = tcx.dcx().struct_span_err( spans, format!( "{} `{}` has {} {kind} parameter{} but its trait \ @@ -1384,8 +1384,8 @@ fn compare_number_of_generics<'tcx>( pluralize!(trait_count), kind = kind, ), - DiagnosticId::Error("E0049".into()), ); + err.code(DiagnosticId::Error("E0049".into())); let msg = format!("expected {trait_count} {kind} parameter{}", pluralize!(trait_count),); diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index ae68a8bf2811e..04c42b4b2e632 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -523,8 +523,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { fn start_diagnostics(&self) -> DiagnosticBuilder<'tcx> { let span = self.path_segment.ident.span; let msg = self.create_error_message(); - - self.tcx.dcx().struct_span_err_with_code(span, msg, self.code()) + self.tcx.dcx().struct_span_err(span, msg).code_mv(self.code()) } /// Builds the `expected 1 type argument / supplied 2 type arguments` message. diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index c716391351737..7617f03fcf290 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -940,12 +940,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } - // FIXME: Make this use Diagnostic once error codes can be dynamically set. - let mut err = self.dcx().struct_span_err_with_code( - op_span, - "invalid left-hand side of assignment", - DiagnosticId::Error(err_code.into()), - ); + let mut err = self.dcx().struct_span_err(op_span, "invalid left-hand side of assignment"); + err.code(DiagnosticId::Error(err_code.into())); err.span_label(lhs.span, "cannot assign to this expression"); self.comes_from_while_condition(lhs.hir_id, |expr| { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 9b89169116182..da6f2042c110d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -664,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("arguments to this {call_name} are incorrect"), ); } else { - err = tcx.dcx().struct_span_err_with_code( + err = tcx.dcx().struct_span_err( full_call_span, format!( "{call_name} takes {}{} but {} {} supplied", @@ -676,8 +676,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { potentially_plural_count(provided_args.len(), "argument"), pluralize!("was", provided_args.len()) ), - DiagnosticId::Error(err_code.to_owned()), ); + err.code(DiagnosticId::Error(err_code.to_owned())); err.multipart_suggestion_verbose( "wrap these arguments in parentheses to construct a tuple", vec![ @@ -815,18 +815,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_name, ) } else { - tcx.dcx().struct_span_err_with_code( - full_call_span, - format!( - "this {} takes {}{} but {} {} supplied", - call_name, - if c_variadic { "at least " } else { "" }, - potentially_plural_count(formal_and_expected_inputs.len(), "argument"), - potentially_plural_count(provided_args.len(), "argument"), - pluralize!("was", provided_args.len()) - ), - DiagnosticId::Error(err_code.to_owned()), - ) + tcx.dcx() + .struct_span_err( + full_call_span, + format!( + "this {} takes {}{} but {} {} supplied", + call_name, + if c_variadic { "at least " } else { "" }, + potentially_plural_count(formal_and_expected_inputs.len(), "argument"), + potentially_plural_count(provided_args.len(), "argument"), + pluralize!("was", provided_args.len()) + ), + ) + .code_mv(DiagnosticId::Error(err_code.to_owned())) }; // As we encounter issues, keep track of what we want to provide for the suggestion diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index c3332a4930673..ffae08d0f27cc 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -366,11 +366,10 @@ fn report_unexpected_variant_res( _ => res.descr(), }; let path_str = rustc_hir_pretty::qpath_to_string(qpath); - let err = tcx.dcx().struct_span_err_with_code( - span, - format!("expected {expected}, found {res_descr} `{path_str}`"), - DiagnosticId::Error(err_code.into()), - ); + let err = tcx + .dcx() + .struct_span_err(span, format!("expected {expected}, found {res_descr} `{path_str}`")) + .code_mv(DiagnosticId::Error(err_code.into())); match res { Res::Def(DefKind::Fn | DefKind::AssocFn, _) if err_code == "E0164" => { let patterns_url = "https://doc.rust-lang.org/book/ch18-00-patterns.html"; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index f88fd617c13ee..5dd4f959bebf9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2356,15 +2356,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }, }; - let mut err = self.tcx.dcx().struct_span_err_with_code( - span, - format!("{labeled_user_string} may not live long enough"), - match sub.kind() { - ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => error_code!(E0309), - ty::ReStatic => error_code!(E0310), - _ => error_code!(E0311), - }, - ); + let mut err = self + .tcx + .dcx() + .struct_span_err(span, format!("{labeled_user_string} may not live long enough")); + err.code(match sub.kind() { + ty::ReEarlyParam(_) | ty::ReLateParam(_) if sub.has_name() => error_code!(E0309), + ty::ReStatic => error_code!(E0310), + _ => error_code!(E0311), + }); '_explain: { let (description, span) = match sub.kind() { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index bc42b1b3ef849..d08f31e69d881 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -395,51 +395,58 @@ impl<'a> StringReader<'a> { match kind { rustc_lexer::LiteralKind::Char { terminated } => { if !terminated { - self.dcx().span_fatal_with_code( - self.mk_sp(start, end), - "unterminated character literal", - error_code!(E0762), - ) + self.dcx() + .struct_span_fatal(self.mk_sp(start, end), "unterminated character literal") + .code_mv(error_code!(E0762)) + .emit() } self.cook_quoted(token::Char, Mode::Char, start, end, 1, 1) // ' ' } rustc_lexer::LiteralKind::Byte { terminated } => { if !terminated { - self.dcx().span_fatal_with_code( - self.mk_sp(start + BytePos(1), end), - "unterminated byte constant", - error_code!(E0763), - ) + self.dcx() + .struct_span_fatal( + self.mk_sp(start + BytePos(1), end), + "unterminated byte constant", + ) + .code_mv(error_code!(E0763)) + .emit() } self.cook_quoted(token::Byte, Mode::Byte, start, end, 2, 1) // b' ' } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { - self.dcx().span_fatal_with_code( - self.mk_sp(start, end), - "unterminated double quote string", - error_code!(E0765), - ) + self.dcx() + .struct_span_fatal( + self.mk_sp(start, end), + "unterminated double quote string", + ) + .code_mv(error_code!(E0765)) + .emit() } self.cook_quoted(token::Str, Mode::Str, start, end, 1, 1) // " " } rustc_lexer::LiteralKind::ByteStr { terminated } => { if !terminated { - self.dcx().span_fatal_with_code( - self.mk_sp(start + BytePos(1), end), - "unterminated double quote byte string", - error_code!(E0766), - ) + self.dcx() + .struct_span_fatal( + self.mk_sp(start + BytePos(1), end), + "unterminated double quote byte string", + ) + .code_mv(error_code!(E0766)) + .emit() } self.cook_quoted(token::ByteStr, Mode::ByteStr, start, end, 2, 1) // b" " } rustc_lexer::LiteralKind::CStr { terminated } => { if !terminated { - self.dcx().span_fatal_with_code( - self.mk_sp(start + BytePos(1), end), - "unterminated C string", - error_code!(E0767), - ) + self.dcx() + .struct_span_fatal( + self.mk_sp(start + BytePos(1), end), + "unterminated C string", + ) + .code_mv(error_code!(E0767)) + .emit() } self.cook_c_string(token::CStr, Mode::CStr, start, end, 2, 1) // c" " } @@ -573,12 +580,9 @@ impl<'a> StringReader<'a> { possible_offset: Option, found_terminators: u32, ) -> ! { - let mut err = self.dcx().struct_span_fatal_with_code( - self.mk_sp(start, start), - "unterminated raw string", - error_code!(E0748), - ); - + let mut err = + self.dcx().struct_span_fatal(self.mk_sp(start, start), "unterminated raw string"); + err.code(error_code!(E0748)); err.span_label(self.mk_sp(start, start), "unterminated raw string"); if n_hashes > 0 { @@ -609,11 +613,8 @@ impl<'a> StringReader<'a> { None => "unterminated block comment", }; let last_bpos = self.pos; - let mut err = self.dcx().struct_span_fatal_with_code( - self.mk_sp(start, last_bpos), - msg, - error_code!(E0758), - ); + let mut err = self.dcx().struct_span_fatal(self.mk_sp(start, last_bpos), msg); + err.code(error_code!(E0758)); let mut nested_block_comment_open_idxs = vec![]; let mut last_nested_block_comment_idxs = None; let mut content_chars = self.str_from(start).char_indices().peekable(); diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 1f8c368b2a999..cec657f7b67ae 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -55,11 +55,10 @@ impl<'a> Parser<'a> { } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind { if attr_style != ast::AttrStyle::Outer { let span = self.token.span; - let mut err = self.dcx().struct_span_err_with_code( - span, - fluent::parse_inner_doc_comment_not_permitted, - error_code!(E0753), - ); + let mut err = self + .dcx() + .struct_span_err(span, fluent::parse_inner_doc_comment_not_permitted); + err.code(error_code!(E0753)); if let Some(replacement_span) = self.annotate_following_item_if_applicable( &mut err, span, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 977a7e796e789..57f23200e795a 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -944,13 +944,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { trait_item_span, trait_path, } => { - self.dcx().struct_span_err_with_code( + self.dcx().struct_span_err( span, format!( "item `{name}` is an associated {kind}, which doesn't match its trait `{trait_path}`", ), - code, ) + .code_mv(code) .span_label_mv(span, "does not match trait") .span_label_mv(trait_item_span, "item in trait") } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 70519af16c580..a36d1377ab5fd 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -429,8 +429,8 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { let base_error = self.make_base_error(path, span, source, res); let code = source.error_code(res.is_some()); - let mut err = - self.r.dcx().struct_span_err_with_code(base_error.span, base_error.msg.clone(), code); + let mut err = self.r.dcx().struct_span_err(base_error.span, base_error.msg.clone()); + err.code(code); self.suggest_at_operator_in_slice_pat_with_range(&mut err, path); self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 51119c3560e61..b05895e4b9a3d 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2525,14 +2525,14 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Replace the more general E0283 with a more specific error err.cancel(); - err = self.dcx().struct_span_err_with_code( + err = self.dcx().struct_span_err( span, format!( "cannot {verb} associated {noun} on trait without specifying the \ corresponding `impl` type", ), - rustc_errors::error_code!(E0790), ); + err.code(rustc_errors::error_code!(E0790)); if let Some(local_def_id) = data.trait_ref.def_id.as_local() && let Some(hir::Node::Item(hir::Item { From 1881055000485527e3ad69e2bc6c9fa247e3f06f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 09:55:07 +1100 Subject: [PATCH 06/14] Remove a `DiagnosticBuilder::emit_without_consuming` call. In this parsing recovery function, we only need to emit the previously obtained error message and mark `expr` as erroneous in the case where we actually recover. --- compiler/rustc_parse/src/parser/diagnostics.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 66d80fa3c5237..b05940f3569a6 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1212,29 +1212,32 @@ impl<'a> Parser<'a> { match x { Ok((_, _, false)) => { if self.eat(&token::Gt) { + // We made sense of it. Improve the error message. e.span_suggestion_verbose( binop.span.shrink_to_lo(), fluent::parse_sugg_turbofish_syntax, "::", Applicability::MaybeIncorrect, - ) - .emit_without_consuming(); + ); match self.parse_expr() { Ok(_) => { + // The subsequent expression is valid. Mark + // `expr` as erroneous and emit `e` now, but + // return `Ok` so parsing can continue. + e.emit(); *expr = self.mk_expr_err(expr.span.to(self.prev_token.span)); return Ok(()); } Err(err) => { - *expr = self.mk_expr_err(expr.span); err.cancel(); } } } } + Ok((_, _, true)) => {} Err(err) => { err.cancel(); } - _ => {} } } Err(e) From 3ce34f42e160d7e63132c7e3994861bb876eb943 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 10:42:31 +1100 Subject: [PATCH 07/14] Remove a second `DiagnosticBuilder::emit_without_consuming` call. Instead of taking `seq` as a mutable reference, `maybe_recover_struct_lit_bad_delims` now consumes `seq` on the recovery path, and returns `seq` unchanged on the non-recovery path. The commit also combines an `if` and a `match` to merge two identical paths. Also change `recover_seq_parse_error` so it receives a `PErr` instead of a `PResult`, because all the call sites now handle the `Ok`/`Err` distinction themselves. --- .../rustc_parse/src/parser/diagnostics.rs | 17 +++--- compiler/rustc_parse/src/parser/expr.rs | 52 +++++++++---------- 2 files changed, 30 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index b05940f3569a6..776d0ace87545 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -35,7 +35,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, FatalError, - PResult, + PErr, PResult, }; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; @@ -2044,17 +2044,12 @@ impl<'a> Parser<'a> { &mut self, delim: Delimiter, lo: Span, - result: PResult<'a, P>, + err: PErr<'a>, ) -> P { - match result { - Ok(x) => x, - Err(err) => { - err.emit(); - // Recover from parse error, callers expect the closing delim to be consumed. - self.consume_block(delim, ConsumeClosingDelim::Yes); - self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err) - } - } + err.emit(); + // Recover from parse error, callers expect the closing delim to be consumed. + self.consume_block(delim, ConsumeClosingDelim::Yes); + self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err) } /// Eats tokens until we can be relatively sure we reached the end of the diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 697c44a9f3e20..db777266b59d2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1272,15 +1272,13 @@ impl<'a> Parser<'a> { }; let open_paren = self.token.span; - let mut seq = self + let seq = self .parse_expr_paren_seq() .map(|args| self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args))); - if let Some(expr) = - self.maybe_recover_struct_lit_bad_delims(lo, open_paren, &mut seq, snapshot) - { - return expr; + match self.maybe_recover_struct_lit_bad_delims(lo, open_paren, seq, snapshot) { + Ok(expr) => expr, + Err(err) => self.recover_seq_parse_error(Delimiter::Parenthesis, lo, err), } - self.recover_seq_parse_error(Delimiter::Parenthesis, lo, seq) } /// If we encounter a parser state that looks like the user has written a `struct` literal with @@ -1290,14 +1288,11 @@ impl<'a> Parser<'a> { &mut self, lo: Span, open_paren: Span, - seq: &mut PResult<'a, P>, + seq: PResult<'a, P>, snapshot: Option<(SnapshotParser<'a>, ExprKind)>, - ) -> Option> { - if !self.may_recover() { - return None; - } - match (seq.as_mut(), snapshot) { - (Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => { + ) -> PResult<'a, P> { + match (self.may_recover(), seq, snapshot) { + (true, Err(err), Some((mut snapshot, ExprKind::Path(None, path)))) => { snapshot.bump(); // `(` match snapshot.parse_struct_fields(path.clone(), false, Delimiter::Parenthesis) { Ok((fields, ..)) @@ -1315,11 +1310,13 @@ impl<'a> Parser<'a> { if !fields.is_empty() && // `token.kind` should not be compared here. // This is because the `snapshot.token.kind` is treated as the same as - // that of the open delim in `TokenTreesReader::parse_token_tree`, even if they are different. + // that of the open delim in `TokenTreesReader::parse_token_tree`, even + // if they are different. self.span_to_snippet(close_paren).is_ok_and(|snippet| snippet == ")") { - let mut replacement_err = - self.dcx().create_err(errors::ParenthesesWithStructFields { + err.cancel(); + self.dcx() + .create_err(errors::ParenthesesWithStructFields { span, r#type: path, braces_for_struct: errors::BracesForStructLiteral { @@ -1332,23 +1329,22 @@ impl<'a> Parser<'a> { .map(|field| field.span.until(field.expr.span)) .collect(), }, - }); - replacement_err.emit_without_consuming(); - - let old_err = mem::replace(err, replacement_err); - old_err.cancel(); + }) + .emit(); } else { - err.emit_without_consuming(); + err.emit(); } - return Some(self.mk_expr_err(span)); + Ok(self.mk_expr_err(span)) + } + Ok(_) => Err(err), + Err(err2) => { + err2.cancel(); + Err(err) } - Ok(_) => {} - Err(err) => err.cancel(), } } - _ => {} + (_, seq, _) => seq, } - None } /// Parse an indexing expression `expr[...]`. @@ -1552,7 +1548,7 @@ impl<'a> Parser<'a> { ) { Ok(x) => x, Err(err) => { - return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, Err(err))); + return Ok(self.recover_seq_parse_error(Delimiter::Parenthesis, lo, err)); } }; let kind = if es.len() == 1 && !trailing_comma { From 1b6c8e7533ae387ed320fc55a45dee95acc311ee Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 10:55:45 +1100 Subject: [PATCH 08/14] Remove a third `DiagnosticBuilder::emit_without_consuming` call. It's not clear why this was here, because the created error is returned as a normal error anyway. Nor is it clear why removing the call works. The change doesn't affect any tests; `tests/ui/parser/issues/issue-102182-impl-trait-recover.rs` looks like the only test that could have been affected. --- compiler/rustc_parse/src/parser/generics.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 7ff72eb5fb3fa..66aa8cbcda4ac 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -77,7 +77,6 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ); } - err.emit_without_consuming(); return Err(err); } } From c733a0216d55977e51a26ead6f2446668f006e02 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 11:10:18 +1100 Subject: [PATCH 09/14] Remove a fourth `DiagnosticBuilder::emit_without_consuming` call. The old code was very hard to understand, involving an `emit_without_consuming` call *and* a `delay_as_bug_without_consuming` call. With slight changes both calls can be avoided. Not creating the error until later is crucial, as is the early return in the `if recovered` block. It took me some time to come up with this reworking -- it went through intermediate states much further from the original code than this final version -- and it's isn't obvious at a glance that it is equivalent. But I think it is, and the unchanged test behaviour is good supporting evidence. The commit also changes `check_trailing_angle_brackets` to return `Option`. This provides a stricter proof that it emitted an error message than asserting `dcx.has_errors().is_some()`, which would succeed if any error had previously been emitted anywhere. --- .../rustc_parse/src/parser/diagnostics.rs | 17 +++++---- compiler/rustc_parse/src/parser/item.rs | 35 +++++++------------ 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 776d0ace87545..a9cf26d991c71 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -34,8 +34,8 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, FatalError, - PErr, PResult, + pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + ErrorGuaranteed, FatalError, PErr, PResult, }; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; @@ -1049,9 +1049,9 @@ impl<'a> Parser<'a> { &mut self, segment: &PathSegment, end: &[&TokenKind], - ) -> bool { + ) -> Option { if !self.may_recover() { - return false; + return None; } // This function is intended to be invoked after parsing a path segment where there are two @@ -1086,7 +1086,7 @@ impl<'a> Parser<'a> { parsed_angle_bracket_args, ); if !parsed_angle_bracket_args { - return false; + return None; } // Keep the span at the start so we can highlight the sequence of `>` characters to be @@ -1124,7 +1124,7 @@ impl<'a> Parser<'a> { number_of_gt, number_of_shr, ); if number_of_gt < 1 && number_of_shr < 1 { - return false; + return None; } // Finally, double check that we have our end token as otherwise this is the @@ -1139,10 +1139,9 @@ impl<'a> Parser<'a> { let span = lo.until(self.token.span); let num_extra_brackets = number_of_gt + number_of_shr * 2; - self.dcx().emit_err(UnmatchedAngleBrackets { span, num_extra_brackets }); - return true; + return Some(self.dcx().emit_err(UnmatchedAngleBrackets { span, num_extra_brackets })); } - false + None } /// Check if a method call with an intended turbofish has been written without surrounding diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 381ea21a2446e..fed3c83a81d16 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1793,52 +1793,43 @@ impl<'a> Parser<'a> { } _ => { let sp = self.prev_token.span.shrink_to_hi(); - let mut err = self.dcx().struct_span_err( - sp, - format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)), - ); + let msg = + format!("expected `,`, or `}}`, found {}", super::token_descr(&self.token)); // Try to recover extra trailing angle brackets - let mut recovered = false; if let TyKind::Path(_, Path { segments, .. }) = &a_var.ty.kind { if let Some(last_segment) = segments.last() { - recovered = self.check_trailing_angle_brackets( + let guar = self.check_trailing_angle_brackets( last_segment, &[&token::Comma, &token::CloseDelim(Delimiter::Brace)], ); - if recovered { + if let Some(_guar) = guar { // Handle a case like `Vec>,` where we can continue parsing fields // after the comma self.eat(&token::Comma); - // `check_trailing_angle_brackets` already emitted a nicer error - // NOTE(eddyb) this was `.cancel()`, but `err` - // gets returned, so we can't fully defuse it. - err.delay_as_bug_without_consuming(); + + // `check_trailing_angle_brackets` already emitted a nicer error, as + // proven by the presence of `_guar`. We can continue parsing. + return Ok(a_var); } } } + let mut err = self.dcx().struct_span_err(sp, msg); + if self.token.is_ident() || (self.token.kind == TokenKind::Pound && (self.look_ahead(1, |t| t == &token::OpenDelim(Delimiter::Bracket)))) { - // This is likely another field, TokenKind::Pound is used for `#[..]` attribute for next field, - // emit the diagnostic and keep going + // This is likely another field, TokenKind::Pound is used for `#[..]` + // attribute for next field. Emit the diagnostic and continue parsing. err.span_suggestion( sp, "try adding a comma", ",", Applicability::MachineApplicable, ); - err.emit_without_consuming(); - recovered = true; - } - - if recovered { - // Make sure an error was emitted (either by recovering an angle bracket, - // or by finding an identifier as the next token), since we're - // going to continue parsing - assert!(self.dcx().has_errors().is_some()); + err.emit(); } else { return Err(err); } From d406278180f1cd7792f50be890658f2739c621fb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 15:25:14 +1100 Subject: [PATCH 10/14] Remove `DiagnosticBuilder::emit_without_consuming`. A nice cleanup: it's now impossible to directly emit a `DiagnosticBuilder` without consuming it. --- compiler/rustc_errors/src/diagnostic_builder.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index dcbf60e4847e3..eb081df040a9f 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -269,12 +269,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { G::emit_producing_guarantee(&mut self) } - /// Emit the diagnostic without consuming it. `emit` should be preferred. - #[track_caller] - pub fn emit_without_consuming(&mut self) -> G::EmitResult { - G::emit_producing_guarantee(self) - } - /// Emit the diagnostic unless `delay` is true, /// in which case the emission will be delayed as a bug. /// @@ -376,7 +370,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { #[track_caller] pub fn delay_as_bug_without_consuming(&mut self) -> G::EmitResult { self.downgrade_to_delayed_bug(); - self.emit_without_consuming() + G::emit_producing_guarantee(self) } forward!((span_label, span_label_mv)( From 4752a923af2a0e26b2da0861e4a8f1f6c35b6d56 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 16:38:04 +1100 Subject: [PATCH 11/14] Remove `DiagnosticBuilder::delay_as_bug_without_consuming`. The existing uses are replaced in one of three ways. - In a function that also has calls to `emit`, just rearrange the code so that exactly one of `delay_as_bug` or `emit` is called on every path. - In a function returning a `DiagnosticBuilder`, use `downgrade_to_delayed_bug`. That's good enough because it will get emitted later anyway. - In `unclosed_delim_err`, one set of errors is being replaced with another set, so just cancel the original errors. --- compiler/rustc_errors/src/diagnostic_builder.rs | 7 ------- compiler/rustc_hir_typeck/src/intrinsicck.rs | 8 +++++--- compiler/rustc_hir_typeck/src/op.rs | 2 +- compiler/rustc_infer/src/infer/error_reporting/mod.rs | 2 +- compiler/rustc_infer/src/infer/error_reporting/note.rs | 2 +- compiler/rustc_parse/src/lexer/mod.rs | 2 +- compiler/rustc_parse/src/lexer/tokentrees.rs | 6 +++--- compiler/rustc_parse/src/parser/pat.rs | 7 ++++--- compiler/rustc_passes/src/errors.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 2 +- 10 files changed, 18 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index eb081df040a9f..6fd485e00adde 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -366,13 +366,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { self.emit() } - /// Non-consuming variant of `delay_as_bug`. - #[track_caller] - pub fn delay_as_bug_without_consuming(&mut self) -> G::EmitResult { - self.downgrade_to_delayed_bug(); - G::emit_producing_guarantee(self) - } - forward!((span_label, span_label_mv)( span: Span, label: impl Into, diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index a18f486b0d252..8bffd2dfc70a1 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -121,15 +121,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if from == to { err.note(format!("`{from}` does not have a fixed size")); + err.emit(); } else { err.note(format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))) .note(format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); if let Err(LayoutError::ReferencesError(_)) = sk_from { - err.delay_as_bug_without_consuming(); + err.delay_as_bug(); } else if let Err(LayoutError::ReferencesError(_)) = sk_to { - err.delay_as_bug_without_consuming(); + err.delay_as_bug(); + } else { + err.emit(); } } - err.emit(); } } diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 59cf0d8c8ed63..3b5226c641431 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -385,7 +385,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let hir::ExprKind::Assign(..) = expr.kind { // We defer to the later error produced by `check_lhs_assignable`. - err.delay_as_bug_without_consuming(); + err.downgrade_to_delayed_bug(); } let suggest_deref_binop = diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 5dd4f959bebf9..b1c360b61cb69 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -361,7 +361,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( ); } ty::ReError(_) => { - err.delay_as_bug_without_consuming(); + err.downgrade_to_delayed_bug(); } _ => { // Ugh. This is a painful case: the hidden region is not one diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index c09646b491c00..77a0accf80bb6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -281,7 +281,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } }; if sub.is_error() || sup.is_error() { - err.delay_as_bug_without_consuming(); + err.downgrade_to_delayed_bug(); } err } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index d08f31e69d881..a45bc58124027 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -67,7 +67,7 @@ pub(crate) fn parse_token_trees<'a>( let (stream, res, unmatched_delims) = tokentrees::TokenTreesReader::parse_all_token_trees(string_reader); match res { - Ok(_open_spacing) if unmatched_delims.is_empty() => Ok(stream), + Ok(()) if unmatched_delims.is_empty() => Ok(stream), _ => { // Return error if there are unmatched delimiters or unclosed delimiters. // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 72f76cd89756b..64b3928689afe 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -277,9 +277,9 @@ impl<'a> TokenTreesReader<'a> { parser.bump(); } if !diff_errs.is_empty() { - errs.iter_mut().for_each(|err| { - err.delay_as_bug_without_consuming(); - }); + for err in errs { + err.cancel(); + } return diff_errs; } return errs; diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index a6804b992043a..00dc307ab60a0 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -242,7 +242,7 @@ impl<'a> Parser<'a> { Some(TopLevelOrPatternNotAllowedSugg::WrapInParens { span, pat }) }; - let mut err = self.dcx().create_err(match syntax_loc { + let err = self.dcx().create_err(match syntax_loc { PatternLocation::LetBinding => { TopLevelOrPatternNotAllowed::LetBinding { span, sub } } @@ -251,9 +251,10 @@ impl<'a> Parser<'a> { } }); if trailing_vert { - err.delay_as_bug_without_consuming(); + err.delay_as_bug(); + } else { + err.emit(); } - err.emit(); } Ok((pat, colon)) diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 44c71dfa8d027..d934e959a417a 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1040,7 +1040,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> { // This error is redundant, we will have already emitted a // suggestion to use the label when `segment` wasn't found // (hence the `Res::Err` check). - diag.delay_as_bug_without_consuming(); + diag.downgrade_to_delayed_bug(); } _ => { diag.span_suggestion( diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index fb1df4e4e766b..4a6ef27e7ba3e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2088,7 +2088,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let ty = self.resolve_vars_if_possible(returned_ty); if ty.references_error() { // don't print out the [type error] here - err.delay_as_bug_without_consuming(); + err.downgrade_to_delayed_bug(); } else { err.span_label(expr.span, format!("this returned value is of type `{ty}`")); } From 0cb486bc5b18fcce37f616bb46b054ebea1028cd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 5 Jan 2024 17:33:12 +1100 Subject: [PATCH 12/14] Make `emit_producing_{guarantee,nothing}` consuming. This is now possible, thanks to changes in previous commits. --- .../rustc_errors/src/diagnostic_builder.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 6fd485e00adde..b81e37501e7e0 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -95,12 +95,12 @@ pub trait EmissionGuarantee: Sized { /// `impl` of `EmissionGuarantee`, to make it impossible to create a value /// of `Self::EmitResult` without actually performing the emission. #[track_caller] - fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult; + fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult; } impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Most `emit_producing_guarantee` functions use this as a starting point. - fn emit_producing_nothing(&mut self) { + fn emit_producing_nothing(mut self) { match self.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -115,7 +115,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. impl EmissionGuarantee for ErrorGuaranteed { - fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + fn emit_producing_guarantee(mut db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult { // Contrast this with `emit_producing_nothing`. match db.state { // First `.emit()` call, the `&DiagCtxt` is still available. @@ -156,7 +156,7 @@ impl EmissionGuarantee for ErrorGuaranteed { // FIXME(eddyb) should there be a `Option` impl as well? impl EmissionGuarantee for () { - fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult { db.emit_producing_nothing(); } } @@ -169,7 +169,7 @@ pub struct BugAbort; impl EmissionGuarantee for BugAbort { type EmitResult = !; - fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult { db.emit_producing_nothing(); panic::panic_any(ExplicitBug); } @@ -183,14 +183,14 @@ pub struct FatalAbort; impl EmissionGuarantee for FatalAbort { type EmitResult = !; - fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult { db.emit_producing_nothing(); crate::FatalError.raise() } } impl EmissionGuarantee for rustc_span::fatal_error::FatalError { - fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult { db.emit_producing_nothing(); rustc_span::fatal_error::FatalError } @@ -265,8 +265,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Emit and consume the diagnostic. #[track_caller] - pub fn emit(mut self) -> G::EmitResult { - G::emit_producing_guarantee(&mut self) + pub fn emit(self) -> G::EmitResult { + G::emit_producing_guarantee(self) } /// Emit the diagnostic unless `delay` is true, From 2d91c6d1bf900276de71a7bde89ffe9cffed59fa Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 8 Jan 2024 07:47:02 +1100 Subject: [PATCH 13/14] Remove `DiagnosticBuilderState`. Currently it's used for two dynamic checks: - When a diagnostic is emitted, has it been emitted before? - When a diagnostic is dropped, has it been emitted/cancelled? The first check is no longer need, because `emit` is consuming, so it's impossible to emit a `DiagnosticBuilder` twice. The second check is still needed. This commit replaces `DiagnosticBuilderState` with a simpler `Option>`, which is enough for the second check: functions like `emit` and `cancel` can take the `Diagnostic` and then `drop` can check that the `Diagnostic` was taken. The `DiagCtxt` reference from `DiagnosticBuilderState` is now stored as its own field, removing the need for the `dcx` method. As well as making the code shorter and simpler, the commit removes: - One (deprecated) `ErrorGuaranteed::unchecked_claim_error_was_emitted` call. - Two `FIXME(eddyb)` comments that are no longer relevant. - The use of a dummy `Diagnostic` in `into_diagnostic`. Nice! --- .../rustc_errors/src/diagnostic_builder.rs | 213 ++++++------------ compiler/rustc_errors/src/lib.rs | 1 + compiler/rustc_mir_transform/src/errors.rs | 3 +- 3 files changed, 74 insertions(+), 143 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index b81e37501e7e0..e72791d89a292 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -35,19 +35,28 @@ where } /// Used for emitting structured error messages and other diagnostic information. +/// Each constructed `DiagnosticBuilder` must be consumed by a function such as +/// `emit`, `cancel`, `delay_as_bug`, or `into_diagnostic`. A panic occurrs if a +/// `DiagnosticBuilder` is dropped without being consumed by one of these +/// functions. /// /// If there is some state in a downstream crate you would like to /// access in the methods of `DiagnosticBuilder` here, consider /// extending `DiagCtxtFlags`. #[must_use] pub struct DiagnosticBuilder<'a, G: EmissionGuarantee = ErrorGuaranteed> { - state: DiagnosticBuilderState<'a>, + pub dcx: &'a DiagCtxt, - /// `Diagnostic` is a large type, and `DiagnosticBuilder` is often used as a - /// return value, especially within the frequently-used `PResult` type. - /// In theory, return value optimization (RVO) should avoid unnecessary - /// copying. In practice, it does not (at the time of writing). - diagnostic: Box, + /// Why the `Option`? It is always `Some` until the `DiagnosticBuilder` is + /// consumed via `emit`, `cancel`, etc. At that point it is consumed and + /// replaced with `None`. Then `drop` checks that it is `None`; if not, it + /// panics because a diagnostic was built but not used. + /// + /// Why the Box? `Diagnostic` is a large type, and `DiagnosticBuilder` is + /// often used as a return value, especially within the frequently-used + /// `PResult` type. In theory, return value optimization (RVO) should avoid + /// unnecessary copying. In practice, it does not (at the time of writing). + diag: Option>, _marker: PhantomData, } @@ -56,32 +65,9 @@ pub struct DiagnosticBuilder<'a, G: EmissionGuarantee = ErrorGuaranteed> { // twice, which would be bad. impl !Clone for DiagnosticBuilder<'_, G> {} -#[derive(Clone)] -enum DiagnosticBuilderState<'a> { - /// Initial state of a `DiagnosticBuilder`, before `.emit()` or `.cancel()`. - /// - /// The `Diagnostic` will be emitted through this `DiagCtxt`. - Emittable(&'a DiagCtxt), - - /// State of a `DiagnosticBuilder`, after `.emit()` or *during* `.cancel()`. - /// - /// The `Diagnostic` will be ignored when calling `.emit()`, and it can be - /// assumed that `.emit()` was previously called, to end up in this state. - /// - /// While this is also used by `.cancel()`, this state is only observed by - /// the `Drop` `impl` of `DiagnosticBuilder`, because `.cancel()` takes - /// `self` by-value specifically to prevent any attempts to `.emit()`. - /// - // FIXME(eddyb) currently this doesn't prevent extending the `Diagnostic`, - // despite that being potentially lossy, if important information is added - // *after* the original `.emit()` call. - AlreadyEmittedOrDuringCancellation, -} - -// `DiagnosticBuilderState` should be pointer-sized. rustc_data_structures::static_assert_size!( - DiagnosticBuilderState<'_>, - std::mem::size_of::<&DiagCtxt>() + DiagnosticBuilder<'_, ()>, + 2 * std::mem::size_of::() ); /// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee" @@ -99,62 +85,44 @@ pub trait EmissionGuarantee: Sized { } impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { + /// Takes the diagnostic. For use by methods that consume the + /// DiagnosticBuilder: `emit`, `cancel`, etc. Afterwards, `drop` is the + /// only code that will be run on `self`. + fn take_diag(&mut self) -> Diagnostic { + Box::into_inner(self.diag.take().unwrap()) + } + /// Most `emit_producing_guarantee` functions use this as a starting point. fn emit_producing_nothing(mut self) { - match self.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - dcx.emit_diagnostic_without_consuming(&mut self.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } + let diag = self.take_diag(); + self.dcx.emit_diagnostic(diag); + } + + /// `ErrorGuaranteed::emit_producing_guarantee` uses this. + // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. + fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed { + let diag = self.take_diag(); + + // Only allow a guarantee if the `level` wasn't switched to a + // non-error. The field isn't `pub`, but the whole `Diagnostic` can be + // overwritten with a new one, thanks to `DerefMut`. + assert!( + diag.is_error(), + "emitted non-error ({:?}) diagnostic from `DiagnosticBuilder`", + diag.level, + ); + + let guar = self.dcx.emit_diagnostic(diag); + guar.unwrap() } } -// FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. impl EmissionGuarantee for ErrorGuaranteed { - fn emit_producing_guarantee(mut db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult { - // Contrast this with `emit_producing_nothing`. - match db.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - let guar = dcx.emit_diagnostic_without_consuming(&mut db.diagnostic); - - // Only allow a guarantee if the `level` wasn't switched to a - // non-error - the field isn't `pub`, but the whole `Diagnostic` - // can be overwritten with a new one, thanks to `DerefMut`. - assert!( - db.diagnostic.is_error(), - "emitted non-error ({:?}) diagnostic \ - from `DiagnosticBuilder`", - db.diagnostic.level, - ); - guar.unwrap() - } - // `.emit()` was previously called, disallowed from repeating it, - // but can take advantage of the previous `.emit()`'s guarantee - // still being applicable (i.e. as a form of idempotency). - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => { - // Only allow a guarantee if the `level` wasn't switched to a - // non-error - the field isn't `pub`, but the whole `Diagnostic` - // can be overwritten with a new one, thanks to `DerefMut`. - assert!( - db.diagnostic.is_error(), - "`DiagnosticBuilder`'s diagnostic \ - became non-error ({:?}), after original `.emit()`", - db.diagnostic.level, - ); - #[allow(deprecated)] - ErrorGuaranteed::unchecked_claim_error_was_emitted() - } - } + fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + db.emit_producing_error_guaranteed() } } -// FIXME(eddyb) should there be a `Option` impl as well? impl EmissionGuarantee for () { fn emit_producing_guarantee(db: DiagnosticBuilder<'_, Self>) -> Self::EmitResult { db.emit_producing_nothing(); @@ -219,12 +187,12 @@ macro_rules! forward { ) => { #[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")] pub fn $n(&mut self, $($name: $ty),*) -> &mut Self { - self.diagnostic.$n($($name),*); + self.diag.as_mut().unwrap().$n($($name),*); self } #[doc = concat!("See [`Diagnostic::", stringify!($n), "()`].")] pub fn $n_mv(mut self, $($name: $ty),*) -> Self { - self.diagnostic.$n($($name),*); + self.diag.as_mut().unwrap().$n($($name),*); self } }; @@ -234,13 +202,13 @@ impl Deref for DiagnosticBuilder<'_, G> { type Target = Diagnostic; fn deref(&self) -> &Diagnostic { - &self.diagnostic + self.diag.as_ref().unwrap() } } impl DerefMut for DiagnosticBuilder<'_, G> { fn deref_mut(&mut self) -> &mut Diagnostic { - &mut self.diagnostic + self.diag.as_mut().unwrap() } } @@ -254,13 +222,9 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// Creates a new `DiagnosticBuilder` with an already constructed /// diagnostic. #[track_caller] - pub(crate) fn new_diagnostic(dcx: &'a DiagCtxt, diagnostic: Diagnostic) -> Self { + pub(crate) fn new_diagnostic(dcx: &'a DiagCtxt, diag: Diagnostic) -> Self { debug!("Created new diagnostic"); - Self { - state: DiagnosticBuilderState::Emittable(dcx), - diagnostic: Box::new(diagnostic), - _marker: PhantomData, - } + Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData } } /// Emit and consume the diagnostic. @@ -281,14 +245,10 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { self.emit() } - /// Cancel the diagnostic (a structured diagnostic must either be emitted or + /// Cancel and consume the diagnostic. (A diagnostic must either be emitted or /// cancelled or it will panic when dropped). - /// - /// This method takes `self` by-value to disallow calling `.emit()` on it, - /// which may be expected to *guarantee* the emission of an error, either - /// at the time of the call, or through a prior `.emit()` call. pub fn cancel(mut self) { - self.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + self.diag = None; drop(self); } @@ -304,44 +264,21 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { } /// Converts the builder to a `Diagnostic` for later emission, - /// unless dcx has disabled such buffering, or `.emit()` was called. + /// unless dcx has disabled such buffering. pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> { - let dcx = match self.state { - // No `.emit()` calls, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => dcx, - // `.emit()` was previously called, nothing we can do. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => { - return None; - } - }; - - if dcx.inner.lock().flags.dont_buffer_diagnostics - || dcx.inner.lock().flags.treat_err_as_bug.is_some() - { + let flags = self.dcx.inner.lock().flags; + if flags.dont_buffer_diagnostics || flags.treat_err_as_bug.is_some() { self.emit(); return None; } - // Take the `Diagnostic` by replacing it with a dummy. - let dummy = Diagnostic::new(Level::Allow, DiagnosticMessage::from("")); - let diagnostic = std::mem::replace(&mut *self.diagnostic, dummy); - - // Disable the ICE on `Drop`. - self.cancel(); + let diag = self.take_diag(); // Logging here is useful to help track down where in logs an error was // actually emitted. - debug!("buffer: diagnostic={:?}", diagnostic); + debug!("buffer: diag={:?}", diag); - Some((diagnostic, dcx)) - } - - /// Retrieves the [`DiagCtxt`] if available - pub fn dcx(&self) -> Option<&DiagCtxt> { - match self.state { - DiagnosticBuilderState::Emittable(dcx) => Some(dcx), - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => None, - } + Some((diag, self.dcx)) } /// Buffers the diagnostic for later emission, @@ -494,30 +431,24 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { impl Debug for DiagnosticBuilder<'_, G> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.diagnostic.fmt(f) + self.diag.fmt(f) } } -/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled -/// or we emit a bug. +/// Destructor bomb: every `DiagnosticBuilder` must be consumed (emitted, +/// cancelled, etc.) or we emit a bug. impl Drop for DiagnosticBuilder<'_, G> { fn drop(&mut self) { - match self.state { - // No `.emit()` or `.cancel()` calls. - DiagnosticBuilderState::Emittable(dcx) => { - if !panicking() { - dcx.emit_diagnostic(Diagnostic::new( - Level::Bug, - DiagnosticMessage::from( - "the following error was constructed but not emitted", - ), - )); - dcx.emit_diagnostic_without_consuming(&mut self.diagnostic); - panic!("error was constructed but not emitted"); - } + match self.diag.take() { + Some(diag) if !panicking() => { + self.dcx.emit_diagnostic(Diagnostic::new( + Level::Bug, + DiagnosticMessage::from("the following error was constructed but not emitted"), + )); + self.dcx.emit_diagnostic(*diag); + panic!("error was constructed but not emitted"); } - // `.emit()` was previously called, or maybe we're during `.cancel()`. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + _ => {} } } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 4710722c77157..8411e188189d0 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -7,6 +7,7 @@ #![feature(rustdoc_internals)] #![feature(array_windows)] #![feature(associated_type_defaults)] +#![feature(box_into_inner)] #![feature(extract_if)] #![feature(if_let_guard)] #![feature(let_chains)] diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index bde442049b1d3..446f13feff089 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -181,8 +181,7 @@ pub(crate) struct UnsafeOpInUnsafeFn { impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn { #[track_caller] fn decorate_lint<'b>(self, diag: &'b mut DiagnosticBuilder<'a, ()>) { - let dcx = diag.dcx().expect("lint should not yet be emitted"); - let desc = dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); + let desc = diag.dcx.eagerly_translate_to_string(self.details.label(), [].into_iter()); diag.arg("details", desc); diag.span_label(self.details.span, self.details.label()); self.details.add_subdiagnostics(diag); From db09eb2d3accf8909ea2813ebb00c58c7f2fad64 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 8 Jan 2024 08:27:38 +1100 Subject: [PATCH 14/14] Remove `{DiagCtxt,DiagCtxtInner}::emit_diagnostic_without_consuming`. They are no longer used, because `{DiagCtxt,DiagCtxtInner}::emit_diagnostic` are used everywhere instead. This also means `track_diagnostic` can become consuming. --- compiler/rustc_errors/src/lib.rs | 30 ++++++----------------- compiler/rustc_interface/src/callbacks.rs | 2 +- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 8411e188189d0..b97ec02675a60 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -509,11 +509,11 @@ pub enum StashKey { Cycle, } -fn default_track_diagnostic(d: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) { - (*f)(d) +fn default_track_diagnostic(diag: Diagnostic, f: &mut dyn FnMut(Diagnostic)) { + (*f)(diag) } -pub static TRACK_DIAGNOSTICS: AtomicRef = +pub static TRACK_DIAGNOSTICS: AtomicRef = AtomicRef::new(&(default_track_diagnostic as _)); #[derive(Copy, Clone, Default)] @@ -1074,17 +1074,8 @@ impl DiagCtxt { self.inner.borrow_mut().emitter.emit_diagnostic(&db); } - pub fn emit_diagnostic(&self, mut diagnostic: Diagnostic) -> Option { - self.emit_diagnostic_without_consuming(&mut diagnostic) - } - - // It's unfortunate this exists. `emit_diagnostic` is preferred, because it - // consumes the diagnostic, thus ensuring it is emitted just once. - pub(crate) fn emit_diagnostic_without_consuming( - &self, - diagnostic: &mut Diagnostic, - ) -> Option { - self.inner.borrow_mut().emit_diagnostic_without_consuming(diagnostic) + pub fn emit_diagnostic(&self, diagnostic: Diagnostic) -> Option { + self.inner.borrow_mut().emit_diagnostic(diagnostic) } #[track_caller] @@ -1273,13 +1264,6 @@ impl DiagCtxtInner { } fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option { - self.emit_diagnostic_without_consuming(&mut diagnostic) - } - - fn emit_diagnostic_without_consuming( - &mut self, - diagnostic: &mut Diagnostic, - ) -> Option { if matches!(diagnostic.level, Error | Fatal) && self.treat_err_as_bug() { diagnostic.level = Bug; } @@ -1335,7 +1319,7 @@ impl DiagCtxtInner { } let mut guaranteed = None; - (*TRACK_DIAGNOSTICS)(diagnostic, &mut |diagnostic| { + (*TRACK_DIAGNOSTICS)(diagnostic, &mut |mut diagnostic| { if let Some(ref code) = diagnostic.code { self.emitted_diagnostic_codes.insert(code.clone()); } @@ -1371,7 +1355,7 @@ impl DiagCtxtInner { ); } - self.emitter.emit_diagnostic(diagnostic); + self.emitter.emit_diagnostic(&diagnostic); if diagnostic.is_error() { self.deduplicated_err_count += 1; } else if let Warning(_) = diagnostic.level { diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index ef00ced67ffea..7458be2c86da7 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -29,7 +29,7 @@ fn track_span_parent(def_id: rustc_span::def_id::LocalDefId) { /// This is a callback from `rustc_errors` as it cannot access the implicit state /// in `rustc_middle` otherwise. It is used when diagnostic messages are /// emitted and stores them in the current query, if there is one. -fn track_diagnostic(diagnostic: &mut Diagnostic, f: &mut dyn FnMut(&mut Diagnostic)) { +fn track_diagnostic(diagnostic: Diagnostic, f: &mut dyn FnMut(Diagnostic)) { tls::with_context_opt(|icx| { if let Some(icx) = icx { if let Some(diagnostics) = icx.diagnostics {