diff options
Diffstat (limited to 'tests')
81 files changed, 1128 insertions, 159 deletions
diff --git a/tests/codegen-llvm/autodiff/typetree.rs b/tests/codegen-llvm/autodiff/typetree.rs new file mode 100644 index 00000000000..1cb0c2fb68b --- /dev/null +++ b/tests/codegen-llvm/autodiff/typetree.rs @@ -0,0 +1,33 @@ +//@ compile-flags: -Zautodiff=Enable -C opt-level=3 -Clto=fat +//@ no-prefer-dynamic +//@ needs-enzyme + +// Test that basic autodiff still works with our TypeTree infrastructure +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +#[autodiff_reverse(d_simple, Duplicated, Active)] +#[no_mangle] +#[inline(never)] +fn simple(x: &f64) -> f64 { + 2.0 * x +} + +// CHECK-LABEL: @simple +// CHECK: fmul double + +// The derivative function should be generated normally +// CHECK-LABEL: diffesimple +// CHECK: fadd fast double + +fn main() { + let x = std::hint::black_box(3.0); + let output = simple(&x); + assert_eq!(6.0, output); + + let mut df_dx = 0.0; + let output_ = d_simple(&x, &mut df_dx, 1.0); + assert_eq!(output, output_); + assert_eq!(2.0, df_dx); +} diff --git a/tests/codegen-llvm/unwind-abis/c-unwind-abi-panic-abort.rs b/tests/codegen-llvm/unwind-abis/c-unwind-abi-panic-abort.rs index 8d2745ba2f7..2ce1d1b2e00 100644 --- a/tests/codegen-llvm/unwind-abis/c-unwind-abi-panic-abort.rs +++ b/tests/codegen-llvm/unwind-abis/c-unwind-abi-panic-abort.rs @@ -1,4 +1,9 @@ //@ compile-flags: -C panic=abort +//@ revisions: NONWASM WASM WASMEXN +//@ [NONWASM] ignore-wasm32 +//@ [WASM] only-wasm32 +//@ [WASMEXN] only-wasm32 +//@ [WASMEXN] compile-flags: -Ctarget-feature=+exception-handling // Test that `nounwind` attributes are also applied to extern `C-unwind` Rust functions // when the code is compiled with `panic=abort`. @@ -9,7 +14,9 @@ #[no_mangle] pub unsafe extern "C-unwind" fn rust_item_that_can_unwind() { // Handle both legacy and v0 symbol mangling. - // CHECK: call void @{{.*core9panicking19panic_cannot_unwind}} + // NONWASM: call void @{{.*core9panicking19panic_cannot_unwind}} + // WASMEXN: call void @{{.*core9panicking19panic_cannot_unwind}} + // WASM-NOT: call void @{{.*core9panicking19panic_cannot_unwind}} may_unwind(); } diff --git a/tests/codegen-llvm/unwind-and-panic-abort.rs b/tests/codegen-llvm/unwind-and-panic-abort.rs index 8efa140058a..c2838be00af 100644 --- a/tests/codegen-llvm/unwind-and-panic-abort.rs +++ b/tests/codegen-llvm/unwind-and-panic-abort.rs @@ -1,4 +1,9 @@ //@ compile-flags: -C panic=abort +//@ revisions: NONWASM WASM WASMEXN +//@ [NONWASM] ignore-wasm32 +//@ [WASM] only-wasm32 +//@ [WASMEXN] only-wasm32 +//@ [WASMEXN] compile-flags: -Ctarget-feature=+exception-handling #![crate_type = "lib"] @@ -9,7 +14,9 @@ extern "C-unwind" { // CHECK: Function Attrs:{{.*}}nounwind // CHECK-NEXT: define{{.*}}void @foo // Handle both legacy and v0 symbol mangling. -// CHECK: call void @{{.*core9panicking19panic_cannot_unwind}} +// NONWASM: call void @{{.*core9panicking19panic_cannot_unwind}} +// WASMEXN: call void @{{.*core9panicking19panic_cannot_unwind}} +// WASM-NOT: call void @{{.*core9panicking19panic_cannot_unwind}} #[no_mangle] pub unsafe extern "C" fn foo() { bar(); diff --git a/tests/codegen-llvm/wasm_exceptions.rs b/tests/codegen-llvm/wasm_exceptions.rs index 796b69b722b..e718f599a3c 100644 --- a/tests/codegen-llvm/wasm_exceptions.rs +++ b/tests/codegen-llvm/wasm_exceptions.rs @@ -1,8 +1,9 @@ //@ only-wasm32 -//@ compile-flags: -C panic=unwind -Z emscripten-wasm-eh +//@ revisions: WASM WASMEXN +//@ [WASMEXN] compile-flags: -C panic=unwind -Z emscripten-wasm-eh #![crate_type = "lib"] -#![feature(core_intrinsics, wasm_exception_handling_intrinsics)] +#![feature(core_intrinsics, wasm_exception_handling_intrinsics, link_llvm_intrinsics)] extern "C-unwind" { fn may_panic(); @@ -22,7 +23,8 @@ impl Drop for LogOnDrop { } } -// CHECK-LABEL: @test_cleanup() {{.*}} @__gxx_wasm_personality_v0 +// WASM-LABEL: @test_cleanup() {{.*}} +// WASMEXN-LABEL: @test_cleanup() {{.*}} @__gxx_wasm_personality_v0 #[no_mangle] pub fn test_cleanup() { let _log_on_drop = LogOnDrop; @@ -30,12 +32,16 @@ pub fn test_cleanup() { may_panic(); } - // CHECK-NOT: call - // CHECK: invoke void @may_panic() - // CHECK: %cleanuppad = cleanuppad within none [] + // WASMEXN-NOT: call + // WASMEXN: invoke void @may_panic() + // WASMEXN: %cleanuppad = cleanuppad within none [] + // + // WASM: call void @may_panic() + // WASM-NOT: invoke void @may_panic() } -// CHECK-LABEL: @test_rtry() {{.*}} @__gxx_wasm_personality_v0 +// WASM-LABEL: @test_rtry() {{.*}} +// WASMEXN-LABEL: @test_rtry() {{.*}} @__gxx_wasm_personality_v0 #[no_mangle] pub fn test_rtry() { unsafe { @@ -51,23 +57,40 @@ pub fn test_rtry() { ); } - // CHECK-NOT: call - // CHECK: invoke void @may_panic() - // CHECK: {{.*}} = catchswitch within none [label {{.*}}] unwind to caller - // CHECK: {{.*}} = catchpad within {{.*}} [ptr null] - // CHECK: catchret + // WASMEXN-NOT: call + // WASMEXN: invoke void @may_panic() + // WASMEXN: {{.*}} = catchswitch within none [label {{.*}}] unwind to caller + // WASMEXN: {{.*}} = catchpad within {{.*}} [ptr null] + // WASMEXN: catchret + + // WASM: call void @may_panic() + // WASM-NOT: invoke void @may_panic() + // WASM-NOT: catchswitch + // WASM-NOT: catchpad + // WASM-NOT: catchret } // Make sure the intrinsic is not inferred as nounwind. This is a regression test for #132416. -// CHECK-LABEL: @test_intrinsic() {{.*}} @__gxx_wasm_personality_v0 +// +// Note that this test uses the raw `wasm_throw` intrinsic because the one from +// libstd was built with `-Cpanic=abort` and it's technically not valid to use +// when this crate is compiled with `-Cpanic=unwind`. +// +// WASMEXN-LABEL: @test_intrinsic() {{.*}} @__gxx_wasm_personality_v0 #[no_mangle] +#[cfg(wasmexn)] pub fn test_intrinsic() { let _log_on_drop = LogOnDrop; + + unsafe extern "C-unwind" { + #[link_name = "llvm.wasm.throw"] + fn wasm_throw(tag: i32, ptr: *mut u8) -> !; + } unsafe { - core::arch::wasm32::throw::<0>(core::ptr::null_mut()); + wasm_throw(0, core::ptr::null_mut()); } - // CHECK-NOT: call - // CHECK: invoke void @llvm.wasm.throw(i32 noundef 0, ptr noundef null) - // CHECK: %cleanuppad = cleanuppad within none [] + // WASMEXN-NOT: call + // WASMEXN: invoke void @llvm.wasm.throw(i32 noundef 0, ptr noundef null) + // WASMEXN: %cleanuppad = cleanuppad within none [] } diff --git a/tests/crashes/120175.rs b/tests/crashes/120175.rs index e441454bed2..e06da5a8e0a 100644 --- a/tests/crashes/120175.rs +++ b/tests/crashes/120175.rs @@ -1,5 +1,6 @@ //@ known-bug: #120175 //@ needs-rustc-debug-assertions +//@ ignore-apple (raw-dylib doesn't work on Apple targets yet) #![feature(extern_types)] #![feature(raw_dylib_elf)] diff --git a/tests/crashes/125772.rs b/tests/crashes/125772.rs index 2965cfc9e7c..2b6cffd9463 100644 --- a/tests/crashes/125772.rs +++ b/tests/crashes/125772.rs @@ -1,5 +1,5 @@ //@ known-bug: rust-lang/rust#125772 -//@ only-x86_64 +//@ only-64bit #![feature(generic_const_exprs)] struct Outer<const A: i64, const B: i64>(); diff --git a/tests/crashes/129095.rs b/tests/crashes/129095.rs deleted file mode 100644 index b1bb74708c2..00000000000 --- a/tests/crashes/129095.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: rust-lang/rust#129095 -//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir - -#![feature(adt_const_params, unsized_const_params)] -#![allow(incomplete_features)] - -pub fn function_with_bytes<const BYTES: &'static [u8; 4]>() -> &'static [u8] { - BYTES -} - -pub fn main() { - assert_eq!(function_with_bytes::<b"AAAAA">(), &[0x41, 0x41, 0x41, 0x41]); -} diff --git a/tests/crashes/131292.rs b/tests/crashes/131292.rs index 01e0eca0bd6..05b93d06b05 100644 --- a/tests/crashes/131292.rs +++ b/tests/crashes/131292.rs @@ -1,5 +1,5 @@ //@ known-bug: #131292 -//@ only-x86_64 +//@ needs-asm-support use std::arch::asm; unsafe fn f6() { diff --git a/tests/crashes/134174.rs b/tests/crashes/134174.rs deleted file mode 100644 index 899cdc6faf3..00000000000 --- a/tests/crashes/134174.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ known-bug: #134175 -//@compile-flags: -Zvalidate-mir -Zinline-mir=yes -use std::vec::IntoIter; - -pub(crate) trait Foo: Iterator<Item = <Self as Foo>::Key> { - type Key; -} - -impl Foo for IntoIter<i16> {} - -fn sum_foo<F: Foo<Key = i32>>(f: F) -> i32 { - f.fold(0, |a, b| a + b) -} - -fn main() { - let x = sum_foo(vec![11, 10, 1].into_iter()); -} diff --git a/tests/crashes/134654.rs b/tests/crashes/134654.rs deleted file mode 100644 index f2323fe4ecd..00000000000 --- a/tests/crashes/134654.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #134654 -//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir -//@ only-x86_64 - -#![feature(adt_const_params, unsized_const_params)] -#![allow(incomplete_features)] - -fn function_with_bytes<const BYTES: - &'static [u8; 0xa9008fb6c9d81e42_0e25730562a601c8_u128]>() -> &'static [u8] { - BYTES -} - -fn main() { - function_with_bytes::<b"aa">() == &[]; -} diff --git a/tests/crashes/135570.rs b/tests/crashes/135570.rs deleted file mode 100644 index 7919ceb26d5..00000000000 --- a/tests/crashes/135570.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #135570 -//@compile-flags: -Zvalidate-mir -Zmir-enable-passes=+Inline -Copt-level=0 -Zmir-enable-passes=+GVN -//@ only-x86_64 - -#![feature(adt_const_params, unsized_const_params)] -#![allow(incomplete_features)] - -fn function_with_bytes<const BYTES: &'static [u8; 0xc7b889180b67b07d_bc1a3c88783d35b5_u128]>( -) -> &'static [u8] { - BYTES -} - -fn main() { - function_with_bytes::<b"aa">() == &[]; -} diff --git a/tests/crashes/136381.rs b/tests/crashes/136381.rs deleted file mode 100644 index 13ccc14a2c5..00000000000 --- a/tests/crashes/136381.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ known-bug: #136381 -//@ compile-flags: -Zvalidate-mir -Zmir-enable-passes=+GVN -#![feature(trait_upcasting)] - -trait A {} -trait B: A { - fn c(&self); -} -impl B for i32 { - fn c(self) { - todo!(); - } -} - -fn main() { - let baz: &dyn B = &1; - let bar: &dyn A = baz; -} diff --git a/tests/crashes/137190-1.rs b/tests/crashes/137190-1.rs deleted file mode 100644 index bdfe883b712..00000000000 --- a/tests/crashes/137190-1.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ known-bug: #137190 -//@ compile-flags: -Zmir-opt-level=2 -Zvalidate-mir -trait A { - fn b(&self); -} -trait C: A {} -impl C for () {} -fn main() { - (&() as &dyn C as &dyn A).b(); -} diff --git a/tests/crashes/137468.rs b/tests/crashes/137468.rs deleted file mode 100644 index cceb0502bd2..00000000000 --- a/tests/crashes/137468.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #137468 -//@ compile-flags: -Copt-level=0 -Zmir-enable-passes=+GVN -Zvalidate-mir -trait Supertrait<T> {} - -trait Identity { - type Selff; -} - -trait Trait<P>: Supertrait<()> + Supertrait<<P as Identity>::Selff> {} - -impl<P> Trait<P> for () {} - -fn main() { - let x: &dyn Trait<()> = &(); - let x: &dyn Supertrait<()> = x; -} diff --git a/tests/crashes/34127.rs b/tests/crashes/34127.rs index ea36b48ecba..26ebe722475 100644 --- a/tests/crashes/34127.rs +++ b/tests/crashes/34127.rs @@ -1,6 +1,6 @@ //@ compile-flags: -g -Copt-level=0 -Z verify-llvm-ir //@ known-bug: #34127 -//@ only-x86_64 +//@ only-64bit pub fn main() { let _a = [(); 1 << 63]; diff --git a/tests/run-make/autodiff/type-trees/array-typetree/array.check b/tests/run-make/autodiff/type-trees/array-typetree/array.check new file mode 100644 index 00000000000..0d38bdec17e --- /dev/null +++ b/tests/run-make/autodiff/type-trees/array-typetree/array.check @@ -0,0 +1,4 @@ +; Check that array TypeTree metadata is correctly generated +; Should show Float@double at each array element offset (0, 8, 16, 24, 32 bytes) + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@double}"{{.*}}@test_array{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,-1]:Float@double}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/array-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/array-typetree/rmake.rs new file mode 100644 index 00000000000..20b6a066906 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/array-typetree/rmake.rs @@ -0,0 +1,9 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + llvm_filecheck().patterns("array.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/array-typetree/test.rs b/tests/run-make/autodiff/type-trees/array-typetree/test.rs new file mode 100644 index 00000000000..f54ebf5a4c7 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/array-typetree/test.rs @@ -0,0 +1,15 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +#[autodiff_reverse(d_test, Duplicated, Active)] +#[no_mangle] +fn test_array(arr: &[f64; 5]) -> f64 { + arr[0] + arr[1] + arr[2] + arr[3] + arr[4] +} + +fn main() { + let arr = [1.0, 2.0, 3.0, 4.0, 5.0]; + let mut d_arr = [0.0; 5]; + let _result = d_test(&arr, &mut d_arr, 1.0); +} diff --git a/tests/run-make/autodiff/type-trees/memcpy-typetree/memcpy-ir.check b/tests/run-make/autodiff/type-trees/memcpy-typetree/memcpy-ir.check new file mode 100644 index 00000000000..0e6351ac4d3 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/memcpy-typetree/memcpy-ir.check @@ -0,0 +1,8 @@ +; Check that enzyme_type attributes are present in the LLVM IR function definition +; This verifies our TypeTree system correctly attaches metadata for Enzyme + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@double}"{{.*}}@test_memcpy({{.*}}"enzyme_type"="{[-1]:Pointer, [-1,-1]:Float@double}" + +; Check that llvm.memcpy exists (either call or declare) +CHECK: {{(call|declare).*}}@llvm.memcpy + diff --git a/tests/run-make/autodiff/type-trees/memcpy-typetree/memcpy.check b/tests/run-make/autodiff/type-trees/memcpy-typetree/memcpy.check new file mode 100644 index 00000000000..ae70830297a --- /dev/null +++ b/tests/run-make/autodiff/type-trees/memcpy-typetree/memcpy.check @@ -0,0 +1,13 @@ +CHECK: force_memcpy + +CHECK: @llvm.memcpy.p0.p0.i64 + +CHECK: test_memcpy - {[-1]:Float@double} |{[-1]:Pointer}:{} + +CHECK-DAG: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@double, [-1,8]:Float@double, [-1,16]:Float@double, [-1,24]:Float@double} + +CHECK-DAG: load double{{.*}}: {[-1]:Float@double} + +CHECK-DAG: fmul double{{.*}}: {[-1]:Float@double} + +CHECK-DAG: fadd double{{.*}}: {[-1]:Float@double} \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/memcpy-typetree/memcpy.rs b/tests/run-make/autodiff/type-trees/memcpy-typetree/memcpy.rs new file mode 100644 index 00000000000..3c1029190c8 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/memcpy-typetree/memcpy.rs @@ -0,0 +1,36 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; +use std::ptr; + +#[inline(never)] +fn force_memcpy(src: *const f64, dst: *mut f64, count: usize) { + unsafe { + ptr::copy_nonoverlapping(src, dst, count); + } +} + +#[autodiff_reverse(d_test_memcpy, Duplicated, Active)] +#[no_mangle] +fn test_memcpy(input: &[f64; 128]) -> f64 { + let mut local_data = [0.0f64; 128]; + + // Use a separate function to prevent inlining and optimization + force_memcpy(input.as_ptr(), local_data.as_mut_ptr(), 128); + + // Sum only first few elements to keep the computation simple + local_data[0] * local_data[0] + + local_data[1] * local_data[1] + + local_data[2] * local_data[2] + + local_data[3] * local_data[3] +} + +fn main() { + let input = [1.0; 128]; + let mut d_input = [0.0; 128]; + let result = test_memcpy(&input); + let result_d = d_test_memcpy(&input, &mut d_input, 1.0); + + assert_eq!(result, result_d); + println!("Memcpy test passed: result = {}", result); +} diff --git a/tests/run-make/autodiff/type-trees/memcpy-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/memcpy-typetree/rmake.rs new file mode 100644 index 00000000000..b4c650330fe --- /dev/null +++ b/tests/run-make/autodiff/type-trees/memcpy-typetree/rmake.rs @@ -0,0 +1,39 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + // First, compile to LLVM IR to check for enzyme_type attributes + let _ir_output = rustc() + .input("memcpy.rs") + .arg("-Zautodiff=Enable") + .arg("-Zautodiff=NoPostopt") + .opt_level("0") + .arg("--emit=llvm-ir") + .arg("-o") + .arg("main.ll") + .run(); + + // Then compile with TypeTree analysis output for the existing checks + let output = rustc() + .input("memcpy.rs") + .arg("-Zautodiff=Enable,PrintTAFn=test_memcpy") + .arg("-Zautodiff=NoPostopt") + .opt_level("3") + .arg("-Clto=fat") + .arg("-g") + .run(); + + let stdout = output.stdout_utf8(); + let stderr = output.stderr_utf8(); + let ir_content = rfs::read_to_string("main.ll"); + + rfs::write("memcpy.stdout", &stdout); + rfs::write("memcpy.stderr", &stderr); + rfs::write("main.ir", &ir_content); + + llvm_filecheck().patterns("memcpy.check").stdin_buf(stdout).run(); + + llvm_filecheck().patterns("memcpy-ir.check").stdin_buf(ir_content).run(); +} diff --git a/tests/run-make/autodiff/type-trees/mixed-struct-typetree/mixed.check b/tests/run-make/autodiff/type-trees/mixed-struct-typetree/mixed.check new file mode 100644 index 00000000000..584f5840843 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/mixed-struct-typetree/mixed.check @@ -0,0 +1,2 @@ +; Check that mixed struct with large array generates correct detailed type tree +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@float}"{{.*}}@test_mixed_struct{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Integer, [-1,8]:Float@float}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/mixed-struct-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/mixed-struct-typetree/rmake.rs new file mode 100644 index 00000000000..1c19963bc36 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/mixed-struct-typetree/rmake.rs @@ -0,0 +1,16 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + rustc() + .input("test.rs") + .arg("-Zautodiff=Enable") + .arg("-Zautodiff=NoPostopt") + .opt_level("0") + .emit("llvm-ir") + .run(); + + llvm_filecheck().patterns("mixed.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/mixed-struct-typetree/test.rs b/tests/run-make/autodiff/type-trees/mixed-struct-typetree/test.rs new file mode 100644 index 00000000000..7a734980e61 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/mixed-struct-typetree/test.rs @@ -0,0 +1,23 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +#[repr(C)] +struct Container { + header: i64, + data: [f32; 1000], +} + +#[autodiff_reverse(d_test, Duplicated, Active)] +#[no_mangle] +#[inline(never)] +fn test_mixed_struct(container: &Container) -> f32 { + container.data[0] + container.data[999] +} + +fn main() { + let container = Container { header: 42, data: [1.0; 1000] }; + let mut d_container = Container { header: 0, data: [0.0; 1000] }; + let result = d_test(&container, &mut d_container, 1.0); + std::hint::black_box(result); +} diff --git a/tests/run-make/autodiff/type-trees/nott-flag/nott.check b/tests/run-make/autodiff/type-trees/nott-flag/nott.check new file mode 100644 index 00000000000..8d23e2ee319 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/nott-flag/nott.check @@ -0,0 +1,5 @@ +// Check that enzyme_type attributes are NOT present when NoTT flag is used +// This verifies the NoTT flag correctly disables TypeTree metadata + +CHECK: define{{.*}}@square +CHECK-NOT: "enzyme_type" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/nott-flag/rmake.rs b/tests/run-make/autodiff/type-trees/nott-flag/rmake.rs new file mode 100644 index 00000000000..de540b990ca --- /dev/null +++ b/tests/run-make/autodiff/type-trees/nott-flag/rmake.rs @@ -0,0 +1,30 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + // Test with NoTT flag - should not generate TypeTree metadata + rustc() + .input("test.rs") + .arg("-Zautodiff=Enable,NoTT") + .emit("llvm-ir") + .arg("-o") + .arg("nott.ll") + .run(); + + // Test without NoTT flag - should generate TypeTree metadata + rustc() + .input("test.rs") + .arg("-Zautodiff=Enable") + .emit("llvm-ir") + .arg("-o") + .arg("with_tt.ll") + .run(); + + // Verify NoTT version does NOT have enzyme_type attributes + llvm_filecheck().patterns("nott.check").stdin_buf(rfs::read("nott.ll")).run(); + + // Verify TypeTree version DOES have enzyme_type attributes + llvm_filecheck().patterns("with_tt.check").stdin_buf(rfs::read("with_tt.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/nott-flag/test.rs b/tests/run-make/autodiff/type-trees/nott-flag/test.rs new file mode 100644 index 00000000000..de3549c37c6 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/nott-flag/test.rs @@ -0,0 +1,15 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +#[autodiff_reverse(d_square, Duplicated, Active)] +#[no_mangle] +fn square(x: &f64) -> f64 { + x * x +} + +fn main() { + let x = 2.0; + let mut dx = 0.0; + let _result = d_square(&x, &mut dx, 1.0); +} diff --git a/tests/run-make/autodiff/type-trees/nott-flag/with_tt.check b/tests/run-make/autodiff/type-trees/nott-flag/with_tt.check new file mode 100644 index 00000000000..0b4c9119179 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/nott-flag/with_tt.check @@ -0,0 +1,4 @@ +// Check that enzyme_type attributes are present when TypeTree is enabled +// This verifies our TypeTree metadata attachment is working + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@double}"{{.*}}@square{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@double}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/recursion-typetree/recursion.check b/tests/run-make/autodiff/type-trees/recursion-typetree/recursion.check new file mode 100644 index 00000000000..1960e7b816c --- /dev/null +++ b/tests/run-make/autodiff/type-trees/recursion-typetree/recursion.check @@ -0,0 +1,3 @@ +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@double}"{{.*}}@test_deep{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@double}" +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@double}"{{.*}}@test_graph{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Integer, [-1,8]:Integer, [-1,16]:Integer, [-1,24]:Float@double}" +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@double}"{{.*}}@test_node{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@double}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/recursion-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/recursion-typetree/rmake.rs new file mode 100644 index 00000000000..78718f3a215 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/recursion-typetree/rmake.rs @@ -0,0 +1,9 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + llvm_filecheck().patterns("recursion.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/recursion-typetree/test.rs b/tests/run-make/autodiff/type-trees/recursion-typetree/test.rs new file mode 100644 index 00000000000..9d40bec1bf1 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/recursion-typetree/test.rs @@ -0,0 +1,100 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +// Self-referential struct to test recursion detection +#[derive(Clone)] +struct Node { + value: f64, + next: Option<Box<Node>>, +} + +// Mutually recursive structs to test cycle detection +#[derive(Clone)] +struct GraphNodeA { + value: f64, + connections: Vec<GraphNodeB>, +} + +#[derive(Clone)] +struct GraphNodeB { + weight: f64, + target: Option<Box<GraphNodeA>>, +} + +#[autodiff_reverse(d_test_node, Duplicated, Active)] +#[no_mangle] +fn test_node(node: &Node) -> f64 { + node.value * 2.0 +} + +#[autodiff_reverse(d_test_graph, Duplicated, Active)] +#[no_mangle] +fn test_graph(a: &GraphNodeA) -> f64 { + a.value * 3.0 +} + +// Simple depth test - deeply nested but not circular +#[derive(Clone)] +struct Level1 { + val: f64, + next: Option<Box<Level2>>, +} +#[derive(Clone)] +struct Level2 { + val: f64, + next: Option<Box<Level3>>, +} +#[derive(Clone)] +struct Level3 { + val: f64, + next: Option<Box<Level4>>, +} +#[derive(Clone)] +struct Level4 { + val: f64, + next: Option<Box<Level5>>, +} +#[derive(Clone)] +struct Level5 { + val: f64, + next: Option<Box<Level6>>, +} +#[derive(Clone)] +struct Level6 { + val: f64, + next: Option<Box<Level7>>, +} +#[derive(Clone)] +struct Level7 { + val: f64, + next: Option<Box<Level8>>, +} +#[derive(Clone)] +struct Level8 { + val: f64, +} + +#[autodiff_reverse(d_test_deep, Duplicated, Active)] +#[no_mangle] +fn test_deep(deep: &Level1) -> f64 { + deep.val * 4.0 +} + +fn main() { + let node = Node { value: 1.0, next: None }; + + let graph = GraphNodeA { value: 2.0, connections: vec![] }; + + let deep = Level1 { val: 5.0, next: None }; + + let mut d_node = Node { value: 0.0, next: None }; + + let mut d_graph = GraphNodeA { value: 0.0, connections: vec![] }; + + let mut d_deep = Level1 { val: 0.0, next: None }; + + let _result1 = d_test_node(&node, &mut d_node, 1.0); + let _result2 = d_test_graph(&graph, &mut d_graph, 1.0); + let _result3 = d_test_deep(&deep, &mut d_deep, 1.0); +} diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/f128.check b/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/f128.check new file mode 100644 index 00000000000..23db64eea52 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/f128.check @@ -0,0 +1,4 @@ +; Check that f128 TypeTree metadata is correctly generated +; Should show Float@fp128 for f128 values and Pointer for references + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@fp128}"{{.*}}@test_f128{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@fp128}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/rmake.rs new file mode 100644 index 00000000000..44320ecdd57 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/rmake.rs @@ -0,0 +1,12 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + // Compile with TypeTree enabled and emit LLVM IR + rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + + // Check that f128 TypeTree metadata is correctly generated + llvm_filecheck().patterns("f128.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/test.rs b/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/test.rs new file mode 100644 index 00000000000..5c71baa3e69 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f128-typetree/test.rs @@ -0,0 +1,15 @@ +#![feature(autodiff, f128)] + +use std::autodiff::autodiff_reverse; + +#[autodiff_reverse(d_test, Duplicated, Active)] +#[no_mangle] +fn test_f128(x: &f128) -> f128 { + *x * *x +} + +fn main() { + let x = 2.0_f128; + let mut dx = 0.0_f128; + let _result = d_test(&x, &mut dx, 1.0); +} diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/f16.check b/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/f16.check new file mode 100644 index 00000000000..9adff68d36f --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/f16.check @@ -0,0 +1,4 @@ +; Check that f16 TypeTree metadata is correctly generated +; Should show Float@half for f16 values and Pointer for references + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@half}"{{.*}}@test_f16{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@half}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/rmake.rs new file mode 100644 index 00000000000..0aebdbf5520 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/rmake.rs @@ -0,0 +1,12 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + // Compile with TypeTree enabled and emit LLVM IR + rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + + // Check that f16 TypeTree metadata is correctly generated + llvm_filecheck().patterns("f16.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/test.rs b/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/test.rs new file mode 100644 index 00000000000..6b68e8252f4 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f16-typetree/test.rs @@ -0,0 +1,15 @@ +#![feature(autodiff, f16)] + +use std::autodiff::autodiff_reverse; + +#[autodiff_reverse(d_test, Duplicated, Active)] +#[no_mangle] +fn test_f16(x: &f16) -> f16 { + *x * *x +} + +fn main() { + let x = 2.0_f16; + let mut dx = 0.0_f16; + let _result = d_test(&x, &mut dx, 1.0); +} diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/f32.check b/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/f32.check new file mode 100644 index 00000000000..176630f57e8 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/f32.check @@ -0,0 +1,4 @@ +; Check that f32 TypeTree metadata is correctly generated +; Should show Float@float for f32 values and Pointer for references + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@float}"{{.*}}@test_f32{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@float}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/rmake.rs new file mode 100644 index 00000000000..ee3ab753bf5 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/rmake.rs @@ -0,0 +1,12 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + // Compile with TypeTree enabled and emit LLVM IR + rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + + // Check that f32 TypeTree metadata is correctly generated + llvm_filecheck().patterns("f32.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/test.rs b/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/test.rs new file mode 100644 index 00000000000..56c118399ee --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f32-typetree/test.rs @@ -0,0 +1,15 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +#[autodiff_reverse(d_test, Duplicated, Active)] +#[no_mangle] +fn test_f32(x: &f32) -> f32 { + x * x +} + +fn main() { + let x = 2.0_f32; + let mut dx = 0.0_f32; + let _result = d_test(&x, &mut dx, 1.0); +} diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/f64.check b/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/f64.check new file mode 100644 index 00000000000..929cd379694 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/f64.check @@ -0,0 +1,4 @@ +; Check that f64 TypeTree metadata is correctly generated +; Should show Float@double for f64 values and Pointer for references + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@double}"{{.*}}@test_f64{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@double}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/rmake.rs new file mode 100644 index 00000000000..5fac9b23bc8 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/rmake.rs @@ -0,0 +1,12 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + // Compile with TypeTree enabled and emit LLVM IR + rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + + // Check that f64 TypeTree metadata is correctly generated + llvm_filecheck().patterns("f64.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/test.rs b/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/test.rs new file mode 100644 index 00000000000..235360b76b2 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/f64-typetree/test.rs @@ -0,0 +1,15 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +#[autodiff_reverse(d_test, Duplicated, Active)] +#[no_mangle] +fn test_f64(x: &f64) -> f64 { + x * x +} + +fn main() { + let x = 2.0_f64; + let mut dx = 0.0_f64; + let _result = d_test(&x, &mut dx, 1.0); +} diff --git a/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/i32.check b/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/i32.check new file mode 100644 index 00000000000..dee4aa5bbb6 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/i32.check @@ -0,0 +1,4 @@ +; Check that i32 TypeTree metadata is correctly generated +; Should show Integer for i32 values and Pointer for references + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Integer}"{{.*}}@test_i32{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Integer}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/rmake.rs new file mode 100644 index 00000000000..a40fd55d88a --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/rmake.rs @@ -0,0 +1,12 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + // Compile with TypeTree enabled and emit LLVM IR + rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + + // Check that i32 TypeTree metadata is correctly generated + llvm_filecheck().patterns("i32.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/test.rs b/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/test.rs new file mode 100644 index 00000000000..249803c5d9f --- /dev/null +++ b/tests/run-make/autodiff/type-trees/scalar-types/i32-typetree/test.rs @@ -0,0 +1,15 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +#[autodiff_reverse(d_test, Duplicated, Active)] +#[no_mangle] +fn test_i32(x: &i32) -> i32 { + x * x +} + +fn main() { + let x = 5_i32; + let mut dx = 0_i32; + let _result = d_test(&x, &mut dx, 1); +} diff --git a/tests/run-make/autodiff/type-trees/slice-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/slice-typetree/rmake.rs new file mode 100644 index 00000000000..b81fb50bf1a --- /dev/null +++ b/tests/run-make/autodiff/type-trees/slice-typetree/rmake.rs @@ -0,0 +1,9 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + llvm_filecheck().patterns("slice.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/slice-typetree/slice.check b/tests/run-make/autodiff/type-trees/slice-typetree/slice.check new file mode 100644 index 00000000000..6543b616115 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/slice-typetree/slice.check @@ -0,0 +1,4 @@ +; Check that slice TypeTree metadata is correctly generated +; Should show Float@double for slice elements + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@double}"{{.*}}@test_slice{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,-1]:Float@double}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/slice-typetree/test.rs b/tests/run-make/autodiff/type-trees/slice-typetree/test.rs new file mode 100644 index 00000000000..7117fa3844f --- /dev/null +++ b/tests/run-make/autodiff/type-trees/slice-typetree/test.rs @@ -0,0 +1,16 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +#[autodiff_reverse(d_test, Duplicated, Active)] +#[no_mangle] +fn test_slice(slice: &[f64]) -> f64 { + slice.iter().sum() +} + +fn main() { + let arr = [1.0, 2.0, 3.0, 4.0, 5.0]; + let slice = &arr[..]; + let mut d_slice = [0.0; 5]; + let _result = d_test(slice, &mut d_slice[..], 1.0); +} diff --git a/tests/run-make/autodiff/type-trees/struct-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/struct-typetree/rmake.rs new file mode 100644 index 00000000000..0af1b65ee18 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/struct-typetree/rmake.rs @@ -0,0 +1,9 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + llvm_filecheck().patterns("struct.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/struct-typetree/struct.check b/tests/run-make/autodiff/type-trees/struct-typetree/struct.check new file mode 100644 index 00000000000..54956317e1e --- /dev/null +++ b/tests/run-make/autodiff/type-trees/struct-typetree/struct.check @@ -0,0 +1,4 @@ +; Check that struct TypeTree metadata is correctly generated +; Should show Float@double at offsets 0, 8, 16 for Point struct fields + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@double}"{{.*}}@test_struct{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@double, [-1,8]:Float@double, [-1,16]:Float@double}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/struct-typetree/test.rs b/tests/run-make/autodiff/type-trees/struct-typetree/test.rs new file mode 100644 index 00000000000..cbe7b10e409 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/struct-typetree/test.rs @@ -0,0 +1,22 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +#[repr(C)] +struct Point { + x: f64, + y: f64, + z: f64, +} + +#[autodiff_reverse(d_test, Duplicated, Active)] +#[no_mangle] +fn test_struct(point: &Point) -> f64 { + point.x + point.y * 2.0 + point.z * 3.0 +} + +fn main() { + let point = Point { x: 1.0, y: 2.0, z: 3.0 }; + let mut d_point = Point { x: 0.0, y: 0.0, z: 0.0 }; + let _result = d_test(&point, &mut d_point, 1.0); +} diff --git a/tests/run-make/autodiff/type-trees/tuple-typetree/rmake.rs b/tests/run-make/autodiff/type-trees/tuple-typetree/rmake.rs new file mode 100644 index 00000000000..76913828901 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/tuple-typetree/rmake.rs @@ -0,0 +1,9 @@ +//@ needs-enzyme +//@ ignore-cross-compile + +use run_make_support::{llvm_filecheck, rfs, rustc}; + +fn main() { + rustc().input("test.rs").arg("-Zautodiff=Enable").emit("llvm-ir").run(); + llvm_filecheck().patterns("tuple.check").stdin_buf(rfs::read("test.ll")).run(); +} diff --git a/tests/run-make/autodiff/type-trees/tuple-typetree/test.rs b/tests/run-make/autodiff/type-trees/tuple-typetree/test.rs new file mode 100644 index 00000000000..32187b587a3 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/tuple-typetree/test.rs @@ -0,0 +1,15 @@ +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +#[autodiff_reverse(d_test, Duplicated, Active)] +#[no_mangle] +fn test_tuple(tuple: &(f64, f64, f64)) -> f64 { + tuple.0 + tuple.1 * 2.0 + tuple.2 * 3.0 +} + +fn main() { + let tuple = (1.0, 2.0, 3.0); + let mut d_tuple = (0.0, 0.0, 0.0); + let _result = d_test(&tuple, &mut d_tuple, 1.0); +} diff --git a/tests/run-make/autodiff/type-trees/tuple-typetree/tuple.check b/tests/run-make/autodiff/type-trees/tuple-typetree/tuple.check new file mode 100644 index 00000000000..47647e78cc3 --- /dev/null +++ b/tests/run-make/autodiff/type-trees/tuple-typetree/tuple.check @@ -0,0 +1,4 @@ +; Check that tuple TypeTree metadata is correctly generated +; Should show Float@double at offsets 0, 8, 16 for (f64, f64, f64) + +CHECK: define{{.*}}"enzyme_type"="{[-1]:Float@double}"{{.*}}@test_tuple{{.*}}"enzyme_type"="{[-1]:Pointer, [-1,0]:Float@double, [-1,8]:Float@double, [-1,16]:Float@double}" \ No newline at end of file diff --git a/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check b/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check index dcf9508b69d..cdb70eb83fc 100644 --- a/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check +++ b/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check @@ -1,7 +1,7 @@ // CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{} // CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer} // CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 8, !dbg !{{[0-9]+}}: {[-1]:Pointer} -// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !102, !noundef !{{[0-9]+}}: {} +// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !{{[0-9]+}}, !noundef !{{[0-9]+}}: {} // CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 16, !dbg !{{[0-9]+}}: {[-1]:Pointer} // CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {} // CHECK-DAG: %{{[0-9]+}} = icmp eq i64 %{{[0-9]+}}, 0, !dbg !{{[0-9]+}}: {[-1]:Integer} diff --git a/tests/run-make/split-debuginfo/rmake.rs b/tests/run-make/split-debuginfo/rmake.rs index e8de5aed172..e53b7101078 100644 --- a/tests/run-make/split-debuginfo/rmake.rs +++ b/tests/run-make/split-debuginfo/rmake.rs @@ -188,6 +188,25 @@ enum UnstableOptions { } #[track_caller] +fn dwo_out_filenames(dwo_out: Option<&str>) -> BTreeSet<String> { + let dwo_out = if let Some(d) = dwo_out { + d + } else { + return BTreeSet::new(); + }; + let files = shallow_find_files(dwo_out, |path| { + // Fiilter out source files + !has_extension(path, "rs") + }); + files + .iter() + .map(|p| { + format!("{}/{}", dwo_out, p.file_name().unwrap().to_os_string().into_string().unwrap()) + }) + .collect() +} + +#[track_caller] fn cwd_filenames() -> BTreeSet<String> { let files = shallow_find_files(cwd(), |path| { // Fiilter out source files @@ -197,6 +216,17 @@ fn cwd_filenames() -> BTreeSet<String> { } #[track_caller] +fn dwo_out_dwo_filenames(dwo_out: &str) -> BTreeSet<String> { + let files = shallow_find_files(dwo_out, |p| has_extension(p, "dwo")); + files + .iter() + .map(|p| { + format!("{}/{}", dwo_out, p.file_name().unwrap().to_os_string().into_string().unwrap()) + }) + .collect() +} + +#[track_caller] fn cwd_dwo_filenames() -> BTreeSet<String> { let files = shallow_find_files(cwd(), |path| has_extension(path, "dwo")); files.iter().map(|p| p.file_name().unwrap().to_os_string().into_string().unwrap()).collect() @@ -376,17 +406,19 @@ mod shared_linux_other_tests { lto: LinkerPluginLto, remap_path_prefix: RemapPathPrefix, remap_path_scope: RemapPathScope, + split_dwarf_output_directory: Option<&str>, ) { run_in_tmpdir(|| { println!( - "checking: unstable_options={:?} + split_kind={:?} + level={:?} + split_dwarf_kind={:?} + lto={:?} + remap_path_prefix={:?} + remap_path_scope={:?}", + "checking: unstable_options={:?} + split_kind={:?} + level={:?} + split_dwarf_kind={:?} + lto={:?} + remap_path_prefix={:?} + remap_path_scope={:?} + split_dwarf_out_dir={:?}", unstable_options, split_kind, level, split_dwarf_kind, lto, remap_path_prefix, - remap_path_scope + remap_path_scope, + split_dwarf_output_directory, ); match cross_crate_test { @@ -398,6 +430,7 @@ mod shared_linux_other_tests { lto, remap_path_prefix, remap_path_scope, + split_dwarf_output_directory, ), CrossCrateTest::No => simple_split_debuginfo( unstable_options, @@ -407,6 +440,7 @@ mod shared_linux_other_tests { lto, remap_path_prefix, remap_path_scope, + split_dwarf_output_directory, ), } }); @@ -420,7 +454,11 @@ mod shared_linux_other_tests { lto: LinkerPluginLto, remap_path_prefix: RemapPathPrefix, remap_path_scope: RemapPathScope, + split_dwarf_output_directory: Option<&str>, ) { + if let Some(dwo_out) = split_dwarf_output_directory { + run_make_support::rfs::create_dir(dwo_out); + } match (split_kind, level, split_dwarf_kind, lto, remap_path_prefix, remap_path_scope) { // packed-crosscrate-split // - Debuginfo in `.dwo` files @@ -531,13 +569,19 @@ mod shared_linux_other_tests { .input("bar.rs") .crate_type("lib") .split_debuginfo(split_kind.cli_value()) + .split_dwarf_out_dir(split_dwarf_output_directory) .debuginfo(level.cli_value()) .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) .run(); - let bar_found_files = cwd_filenames(); + let mut bar_found_files = cwd_filenames(); + bar_found_files.append(&mut dwo_out_filenames(split_dwarf_output_directory)); - let bar_dwo_files = cwd_dwo_filenames(); + let bar_dwo_files = if let Some(dwo_out) = split_dwarf_output_directory { + dwo_out_dwo_filenames(dwo_out) + } else { + cwd_dwo_filenames() + }; assert_eq!(bar_dwo_files.len(), 1); let mut bar_expected_files = BTreeSet::new(); @@ -553,13 +597,19 @@ mod shared_linux_other_tests { .extern_("bar", "libbar.rlib") .input("main.rs") .split_debuginfo(split_kind.cli_value()) + .split_dwarf_out_dir(split_dwarf_output_directory) .debuginfo(level.cli_value()) .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) .run(); - let overall_found_files = cwd_filenames(); + let mut overall_found_files = cwd_filenames(); + overall_found_files.append(&mut dwo_out_filenames(split_dwarf_output_directory)); - let overall_dwo_files = cwd_dwo_filenames(); + let overall_dwo_files = if let Some(dwo_out) = split_dwarf_output_directory { + dwo_out_dwo_filenames(dwo_out) + } else { + cwd_dwo_filenames() + }; assert_eq!(overall_dwo_files.len(), 2); let mut overall_expected_files = BTreeSet::new(); @@ -648,7 +698,11 @@ mod shared_linux_other_tests { lto: LinkerPluginLto, remap_path_prefix: RemapPathPrefix, remap_path_scope: RemapPathScope, + split_dwarf_output_directory: Option<&str>, ) { + if let Some(dwo_out) = split_dwarf_output_directory { + run_make_support::rfs::create_dir(dwo_out); + } match (split_kind, level, split_dwarf_kind, lto, remap_path_prefix, remap_path_scope) { // off (unspecified): // - Debuginfo in `.o` files @@ -921,14 +975,19 @@ mod shared_linux_other_tests { rustc(unstable_options) .input("foo.rs") .split_debuginfo(split_kind.cli_value()) + .split_dwarf_out_dir(split_dwarf_output_directory) .debuginfo(level.cli_value()) .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) .run(); - let found_files = cwd_filenames(); - - let dwo_files = cwd_dwo_filenames(); + let mut found_files = cwd_filenames(); + found_files.append(&mut dwo_out_filenames(split_dwarf_output_directory)); + + let dwo_files = if let Some(dwo_dir) = split_dwarf_output_directory { + dwo_out_dwo_filenames(dwo_dir) + } else { + cwd_dwo_filenames() + }; assert_eq!(dwo_files.len(), 1); - let mut expected_files = BTreeSet::new(); expected_files.extend(dwo_files); expected_files.insert("foo".to_string()); @@ -1056,14 +1115,20 @@ mod shared_linux_other_tests { rustc(unstable_options) .input("foo.rs") .split_debuginfo(split_kind.cli_value()) + .split_dwarf_out_dir(split_dwarf_output_directory) .debuginfo(level.cli_value()) .arg(format!("-Zsplit-dwarf-kind={}", split_dwarf_kind.cli_value())) .remap_path_prefix(cwd(), remapped_prefix) .run(); - let found_files = cwd_filenames(); + let mut found_files = cwd_filenames(); + found_files.append(&mut dwo_out_filenames(split_dwarf_output_directory)); - let dwo_files = cwd_dwo_filenames(); + let dwo_files = if let Some(dwo_out) = split_dwarf_output_directory { + dwo_out_dwo_filenames(dwo_out) + } else { + cwd_dwo_filenames() + }; assert_eq!(dwo_files.len(), 1); let mut expected_files = BTreeSet::new(); @@ -1358,6 +1423,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // off @@ -1370,6 +1436,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // packed-split @@ -1382,6 +1449,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // packed-single @@ -1394,6 +1462,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // packed-lto-split @@ -1406,6 +1475,7 @@ fn main() { LinkerPluginLto::Yes, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // packed-lto-single @@ -1418,6 +1488,7 @@ fn main() { LinkerPluginLto::Yes, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // FIXME: the remapping tests probably need to be reworked, see @@ -1433,6 +1504,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, RemapPathScope::Unspecified, + None, ); // packed-remapped-single @@ -1445,6 +1517,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, RemapPathScope::Unspecified, + None, ); // packed-remapped-scope @@ -1457,6 +1530,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, RemapPathScope::Yes("debuginfo"), + None, ); // packed-remapped-wrong-scope @@ -1469,6 +1543,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, RemapPathScope::Yes("macro"), + None, ); // packed-crosscrate-split @@ -1481,6 +1556,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // packed-crosscrate-single @@ -1493,6 +1569,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // unpacked-split @@ -1505,6 +1582,20 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, + ); + + // unpacked-split with split-dwarf-out-dir + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + UnstableOptions::Yes, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + Some("other-dir"), ); // unpacked-single @@ -1517,6 +1608,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // unpacked-lto-split @@ -1529,6 +1621,7 @@ fn main() { LinkerPluginLto::Yes, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // unpacked-lto-single @@ -1541,6 +1634,7 @@ fn main() { LinkerPluginLto::Yes, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); // unpacked-remapped-split @@ -1553,6 +1647,20 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, RemapPathScope::Unspecified, + None, + ); + + // unpacked-remapped-split with split-dwarf-out-dir + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::No, + UnstableOptions::Yes, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, + RemapPathScope::Unspecified, + Some("other-dir"), ); // unpacked-remapped-single @@ -1565,6 +1673,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, RemapPathScope::Unspecified, + None, ); // unpacked-remapped-scope @@ -1577,6 +1686,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, RemapPathScope::Yes("debuginfo"), + None, ); // unpacked-remapped-wrong-scope @@ -1589,6 +1699,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Yes { remapped_prefix: "/__MY_REMAPPED_PATH__" }, RemapPathScope::Yes("macro"), + None, ); // unpacked-crosscrate-split @@ -1601,6 +1712,20 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, + ); + + // unpacked-crosscrate-split with split-dwarf-out-dir + shared_linux_other_tests::split_debuginfo( + CrossCrateTest::Yes, + UnstableOptions::Yes, + SplitDebuginfo::Unpacked, + DebuginfoLevel::Full, + SplitDwarfKind::Split, + LinkerPluginLto::Unspecified, + RemapPathPrefix::Unspecified, + RemapPathScope::Unspecified, + Some("other-dir"), ); // unpacked-crosscrate-single @@ -1613,6 +1738,7 @@ fn main() { LinkerPluginLto::Unspecified, RemapPathPrefix::Unspecified, RemapPathScope::Unspecified, + None, ); } } diff --git a/tests/rustdoc-ui/issues/issue-91713.stdout b/tests/rustdoc-ui/issues/issue-91713.stdout index 30aadfe89f4..d34714be6c9 100644 --- a/tests/rustdoc-ui/issues/issue-91713.stdout +++ b/tests/rustdoc-ui/issues/issue-91713.stdout @@ -1,11 +1,11 @@ Available passes for running rustdoc: check-doc-cfg - checks `#[doc(cfg(...))]` for stability feature and unexpected cfgs check_doc_test_visibility - run various visibility-related lints on doctests + propagate-doc-cfg - propagates `#[doc(cfg(...))]` to child items strip-aliased-non-local - strips all non-local private aliased items from the output strip-hidden - strips all `#[doc(hidden)]` items from the output strip-private - strips all private items from a crate which cannot be seen externally, implies strip-priv-imports strip-priv-imports - strips all private import statements (`use`, `extern crate`) from a crate - propagate-doc-cfg - propagates `#[doc(cfg(...))]` to child items propagate-stability - propagates stability to child items collect-intra-doc-links - resolves intra-doc links collect-trait-impls - retrieves trait impls for items in the crate @@ -16,11 +16,11 @@ Default passes for rustdoc: collect-trait-impls check_doc_test_visibility check-doc-cfg +collect-intra-doc-links strip-aliased-non-local strip-hidden (when not --document-hidden-items) strip-private (when not --document-private-items) strip-priv-imports (when --document-private-items) -collect-intra-doc-links propagate-doc-cfg propagate-stability run-lints diff --git a/tests/rustdoc/doc-auto-cfg-public-in-private.rs b/tests/rustdoc/doc-auto-cfg-public-in-private.rs new file mode 100644 index 00000000000..b78e3f1b932 --- /dev/null +++ b/tests/rustdoc/doc-auto-cfg-public-in-private.rs @@ -0,0 +1,16 @@ +// This test ensures that even though private items are removed from generated docs, +// their `cfg`s will still impact their child items. + +#![feature(doc_cfg)] +#![crate_name = "foo"] + +pub struct X; + +#[cfg(not(feature = "blob"))] +fn foo() { + impl X { + //@ has 'foo/struct.X.html' + //@ has - '//*[@class="stab portability"]' 'Available on non-crate feature blob only.' + pub fn bar() {} + } +} diff --git a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs index 8449479287f..48f328f4fad 100644 --- a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs +++ b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs @@ -33,6 +33,10 @@ impl CodegenBackend for TheBackend { "" } + fn name(&self) -> &'static str { + "the-backend" + } + fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box<dyn Any> { Box::new(CodegenResults { modules: vec![], diff --git a/tests/ui/attributes/empty-repr.stderr b/tests/ui/attributes/empty-repr.stderr index 92901fa170c..6dfa2df75b7 100644 --- a/tests/ui/attributes/empty-repr.stderr +++ b/tests/ui/attributes/empty-repr.stderr @@ -4,6 +4,7 @@ error: unused attribute LL | #[repr()] | ^^^^^^^^^ help: remove this attribute | + = note: using `repr` with an empty list has no effect note: the lint level is defined here --> $DIR/empty-repr.rs:4:9 | diff --git a/tests/ui/autodiff/flag_nott.rs b/tests/ui/autodiff/flag_nott.rs new file mode 100644 index 00000000000..faa9949fe81 --- /dev/null +++ b/tests/ui/autodiff/flag_nott.rs @@ -0,0 +1,19 @@ +//@ compile-flags: -Zautodiff=Enable,NoTT +//@ needs-enzyme +//@ check-pass + +#![feature(autodiff)] + +use std::autodiff::autodiff_reverse; + +// Test that NoTT flag is accepted and doesn't cause compilation errors +#[autodiff_reverse(d_square, Duplicated, Active)] +fn square(x: &f64) -> f64 { + x * x +} + +fn main() { + let x = 2.0; + let mut dx = 0.0; + let result = d_square(&x, &mut dx, 1.0); +} diff --git a/tests/ui/empty/empty-attributes.stderr b/tests/ui/empty/empty-attributes.stderr index f0be56ddc6a..41dc790737d 100644 --- a/tests/ui/empty/empty-attributes.stderr +++ b/tests/ui/empty/empty-attributes.stderr @@ -56,12 +56,16 @@ error: unused attribute | LL | #[repr()] | ^^^^^^^^^ help: remove this attribute + | + = note: using `repr` with an empty list has no effect error: unused attribute --> $DIR/empty-attributes.rs:12:1 | LL | #[target_feature()] | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: using `target_feature` with an empty list has no effect error: aborting due to 8 previous errors diff --git a/tests/ui/explicit-tail-calls/callee_is_weird.stderr b/tests/ui/explicit-tail-calls/callee_is_weird.stderr index a4e5a38ce33..9a5da28b559 100644 --- a/tests/ui/explicit-tail-calls/callee_is_weird.stderr +++ b/tests/ui/explicit-tail-calls/callee_is_weird.stderr @@ -12,7 +12,7 @@ error: tail calls can only be performed with function definitions or pointers LL | become (&mut &std::sync::Exclusive::new(f))() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: callee has type `Exclusive<fn() {f}>` + = note: callee has type `&Exclusive<fn() {f}>` error: tail calls can only be performed with function definitions or pointers --> $DIR/callee_is_weird.rs:22:12 diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index 08caff326c4..4d8f23bf7ca 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -387,6 +387,8 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani where A: Tuple, F: Fn<A>, F: ?Sized; - impl<Args, F, A> Fn<Args> for Box<F, A> where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized; + - impl<F, Args> Fn<Args> for Exclusive<F> + where F: Sync, F: Fn<Args>, Args: Tuple; error[E0118]: no nominal type found for inherent implementation --> $DIR/where-allowed.rs:240:1 diff --git a/tests/ui/keyword/soup.rs b/tests/ui/keyword/soup.rs new file mode 100644 index 00000000000..c4dbe3fb483 --- /dev/null +++ b/tests/ui/keyword/soup.rs @@ -0,0 +1,30 @@ +//@ edition:2024 +//@ check-pass + +#![allow(unused_imports)] +#![allow(missing_abi)] +#![allow(unused_macros)] +#![allow(non_camel_case_types)] +#![allow(unreachable_code)] +#![allow(unused_variables)] +#![allow(dead_code)] +#![allow(unused_must_use)] + +// all 48 keywords in 300 characters +mod x { + pub(super) struct X; + use Ok; + impl X { + pub(in crate) async fn x(self: Self, x: &'static &'_ dyn for<> Fn()) where { + unsafe extern { safe fn x(); } + macro_rules! x { () => {}; } + if 'x: loop { + return match while let true = break 'x false { continue } { + ref x => { &raw mut x; async { const { enum A {} } }.await as () }, + }; + } { type x = X; } else { move || { trait x { } union B { x: () } }; } + } + } +} + +fn main() {} diff --git a/tests/ui/macros/macro-use-all-and-none.stderr b/tests/ui/macros/macro-use-all-and-none.stderr index a5efb065a21..b4c05adcb33 100644 --- a/tests/ui/macros/macro-use-all-and-none.stderr +++ b/tests/ui/macros/macro-use-all-and-none.stderr @@ -2,8 +2,9 @@ warning: unused attribute --> $DIR/macro-use-all-and-none.rs:7:12 | LL | #[macro_use()] - | ^^ help: remove this attribute + | ^^ help: remove these parentheses | + = note: using `macro_use` with an empty list is equivalent to not using a list at all note: the lint level is defined here --> $DIR/macro-use-all-and-none.rs:4:9 | diff --git a/tests/ui/privacy/ctor-not-accessible-due-to-inaccessible-field-in-reexport.fixed b/tests/ui/privacy/ctor-not-accessible-due-to-inaccessible-field-in-reexport.fixed new file mode 100644 index 00000000000..63cc3333b6b --- /dev/null +++ b/tests/ui/privacy/ctor-not-accessible-due-to-inaccessible-field-in-reexport.fixed @@ -0,0 +1,20 @@ +#![allow(dead_code, unused_variables)] +//@ run-rustfix +pub use my_mod::Foo; +//~^ NOTE the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields +//~| NOTE the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields + +mod my_mod { + pub struct Foo(u32); + + mod my_sub_mod { + fn my_func() { + let crate::my_mod::Foo(x) = crate::my_mod::Foo(42); + //~^ ERROR cannot initialize a tuple struct which contains private fields + //~| HELP the type can be constructed directly, because its fields are available from the current scope + //~| ERROR cannot match against a tuple struct which contains private fields + //~| HELP the type can be constructed directly, because its fields are available from the current scope + } + } +} +fn main() {} diff --git a/tests/ui/privacy/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs b/tests/ui/privacy/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs new file mode 100644 index 00000000000..0b695f90654 --- /dev/null +++ b/tests/ui/privacy/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs @@ -0,0 +1,20 @@ +#![allow(dead_code, unused_variables)] +//@ run-rustfix +pub use my_mod::Foo; +//~^ NOTE the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields +//~| NOTE the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields + +mod my_mod { + pub struct Foo(u32); + + mod my_sub_mod { + fn my_func() { + let crate::Foo(x) = crate::Foo(42); + //~^ ERROR cannot initialize a tuple struct which contains private fields + //~| HELP the type can be constructed directly, because its fields are available from the current scope + //~| ERROR cannot match against a tuple struct which contains private fields + //~| HELP the type can be constructed directly, because its fields are available from the current scope + } + } +} +fn main() {} diff --git a/tests/ui/privacy/ctor-not-accessible-due-to-inaccessible-field-in-reexport.stderr b/tests/ui/privacy/ctor-not-accessible-due-to-inaccessible-field-in-reexport.stderr new file mode 100644 index 00000000000..6ab324cb32f --- /dev/null +++ b/tests/ui/privacy/ctor-not-accessible-due-to-inaccessible-field-in-reexport.stderr @@ -0,0 +1,36 @@ +error[E0423]: cannot initialize a tuple struct which contains private fields + --> $DIR/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs:12:33 + | +LL | let crate::Foo(x) = crate::Foo(42); + | ^^^^^^^^^^ + | +note: the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields + --> $DIR/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs:3:9 + | +LL | pub use my_mod::Foo; + | ^^^^^^^^^^^ +help: the type can be constructed directly, because its fields are available from the current scope + | +LL | let crate::Foo(x) = crate::my_mod::Foo(42); + | ++++++++ + +error[E0532]: cannot match against a tuple struct which contains private fields + --> $DIR/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs:12:17 + | +LL | let crate::Foo(x) = crate::Foo(42); + | ^^^^^^^^^^ + | +note: the type is accessed through this re-export, but the type's constructor is not visible in this import's scope due to private fields + --> $DIR/ctor-not-accessible-due-to-inaccessible-field-in-reexport.rs:3:9 + | +LL | pub use my_mod::Foo; + | ^^^^^^^^^^^ +help: the type can be constructed directly, because its fields are available from the current scope + | +LL | let crate::my_mod::Foo(x) = crate::Foo(42); + | ++++++++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0532. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/repr/repr-empty-packed.stderr b/tests/ui/repr/repr-empty-packed.stderr index 6565b2e8c1d..adf32c95529 100644 --- a/tests/ui/repr/repr-empty-packed.stderr +++ b/tests/ui/repr/repr-empty-packed.stderr @@ -15,6 +15,7 @@ error: unused attribute LL | #[repr()] | ^^^^^^^^^ help: remove this attribute | + = note: using `repr` with an empty list has no effect note: the lint level is defined here --> $DIR/repr-empty-packed.rs:2:9 | diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.rs b/tests/ui/test-attrs/test-panic-abort-nocapture.rs index 6a1025ea087..7c78d432fa0 100644 --- a/tests/ui/test-attrs/test-panic-abort-nocapture.rs +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.rs @@ -6,7 +6,6 @@ //@ exec-env:RUST_BACKTRACE=0 //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ ignore-android #120567 //@ needs-subprocess #![cfg(test)] diff --git a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr index 8d7c62f8ec7..d8f65a78261 100644 --- a/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr +++ b/tests/ui/test-attrs/test-panic-abort-nocapture.run.stderr @@ -1,11 +1,11 @@ -thread 'main' ($TID) panicked at $DIR/test-panic-abort-nocapture.rs:32:5: +thread 'main' ($TID) panicked at $DIR/test-panic-abort-nocapture.rs:31:5: assertion `left == right` failed left: 2 right: 4 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -thread 'main' ($TID) panicked at $DIR/test-panic-abort-nocapture.rs:26:5: +thread 'main' ($TID) panicked at $DIR/test-panic-abort-nocapture.rs:25:5: assertion `left == right` failed left: 2 right: 4 diff --git a/tests/ui/test-attrs/test-panic-abort.rs b/tests/ui/test-attrs/test-panic-abort.rs index 6c9b641fb6f..13a30223399 100644 --- a/tests/ui/test-attrs/test-panic-abort.rs +++ b/tests/ui/test-attrs/test-panic-abort.rs @@ -6,7 +6,6 @@ //@ exec-env:RUST_BACKTRACE=0 //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" -//@ ignore-android #120567 //@ needs-subprocess #![cfg(test)] diff --git a/tests/ui/test-attrs/test-panic-abort.run.stdout b/tests/ui/test-attrs/test-panic-abort.run.stdout index 4d65c05b944..ca247f7da41 100644 --- a/tests/ui/test-attrs/test-panic-abort.run.stdout +++ b/tests/ui/test-attrs/test-panic-abort.run.stdout @@ -18,7 +18,7 @@ testing123 ---- it_fails stderr ---- testing321 -thread 'main' ($TID) panicked at $DIR/test-panic-abort.rs:37:5: +thread 'main' ($TID) panicked at $DIR/test-panic-abort.rs:36:5: assertion `left == right` failed left: 2 right: 5 diff --git a/tests/ui/traits/next-solver/opaques/overflow-hr-fn-trait-sized-1.rs b/tests/ui/traits/next-solver/opaques/overflow-hr-fn-trait-sized-1.rs new file mode 100644 index 00000000000..e35e48dfcec --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/overflow-hr-fn-trait-sized-1.rs @@ -0,0 +1,25 @@ +//@ ignore-compare-mode-next-solver +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#220. Builtin `Fn`-trait +// candidates required `for<'latebound> Output<'latebound>: Sized` which ended +// up resulting in overflow if the return type is an opaque in the defining scope. +// +// We now eagerly instantiate the binder of the function definition which avoids +// that overflow by relating the lifetime of the opaque to something from the +// input. +fn flat_map<T, F, I, G>(_: F, _: G) +where + F: FnOnce(T) -> I, + I: Iterator, + G: Fn(<I as Iterator>::Item) -> usize, +{ +} + +fn rarw<'a>(_: &'a ()) -> impl Iterator<Item = &'a str> { + flat_map(rarw, |x| x.len()); + std::iter::empty() +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/opaques/overflow-hr-fn-trait-sized-2.rs b/tests/ui/traits/next-solver/opaques/overflow-hr-fn-trait-sized-2.rs new file mode 100644 index 00000000000..1d64e422d89 --- /dev/null +++ b/tests/ui/traits/next-solver/opaques/overflow-hr-fn-trait-sized-2.rs @@ -0,0 +1,14 @@ +//@ ignore-compare-mode-next-solver +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for trait-system-refactor-initiative#204, see +// the sibling test for more details. + +fn constrain<'a, F: FnOnce(&'a ())>(_: F) {} +fn foo<'a>(_: &'a ()) -> impl Sized + use<'a> { + constrain(foo); + () +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/well-formed-in-relate.stderr b/tests/ui/traits/next-solver/well-formed-in-relate.stderr index 5294a072d31..d79e465b3e3 100644 --- a/tests/ui/traits/next-solver/well-formed-in-relate.stderr +++ b/tests/ui/traits/next-solver/well-formed-in-relate.stderr @@ -12,6 +12,8 @@ LL | x = unconstrained_map(); where A: Tuple, F: Fn<A>, F: ?Sized; - impl<Args, F, A> Fn<Args> for Box<F, A> where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized; + - impl<F, Args> Fn<Args> for Exclusive<F> + where F: Sync, F: Fn<Args>, Args: Tuple; note: required by a bound in `unconstrained_map` --> $DIR/well-formed-in-relate.rs:21:25 | diff --git a/tests/ui/union/union-unsafe.rs b/tests/ui/union/union-unsafe.rs index bd3946686be..beb074f4e8e 100644 --- a/tests/ui/union/union-unsafe.rs +++ b/tests/ui/union/union-unsafe.rs @@ -1,5 +1,6 @@ use std::cell::RefCell; use std::mem::ManuallyDrop; +use std::ops::Deref; union U1 { a: u8, @@ -17,6 +18,10 @@ union U4<T: Copy> { a: T, } +union U5 { + a: usize, +} + union URef { p: &'static mut i32, } @@ -31,6 +36,20 @@ fn deref_union_field(mut u: URef) { *(u.p) = 13; //~ ERROR access to union field is unsafe } +union A { + a: usize, + b: &'static &'static B, +} + +union B { + c: usize, +} + +fn raw_deref_union_field(mut u: URef) { + // This is unsafe because we first dereference u.p (reading uninitialized memory) + let _p = &raw const *(u.p); //~ ERROR access to union field is unsafe +} + fn assign_noncopy_union_field(mut u: URefCell) { u.a = (ManuallyDrop::new(RefCell::new(0)), 1); // OK (assignment does not drop) u.a.0 = ManuallyDrop::new(RefCell::new(0)); // OK (assignment does not drop) @@ -57,6 +76,20 @@ fn main() { let a = u1.a; //~ ERROR access to union field is unsafe u1.a = 11; // OK + let mut u2 = U1 { a: 10 }; + let a = &raw mut u2.a; // OK + unsafe { *a = 3 }; + + let mut u3 = U1 { a: 10 }; + let a = std::ptr::addr_of_mut!(u3.a); // OK + unsafe { *a = 14 }; + + let u4 = U5 { a: 2 }; + let vec = vec![1, 2, 3]; + // This is unsafe because we read u4.a (potentially uninitialized memory) + // to use as an array index + let _a = &raw const vec[u4.a]; //~ ERROR access to union field is unsafe + let U1 { a } = u1; //~ ERROR access to union field is unsafe if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe if let Some(U1 { a: 13 }) = Some(u1) {} //~ ERROR access to union field is unsafe @@ -73,4 +106,44 @@ fn main() { let mut u3 = U3 { a: ManuallyDrop::new(String::from("old")) }; // OK u3.a = ManuallyDrop::new(String::from("new")); // OK (assignment does not drop) *u3.a = String::from("new"); //~ ERROR access to union field is unsafe + + let mut unions = [U1 { a: 1 }, U1 { a: 2 }]; + + // Array indexing + union field raw borrow - should be OK + let ptr = &raw mut unions[0].a; // OK + let ptr2 = &raw const unions[1].a; // OK + + let a = A { a: 0 }; + let _p = &raw const (**a.b).c; //~ ERROR access to union field is unsafe + + arbitrary_deref(); +} + +// regression test for https://github.com/rust-lang/rust/pull/141469#discussion_r2312546218 +fn arbitrary_deref() { + use std::ops::Deref; + + union A { + a: usize, + b: B, + } + + #[derive(Copy, Clone)] + struct B(&'static str); + + impl Deref for B { + type Target = C; + + fn deref(&self) -> &C { + println!("{:?}", self.0); + &C { c: 0 } + } + } + + union C { + c: usize, + } + + let a = A { a: 0 }; + let _p = &raw const (*a.b).c; //~ ERROR access to union field is unsafe } diff --git a/tests/ui/union/union-unsafe.stderr b/tests/ui/union/union-unsafe.stderr index 82b3f897167..01f4d95eb64 100644 --- a/tests/ui/union/union-unsafe.stderr +++ b/tests/ui/union/union-unsafe.stderr @@ -1,5 +1,5 @@ error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:31:6 + --> $DIR/union-unsafe.rs:36:6 | LL | *(u.p) = 13; | ^^^^^ access to union field @@ -7,7 +7,15 @@ LL | *(u.p) = 13; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:43:6 + --> $DIR/union-unsafe.rs:50:26 + | +LL | let _p = &raw const *(u.p); + | ^^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:62:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -15,7 +23,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:49:6 + --> $DIR/union-unsafe.rs:68:6 | LL | *u3.a = T::default(); | ^^^^ access to union field @@ -23,7 +31,7 @@ LL | *u3.a = T::default(); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:57:13 + --> $DIR/union-unsafe.rs:76:13 | LL | let a = u1.a; | ^^^^ access to union field @@ -31,7 +39,15 @@ LL | let a = u1.a; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:60:14 + --> $DIR/union-unsafe.rs:91:29 + | +LL | let _a = &raw const vec[u4.a]; + | ^^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:93:14 | LL | let U1 { a } = u1; | ^ access to union field @@ -39,7 +55,7 @@ LL | let U1 { a } = u1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:61:20 + --> $DIR/union-unsafe.rs:94:20 | LL | if let U1 { a: 12 } = u1 {} | ^^ access to union field @@ -47,7 +63,7 @@ LL | if let U1 { a: 12 } = u1 {} = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:62:25 + --> $DIR/union-unsafe.rs:95:25 | LL | if let Some(U1 { a: 13 }) = Some(u1) {} | ^^ access to union field @@ -55,7 +71,7 @@ LL | if let Some(U1 { a: 13 }) = Some(u1) {} = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:67:6 + --> $DIR/union-unsafe.rs:100:6 | LL | *u2.a = String::from("new"); | ^^^^ access to union field @@ -63,7 +79,7 @@ LL | *u2.a = String::from("new"); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:71:6 + --> $DIR/union-unsafe.rs:104:6 | LL | *u3.a = 1; | ^^^^ access to union field @@ -71,13 +87,29 @@ LL | *u3.a = 1; = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0133]: access to union field is unsafe and requires unsafe function or block - --> $DIR/union-unsafe.rs:75:6 + --> $DIR/union-unsafe.rs:108:6 | LL | *u3.a = String::from("new"); | ^^^^ access to union field | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -error: aborting due to 10 previous errors +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:117:28 + | +LL | let _p = &raw const (**a.b).c; + | ^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error[E0133]: access to union field is unsafe and requires unsafe function or block + --> $DIR/union-unsafe.rs:148:27 + | +LL | let _p = &raw const (*a.b).c; + | ^^^ access to union field + | + = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior + +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0133`. |
