From 6656413a5c9beb774dfde16804aa523cf9dbf1b5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 11 Jan 2024 14:22:44 +1100 Subject: [PATCH] Stop using `DiagnosticBuilder::buffer` in the parser. One consequence is that errors returned by `maybe_new_parser_from_source_str` now must be consumed, so a bunch of places that previously ignored those errors now cancel them. (Most of them explicitly dropped the errors before. I guess that was to indicate "we are explicitly ignoring these", though I'm not 100% sure.) --- compiler/rustc_interface/src/interface.rs | 11 +++++--- compiler/rustc_parse/src/lexer/mod.rs | 8 +++--- compiler/rustc_parse/src/lib.rs | 26 +++++++++---------- src/librustdoc/clean/render_macro_matchers.rs | 4 +-- src/librustdoc/doctest.rs | 8 +++--- .../src/doc/needless_doctest_main.rs | 2 +- src/tools/rustfmt/src/parse/parser.rs | 4 +-- src/tools/rustfmt/src/parse/session.rs | 8 +++--- 8 files changed, 39 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 6c000380e71..03335996c03 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -82,7 +82,7 @@ pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec) -> Cfg { Ok(..) => {} Err(err) => err.cancel(), }, - Err(errs) => drop(errs), + Err(errs) => errs.into_iter().for_each(|err| err.cancel()), } // If the user tried to use a key="value" flag, but is missing the quotes, provide @@ -129,9 +129,12 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`") }; - let Ok(mut parser) = maybe_new_parser_from_source_str(&sess, filename, s.to_string()) - else { - expected_error(); + let mut parser = match maybe_new_parser_from_source_str(&sess, filename, s.to_string()) { + Ok(parser) => parser, + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); + expected_error(); + } }; let meta_item = match parser.parse_meta_item() { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 9626d4e8171..d7ecf577ed6 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -7,7 +7,7 @@ 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, DiagCtxt, Diagnostic, StashKey}; +use rustc_errors::{error_code, Applicability, DiagCtxt, DiagnosticBuilder, StashKey}; use rustc_lexer::unescape::{self, EscapeError, Mode}; use rustc_lexer::{Base, DocStyle, RawStrError}; use rustc_lexer::{Cursor, LiteralKind}; @@ -47,7 +47,7 @@ pub(crate) fn parse_token_trees<'sess, 'src>( mut src: &'src str, mut start_pos: BytePos, override_span: Option, -) -> Result> { +) -> Result>> { // Skip `#!`, if present. if let Some(shebang_len) = rustc_lexer::strip_shebang(src) { src = &src[shebang_len..]; @@ -76,13 +76,13 @@ pub(crate) fn parse_token_trees<'sess, 'src>( let mut buffer = Vec::with_capacity(1); for unmatched in unmatched_delims { if let Some(err) = make_unclosed_delims_error(unmatched, sess) { - err.buffer(&mut buffer); + buffer.push(err); } } if let Err(errs) = res { // Add unclosing delimiter or diff marker errors for err in errs { - err.buffer(&mut buffer); + buffer.push(err); } } Err(buffer) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 55437de72b5..c00e318f227 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -19,7 +19,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AttrItem, Attribute, MetaItem}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; -use rustc_errors::{Diagnostic, PResult}; +use rustc_errors::{DiagnosticBuilder, FatalError, PResult}; use rustc_session::parse::ParseSess; use rustc_span::{FileName, SourceFile, Span}; @@ -45,14 +45,13 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } /// A variant of 'panictry!' that works on a `Vec` instead of a single /// `DiagnosticBuilder`. macro_rules! panictry_buffer { - ($handler:expr, $e:expr) => {{ - use rustc_errors::FatalError; + ($e:expr) => {{ use std::result::Result::{Err, Ok}; match $e { Ok(e) => e, Err(errs) => { for e in errs { - $handler.emit_diagnostic(e); + e.emit(); } FatalError.raise() } @@ -100,16 +99,17 @@ 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.dcx, maybe_new_parser_from_source_str(sess, name, source)) + panictry_buffer!(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 -/// token stream. +/// token stream; these must be consumed via `emit`, `cancel`, etc., otherwise a panic will occur +/// when they are dropped. pub fn maybe_new_parser_from_source_str( sess: &ParseSess, name: FileName, source: String, -) -> Result, Vec> { +) -> Result, Vec>> { maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source)) } @@ -125,7 +125,7 @@ pub fn new_parser_from_file<'a>(sess: &'a ParseSess, path: &Path, sp: Option(sess: &'a ParseSess, path: &Path, sp: Option, -) -> Result, Vec> { +) -> Result, Vec>> { let end_pos = source_file.end_position(); let stream = maybe_file_to_stream(sess, source_file, None)?; let mut parser = stream_to_parser(sess, stream, None); @@ -152,16 +152,16 @@ pub fn source_file_to_stream( source_file: Lrc, override_span: Option, ) -> TokenStream { - panictry_buffer!(&sess.dcx, maybe_file_to_stream(sess, source_file, override_span)) + panictry_buffer!(maybe_file_to_stream(sess, source_file, override_span)) } /// Given a source file, produces a sequence of token trees. Returns any buffered errors from /// parsing the token stream. -fn maybe_file_to_stream( - sess: &ParseSess, +fn maybe_file_to_stream<'sess>( + sess: &'sess ParseSess, source_file: Lrc, override_span: Option, -) -> Result> { +) -> Result>> { let src = source_file.src.as_ref().unwrap_or_else(|| { sess.dcx.bug(format!( "cannot lex `source_file` without source: {}", diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index 605f9e496c7..b736f4a7956 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -69,8 +69,8 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option parser, - Err(diagnostics) => { - drop(diagnostics); + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); return None; } }; diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 9a900625268..82746a7ab03 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -589,7 +589,7 @@ pub(crate) fn make_test( let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source) { Ok(p) => p, Err(errs) => { - drop(errs); + errs.into_iter().for_each(|err| err.cancel()); return (found_main, found_extern_crate, found_macro); } }; @@ -759,8 +759,10 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { let mut parser = match maybe_new_parser_from_source_str(&sess, filename, source.to_owned()) { Ok(p) => p, - Err(_) => { - // If there is an unclosed delimiter, an error will be returned by the tokentrees. + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); + // If there is an unclosed delimiter, an error will be returned by the + // tokentrees. return false; } }; diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index a744b69ecb4..8b018220c17 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -53,7 +53,7 @@ pub fn check( let mut parser = match maybe_new_parser_from_source_str(&sess, filename, code) { Ok(p) => p, Err(errs) => { - drop(errs); + errs.into_iter().for_each(|err| err.cancel()); return (false, test_attr_spans); }, }; diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs index 7045a7dd9ce..31226cf8c30 100644 --- a/src/tools/rustfmt/src/parse/parser.rs +++ b/src/tools/rustfmt/src/parse/parser.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use rustc_ast::token::TokenKind; use rustc_ast::{ast, attr, ptr}; -use rustc_errors::Diagnostic; +use rustc_errors::DiagnosticBuilder; use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; use rustc_span::{sym, Span}; use thin_vec::ThinVec; @@ -65,7 +65,7 @@ impl<'a> ParserBuilder<'a> { fn parser( sess: &'a rustc_session::parse::ParseSess, input: Input, - ) -> Result, Option>> { + ) -> Result, Option>>> { match input { Input::File(ref file) => catch_unwind(AssertUnwindSafe(move || { new_parser_from_file(sess, file, None) diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index f4fb5073dfd..6dc3eac44d4 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -4,7 +4,9 @@ use std::sync::atomic::{AtomicBool, Ordering}; use rustc_data_structures::sync::{IntoDynSyncSend, Lrc}; use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter}; use rustc_errors::translation::Translate; -use rustc_errors::{ColorConfig, DiagCtxt, Diagnostic, Level as DiagnosticLevel}; +use rustc_errors::{ + ColorConfig, DiagCtxt, Diagnostic, DiagnosticBuilder, Level as DiagnosticLevel, +}; use rustc_session::parse::ParseSess as RawParseSess; use rustc_span::{ source_map::{FilePathMapping, SourceMap}, @@ -283,9 +285,9 @@ impl ParseSess { // Methods that should be restricted within the parse module. impl ParseSess { - pub(super) fn emit_diagnostics(&self, diagnostics: Vec) { + pub(super) fn emit_diagnostics(&self, diagnostics: Vec>) { for diagnostic in diagnostics { - self.parse_sess.dcx.emit_diagnostic(diagnostic); + diagnostic.emit(); } }