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:
commit
9a90d03ad1
@ -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);
|
||||
|
@ -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> {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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> }
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
$(
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>,
|
||||
},
|
||||
]}
|
||||
|
@ -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 || {
|
||||
|
@ -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),
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)));
|
||||
|
@ -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 _,
|
||||
);
|
||||
|
@ -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 }
|
||||
}
|
||||
|
||||
|
@ -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;
|
28
src/test/run-pass/async-await/issue-60709.rs
Normal file
28
src/test/run-pass/async-await/issue-60709.rs
Normal 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.
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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`
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)]
|
||||
|
@ -1,6 +1,7 @@
|
||||
// run-pass
|
||||
// force-host
|
||||
// no-prefer-dynamic
|
||||
// ignore-pass
|
||||
|
||||
#![crate_type = "proc-macro"]
|
||||
|
||||
|
@ -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() {}
|
||||
|
@ -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>,
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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,
|
||||
|
@ -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"]);
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user