about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-03-28 11:08:23 +0000
committerbors <bors@rust-lang.org>2022-03-28 11:08:23 +0000
commit0e4524e5b4a9c5656fef69f532f96eb9959a1803 (patch)
treef3b255fe605208ee5eafc4a41541eeada8a9e807
parentb3e46a9763d86a1681ddaaf0e60ce537302b9c92 (diff)
parent928388bad20572e9ffa575319bb6d3b636bcdc69 (diff)
downloadrust-0e4524e5b4a9c5656fef69f532f96eb9959a1803.tar.gz
rust-0e4524e5b4a9c5656fef69f532f96eb9959a1803.zip
Auto merge of #94789 - compiler-errors:fatal-never, r=eddyb
Make fatal DiagnosticBuilder yield `!`

Fatal errors should really be fatal, so emitting them should cause us to exit at the same time.

Fine with just throwing away these changes if they're not worthwhile. Also, maybe we want to use an uninhabited enum instead of `!`.

r? `@eddyb` who has been working on `DiagnosticBuilder` stuff, feel free to reassign.
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs39
-rw-r--r--compiler/rustc_errors/src/lib.rs9
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs7
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs31
-rw-r--r--compiler/rustc_parse/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/lib.rs1
-rw-r--r--compiler/rustc_session/src/session.rs31
-rw-r--r--compiler/rustc_span/src/fatal_error.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/const_evaluatable.rs3
-rw-r--r--compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs2
-rw-r--r--compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs2
11 files changed, 82 insertions, 46 deletions
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 088f6091528..853243ef3f0 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -198,6 +198,45 @@ impl EmissionGuarantee for () {
     }
 }
 
+impl<'a> DiagnosticBuilder<'a, !> {
+    /// Convenience function for internal use, clients should use one of the
+    /// `struct_*` methods on [`Handler`].
+    crate fn new_fatal(handler: &'a Handler, message: &str) -> Self {
+        let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message);
+        Self::new_diagnostic_fatal(handler, diagnostic)
+    }
+
+    /// Creates a new `DiagnosticBuilder` with an already constructed
+    /// diagnostic.
+    crate fn new_diagnostic_fatal(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
+        debug!("Created new diagnostic");
+        Self {
+            inner: DiagnosticBuilderInner {
+                state: DiagnosticBuilderState::Emittable(handler),
+                diagnostic: Box::new(diagnostic),
+            },
+            _marker: PhantomData,
+        }
+    }
+}
+
+impl EmissionGuarantee for ! {
+    fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
+        match db.inner.state {
+            // First `.emit()` call, the `&Handler` is still available.
+            DiagnosticBuilderState::Emittable(handler) => {
+                db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
+
+                handler.emit_diagnostic(&mut db.inner.diagnostic);
+            }
+            // `.emit()` was previously called, disallowed from repeating it.
+            DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
+        }
+        // Then fatally error, returning `!`
+        crate::FatalError.raise()
+    }
+}
+
 /// In general, the `DiagnosticBuilder` uses deref to allow access to
 /// the fields and methods of the embedded `diagnostic` in a
 /// transparent way. *However,* many of the methods are intended to
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 2f2f6ed1a5a..ec00910ec8b 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -8,6 +8,7 @@
 #![feature(backtrace)]
 #![feature(if_let_guard)]
 #![feature(let_else)]
+#![feature(never_type)]
 #![feature(nll)]
 #![feature(adt_const_params)]
 #![allow(incomplete_features)]
