Skip to content

Rollup of 8 pull requests #123913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Apr 14, 2024
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2aec2fe
Update thread local docs with idiomatic cell type use
tgross35 Apr 8, 2024
6e68a2f
Add `SAFETY` comments to the thread local implementation
tgross35 Apr 8, 2024
313085f
Change method calls to using the method directly
tgross35 Apr 8, 2024
7aaad6b
OpenBSD fix long socket addresses
semarie Apr 11, 2024
fa21dd4
chore: replace x with y for hexa-decimal fmt
Ghamza-Jd Apr 12, 2024
53f55c6
Add missing `unsafe` to internal function `std::sys::pal::unix::threa…
beetrees Apr 12, 2024
126c762
Add missing `unsafe` to internal `std::thread::Thread` creation funct…
beetrees Apr 12, 2024
c6002f1
reduce tidy overheads in run-make checks
onur-ozkan Apr 13, 2024
e994534
run-make-support: make `handle_failed_output` take a `&Command`
jieyouxu Apr 9, 2024
b22099d
run-make-support: introduce macro for common methods to avoid repetition
jieyouxu Apr 13, 2024
3d115b9
run-make-support: use macro to implement common methods
jieyouxu Apr 10, 2024
a67a119
run-make-support: add some top-level docs
jieyouxu Apr 10, 2024
dfbdce0
Check regions earlier when comparing impl with trait item def
fmease Apr 13, 2024
123b303
Update rustfix to 0.8.1
ehuss Apr 13, 2024
7c8c2f0
Rollup merge of #123651 - tgross35:thread-local-updates, r=Mark-Simul…
matthiaskrgr Apr 14, 2024
bd4f67c
Rollup merge of #123699 - jieyouxu:rmake-refactor, r=Mark-Simulacrum
matthiaskrgr Apr 14, 2024
0638780
Rollup merge of #123779 - semarie:notgull-openbsd-socket, r=Mark-Simu…
matthiaskrgr Apr 14, 2024
2bec57d
Rollup merge of #123875 - Ghamza-Jd:master, r=joboet
matthiaskrgr Apr 14, 2024
2ba0c62
Rollup merge of #123879 - beetrees:missing-unsafe, r=Mark-Simulacrum
matthiaskrgr Apr 14, 2024
d1782db
Rollup merge of #123889 - onur-ozkan:improve-tidy, r=Mark-Simulacrum
matthiaskrgr Apr 14, 2024
20656d9
Rollup merge of #123898 - fmease:gci-cmp-impl-item-lt-params, r=compi…
matthiaskrgr Apr 14, 2024
ab65c68
Rollup merge of #123902 - ehuss:update-rustfix2, r=Mark-Simulacrum
matthiaskrgr Apr 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -766,7 +766,7 @@ dependencies = [
"miropt-test-tools",
"once_cell",
"regex",
"rustfix",
"rustfix 0.8.1",
"serde",
"serde_json",
"tracing",
@@ -4855,6 +4855,18 @@ dependencies = [
"serde_json",
]

[[package]]
name = "rustfix"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81864b097046da5df3758fdc6e4822bbb70afa06317e8ca45ea1b51cb8c5e5a4"
dependencies = [
"serde",
"serde_json",
"thiserror",
"tracing",
]

[[package]]
name = "rustfmt-config_proc_macro"
version = "0.3.0"
@@ -5896,7 +5908,7 @@ dependencies = [
"prettydiff",
"regex",
"rustc_version",
"rustfix",
"rustfix 0.6.1",
"serde",
"serde_json",
"tempfile",
@@ -5923,7 +5935,7 @@ dependencies = [
"prettydiff",
"regex",
"rustc_version",
"rustfix",
"rustfix 0.6.1",
"serde",
"serde_json",
"spanned",
6 changes: 2 additions & 4 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
@@ -1723,6 +1723,7 @@ pub(super) fn compare_impl_const_raw(

compare_number_of_generics(tcx, impl_const_item, trait_const_item, false)?;
compare_generic_param_kinds(tcx, impl_const_item, trait_const_item, false)?;
check_region_bounds_on_impl_item(tcx, impl_const_item, trait_const_item, false)?;
compare_const_predicate_entailment(tcx, impl_const_item, trait_const_item, impl_trait_ref)
}

@@ -1763,8 +1764,6 @@ fn compare_const_predicate_entailment<'tcx>(
let impl_ct_predicates = tcx.predicates_of(impl_ct.def_id);
let trait_ct_predicates = tcx.predicates_of(trait_ct.def_id);

check_region_bounds_on_impl_item(tcx, impl_ct, trait_ct, false)?;

// The predicates declared by the impl definition, the trait and the
// associated const in the trait are assumed.
let impl_predicates = tcx.predicates_of(impl_ct_predicates.parent.unwrap());
@@ -1866,6 +1865,7 @@ pub(super) fn compare_impl_ty<'tcx>(
let _: Result<(), ErrorGuaranteed> = try {
compare_number_of_generics(tcx, impl_ty, trait_ty, false)?;
compare_generic_param_kinds(tcx, impl_ty, trait_ty, false)?;
check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;
compare_type_predicate_entailment(tcx, impl_ty, trait_ty, impl_trait_ref)?;
check_type_bounds(tcx, trait_ty, impl_ty, impl_trait_ref)?;
};
@@ -1886,8 +1886,6 @@ fn compare_type_predicate_entailment<'tcx>(
let impl_ty_predicates = tcx.predicates_of(impl_ty.def_id);
let trait_ty_predicates = tcx.predicates_of(trait_ty.def_id);

check_region_bounds_on_impl_item(tcx, impl_ty, trait_ty, false)?;

let impl_ty_own_bounds = impl_ty_predicates.instantiate_own(tcx, impl_args);
if impl_ty_own_bounds.len() == 0 {
// Nothing to check.
12 changes: 6 additions & 6 deletions library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
@@ -860,10 +860,10 @@ pub trait Binary {
/// Basic usage with `i32`:
///
/// ```
/// let x = 42; // 42 is '2a' in hex
/// let y = 42; // 42 is '2a' in hex
///
/// assert_eq!(format!("{x:x}"), "2a");
/// assert_eq!(format!("{x:#x}"), "0x2a");
/// assert_eq!(format!("{y:x}"), "2a");
/// assert_eq!(format!("{y:#x}"), "0x2a");
///
/// assert_eq!(format!("{:x}", -16), "fffffff0");
/// ```
@@ -915,10 +915,10 @@ pub trait LowerHex {
/// Basic usage with `i32`:
///
/// ```
/// let x = 42; // 42 is '2A' in hex
/// let y = 42; // 42 is '2A' in hex
///
/// assert_eq!(format!("{x:X}"), "2A");
/// assert_eq!(format!("{x:#X}"), "0x2A");
/// assert_eq!(format!("{y:X}"), "2A");
/// assert_eq!(format!("{y:#X}"), "0x2A");
///
/// assert_eq!(format!("{:X}", -16), "FFFFFFF0");
/// ```
10 changes: 10 additions & 0 deletions library/std/src/os/unix/net/addr.rs
Original file line number Diff line number Diff line change
@@ -107,6 +107,16 @@ impl SocketAddr {
addr: libc::sockaddr_un,
mut len: libc::socklen_t,
) -> io::Result<SocketAddr> {
if cfg!(target_os = "openbsd") {
// on OpenBSD, getsockname(2) returns the actual size of the socket address,
// and not the len of the content. Figure out the length for ourselves.
// https://marc.info/?l=openbsd-bugs&m=170105481926736&w=2
let sun_path: &[u8] =
unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&addr.sun_path) };
len = core::slice::memchr::memchr(0, sun_path)
.map_or(len, |new_len| (new_len + sun_path_offset(&addr)) as libc::socklen_t);
}

