Skip to content

Commit 9a8d6b8

Browse files
committed
Do not capture stderr in the compiler. Instead just panic silently for fatal errors
1 parent 9fd7da9 commit 9a8d6b8

File tree

19 files changed

+90
-97
lines changed

19 files changed

+90
-97
lines changed

Diff for: src/librustc/hir/lowering.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2837,8 +2837,8 @@ impl<'a> LoweringContext<'a> {
28372837
(&None, &Some(..), Closed) => "RangeToInclusive",
28382838
(&Some(..), &Some(..), Closed) => "RangeInclusive",
28392839
(_, &None, Closed) =>
2840-
panic!(self.diagnostic().span_fatal(
2841-
e.span, "inclusive range with no end")),
2840+
self.diagnostic().span_fatal(
2841+
e.span, "inclusive range with no end").raise(),
28422842
};
28432843

28442844
let fields =

Diff for: src/librustc/session/config.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1333,16 +1333,16 @@ pub fn build_target_config(opts: &Options, sp: &Handler) -> Config {
13331333
sp.struct_fatal(&format!("Error loading target specification: {}", e))
13341334
.help("Use `--print target-list` for a list of built-in targets")
13351335
.emit();
1336-
panic!(FatalError);
1336+
FatalError.raise();
13371337
}
13381338
};
13391339

