diff --git a/Cargo.lock b/Cargo.lock index 6009b11f904..ef4800a2261 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4158,6 +4158,7 @@ dependencies = [ "rustc_errors", "rustc_feature", "rustc_lexer", + "rustc_macros", "rustc_session", "rustc_span", "tracing", diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl index 24e59a93cea..3143b81b609 100644 --- a/compiler/rustc_error_messages/locales/en-US/parser.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl @@ -1,3 +1,7 @@ parser-struct-literal-body-without-path = struct literal body without path .suggestion = you might have forgotten to add the struct literal inside the block + +parser-maybe-report-ambiguous-plus = + ambiguous `+` in a type + .suggestion = use parentheses to disambiguate diff --git a/compiler/rustc_macros/src/session_diagnostic.rs b/compiler/rustc_macros/src/session_diagnostic.rs index ff7506979fc..9466d0f34bc 100644 --- a/compiler/rustc_macros/src/session_diagnostic.rs +++ b/compiler/rustc_macros/src/session_diagnostic.rs @@ -308,7 +308,7 @@ fn into_tokens(self) -> proc_macro2::TokenStream { { fn into_diagnostic( self, - #sess: &'__session_diagnostic_sess rustc_session::Session + #sess: &'__session_diagnostic_sess rustc_session::parse::ParseSess ) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, #param_ty> { use rustc_errors::IntoDiagnosticArg; #implementation diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml index a823607ab0e..c6ca260e983 100644 --- a/compiler/rustc_parse/Cargo.toml +++ b/compiler/rustc_parse/Cargo.toml @@ -13,6 +13,7 @@ rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_feature = { path = "../rustc_feature" } rustc_lexer = { path = "../rustc_lexer" } +rustc_macros = { path = "../rustc_macros" } rustc_errors = { path = "../rustc_errors" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index acc0d7a6ee0..63772c098b5 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -21,6 +21,7 @@ use rustc_errors::{ Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult, }; +use rustc_macros::SessionDiagnostic; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, Ident}; use rustc_span::{Span, SpanSnippetError, DUMMY_SP}; @@ -241,6 +242,16 @@ fn emit_many( err.multipart_suggestions(msg, suggestions.map(|s| s.patches), applicability); } } + +#[derive(SessionDiagnostic)] +#[error(slug = "parser-maybe-report-ambiguous-plus")] +struct AmbiguousPlus { + pub sum_ty: String, + #[primary_span] + #[suggestion(code = "({sum_ty})")] + pub span: Span, +} + // SnapshotParser is used to create a snapshot of the parser // without causing duplicate errors being emitted when the `Parser` // is dropped. @@ -1196,15 +1207,7 @@ pub(super) fn maybe_report_ambiguous_plus( ty: &Ty, ) { if matches!(allow_plus, AllowPlus::No) && impl_dyn_multi { - let sum_with_parens = format!("({})", pprust::ty_to_string(&ty)); - self.struct_span_err(ty.span, "ambiguous `+` in a type") - .span_suggestion( - ty.span, - "use parentheses to disambiguate", - sum_with_parens, - Applicability::MachineApplicable, - ) - .emit(); + self.sess.emit_err(AmbiguousPlus { sum_ty: pprust::ty_to_string(&ty), span: ty.span }); } } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 6a36ae63c68..e933fe1cb24 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -3,13 +3,14 @@ use crate::config::CheckCfg; use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId}; +use crate::SessionDiagnostic; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{ error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, - ErrorGuaranteed, MultiSpan, + DiagnosticMessage, ErrorGuaranteed, MultiSpan, }; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; use rustc_span::edition::Edition; @@ -287,4 +288,23 @@ pub fn save_proc_macro_span(&self, span: Span) -> usize { pub fn proc_macro_quoted_spans(&self) -> Vec { self.proc_macro_quoted_spans.lock().clone() } + + pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed { + err.into_diagnostic(self).emit() + } + + pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) { + warning.into_diagnostic(self).emit() + } + + pub fn struct_err( + &self, + msg: impl Into, + ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + self.span_diagnostic.struct_err(msg) + } + + pub fn struct_warn(&self, msg: impl Into) -> DiagnosticBuilder<'_, ()> { + self.span_diagnostic.struct_warn(msg) + } } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index b4548129689..e8279f6fed2 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -212,7 +212,7 @@ pub struct PerfStats { pub trait SessionDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> { /// Write out as a diagnostic out of `sess`. #[must_use] - fn into_diagnostic(self, sess: &'a Session) -> DiagnosticBuilder<'a, T>; + fn into_diagnostic(self, sess: &'a ParseSess) -> DiagnosticBuilder<'a, T>; } impl Session { @@ -334,7 +334,7 @@ pub fn struct_err( &self, msg: impl Into, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - self.diagnostic().struct_err(msg) + self.parse_sess.struct_err(msg) } pub fn struct_err_with_code( &self, @@ -414,10 +414,10 @@ pub fn err(&self, msg: impl Into) -> ErrorGuaranteed { self.diagnostic().err(msg) } pub fn emit_err<'a>(&'a self, err: impl SessionDiagnostic<'a>) -> ErrorGuaranteed { - err.into_diagnostic(self).emit() + self.parse_sess.emit_err(err) } pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) { - warning.into_diagnostic(self).emit() + self.parse_sess.emit_warning(warning) } #[inline] pub fn err_count(&self) -> usize {