mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Auto merge of #127489 - GuillaumeGomez:rollup-rhqfeom, r=GuillaumeGomez
Rollup of 4 pull requests Successful merges: - #126427 (Rewrite `intrinsic-unreachable`, `sepcomp-cci-copies`, `sepcomp-inlining` and `sepcomp-separate` `run-make` tests to rmake.rs) - #127237 (Improve code of `run-make/llvm-ident`) - #127325 (Migrate `target-cpu-native`, `target-specs` and `target-without-atomic-cas` `run-make` tests to rmake) - #127482 (Infer async closure signature from (old-style) two-part `Fn` + `Future` bounds) Failed merges: - #127357 (Remove `StructuredDiag`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
35b658fb10
@ -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() => {}
|
||||
_ => return None,
|
||||
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<Output = T>` style bound. Let's still
|
||||
// guide inference here, since it's beneficial for the user.
|
||||
hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async)
|
||||
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<Span>,
|
||||
projection: ty::PolyProjectionPredicate<'tcx>,
|
||||
) -> Option<ExpectedSig<'tcx>> {
|
||||
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, Fut>(_f: F)
|
||||
/// where
|
||||
/// F: FnOnce(String, u32) -> Fut,
|
||||
/// Fut: Future<Output = i32>,
|
||||
/// {}
|
||||
/// ```
|
||||
///
|
||||
/// 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<Args, Output = ?Fut>` bound, and if the output type is
|
||||
/// an inference variable `?Fut`, we check if that is bounded by a `Future<Output = Ty>`
|
||||
/// projection.
|
||||
fn extract_sig_from_projection_and_future_bound(
|
||||
&self,
|
||||
cause_span: Option<Span>,
|
||||
projection: ty::PolyProjectionPredicate<'tcx>,
|
||||
) -> Option<ExpectedSig<'tcx>> {
|
||||
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,
|
||||
|
@ -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<P: AsRef<Path>>(path: P) {
|
||||
fs::remove_file(path.as_ref())
|
||||
@ -18,21 +18,21 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(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<P: AsRef<Path>>(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::read`] which includes the file path in the panic message.
|
||||
#[track_caller]
|
||||
pub fn read<P: AsRef<Path>>(path: P) -> Vec<u8> {
|
||||
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<P: AsRef<Path>>(path: P) -> String {
|
||||
fs::read_to_string(path.as_ref()).expect(&format!(
|
||||
@ -41,14 +41,14 @@ pub fn read_to_string<P: AsRef<Path>>(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<P: AsRef<Path>>(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<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) {
|
||||
fs::write(path.as_ref(), contents.as_ref()).expect(&format!(
|
||||
@ -57,7 +57,7 @@ pub fn write<P: AsRef<Path>, 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<P: AsRef<Path>>(path: P) {
|
||||
fs::remove_dir_all(path.as_ref()).expect(&format!(
|
||||
@ -66,7 +66,7 @@ pub fn remove_dir_all<P: AsRef<Path>>(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<P: AsRef<Path>>(path: P) {
|
||||
fs::create_dir(path.as_ref()).expect(&format!(
|
||||
@ -75,7 +75,7 @@ pub fn create_dir<P: AsRef<Path>>(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<P: AsRef<Path>>(path: P) {
|
||||
fs::create_dir_all(path.as_ref()).expect(&format!(
|
||||
@ -84,7 +84,7 @@ pub fn create_dir_all<P: AsRef<Path>>(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<P: AsRef<Path>>(path: P) -> fs::Metadata {
|
||||
fs::metadata(path.as_ref()).expect(&format!(
|
||||
|
@ -303,6 +303,20 @@ pub fn filename_not_in_denylist<P: AsRef<Path>, 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]
|
||||
|
@ -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
|
||||
@ -130,9 +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/sepcomp-separate/Makefile
|
||||
run-make/share-generics-dylib/Makefile
|
||||
run-make/silly-file-names/Makefile
|
||||
run-make/simd-ffi/Makefile
|
||||
@ -147,9 +143,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/thumb-none-cortex-m/Makefile
|
||||
run-make/thumb-none-qemu/Makefile
|
||||
|
@ -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`
|
20
tests/run-make/intrinsic-unreachable/rmake.rs
Normal file
20
tests/run-make/intrinsic-unreachable/rmake.rs
Normal file
@ -0,0 +1,20 @@
|
||||
// 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
|
||||
// Reason: Because of Windows exception handling, the code is not necessarily any shorter.
|
||||
|
||||
use run_make_support::{fs_wrapper, rustc};
|
||||
|
||||
fn main() {
|
||||
rustc().opt().emit("asm").input("exit-ret.rs").run();
|
||||
rustc().opt().emit("asm").input("exit-unreachable.rs").run();
|
||||
assert!(
|
||||
fs_wrapper::read_to_string("exit-unreachable.s").lines().count()
|
||||
< fs_wrapper::read_to_string("exit-ret.s").lines().count()
|
||||
);
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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" ]
|
17
tests/run-make/sepcomp-cci-copies/rmake.rs
Normal file
17
tests/run-make/sepcomp-cci-copies/rmake.rs
Normal file
@ -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);
|
||||
}
|
@ -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" ]
|
23
tests/run-make/sepcomp-inlining/rmake.rs
Normal file
23
tests/run-make/sepcomp-inlining/rmake.rs
Normal file
@ -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);
|
||||
}
|
@ -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" ]
|
15
tests/run-make/sepcomp-separate/rmake.rs
Normal file
15
tests/run-make/sepcomp-separate/rmake.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// 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::{
|
||||
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).run();
|
||||
let re = regex::Regex::new(r#"define\ .*magic_fn"#).unwrap();
|
||||
assert_eq!(count_regex_matches_in_files_with_extension(&re, "ll"), 3);
|
||||
}
|
@ -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)
|
14
tests/run-make/target-cpu-native/rmake.rs
Normal file
14
tests/run-make/target-cpu-native/rmake.rs
Normal file
@ -0,0 +1,14 @@
|
||||
// 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
|
||||
|
||||
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!(out.is_empty());
|
||||
}
|
@ -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'
|
71
tests/run-make/target-specs/rmake.rs
Normal file
71
tests/run-make/target-specs/rmake.rs
Normal file
@ -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 #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
|
||||
|
||||
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");
|
||||
}
|
@ -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"'
|
16
tests/run-make/target-without-atomic-cas/rmake.rs
Normal file
16
tests/run-make/target-without-atomic-cas/rmake.rs
Normal file
@ -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""#);
|
||||
}
|
@ -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, Fut>(_: F)
|
||||
where
|
||||
F: Fn(Struct) -> Fut,
|
||||
Fut: Future<Output = ()>,
|
||||
{}
|
||||
|
||||
fn main() {
|
||||
fake_async_closure(async |s| {
|
||||
s.method();
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user