Merge from rustc

This commit is contained in:
The Miri Cronjob Bot 2024-12-31 05:12:50 +00:00
commit e898da11d2
495 changed files with 5342 additions and 1962 deletions

View file

@ -160,10 +160,10 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"needs-xray",
"no-auto-check-cfg",
"no-prefer-dynamic",
"normalize-stderr",
"normalize-stderr-32bit",
"normalize-stderr-64bit",
"normalize-stderr-test",
"normalize-stdout-test",
"normalize-stdout",
"only-16bit",
"only-32bit",
"only-64bit",

View file

@ -12,7 +12,6 @@ use tracing::*;
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
use crate::debuggers::{extract_cdb_version, extract_gdb_version};
use crate::header::auxiliary::{AuxProps, parse_and_update_aux};
use crate::header::cfg::{MatchOutcome, parse_cfg_name_directive};
use crate::header::needs::CachedNeedsConditions;
use crate::util::static_regex;
@ -472,11 +471,24 @@ impl TestProps {
config.set_name_directive(ln, IGNORE_PASS, &mut self.ignore_pass);
if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stdout") {
self.normalize_stdout.push(rule);
}
if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stderr") {
self.normalize_stderr.push(rule);
if let Some(NormalizeRule { kind, regex, replacement }) =
config.parse_custom_normalization(ln)
{
let rule_tuple = (regex, replacement);
match kind {
NormalizeKind::Stdout => self.normalize_stdout.push(rule_tuple),
NormalizeKind::Stderr => self.normalize_stderr.push(rule_tuple),
NormalizeKind::Stderr32bit => {
if config.target_cfg().pointer_width == 32 {
self.normalize_stderr.push(rule_tuple);
}
}
NormalizeKind::Stderr64bit => {
if config.target_cfg().pointer_width == 64 {
self.normalize_stderr.push(rule_tuple);
}
}
}
}
if let Some(code) = config
@ -966,20 +978,26 @@ impl Config {
}
}
fn parse_custom_normalization(&self, line: &str, prefix: &str) -> Option<(String, String)> {
let parsed = parse_cfg_name_directive(self, line, prefix);
if parsed.outcome != MatchOutcome::Match {
return None;
}
let name = parsed.name.expect("successful match always has a name");
fn parse_custom_normalization(&self, raw_directive: &str) -> Option<NormalizeRule> {
// FIXME(Zalathar): Integrate name/value splitting into `DirectiveLine`
// instead of doing it here.
let (directive_name, raw_value) = raw_directive.split_once(':')?;
let Some((regex, replacement)) = parse_normalize_rule(line) else {
let kind = match directive_name {
"normalize-stdout" => NormalizeKind::Stdout,
"normalize-stderr" => NormalizeKind::Stderr,
"normalize-stderr-32bit" => NormalizeKind::Stderr32bit,
"normalize-stderr-64bit" => NormalizeKind::Stderr64bit,
_ => return None,
};
let Some((regex, replacement)) = parse_normalize_rule(raw_value) else {
panic!(
"couldn't parse custom normalization rule: `{line}`\n\
help: expected syntax is: `{prefix}-{name}: \"REGEX\" -> \"REPLACEMENT\"`"
"couldn't parse custom normalization rule: `{raw_directive}`\n\
help: expected syntax is: `{directive_name}: \"REGEX\" -> \"REPLACEMENT\"`"
);
};
Some((regex, replacement))
Some(NormalizeRule { kind, regex, replacement })
}
fn parse_name_directive(&self, line: &str, directive: &str) -> bool {
@ -1105,27 +1123,42 @@ fn expand_variables(mut value: String, config: &Config) -> String {
value
}
struct NormalizeRule {
kind: NormalizeKind,
regex: String,
replacement: String,
}
enum NormalizeKind {
Stdout,
Stderr,
Stderr32bit,
Stderr64bit,
}
/// Parses the regex and replacement values of a `//@ normalize-*` header,
/// in the format:
/// ```text
/// normalize-*: "REGEX" -> "REPLACEMENT"
/// "REGEX" -> "REPLACEMENT"
/// ```
fn parse_normalize_rule(header: &str) -> Option<(String, String)> {
fn parse_normalize_rule(raw_value: &str) -> Option<(String, String)> {
// FIXME: Support escaped double-quotes in strings.
let captures = static_regex!(
r#"(?x) # (verbose mode regex)
^
[^:\s]+:\s* # (header name followed by colon)
\s* # (leading whitespace)
"(?<regex>[^"]*)" # "REGEX"
\s+->\s+ # ->
"(?<replacement>[^"]*)" # "REPLACEMENT"
$
"#
)
.captures(header)?;
.captures(raw_value)?;
let regex = captures["regex"].to_owned();
let replacement = captures["replacement"].to_owned();
// FIXME: Support escaped new-line in strings.
// A `\n` sequence in the replacement becomes an actual newline.
// FIXME: Do unescaping in a less ad-hoc way, and perhaps support escaped
// backslashes and double-quotes.
let replacement = replacement.replace("\\n", "\n");
Some((regex, replacement))
}

