about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-03-09 16:11:28 -0800
committerMichael Goulet <michael@errs.io>2022-03-27 22:25:32 -0700
commit928388bad20572e9ffa575319bb6d3b636bcdc69 (patch)
tree80cd8720d389e6faa6b0f23ffcf5496cb29ebb25
parent93313d108fb7aa209b6ed1ae64d7c05e425d69ad (diff)
downloadrust-928388bad20572e9ffa575319bb6d3b636bcdc69.tar.gz
rust-928388bad20572e9ffa575319bb6d3b636bcdc69.zip
Make fatal DiagnosticBuilder yield never
-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 `{}`",