13401340
let (isize_ty, usize_ty) = match &target.target_pointer_width[..] {
13411341
"16" => (ast::IntTy::I16, ast::UintTy::U16),
13421342
"32" => (ast::IntTy::I32, ast::UintTy::U32),
13431343
"64" => (ast::IntTy::I64, ast::UintTy::U64),
1344-
w => panic!(sp.fatal(&format!("target specification was invalid: \
1345-
unrecognized target-pointer-width {}", w))),
1344+
w => sp.fatal(&format!("target specification was invalid: \
1345+
unrecognized target-pointer-width {}", w)).raise(),
13461346
};
13471347

13481348
Config {

Diff for: src/librustc/session/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -250,18 +250,18 @@ impl Session {
250250
}
251251

252252
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
253-
panic!(self.diagnostic().span_fatal(sp, msg))
253+
self.diagnostic().span_fatal(sp, msg).raise()
254254
}
255255
pub fn span_fatal_with_code<S: Into<MultiSpan>>(
256256
&self,
257257
sp: S,
258258
msg: &str,
259259
code: DiagnosticId,
260260
) -> ! {
261-
panic!(self.diagnostic().span_fatal_with_code(sp, msg, code))
261+
self.diagnostic().span_fatal_with_code(sp, msg, code).raise()
262262
}
263263
pub fn fatal(&self, msg: &str) -> ! {
264-
panic!(self.diagnostic().fatal(msg))
264+
self.diagnostic().fatal(msg).raise()
265265
}
266266
pub fn span_err_or_warn<S: Into<MultiSpan>>(&self, is_warning: bool, sp: S, msg: &str) {
267267
if is_warning {
@@ -919,7 +919,7 @@ pub fn build_session_(sopts: config::Options,
919919
let host = match Target::search(config::host_triple()) {
920920
Ok(t) => t,
921921
Err(e) => {
922-
panic!(span_diagnostic.fatal(&format!("Error loading host specification: {}", e)));
922+
span_diagnostic.fatal(&format!("Error loading host specification: {}", e)).raise();
923923
}
924924
};
925925
let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
@@ -945,7 +945,7 @@ pub fn build_session_(sopts: config::Options,
945945
let working_dir = match env::current_dir() {
946946
Ok(dir) => dir,
947947
Err(e) => {
948-
panic!(p_s.span_diagnostic.fatal(&format!("Current directory is invalid: {}", e)))
948+
p_s.span_diagnostic.fatal(&format!("Current directory is invalid: {}", e)).raise()
949949
}
950950
};
951951
let working_dir = file_path_mapping.map_prefix(working_dir);
@@ -1076,7 +1076,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
10761076
};
10771077
let handler = errors::Handler::with_emitter(true, false, emitter);
10781078
handler.emit(&MultiSpan::new(), msg, errors::Level::Fatal);
1079-
panic!(errors::FatalError);
1079+
errors::FatalError.raise();
10801080
}
10811081

10821082
pub fn early_warn(output: config::ErrorOutputType, msg: &str) {

Diff for: src/librustc_driver/lib.rs

+7-28
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ use std::env;
8787
use std::ffi::OsString;
8888
use std::io::{self, Read, Write};
8989
use std::iter::repeat;
90+
use std::panic;
9091
use std::path::PathBuf;
9192
use std::process::{self, Command, Stdio};
9293
use std::rc::Rc;
9394
use std::str;
94-
use std::sync::{Arc, Mutex};
9595
use std::thread;
9696

9797
use syntax::ast;
@@ -168,7 +168,7 @@ pub fn run<F>(run_compiler: F) -> isize
168168
handler.emit(&MultiSpan::new(),
169169
"aborting due to previous error(s)",
170170
errors::Level::Fatal);
171-
exit_on_err();
171+
panic::resume_unwind(Box::new(errors::FatalErrorMarker));
172172
}
173173
}
174174
}
@@ -1228,27 +1228,16 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<Any + Send>>
12281228
/// The diagnostic emitter yielded to the procedure should be used for reporting
12291229
/// errors of the compiler.
12301230
pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
1231-
struct Sink(Arc<Mutex<Vec<u8>>>);
1232-
impl Write for Sink {
1233-
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
1234-
Write::write(&mut *self.0.lock().unwrap(), data)
1235-
}
1236-
fn flush(&mut self) -> io::Result<()> {
1237-
Ok(())
1238-
}
1239-
}
1240-
1241-
let data = Arc::new(Mutex::new(Vec::new()));
1242-
let err = Sink(data.clone());
1243-
12441231
let result = in_rustc_thread(move || {
1245-
io::set_panic(Some(box err));
12461232
f()
12471233
});
12481234

12491235
if let Err(value) = result {
12501236
// Thread panicked without emitting a fatal diagnostic
1251-
if !value.is::<errors::FatalError>() {
1237+
if !value.is::<errors::FatalErrorMarker>() {
1238+
// Emit a newline
1239+
eprintln!("");
1240+
12521241
let emitter =
12531242
Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
12541243
None,
@@ -1273,22 +1262,12 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
12731262
&note,
12741263
errors::Level::Note);
12751264
}
1276-
1277-
eprintln!("{}", str::from_utf8(&data.lock().unwrap()).unwrap());
12781265
}
12791266

1280-
exit_on_err();
1267+
panic::resume_unwind(Box::new(errors::FatalErrorMarker));
12811268
}
12821269
}
12831270

1284-
fn exit_on_err() -> ! {
1285-
// Panic so the process returns a failure code, but don't pollute the
1286-
// output with some unnecessary panic messages, we've already
1287-
// printed everything that we needed to.
1288-
io::set_panic(Some(box io::sink()));
1289-
panic!();
1290-
}
1291-
12921271
#[cfg(stage0)]
12931272
pub fn diagnostics_registry() -> errors::registry::Registry {
12941273
use errors::registry::Registry;

Diff for: src/librustc_errors/lib.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#![cfg_attr(unix, feature(libc))]
2020
#![feature(conservative_impl_trait)]
2121
#![feature(i128_type)]
22+
#![feature(optin_builtin_traits)]
2223

2324
extern crate term;
2425
#[cfg(unix)]
@@ -44,6 +45,7 @@ use std::rc::Rc;
4445
use std::{error, fmt};
4546
use std::sync::atomic::AtomicUsize;
4647
use std::sync::atomic::Ordering::SeqCst;
48+
use std::panic;
4749

4850
mod diagnostic;
4951
mod diagnostic_builder;
@@ -201,6 +203,18 @@ impl CodeSuggestion {
201203
#[must_use]
202204
pub struct FatalError;
203205

206+
pub struct FatalErrorMarker;
207+
208+
// Don't implement Send on FatalError. This makes it impossible to panic!(FatalError).
209+
// We don't want to invoke the panic handler and print a backtrace for fatal errors.
210+
impl !Send for FatalError {}
211+
212+
impl FatalError {
213+
pub fn raise(self) -> ! {
214+
panic::resume_unwind(Box::new(FatalErrorMarker))
215+
}
216+
}
217+
204218
impl fmt::Display for FatalError {
205219
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
206220
write!(f, "parser fatal error")
@@ -539,7 +553,7 @@ impl Handler {
539553
}
540554
}
541555

542-
panic!(self.fatal(&s));
556+
self.fatal(&s).raise();
543557
}
544558
pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) {
545559
if lvl == Warning && !self.flags.can_emit_warnings {

Diff for: src/librustc_trans/back/write.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize {
155155

156156
pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
157157
target_machine_factory(sess)().unwrap_or_else(|err| {
158-
panic!(llvm_err(sess.diagnostic(), err))
158+
llvm_err(sess.diagnostic(), err).raise()
159159
})
160160
}
161161

@@ -582,7 +582,7 @@ fn generate_lto_work(cgcx: &CodegenContext,
582582
lto::LTOMode::JustThisCrate
583583
};
584584
let lto_modules = lto::run(cgcx, modules, mode, &mut timeline)
585-
.unwrap_or_else(|e| panic!(e));
585+
.unwrap_or_else(|e| e.raise());
586586

587587
lto_modules.into_iter().map(|module| {
588588
let cost = module.cost();

Diff for: src/libsyntax/ext/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ impl<'a> ExtCtxt<'a> {
786786
/// substitute; we never hit resolve/type-checking so the dummy
787787
/// value doesn't have to match anything)
788788
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
789-
panic!(self.parse_sess.span_diagnostic.span_fatal(sp, msg));
789+
self.parse_sess.span_diagnostic.span_fatal(sp, msg).raise();
790790
}
791791

792792
/// Emit `msg` attached to `sp`, without immediately stopping

Diff for: src/libsyntax/ext/expand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
455455
suggested_limit));
456456
err.emit();
457457
self.cx.trace_macros_diag();
458-
panic!(FatalError);
458+
FatalError.raise();
459459
}
460460

461461
Some(result)

Diff for: src/libsyntax/ext/source_util.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,10 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[tokenstream::T
116116
while self.p.token != token::Eof {
117117
match panictry!(self.p.parse_item()) {
118118
Some(item) => ret.push(item),
119-
None => panic!(self.p.diagnostic().span_fatal(self.p.span,
119+
None => self.p.diagnostic().span_fatal(self.p.span,
120120
&format!("expected item, found `{}`",
121-
self.p.this_token_to_string())))
121+
self.p.this_token_to_string()))
122+
.raise()
122123
}
123124
}
124125
Some(ret)

Diff for: src/libsyntax/ext/tt/macro_parser.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -573,15 +573,15 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
573573
Some(i) => token::NtItem(i),
574574
None => {
575575
p.fatal("expected an item keyword").emit();
576-
panic!(FatalError);
576+
FatalError.raise();
577577
}
578578
},
579579
"block" => token::NtBlock(panictry!(p.parse_block())),
580580
"stmt" => match panictry!(p.parse_stmt()) {
581581
Some(s) => token::NtStmt(s),
582582
None => {
583583
p.fatal("expected a statement").emit();
584-
panic!(FatalError);
584+
FatalError.raise();
585585
}
586586
},
587587
"pat" => token::NtPat(panictry!(p.parse_pat())),
@@ -597,7 +597,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
597597
let token_str = pprust::token_to_string(&p.token);
598598
p.fatal(&format!("expected ident, found {}",
599599
&token_str[..])).emit();
600-
panic!(FatalError)
600+
FatalError.raise()
601601
}
602602
},
603603
"path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),