View file

@ -40,8 +40,8 @@ pub(super) fn handle_only(config: &Config, line: &str) -> IgnoreDecision {
}
/// Parses a name-value directive which contains config-specific information, e.g., `ignore-x86`
/// or `normalize-stderr-32bit`.
pub(super) fn parse_cfg_name_directive<'a>(
/// or `only-windows`.
fn parse_cfg_name_directive<'a>(
config: &Config,
line: &'a str,
prefix: &str,

View file

@ -35,11 +35,14 @@ fn make_test_description<R: Read>(
#[test]
fn test_parse_normalize_rule() {
let good_data = &[(
r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)""#,
"something (32 bits)",
"something ($WORD bits)",
)];
let good_data = &[
(
r#""something (32 bits)" -> "something ($WORD bits)""#,
"something (32 bits)",
"something ($WORD bits)",
),
(r#" " with whitespace" -> " replacement""#, " with whitespace", " replacement"),
];
for &(input, expected_regex, expected_replacement) in good_data {
let parsed = parse_normalize_rule(input);
@ -49,15 +52,15 @@ fn test_parse_normalize_rule() {
}
let bad_data = &[
r#"normalize-stderr-32bit "something (32 bits)" -> "something ($WORD bits)""#,
r#"normalize-stderr-16bit: something (16 bits) -> something ($WORD bits)"#,
r#"normalize-stderr-32bit: something (32 bits) -> something ($WORD bits)"#,
r#"normalize-stderr-32bit: "something (32 bits) -> something ($WORD bits)"#,
r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)"#,
r#"normalize-stderr-32bit: "something (32 bits)" -> "something ($WORD bits)"."#,
r#"something (11 bits) -> something ($WORD bits)"#,
r#"something (12 bits) -> something ($WORD bits)"#,
r#""something (13 bits) -> something ($WORD bits)"#,
r#""something (14 bits)" -> "something ($WORD bits)"#,
r#""something (15 bits)" -> "something ($WORD bits)"."#,
];
for &input in bad_data {
println!("- {input:?}");
let parsed = parse_normalize_rule(input);
assert_eq!(parsed, None);
}

View file

@ -159,7 +159,9 @@ pub fn parse_config(args: Vec<String>) -> Config {
)
.optflag("", "force-rerun", "rerun tests even if the inputs are unchanged")
.optflag("", "only-modified", "only run tests that result been modified")
// FIXME: Temporarily retained so we can point users to `--no-capture`
.optflag("", "nocapture", "")
.optflag("", "no-capture", "don't capture stdout/stderr of tests")
.optflag("", "profiler-runtime", "is the profiler runtime enabled for this target")
.optflag("h", "help", "show this message")
.reqopt("", "channel", "current Rust channel", "CHANNEL")
@ -288,6 +290,10 @@ pub fn parse_config(args: Vec<String>) -> Config {
);
})
});
if matches.opt_present("nocapture") {
panic!("`--nocapture` is deprecated; please use `--no-capture`");
}
Config {
bless: matches.opt_present("bless"),
compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
@ -385,7 +391,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
target_cfgs: OnceLock::new(),
builtin_cfg_names: OnceLock::new(),
nocapture: matches.opt_present("nocapture"),
nocapture: matches.opt_present("no-capture"),
git_repository: matches.opt_str("git-repository").unwrap(),
nightly_branch: matches.opt_str("nightly-branch").unwrap(),

View file

@ -213,7 +213,7 @@ fn remove_and_create_dir_all(path: &Path) {
fs::create_dir_all(path).unwrap();
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
struct TestCx<'test> {
config: &'test Config,
props: &'test TestProps,
@ -2318,32 +2318,47 @@ impl<'test> TestCx<'test> {
match output_kind {
TestOutput::Compile => {
if !self.props.dont_check_compiler_stdout {
errors += self.compare_output(
if self
.compare_output(
stdout_kind,
&normalized_stdout,
&proc_res.stdout,
&expected_stdout,
)
.should_error()
{
errors += 1;
}
}
if !self.props.dont_check_compiler_stderr {
if self
.compare_output(stderr_kind, &normalized_stderr, &stderr, &expected_stderr)
.should_error()
{
errors += 1;
}
}
}
TestOutput::Run => {
if self
.compare_output(
stdout_kind,
&normalized_stdout,
&proc_res.stdout,
&expected_stdout,
);
)
.should_error()
{
errors += 1;
}
if !self.props.dont_check_compiler_stderr {
errors += self.compare_output(
stderr_kind,
&normalized_stderr,
&stderr,
&expected_stderr,
);
if self
.compare_output(stderr_kind, &normalized_stderr, &stderr, &expected_stderr)
.should_error()
{
errors += 1;
}
}
TestOutput::Run => {
errors += self.compare_output(
stdout_kind,
&normalized_stdout,
&proc_res.stdout,
&expected_stdout,
);
errors +=
self.compare_output(stderr_kind, &normalized_stderr, &stderr, &expected_stderr);
}
}
errors
}
@ -2576,7 +2591,14 @@ impl<'test> TestCx<'test> {
actual: &str,
actual_unnormalized: &str,
expected: &str,
) -> usize {
) -> CompareOutcome {
let expected_path =
expected_output_path(self.testpaths, self.revision, &self.config.compare_mode, stream);
if self.config.bless && actual.is_empty() && expected_path.exists() {
self.delete_file(&expected_path);
}
let are_different = match (self.force_color_svg(), expected.find('\n'), actual.find('\n')) {
// FIXME: We ignore the first line of SVG files
// because the width parameter is non-deterministic.
@ -2584,7 +2606,7 @@ impl<'test> TestCx<'test> {
_ => expected != actual,
};
if !are_different {
return 0;
return CompareOutcome::Same;
}
// Wrapper tools set by `runner` might provide extra output on failure,
@ -2600,7 +2622,7 @@ impl<'test> TestCx<'test> {
used.retain(|line| actual_lines.contains(line));
// check if `expected` contains a subset of the lines of `actual`
if used.len() == expected_lines.len() && (expected.is_empty() == actual.is_empty()) {
return 0;
return CompareOutcome::Same;
}
if expected_lines.is_empty() {
// if we have no lines to check, force a full overwite
@ -2626,9 +2648,6 @@ impl<'test> TestCx<'test> {
}
println!("Saved the actual {stream} to {actual_path:?}");
let expected_path =
expected_output_path(self.testpaths, self.revision, &self.config.compare_mode, stream);
if !self.config.bless {
if expected.is_empty() {
println!("normalized {}:\n{}\n", stream, actual);
@ -2651,15 +2670,17 @@ impl<'test> TestCx<'test> {
self.delete_file(&old);
}
if let Err(err) = fs::write(&expected_path, &actual) {
self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}"));
if !actual.is_empty() {
if let Err(err) = fs::write(&expected_path, &actual) {
self.fatal(&format!("failed to write {stream} to `{expected_path:?}`: {err}"));
}
println!("Blessing the {stream} of {test_name} in {expected_path:?}");
}
println!("Blessing the {stream} of {test_name} in {expected_path:?}");
}
println!("\nThe actual {0} differed from the expected {0}.", stream);
if self.config.bless { 0 } else { 1 }
if self.config.bless { CompareOutcome::Blessed } else { CompareOutcome::Differed }
}
/// Returns whether to show the full stderr/stdout.
@ -2885,3 +2906,21 @@ enum AuxType {
Dylib,
ProcMacro,
}
/// Outcome of comparing a stream to a blessed file,
/// e.g. `.stderr` and `.fixed`.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum CompareOutcome {
/// Expected and actual outputs are the same
Same,
/// Outputs differed but were blessed
Blessed,
/// Outputs differed and an error should be emitted
Differed,
}
impl CompareOutcome {
fn should_error(&self) -> bool {
matches!(self, CompareOutcome::Differed)
}
}

View file

@ -39,16 +39,16 @@ impl<'test> TestCx<'test> {
let expected_coverage_dump = self.load_expected_output(kind);
let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]);
let coverage_dump_errors = self.compare_output(
let coverage_dump_compare_outcome = self.compare_output(
kind,
&actual_coverage_dump,
&proc_res.stdout,
&expected_coverage_dump,
);
if coverage_dump_errors > 0 {
if coverage_dump_compare_outcome.should_error() {
self.fatal_proc_rec(
&format!("{coverage_dump_errors} errors occurred comparing coverage output."),
&format!("an error occurred comparing coverage output."),
&proc_res,
);
}
@ -139,16 +139,16 @@ impl<'test> TestCx<'test> {
self.fatal_proc_rec(&err, &proc_res);
});
let coverage_errors = self.compare_output(
let coverage_dump_compare_outcome = self.compare_output(
kind,
&normalized_actual_coverage,
&proc_res.stdout,
&expected_coverage,
);
if coverage_errors > 0 {
if coverage_dump_compare_outcome.should_error() {
self.fatal_proc_rec(
&format!("{} errors occurred comparing coverage output.", coverage_errors),
&format!("an error occurred comparing coverage output."),
&proc_res,
);
}

View file

@ -19,15 +19,9 @@ pub(super) struct DebuggerCommands {
}
impl DebuggerCommands {
pub fn parse_from(
file: &Path,
config: &Config,
debugger_prefixes: &[&str],
) -> Result<Self, String> {
let directives = debugger_prefixes
.iter()
.map(|prefix| (format!("{prefix}-command"), format!("{prefix}-check")))
.collect::<Vec<_>>();
pub fn parse_from(file: &Path, config: &Config, debugger_prefix: &str) -> Result<Self, String> {
let command_directive = format!("{debugger_prefix}-command");
let check_directive = format!("{debugger_prefix}-check");
let mut breakpoint_lines = vec![];
let mut commands = vec![];
@ -48,14 +42,11 @@ impl DebuggerCommands {
continue;
};
for &(ref command_directive, ref check_directive) in &directives {
config
.parse_name_value_directive(&line, command_directive)
.map(|cmd| commands.push(cmd));
config
.parse_name_value_directive(&line, check_directive)
.map(|cmd| check_lines.push((line_no, cmd)));
if let Some(command) = config.parse_name_value_directive(&line, &command_directive) {
commands.push(command);
}
if let Some(pattern) = config.parse_name_value_directive(&line, &check_directive) {
check_lines.push((line_no, pattern));
}
}

View file

@ -59,14 +59,8 @@ impl TestCx<'_> {
return;
}
let prefixes = {
static PREFIXES: &[&str] = &["cdb", "cdbg"];
// No "native rust support" variation for CDB yet.
PREFIXES
};
// Parse debugger commands etc from test files
let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, prefixes)
let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, "cdb")
.unwrap_or_else(|e| self.fatal(&e));
// https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands
@ -137,7 +131,7 @@ impl TestCx<'_> {
}
fn run_debuginfo_gdb_test_no_opt(&self) {
let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, &["gdb"])
let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, "gdb")
.unwrap_or_else(|e| self.fatal(&e));
let mut cmds = dbg_cmds.commands.join("\n");
@ -403,7 +397,7 @@ impl TestCx<'_> {
}
// Parse debugger commands etc from test files
let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, &["lldb"])
let dbg_cmds = DebuggerCommands::parse_from(&self.testpaths.file, self.config, "lldb")
.unwrap_or_else(|e| self.fatal(&e));
// Write debugger script:

View file

@ -100,7 +100,12 @@ impl TestCx<'_> {
)
});
errors += self.compare_output("fixed", &fixed_code, &fixed_code, &expected_fixed);
if self
.compare_output("fixed", &fixed_code, &fixed_code, &expected_fixed)
.should_error()
{
errors += 1;
}
} else if !expected_fixed.is_empty() {
panic!(
"the `//@ run-rustfix` directive wasn't found but a `*.fixed` \

View file

@ -8,7 +8,7 @@
//!
//! Currently uses a combination of HTML parsing to
//! extract the `href` and `id` attributes,
//! and regex search on the orignal markdown to handle intra-doc links.
//! and regex search on the original markdown to handle intra-doc links.
//!
//! These values are then translated to file URLs if possible and then the
//! destination is asserted to exist.

View file

@ -1,7 +1,7 @@
#![feature(core_intrinsics)]
#![feature(rustc_attrs)]
use std::intrinsics::typed_swap;
use std::intrinsics::typed_swap_nonoverlapping;
use std::ptr::addr_of_mut;
fn invalid_array() {
@ -10,7 +10,7 @@ fn invalid_array() {
unsafe {
let a = addr_of_mut!(a).cast::<[bool; 100]>();
let b = addr_of_mut!(b).cast::<[bool; 100]>();
typed_swap(a, b); //~ERROR: constructing invalid value
typed_swap_nonoverlapping(a, b); //~ERROR: constructing invalid value
}
}

View file

@ -1,8 +1,8 @@
error: Undefined Behavior: constructing invalid value at [0]: encountered 0x02, but expected a boolean
--> tests/fail/intrinsics/typed-swap-invalid-array.rs:LL:CC
|
LL | typed_swap(a, b);
| ^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered 0x02, but expected a boolean
LL | typed_swap_nonoverlapping(a, b);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered 0x02, but expected a boolean
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View file

@ -1,8 +1,8 @@
error: Undefined Behavior: constructing invalid value: encountered 0x02, but expected a boolean
--> tests/fail/intrinsics/typed-swap-invalid-scalar.rs:LL:CC
|
LL | typed_swap(a, b);
| ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x02, but expected a boolean
LL | typed_swap_nonoverlapping(a, b);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x02, but expected a boolean
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information

View file

@ -0,0 +1,20 @@
error: Undefined Behavior: constructing invalid value: encountered 0x03, but expected a boolean
--> tests/fail/intrinsics/typed-swap-invalid-scalar.rs:LL:CC
|
LL | typed_swap_nonoverlapping(a, b);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x03, but expected a boolean
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `invalid_scalar` at tests/fail/intrinsics/typed-swap-invalid-scalar.rs:LL:CC
note: inside `main`
--> tests/fail/intrinsics/typed-swap-invalid-scalar.rs:LL:CC
|
LL | invalid_scalar();
| ^^^^^^^^^^^^^^^^
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error

View file

@ -1,16 +1,18 @@
//@revisions: left right
#![feature(core_intrinsics)]
#![feature(rustc_attrs)]
use std::intrinsics::typed_swap;
use std::intrinsics::typed_swap_nonoverlapping;
use std::ptr::addr_of_mut;
fn invalid_scalar() {
let mut a = 1_u8;
let mut b = 2_u8;
// We run the test twice, with either the left or the right side being invalid.
let mut a = if cfg!(left) { 2_u8 } else { 1_u8 };
let mut b = if cfg!(right) { 3_u8 } else { 1_u8 };
unsafe {
let a = addr_of_mut!(a).cast::<bool>();
let b = addr_of_mut!(b).cast::<bool>();
typed_swap(a, b); //~ERROR: constructing invalid value
typed_swap_nonoverlapping(a, b); //~ERROR: constructing invalid value
}
}

View file

@ -0,0 +1,13 @@
#![feature(core_intrinsics)]
#![feature(rustc_attrs)]
use std::intrinsics::typed_swap_nonoverlapping;
use std::ptr::addr_of_mut;
fn main() {
let mut a = 0_u8;
unsafe {
let a = addr_of_mut!(a);
typed_swap_nonoverlapping(a, a); //~ERROR: called on overlapping ranges
}
}

View file

@ -0,0 +1,15 @@
error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
--> tests/fail/intrinsics/typed-swap-overlap.rs:LL:CC
|
LL | typed_swap_nonoverlapping(a, a);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at tests/fail/intrinsics/typed-swap-overlap.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error

View file

@ -1,4 +1,4 @@
# If you want to use this as an .envrc file to create a shell with necessery components
# If you want to use this as an .envrc file to create a shell with necessary components
# to develop rustc, use the following command in the root of the rusr checkout:
#
# ln -s ./src/tools/nix-dev-shell/envrc-flake ./.envrc && nix flake update --flake ./src/tools/nix-dev-shell

View file

@ -1,4 +1,4 @@
# If you want to use this as an .envrc file to create a shell with necessery components
# If you want to use this as an .envrc file to create a shell with necessary components
# to develop rustc, use the following command in the root of the rusr checkout:
#
# ln -s ./src/tools/nix-dev-shell/envrc-shell ./.envrc

View file

@ -96,9 +96,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.94"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
[[package]]
name = "autocfg"
@ -161,9 +161,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cc"
version = "1.2.5"
version = "1.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e"
checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333"
dependencies = [
"shlex",
]
@ -1209,9 +1209,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.37"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
@ -1338,18 +1338,18 @@ checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
[[package]]
name = "serde"
version = "1.0.216"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.216"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
@ -1446,9 +1446,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.90"
version = "2.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
checksum = "9c786062daee0d6db1132800e623df74274a0a87322d8e183338e01b3d98d058"
dependencies = [
"proc-macro2",
"quote",
@ -1639,9 +1639,9 @@ checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
[[package]]
name = "unicase"
version = "2.8.0"
version = "2.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
[[package]]
name = "unicode-ident"

View file

@ -1,5 +1,5 @@
use std::fs::create_dir_all;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::process::Command;
use clap::Parser;
@ -169,7 +169,7 @@ fn execute_benchmark(cmd: &mut Command, compiler: &Path) {
const MANIFEST_DIR: &str = env!("CARGO_MANIFEST_DIR");
let rustc_perf_dir = PathBuf::from(MANIFEST_DIR).join("../rustc-perf");
let rustc_perf_dir = Path::new(MANIFEST_DIR).join("../rustc-perf");
// We need to set the working directory to `src/tools/perf`, so that it can find the directory
// with compile-time benchmarks.

View file

@ -2,7 +2,7 @@ use std::sync::OnceLock;
use crate::{Suggestion, sug};
// FIXME: perhaps this could use `std::lazy` when it is stablizied
// FIXME: perhaps this could use `std::lazy` when it is stabilized
macro_rules! static_suggestions {
($( [ $( $glob:expr ),* $(,)? ] => [ $( $suggestion:expr ),* $(,)? ] ),* $(,)? ) => {
pub(crate) fn static_suggestions() -> &'static [(Vec<&'static str>, Vec<Suggestion>)]

View file

@ -6,7 +6,7 @@ autobins = false
[dependencies]
build_helper = { path = "../../build_helper" }
cargo_metadata = "0.18"
cargo_metadata = "0.19"
regex = "1"
miropt-test-tools = { path = "../miropt-test-tools" }
walkdir = "2"

View file

@ -1,9 +1,6 @@
run-make/branch-protection-check-IBT/Makefile
run-make/cat-and-grep-sanity-check/Makefile
run-make/extern-fn-reachable/Makefile
run-make/incr-add-rust-src-component/Makefile
run-make/jobserver-error/Makefile
run-make/libs-through-symlinks/Makefile
run-make/split-debuginfo/Makefile
run-make/symbol-mangling-hashed/Makefile
run-make/translation/Makefile

View file

@ -1,12 +1,16 @@
//! Checks the licenses of third-party dependencies.
use std::collections::HashSet;
use std::fs::read_dir;
use std::fs::{File, read_dir};
use std::io::Write;
use std::path::Path;
use build_helper::ci::CiEnv;
use cargo_metadata::{Metadata, Package, PackageId};
#[path = "../../../bootstrap/src/utils/proc_macro_deps.rs"]
mod proc_macro_deps;
/// These are licenses that are allowed for all crates, including the runtime,
/// rustc, tools, etc.
#[rustfmt::skip]
@ -564,9 +568,11 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
///
/// `root` is path to the directory with the root `Cargo.toml` (for the workspace). `cargo` is path
/// to the cargo executable.
pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
pub fn check(root: &Path, cargo: &Path, bless: bool, bad: &mut bool) {
let mut checked_runtime_licenses = false;
check_proc_macro_dep_list(root, cargo, bless, bad);
for &(workspace, exceptions, permitted_deps, submodules) in WORKSPACES {
if has_missing_submodule(root, submodules) {
continue;
@ -600,6 +606,71 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
assert!(checked_runtime_licenses);
}
/// Ensure the list of proc-macro crate transitive dependencies is up to date
fn check_proc_macro_dep_list(root: &Path, cargo: &Path, bless: bool, bad: &mut bool) {
let mut cmd = cargo_metadata::MetadataCommand::new();
cmd.cargo_path(cargo)
.manifest_path(root.join("Cargo.toml"))
.features(cargo_metadata::CargoOpt::AllFeatures)
.other_options(vec!["--locked".to_owned()]);
let metadata = t!(cmd.exec());
let is_proc_macro_pkg = |pkg: &Package| pkg.targets.iter().any(|target| target.is_proc_macro());
let mut proc_macro_deps = HashSet::new();
for pkg in metadata.packages.iter().filter(|pkg| is_proc_macro_pkg(*pkg)) {
deps_of(&metadata, &pkg.id, &mut proc_macro_deps);
}
// Remove the proc-macro crates themselves
proc_macro_deps.retain(|pkg| !is_proc_macro_pkg(&metadata[pkg]));
let proc_macro_deps_iter = proc_macro_deps.into_iter().map(|dep| metadata[dep].name.clone());
if bless {
let mut proc_macro_deps: Vec<_> = proc_macro_deps_iter.collect();
proc_macro_deps.sort();
proc_macro_deps.dedup();
let mut file = File::create(root.join("src/bootstrap/src/utils/proc_macro_deps.rs"))
.expect("`proc_macro_deps` should exist");
writeln!(
&mut file,
"/// Do not update manually - use `./x.py test tidy --bless`
/// Holds all direct and indirect dependencies of proc-macro crates in tree.
/// See <https://github.com/rust-lang/rust/issues/134863>
pub static CRATES: &[&str] = &[
// tidy-alphabetical-start"
)
.unwrap();
for dep in proc_macro_deps {
writeln!(&mut file, " {dep:?},").unwrap();
}
writeln!(
&mut file,
" // tidy-alphabetical-end
];"
)
.unwrap();
} else {
let proc_macro_deps: HashSet<_> = proc_macro_deps_iter.collect();
let expected =
proc_macro_deps::CRATES.iter().map(|s| s.to_string()).collect::<HashSet<_>>();
let old_bad = *bad;
for missing in proc_macro_deps.difference(&expected) {
tidy_error!(
bad,
"proc-macro crate dependency `{missing}` is not registered in `src/bootstrap/src/utils/proc_macro_deps.rs`",
);
}
for extra in expected.difference(&proc_macro_deps) {
tidy_error!(
bad,
"`{extra}` is not registered in `src/bootstrap/src/utils/proc_macro_deps.rs`, but is not a proc-macro crate dependency",
);
}
if *bad != old_bad {
eprintln!("Run `./x.py test tidy --bless` to regenerate the list");
}
}
}
/// Used to skip a check if a submodule is not checked out, and not in a CI environment.
///
/// This helps prevent enforcing developers to fetch submodules for tidy.

View file

@ -95,7 +95,7 @@ fn main() {
check!(target_specific_tests, &tests_path);
// Checks that are done on the cargo workspace.
check!(deps, &root_path, &cargo);
check!(deps, &root_path, &cargo, bless);
check!(extdeps, &root_path);
// Checks over tests.

View file

@ -69,8 +69,7 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[
"// gdb",
"// lldb",
"// cdb",
"// normalize-stderr-test",
"//@ normalize-stderr-test",
"//@ normalize-stderr",
];
fn generate_problems<'a>(
@ -198,8 +197,8 @@ fn should_ignore(line: &str) -> bool {
// For `ui_test`-style UI test directives, also ignore
// - `//@[rev] compile-flags`
// - `//@[rev] normalize-stderr-test`
|| static_regex!("\\s*//@(\\[.*\\]) (compile-flags|normalize-stderr-test|error-pattern).*")
// - `//@[rev] normalize-stderr`
|| static_regex!("\\s*//@(\\[.*\\]) (compile-flags|normalize-stderr|error-pattern).*")
.is_match(line)
// Matching for rustdoc tests commands.
// It allows to prevent them emitting warnings like `line longer than 100 chars`.