Skip to content

Commit 928388b

Browse files
Make fatal DiagnosticBuilder yield never
1 parent 93313d1 commit 928388b

File tree

11 files changed

+82
-46
lines changed

11 files changed

+82
-46
lines changed

compiler/rustc_errors/src/diagnostic_builder.rs

+39
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,45 @@ impl EmissionGuarantee for () {
198198
}
199199
}
200200

201+
impl<'a> DiagnosticBuilder<'a, !> {
202+
/// Convenience function for internal use, clients should use one of the
203+
/// `struct_*` methods on [`Handler`].
204+
crate fn new_fatal(handler: &'a Handler, message: &str) -> Self {
205+
let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message);
206+
Self::new_diagnostic_fatal(handler, diagnostic)
207+
}
208+
209+
/// Creates a new `DiagnosticBuilder` with an already constructed
210+
/// diagnostic.
211+
crate fn new_diagnostic_fatal(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
212+
debug!("Created new diagnostic");
213+
Self {
214+
inner: DiagnosticBuilderInner {
215+
state: DiagnosticBuilderState::Emittable(handler),
216+
diagnostic: Box::new(diagnostic),
217+
},
218+
_marker: PhantomData,
219+
}
220+
}
221+
}
222+
223+
impl EmissionGuarantee for ! {
224+
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
225+
match db.inner.state {
226+
// First `.emit()` call, the `&Handler` is still available.
227+
DiagnosticBuilderState::Emittable(handler) => {
228+
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
229+
230+
handler.emit_diagnostic(&mut db.inner.diagnostic);
231+
}
232+
// `.emit()` was previously called, disallowed from repeating it.
233+
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
234+
}
235+
// Then fatally error, returning `!`
236+
crate::FatalError.raise()
237+
}
238+
}
239+
201240
/// In general, the `DiagnosticBuilder` uses deref to allow access to
202241
/// the fields and methods of the embedded `diagnostic` in a
203242
/// transparent way. *However,* many of the methods are intended to

compiler/rustc_errors/src/lib.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#![feature(backtrace)]
99
#![feature(if_let_guard)]
1010
#![feature(let_else)]
11+
#![feature(never_type)]
1112
#![feature(nll)]
1213
#![feature(adt_const_params)]
1314
#![allow(incomplete_features)]
@@ -758,7 +759,7 @@ impl Handler {
758759
&self,
759760
span: impl Into<MultiSpan>,
760761
msg: &str,
761-
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
762+
) -> DiagnosticBuilder<'_, !> {
762763
let mut result = self.struct_fatal(msg);
763764
result.set_span(span);
764765
result
@@ -770,15 +771,15 @@ impl Handler {
770771
span: impl Into<MultiSpan>,
771772
msg: &str,
772773
code: DiagnosticId,
773-
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
774+
) -> DiagnosticBuilder<'_, !> {
774775
let mut result = self.struct_span_fatal(span, msg);
775776
result.code(code);
776777
result
777778
}
778779

779780
/// Construct a builder at the `Error` level with the `msg`.
780-
pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
781-
DiagnosticBuilder::new_guaranteeing_error::<{ Level::Fatal }>(self, msg)
781+
pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> {
782+
DiagnosticBuilder::new_fatal(self, msg)
782783
}
783784

784785
/// Construct a builder at the `Help` level with the `msg`.

compiler/rustc_monomorphize/src/collector.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@
180180
181181
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
182182
use rustc_data_structures::sync::{par_iter, MTLock, MTRef, ParallelIterator};
183-
use rustc_errors::FatalError;
184183
use rustc_hir as hir;
185184
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LOCAL_CRATE};
186185
use rustc_hir::itemlikevisit::ItemLikeVisitor;
@@ -560,8 +559,7 @@ fn check_recursion_limit<'tcx>(
560559
if let Some(path) = written_to_path {
561560
err.note(&format!("the full type name has been written to '{}'", path.display()));
562561
}
563-
err.emit();
564-
FatalError.raise();
562+
err.emit()
565563
}
566564

567565
recursion_depths.insert(def_id, recursion_depth + 1);
@@ -598,8 +596,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
598596
"consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate",
599597
type_length
600598
));
601-
diag.emit();
602-
tcx.sess.abort_if_errors();
599+
diag.emit()
603600
}
604601
}
605602