Diff for: src/libsyntax/ext/tt/macro_rules.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,10 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
222222
Success(m) => m,
223223
Failure(sp, tok) => {
224224
let s = parse_failure_msg(tok);
225-
panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s));
225+
sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s).raise();
226226
}
227227
Error(sp, s) => {
228-
panic!(sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s));
228+
sess.span_diagnostic.span_fatal(sp.substitute_dummy(def.span), &s).raise();
229229
}
230230
};
231231

Diff for: src/libsyntax/feature_gate.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1954,7 +1954,7 @@ impl FeatureChecker {
19541954
.span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
19551955
.emit();
19561956

1957-
panic!(FatalError);
1957+
FatalError.raise();
19581958
}
19591959

19601960
if let (Some(span), None) = (self.copy_closures, self.clone_closures) {
@@ -1963,7 +1963,7 @@ impl FeatureChecker {
19631963
.span_note(span, "`#![feature(copy_closures)]` declared here")
19641964
.emit();
19651965

1966-
panic!(FatalError);
1966+
FatalError.raise();
19671967
}
19681968
}
19691969
}

Diff for: src/libsyntax/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ macro_rules! panictry {
5454
Ok(e) => e,
5555
Err(mut e) => {
5656
e.emit();
57-
panic!(FatalError);
57+
FatalError.raise()
5858
}
5959
}
6060
})

Diff for: src/libsyntax/parse/lexer/comments.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ fn read_block_comment(rdr: &mut StringReader,
265265
while level > 0 {
266266
debug!("=== block comment level {}", level);
267267
if rdr.is_eof() {
268-
panic!(rdr.fatal("unterminated block comment"));
268+
rdr.fatal("unterminated block comment").raise();
269269
}
270270
if rdr.ch_is('\n') {
271271
trim_whitespace_prefix_and_push_line(&mut lines, curr_line, col);

0 commit comments

Comments
 (0)