rustc: distinguish compilation failure from ICE
This commit changes the exit status of rustc to 1 in the presence of compilation errors. In the event of an unexpected panic (ICE) the standard panic error exit status of 101 remains. A run-make test is added to ensure that the exit code does not regress, and compiletest is updated to check for an exit status of 1 or 101, depending on the mode and suite. This is a breaking change for custom drivers. Fixes #51971.
This commit is contained in:
parent
4f3c7a472b
commit
8f4ccac5e2
9 changed files with 110 additions and 25 deletions
|
@ -94,7 +94,9 @@ use std::cmp::max;
|
|||
use std::default::Default;
|
||||
use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::ffi::OsString;
|
||||
use std::fmt::{self, Display};
|
||||
use std::io::{self, Read, Write};
|
||||
use std::iter::repeat;
|
||||
use std::mem;
|
||||
|
@ -146,6 +148,12 @@ pub mod target_features {
|
|||
}
|
||||
}
|
||||
|
||||
/// Exit status code used for successful compilation and help output.
|
||||
pub const EXIT_SUCCESS: isize = 0;
|
||||
|
||||
/// Exit status code used for compilation failures and invalid flags.
|
||||
pub const EXIT_FAILURE: isize = 1;
|
||||
|
||||
const BUG_REPORT_URL: &'static str = "https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.\
|
||||
md#bug-reports";
|
||||
|
||||
|
@ -178,7 +186,7 @@ pub fn abort_on_err<T>(result: Result<T, CompileIncomplete>, sess: &Session) ->
|
|||
pub fn run<F>(run_compiler: F) -> isize
|
||||
where F: FnOnce() -> (CompileResult, Option<Session>) + Send + 'static
|
||||
{
|
||||
monitor(move || {
|
||||
let result = monitor(move || {
|
||||
let (result, session) = run_compiler();
|
||||
if let Err(CompileIncomplete::Errored(_)) = result {
|
||||
match session {
|
||||
|
@ -201,7 +209,11 @@ pub fn run<F>(run_compiler: F) -> isize
|
|||
}
|
||||
}
|
||||
});
|
||||
0
|
||||
|
||||
match result {
|
||||
Ok(()) => EXIT_SUCCESS,
|
||||
Err(_) => EXIT_FAILURE,
|
||||
}
|
||||
}
|
||||
|
||||
fn load_backend_from_dylib(path: &Path) -> fn() -> Box<dyn CodegenBackend> {
|
||||
|
@ -1625,20 +1637,30 @@ fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CompilationFailure;
|
||||
|
||||
impl Error for CompilationFailure {}
|
||||
|
||||
impl Display for CompilationFailure {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "compilation had errors")
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a procedure which will detect panics in the compiler and print nicer
|
||||
/// error messages rather than just failing the test.
|
||||
///
|
||||
/// The diagnostic emitter yielded to the procedure should be used for reporting
|
||||
/// errors of the compiler.
|
||||
pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
|
||||
let result = in_rustc_thread(move || {
|
||||
pub fn monitor<F: FnOnce() + Send + 'static>(f: F) -> Result<(), CompilationFailure> {
|
||||
in_rustc_thread(move || {
|
||||
f()
|
||||
});
|
||||
|
||||
if let Err(value) = result {
|
||||
// Thread panicked without emitting a fatal diagnostic
|
||||
if !value.is::<errors::FatalErrorMarker>() {
|
||||
// Emit a newline
|
||||
}).map_err(|value| {
|
||||
if value.is::<errors::FatalErrorMarker>() {
|
||||
CompilationFailure
|
||||
} else {
|
||||
// Thread panicked without emitting a fatal diagnostic
|
||||
eprintln!("");
|
||||
|
||||
let emitter =
|
||||
|
@ -1677,10 +1699,10 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
|
|||
¬e,
|
||||
errors::Level::Note);
|
||||
}
|
||||
}
|
||||
|
||||
panic::resume_unwind(Box::new(errors::FatalErrorMarker));
|
||||
}
|
||||
panic::resume_unwind(Box::new(errors::FatalErrorMarker));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn diagnostics_registry() -> errors::registry::Registry {
|
||||
|
|
|
@ -57,6 +57,7 @@ use errors::ColorConfig;
|
|||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::default::Default;
|
||||
use std::env;
|
||||
use std::panic;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process;
|
||||
use std::sync::mpsc::channel;
|
||||
|
@ -115,7 +116,7 @@ pub fn main() {
|
|||
syntax::with_globals(move || {
|
||||
get_args().map(|args| main_args(&args)).unwrap_or(1)
|
||||
})
|
||||
}).unwrap().join().unwrap_or(101);
|
||||
}).unwrap().join().unwrap_or(rustc_driver::EXIT_FAILURE);
|
||||
process::exit(res as i32);
|
||||
}
|
||||
|
||||
|
@ -667,7 +668,7 @@ where R: 'static + Send,
|
|||
|
||||
let (tx, rx) = channel();
|
||||
|
||||
rustc_driver::monitor(move || syntax::with_globals(move || {
|
||||
let result = rustc_driver::monitor(move || syntax::with_globals(move || {
|
||||
use rustc::session::config::Input;
|
||||
|
||||
let (mut krate, renderinfo) =
|
||||
|
@ -771,7 +772,11 @@ where R: 'static + Send,
|
|||
|
||||
tx.send(f(Output { krate: krate, renderinfo: renderinfo, passes: passes })).unwrap();
|
||||
}));
|
||||
rx.recv().unwrap()
|
||||
|
||||
match result {
|
||||
Ok(()) => rx.recv().unwrap(),
|
||||
Err(_) => panic::resume_unwind(Box::new(errors::FatalErrorMarker)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Prints deprecation warnings for deprecated options
|
||||
|
|
11
src/test/run-make-fulldeps/exit-code/Makefile
Normal file
11
src/test/run-make-fulldeps/exit-code/Makefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
-include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) success.rs; [ $$? -eq 0 ]
|
||||
$(RUSTC) --invalid-arg-foo; [ $$? -eq 1 ]
|
||||
$(RUSTC) compile-error.rs; [ $$? -eq 1 ]
|
||||
$(RUSTC) -Ztreat-err-as-bug compile-error.rs; [ $$? -eq 101 ]
|
||||
$(RUSTDOC) -o $(TMPDIR)/exit-code success.rs; [ $$? -eq 0 ]
|
||||
$(RUSTDOC) --invalid-arg-foo; [ $$? -eq 1 ]
|
||||
$(RUSTDOC) compile-error.rs; [ $$? -eq 1 ]
|
||||
$(RUSTDOC) lint-failure.rs; [ $$? -eq 1 ]
|
13
src/test/run-make-fulldeps/exit-code/compile-error.rs
Normal file
13
src/test/run-make-fulldeps/exit-code/compile-error.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
compile_error!("kaboom");
|
||||
}
|
16
src/test/run-make-fulldeps/exit-code/lint-failure.rs
Normal file
16
src/test/run-make-fulldeps/exit-code/lint-failure.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![deny(intra_doc_link_resolution_failure)]
|
||||
|
||||
/// [intradoc::failure]
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
14
src/test/run-make-fulldeps/exit-code/success.rs
Normal file
14
src/test/run-make-fulldeps/exit-code/success.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
/// Main function
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
|
@ -8,6 +8,8 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-test currently ICEs when using NLL (#52416)
|
||||
|
||||
// We used to ICE when moving out of a `*mut T` or `*const T`.
|
||||
|
||||
struct T(u8);
|
||||
|
|
|
@ -14,8 +14,7 @@ use std::io::prelude::*;
|
|||
use std::io::BufReader;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use common;
|
||||
use common::Config;
|
||||
use common::{self, Config, Mode};
|
||||
use util;
|
||||
|
||||
use extract_gdb_version;
|
||||
|
@ -262,7 +261,7 @@ impl TestProps {
|
|||
disable_ui_testing_normalization: false,
|
||||
normalize_stdout: vec![],
|
||||
normalize_stderr: vec![],
|
||||
failure_status: 101,
|
||||
failure_status: -1,
|
||||
run_rustfix: false,
|
||||
}
|
||||
}
|
||||
|
@ -393,6 +392,11 @@ impl TestProps {
|
|||
|
||||
if let Some(code) = config.parse_failure_status(ln) {
|
||||
self.failure_status = code;
|
||||
} else {
|
||||
self.failure_status = match config.mode {
|
||||
Mode::RunFail => 101,
|
||||
_ => 1,
|
||||
};
|
||||
}
|
||||
|
||||
if !self.run_rustfix {
|
||||
|
|
|
@ -1170,12 +1170,10 @@ impl<'test> TestCx<'test> {
|
|||
}
|
||||
|
||||
fn check_no_compiler_crash(&self, proc_res: &ProcRes) {
|
||||
for line in proc_res.stderr.lines() {
|
||||
if line.contains("error: internal compiler error") {
|
||||
self.fatal_proc_rec("compiler encountered internal error", proc_res);
|
||||
} else if line.contains(" panicked at ") {
|
||||
self.fatal_proc_rec("compiler panicked", proc_res);
|
||||
}
|
||||
match proc_res.status.code() {
|
||||
Some(101) => self.fatal_proc_rec("compiler encountered internal error", proc_res),
|
||||
None => self.fatal_proc_rec("compiler terminated by signal", proc_res),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue