diff options
Diffstat (limited to 'compiler/rustc_parse/src')
| -rw-r--r-- | compiler/rustc_parse/src/errors.rs | 80 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/lexer/mod.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/lexer/tokentrees.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/lexer/unescape_error_reporting.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/lexer/unicode_chars.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/lib.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/attr_wrapper.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/diagnostics.rs | 87 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 92 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/mod.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/nonterminal.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/pat.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/path.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/stmt.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 76 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/validate_attr.rs | 6 |
18 files changed, 272 insertions, 270 deletions
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index c51a5c095ee..53cce9e2883 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, IntoDiagnostic, Level, + SubdiagnosticMessage, +}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; @@ -1040,25 +1043,28 @@ pub(crate) struct ExpectedIdentifier { impl<'a> IntoDiagnostic<'a> for ExpectedIdentifier { #[track_caller] - fn into_diagnostic( - self, - handler: &'a rustc_errors::Handler, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> { let token_descr = TokenDescription::from_token(&self.token); - let mut diag = handler.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); @@ -1097,23 +1103,26 @@ pub(crate) struct ExpectedSemi { impl<'a> IntoDiagnostic<'a> for ExpectedSemi { #[track_caller] - fn into_diagnostic( - self, - handler: &'a rustc_errors::Handler, - ) -> rustc_errors::DiagnosticBuilder<'a, ErrorGuaranteed> { + fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> DiagnosticBuilder<'a> { let token_descr = TokenDescription::from_token(&self.token); - let mut diag = handler.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 +1445,7 @@ pub(crate) struct FnTraitMissingParen { impl AddToDiagnostic for FnTraitMissingParen { fn add_to_diagnostic_with<F>(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_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index b1dc1f98777..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}; @@ -227,7 +229,7 @@ impl<'a> StringReader<'a> { let string = self.str_from(suffix_start); if string == "_" { self.sess - .span_diagnostic + .dcx .emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) }); None } else { @@ -344,9 +346,9 @@ impl<'a> StringReader<'a> { to_pos: BytePos, m: &str, c: char, - ) -> DiagnosticBuilder<'a, !> { + ) -> DiagnosticBuilder<'a, FatalAbort> { self.sess - .span_diagnostic + .dcx .struct_span_fatal(self.mk_sp(from_pos, to_pos), format!("{}: {}", m, escaped_char(c))) } @@ -403,7 +405,7 @@ impl<'a> StringReader<'a> { match kind { rustc_lexer::LiteralKind::Char { terminated } => { if !terminated { - self.sess.span_diagnostic.span_fatal_with_code( + self.sess.dcx.span_fatal_with_code( self.mk_sp(start, end), "unterminated character literal", error_code!(E0762), @@ -413,7 +415,7 @@ impl<'a> StringReader<'a> { } rustc_lexer::LiteralKind::Byte { terminated } => { if !terminated { - self.sess.span_diagnostic.span_fatal_with_code( + self.sess.dcx.span_fatal_with_code( self.mk_sp(start + BytePos(1), end), "unterminated byte constant", error_code!(E0763), @@ -423,7 +425,7 @@ impl<'a> StringReader<'a> { } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { - self.sess.span_diagnostic.span_fatal_with_code( + self.sess.dcx.span_fatal_with_code( self.mk_sp(start, end), "unterminated double quote string", error_code!(E0765), @@ -433,7 +435,7 @@ impl<'a> StringReader<'a> { } rustc_lexer::LiteralKind::ByteStr { terminated } => { if !terminated { - self.sess.span_diagnostic.span_fatal_with_code( + self.sess.dcx.span_fatal_with_code( self.mk_sp(start + BytePos(1), end), "unterminated double quote byte string", error_code!(E0766), @@ -443,7 +445,7 @@ impl<'a> StringReader<'a> { } rustc_lexer::LiteralKind::CStr { terminated } => { if !terminated { - self.sess.span_diagnostic.span_fatal_with_code( + self.sess.dcx.span_fatal_with_code( self.mk_sp(start + BytePos(1), end), "unterminated C string", error_code!(E0767), @@ -578,7 +580,7 @@ impl<'a> StringReader<'a> { possible_offset: Option<u32>, found_terminators: u32, ) -> ! { - let mut err = self.sess.span_diagnostic.struct_span_fatal_with_code( + let mut err = self.sess.dcx.struct_span_fatal_with_code( self.mk_sp(start, start), "unterminated raw string", error_code!(E0748), @@ -614,7 +616,7 @@ impl<'a> StringReader<'a> { None => "unterminated block comment", }; let last_bpos = self.pos; - let mut err = self.sess.span_diagnostic.struct_span_fatal_with_code( + let mut err = self.sess.dcx.struct_span_fatal_with_code( self.mk_sp(start, last_bpos), msg, error_code!(E0758), @@ -719,7 +721,7 @@ impl<'a> StringReader<'a> { has_fatal_err = true; } emit_unescape_error( - &self.sess.span_diagnostic, + &self.sess.dcx, lit_content, span_with_quotes, span, diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index 8cbadc26635..2bc2789a4f7 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -73,7 +73,7 @@ impl<'a> TokenTreesReader<'a> { fn eof_err(&mut self) -> PErr<'a> { let msg = "this file contains an unclosed delimiter"; - let mut err = self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg); + let mut err = self.string_reader.sess.dcx.struct_span_err(self.token.span, msg); for &(_, sp) in &self.diag_info.open_braces { err.span_label(sp, "unclosed delimiter"); self.diag_info.unmatched_delims.push(UnmatchedDelim { @@ -290,7 +290,7 @@ impl<'a> TokenTreesReader<'a> { // matching opening delimiter). let token_str = token_to_string(&self.token); let msg = format!("unexpected closing delimiter: `{token_str}`"); - let mut err = self.string_reader.sess.span_diagnostic.struct_span_err(self.token.span, msg); + let mut err = self.string_reader.sess.dcx.struct_span_err(self.token.span, msg); report_suspicious_mismatch_block( &mut err, diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 2b4c2e3c250..775082adbe8 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -3,14 +3,14 @@ use std::iter::once; use std::ops::Range; -use rustc_errors::{Applicability, Handler}; +use rustc_errors::{Applicability, DiagCtxt}; use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; use crate::errors::{MoreThanOneCharNote, MoreThanOneCharSugg, NoBraceUnicodeSub, UnescapeError}; pub(crate) fn emit_unescape_error( - handler: &Handler, + dcx: &DiagCtxt, // interior part of the literal, between quotes lit: &str, // full span of the literal, including quotes and any prefix @@ -33,12 +33,10 @@ pub(crate) fn emit_unescape_error( }; match error { EscapeError::LoneSurrogateUnicodeEscape => { - handler - .emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: true }); + dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: true }); } EscapeError::OutOfRangeUnicodeEscape => { - handler - .emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: false }); + dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: false }); } EscapeError::MoreThanOneChar => { use unicode_normalization::{char::is_combining_mark, UnicodeNormalization}; @@ -104,7 +102,7 @@ pub(crate) fn emit_unescape_error( sugg, } }); - handler.emit_err(UnescapeError::MoreThanOneChar { + dcx.emit_err(UnescapeError::MoreThanOneChar { span: full_lit_span, note, suggestion: sugg, @@ -112,7 +110,7 @@ pub(crate) fn emit_unescape_error( } EscapeError::EscapeOnlyChar => { let (c, char_span) = last_char(); - handler.emit_err(UnescapeError::EscapeOnlyChar { + dcx.emit_err(UnescapeError::EscapeOnlyChar { span: err_span, char_span, escaped_sugg: c.escape_default().to_string(), @@ -122,11 +120,11 @@ pub(crate) fn emit_unescape_error( } EscapeError::BareCarriageReturn => { let double_quotes = mode.in_double_quotes(); - handler.emit_err(UnescapeError::BareCr { span: err_span, double_quotes }); + dcx.emit_err(UnescapeError::BareCr { span: err_span, double_quotes }); } EscapeError::BareCarriageReturnInRawString => { assert!(mode.in_double_quotes()); - handler.emit_err(UnescapeError::BareCrRawString(err_span)); + dcx.emit_err(UnescapeError::BareCrRawString(err_span)); } EscapeError::InvalidEscape => { let (c, span) = last_char(); @@ -137,7 +135,7 @@ pub(crate) fn emit_unescape_error( "unknown character escape" }; let ec = escaped_char(c); - let mut diag = handler.struct_span_err(span, format!("{label}: `{ec}`")); + let mut diag = dcx.struct_span_err(span, format!("{label}: `{ec}`")); diag.span_label(span, label); if c == '{' || c == '}' && matches!(mode, Mode::Str | Mode::RawStr) { diag.help( @@ -166,13 +164,13 @@ pub(crate) fn emit_unescape_error( diag.emit(); } EscapeError::TooShortHexEscape => { - handler.emit_err(UnescapeError::TooShortHexEscape(err_span)); + dcx.emit_err(UnescapeError::TooShortHexEscape(err_span)); } EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => { let (c, span) = last_char(); let is_hex = error == EscapeError::InvalidCharInHexEscape; let ch = escaped_char(c); - handler.emit_err(UnescapeError::InvalidCharInEscape { span, is_hex, ch }); + dcx.emit_err(UnescapeError::InvalidCharInEscape { span, is_hex, ch }); } EscapeError::NonAsciiCharInByte => { let (c, span) = last_char(); @@ -182,7 +180,7 @@ pub(crate) fn emit_unescape_error( Mode::RawByteStr => "raw byte string literal", _ => panic!("non-is_byte literal paired with NonAsciiCharInByte"), }; - let mut err = handler.struct_span_err(span, format!("non-ASCII character in {desc}")); + let mut err = dcx.struct_span_err(span, format!("non-ASCII character in {desc}")); let postfix = if unicode_width::UnicodeWidthChar::width(c).unwrap_or(1) == 0 { format!(" but is {c:?}") } else { @@ -218,21 +216,20 @@ pub(crate) fn emit_unescape_error( err.emit(); } EscapeError::OutOfRangeHexEscape => { - handler.emit_err(UnescapeError::OutOfRangeHexEscape(err_span)); + dcx.emit_err(UnescapeError::OutOfRangeHexEscape(err_span)); } EscapeError::LeadingUnderscoreUnicodeEscape => { let (c, span) = last_char(); - handler.emit_err(UnescapeError::LeadingUnderscoreUnicodeEscape { + dcx.emit_err(UnescapeError::LeadingUnderscoreUnicodeEscape { span, ch: escaped_char(c), }); } EscapeError::OverlongUnicodeEscape => { - handler.emit_err(UnescapeError::OverlongUnicodeEscape(err_span)); + dcx.emit_err(UnescapeError::OverlongUnicodeEscape(err_span)); } EscapeError::UnclosedUnicodeEscape => { - handler - .emit_err(UnescapeError::UnclosedUnicodeEscape(err_span, err_span.shrink_to_hi())); + dcx.emit_err(UnescapeError::UnclosedUnicodeEscape(err_span, err_span.shrink_to_hi())); } EscapeError::NoBraceInUnicodeEscape => { let mut suggestion = "\\u{".to_owned(); @@ -251,30 +248,30 @@ pub(crate) fn emit_unescape_error( } else { (Some(err_span), NoBraceUnicodeSub::Help) }; - handler.emit_err(UnescapeError::NoBraceInUnicodeEscape { span: err_span, label, sub }); + dcx.emit_err(UnescapeError::NoBraceInUnicodeEscape { span: err_span, label, sub }); } EscapeError::UnicodeEscapeInByte => { - handler.emit_err(UnescapeError::UnicodeEscapeInByte(err_span)); + dcx.emit_err(UnescapeError::UnicodeEscapeInByte(err_span)); } EscapeError::EmptyUnicodeEscape => { - handler.emit_err(UnescapeError::EmptyUnicodeEscape(err_span)); + dcx.emit_err(UnescapeError::EmptyUnicodeEscape(err_span)); } EscapeError::ZeroChars => { - handler.emit_err(UnescapeError::ZeroChars(err_span)); + dcx.emit_err(UnescapeError::ZeroChars(err_span)); } EscapeError::LoneSlash => { - handler.emit_err(UnescapeError::LoneSlash(err_span)); + dcx.emit_err(UnescapeError::LoneSlash(err_span)); } EscapeError::UnskippedWhitespaceWarning => { let (c, char_span) = last_char(); - handler.emit_warning(UnescapeError::UnskippedWhitespace { + dcx.emit_warning(UnescapeError::UnskippedWhitespace { span: err_span, ch: escaped_char(c), char_span, }); } EscapeError::MultipleSkippedLinesWarning => { - handler.emit_warning(UnescapeError::MultipleSkippedLinesWarning(err_span)); + dcx.emit_warning(UnescapeError::MultipleSkippedLinesWarning(err_span)); } } } diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index 0dc60688955..dac7569e385 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -350,7 +350,7 @@ pub(super) fn check_for_substitution( let Some((_, ascii_name, token)) = ASCII_ARRAY.iter().find(|&&(s, _, _)| s == ascii_str) else { let msg = format!("substitution character not found for '{ch}'"); - reader.sess.span_diagnostic.span_bug(span, msg); + reader.sess.dcx.span_bug(span, msg); }; // special help suggestion for "directed" double quotes diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 9887a85e6a4..82b0ff70c16 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -100,7 +100,7 @@ pub fn parse_stream_from_source_str( /// Creates a new parser from a source string. pub fn new_parser_from_source_str(sess: &ParseSess, name: FileName, source: String) -> Parser<'_> { - panictry_buffer!(&sess.span_diagnostic, maybe_new_parser_from_source_str(sess, name, source)) + panictry_buffer!(&sess.dcx, maybe_new_parser_from_source_str(sess, name, source)) } /// Creates a new parser from a source string. Returns any buffered errors from lexing the initial @@ -121,7 +121,7 @@ pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, sp: Option<Spa /// Given a session and a `source_file`, returns a parser. fn source_file_to_parser(sess: &ParseSess, source_file: Lrc<SourceFile>) -> Parser<'_> { - panictry_buffer!(&sess.span_diagnostic, maybe_source_file_to_parser(sess, source_file)) + panictry_buffer!(&sess.dcx, maybe_source_file_to_parser(sess, source_file)) } /// Given a session and a `source_file`, return a parser. Returns any buffered errors from lexing the @@ -166,7 +166,7 @@ fn file_to_source_file(sess: &ParseSess, path: &Path, spanopt: Option<Span>) -> match try_file_to_source_file(sess, path, spanopt) { Ok(source_file) => source_file, Err(d) => { - sess.span_diagnostic.emit_diagnostic(d); + sess.dcx.emit_diagnostic(d); FatalError.raise(); } } @@ -178,7 +178,7 @@ pub fn source_file_to_stream( source_file: Lrc<SourceFile>, override_span: Option<Span>, ) -> TokenStream { - panictry_buffer!(&sess.span_diagnostic, maybe_file_to_stream(sess, source_file, override_span)) + panictry_buffer!(&sess.dcx, maybe_file_to_stream(sess, source_file, override_span)) } /// Given a source file, produces a sequence of token trees. Returns any buffered errors from @@ -189,7 +189,7 @@ pub fn maybe_file_to_stream( override_span: Option<Span>, ) -> Result<TokenStream, Vec<Diagnostic>> { let src = source_file.src.as_ref().unwrap_or_else(|| { - sess.span_diagnostic.bug(format!( + sess.dcx.bug(format!( "cannot lex `source_file` without source: {}", sess.source_map().filename_for_diagnostics(&source_file.name) )); diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index c9ce896b868..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; @@ -55,7 +55,7 @@ impl<'a> Parser<'a> { } else if let token::DocComment(comment_kind, attr_style, data) = self.token.kind { if attr_style != ast::AttrStyle::Outer { let span = self.token.span; - let mut err = self.diagnostic().struct_span_err_with_code( + let mut err = self.dcx().struct_span_err_with_code( span, fluent::parse_inner_doc_comment_not_permitted, error_code!(E0753), @@ -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.diagnostic())) + Err(self + .dcx() + .create_err(InvalidMetaItem { span: self.token.span, token: self.token.clone() })) } } diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs index 5e8447030f1..2307f4cfffa 100644 --- a/compiler/rustc_parse/src/parser/attr_wrapper.rs +++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs @@ -41,7 +41,7 @@ impl AttrWrapper { } pub(crate) fn take_for_recovery(self, sess: &ParseSess) -> AttrVec { - sess.span_diagnostic.span_delayed_bug( + sess.dcx.span_delayed_bug( self.attrs.get(0).map(|attr| attr.span).unwrap_or(DUMMY_SP), "AttrVec is taken for recovery but no error is produced", ); @@ -266,8 +266,7 @@ impl<'a> Parser<'a> { if let Some(attr_range) = self.capture_state.inner_attr_ranges.remove(&inner_attr.id) { inner_attr_replace_ranges.push(attr_range); } else { - self.diagnostic() - .span_delayed_bug(inner_attr.span, "Missing token range for attribute"); + self.dcx().span_delayed_bug(inner_attr.span, "Missing token range for attribute"); } } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 221fc70d9ff..4d557e495d8 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -10,13 +10,13 @@ use crate::errors::{ ConstGenericWithoutBracesSugg, DocCommentDoesNotDocumentAnything, DocCommentOnParamType, DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, - HelpIdentifierStartsWithNumber, InInTypo, IncorrectAwait, IncorrectSemicolon, - IncorrectUseOfAwait, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, - SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, - StructLiteralNeedingParens, StructLiteralNeedingParensSugg, SuggAddMissingLetStmt, - SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, UnexpectedConstInGenericParam, - UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, - UseEqInstead, WrapType, + HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait, + IncorrectSemicolon, IncorrectUseOfAwait, PatternMethodParamWithoutBody, QuestionMarkInType, + QuestionMarkInTypeSugg, SelfParamNotFirst, StructLiteralBodyWithoutPath, + StructLiteralBodyWithoutPathSugg, StructLiteralNeedingParens, StructLiteralNeedingParensSugg, + SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, + UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, + UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; use crate::fluent_generated as fluent; use crate::parser; @@ -34,8 +34,8 @@ use rustc_ast::{ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ - pluralize, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, - ErrorGuaranteed, FatalError, Handler, IntoDiagnostic, MultiSpan, PResult, + pluralize, AddToDiagnostic, Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, + DiagnosticMessage, FatalError, MultiSpan, PResult, }; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::Spanned; @@ -245,16 +245,16 @@ impl<'a> Parser<'a> { &self, sp: S, m: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - self.diagnostic().struct_span_err(sp, m) + ) -> DiagnosticBuilder<'a> { + self.dcx().struct_span_err(sp, m) } pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: impl Into<DiagnosticMessage>) -> ! { - self.diagnostic().span_bug(sp, msg) + self.dcx().span_bug(sp, msg) } - pub(super) fn diagnostic(&self) -> &'a Handler { - &self.sess.span_diagnostic + pub(super) fn dcx(&self) -> &'a DiagCtxt { + &self.sess.dcx } /// Replace `self` with `snapshot.parser`. @@ -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.diagnostic())); + })); } 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.diagnostic()); + let mut err = self.dcx().create_err(err); // if the token we have is a `<` // it *might* be a misplaced generic @@ -414,7 +413,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn expected_ident_found_err(&mut self) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + pub(super) fn expected_ident_found_err(&mut self) -> DiagnosticBuilder<'a> { self.expected_ident_found(false).unwrap_err() } @@ -640,6 +639,28 @@ impl<'a> Parser<'a> { } } + // Try to detect an intended c-string literal while using a pre-2021 edition. The heuristic + // here is to identify a cooked, uninterpolated `c` id immediately followed by a string, or + // a cooked, uninterpolated `cr` id immediately followed by a string or a `#`, in an edition + // where c-string literals are not allowed. There is the very slight possibility of a false + // positive for a `cr#` that wasn't intended to start a c-string literal, but identifying + // that in the parser requires unbounded lookahead, so we only add a hint to the existing + // error rather than replacing it entirely. + if ((self.prev_token.kind == TokenKind::Ident(sym::c, false) + && matches!(&self.token.kind, TokenKind::Literal(token::Lit { kind: token::Str, .. }))) + || (self.prev_token.kind == TokenKind::Ident(sym::cr, false) + && matches!( + &self.token.kind, + TokenKind::Literal(token::Lit { kind: token::Str, .. }) | token::Pound + ))) + && self.prev_token.span.hi() == self.token.span.lo() + && !self.token.span.at_least_rust_2021() + { + err.note("you may be trying to write a c-string literal"); + err.note("c-string literals require Rust 2021 or later"); + HelpUseLatestEdition::new().add_to_diagnostic(&mut err); + } + // `pub` may be used for an item or `pub(crate)` if self.prev_token.is_ident_named(sym::public) && (self.token.can_begin_item() @@ -937,7 +958,7 @@ impl<'a> Parser<'a> { pub(super) fn recover_closure_body( &mut self, - mut err: DiagnosticBuilder<'a, ErrorGuaranteed>, + mut err: DiagnosticBuilder<'a>, before: token::Token, prev: token::Token, token: token::Token, @@ -1168,7 +1189,7 @@ impl<'a> Parser<'a> { /// encounter a parse error when encountering the first `,`. pub(super) fn check_mistyped_turbofish_with_multiple_type_params( &mut self, - mut e: DiagnosticBuilder<'a, ErrorGuaranteed>, + mut e: DiagnosticBuilder<'a>, expr: &mut P<Expr>, ) -> PResult<'a, ()> { if let ExprKind::Binary(binop, _, _) = &expr.kind @@ -1213,10 +1234,7 @@ impl<'a> Parser<'a> { /// Suggest add the missing `let` before the identifier in stmt /// `a: Ty = 1` -> `let a: Ty = 1` - pub(super) fn suggest_add_missing_let_for_stmt( - &mut self, - err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>, - ) { + pub(super) fn suggest_add_missing_let_for_stmt(&mut self, err: &mut DiagnosticBuilder<'a>) { if self.token == token::Colon { let prev_span = self.prev_token.span.shrink_to_lo(); let snapshot = self.create_snapshot_for_diagnostic(); @@ -1410,7 +1428,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.diagnostic())) + Err(self.dcx().create_err(err)) } } } else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind { @@ -1425,7 +1443,7 @@ impl<'a> Parser<'a> { } // Consume the fn call arguments. match self.consume_fn_args() { - Err(()) => Err(err.into_diagnostic(self.diagnostic())), + 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 +1469,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.diagnostic())) + Err(self.dcx().create_err(err)) } }; } @@ -2299,7 +2317,7 @@ impl<'a> Parser<'a> { } } - pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a> { let (span, msg) = match (&self.token.kind, self.subparser_name) { (&token::Eof, Some(origin)) => { let sp = self.prev_token.span.shrink_to_hi(); @@ -2539,7 +2557,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.diagnostic())).map(Some) + self.recover_const_arg(after_kw_const, self.dcx().create_err(err)).map(Some) } } @@ -2551,7 +2569,7 @@ impl<'a> Parser<'a> { pub fn recover_const_arg( &mut self, start: Span, - mut err: DiagnosticBuilder<'a, ErrorGuaranteed>, + mut err: DiagnosticBuilder<'a>, ) -> PResult<'a, GenericArg> { let is_op_or_dot = AssocOp::from_token(&self.token) .and_then(|op| { @@ -2653,7 +2671,7 @@ impl<'a> Parser<'a> { /// Creates a dummy const argument, and reports that the expression must be enclosed in braces pub fn dummy_const_arg_needs_braces( &self, - mut err: DiagnosticBuilder<'a, ErrorGuaranteed>, + mut err: DiagnosticBuilder<'a>, span: Span, ) -> GenericArg { err.multipart_suggestion( @@ -2893,11 +2911,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.diagnostic())); + })); } } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 509cef9826b..a6783eaf8d4 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -10,7 +10,7 @@ use super::{ use crate::errors; use crate::maybe_recover_from_interpolated_ty_qpath; use ast::mut_visit::{noop_visit_expr, MutVisitor}; -use ast::{CoroutineKind, GenBlockKind, Pat, Path, PathSegment}; +use ast::{CoroutineKind, ForLoopKind, GenBlockKind, Pat, Path, PathSegment}; use core::mem; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; @@ -26,8 +26,7 @@ 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, PResult, StashKey, }; use rustc_macros::Subdiagnostic; use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded}; @@ -1255,21 +1254,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.diagnostic()); + 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); @@ -1691,10 +1690,9 @@ impl<'a> Parser<'a> { &self, lifetime: Ident, mk_lit_char: impl FnOnce(Symbol, Span) -> L, - err: impl FnOnce(&Self) -> DiagnosticBuilder<'a, ErrorGuaranteed>, + err: impl FnOnce(&Self) -> DiagnosticBuilder<'a>, ) -> L { - if let Some(mut diag) = - self.diagnostic().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) + if let Some(mut diag) = self.dcx().steal_diagnostic(lifetime.span, StashKey::LifetimeIsChar) { diag.span_suggestion_verbose( lifetime.span.shrink_to_hi(), @@ -1802,7 +1800,7 @@ impl<'a> Parser<'a> { && matches!( expr.kind, ExprKind::While(_, _, None) - | ExprKind::ForLoop(_, _, _, None) + | ExprKind::ForLoop { label: None, .. } | ExprKind::Loop(_, None, _) | ExprKind::Block(_, None) ) @@ -1884,8 +1882,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.diagnostic()); + 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); @@ -1895,8 +1892,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.diagnostic()); + 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))?; @@ -1959,8 +1958,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.diagnostic()); + let mut err = self + .dcx() + .create_err(errors::InvalidInterpolatedExpression { span: self.token.span }); err.downgrade_to_delayed_bug(); return Err(err); } @@ -2169,10 +2169,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.diagnostic())); + })); } Ok(_) => (), Err(err) => err.cancel(), @@ -2319,8 +2319,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.diagnostic())) + Err(self + .dcx() + .create_err(errors::AsyncMoveOrderIncorrect { span: move_async_span })) } else { Ok(CaptureBy::Value { move_kw: move_kw_span }) } @@ -2510,7 +2511,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.diagnostic())); + return Err(self.dcx().create_err(err)); } else { Some(self.sess.emit_err(err)) } @@ -2683,8 +2684,17 @@ impl<'a> Parser<'a> { Ok((pat, expr)) } - /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten). + /// Parses `for await? <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten). fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> { + let is_await = + self.token.uninterpolated_span().at_least_rust_2018() && self.eat_keyword(kw::Await); + + if is_await { + self.sess.gated_spans.gate(sym::async_for_loop, self.prev_token.span); + } + + let kind = if is_await { ForLoopKind::ForAwait } else { ForLoopKind::For }; + let (pat, expr) = self.parse_for_head()?; // Recover from missing expression in `for` loop if matches!(expr.kind, ExprKind::Block(..)) @@ -2697,13 +2707,13 @@ impl<'a> Parser<'a> { let block = self.mk_block(thin_vec![], BlockCheckMode::Default, self.prev_token.span); return Ok(self.mk_expr( lo.to(self.prev_token.span), - ExprKind::ForLoop(pat, err_expr, block, opt_label), + ExprKind::ForLoop { pat, iter: err_expr, body: block, label: opt_label, kind }, )); } let (attrs, loop_block) = self.parse_inner_attrs_and_block()?; - let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label); + let kind = ExprKind::ForLoop { pat, iter: expr, body: loop_block, label: opt_label, kind }; self.recover_loop_else("for", lo)?; @@ -3194,8 +3204,7 @@ impl<'a> Parser<'a> { fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> { 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.diagnostic())) + 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); @@ -3532,12 +3541,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.span_diagnostic)); + })); } let (ident, expr) = if is_shorthand { // Mimic `x: x` for the `x` field shorthand. @@ -3800,7 +3808,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Lit(_) | ExprKind::If(_, _, _) | ExprKind::While(_, _, _) - | ExprKind::ForLoop(_, _, _, _) + | ExprKind::ForLoop { .. } | ExprKind::Loop(_, _, _) | ExprKind::Match(_, _) | ExprKind::Closure(_) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index fd7dad36c9d..051f19f5a9d 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.diagnostic())) } else { Ok(()) } + if let Some(err) = err { Err(self.dcx().create_err(err)) } else { Ok(()) } } fn parse_item_builtin(&mut self) -> PResult<'a, Option<ItemInfo>> { @@ -759,7 +756,7 @@ impl<'a> Parser<'a> { if self.look_ahead(1, |tok| tok == &token::CloseDelim(Delimiter::Brace)) { // FIXME: merge with `DocCommentDoesNotDocumentAnything` (E0585) struct_span_err!( - self.diagnostic(), + self.dcx(), self.token.span, E0584, "found a documentation comment that doesn't document anything", @@ -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.diagnostic()); + 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.diagnostic())); + return Err(self.dcx().create_err(err)); } } @@ -1484,7 +1480,7 @@ impl<'a> Parser<'a> { (thin_vec![], true) } }; - VariantData::Struct(fields, recovered) + VariantData::Struct { fields, recovered } } else if this.check(&token::OpenDelim(Delimiter::Parenthesis)) { let body = match this.parse_tuple_struct_body() { Ok(body) => body, @@ -1569,7 +1565,7 @@ impl<'a> Parser<'a> { class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct(fields, recovered) + VariantData::Struct { fields, recovered } } // No `where` so: `struct Foo<T>;` } else if self.eat(&token::Semi) { @@ -1581,7 +1577,7 @@ impl<'a> Parser<'a> { class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct(fields, recovered) + VariantData::Struct { fields, recovered } // Tuple-style struct definition with optional where-clause. } else if self.token == token::OpenDelim(Delimiter::Parenthesis) { let body = VariantData::Tuple(self.parse_tuple_struct_body()?, DUMMY_NODE_ID); @@ -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.diagnostic())); + return Err(self.dcx().create_err(err)); }; Ok((class_name, ItemKind::Struct(vdata, generics))) @@ -1610,14 +1606,14 @@ impl<'a> Parser<'a> { class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct(fields, recovered) + VariantData::Struct { fields, recovered } } else if self.token == token::OpenDelim(Delimiter::Brace) { let (fields, recovered) = self.parse_record_struct_body( "union", class_name.span, generics.where_clause.has_where_token, )?; - VariantData::Struct(fields, recovered) + VariantData::Struct { fields, recovered } } else { let token_str = super::token_descr(&self.token); let msg = format!("expected `where` or `{{` after union name, found {token_str}"); @@ -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.diagnostic())); + return Err(self.dcx().create_err(err)); } } _ => { @@ -1837,7 +1833,7 @@ impl<'a> Parser<'a> { // Make sure an error was emitted (either by recovering an angle bracket, // or by finding an identifier as the next token), since we're // going to continue parsing - assert!(self.diagnostic().has_errors().is_some()); + assert!(self.dcx().has_errors().is_some()); } else { return Err(err); } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 2baedb2766f..47c337ad913 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, FatalError, MultiSpan}; use rustc_session::parse::ParseSess; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -910,7 +908,7 @@ impl<'a> Parser<'a> { fn recover_missing_braces_around_closure_body( &mut self, closure_spans: ClosureSpans, - mut expect_err: DiagnosticBuilder<'_, ErrorGuaranteed>, + mut expect_err: DiagnosticBuilder<'_>, ) -> PResult<'a, ()> { let initial_semicolon = self.token.span; @@ -1492,7 +1490,7 @@ impl<'a> Parser<'a> { pub(crate) fn make_unclosed_delims_error( unmatched: UnmatchedDelim, sess: &ParseSess, -) -> Option<DiagnosticBuilder<'_, ErrorGuaranteed>> { +) -> Option<DiagnosticBuilder<'_>> { // `None` here means an `Eof` was found. We already emit those errors elsewhere, we add them to // `unmatched_delims` only for error recovery in the `Parser`. let found_delim = unmatched.found_delim?; @@ -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.span_diagnostic); + }); Some(err) } diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs index 4360a69e501..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,8 +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.diagnostic())); + return Err(self + .dcx() + .create_err(UnexpectedNonterminal::Item(self.token.span))); } }, NonterminalKind::Block => { @@ -126,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.diagnostic())); + return Err(self + .dcx() + .create_err(UnexpectedNonterminal::Statement(self.token.span))); } }, NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => { @@ -159,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.diagnostic())); + })); } NonterminalKind::Path => { NtPath(P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?)) @@ -177,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.diagnostic())); + })); } } }; diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 020b66a985a..56a3f5ce3c2 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, PResult}; use rustc_session::errors::ExprParenthesesNeeded; use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Ident}; @@ -687,7 +687,7 @@ impl<'a> Parser<'a> { fn fatal_unexpected_non_pat( &mut self, - err: DiagnosticBuilder<'a, ErrorGuaranteed>, + err: DiagnosticBuilder<'a>, expected: Option<Expected>, ) -> PResult<'a, P<Pat>> { err.cancel(); @@ -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.diagnostic())); + return Err(self + .dcx() + .create_err(EnumPatternInsteadOfIdentifier { span: self.prev_token.span })); } Ok(PatKind::Ident(binding_annotation, ident, sub)) @@ -968,7 +969,7 @@ impl<'a> Parser<'a> { let mut fields = ThinVec::new(); let mut etc = false; let mut ate_comma = true; - let mut delayed_err: Option<DiagnosticBuilder<'a, ErrorGuaranteed>> = None; + let mut delayed_err: Option<DiagnosticBuilder<'a>> = None; let mut first_etc_and_maybe_comma_span = None; let mut last_non_comma_dotdot_span = None; @@ -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.diagnostic()); + let mut err = + self.dcx().create_err(ExpectedCommaAfterPatternField { span: self.token.span }); if let Some(mut delayed) = delayed_err { delayed.emit(); } @@ -1134,7 +1135,7 @@ impl<'a> Parser<'a> { fn recover_misplaced_pattern_modifiers( &self, fields: &ThinVec<PatField>, - err: &mut DiagnosticBuilder<'a, ErrorGuaranteed>, + err: &mut DiagnosticBuilder<'a>, ) { if let Some(last) = fields.iter().last() && last.is_shorthand diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 0f4ba9617c6..405531c1e41 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; @@ -123,7 +123,7 @@ impl<'a> Parser<'a> { self.bump(); // colon - self.diagnostic() + self.dcx() .struct_span_err( self.prev_token.span, "found single colon before projection in qualified path", @@ -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.diagnostic()); + }); } // Attempt to find places where a missing `>` might belong. else if let Some(arg) = args @@ -841,7 +840,7 @@ impl<'a> Parser<'a> { { return Ok((false, seg.ident, seg.args.as_deref().cloned())); } else if let ast::TyKind::TraitObject(bounds, ast::TraitObjectSyntax::None) = &ty.kind - && let [ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifier::None)] = + && let [ast::GenericBound::Trait(trait_ref, ast::TraitBoundModifiers::NONE)] = bounds.as_slice() && let [seg] = trait_ref.trait_ref.path.segments.as_slice() { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 1ee5a96d5dc..1ac5aba212c 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -19,7 +19,7 @@ use rustc_ast::util::classify; use rustc_ast::{AttrStyle, AttrVec, LocalKind, MacCall, MacCallStmt, MacStmtStyle}; use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, HasAttrs, Local, Stmt}; use rustc_ast::{StmtKind, DUMMY_NODE_ID}; -use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult}; +use rustc_errors::{Applicability, DiagnosticBuilder, PResult}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{BytePos, Span}; @@ -442,7 +442,7 @@ impl<'a> Parser<'a> { fn error_block_no_opening_brace_msg( &mut self, msg: Cow<'static, str>, - ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'a> { let sp = self.token.span; let mut e = self.struct_span_err(sp, msg); let do_not_suggest_help = self.token.is_keyword(kw::In) || self.token == token::Colon; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index da8cc05ff66..f89d6d1d965 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -13,37 +13,15 @@ use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ - self as ast, BareFnTy, BoundPolarity, FnRetTy, GenericBound, GenericBounds, GenericParam, - Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, TraitBoundModifier, - TraitObjectSyntax, Ty, TyKind, + self as ast, BareFnTy, BoundConstness, BoundPolarity, FnRetTy, GenericBound, GenericBounds, + GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, PolyTraitRef, + TraitBoundModifiers, TraitObjectSyntax, Ty, TyKind, }; use rustc_errors::{Applicability, PResult}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{Span, Symbol}; use thin_vec::{thin_vec, ThinVec}; -/// Any `?`, `!`, or `~const` modifiers that appear at the start of a bound. -struct BoundModifiers { - /// `?Trait`. - bound_polarity: BoundPolarity, - - /// `~const Trait`. - maybe_const: Option<Span>, -} - -impl BoundModifiers { - fn to_trait_bound_modifier(&self) -> TraitBoundModifier { - match (self.bound_polarity, self.maybe_const) { - (BoundPolarity::Positive, None) => TraitBoundModifier::None, - (BoundPolarity::Negative(_), None) => TraitBoundModifier::Negative, - (BoundPolarity::Maybe(_), None) => TraitBoundModifier::Maybe, - (BoundPolarity::Positive, Some(sp)) => TraitBoundModifier::MaybeConst(sp), - (BoundPolarity::Negative(_), Some(_)) => TraitBoundModifier::MaybeConstNegative, - (BoundPolarity::Maybe(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe, - } - } -} - #[derive(Copy, Clone, PartialEq)] pub(super) enum AllowPlus { Yes, @@ -461,7 +439,7 @@ impl<'a> Parser<'a> { parse_plus: bool, ) -> PResult<'a, TyKind> { let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_token.span)); - let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)]; + let bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifiers::NONE)]; self.parse_remaining_bounds(bounds, parse_plus) } @@ -800,7 +778,7 @@ impl<'a> Parser<'a> { let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis)); let inner_lo = self.token.span; - let modifiers = self.parse_ty_bound_modifiers()?; + let modifiers = self.parse_trait_bound_modifiers()?; let bound = if self.token.is_lifetime() { self.error_lt_bound_with_modifiers(modifiers); self.parse_generic_lt_bound(lo, inner_lo, has_parens)? @@ -831,18 +809,21 @@ impl<'a> Parser<'a> { } /// Emits an error if any trait bound modifiers were present. - fn error_lt_bound_with_modifiers(&self, modifiers: BoundModifiers) { - if let Some(span) = modifiers.maybe_const { - self.sess.emit_err(errors::TildeConstLifetime { span }); + fn error_lt_bound_with_modifiers(&self, modifiers: TraitBoundModifiers) { + match modifiers.constness { + BoundConstness::Never => {} + BoundConstness::Maybe(span) => { + self.sess.emit_err(errors::TildeConstLifetime { span }); + } } - match modifiers.bound_polarity { + match modifiers.polarity { BoundPolarity::Positive => {} - BoundPolarity::Negative(span) => { - self.sess.emit_err(errors::ModifierLifetime { span, sigil: "!" }); - } - BoundPolarity::Maybe(span) => { - self.sess.emit_err(errors::ModifierLifetime { span, sigil: "?" }); + BoundPolarity::Negative(span) | BoundPolarity::Maybe(span) => { + self.sess.emit_err(errors::ModifierLifetime { + span, + sigil: modifiers.polarity.as_str(), + }); } } } @@ -867,26 +848,26 @@ impl<'a> Parser<'a> { /// If no modifiers are present, this does not consume any tokens. /// /// ```ebnf - /// TY_BOUND_MODIFIERS = ["~const"] ["?"] + /// TRAIT_BOUND_MODIFIERS = ["~const"] ["?" | "!"] /// ``` - fn parse_ty_bound_modifiers(&mut self) -> PResult<'a, BoundModifiers> { - let maybe_const = if self.eat(&token::Tilde) { + fn parse_trait_bound_modifiers(&mut self) -> PResult<'a, TraitBoundModifiers> { + let constness = if self.eat(&token::Tilde) { let tilde = self.prev_token.span; self.expect_keyword(kw::Const)?; let span = tilde.to(self.prev_token.span); self.sess.gated_spans.gate(sym::const_trait_impl, span); - Some(span) + BoundConstness::Maybe(span) } else if self.eat_keyword(kw::Const) { let span = self.prev_token.span; self.sess.gated_spans.gate(sym::const_trait_impl, span); self.sess.emit_err(errors::ConstMissingTilde { span, start: span.shrink_to_lo() }); - Some(span) + BoundConstness::Maybe(span) } else { - None + BoundConstness::Never }; - let bound_polarity = if self.eat(&token::Question) { + let polarity = if self.eat(&token::Question) { BoundPolarity::Maybe(self.prev_token.span) } else if self.eat(&token::Not) { self.sess.gated_spans.gate(sym::negative_bounds, self.prev_token.span); @@ -895,13 +876,13 @@ impl<'a> Parser<'a> { BoundPolarity::Positive }; - Ok(BoundModifiers { bound_polarity, maybe_const }) + Ok(TraitBoundModifiers { constness, polarity }) } /// Parses a type bound according to: /// ```ebnf /// TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) - /// TY_BOUND_NOPAREN = [TY_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH + /// TY_BOUND_NOPAREN = [TRAIT_BOUND_MODIFIERS] [for<LT_PARAM_DEFS>] SIMPLE_PATH /// ``` /// /// For example, this grammar accepts `~const ?for<'a: 'b> m::Trait<'a>`. @@ -909,7 +890,7 @@ impl<'a> Parser<'a> { &mut self, lo: Span, has_parens: bool, - modifiers: BoundModifiers, + modifiers: TraitBoundModifiers, leading_token: &Token, ) -> PResult<'a, GenericBound> { let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?; @@ -991,9 +972,8 @@ impl<'a> Parser<'a> { } } - let modifier = modifiers.to_trait_bound_modifier(); let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_token.span)); - Ok(GenericBound::Trait(poly_trait, modifier)) + Ok(GenericBound::Trait(poly_trait, modifiers)) } // recovers a `Fn(..)` parenthesized-style path from `fn(..)` diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index d10c8c92257..9fea3826652 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -56,7 +56,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta let res = match res { Ok(lit) => { if token_lit.suffix.is_some() { - let mut err = sess.span_diagnostic.struct_span_err( + let mut err = sess.dcx.struct_span_err( expr.span, "suffixed literals are not allowed in attributes", ); @@ -89,7 +89,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta // the error because an earlier error will have already // been reported. let msg = format!("attribute value must be a literal"); - let mut err = sess.span_diagnostic.struct_span_err(expr.span, msg); + let mut err = sess.dcx.struct_span_err(expr.span, msg); if let ast::ExprKind::Err = expr.kind { err.downgrade_to_delayed_bug(); } @@ -206,7 +206,7 @@ fn emit_malformed_attribute( if should_warn(name) { sess.buffer_lint(ILL_FORMED_ATTRIBUTE_INPUT, span, ast::CRATE_NODE_ID, msg); } else { - sess.span_diagnostic + sess.dcx .struct_span_err(span, error_msg) .span_suggestions( span, |
