Skip to content

Commit f7b5e54

Browse files
committed
Auto merge of #131895 - jieyouxu:rollup-jyt3pic, r=jieyouxu
Rollup of 3 pull requests Successful merges: - #126207 (std::unix::stack_overflow::drop_handler addressing todo through libc …) - #131864 (Never emit `vptr` for empty/auto traits) - #131870 (compiletest: Store test collection context/state in two structs) r? `@ghost` `@rustbot` modify labels: rollup
2 parents b0c2d2e + 43e5093 commit f7b5e54

File tree

7 files changed

+135
-121
lines changed

7 files changed

+135
-121
lines changed

Diff for: compiler/rustc_trait_selection/src/traits/vtable.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -154,18 +154,17 @@ fn prepare_vtable_segments_inner<'tcx, T>(
154154

155155
// emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
156156
while let Some((inner_most_trait_ref, emit_vptr, mut siblings)) = stack.pop() {
157+
let has_entries =
158+
has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id());
159+
157160
segment_visitor(VtblSegment::TraitOwnEntries {
158161
trait_ref: inner_most_trait_ref,
159-
emit_vptr: emit_vptr && !tcx.sess.opts.unstable_opts.no_trait_vptr,
162+
emit_vptr: emit_vptr && has_entries && !tcx.sess.opts.unstable_opts.no_trait_vptr,
160163
})?;
161164

162165
// If we've emitted (fed to `segment_visitor`) a trait that has methods present in the vtable,
163166
// we'll need to emit vptrs from now on.
164-
if !emit_vptr_on_new_entry
165-
&& has_own_existential_vtable_entries(tcx, inner_most_trait_ref.def_id())
166-
{
167-
emit_vptr_on_new_entry = true;
168-
}
167+
emit_vptr_on_new_entry |= has_entries;
169168

170169
if let Some(next_inner_most_trait_ref) =
171170
siblings.find(|&sibling| visited.insert(sibling.upcast(tcx)))

Diff for: library/std/src/sys/pal/unix/stack_overflow.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,7 @@ mod imp {
265265
/// Modern kernels on modern hardware can have dynamic signal stack sizes.
266266
#[cfg(any(target_os = "linux", target_os = "android"))]
267267
fn sigstack_size() -> usize {
268-
// FIXME: reuse const from libc when available?
269-
const AT_MINSIGSTKSZ: crate::ffi::c_ulong = 51;
270-
let dynamic_sigstksz = unsafe { libc::getauxval(AT_MINSIGSTKSZ) };
268+
let dynamic_sigstksz = unsafe { libc::getauxval(libc::AT_MINSIGSTKSZ) };
271269
// If getauxval couldn't find the entry, it returns 0,
272270
// so take the higher of the "constant" and auxval.
273271
// This transparently supports older kernels which don't provide AT_MINSIGSTKSZ

Diff for: src/tools/compiletest/src/lib.rs

+95-101
Original file line numberDiff line numberDiff line change
@@ -464,9 +464,7 @@ pub fn run_tests(config: Arc<Config>) {
464464
// structure for each test (or each revision of a multi-revision test).
465465
let mut tests = Vec::new();
466466
for c in configs {
467-
let mut found_paths = HashSet::new();
468-
make_tests(c, &mut tests, &mut found_paths);
469-
check_overlapping_tests(&found_paths);
467+
tests.extend(collect_and_make_tests(c));
470468
}
471469

472470
tests.sort_by(|a, b| a.desc.name.as_slice().cmp(&b.desc.name.as_slice()));
@@ -545,46 +543,62 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
545543
}
546544
}
547545

546+
/// Read-only context data used during test collection.
547+
struct TestCollectorCx {
548+
config: Arc<Config>,
549+
cache: HeadersCache,
550+
common_inputs_stamp: Stamp,
551+
modified_tests: Vec<PathBuf>,
552+
}
553+
554+
/// Mutable state used during test collection.
555+
struct TestCollector {
556+
tests: Vec<test::TestDescAndFn>,
557+
found_path_stems: HashSet<PathBuf>,
558+
poisoned: bool,
559+
}
560+
548561
/// Creates libtest structures for every test/revision in the test suite directory.
549562
///
550563
/// This always inspects _all_ test files in the suite (e.g. all 17k+ ui tests),
551564
/// regardless of whether any filters/tests were specified on the command-line,
552565
/// because filtering is handled later by libtest.
553-
pub fn make_tests(
554-
config: Arc<Config>,
555-
tests: &mut Vec<test::TestDescAndFn>,
556-
found_paths: &mut HashSet<PathBuf>,
557-
) {
566+
pub fn collect_and_make_tests(config: Arc<Config>) -> Vec<test::TestDescAndFn> {
558567
debug!("making tests from {:?}", config.src_base.display());
559-
let inputs = common_inputs_stamp(&config);
568+
let common_inputs_stamp = common_inputs_stamp(&config);
560569
let modified_tests = modified_tests(&config, &config.src_base).unwrap_or_else(|err| {
561570
panic!("modified_tests got error from dir: {}, error: {}", config.src_base.display(), err)
562571
});
563-
564572
let cache = HeadersCache::load(&config);
565-
let mut poisoned = false;
566-
collect_tests_from_dir(
567-
config.clone(),
568-
&cache,
569-
&config.src_base,
570-
&PathBuf::new(),
571-
&inputs,
572-
tests,
573-
found_paths,
574-
&modified_tests,
575-
&mut poisoned,
576-
)
577-
.unwrap_or_else(|reason| {
578-
panic!("Could not read tests from {}: {reason}", config.src_base.display())
579-
});
573+
574+
let cx = TestCollectorCx { config, cache, common_inputs_stamp, modified_tests };
575+
let mut collector =
576+
TestCollector { tests: vec![], found_path_stems: HashSet::new(), poisoned: false };
577+
578+
collect_tests_from_dir(&cx, &mut collector, &cx.config.src_base, &PathBuf::new())
579+
.unwrap_or_else(|reason| {
580+
panic!("Could not read tests from {}: {reason}", cx.config.src_base.display())
581+
});
582+
583+
let TestCollector { tests, found_path_stems, poisoned } = collector;
580584

581585
if poisoned {
582586
eprintln!();
583587
panic!("there are errors in tests");
584588
}
589+
590+
check_for_overlapping_test_paths(&found_path_stems);
591+
592+
tests
585593
}
586594

587-
/// Returns a stamp constructed from input files common to all test cases.
595+
/// Returns the most recent last-modified timestamp from among the input files
596+
/// that are considered relevant to all tests (e.g. the compiler, std, and
597+
/// compiletest itself).
598+
///
599+
/// (Some of these inputs aren't actually relevant to _all_ tests, but they are
600+
/// common to some subset of tests, and are hopefully unlikely to be modified
601+
/// while working on other tests.)
588602
fn common_inputs_stamp(config: &Config) -> Stamp {
589603
let rust_src_dir = config.find_rust_src_root().expect("Could not find Rust source root");
590604

@@ -662,15 +676,10 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
662676
/// Recursively scans a directory to find test files and create test structures
663677
/// that will be handed over to libtest.
664678
fn collect_tests_from_dir(
665-
config: Arc<Config>,
666-
cache: &HeadersCache,
679+
cx: &TestCollectorCx,
680+
collector: &mut TestCollector,
667681
dir: &Path,
668682
relative_dir_path: &Path,
669-
inputs: &Stamp,
670-
tests: &mut Vec<test::TestDescAndFn>,
671-
found_paths: &mut HashSet<PathBuf>,
672-
modified_tests: &Vec<PathBuf>,
673-
poisoned: &mut bool,
674683
) -> io::Result<()> {
675684
// Ignore directories that contain a file named `compiletest-ignore-dir`.
676685
if dir.join("compiletest-ignore-dir").exists() {
@@ -679,7 +688,7 @@ fn collect_tests_from_dir(
679688

680689
// For run-make tests, a "test file" is actually a directory that contains
681690
// an `rmake.rs` or `Makefile`"
682-
if config.mode == Mode::RunMake {
691+
if cx.config.mode == Mode::RunMake {
683692
if dir.join("Makefile").exists() && dir.join("rmake.rs").exists() {
684693
return Err(io::Error::other(
685694
"run-make tests cannot have both `Makefile` and `rmake.rs`",
@@ -691,7 +700,7 @@ fn collect_tests_from_dir(
691700
file: dir.to_path_buf(),
692701
relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
693702
};
694-
tests.extend(make_test(config, cache, &paths, inputs, poisoned));
703+
make_test(cx, collector, &paths);
695704
// This directory is a test, so don't try to find other tests inside it.
696705
return Ok(());
697706
}
@@ -703,7 +712,7 @@ fn collect_tests_from_dir(
703712
// sequential loop because otherwise, if we do it in the
704713
// tests themselves, they race for the privilege of
705714
// creating the directories and sometimes fail randomly.
706-
let build_dir = output_relative_path(&config, relative_dir_path);
715+
let build_dir = output_relative_path(&cx.config, relative_dir_path);
707716
fs::create_dir_all(&build_dir).unwrap();
708717

709718
// Add each `.rs` file as a test, and recurse further on any
@@ -715,33 +724,25 @@ fn collect_tests_from_dir(
715724
let file_path = file.path();
716725
let file_name = file.file_name();
717726

718-
if is_test(&file_name) && (!config.only_modified || modified_tests.contains(&file_path)) {
727+
if is_test(&file_name)
728+
&& (!cx.config.only_modified || cx.modified_tests.contains(&file_path))
729+
{
719730
// We found a test file, so create the corresponding libtest structures.
720731
debug!("found test file: {:?}", file_path.display());
721732

722733
// Record the stem of the test file, to check for overlaps later.
723734
let rel_test_path = relative_dir_path.join(file_path.file_stem().unwrap());
724-
found_paths.insert(rel_test_path);
735+
collector.found_path_stems.insert(rel_test_path);
725736

726737
let paths =
727738
TestPaths { file: file_path, relative_dir: relative_dir_path.to_path_buf() };
728-
tests.extend(make_test(config.clone(), cache, &paths, inputs, poisoned))
739+
make_test(cx, collector, &paths);
729740
} else if file_path.is_dir() {
730741
// Recurse to find more tests in a subdirectory.
731742
let relative_file_path = relative_dir_path.join(file.file_name());
732743
if &file_name != "auxiliary" {
733744
debug!("found directory: {:?}", file_path.display());
734-
collect_tests_from_dir(
735-
config.clone(),
736-
cache,
737-
&file_path,
738-
&relative_file_path,
739-
inputs,
740-
tests,
741-
found_paths,
742-
modified_tests,
743-
poisoned,
744-
)?;
745+
collect_tests_from_dir(cx, collector, &file_path, &relative_file_path)?;
745746
}
746747
} else {
747748
debug!("found other file/directory: {:?}", file_path.display());
@@ -765,17 +766,11 @@ pub fn is_test(file_name: &OsString) -> bool {
765766

766767
/// For a single test file, creates one or more test structures (one per revision)
767768
/// that can be handed over to libtest to run, possibly in parallel.
768-
fn make_test(
769-
config: Arc<Config>,
770-
cache: &HeadersCache,
771-
testpaths: &TestPaths,
772-
inputs: &Stamp,
773-
poisoned: &mut bool,
774-
) -> Vec<test::TestDescAndFn> {
769+
fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &TestPaths) {
775770
// For run-make tests, each "test file" is actually a _directory_ containing
776771
// an `rmake.rs` or `Makefile`. But for the purposes of directive parsing,
777772
// we want to look at that recipe file, not the directory itself.
778-
let test_path = if config.mode == Mode::RunMake {
773+
let test_path = if cx.config.mode == Mode::RunMake {
779774
if testpaths.file.join("rmake.rs").exists() && testpaths.file.join("Makefile").exists() {
780775
panic!("run-make tests cannot have both `rmake.rs` and `Makefile`");
781776
}
@@ -792,57 +787,57 @@ fn make_test(
792787
};
793788

794789
// Scan the test file to discover its revisions, if any.
795-
let early_props = EarlyProps::from_file(&config, &test_path);
790+
let early_props = EarlyProps::from_file(&cx.config, &test_path);
796791

797792
// Normally we create one libtest structure per revision, with two exceptions:
798793
// - If a test doesn't use revisions, create a dummy revision (None) so that
799794
// the test can still run.
800795
// - Incremental tests inherently can't run their revisions in parallel, so
801796
// we treat them like non-revisioned tests here. Incremental revisions are
802797
// handled internally by `runtest::run` instead.
803-
let revisions = if early_props.revisions.is_empty() || config.mode == Mode::Incremental {
798+
let revisions = if early_props.revisions.is_empty() || cx.config.mode == Mode::Incremental {
804799
vec![None]
805800
} else {
806801
early_props.revisions.iter().map(|r| Some(r.as_str())).collect()
807802
};
808803

809-
// For each revision (or the sole dummy revision), create and return a
804+
// For each revision (or the sole dummy revision), create and append a
810805
// `test::TestDescAndFn` that can be handed over to libtest.
811-
revisions
812-
.into_iter()
813-
.map(|revision| {
814-
// Create a test name and description to hand over to libtest.
815-
let src_file =
816-
std::fs::File::open(&test_path).expect("open test file to parse ignores");
817-
let test_name = crate::make_test_name(&config, testpaths, revision);
818-
// Create a libtest description for the test/revision.
819-
// This is where `ignore-*`/`only-*`/`needs-*` directives are handled,
820-
// because they need to set the libtest ignored flag.
821-
let mut desc = make_test_description(
822-
&config, cache, test_name, &test_path, src_file, revision, poisoned,
823-
);
806+
collector.tests.extend(revisions.into_iter().map(|revision| {
807+
// Create a test name and description to hand over to libtest.
808+
let src_file = fs::File::open(&test_path).expect("open test file to parse ignores");
809+
let test_name = make_test_name(&cx.config, testpaths, revision);
810+
// Create a libtest description for the test/revision.
811+
// This is where `ignore-*`/`only-*`/`needs-*` directives are handled,
812+
// because they need to set the libtest ignored flag.
813+
let mut desc = make_test_description(
814+
&cx.config,
815+
&cx.cache,
816+
test_name,
817+
&test_path,
818+
src_file,
819+
revision,
820+
&mut collector.poisoned,
821+
);
824822

825-
// If a test's inputs haven't changed since the last time it ran,
826-
// mark it as ignored so that libtest will skip it.
827-
if !config.force_rerun
828-
&& is_up_to_date(&config, testpaths, &early_props, revision, inputs)
829-
{
830-
desc.ignore = true;
831-
// Keep this in sync with the "up-to-date" message detected by bootstrap.
832-
desc.ignore_message = Some("up-to-date");
833-
}
823+
// If a test's inputs haven't changed since the last time it ran,
824+
// mark it as ignored so that libtest will skip it.
825+
if !cx.config.force_rerun && is_up_to_date(cx, testpaths, &early_props, revision) {
826+
desc.ignore = true;
827+
// Keep this in sync with the "up-to-date" message detected by bootstrap.
828+
desc.ignore_message = Some("up-to-date");
829+
}
834830

835-
// Create the callback that will run this test/revision when libtest calls it.
836-
let testfn = make_test_closure(config.clone(), testpaths, revision);
831+
// Create the callback that will run this test/revision when libtest calls it.
832+
let testfn = make_test_closure(Arc::clone(&cx.config), testpaths, revision);
837833

838-
test::TestDescAndFn { desc, testfn }
839-
})
840-
.collect()
834+
test::TestDescAndFn { desc, testfn }
835+
}));
841836
}
842837

843838
/// The path of the `stamp` file that gets created or updated whenever a
844839
/// particular test completes successfully.
845-
fn stamp(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
840+
fn stamp_file_path(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> PathBuf {
846841
output_base_dir(config, testpaths, revision).join("stamp")
847842
}
848843

@@ -891,21 +886,20 @@ fn files_related_to_test(
891886
/// (This is not very reliable in some circumstances, so the `--force-rerun`
892887
/// flag can be used to ignore up-to-date checking and always re-run tests.)
893888
fn is_up_to_date(
894-
config: &Config,
889+
cx: &TestCollectorCx,
895890
testpaths: &TestPaths,
896891
props: &EarlyProps,
897892
revision: Option<&str>,
898-
inputs: &Stamp, // Last-modified timestamp of the compiler, compiletest etc
899893
) -> bool {
900-
let stamp_name = stamp(config, testpaths, revision);
894+
let stamp_file_path = stamp_file_path(&cx.config, testpaths, revision);
901895
// Check the config hash inside the stamp file.
902-
let contents = match fs::read_to_string(&stamp_name) {
896+
let contents = match fs::read_to_string(&stamp_file_path) {
903897
Ok(f) => f,
904898
Err(ref e) if e.kind() == ErrorKind::InvalidData => panic!("Can't read stamp contents"),
905899
// The test hasn't succeeded yet, so it is not up-to-date.
906900
Err(_) => return false,
907901
};
908-
let expected_hash = runtest::compute_stamp_hash(config);
902+
let expected_hash = runtest::compute_stamp_hash(&cx.config);
909903
if contents != expected_hash {
910904
// Some part of compiletest configuration has changed since the test
911905
// last succeeded, so it is not up-to-date.
@@ -914,14 +908,14 @@ fn is_up_to_date(
914908

915909
// Check the timestamp of the stamp file against the last modified time
916910
// of all files known to be relevant to the test.
917-
let mut inputs = inputs.clone();
918-
for path in files_related_to_test(config, testpaths, props, revision) {
919-
inputs.add_path(&path);
911+
let mut inputs_stamp = cx.common_inputs_stamp.clone();
912+
for path in files_related_to_test(&cx.config, testpaths, props, revision) {
913+
inputs_stamp.add_path(&path);
920914
}
921915

922916
// If no relevant files have been modified since the stamp file was last
923917
// written, the test is up-to-date.
924-
inputs < Stamp::from_path(&stamp_name)
918+
inputs_stamp < Stamp::from_path(&stamp_file_path)
925919
}
926920

927921
/// The maximum of a set of file-modified timestamps.
@@ -1029,11 +1023,11 @@ fn make_test_closure(
10291023
/// To avoid problems, we forbid test names from overlapping in this way.
10301024
///
10311025
/// See <https://github.com/rust-lang/rust/pull/109509> for more context.
1032-
fn check_overlapping_tests(found_paths: &HashSet<PathBuf>) {
1026+
fn check_for_overlapping_test_paths(found_path_stems: &HashSet<PathBuf>) {
10331027
let mut collisions = Vec::new();
1034-
for path in found_paths {
1028+
for path in found_path_stems {
10351029
for ancestor in path.ancestors().skip(1) {
1036-
if found_paths.contains(ancestor) {
1030+
if found_path_stems.contains(ancestor) {
10371031
collisions.push((path, ancestor));
10381032
}
10391033
}

0 commit comments

Comments
 (0)