if len == 0 {
// When there is a datagram from unnamed unix socket
// linux returns zero bytes of address
6 changes: 3 additions & 3 deletions library/std/src/sys/pal/unix/thread.rs
Original file line number Diff line number Diff line change
@@ -709,7 +709,7 @@ mod cgroups {
// is created in an application with big thread-local storage requirements.
// See #6233 for rationale and details.
#[cfg(all(target_os = "linux", target_env = "gnu"))]
fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
unsafe fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
// We use dlsym to avoid an ELF version dependency on GLIBC_PRIVATE. (#23628)
// We shouldn't really be using such an internal symbol, but there's currently
// no other way to account for the TLS size.
@@ -723,11 +723,11 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {

// No point in looking up __pthread_get_minstack() on non-glibc platforms.
#[cfg(all(not(all(target_os = "linux", target_env = "gnu")), not(target_os = "netbsd")))]
fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
libc::PTHREAD_STACK_MIN
}

#[cfg(target_os = "netbsd")]
fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
unsafe fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
2048 // just a guess
}
2 changes: 1 addition & 1 deletion library/std/src/sys/sync/rwlock/queue.rs
Original file line number Diff line number Diff line change
@@ -202,7 +202,7 @@ impl Node {
fn prepare(&mut self) {
// Fall back to creating an unnamed `Thread` handle to allow locking in
// TLS destructors.
self.thread.get_or_init(|| thread::try_current().unwrap_or_else(|| Thread::new(None)));
self.thread.get_or_init(|| thread::try_current().unwrap_or_else(Thread::new_unnamed));
self.completed = AtomicBool::new(false);
}

60 changes: 32 additions & 28 deletions library/std/src/thread/local.rs
Original file line number Diff line number Diff line change
@@ -53,25 +53,25 @@ use crate::fmt;
/// # Examples
///
/// ```
/// use std::cell::RefCell;
/// use std::cell::Cell;
/// use std::thread;
///
/// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
/// thread_local!(static FOO: Cell<u32> = Cell::new(1));
///
/// FOO.with_borrow(|v| assert_eq!(*v, 1));
/// FOO.with_borrow_mut(|v| *v = 2);
/// assert_eq!(FOO.get(), 1);
/// FOO.set(2);
///
/// // each thread starts out with the initial value of 1
/// let t = thread::spawn(move|| {
/// FOO.with_borrow(|v| assert_eq!(*v, 1));
/// FOO.with_borrow_mut(|v| *v = 3);
/// assert_eq!(FOO.get(), 1);
/// FOO.set(3);
/// });
///
/// // wait for the thread to complete and bail out on panic
/// t.join().unwrap();
///
/// // we retain our original value of 2 despite the child thread
/// FOO.with_borrow(|v| assert_eq!(*v, 2));
/// assert_eq!(FOO.get(), 2);
/// ```
///
/// # Platform-specific behavior
@@ -141,15 +141,16 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
/// Publicity and attributes for each static are allowed. Example:
///
/// ```
/// use std::cell::RefCell;
/// use std::cell::{Cell, RefCell};
///
/// thread_local! {
/// pub static FOO: RefCell<u32> = RefCell::new(1);
/// pub static FOO: Cell<u32> = Cell::new(1);
///
/// static BAR: RefCell<f32> = RefCell::new(1.0);
/// static BAR: RefCell<Vec<f32>> = RefCell::new(vec![1.0, 2.0]);
/// }
///
/// FOO.with_borrow(|v| assert_eq!(*v, 1));
/// BAR.with_borrow(|v| assert_eq!(*v, 1.0));
/// assert_eq!(FOO.get(), 1);
/// BAR.with_borrow(|v| assert_eq!(v[1], 2.0));
/// ```
///
/// Note that only shared references (`&T`) to the inner data may be obtained, so a
@@ -164,12 +165,13 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
/// track any additional state.
///
/// ```
/// use std::cell::Cell;
/// use std::cell::RefCell;
///
/// thread_local! {
/// pub static FOO: Cell<u32> = const { Cell::new(1) };
/// pub static FOO: RefCell<Vec<u32>> = const { RefCell::new(Vec::new()) };
/// }
///
/// assert_eq!(FOO.get(), 1);
/// FOO.with_borrow(|v| assert_eq!(v.len(), 0));
/// ```
///
/// See [`LocalKey` documentation][`std::thread::LocalKey`] for more
@@ -279,10 +281,9 @@ impl<T: 'static> LocalKey<T> {
where
F: FnOnce(&T) -> R,
{
unsafe {
let thread_local = (self.inner)(None).ok_or(AccessError)?;
Ok(f(thread_local))
}
// SAFETY: `inner` is safe to call within the lifetime of the thread
let thread_local = unsafe { (self.inner)(None).ok_or(AccessError)? };
Ok(f(thread_local))
}

/// Acquires a reference to the value in this TLS key, initializing it with
@@ -301,14 +302,17 @@ impl<T: 'static> LocalKey<T> {
where
F: FnOnce(Option<T>, &T) -> R,
{
unsafe {
let mut init = Some(init);
let reference = (self.inner)(Some(&mut init)).expect(
let mut init = Some(init);

// SAFETY: `inner` is safe to call within the lifetime of the thread
let reference = unsafe {
(self.inner)(Some(&mut init)).expect(
"cannot access a Thread Local Storage value \
during or after destruction",
);
f(init, reference)
}
)
};

f(init, reference)
}
}

@@ -377,7 +381,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
where
T: Copy,
{
self.with(|cell| cell.get())
self.with(Cell::get)
}

/// Takes the contained value, leaving `Default::default()` in its place.
@@ -407,7 +411,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
where
T: Default,
{
self.with(|cell| cell.take())
self.with(Cell::take)
}

/// Replaces the contained value, returning the old value.
@@ -578,7 +582,7 @@ impl<T: 'static> LocalKey<RefCell<T>> {
where
T: Default,
{
self.with(|cell| cell.take())
self.with(RefCell::take)
}

/// Replaces the contained value, returning the old value.
33 changes: 20 additions & 13 deletions library/std/src/thread/mod.rs
Original file line number Diff line number Diff line change
@@ -487,9 +487,11 @@ impl Builder {
amt
});