@@ -758,7 +759,7 @@ impl Handler {
         &self,
         span: impl Into<MultiSpan>,
         msg: &str,
-    ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'_, !> {
         let mut result = self.struct_fatal(msg);
         result.set_span(span);
         result
@@ -770,15 +771,15 @@ impl Handler {
         span: impl Into<MultiSpan>,
         msg: &str,
         code: DiagnosticId,
-    ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'_, !> {
         let mut result = self.struct_span_fatal(span, msg);
         result.code(code);
         result
     }
 
     /// Construct a builder at the `Error` level with the `msg`.
-    pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
-        DiagnosticBuilder::new_guaranteeing_error::<{ Level::Fatal }>(self, msg)
+    pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> {
+        DiagnosticBuilder::new_fatal(self, msg)
     }
 
     /// Construct a builder at the `Help` level with the `msg`.
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index a9dcc484b9e..1477bc28cff 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -180,7 +180,6 @@
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
-use rustc_errors::FatalError;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -560,8 +559,7 @@ fn check_recursion_limit<'tcx>(
         if let Some(path) = written_to_path {
             err.note(&format!("the full type name has been written to '{}'", path.display()));
         }
-        err.emit();
-        FatalError.raise();
+        err.emit()
     }
 
     recursion_depths.insert(def_id, recursion_depth + 1);
@@ -598,8 +596,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
             "consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate",
             type_length
         ));
-        diag.emit();
-        tcx.sess.abort_if_errors();
+        diag.emit()
     }
 }
 
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 601a39e69ab..92c5d329f6e 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -3,9 +3,7 @@ use rustc_ast::ast::{self, AttrStyle};
 use rustc_ast::token::{self, CommentKind, Token, TokenKind};
 use rustc_ast::tokenstream::{Spacing, TokenStream};
 use rustc_ast::util::unicode::contains_text_flow_control_chars;
-use rustc_errors::{
-    error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, PResult,
-};
+use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
 use rustc_lexer::unescape::{self, Mode};
 use rustc_lexer::{Base, DocStyle, RawStrError};
 use rustc_session::lint::builtin::{
@@ -104,7 +102,7 @@ impl<'a> StringReader<'a> {
     }
 
     /// Report a fatal lexical error with a given span.
-    fn fatal_span(&self, sp: Span, m: &str) -> FatalError {
+    fn fatal_span(&self, sp: Span, m: &str) -> ! {
         self.sess.span_diagnostic.span_fatal(sp, m)
     }
 
@@ -114,7 +112,7 @@ impl<'a> StringReader<'a> {
     }
 
     /// Report a fatal error spanning [`from_pos`, `to_pos`).
-    fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> FatalError {
+    fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> ! {
         self.fatal_span(self.mk_sp(from_pos, to_pos), m)
     }
 
@@ -129,12 +127,24 @@ impl<'a> StringReader<'a> {
         to_pos: BytePos,
         m: &str,
         c: char,
-    ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'a, !> {
         self.sess
             .span_diagnostic
             .struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))
     }
 
+    fn struct_err_span_char(
+        &self,
+        from_pos: BytePos,
+        to_pos: BytePos,
+        m: &str,
+        c: char,
+    ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+        self.sess
+            .span_diagnostic
+            .struct_span_err(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))
+    }
+
     /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly
     /// complain about it.
     fn lint_unicode_text_flow(&self, start: BytePos) {
@@ -311,7 +321,7 @@ impl<'a> StringReader<'a> {
             rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
                 let c = self.str_from(start).chars().next().unwrap();
                 let mut err =
-                    self.struct_fatal_span_char(start, self.pos, "unknown start of token", c);
+                    self.struct_err_span_char(start, self.pos, "unknown start of token", c);
                 // FIXME: the lexer could be used to turn the ASCII version of unicode homoglyphs,
                 // instead of keeping a table in `check_for_substitution`into the token. Ideally,
                 // this should be inside `rustc_lexer`. However, we should first remove compound
@@ -503,8 +513,7 @@ impl<'a> StringReader<'a> {
             "found invalid character; only `#` is allowed in raw string delimitation",
             bad_char,
         )
-        .emit();
-        FatalError.raise()
+        .emit()
     }
 
     fn report_unterminated_raw_string(
@@ -541,8 +550,7 @@ impl<'a> StringReader<'a> {
             );
         }
 
-        err.emit();
-        FatalError.raise()
+        err.emit()
     }
 
     // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021,
@@ -601,7 +609,6 @@ impl<'a> StringReader<'a> {
                 found
             ),
         )