compiler/rustc_parse/src/lexer/mod.rs

+19-12
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ use rustc_ast::ast::{self, AttrStyle};
33
use rustc_ast::token::{self, CommentKind, Token, TokenKind};
44
use rustc_ast::tokenstream::{Spacing, TokenStream};
55
use rustc_ast::util::unicode::contains_text_flow_control_chars;
6-
use rustc_errors::{
7-
error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, PResult,
8-
};
6+
use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
97
use rustc_lexer::unescape::{self, Mode};
108
use rustc_lexer::{Base, DocStyle, RawStrError};
119
use rustc_session::lint::builtin::{
@@ -104,7 +102,7 @@ impl<'a> StringReader<'a> {
104102
}
105103

106104
/// Report a fatal lexical error with a given span.
107-
fn fatal_span(&self, sp: Span, m: &str) -> FatalError {
105+
fn fatal_span(&self, sp: Span, m: &str) -> ! {
108106
self.sess.span_diagnostic.span_fatal(sp, m)
109107
}
110108

@@ -114,7 +112,7 @@ impl<'a> StringReader<'a> {
114112
}
115113

116114
/// Report a fatal error spanning [`from_pos`, `to_pos`).
117-
fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> FatalError {
115+
fn fatal_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) -> ! {
118116
self.fatal_span(self.mk_sp(from_pos, to_pos), m)
119117
}
120118

@@ -129,12 +127,24 @@ impl<'a> StringReader<'a> {
129127
to_pos: BytePos,
130128
m: &str,
131129
c: char,
132-
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
130+
) -> DiagnosticBuilder<'a, !> {
133131
self.sess
134132
.span_diagnostic
135133
.struct_span_fatal(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))
136134
}
137135

136+
fn struct_err_span_char(
137+
&self,
138+
from_pos: BytePos,
139+
to_pos: BytePos,
140+
m: &str,
141+
c: char,
142+
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
143+
self.sess
144+
.span_diagnostic
145+
.struct_span_err(self.mk_sp(from_pos, to_pos), &format!("{}: {}", m, escaped_char(c)))
146+
}
147+
138148
/// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly
139149
/// complain about it.
140150
fn lint_unicode_text_flow(&self, start: BytePos) {
@@ -311,7 +321,7 @@ impl<'a> StringReader<'a> {
311321
rustc_lexer::TokenKind::Unknown | rustc_lexer::TokenKind::InvalidIdent => {
312322
let c = self.str_from(start).chars().next().unwrap();
313323
let mut err =
314-
self.struct_fatal_span_char(start, self.pos, "unknown start of token", c);
324+
self.struct_err_span_char(start, self.pos, "unknown start of token", c);
315325
// FIXME: the lexer could be used to turn the ASCII version of unicode homoglyphs,
316326
// instead of keeping a table in `check_for_substitution`into the token. Ideally,
317327
// this should be inside `rustc_lexer`. However, we should first remove compound
@@ -503,8 +513,7 @@ impl<'a> StringReader<'a> {
503513
"found invalid character; only `#` is allowed in raw string delimitation",
504514
bad_char,
505515
)
506-
.emit();
507-
FatalError.raise()
516+
.emit()
508517
}
509518

510519
fn report_unterminated_raw_string(
@@ -541,8 +550,7 @@ impl<'a> StringReader<'a> {
541550
);
542551
}
543552

544-
err.emit();
545-
FatalError.raise()
553+
err.emit()
546554
}
547555

548556
// RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021,
@@ -601,7 +609,6 @@ impl<'a> StringReader<'a> {
601609
found
602610
),
603611
)
604-
.raise();
605612
}
606613