let my_thread = Thread::new(name.map(|name| {
CString::new(name).expect("thread name may not contain interior null bytes")
}));
let my_thread = name.map_or_else(Thread::new_unnamed, |name| unsafe {
Thread::new(
CString::new(name).expect("thread name may not contain interior null bytes"),
)
});
let their_thread = my_thread.clone();

let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet {
@@ -711,7 +713,7 @@ pub(crate) fn set_current(thread: Thread) {
/// In contrast to the public `current` function, this will not panic if called
/// from inside a TLS destructor.
pub(crate) fn try_current() -> Option<Thread> {
CURRENT.try_with(|current| current.get_or_init(|| Thread::new(None)).clone()).ok()
CURRENT.try_with(|current| current.get_or_init(|| Thread::new_unnamed()).clone()).ok()
}

/// Gets a handle to the thread that invokes it.
@@ -1307,21 +1309,26 @@ pub struct Thread {
}

impl Thread {
// Used only internally to construct a thread object without spawning
pub(crate) fn new(name: Option<CString>) -> Thread {
if let Some(name) = name {
Self::new_inner(ThreadName::Other(name))
} else {
Self::new_inner(ThreadName::Unnamed)
}
/// Used only internally to construct a thread object without spawning.
///
/// # Safety
/// `name` must be valid UTF-8.
pub(crate) unsafe fn new(name: CString) -> Thread {
unsafe { Self::new_inner(ThreadName::Other(name)) }
}

pub(crate) fn new_unnamed() -> Thread {
unsafe { Self::new_inner(ThreadName::Unnamed) }
}

// Used in runtime to construct main thread
pub(crate) fn new_main() -> Thread {
Self::new_inner(ThreadName::Main)
unsafe { Self::new_inner(ThreadName::Main) }
}

fn new_inner(name: ThreadName) -> Thread {
/// # Safety
/// If `name` is `ThreadName::Other(_)`, the contained string must be valid UTF-8.
unsafe fn new_inner(name: ThreadName) -> Thread {
// We have to use `unsafe` here to construct the `Parker` in-place,
// which is required for the UNIX implementation.
//
2 changes: 1 addition & 1 deletion src/tools/compiletest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ tracing-subscriber = { version = "0.3.3", default-features = false, features = [
regex = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rustfix = "0.6.0"
rustfix = "0.8.1"
once_cell = "1.16.0"
walkdir = "2"
glob = "0.3.0"
39 changes: 3 additions & 36 deletions src/tools/run-make-support/src/cc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::env;
use std::path::Path;
use std::process::{Command, Output};
use std::process::Command;

use crate::{bin_name, cygpath_windows, handle_failed_output, is_msvc, is_windows, tmp_dir, uname};

@@ -19,6 +19,8 @@ pub struct Cc {
cmd: Command,
}

crate::impl_common_helpers!(Cc);

impl Cc {
/// Construct a new platform-specific C compiler invocation.
///
@@ -43,22 +45,6 @@ impl Cc {
self
}

/// Add a *platform-and-compiler-specific* argument. Please consult the docs for the various
/// possible C compilers on the various platforms to check which arguments are legal for
/// which compiler.
pub fn arg(&mut self, flag: &str) -> &mut Self {
self.cmd.arg(flag);
self
}

/// Add multiple *platform-and-compiler-specific* arguments. Please consult the docs for the
/// various possible C compilers on the various platforms to check which arguments are legal
/// for which compiler.
pub fn args(&mut self, args: &[&str]) -> &mut Self {
self.cmd.args(args);
self
}

/// Specify `-o` or `-Fe`/`-Fo` depending on platform/compiler. This assumes that the executable
/// is under `$TMPDIR`.
pub fn out_exe(&mut self, name: &str) -> &mut Self {
@@ -85,25 +71,6 @@ impl Cc {

self
}

/// Run the constructed C invocation command and assert that it is successfully run.
#[track_caller]
pub fn run(&mut self) -> Output {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.cmd.output().unwrap();
if !output.status.success() {
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
}
output
}

/// Inspect what the underlying [`Command`] is up to the current construction.
pub fn inspect(&mut self, f: impl FnOnce(&Command)) -> &mut Self {
f(&self.cmd);
self
}
}

/// `EXTRACFLAGS`
139 changes: 134 additions & 5 deletions src/tools/run-make-support/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//! `run-make-support` is a support library for run-make tests. It provides command wrappers and
//! convenience utility functions to help test writers reduce duplication. The support library
//! notably is built via cargo: this means that if your test wants some non-trivial utility, such
//! as `object` or `wasmparser`, they can be re-exported and be made available through this library.
pub mod cc;
pub mod run;
pub mod rustc;
@@ -82,7 +87,7 @@ pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
cygpath.arg(path.as_ref());
let output = cygpath.output().unwrap();
if !output.status.success() {
handle_failed_output(&format!("{:#?}", cygpath), output, caller_line_number);
handle_failed_output(&cygpath, output, caller_line_number);
}
let s = String::from_utf8(output.stdout).unwrap();
// cygpath -w can attach a newline
@@ -98,18 +103,18 @@ pub fn uname() -> String {
let mut uname = Command::new("uname");
let output = uname.output().unwrap();
if !output.status.success() {
handle_failed_output(&format!("{:#?}", uname), output, caller_line_number);
handle_failed_output(&uname, output, caller_line_number);
}
String::from_utf8(output.stdout).unwrap()
}

fn handle_failed_output(cmd: &str, output: Output, caller_line_number: u32) -> ! {
fn handle_failed_output(cmd: &Command, output: Output, caller_line_number: u32) -> ! {
if output.status.success() {
eprintln!("command incorrectly succeeded at line {caller_line_number}");
eprintln!("command unexpectedly succeeded at line {caller_line_number}");
} else {
eprintln!("command failed at line {caller_line_number}");
}
eprintln!("{cmd}");
eprintln!("{cmd:?}");
eprintln!("output status: `{}`", output.status);
eprintln!("=== STDOUT ===\n{}\n\n", String::from_utf8(output.stdout).unwrap());
eprintln!("=== STDERR ===\n{}\n\n", String::from_utf8(output.stderr).unwrap());
@@ -129,3 +134,127 @@ pub fn set_host_rpath(cmd: &mut Command) {
env::join_paths(paths.iter()).unwrap()
});
}

/// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
/// containing a `cmd: Command` field. The provided helpers are:
///
/// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended
/// to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add
/// new specific helper methods over relying on these generic argument providers.
/// 2. Environment manipulation methods: `env`, `env_remove` and `env_clear`: these delegate to
/// methods of the same name on [`Command`].
/// 3. Output and execution: `output`, `run` and `run_fail` are provided. `output` waits for the
/// command to finish running and returns the process's [`Output`]. `run` and `run_fail` are
/// higher-level convenience methods which waits for the command to finish running and assert
/// that the command successfully ran or failed as expected. Prefer `run` and `run_fail` when
/// possible.
///
/// Example usage:
///
/// ```ignore (illustrative)
/// struct CommandWrapper { cmd: Command }
///
/// crate::impl_common_helpers!(CommandWrapper);
///
/// impl CommandWrapper {
/// // ... additional specific helper methods
/// }
/// ```
///
/// [`Command`]: ::std::process::Command
/// [`Output`]: ::std::process::Output
macro_rules! impl_common_helpers {
($wrapper: ident) => {
impl $wrapper {
/// Specify an environment variable.
pub fn env<K, V>(&mut self, key: K, value: V) -> &mut Self
where
K: AsRef<::std::ffi::OsStr>,
V: AsRef<::std::ffi::OsStr>,
{
self.cmd.env(key, value);
self
}

/// Remove an environmental variable.
pub fn env_remove<K>(&mut self, key: K) -> &mut Self
where
K: AsRef<::std::ffi::OsStr>,
{
self.cmd.env_remove(key);
self
}

/// Clear all environmental variables.
pub fn env_var(&mut self) -> &mut Self {
self.cmd.env_clear();
self
}

/// Generic command argument provider. Prefer specific helper methods if possible.
/// Note that for some executables, arguments might be platform specific. For C/C++
/// compilers, arguments might be platform *and* compiler specific.
pub fn arg<S>(&mut self, arg: S) -> &mut Self
where
S: AsRef<::std::ffi::OsStr>,
{
self.cmd.arg(arg);
self
}

/// Generic command arguments provider. Prefer specific helper methods if possible.
/// Note that for some executables, arguments might be platform specific. For C/C++
/// compilers, arguments might be platform *and* compiler specific.
pub fn args<S>(&mut self, args: &[S]) -> &mut Self
where
S: AsRef<::std::ffi::OsStr>,
{
self.cmd.args(args);
self
}

/// Inspect what the underlying [`Command`][::std::process::Command] is up to the
/// current construction.
pub fn inspect<I>(&mut self, inspector: I) -> &mut Self
where
I: FnOnce(&::std::process::Command),
{
inspector(&self.cmd);
self
}

/// Get the [`Output`][::std::process::Output] of the finished process.
pub fn output(&mut self) -> ::std::process::Output {
self.cmd.output().expect("failed to get output of finished process")
}

/// Run the constructed command and assert that it is successfully run.
#[track_caller]
pub fn run(&mut self) -> ::std::process::Output {
let caller_location = ::std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.cmd.output().unwrap();
if !output.status.success() {
handle_failed_output(&self.cmd, output, caller_line_number);
}
output
}

/// Run the constructed command and assert that it does not successfully run.
#[track_caller]
pub fn run_fail(&mut self) -> ::std::process::Output {
let caller_location = ::std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.cmd.output().unwrap();
if output.status.success() {
handle_failed_output(&self.cmd, output, caller_line_number);
}
output
}
}
};
}

pub(crate) use impl_common_helpers;
4 changes: 2 additions & 2 deletions src/tools/run-make-support/src/run.rs
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@ pub fn run(name: &str) -> Output {

let (cmd, output) = run_common(name);
if !output.status.success() {
handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
handle_failed_output(&cmd, output, caller_line_number);
}
output
}
@@ -58,7 +58,7 @@ pub fn run_fail(name: &str) -> Output {

let (cmd, output) = run_common(name);
if output.status.success() {
handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
handle_failed_output(&cmd, output, caller_line_number);
}
output
}
61 changes: 4 additions & 57 deletions src/tools/run-make-support/src/rustc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::env;
use std::ffi::{OsStr, OsString};
use std::ffi::OsString;
use std::path::Path;
use std::process::{Command, Output};

@@ -21,6 +21,8 @@ pub struct Rustc {
cmd: Command,
}

crate::impl_common_helpers!(Rustc);

fn setup_common() -> Command {
let rustc = env::var("RUSTC").unwrap();
let mut cmd = Command::new(rustc);
@@ -133,12 +135,6 @@ impl Rustc {
self
}

/// Generic command argument provider. Use `.arg("-Zname")` over `.arg("-Z").arg("arg")`.
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self {
self.cmd.arg(arg);
self
}

/// Specify the crate type.
pub fn crate_type(&mut self, crate_type: &str) -> &mut Self {
self.cmd.arg("--crate-type");
@@ -153,64 +149,15 @@ impl Rustc {
self
}

/// Generic command arguments provider. Use `.arg("-Zname")` over `.arg("-Z").arg("arg")`.
pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut Self {
self.cmd.args(args);
self
}

pub fn env(&mut self, name: impl AsRef<OsStr>, value: impl AsRef<OsStr>) -> &mut Self {
self.cmd.env(name, value);
self
}

// Command inspection, output and running helper methods

/// Get the [`Output`][std::process::Output] of the finished `rustc` process.
pub fn output(&mut self) -> Output {
self.cmd.output().unwrap()
}

/// Run the constructed `rustc` command and assert that it is successfully run.
#[track_caller]
pub fn run(&mut self) -> Output {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.cmd.output().unwrap();
if !output.status.success() {
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
}
output
}

#[track_caller]
pub fn run_fail(&mut self) -> Output {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.cmd.output().unwrap();
if output.status.success() {
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
}
output
}

#[track_caller]
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.cmd.output().unwrap();
if output.status.code().unwrap() != code {
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
handle_failed_output(&self.cmd, output, caller_line_number);
}
output
}

/// Inspect what the underlying [`Command`] is up to the current construction.
pub fn inspect(&mut self, f: impl FnOnce(&Command)) -> &mut Self {
f(&self.cmd);
self
}
}
24 changes: 3 additions & 21 deletions src/tools/run-make-support/src/rustdoc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use std::env;
use std::ffi::OsStr;
use std::path::Path;
use std::process::{Command, Output};

@@ -20,6 +19,8 @@ pub struct Rustdoc {
cmd: Command,
}

crate::impl_common_helpers!(Rustdoc);

fn setup_common() -> Command {
let rustdoc = env::var("RUSTDOC").unwrap();
let mut cmd = Command::new(rustdoc);
@@ -61,33 +62,14 @@ impl Rustdoc {
self
}

/// Generic command argument provider. Use `.arg("-Zname")` over `.arg("-Z").arg("arg")`.
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self {
self.cmd.arg(arg);
self
}

/// Run the build `rustdoc` command and assert that the run is successful.
#[track_caller]
pub fn run(&mut self) -> Output {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.cmd.output().unwrap();
if !output.status.success() {
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
}
output
}

#[track_caller]
pub fn run_fail_assert_exit_code(&mut self, code: i32) -> Output {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();

let output = self.cmd.output().unwrap();
if output.status.code().unwrap() != code {
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
handle_failed_output(&self.cmd, output, caller_line_number);
}
output
}
33 changes: 24 additions & 9 deletions src/tools/tidy/src/run_make_tests.rs
Original file line number Diff line number Diff line change
@@ -6,10 +6,26 @@ use std::io::Write;
use std::path::{Path, PathBuf};

pub fn check(tests_path: &Path, src_path: &Path, bless: bool, bad: &mut bool) {
let mut is_sorted = true;

let allowed_makefiles = {
let allowed_makefiles = include_str!("allowed_run_make_makefiles.txt");
let allowed_makefiles = allowed_makefiles.lines().collect::<Vec<_>>();
let is_sorted = allowed_makefiles.windows(2).all(|w| w[0] < w[1]);
let mut total_lines = 0;
let mut prev_line = "";
let allowed_makefiles: BTreeSet<&str> = include_str!("allowed_run_make_makefiles.txt")
.lines()
.map(|line| {
total_lines += 1;

if prev_line > line {
is_sorted = false;
}

prev_line = line;

line
})
.collect();

if !is_sorted && !bless {
tidy_error!(
bad,
@@ -18,17 +34,16 @@ pub fn check(tests_path: &Path, src_path: &Path, bless: bool, bad: &mut bool) {
`x test tidy --bless`"
);
}
let allowed_makefiles_unique =
allowed_makefiles.iter().map(ToString::to_string).collect::<BTreeSet<String>>();
if allowed_makefiles_unique.len() != allowed_makefiles.len() {
if allowed_makefiles.len() != total_lines {
tidy_error!(
bad,
"`src/tools/tidy/src/allowed_run_make_makefiles.txt` contains duplicate entries, \
likely because you modified it manually, please only update it with command \
`x test tidy --bless`"
);
}
allowed_makefiles_unique

allowed_makefiles
};

let mut remaining_makefiles = allowed_makefiles.clone();
@@ -48,7 +63,7 @@ pub fn check(tests_path: &Path, src_path: &Path, bless: bool, bad: &mut bool) {
let makefile_path = entry.path().strip_prefix(&tests_path).unwrap();
let makefile_path = makefile_path.to_str().unwrap().replace('\\', "/");

if !remaining_makefiles.remove(&makefile_path) {
if !remaining_makefiles.remove(makefile_path.as_str()) {
tidy_error!(
bad,
"found run-make Makefile not permitted in \
@@ -64,7 +79,7 @@ pub fn check(tests_path: &Path, src_path: &Path, bless: bool, bad: &mut bool) {
// Our data must remain up to date, so they must be removed from
// `src/tools/tidy/src/allowed_run_make_makefiles.txt`.
// This can be done automatically on --bless, or else a tidy error will be issued.
if bless && !remaining_makefiles.is_empty() {
if bless && (!remaining_makefiles.is_empty() || !is_sorted) {
let tidy_src = src_path.join("tools").join("tidy").join("src");
let org_file_path = tidy_src.join("allowed_run_make_makefiles.txt");
let temp_file_path = tidy_src.join("blessed_allowed_run_make_makefiles.txt");
11 changes: 7 additions & 4 deletions tests/ui/generic-const-items/compare-impl-item.rs
Original file line number Diff line number Diff line change
@@ -6,9 +6,10 @@ trait Trait<P> {
const B<const K: u64, const Q: u64>: u64;
const C<T>: T;
const D<const N: usize>: usize;
const E<'a>: &'a ();

const E: usize;
const F<T: PartialEq>: ();
const F: usize;
const G<T: PartialEq>: ();
}

impl<P> Trait<P> for () {
@@ -20,11 +21,13 @@ impl<P> Trait<P> for () {
//~^ ERROR const `C` has 0 type parameters but its trait declaration has 1 type parameter
const D<const N: u16>: u16 = N;
//~^ ERROR const `D` has an incompatible generic parameter for trait `Trait`
const E: &'static () = &();
//~^ ERROR lifetime parameters or bounds on const `E` do not match the trait declaration

const E: usize = 1024
const F: usize = 1024
where
P: Copy; //~ ERROR impl has stricter requirements than trait
const F<T: Eq>: () = (); //~ ERROR impl has stricter requirements than trait
const G<T: Eq>: () = (); //~ ERROR impl has stricter requirements than trait
}

fn main() {}
35 changes: 22 additions & 13 deletions tests/ui/generic-const-items/compare-impl-item.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0049]: const `A` has 1 type parameter but its trait declaration has 0 type parameters
--> $DIR/compare-impl-item.rs:15:13
--> $DIR/compare-impl-item.rs:16:13
|
LL | const A: ();
| - expected 0 type parameters
@@ -8,7 +8,7 @@ LL | const A<T>: () = ();
| ^ found 1 type parameter

error[E0049]: const `B` has 1 const parameter but its trait declaration has 2 const parameters
--> $DIR/compare-impl-item.rs:17:13
--> $DIR/compare-impl-item.rs:18:13
|
LL | const B<const K: u64, const Q: u64>: u64;
| ------------ ------------
@@ -19,7 +19,7 @@ LL | const B<const K: u64>: u64 = 0;
| ^^^^^^^^^^^^ found 1 const parameter

error[E0049]: const `C` has 0 type parameters but its trait declaration has 1 type parameter
--> $DIR/compare-impl-item.rs:19:13
--> $DIR/compare-impl-item.rs:20:13
|
LL | const C<T>: T;
| - expected 1 type parameter
@@ -28,7 +28,7 @@ LL | const C<'a>: &'a str = "";
| ^^ found 0 type parameters

error[E0053]: const `D` has an incompatible generic parameter for trait `Trait`
--> $DIR/compare-impl-item.rs:21:13
--> $DIR/compare-impl-item.rs:22:13
|
LL | trait Trait<P> {
| -----
@@ -42,25 +42,34 @@ LL | impl<P> Trait<P> for () {
LL | const D<const N: u16>: u16 = N;
| ^^^^^^^^^^^^ found const parameter of type `u16`

error[E0195]: lifetime parameters or bounds on const `E` do not match the trait declaration
--> $DIR/compare-impl-item.rs:24:12
|
LL | const E<'a>: &'a ();
| ---- lifetimes in impl do not match this const in trait
...
LL | const E: &'static () = &();
| ^ lifetimes do not match const in trait

error[E0276]: impl has stricter requirements than trait
--> $DIR/compare-impl-item.rs:26:12
--> $DIR/compare-impl-item.rs:29:12
|
LL | const E: usize;
| -------------- definition of `E` from trait
LL | const F: usize;
| -------------- definition of `F` from trait
...
LL | P: Copy;
| ^^^^ impl has extra requirement `P: Copy`

error[E0276]: impl has stricter requirements than trait
--> $DIR/compare-impl-item.rs:27:16
--> $DIR/compare-impl-item.rs:30:16
|
LL | const F<T: PartialEq>: ();
| ------------------------- definition of `F` from trait
LL | const G<T: PartialEq>: ();
| ------------------------- definition of `G` from trait
...
LL | const F<T: Eq>: () = ();
LL | const G<T: Eq>: () = ();
| ^^ impl has extra requirement `T: Eq`

error: aborting due to 6 previous errors
error: aborting due to 7 previous errors

Some errors have detailed explanations: E0049, E0053, E0276.
Some errors have detailed explanations: E0049, E0053, E0195, E0276.
For more information about an error, try `rustc --explain E0049`.