Merge from rustc

This commit is contained in:
Ralf Jung 2024-06-11 07:51:38 +02:00
commit 6e06c49954
247 changed files with 3973 additions and 1598 deletions

View file

@ -0,0 +1 @@
Types and functions shared across tools in this workspace.

View file

@ -1,5 +1,30 @@
//! Types and functions shared across tools in this workspace.
pub mod ci;
pub mod git;
pub mod metrics;
pub mod stage0_parser;
pub mod util;
/// The default set of crates for opt-dist to collect LLVM profiles.
pub const LLVM_PGO_CRATES: &[&str] = &[
"syn-1.0.89",
"cargo-0.60.0",
"serde-1.0.136",
"ripgrep-13.0.0",
"regex-1.5.5",
"clap-3.1.6",
"hyper-0.14.18",
];
/// The default set of crates for opt-dist to collect rustc profiles.
pub const RUSTC_PGO_CRATES: &[&str] = &[
"externs",
"ctfe-stress-5",
"cargo-0.60.0",
"token-stream-stress",
"match-stress",
"tuple-stress",
"diesel-1.4.8",
"bitmaps-3.1.0",
];

View file

@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays {
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
&& let ty::Array(element_type, cst) = ty.kind()
&& let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
&& let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
&& let element_count = element_count.to_target_usize(cx.tcx)
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size)
{

View file

@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays {
&& !self.is_from_vec_macro(cx, expr.span)
&& let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind()
&& let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
&& let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
&& let element_count = element_count.to_target_usize(cx.tcx)
&& let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes())
&& !cx.tcx.hir().parent_iter(expr.hir_id).any(|(_, node)| {
matches!(

View file

@ -199,7 +199,7 @@ impl<'tcx> NonCopyConst<'tcx> {
.any(|field| Self::is_value_unfrozen_raw_inner(cx, *field, ty)),
ty::Adt(def, args) if def.is_enum() => {
let (&variant_index, fields) = val.unwrap_branch().split_first().unwrap();
let variant_index = VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap());
let variant_index = VariantIdx::from_u32(variant_index.unwrap_leaf().to_u32());
fields
.iter()
.copied()

View file

@ -56,8 +56,7 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects {
} else if let ExprKind::Repeat(inner_expr, _) = expr.kind
&& let ty::Array(_, cst) = cx.typeck_results().expr_ty(expr).kind()
&& let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind()
&& let Ok(element_count) = element_count.try_to_target_usize(cx.tcx)
&& element_count == 0
&& element_count.to_target_usize(cx.tcx) == 0
{
inner_check(cx, expr, inner_expr, false);
}

View file

@ -810,14 +810,14 @@ pub fn mir_to_const<'tcx>(lcx: &LateContext<'tcx>, result: mir::Const<'tcx>) ->
(ConstValue::Scalar(Scalar::Int(int)), _) => match result.ty().kind() {
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.assert_bits(int.size()))),
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.to_bits(int.size()))),
ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(
int.try_into().expect("invalid f32 bit representation"),
))),
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(
int.try_into().expect("invalid f64 bit representation"),
))),
ty::RawPtr(_, _) => Some(Constant::RawPtr(int.assert_bits(int.size()))),
ty::RawPtr(_, _) => Some(Constant::RawPtr(int.to_bits(int.size()))),
_ => None,
},
(_, ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Str) => {

View file

@ -23,7 +23,7 @@ use rustc_middle::ty::{
};
use rustc_span::symbol::Ident;
use rustc_span::{sym, Span, Symbol, DUMMY_SP};
use rustc_target::abi::{Size, VariantIdx};
use rustc_target::abi::VariantIdx;
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::{Obligation, ObligationCause};
@ -865,22 +865,8 @@ impl core::ops::Add<u32> for EnumValue {
pub fn read_explicit_enum_value(tcx: TyCtxt<'_>, id: DefId) -> Option<EnumValue> {
if let Ok(ConstValue::Scalar(Scalar::Int(value))) = tcx.const_eval_poly(id) {
match tcx.type_of(id).instantiate_identity().kind() {
ty::Int(_) => Some(EnumValue::Signed(match value.size().bytes() {
1 => i128::from(value.assert_bits(Size::from_bytes(1)) as u8 as i8),
2 => i128::from(value.assert_bits(Size::from_bytes(2)) as u16 as i16),
4 => i128::from(value.assert_bits(Size::from_bytes(4)) as u32 as i32),
8 => i128::from(value.assert_bits(Size::from_bytes(8)) as u64 as i64),
16 => value.assert_bits(Size::from_bytes(16)) as i128,
_ => return None,
})),
ty::Uint(_) => Some(EnumValue::Unsigned(match value.size().bytes() {
1 => value.assert_bits(Size::from_bytes(1)),
2 => value.assert_bits(Size::from_bytes(2)),
4 => value.assert_bits(Size::from_bytes(4)),
8 => value.assert_bits(Size::from_bytes(8)),
16 => value.assert_bits(Size::from_bytes(16)),
_ => return None,
})),
ty::Int(_) => Some(EnumValue::Signed(value.to_int(value.size()))),
ty::Uint(_) => Some(EnumValue::Unsigned(value.to_uint(value.size()))),
_ => None,
}
} else {

View file

@ -11,7 +11,7 @@ error: invisible character detected
--> tests/ui/unicode.rs:7:12
|
LL | print!("Here >­< is a SHY, and ­another");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >\u{AD}< is a SHY, and \u{AD}another"`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider replacing the string with: `"Here >\u{AD}< is a SHY, and \u{AD}another"`
error: invisible character detected
--> tests/ui/unicode.rs:9:12

View file

@ -645,8 +645,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
for i in 0..dest_len {
let src_index: u64 = index[usize::try_from(i).unwrap()]
.unwrap_leaf()
.try_to_u32()
.unwrap()
.to_u32()
.into();
let dest = this.project_index(&dest, i)?;

View file

@ -222,9 +222,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
let fds = &mut this.machine.fds;
let sv0 = fds.insert_fd(FileDescriptor::new(socketpair_0));
let sv0 = Scalar::try_from_int(sv0, sv.layout.size).unwrap();
let sv0 = Scalar::from_int(sv0, sv.layout.size);
let sv1 = fds.insert_fd(FileDescriptor::new(socketpair_1));
let sv1 = Scalar::try_from_int(sv1, sv.layout.size).unwrap();
let sv1 = Scalar::from_int(sv1, sv.layout.size);
this.write_scalar(sv0, &sv)?;
this.write_scalar(sv1, &sv.offset(sv.layout.size, sv.layout, this)?)?;

View file

@ -658,11 +658,32 @@ fn simd_masked_loadstore() {
assert_eq!(buf, [2, 3, 4]);
}
fn simd_ops_non_pow2() {
// Just a little smoke test for operations on non-power-of-two vectors.
#[repr(simd, packed)]
#[derive(Copy, Clone)]
pub struct SimdPacked<T, const N: usize>([T; N]);
#[repr(simd)]
#[derive(Copy, Clone)]
pub struct SimdPadded<T, const N: usize>([T; N]);
let x = SimdPacked([1u32; 3]);
let y = SimdPacked([2u32; 3]);
let z = unsafe { intrinsics::simd_add(x, y) };
assert_eq!({ z.0 }, [3u32; 3]);
let x = SimdPadded([1u32; 3]);
let y = SimdPadded([2u32; 3]);
let z = unsafe { intrinsics::simd_add(x, y) };
assert_eq!(z.0, [3u32; 3]);
}
fn main() {
simd_mask();
simd_ops_f32();
simd_ops_f64();
simd_ops_i32();
simd_ops_non_pow2();
simd_cast();
simd_swizzle();
simd_gather_scatter();

View file

@ -3,30 +3,10 @@ use crate::exec::{cmd, CmdBuilder};
use crate::utils::io::{count_files, delete_directory};
use crate::utils::with_log_group;
use anyhow::Context;
use build_helper::{LLVM_PGO_CRATES, RUSTC_PGO_CRATES};
use camino::{Utf8Path, Utf8PathBuf};
use humansize::BINARY;
const LLVM_PGO_CRATES: &[&str] = &[
"syn-1.0.89",
"cargo-0.60.0",
"serde-1.0.136",
"ripgrep-13.0.0",
"regex-1.5.5",
"clap-3.1.6",
"hyper-0.14.18",
];
const RUSTC_PGO_CRATES: &[&str] = &[
"externs",
"ctfe-stress-5",
"cargo-0.60.0",
"token-stream-stress",
"match-stress",
"tuple-stress",
"diesel-1.4.8",
"bitmaps-3.1.0",
];
fn init_compiler_benchmarks(
env: &Environment,
profiles: &[&str],

View file

@ -1,7 +1,7 @@
use std::path::Path;
use std::process::Command;
use crate::{bin_name, cygpath_windows, env_var, handle_failed_output, is_msvc, is_windows, uname};
use crate::command::Command;
use crate::{bin_name, cygpath_windows, env_var, is_msvc, is_windows, uname};
/// Construct a new platform-specific C compiler invocation.
///

View file

@ -1,7 +1,7 @@
use std::path::Path;
use std::process::Command;
use crate::{bin_name, env_var, handle_failed_output};
use crate::command::Command;
use crate::{bin_name, env_var};
/// Construct a new `clang` invocation. `clang` is not always available for all targets.
pub fn clang() -> Clang {
@ -68,9 +68,4 @@ impl Clang {
self.cmd.arg(format!("-fuse-ld={ld}"));
self
}
/// Get the [`Output`][::std::process::Output] of the finished process.
pub fn command_output(&mut self) -> ::std::process::Output {
self.cmd.output().expect("failed to get output of finished process")
}
}

View file

@ -0,0 +1,151 @@
use crate::{assert_not_contains, handle_failed_output};
use std::ffi::OsStr;
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
/// This is a custom command wrapper that simplifies working with commands
/// and makes it easier to ensure that we check the exit status of executed
/// processes.
#[derive(Debug)]
pub struct Command {
cmd: StdCommand,
stdin: Option<Box<[u8]>>,
}
impl Command {
pub fn new<S: AsRef<OsStr>>(program: S) -> Self {
Self { cmd: StdCommand::new(program), stdin: None }
}
pub fn set_stdin(&mut self, stdin: Box<[u8]>) {
self.stdin = Some(stdin);
}
/// Run the constructed command and assert that it is successfully run.
#[track_caller]
pub fn run(&mut self) -> CompletedProcess {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();
let output = self.command_output();
if !output.status().success() {
handle_failed_output(&self, 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) -> CompletedProcess {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();
let output = self.command_output();
if output.status().success() {
handle_failed_output(&self, output, caller_line_number);
}
output
}
#[track_caller]
pub(crate) fn command_output(&mut self) -> CompletedProcess {
// let's make sure we piped all the input and outputs
self.cmd.stdin(Stdio::piped());
self.cmd.stdout(Stdio::piped());
self.cmd.stderr(Stdio::piped());
let output = if let Some(input) = &self.stdin {
let mut child = self.cmd.spawn().unwrap();
{
let mut stdin = child.stdin.take().unwrap();
stdin.write_all(input.as_ref()).unwrap();
}
child.wait_with_output().expect("failed to get output of finished process")
} else {
self.cmd.output().expect("failed to get output of finished process")
};
output.into()
}
}
impl Deref for Command {
type Target = StdCommand;
fn deref(&self) -> &Self::Target {
&self.cmd
}
}
impl DerefMut for Command {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.cmd
}
}
/// Represents the result of an executed process.
/// The various `assert_` helper methods should preferably be used for
/// checking the contents of stdout/stderr.
pub struct CompletedProcess {
output: Output,
}
impl CompletedProcess {
pub fn stdout_utf8(&self) -> String {
String::from_utf8(self.output.stdout.clone()).expect("stdout is not valid UTF-8")
}
pub fn stderr_utf8(&self) -> String {
String::from_utf8(self.output.stderr.clone()).expect("stderr is not valid UTF-8")
}
pub fn status(&self) -> ExitStatus {
self.output.status
}
/// Checks that trimmed `stdout` matches trimmed `content`.
#[track_caller]
pub fn assert_stdout_equals<S: AsRef<str>>(self, content: S) -> Self {
assert_eq!(self.stdout_utf8().trim(), content.as_ref().trim());
self
}
#[track_caller]
pub fn assert_stdout_not_contains<S: AsRef<str>>(self, needle: S) -> Self {
assert_not_contains(&self.stdout_utf8(), needle.as_ref());
self
}
/// Checks that trimmed `stderr` matches trimmed `content`.
#[track_caller]
pub fn assert_stderr_equals<S: AsRef<str>>(self, content: S) -> Self {
assert_eq!(self.stderr_utf8().trim(), content.as_ref().trim());
self
}
#[track_caller]
pub fn assert_stderr_contains<S: AsRef<str>>(self, needle: S) -> Self {
assert!(self.stderr_utf8().contains(needle.as_ref()));
self
}
#[track_caller]
pub fn assert_stderr_not_contains<S: AsRef<str>>(self, needle: S) -> Self {
assert_not_contains(&self.stdout_utf8(), needle.as_ref());
self
}
#[track_caller]
pub fn assert_exit_code(self, code: i32) -> Self {
assert!(self.output.status.code() == Some(code));
self
}
}
impl From<Output> for CompletedProcess {
fn from(output: Output) -> Self {
Self { output }
}
}

View file

@ -5,6 +5,7 @@
pub mod cc;
pub mod clang;
mod command;
pub mod diff;
pub mod llvm_readobj;
pub mod run;
@ -16,7 +17,6 @@ use std::ffi::OsString;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use std::process::{Command, Output};
pub use gimli;
pub use object;
@ -27,7 +27,7 @@ pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
pub use clang::{clang, Clang};
pub use diff::{diff, Diff};
pub use llvm_readobj::{llvm_readobj, LlvmReadobj};
pub use run::{run, run_fail};
pub use run::{cmd, run, run_fail};
pub use rustc::{aux_build, rustc, Rustc};
pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
@ -167,13 +167,12 @@ pub fn cygpath_windows<P: AsRef<Path>>(path: P) -> String {
let mut cygpath = Command::new("cygpath");
cygpath.arg("-w");
cygpath.arg(path.as_ref());
let output = cygpath.output().unwrap();
if !output.status.success() {
let output = cygpath.command_output();
if !output.status().success() {
handle_failed_output(&cygpath, output, caller_line_number);
}
let s = String::from_utf8(output.stdout).unwrap();
// cygpath -w can attach a newline
s.trim().to_string()
output.stdout_utf8().trim().to_string()
}
/// Run `uname`. This assumes that `uname` is available on the platform!
@ -183,23 +182,23 @@ pub fn uname() -> String {
let caller_line_number = caller_location.line();
let mut uname = Command::new("uname");
let output = uname.output().unwrap();
if !output.status.success() {
let output = uname.command_output();
if !output.status().success() {
handle_failed_output(&uname, output, caller_line_number);
}
String::from_utf8(output.stdout).unwrap()
output.stdout_utf8()
}
fn handle_failed_output(cmd: &Command, output: Output, caller_line_number: u32) -> ! {
if output.status.success() {
fn handle_failed_output(cmd: &Command, output: CompletedProcess, caller_line_number: u32) -> ! {
if output.status().success() {
eprintln!("command unexpectedly succeeded at line {caller_line_number}");
} else {
eprintln!("command failed at line {caller_line_number}");
}
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());
eprintln!("output status: `{}`", output.status());
eprintln!("=== STDOUT ===\n{}\n\n", output.stdout_utf8());
eprintln!("=== STDERR ===\n{}\n\n", output.stderr_utf8());
std::process::exit(1)
}
@ -286,6 +285,7 @@ pub fn read_dir<F: Fn(&Path)>(dir: impl AsRef<Path>, callback: F) {
}
/// Check that `haystack` does not contain `needle`. Panic otherwise.
#[track_caller]
pub fn assert_not_contains(haystack: &str, needle: &str) {
if haystack.contains(needle) {
eprintln!("=== HAYSTACK ===");
@ -318,38 +318,30 @@ pub fn run_in_tmpdir<F: FnOnce()>(callback: F) {
}
/// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
/// containing a `cmd: Command` field and a `output` function. The provided helpers are:
/// 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.
/// 3. Output and execution: `run` and `run_fail` are provided. These are
/// higher-level convenience methods which wait for the command to finish running and assert
/// that the command successfully ran or failed as expected. They return
/// [`CompletedProcess`], which can be used to assert the stdout/stderr/exit code of the executed
/// process.
///
/// Example usage:
///
/// ```ignore (illustrative)
/// struct CommandWrapper { cmd: Command } // <- required `cmd` field
///
/// impl CommandWrapper {
/// /// Get the [`Output`][::std::process::Output] of the finished process.
/// pub fn command_output(&mut self) -> Output { /* ... */ } // <- required `command_output()` method
/// }
///
/// 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 {
@ -412,28 +404,14 @@ macro_rules! impl_common_helpers {
/// 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.command_output();
if !output.status.success() {
handle_failed_output(&self.cmd, output, caller_line_number);
}
output
pub fn run(&mut self) -> crate::command::CompletedProcess {
self.cmd.run()
}
/// 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.command_output();
if output.status.success() {
handle_failed_output(&self.cmd, output, caller_line_number);
}
output
pub fn run_fail(&mut self) -> crate::command::CompletedProcess {
self.cmd.run_fail()
}
/// Set the path where the command will be run.
@ -445,4 +423,5 @@ macro_rules! impl_common_helpers {
};
}
use crate::command::{Command, CompletedProcess};
pub(crate) use impl_common_helpers;

View file

@ -1,7 +1,7 @@
use std::path::{Path, PathBuf};
use std::process::Command;
use crate::{env_var, handle_failed_output};
use crate::command::Command;
use crate::env_var;
/// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
/// at `$LLVM_BIN_DIR/llvm-readobj`.
@ -39,10 +39,4 @@ impl LlvmReadobj {
self.cmd.arg("--file-header");
self
}
/// Get the [`Output`][::std::process::Output] of the finished process.
#[track_caller]
pub fn command_output(&mut self) -> ::std::process::Output {
self.cmd.output().expect("failed to get output of finished process")
}
}

View file

@ -1,12 +1,13 @@
use std::env;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use std::process::{Command, Output};
use crate::{cwd, env_var, is_windows};
use crate::command::{Command, CompletedProcess};
use crate::{cwd, env_var, is_windows, set_host_rpath};
use super::handle_failed_output;
fn run_common(name: &str) -> (Command, Output) {
fn run_common(name: &str) -> (Command, CompletedProcess) {
let mut bin_path = PathBuf::new();
bin_path.push(cwd());
bin_path.push(name);
@ -33,18 +34,18 @@ fn run_common(name: &str) -> (Command, Output) {
cmd.env("PATH", env::join_paths(paths.iter()).unwrap());
}
let output = cmd.output().unwrap();
let output = cmd.command_output();
(cmd, output)
}
/// Run a built binary and make sure it succeeds.
#[track_caller]
pub fn run(name: &str) -> Output {
pub fn run(name: &str) -> CompletedProcess {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();
let (cmd, output) = run_common(name);
if !output.status.success() {
if !output.status().success() {
handle_failed_output(&cmd, output, caller_line_number);
}
output
@ -52,13 +53,21 @@ pub fn run(name: &str) -> Output {
/// Run a built binary and make sure it fails.
#[track_caller]
pub fn run_fail(name: &str) -> Output {
pub fn run_fail(name: &str) -> CompletedProcess {
let caller_location = std::panic::Location::caller();
let caller_line_number = caller_location.line();
let (cmd, output) = run_common(name);
if output.status.success() {
if output.status().success() {
handle_failed_output(&cmd, output, caller_line_number);
}
output
}
/// Create a new custom Command.
/// This should be preferred to creating `std::process::Command` directly.
pub fn cmd<S: AsRef<OsStr>>(program: S) -> Command {
let mut command = Command::new(program);
set_host_rpath(&mut command);
command
}

View file

@ -1,9 +1,8 @@
use command::Command;
use std::ffi::{OsStr, OsString};
use std::io::Write;
use std::path::Path;
use std::process::{Command, Output, Stdio};
use crate::{cwd, env_var, handle_failed_output, set_host_rpath};
use crate::{command, cwd, env_var, set_host_rpath};
/// Construct a new `rustc` invocation.
pub fn rustc() -> Rustc {
@ -19,7 +18,6 @@ pub fn aux_build() -> Rustc {
#[derive(Debug)]
pub struct Rustc {
cmd: Command,
stdin: Option<Box<[u8]>>,
}
crate::impl_common_helpers!(Rustc);
@ -38,14 +36,14 @@ impl Rustc {
/// Construct a new `rustc` invocation.
pub fn new() -> Self {
let cmd = setup_common();
Self { cmd, stdin: None }
Self { cmd }
}
/// Construct a new `rustc` invocation with `aux_build` preset (setting `--crate-type=lib`).
pub fn new_aux_build() -> Self {
let mut cmd = setup_common();
cmd.arg("--crate-type=lib");
Self { cmd, stdin: None }
Self { cmd }
}
// Argument provider methods
@ -109,6 +107,13 @@ impl Rustc {
self
}
/// Specify path to the output directory. Equivalent to `--out-dir`` in rustc.
pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
self.cmd.arg("--out-dir");
self.cmd.arg(path.as_ref());
self
}
/// This flag defers LTO optimizations to the linker.
pub fn linker_plugin_lto(&mut self, option: &str) -> &mut Self {
self.cmd.arg(format!("-Clinker-plugin-lto={option}"));
@ -197,7 +202,7 @@ impl Rustc {
/// Specify a stdin input
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
self
}
@ -213,38 +218,4 @@ impl Rustc {
self.cmd.arg(format!("-Clinker={linker}"));
self
}
/// Get the [`Output`] of the finished process.
#[track_caller]
pub fn command_output(&mut self) -> Output {
// let's make sure we piped all the input and outputs
self.cmd.stdin(Stdio::piped());
self.cmd.stdout(Stdio::piped());
self.cmd.stderr(Stdio::piped());
if let Some(input) = &self.stdin {
let mut child = self.cmd.spawn().unwrap();
{
let mut stdin = child.stdin.take().unwrap();
stdin.write_all(input.as_ref()).unwrap();
}
child.wait_with_output().expect("failed to get output of finished process")
} else {
self.cmd.output().expect("failed to get output of finished process")
}
}
#[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.command_output();
if output.status.code().unwrap() != code {
handle_failed_output(&self.cmd, output, caller_line_number);
}
output
}
}

View file

@ -1,9 +1,8 @@
use std::ffi::OsStr;
use std::io::Write;
use std::path::Path;
use std::process::{Command, Output, Stdio};
use crate::{env_var, env_var_os, handle_failed_output, set_host_rpath};
use crate::command::Command;
use crate::{env_var, env_var_os, set_host_rpath};
/// Construct a plain `rustdoc` invocation with no flags set.
pub fn bare_rustdoc() -> Rustdoc {
@ -18,7 +17,6 @@ pub fn rustdoc() -> Rustdoc {
#[derive(Debug)]
pub struct Rustdoc {
cmd: Command,
stdin: Option<Box<[u8]>>,
}
crate::impl_common_helpers!(Rustdoc);
@ -34,7 +32,7 @@ impl Rustdoc {
/// Construct a bare `rustdoc` invocation.
pub fn bare() -> Self {
let cmd = setup_common();
Self { cmd, stdin: None }
Self { cmd }
}
/// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
@ -42,7 +40,7 @@ impl Rustdoc {
let mut cmd = setup_common();
let target_rpath_dir = env_var_os("TARGET_RPATH_DIR");
cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
Self { cmd, stdin: None }
Self { cmd }
}
/// Specify where an external library is located.
@ -88,33 +86,10 @@ impl Rustdoc {
/// Specify a stdin input
pub fn stdin<I: AsRef<[u8]>>(&mut self, input: I) -> &mut Self {
self.cmd.stdin(Stdio::piped());
self.stdin = Some(input.as_ref().to_vec().into_boxed_slice());
self.cmd.set_stdin(input.as_ref().to_vec().into_boxed_slice());
self
}
/// Get the [`Output`] of the finished process.
#[track_caller]
pub fn command_output(&mut self) -> ::std::process::Output {
// let's make sure we piped all the input and outputs
self.cmd.stdin(Stdio::piped());
self.cmd.stdout(Stdio::piped());
self.cmd.stderr(Stdio::piped());
if let Some(input) = &self.stdin {
let mut child = self.cmd.spawn().unwrap();
{
let mut stdin = child.stdin.take().unwrap();
stdin.write_all(input.as_ref()).unwrap();
}
child.wait_with_output().expect("failed to get output of finished process")
} else {
self.cmd.output().expect("failed to get output of finished process")
}
}
/// Specify the edition year.
pub fn edition(&mut self, edition: &str) -> &mut Self {
self.cmd.arg("--edition");
@ -156,16 +131,4 @@ impl Rustdoc {
self.cmd.arg(format);
self
}
#[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.command_output();
if output.status.code().unwrap() != code {
handle_failed_output(&self.cmd, output, caller_line_number);
}
output
}
}

View file

@ -122,7 +122,6 @@ run-make/link-framework/Makefile
run-make/link-path-order/Makefile
run-make/linkage-attr-on-static/Makefile
run-make/llvm-ident/Makefile
run-make/llvm-outputs/Makefile
run-make/long-linker-command-lines-cmd-exe/Makefile
run-make/long-linker-command-lines/Makefile
run-make/longjmp-across-rust/Makefile

View file

@ -27,7 +27,8 @@ const LICENSES: &[&str] = &[
"MIT OR Zlib OR Apache-2.0", // miniz_oxide
"MIT",
"MIT/Apache-2.0",
"Unicode-DFS-2016", // tinystr and icu4x
"Unicode-3.0", // icu4x
"Unicode-DFS-2016", // tinystr
"Unlicense OR MIT",
"Unlicense/MIT",
"Zlib OR Apache-2.0 OR MIT", // tinyvec
@ -67,6 +68,7 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>)
//("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
//("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None),
("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None),
("src/tools/x", &[], None),
// tidy-alphabetical-end
];
@ -142,6 +144,22 @@ const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[
// tidy-alphabetical-end
];
const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[
// tidy-alphabetical-start
("alloc-no-stdlib", "BSD-3-Clause"),
("alloc-stdlib", "BSD-3-Clause"),
("brotli", "BSD-3-Clause/MIT"),
("brotli-decompressor", "BSD-3-Clause/MIT"),
("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"),
("inferno", "CDDL-1.0"),
("instant", "BSD-3-Clause"),
("ring", NON_STANDARD_LICENSE), // see EXCEPTIONS_NON_STANDARD_LICENSE_DEPS for more.
("ryu", "Apache-2.0 OR BSL-1.0"),
("snap", "BSD-3-Clause"),
("subtle", "BSD-3-Clause"),
// tidy-alphabetical-end
];
const EXCEPTIONS_CRANELIFT: ExceptionList = &[
// tidy-alphabetical-start
("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
@ -178,6 +196,20 @@ const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[
("r-efi", "MIT OR Apache-2.0 OR LGPL-2.1-or-later"), // LGPL is not acceptible, but we use it under MIT OR Apache-2.0
];
/// Placeholder for non-standard license file.
const NON_STANDARD_LICENSE: &str = "NON_STANDARD_LICENSE";
/// These dependencies have non-standard licenses but are genenrally permitted.
const EXCEPTIONS_NON_STANDARD_LICENSE_DEPS: &[&str] = &[
// `ring` is included because it is an optional dependency of `hyper`,
// which is a training data in rustc-perf for optimized build.
// The license of it is generally `ISC AND MIT AND OpenSSL`,
// though the `package.license` field is not set.
//
// See https://github.com/briansmith/ring/issues/902
"ring",
];
/// These are the root crates that are part of the runtime. The licenses for
/// these and all their dependencies *must not* be in the exception list.
const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"];
@ -411,32 +443,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
// tidy-alphabetical-end
];
// These crates come from ICU4X and are licensed under the unicode license.
// It currently doesn't have an SPDX identifier, so they cannot put one there.
// See https://github.com/unicode-org/icu4x/pull/3875
// FIXME: This should be removed once ICU4X crates update.
const ICU4X_UNICODE_LICENSE_DEPENDENCIES: &[&str] = &[
// tidy-alphabetical-start
"icu_list",
"icu_list_data",
"icu_locid",
"icu_locid_transform",
"icu_locid_transform_data",
"icu_provider",
"icu_provider_adapters",
"icu_provider_macros",
"litemap",
"tinystr",
"writeable",
"yoke",
"yoke-derive",
"zerofrom",
"zerofrom-derive",
"zerovec",
"zerovec-derive",
// tidy-alphabetical-end
];
const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
// tidy-alphabetical-start
"ahash",
@ -610,6 +616,11 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba
for pkg in metadata.packages.iter().filter(|p| p.name == *name) {
match &pkg.license {
None => {
if *license == NON_STANDARD_LICENSE
&& EXCEPTIONS_NON_STANDARD_LICENSE_DEPS.contains(&pkg.name.as_str())
{
continue;
}
tidy_error!(
bad,
"dependency exception `{}` does not declare a license expression",
@ -642,10 +653,6 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba
let license = match &pkg.license {
Some(license) => license,
None => {
if ICU4X_UNICODE_LICENSE_DEPENDENCIES.contains(&pkg.name.as_str()) {
// See the comment on ICU4X_UNICODE_LICENSE_DEPENDENCIES.
continue;
}
tidy_error!(bad, "dependency `{}` does not define a license expression", pkg.id);
continue;
}

View file

@ -320,7 +320,7 @@ fn install_requirements(
}
let stat = Command::new(py_path)
.args(["-m", "pip", "install", "--require-hashes", "-r"])
.args(["-m", "pip", "install", "--quiet", "--require-hashes", "-r"])
.arg(src_reqs_path)
.status()?;
if !stat.success() {

View file

@ -4,7 +4,11 @@ use std::fs;
use std::path::Path;
/// List of allowed sources for packages.
const ALLOWED_SOURCES: &[&str] = &["\"registry+https://github.com/rust-lang/crates.io-index\""];
const ALLOWED_SOURCES: &[&str] = &[
r#""registry+https://github.com/rust-lang/crates.io-index""#,
// This is `rust_team_data` used by `site` in src/tools/rustc-perf,
r#""git+https://github.com/rust-lang/team#a5260e76d3aa894c64c56e6ddc8545b9a98043ec""#,
];
/// Checks for external package sources. `root` is the path to the directory that contains the
/// workspace `Cargo.toml`.