Auto merge of #62226 - Centril:rollup-rcy1alx, r=Centril

Rollup of 7 pull requests

Successful merges:

 - #61199 (Revert "Set test flag when rustdoc is running with --test option" )
 - #61755 (Add `--pass $mode` to compiletest through `./x.py`)
 - #61818 (Issue #60709 test)
 - #62023 (publish_toolstate: don't use 'new' from inside the loop)
 - #62104 (Inform the query system about properties of queries at compile time)
 - #62163 (Avoid mem::uninitialized() in std::sys::unix)
 - #62204 (doc(libcore) Fix CS)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-06-29 11:45:11 +00:00
commit 9a90d03ad1
41 changed files with 392 additions and 224 deletions

View File

@ -598,6 +598,7 @@ fn test_with_no_doc_stage0() {
bless: false,
compare_mode: None,
rustfix_coverage: false,
pass: None,
};
let build = Build::new(config);
@ -640,6 +641,7 @@ fn test_exclude() {
bless: false,
compare_mode: None,
rustfix_coverage: false,
pass: None,
};
let build = Build::new(config);

View File

@ -58,6 +58,7 @@ pub enum Subcommand {
/// Whether to automatically update stderr/stdout files
bless: bool,
compare_mode: Option<String>,
pass: Option<String>,
test_args: Vec<String>,
rustc_args: Vec<String>,
fail_fast: bool,
@ -199,6 +200,12 @@ To learn more about a subcommand, run `./x.py <subcommand> -h`"
"mode describing what file the actual ui output will be compared to",
"COMPARE MODE",
);
opts.optopt(
"",
"pass",
"force {check,build,run}-pass tests to this mode.",
"check | build | run"
);
opts.optflag(
"",
"rustfix-coverage",
@ -401,6 +408,7 @@ Arguments:
paths,
bless: matches.opt_present("bless"),
compare_mode: matches.opt_str("compare-mode"),
pass: matches.opt_str("pass"),
test_args: matches.opt_strs("test-args"),
rustc_args: matches.opt_strs("rustc-args"),
fail_fast: !matches.opt_present("no-fail-fast"),
@ -524,6 +532,15 @@ impl Subcommand {
_ => None,
}
}
pub fn pass(&self) -> Option<&str> {
match *self {
Subcommand::Test {
ref pass, ..
} => pass.as_ref().map(|s| &s[..]),
_ => None,
}
}
}
fn split(s: &[String]) -> Vec<String> {

View File

@ -1065,6 +1065,11 @@ impl Step for Compiletest {
}
});
if let Some(ref pass) = builder.config.cmd.pass() {
cmd.arg("--pass");
cmd.arg(pass);
}
if let Some(ref nodejs) = builder.config.nodejs {
cmd.arg("--nodejs").arg(nodejs);
}

View File