607614
fn validate_literal_escape(

compiler/rustc_parse/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![feature(if_let_guard)]
77
#![feature(let_chains)]
88
#![feature(let_else)]
9+
#![feature(never_type)]
910
#![recursion_limit = "256"]
1011

1112
#[macro_use]

compiler/rustc_session/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#![feature(let_chains)]
44
#![feature(let_else)]
55
#![feature(min_specialization)]
6+
#![feature(never_type)]
67
#![feature(once_cell)]
78
#![feature(option_get_or_insert_default)]
89
#![recursion_limit = "256"]

compiler/rustc_session/src/session.rs

+11-20
Original file line numberDiff line numberDiff line change
@@ -341,18 +341,18 @@ impl Session {
341341
&self,
342342
sp: S,
343343
msg: &str,
344-
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
344+
) -> DiagnosticBuilder<'_, !> {
345345
self.diagnostic().struct_span_fatal(sp, msg)
346346
}
347347
pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(
348348
&self,
349349
sp: S,
350350
msg: &str,
351351
code: DiagnosticId,
352-
) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
352+
) -> DiagnosticBuilder<'_, !> {
353353
self.diagnostic().struct_span_fatal_with_code(sp, msg, code)
354354
}
355-
pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
355+
pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> {
356356
self.diagnostic().struct_fatal(msg)
357357
}
358358

@@ -1384,7 +1384,7 @@ pub enum IncrCompSession {
13841384
InvalidBecauseOfErrors { session_directory: PathBuf },
13851385
}
13861386

1387-
pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
1387+
fn early_error_handler(output: config::ErrorOutputType) -> rustc_errors::Handler {
13881388
let emitter: Box<dyn Emitter + sync::Send> = match output {
13891389
config::ErrorOutputType::HumanReadable(kind) => {
13901390
let (short, color_config) = kind.unzip();
@@ -1394,26 +1394,17 @@ pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> Error
13941394
Box::new(JsonEmitter::basic(pretty, json_rendered, None, false))
13951395
}
13961396
};
1397-
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
1398-
let reported = handler.struct_fatal(msg).emit();
1399-
reported
1397+
rustc_errors::Handler::with_emitter(true, None, emitter)
1398+
}
1399+
1400+
pub fn early_error_no_abort(output: config::ErrorOutputType, msg: &str) -> ErrorGuaranteed {
1401+
early_error_handler(output).struct_err(msg).emit()
14001402
}
14011403

14021404
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
1403-
early_error_no_abort(output, msg);
1404-
rustc_errors::FatalError.raise();
1405+
early_error_handler(output).struct_fatal(msg).emit()
14051406
}
14061407

14071408
pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
1408-
let emitter: Box<dyn Emitter + sync::Send> = match output {
1409-
config::ErrorOutputType::HumanReadable(kind) => {
1410-
let (short, color_config) = kind.unzip();
1411-
Box::new(EmitterWriter::stderr(color_config, None, short, false, None, false))
1412-
}
1413-
config::ErrorOutputType::Json { pretty, json_rendered } => {
1414-
Box::new(JsonEmitter::basic(pretty, json_rendered, None, false))
1415-
}
1416-
};
1417-
let handler = rustc_errors::Handler::with_emitter(true, None, emitter);
1418-
handler.struct_warn(msg).emit();
1409+
early_error_handler(output).struct_warn(msg).emit()
14191410
}

compiler/rustc_span/src/fatal_error.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ impl FatalError {
1919

2020
impl std::fmt::Display for FatalError {
2121
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22-
write!(f, "parser fatal error")
22+
write!(f, "fatal error")
2323
}
2424
}
2525

compiler/rustc_trait_selection/src/traits/const_evaluatable.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
168168
"#![feature(generic_const_exprs)]\n".to_string(),
169169
rustc_errors::Applicability::MaybeIncorrect,
170170
)
171-
.emit();
172-
rustc_errors::FatalError.raise();
171+
.emit()
173172
}
174173

175174
debug!(?concrete, "is_const_evaluatable");

compiler/rustc_typeck/src/structured_errors/missing_cast_for_variadic_arg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for MissingCastForVariadicArg<'tcx> {
2121
}
2222

2323
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
24-
let mut err = self.sess.struct_span_fatal_with_code(
24+
let mut err = self.sess.struct_span_err_with_code(
2525
self.span,
2626
&format!("can't pass `{}` to variadic function", self.ty),
2727
self.code(),

compiler/rustc_typeck/src/structured_errors/sized_unsized_cast.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl<'tcx> StructuredDiagnostic<'tcx> for SizedUnsizedCast<'tcx> {
2121
}
2222

2323
fn diagnostic_common(&self) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
24-
let mut err = self.sess.struct_span_fatal_with_code(
24+
let mut err = self.sess.struct_span_err_with_code(
2525
self.span,
2626
&format!(
2727
"cannot cast thin pointer `{}` to fat pointer `{}`",

0 commit comments

Comments
 (0)