diff options
Diffstat (limited to 'tests')
87 files changed, 2798 insertions, 640 deletions
diff --git a/tests/codegen-llvm/debug-fndef-size.rs b/tests/codegen-llvm/debug-fndef-size.rs index 8f716c34e7b..02629bd748c 100644 --- a/tests/codegen-llvm/debug-fndef-size.rs +++ b/tests/codegen-llvm/debug-fndef-size.rs @@ -16,5 +16,5 @@ pub fn main() { // CHECK: %compare.dbg.spill = alloca [0 x i8], align 1 // CHECK: dbg{{.}}declare({{(metadata )?}}ptr %compare.dbg.spill, {{(metadata )?}}![[VAR:.*]], {{(metadata )?}}!DIExpression() -// CHECK: ![[TYPE:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "fn(&i32, &i32) -> core::cmp::Ordering", baseType: !{{.*}}, align: 8, dwarfAddressSpace: {{.*}}) -// CHECK: ![[VAR]] = !DILocalVariable(name: "compare", scope: !{{.*}}, file: !{{.*}}, line: {{.*}}, type: ![[TYPE]], align: 8) +// CHECK-DAG: ![[TYPE:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "fn(&i32, &i32) -> core::cmp::Ordering", baseType: !{{.*}}, align: 8, dwarfAddressSpace: {{.*}}) +// CHECK-DAG: ![[VAR]] = !DILocalVariable(name: "compare", scope: !{{.*}}, file: !{{.*}}, line: {{.*}}, type: ![[TYPE]], align: 8) diff --git a/tests/codegen-llvm/debuginfo-dse.rs b/tests/codegen-llvm/debuginfo-dse.rs new file mode 100644 index 00000000000..fd0c9f1c676 --- /dev/null +++ b/tests/codegen-llvm/debuginfo-dse.rs @@ -0,0 +1,362 @@ +//@ compile-flags: -Copt-level=3 -g -Zverify-llvm-ir -Zmerge-functions=disabled +//@ revisions: CODEGEN OPTIMIZED +//@[CODEGEN] compile-flags: -Cno-prepopulate-passes +//@ only-64bit +// ignore-tidy-linelength + +#![crate_type = "lib"] +#![feature(repr_simd, rustc_attrs)] + +// The pass mode is direct and the backend represent is scalar. +type Scalar = i32; // scalar(i32) +type Scalar_Ref = &'static i32; // scalar(ptr) + +// The pass modes are pair and the backend represents are scalar pair. +type Tuple_Scalar_Scalar = (i32, i32); +struct Tuple_Ref_Scalar(&'static i32, i32); +struct Tuple_ArrayRef_Scalar(&'static [i32; 16], i32); // pair(ptr, i32) +impl Default for Tuple_ArrayRef_Scalar { + fn default() -> Tuple_ArrayRef_Scalar { + Tuple_ArrayRef_Scalar(&[0; 16], 0) + } +} +struct Tuple_Scalar_ArrayRef(i32, &'static [i32; 16]); // pair(i32, ptr) +impl Default for Tuple_Scalar_ArrayRef { + fn default() -> Tuple_Scalar_ArrayRef { + Tuple_Scalar_ArrayRef(0, &[0; 16]) + } +} +// The pass mode is indirect and the backend represent is memory. +type Tuple_SliceRef_Scalar = (&'static [i32], i32); + +// The pass mode is pair and the backend represent is scalar pair. +type SliceRef = &'static [i32]; // pair(ptr, i32) +// The pass mode is indirect and the backend represent is memory. +type Array = [i32; 16]; +// The pass mode is direct and the backend represent is scalar. +type ArrayRef = &'static [i32; 16]; + +// The pass mode is indirect and the backend represent is memory. +type Typle_i32_i64_i8 = (i32, i64, i8); +// The pass mode is indirect and the backend represent is memory. +#[repr(C)] +struct Aggregate_i32_Array_i8(i32, &'static [i32; 16], i8); + +type ZST = (); + +impl Default for Aggregate_i32_Array_i8 { + fn default() -> Aggregate_i32_Array_i8 { + Aggregate_i32_Array_i8(0, &[0; 16], 0) + } +} +// The pass mode is cast and the backend represent is scalar. +#[derive(Default)] +struct Aggregate_4xi8(i8, i8, i8, i8); // scalar(i32) + +// The pass mode is indirect and the backend represent is simd vector. +#[repr(simd)] +struct Simd_i32x4([i32; 4]); + +unsafe extern "Rust" { + #[rustc_nounwind] + safe fn opaque_fn(); + #[rustc_nounwind] + safe fn opaque_ptr(_: *const core::ffi::c_void); +} + +#[inline(never)] +#[rustc_nounwind] +fn opaque_use<T>(p: &T) { + opaque_ptr(&raw const p as *const _); +} + +#[inline(never)] +#[rustc_nounwind] +fn opaque_read<T: Default>() -> T { + core::hint::black_box(T::default()) +} + +#[unsafe(no_mangle)] +fn local_var() { + // CHECK-LABEL: define{{( dso_local)?}} void @local_var + let local_var_scalar: Scalar = opaque_read(); + opaque_use(&local_var_scalar); + let dead_local_var_scalar: Scalar = opaque_read(); + let local_var_aggregate_4xi8: Aggregate_4xi8 = opaque_read(); + opaque_use(&local_var_aggregate_4xi8); + let local_var_aggregate_i32_array_i8: Aggregate_i32_Array_i8 = opaque_read(); + opaque_use(&local_var_aggregate_i32_array_i8); + // CHECK: call void @opaque_fn() + opaque_fn(); + // CHECK-NEXT: #dbg_value(ptr %local_var_scalar, [[ref_local_var_scalar:![0-9]+]], !DIExpression() + let ref_local_var_scalar = &local_var_scalar; + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_dead_local_var_scalar:![0-9]+]], !DIExpression() + let ref_dead_local_var_scalar = &dead_local_var_scalar; + // CHECK-NEXT: #dbg_value(ptr %local_var_aggregate_4xi8, [[ref_local_var_aggregate_4xi8:![0-9]+]], !DIExpression() + let ref_local_var_aggregate_4xi8 = &local_var_aggregate_4xi8; + // CHECK-NEXT: #dbg_value(ptr %local_var_aggregate_4xi8, [[ref_0_local_var_aggregate_4xi8:![0-9]+]], !DIExpression() + let ref_0_local_var_aggregate_4xi8 = &local_var_aggregate_4xi8.0; + // CHECK-NEXT: #dbg_value(ptr %local_var_aggregate_4xi8, [[ref_2_local_var_aggregate_4xi8:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 2, DW_OP_stack_value) + let ref_2_local_var_aggregate_4xi8 = &local_var_aggregate_4xi8.2; + // This introduces an extra load instruction. + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_1_1_local_var_aggregate_i32_array_i8:![0-9]+]], !DIExpression() + let ref_1_1_local_var_aggregate_i32_array_i8 = &local_var_aggregate_i32_array_i8.1[1]; + // CHECK-NEXT: #dbg_value(ptr %local_var_aggregate_i32_array_i8, [[ref_2_local_var_aggregate_i32_array_i8:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16, DW_OP_stack_value) + let ref_2_local_var_aggregate_i32_array_i8 = &local_var_aggregate_i32_array_i8.2; + // CHECK: call void @opaque_fn() + opaque_fn(); +} + +#[unsafe(no_mangle)] +fn zst(zst: ZST, zst_ref: &ZST) { + // CHECK-LABEL: define{{( dso_local)?}} void @zst + // CHECK: call void @opaque_fn() + opaque_fn(); + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_zst:![0-9]+]], !DIExpression() + let ref_zst = &zst; + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_zst_ref:![0-9]+]], !DIExpression() + let ref_zst_ref = &zst_ref; + // CHECK: call void @opaque_fn() + opaque_fn(); +} + +// It only makes sense if the argument is a reference and it refer to projections. +#[unsafe(no_mangle)] +fn direct( + scalar: Scalar, + scalar_ref: Scalar_Ref, + array_ref: ArrayRef, + aggregate_4xi8_ref: &Aggregate_4xi8, +) { + // CHECK-LABEL: define{{( dso_local)?}} void @direct + // CHECK: call void @opaque_fn() + opaque_fn(); + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_scalar:![0-9]+]], !DIExpression() + let ref_scalar = &scalar; + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_scalar_ref:![0-9]+]], !DIExpression() + let ref_scalar_ref = &scalar_ref; + // CHECK-NEXT: #dbg_value(ptr %array_ref, [[ref_0_array_ref:![0-9]+]], !DIExpression() + let ref_0_array_ref = &array_ref[0]; + // CHECK-NEXT: #dbg_value(ptr %array_ref, [[ref_1_array_ref:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value) + let ref_1_array_ref = &array_ref[1]; + // CHECK-NEXT: #dbg_value(ptr %aggregate_4xi8_ref, [[ref_1_aggregate_4xi8_ref:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value) + let ref_1_aggregate_4xi8_ref = &aggregate_4xi8_ref.1; + // CHECK: call void @opaque_fn() + opaque_fn(); +} + +// Arguments are passed through registers, the final values are poison. +#[unsafe(no_mangle)] +fn cast(aggregate_4xi8: Aggregate_4xi8) { + // CHECK-LABEL: define{{( dso_local)?}} void @cast(i32 %0) + // CHECK: call void @opaque_fn() + opaque_fn(); + // The temporary allocated variable is eliminated. + // CODEGEN-NEXT: #dbg_value(ptr %aggregate_4xi8, [[ref_aggregate_4xi8:![0-9]+]], !DIExpression() + // OPTIMIZED-NEXT: #dbg_value(ptr undef, [[ref_aggregate_4xi8:![0-9]+]], !DIExpression() + let ref_aggregate_4xi8 = &aggregate_4xi8; + // CODEGEN-NEXT: #dbg_value(ptr %aggregate_4xi8, [[ref_0_aggregate_4xi8:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value) + // OPTIMIZED-NEXT: #dbg_value(ptr undef, [[ref_0_aggregate_4xi8:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value) + let ref_0_aggregate_4xi8 = &aggregate_4xi8.1; + // CHECK: call void @opaque_fn() + opaque_fn(); +} + +// Arguments are passed indirectly via a pointer. +// The reference of argument is the pointer itself. +#[unsafe(no_mangle)] +fn indirect( + tuple_sliceref_scalar: Tuple_SliceRef_Scalar, + array: Array, + typle_i32_i64_i8: Typle_i32_i64_i8, + simd_i32x4: Simd_i32x4, +) { + // CHECK-LABEL: define{{( dso_local)?}} void @indirect + // CHECK-SAME: (ptr{{.*}} %tuple_sliceref_scalar, ptr{{.*}} %array, ptr{{.*}} %typle_i32_i64_i8, ptr{{.*}} %simd_i32x4) + // CHECK: call void @opaque_fn() + opaque_fn(); + // CHECK-NEXT: #dbg_value(ptr %tuple_sliceref_scalar, [[ref_tuple_sliceref_scalar:![0-9]+]], !DIExpression() + let ref_tuple_sliceref_scalar = &tuple_sliceref_scalar; + // CHECK-NEXT: #dbg_value(ptr %tuple_sliceref_scalar, [[ref_1_tuple_sliceref_scalar:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16, DW_OP_stack_value) + let ref_1_tuple_sliceref_scalar = &tuple_sliceref_scalar.1; + // CHECK-NEXT: #dbg_value(ptr %array, [[ref_1_array:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value) + let ref_1_array = &array[1]; + // CHECK-NEXT: #dbg_value(ptr %typle_i32_i64_i8, [[ref_1_typle_i32_i64_i8:![0-9]+]], !DIExpression() + let ref_1_typle_i32_i64_i8 = &typle_i32_i64_i8.1; + // CHECK-NEXT: #dbg_value(ptr %simd_i32x4, [[ref_simd_i32x4:![0-9]+]], !DIExpression() + let ref_simd_i32x4 = &simd_i32x4; + // CHECK: call void @opaque_fn() + opaque_fn(); +} + +// They are different MIR statements, but they have the same LLVM IR statement due to the ABI of arguments. +// Both `direct_ref` and `indirect_byval` are passed as a pointer here. +#[unsafe(no_mangle)] +fn direct_ref_and_indirect( + direct_ref: &Aggregate_i32_Array_i8, + indirect_byval: Aggregate_i32_Array_i8, +) { + // CHECK-LABEL: define{{( dso_local)?}} void @direct_ref_and_indirect + // CHECK-SAME: (ptr{{.*}} %direct_ref, ptr{{.*}} %indirect_byval) + // CHECK: call void @opaque_fn() + opaque_fn(); + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_direct_ref:![0-9]+]], !DIExpression() + let ref_direct_ref: &&Aggregate_i32_Array_i8 = &direct_ref; + // CHECK-NEXT: #dbg_value(ptr %direct_ref, [[ref_1_direct_ref:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 8, DW_OP_stack_value) + let ref_1_direct_ref = &direct_ref.1; + // CHECK-NEXT: #dbg_value(ptr %indirect_byval, [[ref_indirect_byval:![0-9]+]], !DIExpression() + let ref_indirect_byval: &Aggregate_i32_Array_i8 = &indirect_byval; + // CHECK-NEXT: #dbg_value(ptr %indirect_byval, [[ref_1_indirect_byval:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 8, DW_OP_stack_value) + let ref_1_indirect_byval = &indirect_byval.1; + // CHECK: call void @opaque_fn() + opaque_fn(); +} + +#[unsafe(no_mangle)] +fn pair( + tuple_scalar_scalar: Tuple_Scalar_Scalar, + tuple_ref_scalar: Tuple_Ref_Scalar, + tuple_arrayref_scalar: Tuple_ArrayRef_Scalar, + tuple_scalar_arrayref: Tuple_Scalar_ArrayRef, + sliceref: SliceRef, +) { + // CHECK-LABEL: define{{( dso_local)?}} void @pair + // CHECK: call void @opaque_fn() + opaque_fn(); + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_0_tuple_scalar_scalar:![0-9]+]], !DIExpression() + let ref_0_tuple_scalar_scalar = &tuple_scalar_scalar.0; + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_0_tuple_ref_scalar:![0-9]+]], !DIExpression() + let ref_0_tuple_ref_scalar = &tuple_ref_scalar.0; + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_1_tuple_ref_scalar:![0-9]+]], !DIExpression() + let ref_1_tuple_ref_scalar = &tuple_ref_scalar.1; + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_0_tuple_arrayref_scalar:![0-9]+]], !DIExpression() + let ref_0_tuple_arrayref_scalar = &tuple_arrayref_scalar.0; + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_1_tuple_arrayref_scalar:![0-9]+]], !DIExpression() + let ref_1_tuple_arrayref_scalar = &tuple_arrayref_scalar.1; + // FIXME: This can be a valid value. + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_0_1_tuple_arrayref_scalar:![0-9]+]], !DIExpression() + let ref_0_1_tuple_arrayref_scalar = &tuple_arrayref_scalar.0[1]; + // FIXME: This can be a valid value. + // CHECK-NEXT: #dbg_value(ptr poison, [[ref_1_1_tuple_scalar_arrayref:![0-9]+]], !DIExpression() + let ref_1_1_tuple_scalar_arrayref = &tuple_scalar_arrayref.1[1]; + // CHECK: #dbg_value(ptr %sliceref.0, [[ref_1_sliceref:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value) + let ref_1_sliceref = &sliceref[1]; + // CHECK: call void @opaque_fn() + opaque_fn(); +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct Foo(i32, i64, i32); + +#[repr(C)] +pub struct Bar<'a> { + a: i32, + b: i64, + foo: &'a Foo, +} + +#[unsafe(no_mangle)] +pub fn dead_first(dead_first_foo: &Foo) -> &i32 { + // CHECK-LABEL: def {{.*}} ptr @dead_first + // CHECK-SAME: (ptr {{.*}} [[ARG_dead_first_foo:%.*]]) + // CODEGEN: #dbg_declare(ptr %dead_first_foo.dbg.spill, [[ARG_dead_first_foo:![0-9]+]], !DIExpression() + // OPTIMIZED: #dbg_value(ptr %dead_first_foo, [[ARG_dead_first_foo:![0-9]+]], !DIExpression() + // CHECK: #dbg_value(ptr %dead_first_foo, [[VAR_dead_first_v0:![0-9]+]], !DIExpression() + // CHECK: %dead_first_v0 = getelementptr{{.*}} i8, ptr %dead_first_foo, i64 16 + // CODEGEN: #dbg_declare(ptr %dead_first_v0.dbg.spill, [[VAR_dead_first_v0]], !DIExpression() + // OPTIMIZED: #dbg_value(ptr %dead_first_v0, [[VAR_dead_first_v0]], !DIExpression() + let mut dead_first_v0 = &dead_first_foo.0; + dead_first_v0 = &dead_first_foo.2; + dead_first_v0 +} + +#[unsafe(no_mangle)] +pub fn fragment(fragment_v1: Foo, mut fragment_v2: Foo) -> Foo { + // CHECK-LABEL: define{{( dso_local)?}} void @fragment + // CHECK-SAME: (ptr {{.*}}, ptr {{.*}} [[ARG_fragment_v1:%.*]], ptr {{.*}} [[ARG_fragment_v2:%.*]]) + // CHECK: #dbg_declare(ptr [[ARG_fragment_v1]] + // CHECK-NEXT: #dbg_declare(ptr [[ARG_fragment_v2]] + // CHECK-NEXT: #dbg_value(ptr [[ARG_fragment_v2]], [[VAR_fragment_f:![0-9]+]], !DIExpression(DW_OP_LLVM_fragment, 0, 64) + // CHECK-NEXT: #dbg_value(ptr [[ARG_fragment_v1]], [[VAR_fragment_f:![0-9]+]], !DIExpression(DW_OP_LLVM_fragment, 64, 64) + let fragment_f = || { + fragment_v2 = fragment_v1; + }; + fragment_v2 = fragment_v1; + fragment_v2 +} + +#[unsafe(no_mangle)] +pub fn deref(bar: Bar) -> i32 { + // CHECK-LABEL: define{{.*}} i32 @deref + // We are unable to represent dereference within this expression. + // CHECK: #dbg_value(ptr poison, [[VAR_deref_dead:![0-9]+]], !DIExpression() + let deref_dead = &bar.foo.2; + bar.a +} + +#[unsafe(no_mangle)] +fn index(slice: &[i32; 4], idx: usize) -> i32 { + // CHECK-LABEL: define{{.*}} i32 @index + // CHECK: call void @opaque_fn() + opaque_fn(); + // CHECK: #dbg_value(ptr poison, [[VAR_index_from_var:![0-9]+]], !DIExpression() + let index_from_var = &slice[idx]; + // CHECK: #dbg_value(ptr %slice, [[VAR_const_index_from_start:![0-9]+]], !DIExpression() + // CHECK-NEXT: #dbg_value(ptr poison, [[VAR_const_index_from_end:![0-9]+]], !DIExpression() + let [ref const_index_from_start, .., ref const_index_from_end] = slice[..] else { + return 0; + }; + slice[0] +} + +// CHECK-DAG: [[ref_local_var_scalar]] = !DILocalVariable(name: "ref_local_var_scalar" +// CHECK-DAG: [[ref_dead_local_var_scalar]] = !DILocalVariable(name: "ref_dead_local_var_scalar" +// CHECK-DAG: [[ref_local_var_aggregate_4xi8]] = !DILocalVariable(name: "ref_local_var_aggregate_4xi8" +// CHECK-DAG: [[ref_0_local_var_aggregate_4xi8]] = !DILocalVariable(name: "ref_0_local_var_aggregate_4xi8" +// CHECK-DAG: [[ref_2_local_var_aggregate_4xi8]] = !DILocalVariable(name: "ref_2_local_var_aggregate_4xi8" +// CHECK-DAG: [[ref_1_1_local_var_aggregate_i32_array_i8]] = !DILocalVariable(name: "ref_1_1_local_var_aggregate_i32_array_i8" +// CHECK-DAG: [[ref_2_local_var_aggregate_i32_array_i8]] = !DILocalVariable(name: "ref_2_local_var_aggregate_i32_array_i8" + +// CHECK-DAG: [[ref_zst]] = !DILocalVariable(name: "ref_zst" +// CHECK-DAG: [[ref_zst_ref]] = !DILocalVariable(name: "ref_zst_ref" + +// CHECK-DAG: [[ref_scalar]] = !DILocalVariable(name: "ref_scalar" +// CHECK-DAG: [[ref_scalar_ref]] = !DILocalVariable(name: "ref_scalar_ref" +// CHECK-DAG: [[ref_0_array_ref]] = !DILocalVariable(name: "ref_0_array_ref" +// CHECK-DAG: [[ref_1_array_ref]] = !DILocalVariable(name: "ref_1_array_ref" +// CHECK-DAG: [[ref_1_aggregate_4xi8_ref]] = !DILocalVariable(name: "ref_1_aggregate_4xi8_ref" + +// CHECK-DAG: [[ref_aggregate_4xi8]] = !DILocalVariable(name: "ref_aggregate_4xi8" +// CHECK-DAG: [[ref_0_aggregate_4xi8]] = !DILocalVariable(name: "ref_0_aggregate_4xi8" + +// CHECK-DAG: [[ref_tuple_sliceref_scalar]] = !DILocalVariable(name: "ref_tuple_sliceref_scalar" +// CHECK-DAG: [[ref_1_tuple_sliceref_scalar]] = !DILocalVariable(name: "ref_1_tuple_sliceref_scalar" +// CHECK-DAG: [[ref_1_array]] = !DILocalVariable(name: "ref_1_array" +// CHECK-DAG: [[ref_1_typle_i32_i64_i8]] = !DILocalVariable(name: "ref_1_typle_i32_i64_i8" +// CHECK-DAG: [[ref_simd_i32x4]] = !DILocalVariable(name: "ref_simd_i32x4" + +// CHECK-DAG: [[ref_direct_ref]] = !DILocalVariable(name: "ref_direct_ref" +// CHECK-DAG: [[ref_1_direct_ref]] = !DILocalVariable(name: "ref_1_direct_ref" +// CHECK-DAG: [[ref_indirect_byval]] = !DILocalVariable(name: "ref_indirect_byval" +// CHECK-DAG: [[ref_1_indirect_byval]] = !DILocalVariable(name: "ref_1_indirect_byval" + +// CHECK-DAG: [[ref_0_tuple_scalar_scalar]] = !DILocalVariable(name: "ref_0_tuple_scalar_scalar" +// CHECK-DAG: [[ref_0_tuple_ref_scalar]] = !DILocalVariable(name: "ref_0_tuple_ref_scalar" +// CHECK-DAG: [[ref_1_tuple_ref_scalar]] = !DILocalVariable(name: "ref_1_tuple_ref_scalar" +// CHECK-DAG: [[ref_0_tuple_arrayref_scalar]] = !DILocalVariable(name: "ref_0_tuple_arrayref_scalar" +// CHECK-DAG: [[ref_1_tuple_arrayref_scalar]] = !DILocalVariable(name: "ref_1_tuple_arrayref_scalar" +// CHECK-DAG: [[ref_0_1_tuple_arrayref_scalar]] = !DILocalVariable(name: "ref_0_1_tuple_arrayref_scalar" +// CHECK-DAG: [[ref_1_1_tuple_scalar_arrayref]] = !DILocalVariable(name: "ref_1_1_tuple_scalar_arrayref" +// CHECK-DAG: [[ref_1_sliceref]] = !DILocalVariable(name: "ref_1_sliceref" + +// CHECK-DAG: [[ARG_dead_first_foo]] = !DILocalVariable(name: "dead_first_foo" +// CHECK-DAG: [[VAR_dead_first_v0]] = !DILocalVariable(name: "dead_first_v0" + +// CHECK-DAG: [[VAR_fragment_f]] = !DILocalVariable(name: "fragment_f" + +// CHECK-DAG: [[VAR_deref_dead]] = !DILocalVariable(name: "deref_dead" + +// CHECK-DAG: [[VAR_index_from_var]] = !DILocalVariable(name: "index_from_var" +// CHECK-DAG: [[VAR_const_index_from_start]] = !DILocalVariable(name: "const_index_from_start" +// CHECK-DAG: [[VAR_const_index_from_end]] = !DILocalVariable(name: "const_index_from_end" diff --git a/tests/debuginfo/opt/dead_refs.rs b/tests/debuginfo/opt/dead_refs.rs new file mode 100644 index 00000000000..61e74157334 --- /dev/null +++ b/tests/debuginfo/opt/dead_refs.rs @@ -0,0 +1,50 @@ +//@ min-lldb-version: 1800 +//@ min-gdb-version: 13.0 +//@ compile-flags: -g -Copt-level=3 +//@ disable-gdb-pretty-printers + +// Checks that we still can access dead variables from debuginfos. + +// === GDB TESTS =================================================================================== + +// gdb-command:run +// gdb-command:print *ref_v0 +// gdb-check:$1 = 0 + +// gdb-command:print *ref_v1 +// gdb-check:$2 = 1 + +// gdb-command:print *ref_v2 +// gdb-check:$3 = 2 + +// === LLDB TESTS ================================================================================== + +// lldb-command:run +// lldb-command:v *ref_v0 +// lldb-check:[...] 0 + +// lldb-command:v *ref_v1 +// lldb-check:[...] 1 + +// lldb-command:v *ref_v2 +// lldb-check:[...] 2 + +#![allow(unused_variables)] + +use std::hint::black_box; + +pub struct Foo(i32, i64, i32); + +#[inline(never)] +#[no_mangle] +fn test_ref(ref_foo: &Foo) -> i32 { + let ref_v0 = &ref_foo.0; + let ref_v1 = &ref_foo.1; + let ref_v2 = &ref_foo.2; + ref_foo.0 // #break +} + +fn main() { + let foo = black_box(Foo(0, 1, 2)); + black_box(test_ref(&foo)); +} diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff index ff18df1efcf..d584de6861c 100644 --- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff +++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination-initial.diff @@ -19,10 +19,6 @@ - _3 = copy _2; - _2 = copy _1; - _1 = copy _5; -+ nop; -+ nop; -+ nop; -+ nop; _4 = cond() -> [return: bb1, unwind continue]; } diff --git a/tests/mir-opt/dead-store-elimination/ref.dead_first.DeadStoreElimination-initial.diff b/tests/mir-opt/dead-store-elimination/ref.dead_first.DeadStoreElimination-initial.diff new file mode 100644 index 00000000000..2a793e24990 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/ref.dead_first.DeadStoreElimination-initial.diff @@ -0,0 +1,30 @@ +- // MIR for `dead_first` before DeadStoreElimination-initial ++ // MIR for `dead_first` after DeadStoreElimination-initial + + fn dead_first(_1: &Foo) -> &i32 { + debug v => _1; + let mut _0: &i32; + let mut _2: &i32; + let mut _3: &i32; + let _4: &i32; + scope 1 { + debug a => _2; + } + + bb0: { + StorageLive(_2); +- _2 = &((*_1).2: i32); ++ // DBG: _2 = &((*_1).2: i32); + StorageLive(_3); + StorageLive(_4); + _4 = &((*_1).0: i32); + _3 = &(*_4); + _2 = move _3; + StorageDead(_3); + StorageDead(_4); + _0 = &(*_2); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/dead-store-elimination/ref.rs b/tests/mir-opt/dead-store-elimination/ref.rs new file mode 100644 index 00000000000..2d3200edab9 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/ref.rs @@ -0,0 +1,31 @@ +//@ test-mir-pass: DeadStoreElimination-initial + +pub struct Foo { + a: i32, + b: i64, + c: i32, +} + +// EMIT_MIR ref.tuple.DeadStoreElimination-initial.diff +pub fn tuple(v: (i32, &Foo)) -> i32 { + // CHECK-LABEL: fn tuple + // CHECK: debug _dead => [[dead:_[0-9]+]]; + // CHECK: bb0: + // CHECK: DBG: [[dead]] = &((*_3).2: i32) + let _dead = &v.1.c; + v.1.a +} + +// EMIT_MIR ref.dead_first.DeadStoreElimination-initial.diff +pub fn dead_first(v: &Foo) -> &i32 { + // CHECK-LABEL: fn dead_first + // CHECK: debug a => [[var_a:_[0-9]+]]; + // CHECK: bb0: + // CHECK: DBG: [[var_a]] = &((*_1).2: i32) + // CHECK: [[tmp_4:_[0-9]+]] = &((*_1).0: i32) + // CHECK: [[tmp_3:_[0-9]+]] = &(*[[tmp_4]]) + // CHECK: [[var_a]] = move [[tmp_3]] + let mut a = &v.c; + a = &v.a; + a +} diff --git a/tests/mir-opt/dead-store-elimination/ref.tuple.DeadStoreElimination-initial.diff b/tests/mir-opt/dead-store-elimination/ref.tuple.DeadStoreElimination-initial.diff new file mode 100644 index 00000000000..0b96569cbe4 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/ref.tuple.DeadStoreElimination-initial.diff @@ -0,0 +1,25 @@ +- // MIR for `tuple` before DeadStoreElimination-initial ++ // MIR for `tuple` after DeadStoreElimination-initial + + fn tuple(_1: (i32, &Foo)) -> i32 { + debug v => _1; + let mut _0: i32; + let _2: &i32; + let mut _3: &Foo; + let mut _4: &Foo; + scope 1 { + debug _dead => _2; + } + + bb0: { +- StorageLive(_2); +- _3 = deref_copy (_1.1: &Foo); +- _2 = &((*_3).2: i32); ++ // DBG: _2 = &((*_3).2: i32); + _4 = deref_copy (_1.1: &Foo); + _0 = copy ((*_4).0: i32); +- StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/debuginfo/simplifycfg.drop_debuginfo.SimplifyCfg-final.diff b/tests/mir-opt/debuginfo/simplifycfg.drop_debuginfo.SimplifyCfg-final.diff new file mode 100644 index 00000000000..d4a73351ee4 --- /dev/null +++ b/tests/mir-opt/debuginfo/simplifycfg.drop_debuginfo.SimplifyCfg-final.diff @@ -0,0 +1,26 @@ +- // MIR for `drop_debuginfo` before SimplifyCfg-final ++ // MIR for `drop_debuginfo` after SimplifyCfg-final + + fn drop_debuginfo(_1: &Foo, _2: bool) -> i32 { + debug foo_a => _3; + debug foo_b => _4; + let mut _0: i32; + let mut _3: &i32; + let mut _4: &i64; + + bb0: { +- switchInt(copy _2) -> [1: bb1, otherwise: bb2]; +- } +- +- bb1: { +- // DBG: _3 = &((*_1).0: i32); +- goto -> bb2; +- } +- +- bb2: { + // DBG: _4 = &((*_1).1: i64); + _0 = copy ((*_1).2: i32); + return; + } + } + diff --git a/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_1.SimplifyCfg-final.diff b/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_1.SimplifyCfg-final.diff new file mode 100644 index 00000000000..1c12358ad89 --- /dev/null +++ b/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_1.SimplifyCfg-final.diff @@ -0,0 +1,30 @@ +- // MIR for `preserve_debuginfo_1` before SimplifyCfg-final ++ // MIR for `preserve_debuginfo_1` after SimplifyCfg-final + + fn preserve_debuginfo_1(_1: &Foo, _2: &mut bool) -> i32 { + debug foo_a => _3; + debug foo_b => _4; + debug foo_c => _5; + let mut _0: i32; + let mut _3: &i32; + let mut _4: &i64; + let mut _5: &i32; + + bb0: { +- goto -> bb1; +- } +- +- bb1: { + (*_2) = const true; + // DBG: _3 = &((*_1).0: i32); +- goto -> bb2; +- } +- +- bb2: { + // DBG: _4 = &((*_1).1: i64); + _0 = copy ((*_1).2: i32); + // DBG: _5 = &((*_1).2: i32); + return; + } + } + diff --git a/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_2.SimplifyCfg-final.diff b/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_2.SimplifyCfg-final.diff new file mode 100644 index 00000000000..de8e5612c87 --- /dev/null +++ b/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_2.SimplifyCfg-final.diff @@ -0,0 +1,29 @@ +- // MIR for `preserve_debuginfo_2` before SimplifyCfg-final ++ // MIR for `preserve_debuginfo_2` after SimplifyCfg-final + + fn preserve_debuginfo_2(_1: &Foo) -> i32 { + debug foo_a => _2; + debug foo_b => _3; + debug foo_c => _4; + let mut _0: i32; + let mut _2: &i32; + let mut _3: &i64; + let mut _4: &i32; + + bb0: { +- goto -> bb1; +- } +- +- bb1: { + // DBG: _2 = &((*_1).0: i32); +- goto -> bb2; +- } +- +- bb2: { + // DBG: _3 = &((*_1).1: i64); + _0 = copy ((*_1).2: i32); + // DBG: _4 = &((*_1).2: i32); + return; + } + } + diff --git a/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_3.SimplifyCfg-final.diff b/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_3.SimplifyCfg-final.diff new file mode 100644 index 00000000000..11372a262a7 --- /dev/null +++ b/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_3.SimplifyCfg-final.diff @@ -0,0 +1,37 @@ +- // MIR for `preserve_debuginfo_3` before SimplifyCfg-final ++ // MIR for `preserve_debuginfo_3` after SimplifyCfg-final + + fn preserve_debuginfo_3(_1: &Foo, _2: bool) -> i32 { + debug foo_a => _3; + debug foo_b => _4; + debug foo_c => _5; + let mut _0: i32; + let mut _3: &i32; + let mut _4: &i64; + let mut _5: &i32; + + bb0: { +- switchInt(copy _2) -> [1: bb1, otherwise: bb2]; ++ switchInt(copy _2) -> [1: bb2, otherwise: bb1]; + } + + bb1: { +- // DBG: _3 = &((*_1).0: i32); +- goto -> bb3; +- } +- +- bb2: { + // DBG: _4 = &((*_1).1: i64); + _0 = copy ((*_1).2: i32); + return; + } + +- bb3: { ++ bb2: { ++ // DBG: _3 = &((*_1).0: i32); + // DBG: _5 = &((*_1).2: i32); + _0 = copy ((*_1).0: i32); + return; + } + } + diff --git a/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_identical_succs.SimplifyCfg-final.diff b/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_identical_succs.SimplifyCfg-final.diff new file mode 100644 index 00000000000..0c6a75237d8 --- /dev/null +++ b/tests/mir-opt/debuginfo/simplifycfg.preserve_debuginfo_identical_succs.SimplifyCfg-final.diff @@ -0,0 +1,29 @@ +- // MIR for `preserve_debuginfo_identical_succs` before SimplifyCfg-final ++ // MIR for `preserve_debuginfo_identical_succs` after SimplifyCfg-final + + fn preserve_debuginfo_identical_succs(_1: &Foo, _2: bool) -> i32 { + debug foo_a => _3; + debug foo_b => _4; + debug foo_c => _5; + let mut _0: i32; + let mut _3: &i32; + let mut _4: &i64; + let mut _5: &i32; + + bb0: { +- switchInt(copy _2) -> [1: bb1, otherwise: bb1]; +- } +- +- bb1: { + // DBG: _3 = &((*_1).0: i32); +- goto -> bb2; +- } +- +- bb2: { + // DBG: _4 = &((*_1).1: i64); + _0 = copy ((*_1).2: i32); + // DBG: _5 = &((*_1).2: i32); + return; + } + } + diff --git a/tests/mir-opt/debuginfo/simplifycfg.rs b/tests/mir-opt/debuginfo/simplifycfg.rs new file mode 100644 index 00000000000..2bd510fd3b9 --- /dev/null +++ b/tests/mir-opt/debuginfo/simplifycfg.rs @@ -0,0 +1,207 @@ +//@ test-mir-pass: SimplifyCfg-final +//@ compile-flags: -Zmir-enable-passes=+DeadStoreElimination-initial + +#![feature(core_intrinsics, custom_mir)] +#![crate_type = "lib"] + +use std::intrinsics::mir::*; + +pub struct Foo { + a: i32, + b: i64, + c: i32, +} + +// EMIT_MIR simplifycfg.drop_debuginfo.SimplifyCfg-final.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn drop_debuginfo(foo: &Foo, c: bool) -> i32 { + // CHECK-LABEL: fn drop_debuginfo + // CHECK: debug foo_b => [[foo_b:_[0-9]+]]; + // CHECK: bb0: { + // CHECK-NEXT: DBG: [[foo_b]] = &((*_1).1: i64) + // CHECK-NEXT: _0 = copy ((*_1).2: i32); + // CHECK-NEXT: return; + mir! { + let _foo_a: &i32; + let _foo_b: &i64; + debug foo_a => _foo_a; + debug foo_b => _foo_b; + { + match c { + true => tmp, + _ => ret, + } + } + tmp = { + // Because we don't know if `c` is always true, we must drop this debuginfo. + _foo_a = &(*foo).a; + Goto(ret) + } + ret = { + _foo_b = &(*foo).b; + RET = (*foo).c; + Return() + } + } +} + +// EMIT_MIR simplifycfg.preserve_debuginfo_1.SimplifyCfg-final.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn preserve_debuginfo_1(foo: &Foo, v: &mut bool) -> i32 { + // CHECK-LABEL: fn preserve_debuginfo_1 + // CHECK: debug foo_a => [[foo_a:_[0-9]+]]; + // CHECK: debug foo_b => [[foo_b:_[0-9]+]]; + // CHECK: debug foo_c => [[foo_c:_[0-9]+]]; + // CHECK: bb0: { + // CHECK-NEXT: (*_2) = const true; + // CHECK-NEXT: DBG: [[foo_a]] = &((*_1).0: i32) + // CHECK-NEXT: DBG: [[foo_b]] = &((*_1).1: i64) + // CHECK-NEXT: _0 = copy ((*_1).2: i32); + // CHECK-NEXT: DBG: [[foo_c]] = &((*_1).2: i32) + // CHECK-NEXT: return; + mir! { + let _foo_a: &i32; + let _foo_b: &i64; + let _foo_c: &i32; + debug foo_a => _foo_a; + debug foo_b => _foo_b; + debug foo_c => _foo_c; + { + Goto(tmp) + } + tmp = { + *v = true; + _foo_a = &(*foo).a; + Goto(ret) + } + ret = { + _foo_b = &(*foo).b; + RET = (*foo).c; + _foo_c = &(*foo).c; + Return() + } + } +} + +// EMIT_MIR simplifycfg.preserve_debuginfo_2.SimplifyCfg-final.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn preserve_debuginfo_2(foo: &Foo) -> i32 { + // CHECK-LABEL: fn preserve_debuginfo_2 + // CHECK: debug foo_a => [[foo_a:_[0-9]+]]; + // CHECK: debug foo_b => [[foo_b:_[0-9]+]]; + // CHECK: debug foo_c => [[foo_c:_[0-9]+]]; + // CHECK: bb0: { + // CHECK-NEXT: DBG: [[foo_a]] = &((*_1).0: i32) + // CHECK-NEXT: DBG: [[foo_b]] = &((*_1).1: i64) + // CHECK-NEXT: _0 = copy ((*_1).2: i32); + // CHECK-NEXT: DBG: [[foo_c]] = &((*_1).2: i32) + // CHECK-NEXT: return; + mir! { + let _foo_a: &i32; + let _foo_b: &i64; + let _foo_c: &i32; + debug foo_a => _foo_a; + debug foo_b => _foo_b; + debug foo_c => _foo_c; + { + Goto(tmp) + } + tmp = { + _foo_a = &(*foo).a; + Goto(ret) + } + ret = { + _foo_b = &(*foo).b; + RET = (*foo).c; + _foo_c = &(*foo).c; + Return() + } + } +} + +// EMIT_MIR simplifycfg.preserve_debuginfo_3.SimplifyCfg-final.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn preserve_debuginfo_3(foo: &Foo, c: bool) -> i32 { + // CHECK-LABEL: fn preserve_debuginfo_3 + // CHECK: debug foo_a => [[foo_a:_[0-9]+]]; + // CHECK: debug foo_b => [[foo_b:_[0-9]+]]; + // CHECK: debug foo_c => [[foo_c:_[0-9]+]]; + // CHECK: bb0: { + // CHECK-NEXT: switchInt(copy _2) -> [1: bb2, otherwise: bb1]; + // CHECK: bb1: { + // CHECK-NEXT: DBG: [[foo_b]] = &((*_1).1: i64) + // CHECK-NEXT: _0 = copy ((*_1).2: i32); + // CHECK-NEXT: return; + // CHECK: bb2: { + // CHECK-NEXT: DBG: [[foo_a]] = &((*_1).0: i32) + // CHECK-NEXT: DBG: [[foo_c]] = &((*_1).2: i32) + // CHECK-NEXT: _0 = copy ((*_1).0: i32); + // CHECK-NEXT: return; + mir! { + let _foo_a: &i32; + let _foo_b: &i64; + let _foo_c: &i32; + debug foo_a => _foo_a; + debug foo_b => _foo_b; + debug foo_c => _foo_c; + { + match c { + true => tmp, + _ => ret, + } + } + tmp = { + _foo_a = &(*foo).a; + Goto(ret_1) + } + ret = { + _foo_b = &(*foo).b; + RET = (*foo).c; + Return() + } + ret_1 = { + _foo_c = &(*foo).c; + RET = (*foo).a; + Return() + } + } +} + +// EMIT_MIR simplifycfg.preserve_debuginfo_identical_succs.SimplifyCfg-final.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn preserve_debuginfo_identical_succs(foo: &Foo, c: bool) -> i32 { + // CHECK-LABEL: fn preserve_debuginfo_identical_succs + // CHECK: debug foo_a => [[foo_a:_[0-9]+]]; + // CHECK: debug foo_b => [[foo_b:_[0-9]+]]; + // CHECK: debug foo_c => [[foo_c:_[0-9]+]]; + // CHECK: bb0: { + // CHECK-NEXT: DBG: [[foo_a]] = &((*_1).0: i32) + // CHECK-NEXT: DBG: [[foo_b]] = &((*_1).1: i64) + // CHECK-NEXT: _0 = copy ((*_1).2: i32); + // CHECK-NEXT: DBG: [[foo_c]] = &((*_1).2: i32) + // CHECK-NEXT: return; + mir! { + let _foo_a: &i32; + let _foo_b: &i64; + let _foo_c: &i32; + debug foo_a => _foo_a; + debug foo_b => _foo_b; + debug foo_c => _foo_c; + { + match c { + true => tmp, + _ => tmp, + } + } + tmp = { + _foo_a = &(*foo).a; + Goto(ret) + } + ret = { + _foo_b = &(*foo).b; + RET = (*foo).c; + _foo_c = &(*foo).c; + Return() + } + } +} diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff index f6c111a2228..9509739413b 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff @@ -84,7 +84,6 @@ _5 = copy _2; - _0 = drop_in_place::<Option<B>>(move _5) -> [return: bb2, unwind unreachable]; + StorageLive(_15); -+ StorageLive(_16); + _15 = discriminant((*_5)); + switchInt(move _15) -> [0: bb5, otherwise: bb6]; } @@ -110,7 +109,6 @@ + } + + bb5: { -+ StorageDead(_16); + StorageDead(_15); StorageDead(_5); return; diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff index 18324276425..34f89da19f5 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-unwind.diff @@ -27,13 +27,11 @@ _5 = copy _2; - _0 = drop_in_place::<Option<B>>(move _5) -> [return: bb2, unwind continue]; + StorageLive(_6); -+ StorageLive(_7); + _6 = discriminant((*_5)); + switchInt(move _6) -> [0: bb2, otherwise: bb3]; } bb2: { -+ StorageDead(_7); + StorageDead(_6); StorageDead(_5); return; diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 2ae86e2eb8b..0acb33febe5 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -129,11 +129,8 @@ _10 = deref_copy (_1.1: &mut std::task::Context<'_>); _9 = &mut (*_10); - _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable]; -+ StorageLive(_11); -+ StorageLive(_15); + StorageLive(_16); + StorageLive(_25); -+ StorageLive(_27); + StorageLive(_30); + StorageLive(_31); + StorageLive(_32); @@ -166,11 +163,8 @@ + StorageDead(_32); + StorageDead(_31); + StorageDead(_30); -+ StorageDead(_27); + StorageDead(_25); + StorageDead(_16); -+ StorageDead(_15); -+ StorageDead(_11); StorageDead(_9); StorageDead(_8); StorageDead(_7); @@ -223,23 +217,15 @@ + _22 = &mut (*_23); + StorageDead(_24); + StorageLive(_44); -+ StorageLive(_45); + StorageLive(_49); + StorageLive(_41); + StorageLive(_42); -+ StorageLive(_43); -+ _45 = &mut _19; -+ StorageLive(_46); -+ _46 = &mut (_19.0: &mut std::future::Ready<()>); + _44 = copy (_19.0: &mut std::future::Ready<()>); -+ StorageDead(_46); -+ _43 = &mut ((*_44).0: std::option::Option<()>); + StorageLive(_47); + _47 = Option::<()>::None; + _42 = copy ((*_44).0: std::option::Option<()>); + ((*_44).0: std::option::Option<()>) = copy _47; + StorageDead(_47); -+ StorageDead(_43); + StorageLive(_48); + _48 = discriminant(_42); + switchInt(move _48) -> [0: bb11, 1: bb12, otherwise: bb5]; @@ -315,7 +301,6 @@ + _18 = Poll::<()>::Ready(move _41); + StorageDead(_41); + StorageDead(_49); -+ StorageDead(_45); + StorageDead(_44); + StorageDead(_22); + StorageDead(_19); diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index d7ae931aaae..98ee46c29b1 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -131,11 +131,8 @@ _10 = deref_copy (_1.1: &mut std::task::Context<'_>); _9 = &mut (*_10); - _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5]; -+ StorageLive(_11); -+ StorageLive(_15); + StorageLive(_16); + StorageLive(_25); -+ StorageLive(_27); + StorageLive(_30); + StorageLive(_31); + StorageLive(_32); @@ -180,11 +177,8 @@ + StorageDead(_32); + StorageDead(_31); + StorageDead(_30); -+ StorageDead(_27); + StorageDead(_25); + StorageDead(_16); -+ StorageDead(_15); -+ StorageDead(_11); StorageDead(_9); StorageDead(_8); StorageDead(_7); @@ -240,23 +234,15 @@ + _22 = &mut (*_23); + StorageDead(_24); + StorageLive(_46); -+ StorageLive(_47); + StorageLive(_51); + StorageLive(_43); + StorageLive(_44); -+ StorageLive(_45); -+ _47 = &mut _19; -+ StorageLive(_48); -+ _48 = &mut (_19.0: &mut std::future::Ready<()>); + _46 = copy (_19.0: &mut std::future::Ready<()>); -+ StorageDead(_48); -+ _45 = &mut ((*_46).0: std::option::Option<()>); + StorageLive(_49); + _49 = Option::<()>::None; + _44 = copy ((*_46).0: std::option::Option<()>); + ((*_46).0: std::option::Option<()>) = copy _49; + StorageDead(_49); -+ StorageDead(_45); + StorageLive(_50); + _50 = discriminant(_44); + switchInt(move _50) -> [0: bb16, 1: bb17, otherwise: bb7]; @@ -356,7 +342,6 @@ + _18 = Poll::<()>::Ready(move _43); + StorageDead(_43); + StorageDead(_51); -+ StorageDead(_47); + StorageDead(_46); + StorageDead(_22); + StorageDead(_19); diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff index ac88fe67bb8..3ea7387a48d 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-abort.diff @@ -30,7 +30,6 @@ StorageLive(_4); StorageLive(_5); _5 = copy _1; - nop; - StorageLive(_14); - _14 = BitAnd(copy _5, const 255_u32); - _4 = BitOr(const 0_u32, move _14); diff --git a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff index 96c3cae2d33..832db856b2c 100644 --- a/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff +++ b/tests/mir-opt/issue_101973.inner.GVN.panic-unwind.diff @@ -30,7 +30,6 @@ StorageLive(_4); StorageLive(_5); _5 = copy _1; - nop; - StorageLive(_14); - _14 = BitAnd(copy _5, const 255_u32); - _4 = BitOr(const 0_u32, move _14); diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff index 5cf36b9aebf..614d9ad440d 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff @@ -33,15 +33,9 @@ } bb2: { - StorageLive(_5); - _5 = &(*_2)[0 of 3]; - StorageLive(_6); - _6 = &(*_2)[1 of 3]; - StorageLive(_7); - _7 = &(*_2)[2 of 3]; - StorageDead(_7); - StorageDead(_6); - StorageDead(_5); + // DBG: _5 = &(*_2)[0 of 3]; + // DBG: _6 = &(*_2)[1 of 3]; + // DBG: _7 = &(*_2)[2 of 3]; StorageDead(_4); return; } diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff index 0598a3aa3f1..57a88cf8984 100644 --- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff +++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff @@ -33,15 +33,9 @@ } bb2: { - StorageLive(_5); - _5 = &(*_2)[0 of 3]; - StorageLive(_6); - _6 = &(*_2)[1 of 3]; - StorageLive(_7); - _7 = &(*_2)[2 of 3]; - StorageDead(_7); - StorageDead(_6); - StorageDead(_5); + // DBG: _5 = &(*_2)[0 of 3]; + // DBG: _6 = &(*_2)[1 of 3]; + // DBG: _7 = &(*_2)[2 of 3]; StorageDead(_4); return; } diff --git a/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir index 34747e5a928..1e6e2ee1b8b 100644 --- a/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/clone_as_copy.clone_as_copy.PreCodegen.after.mir @@ -12,10 +12,8 @@ fn clone_as_copy(_1: &NestCopy) -> NestCopy { } bb0: { - StorageLive(_2); - _2 = &((*_1).1: AllCopy); + // DBG: _2 = &((*_1).1: AllCopy); _0 = copy (*_1); - StorageDead(_2); return; } } diff --git a/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir index e67f362ee04..76bb49bc9c1 100644 --- a/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir @@ -5,58 +5,28 @@ fn enum_clone_as_copy(_1: &Enum1) -> Enum1 { let mut _0: Enum1; scope 1 (inlined <Enum1 as Clone>::clone) { debug self => _1; - let mut _2: isize; - let _3: &AllCopy; - let _4: &NestCopy; + let _2: &AllCopy; + let _3: &NestCopy; scope 2 { - debug __self_0 => _3; + debug __self_0 => _2; scope 6 (inlined <AllCopy as Clone>::clone) { - debug self => _3; + debug self => _2; } } scope 3 { - debug __self_0 => _4; + debug __self_0 => _3; scope 4 (inlined <NestCopy as Clone>::clone) { - debug self => _4; - let _5: &AllCopy; + debug self => _3; + let _4: &AllCopy; scope 5 (inlined <AllCopy as Clone>::clone) { - debug self => _5; + debug self => _4; } } } } bb0: { - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - _2 = discriminant((*_1)); - switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; - } - - bb1: { - _3 = &(((*_1) as A).0: AllCopy); _0 = copy (*_1); - goto -> bb3; - } - - bb2: { - _4 = &(((*_1) as B).0: NestCopy); - StorageLive(_5); - _5 = &((((*_1) as B).0: NestCopy).1: AllCopy); - StorageDead(_5); - _0 = copy (*_1); - goto -> bb3; - } - - bb3: { - StorageDead(_4); - StorageDead(_3); - StorageDead(_2); return; } - - bb4: { - unreachable; - } } diff --git a/tests/mir-opt/pre-codegen/clone_as_copy.rs b/tests/mir-opt/pre-codegen/clone_as_copy.rs index f5ff1854d38..00f24754d59 100644 --- a/tests/mir-opt/pre-codegen/clone_as_copy.rs +++ b/tests/mir-opt/pre-codegen/clone_as_copy.rs @@ -25,19 +25,19 @@ enum Enum1 { // EMIT_MIR clone_as_copy.clone_as_copy.PreCodegen.after.mir fn clone_as_copy(v: &NestCopy) -> NestCopy { // CHECK-LABEL: fn clone_as_copy( - // CHECK-NOT: = AllCopy { {{.*}} }; - // CHECK-NOT: = NestCopy { {{.*}} }; - // CHECK: _0 = copy (*_1); - // CHECK: return; + // CHECK: let [[DEAD_VAR:_.*]]: &AllCopy; + // CHECK: bb0: { + // CHECK-NEXT: DBG: [[DEAD_VAR]] = &((*_1).1: AllCopy) + // CHECK-NEXT: _0 = copy (*_1); + // CHECK-NEXT: return; v.clone() } -// FIXME: We can merge into exactly one assignment statement. // EMIT_MIR clone_as_copy.enum_clone_as_copy.PreCodegen.after.mir fn enum_clone_as_copy(v: &Enum1) -> Enum1 { // CHECK-LABEL: fn enum_clone_as_copy( - // CHECK-NOT: = Enum1:: - // CHECK: _0 = copy (*_1); - // CHECK: _0 = copy (*_1); + // CHECK: bb0: { + // CHECK-NEXT: _0 = copy (*_1); + // CHECK-NEXT: return; v.clone() } diff --git a/tests/mir-opt/pre-codegen/dead_on_invalid_place.invalid_place.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/dead_on_invalid_place.invalid_place.PreCodegen.after.mir new file mode 100644 index 00000000000..4a2127178fb --- /dev/null +++ b/tests/mir-opt/pre-codegen/dead_on_invalid_place.invalid_place.PreCodegen.after.mir @@ -0,0 +1,13 @@ +// MIR for `invalid_place` after PreCodegen + +fn invalid_place(_1: bool) -> bool { + debug c1_ref => _2; + let mut _0: bool; + let mut _2: &bool; + + bb0: { + // DBG: _2 = &?; + _0 = copy _1; + return; + } +} diff --git a/tests/mir-opt/pre-codegen/dead_on_invalid_place.rs b/tests/mir-opt/pre-codegen/dead_on_invalid_place.rs new file mode 100644 index 00000000000..5abe9fa43a5 --- /dev/null +++ b/tests/mir-opt/pre-codegen/dead_on_invalid_place.rs @@ -0,0 +1,27 @@ +#![feature(core_intrinsics, custom_mir)] +#![crate_type = "lib"] + +use std::intrinsics::mir::*; + +// EMIT_MIR dead_on_invalid_place.invalid_place.PreCodegen.after.mir +#[custom_mir(dialect = "runtime")] +pub fn invalid_place(c: bool) -> bool { + // CHECK-LABEL: fn invalid_place + // CHECK: debug c1_ref => [[c1_ref:_[0-9]+]]; + // CHECK: bb0: { + // We cannot read the reference, since `c1` is dead. + // CHECK-NEXT: DBG: [[c1_ref]] = &? + // CHECK-NEXT: _0 = copy _1; + // CHECK-NEXT: return; + mir! { + let _c1_ref: &bool; + let c1: bool; + debug c1_ref => _c1_ref; + { + c1 = c; + _c1_ref = &c1; + RET = c; + Return() + } + } +} diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir index 75e8cb1d861..8f30ad30fcc 100644 --- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir @@ -6,20 +6,20 @@ fn filter_mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> Option<U>) -> () let mut _0: (); let mut _3: std::iter::FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>>; let mut _4: std::iter::FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>>; - let mut _5: &mut std::iter::FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>>; - let mut _8: std::option::Option<U>; - let mut _9: isize; - let _11: (); + let mut _7: std::option::Option<U>; + let mut _8: isize; + let _10: (); + let mut _11: &mut std::iter::FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>>; scope 1 { debug iter => _4; - let _10: U; + let _9: U; scope 2 { - debug x => _10; + debug x => _9; } scope 4 (inlined <FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>> as Iterator>::next) { - debug self => _5; - let mut _6: &mut impl Iterator<Item = T>; - let mut _7: &mut impl Fn(T) -> Option<U>; + debug self => _11; + let mut _5: &mut impl Iterator<Item = T>; + let mut _6: &mut impl Fn(T) -> Option<U>; } } scope 3 (inlined <FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>> as IntoIterator>::into_iter) { @@ -37,24 +37,24 @@ fn filter_mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> Option<U>) -> () } bb2: { - StorageLive(_8); - _5 = &mut _4; - StorageLive(_6); - _6 = &mut (_4.0: impl Iterator<Item = T>); StorageLive(_7); - _7 = &mut (_4.1: impl Fn(T) -> Option<U>); - _8 = <impl Iterator<Item = T> as Iterator>::find_map::<U, &mut impl Fn(T) -> Option<U>>(move _6, move _7) -> [return: bb3, unwind: bb9]; + // DBG: _11 = &_4; + StorageLive(_5); + _5 = &mut (_4.0: impl Iterator<Item = T>); + StorageLive(_6); + _6 = &mut (_4.1: impl Fn(T) -> Option<U>); + _7 = <impl Iterator<Item = T> as Iterator>::find_map::<U, &mut impl Fn(T) -> Option<U>>(move _5, move _6) -> [return: bb3, unwind: bb9]; } bb3: { - StorageDead(_7); StorageDead(_6); - _9 = discriminant(_8); - switchInt(move _9) -> [0: bb4, 1: bb6, otherwise: bb8]; + StorageDead(_5); + _8 = discriminant(_7); + switchInt(move _8) -> [0: bb4, 1: bb6, otherwise: bb8]; } bb4: { - StorageDead(_8); + StorageDead(_7); drop(_4) -> [return: bb5, unwind continue]; } @@ -64,12 +64,12 @@ fn filter_mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> Option<U>) -> () } bb6: { - _10 = move ((_8 as Some).0: U); - _11 = opaque::<U>(move _10) -> [return: bb7, unwind: bb9]; + _9 = move ((_7 as Some).0: U); + _10 = opaque::<U>(move _9) -> [return: bb7, unwind: bb9]; } bb7: { - StorageDead(_8); + StorageDead(_7); goto -> bb2; } diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir index 154cbd3791c..beb7b936ccf 100644 --- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir @@ -5,32 +5,31 @@ fn int_range(_1: usize, _2: usize) -> () { debug end => _2; let mut _0: (); let mut _3: std::ops::Range<usize>; - let mut _4: std::ops::Range<usize>; - let mut _5: &mut std::ops::Range<usize>; - let mut _13: std::option::Option<usize>; - let _15: (); + let mut _9: std::option::Option<usize>; + let _11: (); + let mut _12: &mut std::ops::Range<usize>; scope 1 { - debug iter => _4; - let _14: usize; + debug iter => _3; + let _10: usize; scope 2 { - debug i => _14; + debug i => _10; } scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) { - debug self => _5; + debug self => _12; scope 5 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) { - debug self => _5; - let mut _6: &usize; - let mut _7: &usize; - let mut _10: bool; - let _11: usize; - let mut _12: usize; + debug self => _12; + let mut _6: bool; + let _7: usize; + let mut _8: usize; + let mut _13: &usize; + let mut _14: &usize; scope 6 { - debug old => _11; + debug old => _7; scope 8 (inlined <usize as Step>::forward_unchecked) { - debug start => _11; + debug start => _7; debug n => const 1_usize; scope 9 (inlined #[track_caller] core::num::<impl usize>::unchecked_add) { - debug self => _11; + debug self => _7; debug rhs => const 1_usize; scope 10 (inlined core::ub_checks::check_language_ub) { scope 11 (inlined core::ub_checks::check_language_ub::runtime) { @@ -40,10 +39,10 @@ fn int_range(_1: usize, _2: usize) -> () { } } scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::lt) { - debug self => _6; - debug other => _7; - let mut _8: usize; - let mut _9: usize; + debug self => _13; + debug other => _14; + let mut _4: usize; + let mut _5: usize; } } } @@ -54,54 +53,45 @@ fn int_range(_1: usize, _2: usize) -> () { bb0: { _3 = std::ops::Range::<usize> { start: copy _1, end: copy _2 }; - StorageLive(_4); - _4 = copy _3; goto -> bb1; } bb1: { - StorageLive(_13); - _5 = &mut _4; - StorageLive(_10); - StorageLive(_6); - _6 = &(_4.0: usize); - StorageLive(_7); - _7 = &(_4.1: usize); - StorageLive(_8); - _8 = copy (_4.0: usize); StorageLive(_9); - _9 = copy (_4.1: usize); - _10 = Lt(move _8, move _9); - StorageDead(_9); - StorageDead(_8); - switchInt(move _10) -> [0: bb2, otherwise: bb3]; + // DBG: _12 = &_3; + StorageLive(_6); + // DBG: _13 = &(_3.0: usize); + // DBG: _14 = &(_3.1: usize); + StorageLive(_4); + _4 = copy (_3.0: usize); + StorageLive(_5); + _5 = copy (_3.1: usize); + _6 = Lt(move _4, move _5); + StorageDead(_5); + StorageDead(_4); + switchInt(move _6) -> [0: bb2, otherwise: bb3]; } bb2: { - StorageDead(_7); StorageDead(_6); - StorageDead(_10); - StorageDead(_13); - StorageDead(_4); + StorageDead(_9); return; } bb3: { - StorageDead(_7); + _7 = copy (_3.0: usize); + StorageLive(_8); + _8 = AddUnchecked(copy _7, const 1_usize); + (_3.0: usize) = move _8; + StorageDead(_8); + _9 = Option::<usize>::Some(copy _7); StorageDead(_6); - _11 = copy (_4.0: usize); - StorageLive(_12); - _12 = AddUnchecked(copy _11, const 1_usize); - (_4.0: usize) = move _12; - StorageDead(_12); - _13 = Option::<usize>::Some(copy _11); - StorageDead(_10); - _14 = copy ((_13 as Some).0: usize); - _15 = opaque::<usize>(move _14) -> [return: bb4, unwind continue]; + _10 = copy ((_9 as Some).0: usize); + _11 = opaque::<usize>(move _10) -> [return: bb4, unwind continue]; } bb4: { - StorageDead(_13); + StorageDead(_9); goto -> bb1; } } diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index d22ea54004c..406c96fc32f 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -6,32 +6,32 @@ fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () { let mut _0: (); let mut _3: std::iter::Map<impl Iterator<Item = T>, impl Fn(T) -> U>; let mut _4: std::iter::Map<impl Iterator<Item = T>, impl Fn(T) -> U>; - let mut _5: &mut std::iter::Map<impl Iterator<Item = T>, impl Fn(T) -> U>; - let mut _13: std::option::Option<U>; - let _15: (); + let mut _12: std::option::Option<U>; + let _14: (); + let mut _15: &mut std::iter::Map<impl Iterator<Item = T>, impl Fn(T) -> U>; scope 1 { debug iter => _4; - let _14: U; + let _13: U; scope 2 { - debug x => _14; + debug x => _13; } scope 4 (inlined <Map<impl Iterator<Item = T>, impl Fn(T) -> U> as Iterator>::next) { - debug self => _5; - let mut _6: &mut impl Iterator<Item = T>; - let mut _7: std::option::Option<T>; - let mut _8: &mut impl Fn(T) -> U; + debug self => _15; + let mut _5: &mut impl Iterator<Item = T>; + let mut _6: std::option::Option<T>; + let mut _7: &mut impl Fn(T) -> U; scope 5 (inlined Option::<T>::map::<U, &mut impl Fn(T) -> U>) { - debug self => _7; - debug f => _8; - let mut _9: isize; - let _10: T; - let mut _11: (T,); - let mut _12: U; + debug self => _6; + debug f => _7; + let mut _8: isize; + let _9: T; + let mut _10: (T,); + let mut _11: U; scope 6 { - debug x => _10; + debug x => _9; scope 7 (inlined ops::function::impls::<impl FnOnce<(T,)> for &mut impl Fn(T) -> U>::call_once) { - debug self => _8; - debug args => _11; + debug self => _7; + debug args => _10; } } } @@ -52,30 +52,30 @@ fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () { } bb2: { - StorageLive(_13); - _5 = &mut _4; - StorageLive(_8); + StorageLive(_12); + // DBG: _15 = &_4; StorageLive(_7); StorageLive(_6); - _6 = &mut (_4.0: impl Iterator<Item = T>); - _7 = <impl Iterator<Item = T> as Iterator>::next(move _6) -> [return: bb3, unwind: bb10]; + StorageLive(_5); + _5 = &mut (_4.0: impl Iterator<Item = T>); + _6 = <impl Iterator<Item = T> as Iterator>::next(move _5) -> [return: bb3, unwind: bb10]; } bb3: { - StorageDead(_6); - _8 = &mut (_4.1: impl Fn(T) -> U); + StorageDead(_5); + _7 = &mut (_4.1: impl Fn(T) -> U); + StorageLive(_8); StorageLive(_9); - StorageLive(_10); - _9 = discriminant(_7); - switchInt(move _9) -> [0: bb4, 1: bb6, otherwise: bb9]; + _8 = discriminant(_6); + switchInt(move _8) -> [0: bb4, 1: bb6, otherwise: bb9]; } bb4: { - StorageDead(_10); StorageDead(_9); - StorageDead(_7); StorageDead(_8); - StorageDead(_13); + StorageDead(_6); + StorageDead(_7); + StorageDead(_12); drop(_4) -> [return: bb5, unwind continue]; } @@ -85,27 +85,27 @@ fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () { } bb6: { - _10 = move ((_7 as Some).0: T); - StorageLive(_12); + _9 = move ((_6 as Some).0: T); StorageLive(_11); - _11 = (copy _10,); - _12 = <impl Fn(T) -> U as FnMut<(T,)>>::call_mut(move _8, move _11) -> [return: bb7, unwind: bb10]; + StorageLive(_10); + _10 = (copy _9,); + _11 = <impl Fn(T) -> U as FnMut<(T,)>>::call_mut(move _7, move _10) -> [return: bb7, unwind: bb10]; } bb7: { - StorageDead(_11); - _13 = Option::<U>::Some(move _12); - StorageDead(_12); StorageDead(_10); + _12 = Option::<U>::Some(move _11); + StorageDead(_11); StorageDead(_9); - StorageDead(_7); StorageDead(_8); - _14 = move ((_13 as Some).0: U); - _15 = opaque::<U>(move _14) -> [return: bb8, unwind: bb10]; + StorageDead(_6); + StorageDead(_7); + _13 = move ((_12 as Some).0: U); + _14 = opaque::<U>(move _13) -> [return: bb8, unwind: bb10]; } bb8: { - StorageDead(_13); + StorageDead(_12); goto -> bb2; } diff --git a/tests/mir-opt/pre-codegen/loops.rs b/tests/mir-opt/pre-codegen/loops.rs index d0b8cc8db7a..952dd8cac60 100644 --- a/tests/mir-opt/pre-codegen/loops.rs +++ b/tests/mir-opt/pre-codegen/loops.rs @@ -1,5 +1,6 @@ // skip-filecheck //@ compile-flags: -O -Zmir-opt-level=2 -g +//@ ignore-std-debug-assertions (debug assertions result in different inlines) //@ needs-unwind #![crate_type = "lib"] diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir index e537dd6a28e..66eb1bcfaa6 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir @@ -3,72 +3,320 @@ fn vec_move(_1: Vec<impl Sized>) -> () { debug v => _1; let mut _0: (); - let mut _2: std::vec::IntoIter<impl Sized>; - let mut _3: std::vec::IntoIter<impl Sized>; - let mut _4: &mut std::vec::IntoIter<impl Sized>; - let mut _5: std::option::Option<impl Sized>; - let mut _6: isize; - let _8: (); + let mut _22: std::vec::IntoIter<impl Sized>; + let mut _23: std::vec::IntoIter<impl Sized>; + let mut _24: &mut std::vec::IntoIter<impl Sized>; + let mut _25: std::option::Option<impl Sized>; + let mut _26: isize; + let _28: (); scope 1 { - debug iter => _3; - let _7: impl Sized; + debug iter => _23; + let _27: impl Sized; scope 2 { - debug x => _7; + debug x => _27; + } + } + scope 3 (inlined <Vec<impl Sized> as IntoIterator>::into_iter) { + debug self => _1; + let _2: std::mem::ManuallyDrop<std::vec::Vec<impl Sized>>; + let mut _3: *const std::alloc::Global; + let mut _8: usize; + let mut _10: *mut impl Sized; + let mut _11: *const impl Sized; + let mut _12: usize; + let _29: &std::vec::Vec<impl Sized>; + let mut _30: &std::mem::ManuallyDrop<std::vec::Vec<impl Sized>>; + let mut _31: &alloc::raw_vec::RawVec<impl Sized>; + let mut _32: &std::mem::ManuallyDrop<std::vec::Vec<impl Sized>>; + let _33: &std::vec::Vec<impl Sized>; + let mut _34: &std::mem::ManuallyDrop<std::vec::Vec<impl Sized>>; + let _35: &std::vec::Vec<impl Sized>; + let mut _36: &std::mem::ManuallyDrop<std::vec::Vec<impl Sized>>; + let mut _37: &alloc::raw_vec::RawVec<impl Sized>; + let mut _38: &std::mem::ManuallyDrop<std::vec::Vec<impl Sized>>; + scope 4 { + debug me => _2; + scope 5 { + debug alloc => const ManuallyDrop::<std::alloc::Global> {{ value: std::alloc::Global }}; + let _6: std::ptr::NonNull<impl Sized>; + scope 6 { + debug buf => _6; + let _7: *mut impl Sized; + scope 7 { + debug begin => _7; + scope 8 { + debug end => _11; + let _20: usize; + scope 9 { + debug cap => _20; + } + scope 39 (inlined <ManuallyDrop<Vec<impl Sized>> as Deref>::deref) { + debug self => _38; + } + scope 40 (inlined alloc::raw_vec::RawVec::<impl Sized>::capacity) { + debug self => _37; + let mut _19: usize; + let mut _39: &alloc::raw_vec::RawVecInner; + scope 41 (inlined std::mem::size_of::<impl Sized>) { + } + scope 42 (inlined alloc::raw_vec::RawVecInner::capacity) { + debug self => _39; + debug elem_size => _19; + let mut _21: core::num::niche_types::UsizeNoHighBit; + scope 43 (inlined core::num::niche_types::UsizeNoHighBit::as_inner) { + debug self => _21; + } + } + } + } + scope 25 (inlined <ManuallyDrop<Vec<impl Sized>> as Deref>::deref) { + debug self => _34; + } + scope 26 (inlined Vec::<impl Sized>::len) { + debug self => _33; + let mut _13: bool; + scope 27 { + } + } + scope 28 (inlined std::ptr::mut_ptr::<impl *mut impl Sized>::wrapping_byte_add) { + debug self => _7; + debug count => _12; + let mut _14: *mut u8; + let mut _18: *mut u8; + scope 29 (inlined std::ptr::mut_ptr::<impl *mut impl Sized>::cast::<u8>) { + debug self => _7; + } + scope 30 (inlined std::ptr::mut_ptr::<impl *mut u8>::wrapping_add) { + debug self => _14; + debug count => _12; + let mut _15: isize; + scope 31 (inlined std::ptr::mut_ptr::<impl *mut u8>::wrapping_offset) { + debug self => _14; + debug count => _15; + let mut _16: *const u8; + let mut _17: *const u8; + } + } + scope 32 (inlined std::ptr::mut_ptr::<impl *mut u8>::with_metadata_of::<impl Sized>) { + debug self => _18; + debug meta => _5; + scope 33 (inlined std::ptr::metadata::<impl Sized>) { + debug ptr => _5; + } + scope 34 (inlined std::ptr::from_raw_parts_mut::<impl Sized, ()>) { + } + } + } + scope 35 (inlined <ManuallyDrop<Vec<impl Sized>> as Deref>::deref) { + debug self => _36; + } + scope 36 (inlined Vec::<impl Sized>::len) { + debug self => _35; + let mut _9: bool; + scope 37 { + } + } + scope 38 (inlined #[track_caller] std::ptr::mut_ptr::<impl *mut impl Sized>::add) { + debug self => _7; + debug count => _8; + } + } + scope 24 (inlined NonNull::<impl Sized>::as_ptr) { + debug self => _6; + } + } + scope 17 (inlined <ManuallyDrop<Vec<impl Sized>> as Deref>::deref) { + debug self => _32; + } + scope 18 (inlined alloc::raw_vec::RawVec::<impl Sized>::non_null) { + debug self => _31; + scope 19 (inlined alloc::raw_vec::RawVecInner::non_null::<impl Sized>) { + let mut _4: std::ptr::NonNull<u8>; + scope 20 (inlined Unique::<u8>::cast::<impl Sized>) { + scope 21 (inlined NonNull::<u8>::cast::<impl Sized>) { + let mut _5: *const impl Sized; + scope 22 (inlined NonNull::<u8>::as_ptr) { + } + } + } + scope 23 (inlined Unique::<impl Sized>::as_non_null_ptr) { + } + } + } + } + scope 11 (inlined <ManuallyDrop<Vec<impl Sized>> as Deref>::deref) { + debug self => _30; + } + scope 12 (inlined Vec::<impl Sized>::allocator) { + debug self => _29; + scope 13 (inlined alloc::raw_vec::RawVec::<impl Sized>::allocator) { + scope 14 (inlined alloc::raw_vec::RawVecInner::allocator) { + } + } + } + scope 15 (inlined #[track_caller] std::ptr::read::<std::alloc::Global>) { + debug src => _3; + } + scope 16 (inlined ManuallyDrop::<std::alloc::Global>::new) { + debug value => const std::alloc::Global; + } + } + scope 10 (inlined ManuallyDrop::<Vec<impl Sized>>::new) { + debug value => _1; } } bb0: { + StorageLive(_22); + StorageLive(_6); + StorageLive(_7); + StorageLive(_11); + StorageLive(_20); + StorageLive(_5); + StorageLive(_4); + StorageLive(_17); StorageLive(_2); - _2 = <Vec<impl Sized> as IntoIterator>::into_iter(move _1) -> [return: bb1, unwind continue]; + _2 = ManuallyDrop::<Vec<impl Sized>> { value: copy _1 }; + StorageLive(_3); + // DBG: _30 = &_2; + // DBG: _29 = &(_2.0: std::vec::Vec<impl Sized>); + _3 = &raw const ((((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>).0: alloc::raw_vec::RawVecInner).2: std::alloc::Global); + StorageDead(_3); + // DBG: _32 = &_2; + // DBG: _31 = &((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>); + _4 = copy (((((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique<u8>).0: std::ptr::NonNull<u8>); + _5 = copy _4 as *const impl Sized (Transmute); + _6 = NonNull::<impl Sized> { pointer: copy _5 }; + _7 = copy _4 as *mut impl Sized (Transmute); + switchInt(const <impl Sized as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_3); - _3 = move _2; - goto -> bb2; + StorageLive(_10); + StorageLive(_8); + // DBG: _36 = &_2; + // DBG: _35 = &(_2.0: std::vec::Vec<impl Sized>); + _8 = copy ((_2.0: std::vec::Vec<impl Sized>).1: usize); + StorageLive(_9); + _9 = Le(copy _8, const <impl Sized as std::mem::SizedTypeProperties>::MAX_SLICE_LEN); + assume(move _9); + StorageDead(_9); + _10 = Offset(copy _7, copy _8); + _11 = copy _10 as *const impl Sized (PtrToPtr); + StorageDead(_8); + StorageDead(_10); + goto -> bb4; } bb2: { - StorageLive(_5); - _4 = &mut _3; - _5 = <std::vec::IntoIter<impl Sized> as Iterator>::next(move _4) -> [return: bb3, unwind: bb9]; + StorageLive(_12); + // DBG: _34 = &_2; + // DBG: _33 = &(_2.0: std::vec::Vec<impl Sized>); + _12 = copy ((_2.0: std::vec::Vec<impl Sized>).1: usize); + StorageLive(_13); + _13 = Le(copy _12, const <impl Sized as std::mem::SizedTypeProperties>::MAX_SLICE_LEN); + assume(move _13); + StorageDead(_13); + StorageLive(_18); + StorageLive(_14); + _14 = copy _4 as *mut u8 (Transmute); + StorageLive(_15); + _15 = copy _12 as isize (IntToInt); + StorageLive(_16); + _16 = copy _4 as *const u8 (Transmute); + _17 = arith_offset::<u8>(move _16, move _15) -> [return: bb3, unwind unreachable]; } bb3: { - _6 = discriminant(_5); - switchInt(move _6) -> [0: bb4, 1: bb6, otherwise: bb8]; + StorageDead(_16); + _18 = copy _17 as *mut u8 (PtrToPtr); + StorageDead(_15); + StorageDead(_14); + StorageDead(_18); + StorageDead(_12); + _11 = copy _17 as *const impl Sized (PtrToPtr); + goto -> bb4; } bb4: { - StorageDead(_5); - drop(_3) -> [return: bb5, unwind continue]; + // DBG: _38 = &_2; + // DBG: _37 = &((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>); + // DBG: _39 = &(((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>).0: alloc::raw_vec::RawVecInner); + StorageLive(_19); + _19 = SizeOf(impl Sized); + switchInt(move _19) -> [0: bb5, otherwise: bb6]; } bb5: { - StorageDead(_3); - StorageDead(_2); - return; + _20 = const usize::MAX; + goto -> bb7; } bb6: { - _7 = move ((_5 as Some).0: impl Sized); - _8 = opaque::<impl Sized>(move _7) -> [return: bb7, unwind: bb9]; + StorageLive(_21); + _21 = copy ((((_2.0: std::vec::Vec<impl Sized>).0: alloc::raw_vec::RawVec<impl Sized>).0: alloc::raw_vec::RawVecInner).1: core::num::niche_types::UsizeNoHighBit); + _20 = copy _21 as usize (Transmute); + StorageDead(_21); + goto -> bb7; } bb7: { + StorageDead(_19); + _22 = std::vec::IntoIter::<impl Sized> { buf: copy _6, phantom: const ZeroSized: PhantomData<impl Sized>, cap: move _20, alloc: const ManuallyDrop::<std::alloc::Global> {{ value: std::alloc::Global }}, ptr: copy _6, end: copy _11 }; + StorageDead(_2); + StorageDead(_17); + StorageDead(_4); StorageDead(_5); - goto -> bb2; + StorageDead(_20); + StorageDead(_11); + StorageDead(_7); + StorageDead(_6); + StorageLive(_23); + _23 = move _22; + goto -> bb8; } bb8: { + StorageLive(_25); + _24 = &mut _23; + _25 = <std::vec::IntoIter<impl Sized> as Iterator>::next(move _24) -> [return: bb9, unwind: bb15]; + } + + bb9: { + _26 = discriminant(_25); + switchInt(move _26) -> [0: bb10, 1: bb12, otherwise: bb14]; + } + + bb10: { + StorageDead(_25); + drop(_23) -> [return: bb11, unwind continue]; + } + + bb11: { + StorageDead(_23); + StorageDead(_22); + return; + } + + bb12: { + _27 = move ((_25 as Some).0: impl Sized); + _28 = opaque::<impl Sized>(move _27) -> [return: bb13, unwind: bb15]; + } + + bb13: { + StorageDead(_25); + goto -> bb8; + } + + bb14: { unreachable; } - bb9 (cleanup): { - drop(_3) -> [return: bb10, unwind terminate(cleanup)]; + bb15 (cleanup): { + drop(_23) -> [return: bb16, unwind terminate(cleanup)]; } - bb10 (cleanup): { + bb16 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir index cbdd194afd3..2cab8818296 100644 --- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir @@ -3,183 +3,134 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2: &&(usize, usize, usize, usize)) -> bool { let mut _0: bool; let mut _3: &(usize, usize, usize, usize); - let _4: &usize; - let _5: &usize; - let _6: &usize; - let _7: &usize; - let mut _8: &&usize; - let _9: &usize; - let mut _10: &&usize; - let mut _13: bool; - let mut _14: &&usize; + let mut _6: bool; + let mut _9: bool; + let mut _10: bool; + let _13: &usize; + let _14: &usize; let _15: &usize; - let mut _16: &&usize; - let mut _19: bool; + let _16: &usize; + let mut _17: &&usize; + let mut _18: &&usize; + let mut _19: &&usize; let mut _20: &&usize; - let _21: &usize; + let mut _21: &&usize; let mut _22: &&usize; - let mut _23: bool; + let mut _23: &&usize; let mut _24: &&usize; - let _25: &usize; - let mut _26: &&usize; scope 1 { - debug a => _4; - debug b => _5; - debug c => _6; - debug d => _7; + debug a => _13; + debug b => _14; + debug c => _15; + debug d => _16; scope 2 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _8; - debug other => _10; + debug self => _17; + debug other => _18; scope 3 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _4; - debug other => _6; - let mut _11: usize; - let mut _12: usize; + debug self => _13; + debug other => _15; + let mut _4: usize; + let mut _5: usize; } } scope 4 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _14; - debug other => _16; + debug self => _19; + debug other => _20; scope 5 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _7; - debug other => _5; - let mut _17: usize; - let mut _18: usize; + debug self => _16; + debug other => _14; + let mut _7: usize; + let mut _8: usize; } } scope 6 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _20; + debug self => _21; debug other => _22; scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _6; - debug other => _4; + debug self => _15; + debug other => _13; } } scope 8 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) { - debug self => _24; - debug other => _26; + debug self => _23; + debug other => _24; scope 9 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) { - debug self => _5; - debug other => _7; - let mut _27: usize; - let mut _28: usize; + debug self => _14; + debug other => _16; + let mut _11: usize; + let mut _12: usize; } } } bb0: { _3 = copy (*_2); - _4 = &((*_3).0: usize); - _5 = &((*_3).1: usize); - _6 = &((*_3).2: usize); - _7 = &((*_3).3: usize); - StorageLive(_13); - StorageLive(_8); - _8 = &_4; - StorageLive(_10); - StorageLive(_9); - _9 = copy _6; - _10 = &_9; - _11 = copy ((*_3).0: usize); - _12 = copy ((*_3).2: usize); - _13 = Le(copy _11, copy _12); - switchInt(move _13) -> [0: bb1, otherwise: bb2]; + // DBG: _13 = &((*_3).0: usize); + // DBG: _14 = &((*_3).1: usize); + // DBG: _15 = &((*_3).2: usize); + // DBG: _16 = &((*_3).3: usize); + StorageLive(_6); + // DBG: _17 = &_13; + // DBG: _18 = &?; + _4 = copy ((*_3).0: usize); + _5 = copy ((*_3).2: usize); + _6 = Le(copy _4, copy _5); + switchInt(move _6) -> [0: bb2, otherwise: bb1]; } bb1: { - StorageDead(_9); - StorageDead(_10); + StorageLive(_9); + // DBG: _19 = &_16; + // DBG: _20 = &?; + StorageLive(_7); + _7 = copy ((*_3).3: usize); + StorageLive(_8); + _8 = copy ((*_3).1: usize); + _9 = Le(move _7, move _8); StorageDead(_8); - goto -> bb4; + StorageDead(_7); + switchInt(move _9) -> [0: bb2, otherwise: bb6]; } bb2: { - StorageDead(_9); - StorageDead(_10); - StorageDead(_8); - StorageLive(_19); - StorageLive(_14); - _14 = &_7; - StorageLive(_16); - StorageLive(_15); - _15 = copy _5; - _16 = &_15; - StorageLive(_17); - _17 = copy ((*_3).3: usize); - StorageLive(_18); - _18 = copy ((*_3).1: usize); - _19 = Le(move _17, move _18); - StorageDead(_18); - StorageDead(_17); - switchInt(move _19) -> [0: bb3, otherwise: bb8]; + StorageLive(_10); + // DBG: _21 = &_15; + // DBG: _22 = &?; + _10 = Le(copy _5, copy _4); + switchInt(move _10) -> [0: bb3, otherwise: bb4]; } bb3: { - StorageDead(_15); - StorageDead(_16); - StorageDead(_14); - goto -> bb4; + _0 = const false; + goto -> bb5; } bb4: { - StorageLive(_23); - StorageLive(_20); - _20 = &_6; - StorageLive(_22); - StorageLive(_21); - _21 = copy _4; - _22 = &_21; - _23 = Le(copy _12, copy _11); - switchInt(move _23) -> [0: bb5, otherwise: bb6]; + // DBG: _23 = &_14; + // DBG: _24 = &?; + StorageLive(_11); + _11 = copy ((*_3).1: usize); + StorageLive(_12); + _12 = copy ((*_3).3: usize); + _0 = Le(move _11, move _12); + StorageDead(_12); + StorageDead(_11); + goto -> bb5; } bb5: { - StorageDead(_21); - StorageDead(_22); - StorageDead(_20); - _0 = const false; + StorageDead(_10); goto -> bb7; } bb6: { - StorageDead(_21); - StorageDead(_22); - StorageDead(_20); - StorageLive(_24); - _24 = &_5; - StorageLive(_26); - StorageLive(_25); - _25 = copy _7; - _26 = &_25; - StorageLive(_27); - _27 = copy ((*_3).1: usize); - StorageLive(_28); - _28 = copy ((*_3).3: usize); - _0 = Le(move _27, move _28); - StorageDead(_28); - StorageDead(_27); - StorageDead(_25); - StorageDead(_26); - StorageDead(_24); + _0 = const true; goto -> bb7; } bb7: { - StorageDead(_23); - goto -> bb9; - } - - bb8: { - StorageDead(_15); - StorageDead(_16); - StorageDead(_14); - _0 = const true; - goto -> bb9; - } - - bb9: { - StorageDead(_19); - StorageDead(_13); + StorageDead(_9); + StorageDead(_6); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index 0adf268d766..3009be3f9dc 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -7,19 +7,87 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _10: std::slice::Iter<'_, T>; let mut _11: std::iter::Rev<std::slice::Iter<'_, T>>; let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>; - let mut _14: std::option::Option<&T>; - let mut _15: isize; - let mut _17: &impl Fn(&T); - let mut _18: (&T,); - let _19: (); + let mut _33: std::option::Option<&T>; + let mut _35: &impl Fn(&T); + let mut _36: (&T,); + let _37: (); scope 1 { debug iter => _12; - let _16: &T; + let _34: &T; scope 2 { - debug x => _16; + debug x => _34; } scope 18 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { - let mut _13: &mut std::slice::Iter<'_, T>; + scope 19 (inlined <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back) { + let mut _13: *const T; + let mut _18: bool; + let mut _19: *const T; + let _32: &T; + scope 20 { + let _14: std::ptr::NonNull<T>; + let _20: usize; + scope 21 { + } + scope 22 { + scope 25 (inlined <NonNull<T> as PartialEq>::eq) { + let mut _15: std::ptr::NonNull<T>; + let mut _16: *mut T; + let mut _17: *mut T; + scope 26 (inlined NonNull::<T>::as_ptr) { + } + scope 27 (inlined NonNull::<T>::as_ptr) { + } + } + } + scope 23 (inlined std::ptr::const_ptr::<impl *const T>::addr) { + scope 24 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) { + } + } + } + scope 28 (inlined std::slice::Iter::<'_, T>::next_back_unchecked) { + let _26: std::ptr::NonNull<T>; + scope 29 (inlined std::slice::Iter::<'_, T>::pre_dec_end) { + let mut _21: *mut *const T; + let mut _22: *mut std::ptr::NonNull<T>; + let mut _23: std::ptr::NonNull<T>; + let mut _27: *mut *const T; + let mut _28: *mut usize; + let mut _29: usize; + let mut _30: usize; + scope 30 { + scope 31 { + } + scope 32 { + scope 35 (inlined NonNull::<T>::sub) { + scope 36 (inlined #[track_caller] core::num::<impl isize>::unchecked_neg) { + scope 37 (inlined core::ub_checks::check_language_ub) { + scope 38 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + scope 39 (inlined NonNull::<T>::offset) { + let mut _24: *const T; + let mut _25: *const T; + scope 40 (inlined NonNull::<T>::as_ptr) { + } + } + } + } + scope 33 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<usize>) { + } + scope 34 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<NonNull<T>>) { + } + } + } + scope 41 (inlined NonNull::<T>::as_ref::<'_>) { + let _31: *const T; + scope 42 (inlined NonNull::<T>::as_ptr) { + } + scope 43 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) { + } + } + } + } } } scope 3 (inlined core::slice::<impl [T]>::iter) { @@ -105,45 +173,136 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb4: { + StorageLive(_33); + StorageLive(_20); + StorageLive(_19); StorageLive(_14); - StorageLive(_13); - _13 = &mut (_12.0: std::slice::Iter<'_, T>); - _14 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _13) -> [return: bb5, unwind unreachable]; + StorageLive(_32); + StorageLive(_18); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb6]; } bb5: { + StorageLive(_13); + _13 = copy ((_12.0: std::slice::Iter<'_, T>).1: *const T); + _14 = copy _13 as std::ptr::NonNull<T> (Transmute); StorageDead(_13); - _15 = discriminant(_14); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageLive(_16); + StorageLive(_15); + _15 = copy ((_12.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>); + _16 = copy _15 as *mut T (Transmute); + StorageDead(_15); + StorageLive(_17); + _17 = copy _14 as *mut T (Transmute); + _18 = Eq(copy _16, copy _17); + StorageDead(_17); + StorageDead(_16); + goto -> bb7; } bb6: { - StorageDead(_14); - StorageDead(_12); - drop(_2) -> [return: bb7, unwind unreachable]; + _19 = copy ((_12.0: std::slice::Iter<'_, T>).1: *const T); + _20 = copy _19 as usize (Transmute); + _18 = Eq(copy _20, const 0_usize); + goto -> bb7; } bb7: { - return; + switchInt(move _18) -> [0: bb8, otherwise: bb15]; } bb8: { - _16 = copy ((_14 as Some).0: &T); - StorageLive(_17); - _17 = &_2; - StorageLive(_18); - _18 = (copy _16,); - _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind unreachable]; + StorageLive(_26); + StorageLive(_28); + StorageLive(_22); + StorageLive(_23); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb9, otherwise: bb12]; } bb9: { + StorageLive(_21); + _21 = &raw mut ((_12.0: std::slice::Iter<'_, T>).1: *const T); + _22 = copy _21 as *mut std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_21); + _23 = copy (*_22); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb10, otherwise: bb11]; + } + + bb10: { + StorageLive(_25); + StorageLive(_24); + _24 = copy _23 as *const T (Transmute); + _25 = Offset(copy _24, const -1_isize); + StorageDead(_24); + _23 = NonNull::<T> { pointer: copy _25 }; + StorageDead(_25); + goto -> bb11; + } + + bb11: { + (*_22) = move _23; + _26 = copy (*_22); + goto -> bb13; + } + + bb12: { + StorageLive(_27); + _27 = &raw mut ((_12.0: std::slice::Iter<'_, T>).1: *const T); + _28 = copy _27 as *mut usize (PtrToPtr); + StorageDead(_27); + StorageLive(_30); + StorageLive(_29); + _29 = copy (*_28); + _30 = SubUnchecked(move _29, const 1_usize); + StorageDead(_29); + (*_28) = move _30; + StorageDead(_30); + _26 = copy ((_12.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>); + goto -> bb13; + } + + bb13: { + StorageDead(_23); + StorageDead(_22); + StorageDead(_28); + StorageLive(_31); + _31 = copy _26 as *const T (Transmute); + _32 = &(*_31); + StorageDead(_31); + StorageDead(_26); + _33 = Option::<&T>::Some(copy _32); StorageDead(_18); - StorageDead(_17); + StorageDead(_32); StorageDead(_14); + StorageDead(_19); + StorageDead(_20); + _34 = copy ((_33 as Some).0: &T); + StorageLive(_35); + _35 = &_2; + StorageLive(_36); + _36 = (copy _34,); + _37 = <impl Fn(&T) as Fn<(&T,)>>::call(move _35, move _36) -> [return: bb14, unwind unreachable]; + } + + bb14: { + StorageDead(_36); + StorageDead(_35); + StorageDead(_33); goto -> bb4; } - bb10: { - unreachable; + bb15: { + StorageDead(_18); + StorageDead(_32); + StorageDead(_14); + StorageDead(_19); + StorageDead(_20); + StorageDead(_33); + StorageDead(_12); + drop(_2) -> [return: bb16, unwind unreachable]; + } + + bb16: { + return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index cb0d640d445..e40bff5ea35 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -7,19 +7,87 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { let mut _10: std::slice::Iter<'_, T>; let mut _11: std::iter::Rev<std::slice::Iter<'_, T>>; let mut _12: std::iter::Rev<std::slice::Iter<'_, T>>; - let mut _14: std::option::Option<&T>; - let mut _15: isize; - let mut _17: &impl Fn(&T); - let mut _18: (&T,); - let _19: (); + let mut _33: std::option::Option<&T>; + let mut _35: &impl Fn(&T); + let mut _36: (&T,); + let _37: (); scope 1 { debug iter => _12; - let _16: &T; + let _34: &T; scope 2 { - debug x => _16; + debug x => _34; } scope 18 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) { - let mut _13: &mut std::slice::Iter<'_, T>; + scope 19 (inlined <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back) { + let mut _13: *const T; + let mut _18: bool; + let mut _19: *const T; + let _32: &T; + scope 20 { + let _14: std::ptr::NonNull<T>; + let _20: usize; + scope 21 { + } + scope 22 { + scope 25 (inlined <NonNull<T> as PartialEq>::eq) { + let mut _15: std::ptr::NonNull<T>; + let mut _16: *mut T; + let mut _17: *mut T; + scope 26 (inlined NonNull::<T>::as_ptr) { + } + scope 27 (inlined NonNull::<T>::as_ptr) { + } + } + } + scope 23 (inlined std::ptr::const_ptr::<impl *const T>::addr) { + scope 24 (inlined std::ptr::const_ptr::<impl *const T>::cast::<()>) { + } + } + } + scope 28 (inlined std::slice::Iter::<'_, T>::next_back_unchecked) { + let _26: std::ptr::NonNull<T>; + scope 29 (inlined std::slice::Iter::<'_, T>::pre_dec_end) { + let mut _21: *mut *const T; + let mut _22: *mut std::ptr::NonNull<T>; + let mut _23: std::ptr::NonNull<T>; + let mut _27: *mut *const T; + let mut _28: *mut usize; + let mut _29: usize; + let mut _30: usize; + scope 30 { + scope 31 { + } + scope 32 { + scope 35 (inlined NonNull::<T>::sub) { + scope 36 (inlined #[track_caller] core::num::<impl isize>::unchecked_neg) { + scope 37 (inlined core::ub_checks::check_language_ub) { + scope 38 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + scope 39 (inlined NonNull::<T>::offset) { + let mut _24: *const T; + let mut _25: *const T; + scope 40 (inlined NonNull::<T>::as_ptr) { + } + } + } + } + scope 33 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<usize>) { + } + scope 34 (inlined std::ptr::mut_ptr::<impl *mut *const T>::cast::<NonNull<T>>) { + } + } + } + scope 41 (inlined NonNull::<T>::as_ref::<'_>) { + let _31: *const T; + scope 42 (inlined NonNull::<T>::as_ptr) { + } + scope 43 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) { + } + } + } + } } } scope 3 (inlined core::slice::<impl [T]>::iter) { @@ -105,53 +173,144 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb4: { + StorageLive(_33); + StorageLive(_20); + StorageLive(_19); StorageLive(_14); - StorageLive(_13); - _13 = &mut (_12.0: std::slice::Iter<'_, T>); - _14 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _13) -> [return: bb5, unwind: bb11]; + StorageLive(_32); + StorageLive(_18); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb6]; } bb5: { + StorageLive(_13); + _13 = copy ((_12.0: std::slice::Iter<'_, T>).1: *const T); + _14 = copy _13 as std::ptr::NonNull<T> (Transmute); StorageDead(_13); - _15 = discriminant(_14); - switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageLive(_16); + StorageLive(_15); + _15 = copy ((_12.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>); + _16 = copy _15 as *mut T (Transmute); + StorageDead(_15); + StorageLive(_17); + _17 = copy _14 as *mut T (Transmute); + _18 = Eq(copy _16, copy _17); + StorageDead(_17); + StorageDead(_16); + goto -> bb7; } bb6: { - StorageDead(_14); - StorageDead(_12); - drop(_2) -> [return: bb7, unwind continue]; + _19 = copy ((_12.0: std::slice::Iter<'_, T>).1: *const T); + _20 = copy _19 as usize (Transmute); + _18 = Eq(copy _20, const 0_usize); + goto -> bb7; } bb7: { - return; + switchInt(move _18) -> [0: bb8, otherwise: bb17]; } bb8: { - _16 = copy ((_14 as Some).0: &T); - StorageLive(_17); - _17 = &_2; - StorageLive(_18); - _18 = (copy _16,); - _19 = <impl Fn(&T) as Fn<(&T,)>>::call(move _17, move _18) -> [return: bb9, unwind: bb11]; + StorageLive(_26); + StorageLive(_28); + StorageLive(_22); + StorageLive(_23); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb9, otherwise: bb12]; } bb9: { + StorageLive(_21); + _21 = &raw mut ((_12.0: std::slice::Iter<'_, T>).1: *const T); + _22 = copy _21 as *mut std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_21); + _23 = copy (*_22); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb10, otherwise: bb11]; + } + + bb10: { + StorageLive(_25); + StorageLive(_24); + _24 = copy _23 as *const T (Transmute); + _25 = Offset(copy _24, const -1_isize); + StorageDead(_24); + _23 = NonNull::<T> { pointer: copy _25 }; + StorageDead(_25); + goto -> bb11; + } + + bb11: { + (*_22) = move _23; + _26 = copy (*_22); + goto -> bb13; + } + + bb12: { + StorageLive(_27); + _27 = &raw mut ((_12.0: std::slice::Iter<'_, T>).1: *const T); + _28 = copy _27 as *mut usize (PtrToPtr); + StorageDead(_27); + StorageLive(_30); + StorageLive(_29); + _29 = copy (*_28); + _30 = SubUnchecked(move _29, const 1_usize); + StorageDead(_29); + (*_28) = move _30; + StorageDead(_30); + _26 = copy ((_12.0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>); + goto -> bb13; + } + + bb13: { + StorageDead(_23); + StorageDead(_22); + StorageDead(_28); + StorageLive(_31); + _31 = copy _26 as *const T (Transmute); + _32 = &(*_31); + StorageDead(_31); + StorageDead(_26); + _33 = Option::<&T>::Some(copy _32); StorageDead(_18); - StorageDead(_17); + StorageDead(_32); StorageDead(_14); - goto -> bb4; + StorageDead(_19); + StorageDead(_20); + _34 = copy ((_33 as Some).0: &T); + StorageLive(_35); + _35 = &_2; + StorageLive(_36); + _36 = (copy _34,); + _37 = <impl Fn(&T) as Fn<(&T,)>>::call(move _35, move _36) -> [return: bb14, unwind: bb15]; } - bb10: { - unreachable; + bb14: { + StorageDead(_36); + StorageDead(_35); + StorageDead(_33); + goto -> bb4; } - bb11 (cleanup): { - drop(_2) -> [return: bb12, unwind terminate(cleanup)]; + bb15 (cleanup): { + drop(_2) -> [return: bb16, unwind terminate(cleanup)]; } - bb12 (cleanup): { + bb16 (cleanup): { resume; } + + bb17: { + StorageDead(_18); + StorageDead(_32); + StorageDead(_14); + StorageDead(_19); + StorageDead(_20); + StorageDead(_33); + StorageDead(_12); + drop(_2) -> [return: bb18, unwind continue]; + } + + bb18: { + return; + } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir index 78f96bf4195..62b738c36bf 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-abort.mir @@ -3,12 +3,187 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut T> { debug it => _1; let mut _0: std::option::Option<&mut T>; + scope 1 (inlined <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back) { + let mut _2: *mut T; + let mut _7: bool; + let mut _8: *mut T; + let mut _21: &mut T; + scope 2 { + let _3: std::ptr::NonNull<T>; + let _9: usize; + scope 3 { + } + scope 4 { + scope 7 (inlined <NonNull<T> as PartialEq>::eq) { + let mut _4: std::ptr::NonNull<T>; + let mut _5: *mut T; + let mut _6: *mut T; + scope 8 (inlined NonNull::<T>::as_ptr) { + } + scope 9 (inlined NonNull::<T>::as_ptr) { + } + } + } + scope 5 (inlined std::ptr::mut_ptr::<impl *mut T>::addr) { + scope 6 (inlined std::ptr::mut_ptr::<impl *mut T>::cast::<()>) { + } + } + } + scope 10 (inlined std::slice::IterMut::<'_, T>::next_back_unchecked) { + let mut _15: std::ptr::NonNull<T>; + scope 11 (inlined std::slice::IterMut::<'_, T>::pre_dec_end) { + let mut _10: *mut *mut T; + let mut _11: *mut std::ptr::NonNull<T>; + let mut _12: std::ptr::NonNull<T>; + let mut _16: *mut *mut T; + let mut _17: *mut usize; + let mut _18: usize; + let mut _19: usize; + scope 12 { + scope 13 { + } + scope 14 { + scope 17 (inlined NonNull::<T>::sub) { + scope 18 (inlined #[track_caller] core::num::<impl isize>::unchecked_neg) { + scope 19 (inlined core::ub_checks::check_language_ub) { + scope 20 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + scope 21 (inlined NonNull::<T>::offset) { + let mut _13: *const T; + let mut _14: *const T; + scope 22 (inlined NonNull::<T>::as_ptr) { + } + } + } + } + scope 15 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<usize>) { + } + scope 16 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<NonNull<T>>) { + } + } + } + scope 23 (inlined NonNull::<T>::as_mut::<'_>) { + let mut _20: *mut T; + scope 24 (inlined NonNull::<T>::as_ptr) { + } + } + } + } bb0: { - _0 = <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back(move _1) -> [return: bb1, unwind unreachable]; + StorageLive(_9); + StorageLive(_8); + StorageLive(_3); + StorageLive(_2); + StorageLive(_21); + StorageLive(_7); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { + _2 = copy ((*_1).1: *mut T); + _3 = copy _2 as std::ptr::NonNull<T> (Transmute); + StorageLive(_5); + StorageLive(_4); + _4 = copy ((*_1).0: std::ptr::NonNull<T>); + _5 = copy _4 as *mut T (Transmute); + StorageDead(_4); + StorageLive(_6); + _6 = copy _3 as *mut T (Transmute); + _7 = Eq(copy _5, copy _6); + StorageDead(_6); + StorageDead(_5); + goto -> bb3; + } + + bb2: { + _8 = copy ((*_1).1: *mut T); + _9 = copy _8 as usize (Transmute); + _7 = Eq(copy _9, const 0_usize); + goto -> bb3; + } + + bb3: { + switchInt(move _7) -> [0: bb4, otherwise: bb10]; + } + + bb4: { + StorageLive(_15); + StorageLive(_17); + StorageLive(_11); + StorageLive(_12); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb8]; + } + + bb5: { + StorageLive(_10); + _10 = &raw mut ((*_1).1: *mut T); + _11 = copy _10 as *mut std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_10); + _12 = copy (*_11); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb6, otherwise: bb7]; + } + + bb6: { + StorageLive(_14); + StorageLive(_13); + _13 = copy _12 as *const T (Transmute); + _14 = Offset(copy _13, const -1_isize); + StorageDead(_13); + _12 = NonNull::<T> { pointer: copy _14 }; + StorageDead(_14); + goto -> bb7; + } + + bb7: { + (*_11) = move _12; + _15 = copy (*_11); + goto -> bb9; + } + + bb8: { + StorageLive(_16); + _16 = &raw mut ((*_1).1: *mut T); + _17 = copy _16 as *mut usize (PtrToPtr); + StorageDead(_16); + StorageLive(_19); + StorageLive(_18); + _18 = copy (*_17); + _19 = SubUnchecked(move _18, const 1_usize); + StorageDead(_18); + (*_17) = move _19; + StorageDead(_19); + _15 = copy ((*_1).0: std::ptr::NonNull<T>); + goto -> bb9; + } + + bb9: { + StorageDead(_12); + StorageDead(_11); + StorageDead(_17); + StorageLive(_20); + _20 = copy _15 as *mut T (Transmute); + _21 = &mut (*_20); + StorageDead(_20); + StorageDead(_15); + _0 = Option::<&mut T>::Some(copy _21); + goto -> bb11; + } + + bb10: { + _0 = const {transmute(0x0000000000000000): Option<&mut T>}; + goto -> bb11; + } + + bb11: { + StorageDead(_7); + StorageDead(_21); + StorageDead(_2); + StorageDead(_3); + StorageDead(_8); + StorageDead(_9); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir index dfe5e206fad..62b738c36bf 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_mut_next_back.PreCodegen.after.panic-unwind.mir @@ -3,12 +3,187 @@ fn slice_iter_mut_next_back(_1: &mut std::slice::IterMut<'_, T>) -> Option<&mut T> { debug it => _1; let mut _0: std::option::Option<&mut T>; + scope 1 (inlined <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back) { + let mut _2: *mut T; + let mut _7: bool; + let mut _8: *mut T; + let mut _21: &mut T; + scope 2 { + let _3: std::ptr::NonNull<T>; + let _9: usize; + scope 3 { + } + scope 4 { + scope 7 (inlined <NonNull<T> as PartialEq>::eq) { + let mut _4: std::ptr::NonNull<T>; + let mut _5: *mut T; + let mut _6: *mut T; + scope 8 (inlined NonNull::<T>::as_ptr) { + } + scope 9 (inlined NonNull::<T>::as_ptr) { + } + } + } + scope 5 (inlined std::ptr::mut_ptr::<impl *mut T>::addr) { + scope 6 (inlined std::ptr::mut_ptr::<impl *mut T>::cast::<()>) { + } + } + } + scope 10 (inlined std::slice::IterMut::<'_, T>::next_back_unchecked) { + let mut _15: std::ptr::NonNull<T>; + scope 11 (inlined std::slice::IterMut::<'_, T>::pre_dec_end) { + let mut _10: *mut *mut T; + let mut _11: *mut std::ptr::NonNull<T>; + let mut _12: std::ptr::NonNull<T>; + let mut _16: *mut *mut T; + let mut _17: *mut usize; + let mut _18: usize; + let mut _19: usize; + scope 12 { + scope 13 { + } + scope 14 { + scope 17 (inlined NonNull::<T>::sub) { + scope 18 (inlined #[track_caller] core::num::<impl isize>::unchecked_neg) { + scope 19 (inlined core::ub_checks::check_language_ub) { + scope 20 (inlined core::ub_checks::check_language_ub::runtime) { + } + } + } + scope 21 (inlined NonNull::<T>::offset) { + let mut _13: *const T; + let mut _14: *const T; + scope 22 (inlined NonNull::<T>::as_ptr) { + } + } + } + } + scope 15 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<usize>) { + } + scope 16 (inlined std::ptr::mut_ptr::<impl *mut *mut T>::cast::<NonNull<T>>) { + } + } + } + scope 23 (inlined NonNull::<T>::as_mut::<'_>) { + let mut _20: *mut T; + scope 24 (inlined NonNull::<T>::as_ptr) { + } + } + } + } bb0: { - _0 = <std::slice::IterMut<'_, T> as DoubleEndedIterator>::next_back(move _1) -> [return: bb1, unwind continue]; + StorageLive(_9); + StorageLive(_8); + StorageLive(_3); + StorageLive(_2); + StorageLive(_21); + StorageLive(_7); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { + _2 = copy ((*_1).1: *mut T); + _3 = copy _2 as std::ptr::NonNull<T> (Transmute); + StorageLive(_5); + StorageLive(_4); + _4 = copy ((*_1).0: std::ptr::NonNull<T>); + _5 = copy _4 as *mut T (Transmute); + StorageDead(_4); + StorageLive(_6); + _6 = copy _3 as *mut T (Transmute); + _7 = Eq(copy _5, copy _6); + StorageDead(_6); + StorageDead(_5); + goto -> bb3; + } + + bb2: { + _8 = copy ((*_1).1: *mut T); + _9 = copy _8 as usize (Transmute); + _7 = Eq(copy _9, const 0_usize); + goto -> bb3; + } + + bb3: { + switchInt(move _7) -> [0: bb4, otherwise: bb10]; + } + + bb4: { + StorageLive(_15); + StorageLive(_17); + StorageLive(_11); + StorageLive(_12); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb8]; + } + + bb5: { + StorageLive(_10); + _10 = &raw mut ((*_1).1: *mut T); + _11 = copy _10 as *mut std::ptr::NonNull<T> (PtrToPtr); + StorageDead(_10); + _12 = copy (*_11); + switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb6, otherwise: bb7]; + } + + bb6: { + StorageLive(_14); + StorageLive(_13); + _13 = copy _12 as *const T (Transmute); + _14 = Offset(copy _13, const -1_isize); + StorageDead(_13); + _12 = NonNull::<T> { pointer: copy _14 }; + StorageDead(_14); + goto -> bb7; + } + + bb7: { + (*_11) = move _12; + _15 = copy (*_11); + goto -> bb9; + } + + bb8: { + StorageLive(_16); + _16 = &raw mut ((*_1).1: *mut T); + _17 = copy _16 as *mut usize (PtrToPtr); + StorageDead(_16); + StorageLive(_19); + StorageLive(_18); + _18 = copy (*_17); + _19 = SubUnchecked(move _18, const 1_usize); + StorageDead(_18); + (*_17) = move _19; + StorageDead(_19); + _15 = copy ((*_1).0: std::ptr::NonNull<T>); + goto -> bb9; + } + + bb9: { + StorageDead(_12); + StorageDead(_11); + StorageDead(_17); + StorageLive(_20); + _20 = copy _15 as *mut T (Transmute); + _21 = &mut (*_20); + StorageDead(_20); + StorageDead(_15); + _0 = Option::<&mut T>::Some(copy _21); + goto -> bb11; + } + + bb10: { + _0 = const {transmute(0x0000000000000000): Option<&mut T>}; + goto -> bb11; + } + + bb11: { + StorageDead(_7); + StorageDead(_21); + StorageDead(_2); + StorageDead(_3); + StorageDead(_8); + StorageDead(_9); return; } } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir index fe4e2deab87..79aa9c5ae1e 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-abort.mir @@ -9,7 +9,7 @@ fn outer(_1: u8) -> u8 { } bb0: { - _2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13 + // DBG: _2 = &_1; _0 = copy _1; // scope 1 at $DIR/spans.rs:15:5: 15:7 return; // scope 0 at $DIR/spans.rs:12:2: 12:2 } diff --git a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir index fe4e2deab87..79aa9c5ae1e 100644 --- a/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/spans.outer.PreCodegen.after.panic-unwind.mir @@ -9,7 +9,7 @@ fn outer(_1: u8) -> u8 { } bb0: { - _2 = &_1; // scope 0 at $DIR/spans.rs:11:11: 11:13 + // DBG: _2 = &_1; _0 = copy _1; // scope 1 at $DIR/spans.rs:15:5: 15:7 return; // scope 0 at $DIR/spans.rs:12:2: 12:2 } diff --git a/tests/run-make/panic-abort-eh_frame/rmake.rs b/tests/run-make/panic-abort-eh_frame/rmake.rs index 23d95dc5774..2eccde62795 100644 --- a/tests/run-make/panic-abort-eh_frame/rmake.rs +++ b/tests/run-make/panic-abort-eh_frame/rmake.rs @@ -1,9 +1,11 @@ // An `.eh_frame` section in an object file is a symptom of an UnwindAction::Terminate // being inserted, useful for determining whether or not unwinding is necessary. -// This is useless when panics would NEVER unwind due to -C panic=abort. This section should -// therefore never appear in the emit file of a -C panic=abort compilation, and this test -// checks that this is respected. -// See https://github.com/rust-lang/rust/pull/112403 +// This is useless when panics would NEVER unwind due to -C panic=abort and when we don't need +// being able to generate backtraces (which depend on unwind tables on linux). This section should +// therefore never appear in the emit file of a -C panic=abort compilation +// with -C force-unwind-tables=no, and this test checks that this is respected. +// See https://github.com/rust-lang/rust/pull/112403 and +// https://github.com/rust-lang/rust/pull/143613. //@ only-linux // FIXME(Oneirical): the DW_CFA symbol appears on Windows-gnu, because uwtable @@ -19,6 +21,7 @@ fn main() { .panic("abort") .edition("2021") .arg("-Zvalidate-mir") + .arg("-Cforce-unwind-tables=no") .run(); llvm_objdump().arg("--dwarf=frames").input("foo.o").run().assert_stdout_not_contains("DW_CFA"); } diff --git a/tests/rustdoc-gui/search-result-color.goml b/tests/rustdoc-gui/search-result-color.goml index fe0f6401089..e5c11651bd2 100644 --- a/tests/rustdoc-gui/search-result-color.goml +++ b/tests/rustdoc-gui/search-result-color.goml @@ -5,7 +5,7 @@ include: "utils.goml" define-function: ( "check-search-color", [ - theme, count_color, desc_color, path_color, bottom_border_color, keyword_color, + theme, count_color, path_color, bottom_border_color, keyword_color, struct_color, associatedtype_color, tymethod_color, method_color, structfield_color, structfield_hover_color, macro_color, fn_color, hover_path_color, hover_background, attribute_color, grey @@ -22,10 +22,6 @@ define-function: ( ALL, ) assert-css: ( - "//*[@class='desc'][normalize-space()='Just a normal struct.']", - {"color": |desc_color|}, - ) - assert-css: ( "//*[@class='result-name']//*[normalize-space()='test_docs::']", {"color": |path_color|}, ) @@ -97,16 +93,6 @@ define-function: ( ALL, ) - // Checking color and background on hover. - move-cursor-to: "//*[@class='desc'][normalize-space()='Just a normal struct.']" - assert-css: ( - "//*[@class='result-name']//*[normalize-space()='test_docs::']", - {"color": |hover_path_color|}, - ) - assert-css: ( - "//*[@class='result-name']//*[normalize-space()='test_docs::']/ancestor::a", - {"color": |hover_path_color|, "background-color": |hover_background|}, - ) } ) @@ -157,7 +143,6 @@ show-text: true call-function: ("check-search-color", { "theme": "ayu", "count_color": "#888", - "desc_color": "#c5c5c5", "path_color": "#0096cf", "bottom_border_color": "#aaa3", "keyword_color": "#39afd7", @@ -179,7 +164,6 @@ call-function: ("check-search-color", { call-function: ("check-search-color", { "theme": "dark", "count_color": "#888", - "desc_color": "#ddd", "path_color": "#ddd", "bottom_border_color": "#aaa3", "keyword_color": "#d2991d", @@ -201,7 +185,6 @@ call-function: ("check-search-color", { call-function: ("check-search-color", { "theme": "light", "count_color": "#888", - "desc_color": "#000", "path_color": "#000", "bottom_border_color": "#aaa3", "keyword_color": "#3873ad", @@ -226,12 +209,27 @@ call-function: ("perform-search", {"query": "thisisanalias"}) define-function: ( "check-alias", - [theme, alias, grey], + [theme, alias, grey, desc_color, hover_path_color, hover_background], block { call-function: ("switch-theme", {"theme": |theme|}) // Checking that the colors for the alias element are the ones expected. assert-css: (".result-name .path .alias", {"color": |alias|}) assert-css: (".result-name .path .alias > .grey", {"color": |grey|}) + assert-css: ( + "//*[@class='desc'][normalize-space()='Just a normal enum.']", + {"color": |desc_color|}, + ) + // Checking color and background on hover. + move-cursor-to: "//*[@class='desc'][normalize-space()='Just a normal enum.']" + assert-css: ( + "//*[@class='result-name']//*[normalize-space()='test_docs::']", + {"color": |hover_path_color|}, + ) + assert-css: ( + "//*[@class='result-name']//*[normalize-space()='test_docs::']/ancestor::a", + {"color": |hover_path_color|, "background-color": |hover_background|}, + ) + }, ) @@ -239,14 +237,23 @@ call-function: ("check-alias", { "theme": "ayu", "alias": "#c5c5c5", "grey": "#999", + "desc_color": "#c5c5c5", + "hover_path_color": "#fff", + "hover_background": "#3c3c3c", }) call-function: ("check-alias", { "theme": "dark", "alias": "#fff", "grey": "#ccc", + "desc_color": "#ddd", + "hover_path_color": "#ddd", + "hover_background": "#616161", }) call-function: ("check-alias", { "theme": "light", "alias": "#000", "grey": "#999", + "desc_color": "#000", + "hover_path_color": "#000", + "hover_background": "#ccc", }) diff --git a/tests/rustdoc-gui/search-tab.goml b/tests/rustdoc-gui/search-tab.goml index 00ca952033d..0a3cfc231e5 100644 --- a/tests/rustdoc-gui/search-tab.goml +++ b/tests/rustdoc-gui/search-tab.goml @@ -79,7 +79,7 @@ call-function: ("check-colors", { set-window-size: (851, 600) // Check the size and count in tabs -assert-text: ("#search-tabs > button:nth-child(1) > .count", " (27) ") +assert-text: ("#search-tabs > button:nth-child(1) > .count", " (25) ") assert-text: ("#search-tabs > button:nth-child(2) > .count", " (7)  ") assert-text: ("#search-tabs > button:nth-child(3) > .count", " (0)  ") store-property: ("#search-tabs > button:nth-child(1)", {"offsetWidth": buttonWidth}) diff --git a/tests/rustdoc-gui/sidebar.goml b/tests/rustdoc-gui/sidebar.goml index 5ec0008ad8a..0d371c8c6a4 100644 --- a/tests/rustdoc-gui/sidebar.goml +++ b/tests/rustdoc-gui/sidebar.goml @@ -1,5 +1,7 @@ // Checks multiple things on the sidebar display (width of its elements, colors, etc). include: "utils.goml" +// Disable animations so they don't mess up color assertions later. +emulate-media-features: { "prefers-reduced-motion": "reduce" } go-to: "file://" + |DOC_PATH| + "/test_docs/index.html" assert-property: (".sidebar", {"clientWidth": "199"}) show-text: true diff --git a/tests/rustdoc-js-std/asrawfd.js b/tests/rustdoc-js-std/asrawfd.js index 5dbc4ba95d9..da08eeb8a53 100644 --- a/tests/rustdoc-js-std/asrawfd.js +++ b/tests/rustdoc-js-std/asrawfd.js @@ -1,12 +1,10 @@ // ignore-order const EXPECTED = { - 'query': 'RawFd::as_raw_fd', + 'query': 'method:RawFd::as_raw_fd', 'others': [ // Reproduction test for https://github.com/rust-lang/rust/issues/78724 // Validate that type alias methods get the correct path. - { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' }, - { 'path': 'std::os::fd::AsRawFd', 'name': 'as_raw_fd' }, { 'path': 'std::os::fd::RawFd', 'name': 'as_raw_fd' }, ], }; diff --git a/tests/rustdoc-js-std/quoted.js b/tests/rustdoc-js-std/quoted.js index 8a927501925..a8ca6521208 100644 --- a/tests/rustdoc-js-std/quoted.js +++ b/tests/rustdoc-js-std/quoted.js @@ -1,21 +1,21 @@ +// make sure quoted search works both for items and and without generics // ignore-order const FILTER_CRATE = 'std'; const EXPECTED = { - 'query': '"error"', + 'query': '"result"', 'others': [ - { 'path': 'std', 'name': 'error' }, - { 'path': 'std::fmt', 'name': 'Error' }, - { 'path': 'std::io', 'name': 'Error' }, + { 'path': 'std', 'name': 'result' }, + { 'path': 'std::result', 'name': 'Result' }, + { 'path': 'std::fmt', 'name': 'Result' }, ], 'in_args': [ - { 'path': 'std::fmt::Error', 'name': 'eq' }, - { 'path': 'std::fmt::Error', 'name': 'cmp' }, - { 'path': 'std::fmt::Error', 'name': 'partial_cmp' }, - + { 'path': 'std::result::Result', 'name': 'branch' }, + { 'path': 'std::result::Result', 'name': 'ok' }, + { 'path': 'std::result::Result', 'name': 'unwrap' }, ], 'returned': [ - { 'path': 'std::fmt::LowerExp', 'name': 'fmt' }, + { 'path': 'std::bool', 'name': 'try_into' }, ], }; diff --git a/tests/rustdoc-js-std/bufread-fill-buf.js b/tests/rustdoc-js-std/trait-unbox.js index 6b9309f6864..44ddc0c1e75 100644 --- a/tests/rustdoc-js-std/bufread-fill-buf.js +++ b/tests/rustdoc-js-std/trait-unbox.js @@ -1,10 +1,10 @@ -// ignore-order +// make sure type-based searches with traits get unboxed too const EXPECTED = [ { - 'query': 'bufread -> result<[u8]>', + 'query': 'any -> result<box>', 'others': [ - { 'path': 'std::boxed::Box', 'name': 'fill_buf' }, + { 'path': 'std::boxed::Box', 'name': 'downcast' }, ], }, { diff --git a/tests/rustdoc-js/trait-methods.js b/tests/rustdoc-js/trait-methods.js index dafad5e4378..083e52439f4 100644 --- a/tests/rustdoc-js/trait-methods.js +++ b/tests/rustdoc-js/trait-methods.js @@ -9,4 +9,24 @@ const EXPECTED = [ { 'path': 'trait_methods::MyTrait', 'name': 'next' }, ], }, + // the traitParent deduplication pass should remove + // Empty::next, as it would be redundant + { + 'query': 'next', + 'correction': null, + 'in_args': [], + 'others': [ + { 'path': 'trait_methods::MyTrait', 'name': 'next' }, + ], + }, + // if the trait does not match, no deduplication happens + { + 'query': '-> option<()>', + 'correction': null, + 'in_args': [], + 'others': [ + { 'path': 'trait_methods::Empty', 'name': 'next' }, + { 'path': 'trait_methods::Void', 'name': 'next' }, + ], + }, ]; diff --git a/tests/rustdoc-js/trait-methods.rs b/tests/rustdoc-js/trait-methods.rs index c88f5edfd55..a741b361a33 100644 --- a/tests/rustdoc-js/trait-methods.rs +++ b/tests/rustdoc-js/trait-methods.rs @@ -2,3 +2,21 @@ pub trait MyTrait { type Item; fn next(&mut self) -> Option<Self::Item>; } + +pub struct Empty; + +impl MyTrait for Empty { + type Item = (); + fn next(&mut self) -> Option<()> { + None + } +} + +pub struct Void; + +impl MyTrait for Void { + type Item = (); + fn next(&mut self) -> Option<()> { + Some(()) + } +} diff --git a/tests/rustdoc-ui/doctest/check-attr-test.rs b/tests/rustdoc-ui/doctest/check-attr-test.rs index 81281db624b..d69dae63860 100644 --- a/tests/rustdoc-ui/doctest/check-attr-test.rs +++ b/tests/rustdoc-ui/doctest/check-attr-test.rs @@ -2,6 +2,9 @@ #![deny(rustdoc::invalid_codeblock_attributes)] +//~vvv ERROR unknown attribute `compile-fail` +//~| ERROR unknown attribute `compilefail` +//~| ERROR unknown attribute `comPile_fail` /// foo /// /// ```compile-fail,compilefail,comPile_fail @@ -9,6 +12,9 @@ /// ``` pub fn foo() {} +//~vvv ERROR unknown attribute `should-panic` +//~| ERROR unknown attribute `shouldpanic` +//~| ERROR unknown attribute `shOuld_panic` /// bar /// /// ```should-panic,shouldpanic,shOuld_panic @@ -16,6 +22,9 @@ pub fn foo() {} /// ``` pub fn bar() {} +//~vvv ERROR unknown attribute `no-run` +//~| ERROR unknown attribute `norun` +//~| ERROR unknown attribute `nO_run` /// foobar /// /// ```no-run,norun,nO_run @@ -23,6 +32,9 @@ pub fn bar() {} /// ``` pub fn foobar() {} +//~vvv ERROR unknown attribute `test-harness` +//~| ERROR unknown attribute `testharness` +//~| ERROR unknown attribute `tesT_harness` /// b /// /// ```test-harness,testharness,tesT_harness diff --git a/tests/rustdoc-ui/doctest/check-attr-test.stderr b/tests/rustdoc-ui/doctest/check-attr-test.stderr index 257136d1633..1fc7ab592de 100644 --- a/tests/rustdoc-ui/doctest/check-attr-test.stderr +++ b/tests/rustdoc-ui/doctest/check-attr-test.stderr @@ -1,159 +1,159 @@ error: unknown attribute `compile-fail` - --> $DIR/check-attr-test.rs:5:1 - | -5 | / /// foo -6 | | /// -7 | | /// ```compile-fail,compilefail,comPile_fail -8 | | /// boo -9 | | /// ``` - | |_______^ - | - = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can - = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` + --> $DIR/check-attr-test.rs:8:1 + | +LL | / /// foo +LL | | /// +LL | | /// ```compile-fail,compilefail,comPile_fail +LL | | /// boo +LL | | /// ``` + | |_______^ + | + = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can + = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` note: the lint level is defined here - --> $DIR/check-attr-test.rs:3:9 - | -3 | #![deny(rustdoc::invalid_codeblock_attributes)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + --> $DIR/check-attr-test.rs:3:9 + | +LL | #![deny(rustdoc::invalid_codeblock_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: unknown attribute `compilefail` - --> $DIR/check-attr-test.rs:5:1 - | -5 | / /// foo -6 | | /// -7 | | /// ```compile-fail,compilefail,comPile_fail -8 | | /// boo -9 | | /// ``` - | |_______^ - | - = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can - = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` + --> $DIR/check-attr-test.rs:8:1 + | +LL | / /// foo +LL | | /// +LL | | /// ```compile-fail,compilefail,comPile_fail +LL | | /// boo +LL | | /// ``` + | |_______^ + | + = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can + = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: unknown attribute `comPile_fail` - --> $DIR/check-attr-test.rs:5:1 - | -5 | / /// foo -6 | | /// -7 | | /// ```compile-fail,compilefail,comPile_fail -8 | | /// boo -9 | | /// ``` - | |_______^ - | - = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can - = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` + --> $DIR/check-attr-test.rs:8:1 + | +LL | / /// foo +LL | | /// +LL | | /// ```compile-fail,compilefail,comPile_fail +LL | | /// boo +LL | | /// ``` + | |_______^ + | + = help: use `compile_fail` to invert the results of this test, so that it passes if it cannot be compiled and fails if it can + = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: unknown attribute `should-panic` - --> $DIR/check-attr-test.rs:12:1 + --> $DIR/check-attr-test.rs:18:1 | -12 | / /// bar -13 | | /// -14 | | /// ```should-panic,shouldpanic,shOuld_panic -15 | | /// boo -16 | | /// ``` +LL | / /// bar +LL | | /// +LL | | /// ```should-panic,shouldpanic,shOuld_panic +LL | | /// boo +LL | | /// ``` | |_______^ | = help: use `should_panic` to invert the results of this test, so that if passes if it panics and fails if it does not = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: unknown attribute `shouldpanic` - --> $DIR/check-attr-test.rs:12:1 + --> $DIR/check-attr-test.rs:18:1 | -12 | / /// bar -13 | | /// -14 | | /// ```should-panic,shouldpanic,shOuld_panic -15 | | /// boo -16 | | /// ``` +LL | / /// bar +LL | | /// +LL | | /// ```should-panic,shouldpanic,shOuld_panic +LL | | /// boo +LL | | /// ``` | |_______^ | = help: use `should_panic` to invert the results of this test, so that if passes if it panics and fails if it does not = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: unknown attribute `shOuld_panic` - --> $DIR/check-attr-test.rs:12:1 + --> $DIR/check-attr-test.rs:18:1 | -12 | / /// bar -13 | | /// -14 | | /// ```should-panic,shouldpanic,shOuld_panic -15 | | /// boo -16 | | /// ``` +LL | / /// bar +LL | | /// +LL | | /// ```should-panic,shouldpanic,shOuld_panic +LL | | /// boo +LL | | /// ``` | |_______^ | = help: use `should_panic` to invert the results of this test, so that if passes if it panics and fails if it does not = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: unknown attribute `no-run` - --> $DIR/check-attr-test.rs:19:1 + --> $DIR/check-attr-test.rs:28:1 | -19 | / /// foobar -20 | | /// -21 | | /// ```no-run,norun,nO_run -22 | | /// boo -23 | | /// ``` +LL | / /// foobar +LL | | /// +LL | | /// ```no-run,norun,nO_run +LL | | /// boo +LL | | /// ``` | |_______^ | = help: use `no_run` to compile, but not run, the code sample during testing = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: unknown attribute `norun` - --> $DIR/check-attr-test.rs:19:1 + --> $DIR/check-attr-test.rs:28:1 | -19 | / /// foobar -20 | | /// -21 | | /// ```no-run,norun,nO_run -22 | | /// boo -23 | | /// ``` +LL | / /// foobar +LL | | /// +LL | | /// ```no-run,norun,nO_run +LL | | /// boo +LL | | /// ``` | |_______^ | = help: use `no_run` to compile, but not run, the code sample during testing = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: unknown attribute `nO_run` - --> $DIR/check-attr-test.rs:19:1 + --> $DIR/check-attr-test.rs:28:1 | -19 | / /// foobar -20 | | /// -21 | | /// ```no-run,norun,nO_run -22 | | /// boo -23 | | /// ``` +LL | / /// foobar +LL | | /// +LL | | /// ```no-run,norun,nO_run +LL | | /// boo +LL | | /// ``` | |_______^ | = help: use `no_run` to compile, but not run, the code sample during testing = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: unknown attribute `test-harness` - --> $DIR/check-attr-test.rs:26:1 + --> $DIR/check-attr-test.rs:38:1 | -26 | / /// b -27 | | /// -28 | | /// ```test-harness,testharness,tesT_harness -29 | | /// boo -30 | | /// ``` +LL | / /// b +LL | | /// +LL | | /// ```test-harness,testharness,tesT_harness +LL | | /// boo +LL | | /// ``` | |_______^ | = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: unknown attribute `testharness` - --> $DIR/check-attr-test.rs:26:1 + --> $DIR/check-attr-test.rs:38:1 | -26 | / /// b -27 | | /// -28 | | /// ```test-harness,testharness,tesT_harness -29 | | /// boo -30 | | /// ``` +LL | / /// b +LL | | /// +LL | | /// ```test-harness,testharness,tesT_harness +LL | | /// boo +LL | | /// ``` | |_______^ | = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function = help: this code block may be skipped during testing, because unknown attributes are treated as markers for code samples written in other programming languages, unless it is also explicitly marked as `rust` error: unknown attribute `tesT_harness` - --> $DIR/check-attr-test.rs:26:1 + --> $DIR/check-attr-test.rs:38:1 | -26 | / /// b -27 | | /// -28 | | /// ```test-harness,testharness,tesT_harness -29 | | /// boo -30 | | /// ``` +LL | / /// b +LL | | /// +LL | | /// ```test-harness,testharness,tesT_harness +LL | | /// boo +LL | | /// ``` | |_______^ | = help: use `test_harness` to run functions marked `#[test]` instead of a potentially-implicit `main` function diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs index ca5dd787467..05e4a348d11 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.rs @@ -9,6 +9,7 @@ /// <https://github.com/rust-lang/rust/issues/91014> /// /// ```rust +//~^ WARN the `main` function of this doctest won't be run /// struct S {}; /// /// fn main() { diff --git a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stderr b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stderr index 113fb7ccb60..cffda43ba1c 100644 --- a/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stderr +++ b/tests/rustdoc-ui/doctest/failed-doctest-extra-semicolon-on-item.stderr @@ -1,7 +1,7 @@ warning: the `main` function of this doctest won't be run as it contains expressions at the top level, meaning that the whole doctest code will be wrapped in a function --> $DIR/failed-doctest-extra-semicolon-on-item.rs:11:1 | -11 | /// ```rust +LL | /// ```rust | ^^^^^^^^^^^ warning: 1 warning emitted diff --git a/tests/rustdoc-ui/doctest/main-alongside-stmts.rs b/tests/rustdoc-ui/doctest/main-alongside-stmts.rs index 5965f928cdd..595de133932 100644 --- a/tests/rustdoc-ui/doctest/main-alongside-stmts.rs +++ b/tests/rustdoc-ui/doctest/main-alongside-stmts.rs @@ -14,6 +14,7 @@ //@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" //@ check-pass +//~v WARN the `main` function of this doctest won't be run //! ``` //! # if cfg!(miri) { return; } //! use std::ops::Deref; @@ -22,6 +23,7 @@ //! assert!(false); //! } //! ``` +//~v WARN the `main` function of this doctest won't be run //! //! ``` //! let x = 2; diff --git a/tests/rustdoc-ui/doctest/main-alongside-stmts.stderr b/tests/rustdoc-ui/doctest/main-alongside-stmts.stderr index d90a289ca69..b7a5421f8f7 100644 --- a/tests/rustdoc-ui/doctest/main-alongside-stmts.stderr +++ b/tests/rustdoc-ui/doctest/main-alongside-stmts.stderr @@ -1,14 +1,14 @@ warning: the `main` function of this doctest won't be run as it contains expressions at the top level, meaning that the whole doctest code will be wrapped in a function - --> $DIR/main-alongside-stmts.rs:17:1 + --> $DIR/main-alongside-stmts.rs:18:1 | -17 | //! ``` +LL | //! ``` | ^^^^^^^ warning: the `main` function of this doctest won't be run as it contains expressions at the top level, meaning that the whole doctest code will be wrapped in a function - --> $DIR/main-alongside-stmts.rs:26:1 + --> $DIR/main-alongside-stmts.rs:27:1 | -26 | //! ``` - | ^^^^^^^ +LL | //! + | ^^^ warning: 2 warnings emitted diff --git a/tests/rustdoc-ui/doctest/main-alongside-stmts.stdout b/tests/rustdoc-ui/doctest/main-alongside-stmts.stdout index 9b9a3fe8a68..bebaeb49c5a 100644 --- a/tests/rustdoc-ui/doctest/main-alongside-stmts.stdout +++ b/tests/rustdoc-ui/doctest/main-alongside-stmts.stdout @@ -1,7 +1,7 @@ running 2 tests -test $DIR/main-alongside-stmts.rs - (line 17) ... ok -test $DIR/main-alongside-stmts.rs - (line 26) ... ok +test $DIR/main-alongside-stmts.rs - (line 18) ... ok +test $DIR/main-alongside-stmts.rs - (line 27) ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME diff --git a/tests/rustdoc-ui/doctest/standalone-warning-2024.rs b/tests/rustdoc-ui/doctest/standalone-warning-2024.rs index c53a8b48749..3bb0083d849 100644 --- a/tests/rustdoc-ui/doctest/standalone-warning-2024.rs +++ b/tests/rustdoc-ui/doctest/standalone-warning-2024.rs @@ -9,6 +9,8 @@ #![deny(warnings)] //! ```standalone +//~^ ERROR unknown attribute `standalone` +//~| ERROR unknown attribute `standalone-crate` //! bla //! ``` //! diff --git a/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr b/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr index ce65557c2c4..db0d53a204c 100644 --- a/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr +++ b/tests/rustdoc-ui/doctest/standalone-warning-2024.stderr @@ -1,13 +1,13 @@ error: unknown attribute `standalone` --> $DIR/standalone-warning-2024.rs:11:1 | -11 | / //! ```standalone -12 | | //! bla -13 | | //! ``` -14 | | //! -15 | | //! ```standalone-crate -16 | | //! bla -17 | | //! ``` +LL | / //! ```standalone +LL | | +LL | | +LL | | //! bla +... | +LL | | //! bla +LL | | //! ``` | |_______^ | = help: use `standalone_crate` to compile this code block separately @@ -15,20 +15,20 @@ error: unknown attribute `standalone` note: the lint level is defined here --> $DIR/standalone-warning-2024.rs:9:9 | - 9 | #![deny(warnings)] +LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(rustdoc::invalid_codeblock_attributes)]` implied by `#[deny(warnings)]` error: unknown attribute `standalone-crate` --> $DIR/standalone-warning-2024.rs:11:1 | -11 | / //! ```standalone -12 | | //! bla -13 | | //! ``` -14 | | //! -15 | | //! ```standalone-crate -16 | | //! bla -17 | | //! ``` +LL | / //! ```standalone +LL | | +LL | | +LL | | //! bla +... | +LL | | //! bla +LL | | //! ``` | |_______^ | = help: use `standalone_crate` to compile this code block separately diff --git a/tests/rustdoc-ui/doctest/test-compile-fail1.rs b/tests/rustdoc-ui/doctest/test-compile-fail1.rs index 278f01f4c83..c692c4c61bc 100644 --- a/tests/rustdoc-ui/doctest/test-compile-fail1.rs +++ b/tests/rustdoc-ui/doctest/test-compile-fail1.rs @@ -6,3 +6,4 @@ pub fn f() {} pub fn f() {} +//~^ ERROR the name `f` is defined multiple times diff --git a/tests/rustdoc-ui/doctest/test-compile-fail1.stderr b/tests/rustdoc-ui/doctest/test-compile-fail1.stderr index 02f4d8d754f..aa5cc2e14d6 100644 --- a/tests/rustdoc-ui/doctest/test-compile-fail1.stderr +++ b/tests/rustdoc-ui/doctest/test-compile-fail1.stderr @@ -1,13 +1,13 @@ error[E0428]: the name `f` is defined multiple times - --> $DIR/test-compile-fail1.rs:8:1 - | -6 | pub fn f() {} - | ---------- previous definition of the value `f` here -7 | -8 | pub fn f() {} - | ^^^^^^^^^^ `f` redefined here - | - = note: `f` must be defined only once in the value namespace of this module + --> $DIR/test-compile-fail1.rs:8:1 + | +LL | pub fn f() {} + | ---------- previous definition of the value `f` here +LL | +LL | pub fn f() {} + | ^^^^^^^^^^ `f` redefined here + | + = note: `f` must be defined only once in the value namespace of this module error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doctest/test-compile-fail2.rs b/tests/rustdoc-ui/doctest/test-compile-fail2.rs index 7432cc9f826..8239440262d 100644 --- a/tests/rustdoc-ui/doctest/test-compile-fail2.rs +++ b/tests/rustdoc-ui/doctest/test-compile-fail2.rs @@ -1,3 +1,4 @@ //@ compile-flags:--test fail +//~^ ERROR diff --git a/tests/rustdoc-ui/doctest/test-compile-fail2.stderr b/tests/rustdoc-ui/doctest/test-compile-fail2.stderr index f0ad40eb6ca..9f50c857275 100644 --- a/tests/rustdoc-ui/doctest/test-compile-fail2.stderr +++ b/tests/rustdoc-ui/doctest/test-compile-fail2.stderr @@ -1,8 +1,8 @@ error: expected one of `!` or `::`, found `<eof>` - --> $DIR/test-compile-fail2.rs:3:1 - | -3 | fail - | ^^^^ expected one of `!` or `::` + --> $DIR/test-compile-fail2.rs:3:1 + | +LL | fail + | ^^^^ expected one of `!` or `::` error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doctest/test-compile-fail3.rs b/tests/rustdoc-ui/doctest/test-compile-fail3.rs index a2486d9dc6f..272ba95396c 100644 --- a/tests/rustdoc-ui/doctest/test-compile-fail3.rs +++ b/tests/rustdoc-ui/doctest/test-compile-fail3.rs @@ -1,3 +1,4 @@ //@ compile-flags:--test "fail +//~^ ERROR diff --git a/tests/rustdoc-ui/doctest/test-compile-fail3.stderr b/tests/rustdoc-ui/doctest/test-compile-fail3.stderr index 09d78b2f346..8061097e73a 100644 --- a/tests/rustdoc-ui/doctest/test-compile-fail3.stderr +++ b/tests/rustdoc-ui/doctest/test-compile-fail3.stderr @@ -1,8 +1,9 @@ error[E0765]: unterminated double quote string - --> $DIR/test-compile-fail3.rs:3:1 - | -3 | "fail - | ^^^^^ + --> $DIR/test-compile-fail3.rs:3:1 + | +LL | / "fail +LL | | + | |___________^ error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/doctest/unstable-opts-143930.rs b/tests/rustdoc-ui/doctest/unstable-opts-143930.rs new file mode 100644 index 00000000000..30c47f5b7e9 --- /dev/null +++ b/tests/rustdoc-ui/doctest/unstable-opts-143930.rs @@ -0,0 +1,14 @@ +// This test verifies that unstable options like `-Zcrate-attr` are respected when `--test` is +// passed. +// +// <https://github.com/rust-lang/rust/issues/143930> +// +// NOTE: If any of these command line arguments or features get stabilized, please replace with +// another unstable one. + +//@ check-pass +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@ compile-flags: --test -Zcrate-attr=feature(register_tool) -Zcrate-attr=register_tool(rapx) + +#[rapx::tag] +fn f() {} diff --git a/tests/rustdoc-ui/doctest/unstable-opts-143930.stdout b/tests/rustdoc-ui/doctest/unstable-opts-143930.stdout new file mode 100644 index 00000000000..7326c0a25a0 --- /dev/null +++ b/tests/rustdoc-ui/doctest/unstable-opts-143930.stdout @@ -0,0 +1,5 @@ + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/unstable-opts-147276.crate_attr.stdout b/tests/rustdoc-ui/doctest/unstable-opts-147276.crate_attr.stdout new file mode 100644 index 00000000000..7326c0a25a0 --- /dev/null +++ b/tests/rustdoc-ui/doctest/unstable-opts-147276.crate_attr.stdout @@ -0,0 +1,5 @@ + +running 0 tests + +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME + diff --git a/tests/rustdoc-ui/doctest/unstable-opts-147276.normal.stderr b/tests/rustdoc-ui/doctest/unstable-opts-147276.normal.stderr new file mode 100644 index 00000000000..eebf4f307f1 --- /dev/null +++ b/tests/rustdoc-ui/doctest/unstable-opts-147276.normal.stderr @@ -0,0 +1,13 @@ +error[E0658]: `#[used(linker)]` is currently unstable + --> $DIR/unstable-opts-147276.rs:15:1 + | +LL | #[used(linker)] + | ^^^^^^^^^^^^^^^ + | + = note: see issue #93798 <https://github.com/rust-lang/rust/issues/93798> for more information + = help: add `#![feature(used_with_arg)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/rustdoc-ui/doctest/unstable-opts-147276.rs b/tests/rustdoc-ui/doctest/unstable-opts-147276.rs new file mode 100644 index 00000000000..64cafcaaff4 --- /dev/null +++ b/tests/rustdoc-ui/doctest/unstable-opts-147276.rs @@ -0,0 +1,17 @@ +// This test verifies that unstable options like `-Zcrate-attr` are respected when `--test` is +// passed. +// +// <https://github.com/rust-lang/rust/issues/147276> +// +// NOTE: If any of these command line arguments or features get stabilized, please replace with +// another unstable one. + +//@ revisions: normal crate_attr +//@ compile-flags: --test +//@ normalize-stdout: "finished in \d+\.\d+s" -> "finished in $$TIME" +//@[crate_attr] check-pass +//@[crate_attr] compile-flags: -Zcrate-attr=feature(used_with_arg) + +#[used(linker)] +//[normal]~^ ERROR `#[used(linker)]` is currently unstable +static REPRO: isize = 1; diff --git a/tests/rustdoc-ui/doctest/warn-main-not-called.rs b/tests/rustdoc-ui/doctest/warn-main-not-called.rs index 25d92e9cee9..ec762486d5d 100644 --- a/tests/rustdoc-ui/doctest/warn-main-not-called.rs +++ b/tests/rustdoc-ui/doctest/warn-main-not-called.rs @@ -8,6 +8,7 @@ // won't be called. //! ``` +//~^ WARN the `main` function of this doctest won't be run //! macro_rules! bla { //! ($($x:tt)*) => {} //! } @@ -17,6 +18,7 @@ //! ``` //! //! ``` +//~^^ WARN the `main` function of this doctest won't be run //! let x = 12; //! fn main() {} //! ``` diff --git a/tests/rustdoc-ui/doctest/warn-main-not-called.stderr b/tests/rustdoc-ui/doctest/warn-main-not-called.stderr index 3a079f47555..5feca6f9175 100644 --- a/tests/rustdoc-ui/doctest/warn-main-not-called.stderr +++ b/tests/rustdoc-ui/doctest/warn-main-not-called.stderr @@ -1,14 +1,14 @@ warning: the `main` function of this doctest won't be run as it contains expressions at the top level, meaning that the whole doctest code will be wrapped in a function --> $DIR/warn-main-not-called.rs:10:1 | -10 | //! ``` +LL | //! ``` | ^^^^^^^ warning: the `main` function of this doctest won't be run as it contains expressions at the top level, meaning that the whole doctest code will be wrapped in a function --> $DIR/warn-main-not-called.rs:19:1 | -19 | //! ``` - | ^^^^^^^ +LL | //! + | ^^^ warning: 2 warnings emitted diff --git a/tests/ui/associated-types/projection-dyn-associated-type.rs b/tests/ui/associated-types/projection-dyn-associated-type.rs new file mode 100644 index 00000000000..3b981e7987e --- /dev/null +++ b/tests/ui/associated-types/projection-dyn-associated-type.rs @@ -0,0 +1,28 @@ +// Regression test for the projection bug in <https://github.com/rust-lang/rust/issues/123953> +// +//@ compile-flags: -Zincremental-verify-ich=yes +//@ incremental + +pub trait A {} +pub trait B: A {} + +pub trait Mirror { + type Assoc: ?Sized; +} + +impl<T: ?Sized> Mirror for A { + //~^ ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates [E0207] + //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + type Assoc = T; +} + +pub fn foo<'a>( + x: &'a <dyn A + 'static as Mirror>::Assoc +) -> &'a <dyn B + 'static as Mirror>::Assoc { + //~^ ERROR the trait bound `(dyn B + 'static): Mirror` is not satisfied [E0277] + //~| ERROR the trait bound `(dyn B + 'static): Mirror` is not satisfied [E0277] + static +} //~ ERROR expected identifier, found `}` + +pub fn main() {} diff --git a/tests/ui/associated-types/projection-dyn-associated-type.stderr b/tests/ui/associated-types/projection-dyn-associated-type.stderr new file mode 100644 index 00000000000..1ac2beb0414 --- /dev/null +++ b/tests/ui/associated-types/projection-dyn-associated-type.stderr @@ -0,0 +1,52 @@ +error: expected identifier, found `}` + --> $DIR/projection-dyn-associated-type.rs:26:1 + | +LL | } + | ^ expected identifier + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/projection-dyn-associated-type.rs:13:28 + | +LL | impl<T: ?Sized> Mirror for A { + | ^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/warnings-promoted-to-error.html> + = note: `#[warn(bare_trait_objects)]` (part of `#[warn(rust_2021_compatibility)]`) on by default +help: if this is a dyn-compatible trait, use `dyn` + | +LL | impl<T: ?Sized> Mirror for dyn A { + | +++ +help: alternatively use a blanket implementation to implement `Mirror` for all types that also implement `A` + | +LL - impl<T: ?Sized> Mirror for A { +LL + impl<T: ?Sized, U: A> Mirror for U { + | + +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/projection-dyn-associated-type.rs:13:6 + | +LL | impl<T: ?Sized> Mirror for A { + | ^ unconstrained type parameter + +error[E0277]: the trait bound `(dyn B + 'static): Mirror` is not satisfied + --> $DIR/projection-dyn-associated-type.rs:22:6 + | +LL | ) -> &'a <dyn B + 'static as Mirror>::Assoc { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Mirror` is not implemented for `(dyn B + 'static)` + | + = help: the trait `Mirror` is implemented for `dyn A` + +error[E0277]: the trait bound `(dyn B + 'static): Mirror` is not satisfied + --> $DIR/projection-dyn-associated-type.rs:22:6 + | +LL | ) -> &'a <dyn B + 'static as Mirror>::Assoc { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Mirror` is not implemented for `(dyn B + 'static)` + | + = help: the trait `Mirror` is implemented for `dyn A` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors; 1 warning emitted + +Some errors have detailed explanations: E0207, E0277. +For more information about an error, try `rustc --explain E0207`. diff --git a/tests/ui/async-await/higher-ranked-normalize-assumptions-2.rs b/tests/ui/async-await/higher-ranked-normalize-assumptions-2.rs new file mode 100644 index 00000000000..410d4e503b7 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-normalize-assumptions-2.rs @@ -0,0 +1,38 @@ +//@ revisions: stock hr +//@[hr] compile-flags: -Zhigher-ranked-assumptions +//@ edition: 2024 +//@ check-pass + +// Test that we don't normalize the higher-ranked assumptions of an auto trait goal +// unless we have `-Zhigher-ranked-assumptions`, since obligations that result from +// this normalization may lead to higher-ranked lifetime errors when the flag is not +// enabled. + +// Regression test for <https://github.com/rust-lang/rust/issues/147244>. + +pub fn a() -> impl Future + Send { + async { + let queries = core::iter::empty().map(Thing::f); + b(queries).await; + } +} + +async fn b(queries: impl IntoIterator) { + c(queries).await; +} + +fn c<'a, I>(_queries: I) -> impl Future +where + I: IntoIterator, + I::IntoIter: 'a, +{ + async {} +} + +pub struct Thing<'a>(pub &'a ()); + +impl Thing<'_> { + fn f(_: &Self) {} +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-normalize-assumptions.rs b/tests/ui/async-await/higher-ranked-normalize-assumptions.rs new file mode 100644 index 00000000000..ec9cf3a1522 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-normalize-assumptions.rs @@ -0,0 +1,51 @@ +//@ revisions: stock hr +//@[hr] compile-flags: -Zhigher-ranked-assumptions +//@ edition: 2024 +//@ check-pass + +// Test that we don't normalize the higher-ranked assumptions of an auto trait goal +// unless we have `-Zhigher-ranked-assumptions`, since obligations that result from +// this normalization may lead to higher-ranked lifetime errors when the flag is not +// enabled. + +// Regression test for <https://github.com/rust-lang/rust/issues/147285>. + +pub trait Service { + type Response; +} + +impl<T, R> Service for T +where + T: FnMut() -> R, + R: 'static, +{ + type Response = R; +} + +async fn serve<C>(_: C) +where + C: Service, + C::Response: 'static, +{ + connect::<C>().await; +} + +async fn connect<C>() +where + C: Service, + C::Response: 'static, +{ +} + +fn repro() -> impl Send { + async { + let server = || do_something(); + serve(server).await; + } +} + +fn do_something() -> Box<dyn std::error::Error> { + unimplemented!() +} + +fn main() {} diff --git a/tests/ui/consts/std/conjure_zst.rs b/tests/ui/consts/std/conjure_zst.rs new file mode 100644 index 00000000000..c04deae502b --- /dev/null +++ b/tests/ui/consts/std/conjure_zst.rs @@ -0,0 +1,10 @@ +#![feature(mem_conjure_zst)] + +use std::{convert::Infallible, mem}; + +const INVALID: Infallible = unsafe { mem::conjure_zst() }; +//~^ ERROR attempted to instantiate uninhabited type + +const VALID: () = unsafe { mem::conjure_zst() }; + +fn main() {} diff --git a/tests/ui/consts/std/conjure_zst.stderr b/tests/ui/consts/std/conjure_zst.stderr new file mode 100644 index 00000000000..0c4a978b81e --- /dev/null +++ b/tests/ui/consts/std/conjure_zst.stderr @@ -0,0 +1,12 @@ +error[E0080]: evaluation panicked: aborted execution: attempted to instantiate uninhabited type `Infallible` + --> $DIR/conjure_zst.rs:5:38 + | +LL | const INVALID: Infallible = unsafe { mem::conjure_zst() }; + | ^^^^^^^^^^^^^^^^^^ evaluation of `INVALID` failed inside this call + | +note: inside `conjure_zst::<Infallible>` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/delegation/unsupported.stderr b/tests/ui/delegation/unsupported.current.stderr index f69be60133e..55564e8f231 100644 --- a/tests/ui/delegation/unsupported.stderr +++ b/tests/ui/delegation/unsupported.current.stderr @@ -1,43 +1,43 @@ -error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::opaque_ret::{anon_assoc#0}` - --> $DIR/unsupported.rs:22:25 +error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:24>::opaque_ret::{anon_assoc#0}` + --> $DIR/unsupported.rs:30:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/unsupported.rs:22:25 + --> $DIR/unsupported.rs:30:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::opaque_ret::{anon_assoc#0}`, completing the cycle -note: cycle used when checking assoc item `opaque::<impl at $DIR/unsupported.rs:21:5: 21:24>::opaque_ret` is compatible with trait definition - --> $DIR/unsupported.rs:22:25 + = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:24>::opaque_ret::{anon_assoc#0}`, completing the cycle +note: cycle used when checking assoc item `opaque::<impl at $DIR/unsupported.rs:29:5: 29:24>::opaque_ret` is compatible with trait definition + --> $DIR/unsupported.rs:30:25 | LL | reuse to_reuse::opaque_ret; | ^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::opaque_ret::{anon_assoc#0}` - --> $DIR/unsupported.rs:25:24 +error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:32:5: 32:25>::opaque_ret::{anon_assoc#0}` + --> $DIR/unsupported.rs:33:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ | note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... - --> $DIR/unsupported.rs:25:24 + --> $DIR/unsupported.rs:33:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ - = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::opaque_ret::{anon_assoc#0}`, completing the cycle -note: cycle used when checking assoc item `opaque::<impl at $DIR/unsupported.rs:24:5: 24:25>::opaque_ret` is compatible with trait definition - --> $DIR/unsupported.rs:25:24 + = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:32:5: 32:25>::opaque_ret::{anon_assoc#0}`, completing the cycle +note: cycle used when checking assoc item `opaque::<impl at $DIR/unsupported.rs:32:5: 32:25>::opaque_ret` is compatible with trait definition + --> $DIR/unsupported.rs:33:24 | LL | reuse ToReuse::opaque_ret; | ^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information error: recursive delegation is not supported yet - --> $DIR/unsupported.rs:38:22 + --> $DIR/unsupported.rs:46:22 | LL | pub reuse to_reuse2::foo; | --- callee defined here @@ -46,7 +46,7 @@ LL | reuse to_reuse1::foo; | ^^^ error[E0283]: type annotations needed - --> $DIR/unsupported.rs:48:18 + --> $DIR/unsupported.rs:56:18 | LL | reuse Trait::foo; | ^^^ cannot infer type diff --git a/tests/ui/delegation/unsupported.next.stderr b/tests/ui/delegation/unsupported.next.stderr new file mode 100644 index 00000000000..606a25d4269 --- /dev/null +++ b/tests/ui/delegation/unsupported.next.stderr @@ -0,0 +1,51 @@ +error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:24>::opaque_ret::{anon_assoc#0}` + --> $DIR/unsupported.rs:30:25 + | +LL | reuse to_reuse::opaque_ret; + | ^^^^^^^^^^ + | +note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... + --> $DIR/unsupported.rs:30:25 + | +LL | reuse to_reuse::opaque_ret; + | ^^^^^^^^^^ + = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:29:5: 29:24>::opaque_ret::{anon_assoc#0}`, completing the cycle + = note: cycle used when computing implied outlives bounds for `<u8 as opaque::ToReuse>::opaque_ret::{anon_assoc#0}` (hack disabled = false) + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:32:5: 32:25>::opaque_ret::{anon_assoc#0}` + --> $DIR/unsupported.rs:33:24 + | +LL | reuse ToReuse::opaque_ret; + | ^^^^^^^^^^ + | +note: ...which requires comparing an impl and trait method signature, inferring any hidden `impl Trait` types in the process... + --> $DIR/unsupported.rs:33:24 + | +LL | reuse ToReuse::opaque_ret; + | ^^^^^^^^^^ + = note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:32:5: 32:25>::opaque_ret::{anon_assoc#0}`, completing the cycle + = note: cycle used when computing implied outlives bounds for `<u16 as opaque::ToReuse>::opaque_ret::{anon_assoc#0}` (hack disabled = false) + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error: recursive delegation is not supported yet + --> $DIR/unsupported.rs:46:22 + | +LL | pub reuse to_reuse2::foo; + | --- callee defined here +... +LL | reuse to_reuse1::foo; + | ^^^ + +error[E0283]: type annotations needed + --> $DIR/unsupported.rs:56:18 + | +LL | reuse Trait::foo; + | ^^^ cannot infer type + | + = note: cannot satisfy `_: effects::Trait` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0283, E0391. +For more information about an error, try `rustc --explain E0283`. diff --git a/tests/ui/delegation/unsupported.rs b/tests/ui/delegation/unsupported.rs index af1c20976d7..79bab342da0 100644 --- a/tests/ui/delegation/unsupported.rs +++ b/tests/ui/delegation/unsupported.rs @@ -1,3 +1,11 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-fail + +// Next solver revision included because of trait-system-refactor-initiative#234. +// If we end up in a query cycle, it should be okay as long as results are the same. + #![feature(const_trait_impl)] #![feature(c_variadic)] #![feature(fn_delegation)] diff --git a/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr b/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr index c74cb89f85c..286d6021396 100644 --- a/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr +++ b/tests/ui/did_you_mean/issue-48492-tuple-destructure-missing-parens.stderr @@ -32,10 +32,10 @@ help: try adding parentheses to match on a tuple... | LL | (Nucleotide::Adenine, Nucleotide::Cytosine, _) => true | + + -help: ...or a vertical bar to match on multiple alternatives +help: ...or a vertical bar to match on alternatives | LL - Nucleotide::Adenine, Nucleotide::Cytosine, _ => true -LL + Nucleotide::Adenine | Nucleotide::Cytosine | _ => true +LL + Nucleotide::Adenine | Nucleotide::Cytosine, _ => true | error: unexpected `,` in pattern diff --git a/tests/ui/extern/extern-types-field-offset.rs b/tests/ui/extern/extern-types-field-offset.rs index 7a5f36da209..470ae07a0b5 100644 --- a/tests/ui/extern/extern-types-field-offset.rs +++ b/tests/ui/extern/extern-types-field-offset.rs @@ -23,12 +23,17 @@ fn main() { let x: &Newtype = unsafe { &*(&buf as *const _ as *const Newtype) }; // Projecting to the newtype works, because it is always at offset 0. let field = &x.0; + // Avoid being eliminated by DSE. + std::hint::black_box(field); let x: &S = unsafe { &*(&buf as *const _ as *const S) }; // Accessing sized fields is perfectly fine, even at non-zero offsets. let field = &x.i; + std::hint::black_box(field); let field = &x.j; + std::hint::black_box(field); // This needs to compute the field offset, but we don't know the type's alignment, // so this panics. let field = &x.a; + std::hint::black_box(field); } diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.stderr b/tests/ui/feature-gates/feature-gate-never_patterns.stderr index 473e263c796..e655209924a 100644 --- a/tests/ui/feature-gates/feature-gate-never_patterns.stderr +++ b/tests/ui/feature-gates/feature-gate-never_patterns.stderr @@ -8,7 +8,7 @@ help: try adding parentheses to match on a tuple... | LL | (Some(_),) | + + -help: ...or a vertical bar to match on multiple alternatives +help: ...or a vertical bar to match on alternatives | LL - Some(_), LL + Some(_) | diff --git a/tests/ui/panics/panic-abort-backtrace-without-debuginfo.rs b/tests/ui/panics/panic-abort-backtrace-without-debuginfo.rs new file mode 100644 index 00000000000..a29afd68523 --- /dev/null +++ b/tests/ui/panics/panic-abort-backtrace-without-debuginfo.rs @@ -0,0 +1,57 @@ +//! Test that with `-C panic=abort` the backtrace is not cut off by default +//! (i.e. without using `-C force-unwind-tables=yes`) by ensuring that our own +//! functions are in the backtrace. If we just check one function it might be +//! the last function, so make sure the backtrace can continue by checking for +//! two functions. Regression test for +//! <https://github.com/rust-lang/rust/issues/81902>. + +//@ run-pass +//@ needs-subprocess +// We want to test if unwind tables are emitted by default. We must make sure +// to disable debuginfo to test that, because enabling debuginfo also means that +// unwind tables are emitted, which prevents us from testing what we want. +// We also need to set opt-level=0 to avoid optimizing away our functions. +//@ compile-flags: -C panic=abort -C opt-level=0 -C debuginfo=0 +//@ no-prefer-dynamic +//@ ignore-apple +//@ ignore-arm-unknown-linux-gnueabihf FIXME(#146996) Try removing this once #146996 has been fixed. +//@ ignore-msvc Backtraces on Windows requires debuginfo which we can't use here + +static FN_1: &str = "this_function_must_be_in_the_backtrace"; +fn this_function_must_be_in_the_backtrace() { + and_this_function_too(); +} + +static FN_2: &str = "and_this_function_too"; +fn and_this_function_too() { + panic!("generate panic backtrace"); +} + +fn run_test() { + let output = std::process::Command::new(std::env::current_exe().unwrap()) + .arg("whatever") + .env("RUST_BACKTRACE", "full") + .output() + .unwrap(); + let backtrace = std::str::from_utf8(&output.stderr).unwrap(); + + fn assert(function_name: &str, backtrace: &str) { + assert!( + backtrace.contains(function_name), + "ERROR: no `{}` in stderr! actual stderr: {}", + function_name, + backtrace + ); + } + assert(FN_1, backtrace); + assert(FN_2, backtrace); +} + +fn main() { + let args: Vec<String> = std::env::args().collect(); + if args.len() == 1 { + run_test(); + } else { + this_function_must_be_in_the_backtrace(); + } +} diff --git a/tests/ui/parser/match-arm-without-body.rs b/tests/ui/parser/match-arm-without-body.rs index 4723abff8b6..7fe5b6d2539 100644 --- a/tests/ui/parser/match-arm-without-body.rs +++ b/tests/ui/parser/match-arm-without-body.rs @@ -17,13 +17,13 @@ fn main() { Some(_), //~^ ERROR unexpected `,` in pattern //~| HELP try adding parentheses to match on a tuple - //~| HELP or a vertical bar to match on multiple alternatives + //~| HELP or a vertical bar to match on alternative } match Some(false) { Some(_), //~^ ERROR unexpected `,` in pattern //~| HELP try adding parentheses to match on a tuple - //~| HELP or a vertical bar to match on multiple alternatives + //~| HELP or a vertical bar to match on alternative _ => {} } match Some(false) { diff --git a/tests/ui/parser/match-arm-without-body.stderr b/tests/ui/parser/match-arm-without-body.stderr index a65875b787a..59a323f2cc1 100644 --- a/tests/ui/parser/match-arm-without-body.stderr +++ b/tests/ui/parser/match-arm-without-body.stderr @@ -16,7 +16,7 @@ help: try adding parentheses to match on a tuple... | LL | (Some(_),) | + + -help: ...or a vertical bar to match on multiple alternatives +help: ...or a vertical bar to match on alternatives | LL - Some(_), LL + Some(_) | @@ -36,13 +36,10 @@ LL | LL | LL ~ _) => {} | -help: ...or a vertical bar to match on multiple alternatives +help: ...or a vertical bar to match on alternatives | -LL ~ Some(_) | -LL + -LL + -LL + -LL ~ _ => {} +LL - Some(_), +LL + Some(_) | | error: expected one of `.`, `=>`, `?`, or an operator, found reserved identifier `_` diff --git a/tests/ui/suggestions/only-replace-intended-coma-not-all-in-pattern.fixed b/tests/ui/suggestions/only-replace-intended-coma-not-all-in-pattern.fixed new file mode 100644 index 00000000000..0258f868f00 --- /dev/null +++ b/tests/ui/suggestions/only-replace-intended-coma-not-all-in-pattern.fixed @@ -0,0 +1,18 @@ +//@ run-rustfix + +// Regression test for issue #143330. +// Ensure we suggest to replace only the intended coma with a bar, not all commas in the pattern. + +fn main() { + struct Foo { x: i32, ch: char } + let pos = Foo { x: 2, ch: 'x' }; + match pos { + // All commas here were replaced with bars. + // Foo { x: 2 | ch: ' |' } | Foo { x: 3 | ch: '@' } => (), + (Foo { x: 2, ch: ',' } | Foo { x: 3, ch: '@' }) => (), + //~^ ERROR unexpected `,` in pattern + //~| HELP try adding parentheses to match on a tuple... + //~| HELP ...or a vertical bar to match on alternative + _ => todo!(), + } +} diff --git a/tests/ui/suggestions/only-replace-intended-coma-not-all-in-pattern.rs b/tests/ui/suggestions/only-replace-intended-coma-not-all-in-pattern.rs new file mode 100644 index 00000000000..7d5087fa0ff --- /dev/null +++ b/tests/ui/suggestions/only-replace-intended-coma-not-all-in-pattern.rs @@ -0,0 +1,18 @@ +//@ run-rustfix + +// Regression test for issue #143330. +// Ensure we suggest to replace only the intended coma with a bar, not all commas in the pattern. + +fn main() { + struct Foo { x: i32, ch: char } + let pos = Foo { x: 2, ch: 'x' }; + match pos { + // All commas here were replaced with bars. + // Foo { x: 2 | ch: ' |' } | Foo { x: 3 | ch: '@' } => (), + Foo { x: 2, ch: ',' }, Foo { x: 3, ch: '@' } => (), + //~^ ERROR unexpected `,` in pattern + //~| HELP try adding parentheses to match on a tuple... + //~| HELP ...or a vertical bar to match on alternative + _ => todo!(), + } +} diff --git a/tests/ui/suggestions/only-replace-intended-coma-not-all-in-pattern.stderr b/tests/ui/suggestions/only-replace-intended-coma-not-all-in-pattern.stderr new file mode 100644 index 00000000000..ee75e2db133 --- /dev/null +++ b/tests/ui/suggestions/only-replace-intended-coma-not-all-in-pattern.stderr @@ -0,0 +1,18 @@ +error: unexpected `,` in pattern + --> $DIR/only-replace-intended-coma-not-all-in-pattern.rs:12:30 + | +LL | Foo { x: 2, ch: ',' }, Foo { x: 3, ch: '@' } => (), + | ^ + | +help: try adding parentheses to match on a tuple... + | +LL | (Foo { x: 2, ch: ',' }, Foo { x: 3, ch: '@' }) => (), + | + + +help: ...or a vertical bar to match on alternatives + | +LL - Foo { x: 2, ch: ',' }, Foo { x: 3, ch: '@' } => (), +LL + Foo { x: 2, ch: ',' } | Foo { x: 3, ch: '@' } => (), + | + +error: aborting due to 1 previous error + |