-        .raise();
     }
 
     fn validate_literal_escape(
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 0ce86a764f4..1118caf5075 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -6,6 +6,7 @@
 #![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(let_else)]
+#![feature(never_type)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index bd4e37f1ab7..14273b07ebd 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -3,6 +3,7 @@
 #![feature(let_chains)]
 #![feature(let_else)]
 #![feature(min_specialization)]
+#![feature(never_type)]
 #![feature(once_cell)]
 #![feature(option_get_or_insert_default)]
 #![recursion_limit = "256"]
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 4876e2eb851..eed0f1e09ff 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -341,7 +341,7 @@ impl Session {
         &self,
         sp: S,
         msg: &str,
-    ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_span_fatal(sp, msg)
     }
     pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
@@ -349,10 +349,10 @@ impl Session {
         sp: S,
         msg: &str,
         code: DiagnosticId,
-    ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+    ) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
     }
-    pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
+    pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> {
         self.diagnostic().struct_fatal(msg)
     }
 
@@ -1384,7 +1384,7 @@ pub enum IncrCompSession {
     InvalidBecauseOfErrors { session_directory: PathBuf },
 }
 
-pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
+fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler {
     let emitter: Box<dyn Emitter + sync::Send> = match output {
         config::ErrorOutputType::HumanReadable(kind) => {
             let (short, color_config) = kind.unzip();
@@ -1394,26 +1394,17 @@ pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> Error
             Box::new(JsonEmitter::basic(pretty, json_rendered, None, false))
         }
     };
-    let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
-    let reported = handler.struct_fatal(msg).emit();
-    reported
+    rustc_errors::Handler::with_emitter(true, None, emitter)
+}
+
+pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
+    early_error_handler(output).struct_err(msg).emit()
 }
 
 pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
-    early_error_no_abort(output, msg);
-    rustc_errors::FatalError.raise();
+    early_error_handler(output).struct_fatal(msg).emit()
 }
 
 pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
-    let emitter: Box<dyn Emitter + sync::Send> = match output {
-        config::ErrorOutputType::HumanReadable(kind) => {
-            let (short, color_config) = kind.unzip();
-            Box::new(EmitterWriter::stderr(color_config, None, short, false, None, false))
-        }
-        config::ErrorOutputType::Json { pretty, json_rendered } => {
-            Box::new(JsonEmitter::basic(pretty, json_rendered, None, false))
-        }
-    };
-    let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
-    handler.struct_warn(msg).emit();
+    early_error_handler(output).struct_warn(msg).emit()
 }
diff --git a/compiler/rustc_span/src/fatal_error.rs b/compiler/rustc_span/src/fatal_error.rs
index 718c0ddbc63..fa84c486df5 100644
--- a/compiler/rustc_span/src/fatal_error.rs
+++ b/compiler/rustc_span/src/fatal_error.rs
@@ -19,7 +19,7 @@ impl FatalError {
 
 impl std::fmt::Display for FatalError {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "parser fatal error")
+        write!(f, "fatal error")
     }
 }
 
diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
index 959b644becd..d114515eca1 100644
--- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
+++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs
@@ -168,8 +168,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
                 "#![feature(generic_const_exprs)]\n".to_string(),
                 rustc_errors::Applicability::MaybeIncorrect,
             )
-            .emit();
-        rustc_errors::FatalError.raise();
+            .emit()
     }
 
     debug!(?concrete, "is_const_evaluatable");
diff --git a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
index 79965c1dc28..e2bd018cb20 100644
--- a/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
+++ b/compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs
@@ -21,7 +21,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx> {
     }
 
     fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let mut err = self.sess.struct_span_fatal_with_code(
+        let mut err = self.sess.struct_span_err_with_code(
             self.span,
             &format!("can't pass `{}` to variadic function", self.ty),
             self.code(),
diff --git a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
index 9b058d32f79..afc5c1fe6cc 100644
--- a/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
+++ b/compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs
@@ -21,7 +21,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
     }
 
     fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let mut err = self.sess.struct_span_fatal_with_code(
+        let mut err = self.sess.struct_span_err_with_code(
             self.span,
             &format!(
                 "cannot cast thin pointer `{}` to fat pointer `{}`",