1#![feature(rustc_private, never_type)]
2
3extern crate rustc_data_structures;
4extern crate rustc_errors;
5extern crate rustc_session;
6extern crate rustc_span;
7
8use std::{cell::Cell, io, sync::Arc};
9
10use flux_common::result::{ErrorCollector, ErrorEmitter};
11use rustc_data_structures::sync;
12pub use rustc_errors::ErrorGuaranteed;
13use rustc_errors::{
14 Diagnostic, ErrCode, FatalAbort, FatalError, LazyFallbackBundle,
15 annotate_snippet_emitter_writer::AnnotateSnippetEmitter,
16 emitter::{Emitter, HumanEmitter, HumanReadableErrorType, stderr_destination},
17 json::JsonEmitter,
18 translation::Translator,
19};
20use rustc_session::{
21 config::{self, ErrorOutputType},
22 parse::ParseSess,
23};
24use rustc_span::source_map::SourceMap;
25
26pub struct FluxSession {
27 pub parse_sess: ParseSess,
28}
29
30pub const E0999: ErrCode = ErrCode::from_u32(999);
32
33impl FluxSession {
34 pub fn new(
35 opts: &config::Options,
36 source_map: Arc<SourceMap>,
37 fallback_bundle: LazyFallbackBundle,
38 ) -> Self {
39 let emitter = emitter(opts, source_map.clone(), fallback_bundle);
40 let dcx = rustc_errors::DiagCtxt::new(emitter);
41 Self { parse_sess: ParseSess::with_dcx(dcx, source_map) }
42 }
43
44 pub fn err_count(&self) -> usize {
45 self.parse_sess.dcx().err_count()
46 }
47
48 #[track_caller]
49 pub fn emit_err<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
50 self.parse_sess.dcx().emit_err(err)
51 }
52
53 #[track_caller]
54 pub fn emit_fatal<'a>(&'a self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! {
55 self.parse_sess.dcx().emit_fatal(fatal)
56 }
57
58 pub fn abort(&self, _: ErrorGuaranteed) -> ! {
59 self.parse_sess.dcx().abort_if_errors();
60 FatalError.raise()
61 }
62
63 pub fn abort_if_errors(&self) {
64 self.parse_sess.dcx().abort_if_errors();
65 }
66
67 pub fn finish_diagnostics(&self) {
68 self.parse_sess.dcx().print_error_count();
69 self.abort_if_errors();
70 }
71
72 pub fn dcx(&self) -> &rustc_errors::DiagCtxt {
73 &self.parse_sess.dcx()
74 }
75}
76
77fn emitter(
78 opts: &config::Options,
79 source_map: Arc<SourceMap>,
80 fallback_fluent_bundle: LazyFallbackBundle,
81) -> Box<dyn Emitter + sync::DynSend> {
82 let track_diagnostics = opts.unstable_opts.track_diagnostics;
83
84 let translator = Translator { fluent_bundle: None, fallback_fluent_bundle };
85 match opts.error_format {
86 ErrorOutputType::HumanReadable { kind, color_config } => {
87 if let HumanReadableErrorType::AnnotateSnippet = kind {
88 let emitter =
89 AnnotateSnippetEmitter::new(Some(source_map), translator, false, false);
90 Box::new(emitter)
91 } else {
92 let dst = stderr_destination(color_config);
93 let emitter = HumanEmitter::new(dst, translator)
94 .sm(Some(source_map))
95 .short_message(kind.short())
96 .diagnostic_width(opts.diagnostic_width)
97 .track_diagnostics(track_diagnostics)
98 .terminal_url(opts.unstable_opts.terminal_urls);
99 Box::new(emitter)
100 }
101 }
102 ErrorOutputType::Json { pretty, json_rendered, color_config } => {
103 Box::new(
104 JsonEmitter::new(
105 Box::new(io::BufWriter::new(io::stderr())),
106 Some(source_map),
107 translator,
108 pretty,
109 json_rendered,
110 color_config,
111 )
112 .track_diagnostics(track_diagnostics)
113 .diagnostic_width(opts.diagnostic_width)
114 .terminal_url(opts.unstable_opts.terminal_urls),
115 )
116 }
117 }
118}
119
120impl ErrorEmitter for FluxSession {
121 fn emit<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
122 self.emit_err(err)
123 }
124}
125
126pub struct Errors<'sess> {
128 sess: &'sess FluxSession,
129 err: Cell<Option<ErrorGuaranteed>>,
130}
131
132impl<'sess> Errors<'sess> {
133 pub fn new(sess: &'sess FluxSession) -> Self {
134 Self { sess, err: Cell::new(None) }
135 }
136
137 pub fn has_errors(&self) -> bool {
138 self.err.get().is_some()
139 }
140
141 #[track_caller]
142 pub fn emit<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
143 let err = self.sess.emit_err(err);
144 self.err.set(Some(err));
145 err
146 }
147
148 pub fn into_result(self) -> Result<(), ErrorGuaranteed> {
149 if let Some(err) = self.err.into_inner() { Err(err) } else { Ok(()) }
150 }
151}
152
153impl ErrorEmitter for Errors<'_> {
154 #[track_caller]
155 fn emit<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
156 Errors::emit(self, err)
157 }
158}
159
160impl ErrorCollector<ErrorGuaranteed> for Errors<'_> {
161 type Result = Result<(), ErrorGuaranteed>;
162
163 fn collect(&mut self, err: ErrorGuaranteed) {
164 *self.err.get_mut() = Some(err);
165 }
166
167 fn into_result(self) -> Self::Result {
168 Errors::into_result(self)
169 }
170}