From cea683c08f775f980e5e8de408ea3b47235329c7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Dec 2023 14:00:17 +1100 Subject: [PATCH 01/10] Use `.into_diagnostic()` less. This commit replaces this pattern: ``` err.into_diagnostic(dcx) ``` with this pattern: ``` dcx.create_err(err) ``` in a lot of places. It's a little shorter, makes the error level explicit, avoids some `IntoDiagnostic` imports, and is a necessary prerequisite for the next commit which will add a `level` arg to `into_diagnostic`. This requires adding `track_caller` on `create_err` to avoid mucking up the output of `tests/ui/track-diagnostics/track4.rs`. It probably should have been there already. --- compiler/rustc_errors/src/lib.rs | 1 + compiler/rustc_expand/src/base.rs | 5 +- .../infer/error_reporting/need_type_info.rs | 31 ++++----- .../src/infer/error_reporting/note.rs | 36 +++++----- compiler/rustc_parse/src/parser/attr.rs | 7 +- .../rustc_parse/src/parser/diagnostics.rs | 22 +++---- compiler/rustc_parse/src/parser/expr.rs | 66 ++++++++++--------- compiler/rustc_parse/src/parser/item.rs | 16 ++--- compiler/rustc_parse/src/parser/mod.rs | 9 +-- .../rustc_parse/src/parser/nonterminal.rs | 22 +++---- compiler/rustc_parse/src/parser/pat.rs | 11 ++-- compiler/rustc_parse/src/parser/path.rs | 7 +- compiler/rustc_query_system/src/query/job.rs | 6 +- 13 files changed, 109 insertions(+), 130 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 959e26fec70..763de78451e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1274,6 +1274,7 @@ impl DiagCtxt { self.create_err(err).emit() } + #[track_caller] pub fn create_err<'a>( &'a self, err: impl IntoDiagnostic<'a>, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index b63609c48e9..5aeb5e61cd7 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1204,11 +1204,10 @@ pub fn resolve_path( .expect("attempting to resolve a file path in an external file"), FileName::DocTest(path, _) => path, other => { - return Err(errors::ResolveRelativePath { + return Err(parse_sess.dcx.create_err(errors::ResolveRelativePath { span, path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(), - } - .into_diagnostic(&parse_sess.dcx)); + })); } }; result.pop(); diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 817a4451dd1..700fb5d3510 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -5,7 +5,6 @@ use crate::errors::{ use crate::infer::error_reporting::TypeErrCtxt; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::InferCtxt; -use rustc_errors::IntoDiagnostic; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_hir as hir; use rustc_hir::def::Res; @@ -367,7 +366,7 @@ impl<'tcx> InferCtxt<'tcx> { let multi_suggestions = Vec::new(); let bad_label = Some(arg_data.make_bad_error(span)); match error_code { - TypeAnnotationNeeded::E0282 => AnnotationRequired { + TypeAnnotationNeeded::E0282 => self.tcx.sess.dcx().create_err(AnnotationRequired { span, source_kind, source_name, @@ -375,9 +374,8 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0283 => AmbiguousImpl { + }), + TypeAnnotationNeeded::E0283 => self.tcx.sess.dcx().create_err(AmbiguousImpl { span, source_kind, source_name, @@ -385,9 +383,8 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0284 => AmbiguousReturn { + }), + TypeAnnotationNeeded::E0284 => self.tcx.sess.dcx().create_err(AmbiguousReturn { span, source_kind, source_name, @@ -395,8 +392,7 @@ impl<'tcx> InferCtxt<'tcx> { infer_subdiags, multi_suggestions, bad_label, - } - .into_diagnostic(self.tcx.sess.dcx()), + }), } } } @@ -574,7 +570,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } match error_code { - TypeAnnotationNeeded::E0282 => AnnotationRequired { + TypeAnnotationNeeded::E0282 => self.tcx.sess.dcx().create_err(AnnotationRequired { span, source_kind, source_name: &name, @@ -582,9 +578,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0283 => AmbiguousImpl { + }), + TypeAnnotationNeeded::E0283 => self.tcx.sess.dcx().create_err(AmbiguousImpl { span, source_kind, source_name: &name, @@ -592,9 +587,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - } - .into_diagnostic(self.tcx.sess.dcx()), - TypeAnnotationNeeded::E0284 => AmbiguousReturn { + }), + TypeAnnotationNeeded::E0284 => self.tcx.sess.dcx().create_err(AmbiguousReturn { span, source_kind, source_name: &name, @@ -602,8 +596,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer_subdiags, multi_suggestions, bad_label: None, - } - .into_diagnostic(self.tcx.sess.dcx()), + }), } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 859c10ef142..1f1c2bc20e2 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -5,9 +5,7 @@ use crate::errors::{ use crate::fluent_generated as fluent; use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt}; use crate::infer::{self, SubregionOrigin}; -use rustc_errors::{ - AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, -}; +use rustc_errors::{AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; @@ -136,11 +134,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::ContentValidFor, note_and_explain::SuffixKind::Empty, ); - OutlivesContent { + self.tcx.sess.dcx().create_err(OutlivesContent { span, notes: reference_valid.into_iter().chain(content_valid).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::RelateObjectBound(span) => { let object_valid = note_and_explain::RegionExplanation::new( @@ -157,11 +154,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::SourcePointerValidFor, note_and_explain::SuffixKind::Empty, ); - OutlivesBound { + self.tcx.sess.dcx().create_err(OutlivesBound { span, notes: object_valid.into_iter().chain(pointer_valid).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::RelateParamBound(span, ty, opt_span) => { let prefix = match *sub { @@ -176,8 +172,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let note = note_and_explain::RegionExplanation::new( self.tcx, sub, opt_span, prefix, suffix, ); - FulfillReqLifetime { span, ty: self.resolve_vars_if_possible(ty), note } - .into_diagnostic(self.tcx.sess.dcx()) + self.tcx.sess.dcx().create_err(FulfillReqLifetime { + span, + ty: self.resolve_vars_if_possible(ty), + note, + }) } infer::RelateRegionParamBound(span) => { let param_instantiated = note_and_explain::RegionExplanation::new( @@ -194,11 +193,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::LfParamMustOutlive, note_and_explain::SuffixKind::Empty, ); - LfBoundNotSatisfied { + self.tcx.sess.dcx().create_err(LfBoundNotSatisfied { span, notes: param_instantiated.into_iter().chain(param_must_outlive).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::ReferenceOutlivesReferent(ty, span) => { let pointer_valid = note_and_explain::RegionExplanation::new( @@ -215,12 +213,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::DataValidFor, note_and_explain::SuffixKind::Empty, ); - RefLongerThanData { + self.tcx.sess.dcx().create_err(RefLongerThanData { span, ty: self.resolve_vars_if_possible(ty), notes: pointer_valid.into_iter().chain(data_valid).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => { let mut err = self.report_extra_impl_obligation( @@ -277,11 +274,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { note_and_explain::PrefixKind::LfMustOutlive, note_and_explain::SuffixKind::Empty, ); - LfBoundNotSatisfied { + self.tcx.sess.dcx().create_err(LfBoundNotSatisfied { span, notes: instantiated.into_iter().chain(must_outlive).collect(), - } - .into_diagnostic(self.tcx.sess.dcx()) + }) } }; if sub.is_error() || sup.is_error() { diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index 56e52baf98b..53b29eccc2c 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -5,7 +5,7 @@ use super::{AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle use rustc_ast as ast; use rustc_ast::attr; use rustc_ast::token::{self, Delimiter, Nonterminal}; -use rustc_errors::{error_code, Diagnostic, IntoDiagnostic, PResult}; +use rustc_errors::{error_code, Diagnostic, PResult}; use rustc_span::{sym, BytePos, Span}; use thin_vec::ThinVec; use tracing::debug; @@ -416,8 +416,9 @@ impl<'a> Parser<'a> { Err(err) => err.cancel(), } - Err(InvalidMetaItem { span: self.token.span, token: self.token.clone() } - .into_diagnostic(self.dcx())) + Err(self + .dcx() + .create_err(InvalidMetaItem { span: self.token.span, token: self.token.clone() })) } } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 9e3637ea9f3..fb31815c302 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, - DiagnosticMessage, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan, PResult, + DiagnosticMessage, ErrorGuaranteed, FatalError, MultiSpan, PResult, }; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; @@ -280,11 +280,10 @@ impl<'a> Parser<'a> { recover: bool, ) -> PResult<'a, (Ident, /* is_raw */ bool)> { if let TokenKind::DocComment(..) = self.prev_token.kind { - return Err(DocCommentDoesNotDocumentAnything { + return Err(self.dcx().create_err(DocCommentDoesNotDocumentAnything { span: self.prev_token.span, missing_comma: None, - } - .into_diagnostic(self.dcx())); + })); } let valid_follow = &[ @@ -347,7 +346,7 @@ impl<'a> Parser<'a> { suggest_remove_comma, help_cannot_start_number, }; - let mut err = err.into_diagnostic(self.dcx()); + let mut err = self.dcx().create_err(err); // if the token we have is a `<` // it *might* be a misplaced generic @@ -1410,7 +1409,7 @@ impl<'a> Parser<'a> { // Not entirely sure now, but we bubble the error up with the // suggestion. self.restore_snapshot(snapshot); - Err(err.into_diagnostic(self.dcx())) + Err(self.dcx().create_err(err)) } } } else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind { @@ -1425,7 +1424,7 @@ impl<'a> Parser<'a> { } // Consume the fn call arguments. match self.consume_fn_args() { - Err(()) => Err(err.into_diagnostic(self.dcx())), + Err(()) => Err(self.dcx().create_err(err)), Ok(()) => { self.sess.emit_err(err); // FIXME: actually check that the two expressions in the binop are @@ -1451,7 +1450,7 @@ impl<'a> Parser<'a> { mk_err_expr(self, inner_op.span.to(self.prev_token.span)) } else { // These cases cause too many knock-down errors, bail out (#61329). - Err(err.into_diagnostic(self.dcx())) + Err(self.dcx().create_err(err)) } }; } @@ -2539,7 +2538,7 @@ impl<'a> Parser<'a> { Ok(Some(GenericArg::Const(self.parse_const_arg()?))) } else { let after_kw_const = self.token.span; - self.recover_const_arg(after_kw_const, err.into_diagnostic(self.dcx())).map(Some) + self.recover_const_arg(after_kw_const, self.dcx().create_err(err)).map(Some) } } @@ -2893,11 +2892,10 @@ impl<'a> Parser<'a> { let (a_span, b_span) = (a.span(), b.span()); let between_span = a_span.shrink_to_hi().to(b_span.shrink_to_lo()); if self.span_to_snippet(between_span).as_deref() == Ok(":: ") { - return Err(DoubleColonInBound { + return Err(self.dcx().create_err(DoubleColonInBound { span: path.span.shrink_to_hi(), between: between_span, - } - .into_diagnostic(self.dcx())); + })); } } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index cd3e8b92f2f..a21a1533848 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -26,8 +26,8 @@ use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ - AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - PResult, StashKey, + AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult, + StashKey, }; use rustc_macros::Subdiagnostic; use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded}; @@ -1255,21 +1255,21 @@ impl<'a> Parser<'a> { // 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 = errors::ParenthesesWithStructFields { - span, - r#type: path, - braces_for_struct: errors::BracesForStructLiteral { - first: open_paren, - second: close_paren, - }, - no_fields_for_fn: errors::NoFieldsForFnCall { - fields: fields - .into_iter() - .map(|field| field.span.until(field.expr.span)) - .collect(), - }, - } - .into_diagnostic(self.dcx()); + let mut replacement_err = + self.dcx().create_err(errors::ParenthesesWithStructFields { + span, + r#type: path, + braces_for_struct: errors::BracesForStructLiteral { + first: open_paren, + second: close_paren, + }, + no_fields_for_fn: errors::NoFieldsForFnCall { + fields: fields + .into_iter() + .map(|field| field.span.until(field.expr.span)) + .collect(), + }, + }); replacement_err.emit(); let old_err = mem::replace(err, replacement_err); @@ -1883,8 +1883,7 @@ impl<'a> Parser<'a> { self.bump(); // `#` let Some((ident, false)) = self.token.ident() else { - let err = - errors::ExpectedBuiltinIdent { span: self.token.span }.into_diagnostic(self.dcx()); + let err = self.dcx().create_err(errors::ExpectedBuiltinIdent { span: self.token.span }); return Err(err); }; self.sess.gated_spans.gate(sym::builtin_syntax, ident.span); @@ -1894,8 +1893,10 @@ impl<'a> Parser<'a> { let ret = if let Some(res) = parse(self, lo, ident)? { Ok(res) } else { - let err = errors::UnknownBuiltinConstruct { span: lo.to(ident.span), name: ident.name } - .into_diagnostic(self.dcx()); + let err = self.dcx().create_err(errors::UnknownBuiltinConstruct { + span: lo.to(ident.span), + name: ident.name, + }); return Err(err); }; self.expect(&TokenKind::CloseDelim(Delimiter::Parenthesis))?; @@ -1958,8 +1959,9 @@ impl<'a> Parser<'a> { && let token::NtExpr(e) | token::NtLiteral(e) = &nt.0 && matches!(e.kind, ExprKind::Err) { - let mut err = errors::InvalidInterpolatedExpression { span: self.token.span } - .into_diagnostic(self.dcx()); + let mut err = self + .dcx() + .create_err(errors::InvalidInterpolatedExpression { span: self.token.span }); err.downgrade_to_delayed_bug(); return Err(err); } @@ -2168,10 +2170,10 @@ impl<'a> Parser<'a> { .span_to_snippet(snapshot.token.span) .is_ok_and(|snippet| snippet == "]") => { - return Err(errors::MissingSemicolonBeforeArray { + return Err(self.dcx().create_err(errors::MissingSemicolonBeforeArray { open_delim: open_delim_span, semicolon: prev_span.shrink_to_hi(), - }.into_diagnostic(self.dcx())); + })); } Ok(_) => (), Err(err) => err.cancel(), @@ -2318,8 +2320,9 @@ impl<'a> Parser<'a> { // Check for `move async` and recover if self.check_keyword(kw::Async) { let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); - Err(errors::AsyncMoveOrderIncorrect { span: move_async_span } - .into_diagnostic(self.dcx())) + Err(self + .dcx() + .create_err(errors::AsyncMoveOrderIncorrect { span: move_async_span })) } else { Ok(CaptureBy::Value { move_kw: move_kw_span }) } @@ -2509,7 +2512,7 @@ impl<'a> Parser<'a> { }; if self.prev_token.kind == token::BinOp(token::Or) { // This was part of a closure, the that part of the parser recover. - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); } else { Some(self.sess.emit_err(err)) } @@ -3193,7 +3196,7 @@ impl<'a> Parser<'a> { fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P> { let (attrs, body) = self.parse_inner_attrs_and_block()?; if self.eat_keyword(kw::Catch) { - Err(errors::CatchAfterTry { span: self.prev_token.span }.into_diagnostic(self.dcx())) + Err(self.dcx().create_err(errors::CatchAfterTry { span: self.prev_token.span })) } else { let span = span_lo.to(body.span); self.sess.gated_spans.gate(sym::try_blocks, span); @@ -3530,12 +3533,11 @@ impl<'a> Parser<'a> { || t == &token::CloseDelim(Delimiter::Parenthesis) }); if is_wrong { - return Err(errors::ExpectedStructField { + return Err(this.dcx().create_err(errors::ExpectedStructField { span: this.look_ahead(1, |t| t.span), ident_span: this.token.span, token: this.look_ahead(1, |t| t.clone()), - } - .into_diagnostic(&self.sess.dcx)); + })); } let (ident, expr) = if is_shorthand { // Mimic `x: x` for the `x` field shorthand. diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index bf619daba50..32c5bef7c8e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -10,10 +10,7 @@ use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; use rustc_ast::{self as ast}; use rustc_ast_pretty::pprust; -use rustc_errors::{ - struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult, - StashKey, -}; +use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; use rustc_span::edit_distance::edit_distance; use rustc_span::edition::Edition; use rustc_span::source_map; @@ -438,7 +435,7 @@ impl<'a> Parser<'a> { None }; - if let Some(err) = err { Err(err.into_diagnostic(self.dcx())) } else { Ok(()) } + if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) } } fn parse_item_builtin(&mut self) -> PResult<'a, Option> { @@ -1373,8 +1370,7 @@ impl<'a> Parser<'a> { }; let span = self.prev_token.span.shrink_to_hi(); - let err: DiagnosticBuilder<'_, ErrorGuaranteed> = - errors::MissingConstType { span, colon, kind }.into_diagnostic(self.dcx()); + let err = self.dcx().create_err(errors::MissingConstType { span, colon, kind }); err.stash(span, StashKey::ItemNoType); // The user intended that the type be inferred, @@ -1391,7 +1387,7 @@ impl<'a> Parser<'a> { self.bump(); self.sess.emit_err(err); } else { - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); } } @@ -1591,7 +1587,7 @@ impl<'a> Parser<'a> { } else { let err = errors::UnexpectedTokenAfterStructName::new(self.token.span, self.token.clone()); - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); }; Ok((class_name, ItemKind::Struct(vdata, generics))) @@ -1787,7 +1783,7 @@ impl<'a> Parser<'a> { let sp = previous_span.shrink_to_hi(); err.missing_comma = Some(sp); } - return Err(err.into_diagnostic(self.dcx())); + return Err(self.dcx().create_err(err)); } } _ => { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b91432f10c8..0ab2adb404a 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -32,9 +32,7 @@ use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_errors::PResult; -use rustc_errors::{ - Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan, -}; +use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, MultiSpan}; use rustc_session::parse::ParseSess; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -1500,14 +1498,13 @@ pub(crate) fn make_unclosed_delims_error( if let Some(sp) = unmatched.unclosed_span { spans.push(sp); }; - let err = MismatchedClosingDelimiter { + let err = sess.dcx.create_err(MismatchedClosingDelimiter { spans, delimiter: pprust::token_kind_to_string(&token::CloseDelim(found_delim)).to_string(), unmatched: unmatched.found_span, opening_candidate: unmatched.candidate_span, unclosed: unmatched.unclosed_span, - } - .into_diagnostic(&sess.dcx); + }); Some(err) } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 301a88cd077..071d6b72f3b 100644 --- a/compiler/rustc_parse/src/parser/nonterminal.rs +++ b/compiler/rustc_parse/src/parser/nonterminal.rs @@ -2,7 +2,6 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token}; use rustc_ast::HasTokens; use rustc_ast_pretty::pprust; -use rustc_errors::IntoDiagnostic; use rustc_errors::PResult; use rustc_span::symbol::{kw, Ident}; @@ -114,9 +113,9 @@ impl<'a> Parser<'a> { NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? { Some(item) => NtItem(item), None => { - return Err( - UnexpectedNonterminal::Item(self.token.span).into_diagnostic(self.dcx()) - ); + return Err(self + .dcx() + .create_err(UnexpectedNonterminal::Item(self.token.span))); } }, NonterminalKind::Block => { @@ -127,8 +126,9 @@ impl<'a> Parser<'a> { NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? { Some(s) => NtStmt(P(s)), None => { - return Err(UnexpectedNonterminal::Statement(self.token.span) - .into_diagnostic(self.dcx())); + return Err(self + .dcx() + .create_err(UnexpectedNonterminal::Statement(self.token.span))); } }, NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { @@ -160,11 +160,10 @@ impl<'a> Parser<'a> { NtIdent(ident, is_raw) } NonterminalKind::Ident => { - return Err(UnexpectedNonterminal::Ident { + return Err(self.dcx().create_err(UnexpectedNonterminal::Ident { span: self.token.span, token: self.token.clone(), - } - .into_diagnostic(self.dcx())); + })); } NonterminalKind::Path => { NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?)) @@ -178,11 +177,10 @@ impl<'a> Parser<'a> { if self.check_lifetime() { NtLifetime(self.expect_lifetime().ident) } else { - return Err(UnexpectedNonterminal::Lifetime { + return Err(self.dcx().create_err(UnexpectedNonterminal::Lifetime { span: self.token.span, token: self.token.clone(), - } - .into_diagnostic(self.dcx())); + })); } } }; diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 80233eddb9b..d32582fd43d 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -18,7 +18,7 @@ use rustc_ast::{ PatField, PatKind, Path, QSelf, RangeEnd, RangeSyntax, }; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult}; +use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; @@ -872,8 +872,9 @@ impl<'a> Parser<'a> { // binding mode then we do not end up here, because the lookahead // will direct us over to `parse_enum_variant()`. if self.token == token::OpenDelim(Delimiter::Parenthesis) { - return Err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span } - .into_diagnostic(self.dcx())); + return Err(self + .dcx() + .create_err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span })); } Ok(PatKind::Ident(binding_annotation, ident, sub)) @@ -986,8 +987,8 @@ impl<'a> Parser<'a> { // check that a comma comes after every field if !ate_comma { - let mut err = ExpectedCommaAfterPatternField { span: self.token.span } - .into_diagnostic(self.dcx()); + let mut err = + self.dcx().create_err(ExpectedCommaAfterPatternField { span: self.token.span }); if let Some(mut delayed) = delayed_err { delayed.emit(); } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 3b92a911983..8970a99f1b7 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -9,7 +9,7 @@ use rustc_ast::{ AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs, Path, PathSegment, QSelf, }; -use rustc_errors::{Applicability, IntoDiagnostic, PResult}; +use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span}; use std::mem; @@ -318,15 +318,14 @@ impl<'a> Parser<'a> { }) { err.cancel(); - err = PathSingleColon { + err = self.dcx().create_err(PathSingleColon { span: self.token.span, type_ascription: self .sess .unstable_features .is_nightly_build() .then_some(()), - } - .into_diagnostic(self.dcx()); + }); } // Attempt to find places where a missing `>` might belong. else if let Some(arg) = args diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 2a34ffb75f2..0561fd147a9 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -4,9 +4,7 @@ use crate::query::plumbing::CycleError; use crate::query::DepKind; use crate::query::{QueryContext, QueryStackFrame}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{ - DiagCtxt, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, Level, -}; +use rustc_errors::{DiagCtxt, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, Level}; use rustc_hir::def::DefKind; use rustc_session::Session; use rustc_span::Span; @@ -604,7 +602,7 @@ pub(crate) fn report_cycle<'a>( note_span: (), }; - cycle_diag.into_diagnostic(sess.dcx()) + sess.dcx().create_err(cycle_diag) } pub fn print_query_stack( From 18251c480b37c96db2d93ce79c138754d4e28904 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 19 Dec 2023 08:11:25 +1100 Subject: [PATCH 02/10] Remove unnecessary `use` items in derived `IntoDiagnostic` impls. Presumably these are a hangover from an earlier time when they were necessary. --- compiler/rustc_macros/src/diagnostics/diagnostic.rs | 2 -- compiler/rustc_macros/src/diagnostics/subdiagnostic.rs | 1 - 2 files changed, 3 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 5de0203fc1d..76ef2c264a8 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -92,7 +92,6 @@ impl<'a> DiagnosticDerive<'a> { self, #dcx: &'_sess rustc_errors::DiagCtxt ) -> rustc_errors::DiagnosticBuilder<'_sess, G> { - use rustc_errors::IntoDiagnosticArg; #implementation } } @@ -177,7 +176,6 @@ impl<'a> LintDiagnosticDerive<'a> { self, #diag: &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()> ) { - use rustc_errors::IntoDiagnosticArg; #implementation; } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 0f9e68cdc50..663abecb67c 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -94,7 +94,6 @@ impl SubdiagnosticDeriveBuilder { rustc_errors::SubdiagnosticMessage ) -> rustc_errors::SubdiagnosticMessage, { - use rustc_errors::{Applicability, IntoDiagnosticArg}; #implementation } } From 31df50c8973aeb70fcf42b403239f4fc4712988c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 19 Dec 2023 08:27:37 +1100 Subject: [PATCH 03/10] Streamline `Diagnostic` proc macro. First, it is parameterized by the name of the diagnostic and the DiagCtxt. These are given to `session_diagnostic_derive` and `lint_diagnostic_derive`. But the names are hard-wired as "diag" and "handler" (should be "dcx"), and there's no clear reason for the parameterization. So this commit removes the parameterization and hard-wires the names internally. Once that is done `DiagnosticDeriveBuilder` is reduced to a trivial wrapper around `DiagnosticDeriveKind`, and can be removed. Also, `DiagnosticDerive` and `LintDiagnosticDerive` don't need the `builder` field, because it has been reduced to a kind, and they know their own kind. This avoids the need for some `let`/`else`/`unreachable!` kind checks And `DiagnosticDeriveVariantBuilder` no longer needs a lifetime, because the `parent` field is changed to `kind`, which is now a trivial copy type. --- .../src/diagnostics/diagnostic.rs | 53 +++++--------- .../src/diagnostics/diagnostic_builder.rs | 70 +++++++------------ compiler/rustc_macros/src/diagnostics/mod.rs | 5 +- 3 files changed, 45 insertions(+), 83 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 76ef2c264a8..be8582d0ba0 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; -use crate::diagnostics::diagnostic_builder::{DiagnosticDeriveBuilder, DiagnosticDeriveKind}; +use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind; use crate::diagnostics::error::{span_err, DiagnosticDeriveError}; use crate::diagnostics::utils::SetOnce; use proc_macro2::TokenStream; @@ -13,32 +13,21 @@ use synstructure::Structure; /// The central struct for constructing the `into_diagnostic` method from an annotated struct. pub(crate) struct DiagnosticDerive<'a> { structure: Structure<'a>, - builder: DiagnosticDeriveBuilder, } impl<'a> DiagnosticDerive<'a> { - pub(crate) fn new(diag: syn::Ident, dcx: syn::Ident, structure: Structure<'a>) -> Self { - Self { - builder: DiagnosticDeriveBuilder { - diag, - kind: DiagnosticDeriveKind::Diagnostic { dcx }, - }, - structure, - } + pub(crate) fn new(structure: Structure<'a>) -> Self { + Self { structure } } pub(crate) fn into_tokens(self) -> TokenStream { - let DiagnosticDerive { mut structure, mut builder } = self; - + let DiagnosticDerive { mut structure } = self; + let kind = DiagnosticDeriveKind::Diagnostic; let slugs = RefCell::new(Vec::new()); - let implementation = builder.each_variant(&mut structure, |mut builder, variant| { + let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); - let diag = &builder.parent.diag; - let DiagnosticDeriveKind::Diagnostic { dcx } = &builder.parent.kind else { - unreachable!() - }; let init = match builder.slug.value_ref() { None => { span_err(builder.span, "diagnostic slug not specified") @@ -62,7 +51,7 @@ impl<'a> DiagnosticDerive<'a> { Some(slug) => { slugs.borrow_mut().push(slug.clone()); quote! { - let mut #diag = #dcx.struct_diagnostic(crate::fluent_generated::#slug); + let mut diag = dcx.struct_diagnostic(crate::fluent_generated::#slug); } } }; @@ -73,12 +62,10 @@ impl<'a> DiagnosticDerive<'a> { #formatting_init #preamble #body - #diag + diag } }); - let DiagnosticDeriveKind::Diagnostic { dcx } = &builder.kind else { unreachable!() }; - // A lifetime of `'a` causes conflicts, but `_sess` is fine. let mut imp = structure.gen_impl(quote! { gen impl<'_sess, G> @@ -90,7 +77,7 @@ impl<'a> DiagnosticDerive<'a> { #[track_caller] fn into_diagnostic( self, - #dcx: &'_sess rustc_errors::DiagCtxt + dcx: &'_sess rustc_errors::DiagCtxt ) -> rustc_errors::DiagnosticBuilder<'_sess, G> { #implementation } @@ -106,36 +93,31 @@ impl<'a> DiagnosticDerive<'a> { /// The central struct for constructing the `decorate_lint` method from an annotated struct. pub(crate) struct LintDiagnosticDerive<'a> { structure: Structure<'a>, - builder: DiagnosticDeriveBuilder, } impl<'a> LintDiagnosticDerive<'a> { - pub(crate) fn new(diag: syn::Ident, structure: Structure<'a>) -> Self { - Self { - builder: DiagnosticDeriveBuilder { diag, kind: DiagnosticDeriveKind::LintDiagnostic }, - structure, - } + pub(crate) fn new(structure: Structure<'a>) -> Self { + Self { structure } } pub(crate) fn into_tokens(self) -> TokenStream { - let LintDiagnosticDerive { mut structure, mut builder } = self; - - let implementation = builder.each_variant(&mut structure, |mut builder, variant| { + let LintDiagnosticDerive { mut structure } = self; + let kind = DiagnosticDeriveKind::LintDiagnostic; + let implementation = kind.each_variant(&mut structure, |mut builder, variant| { let preamble = builder.preamble(variant); let body = builder.body(variant); - let diag = &builder.parent.diag; let formatting_init = &builder.formatting_init; quote! { #preamble #formatting_init #body - #diag + diag } }); let slugs = RefCell::new(Vec::new()); - let msg = builder.each_variant(&mut structure, |mut builder, variant| { + let msg = kind.each_variant(&mut structure, |mut builder, variant| { // Collect the slug by generating the preamble. let _ = builder.preamble(variant); @@ -168,13 +150,12 @@ impl<'a> LintDiagnosticDerive<'a> { } }); - let diag = &builder.diag; let mut imp = structure.gen_impl(quote! { gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self { #[track_caller] fn decorate_lint<'__b>( self, - #diag: &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()> + diag: &'__b mut rustc_errors::DiagnosticBuilder<'__a, ()> ) { #implementation; } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 511654d9949..f3e98d68b60 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -17,28 +17,18 @@ use synstructure::{BindingInfo, Structure, VariantInfo}; use super::utils::SubdiagnosticVariant; /// What kind of diagnostic is being derived - a fatal/error/warning or a lint? -#[derive(Clone, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq)] pub(crate) enum DiagnosticDeriveKind { - Diagnostic { dcx: syn::Ident }, + Diagnostic, LintDiagnostic, } -/// Tracks persistent information required for the entire type when building up individual calls to -/// diagnostic methods for generated diagnostic derives - both `Diagnostic` for -/// fatal/errors/warnings and `LintDiagnostic` for lints. -pub(crate) struct DiagnosticDeriveBuilder { - /// The identifier to use for the generated `DiagnosticBuilder` instance. - pub diag: syn::Ident, - /// Kind of diagnostic that should be derived. - pub kind: DiagnosticDeriveKind, -} - /// Tracks persistent information required for a specific variant when building up individual calls /// to diagnostic methods for generated diagnostic derives - both `Diagnostic` for /// fatal/errors/warnings and `LintDiagnostic` for lints. -pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> { - /// The parent builder for the entire type. - pub parent: &'parent DiagnosticDeriveBuilder, +pub(crate) struct DiagnosticDeriveVariantBuilder { + /// The kind for the entire type. + pub kind: DiagnosticDeriveKind, /// Initialization of format strings for code suggestions. pub formatting_init: TokenStream, @@ -59,19 +49,19 @@ pub(crate) struct DiagnosticDeriveVariantBuilder<'parent> { pub code: SpannedOption<()>, } -impl<'a> HasFieldMap for DiagnosticDeriveVariantBuilder<'a> { +impl HasFieldMap for DiagnosticDeriveVariantBuilder { fn get_field_binding(&self, field: &String) -> Option<&TokenStream> { self.field_map.get(field) } } -impl DiagnosticDeriveBuilder { +impl DiagnosticDeriveKind { /// Call `f` for the struct or for each variant of the enum, returning a `TokenStream` with the /// tokens from `f` wrapped in an `match` expression. Emits errors for use of derive on unions /// or attributes on the type itself when input is an enum. - pub(crate) fn each_variant<'s, F>(&mut self, structure: &mut Structure<'s>, f: F) -> TokenStream + pub(crate) fn each_variant<'s, F>(self, structure: &mut Structure<'s>, f: F) -> TokenStream where - F: for<'a, 'v> Fn(DiagnosticDeriveVariantBuilder<'a>, &VariantInfo<'v>) -> TokenStream, + F: for<'v> Fn(DiagnosticDeriveVariantBuilder, &VariantInfo<'v>) -> TokenStream, { let ast = structure.ast(); let span = ast.span().unwrap(); @@ -101,7 +91,7 @@ impl DiagnosticDeriveBuilder { _ => variant.ast().ident.span().unwrap(), }; let builder = DiagnosticDeriveVariantBuilder { - parent: self, + kind: self, span, field_map: build_field_mapping(variant), formatting_init: TokenStream::new(), @@ -119,7 +109,7 @@ impl DiagnosticDeriveBuilder { } } -impl<'a> DiagnosticDeriveVariantBuilder<'a> { +impl DiagnosticDeriveVariantBuilder { /// Generates calls to `code` and similar functions based on the attributes on the type or /// variant. pub(crate) fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream { @@ -184,8 +174,6 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { &mut self, attr: &Attribute, ) -> Result { - let diag = &self.parent.diag; - // Always allow documentation comments. if is_doc_comment(attr) { return Ok(quote! {}); @@ -223,7 +211,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { let code = nested.parse::()?; tokens.extend(quote! { - #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); + diag.code(rustc_errors::DiagnosticId::Error(#code.to_string())); }); } else { span_err(path.span().unwrap(), "unknown argument") @@ -257,8 +245,6 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { } fn generate_field_code(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { - let diag = &self.parent.diag; - let field = binding_info.ast(); let mut field_binding = binding_info.binding.clone(); field_binding.set_span(field.ty.span()); @@ -267,7 +253,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { let ident = format_ident!("{}", ident); // strip `r#` prefix, if present quote! { - #diag.set_arg( + diag.set_arg( stringify!(#ident), #field_binding ); @@ -322,8 +308,6 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { info: FieldInfo<'_>, binding: TokenStream, ) -> Result { - let diag = &self.parent.diag; - let ident = &attr.path().segments.last().unwrap().ident; let name = ident.to_string(); match (&attr.meta, name.as_str()) { @@ -331,12 +315,12 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { // `set_arg` call will not be generated. (Meta::Path(_), "skip_arg") => return Ok(quote! {}), (Meta::Path(_), "primary_span") => { - match self.parent.kind { - DiagnosticDeriveKind::Diagnostic { .. } => { + match self.kind { + DiagnosticDeriveKind::Diagnostic => { report_error_if_not_applied_to_span(attr, &info)?; return Ok(quote! { - #diag.set_span(#binding); + diag.set_span(#binding); }); } DiagnosticDeriveKind::LintDiagnostic => { @@ -348,13 +332,13 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { } (Meta::Path(_), "subdiagnostic") => { if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() { - let DiagnosticDeriveKind::Diagnostic { dcx } = &self.parent.kind else { + let DiagnosticDeriveKind::Diagnostic = self.kind else { // No eager translation for lints. - return Ok(quote! { #diag.subdiagnostic(#binding); }); + return Ok(quote! { diag.subdiagnostic(#binding); }); }; - return Ok(quote! { #diag.eager_subdiagnostic(#dcx, #binding); }); + return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); }); } else { - return Ok(quote! { #diag.subdiagnostic(#binding); }); + return Ok(quote! { diag.subdiagnostic(#binding); }); } } (Meta::List(meta_list), "subdiagnostic") => { @@ -376,15 +360,15 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { return Ok(quote! {}); } - let dcx = match &self.parent.kind { - DiagnosticDeriveKind::Diagnostic { dcx } => dcx, + match &self.kind { + DiagnosticDeriveKind::Diagnostic => {} DiagnosticDeriveKind::LintDiagnostic => { throw_invalid_attr!(attr, |diag| { diag.help("eager subdiagnostics are not supported on lints") }) } }; - return Ok(quote! { #diag.eager_subdiagnostic(#dcx, #binding); }); + return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); }); } _ => (), } @@ -442,7 +426,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { self.formatting_init.extend(code_init); Ok(quote! { - #diag.span_suggestions_with_style( + diag.span_suggestions_with_style( #span_field, crate::fluent_generated::#slug, #code_field, @@ -463,10 +447,9 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { kind: &Ident, fluent_attr_identifier: Path, ) -> TokenStream { - let diag = &self.parent.diag; let fn_name = format_ident!("span_{}", kind); quote! { - #diag.#fn_name( + diag.#fn_name( #field_binding, crate::fluent_generated::#fluent_attr_identifier ); @@ -476,9 +459,8 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> { /// Adds a subdiagnostic by generating a `diag.span_$kind` call with the current slug /// and `fluent_attr_identifier`. fn add_subdiagnostic(&self, kind: &Ident, fluent_attr_identifier: Path) -> TokenStream { - let diag = &self.parent.diag; quote! { - #diag.#kind(crate::fluent_generated::#fluent_attr_identifier); + diag.#kind(crate::fluent_generated::#fluent_attr_identifier); } } diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs index a536eb3b04e..d3a4e7ba7d1 100644 --- a/compiler/rustc_macros/src/diagnostics/mod.rs +++ b/compiler/rustc_macros/src/diagnostics/mod.rs @@ -6,7 +6,6 @@ mod utils; use diagnostic::{DiagnosticDerive, LintDiagnosticDerive}; use proc_macro2::TokenStream; -use quote::format_ident; use subdiagnostic::SubdiagnosticDeriveBuilder; use synstructure::Structure; @@ -57,7 +56,7 @@ use synstructure::Structure; /// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`: /// pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { - DiagnosticDerive::new(format_ident!("diag"), format_ident!("handler"), s).into_tokens() + DiagnosticDerive::new(s).into_tokens() } /// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct, @@ -103,7 +102,7 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream { /// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`: /// pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream { - LintDiagnosticDerive::new(format_ident!("diag"), s).into_tokens() + LintDiagnosticDerive::new(s).into_tokens() } /// Implements `#[derive(Subdiagnostic)]`, which allows for labels, notes, helps and From e7724a2e319f112ee6a97999976d8225b009456e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Dec 2023 14:12:39 +1100 Subject: [PATCH 04/10] Add `level` arg to `into_diagnostic`. And make all hand-written `IntoDiagnostic` impls generic, by using `DiagnosticBuilder::new(dcx, level, ...)` instead of e.g. `dcx.struct_err(...)`. This means the `create_*` functions are the source of the error level. This change will let us remove `struct_diagnostic`. Note: `#[rustc_lint_diagnostics]` is added to `DiagnosticBuilder::new`, it's necessary to pass diagnostics tests now that it's used in `into_diagnostic` functions. --- .../rustc_attr/src/session_diagnostics.rs | 27 +++--- compiler/rustc_builtin_macros/src/errors.rs | 20 ++-- compiler/rustc_codegen_gcc/src/errors.rs | 14 ++- compiler/rustc_codegen_llvm/src/errors.rs | 27 +++--- compiler/rustc_codegen_ssa/src/errors.rs | 95 ++++++++++--------- compiler/rustc_const_eval/src/errors.rs | 7 +- .../rustc_errors/src/diagnostic_builder.rs | 28 +++--- compiler/rustc_errors/src/diagnostic_impls.rs | 39 +++++--- compiler/rustc_errors/src/lib.rs | 12 +-- compiler/rustc_hir_analysis/src/errors.rs | 16 ++-- .../src/diagnostics/diagnostic.rs | 9 +- compiler/rustc_metadata/src/errors.rs | 31 +++--- compiler/rustc_middle/src/ty/layout.rs | 11 ++- compiler/rustc_mir_build/src/errors.rs | 17 ++-- compiler/rustc_mir_transform/src/errors.rs | 8 +- compiler/rustc_monomorphize/src/errors.rs | 13 +-- compiler/rustc_parse/src/errors.rs | 80 +++++++++------- compiler/rustc_passes/src/errors.rs | 74 ++++++--------- compiler/rustc_session/src/errors.rs | 12 ++- compiler/rustc_session/src/parse.rs | 10 +- compiler/rustc_symbol_mangling/src/errors.rs | 11 +-- compiler/rustc_trait_selection/src/errors.rs | 12 ++- .../ui-fulldeps/internal-lints/diagnostics.rs | 16 ++-- .../internal-lints/diagnostics.stderr | 6 +- 24 files changed, 307 insertions(+), 288 deletions(-) diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index ce8e04defb2..fd2b0866867 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -2,7 +2,8 @@ use std::num::IntErrorKind; use rustc_ast as ast; use rustc_errors::{ - error_code, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, + error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + Level, }; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -50,14 +51,12 @@ pub(crate) struct UnknownMetaItem<'a> { } // Manual implementation to be able to format `expected` items correctly. -impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { +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 = dcx.struct_span_err_with_code( - self.span, - fluent::attr_unknown_meta_item, - error_code!(E0541), - ); + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::attr_unknown_meta_item); + diag.set_span(self.span); + diag.code(error_code!(E0541)); diag.set_arg("item", self.item); diag.set_arg("expected", expected.join(", ")); diag.span_label(self.span, fluent::attr_label); @@ -200,10 +199,11 @@ pub(crate) struct UnsupportedLiteral { pub start_point_span: Span, } -impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, match self.reason { UnsupportedLiteralReason::Generic => fluent::attr_unsupported_literal_generic, UnsupportedLiteralReason::CfgString => fluent::attr_unsupported_literal_cfg_string, @@ -214,8 +214,9 @@ impl<'a> IntoDiagnostic<'a> for UnsupportedLiteral { fluent::attr_unsupported_literal_deprecated_kv_pair } }, - error_code!(E0565), ); + diag.set_span(self.span); + diag.code(error_code!(E0565)); if self.is_bytestr { diag.span_suggestion( self.start_point_span, diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 6ffeb401453..e07eb2e490b 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - AddToDiagnostic, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, - SingleLabelManySpans, + AddToDiagnostic, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, + MultiSpan, SingleLabelManySpans, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -446,14 +446,14 @@ pub(crate) struct EnvNotDefinedWithUserMessage { } // Hand-written implementation to support custom user messages. -impl<'a> IntoDiagnostic<'a> for EnvNotDefinedWithUserMessage { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage { #[track_caller] - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { #[expect( rustc::untranslatable_diagnostic, reason = "cannot translate user-provided messages" )] - let mut diag = dcx.struct_err(self.msg_from_user.to_string()); + let mut diag = DiagnosticBuilder::new(dcx, level, self.msg_from_user.to_string()); diag.set_span(self.span); diag } @@ -801,9 +801,13 @@ pub(crate) struct AsmClobberNoReg { pub(crate) clobbers: Vec, } -impl<'a> IntoDiagnostic<'a> for AsmClobberNoReg { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_err(crate::fluent_generated::builtin_macros_asm_clobber_no_reg); +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.set_span(self.spans.clone()); // eager translation as `span_labels` takes `AsRef` let lbl1 = dcx.eagerly_translate_to_string( diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index 766d90cf724..1b1ed0b411c 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -111,9 +111,13 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { #[help(codegen_gcc_missing_features)] pub(crate) struct MissingFeatures; -impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::codegen_gcc_target_feature_disable_or_enable); +impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, + fluent::codegen_gcc_target_feature_disable_or_enable + ); if let Some(span) = self.span { diag.set_span(span); }; diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 671a225259a..6b7e38a6cb1 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -4,9 +4,7 @@ use std::path::Path; use crate::fluent_generated as fluent; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_errors::{ - DiagCtxt, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, FatalError, IntoDiagnostic, -}; +use rustc_errors::{DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -101,13 +99,14 @@ pub(crate) struct DynamicLinkingWithLTO; pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); -impl IntoDiagnostic<'_, FatalError> for ParseTargetMachineConfig<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, FatalError> { - let diag: DiagnosticBuilder<'_, FatalError> = self.0.into_diagnostic(dcx); +impl IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let diag: DiagnosticBuilder<'_, G> = self.0.into_diagnostic(dcx, level); let (message, _) = diag.styled_message().first().expect("`LlvmError` with no message"); let message = dcx.eagerly_translate_to_string(message.clone(), diag.args()); - let mut diag = dcx.struct_almost_fatal(fluent::codegen_llvm_parse_target_machine_config); + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config); diag.set_arg("error", message); diag } @@ -123,9 +122,13 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { #[help(codegen_llvm_missing_features)] pub(crate) struct MissingFeatures; -impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable); +impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, + fluent::codegen_llvm_target_feature_disable_or_enable, + ); if let Some(span) = self.span { diag.set_span(span); }; @@ -184,7 +187,7 @@ pub enum LlvmError<'a> { pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String); impl IntoDiagnostic<'_, G> for WithLlvmError<'_> { - fn into_diagnostic(self, dcx: &'_ DiagCtxt) -> DiagnosticBuilder<'_, G> { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { use LlvmError::*; let msg_with_llvm_err = match &self.0 { WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err, @@ -201,7 +204,7 @@ 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); + let mut diag = self.0.into_diagnostic(dcx, level); diag.set_primary_message(msg_with_llvm_err); diag.set_arg("llvm_err", self.1); diag diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 668d39afbda..2b628d2aa69 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -4,8 +4,8 @@ use crate::assert_module_sources::CguReuse; use crate::back::command::Command; use crate::fluent_generated as fluent; use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, }; use rustc_macros::Diagnostic; use rustc_middle::ty::layout::LayoutError; @@ -209,192 +209,193 @@ pub enum LinkRlibError { pub struct ThorinErrorWrapper(pub thorin::Error); -impl IntoDiagnostic<'_> for ThorinErrorWrapper { - fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { +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 = dcx.struct_err(fluent::codegen_ssa_thorin_read_input_failure); + diag = build(fluent::codegen_ssa_thorin_read_input_failure); diag } thorin::Error::ParseFileKind(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_file_kind); + diag = build(fluent::codegen_ssa_thorin_parse_input_file_kind); diag } thorin::Error::ParseObjectFile(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_object_file); + diag = build(fluent::codegen_ssa_thorin_parse_input_object_file); diag } thorin::Error::ParseArchiveFile(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_input_archive_file); + diag = build(fluent::codegen_ssa_thorin_parse_input_archive_file); diag } thorin::Error::ParseArchiveMember(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_archive_member); + diag = build(fluent::codegen_ssa_thorin_parse_archive_member); diag } thorin::Error::InvalidInputKind => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_invalid_input_kind); + diag = build(fluent::codegen_ssa_thorin_invalid_input_kind); diag } thorin::Error::DecompressData(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_decompress_data); + diag = build(fluent::codegen_ssa_thorin_decompress_data); diag } thorin::Error::NamelessSection(_, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_section_without_name); + diag = build(fluent::codegen_ssa_thorin_section_without_name); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::RelocationWithInvalidSymbol(section, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); + diag = build(fluent::codegen_ssa_thorin_relocation_with_invalid_symbol); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MultipleRelocations(section, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_relocations); + diag = build(fluent::codegen_ssa_thorin_multiple_relocations); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::UnsupportedRelocation(section, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_unsupported_relocation); + diag = build(fluent::codegen_ssa_thorin_unsupported_relocation); diag.set_arg("section", section); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::MissingDwoName(id) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_dwo_name); + diag = build(fluent::codegen_ssa_thorin_missing_dwo_name); diag.set_arg("id", format!("0x{id:08x}")); diag } thorin::Error::NoCompilationUnits => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_no_compilation_units); + diag = build(fluent::codegen_ssa_thorin_no_compilation_units); diag } thorin::Error::NoDie => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_no_die); + diag = build(fluent::codegen_ssa_thorin_no_die); diag } thorin::Error::TopLevelDieNotUnit => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_top_level_die_not_unit); + diag = build(fluent::codegen_ssa_thorin_top_level_die_not_unit); diag } thorin::Error::MissingRequiredSection(section) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_required_section); + diag = build(fluent::codegen_ssa_thorin_missing_required_section); diag.set_arg("section", section); diag } thorin::Error::ParseUnitAbbreviations(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_abbreviations); + diag = build(fluent::codegen_ssa_thorin_parse_unit_abbreviations); diag } thorin::Error::ParseUnitAttribute(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_attribute); + diag = build(fluent::codegen_ssa_thorin_parse_unit_attribute); diag } thorin::Error::ParseUnitHeader(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit_header); + diag = build(fluent::codegen_ssa_thorin_parse_unit_header); diag } thorin::Error::ParseUnit(_) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_unit); + diag = build(fluent::codegen_ssa_thorin_parse_unit); diag } thorin::Error::IncompatibleIndexVersion(section, format, actual) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_incompatible_index_version); + diag = build(fluent::codegen_ssa_thorin_incompatible_index_version); diag.set_arg("section", section); diag.set_arg("actual", actual); diag.set_arg("format", format); diag } thorin::Error::OffsetAtIndex(_, index) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_offset_at_index); + diag = build(fluent::codegen_ssa_thorin_offset_at_index); diag.set_arg("index", index); diag } thorin::Error::StrAtOffset(_, offset) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_str_at_offset); + diag = build(fluent::codegen_ssa_thorin_str_at_offset); diag.set_arg("offset", format!("0x{offset:08x}")); diag } thorin::Error::ParseIndex(_, section) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_parse_index); + diag = build(fluent::codegen_ssa_thorin_parse_index); diag.set_arg("section", section); diag } thorin::Error::UnitNotInIndex(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_unit_not_in_index); + diag = build(fluent::codegen_ssa_thorin_unit_not_in_index); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::RowNotInIndex(_, row) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_row_not_in_index); + diag = build(fluent::codegen_ssa_thorin_row_not_in_index); diag.set_arg("row", row); diag } thorin::Error::SectionNotInRow => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_section_not_in_row); + diag = build(fluent::codegen_ssa_thorin_section_not_in_row); diag } thorin::Error::EmptyUnit(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_empty_unit); + diag = build(fluent::codegen_ssa_thorin_empty_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MultipleDebugInfoSection => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_debug_info_section); + diag = build(fluent::codegen_ssa_thorin_multiple_debug_info_section); diag } thorin::Error::MultipleDebugTypesSection => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_multiple_debug_types_section); + diag = build(fluent::codegen_ssa_thorin_multiple_debug_types_section); diag } thorin::Error::NotSplitUnit => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_not_split_unit); + diag = build(fluent::codegen_ssa_thorin_not_split_unit); diag } thorin::Error::DuplicateUnit(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_duplicate_unit); + diag = build(fluent::codegen_ssa_thorin_duplicate_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::MissingReferencedUnit(unit) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_missing_referenced_unit); + diag = build(fluent::codegen_ssa_thorin_missing_referenced_unit); diag.set_arg("unit", format!("0x{unit:08x}")); diag } thorin::Error::NoOutputObjectCreated => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_not_output_object_created); + diag = build(fluent::codegen_ssa_thorin_not_output_object_created); diag } thorin::Error::MixedInputEncodings => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_mixed_input_encodings); + diag = build(fluent::codegen_ssa_thorin_mixed_input_encodings); diag } thorin::Error::Io(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_io); + diag = build(fluent::codegen_ssa_thorin_io); diag.set_arg("error", format!("{e}")); diag } thorin::Error::ObjectRead(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_object_read); + diag = build(fluent::codegen_ssa_thorin_object_read); diag.set_arg("error", format!("{e}")); diag } thorin::Error::ObjectWrite(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_object_write); + diag = build(fluent::codegen_ssa_thorin_object_write); diag.set_arg("error", format!("{e}")); diag } thorin::Error::GimliRead(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_gimli_read); + diag = build(fluent::codegen_ssa_thorin_gimli_read); diag.set_arg("error", format!("{e}")); diag } thorin::Error::GimliWrite(e) => { - diag = dcx.struct_err(fluent::codegen_ssa_thorin_gimli_write); + diag = build(fluent::codegen_ssa_thorin_gimli_write); diag.set_arg("error", format!("{e}")); diag } @@ -410,9 +411,9 @@ pub struct LinkingFailed<'a> { pub escaped_output: String, } -impl IntoDiagnostic<'_> for LinkingFailed<'_> { - fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::codegen_ssa_linking_failed); +impl IntoDiagnostic<'_, G> for LinkingFailed<'_> { + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::codegen_ssa_linking_failed); diag.set_arg("linker_path", format!("{}", self.linker_path.display())); diag.set_arg("exit_status", format!("{}", self.exit_status)); diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index adce1f5430f..eb9bf52676a 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -1,6 +1,6 @@ use rustc_errors::{ DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, - IntoDiagnostic, + IntoDiagnostic, Level, }; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -875,7 +875,10 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> { | InvalidProgramInfo::AlreadyReported(_) | InvalidProgramInfo::ConstPropNonsense => {} InvalidProgramInfo::Layout(e) => { - let diag: DiagnosticBuilder<'_, ()> = e.into_diagnostic().into_diagnostic(dcx); + // The level doesn't matter, `diag` is consumed without it being used. + let dummy_level = Level::Bug; + let diag: DiagnosticBuilder<'_, ()> = + e.into_diagnostic().into_diagnostic(dcx, dummy_level); for (name, val) in diag.args() { builder.set_arg(name.clone(), val.clone()); } diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 3f66af1fcff..0079fa8b995 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -21,7 +21,7 @@ use std::thread::panicking; pub trait IntoDiagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> { /// Write out as a diagnostic out of `DiagCtxt`. #[must_use] - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, G>; + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G>; } impl<'a, T, G> IntoDiagnostic<'a, G> for Spanned @@ -29,8 +29,8 @@ where T: IntoDiagnostic<'a, G>, G: EmissionGuarantee, { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, G> { - let mut diag = self.node.into_diagnostic(dcx); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = self.node.into_diagnostic(dcx, level); diag.set_span(self.span); diag } @@ -339,16 +339,10 @@ impl DerefMut for DiagnosticBuilder<'_, G> { } impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { - /// Convenience function for internal use, clients should use one of the - /// `struct_*` methods on [`DiagCtxt`]. + #[rustc_lint_diagnostics] #[track_caller] - pub(crate) fn new>( - dcx: &'a DiagCtxt, - level: Level, - message: M, - ) -> Self { - let diagnostic = Diagnostic::new(level, message); - Self::new_diagnostic(dcx, diagnostic) + pub fn new>(dcx: &'a DiagCtxt, level: Level, message: M) -> Self { + Self::new_diagnostic(dcx, Diagnostic::new(level, message)) } /// Creates a new `DiagnosticBuilder` with an already constructed @@ -400,15 +394,15 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// later stage of the compiler. The diagnostic can be accessed with /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`]. /// - /// As with `buffer`, this is unless the handler has disabled such buffering. + /// As with `buffer`, this is unless the dcx has disabled such buffering. pub fn stash(self, span: Span, key: StashKey) { - if let Some((diag, handler)) = self.into_diagnostic() { - handler.stash_diagnostic(span, key, diag); + if let Some((diag, dcx)) = self.into_diagnostic() { + dcx.stash_diagnostic(span, key, diag); } } /// Converts the builder to a `Diagnostic` for later emission, - /// unless handler has disabled such buffering, or `.emit()` was called. + /// unless dcx has disabled such buffering, or `.emit()` was called. pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> { let dcx = match self.inner.state { // No `.emit()` calls, the `&DiagCtxt` is still available. @@ -449,7 +443,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { } /// Buffers the diagnostic for later emission, - /// unless handler has disabled such buffering. + /// unless dcx has disabled such buffering. pub fn buffer(self, buffered_diagnostics: &mut Vec) { buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag)); } diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 3e4b3ee758a..ccc951543d8 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -1,10 +1,12 @@ use crate::diagnostic::DiagnosticLocation; use crate::{fluent_generated as fluent, AddToDiagnostic}; -use crate::{DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, IntoDiagnostic, IntoDiagnosticArg}; +use crate::{ + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, +}; use rustc_ast as ast; use rustc_ast_pretty::pprust; use rustc_hir as hir; -use rustc_lint_defs::Level; use rustc_span::edition::Edition; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_span::Span; @@ -216,7 +218,7 @@ impl IntoDiagnosticArg for ast::Visibility { } } -impl IntoDiagnosticArg for Level { +impl IntoDiagnosticArg for rustc_lint_defs::Level { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Borrowed(self.to_cmd_flag())) } @@ -245,19 +247,20 @@ impl IntoDiagnosticArg for hir::def::Res { } } -impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { - fn into_diagnostic(self, dcx: &DiagCtxt) -> DiagnosticBuilder<'_, !> { +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 = dcx.struct_fatal(fluent::errors_target_invalid_address_space); + diag = + DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_address_space); diag.set_arg("addr_space", addr_space); diag.set_arg("cause", cause); diag.set_arg("err", err); diag } TargetDataLayoutErrors::InvalidBits { kind, bit, cause, err } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_bits); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits); diag.set_arg("kind", kind); diag.set_arg("bit", bit); diag.set_arg("cause", cause); @@ -265,31 +268,39 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> { diag } TargetDataLayoutErrors::MissingAlignment { cause } => { - diag = dcx.struct_fatal(fluent::errors_target_missing_alignment); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_missing_alignment); diag.set_arg("cause", cause); diag } TargetDataLayoutErrors::InvalidAlignment { cause, err } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_alignment); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_alignment); diag.set_arg("cause", cause); diag.set_arg("err_kind", err.diag_ident()); diag.set_arg("align", err.align()); diag } TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => { - diag = dcx.struct_fatal(fluent::errors_target_inconsistent_architecture); + diag = DiagnosticBuilder::new( + dcx, + level, + fluent::errors_target_inconsistent_architecture, + ); diag.set_arg("dl", dl); diag.set_arg("target", target); diag } TargetDataLayoutErrors::InconsistentTargetPointerWidth { pointer_size, target } => { - diag = dcx.struct_fatal(fluent::errors_target_inconsistent_pointer_width); + diag = DiagnosticBuilder::new( + dcx, + level, + fluent::errors_target_inconsistent_pointer_width, + ); diag.set_arg("pointer_size", pointer_size); diag.set_arg("target", target); diag } TargetDataLayoutErrors::InvalidBitsSize { err } => { - diag = dcx.struct_fatal(fluent::errors_target_invalid_bits_size); + diag = DiagnosticBuilder::new(dcx, level, fluent::errors_target_invalid_bits_size); diag.set_arg("err", err); diag } @@ -362,9 +373,9 @@ impl IntoDiagnosticArg for Backtrace { pub struct InvalidFlushedDelayedDiagnosticLevel { #[primary_span] pub span: Span, - pub level: rustc_errors::Level, + pub level: Level, } -impl IntoDiagnosticArg for rustc_errors::Level { +impl IntoDiagnosticArg for Level { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::from(self.to_string())) } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 763de78451e..5027f63a970 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1279,14 +1279,14 @@ impl DiagCtxt { &'a self, err: impl IntoDiagnostic<'a>, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - err.into_diagnostic(self) + err.into_diagnostic(self, Level::Error { lint: false }) } pub fn create_warning<'a>( &'a self, warning: impl IntoDiagnostic<'a, ()>, ) -> DiagnosticBuilder<'a, ()> { - warning.into_diagnostic(self) + warning.into_diagnostic(self, Level::Warning(None)) } pub fn emit_warning<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) { @@ -1297,7 +1297,7 @@ impl DiagCtxt { &'a self, fatal: impl IntoDiagnostic<'a, FatalError>, ) -> DiagnosticBuilder<'a, FatalError> { - fatal.into_diagnostic(self) + fatal.into_diagnostic(self, Level::Fatal) } pub fn emit_almost_fatal<'a>( @@ -1311,7 +1311,7 @@ impl DiagCtxt { &'a self, fatal: impl IntoDiagnostic<'a, !>, ) -> DiagnosticBuilder<'a, !> { - fatal.into_diagnostic(self) + fatal.into_diagnostic(self, Level::Fatal) } pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { @@ -1322,7 +1322,7 @@ impl DiagCtxt { &'a self, bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, ) -> DiagnosticBuilder<'a, diagnostic_builder::Bug> { - bug.into_diagnostic(self) + bug.into_diagnostic(self, Level::Bug) } pub fn emit_bug<'a>( @@ -1340,7 +1340,7 @@ impl DiagCtxt { &'a self, note: impl IntoDiagnostic<'a, Noted>, ) -> DiagnosticBuilder<'a, Noted> { - note.into_diagnostic(self) + note.into_diagnostic(self, Level::Note) } pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f461b6a94ec..41f30057902 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -2,8 +2,8 @@ use crate::fluent_generated as fluent; use rustc_errors::{ - error_code, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, - MultiSpan, + error_code, Applicability, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + Level, MultiSpan, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::Ty; @@ -315,14 +315,12 @@ pub struct MissingTypeParams { } // Manual implementation of `IntoDiagnostic` to be able to call `span_to_snippet`. -impl<'a> IntoDiagnostic<'a> for MissingTypeParams { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams { #[track_caller] - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut err = dcx.struct_span_err_with_code( - self.span, - fluent::hir_analysis_missing_type_params, - error_code!(E0393), - ); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut err = DiagnosticBuilder::new(dcx, level, fluent::hir_analysis_missing_type_params); + err.set_span(self.span); + err.code(error_code!(E0393)); err.set_arg("parameterCount", self.missing_type_params.len()); err.set_arg( "parameters", diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index be8582d0ba0..027c97330b1 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -51,7 +51,11 @@ impl<'a> DiagnosticDerive<'a> { Some(slug) => { slugs.borrow_mut().push(slug.clone()); quote! { - let mut diag = dcx.struct_diagnostic(crate::fluent_generated::#slug); + let mut diag = rustc_errors::DiagnosticBuilder::new( + dcx, + level, + crate::fluent_generated::#slug + ); } } }; @@ -77,7 +81,8 @@ impl<'a> DiagnosticDerive<'a> { #[track_caller] fn into_diagnostic( self, - dcx: &'_sess rustc_errors::DiagCtxt + dcx: &'_sess rustc_errors::DiagCtxt, + level: rustc_errors::Level ) -> rustc_errors::DiagnosticBuilder<'_sess, G> { #implementation } diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs index 206c15edd78..e13068cb6f9 100644 --- a/compiler/rustc_metadata/src/errors.rs +++ b/compiler/rustc_metadata/src/errors.rs @@ -3,7 +3,9 @@ use std::{ path::{Path, PathBuf}, }; -use rustc_errors::{error_code, ErrorGuaranteed, IntoDiagnostic}; +use rustc_errors::{ + error_code, DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level, +}; use rustc_macros::Diagnostic; use rustc_session::config; use rustc_span::{sym, Span, Symbol}; @@ -495,12 +497,9 @@ pub(crate) struct MultipleCandidates { pub candidates: Vec, } -impl IntoDiagnostic<'_> for MultipleCandidates { - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::metadata_multiple_candidates); +impl IntoDiagnostic<'_, G> for MultipleCandidates { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_multiple_candidates); diag.set_arg("crate_name", self.crate_name); diag.set_arg("flavor", self.flavor); diag.code(error_code!(E0464)); @@ -593,13 +592,10 @@ pub struct InvalidMetadataFiles { pub crate_rejections: Vec, } -impl IntoDiagnostic<'_> for InvalidMetadataFiles { +impl IntoDiagnostic<'_, G> for InvalidMetadataFiles { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::metadata_invalid_meta_files); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_invalid_meta_files); diag.set_arg("crate_name", self.crate_name); diag.set_arg("add_info", self.add_info); diag.code(error_code!(E0786)); @@ -623,13 +619,10 @@ pub struct CannotFindCrate { pub is_ui_testing: bool, } -impl IntoDiagnostic<'_> for CannotFindCrate { +impl IntoDiagnostic<'_, G> for CannotFindCrate { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::metadata_cannot_find_crate); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::metadata_cannot_find_crate); diag.set_arg("crate_name", self.crate_name); diag.set_arg("current_crate", self.current_crate); diag.set_arg("add_info", self.add_info); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 225dd217807..5ae758edfa3 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -5,7 +5,8 @@ use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt}; use rustc_error_messages::DiagnosticMessage; use rustc_errors::{ - DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, IntoDiagnostic, IntoDiagnosticArg, + DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, + IntoDiagnosticArg, Level, }; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -1272,14 +1273,14 @@ pub enum FnAbiError<'tcx> { AdjustForForeignAbi(call::AdjustForForeignAbiError), } -impl<'a, 'b> IntoDiagnostic<'a, !> for FnAbiError<'b> { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, !> { +impl<'a, 'b, G: EmissionGuarantee> IntoDiagnostic<'a, G> for FnAbiError<'b> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { match self { - Self::Layout(e) => e.into_diagnostic().into_diagnostic(dcx), + Self::Layout(e) => e.into_diagnostic().into_diagnostic(dcx, level), Self::AdjustForForeignAbi(call::AdjustForForeignAbiError::Unsupported { arch, abi, - }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(dcx), + }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(dcx, level), } } } diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index db2624cac02..0f6d8c36203 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -2,7 +2,7 @@ use crate::fluent_generated as fluent; use rustc_errors::DiagnosticArgValue; use rustc_errors::{ error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, IntoDiagnostic, MultiSpan, SubdiagnosticMessage, + ErrorGuaranteed, IntoDiagnostic, Level, MultiSpan, SubdiagnosticMessage, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::ty::{self, Ty}; @@ -461,13 +461,18 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> { } impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, + fn into_diagnostic( + self, + dcx: &'a DiagCtxt, + level: Level, + ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, fluent::mir_build_non_exhaustive_patterns_type_not_empty, - error_code!(E0004), ); - + diag.set_span(self.span); + diag.code(error_code!(E0004)); let peeled_ty = self.ty.peel_refs(); diag.set_arg("ty", self.ty); diag.set_arg("peeled_ty", peeled_ty); diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index fd4af31501c..17916e16daf 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use rustc_errors::{ Applicability, DecorateLint, DiagCtxt, DiagnosticArgValue, DiagnosticBuilder, - DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic, + DiagnosticMessage, EmissionGuarantee, IntoDiagnostic, Level, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails}; @@ -62,10 +62,10 @@ pub(crate) struct RequiresUnsafe { // so we need to eagerly translate the label here, which isn't supported by the derive API // We could also exhaustively list out the primary messages for all unsafe violations, // but this would result in a lot of duplication. -impl<'sess> IntoDiagnostic<'sess> for RequiresUnsafe { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe { #[track_caller] - fn into_diagnostic(self, dcx: &'sess DiagCtxt) -> DiagnosticBuilder<'sess, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::mir_transform_requires_unsafe); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::mir_transform_requires_unsafe); diag.code(rustc_errors::DiagnosticId::Error("E0133".to_string())); diag.set_span(self.span); diag.span_label(self.span, self.details.label()); diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index 247b2245583..592e71251b8 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -1,8 +1,7 @@ use std::path::PathBuf; use crate::fluent_generated as fluent; -use rustc_errors::ErrorGuaranteed; -use rustc_errors::IntoDiagnostic; +use rustc_errors::{DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level}; use rustc_macros::{Diagnostic, LintDiagnostic}; use rustc_span::{Span, Symbol}; @@ -47,13 +46,11 @@ pub struct UnusedGenericParamsHint { pub param_names: Vec, } -impl IntoDiagnostic<'_> for UnusedGenericParamsHint { +impl IntoDiagnostic<'_, G> for UnusedGenericParamsHint { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::monomorphize_unused_generic_params); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::monomorphize_unused_generic_params); diag.set_span(self.span); for (span, name) in self.param_spans.into_iter().zip(self.param_names) { // FIXME: I can figure out how to do a label with a fluent string with a fixed message, diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 008adcc83d0..8ccfcb625a6 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2,7 +2,10 @@ use std::borrow::Cow; use rustc_ast::token::Token; use rustc_ast::{Path, Visibility}; -use rustc_errors::{AddToDiagnostic, Applicability, ErrorGuaranteed, IntoDiagnostic}; +use rustc_errors::{ + AddToDiagnostic, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, + Level, SubdiagnosticMessage, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; @@ -1042,23 +1045,30 @@ impl<'a> IntoDiagnostic<'a> for ExpectedIdentifier { #[track_caller] fn into_diagnostic( self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { + dcx: &'a DiagCtxt, + level: Level, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { let token_descr = TokenDescription::from_token(&self.token); - let mut diag = dcx.struct_err(match token_descr { - Some(TokenDescription::ReservedIdentifier) => { - fluent::parse_expected_identifier_found_reserved_identifier_str - } - Some(TokenDescription::Keyword) => fluent::parse_expected_identifier_found_keyword_str, - Some(TokenDescription::ReservedKeyword) => { - fluent::parse_expected_identifier_found_reserved_keyword_str - } - Some(TokenDescription::DocComment) => { - fluent::parse_expected_identifier_found_doc_comment_str - } - None => fluent::parse_expected_identifier_found_str, - }); + let mut diag = DiagnosticBuilder::new( + dcx, + level, + match token_descr { + Some(TokenDescription::ReservedIdentifier) => { + fluent::parse_expected_identifier_found_reserved_identifier_str + } + Some(TokenDescription::Keyword) => { + fluent::parse_expected_identifier_found_keyword_str + } + Some(TokenDescription::ReservedKeyword) => { + fluent::parse_expected_identifier_found_reserved_keyword_str + } + Some(TokenDescription::DocComment) => { + fluent::parse_expected_identifier_found_doc_comment_str + } + None => fluent::parse_expected_identifier_found_str, + }, + ); diag.set_span(self.span); diag.set_arg("token", self.token); @@ -1099,21 +1109,28 @@ impl<'a> IntoDiagnostic<'a> for ExpectedSemi { #[track_caller] fn into_diagnostic( self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { + dcx: &'a DiagCtxt, + level: Level, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { let token_descr = TokenDescription::from_token(&self.token); - let mut diag = dcx.struct_err(match token_descr { - Some(TokenDescription::ReservedIdentifier) => { - fluent::parse_expected_semi_found_reserved_identifier_str - } - Some(TokenDescription::Keyword) => fluent::parse_expected_semi_found_keyword_str, - Some(TokenDescription::ReservedKeyword) => { - fluent::parse_expected_semi_found_reserved_keyword_str - } - Some(TokenDescription::DocComment) => fluent::parse_expected_semi_found_doc_comment_str, - None => fluent::parse_expected_semi_found_str, - }); + let mut diag = DiagnosticBuilder::new( + dcx, + level, + match token_descr { + Some(TokenDescription::ReservedIdentifier) => { + fluent::parse_expected_semi_found_reserved_identifier_str + } + Some(TokenDescription::Keyword) => fluent::parse_expected_semi_found_keyword_str, + Some(TokenDescription::ReservedKeyword) => { + fluent::parse_expected_semi_found_reserved_keyword_str + } + Some(TokenDescription::DocComment) => { + fluent::parse_expected_semi_found_doc_comment_str + } + None => fluent::parse_expected_semi_found_str, + }, + ); diag.set_span(self.span); diag.set_arg("token", self.token); @@ -1436,10 +1453,7 @@ pub(crate) struct FnTraitMissingParen { impl AddToDiagnostic for FnTraitMissingParen { fn add_to_diagnostic_with(self, diag: &mut rustc_errors::Diagnostic, _: F) where - F: Fn( - &mut rustc_errors::Diagnostic, - rustc_errors::SubdiagnosticMessage, - ) -> rustc_errors::SubdiagnosticMessage, + F: Fn(&mut rustc_errors::Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); let applicability = if self.machine_applicable { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 8f8da211d31..856256a0641 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -6,8 +6,8 @@ use std::{ use crate::fluent_generated as fluent; use rustc_ast::Label; use rustc_errors::{ - error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticSymbolList, ErrorGuaranteed, - IntoDiagnostic, MultiSpan, + error_code, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + DiagnosticSymbolList, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan, }; use rustc_hir::{self as hir, ExprKind, Target}; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; @@ -863,13 +863,11 @@ pub struct ItemFollowingInnerAttr { pub kind: &'static str, } -impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel { +impl IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel { #[track_caller] - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::passes_invalid_attr_at_crate_level); + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::passes_invalid_attr_at_crate_level); diag.set_span(self.span); diag.set_arg("name", self.name); // Only emit an error with a suggestion if we can create a string out @@ -879,7 +877,7 @@ impl IntoDiagnostic<'_> for InvalidAttrAtCrateLevel { span, fluent::passes_suggestion, String::new(), - rustc_errors::Applicability::MachineApplicable, + Applicability::MachineApplicable, ); } if let Some(item) = self.item { @@ -1016,17 +1014,12 @@ pub struct BreakNonLoop<'a> { pub break_expr_span: Span, } -impl<'a> IntoDiagnostic<'_> for BreakNonLoop<'a> { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> { #[track_caller] - fn into_diagnostic( - self, - dcx: &rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, - fluent::passes_break_non_loop, - error_code!(E0571), - ); + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_break_non_loop); + diag.set_span(self.span); + diag.code(error_code!(E0571)); diag.set_arg("kind", self.kind); diag.span_label(self.span, fluent::passes_label); if let Some(head) = self.head { @@ -1165,17 +1158,12 @@ pub struct NakedFunctionsAsmBlock { pub non_asms: Vec, } -impl IntoDiagnostic<'_> for NakedFunctionsAsmBlock { +impl IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock { #[track_caller] - fn into_diagnostic( - self, - dcx: &rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - self.span, - fluent::passes_naked_functions_asm_block, - error_code!(E0787), - ); + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_naked_functions_asm_block); + diag.set_span(self.span); + diag.code(error_code!(E0787)); for span in self.multiple_asms.iter() { diag.span_label(*span, fluent::passes_label_multiple_asm); } @@ -1281,17 +1269,12 @@ pub struct NoMainErr { pub add_teach_note: bool, } -impl<'a> IntoDiagnostic<'a> for NoMainErr { +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr { #[track_caller] - fn into_diagnostic( - self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_span_err_with_code( - DUMMY_SP, - fluent::passes_no_main_function, - error_code!(E0601), - ); + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + let mut diag = DiagnosticBuilder::new(dcx, level, fluent::passes_no_main_function); + diag.set_span(DUMMY_SP); + diag.code(error_code!(E0601)); diag.set_arg("crate_name", self.crate_name); diag.set_arg("filename", self.filename); diag.set_arg("has_filename", self.has_filename); @@ -1344,20 +1327,19 @@ pub struct DuplicateLangItem { pub(crate) duplicate: Duplicate, } -impl IntoDiagnostic<'_> for DuplicateLangItem { +impl IntoDiagnostic<'_, G> for DuplicateLangItem { #[track_caller] - fn into_diagnostic( - self, - dcx: &rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err_with_code( + fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { + let mut diag = DiagnosticBuilder::new( + dcx, + level, match self.duplicate { Duplicate::Plain => fluent::passes_duplicate_lang_item, Duplicate::Crate => fluent::passes_duplicate_lang_item_crate, Duplicate::CrateDepends => fluent::passes_duplicate_lang_item_crate_depends, }, - error_code!(E0152), ); + diag.code(error_code!(E0152)); diag.set_arg("lang_item_name", self.lang_item_name); diag.set_arg("crate_name", self.crate_name); diag.set_arg("dependency_of", self.dependency_of); diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index c3360815ac9..8ab31f6f382 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -3,7 +3,10 @@ use std::num::NonZeroU32; use crate::parse::ParseSess; use rustc_ast::token; use rustc_ast::util::literal::LitError; -use rustc_errors::{error_code, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic, MultiSpan}; +use rustc_errors::{ + error_code, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic, + Level, MultiSpan, +}; use rustc_macros::Diagnostic; use rustc_span::{BytePos, Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; @@ -17,9 +20,10 @@ impl<'a> IntoDiagnostic<'a> for FeatureGateError { #[track_caller] fn into_diagnostic( self, - dcx: &'a rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut diag = dcx.struct_err(self.explain); + dcx: &'a DiagCtxt, + level: Level, + ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let mut diag = DiagnosticBuilder::new(dcx, level, self.explain); diag.set_span(self.span); diag.code(error_code!(E0658)); diag diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 2cb47e3a932..8e8b420df13 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -14,7 +14,7 @@ use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, DiagCtxt}; use rustc_errors::{ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, - ErrorGuaranteed, IntoDiagnostic, MultiSpan, Noted, StashKey, + ErrorGuaranteed, IntoDiagnostic, Level, MultiSpan, Noted, StashKey, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_span::edition::Edition; @@ -322,7 +322,7 @@ impl ParseSess { &'a self, err: impl IntoDiagnostic<'a>, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - err.into_diagnostic(&self.dcx) + err.into_diagnostic(&self.dcx, Level::Error { lint: false }) } #[track_caller] @@ -335,7 +335,7 @@ impl ParseSess { &'a self, warning: impl IntoDiagnostic<'a, ()>, ) -> DiagnosticBuilder<'a, ()> { - warning.into_diagnostic(&self.dcx) + warning.into_diagnostic(&self.dcx, Level::Warning(None)) } #[track_caller] @@ -348,7 +348,7 @@ impl ParseSess { &'a self, note: impl IntoDiagnostic<'a, Noted>, ) -> DiagnosticBuilder<'a, Noted> { - note.into_diagnostic(&self.dcx) + note.into_diagnostic(&self.dcx, Level::Note) } #[track_caller] @@ -361,7 +361,7 @@ impl ParseSess { &'a self, fatal: impl IntoDiagnostic<'a, !>, ) -> DiagnosticBuilder<'a, !> { - fatal.into_diagnostic(&self.dcx) + fatal.into_diagnostic(&self.dcx, Level::Fatal) } #[track_caller] diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs index ff253b6f467..06a2b3ca9c4 100644 --- a/compiler/rustc_symbol_mangling/src/errors.rs +++ b/compiler/rustc_symbol_mangling/src/errors.rs @@ -1,6 +1,6 @@ //! Errors emitted by symbol_mangling. -use rustc_errors::{ErrorGuaranteed, IntoDiagnostic}; +use rustc_errors::{DiagCtxt, DiagnosticBuilder, EmissionGuarantee, IntoDiagnostic, Level}; use rustc_span::Span; use std::fmt; @@ -13,15 +13,12 @@ pub struct TestOutput { // This diagnostic doesn't need translation because (a) it doesn't contain any // natural language, and (b) it's only used in tests. So we construct it // manually and avoid the fluent machinery. -impl IntoDiagnostic<'_> for TestOutput { - fn into_diagnostic( - self, - dcx: &'_ rustc_errors::DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { +impl IntoDiagnostic<'_, G> for TestOutput { + fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> DiagnosticBuilder<'_, G> { let TestOutput { span, kind, content } = self; #[allow(rustc::untranslatable_diagnostic)] - let mut diag = dcx.struct_err(format!("{kind}({content})")); + let mut diag = DiagnosticBuilder::new(dcx, level, format!("{kind}({content})")); diag.set_span(span); diag } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index b0ec8b3a4fa..bea6fbd6ac5 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,7 +1,7 @@ use crate::fluent_generated as fluent; use rustc_errors::{ - AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, ErrorGuaranteed, IntoDiagnostic, - SubdiagnosticMessage, + AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, EmissionGuarantee, + IntoDiagnostic, Level, SubdiagnosticMessage, }; use rustc_macros::Diagnostic; use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty}; @@ -57,13 +57,15 @@ pub struct NegativePositiveConflict<'tcx> { pub positive_impl_span: Result, } -impl IntoDiagnostic<'_> for NegativePositiveConflict<'_> { +impl IntoDiagnostic<'_, G> for NegativePositiveConflict<'_> { #[track_caller] fn into_diagnostic( self, dcx: &DiagCtxt, - ) -> rustc_errors::DiagnosticBuilder<'_, ErrorGuaranteed> { - let mut diag = dcx.struct_err(fluent::trait_selection_negative_positive_conflict); + level: Level, + ) -> rustc_errors::DiagnosticBuilder<'_, G> { + let mut diag = + DiagnosticBuilder::new(dcx, level, fluent::trait_selection_negative_positive_conflict); diag.set_arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); diag.set_arg( "self_desc", diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index 4b006151c64..ab42d3b8c1e 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -13,8 +13,8 @@ extern crate rustc_session; extern crate rustc_span; use rustc_errors::{ - AddToDiagnostic, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, - IntoDiagnostic, SubdiagnosticMessage, + AddToDiagnostic, Diagnostic, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, DiagCtxt, + IntoDiagnostic, Level, SubdiagnosticMessage, }; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::Span; @@ -37,18 +37,18 @@ struct Note { pub struct UntranslatableInIntoDiagnostic; -impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for UntranslatableInIntoDiagnostic { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - dcx.struct_err("untranslatable diagnostic") +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UntranslatableInIntoDiagnostic { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + DiagnosticBuilder::new(dcx, level, "untranslatable diagnostic") //~^ ERROR diagnostics should be created using translatable messages } } pub struct TranslatableInIntoDiagnostic; -impl<'a> IntoDiagnostic<'a, ErrorGuaranteed> for TranslatableInIntoDiagnostic { - fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - dcx.struct_err(crate::fluent_generated::no_crate_example) +impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagnostic { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a, G> { + DiagnosticBuilder::new(dcx, level, crate::fluent_generated::no_crate_example) } } diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr index d18db3cbbd3..f70240ecf17 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr +++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr @@ -1,8 +1,8 @@ error: diagnostics should be created using translatable messages - --> $DIR/diagnostics.rs:42:13 + --> $DIR/diagnostics.rs:42:9 | -LL | dcx.struct_err("untranslatable diagnostic") - | ^^^^^^^^^^ +LL | DiagnosticBuilder::new(dcx, level, "untranslatable diagnostic") + | ^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/diagnostics.rs:6:9 From 3a5f28f7e821a2325e9dbdb4ff40cd9ff417f065 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Dec 2023 16:22:45 +1100 Subject: [PATCH 05/10] Remove `struct_diagnostic` and `G::make_diagnostic_builder`. `EmissionGuarantee` no longer determines the error level, the `create_*` functions do. --- .../rustc_errors/src/diagnostic_builder.rs | 50 ------------------- compiler/rustc_errors/src/lib.rs | 15 ------ 2 files changed, 65 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 0079fa8b995..59e5c1f352f 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -106,13 +106,6 @@ pub trait EmissionGuarantee: Sized { /// of `Self` without actually performing the emission. #[track_caller] fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self; - - /// Creates a new `DiagnosticBuilder` that will return this type of guarantee. - #[track_caller] - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self>; } impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { @@ -163,14 +156,6 @@ impl EmissionGuarantee for ErrorGuaranteed { } } } - - #[track_caller] - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Error { lint: false }, msg) - } } // FIXME(eddyb) should there be a `Option` impl as well? @@ -187,13 +172,6 @@ impl EmissionGuarantee for () { DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} } } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Warning(None), msg) - } } /// Marker type which enables implementation of `create_note` and `emit_note` functions for @@ -215,13 +193,6 @@ impl EmissionGuarantee for Noted { Noted } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Note, msg) - } } /// Marker type which enables implementation of `create_bug` and `emit_bug` functions for @@ -244,13 +215,6 @@ impl EmissionGuarantee for Bug { // Then panic. No need to return the marker type. panic::panic_any(ExplicitBug); } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Bug, msg) - } } impl EmissionGuarantee for ! { @@ -268,13 +232,6 @@ impl EmissionGuarantee for ! { // Then fatally error, returning `!` crate::FatalError.raise() } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Fatal, msg) - } } impl EmissionGuarantee for rustc_span::fatal_error::FatalError { @@ -292,13 +249,6 @@ impl EmissionGuarantee for rustc_span::fatal_error::FatalError { // Then fatally error.. rustc_span::fatal_error::FatalError } - - fn make_diagnostic_builder( - dcx: &DiagCtxt, - msg: impl Into, - ) -> DiagnosticBuilder<'_, Self> { - DiagnosticBuilder::new(dcx, Level::Fatal, msg) - } } /// In general, the `DiagnosticBuilder` uses deref to allow access to diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 5027f63a970..a86a12506ad 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -722,21 +722,6 @@ impl DiagCtxt { self.inner.borrow_mut().emit_stashed_diagnostics() } - /// Construct a builder with the `msg` at the level appropriate for the - /// specific `EmissionGuarantee`. - /// - /// Note: this is necessary for `derive(Diagnostic)`, but shouldn't be used - /// outside of that. Instead use `struct_err`, `struct_warn`, etc., which - /// make the diagnostic kind clearer. - #[rustc_lint_diagnostics] - #[track_caller] - pub fn struct_diagnostic( - &self, - msg: impl Into, - ) -> DiagnosticBuilder<'_, G> { - G::make_diagnostic_builder(self, msg) - } - /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. /// /// Attempting to `.emit()` the builder will only emit if either: From f5459201e0f4f751bc30d890107942774ebf68fb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Dec 2023 16:31:15 +1100 Subject: [PATCH 06/10] Add `EmitResult` associated type to `EmissionGuarantee`. This lets different error levels share the same return type from `emit_*`. - A lot of inconsistencies in the `DiagCtxt` API are removed. - `Noted` is removed. - `FatalAbort` is introduced for fatal errors (abort via `raise`), replacing the `EmissionGuarantee` impl for `!`. - `Bug` is renamed `BugAbort` (to avoid clashing with `Level::Bug` and to mirror `FatalAbort`), and modified to work in the new way with bug errors (abort via panic). - Various diagnostic creators and emitters updated to the new, better signatures. Note that `DiagCtxt::bug` no longer needs to call `panic_any`, because `emit` handles that. Also shorten the obnoxiously long `diagnostic_builder_emit_producing_guarantee` name. --- .../rustc_errors/src/diagnostic_builder.rs | 64 ++++++++----------- compiler/rustc_errors/src/lib.rs | 36 +++++------ compiler/rustc_parse/src/lexer/mod.rs | 6 +- compiler/rustc_session/src/parse.rs | 19 +++--- compiler/rustc_session/src/session.rs | 27 ++++---- 5 files changed, 76 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 59e5c1f352f..1c83250e017 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -101,11 +101,15 @@ rustc_data_structures::static_assert_size!( /// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee" /// (or "proof") token that the emission happened. pub trait EmissionGuarantee: Sized { + /// This exists so that bugs and fatal errors can both result in `!` (an + /// abort) when emitted, but have different aborting behaviour. + type EmitResult = Self; + /// Implementation of `DiagnosticBuilder::emit`, fully controlled by each /// `impl` of `EmissionGuarantee`, to make it impossible to create a value - /// of `Self` without actually performing the emission. + /// of `Self::EmitResult` without actually performing the emission. #[track_caller] - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self; + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult; } impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { @@ -119,7 +123,7 @@ impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. impl EmissionGuarantee for ErrorGuaranteed { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -160,7 +164,7 @@ impl EmissionGuarantee for ErrorGuaranteed { // FIXME(eddyb) should there be a `Option` impl as well? impl EmissionGuarantee for () { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -174,34 +178,15 @@ impl EmissionGuarantee for () { } } -/// Marker type which enables implementation of `create_note` and `emit_note` functions for -/// note-without-error struct diagnostics. -#[derive(Copy, Clone)] -pub struct Noted; - -impl EmissionGuarantee for Noted { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - - Noted - } -} - /// Marker type which enables implementation of `create_bug` and `emit_bug` functions for -/// bug struct diagnostics. +/// bug diagnostics. #[derive(Copy, Clone)] -pub struct Bug; +pub struct BugAbort; -impl EmissionGuarantee for Bug { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { +impl EmissionGuarantee for BugAbort { + type EmitResult = !; + + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -217,8 +202,15 @@ impl EmissionGuarantee for Bug { } } -impl EmissionGuarantee for ! { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { +/// Marker type which enables implementation of `create_fatal` and `emit_fatal` functions for +/// fatal diagnostics. +#[derive(Copy, Clone)] +pub struct FatalAbort; + +impl EmissionGuarantee for FatalAbort { + type EmitResult = !; + + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -235,7 +227,7 @@ impl EmissionGuarantee for ! { } impl EmissionGuarantee for rustc_span::fatal_error::FatalError { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -313,8 +305,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// but there are various places that rely on continuing to use `self` /// after calling `emit`. #[track_caller] - pub fn emit(&mut self) -> G { - G::diagnostic_builder_emit_producing_guarantee(self) + pub fn emit(&mut self) -> G::EmitResult { + G::emit_producing_guarantee(self) } /// Emit the diagnostic unless `delay` is true, @@ -322,7 +314,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 { + pub fn emit_unless(&mut self, delay: bool) -> G::EmitResult { if delay { self.downgrade_to_delayed_bug(); } @@ -409,7 +401,7 @@ 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 { + pub fn delay_as_bug(&mut self) -> G::EmitResult { self.downgrade_to_delayed_bug(); self.emit() } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a86a12506ad..93813458718 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,6 +6,7 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![feature(array_windows)] +#![feature(associated_type_defaults)] #![feature(extract_if)] #![feature(if_let_guard)] #![feature(let_chains)] @@ -401,7 +402,7 @@ pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; -pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted}; +pub use diagnostic_builder::{BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort}; pub use diagnostic_impls::{ DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter, IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, LabelKind, @@ -907,7 +908,7 @@ impl DiagCtxt { &self, span: impl Into, msg: impl Into, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_fatal(msg); result.set_span(span); result @@ -921,7 +922,7 @@ impl DiagCtxt { span: impl Into, msg: impl Into, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_span_fatal(span, msg); result.code(code); result @@ -930,7 +931,10 @@ impl DiagCtxt { /// Construct a builder at the `Fatal` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal( + &self, + msg: impl Into, + ) -> DiagnosticBuilder<'_, FatalAbort> { DiagnosticBuilder::new(self, Level::Fatal, msg) } @@ -1101,8 +1105,7 @@ impl DiagCtxt { } pub fn bug(&self, msg: impl Into) -> ! { - DiagnosticBuilder::::new(self, Bug, msg).emit(); - panic::panic_any(ExplicitBug); + DiagnosticBuilder::::new(self, Bug, msg).emit() } #[inline] @@ -1294,37 +1297,34 @@ impl DiagCtxt { pub fn create_fatal<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, !>, - ) -> DiagnosticBuilder<'a, !> { + fatal: impl IntoDiagnostic<'a, FatalAbort>, + ) -> DiagnosticBuilder<'a, FatalAbort> { fatal.into_diagnostic(self, Level::Fatal) } - pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { + pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { self.create_fatal(fatal).emit() } pub fn create_bug<'a>( &'a self, - bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, - ) -> DiagnosticBuilder<'a, diagnostic_builder::Bug> { + bug: impl IntoDiagnostic<'a, BugAbort>, + ) -> DiagnosticBuilder<'a, BugAbort> { bug.into_diagnostic(self, Level::Bug) } - pub fn emit_bug<'a>( - &'a self, - bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, - ) -> diagnostic_builder::Bug { + pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, BugAbort>) -> ! { self.create_bug(bug).emit() } - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { self.create_note(note).emit() } pub fn create_note<'a>( &'a self, - note: impl IntoDiagnostic<'a, Noted>, - ) -> DiagnosticBuilder<'a, Noted> { + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { note.into_diagnostic(self, Level::Note) } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index c158edaac25..59bc0eeb1c5 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -7,7 +7,9 @@ use rustc_ast::ast::{self, AttrStyle}; use rustc_ast::token::{self, CommentKind, Delimiter, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::contains_text_flow_control_chars; -use rustc_errors::{error_code, Applicability, Diagnostic, DiagnosticBuilder, StashKey}; +use rustc_errors::{ + error_code, Applicability, Diagnostic, DiagnosticBuilder, FatalAbort, StashKey, +}; use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_lexer::{Cursor, LiteralKind}; @@ -344,7 +346,7 @@ impl<'a> StringReader<'a> { to_pos: BytePos, m: &str, c: char, - ) -> DiagnosticBuilder<'a, !> { + ) -> DiagnosticBuilder<'a, FatalAbort> { self.sess .dcx .struct_span_fatal(self.mk_sp(from_pos, to_pos), format!("{}: {}", m, escaped_char(c))) diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 8e8b420df13..b33cc83f9cf 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -14,7 +14,7 @@ use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, DiagCtxt}; use rustc_errors::{ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, - ErrorGuaranteed, IntoDiagnostic, Level, MultiSpan, Noted, StashKey, + ErrorGuaranteed, FatalAbort, IntoDiagnostic, Level, MultiSpan, StashKey, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_span::edition::Edition; @@ -346,26 +346,26 @@ impl ParseSess { #[track_caller] pub fn create_note<'a>( &'a self, - note: impl IntoDiagnostic<'a, Noted>, - ) -> DiagnosticBuilder<'a, Noted> { + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { note.into_diagnostic(&self.dcx, Level::Note) } #[track_caller] - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { self.create_note(note).emit() } #[track_caller] pub fn create_fatal<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, !>, - ) -> DiagnosticBuilder<'a, !> { + fatal: impl IntoDiagnostic<'a, FatalAbort>, + ) -> DiagnosticBuilder<'a, FatalAbort> { fatal.into_diagnostic(&self.dcx, Level::Fatal) } #[track_caller] - pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { + pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { self.create_fatal(fatal).emit() } @@ -386,7 +386,10 @@ impl ParseSess { #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal( + &self, + msg: impl Into, + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx.struct_fatal(msg) } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 7f168572f7d..c9f0f74b0b2 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -23,8 +23,8 @@ use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{ error_code, fallback_fluent_bundle, DiagCtxt, DiagnosticBuilder, DiagnosticId, - DiagnosticMessage, ErrorGuaranteed, FluentBundle, IntoDiagnostic, LazyFallbackBundle, - MultiSpan, Noted, TerminalUrl, + DiagnosticMessage, ErrorGuaranteed, FatalAbort, FluentBundle, IntoDiagnostic, + LazyFallbackBundle, MultiSpan, TerminalUrl, }; use rustc_macros::HashStable_Generic; pub use rustc_span::def_id::StableCrateId; @@ -428,7 +428,7 @@ impl Session { &self, sp: S, msg: impl Into, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx().struct_span_fatal(sp, msg) } #[rustc_lint_diagnostics] @@ -437,11 +437,14 @@ impl Session { sp: S, msg: impl Into, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx().struct_span_fatal_with_code(sp, msg, code) } #[rustc_lint_diagnostics] - pub fn struct_fatal(&self, msg: impl Into) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal( + &self, + msg: impl Into, + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx().struct_fatal(msg) } @@ -525,23 +528,23 @@ impl Session { #[track_caller] pub fn create_note<'a>( &'a self, - note: impl IntoDiagnostic<'a, Noted>, - ) -> DiagnosticBuilder<'a, Noted> { + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { self.parse_sess.create_note(note) } #[track_caller] - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { self.parse_sess.emit_note(note) } #[track_caller] pub fn create_fatal<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, !>, - ) -> DiagnosticBuilder<'a, !> { + fatal: impl IntoDiagnostic<'a, FatalAbort>, + ) -> DiagnosticBuilder<'a, FatalAbort> { self.parse_sess.create_fatal(fatal) } #[track_caller] - pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { + pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { self.parse_sess.emit_fatal(fatal) } #[inline] @@ -1780,7 +1783,7 @@ impl EarlyDiagCtxt { pub fn early_struct_error( &self, msg: impl Into, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { self.dcx.struct_fatal(msg) } From 9ed87336b07d26776470218e316e2df5bc9f4112 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Dec 2023 17:02:37 +1100 Subject: [PATCH 07/10] Factor out common `emit_producing_guarantee` code. --- .../rustc_errors/src/diagnostic_builder.rs | 64 ++++++------------- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 1c83250e017..828560ec452 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -112,6 +112,22 @@ pub trait EmissionGuarantee: Sized { fn emit_producing_guarantee(db: &mut 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) { + match self.inner.state { + // First `.emit()` call, the `&DiagCtxt` is still available. + DiagnosticBuilderState::Emittable(dcx) => { + self.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + + dcx.emit_diagnostic_without_consuming(&mut self.inner.diagnostic); + } + // `.emit()` was previously called, disallowed from repeating it. + DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + } + } +} + impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { /// Discard the guarantee `.emit()` would return, in favor of having the /// type `DiagnosticBuilder<'a, ()>`. This may be necessary whenever there @@ -124,6 +140,7 @@ impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. impl EmissionGuarantee for ErrorGuaranteed { fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { + // Contrast this with `emit_producing_nothing`. match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -165,16 +182,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 { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } + db.emit_producing_nothing(); } } @@ -187,17 +195,7 @@ impl EmissionGuarantee for BugAbort { type EmitResult = !; fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - // Then panic. No need to return the marker type. + db.emit_producing_nothing(); panic::panic_any(ExplicitBug); } } @@ -211,34 +209,14 @@ impl EmissionGuarantee for FatalAbort { type EmitResult = !; fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - // Then fatally error, returning `!` + 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 { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - // Then fatally error.. + db.emit_producing_nothing(); rustc_span::fatal_error::FatalError } } From 072c157d680a0838b25bf1d7cb33c373945dc6db Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 18 Dec 2023 17:05:01 +1100 Subject: [PATCH 08/10] Introduce `DiagCtxt::struct_bug`. This makes `DiagCtxt::bug` look like the other similar functions. --- compiler/rustc_errors/src/lib.rs | 10 +++++++++- compiler/rustc_expand/src/base.rs | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 93813458718..ae086153647 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -961,6 +961,13 @@ impl DiagCtxt { DiagnosticBuilder::new(self, Level::Note, msg) } + /// Construct a builder at the `Bug` level with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_bug(&self, msg: impl Into) -> DiagnosticBuilder<'_, BugAbort> { + DiagnosticBuilder::new(self, Level::Bug, msg) + } + #[rustc_lint_diagnostics] #[track_caller] pub fn span_fatal(&self, span: impl Into, msg: impl Into) -> ! { @@ -1104,8 +1111,9 @@ impl DiagCtxt { self.struct_note(msg).emit() } + #[rustc_lint_diagnostics] pub fn bug(&self, msg: impl Into) -> ! { - DiagnosticBuilder::::new(self, Bug, msg).emit() + self.struct_bug(msg).emit() } #[inline] diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 5aeb5e61cd7..ee0b10edfda 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1159,6 +1159,7 @@ impl<'a> ExtCtxt<'a> { // Fixme: does this result in errors? self.expansions.clear(); } + #[rustc_lint_diagnostics] pub fn bug(&self, msg: &'static str) -> ! { self.sess.dcx().bug(msg); } From 286329870dbae9c9e0f61f0c7a5d3d3963ce9f6a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 19 Dec 2023 07:47:39 +1100 Subject: [PATCH 09/10] De-weirdify `fatally_break_rust`. The easter egg ICE on `break rust` is weird: it's the one ICE in the entire compiler that doesn't immediately abort, which makes it annoyingly inconsistent. This commit changes it to abort. As part of this, the extra notes are now appended onto the bug dignostic, rather than being printed as individual note diagnostics, which changes the output format a bit. These changes don't interferes with the joke, but they do help with my ongoing cleanups to error handling. --- compiler/rustc_errors/src/lib.rs | 13 +++++++++++++ compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 19 ++++++++++--------- tests/ui/track-diagnostics/track.rs | 2 ++ tests/ui/track-diagnostics/track.stderr | 20 ++++++++++++++++++-- 5 files changed, 44 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index ae086153647..7dd9bd9c765 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -968,6 +968,19 @@ impl DiagCtxt { DiagnosticBuilder::new(self, Level::Bug, msg) } + /// Construct a builder at the `Bug` level at the given `span` with the `msg`. + #[rustc_lint_diagnostics] + #[track_caller] + pub fn struct_span_bug( + &self, + span: impl Into, + msg: impl Into, + ) -> DiagnosticBuilder<'_, BugAbort> { + let mut result = self.struct_bug(msg); + result.set_span(span); + result + } + #[rustc_lint_diagnostics] #[track_caller] pub fn span_fatal(&self, span: impl Into, msg: impl Into) -> ! { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7bd2c3f8b6b..5d5b5f39ccf 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -722,7 +722,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let [segment] = path.segments && segment.ident.name == sym::rust { - fatally_break_rust(self.tcx); + fatally_break_rust(self.tcx, expr.span); } } } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 13a24948611..c6d7650f745 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -52,7 +52,7 @@ use crate::expectation::Expectation; use crate::fn_ctxt::RawTy; use crate::gather_locals::GatherLocalsVisitor; use rustc_data_structures::unord::UnordSet; -use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{struct_span_err, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; @@ -412,24 +412,25 @@ enum TupleArgumentsFlag { TupleArguments, } -fn fatally_break_rust(tcx: TyCtxt<'_>) { +fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! { let dcx = tcx.sess.dcx(); - dcx.span_bug_no_panic( - MultiSpan::new(), + let mut diag = dcx.struct_span_bug( + span, "It looks like you're trying to break rust; would you like some ICE?", ); - dcx.note("the compiler expectedly panicked. this is a feature."); - dcx.note( + diag.note("the compiler expectedly panicked. this is a feature."); + diag.note( "we would appreciate a joke overview: \ https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675", ); - dcx.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),)); + diag.note(format!("rustc {} running on {}", tcx.sess.cfg_version, config::host_triple(),)); if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() { - dcx.note(format!("compiler flags: {}", flags.join(" "))); + diag.note(format!("compiler flags: {}", flags.join(" "))); if excluded_cargo_defaults { - dcx.note("some of the compiler flags provided by cargo are hidden"); + diag.note("some of the compiler flags provided by cargo are hidden"); } } + diag.emit() } /// `expected` here is the expected number of explicit generic arguments on the trait. diff --git a/tests/ui/track-diagnostics/track.rs b/tests/ui/track-diagnostics/track.rs index 97bd7789a63..08f926610d7 100644 --- a/tests/ui/track-diagnostics/track.rs +++ b/tests/ui/track-diagnostics/track.rs @@ -1,5 +1,7 @@ // compile-flags: -Z track-diagnostics // error-pattern: created at +// rustc-env:RUST_BACKTRACE=0 +// failure-status: 101 // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. diff --git a/tests/ui/track-diagnostics/track.stderr b/tests/ui/track-diagnostics/track.stderr index 60254dc475b..54b1ea2764a 100644 --- a/tests/ui/track-diagnostics/track.stderr +++ b/tests/ui/track-diagnostics/track.stderr @@ -13,15 +13,31 @@ LL | break rust -Ztrack-diagnostics: created at compiler/rustc_passes/src/loops.rs:LL:CC error: internal compiler error: It looks like you're trying to break rust; would you like some ICE? + --> $DIR/track.rs:LL:CC + | +LL | break rust + | ^^^^^^^^^^ +-Ztrack-diagnostics: created at compiler/rustc_hir_typeck/src/lib.rs:LL:CC + | + = note: the compiler expectedly panicked. this is a feature. + = note: we would appreciate a joke overview: https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675 + = note: rustc $VERSION running on $TARGET + = note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics -note: the compiler expectedly panicked. this is a feature. +thread 'rustc' panicked at compiler/rustc_hir_typeck/src/lib.rs:LL:CC: +Box +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -note: we would appreciate a joke overview: https://github.com/rust-lang/rust/issues/43162#issuecomment-320764675 +note: we would appreciate a bug report: https://github.com/rust-lang/rust/issues/new?labels=C-bug%2C+I-ICE%2C+T-compiler&template=ice.md note: rustc $VERSION running on $TARGET note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics +query stack during panic: +#0 [typeck] type-checking `main` +#1 [analysis] running analysis passes on this crate +end of query stack error: aborting due to 3 previous errors Some errors have detailed explanations: E0268, E0425. From 006446e373eae84f585d17a9945fe75a5f56c37e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 19 Dec 2023 09:50:29 +1100 Subject: [PATCH 10/10] Remove unused `DiagCtxt::span_bug_no_panic`. --- compiler/rustc_errors/src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 7dd9bd9c765..518a2ddb71d 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1079,13 +1079,6 @@ impl DiagCtxt { inner.good_path_delayed_bugs.push(DelayedDiagnostic::with_backtrace(diagnostic, backtrace)); } - #[track_caller] - pub fn span_bug_no_panic(&self, span: impl Into, msg: impl Into) { - let mut diag = Diagnostic::new(Bug, msg); - diag.set_span(span); - self.emit_diagnostic(diag); - } - #[track_caller] #[rustc_lint_diagnostics] pub fn span_note(&self, span: impl Into, msg: impl Into) {