@ -196,7 +196,7 @@ pub trait FromIterator<A>: Sized {
/// ```rust
/// fn collect_as_strings<T>(collection: T) -> Vec<String>
/// where T: IntoIterator,
/// T::Item : std::fmt::Debug,
/// T::Item: std::fmt::Debug,
/// {
/// collection
/// .into_iter()

View File

@ -73,9 +73,9 @@ impl<T: ?Sized> !Send for *mut T { }
/// impl Foo for Impl { }
/// impl Bar for Impl { }
///
/// let x: &Foo = &Impl; // OK
/// // let y: &Bar = &Impl; // error: the trait `Bar` cannot
/// // be made into an object
/// let x: &dyn Foo = &Impl; // OK
/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot
/// // be made into an object
/// ```
///
/// [trait object]: ../../book/ch17-02-trait-objects.html

View File

@ -510,6 +510,8 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
/// A simple example:
///
/// ```
/// #![feature(mem_take)]
///
/// use std::mem;
///
/// let mut v: Vec<i32> = vec![1, 2];
@ -540,7 +542,8 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
/// `self`, allowing it to be returned:
///
/// ```
/// # #![allow(dead_code)]
/// #![feature(mem_take)]
///
/// use std::mem;
///
/// # struct Buffer<T> { buf: Vec<T> }

View File

@ -53,7 +53,7 @@
/// let value: i32 = 123;
///
/// // let the compiler make a trait object
/// let object: &Foo = &value;
/// let object: &dyn Foo = &value;
///
/// // look at the raw representation
/// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) };
@ -65,7 +65,7 @@
///
/// // construct a new object, pointing to a different `i32`, being
/// // careful to use the `i32` vtable from `object`
/// let synthesized: &Foo = unsafe {
/// let synthesized: &dyn Foo = unsafe {
/// mem::transmute(raw::TraitObject {
/// data: &other_value as *const _ as *mut (),
/// vtable: raw_object.vtable,

View File

@ -142,9 +142,6 @@ macro_rules! define_dep_nodes {
}
}
// FIXME: Make `is_anon`, `is_eval_always` and `has_params` properties
// of queries
#[inline(always)]
pub fn is_anon(&self) -> bool {
match *self {
$(
@ -163,7 +160,6 @@ macro_rules! define_dep_nodes {
}
#[allow(unreachable_code)]
#[inline(always)]
pub fn has_params(&self) -> bool {
match *self {
$(

View File

@ -1,5 +1,5 @@
use crate::dep_graph::SerializedDepNodeIndex;
use crate::dep_graph::DepNode;
use crate::dep_graph::{DepKind, DepNode};
use crate::hir::def_id::{CrateNum, DefId};
use crate::ty::TyCtxt;
use crate::ty::query::queries;
@ -28,6 +28,9 @@ pub trait QueryConfig<'tcx> {
}
pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
const ANON: bool;
const EVAL_ALWAYS: bool;
fn query(key: Self::Key) -> Query<'tcx>;
// Don't use this method to access query results, instead use the methods on TyCtxt
@ -35,6 +38,8 @@ pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode;
fn dep_kind() -> DepKind;
// Don't use this method to compute query results, instead use the methods on TyCtxt
fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value;

View File

@ -101,6 +101,6 @@ pub use self::on_disk_cache::OnDiskCache;
rustc_query_append! { [define_queries!][ <'tcx>
Other {
/// Runs analysis passes on the crate.
[] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
[eval_always] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>,
},
]}

View File

@ -376,15 +376,13 @@ impl<'tcx> TyCtxt<'tcx> {
return self.force_query_with_job::<Q>(key, job, null_dep_node).0;
}
let dep_node = Q::to_dep_node(self, &key);
if dep_node.kind.is_anon() {
if Q::ANON {
profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
self.sess.profiler(|p| p.start_query(Q::NAME));
let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
self.start_query(job.job.clone(), diagnostics, |tcx| {
tcx.dep_graph.with_anon_task(dep_node.kind, || {
tcx.dep_graph.with_anon_task(Q::dep_kind(), || {
Q::compute(tcx.global_tcx(), key)
})
})
@ -405,7 +403,9 @@ impl<'tcx> TyCtxt<'tcx> {
return result;
}
if !dep_node.kind.is_eval_always() {
let dep_node = Q::to_dep_node(self, &key);
if !Q::EVAL_ALWAYS {
// The diagnostics for this query will be
// promoted to the current session during
// try_mark_green(), so we can ignore them here.
@ -546,7 +546,7 @@ impl<'tcx> TyCtxt<'tcx> {
let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| {
self.start_query(job.job.clone(), diagnostics, |tcx| {
if dep_node.kind.is_eval_always() {
if Q::EVAL_ALWAYS {
tcx.dep_graph.with_eval_always_task(dep_node,
tcx,
key,
@ -569,8 +569,8 @@ impl<'tcx> TyCtxt<'tcx> {
self.dep_graph.mark_loaded_from_cache(dep_node_index, false);
}
if dep_node.kind != crate::dep_graph::DepKind::Null {
if unlikely!(!diagnostics.is_empty()) {
if unlikely!(!diagnostics.is_empty()) {
if dep_node.kind != crate::dep_graph::DepKind::Null {
self.queries.on_disk_cache
.store_diagnostics(dep_node_index, diagnostics);
}
@ -589,15 +589,16 @@ impl<'tcx> TyCtxt<'tcx> {
///
/// Note: The optimization is only available during incr. comp.
pub(super) fn ensure_query<Q: QueryDescription<'tcx>>(self, key: Q::Key) -> () {
let dep_node = Q::to_dep_node(self, &key);
if dep_node.kind.is_eval_always() {
if Q::EVAL_ALWAYS {
let _ = self.get_query::<Q>(DUMMY_SP, key);
return;
}
// Ensuring an anonymous query makes no sense
assert!(!dep_node.kind.is_anon());
assert!(!Q::ANON);
let dep_node = Q::to_dep_node(self, &key);
if self.dep_graph.try_mark_green_and_read(self, &dep_node).is_none() {
// A None return from `try_mark_green_and_read` means that this is either
// a new dep node or that the dep node has already been marked red.
@ -653,6 +654,30 @@ macro_rules! handle_cycle_error {
};
}
macro_rules! is_anon {
([]) => {{
false
}};
([anon$(, $modifiers:ident)*]) => {{
true
}};
([$other:ident$(, $modifiers:ident)*]) => {
is_anon!([$($modifiers),*])
};
}
macro_rules! is_eval_always {
([]) => {{
false
}};
([eval_always$(, $modifiers:ident)*]) => {{
true
}};
([$other:ident$(, $modifiers:ident)*]) => {
is_eval_always!([$($modifiers),*])
};
}
macro_rules! hash_result {
([][$hcx:expr, $result:expr]) => {{
dep_graph::hash_result($hcx, &$result)
@ -933,6 +958,9 @@ macro_rules! define_queries_inner {
}
impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> {
const ANON: bool = is_anon!([$($modifiers)*]);
const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]);
#[inline(always)]
fn query(key: Self::Key) -> Query<'tcx> {
Query::$name(key)
@ -951,6 +979,11 @@ macro_rules! define_queries_inner {
DepNode::new(tcx, $node(*key))
}
#[inline(always)]
fn dep_kind() -> dep_graph::DepKind {
dep_graph::DepKind::$node
}
#[inline]
fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value {
__query_compute::$name(move || {

View File

@ -423,20 +423,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
if modifiers.no_hash {
attributes.push(quote! { no_hash });
};
let mut attribute_stream = quote! {};
for e in attributes.into_iter().intersperse(quote! {,}) {
attribute_stream.extend(e);
}
// Add the query to the group
group_stream.extend(quote! {
[#attribute_stream] fn #name: #name(#arg) #result,
});
let mut attributes = Vec::new();
// Pass on the anon modifier
if modifiers.anon {
attributes.push(quote! { anon });
@ -450,6 +436,12 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
for e in attributes.into_iter().intersperse(quote! {,}) {
attribute_stream.extend(e);
}
// Add the query to the group
group_stream.extend(quote! {
[#attribute_stream] fn #name: #name(#arg) #result,
});
// Create a dep node for the query
dep_node_def_stream.extend(quote! {
[#attribute_stream] #name(#arg),

View File

@ -351,9 +351,6 @@ impl Options {
.unwrap_or_else(|| PathBuf::from("doc"));
let mut cfgs = matches.opt_strs("cfg");
cfgs.push("rustdoc".to_string());
if should_test {
cfgs.push("test".to_string());
}
let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s));

View File

@ -40,15 +40,15 @@ impl Condvar {
target_os = "android",
target_os = "hermit")))]
pub unsafe fn init(&mut self) {
use crate::mem;
let mut attr: libc::pthread_condattr_t = mem::uninitialized();
let r = libc::pthread_condattr_init(&mut attr);
use crate::mem::MaybeUninit;
let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit();
let r = libc::pthread_condattr_init(attr.as_mut_ptr());
assert_eq!(r, 0);
let r = libc::pthread_condattr_setclock(&mut attr, libc::CLOCK_MONOTONIC);
let r = libc::pthread_condattr_setclock(attr.as_mut_ptr(), libc::CLOCK_MONOTONIC);
assert_eq!(r, 0);
let r = libc::pthread_cond_init(self.inner.get(), &attr);
let r = libc::pthread_cond_init(self.inner.get(), attr.as_ptr());
assert_eq!(r, 0);
let r = libc::pthread_condattr_destroy(&mut attr);
let r = libc::pthread_condattr_destroy(attr.as_mut_ptr());
assert_eq!(r, 0);
}

View File

@ -40,10 +40,9 @@ use libc::MSG_NOSIGNAL;
target_os = "haiku")))]
const MSG_NOSIGNAL: libc::c_int = 0x0;
fn sun_path_offset() -> usize {
fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
// Work with an actual instance of the type since using a null pointer is UB
let addr: libc::sockaddr_un = unsafe { mem::uninitialized() };
let base = &addr as *const _ as usize;
let base = addr as *const _ as usize;
let path = &addr.sun_path as *const _ as usize;
path - base
}
@ -69,7 +68,7 @@ unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::sockl
// null byte for pathname addresses is already there because we zeroed the
// struct
let mut len = sun_path_offset() + bytes.len();
let mut len = sun_path_offset(&addr) + bytes.len();
match bytes.get(0) {
Some(&0) | None => {}
Some(_) => len += 1,
@ -122,7 +121,7 @@ impl SocketAddr {
if len == 0 {
// When there is a datagram from unnamed unix socket
// linux returns zero bytes of address
len = sun_path_offset() as libc::socklen_t; // i.e., zero-length address
len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address
} else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
return Err(io::Error::new(io::ErrorKind::InvalidInput,
"file descriptor did not correspond to a Unix socket"));
@ -200,7 +199,7 @@ impl SocketAddr {
}
fn address<'a>(&'a self) -> AddressKind<'a> {
let len = self.len as usize - sun_path_offset();
let len = self.len as usize - sun_path_offset(&self.addr);
let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
// macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses

View File

@ -1,5 +1,5 @@
use crate::cell::UnsafeCell;
use crate::mem;
use crate::mem::MaybeUninit;
pub struct Mutex { inner: UnsafeCell<libc::pthread_mutex_t> }
@ -40,14 +40,14 @@ impl Mutex {
// references, we instead create the mutex with type
// PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to
// re-lock it from the same thread, thus avoiding undefined behavior.
let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
let r = libc::pthread_mutexattr_init(&mut attr);
let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
let r = libc::pthread_mutexattr_init(attr.as_mut_ptr());
debug_assert_eq!(r, 0);
let r = libc::pthread_mutexattr_settype(&mut attr, libc::PTHREAD_MUTEX_NORMAL);
let r = libc::pthread_mutexattr_settype(attr.as_mut_ptr(), libc::PTHREAD_MUTEX_NORMAL);
debug_assert_eq!(r, 0);
let r = libc::pthread_mutex_init(self.inner.get(), &attr);
let r = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
debug_assert_eq!(r, 0);
let r = libc::pthread_mutexattr_destroy(&mut attr);
let r = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
debug_assert_eq!(r, 0);
}
#[inline]
@ -89,19 +89,19 @@ unsafe impl Sync for ReentrantMutex {}
impl ReentrantMutex {
pub unsafe fn uninitialized() -> ReentrantMutex {
ReentrantMutex { inner: mem::uninitialized() }
ReentrantMutex { inner: UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER) }
}
pub unsafe fn init(&mut self) {
let mut attr: libc::pthread_mutexattr_t = mem::uninitialized();
let result = libc::pthread_mutexattr_init(&mut attr as *mut _);
let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit();
let result = libc::pthread_mutexattr_init(attr.as_mut_ptr());
debug_assert_eq!(result, 0);
let result = libc::pthread_mutexattr_settype(&mut attr as *mut _,
let result = libc::pthread_mutexattr_settype(attr.as_mut_ptr(),
libc::PTHREAD_MUTEX_RECURSIVE);
debug_assert_eq!(result, 0);
let result = libc::pthread_mutex_init(self.inner.get(), &attr as *const _);
let result = libc::pthread_mutex_init(self.inner.get(), attr.as_ptr());
debug_assert_eq!(result, 0);
let result = libc::pthread_mutexattr_destroy(&mut attr as *mut _);
let result = libc::pthread_mutexattr_destroy(attr.as_mut_ptr());
debug_assert_eq!(result, 0);
}

View File

@ -437,7 +437,7 @@ mod tests {
#[cfg(target_os = "android")]
unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
libc::memset(set as *mut _, 0, mem::size_of::<libc::sigset_t>());
set.write_bytes(0u8, 1);
return 0;
}
@ -466,11 +466,11 @@ mod tests {
// Test to make sure that a signal mask does not get inherited.
let mut cmd = Command::new(OsStr::new("cat"));
let mut set: libc::sigset_t = mem::uninitialized();
let mut old_set: libc::sigset_t = mem::uninitialized();
t!(cvt(sigemptyset(&mut set)));
t!(cvt(sigaddset(&mut set, libc::SIGINT)));
t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set)));
let mut set = mem::MaybeUninit::<libc::sigset_t>::uninit();
let mut old_set = mem::MaybeUninit::<libc::sigset_t>::uninit();
t!(cvt(sigemptyset(set.as_mut_ptr())));
t!(cvt(sigaddset(set.as_mut_ptr(), libc::SIGINT)));
t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(), old_set.as_mut_ptr())));
cmd.stdin(Stdio::MakePipe);
cmd.stdout(Stdio::MakePipe);
@ -479,7 +479,7 @@ mod tests {
let stdin_write = pipes.stdin.take().unwrap();
let stdout_read = pipes.stdout.take().unwrap();
t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &old_set,
t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, old_set.as_ptr(),
ptr::null_mut())));
t!(cvt(libc::kill(cat.id() as libc::pid_t, libc::SIGINT)));

View File

@ -202,7 +202,7 @@ impl Command {
// emscripten has no signal support.
#[cfg(not(any(target_os = "emscripten")))]
{
use crate::mem;
use crate::mem::MaybeUninit;
// Reset signal handling so the child process starts in a
// standardized state. libstd ignores SIGPIPE, and signal-handling
// libraries often set a mask. Child processes inherit ignored
@ -210,18 +210,16 @@ impl Command {
// UNIX programs do not reset these things on their own, so we
// need to clean things up now to avoid confusing the program
// we're about to run.
let mut set: libc::sigset_t = mem::uninitialized();
let mut set = MaybeUninit::<libc::sigset_t>::uninit();
if cfg!(target_os = "android") {
// Implementing sigemptyset allow us to support older Android
// versions. See the comment about Android and sig* functions in
// process_common.rs
libc::memset(&mut set as *mut _ as *mut _,
0,
mem::size_of::<libc::sigset_t>());
set.as_mut_ptr().write_bytes(0u8, 1);
} else {
cvt(libc::sigemptyset(&mut set))?;
cvt(libc::sigemptyset(set.as_mut_ptr()))?;
}
cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set,
cvt(libc::pthread_sigmask(libc::SIG_SETMASK, set.as_ptr(),
ptr::null_mut()))?;
let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
if ret == libc::SIG_ERR {
@ -273,7 +271,7 @@ impl Command {
fn posix_spawn(&mut self, stdio: &ChildPipes, envp: Option<&CStringArray>)
-> io::Result<Option<Process>>
{
use crate::mem;
use crate::mem::MaybeUninit;
use crate::sys;
if self.get_gid().is_some() ||
@ -315,63 +313,63 @@ impl Command {
let mut p = Process { pid: 0, status: None };
struct PosixSpawnFileActions(libc::posix_spawn_file_actions_t);
struct PosixSpawnFileActions(MaybeUninit<libc::posix_spawn_file_actions_t>);
impl Drop for PosixSpawnFileActions {
fn drop(&mut self) {
unsafe {
libc::posix_spawn_file_actions_destroy(&mut self.0);
libc::posix_spawn_file_actions_destroy(self.0.as_mut_ptr());
}
}
}
struct PosixSpawnattr(libc::posix_spawnattr_t);
struct PosixSpawnattr(MaybeUninit<libc::posix_spawnattr_t>);
impl Drop for PosixSpawnattr {
fn drop(&mut self) {
unsafe {
libc::posix_spawnattr_destroy(&mut self.0);
libc::posix_spawnattr_destroy(self.0.as_mut_ptr());
}
}
}
unsafe {
let mut file_actions = PosixSpawnFileActions(mem::uninitialized());
let mut attrs = PosixSpawnattr(mem::uninitialized());
let mut file_actions = PosixSpawnFileActions(MaybeUninit::uninit());
let mut attrs = PosixSpawnattr(MaybeUninit::uninit());
libc::posix_spawnattr_init(&mut attrs.0);
libc::posix_spawn_file_actions_init(&mut file_actions.0);
libc::posix_spawnattr_init(attrs.0.as_mut_ptr());
libc::posix_spawn_file_actions_init(file_actions.0.as_mut_ptr());
if let Some(fd) = stdio.stdin.fd() {
cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
cvt(libc::posix_spawn_file_actions_adddup2(file_actions.0.as_mut_ptr(),
fd,
libc::STDIN_FILENO))?;
}
if let Some(fd) = stdio.stdout.fd() {
cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
cvt(libc::posix_spawn_file_actions_adddup2(file_actions.0.as_mut_ptr(),
fd,
libc::STDOUT_FILENO))?;
}
if let Some(fd) = stdio.stderr.fd() {
cvt(libc::posix_spawn_file_actions_adddup2(&mut file_actions.0,
cvt(libc::posix_spawn_file_actions_adddup2(file_actions.0.as_mut_ptr(),
fd,
libc::STDERR_FILENO))?;
}
if let Some((f, cwd)) = addchdir {
cvt(f(&mut file_actions.0, cwd.as_ptr()))?;
cvt(f(file_actions.0.as_mut_ptr(), cwd.as_ptr()))?;
}
let mut set: libc::sigset_t = mem::uninitialized();
cvt(libc::sigemptyset(&mut set))?;
cvt(libc::posix_spawnattr_setsigmask(&mut attrs.0,
&set))?;
cvt(libc::sigaddset(&mut set, libc::SIGPIPE))?;
cvt(libc::posix_spawnattr_setsigdefault(&mut attrs.0,
&set))?;
let mut set = MaybeUninit::<libc::sigset_t>::uninit();
cvt(libc::sigemptyset(set.as_mut_ptr()))?;
cvt(libc::posix_spawnattr_setsigmask(attrs.0.as_mut_ptr(),
set.as_ptr()))?;
cvt(libc::sigaddset(set.as_mut_ptr(), libc::SIGPIPE))?;
cvt(libc::posix_spawnattr_setsigdefault(attrs.0.as_mut_ptr(),
set.as_ptr()))?;
let flags = libc::POSIX_SPAWN_SETSIGDEF |
libc::POSIX_SPAWN_SETSIGMASK;
cvt(libc::posix_spawnattr_setflags(&mut attrs.0, flags as _))?;
cvt(libc::posix_spawnattr_setflags(attrs.0.as_mut_ptr(), flags as _))?;
// Make sure we synchronize access to the global `environ` resource
let _env_lock = sys::os::env_lock();
@ -380,8 +378,8 @@ impl Command {
let ret = libc::posix_spawnp(
&mut p.pid,
self.get_argv()[0],
&file_actions.0,
&attrs.0,
file_actions.0.as_ptr(),
attrs.0.as_ptr(),
self.get_argv().as_ptr() as *const _,
envp as *const _,
);

View File

@ -1132,6 +1132,7 @@ impl LocalInternedString {
}
}
#[inline]
pub fn get(&self) -> &str {
// This returns a valid string since we ensure that `self` outlives the interner
// by creating the interner on a thread which outlives threads which can access it.
@ -1145,6 +1146,7 @@ impl<U: ?Sized> std::convert::AsRef<U> for LocalInternedString
where
str: std::convert::AsRef<U>
{
#[inline]
fn as_ref(&self) -> &U {
self.string.as_ref()
}
@ -1185,6 +1187,7 @@ impl !Sync for LocalInternedString {}
impl std::ops::Deref for LocalInternedString {
type Target = str;
#[inline]
fn deref(&self) -> &str { self.string }
}

View File

@ -1,9 +1,9 @@
// edition:2018
// aux-build:arc_wake.rs
#![feature(async_await, await_macro)]
extern crate arc_wake;
#[path = "../auxiliary/arc_wake.rs"]
mod arc_wake;
use std::pin::Pin;
use std::future::Future;

View File

@ -0,0 +1,28 @@
// This used to compile the future down to ud2, due to uninhabited types being
// handled incorrectly in generators.
// compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018
#![feature(async_await, await_macro)]
#![allow(unused)]
use std::future::Future;
use std::task::Poll;
use std::task::Context;
use std::pin::Pin;
use std::rc::Rc;
struct Never();
impl Future for Never {
type Output = ();
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Pending
}
}
fn main() {
let fut = async {
let _rc = Rc::new(()); // Also crashes with Arc
await!(Never());
};
let _bla = fut; // Moving the future is required.
}

View File

@ -2,12 +2,15 @@
// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// Crates like core have doctests gated on `cfg(not(test))` so we need to make
// sure `cfg(test)` is not active when running `rustdoc --test`.
/// this doctest will be ignored:
///
/// ```
/// assert!(false);
/// ```
#[cfg(not(test))]
#[cfg(test)]
pub struct Foo;
/// this doctest will be tested:
@ -15,5 +18,5 @@ pub struct Foo;
/// ```
/// assert!(true);
/// ```
#[cfg(test)]
#[cfg(not(test))]
pub struct Foo;

View File

@ -1,6 +1,6 @@
running 1 test
test $DIR/cfg-test.rs - Foo (line 15) ... ok
test $DIR/cfg-test.rs - Foo (line 18) ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

View File

@ -1,19 +1,23 @@
#![warn(const_err)]
// compile-pass
// compile-flags: -O
#![deny(const_err)]
fn main() {
println!("{}", 0u32 - 1);
let _x = 0u32 - 1;
//~^ WARN const_err
//~^ ERROR this expression will panic at runtime [const_err]
println!("{}", 1/(1-1));
//~^ WARN const_err
//~^ ERROR this expression will panic at runtime [const_err]
//~| ERROR attempt to divide by zero [const_err]
//~| ERROR reaching this expression at runtime will panic or abort [const_err]
let _x = 1/(1-1);
//~^ WARN const_err
//~| WARN const_err
//~^ ERROR const_err
//~| ERROR const_err
println!("{}", 1/(false as u32));
//~^ WARN const_err
//~^ ERROR this expression will panic at runtime [const_err]
//~| ERROR attempt to divide by zero [const_err]
//~| ERROR reaching this expression at runtime will panic or abort [const_err]
let _x = 1/(false as u32);
//~^ WARN const_err
//~| WARN const_err
//~^ ERROR const_err
//~| ERROR const_err
}

View File

@ -1,72 +1,74 @@
warning: this expression will panic at runtime
error: this expression will panic at runtime
--> $DIR/promoted_errors.rs:7:14
|
LL | let _x = 0u32 - 1;
| ^^^^^^^^ attempt to subtract with overflow
|
note: lint level defined here
--> $DIR/promoted_errors.rs:1:9
--> $DIR/promoted_errors.rs:3:9
|
LL | #![warn(const_err)]
LL | #![deny(const_err)]
| ^^^^^^^^^
warning: attempt to divide by zero
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:9:20
|
LL | println!("{}", 1/(1-1));
| ^^^^^^^
warning: this expression will panic at runtime
error: this expression will panic at runtime
--> $DIR/promoted_errors.rs:9:20
|
LL | println!("{}", 1/(1-1));
| ^^^^^^^ attempt to divide by zero
warning: attempt to divide by zero
--> $DIR/promoted_errors.rs:11:14
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:13:14
|
LL | let _x = 1/(1-1);
| ^^^^^^^
warning: this expression will panic at runtime
--> $DIR/promoted_errors.rs:11:14
error: this expression will panic at runtime
--> $DIR/promoted_errors.rs:13:14
|
LL | let _x = 1/(1-1);
| ^^^^^^^ attempt to divide by zero
warning: attempt to divide by zero
--> $DIR/promoted_errors.rs:14:20
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^
warning: this expression will panic at runtime
--> $DIR/promoted_errors.rs:14:20
error: this expression will panic at runtime
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^ attempt to divide by zero
warning: attempt to divide by zero
--> $DIR/promoted_errors.rs:16:14
error: attempt to divide by zero
--> $DIR/promoted_errors.rs:20:14
|
LL | let _x = 1/(false as u32);
| ^^^^^^^^^^^^^^^^
warning: this expression will panic at runtime
--> $DIR/promoted_errors.rs:16:14
error: this expression will panic at runtime
--> $DIR/promoted_errors.rs:20:14
|
LL | let _x = 1/(false as u32);
| ^^^^^^^^^^^^^^^^ attempt to divide by zero
warning: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:14:20
error: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:16:20
|
LL | println!("{}", 1/(false as u32));
| ^^^^^^^^^^^^^^^^ attempt to divide by zero
warning: reaching this expression at runtime will panic or abort
error: reaching this expression at runtime will panic or abort
--> $DIR/promoted_errors.rs:9:20
|
LL | println!("{}", 1/(1-1));
| ^^^^^^^ attempt to divide by zero
error: aborting due to 11 previous errors

View File

@ -1,5 +1,7 @@
// compile-flags:--emit=metadata --error-format=json -Z emit-artifact-notifications
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// A very basic test for the emission of artifact notifications in JSON output.

View File

@ -1,15 +1,13 @@
// compile-flags: -O
#![warn(overflowing_literals)]
#![warn(const_err)]
// compile-pass
#[allow(unused_variables)]
#![deny(overflowing_literals)]
#![deny(const_err)]
fn main() {
let x2: i8 = --128; //~ warn: literal out of range for i8
let x2: i8 = --128; //~ ERROR literal out of range for `i8`
let x = -3.40282357e+38_f32; //~ warn: literal out of range for f32
let x = 3.40282357e+38_f32; //~ warn: literal out of range for f32
let x = -1.7976931348623159e+308_f64; //~ warn: literal out of range for f64
let x = 1.7976931348623159e+308_f64; //~ warn: literal out of range for f64
let x = -3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
let x = 3.40282357e+38_f32; //~ ERROR literal out of range for `f32`
let x = -1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64`
let x = 1.7976931348623159e+308_f64; //~ ERROR literal out of range for `f64`
}

View File

@ -1,48 +1,38 @@
warning: literal out of range for `i8`
--> $DIR/lint-type-overflow2.rs:9:20
error: literal out of range for `i8`
--> $DIR/lint-type-overflow2.rs:7:20
|
LL | let x2: i8 = --128;
| ^^^
|
note: lint level defined here
--> $DIR/lint-type-overflow2.rs:2:9
--> $DIR/lint-type-overflow2.rs:3:9
|
LL | #![warn(overflowing_literals)]
LL | #![deny(overflowing_literals)]
| ^^^^^^^^^^^^^^^^^^^^
warning: literal out of range for `f32`
--> $DIR/lint-type-overflow2.rs:11:14
error: literal out of range for `f32`
--> $DIR/lint-type-overflow2.rs:9:14
|
LL | let x = -3.40282357e+38_f32;
| ^^^^^^^^^^^^^^^^^^
warning: literal out of range for `f32`
--> $DIR/lint-type-overflow2.rs:12:14
error: literal out of range for `f32`
--> $DIR/lint-type-overflow2.rs:10:14
|
LL | let x = 3.40282357e+38_f32;
| ^^^^^^^^^^^^^^^^^^
warning: literal out of range for `f64`
--> $DIR/lint-type-overflow2.rs:13:14
error: literal out of range for `f64`
--> $DIR/lint-type-overflow2.rs:11:14
|
LL | let x = -1.7976931348623159e+308_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: literal out of range for `f64`
--> $DIR/lint-type-overflow2.rs:14:14
error: literal out of range for `f64`
--> $DIR/lint-type-overflow2.rs:12:14
|
LL | let x = 1.7976931348623159e+308_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: this expression will panic at runtime
--> $DIR/lint-type-overflow2.rs:9:18
|
LL | let x2: i8 = --128;
| ^^^^^ attempt to negate with overflow
|
note: lint level defined here
--> $DIR/lint-type-overflow2.rs:3:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
error: aborting due to 5 previous errors

View File

@ -1,5 +1,8 @@
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// This file illustrates how generics are handled: types have to be
// monomorphized, in the MIR of the original function in which they

View File

@ -1,5 +1,8 @@
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// This file illustrates how niche-filling enums are handled,
// modelled after cases like `Option<&u32>`, `Option<bool>` and such.

View File

@ -1,5 +1,8 @@
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// This file illustrates that when the same type occurs repeatedly
// (even if multiple functions), it is only printed once in the

View File

@ -1,5 +1,8 @@
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// This file illustrates how packing is handled; it should cause
// the elimination of padding that would normally be introduced

View File

@ -1,5 +1,8 @@
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
// This file illustrates how padding is handled: alignment
// requirements can lead to the introduction of padding, either before

View File

@ -1,5 +1,8 @@
// compile-flags: -Z print-type-sizes
// compile-pass
// ignore-pass
// ^-- needed because `--pass check` does not emit the output needed.
// FIXME: consider using an attribute instead of side-effects.
#![feature(never_type)]
#![feature(start)]

View File

@ -1,6 +1,7 @@
// run-pass
// force-host
// no-prefer-dynamic
// ignore-pass
#![crate_type = "proc-macro"]

View File

@ -1,4 +1,7 @@
// compile-pass
// compile-flags: -Zsave-analysis -Zemit-artifact-notifications
// compile-flags: --crate-type rlib --error-format=json
// ignore-pass
// ^-- needed because otherwise, the .stderr file changes with --pass check
pub fn foo() {}

View File

@ -99,6 +99,36 @@ impl fmt::Display for Mode {
}
}
#[derive(Clone, Copy, PartialEq, Debug, Hash)]
pub enum PassMode {
Check,
Build,
Run,
}
impl FromStr for PassMode {
type Err = ();
fn from_str(s: &str) -> Result<Self, ()> {
match s {
"check" => Ok(PassMode::Check),
"build" => Ok(PassMode::Build),
"run" => Ok(PassMode::Run),
_ => Err(()),
}
}
}
impl fmt::Display for PassMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match *self {
PassMode::Check => "check",
PassMode::Build => "build",
PassMode::Run => "run",
};
fmt::Display::fmt(s, f)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum CompareMode {
Nll,
@ -184,6 +214,9 @@ pub struct Config {
/// Exactly match the filter, rather than a substring
pub filter_exact: bool,
/// Force the pass mode of a check/build/run-pass test to this mode.
pub force_pass_mode: Option<PassMode>,
/// Write out a parseable log of tests that were run
pub logfile: Option<PathBuf>,

View File

@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
use log::*;
use crate::common::{self, CompareMode, Config, Mode};
use crate::common::{self, CompareMode, Config, Mode, PassMode};
use crate::util;
use crate::extract_gdb_version;
@ -290,13 +290,6 @@ impl EarlyProps {
}
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum PassMode {
Check,
Build,
Run,
}
#[derive(Clone, Debug)]
pub struct TestProps {
// Lines that should be expected, in order, on standard out
@ -357,7 +350,9 @@ pub struct TestProps {
// arguments. (In particular, it propagates to the aux-builds.)
pub incremental_dir: Option<PathBuf>,
// How far should the test proceed while still passing.
pub pass_mode: Option<PassMode>,
pass_mode: Option<PassMode>,
// Ignore `--pass` overrides from the command line for this test.
ignore_pass: bool,
// rustdoc will test the output of the `--test` option
pub check_test_line_numbers_match: bool,
// Do not pass `-Z ui-testing` to UI tests
@ -400,6 +395,7 @@ impl TestProps {
forbid_output: vec![],
incremental_dir: None,
pass_mode: None,
ignore_pass: false,
check_test_line_numbers_match: false,
disable_ui_testing_normalization: false,
normalize_stdout: vec![],
@ -528,6 +524,10 @@ impl TestProps {
self.update_pass_mode(ln, cfg, config);
if !self.ignore_pass {
self.ignore_pass = config.parse_ignore_pass(ln);
}
if !self.disable_ui_testing_normalization {
self.disable_ui_testing_normalization =
config.parse_disable_ui_testing_normalization(ln);
@ -608,6 +608,15 @@ impl TestProps {
(_, None) => {}
}
}
pub fn pass_mode(&self, config: &Config) -> Option<PassMode> {
if !self.ignore_pass {
if let (mode @ Some(_), Some(_)) = (config.force_pass_mode, self.pass_mode) {
return mode;
}
}
self.pass_mode
}
}
fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut dyn FnMut(&str)) {
@ -743,6 +752,10 @@ impl Config {
self.parse_name_directive(line, "check-test-line-numbers-match")
}
fn parse_ignore_pass(&self, line: &str) -> bool {
self.parse_name_directive(line, "ignore-pass")
}
fn parse_assembly_output(&self, line: &str) -> Option<String> {
self.parse_name_value_directive(line, "assembly-output")
.map(|r| r.trim().to_string())

View File

@ -5,7 +5,7 @@
extern crate test;
use crate::common::CompareMode;
use crate::common::{CompareMode, PassMode};
use crate::common::{expected_output_path, output_base_dir, output_relative_path, UI_EXTENSIONS};
use crate::common::{Config, TestPaths};
use crate::common::{DebugInfoCdb, DebugInfoGdbLldb, DebugInfoGdb, DebugInfoLldb, Mode, Pretty};
@ -128,6 +128,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
"(compile-fail|run-fail|run-pass|\
run-pass-valgrind|pretty|debug-info|incremental|mir-opt)",
)
.optopt(
"",
"pass",
"force {check,build,run}-pass tests to this mode.",
"check | build | run"
)
.optflag("", "ignored", "run tests marked as ignored")
.optflag("", "exact", "filters match exactly")
.optopt(
@ -320,6 +326,10 @@ pub fn parse_config(args: Vec<String>) -> Config {
run_ignored,
filter: matches.free.first().cloned(),
filter_exact: matches.opt_present("exact"),
force_pass_mode: matches.opt_str("pass").map(|mode|
mode.parse::<PassMode>()
.unwrap_or_else(|_| panic!("unknown `--pass` option `{}` given", mode))
),
logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
runtool: matches.opt_str("runtool"),
host_rustcflags: matches.opt_str("host-rustcflags"),
@ -382,6 +392,10 @@ pub fn log_config(config: &Config) {
),
);
logv(c, format!("filter_exact: {}", config.filter_exact));
logv(c, format!(
"force_pass_mode: {}",
opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),
));
logv(c, format!("runtool: {}", opt_str(&config.runtool)));
logv(
c,

View File

@ -1,6 +1,6 @@
// ignore-tidy-filelength
use crate::common::CompareMode;
use crate::common::{CompareMode, PassMode};
use crate::common::{expected_output_path, UI_EXTENSIONS, UI_FIXED, UI_STDERR, UI_STDOUT};
use crate::common::{output_base_dir, output_base_name, output_testname_unique};
use crate::common::{Codegen, CodegenUnits, Rustdoc};
@ -10,7 +10,7 @@ use crate::common::{Config, TestPaths};
use crate::common::{Incremental, MirOpt, RunMake, Ui, JsDocTest, Assembly};
use diff;
use crate::errors::{self, Error, ErrorKind};
use crate::header::{TestProps, PassMode};
use crate::header::TestProps;
use crate::json;
use regex::{Captures, Regex};
use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
@ -260,6 +260,10 @@ pub fn compute_stamp_hash(config: &Config) -> String {
env::var_os("PYTHONPATH").hash(&mut hash);
}
if let Ui | RunPass | Incremental | Pretty = config.mode {
config.force_pass_mode.hash(&mut hash);
}
format!("{:x}", hash.finish())
}
@ -309,10 +313,13 @@ impl<'test> TestCx<'test> {
}
}
fn pass_mode(&self) -> Option<PassMode> {
self.props.pass_mode(self.config)
}
fn should_run_successfully(&self) -> bool {
match self.config.mode {
RunPass => true,
Ui => self.props.pass_mode == Some(PassMode::Run),
RunPass | Ui => self.pass_mode() == Some(PassMode::Run),
mode => panic!("unimplemented for mode {:?}", mode),
}
}
@ -322,7 +329,7 @@ impl<'test> TestCx<'test> {
CompileFail => false,
RunPass => true,
JsDocTest => true,
Ui => self.props.pass_mode.is_some(),
Ui => self.pass_mode().is_some(),
Incremental => {
let revision = self.revision
.expect("incremental tests require a list of revisions");
@ -330,7 +337,7 @@ impl<'test> TestCx<'test> {
true
} else if revision.starts_with("cfail") {
// FIXME: would be nice if incremental revs could start with "cpass"
self.props.pass_mode.is_some()
self.pass_mode().is_some()
} else {
panic!("revision name must begin with rpass, rfail, or cfail");
}
@ -1341,7 +1348,7 @@ impl<'test> TestCx<'test> {
fn check_error_patterns(&self, output_to_check: &str, proc_res: &ProcRes) {
debug!("check_error_patterns");
if self.props.error_patterns.is_empty() {
if self.props.pass_mode.is_some() {
if self.pass_mode().is_some() {
return;
} else {
self.fatal(&format!(
@ -1871,7 +1878,11 @@ impl<'test> TestCx<'test> {
result
}
fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command {
fn make_compile_args(
&self,
input_file: &Path,
output_file: TargetLocation,
) -> Command {
let is_rustdoc = self.config.src_base.ends_with("rustdoc-ui") ||
self.config.src_base.ends_with("rustdoc-js");
let mut rustc = if !is_rustdoc {
@ -1968,14 +1979,7 @@ impl<'test> TestCx<'test> {
}
}
if self.props.pass_mode == Some(PassMode::Check) {
assert!(
!self
.props
.compile_flags
.iter()
.any(|s| s.starts_with("--emit"))
);
if let Some(PassMode::Check) = self.pass_mode() {
rustc.args(&["--emit", "metadata"]);
}

View File

@ -72,32 +72,33 @@ def issue(
):
# Open an issue about the toolstate failure.
assignees = [x.strip() for x in maintainers.split('@') if x != '']
assignees.append(relevant_pr_user)
if status == 'test-fail':
status_description = 'has failing tests'
else:
status_description = 'no longer builds'
request = json.dumps({
'body': maybe_delink(textwrap.dedent('''\
Hello, this is your friendly neighborhood mergebot.
After merging PR {}, I observed that the tool {} {}.
A follow-up PR to the repository {} is needed to fix the fallout.
cc @{}, do you think you would have time to do the follow-up work?
If so, that would be great!
cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization.
''').format(
relevant_pr_number, tool, status_description,
REPOS.get(tool), relevant_pr_user, pr_reviewer
)),
'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
'assignees': assignees,
'labels': ['T-compiler', 'I-nominated'],
})
print("Creating issue:\n{}".format(request))
response = urllib2.urlopen(urllib2.Request(
gh_url(),
json.dumps({
'body': maybe_delink(textwrap.dedent('''\
Hello, this is your friendly neighborhood mergebot.
After merging PR {}, I observed that the tool {} {}.
A follow-up PR to the repository {} is needed to fix the fallout.
cc @{}, do you think you would have time to do the follow-up work?
If so, that would be great!
cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization.
''').format(
relevant_pr_number, tool, status_description,
REPOS.get(tool), relevant_pr_user, pr_reviewer
)),
'title': '`{}` no longer builds after {}'.format(tool, relevant_pr_number),
'assignees': assignees,
'labels': ['T-compiler', 'I-nominated'],
}),
request,
{
'Authorization': 'token ' + github_token,
'Content-Type': 'application/json',
@ -135,13 +136,13 @@ def update_latest(
for status in latest:
tool = status['tool']
changed = False
create_issue = False
create_issue_for_status = None # set to the status that caused the issue
for os, s in current_status.items():
old = status[os]
new = s.get(tool, old)
status[os] = new
if new > old:
if new > old: # comparing the strings, but they are ordered appropriately!
# things got fixed or at least the status quo improved
changed = True
message += '🎉 {} on {}: {}{} (cc {}, @rust-lang/infra).\n' \
@ -156,20 +157,24 @@ def update_latest(
# Most tools only create issues for build failures.
# Other failures can be spurious.
if new == 'build-fail' or (tool == 'miri' and new == 'test-fail'):
create_issue = True
create_issue_for_status = new
if create_issue:
if create_issue_for_status is not None:
try:
issue(
tool, new, MAINTAINERS.get(tool, ''),
tool, create_issue_for_status, MAINTAINERS.get(tool, ''),
relevant_pr_number, relevant_pr_user, pr_reviewer,
)
except IOError as e:
except urllib2.HTTPError as e:
# network errors will simply end up not creating an issue, but that's better
# than failing the entire build job
print("I/O error: {0}".format(e))
print("HTTPError when creating issue for status regression: {0}\n{1}"
.format(e, e.read()))
except IOError as e:
print("I/O error when creating issue for status regression: {0}".format(e))
except:
print("Unexpected error: {0}".format(sys.exc_info()[0]))
print("Unexpected error when creating issue for status regression: {0}"
.format(sys.exc_info()[0]))
raise
if changed: