From 5cddb156d114d77bb5f9ba3876fb2dada7ad9276 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 4 Jul 2024 11:15:57 -0400 Subject: [PATCH 1/8] rewrite target-specs to rmake --- tests/run-make/target-specs/Makefile | 12 ----- tests/run-make/target-specs/rmake.rs | 71 ++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 12 deletions(-) delete mode 100644 tests/run-make/target-specs/Makefile create mode 100644 tests/run-make/target-specs/rmake.rs diff --git a/tests/run-make/target-specs/Makefile b/tests/run-make/target-specs/Makefile deleted file mode 100644 index 161b66021857b..0000000000000 --- a/tests/run-make/target-specs/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -include ../tools.mk -all: - $(RUSTC) foo.rs --target=my-awesome-platform.json --crate-type=lib --emit=asm - $(CGREP) -v morestack < $(TMPDIR)/foo.s - $(RUSTC) foo.rs --target=my-invalid-platform.json 2>&1 | $(CGREP) "Error loading target specification" - $(RUSTC) foo.rs --target=my-incomplete-platform.json 2>&1 | $(CGREP) 'Field llvm-target' - RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-awesome-platform --crate-type=lib --emit=asm - RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-x86_64-unknown-linux-gnu-platform --crate-type=lib --emit=asm - $(RUSTC) -Z unstable-options --target=my-awesome-platform.json --print target-spec-json > $(TMPDIR)/test-platform.json && $(RUSTC) -Z unstable-options --target=$(TMPDIR)/test-platform.json --print target-spec-json | diff -q $(TMPDIR)/test-platform.json - - $(RUSTC) foo.rs --target=definitely-not-builtin-target 2>&1 | $(CGREP) 'may not set is_builtin' - $(RUSTC) foo.rs --target=endianness-mismatch 2>&1 | $(CGREP) '"data-layout" claims architecture is little-endian' - $(RUSTC) foo.rs --target=mismatching-data-layout --crate-type=lib 2>&1 | $(CGREP) 'data-layout for target' diff --git a/tests/run-make/target-specs/rmake.rs b/tests/run-make/target-specs/rmake.rs new file mode 100644 index 0000000000000..10c2fa298303d --- /dev/null +++ b/tests/run-make/target-specs/rmake.rs @@ -0,0 +1,71 @@ +// Target-specific compilation in rustc used to have case-by-case peculiarities in 2014, +// with the compiler having redundant target types and unspecific names. An overarching rework +// in #161156 changed the way the target flag functions, and this test attempts compilation +// with the target flag's bundle of new features to check that compilation either succeeds while +// using them correctly, or fails with the right error message when using them improperly. +// See https://github.com/rust-lang/rust/pull/16156 + +use run_make_support::{diff, fs_wrapper, rustc}; + +fn main() { + rustc().input("foo.rs").target("my-awesome-platform.json").crate_type("lib").emit("asm").run(); + assert!(!fs_wrapper::read_to_string("foo.s").contains("morestack")); + rustc() + .input("foo.rs") + .target("my-invalid-platform.json") + .run_fail() + .assert_stderr_contains("Error loading target specification"); + rustc() + .input("foo.rs") + .target("my-incomplete-platform.json") + .run_fail() + .assert_stderr_contains("Field llvm-target"); + rustc() + .env("RUST_TARGET_PATH", ".") + .input("foo.rs") + .target("my-awesome-platform") + .crate_type("lib") + .emit("asm") + .run(); + rustc() + .env("RUST_TARGET_PATH", ".") + .input("foo.rs") + .target("my-x86_64-unknown-linux-gnu-platform") + .crate_type("lib") + .emit("asm") + .run(); + let test_platform = rustc() + .arg("-Zunstable-options") + .target("my-awesome-platform.json") + .print("target-spec-json") + .run() + .stdout_utf8(); + fs_wrapper::create_file("test-platform.json"); + fs_wrapper::write("test-platform.json", test_platform.as_bytes()); + let test_platform_2 = rustc() + .arg("-Zunstable-options") + .target("test-platform.json") + .print("target-spec-json") + .run() + .stdout_utf8(); + diff() + .expected_file("test-platform.json") + .actual_text("test-platform-2", test_platform_2) + .run(); + rustc() + .input("foo.rs") + .target("definitely-not-builtin-target") + .run_fail() + .assert_stderr_contains("may not set is_builtin"); + rustc() + .input("foo.rs") + .target("endianness-mismatch") + .run_fail() + .assert_stderr_contains(r#""data-layout" claims architecture is little-endian"#); + rustc() + .input("foo.rs") + .target("mismatching-data-layout") + .crate_type("lib") + .run_fail() + .assert_stderr_contains("data-layout for target"); +} From e45d72dee0cd4bc56b9c8946678e09daf17c9cf3 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 4 Jul 2024 11:28:16 -0400 Subject: [PATCH 2/8] rewrite target-cpu-native to rmake --- tests/run-make/target-cpu-native/Makefile | 20 -------------------- tests/run-make/target-cpu-native/rmake.rs | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 20 deletions(-) delete mode 100644 tests/run-make/target-cpu-native/Makefile create mode 100644 tests/run-make/target-cpu-native/rmake.rs diff --git a/tests/run-make/target-cpu-native/Makefile b/tests/run-make/target-cpu-native/Makefile deleted file mode 100644 index eb3ca1e13aa62..0000000000000 --- a/tests/run-make/target-cpu-native/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -include ../tools.mk - -# only-linux -# only-x86_64 -# -# I *really* don't want to deal with a cross-platform way to compare file sizes, -# tests in `make` sort of are awful - -all: $(TMPDIR)/out.log - # Make sure no warnings about "unknown CPU `native`" were emitted - if [ "$$(wc -c $(TMPDIR)/out.log | cut -d' ' -f 1)" = "0" ]; then \ - echo no warnings generated; \ - else \ - exit 1; \ - fi - - -$(TMPDIR)/out.log: - $(RUSTC) foo.rs -C target-cpu=native 2>&1 | tee $(TMPDIR)/out.log - $(call RUN,foo) diff --git a/tests/run-make/target-cpu-native/rmake.rs b/tests/run-make/target-cpu-native/rmake.rs new file mode 100644 index 0000000000000..c5bd0245051a9 --- /dev/null +++ b/tests/run-make/target-cpu-native/rmake.rs @@ -0,0 +1,16 @@ +// target-cpu is a codegen flag that generates code for the processor of the host machine +// running the compilation. This test is a sanity test that this flag does not cause any +// warnings when used, and that binaries produced by it can also be successfully executed. +// See https://github.com/rust-lang/rust/pull/23238 + +// FIXME(Oneirical): only-linux only-x86_64 + +use run_make_support::{run, rustc}; + +fn main() { + let out = rustc().input("foo.rs").arg("-Ctarget-cpu=native").run().stderr_utf8(); + run("foo"); + // There should be zero warnings emitted - the bug would cause "unknown CPU `native`" + // to be printed out. + assert_eq!(out.len(), 0); +} From a4c72b627535c5ed9c58f1efbbe36491a820511a Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 11 Jun 2024 14:18:27 -0400 Subject: [PATCH 3/8] rewrite intrinsic-unreachable to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/intrinsic-unreachable/Makefile | 12 ------------ tests/run-make/intrinsic-unreachable/rmake.rs | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+), 13 deletions(-) delete mode 100644 tests/run-make/intrinsic-unreachable/Makefile create mode 100644 tests/run-make/intrinsic-unreachable/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 31cb32d349ace..1cc414ecdc68a 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -47,7 +47,6 @@ run-make/foreign-rust-exceptions/Makefile run-make/incr-add-rust-src-component/Makefile run-make/incr-foreign-head-span/Makefile run-make/interdependent-c-libraries/Makefile -run-make/intrinsic-unreachable/Makefile run-make/issue-107094/Makefile run-make/issue-109934-lto-debuginfo/Makefile run-make/issue-14698/Makefile diff --git a/tests/run-make/intrinsic-unreachable/Makefile b/tests/run-make/intrinsic-unreachable/Makefile deleted file mode 100644 index ff9cc57098c6b..0000000000000 --- a/tests/run-make/intrinsic-unreachable/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -include ../tools.mk - -# needs-asm-support -# ignore-windows-msvc -# -# Because of Windows exception handling, the code is not necessarily any shorter. -# https://github.com/llvm-mirror/llvm/commit/64b2297786f7fd6f5fa24cdd4db0298fbf211466 - -all: - $(RUSTC) -O --emit asm exit-ret.rs - $(RUSTC) -O --emit asm exit-unreachable.rs - test `wc -l < $(TMPDIR)/exit-unreachable.s` -lt `wc -l < $(TMPDIR)/exit-ret.s` diff --git a/tests/run-make/intrinsic-unreachable/rmake.rs b/tests/run-make/intrinsic-unreachable/rmake.rs new file mode 100644 index 0000000000000..6c951147604a1 --- /dev/null +++ b/tests/run-make/intrinsic-unreachable/rmake.rs @@ -0,0 +1,19 @@ +// intrinsics::unreachable tells the compiler that a certain point in the code +// is not reachable by any means, which enables some useful optimizations. +// In this test, exit-unreachable contains this instruction and exit-ret does not, +// which means the emitted artifacts should be shorter in length. +// See https://github.com/rust-lang/rust/pull/16970 + +//@ needs-asm-support +//@ ignore-windows-msvc +// Reason: Because of Windows exception handling, the code is not necessarily any shorter. + +use run_make_support::rustc; +use std::io::BufReader; +use std::fs::File; + +fn main() { + rustc().opt().emit("asm").input("exit-ret.rs").run(); + rustc().opt().emit("asm").input("exit-unreachable.rs").run(); + assert!(BufReader::new(File::open("exit-unreachable.s")).lines().count() < BufReader::new(File::open("exit-ret.s")).lines().count()); +} From 2dda1e31bead614a45e7f51c86dc14cf6a4ebe1c Mon Sep 17 00:00:00 2001 From: Oneirical Date: Wed, 12 Jun 2024 11:24:21 -0400 Subject: [PATCH 4/8] rewrite sepcomp-separate to rmake --- Cargo.lock | 1 + src/tools/run-make-support/src/fs_wrapper.rs | 27 ++++++++++++------- src/tools/run-make-support/src/lib.rs | 1 + .../tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/intrinsic-unreachable/rmake.rs | 13 +++++---- tests/run-make/sepcomp-separate/Makefile | 9 ------- tests/run-make/sepcomp-separate/rmake.rs | 24 +++++++++++++++++ 7 files changed, 51 insertions(+), 25 deletions(-) delete mode 100644 tests/run-make/sepcomp-separate/Makefile create mode 100644 tests/run-make/sepcomp-separate/rmake.rs diff --git a/Cargo.lock b/Cargo.lock index afeb9faec097e..05e5685270ef1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3421,6 +3421,7 @@ dependencies = [ "ar", "bstr", "gimli 0.28.1", + "glob", "object 0.34.0", "regex", "similar", diff --git a/src/tools/run-make-support/src/fs_wrapper.rs b/src/tools/run-make-support/src/fs_wrapper.rs index 8a2bfce8b4a72..d65c10b17c991 100644 --- a/src/tools/run-make-support/src/fs_wrapper.rs +++ b/src/tools/run-make-support/src/fs_wrapper.rs @@ -1,7 +1,7 @@ use std::fs; use std::path::Path; -/// A wrapper around [`std::fs::remove_file`] which includes the file path in the panic message.. +/// A wrapper around [`std::fs::remove_file`] which includes the file path in the panic message. #[track_caller] pub fn remove_file>(path: P) { fs::remove_file(path.as_ref()) @@ -18,21 +18,28 @@ pub fn copy, Q: AsRef>(from: P, to: Q) { )); } -/// A wrapper around [`std::fs::File::create`] which includes the file path in the panic message.. +/// A wrapper around [`std::fs::File::create`] which includes the file path in the panic message. #[track_caller] pub fn create_file>(path: P) { fs::File::create(path.as_ref()) .expect(&format!("the file in path \"{}\" could not be created", path.as_ref().display())); } -/// A wrapper around [`std::fs::read`] which includes the file path in the panic message.. +/// A wrapper around [`std::fs::File::open`] which includes the file path in the panic message. +#[track_caller] +pub fn open_file>(path: P) -> fs::File { + fs::File::open(path.as_ref()) + .expect(&format!("the file in path \"{}\" could not be opened", path.as_ref().display())) +} + +/// A wrapper around [`std::fs::read`] which includes the file path in the panic message. #[track_caller] pub fn read>(path: P) -> Vec { fs::read(path.as_ref()) .expect(&format!("the file in path \"{}\" could not be read", path.as_ref().display())) } -/// A wrapper around [`std::fs::read_to_string`] which includes the file path in the panic message.. +/// A wrapper around [`std::fs::read_to_string`] which includes the file path in the panic message. #[track_caller] pub fn read_to_string>(path: P) -> String { fs::read_to_string(path.as_ref()).expect(&format!( @@ -41,14 +48,14 @@ pub fn read_to_string>(path: P) -> String { )) } -/// A wrapper around [`std::fs::read_dir`] which includes the file path in the panic message.. +/// A wrapper around [`std::fs::read_dir`] which includes the file path in the panic message. #[track_caller] pub fn read_dir>(path: P) -> fs::ReadDir { fs::read_dir(path.as_ref()) .expect(&format!("the directory in path \"{}\" could not be read", path.as_ref().display())) } -/// A wrapper around [`std::fs::write`] which includes the file path in the panic message.. +/// A wrapper around [`std::fs::write`] which includes the file path in the panic message. #[track_caller] pub fn write, C: AsRef<[u8]>>(path: P, contents: C) { fs::write(path.as_ref(), contents.as_ref()).expect(&format!( @@ -57,7 +64,7 @@ pub fn write, C: AsRef<[u8]>>(path: P, contents: C) { )); } -/// A wrapper around [`std::fs::remove_dir_all`] which includes the file path in the panic message.. +/// A wrapper around [`std::fs::remove_dir_all`] which includes the file path in the panic message. #[track_caller] pub fn remove_dir_all>(path: P) { fs::remove_dir_all(path.as_ref()).expect(&format!( @@ -66,7 +73,7 @@ pub fn remove_dir_all>(path: P) { )); } -/// A wrapper around [`std::fs::create_dir`] which includes the file path in the panic message.. +/// A wrapper around [`std::fs::create_dir`] which includes the file path in the panic message. #[track_caller] pub fn create_dir>(path: P) { fs::create_dir(path.as_ref()).expect(&format!( @@ -75,7 +82,7 @@ pub fn create_dir>(path: P) { )); } -/// A wrapper around [`std::fs::create_dir_all`] which includes the file path in the panic message.. +/// A wrapper around [`std::fs::create_dir_all`] which includes the file path in the panic message. #[track_caller] pub fn create_dir_all>(path: P) { fs::create_dir_all(path.as_ref()).expect(&format!( @@ -84,7 +91,7 @@ pub fn create_dir_all>(path: P) { )); } -/// A wrapper around [`std::fs::metadata`] which includes the file path in the panic message.. +/// A wrapper around [`std::fs::metadata`] which includes the file path in the panic message. #[track_caller] pub fn metadata>(path: P) -> fs::Metadata { fs::metadata(path.as_ref()).expect(&format!( diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index f464a109e7711..068b022599e50 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -23,6 +23,7 @@ use std::path::{Path, PathBuf}; pub use bstr; pub use gimli; +pub use glob; pub use object; pub use regex; pub use wasmparser; diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 1cc414ecdc68a..233c2d0b808de 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -131,7 +131,6 @@ run-make/sanitizer-dylib-link/Makefile run-make/sanitizer-staticlib-link/Makefile run-make/sepcomp-cci-copies/Makefile run-make/sepcomp-inlining/Makefile -run-make/sepcomp-separate/Makefile run-make/share-generics-dylib/Makefile run-make/silly-file-names/Makefile run-make/simd-ffi/Makefile diff --git a/tests/run-make/intrinsic-unreachable/rmake.rs b/tests/run-make/intrinsic-unreachable/rmake.rs index 6c951147604a1..5e62a966c5476 100644 --- a/tests/run-make/intrinsic-unreachable/rmake.rs +++ b/tests/run-make/intrinsic-unreachable/rmake.rs @@ -5,15 +5,18 @@ // See https://github.com/rust-lang/rust/pull/16970 //@ needs-asm-support -//@ ignore-windows-msvc +//@ ignore-windows // Reason: Because of Windows exception handling, the code is not necessarily any shorter. -use run_make_support::rustc; -use std::io::BufReader; -use std::fs::File; +use run_make_support::{fs_wrapper, rustc}; +use std::io::{BufRead, BufReader}; fn main() { rustc().opt().emit("asm").input("exit-ret.rs").run(); rustc().opt().emit("asm").input("exit-unreachable.rs").run(); - assert!(BufReader::new(File::open("exit-unreachable.s")).lines().count() < BufReader::new(File::open("exit-ret.s")).lines().count()); + let unreachable_file = fs_wrapper::open_file("exit-unreachable.s"); + let ret_file = fs_wrapper::open_file("exit-ret.s"); + assert!( + BufReader::new(unreachable_file).lines().count() < BufReader::new(ret_file).lines().count() + ); } diff --git a/tests/run-make/sepcomp-separate/Makefile b/tests/run-make/sepcomp-separate/Makefile deleted file mode 100644 index 62cf54a88fbe9..0000000000000 --- a/tests/run-make/sepcomp-separate/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../tools.mk - -# Test that separate compilation actually puts code into separate compilation -# units. `foo.rs` defines `magic_fn` in three different modules, which should -# wind up in three different compilation units. - -all: - $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 - [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ .*magic_fn)" -eq "3" ] diff --git a/tests/run-make/sepcomp-separate/rmake.rs b/tests/run-make/sepcomp-separate/rmake.rs new file mode 100644 index 0000000000000..d3ef2450a847d --- /dev/null +++ b/tests/run-make/sepcomp-separate/rmake.rs @@ -0,0 +1,24 @@ +// Test that separate compilation actually puts code into separate compilation +// units. `foo.rs` defines `magic_fn` in three different modules, which should +// wind up in three different compilation units. +// See https://github.com/rust-lang/rust/pull/16367 + +use run_make_support::{fs_wrapper, glob, regex, rustc}; +use std::io::{BufRead, BufReader}; + +fn main() { + let mut match_count = 0; + rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).run(); + let re = regex::Regex::new(r#"define.*magic_fn"#).unwrap(); + let paths = glob::glob("foo.*.ll").unwrap(); + paths.filter_map(|entry| entry.ok()).filter(|path| path.is_file()).for_each(|path| { + let file = fs_wrapper::open_file(path); + let reader = BufReader::new(file); + reader + .lines() + .filter_map(|line| line.ok()) + .filter(|line| re.is_match(line)) + .for_each(|_| match_count += 1); + }); + assert_eq!(match_count, 3); +} From f04d0c68eeeb32f2bf7477806482551f2a308ae0 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 13 Jun 2024 15:02:08 -0400 Subject: [PATCH 5/8] rewrite sepcomp-inlining and -separate to rmake.rs --- Cargo.lock | 1 - src/tools/run-make-support/src/fs_wrapper.rs | 7 ------ src/tools/run-make-support/src/lib.rs | 15 +++++++++++- .../tidy/src/allowed_run_make_makefiles.txt | 2 -- tests/run-make/intrinsic-unreachable/rmake.rs | 6 ++--- tests/run-make/sepcomp-cci-copies/Makefile | 12 ---------- tests/run-make/sepcomp-cci-copies/rmake.rs | 17 ++++++++++++++ tests/run-make/sepcomp-inlining/Makefile | 15 ------------ tests/run-make/sepcomp-inlining/rmake.rs | 23 +++++++++++++++++++ tests/run-make/sepcomp-separate/rmake.rs | 21 +++++------------ 10 files changed, 62 insertions(+), 57 deletions(-) delete mode 100644 tests/run-make/sepcomp-cci-copies/Makefile create mode 100644 tests/run-make/sepcomp-cci-copies/rmake.rs delete mode 100644 tests/run-make/sepcomp-inlining/Makefile create mode 100644 tests/run-make/sepcomp-inlining/rmake.rs diff --git a/Cargo.lock b/Cargo.lock index 05e5685270ef1..afeb9faec097e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3421,7 +3421,6 @@ dependencies = [ "ar", "bstr", "gimli 0.28.1", - "glob", "object 0.34.0", "regex", "similar", diff --git a/src/tools/run-make-support/src/fs_wrapper.rs b/src/tools/run-make-support/src/fs_wrapper.rs index d65c10b17c991..0f0d6f6618ced 100644 --- a/src/tools/run-make-support/src/fs_wrapper.rs +++ b/src/tools/run-make-support/src/fs_wrapper.rs @@ -25,13 +25,6 @@ pub fn create_file>(path: P) { .expect(&format!("the file in path \"{}\" could not be created", path.as_ref().display())); } -/// A wrapper around [`std::fs::File::open`] which includes the file path in the panic message. -#[track_caller] -pub fn open_file>(path: P) -> fs::File { - fs::File::open(path.as_ref()) - .expect(&format!("the file in path \"{}\" could not be opened", path.as_ref().display())) -} - /// A wrapper around [`std::fs::read`] which includes the file path in the panic message. #[track_caller] pub fn read>(path: P) -> Vec { diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 068b022599e50..3fdf94804f16a 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -23,7 +23,6 @@ use std::path::{Path, PathBuf}; pub use bstr; pub use gimli; -pub use glob; pub use object; pub use regex; pub use wasmparser; @@ -304,6 +303,20 @@ pub fn filename_not_in_denylist, V: AsRef<[String]>>(path: P, exp .is_some_and(|name| !expected.contains(&name.to_str().unwrap().to_owned())) } +/// Gathers all files in the current working directory that have the extension `ext`, and counts +/// the number of lines within that contain a match with the regex pattern `re`. +pub fn count_regex_matches_in_files_with_extension(re: ®ex::Regex, ext: &str) -> usize { + let fetched_files = shallow_find_files(cwd(), |path| has_extension(path, ext)); + + let mut count = 0; + for file in fetched_files { + let content = fs_wrapper::read_to_string(file); + count += content.lines().filter(|line| re.is_match(&line)).count(); + } + + count +} + /// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is /// available on the platform! #[track_caller] diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 233c2d0b808de..184ef22317afe 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -129,8 +129,6 @@ run-make/rustc-macro-dep-files/Makefile run-make/sanitizer-cdylib-link/Makefile run-make/sanitizer-dylib-link/Makefile run-make/sanitizer-staticlib-link/Makefile -run-make/sepcomp-cci-copies/Makefile -run-make/sepcomp-inlining/Makefile run-make/share-generics-dylib/Makefile run-make/silly-file-names/Makefile run-make/simd-ffi/Makefile diff --git a/tests/run-make/intrinsic-unreachable/rmake.rs b/tests/run-make/intrinsic-unreachable/rmake.rs index 5e62a966c5476..7e78c8288b821 100644 --- a/tests/run-make/intrinsic-unreachable/rmake.rs +++ b/tests/run-make/intrinsic-unreachable/rmake.rs @@ -9,14 +9,12 @@ // Reason: Because of Windows exception handling, the code is not necessarily any shorter. use run_make_support::{fs_wrapper, rustc}; -use std::io::{BufRead, BufReader}; fn main() { rustc().opt().emit("asm").input("exit-ret.rs").run(); rustc().opt().emit("asm").input("exit-unreachable.rs").run(); - let unreachable_file = fs_wrapper::open_file("exit-unreachable.s"); - let ret_file = fs_wrapper::open_file("exit-ret.s"); assert!( - BufReader::new(unreachable_file).lines().count() < BufReader::new(ret_file).lines().count() + fs_wrapper::read_to_string("exit-unreachable.s").lines().count() + < fs_wrapper::read_to_string("exit-ret.s").lines().count() ); } diff --git a/tests/run-make/sepcomp-cci-copies/Makefile b/tests/run-make/sepcomp-cci-copies/Makefile deleted file mode 100644 index df289d0b0b1a2..0000000000000 --- a/tests/run-make/sepcomp-cci-copies/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -include ../tools.mk - -# Check that cross-crate inlined items are inlined in all compilation units -# that refer to them, and not in any other compilation units. -# Note that we have to pass `-C codegen-units=6` because up to two CGUs may be -# created for each source module (see `rustc_const_eval::monomorphize::partitioning`). - -all: - $(RUSTC) cci_lib.rs - $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=6 \ - -Z inline-in-all-cgus - [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ .*cci_fn)" -eq "2" ] diff --git a/tests/run-make/sepcomp-cci-copies/rmake.rs b/tests/run-make/sepcomp-cci-copies/rmake.rs new file mode 100644 index 0000000000000..612a73977feea --- /dev/null +++ b/tests/run-make/sepcomp-cci-copies/rmake.rs @@ -0,0 +1,17 @@ +// Check that cross-crate inlined items are inlined in all compilation units +// that refer to them, and not in any other compilation units. +// Note that we have to pass `-C codegen-units=6` because up to two CGUs may be +// created for each source module (see `rustc_const_eval::monomorphize::partitioning`). +// See https://github.com/rust-lang/rust/pull/16367 + +use run_make_support::{ + count_regex_matches_in_files_with_extension, cwd, fs_wrapper, has_extension, regex, rustc, + shallow_find_files, +}; + +fn main() { + rustc().input("cci_lib.rs").run(); + rustc().input("foo.rs").emit("llvm-ir").codegen_units(6).arg("-Zinline-in-all-cgus").run(); + let re = regex::Regex::new(r#"define\ .*cci_fn"#).unwrap(); + assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 2); +} diff --git a/tests/run-make/sepcomp-inlining/Makefile b/tests/run-make/sepcomp-inlining/Makefile deleted file mode 100644 index 327aeb75e5eda..0000000000000 --- a/tests/run-make/sepcomp-inlining/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -include ../tools.mk - -# Test that #[inline] functions still get inlined across compilation unit -# boundaries. Compilation should produce three IR files, but only the two -# compilation units that have a usage of the #[inline] function should -# contain a definition. Also, the non-#[inline] function should be defined -# in only one compilation unit. - -all: - $(RUSTC) foo.rs --emit=llvm-ir -C codegen-units=3 \ - -Z inline-in-all-cgus - [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ i32\ .*inlined)" -eq "0" ] - [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ internal\ i32\ .*inlined)" -eq "2" ] - [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c define\ hidden\ i32\ .*normal)" -eq "1" ] - [ "$$(cat "$(TMPDIR)"/foo.*.ll | grep -c declare\ hidden\ i32\ .*normal)" -eq "2" ] diff --git a/tests/run-make/sepcomp-inlining/rmake.rs b/tests/run-make/sepcomp-inlining/rmake.rs new file mode 100644 index 0000000000000..de7551b9a512d --- /dev/null +++ b/tests/run-make/sepcomp-inlining/rmake.rs @@ -0,0 +1,23 @@ +// Test that #[inline] functions still get inlined across compilation unit +// boundaries. Compilation should produce three IR files, but only the two +// compilation units that have a usage of the #[inline] function should +// contain a definition. Also, the non-#[inline] function should be defined +// in only one compilation unit. +// See https://github.com/rust-lang/rust/pull/16367 + +use run_make_support::{ + count_regex_matches_in_files_with_extension, cwd, fs_wrapper, has_extension, regex, rustc, + shallow_find_files, +}; + +fn main() { + rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).arg("-Zinline-in-all-cgus").run(); + let re = regex::Regex::new(r#"define\ i32\ .*inlined"#).unwrap(); + assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 0); + let re = regex::Regex::new(r#"define\ internal\ .*inlined"#).unwrap(); + assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 2); + let re = regex::Regex::new(r#"define\ hidden\ i32\ .*normal"#).unwrap(); + assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 1); + let re = regex::Regex::new(r#"declare\ hidden\ i32\ .*normal"#).unwrap(); + assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 2); +} diff --git a/tests/run-make/sepcomp-separate/rmake.rs b/tests/run-make/sepcomp-separate/rmake.rs index d3ef2450a847d..6f1d22424b5b9 100644 --- a/tests/run-make/sepcomp-separate/rmake.rs +++ b/tests/run-make/sepcomp-separate/rmake.rs @@ -3,22 +3,13 @@ // wind up in three different compilation units. // See https://github.com/rust-lang/rust/pull/16367 -use run_make_support::{fs_wrapper, glob, regex, rustc}; -use std::io::{BufRead, BufReader}; +use run_make_support::{ + count_regex_matches_in_files_with_extension, cwd, fs_wrapper, has_extension, regex, rustc, + shallow_find_files, +}; fn main() { - let mut match_count = 0; rustc().input("foo.rs").emit("llvm-ir").codegen_units(3).run(); - let re = regex::Regex::new(r#"define.*magic_fn"#).unwrap(); - let paths = glob::glob("foo.*.ll").unwrap(); - paths.filter_map(|entry| entry.ok()).filter(|path| path.is_file()).for_each(|path| { - let file = fs_wrapper::open_file(path); - let reader = BufReader::new(file); - reader - .lines() - .filter_map(|line| line.ok()) - .filter(|line| re.is_match(line)) - .for_each(|_| match_count += 1); - }); - assert_eq!(match_count, 3); + let re = regex::Regex::new(r#"define\ .*magic_fn"#).unwrap(); + assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 3); } From 0d85ef2857824bf6aa8727f418ee91587de04016 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Thu, 4 Jul 2024 11:37:16 -0400 Subject: [PATCH 6/8] rewrite target-without-atomic-cas to rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 3 --- tests/run-make/target-cpu-native/rmake.rs | 4 +--- tests/run-make/target-specs/rmake.rs | 2 +- .../run-make/target-without-atomic-cas/Makefile | 5 ----- .../run-make/target-without-atomic-cas/rmake.rs | 16 ++++++++++++++++ 5 files changed, 18 insertions(+), 12 deletions(-) delete mode 100644 tests/run-make/target-without-atomic-cas/Makefile create mode 100644 tests/run-make/target-without-atomic-cas/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 276d2d694cda0..686cc2f9c43e9 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -162,9 +162,6 @@ run-make/symbol-mangling-hashed/Makefile run-make/symbol-visibility/Makefile run-make/symbols-include-type-name/Makefile run-make/sysroot-crates-are-unstable/Makefile -run-make/target-cpu-native/Makefile -run-make/target-specs/Makefile -run-make/target-without-atomic-cas/Makefile run-make/test-benches/Makefile run-make/test-harness/Makefile run-make/thumb-none-cortex-m/Makefile diff --git a/tests/run-make/target-cpu-native/rmake.rs b/tests/run-make/target-cpu-native/rmake.rs index c5bd0245051a9..fd5fb6193fe06 100644 --- a/tests/run-make/target-cpu-native/rmake.rs +++ b/tests/run-make/target-cpu-native/rmake.rs @@ -3,8 +3,6 @@ // warnings when used, and that binaries produced by it can also be successfully executed. // See https://github.com/rust-lang/rust/pull/23238 -// FIXME(Oneirical): only-linux only-x86_64 - use run_make_support::{run, rustc}; fn main() { @@ -12,5 +10,5 @@ fn main() { run("foo"); // There should be zero warnings emitted - the bug would cause "unknown CPU `native`" // to be printed out. - assert_eq!(out.len(), 0); + assert!(out.is_empty()); } diff --git a/tests/run-make/target-specs/rmake.rs b/tests/run-make/target-specs/rmake.rs index 10c2fa298303d..d2b5f65083808 100644 --- a/tests/run-make/target-specs/rmake.rs +++ b/tests/run-make/target-specs/rmake.rs @@ -1,6 +1,6 @@ // Target-specific compilation in rustc used to have case-by-case peculiarities in 2014, // with the compiler having redundant target types and unspecific names. An overarching rework -// in #161156 changed the way the target flag functions, and this test attempts compilation +// in #16156 changed the way the target flag functions, and this test attempts compilation // with the target flag's bundle of new features to check that compilation either succeeds while // using them correctly, or fails with the right error message when using them improperly. // See https://github.com/rust-lang/rust/pull/16156 diff --git a/tests/run-make/target-without-atomic-cas/Makefile b/tests/run-make/target-without-atomic-cas/Makefile deleted file mode 100644 index 451f03d66cd23..0000000000000 --- a/tests/run-make/target-without-atomic-cas/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -include ../tools.mk - -# The target used below doesn't support atomic CAS operations. Verify that's the case -all: - $(RUSTC) --print cfg --target thumbv6m-none-eabi | $(CGREP) -v 'target_has_atomic="ptr"' diff --git a/tests/run-make/target-without-atomic-cas/rmake.rs b/tests/run-make/target-without-atomic-cas/rmake.rs new file mode 100644 index 0000000000000..c8782b6d1a566 --- /dev/null +++ b/tests/run-make/target-without-atomic-cas/rmake.rs @@ -0,0 +1,16 @@ +// ARM Cortex-M are a class of processors supported by the rust compiler. However, +// they cannot support any atomic features, such as Arc. This test simply prints +// the configuration details of one Cortex target, and checks that the compiler +// does not falsely list atomic support. +// See https://github.com/rust-lang/rust/pull/36874 + +use run_make_support::rustc; + +// The target used below doesn't support atomic CAS operations. Verify that's the case +fn main() { + rustc() + .print("cfg") + .target("thumbv6m-none-eabi") + .run() + .assert_stdout_not_contains(r#"target_has_atomic="ptr""#); +} From f4f678f27e84254cc89fd53ae20e467a254982de Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 7 Jul 2024 22:39:30 -0400 Subject: [PATCH 7/8] Infer async closure signature from old-style two-part Fn + Future bounds --- compiler/rustc_hir_typeck/src/closure.rs | 102 ++++++++++++++++-- ...signature-inference-from-two-part-bound.rs | 27 +++++ 2 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index ac7ed3e26f976..53cf121dfebcd 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -424,9 +424,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(trait_def_id) = trait_def_id { let found_kind = match closure_kind { hir::ClosureKind::Closure => self.tcx.fn_trait_kind_from_def_id(trait_def_id), - hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => { - self.tcx.async_fn_trait_kind_from_def_id(trait_def_id) - } + hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => self + .tcx + .async_fn_trait_kind_from_def_id(trait_def_id) + .or_else(|| self.tcx.fn_trait_kind_from_def_id(trait_def_id)), _ => None, }; @@ -470,14 +471,37 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // for closures and async closures, respectively. match closure_kind { hir::ClosureKind::Closure - if self.tcx.fn_trait_kind_from_def_id(trait_def_id).is_some() => {} + if self.tcx.fn_trait_kind_from_def_id(trait_def_id).is_some() => + { + self.extract_sig_from_projection(cause_span, projection) + } + hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) + if self.tcx.async_fn_trait_kind_from_def_id(trait_def_id).is_some() => + { + self.extract_sig_from_projection(cause_span, projection) + } + // It's possible we've passed the closure to a (somewhat out-of-fashion) + // `F: FnOnce() -> Fut, Fut: Future` style bound. Let's still + // guide inference here, since it's beneficial for the user. hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) - if self.tcx.async_fn_trait_kind_from_def_id(trait_def_id).is_some() => {} - _ => return None, + if self.tcx.fn_trait_kind_from_def_id(trait_def_id).is_some() => + { + self.extract_sig_from_projection_and_future_bound(cause_span, projection) + } + _ => None, } + } + + /// Given an `FnOnce::Output` or `AsyncFn::Output` projection, extract the args + /// and return type to infer a [`ty::PolyFnSig`] for the closure. + fn extract_sig_from_projection( + &self, + cause_span: Option, + projection: ty::PolyProjectionPredicate<'tcx>, + ) -> Option> { + let projection = self.resolve_vars_if_possible(projection); let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1); - let arg_param_ty = self.resolve_vars_if_possible(arg_param_ty); debug!(?arg_param_ty); let ty::Tuple(input_tys) = *arg_param_ty.kind() else { @@ -486,7 +510,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Since this is a return parameter type it is safe to unwrap. let ret_param_ty = projection.skip_binder().term.expect_type(); - let ret_param_ty = self.resolve_vars_if_possible(ret_param_ty); debug!(?ret_param_ty); let sig = projection.rebind(self.tcx.mk_fn_sig( @@ -500,6 +523,69 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(ExpectedSig { cause_span, sig }) } + /// When an async closure is passed to a function that has a "two-part" `Fn` + /// and `Future` trait bound, like: + /// + /// ```rust + /// use std::future::Future; + /// + /// fn not_exactly_an_async_closure(_f: F) + /// where + /// F: FnOnce(String, u32) -> Fut, + /// Fut: Future, + /// {} + /// ``` + /// + /// The we want to be able to extract the signature to guide inference in the async + /// closure. We will have two projection predicates registered in this case. First, + /// we identify the `FnOnce` bound, and if the output type is + /// an inference variable `?Fut`, we check if that is bounded by a `Future` + /// projection. + fn extract_sig_from_projection_and_future_bound( + &self, + cause_span: Option, + projection: ty::PolyProjectionPredicate<'tcx>, + ) -> Option> { + let projection = self.resolve_vars_if_possible(projection); + + let arg_param_ty = projection.skip_binder().projection_term.args.type_at(1); + debug!(?arg_param_ty); + + let ty::Tuple(input_tys) = *arg_param_ty.kind() else { + return None; + }; + + // If the return type is a type variable, look for bounds on it. + // We could theoretically support other kinds of return types here, + // but none of them would be useful, since async closures return + // concrete anonymous future types, and their futures are not coerced + // into any other type within the body of the async closure. + let ty::Infer(ty::TyVar(return_vid)) = *projection.skip_binder().term.expect_type().kind() + else { + return None; + }; + + // FIXME: We may want to elaborate here, though I assume this will be exceedingly rare. + for bound in self.obligations_for_self_ty(return_vid) { + if let Some(ret_projection) = bound.predicate.as_projection_clause() + && let Some(ret_projection) = ret_projection.no_bound_vars() + && self.tcx.is_lang_item(ret_projection.def_id(), LangItem::FutureOutput) + { + let sig = projection.rebind(self.tcx.mk_fn_sig( + input_tys, + ret_projection.term.expect_type(), + false, + hir::Safety::Safe, + Abi::Rust, + )); + + return Some(ExpectedSig { cause_span, sig }); + } + } + + None + } + fn sig_of_closure( &self, expr_def_id: LocalDefId, diff --git a/tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs b/tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs new file mode 100644 index 0000000000000..0e2d1ef12082b --- /dev/null +++ b/tests/ui/async-await/async-closures/signature-inference-from-two-part-bound.rs @@ -0,0 +1,27 @@ +//@ edition: 2021 +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +#![feature(async_closure)] + +use std::future::Future; +use std::any::Any; + +struct Struct; +impl Struct { + fn method(&self) {} +} + +fn fake_async_closure(_: F) +where + F: Fn(Struct) -> Fut, + Fut: Future, +{} + +fn main() { + fake_async_closure(async |s| { + s.method(); + }) +} From aa1c24a908fb7c37b9ed2998e240f06101050047 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 8 Jul 2024 20:18:21 +0200 Subject: [PATCH 8/8] Improve code of `run-make/llvm-ident` --- tests/run-make/llvm-ident/rmake.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/tests/run-make/llvm-ident/rmake.rs b/tests/run-make/llvm-ident/rmake.rs index 6934a4b36d013..9699d0579f6ef 100644 --- a/tests/run-make/llvm-ident/rmake.rs +++ b/tests/run-make/llvm-ident/rmake.rs @@ -2,9 +2,9 @@ //@ ignore-cross-compile use run_make_support::llvm::llvm_bin_dir; -use run_make_support::{cmd, env_var, llvm_filecheck, read_dir, rustc, source_root}; - -use std::ffi::OsStr; +use run_make_support::{ + cmd, env_var, has_extension, llvm_filecheck, rustc, shallow_find_files, source_root, +}; fn main() { // `-Ccodegen-units=16 -Copt-level=2` is used here to trigger thin LTO @@ -22,20 +22,14 @@ fn main() { // `llvm-dis` is used here since `--emit=llvm-ir` does not emit LLVM IR // for temporary outputs. - let mut files = Vec::new(); - read_dir(".", |path| { - if path.is_file() && path.extension().is_some_and(|ext| ext == OsStr::new("bc")) { - files.push(path.to_path_buf()); - } - }); + let files = shallow_find_files(".", |path| has_extension(path, "bc")); cmd(llvm_bin_dir().join("llvm-dis")).args(files).run(); // Check LLVM IR files (including temporary outputs) have `!llvm.ident` // named metadata, reusing the related codegen test. let llvm_ident_path = source_root().join("tests/codegen/llvm-ident.rs"); - read_dir(".", |path| { - if path.is_file() && path.extension().is_some_and(|ext| ext == OsStr::new("ll")) { - llvm_filecheck().input_file(path).arg(&llvm_ident_path).run(); - } - }); + let files = shallow_find_files(".", |path| has_extension(path, "ll")); + for file in files { + llvm_filecheck().input_file(file).arg(&llvm_ident_path).run(); + } }