diff options
| author | Ralf Jung <post@ralfj.de> | 2023-12-10 09:03:54 +0100 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2023-12-10 09:03:54 +0100 |
| commit | 035d86594ddcaec12b59c35f8de1a99c3b8b81fb (patch) | |
| tree | 0a9542f67746bf7a90b8bb4881b56de39b138cb9 /tests | |
| parent | e8a25b0723b2d4e693881ecd4c1d4c7f8ba8eb51 (diff) | |
| parent | 43714edb6f291892f571875b42235208f075884f (diff) | |
| download | rust-035d86594ddcaec12b59c35f8de1a99c3b8b81fb.tar.gz rust-035d86594ddcaec12b59c35f8de1a99c3b8b81fb.zip | |
Merge from rustc
Diffstat (limited to 'tests')
239 files changed, 5117 insertions, 1581 deletions
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs new file mode 100644 index 00000000000..7b1fb320894 --- /dev/null +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs @@ -0,0 +1,34 @@ +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct Vec2<T>(pub T, pub T); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct Vec4<T>(pub T, pub T, pub T, pub T); + +extern "platform-intrinsic" { + fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T; +} + +// CHECK-LABEL: @load_f32x2 +#[no_mangle] +pub unsafe fn load_f32x2(mask: Vec2<i32>, pointer: *const f32, + values: Vec2<f32>) -> Vec2<f32> { + // CHECK: call <2 x float> @llvm.masked.load.v2f32.p0(ptr {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x float> {{.*}}) + simd_masked_load(mask, pointer, values) +} + +// CHECK-LABEL: @load_pf32x4 +#[no_mangle] +pub unsafe fn load_pf32x4(mask: Vec4<i32>, pointer: *const *const f32, + values: Vec4<*const f32>) -> Vec4<*const f32> { + // CHECK: call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr {{.*}}, i32 {{.*}}, <4 x i1> {{.*}}, <4 x ptr> {{.*}}) + simd_masked_load(mask, pointer, values) +} diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs new file mode 100644 index 00000000000..d8a37020f23 --- /dev/null +++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs @@ -0,0 +1,32 @@ +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct Vec2<T>(pub T, pub T); + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct Vec4<T>(pub T, pub T, pub T, pub T); + +extern "platform-intrinsic" { + fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> (); +} + +// CHECK-LABEL: @store_f32x2 +#[no_mangle] +pub unsafe fn store_f32x2(mask: Vec2<i32>, pointer: *mut f32, values: Vec2<f32>) { + // CHECK: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}) + simd_masked_store(mask, pointer, values) +} + +// CHECK-LABEL: @store_pf32x4 +#[no_mangle] +pub unsafe fn store_pf32x4(mask: Vec4<i32>, pointer: *mut *const f32, values: Vec4<*const f32>) { + // CHECK: call void @llvm.masked.store.v4p0.p0(<4 x ptr> {{.*}}, ptr {{.*}}, i32 {{.*}}, <4 x i1> {{.*}}) + simd_masked_store(mask, pointer, values) +} diff --git a/tests/coverage/if_not.cov-map b/tests/coverage/if_not.cov-map new file mode 100644 index 00000000000..fb893e37960 --- /dev/null +++ b/tests/coverage/if_not.cov-map @@ -0,0 +1,39 @@ +Function name: if_not::if_not +Raw bytes (86): 0x[01, 01, 10, 01, 05, 05, 02, 3f, 09, 05, 02, 09, 3a, 3f, 09, 05, 02, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0d, 32, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0a, 01, 04, 01, 03, 0d, 02, 04, 05, 02, 06, 05, 02, 06, 00, 07, 3f, 03, 09, 01, 0d, 3a, 02, 05, 02, 06, 09, 02, 06, 00, 07, 37, 03, 09, 01, 0d, 32, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 2f, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 16 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Expression(15, Add), rhs = Counter(2) +- expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 4 operands: lhs = Counter(2), rhs = Expression(14, Sub) +- expression 5 operands: lhs = Expression(15, Add), rhs = Counter(2) +- expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 7 operands: lhs = Expression(13, Add), rhs = Counter(3) +- expression 8 operands: lhs = Counter(2), rhs = Expression(14, Sub) +- expression 9 operands: lhs = Expression(15, Add), rhs = Counter(2) +- expression 10 operands: lhs = Counter(1), rhs = Expression(0, Sub) +- expression 11 operands: lhs = Counter(3), rhs = Expression(12, Sub) +- expression 12 operands: lhs = Expression(13, Add), rhs = Counter(3) +- expression 13 operands: lhs = Counter(2), rhs = Expression(14, Sub) +- expression 14 operands: lhs = Expression(15, Add), rhs = Counter(2) +- expression 15 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13) +- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 2, 6) + = (c0 - c1) +- Code(Counter(1)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(15, Add)) at (prev + 3, 9) to (start + 1, 13) + = (c1 + (c0 - c1)) +- Code(Expression(14, Sub)) at (prev + 2, 5) to (start + 2, 6) + = ((c1 + (c0 - c1)) - c2) +- Code(Counter(2)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(13, Add)) at (prev + 3, 9) to (start + 1, 13) + = (c2 + ((c1 + (c0 - c1)) - c2)) +- Code(Expression(12, Sub)) at (prev + 2, 5) to (start + 2, 6) + = ((c2 + ((c1 + (c0 - c1)) - c2)) - c3) +- Code(Counter(3)) at (prev + 2, 12) to (start + 2, 6) +- Code(Expression(11, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) + diff --git a/tests/coverage/if_not.coverage b/tests/coverage/if_not.coverage new file mode 100644 index 00000000000..41838b8513f --- /dev/null +++ b/tests/coverage/if_not.coverage @@ -0,0 +1,38 @@ + LL| |#![feature(coverage_attribute)] + LL| |// edition: 2021 + LL| | + LL| 12|fn if_not(cond: bool) { + LL| 12| if + LL| 12| ! + LL| 12| cond + LL| 4| { + LL| 4| println!("cond was false"); + LL| 8| } + LL| | + LL| | if + LL| 12| ! + LL| 12| cond + LL| 4| { + LL| 4| println!("cond was false"); + LL| 8| } + LL| | + LL| | if + LL| 12| ! + LL| 12| cond + LL| 4| { + LL| 4| println!("cond was false"); + LL| 8| } else { + LL| 8| println!("cond was true"); + LL| 8| } + LL| 12|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | for _ in 0..8 { + LL| | if_not(std::hint::black_box(true)); + LL| | } + LL| | for _ in 0..4 { + LL| | if_not(std::hint::black_box(false)); + LL| | } + LL| |} + diff --git a/tests/coverage/if_not.rs b/tests/coverage/if_not.rs new file mode 100644 index 00000000000..4f45ae0b3d4 --- /dev/null +++ b/tests/coverage/if_not.rs @@ -0,0 +1,37 @@ +#![feature(coverage_attribute)] +// edition: 2021 + +fn if_not(cond: bool) { + if + ! + cond + { + println!("cond was false"); + } + + if + ! + cond + { + println!("cond was false"); + } + + if + ! + cond + { + println!("cond was false"); + } else { + println!("cond was true"); + } +} + +#[coverage(off)] +fn main() { + for _ in 0..8 { + if_not(std::hint::black_box(true)); + } + for _ in 0..4 { + if_not(std::hint::black_box(false)); + } +} diff --git a/tests/coverage/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map index 0ad393c40fa..2d1ff24e62d 100644 --- a/tests/coverage/lazy_boolean.cov-map +++ b/tests/coverage/lazy_boolean.cov-map @@ -1,5 +1,5 @@ Function name: lazy_boolean::main -Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 04, 09, 00, 10, ea, 04, 01, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 09, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02] +Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 03, 09, 01, 10, ea, 04, 02, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 08, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 164 @@ -194,9 +194,9 @@ Number of file 0 mappings: 28 - Code(Expression(157, Add)) at (prev + 0, 20) to (start + 0, 25) = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - Code(Counter(5)) at (prev + 0, 29) to (start + 0, 34) -- Code(Expression(155, Add)) at (prev + 4, 9) to (start + 0, 16) +- Code(Expression(155, Add)) at (prev + 3, 9) to (start + 1, 16) = (c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) -- Code(Expression(154, Sub)) at (prev + 1, 5) to (start + 3, 6) +- Code(Expression(154, Sub)) at (prev + 2, 5) to (start + 3, 6) = ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6) - Code(Counter(6)) at (prev + 3, 6) to (start + 0, 7) - Code(Expression(153, Add)) at (prev + 3, 9) to (start + 0, 16) @@ -204,7 +204,7 @@ Number of file 0 mappings: 28 - Code(Counter(7)) at (prev + 1, 5) to (start + 3, 6) - Code(Expression(152, Sub)) at (prev + 5, 5) to (start + 3, 6) = ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7) -- Code(Expression(151, Add)) at (prev + 5, 9) to (start + 0, 16) +- Code(Expression(151, Add)) at (prev + 5, 8) to (start + 0, 16) = (c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - Code(Expression(150, Sub)) at (prev + 0, 17) to (start + 2, 6) = ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8) diff --git a/tests/coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage index 8f14082ef68..2d927a08356 100644 --- a/tests/coverage/lazy_boolean.coverage +++ b/tests/coverage/lazy_boolean.coverage @@ -32,7 +32,7 @@ ^0 LL| | LL| | if - LL| | ! + LL| 1| ! LL| 1| is_true LL| 0| { LL| 0| a = 2 diff --git a/tests/coverage/no_spans.cov-map b/tests/coverage/no_spans.cov-map new file mode 100644 index 00000000000..9915fc52e6d --- /dev/null +++ b/tests/coverage/no_spans.cov-map @@ -0,0 +1,8 @@ +Function name: no_spans::affected_function::{closure#0} +Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 0c, 00, 0e] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 27, 12) to (start + 0, 14) + diff --git a/tests/coverage/no_spans.coverage b/tests/coverage/no_spans.coverage new file mode 100644 index 00000000000..e55177698a2 --- /dev/null +++ b/tests/coverage/no_spans.coverage @@ -0,0 +1,30 @@ + LL| |#![feature(coverage_attribute)] + LL| |// edition: 2021 + LL| | + LL| |// If the span extractor can't find any relevant spans for a function, the + LL| |// refinement loop will terminate with nothing in its `prev` slot. If the + LL| |// subsequent code tries to unwrap `prev`, it will panic. + LL| |// + LL| |// This scenario became more likely after #118525 started discarding spans that + LL| |// can't be un-expanded back to within the function body. + LL| |// + LL| |// Regression test for "invalid attempt to unwrap a None some_prev", as seen + LL| |// in issues such as #118643 and #118662. + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | affected_function()(); + LL| |} + LL| | + LL| |macro_rules! macro_that_defines_a_function { + LL| | (fn $name:ident () $body:tt) => { + LL| | fn $name () -> impl Fn() $body + LL| | } + LL| |} + LL| | + LL| |macro_that_defines_a_function! { + LL| | fn affected_function() { + LL| 1| || () + LL| | } + LL| |} + diff --git a/tests/coverage/no_spans.rs b/tests/coverage/no_spans.rs new file mode 100644 index 00000000000..a5234bc6b60 --- /dev/null +++ b/tests/coverage/no_spans.rs @@ -0,0 +1,29 @@ +#![feature(coverage_attribute)] +// edition: 2021 + +// If the span extractor can't find any relevant spans for a function, the +// refinement loop will terminate with nothing in its `prev` slot. If the +// subsequent code tries to unwrap `prev`, it will panic. +// +// This scenario became more likely after #118525 started discarding spans that +// can't be un-expanded back to within the function body. +// +// Regression test for "invalid attempt to unwrap a None some_prev", as seen +// in issues such as #118643 and #118662. + +#[coverage(off)] +fn main() { + affected_function()(); +} + +macro_rules! macro_that_defines_a_function { + (fn $name:ident () $body:tt) => { + fn $name () -> impl Fn() $body + } +} + +macro_that_defines_a_function! { + fn affected_function() { + || () + } +} diff --git a/tests/mir-opt/const_prop/address_of_pair.rs b/tests/mir-opt/const_prop/address_of_pair.rs index 169469a0739..730ebe2ca63 100644 --- a/tests/mir-opt/const_prop/address_of_pair.rs +++ b/tests/mir-opt/const_prop/address_of_pair.rs @@ -1,8 +1,21 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR address_of_pair.fn0.ConstProp.diff pub fn fn0() -> bool { + // CHECK-LABEL: fn fn0( + // CHECK: debug pair => [[pair:_.*]]; + // CHECK: debug ptr => [[ptr:_.*]]; + // CHECK: debug ret => [[ret:_.*]]; + // CHECK: (*[[ptr]]) = const true; + // CHECK-NOT: = const false; + // CHECK-NOT: = const true; + // CHECK: [[tmp:_.*]] = ([[pair]].1: bool); + // CHECK-NOT: = const false; + // CHECK-NOT: = const true; + // CHECK: [[ret]] = Not(move [[tmp]]); + // CHECK-NOT: = const false; + // CHECK-NOT: = const true; + // CHECK: _0 = [[ret]]; let mut pair = (1, false); let ptr = core::ptr::addr_of_mut!(pair.1); pair = (1, false); diff --git a/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-abort.mir b/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-abort.mir deleted file mode 100644 index b9c5859cade..00000000000 --- a/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-abort.mir +++ /dev/null @@ -1,49 +0,0 @@ -// MIR for `foo` after PreCodegen - -fn foo(_1: u8) -> () { - debug x => _1; - let mut _0: (); - let _2: i32; - let mut _3: i32; - let mut _4: (i32, u8); - let mut _5: u8; - let mut _7: i32; - let mut _8: (u8, i32); - let mut _9: u8; - scope 1 { - debug first => _2; - let _6: i32; - scope 2 { - debug second => _6; - } - } - - bb0: { - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); - _5 = _1; - _4 = (const 0_i32, move _5); - StorageDead(_5); - _3 = const 0_i32; - _2 = const 1_i32; - StorageDead(_3); - StorageDead(_4); - StorageLive(_6); - StorageLive(_7); - StorageLive(_8); - StorageLive(_9); - _9 = _1; - _8 = (move _9, const 1_i32); - StorageDead(_9); - _7 = const 1_i32; - _6 = const 3_i32; - StorageDead(_7); - StorageDead(_8); - _0 = const (); - StorageDead(_6); - StorageDead(_2); - return; - } -} diff --git a/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-unwind.mir deleted file mode 100644 index b9c5859cade..00000000000 --- a/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-unwind.mir +++ /dev/null @@ -1,49 +0,0 @@ -// MIR for `foo` after PreCodegen - -fn foo(_1: u8) -> () { - debug x => _1; - let mut _0: (); - let _2: i32; - let mut _3: i32; - let mut _4: (i32, u8); - let mut _5: u8; - let mut _7: i32; - let mut _8: (u8, i32); - let mut _9: u8; - scope 1 { - debug first => _2; - let _6: i32; - scope 2 { - debug second => _6; - } - } - - bb0: { - StorageLive(_2); - StorageLive(_3); - StorageLive(_4); - StorageLive(_5); - _5 = _1; - _4 = (const 0_i32, move _5); - StorageDead(_5); - _3 = const 0_i32; - _2 = const 1_i32; - StorageDead(_3); - StorageDead(_4); - StorageLive(_6); - StorageLive(_7); - StorageLive(_8); - StorageLive(_9); - _9 = _1; - _8 = (move _9, const 1_i32); - StorageDead(_9); - _7 = const 1_i32; - _6 = const 3_i32; - StorageDead(_7); - StorageDead(_8); - _0 = const (); - StorageDead(_6); - StorageDead(_2); - return; - } -} diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-abort.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-abort.mir deleted file mode 100644 index 44a85a5636b..00000000000 --- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-abort.mir +++ /dev/null @@ -1,36 +0,0 @@ -// MIR for `main` after PreCodegen - -fn main() -> () { - let mut _0: (); - let _1: u8; - let mut _2: u8; - let mut _3: (i32, u8, i32); - let _4: (); - let mut _5: u8; - scope 1 { - debug x => _1; - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - StorageLive(_3); - _3 = (const 0_i32, const 1_u8, const 2_i32); - _2 = const 1_u8; - _1 = const 1_u8; - StorageDead(_2); - StorageDead(_3); - StorageLive(_4); - StorageLive(_5); - _5 = const 1_u8; - _4 = foo(const 1_u8) -> [return: bb1, unwind unreachable]; - } - - bb1: { - StorageDead(_5); - StorageDead(_4); - _0 = const (); - StorageDead(_1); - return; - } -} diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir deleted file mode 100644 index 2c7bdbb5055..00000000000 --- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir +++ /dev/null @@ -1,36 +0,0 @@ -// MIR for `main` after PreCodegen - -fn main() -> () { - let mut _0: (); - let _1: u8; - let mut _2: u8; - let mut _3: (i32, u8, i32); - let _4: (); - let mut _5: u8; - scope 1 { - debug x => _1; - } - - bb0: { - StorageLive(_1); - StorageLive(_2); - StorageLive(_3); - _3 = (const 0_i32, const 1_u8, const 2_i32); - _2 = const 1_u8; - _1 = const 1_u8; - StorageDead(_2); - StorageDead(_3); - StorageLive(_4); - StorageLive(_5); - _5 = const 1_u8; - _4 = foo(const 1_u8) -> [return: bb1, unwind continue]; - } - - bb1: { - StorageDead(_5); - StorageDead(_4); - _0 = const (); - StorageDead(_1); - return; - } -} diff --git a/tests/mir-opt/const_prop/aggregate.rs b/tests/mir-opt/const_prop/aggregate.rs index 2e043af08bf..fa716b0843d 100644 --- a/tests/mir-opt/const_prop/aggregate.rs +++ b/tests/mir-opt/const_prop/aggregate.rs @@ -1,19 +1,29 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp // compile-flags: -O // EMIT_MIR aggregate.main.ConstProp.diff -// EMIT_MIR aggregate.main.PreCodegen.after.mir fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK-NOT: = Add( + // CHECK: [[x]] = const 1_u8; + // CHECK-NOT: = Add( + // CHECK: foo(const 1_u8) let x = (0, 1, 2).1 + 0; foo(x); } +// Verify that we still propagate if part of the aggregate is not known. // EMIT_MIR aggregate.foo.ConstProp.diff -// EMIT_MIR aggregate.foo.PreCodegen.after.mir fn foo(x: u8) { - // Verify that we still propagate if part of the aggregate is not known. + // CHECK-LABEL: fn foo( + // CHECK: debug first => [[first:_.*]]; + // CHECK: debug second => [[second:_.*]]; + // CHECK-NOT: = Add( + // CHECK: [[first]] = const 1_i32; + // CHECK-NOT: = Add( + // CHECK: [[second]] = const 3_i32; let first = (0, x).0 + 1; let second = (x, 1).1 + 2; } diff --git a/tests/mir-opt/const_prop/array_index.rs b/tests/mir-opt/const_prop/array_index.rs index 3bd2321653d..c4c46d78f75 100644 --- a/tests/mir-opt/const_prop/array_index.rs +++ b/tests/mir-opt/const_prop/array_index.rs @@ -1,9 +1,11 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR array_index.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[x]] = const 2_u32; let x: u32 = [0, 1, 2, 3][2]; } diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs index ab41f64a573..0e8765a0771 100644 --- a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs +++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs @@ -1,9 +1,15 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + // EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff #[allow(unconditional_panic)] fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug y => [[y:_.*]]; + // CHECK: debug _z => [[z:_.*]]; + // CHECK: assert(!const true, "attempt to divide `{}` by zero", const 1_i32) + // CHECK: assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, const 0_i32) + // CHECK: [[z]] = Div(const 1_i32, const 0_i32); let y = 0; let _z = 1 / y; } diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs index e747b21cf9b..d895d9e2155 100644 --- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs +++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs @@ -1,9 +1,16 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY + // EMIT_MIR bad_op_mod_by_zero.main.ConstProp.diff #[allow(unconditional_panic)] fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug y => [[y:_.*]]; + // CHECK: debug _z => [[z:_.*]]; + // CHECK: assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of + // zero", const 1_i32) + // CHECK: assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, const 0_i32) + // CHECK: [[z]] = Rem(const 1_i32, const 0_i32); let y = 0; let _z = 1 % y; } diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs index 38c97a4cf0e..266105c11f2 100644 --- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs +++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH @@ -6,6 +5,10 @@ // EMIT_MIR bad_op_unsafe_oob_for_slices.main.ConstProp.diff #[allow(unconditional_panic)] fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug _b => [[b:_.*]]; + // CHECK: [[b]] = (*[[a]])[3 of 4]; let a: *const [_] = &[1, 2, 3]; unsafe { let _b = (*a)[3]; diff --git a/tests/mir-opt/const_prop/boolean_identities.rs b/tests/mir-opt/const_prop/boolean_identities.rs index 781cce8c7dd..2aa038034d8 100644 --- a/tests/mir-opt/const_prop/boolean_identities.rs +++ b/tests/mir-opt/const_prop/boolean_identities.rs @@ -1,10 +1,16 @@ -// skip-filecheck // unit-test: ConstProp -// compile-flags: -O -Zmir-opt-level=4 // EMIT_MIR boolean_identities.test.ConstProp.diff pub fn test(x: bool, y: bool) -> bool { - (y | true) & (x & false) + // CHECK-LABEL: fn test( + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: [[a]] = const true; + // CHECK: [[b]] = const false; + // CHECK: _0 = const false; + let a = (y | true); + let b = (x & false); + a & b } fn main() { diff --git a/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff b/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff index d805341991d..41e1acdff59 100644 --- a/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff +++ b/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff @@ -5,20 +5,42 @@ debug x => _1; debug y => _2; let mut _0: bool; - let mut _3: bool; + let _3: bool; let mut _4: bool; - let mut _5: bool; let mut _6: bool; + let mut _7: bool; + let mut _8: bool; + scope 1 { + debug a => _3; + let _5: bool; + scope 2 { + debug b => _5; + } + } bb0: { StorageLive(_3); -- _3 = BitOr(_2, const true); + StorageLive(_4); + _4 = _2; +- _3 = BitOr(move _4, const true); + _3 = const true; + StorageDead(_4); StorageLive(_5); -- _5 = BitAnd(_1, const false); -- _0 = BitAnd(move _3, move _5); + StorageLive(_6); + _6 = _1; +- _5 = BitAnd(move _6, const false); + _5 = const false; + StorageDead(_6); + StorageLive(_7); +- _7 = _3; ++ _7 = const true; + StorageLive(_8); +- _8 = _5; +- _0 = BitAnd(move _7, move _8); ++ _8 = const false; + _0 = const false; + StorageDead(_8); + StorageDead(_7); StorageDead(_5); StorageDead(_3); return; diff --git a/tests/mir-opt/const_prop/boxes.rs b/tests/mir-opt/const_prop/boxes.rs index c6807ece199..90a8e33e823 100644 --- a/tests/mir-opt/const_prop/boxes.rs +++ b/tests/mir-opt/const_prop/boxes.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: ConstProp // compile-flags: -O // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -9,6 +8,11 @@ // EMIT_MIR boxes.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: (*{{_.*}}) = const 42_i32; + // CHECK: [[tmp:_.*]] = (*{{_.*}}); + // CHECK: [[x]] = Add(move [[tmp]], const 0_i32); let x = *(#[rustc_box] Box::new(42)) + 0; diff --git a/tests/mir-opt/const_prop/cast.rs b/tests/mir-opt/const_prop/cast.rs index 3d543badace..b81c2740a73 100644 --- a/tests/mir-opt/const_prop/cast.rs +++ b/tests/mir-opt/const_prop/cast.rs @@ -1,9 +1,12 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR cast.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: [[x]] = const 42_u32; + // CHECK: [[y]] = const 42_u8; let x = 42u8 as u32; - let y = 42u32 as u8; } diff --git a/tests/mir-opt/const_prop/checked_add.rs b/tests/mir-opt/const_prop/checked_add.rs index 6a53aced091..571a5cc4e4d 100644 --- a/tests/mir-opt/const_prop/checked_add.rs +++ b/tests/mir-opt/const_prop/checked_add.rs @@ -1,9 +1,12 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp // compile-flags: -C overflow-checks=on // EMIT_MIR checked_add.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: assert(!const false, + // CHECK: [[x]] = const 2_u32; let x: u32 = 1 + 1; } diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs b/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs deleted file mode 100644 index 5bd4731bf08..00000000000 --- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs +++ /dev/null @@ -1,12 +0,0 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY -// unit-test: ConstProp -#[inline(never)] -fn read(_: usize) { } - -// EMIT_MIR const_prop_fails_gracefully.main.ConstProp.diff -fn main() { - const FOO: &i32 = &1; - let x = FOO as *const i32 as usize; - read(x); -} diff --git a/tests/mir-opt/const_prop/discriminant.rs b/tests/mir-opt/const_prop/discriminant.rs index 11405f38bdc..0ed683d629c 100644 --- a/tests/mir-opt/const_prop/discriminant.rs +++ b/tests/mir-opt/const_prop/discriminant.rs @@ -1,6 +1,4 @@ -// skip-filecheck // unit-test: ConstProp -// compile-flags: -O // FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with // `let x = 42` but that doesn't work because const-prop doesn't support `Operand::Indirect` @@ -10,5 +8,18 @@ // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR discriminant.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: bb0: { + // CHECK: switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; + // CHECK: bb1: { + // CHECK: switchInt(const true) -> [0: bb3, otherwise: bb2]; + // CHECK: bb2: { + // CHECK: [[tmp:_.*]] = const 42_i32; + // CHECK: goto -> bb4; + // CHECK: bb3: { + // CHECK: [[tmp]] = const 10_i32; + // CHECK: goto -> bb4; + // CHECK: bb4: { + // CHECK: {{_.*}} = Add(move [[tmp]], const 0_i32); let x = (if let Some(true) = Some(true) { 42 } else { 10 }) + 0; } diff --git a/tests/mir-opt/const_prop/indirect.rs b/tests/mir-opt/const_prop/indirect.rs index 0e6e1d78d1e..d3c42e3eb0b 100644 --- a/tests/mir-opt/const_prop/indirect.rs +++ b/tests/mir-opt/const_prop/indirect.rs @@ -1,9 +1,11 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp // compile-flags: -C overflow-checks=on // EMIT_MIR indirect.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[x]] = const 3_u8; let x = (2u32 as u8) + 1; } diff --git a/tests/mir-opt/const_prop/inherit_overflow.rs b/tests/mir-opt/const_prop/inherit_overflow.rs index 41989462deb..5b561ae14ad 100644 --- a/tests/mir-opt/const_prop/inherit_overflow.rs +++ b/tests/mir-opt/const_prop/inherit_overflow.rs @@ -1,11 +1,14 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp // compile-flags: -Zmir-enable-passes=+Inline +// After inlining, this will contain a `CheckedBinaryOp`. +// Propagating the overflow is ok as codegen will just skip emitting the panic. // EMIT_MIR inherit_overflow.main.ConstProp.diff fn main() { - // After inlining, this will contain a `CheckedBinaryOp`. - // Propagating the overflow is ok as codegen will just skip emitting the panic. + // CHECK-LABEL: fn main( + // CHECK: {{_.*}} = const (0_u8, true); + // CHECK: assert(!const true, + // CHECK: {{_.*}} = const 0_u8; let _ = <u8 as std::ops::Add>::add(255, 1); } diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff index 6484b4b67af..ff93c85e586 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff @@ -5,17 +5,24 @@ let mut _0: (); let _1: (); let mut _2: ((), u8, u8); + let mut _3: (); bb0: { + StorageLive(_1); StorageLive(_2); -- _2 = (const (), const 0_u8, const 0_u8); -- _1 = encode(move _2) -> [return: bb1, unwind unreachable]; + StorageLive(_3); + _3 = (); +- _2 = (move _3, const 0_u8, const 0_u8); + _2 = const ((), 0_u8, 0_u8); + StorageDead(_3); +- _1 = encode(move _2) -> [return: bb1, unwind unreachable]; + _1 = encode(const ((), 0_u8, 0_u8)) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_2); + StorageDead(_1); + _0 = const (); return; } + } diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff index b02f0407839..8790aad4559 100644 --- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff @@ -5,17 +5,24 @@ let mut _0: (); let _1: (); let mut _2: ((), u8, u8); + let mut _3: (); bb0: { + StorageLive(_1); StorageLive(_2); -- _2 = (const (), const 0_u8, const 0_u8); -- _1 = encode(move _2) -> [return: bb1, unwind continue]; + StorageLive(_3); + _3 = (); +- _2 = (move _3, const 0_u8, const 0_u8); + _2 = const ((), 0_u8, 0_u8); + StorageDead(_3); +- _1 = encode(move _2) -> [return: bb1, unwind continue]; + _1 = encode(const ((), 0_u8, 0_u8)) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_2); + StorageDead(_1); + _0 = const (); return; } + } diff --git a/tests/mir-opt/const_prop/issue_66971.rs b/tests/mir-opt/const_prop/issue_66971.rs index 386c95b5b69..49d598ff230 100644 --- a/tests/mir-opt/const_prop/issue_66971.rs +++ b/tests/mir-opt/const_prop/issue_66971.rs @@ -1,7 +1,5 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp -// compile-flags: -Z mir-opt-level=3 // Due to a bug in propagating scalar pairs the assertion below used to fail. In the expected // outputs below, after ConstProp this is how _2 would look like with the bug: @@ -16,5 +14,7 @@ fn encode(this: ((), u8, u8)) { // EMIT_MIR issue_66971.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: = encode(const ((), 0_u8, 0_u8)) encode(((), 0, 0)); } diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff index c1ef453e9df..3de9cdd79bc 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff @@ -8,6 +8,7 @@ let mut _3: (u8, u8); bb0: { + StorageLive(_1); StorageLive(_2); StorageLive(_3); - _3 = (const 1_u8, const 2_u8); @@ -21,6 +22,8 @@ bb1: { StorageDead(_2); + StorageDead(_1); + _0 = const (); return; } + } diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff index 53cdcc18167..72cf48b5cba 100644 --- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff @@ -8,6 +8,7 @@ let mut _3: (u8, u8); bb0: { + StorageLive(_1); StorageLive(_2); StorageLive(_3); - _3 = (const 1_u8, const 2_u8); @@ -21,6 +22,8 @@ bb1: { StorageDead(_2); + StorageDead(_1); + _0 = const (); return; } + } diff --git a/tests/mir-opt/const_prop/issue_67019.rs b/tests/mir-opt/const_prop/issue_67019.rs index 2f61298bb98..f0a09e6e852 100644 --- a/tests/mir-opt/const_prop/issue_67019.rs +++ b/tests/mir-opt/const_prop/issue_67019.rs @@ -1,7 +1,5 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp -// compile-flags: -Z mir-opt-level=3 // This used to ICE in const-prop @@ -11,5 +9,7 @@ fn test(this: ((u8, u8),)) { // EMIT_MIR issue_67019.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: = test(const ((1_u8, 2_u8),)) test(((1, 2),)); } diff --git a/tests/mir-opt/const_prop/mult_by_zero.rs b/tests/mir-opt/const_prop/mult_by_zero.rs index 47e15205ea9..2e9c63a1ca1 100644 --- a/tests/mir-opt/const_prop/mult_by_zero.rs +++ b/tests/mir-opt/const_prop/mult_by_zero.rs @@ -1,9 +1,10 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR mult_by_zero.test.ConstProp.diff -fn test(x : i32) -> i32 { - x * 0 +fn test(x: i32) -> i32 { + // CHECK: fn test( + // CHECK: _0 = const 0_i32; + x * 0 } fn main() { diff --git a/tests/mir-opt/const_prop/mutable_variable.rs b/tests/mir-opt/const_prop/mutable_variable.rs index 175d63d46f5..6c74ea5b9f4 100644 --- a/tests/mir-opt/const_prop/mutable_variable.rs +++ b/tests/mir-opt/const_prop/mutable_variable.rs @@ -1,8 +1,13 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR mutable_variable.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: [[x]] = const 42_i32; + // CHECK: [[x]] = const 99_i32; + // CHECK: [[y]] = const 99_i32; let mut x = 42; x = 99; let y = x; diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate.rs index f926771ae38..a3829650290 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.rs @@ -1,8 +1,13 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR mutable_variable_aggregate.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: [[x]] = const (42_i32, 43_i32); + // CHECK: ([[x]].1: i32) = const 99_i32; + // CHECK: [[y]] = const (42_i32, 99_i32); let mut x = (42, 43); x.1 = 99; let y = x; diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs index a81aa7b4979..60f414ae286 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs @@ -1,8 +1,15 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR mutable_variable_aggregate_mut_ref.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug z => [[z:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: [[x]] = (const 42_i32, const 43_i32); + // CHECK: [[z]] = &mut [[x]]; + // CHECK: ((*[[z]]).1: i32) = const 99_i32; + // CHECK: [[y]] = [[x]]; let mut x = (42, 43); let z = &mut x; z.1 = 99; diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs index 54a5d922321..888fcde2de6 100644 --- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs +++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs @@ -1,9 +1,15 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp // EMIT_MIR mutable_variable_aggregate_partial_read.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: [[x]] = foo() + // CHECK: ([[x]].1: i32) = const 99_i32; + // CHECK: ([[x]].0: i32) = const 42_i32; + // CHECK: [[y]] = const 99_i32; let mut x: (i32, i32) = foo(); x.1 = 99; x.0 = 42; diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs index a7aeeccd861..49e9a701581 100644 --- a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs +++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs @@ -1,10 +1,17 @@ -// skip-filecheck // unit-test: ConstProp +// Verify that we do not propagate the contents of this mutable static. static mut STATIC: u32 = 0x42424242; // EMIT_MIR mutable_variable_no_prop.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: [[x]] = const 42_u32; + // CHECK: [[tmp:_.*]] = (*{{_.*}}); + // CHECK: [[x]] = move [[tmp]]; + // CHECK: [[y]] = [[x]]; let mut x = 42; unsafe { x = STATIC; diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs index 6bdb136a949..04e347fc03d 100644 --- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs +++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs @@ -1,14 +1,24 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp // EMIT_MIR mutable_variable_unprop_assign.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: debug z => [[z:_.*]]; + // CHECK: [[a]] = foo() + // CHECK: [[x]] = const (1_i32, 2_i32); + // CHECK: [[tmp:_.*]] = [[a]]; + // CHECK: ([[x]].1: i32) = move [[tmp]]; + // CHECK: [[y]] = ([[x]].1: i32); + // CHECK: [[z]] = const 1_i32; let a = foo(); let mut x: (i32, i32) = (1, 2); x.1 = a; let y = x.1; - let z = x.0; // this could theoretically be allowed, but we can't handle it right now + let z = x.0; } #[inline(never)] diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-abort.diff index bd1de7476a2..bd1de7476a2 100644 --- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-abort.diff +++ b/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-abort.diff diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-unwind.diff index 850b743feb1..850b743feb1 100644 --- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-unwind.diff +++ b/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-unwind.diff diff --git a/tests/mir-opt/const_prop/pointer_expose_address.rs b/tests/mir-opt/const_prop/pointer_expose_address.rs new file mode 100644 index 00000000000..631aac901b9 --- /dev/null +++ b/tests/mir-opt/const_prop/pointer_expose_address.rs @@ -0,0 +1,18 @@ +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// unit-test: ConstProp + +#[inline(never)] +fn read(_: usize) { } + +// EMIT_MIR pointer_expose_address.main.ConstProp.diff +fn main() { + // CHECK-LABEL: fn main( + // CHECK: [[ptr:_.*]] = const _; + // CHECK: [[ref:_.*]] = &raw const (*[[ptr]]); + // CHECK: [[x:_.*]] = move [[ref]] as usize (PointerExposeAddress); + // CHECK: [[arg:_.*]] = [[x]]; + // CHECK: = read(move [[arg]]) + const FOO: &i32 = &1; + let x = FOO as *const i32 as usize; + read(x); +} diff --git a/tests/mir-opt/const_prop/read_immutable_static.rs b/tests/mir-opt/const_prop/read_immutable_static.rs index a8d8cfacc7c..0fa18dd101a 100644 --- a/tests/mir-opt/const_prop/read_immutable_static.rs +++ b/tests/mir-opt/const_prop/read_immutable_static.rs @@ -1,9 +1,11 @@ -// skip-filecheck // unit-test: ConstProp static FOO: u8 = 2; // EMIT_MIR read_immutable_static.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[x]] = const 4_u8; let x = FOO + FOO; } diff --git a/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff index 6b897a88181..a54ae8d2fdd 100644 --- a/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff @@ -7,6 +7,9 @@ let mut _2: &i32; let _3: i32; let mut _4: &i32; + scope 1 { + debug a => _1; + } bb0: { StorageLive(_1); @@ -15,8 +18,8 @@ _2 = &(*_4); _1 = (*_2); StorageDead(_2); - StorageDead(_1); _0 = const (); + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/ref_deref.rs b/tests/mir-opt/const_prop/ref_deref.rs index f2fa024f722..5bceae749ff 100644 --- a/tests/mir-opt/const_prop/ref_deref.rs +++ b/tests/mir-opt/const_prop/ref_deref.rs @@ -1,7 +1,9 @@ -// skip-filecheck // unit-test: ConstProp -// EMIT_MIR ref_deref.main.ConstProp.diff +// EMIT_MIR ref_deref.main.ConstProp.diff fn main() { - *(&4); + // CHECK-LABEL: fn main( + // CHECK: debug a => [[a:_.*]]; + // CHECK: [[a]] = (*{{_.*}}); + let a = *(&4); } diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff index 7f616166573..05a4e17742d 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff +++ b/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff @@ -7,6 +7,9 @@ let mut _2: &i32; let _3: (i32, i32); let mut _4: &(i32, i32); + scope 1 { + debug a => _1; + } bb0: { StorageLive(_1); @@ -15,8 +18,8 @@ _2 = &((*_4).1: i32); _1 = (*_2); StorageDead(_2); - StorageDead(_1); _0 = const (); + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/ref_deref_project.rs b/tests/mir-opt/const_prop/ref_deref_project.rs index 1b9e0acb2c0..4b5c6730316 100644 --- a/tests/mir-opt/const_prop/ref_deref_project.rs +++ b/tests/mir-opt/const_prop/ref_deref_project.rs @@ -1,7 +1,10 @@ -// skip-filecheck +// This does not currently propagate (#67862) // unit-test: ConstProp -// EMIT_MIR ref_deref_project.main.ConstProp.diff +// EMIT_MIR ref_deref_project.main.ConstProp.diff fn main() { - *(&(4, 5).1); // This does not currently propagate (#67862) + // CHECK-LABEL: fn main( + // CHECK: debug a => [[a:_.*]]; + // CHECK: [[a]] = (*{{_.*}}); + let a = *(&(4, 5).1); } diff --git a/tests/mir-opt/const_prop/reify_fn_ptr.rs b/tests/mir-opt/const_prop/reify_fn_ptr.rs index da7de80c5f4..33fdd4142c1 100644 --- a/tests/mir-opt/const_prop/reify_fn_ptr.rs +++ b/tests/mir-opt/const_prop/reify_fn_ptr.rs @@ -1,7 +1,10 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR reify_fn_ptr.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: [[ptr:_.*]] = main as fn() (PointerCoercion(ReifyFnPointer)); + // CHECK: [[addr:_.*]] = move [[ptr]] as usize (PointerExposeAddress); + // CHECK: [[back:_.*]] = move [[addr]] as *const fn() (PointerFromExposedAddress); let _ = main as usize as *const fn(); } diff --git a/tests/mir-opt/const_prop/repeat.rs b/tests/mir-opt/const_prop/repeat.rs index 92194d6bb58..9f688bbb53e 100644 --- a/tests/mir-opt/const_prop/repeat.rs +++ b/tests/mir-opt/const_prop/repeat.rs @@ -1,9 +1,11 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR repeat.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[x]] = const 42_u32; let x: u32 = [42; 8][2] + 0; } diff --git a/tests/mir-opt/const_prop/return_place.rs b/tests/mir-opt/const_prop/return_place.rs index 1263de7931f..286543abb99 100644 --- a/tests/mir-opt/const_prop/return_place.rs +++ b/tests/mir-opt/const_prop/return_place.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // compile-flags: -C overflow-checks=on @@ -6,6 +5,8 @@ // EMIT_MIR return_place.add.ConstProp.diff // EMIT_MIR return_place.add.PreCodegen.before.mir fn add() -> u32 { + // CHECK-LABEL: fn add( + // CHECK: _0 = const 4_u32; 2 + 2 } diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.rs b/tests/mir-opt/const_prop/scalar_literal_propagation.rs index 9dcddf7c770..782cd35d422 100644 --- a/tests/mir-opt/const_prop/scalar_literal_propagation.rs +++ b/tests/mir-opt/const_prop/scalar_literal_propagation.rs @@ -1,8 +1,10 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY + // EMIT_MIR scalar_literal_propagation.main.ConstProp.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: = consume(const 1_u32) let x = 1; consume(x); } diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff index c2e1288b41e..7d5d036f460 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff @@ -12,6 +12,9 @@ let mut _7: usize; let mut _8: bool; let mut _9: &[u32; 3]; + scope 1 { + debug a => _1; + } bb0: { StorageLive(_1); @@ -39,8 +42,8 @@ StorageDead(_6); StorageDead(_4); StorageDead(_2); - StorageDead(_1); _0 = const (); + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff index 23646c3c976..fa4c5a71be5 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff @@ -12,6 +12,9 @@ let mut _7: usize; let mut _8: bool; let mut _9: &[u32; 3]; + scope 1 { + debug a => _1; + } bb0: { StorageLive(_1); @@ -39,8 +42,8 @@ StorageDead(_6); StorageDead(_4); StorageDead(_2); - StorageDead(_1); _0 = const (); + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff index c2e1288b41e..7d5d036f460 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff @@ -12,6 +12,9 @@ let mut _7: usize; let mut _8: bool; let mut _9: &[u32; 3]; + scope 1 { + debug a => _1; + } bb0: { StorageLive(_1); @@ -39,8 +42,8 @@ StorageDead(_6); StorageDead(_4); StorageDead(_2); - StorageDead(_1); _0 = const (); + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff index 23646c3c976..fa4c5a71be5 100644 --- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff +++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff @@ -12,6 +12,9 @@ let mut _7: usize; let mut _8: bool; let mut _9: &[u32; 3]; + scope 1 { + debug a => _1; + } bb0: { StorageLive(_1); @@ -39,8 +42,8 @@ StorageDead(_6); StorageDead(_4); StorageDead(_2); - StorageDead(_1); _0 = const (); + StorageDead(_1); return; } } diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs index 3b551b6b173..0bf44272698 100644 --- a/tests/mir-opt/const_prop/slice_len.rs +++ b/tests/mir-opt/const_prop/slice_len.rs @@ -1,10 +1,13 @@ -// skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: ConstProp // compile-flags: -Zmir-enable-passes=+InstSimplify +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR slice_len.main.ConstProp.diff fn main() { - (&[1u32, 2, 3] as &[u32])[1]; + // CHECK-LABEL: fn main( + // CHECK: debug a => [[a:_.*]]; + // CHECK: assert(const true, + // CHECK: [[a]] = const 2_u32; + let a = (&[1u32, 2, 3] as &[u32])[1]; } diff --git a/tests/mir-opt/const_prop/switch_int.rs b/tests/mir-opt/const_prop/switch_int.rs index 7ec56e11e85..d1cbaae49aa 100644 --- a/tests/mir-opt/const_prop/switch_int.rs +++ b/tests/mir-opt/const_prop/switch_int.rs @@ -1,13 +1,20 @@ -// skip-filecheck // unit-test: ConstProp // compile-flags: -Zmir-enable-passes=+SimplifyConstCondition-after-const-prop // EMIT_MIR_FOR_EACH_PANIC_STRATEGY + #[inline(never)] fn foo(_: i32) { } // EMIT_MIR switch_int.main.ConstProp.diff // EMIT_MIR switch_int.main.SimplifyConstCondition-after-const-prop.diff fn main() { + // CHECK-LABEL: fn main( + // CHECK: bb0: { + // CHECK-NOT: switchInt( + // CHECK: goto -> [[bb:bb.*]]; + // CHECK: [[bb]]: { + // CHECK-NOT: _0 = foo(const -1_i32) + // CHECK: _0 = foo(const 0_i32) match 1 { 1 => foo(0), _ => foo(-1), diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.rs b/tests/mir-opt/const_prop/tuple_literal_propagation.rs index e0bc6e1be37..dfc4a6f3fbb 100644 --- a/tests/mir-opt/const_prop/tuple_literal_propagation.rs +++ b/tests/mir-opt/const_prop/tuple_literal_propagation.rs @@ -1,10 +1,11 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR tuple_literal_propagation.main.ConstProp.diff + fn main() { + // CHECK-LABEL: fn main( + // CHECK: = consume(const (1_u32, 2_u32)) let x = (1, 2); - consume(x); } diff --git a/tests/mir-opt/const_prop/while_let_loops.rs b/tests/mir-opt/const_prop/while_let_loops.rs index 39081c3550a..8b2a73438d6 100644 --- a/tests/mir-opt/const_prop/while_let_loops.rs +++ b/tests/mir-opt/const_prop/while_let_loops.rs @@ -1,8 +1,9 @@ -// skip-filecheck // unit-test: ConstProp // EMIT_MIR while_let_loops.change_loop_body.ConstProp.diff pub fn change_loop_body() { + // CHECK-LABEL: fn change_loop_body( + // CHECK: switchInt(const 0_isize) let mut _x = 0; while let Some(0u32) = None { _x = 1; diff --git a/tests/run-make/jobserver-error/cannot_open_fd.stderr b/tests/run-make/jobserver-error/cannot_open_fd.stderr index a2f77a94e4f..343de5cd52c 100644 --- a/tests/run-make/jobserver-error/cannot_open_fd.stderr +++ b/tests/run-make/jobserver-error/cannot_open_fd.stderr @@ -4,5 +4,3 @@ warning: failed to connect to jobserver from environment variable `MAKEFLAGS="-- error: no input filename given -warning: 1 warning emitted - diff --git a/tests/run-make/jobserver-error/not_a_pipe.stderr b/tests/run-make/jobserver-error/not_a_pipe.stderr index 9158fda6e47..536c04576b9 100644 --- a/tests/run-make/jobserver-error/not_a_pipe.stderr +++ b/tests/run-make/jobserver-error/not_a_pipe.stderr @@ -2,5 +2,3 @@ warning: failed to connect to jobserver from environment variable `MAKEFLAGS="-- | = note: the build environment is likely misconfigured -warning: 1 warning emitted - diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml index 030ff8f8a3e..b46d4255ee5 100644 --- a/tests/rustdoc-gui/item-info.goml +++ b/tests/rustdoc-gui/item-info.goml @@ -8,7 +8,22 @@ assert-size: (".item-info", {"width": 840}) assert-size: (".item-info .stab", {"width": 289}) assert-position: (".item-info .stab", {"x": 245}) +// We check that the display of the feature elements is not broken. It serves as regression +// test for <https://github.com/rust-lang/rust/issues/118615>. +set-window-size: (850, 800) +store-position: ( + "//*[@class='stab portability']//code[text()='Win32_System']", + {"x": first_line_x, "y": first_line_y}, +) +store-position: ( + "//*[@class='stab portability']//code[text()='Win32_System_Diagnostics']", + {"x": second_line_x, "y": second_line_y}, +) +assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272 +assert: |first_line_y| != |second_line_y| && |first_line_y| == 688 && |second_line_y| == 711 + // Now we ensure that they're not rendered on the same line. +set-window-size: (1100, 800) go-to: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html" // We first ensure that there are two item info on the trait. assert-count: ("#main-content > .item-info .stab", 2) diff --git a/tests/rustdoc-gui/src/lib2/Cargo.toml b/tests/rustdoc-gui/src/lib2/Cargo.toml index 8bca77ff834..6c4ca27d550 100644 --- a/tests/rustdoc-gui/src/lib2/Cargo.toml +++ b/tests/rustdoc-gui/src/lib2/Cargo.toml @@ -6,6 +6,13 @@ edition = "2018" [lib] path = "lib.rs" +[features] +Win32 = ["Win32_System"] +Win32_System = ["Win32_System_Diagnostics"] +Win32_System_Diagnostics = ["Win32_System_Diagnostics_Debug"] +Win32_System_Diagnostics_Debug = [] +default = ["Win32"] + [dependencies] implementors = { path = "./implementors" } http = { path = "./http" } diff --git a/tests/rustdoc-gui/src/lib2/lib.rs b/tests/rustdoc-gui/src/lib2/lib.rs index a2a3c31878b..b467b044052 100644 --- a/tests/rustdoc-gui/src/lib2/lib.rs +++ b/tests/rustdoc-gui/src/lib2/lib.rs @@ -1,6 +1,7 @@ // ignore-tidy-linelength #![feature(doc_cfg)] +#![feature(doc_auto_cfg)] pub mod another_folder; pub mod another_mod; @@ -28,6 +29,14 @@ impl Foo { /// Some documentation /// # A Heading pub fn a_method(&self) {} + + #[cfg(all( + feature = "Win32", + feature = "Win32_System", + feature = "Win32_System_Diagnostics", + feature = "Win32_System_Diagnostics_Debug" + ))] + pub fn lot_of_features() {} } #[doc(cfg(feature = "foo-method"))] diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index 9e581620ec1..fe5333643ed 100644 --- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs @@ -132,7 +132,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) { binder: ClosureBinder::NotPresent, capture_clause: CaptureBy::Value { move_kw: DUMMY_SP }, constness: Const::No, - coro_kind: None, + coroutine_kind: None, movability: Movability::Movable, fn_decl: decl.clone(), body: e, diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs index 170b1fd73b1..88c41537d9f 100644 --- a/tests/ui-fulldeps/stable-mir/check_allocation.rs +++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs @@ -23,12 +23,16 @@ extern crate stable_mir; use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; -use stable_mir::{CrateItem, CrateItems, ItemKind}; use stable_mir::crate_def::CrateDef; use stable_mir::mir::alloc::GlobalAlloc; -use stable_mir::mir::mono::StaticDef; +use stable_mir::mir::mono::{Instance, InstanceKind, StaticDef}; +use stable_mir::mir::{Body, TerminatorKind}; +use stable_mir::ty::{Allocation, ConstantKind, RigidTy, TyKind}; +use stable_mir::{CrateItem, CrateItems, ItemKind}; use std::ascii::Char; use std::assert_matches::assert_matches; +use std::cmp::{max, min}; +use std::collections::HashMap; use std::io::Write; use std::ops::ControlFlow; @@ -40,6 +44,9 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { let items = stable_mir::all_local_items(); check_foo(*get_item(&items, (ItemKind::Static, "FOO")).unwrap()); check_bar(*get_item(&items, (ItemKind::Static, "BAR")).unwrap()); + check_len(*get_item(&items, (ItemKind::Static, "LEN")).unwrap()); + check_other_consts(*get_item(&items, (ItemKind::Fn, "other_consts")).unwrap()); + check_type_id(*get_item(&items, (ItemKind::Fn, "check_type_id")).unwrap()); ControlFlow::Continue(()) } @@ -76,6 +83,110 @@ fn check_bar(item: CrateItem) { assert_eq!(allocation.bytes[0].unwrap(), Char::CapitalB.to_u8()); assert_eq!(allocation.bytes[1].unwrap(), Char::SmallA.to_u8()); assert_eq!(allocation.bytes[2].unwrap(), Char::SmallR.to_u8()); + assert_eq!(std::str::from_utf8(&allocation.raw_bytes().unwrap()), Ok("Bar")); +} + +/// Check the allocation data for constants used in `other_consts` function. +fn check_other_consts(item: CrateItem) { + // Instance body will force constant evaluation. + let body = Instance::try_from(item).unwrap().body().unwrap(); + let assigns = collect_consts(&body); + assert_eq!(assigns.len(), 9); + for (name, alloc) in assigns { + match name.as_str() { + "_max_u128" => { + assert_eq!(alloc.read_uint(), Ok(u128::MAX), "Failed parsing allocation: {alloc:?}") + } + "_min_i128" => { + assert_eq!(alloc.read_int(), Ok(i128::MIN), "Failed parsing allocation: {alloc:?}") + } + "_max_i8" => { + assert_eq!( + alloc.read_int().unwrap() as i8, + i8::MAX, + "Failed parsing allocation: {alloc:?}" + ) + } + "_char" => { + assert_eq!( + char::from_u32(alloc.read_uint().unwrap() as u32), + Some('x'), + "Failed parsing allocation: {alloc:?}" + ) + } + "_false" => { + assert_eq!(alloc.read_bool(), Ok(false), "Failed parsing allocation: {alloc:?}") + } + "_true" => { + assert_eq!(alloc.read_bool(), Ok(true), "Failed parsing allocation: {alloc:?}") + } + "_ptr" => { + assert_eq!(alloc.is_null(), Ok(false), "Failed parsing allocation: {alloc:?}") + } + "_null_ptr" => { + assert_eq!(alloc.is_null(), Ok(true), "Failed parsing allocation: {alloc:?}") + } + "_tuple" => { + // The order of fields is not guaranteed. + let first = alloc.read_partial_uint(0..4).unwrap(); + let second = alloc.read_partial_uint(4..8).unwrap(); + assert_eq!(max(first, second) as u32, u32::MAX); + assert_eq!(min(first, second), 10); + } + _ => { + unreachable!("{name} -- {alloc:?}") + } + } + } +} + +/// Check that we can retrieve the type id of char and bool, and that they have different values. +fn check_type_id(item: CrateItem) { + let body = Instance::try_from(item).unwrap().body().unwrap(); + let mut ids: Vec<u128> = vec![]; + for term in body.blocks.iter().map(|bb| &bb.terminator) { + match &term.kind { + TerminatorKind::Call { func, destination, .. } => { + let TyKind::RigidTy(ty) = func.ty(body.locals()).unwrap().kind() else { + unreachable!() + }; + let RigidTy::FnDef(def, args) = ty else { unreachable!() }; + let instance = Instance::resolve(def, &args).unwrap(); + assert_eq!(instance.kind, InstanceKind::Intrinsic); + let dest_ty = destination.ty(body.locals()).unwrap(); + let alloc = instance.try_const_eval(dest_ty).unwrap(); + ids.push(alloc.read_uint().unwrap()); + } + _ => { /* Do nothing */ } + } + } + assert_eq!(ids.len(), 2); + assert_ne!(ids[0], ids[1]); +} + +/// Collects all the constant assignments. +pub fn collect_consts(body: &Body) -> HashMap<String, &Allocation> { + body.var_debug_info + .iter() + .filter_map(|info| { + info.constant().map(|const_op| { + let ConstantKind::Allocated(alloc) = const_op.const_.kind() else { unreachable!() }; + (info.name.clone(), alloc) + }) + }) + .collect::<HashMap<_, _>>() +} + +/// Check the allocation data for `LEN`. +/// +/// ```no_run +/// static LEN: usize = 2; +/// ``` +fn check_len(item: CrateItem) { + let def = StaticDef::try_from(item).unwrap(); + let alloc = def.eval_initializer().unwrap(); + assert!(alloc.provenance.ptrs.is_empty()); + assert_eq!(alloc.read_uint(), Ok(2)); } // Use internal API to find a function in a crate. @@ -83,9 +194,7 @@ fn get_item<'a>( items: &'a CrateItems, item: (ItemKind, &str), ) -> Option<&'a stable_mir::CrateItem> { - items.iter().find(|crate_item| { - (item.0 == crate_item.kind()) && crate_item.name() == item.1 - }) + items.iter().find(|crate_item| (item.0 == crate_item.kind()) && crate_item.name() == item.1) } /// This test will generate and analyze a dummy crate using the stable mir. @@ -109,11 +218,36 @@ fn generate_input(path: &str) -> std::io::Result<()> { write!( file, r#" + #![feature(core_intrinsics)] + use std::intrinsics::type_id; + + static LEN: usize = 2; static FOO: [&str; 2] = ["hi", "there"]; static BAR: &str = "Bar"; + const NULL: *const u8 = std::ptr::null(); + const TUPLE: (u32, u32) = (10, u32::MAX); + + fn other_consts() {{ + let _max_u128 = u128::MAX; + let _min_i128 = i128::MIN; + let _max_i8 = i8::MAX; + let _char = 'x'; + let _false = false; + let _true = true; + let _ptr = &BAR; + let _null_ptr: *const u8 = NULL; + let _tuple = TUPLE; + }} + + fn check_type_id() {{ + let _char_id = type_id::<char>(); + let _bool_id = type_id::<bool>(); + }} pub fn main() {{ println!("{{FOO:?}}! {{BAR}}"); + assert_eq!(FOO.len(), LEN); + other_consts(); }}"# )?; Ok(()) diff --git a/tests/ui/abi/riscv-discoverability-guidance.rs b/tests/ui/abi/riscv-discoverability-guidance.rs index f57fcd6044f..361ed8f3d91 100644 --- a/tests/ui/abi/riscv-discoverability-guidance.rs +++ b/tests/ui/abi/riscv-discoverability-guidance.rs @@ -2,9 +2,9 @@ // revisions: riscv32 riscv64 // // [riscv32] needs-llvm-components: riscv -// [riscv32] compile-flags: --target=riscv32i-unknown-none-elf -C target-feature=-unaligned-scalar-mem --crate-type=rlib +// [riscv32] compile-flags: --target=riscv32i-unknown-none-elf -C target-feature=-fast-unaligned-access --crate-type=rlib // [riscv64] needs-llvm-components: riscv -// [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf -C target-feature=-unaligned-scalar-mem --crate-type=rlib +// [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf -C target-feature=-fast-unaligned-access --crate-type=rlib #![no_core] #![feature( no_core, diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs b/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs new file mode 100644 index 00000000000..ac085864ff0 --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs @@ -0,0 +1,19 @@ +// We used to say "ambiguous associated type" on ambiguous associated consts. +// Ensure that we now use the correct label. + +#![feature(associated_const_equality)] + +trait Trait0: Parent0<i32> + Parent0<u32> {} +trait Parent0<T> { const K: (); } + +fn take0(_: impl Trait0<K = { () }>) {} +//~^ ERROR ambiguous associated constant `K` in bounds of `Trait0` + +trait Trait1: Parent1 + Parent2 {} +trait Parent1 { const C: i32; } +trait Parent2 { const C: &'static str; } + +fn take1(_: impl Trait1<C = "?">) {} +//~^ ERROR ambiguous associated constant `C` in bounds of `Trait1` + +fn main() {} diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr new file mode 100644 index 00000000000..ba3a8701316 --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr @@ -0,0 +1,38 @@ +error[E0222]: ambiguous associated constant `K` in bounds of `Trait0` + --> $DIR/assoc-const-eq-ambiguity.rs:9:25 + | +LL | trait Parent0<T> { const K: (); } + | ----------- + | | + | ambiguous `K` from `Parent0<u32>` + | ambiguous `K` from `Parent0<i32>` +LL | +LL | fn take0(_: impl Trait0<K = { () }>) {} + | ^^^^^^^^^^ ambiguous associated constant `K` + | + = help: consider introducing a new type parameter `T` and adding `where` constraints: + where + T: Trait0, + T: Parent0<u32>::K = { () }, + T: Parent0<i32>::K = { () } + +error[E0222]: ambiguous associated constant `C` in bounds of `Trait1` + --> $DIR/assoc-const-eq-ambiguity.rs:16:25 + | +LL | trait Parent1 { const C: i32; } + | ------------ ambiguous `C` from `Parent1` +LL | trait Parent2 { const C: &'static str; } + | --------------------- ambiguous `C` from `Parent2` +LL | +LL | fn take1(_: impl Trait1<C = "?">) {} + | ^^^^^^^ ambiguous associated constant `C` + | + = help: consider introducing a new type parameter `T` and adding `where` constraints: + where + T: Trait1, + T: Parent2::C = "?", + T: Parent1::C = "?" + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0222`. diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.rs b/tests/ui/associated-consts/assoc-const-eq-missing.rs index 5e029a12df2..f384927e4a3 100644 --- a/tests/ui/associated-consts/assoc-const-eq-missing.rs +++ b/tests/ui/associated-consts/assoc-const-eq-missing.rs @@ -11,13 +11,12 @@ impl Foo for Bar { const N: usize = 3; } - -fn foo1<F: Foo<Z=3>>() {} -//~^ ERROR associated type -fn foo2<F: Foo<Z=usize>>() {} -//~^ ERROR associated type -fn foo3<F: Foo<Z=5>>() {} -//~^ ERROR associated type +fn foo1<F: Foo<Z = 3>>() {} +//~^ ERROR associated constant `Z` not found for `Foo` +fn foo2<F: Foo<Z = usize>>() {} +//~^ ERROR associated type `Z` not found for `Foo` +fn foo3<F: Foo<Z = 5>>() {} +//~^ ERROR associated constant `Z` not found for `Foo` fn main() { foo1::<Bar>(); diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.stderr b/tests/ui/associated-consts/assoc-const-eq-missing.stderr index b4bd6456c85..318c85dcfd6 100644 --- a/tests/ui/associated-consts/assoc-const-eq-missing.stderr +++ b/tests/ui/associated-consts/assoc-const-eq-missing.stderr @@ -1,20 +1,20 @@ -error[E0220]: associated type `Z` not found for `Foo` - --> $DIR/assoc-const-eq-missing.rs:15:16 +error[E0220]: associated constant `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:14:16 | -LL | fn foo1<F: Foo<Z=3>>() {} - | ^ associated type `Z` not found +LL | fn foo1<F: Foo<Z = 3>>() {} + | ^ help: there is an associated constant with a similar name: `N` error[E0220]: associated type `Z` not found for `Foo` - --> $DIR/assoc-const-eq-missing.rs:17:16 + --> $DIR/assoc-const-eq-missing.rs:16:16 | -LL | fn foo2<F: Foo<Z=usize>>() {} +LL | fn foo2<F: Foo<Z = usize>>() {} | ^ associated type `Z` not found -error[E0220]: associated type `Z` not found for `Foo` - --> $DIR/assoc-const-eq-missing.rs:19:16 +error[E0220]: associated constant `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:18:16 | -LL | fn foo3<F: Foo<Z=5>>() {} - | ^ associated type `Z` not found +LL | fn foo3<F: Foo<Z = 5>>() {} + | ^ help: there is an associated constant with a similar name: `N` error: aborting due to 3 previous errors diff --git a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs new file mode 100644 index 00000000000..de9008bfcf9 --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs @@ -0,0 +1,21 @@ +// Regression test for issue #112560. +// Respect the fact that (associated) types and constants live in different namespaces and +// therefore equality bounds involving identically named associated items don't conflict if +// their kind (type vs. const) differs. + +// FIXME(fmease): Extend this test to cover supertraits again +// once #118040 is fixed. See initial version of PR #118360. + +// check-pass + +#![feature(associated_const_equality)] + +trait Trait { + type N; + + const N: usize; +} + +fn take(_: impl Trait<N = 0, N = ()>) {} + +fn main() {} diff --git a/tests/ui/associated-consts/assoc-const-ty-mismatch.rs b/tests/ui/associated-consts/assoc-const-ty-mismatch.rs index c5d78469e95..7211637659b 100644 --- a/tests/ui/associated-consts/assoc-const-ty-mismatch.rs +++ b/tests/ui/associated-consts/assoc-const-ty-mismatch.rs @@ -2,30 +2,30 @@ #![allow(unused)] pub trait Foo { - const N: usize; + const N: usize; } pub trait FooTy { - type T; + type T; } pub struct Bar; impl Foo for Bar { - const N: usize = 3; + const N: usize = 3; } impl FooTy for Bar { - type T = usize; + type T = usize; } -fn foo<F: Foo<N=usize>>() {} -//~^ ERROR expected associated constant bound, found type -fn foo2<F: FooTy<T=3usize>>() {} -//~^ ERROR expected associated type bound, found constant +fn foo<F: Foo<N = usize>>() {} +//~^ ERROR expected constant, found type +fn foo2<F: FooTy<T = 3usize>>() {} +//~^ ERROR expected type, found constant fn main() { - foo::<Bar>(); - foo2::<Bar>(); + foo::<Bar>(); + foo2::<Bar>(); } diff --git a/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr b/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr index 11198729e38..b844cfc4ae4 100644 --- a/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr +++ b/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr @@ -1,26 +1,30 @@ -error: expected associated constant bound, found type - --> $DIR/assoc-const-ty-mismatch.rs:23:15 +error: expected constant, found type + --> $DIR/assoc-const-ty-mismatch.rs:23:19 | -LL | fn foo<F: Foo<N=usize>>() {} - | ^^^^^^^ +LL | fn foo<F: Foo<N = usize>>() {} + | - ^^^^^ unexpected type + | | + | expected a constant because of this associated constant | -note: associated constant defined here - --> $DIR/assoc-const-ty-mismatch.rs:5:3 +note: the associated constant is defined here + --> $DIR/assoc-const-ty-mismatch.rs:5:5 | -LL | const N: usize; - | ^^^^^^^^^^^^^^ +LL | const N: usize; + | ^^^^^^^^^^^^^^ -error: expected associated type bound, found constant - --> $DIR/assoc-const-ty-mismatch.rs:25:18 +error: expected type, found constant + --> $DIR/assoc-const-ty-mismatch.rs:25:22 | -LL | fn foo2<F: FooTy<T=3usize>>() {} - | ^^^^^^^^ +LL | fn foo2<F: FooTy<T = 3usize>>() {} + | - ^^^^^^ unexpected constant + | | + | expected a type because of this associated type | -note: associated type defined here - --> $DIR/assoc-const-ty-mismatch.rs:9:3 +note: the associated type is defined here + --> $DIR/assoc-const-ty-mismatch.rs:9:5 | -LL | type T; - | ^^^^^^ +LL | type T; + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr index 6037122a365..1304bef4211 100644 --- a/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr +++ b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr @@ -4,8 +4,8 @@ error[E0308]: const not compatible with trait LL | const NAME: &'a str = "unit"; | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected reference `&'static str` - found reference `&'a str` + = note: expected reference `&'static _` + found reference `&'a _` note: the lifetime `'a` as defined here... --> $DIR/associated-const-impl-wrong-lifetime.rs:6:6 | diff --git a/tests/ui/associated-consts/shadowed-const.rs b/tests/ui/associated-consts/shadowed-const.rs index cfdb391d39d..d9b565742d4 100644 --- a/tests/ui/associated-consts/shadowed-const.rs +++ b/tests/ui/associated-consts/shadowed-const.rs @@ -17,7 +17,7 @@ trait Baz2: Foo { trait Baz3 { const BAR: usize; const QUX: Self::BAR; - //~^ ERROR found associated const + //~^ ERROR expected type, found constant } fn main() {} diff --git a/tests/ui/associated-consts/shadowed-const.stderr b/tests/ui/associated-consts/shadowed-const.stderr index a01a9ae561f..2db645b3c96 100644 --- a/tests/ui/associated-consts/shadowed-const.stderr +++ b/tests/ui/associated-consts/shadowed-const.stderr @@ -1,8 +1,14 @@ -error: found associated const `BAR` when type was expected - --> $DIR/shadowed-const.rs:19:14 +error: expected type, found constant + --> $DIR/shadowed-const.rs:19:20 | LL | const QUX: Self::BAR; - | ^^^^^^^^^ + | ^^^ unexpected constant + | +note: the associated constant is defined here + --> $DIR/shadowed-const.rs:18:3 + | +LL | const BAR: usize; + | ^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/consts.rs b/tests/ui/associated-type-bounds/consts.rs index 9b95b1b52c0..8f90c36ed45 100644 --- a/tests/ui/associated-type-bounds/consts.rs +++ b/tests/ui/associated-type-bounds/consts.rs @@ -1,7 +1,7 @@ #![feature(associated_type_bounds)] pub fn accept(_: impl Trait<K: Copy>) {} -//~^ ERROR expected associated type, found associated constant +//~^ ERROR expected type, found constant pub trait Trait { const K: i32; diff --git a/tests/ui/associated-type-bounds/consts.stderr b/tests/ui/associated-type-bounds/consts.stderr index eef24c8827b..7f9fe5e500a 100644 --- a/tests/ui/associated-type-bounds/consts.stderr +++ b/tests/ui/associated-type-bounds/consts.stderr @@ -1,10 +1,16 @@ -error: expected associated type, found associated constant +error: expected type, found constant --> $DIR/consts.rs:3:29 | LL | pub fn accept(_: impl Trait<K: Copy>) {} - | ^ + | ^------ bounds are not allowed on associated constants + | | + | unexpected constant | - = note: trait bounds not allowed on associated constant +note: the associated constant is defined here + --> $DIR/consts.rs:7:5 + | +LL | const K: i32; + | ^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/issue-99828.rs b/tests/ui/associated-type-bounds/issue-99828.rs index 7b711283f5b..67ba50f3cbc 100644 --- a/tests/ui/associated-type-bounds/issue-99828.rs +++ b/tests/ui/associated-type-bounds/issue-99828.rs @@ -1,5 +1,5 @@ fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ { - //~^ ERROR expected associated type bound, found constant + //~^ ERROR expected type, found constant //~| ERROR associated const equality is incomplete vec.iter() } diff --git a/tests/ui/associated-type-bounds/issue-99828.stderr b/tests/ui/associated-type-bounds/issue-99828.stderr index dc93c47dace..8813baf84de 100644 --- a/tests/ui/associated-type-bounds/issue-99828.stderr +++ b/tests/ui/associated-type-bounds/issue-99828.stderr @@ -7,13 +7,15 @@ LL | fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ { = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable -error: expected associated type bound, found constant - --> $DIR/issue-99828.rs:1:43 +error: expected type, found constant + --> $DIR/issue-99828.rs:1:50 | LL | fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ { - | ^^^^^^^^^ + | ---- ^^ unexpected constant + | | + | expected a type because of this associated type | -note: associated type defined here +note: the associated type is defined here --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL error: aborting due to 2 previous errors diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.rs b/tests/ui/associated-type-bounds/return-type-notation/missing.rs index 0679b96f6c5..e6270ec3166 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/missing.rs +++ b/tests/ui/associated-type-bounds/return-type-notation/missing.rs @@ -8,6 +8,6 @@ trait Trait { } fn bar<T: Trait<methid(): Send>>() {} -//~^ ERROR cannot find associated function `methid` for `Trait` +//~^ ERROR associated function `methid` not found for `Trait` fn main() {} diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr index 3ca5e66866d..db9cb9f49a3 100644 --- a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr +++ b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr @@ -7,11 +7,12 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information = note: `#[warn(incomplete_features)]` on by default -error: cannot find associated function `methid` for `Trait` +error[E0220]: associated function `methid` not found for `Trait` --> $DIR/missing.rs:10:17 | LL | fn bar<T: Trait<methid(): Send>>() {} - | ^^^^^^^^^^^^^^ + | ^^^^^^ help: there is an associated function with a similar name: `method` error: aborting due to 1 previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr index 606084aea34..1b4694a2125 100644 --- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr +++ b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | debug_assert_eq!(iter.next(), Some(value)); | ^^^^^^^^^^^ expected `Option<<I as Iterator>::Item>`, found `Option<&<I as Iterator>::Item>` | - = note: expected enum `Option<<I as Iterator>::Item>` - found enum `Option<&<I as Iterator>::Item>` + = note: expected enum `Option<_>` + found enum `Option<&_>` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr index 34aded73da5..54df0edf5a8 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr @@ -9,8 +9,8 @@ note: type in trait | LL | fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected signature `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>` - found signature `fn(&i32) -> impl Future<Output = i32>` + = note: expected signature `fn(&_) -> Pin<Box<dyn Future<Output = i32>>>` + found signature `fn(&_) -> impl Future<Output = i32>` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs index 891b30638ee..73c08531599 100644 --- a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs +++ b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs @@ -23,7 +23,7 @@ impl Foo for () {} fn test<T>() where T: Foo<test(): Send>, - //~^ ERROR ambiguous associated function `test` for `Foo` + //~^ ERROR ambiguous associated function `test` in bounds of `Foo` { } diff --git a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr index 7eaf3b82d98..4003aad6d03 100644 --- a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr +++ b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr @@ -7,13 +7,18 @@ LL | #![feature(return_type_notation)] = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information = note: `#[warn(incomplete_features)]` on by default -error: ambiguous associated function `test` for `Foo` +error[E0221]: ambiguous associated function `test` in bounds of `Foo` --> $DIR/super-method-bound-ambig.rs:25:12 | +LL | async fn test(); + | ---------------- ambiguous `test` from `for<'a> Super1<'a>` +... +LL | async fn test(); + | ---------------- ambiguous `test` from `Super2` +... LL | T: Foo<test(): Send>, - | ^^^^^^^^^^^^ - | - = note: `test` is declared in two supertraits: `Super2` and `Super1<'a>` + | ^^^^^^^^^^^^ ambiguous associated function `test` error: aborting due to 1 previous error; 1 warning emitted +For more information about this error, try `rustc --explain E0221`. diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 7ebea3c03d3..54d8f26f4ea 100644 --- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -22,8 +22,8 @@ error[E0308]: method not compatible with trait LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` - found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` + = note: expected signature `fn(&'a _, Inv<'c>, Inv<'c>, Inv<'_>)` + found signature `fn(&'a _, Inv<'_>, Inv<'c>, Inv<'_>)` note: the lifetime `'c` as defined here... --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | @@ -41,8 +41,8 @@ error[E0308]: method not compatible with trait LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` - found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` + = note: expected signature `fn(&'a _, Inv<'c>, Inv<'c>, Inv<'_>)` + found signature `fn(&'a _, Inv<'_>, Inv<'c>, Inv<'_>)` note: the lifetime `'c` as defined here... --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | diff --git a/tests/ui/box/issue-82446.stderr b/tests/ui/box/issue-82446.stderr index 568d23c2cb7..66daaceffb1 100644 --- a/tests/ui/box/issue-82446.stderr +++ b/tests/ui/box/issue-82446.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | val | ^^^ expected `Box<dyn MyTrait>`, found `&Box<dyn MyTrait>` | - = note: expected struct `Box<(dyn MyTrait + 'static)>` - found reference `&Box<(dyn MyTrait + 'static)>` + = note: expected struct `Box<_>` + found reference `&Box<_>` error: aborting due to 1 previous error diff --git a/tests/ui/check-cfg/compact-values.rs b/tests/ui/check-cfg/compact-values.rs index 13c072fe920..80cf75d2770 100644 --- a/tests/ui/check-cfg/compact-values.rs +++ b/tests/ui/check-cfg/compact-values.rs @@ -8,7 +8,7 @@ #[cfg(target(os = "linux", arch = "arm"))] pub fn expected() {} -#[cfg(target(os = "linux", arch = "X"))] +#[cfg(target(os = "linux", pointer_width = "X"))] //~^ WARNING unexpected `cfg` condition value pub fn unexpected() {} diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr index bb2f4915b5e..819b789c3e5 100644 --- a/tests/ui/check-cfg/compact-values.stderr +++ b/tests/ui/check-cfg/compact-values.stderr @@ -1,10 +1,10 @@ warning: unexpected `cfg` condition value: `X` --> $DIR/compact-values.rs:11:28 | -LL | #[cfg(target(os = "linux", arch = "X"))] - | ^^^^^^^^^^ +LL | #[cfg(target(os = "linux", pointer_width = "X"))] + | ^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` + = note: expected values for `target_pointer_width` are: `16`, `32`, `64` = note: `#[warn(unexpected_cfgs)]` on by default warning: 1 warning emitted diff --git a/tests/ui/check-cfg/values-target-json.rs b/tests/ui/check-cfg/values-target-json.rs index e4c1b54cccc..47ac79e0dbf 100644 --- a/tests/ui/check-cfg/values-target-json.rs +++ b/tests/ui/check-cfg/values-target-json.rs @@ -10,10 +10,6 @@ #[lang = "sized"] trait Sized {} -#[cfg(target_os = "linuz")] -//~^ WARNING unexpected `cfg` condition value -fn target_os_linux_misspell() {} - #[cfg(target_os = "linux")] fn target_os_linux() {} diff --git a/tests/ui/check-cfg/values-target-json.stderr b/tests/ui/check-cfg/values-target-json.stderr deleted file mode 100644 index e71149f337f..00000000000 --- a/tests/ui/check-cfg/values-target-json.stderr +++ /dev/null @@ -1,13 +0,0 @@ -warning: unexpected `cfg` condition value: `linuz` - --> $DIR/values-target-json.rs:13:7 - | -LL | #[cfg(target_os = "linuz")] - | ^^^^^^^^^^^^------- - | | - | help: there is a expected value with a similar name: `"linux"` - | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `ericos`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` - = note: `#[warn(unexpected_cfgs)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs index 8b56c8729d8..39a470c202f 100644 --- a/tests/ui/check-cfg/well-known-values.rs +++ b/tests/ui/check-cfg/well-known-values.rs @@ -1,41 +1,104 @@ -// This test check that we lint on non well known values and that we don't lint on well known -// values +// This test check that we recognize all the well known config names +// and that we correctly lint on unexpected values. +// +// This test also serve as an "anti-regression" for the well known +// values since the suggestion shows them. // // check-pass // compile-flags: --check-cfg=cfg() -Z unstable-options -#[cfg(target_os = "linuz")] +#![feature(cfg_overflow_checks)] +#![feature(cfg_relocation_model)] +#![feature(cfg_sanitize)] +#![feature(cfg_target_abi)] +#![feature(cfg_target_has_atomic)] +#![feature(cfg_target_has_atomic_equal_alignment)] +#![feature(cfg_target_thread_local)] + +// This part makes sure that none of the well known names are +// unexpected. +// +// BUT to make sure that no expected values changes without +// being noticed we pass them a obviously wrong value so the +// diagnostic prints the list of expected values. +#[cfg(any( + // tidy-alphabetical-start + debug_assertions = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + doc = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + doctest = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + miri = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + overflow_checks = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + panic = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + proc_macro = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + relocation_model = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + sanitize = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_abi = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_arch = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_endian = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_env = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_family = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_feature = "_UNEXPECTED_VALUE", // currently *any* values are "expected" + target_has_atomic = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_has_atomic_load_store = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_os = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_pointer_width = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_thread_local = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + target_vendor = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + test = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + unix = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + windows = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value + // tidy-alphabetical-end +))] +fn unexpected_values() {} + +#[cfg(target_os = "linuz")] // testing that we suggest `linux` //~^ WARNING unexpected `cfg` condition value fn target_os_linux_misspell() {} +// The #[cfg]s below serve as a safeguard to make sure we +// don't lint when using an expected well-known name and +// value, only a small subset of all possible expected +// configs are tested, since we already test the names +// above and don't need to test all values, just different +// combinations (without value, with value, both...). + #[cfg(target_os = "linux")] fn target_os_linux() {} -#[cfg(target_has_atomic = "0")] -//~^ WARNING unexpected `cfg` condition value -fn target_has_atomic_invalid() {} - #[cfg(target_has_atomic = "8")] -fn target_has_atomic() {} +fn target_has_atomic_8() {} -#[cfg(unix = "aa")] -//~^ WARNING unexpected `cfg` condition value -fn unix_with_value() {} +#[cfg(target_has_atomic)] +fn target_has_atomic() {} #[cfg(unix)] fn unix() {} -#[cfg(miri = "miri")] -//~^ WARNING unexpected `cfg` condition value -fn miri_with_value() {} - -#[cfg(miri)] -fn miri() {} - -#[cfg(doc = "linux")] -//~^ WARNING unexpected `cfg` condition value -fn doc_with_value() {} - #[cfg(doc)] fn doc() {} diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 6877d8f5bb7..a6b9c75a142 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -1,53 +1,225 @@ -warning: unexpected `cfg` condition value: `linuz` - --> $DIR/well-known-values.rs:7:7 +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:26:5 | -LL | #[cfg(target_os = "linuz")] - | ^^^^^^^^^^^^------- - | | - | help: there is a expected value with a similar name: `"linux"` +LL | debug_assertions = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^---------------------- + | | + | help: remove the value | - = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` + = note: no expected value for `debug_assertions` = note: `#[warn(unexpected_cfgs)]` on by default -warning: unexpected `cfg` condition value: `0` - --> $DIR/well-known-values.rs:14:7 +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:28:5 + | +LL | doc = "_UNEXPECTED_VALUE", + | ^^^---------------------- + | | + | help: remove the value + | + = note: no expected value for `doc` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:30:5 + | +LL | doctest = "_UNEXPECTED_VALUE", + | ^^^^^^^---------------------- + | | + | help: remove the value + | + = note: no expected value for `doctest` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:32:5 + | +LL | miri = "_UNEXPECTED_VALUE", + | ^^^^---------------------- + | | + | help: remove the value + | + = note: no expected value for `miri` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:34:5 + | +LL | overflow_checks = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^---------------------- + | | + | help: remove the value + | + = note: no expected value for `overflow_checks` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:36:5 | -LL | #[cfg(target_has_atomic = "0")] - | ^^^^^^^^^^^^^^^^^^^^--- - | | - | help: there is a expected value with a similar name: `"8"` +LL | panic = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `panic` are: `abort`, `unwind` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:38:5 + | +LL | proc_macro = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^---------------------- + | | + | help: remove the value + | + = note: no expected value for `proc_macro` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:40:5 + | +LL | relocation_model = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `relocation_model` are: `dynamic-no-pic`, `pic`, `pie`, `ropi`, `ropi-rwpi`, `rwpi`, `static` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:42:5 + | +LL | sanitize = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `sanitize` are: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:44:5 + | +LL | target_abi = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elf`, `fortanix`, `ilp32`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, `x32` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:46:5 + | +LL | target_arch = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:48:5 + | +LL | target_endian = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_endian` are: `big`, `little` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:50:5 + | +LL | target_env = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_env` are: ``, `eabihf`, `gnu`, `gnueabihf`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `psx`, `relibc`, `sgx`, `uclibc` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:52:5 + | +LL | target_family = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_family` are: `unix`, `wasm`, `windows` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:55:5 + | +LL | target_has_atomic = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr` -warning: unexpected `cfg` condition value: `aa` - --> $DIR/well-known-values.rs:21:7 +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:57:5 | -LL | #[cfg(unix = "aa")] - | ^^^^------- - | | - | help: remove the value +LL | target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_has_atomic_equal_alignment` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:59:5 + | +LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_has_atomic_load_store` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:61:5 + | +LL | target_os = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:63:5 + | +LL | target_pointer_width = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_pointer_width` are: `16`, `32`, `64` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:65:5 + | +LL | target_thread_local = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^---------------------- + | | + | help: remove the value + | + = note: no expected value for `target_thread_local` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:67:5 + | +LL | target_vendor = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `nintendo`, `nvidia`, `pc`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, `wrs` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:69:5 + | +LL | test = "_UNEXPECTED_VALUE", + | ^^^^---------------------- + | | + | help: remove the value + | + = note: no expected value for `test` + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:71:5 + | +LL | unix = "_UNEXPECTED_VALUE", + | ^^^^---------------------- + | | + | help: remove the value | = note: no expected value for `unix` -warning: unexpected `cfg` condition value: `miri` - --> $DIR/well-known-values.rs:28:7 +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:73:5 | -LL | #[cfg(miri = "miri")] - | ^^^^--------- - | | - | help: remove the value +LL | windows = "_UNEXPECTED_VALUE", + | ^^^^^^^---------------------- + | | + | help: remove the value | - = note: no expected value for `miri` + = note: no expected value for `windows` -warning: unexpected `cfg` condition value: `linux` - --> $DIR/well-known-values.rs:35:7 +warning: unexpected `cfg` condition value: `linuz` + --> $DIR/well-known-values.rs:79:7 | -LL | #[cfg(doc = "linux")] - | ^^^---------- - | | - | help: remove the value +LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` + | ^^^^^^^^^^^^------- + | | + | help: there is a expected value with a similar name: `"linux"` | - = note: no expected value for `doc` + = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous` -warning: 5 warnings emitted +warning: 25 warnings emitted diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr index e6ddc606897..e010f0502f8 100644 --- a/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -25,8 +25,8 @@ error[E0308]: mismatched types LL | with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {}); | ^ one type is more general than the other | - = note: expected fn pointer `fn(&u32)` - found fn pointer `for<'a> fn(&'a u32)` + = note: expected fn pointer `fn(&_)` + found fn pointer `for<'a> fn(&'a _)` error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:39:50 @@ -34,8 +34,8 @@ error[E0308]: mismatched types LL | with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {}); | ^ one type is more general than the other | - = note: expected fn pointer `for<'a> fn(&'a u32)` - found fn pointer `fn(&u32)` + = note: expected fn pointer `for<'a> fn(&'a _)` + found fn pointer `fn(&_)` error[E0308]: mismatched types --> $DIR/expect-fn-supply-fn.rs:48:50 @@ -43,8 +43,8 @@ error[E0308]: mismatched types LL | with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| { | ^ one type is more general than the other | - = note: expected fn pointer `for<'a> fn(&'a u32)` - found fn pointer `fn(&u32)` + = note: expected fn pointer `for<'a> fn(&'a _)` + found fn pointer `fn(&_)` error: aborting due to 5 previous errors diff --git a/tests/ui/closures/multiple-fn-bounds.stderr b/tests/ui/closures/multiple-fn-bounds.stderr index d510fc585f6..325652ef14c 100644 --- a/tests/ui/closures/multiple-fn-bounds.stderr +++ b/tests/ui/closures/multiple-fn-bounds.stderr @@ -6,8 +6,8 @@ LL | foo(move |x| v); | | | expected due to this | - = note: expected closure signature `fn(char) -> _` - found closure signature `for<'a> fn(&'a char) -> _` + = note: expected closure signature `fn(_) -> _` + found closure signature `for<'a> fn(&'a _) -> _` note: closure inferred to have a different signature due to this bound --> $DIR/multiple-fn-bounds.rs:1:11 | diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.rs b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs index bf8202ac152..d51696f9ebd 100644 --- a/tests/ui/const-generics/assoc_const_eq_diagnostic.rs +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs @@ -9,9 +9,9 @@ pub trait Parse { } pub trait CoolStuff: Parse<MODE = Mode::Cool> {} -//~^ ERROR expected associated constant bound -//~| ERROR expected associated constant bound -//~| ERROR expected type +//~^ ERROR expected type, found variant +//~| ERROR expected constant, found type +//~| ERROR expected constant, found type fn no_help() -> Mode::Cool {} //~^ ERROR expected type, found variant diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr index 6d5cd45479e..3d724bb1642 100644 --- a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr +++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr @@ -16,30 +16,42 @@ LL | fn no_help() -> Mode::Cool {} | not a type | help: try using the variant's enum: `Mode` -error: expected associated constant bound, found type - --> $DIR/assoc_const_eq_diagnostic.rs:11:28 +error: expected constant, found type + --> $DIR/assoc_const_eq_diagnostic.rs:11:35 | LL | pub trait CoolStuff: Parse<MODE = Mode::Cool> {} - | ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }` + | ---- ^^^^^^^^^^ unexpected type + | | + | expected a constant because of this associated constant | -note: associated constant defined here +note: the associated constant is defined here --> $DIR/assoc_const_eq_diagnostic.rs:8:5 | LL | const MODE: Mode; | ^^^^^^^^^^^^^^^^ +help: consider adding braces here + | +LL | pub trait CoolStuff: Parse<MODE = { Mode::Cool }> {} + | + + -error: expected associated constant bound, found type - --> $DIR/assoc_const_eq_diagnostic.rs:11:28 +error: expected constant, found type + --> $DIR/assoc_const_eq_diagnostic.rs:11:35 | LL | pub trait CoolStuff: Parse<MODE = Mode::Cool> {} - | ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }` + | ---- ^^^^^^^^^^ unexpected type + | | + | expected a constant because of this associated constant | -note: associated constant defined here +note: the associated constant is defined here --> $DIR/assoc_const_eq_diagnostic.rs:8:5 | LL | const MODE: Mode; | ^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider adding braces here + | +LL | pub trait CoolStuff: Parse<MODE = { Mode::Cool }> {} + | + + error: aborting due to 4 previous errors diff --git a/tests/ui/consts/precise-drop-with-promoted.rs b/tests/ui/consts/precise-drop-with-promoted.rs index 0c0514dd9d5..7cbe3c4e415 100644 --- a/tests/ui/consts/precise-drop-with-promoted.rs +++ b/tests/ui/consts/precise-drop-with-promoted.rs @@ -1,11 +1,6 @@ // Regression test for issue #89938. +// check-pass // compile-flags: --crate-type=lib -// known-bug: #103507 -// failure-status: 101 -// normalize-stderr-test "note: .*\n\n" -> "" -// normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> "" -// normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " -// rustc-env:RUST_BACKTRACE=0 #![feature(const_precise_live_drops)] diff --git a/tests/ui/consts/precise-drop-with-promoted.stderr b/tests/ui/consts/precise-drop-with-promoted.stderr deleted file mode 100644 index a56672048eb..00000000000 --- a/tests/ui/consts/precise-drop-with-promoted.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: the compiler unexpectedly panicked. this is a bug. - -query stack during panic: -#0 [mir_drops_elaborated_and_const_checked] elaborating drops for `f` -#1 [analysis] running analysis passes on this crate -end of query stack diff --git a/tests/ui/coroutine/async_gen_fn.e2024.stderr b/tests/ui/coroutine/async_gen_fn.e2024.stderr new file mode 100644 index 00000000000..d24cdbbc30d --- /dev/null +++ b/tests/ui/coroutine/async_gen_fn.e2024.stderr @@ -0,0 +1,12 @@ +error[E0658]: gen blocks are experimental + --> $DIR/async_gen_fn.rs:4:1 + | +LL | async gen fn foo() {} + | ^^^^^^^^^ + | + = note: see issue #117078 <https://github.com/rust-lang/rust/issues/117078> for more information + = help: add `#![feature(gen_blocks)]` to the crate attributes to enable + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/coroutine/async_gen_fn.none.stderr b/tests/ui/coroutine/async_gen_fn.none.stderr new file mode 100644 index 00000000000..7950251a75d --- /dev/null +++ b/tests/ui/coroutine/async_gen_fn.none.stderr @@ -0,0 +1,18 @@ +error[E0670]: `async fn` is not permitted in Rust 2015 + --> $DIR/async_gen_fn.rs:4:1 + | +LL | async gen fn foo() {} + | ^^^^^ to use `async fn`, switch to Rust 2018 or later + | + = help: pass `--edition 2021` to `rustc` + = note: for more on editions, read https://doc.rust-lang.org/edition-guide + +error: expected one of `extern`, `fn`, or `unsafe`, found `gen` + --> $DIR/async_gen_fn.rs:4:7 + | +LL | async gen fn foo() {} + | ^^^ expected one of `extern`, `fn`, or `unsafe` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0670`. diff --git a/tests/ui/coroutine/async_gen_fn.rs b/tests/ui/coroutine/async_gen_fn.rs index f8860e07f6c..20564106f99 100644 --- a/tests/ui/coroutine/async_gen_fn.rs +++ b/tests/ui/coroutine/async_gen_fn.rs @@ -1,11 +1,9 @@ -// edition: 2024 -// compile-flags: -Zunstable-options -#![feature(gen_blocks)] - -// async generators are not yet supported, so this test makes sure they make some kind of reasonable -// error. +// revisions: e2024 none +//[e2024] compile-flags: --edition 2024 -Zunstable-options async gen fn foo() {} -//~^ `async gen` functions are not supported +//[none]~^ ERROR: `async fn` is not permitted in Rust 2015 +//[none]~| ERROR: expected one of `extern`, `fn`, or `unsafe`, found `gen` +//[e2024]~^^^ ERROR: gen blocks are experimental fn main() {} diff --git a/tests/ui/coroutine/async_gen_fn.stderr b/tests/ui/coroutine/async_gen_fn.stderr deleted file mode 100644 index 6857ebe6c79..00000000000 --- a/tests/ui/coroutine/async_gen_fn.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: `async gen` functions are not supported - --> $DIR/async_gen_fn.rs:8:1 - | -LL | async gen fn foo() {} - | ^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/coroutine/async_gen_fn_iter.rs b/tests/ui/coroutine/async_gen_fn_iter.rs new file mode 100644 index 00000000000..4fa29e1095a --- /dev/null +++ b/tests/ui/coroutine/async_gen_fn_iter.rs @@ -0,0 +1,100 @@ +// edition: 2024 +// compile-flags: -Zunstable-options +// run-pass + +#![feature(gen_blocks, async_iterator)] + +// make sure that a ridiculously simple async gen fn works as an iterator. + +async fn pause() { + // this doesn't actually do anything, lol +} + +async fn one() -> i32 { + 1 +} + +async fn two() -> i32 { + 2 +} + +async gen fn foo() -> i32 { + yield one().await; + pause().await; + yield two().await; + pause().await; + yield 3; + pause().await; +} + +async fn async_main() { + let mut iter = std::pin::pin!(foo()); + assert_eq!(iter.next().await, Some(1)); + assert_eq!(iter.as_mut().next().await, Some(2)); + assert_eq!(iter.as_mut().next().await, Some(3)); + assert_eq!(iter.as_mut().next().await, None); + + // Test that the iterator is fused and does not panic + assert_eq!(iter.as_mut().next().await, None); + assert_eq!(iter.as_mut().next().await, None); +} + +// ------------------------------------------------------------------------- // +// Implementation Details Below... + +use std::pin::Pin; +use std::task::*; +use std::async_iter::AsyncIterator; +use std::future::Future; + +trait AsyncIterExt { + fn next(&mut self) -> Next<'_, Self>; +} + +impl<T> AsyncIterExt for T { + fn next(&mut self) -> Next<'_, Self> { + Next { s: self } + } +} + +struct Next<'s, S: ?Sized> { + s: &'s mut S, +} + +impl<'s, S: AsyncIterator> Future for Next<'s, S> where S: Unpin { + type Output = Option<S::Item>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<S::Item>> { + Pin::new(&mut *self.s).poll_next(cx) + } +} + +pub fn noop_waker() -> Waker { + let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE); + + // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld + unsafe { Waker::from_raw(raw) } +} + +const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop); + +unsafe fn noop_clone(_p: *const ()) -> RawWaker { + RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE) +} + +unsafe fn noop(_p: *const ()) {} + +fn main() { + let mut fut = async_main(); + + // Poll loop, just to test the future... + let waker = noop_waker(); + let ctx = &mut Context::from_waker(&waker); + + loop { + match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } { + Poll::Pending => {} + Poll::Ready(()) => break, + } + } +} diff --git a/tests/ui/error-codes/E0221.stderr b/tests/ui/error-codes/E0221.stderr index e600acf7834..07e7485b67e 100644 --- a/tests/ui/error-codes/E0221.stderr +++ b/tests/ui/error-codes/E0221.stderr @@ -28,7 +28,7 @@ LL | fn test() { LL | let _: Self::Err; | ^^^^^^^^^ ambiguous associated type `Err` | - = note: associated type `Self` could derive from `FromStr` + = note: associated type `Err` could derive from `FromStr` help: use fully-qualified syntax to disambiguate | LL | let _: <Self as My>::Err; diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.rs b/tests/ui/feature-gates/feature-gate-never_patterns.rs index 69e9f62abf0..ca5ce3b9489 100644 --- a/tests/ui/feature-gates/feature-gate-never_patterns.rs +++ b/tests/ui/feature-gates/feature-gate-never_patterns.rs @@ -12,7 +12,7 @@ fn main() { unsafe { let ptr: *const Void = NonNull::dangling().as_ptr(); match *ptr { - ! => {} //~ ERROR `!` patterns are experimental + ! //~ ERROR `!` patterns are experimental } } diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.stderr b/tests/ui/feature-gates/feature-gate-never_patterns.stderr index b7290eeb36d..2354a3b0476 100644 --- a/tests/ui/feature-gates/feature-gate-never_patterns.stderr +++ b/tests/ui/feature-gates/feature-gate-never_patterns.stderr @@ -18,7 +18,7 @@ LL | let (Ok(_x) | Err(&!)) = res.as_ref(); error[E0658]: `!` patterns are experimental --> $DIR/feature-gate-never_patterns.rs:15:13 | -LL | ! => {} +LL | ! | ^ | = note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr index 1bdb2574ead..a15b01618f5 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr @@ -15,13 +15,18 @@ LL | fn foo<T: Trait<m(): Send>>() {} | | | help: remove these parentheses -error[E0220]: associated type `m` not found for `Trait` +error: expected type, found function --> $DIR/feature-gate-return_type_notation.rs:14:17 | LL | fn foo<T: Trait<m(): Send>>() {} - | ^ associated type `m` not found + | ^ unexpected function + | +note: the associated function is defined here + --> $DIR/feature-gate-return_type_notation.rs:10:5 + | +LL | async fn m(); + | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors -Some errors have detailed explanations: E0220, E0658. -For more information about an error, try `rustc --explain E0220`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs index 86e2c48e188..60ac9f8d4f1 100644 --- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs +++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs @@ -14,7 +14,7 @@ trait Trait { fn foo<T: Trait<m(): Send>>() {} //[cfg]~^ ERROR return type notation is experimental //[cfg]~| ERROR parenthesized generic arguments cannot be used in associated type constraints -//[cfg]~| ERROR associated type `m` not found for `Trait` +//[cfg]~| ERROR expected type, found function //[no]~^^^^ WARN return type notation is experimental //[no]~| WARN unstable syntax can change at any point in the future, causing a hard error! diff --git a/tests/ui/fn/fn-pointer-mismatch.rs b/tests/ui/fn/fn-pointer-mismatch.rs index 0597478cb42..1c50d8b0f8b 100644 --- a/tests/ui/fn/fn-pointer-mismatch.rs +++ b/tests/ui/fn/fn-pointer-mismatch.rs @@ -35,20 +35,20 @@ fn main() { // suggest removing reference let c: fn(u32) -> u32 = &foo; //~^ ERROR mismatched types - //~| expected fn pointer `fn(u32) -> u32` - //~| found reference `&fn(u32) -> u32 {foo}` + //~| expected fn pointer `fn(_) -> _` + //~| found reference `&fn(_) -> _ {foo}` // suggest using reference let d: &fn(u32) -> u32 = foo; //~^ ERROR mismatched types - //~| expected reference `&fn(u32) -> u32` - //~| found fn item `fn(u32) -> u32 {foo}` + //~| expected reference `&fn(_) -> _` + //~| found fn item `fn(_) -> _ {foo}` // suggest casting with reference let e: &fn(u32) -> u32 = &foo; //~^ ERROR mismatched types - //~| expected reference `&fn(u32) -> u32` - //~| found reference `&fn(u32) -> u32 {foo}` + //~| expected reference `&fn(_) -> _` + //~| found reference `&fn(_) -> _ {foo}` // OK let mut z: fn(u32) -> u32 = foo as fn(u32) -> u32; diff --git a/tests/ui/fn/fn-pointer-mismatch.stderr b/tests/ui/fn/fn-pointer-mismatch.stderr index 87ece845b83..9cda11639d0 100644 --- a/tests/ui/fn/fn-pointer-mismatch.stderr +++ b/tests/ui/fn/fn-pointer-mismatch.stderr @@ -6,8 +6,8 @@ LL | let g = if n % 2 == 0 { &foo } else { &bar }; | | | expected because of this | - = note: expected reference `&fn(u32) -> u32 {foo}` - found reference `&fn(u32) -> u32 {bar}` + = note: expected reference `&fn(_) -> _ {foo}` + found reference `&fn(_) -> _ {bar}` = note: different fn items have unique types, even if their signatures are the same = help: consider casting both fn items to fn pointers using `as fn(u32) -> u32` @@ -47,8 +47,8 @@ LL | let c: fn(u32) -> u32 = &foo; | | | expected due to this | - = note: expected fn pointer `fn(u32) -> u32` - found reference `&fn(u32) -> u32 {foo}` + = note: expected fn pointer `fn(_) -> _` + found reference `&fn(_) -> _ {foo}` help: consider removing the reference | LL | let c: fn(u32) -> u32 = foo; @@ -62,8 +62,8 @@ LL | let d: &fn(u32) -> u32 = foo; | | | expected due to this | - = note: expected reference `&fn(u32) -> u32` - found fn item `fn(u32) -> u32 {foo}` + = note: expected reference `&fn(_) -> _` + found fn item `fn(_) -> _ {foo}` help: consider using a reference | LL | let d: &fn(u32) -> u32 = &foo; @@ -77,8 +77,8 @@ LL | let e: &fn(u32) -> u32 = &foo; | | | expected due to this | - = note: expected reference `&fn(u32) -> u32` - found reference `&fn(u32) -> u32 {foo}` + = note: expected reference `&fn(_) -> _` + found reference `&fn(_) -> _ {foo}` = note: fn items are distinct from fn pointers help: consider casting to a fn pointer | diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr index 64cd55e684c..49d36acadd6 100644 --- a/tests/ui/generic-associated-types/issue-88360.stderr +++ b/tests/ui/generic-associated-types/issue-88360.stderr @@ -9,8 +9,8 @@ LL | fn copy(&self) -> Self::Gat<'_> where T: Copy { LL | *self.test() | ^^^^^^^^^^^^ expected `&T`, found type parameter `T` | - = note: expected reference `&T` - found type parameter `T` + = note: expected reference `&_` + found type parameter `_` help: consider removing deref here | LL - *self.test() diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs index 55353999b67..9ffc2190d20 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs @@ -17,7 +17,7 @@ fn main() { } match x as i32 { 0..5+1 => errors_only.push(x), - //~^ error: expected one of `=>`, `if`, or `|`, found `+` + //~^ error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `+` 1 | -3..0 => first_or.push(x), y @ (0..5 | 6) => or_two.push(y), y @ 0..const { 5 + 1 } => assert_eq!(y, 5), diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr index 19ebcaf0f36..05235c9b922 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr @@ -1,8 +1,8 @@ -error: expected one of `=>`, `if`, or `|`, found `+` +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `+` --> $DIR/range_pat_interactions1.rs:19:17 | LL | 0..5+1 => errors_only.push(x), - | ^ expected one of `=>`, `if`, or `|` + | ^ expected one of `,`, `=>`, `if`, `|`, or `}` error[E0408]: variable `n` is not bound in all patterns --> $DIR/range_pat_interactions1.rs:10:25 diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs index 4615ebd688a..b212bfbe093 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs @@ -9,7 +9,7 @@ fn main() { match x as i32 { 0..=(5+1) => errors_only.push(x), //~^ error: inclusive range with no end - //~| error: expected one of `=>`, `if`, or `|`, found `(` + //~| error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `(` 1 | -3..0 => first_or.push(x), y @ (0..5 | 6) => or_two.push(y), y @ 0..const { 5 + 1 } => assert_eq!(y, 5), diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr index 13a5542a474..0129f927e34 100644 --- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr +++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr @@ -6,11 +6,11 @@ LL | 0..=(5+1) => errors_only.push(x), | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `=>`, `if`, or `|`, found `(` +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `(` --> $DIR/range_pat_interactions2.rs:10:17 | LL | 0..=(5+1) => errors_only.push(x), - | ^ expected one of `=>`, `if`, or `|` + | ^ expected one of `,`, `=>`, `if`, `|`, or `}` error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index 7cb7edfafeb..d7f0860a026 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -8,8 +8,8 @@ LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u3 LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } | |_____________________________________________- in this macro invocation | - = note: expected enum `Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32>` - found enum `Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32>` + = note: expected enum `Option<for<'a, 'b> fn(&'a _, &'b _) -> &'a _>` + found enum `Option<for<'a> fn(&'a _, &'a _) -> &'a _>` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr index c6adbd91e78..9b5ca3b2056 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -8,8 +8,8 @@ LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32), LL | | fn(&'x u32)) } | |______________- in this macro invocation | - = note: expected enum `Option<for<'a> fn(&'a u32)>` - found enum `Option<fn(&u32)>` + = note: expected enum `Option<for<'a> fn(&'a _)>` + found enum `Option<fn(&_)>` = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr index f269babcf71..2d6b8063f69 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr @@ -6,8 +6,8 @@ LL | let _: for<'b> fn(&'b u32) = foo(); | | | expected due to this | - = note: expected fn pointer `for<'b> fn(&'b u32)` - found fn pointer `fn(&u32)` + = note: expected fn pointer `for<'b> fn(&'b _)` + found fn pointer `fn(&_)` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.stderr index 25c0adeddbd..b8a8e2401b2 100644 --- a/tests/ui/impl-trait/in-trait/specialization-broken.stderr +++ b/tests/ui/impl-trait/in-trait/specialization-broken.stderr @@ -15,8 +15,8 @@ note: type in trait | LL | fn bar(&self) -> impl Sized; | ^^^^^^^^^^ - = note: expected signature `fn(&U) -> impl Sized` - found signature `fn(&U) -> U` + = note: expected signature `fn(&_) -> impl Sized` + found signature `fn(&_) -> U` error: method with return-position `impl Trait` in trait cannot be specialized --> $DIR/specialization-broken.rs:15:5 diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index fe765271bd2..07ac1a37e75 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -18,8 +18,8 @@ LL | fn eq(&self, _other: &(Foo, i32)) -> bool { | expected `a::Bar`, found opaque type | help: change the parameter type to match the trait: `&(a::Bar, i32)` | - = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _` - found signature `fn(&a::Bar, &(a::Foo, i32)) -> _` + = note: expected signature `fn(&a::Bar, &(a::Bar, _)) -> _` + found signature `fn(&a::Bar, &(a::Foo, _)) -> _` error: unconstrained opaque type --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16 @@ -41,8 +41,8 @@ LL | fn eq(&self, _other: &(Bar, i32)) -> bool { | expected opaque type, found `b::Bar` | help: change the parameter type to match the trait: `&(b::Foo, i32)` | - = note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _` - found signature `fn(&b::Bar, &(b::Bar, i32)) -> _` + = note: expected signature `fn(&b::Bar, &(b::Foo, _)) -> _` + found signature `fn(&b::Bar, &(b::Bar, _)) -> _` note: this item must have the opaque type in its signature in order to be able to register hidden types --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:12 | diff --git a/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs b/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs new file mode 100644 index 00000000000..b373d39f4d9 --- /dev/null +++ b/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs @@ -0,0 +1,18 @@ +// Related to Bevy regression #118553 + +pub trait WorldQuery {} +impl WorldQuery for &u8 {} + +pub struct Query<Q: WorldQuery>(Q); + +pub trait SystemParam { + type State; +} +impl<Q: WorldQuery + 'static> SystemParam for Query<Q> { + type State = (); + // `Q: 'static` is required because we need the TypeId of Q ... +} + +pub struct ParamSet<T: SystemParam>(T) +where + T::State: Sized; diff --git a/tests/ui/implied-bounds/bevy_world_query.rs b/tests/ui/implied-bounds/bevy_world_query.rs new file mode 100644 index 00000000000..f8e64632676 --- /dev/null +++ b/tests/ui/implied-bounds/bevy_world_query.rs @@ -0,0 +1,11 @@ +// aux-crate:bevy_ecs=bevy_ecs.rs +// check-pass +// Related to Bevy regression #118553 + +extern crate bevy_ecs; + +use bevy_ecs::*; + +fn handler<'a>(_: ParamSet<Query<&'a u8>>) {} + +fn main() {} diff --git a/tests/ui/implied-bounds/from-trait-impl.rs b/tests/ui/implied-bounds/from-trait-impl.rs new file mode 100644 index 00000000000..d13fddd9b8d --- /dev/null +++ b/tests/ui/implied-bounds/from-trait-impl.rs @@ -0,0 +1,24 @@ +// check-pass +// known-bug: #109628 + +trait Trait { + type Assoc; +} + +impl<X: 'static> Trait for (X,) { + type Assoc = (); +} + +struct Foo<T: Trait>(T) +where + T::Assoc: Clone; // any predicate using `T::Assoc` works here + +fn func1(foo: Foo<(&str,)>) { + let _: &'static str = foo.0.0; +} + +trait TestTrait {} + +impl<X> TestTrait for [Foo<(X,)>; 1] {} + +fn main() {} diff --git a/tests/ui/implied-bounds/gluon_salsa.rs b/tests/ui/implied-bounds/gluon_salsa.rs new file mode 100644 index 00000000000..98951af8ac2 --- /dev/null +++ b/tests/ui/implied-bounds/gluon_salsa.rs @@ -0,0 +1,31 @@ +// check-pass +// Related to Bevy regression #118553 + +pub trait QueryBase { + type Db; +} + +pub trait AsyncQueryFunction<'f>: // 'f is important + QueryBase<Db = <Self as AsyncQueryFunction<'f>>::SendDb> // bound is important +{ + type SendDb; +} + +pub struct QueryTable<'me, Q, DB> { + _q: Option<Q>, + _db: Option<DB>, + _marker: Option<&'me ()>, +} + +impl<'me, Q> QueryTable<'me, Q, <Q as QueryBase>::Db> +// projection is important +// ^^^ removing 'me (and in QueryTable) gives a different error +where + Q: for<'f> AsyncQueryFunction<'f>, +{ + pub fn get_async<'a>(&'a mut self) { + panic!(); + } +} + +fn main() {} diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr index 49f2fcd0a67..df069d875ce 100644 --- a/tests/ui/implied-bounds/issue-100690.stderr +++ b/tests/ui/implied-bounds/issue-100690.stderr @@ -6,8 +6,8 @@ LL | real_dispatch(f) | | | required by a bound introduced by this call | - = note: expected a closure with arguments `(&mut UIView<'a, T>,)` - found a closure with arguments `(&mut UIView<'_, T>,)` + = note: expected a closure with arguments `(&mut UIView<'a, _>,)` + found a closure with arguments `(&mut UIView<'_, _>,)` note: required by a bound in `real_dispatch` --> $DIR/issue-100690.rs:9:8 | diff --git a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr index abffee57a0f..e020230d86a 100644 --- a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr +++ b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr @@ -1,11 +1,11 @@ error[E0759]: `fn` parameter has lifetime `'x` but it needs to satisfy a `'static` lifetime requirement - --> $DIR/normalization-nested.rs:35:20 + --> $DIR/normalization-nested.rs:35:28 | -LL | pub fn test<'x>(_: Map<Vec<&'x ()>>, s: &'x str) -> &'static str { - | ^^^^^^^^^^^^^^^^ - | | - | this data with lifetime `'x`... - | ...is used and required to live as long as `'static` here +LL | pub fn test_wfcheck<'x>(_: Map<Vec<&'x ()>>) {} + | ^^^^^^^^^^^^^^^^ + | | + | this data with lifetime `'x`... + | ...is used and required to live as long as `'static` here | note: `'static` lifetime requirement introduced by this bound --> $DIR/normalization-nested.rs:33:14 @@ -13,6 +13,21 @@ note: `'static` lifetime requirement introduced by this bound LL | I::Item: 'static; | ^^^^^^^ -error: aborting due to 1 previous error +error[E0759]: `fn` parameter has lifetime `'x` but it needs to satisfy a `'static` lifetime requirement + --> $DIR/normalization-nested.rs:37:29 + | +LL | pub fn test_borrowck<'x>(_: Map<Vec<&'x ()>>, s: &'x str) -> &'static str { + | ^^^^^^^^^^^^^^^^ + | | + | this data with lifetime `'x`... + | ...is used and required to live as long as `'static` here + | +note: `'static` lifetime requirement introduced by this bound + --> $DIR/normalization-nested.rs:33:14 + | +LL | I::Item: 'static; + | ^^^^^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0759`. diff --git a/tests/ui/implied-bounds/normalization-nested.rs b/tests/ui/implied-bounds/normalization-nested.rs index 5f1cbb3f697..87903783a67 100644 --- a/tests/ui/implied-bounds/normalization-nested.rs +++ b/tests/ui/implied-bounds/normalization-nested.rs @@ -32,7 +32,9 @@ where I: Iter, I::Item: 'static; -pub fn test<'x>(_: Map<Vec<&'x ()>>, s: &'x str) -> &'static str { +pub fn test_wfcheck<'x>(_: Map<Vec<&'x ()>>) {} + +pub fn test_borrowck<'x>(_: Map<Vec<&'x ()>>, s: &'x str) -> &'static str { s } diff --git a/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr b/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr new file mode 100644 index 00000000000..96c76ca9ac3 --- /dev/null +++ b/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr @@ -0,0 +1,28 @@ +error: lifetime may not live long enough + --> $DIR/normalization-preserve-equality.rs:24:1 + | +LL | fn test_borrowck<'a, 'b>(_: (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>)) { + | ^^^^^^^^^^^^^^^^^--^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | lifetime `'b` defined here + | | lifetime `'a` defined here + | requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` + +error: lifetime may not live long enough + --> $DIR/normalization-preserve-equality.rs:24:1 + | +LL | fn test_borrowck<'a, 'b>(_: (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>)) { + | ^^^^^^^^^^^^^^^^^--^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | | + | | | lifetime `'b` defined here + | | lifetime `'a` defined here + | requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +help: `'a` and `'b` must be the same: replace one with the other + +error: aborting due to 2 previous errors + diff --git a/tests/ui/implied-bounds/normalization-preserve-equality.rs b/tests/ui/implied-bounds/normalization-preserve-equality.rs new file mode 100644 index 00000000000..557c171e515 --- /dev/null +++ b/tests/ui/implied-bounds/normalization-preserve-equality.rs @@ -0,0 +1,28 @@ +// Both revisions should pass. `borrowck` revision is a bug! +// +// revisions: wfcheck borrowck +// [wfcheck] check-pass +// [borrowck] check-fail +// [borrowck] known-bug: #106569 + +struct Equal<'a, 'b>(&'a &'b (), &'b &'a ()); // implies 'a == 'b + +trait Trait { + type Ty; +} + +impl<'x> Trait for Equal<'x, 'x> { + type Ty = (); +} + +trait WfCheckTrait {} + +#[cfg(wfcheck)] +impl<'a, 'b> WfCheckTrait for (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>) {} + +#[cfg(borrowck)] +fn test_borrowck<'a, 'b>(_: (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>)) { + let _ = None::<Equal<'a, 'b>>; +} + +fn main() {} diff --git a/tests/ui/implied-bounds/sod_service_chain.rs b/tests/ui/implied-bounds/sod_service_chain.rs new file mode 100644 index 00000000000..f45ced71f75 --- /dev/null +++ b/tests/ui/implied-bounds/sod_service_chain.rs @@ -0,0 +1,37 @@ +// check-pass +// Related to crater regressions on #118553 + +pub trait Debug {} + +pub trait Service { + type Input; + type Output; + type Error; +} + +pub struct ServiceChain<P, S> { + prev: P, + service: S, +} +impl<P: Service, S: Service<Input = P::Output>> Service for ServiceChain<P, S> +where + P::Error: 'static, + S::Error: 'static, +{ + type Input = P::Input; + type Output = S::Output; + type Error = (); +} + +pub struct ServiceChainBuilder<P: Service, S: Service<Input = P::Output>> { + chain: ServiceChain<P, S>, +} +impl<P: Service, S: Service<Input = P::Output>> ServiceChainBuilder<P, S> { + pub fn next<NS: Service<Input = S::Output>>( + self, + ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> { + panic!(); + } +} + +fn main() {} diff --git a/tests/ui/issues/issue-17905-2.stderr b/tests/ui/issues/issue-17905-2.stderr index 88b5fbec6cf..c66cb222489 100644 --- a/tests/ui/issues/issue-17905-2.stderr +++ b/tests/ui/issues/issue-17905-2.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched `self` parameter type LL | fn say(self: &Pair<&str, isize>) { | ^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected struct `Pair<&str, _>` - found struct `Pair<&str, _>` + = note: expected struct `Pair<&_, _>` + found struct `Pair<&_, _>` note: the anonymous lifetime defined here... --> $DIR/issue-17905-2.rs:8:24 | @@ -23,8 +23,8 @@ error[E0308]: mismatched `self` parameter type LL | fn say(self: &Pair<&str, isize>) { | ^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected struct `Pair<&str, _>` - found struct `Pair<&str, _>` + = note: expected struct `Pair<&_, _>` + found struct `Pair<&_, _>` note: the anonymous lifetime as defined here... --> $DIR/issue-17905-2.rs:5:5 | diff --git a/tests/ui/issues/issue-20225.stderr b/tests/ui/issues/issue-20225.stderr index b34aa8e1ff5..2d24a5bbd50 100644 --- a/tests/ui/issues/issue-20225.stderr +++ b/tests/ui/issues/issue-20225.stderr @@ -9,8 +9,8 @@ LL | extern "rust-call" fn call(&self, (_,): (T,)) {} | expected `&'a T`, found type parameter `T` | help: change the parameter type to match the trait: `(&'a T,)` | - = note: expected signature `extern "rust-call" fn(&Foo, (&'a T,))` - found signature `extern "rust-call" fn(&Foo, (T,))` + = note: expected signature `extern "rust-call" fn(&Foo, (&'a _,))` + found signature `extern "rust-call" fn(&Foo, (_,))` error[E0053]: method `call_mut` has an incompatible type for trait --> $DIR/issue-20225.rs:11:51 @@ -23,8 +23,8 @@ LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} | expected `&'a T`, found type parameter `T` | help: change the parameter type to match the trait: `(&'a T,)` | - = note: expected signature `extern "rust-call" fn(&mut Foo, (&'a T,))` - found signature `extern "rust-call" fn(&mut Foo, (T,))` + = note: expected signature `extern "rust-call" fn(&mut Foo, (&'a _,))` + found signature `extern "rust-call" fn(&mut Foo, (_,))` error[E0053]: method `call_once` has an incompatible type for trait --> $DIR/issue-20225.rs:18:47 @@ -38,8 +38,8 @@ LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} | expected `&'a T`, found type parameter `T` | help: change the parameter type to match the trait: `(&'a T,)` | - = note: expected signature `extern "rust-call" fn(Foo, (&'a T,))` - found signature `extern "rust-call" fn(Foo, (T,))` + = note: expected signature `extern "rust-call" fn(Foo, (&'a _,))` + found signature `extern "rust-call" fn(Foo, (_,))` error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-24322.stderr b/tests/ui/issues/issue-24322.stderr index b260d027388..d078069addc 100644 --- a/tests/ui/issues/issue-24322.stderr +++ b/tests/ui/issues/issue-24322.stderr @@ -6,8 +6,8 @@ LL | let x: &fn(&B) -> u32 = &B::func; | | | expected due to this | - = note: expected reference `&for<'a> fn(&'a B) -> u32` - found reference `&for<'a> fn(&'a B) -> u32 {B::func}` + = note: expected reference `&for<'a> fn(&'a B) -> _` + found reference `&for<'a> fn(&'a B) -> _ {B::func}` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-37884.stderr b/tests/ui/issues/issue-37884.stderr index 633abeb6f22..b7c0095d682 100644 --- a/tests/ui/issues/issue-37884.stderr +++ b/tests/ui/issues/issue-37884.stderr @@ -4,8 +4,8 @@ error[E0308]: method not compatible with trait LL | fn next(&'a mut self) -> Option<Self::Item> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected signature `fn(&mut RepeatMut<'a, T>) -> Option<_>` - found signature `fn(&'a mut RepeatMut<'a, T>) -> Option<_>` + = note: expected signature `fn(&mut RepeatMut<'_, _>) -> Option<_>` + found signature `fn(&'a mut RepeatMut<'_, _>) -> Option<_>` note: the anonymous lifetime as defined here... --> $DIR/issue-37884.rs:6:5 | diff --git a/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr b/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr index 065787cab08..1d41335036e 100644 --- a/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr +++ b/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr @@ -6,8 +6,8 @@ LL | let Some(n): &mut Option<i32> = &&Some(5i32) else { return }; | | | expected due to this | - = note: expected mutable reference `&mut Option<i32>` - found reference `&&Option<i32>` + = note: expected mutable reference `&mut Option<_>` + found reference `&&Option<_>` error[E0308]: mismatched types --> $DIR/let-else-binding-explicit-mut-annotated.rs:13:37 @@ -17,8 +17,8 @@ LL | let Some(n): &mut Option<i32> = &&mut Some(5i32) else { return }; | | | expected due to this | - = note: expected mutable reference `&mut Option<i32>` - found reference `&&mut Option<i32>` + = note: expected mutable reference `&mut Option<_>` + found reference `&&mut Option<_>` error: aborting due to 2 previous errors diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr index 86a4ac4132e..e8115bb6b06 100644 --- a/tests/ui/lifetimes/issue-79187-2.stderr +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -54,8 +54,8 @@ error[E0308]: mismatched types LL | take_foo(|a: &i32| a); | ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected reference `&i32` - found reference `&i32` + = note: expected reference `&_` + found reference `&_` note: the lifetime requirement is introduced here --> $DIR/issue-79187-2.rs:5:21 | @@ -68,8 +68,8 @@ error[E0308]: mismatched types LL | take_foo(|a: &i32| -> &i32 { a }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected reference `&i32` - found reference `&i32` + = note: expected reference `&_` + found reference `&_` note: the lifetime requirement is introduced here --> $DIR/issue-79187-2.rs:5:21 | diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr index c3d7960de56..10e3fc92868 100644 --- a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr @@ -12,8 +12,8 @@ LL | | LL | | }; | |_____- `match` arms have incompatible types | - = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + = note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _` + found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _` error: aborting due to 1 previous error diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr index 8e4a514c7c6..bf77875fa7a 100644 --- a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | _ => y, | ^ one type is more general than the other | - = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` - found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` + = note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _` + found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _` error: aborting due to 1 previous error diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr index a1958cc436a..1c8925e0bfb 100644 --- a/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr +++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr @@ -11,8 +11,8 @@ LL | | LL | | }; | |_____- `match` arms have incompatible types | - = note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8` - found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8` + = note: expected fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _` + found fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _` error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-118048.rs b/tests/ui/macros/issue-118048.rs new file mode 100644 index 00000000000..15a834fa2df --- /dev/null +++ b/tests/ui/macros/issue-118048.rs @@ -0,0 +1,10 @@ +macro_rules! foo { + ($ty:ty) => { + fn foo(_: $ty, _: $ty) {} + } +} + +foo!(_); +//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions + +fn main() {} diff --git a/tests/ui/macros/issue-118048.stderr b/tests/ui/macros/issue-118048.stderr new file mode 100644 index 00000000000..6acf78f63b2 --- /dev/null +++ b/tests/ui/macros/issue-118048.stderr @@ -0,0 +1,21 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions + --> $DIR/issue-118048.rs:7:6 + | +LL | foo!(_); + | ^ + | | + | not allowed in type signatures + | not allowed in type signatures + | +help: use type parameters instead + | +LL ~ fn foo<T>(_: $ty, _: $ty) {} +LL | } +LL | } +LL | +LL ~ foo!(T); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0121`. diff --git a/tests/ui/mir/field-projection-mutating-context.stderr b/tests/ui/mir/field-projection-mutating-context.stderr index 62c9e55a44b..c7289c0f07c 100644 --- a/tests/ui/mir/field-projection-mutating-context.stderr +++ b/tests/ui/mir/field-projection-mutating-context.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | let Foo(ref mut y): Foo<fn(&'static str)> = x; | ^^^^^^^^^ one type is more general than the other | - = note: expected fn pointer `for<'a> fn(&'a str)` - found fn pointer `fn(&str)` + = note: expected fn pointer `for<'a> fn(&'a _)` + found fn pointer `fn(&_)` error: aborting due to 1 previous error diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index 760e3327b77..e9808b86991 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -6,8 +6,8 @@ LL | a.iter().map(|_: (u32, u32)| 45); | | | expected due to this | - = note: expected closure signature `fn(&(u32, u32)) -> _` - found closure signature `fn((u32, u32)) -> _` + = note: expected closure signature `fn(&(_, _)) -> _` + found closure signature `fn((_, _)) -> _` note: required by a bound in `map` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL help: consider adjusting the signature so it borrows its argument diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr index bac27788a2d..292525daa3d 100644 --- a/tests/ui/mismatched_types/issue-36053-2.stderr +++ b/tests/ui/mismatched_types/issue-36053-2.stderr @@ -6,8 +6,8 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | | | expected due to this | - = note: expected closure signature `for<'a> fn(&'a &str) -> _` - found closure signature `for<'a> fn(&'a str) -> _` + = note: expected closure signature `for<'a> fn(&'a &_) -> _` + found closure signature `for<'a> fn(&'a _) -> _` note: required by a bound in `filter` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL help: consider adjusting the signature so it borrows its argument diff --git a/tests/ui/mismatched_types/normalize-fn-sig.stderr b/tests/ui/mismatched_types/normalize-fn-sig.stderr index 2166de85f1f..0fb3975c3c2 100644 --- a/tests/ui/mismatched_types/normalize-fn-sig.stderr +++ b/tests/ui/mismatched_types/normalize-fn-sig.stderr @@ -6,8 +6,8 @@ LL | needs_i32_ref_fn(foo::<()>); | | | arguments to this function are incorrect | - = note: expected fn pointer `fn(&'static i32, i32)` - found fn item `fn(i32, &'static i32) {foo::<()>}` + = note: expected fn pointer `fn(&'static _, _)` + found fn item `fn(_, &'static _) {foo::<()>}` note: function defined here --> $DIR/normalize-fn-sig.rs:11:4 | diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr index 821661f1a56..6a9d76f7998 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr @@ -6,8 +6,8 @@ LL | let mut x: HashSet<Day> = v.clone(); | | | expected due to this | - = note: expected struct `HashSet<Day>` - found reference `&HashSet<Day>` + = note: expected struct `HashSet<_>` + found reference `&HashSet<_>` note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39 | diff --git a/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr b/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr index 7d76c916d6d..58fd7776f2f 100644 --- a/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr +++ b/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); | ^^^^^^^^^ one type is more general than the other | - = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32` - found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32` + = note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _` + found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _` error[E0308]: mismatched types --> $DIR/hr-fn-aaa-as-aba.rs:20:12 @@ -13,8 +13,8 @@ error[E0308]: mismatched types LL | let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other | - = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32` - found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32` + = note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _` + found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _` error: aborting due to 2 previous errors diff --git a/tests/ui/nll/relate_tys/universe-violation.stderr b/tests/ui/nll/relate_tys/universe-violation.stderr index b585eee0769..a538a59a495 100644 --- a/tests/ui/nll/relate_tys/universe-violation.stderr +++ b/tests/ui/nll/relate_tys/universe-violation.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | let b: fn(&u32) -> &u32 = a; | ^ one type is more general than the other | - = note: expected fn pointer `for<'a> fn(&'a u32) -> &'a u32` - found fn pointer `fn(&u32) -> &u32` + = note: expected fn pointer `for<'a> fn(&'a _) -> &'a _` + found fn pointer `fn(&_) -> &_` error: aborting due to 1 previous error diff --git a/tests/ui/nll/trait-associated-constant.stderr b/tests/ui/nll/trait-associated-constant.stderr index f6277508eeb..371f7860d4d 100644 --- a/tests/ui/nll/trait-associated-constant.stderr +++ b/tests/ui/nll/trait-associated-constant.stderr @@ -4,8 +4,8 @@ error[E0308]: const not compatible with trait LL | const AC: Option<&'c str> = None; | ^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected enum `Option<&'b str>` - found enum `Option<&'c str>` + = note: expected enum `Option<&'b _>` + found enum `Option<&'c _>` note: the lifetime `'c` as defined here... --> $DIR/trait-associated-constant.rs:20:18 | diff --git a/tests/ui/or-patterns/inconsistent-modes.stderr b/tests/ui/or-patterns/inconsistent-modes.stderr index f6367ef8234..19618d336f8 100644 --- a/tests/ui/or-patterns/inconsistent-modes.stderr +++ b/tests/ui/or-patterns/inconsistent-modes.stderr @@ -57,8 +57,8 @@ LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); | | types differ in mutability | first introduced with type `&&u8` here | - = note: expected reference `&&u8` - found mutable reference `&mut &mut u8` + = note: expected reference `&&_` + found mutable reference `&mut &mut _` = note: a binding must have the same type in all alternatives error[E0308]: mismatched types diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs index d1950087c4c..2c402e4c65e 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs @@ -84,15 +84,15 @@ fn main() {} #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } //~^ ERROR inclusive range with no end -//~| ERROR expected one of `=>`, `if`, or `|`, found `#` +//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } //~^ ERROR inclusive range with no end -//~| ERROR expected one of `=>`, `if`, or `|`, found `#` +//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } } //~^ ERROR unexpected token: `#` #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } //~^ ERROR inclusive range with no end -//~| ERROR expected one of `=>`, `if`, or `|`, found `#` +//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } //~^ ERROR unexpected token: `#` diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr index e46c591080d..a0e95c5c1ed 100644 --- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr +++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr @@ -365,11 +365,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `=>`, `if`, or `|`, found `#` +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:85:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } - | ^ expected one of `=>`, `if`, or `|` + | ^ expected one of `,`, `=>`, `if`, `|`, or `}` error[E0586]: inclusive range with no end --> $DIR/attr-stmt-expr-attr-bad.rs:88:35 @@ -379,11 +379,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `=>`, `if`, or `|`, found `#` +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:88:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } - | ^ expected one of `=>`, `if`, or `|` + | ^ expected one of `,`, `=>`, `if`, `|`, or `}` error: unexpected token: `#` --> $DIR/attr-stmt-expr-attr-bad.rs:91:39 @@ -399,11 +399,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) -error: expected one of `=>`, `if`, or `|`, found `#` +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:93:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } - | ^ expected one of `=>`, `if`, or `|` + | ^ expected one of `,`, `=>`, `if`, `|`, or `}` error: unexpected token: `#` --> $DIR/attr-stmt-expr-attr-bad.rs:97:34 diff --git a/tests/ui/parser/issues/issue-24375.rs b/tests/ui/parser/issues/issue-24375.rs index 1d128d33e4f..8d1bc579e7b 100644 --- a/tests/ui/parser/issues/issue-24375.rs +++ b/tests/ui/parser/issues/issue-24375.rs @@ -3,7 +3,7 @@ static tmp : [&'static str; 2] = ["hello", "he"]; fn main() { let z = "hello"; match z { - tmp[0] => {} //~ ERROR expected one of `=>`, `@`, `if`, or `|`, found `[` + tmp[0] => {} //~ ERROR expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `[` _ => {} } } diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr index bb1e19e9e6d..2b980a5520f 100644 --- a/tests/ui/parser/issues/issue-24375.stderr +++ b/tests/ui/parser/issues/issue-24375.stderr @@ -1,8 +1,8 @@ -error: expected one of `=>`, `@`, `if`, or `|`, found `[` +error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `[` --> $DIR/issue-24375.rs:6:12 | LL | tmp[0] => {} - | ^ expected one of `=>`, `@`, `if`, or `|` + | ^ expected one of `,`, `=>`, `@`, `if`, `|`, or `}` error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.rs b/tests/ui/parser/macro/macro-expand-to-match-arm.rs index 39d1d065ed9..db38fa0d7bc 100644 --- a/tests/ui/parser/macro/macro-expand-to-match-arm.rs +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.rs @@ -1,6 +1,9 @@ macro_rules! arm { ($pattern:pat => $block:block) => { $pattern => $block + //~^ ERROR macro expansion ignores token `=>` and any following + //~| NOTE the usage of `arm!` is likely invalid in pattern context + //~| NOTE macros cannot expand to match arms }; } @@ -9,9 +12,8 @@ fn main() { match x { Some(1) => {}, arm!(None => {}), - //~^ NOTE macros cannot expand to match arms - //~| ERROR unexpected `,` in pattern - // doesn't recover + //~^ NOTE caused by the macro expansion here + //~| ERROR `match` arm with no body Some(2) => {}, _ => {}, }; diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr index 1b34d2d12b2..e3e7ff89c81 100644 --- a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr +++ b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr @@ -1,10 +1,20 @@ -error: unexpected `,` in pattern - --> $DIR/macro-expand-to-match-arm.rs:11:25 +error: macro expansion ignores token `=>` and any following + --> $DIR/macro-expand-to-match-arm.rs:3:18 | +LL | $pattern => $block + | ^^ +... LL | arm!(None => {}), - | ^ + | ---------------- caused by the macro expansion here | + = note: the usage of `arm!` is likely invalid in pattern context = note: macros cannot expand to match arms -error: aborting due to 1 previous error +error: `match` arm with no body + --> $DIR/macro-expand-to-match-arm.rs:14:9 + | +LL | arm!(None => {}), + | ^^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/match-arm-without-body.rs b/tests/ui/parser/match-arm-without-body.rs new file mode 100644 index 00000000000..c3487c2c658 --- /dev/null +++ b/tests/ui/parser/match-arm-without-body.rs @@ -0,0 +1,79 @@ +macro_rules! pat { + () => { Some(_) } +} + +fn main() { + match Some(false) { + Some(_) + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + Some(_) + _ => {} + //~^ ERROR expected one of + } + 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 + } + 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 + _ => {} + } + match Some(false) { + Some(_) if true + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + Some(_) if true + _ => {} + //~^ ERROR expected one of + } + match Some(false) { + Some(_) if true, + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + Some(_) if true, + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + _ => {} + } + match Some(false) { + pat!() + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + pat!(), + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + pat!() if true, + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + } + match Some(false) { + pat!() + //~^ ERROR expected `,` following `match` arm + //~| HELP missing a comma here + //~| ERROR `match` arm with no body + //~| HELP add a body after the pattern + _ => {} + } + match Some(false) { + pat!(), + //~^ ERROR `match` arm with no body + //~| HELP add a body after the pattern + _ => {} + } +} diff --git a/tests/ui/parser/match-arm-without-body.stderr b/tests/ui/parser/match-arm-without-body.stderr new file mode 100644 index 00000000000..3a06ed050b5 --- /dev/null +++ b/tests/ui/parser/match-arm-without-body.stderr @@ -0,0 +1,116 @@ +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found reserved identifier `_` + --> $DIR/match-arm-without-body.rs:13:9 + | +LL | Some(_) + | - expected one of `,`, `=>`, `if`, `|`, or `}` +LL | _ => {} + | ^ unexpected token + +error: unexpected `,` in pattern + --> $DIR/match-arm-without-body.rs:17:16 + | +LL | Some(_), + | ^ + | +help: try adding parentheses to match on a tuple... + | +LL | (Some(_),) + | + + +help: ...or a vertical bar to match on multiple alternatives + | +LL | Some(_) | + | + +error: unexpected `,` in pattern + --> $DIR/match-arm-without-body.rs:23:16 + | +LL | Some(_), + | ^ + | +help: try adding parentheses to match on a tuple... + | +LL ~ (Some(_), +LL | +LL | +LL | +LL ~ _) => {} + | +help: ...or a vertical bar to match on multiple alternatives + | +LL ~ Some(_) | +LL + +LL + +LL + +LL ~ _ => {} + | + +error: expected one of `,`, `.`, `=>`, `?`, `}`, or an operator, found reserved identifier `_` + --> $DIR/match-arm-without-body.rs:36:9 + | +LL | Some(_) if true + | - expected one of `,`, `.`, `=>`, `?`, `}`, or an operator +LL | _ => {} + | ^ unexpected token + +error: expected `,` following `match` arm + --> $DIR/match-arm-without-body.rs:66:15 + | +LL | pat!() + | ^ help: missing a comma here to end this `match` arm: `,` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:7:9 + | +LL | Some(_) + | ^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:30:9 + | +LL | Some(_) if true + | ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:40:9 + | +LL | Some(_) if true, + | ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:45:9 + | +LL | Some(_) if true, + | ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:51:9 + | +LL | pat!() + | ^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:56:9 + | +LL | pat!(), + | ^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:61:9 + | +LL | pat!() if true, + | ^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:66:9 + | +LL | pat!() + | ^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: `match` arm with no body + --> $DIR/match-arm-without-body.rs:74:9 + | +LL | pat!(), + | ^^^^^^- help: add a body after the pattern: `=> todo!(),` + +error: aborting due to 14 previous errors + diff --git a/tests/ui/parser/pat-lt-bracket-1.rs b/tests/ui/parser/pat-lt-bracket-1.rs index 2e2001434f2..33da15adb9e 100644 --- a/tests/ui/parser/pat-lt-bracket-1.rs +++ b/tests/ui/parser/pat-lt-bracket-1.rs @@ -1,7 +1,7 @@ fn main() { match 42 { x < 7 => (), - //~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<` + //~^ error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `<` _ => () } } diff --git a/tests/ui/parser/pat-lt-bracket-1.stderr b/tests/ui/parser/pat-lt-bracket-1.stderr index 14e679bbee0..f39487052ad 100644 --- a/tests/ui/parser/pat-lt-bracket-1.stderr +++ b/tests/ui/parser/pat-lt-bracket-1.stderr @@ -1,8 +1,8 @@ -error: expected one of `=>`, `@`, `if`, or `|`, found `<` +error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `<` --> $DIR/pat-lt-bracket-1.rs:3:7 | LL | x < 7 => (), - | ^ expected one of `=>`, `@`, `if`, or `|` + | ^ expected one of `,`, `=>`, `@`, `if`, `|`, or `}` error: aborting due to 1 previous error diff --git a/tests/ui/pattern/never_patterns.rs b/tests/ui/pattern/never_patterns.rs index e2e17e0e9a7..915f3e75e7b 100644 --- a/tests/ui/pattern/never_patterns.rs +++ b/tests/ui/pattern/never_patterns.rs @@ -20,58 +20,58 @@ fn never_pattern_location(void: Void) { // FIXME(never_patterns): Don't accept on a non-empty type. match Some(0) { None => {} - Some(!) => {} + Some(!), } // FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches. match () { () => {} - ! => {} + !, } // FIXME(never_patterns): Don't accept even on an empty branch. match None::<Void> { None => {} - ! => {} + !, } // FIXME(never_patterns): Let alone if the emptiness is behind a reference. match None::<&Void> { None => {} - ! => {} + !, } // Participate in match ergonomics. match &void { - ! => {} + ! } match &&void { - ! => {} + ! } match &&void { - &! => {} + &! } match &None::<Void> { None => {} - Some(!) => {} + Some(!) } match None::<&Void> { None => {} - Some(!) => {} + Some(!), } // Accept on a composite empty type. match None::<&(u32, Void)> { None => {} - Some(&!) => {} + Some(&!), } // Accept on an simple empty type. match None::<Void> { None => {} - Some(!) => {} + Some(!), } match None::<&Void> { None => {} - Some(&!) => {} + Some(&!), } match None::<&(u32, Void)> { None => {} - Some(&(_, !)) => {} + Some(&(_, !)), } } @@ -84,12 +84,12 @@ fn never_and_bindings() { //~^ ERROR: is not bound in all patterns } let (Ok(_x) | Err(&!)) = x; - //~^ ERROR: is not bound in all patterns + //~^ ERROR: is not bound in all patterns // FIXME(never_patterns): A never pattern mustn't have bindings. match x { Ok(_) => {} - Err(&(_b, !)) => {} + Err(&(_b, !)), } match x { Ok(_a) | Err(&(_b, !)) => {} diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr new file mode 100644 index 00000000000..304435cb21e --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr @@ -0,0 +1,63 @@ +error: unreachable pattern + --> $DIR/empty-match-check-notes.rs:17:9 + | +LL | _ => {} + | ^ + | +note: the lint level is defined here + --> $DIR/empty-match-check-notes.rs:7:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-match-check-notes.rs:20:9 + | +LL | _ if false => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-match-check-notes.rs:27:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-match-check-notes.rs:30:9 + | +LL | _ if false => {} + | ^ + +error[E0005]: refutable pattern in local binding + --> $DIR/empty-match-check-notes.rs:35:9 + | +LL | let None = x; + | ^^^^ pattern `Some(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future + = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>` +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let None = x { todo!() }; + | ++ +++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match-check-notes.rs:45:11 + | +LL | match 0u8 { + | ^^^ pattern `_` not covered + | + = note: the matched value is of type `u8` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + _ => todo!() + | + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr new file mode 100644 index 00000000000..40494b726f0 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr @@ -0,0 +1,62 @@ +error: unreachable pattern + --> $DIR/empty-match-check-notes.rs:17:9 + | +LL | _ => {} + | ^ + | +note: the lint level is defined here + --> $DIR/empty-match-check-notes.rs:7:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-match-check-notes.rs:20:9 + | +LL | _ if false => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-match-check-notes.rs:27:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-match-check-notes.rs:30:9 + | +LL | _ if false => {} + | ^ + +error[E0005]: refutable pattern in local binding + --> $DIR/empty-match-check-notes.rs:35:9 + | +LL | let None = x; + | ^^^^ pattern `Some(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>` +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let None = x { todo!() }; + | ++ +++++++++++ + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/empty-match-check-notes.rs:45:11 + | +LL | match 0u8 { + | ^^^ pattern `_` not covered + | + = note: the matched value is of type `u8` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ _ if false => {}, +LL + _ => todo!() + | + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.rs b/tests/ui/pattern/usefulness/empty-match-check-notes.rs new file mode 100644 index 00000000000..ee9ff3dcf90 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-match-check-notes.rs @@ -0,0 +1,52 @@ +// aux-build:empty.rs +// revisions: normal exhaustive_patterns +// +// This tests a match with no arms on various types, and checks NOTEs. +#![feature(never_type)] +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![deny(unreachable_patterns)] +//~^ NOTE the lint level is defined here + +extern crate empty; + +enum EmptyEnum {} + +fn empty_enum(x: EmptyEnum) { + match x {} // ok + match x { + _ => {} //~ ERROR unreachable pattern + } + match x { + _ if false => {} //~ ERROR unreachable pattern + } +} + +fn empty_foreign_enum(x: empty::EmptyForeignEnum) { + match x {} // ok + match x { + _ => {} //~ ERROR unreachable pattern + } + match x { + _ if false => {} //~ ERROR unreachable pattern + } +} + +fn empty_foreign_enum_private(x: Option<empty::SecretlyUninhabitedForeignStruct>) { + let None = x; + //~^ ERROR refutable pattern in local binding + //~| NOTE `let` bindings require an "irrefutable pattern" + //~| NOTE for more information, visit + //~| NOTE the matched value is of type + //~| NOTE pattern `Some(_)` not covered + //[exhaustive_patterns]~| NOTE currently uninhabited, but this variant contains private fields +} + +fn main() { + match 0u8 { + //~^ ERROR `_` not covered + //~| NOTE the matched value is of type + //~| NOTE match arms with guards don't count towards exhaustivity + //~| NOTE pattern `_` not covered + _ if false => {} + } +} diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr index 8f9bd5bde89..9c3bebd7797 100644 --- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr +++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr @@ -1,62 +1,5 @@ -error: unreachable pattern - --> $DIR/empty-match.rs:68:9 - | -LL | _ => {}, - | ^ - | -note: the lint level is defined here - --> $DIR/empty-match.rs:8:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - -error: unreachable pattern - --> $DIR/empty-match.rs:71:9 - | -LL | _ if false => {}, - | ^ - -error: unreachable pattern - --> $DIR/empty-match.rs:78:9 - | -LL | _ => {}, - | ^ - -error: unreachable pattern - --> $DIR/empty-match.rs:81:9 - | -LL | _ if false => {}, - | ^ - -error[E0005]: refutable pattern in local binding - --> $DIR/empty-match.rs:86:9 - | -LL | let None = x; - | ^^^^ pattern `Some(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html - = note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future - = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>` -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let None = x { todo!() }; - | ++ +++++++++++ - -error: unreachable pattern - --> $DIR/empty-match.rs:98:9 - | -LL | _ => {}, - | ^ - -error: unreachable pattern - --> $DIR/empty-match.rs:101:9 - | -LL | _ if false => {}, - | ^ - error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/empty-match.rs:119:20 + --> $DIR/empty-match.rs:46:20 | LL | match_no_arms!(0u8); | ^^^ @@ -65,122 +8,121 @@ LL | match_no_arms!(0u8); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty - --> $DIR/empty-match.rs:121:20 + --> $DIR/empty-match.rs:47:20 | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ | note: `NonEmptyStruct1` defined here - --> $DIR/empty-match.rs:15:8 + --> $DIR/empty-match.rs:22:12 | -LL | struct NonEmptyStruct1; - | ^^^^^^^^^^^^^^^ +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyStruct1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:123:20 + --> $DIR/empty-match.rs:48:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ | note: `NonEmptyStruct2` defined here - --> $DIR/empty-match.rs:18:8 + --> $DIR/empty-match.rs:23:12 | -LL | struct NonEmptyStruct2(bool); - | ^^^^^^^^^^^^^^^ +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyStruct2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:125:20 + --> $DIR/empty-match.rs:49:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `NonEmptyUnion1` defined here - --> $DIR/empty-match.rs:21:7 + --> $DIR/empty-match.rs:24:11 | -LL | union NonEmptyUnion1 { - | ^^^^^^^^^^^^^^ +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyUnion1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:127:20 + --> $DIR/empty-match.rs:50:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `NonEmptyUnion2` defined here - --> $DIR/empty-match.rs:26:7 + --> $DIR/empty-match.rs:27:11 | -LL | union NonEmptyUnion2 { - | ^^^^^^^^^^^^^^ +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyUnion2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:129:20 + --> $DIR/empty-match.rs:51:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:32:6 + --> $DIR/empty-match.rs:31:10 | -LL | enum NonEmptyEnum1 { - | ^^^^^^^^^^^^^ -... -LL | Foo(bool), - | --- not covered +LL | enum NonEmptyEnum1 { + | ^^^^^^^^^^^^^ +LL | Foo(bool), + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:132:20 + --> $DIR/empty-match.rs:52:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:39:6 - | -LL | enum NonEmptyEnum2 { - | ^^^^^^^^^^^^^ -... -LL | Foo(bool), - | --- not covered -... -LL | Bar, - | --- not covered + --> $DIR/empty-match.rs:34:10 + | +LL | enum NonEmptyEnum2 { + | ^^^^^^^^^^^^^ +LL | Foo(bool), + | --- not covered +LL | Bar, + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:135:20 + --> $DIR/empty-match.rs:53:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:49:6 - | -LL | enum NonEmptyEnum5 { - | ^^^^^^^^^^^^^ -... -LL | V1, V2, V3, V4, V5, - | -- -- -- -- -- not covered - | | | | | - | | | | not covered - | | | not covered - | | not covered - | not covered + --> $DIR/empty-match.rs:38:10 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ +LL | V1, + | -- not covered +LL | V2, + | -- not covered +LL | V3, + | -- not covered +LL | V4, + | -- not covered +LL | V5, + | -- not covered = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:139:24 + --> $DIR/empty-match.rs:55:24 | LL | match_guarded_arm!(0u8); | ^^^ pattern `_` not covered @@ -189,161 +131,159 @@ LL | match_guarded_arm!(0u8); = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + _ => todo!() +LL ~ _ if false => {}, +LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:144:24 + --> $DIR/empty-match.rs:56:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered | note: `NonEmptyStruct1` defined here - --> $DIR/empty-match.rs:15:8 + --> $DIR/empty-match.rs:22:12 | -LL | struct NonEmptyStruct1; - | ^^^^^^^^^^^^^^^ +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyStruct1` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + NonEmptyStruct1 => todo!() +LL ~ _ if false => {}, +LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:149:24 + --> $DIR/empty-match.rs:57:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered | note: `NonEmptyStruct2` defined here - --> $DIR/empty-match.rs:18:8 + --> $DIR/empty-match.rs:23:12 | -LL | struct NonEmptyStruct2(bool); - | ^^^^^^^^^^^^^^^ +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyStruct2` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + NonEmptyStruct2(_) => todo!() +LL ~ _ if false => {}, +LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:154:24 + --> $DIR/empty-match.rs:58:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered | note: `NonEmptyUnion1` defined here - --> $DIR/empty-match.rs:21:7 + --> $DIR/empty-match.rs:24:11 | -LL | union NonEmptyUnion1 { - | ^^^^^^^^^^^^^^ +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyUnion1` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + NonEmptyUnion1 { .. } => todo!() +LL ~ _ if false => {}, +LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:159:24 + --> $DIR/empty-match.rs:59:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered | note: `NonEmptyUnion2` defined here - --> $DIR/empty-match.rs:26:7 + --> $DIR/empty-match.rs:27:11 | -LL | union NonEmptyUnion2 { - | ^^^^^^^^^^^^^^ +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyUnion2` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + NonEmptyUnion2 { .. } => todo!() +LL ~ _ if false => {}, +LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:164:24 + --> $DIR/empty-match.rs:60:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:32:6 + --> $DIR/empty-match.rs:31:10 | -LL | enum NonEmptyEnum1 { - | ^^^^^^^^^^^^^ -... -LL | Foo(bool), - | --- not covered +LL | enum NonEmptyEnum1 { + | ^^^^^^^^^^^^^ +LL | Foo(bool), + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + NonEmptyEnum1::Foo(_) => todo!() +LL ~ _ if false => {}, +LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:169:24 + --> $DIR/empty-match.rs:61:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:39:6 - | -LL | enum NonEmptyEnum2 { - | ^^^^^^^^^^^^^ -... -LL | Foo(bool), - | --- not covered -... -LL | Bar, - | --- not covered + --> $DIR/empty-match.rs:34:10 + | +LL | enum NonEmptyEnum2 { + | ^^^^^^^^^^^^^ +LL | Foo(bool), + | --- not covered +LL | Bar, + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ _ if false => {}, -LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() +LL ~ _ if false => {}, +LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:174:24 + --> $DIR/empty-match.rs:62:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:49:6 - | -LL | enum NonEmptyEnum5 { - | ^^^^^^^^^^^^^ -... -LL | V1, V2, V3, V4, V5, - | -- -- -- -- -- not covered - | | | | | - | | | | not covered - | | | not covered - | | not covered - | not covered + --> $DIR/empty-match.rs:38:10 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ +LL | V1, + | -- not covered +LL | V2, + | -- not covered +LL | V3, + | -- not covered +LL | V4, + | -- not covered +LL | V5, + | -- not covered = note: the matched value is of type `NonEmptyEnum5` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ _ if false => {}, -LL + _ => todo!() +LL ~ _ if false => {}, +LL + _ => todo!() | -error: aborting due to 23 previous errors +error: aborting due to 16 previous errors -Some errors have detailed explanations: E0004, E0005. -For more information about an error, try `rustc --explain E0004`. +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr index 7f0389f40e2..9c3bebd7797 100644 --- a/tests/ui/pattern/usefulness/empty-match.normal.stderr +++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr @@ -1,61 +1,5 @@ -error: unreachable pattern - --> $DIR/empty-match.rs:68:9 - | -LL | _ => {}, - | ^ - | -note: the lint level is defined here - --> $DIR/empty-match.rs:8:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - -error: unreachable pattern - --> $DIR/empty-match.rs:71:9 - | -LL | _ if false => {}, - | ^ - -error: unreachable pattern - --> $DIR/empty-match.rs:78:9 - | -LL | _ => {}, - | ^ - -error: unreachable pattern - --> $DIR/empty-match.rs:81:9 - | -LL | _ if false => {}, - | ^ - -error[E0005]: refutable pattern in local binding - --> $DIR/empty-match.rs:86:9 - | -LL | let None = x; - | ^^^^ pattern `Some(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html - = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>` -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let None = x { todo!() }; - | ++ +++++++++++ - -error: unreachable pattern - --> $DIR/empty-match.rs:98:9 - | -LL | _ => {}, - | ^ - -error: unreachable pattern - --> $DIR/empty-match.rs:101:9 - | -LL | _ if false => {}, - | ^ - error[E0004]: non-exhaustive patterns: type `u8` is non-empty - --> $DIR/empty-match.rs:119:20 + --> $DIR/empty-match.rs:46:20 | LL | match_no_arms!(0u8); | ^^^ @@ -64,122 +8,121 @@ LL | match_no_arms!(0u8); = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty - --> $DIR/empty-match.rs:121:20 + --> $DIR/empty-match.rs:47:20 | LL | match_no_arms!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ | note: `NonEmptyStruct1` defined here - --> $DIR/empty-match.rs:15:8 + --> $DIR/empty-match.rs:22:12 | -LL | struct NonEmptyStruct1; - | ^^^^^^^^^^^^^^^ +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyStruct1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty - --> $DIR/empty-match.rs:123:20 + --> $DIR/empty-match.rs:48:20 | LL | match_no_arms!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ | note: `NonEmptyStruct2` defined here - --> $DIR/empty-match.rs:18:8 + --> $DIR/empty-match.rs:23:12 | -LL | struct NonEmptyStruct2(bool); - | ^^^^^^^^^^^^^^^ +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyStruct2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty - --> $DIR/empty-match.rs:125:20 + --> $DIR/empty-match.rs:49:20 | LL | match_no_arms!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `NonEmptyUnion1` defined here - --> $DIR/empty-match.rs:21:7 + --> $DIR/empty-match.rs:24:11 | -LL | union NonEmptyUnion1 { - | ^^^^^^^^^^^^^^ +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyUnion1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty - --> $DIR/empty-match.rs:127:20 + --> $DIR/empty-match.rs:50:20 | LL | match_no_arms!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: `NonEmptyUnion2` defined here - --> $DIR/empty-match.rs:26:7 + --> $DIR/empty-match.rs:27:11 | -LL | union NonEmptyUnion2 { - | ^^^^^^^^^^^^^^ +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyUnion2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:129:20 + --> $DIR/empty-match.rs:51:20 | LL | match_no_arms!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:32:6 + --> $DIR/empty-match.rs:31:10 | -LL | enum NonEmptyEnum1 { - | ^^^^^^^^^^^^^ -... -LL | Foo(bool), - | --- not covered +LL | enum NonEmptyEnum1 { + | ^^^^^^^^^^^^^ +LL | Foo(bool), + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:132:20 + --> $DIR/empty-match.rs:52:20 | LL | match_no_arms!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:39:6 - | -LL | enum NonEmptyEnum2 { - | ^^^^^^^^^^^^^ -... -LL | Foo(bool), - | --- not covered -... -LL | Bar, - | --- not covered + --> $DIR/empty-match.rs:34:10 + | +LL | enum NonEmptyEnum2 { + | ^^^^^^^^^^^^^ +LL | Foo(bool), + | --- not covered +LL | Bar, + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:135:20 + --> $DIR/empty-match.rs:53:20 | LL | match_no_arms!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:49:6 - | -LL | enum NonEmptyEnum5 { - | ^^^^^^^^^^^^^ -... -LL | V1, V2, V3, V4, V5, - | -- -- -- -- -- not covered - | | | | | - | | | | not covered - | | | not covered - | | not covered - | not covered + --> $DIR/empty-match.rs:38:10 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ +LL | V1, + | -- not covered +LL | V2, + | -- not covered +LL | V3, + | -- not covered +LL | V4, + | -- not covered +LL | V5, + | -- not covered = note: the matched value is of type `NonEmptyEnum5` = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms error[E0004]: non-exhaustive patterns: `_` not covered - --> $DIR/empty-match.rs:139:24 + --> $DIR/empty-match.rs:55:24 | LL | match_guarded_arm!(0u8); | ^^^ pattern `_` not covered @@ -188,161 +131,159 @@ LL | match_guarded_arm!(0u8); = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + _ => todo!() +LL ~ _ if false => {}, +LL + _ => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered - --> $DIR/empty-match.rs:144:24 + --> $DIR/empty-match.rs:56:24 | LL | match_guarded_arm!(NonEmptyStruct1); | ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered | note: `NonEmptyStruct1` defined here - --> $DIR/empty-match.rs:15:8 + --> $DIR/empty-match.rs:22:12 | -LL | struct NonEmptyStruct1; - | ^^^^^^^^^^^^^^^ +LL | struct NonEmptyStruct1; + | ^^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyStruct1` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + NonEmptyStruct1 => todo!() +LL ~ _ if false => {}, +LL + NonEmptyStruct1 => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered - --> $DIR/empty-match.rs:149:24 + --> $DIR/empty-match.rs:57:24 | LL | match_guarded_arm!(NonEmptyStruct2(true)); | ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered | note: `NonEmptyStruct2` defined here - --> $DIR/empty-match.rs:18:8 + --> $DIR/empty-match.rs:23:12 | -LL | struct NonEmptyStruct2(bool); - | ^^^^^^^^^^^^^^^ +LL | struct NonEmptyStruct2(bool); + | ^^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyStruct2` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + NonEmptyStruct2(_) => todo!() +LL ~ _ if false => {}, +LL + NonEmptyStruct2(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered - --> $DIR/empty-match.rs:154:24 + --> $DIR/empty-match.rs:58:24 | LL | match_guarded_arm!((NonEmptyUnion1 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered | note: `NonEmptyUnion1` defined here - --> $DIR/empty-match.rs:21:7 + --> $DIR/empty-match.rs:24:11 | -LL | union NonEmptyUnion1 { - | ^^^^^^^^^^^^^^ +LL | union NonEmptyUnion1 { + | ^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyUnion1` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + NonEmptyUnion1 { .. } => todo!() +LL ~ _ if false => {}, +LL + NonEmptyUnion1 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered - --> $DIR/empty-match.rs:159:24 + --> $DIR/empty-match.rs:59:24 | LL | match_guarded_arm!((NonEmptyUnion2 { foo: () })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered | note: `NonEmptyUnion2` defined here - --> $DIR/empty-match.rs:26:7 + --> $DIR/empty-match.rs:27:11 | -LL | union NonEmptyUnion2 { - | ^^^^^^^^^^^^^^ +LL | union NonEmptyUnion2 { + | ^^^^^^^^^^^^^^ = note: the matched value is of type `NonEmptyUnion2` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + NonEmptyUnion2 { .. } => todo!() +LL ~ _ if false => {}, +LL + NonEmptyUnion2 { .. } => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered - --> $DIR/empty-match.rs:164:24 + --> $DIR/empty-match.rs:60:24 | LL | match_guarded_arm!(NonEmptyEnum1::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered | note: `NonEmptyEnum1` defined here - --> $DIR/empty-match.rs:32:6 + --> $DIR/empty-match.rs:31:10 | -LL | enum NonEmptyEnum1 { - | ^^^^^^^^^^^^^ -... -LL | Foo(bool), - | --- not covered +LL | enum NonEmptyEnum1 { + | ^^^^^^^^^^^^^ +LL | Foo(bool), + | --- not covered = note: the matched value is of type `NonEmptyEnum1` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL ~ _ if false => {}, -LL + NonEmptyEnum1::Foo(_) => todo!() +LL ~ _ if false => {}, +LL + NonEmptyEnum1::Foo(_) => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - --> $DIR/empty-match.rs:169:24 + --> $DIR/empty-match.rs:61:24 | LL | match_guarded_arm!(NonEmptyEnum2::Foo(true)); | ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered | note: `NonEmptyEnum2` defined here - --> $DIR/empty-match.rs:39:6 - | -LL | enum NonEmptyEnum2 { - | ^^^^^^^^^^^^^ -... -LL | Foo(bool), - | --- not covered -... -LL | Bar, - | --- not covered + --> $DIR/empty-match.rs:34:10 + | +LL | enum NonEmptyEnum2 { + | ^^^^^^^^^^^^^ +LL | Foo(bool), + | --- not covered +LL | Bar, + | --- not covered = note: the matched value is of type `NonEmptyEnum2` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | -LL ~ _ if false => {}, -LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() +LL ~ _ if false => {}, +LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!() | error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - --> $DIR/empty-match.rs:174:24 + --> $DIR/empty-match.rs:62:24 | LL | match_guarded_arm!(NonEmptyEnum5::V1); | ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered | note: `NonEmptyEnum5` defined here - --> $DIR/empty-match.rs:49:6 - | -LL | enum NonEmptyEnum5 { - | ^^^^^^^^^^^^^ -... -LL | V1, V2, V3, V4, V5, - | -- -- -- -- -- not covered - | | | | | - | | | | not covered - | | | not covered - | | not covered - | not covered + --> $DIR/empty-match.rs:38:10 + | +LL | enum NonEmptyEnum5 { + | ^^^^^^^^^^^^^ +LL | V1, + | -- not covered +LL | V2, + | -- not covered +LL | V3, + | -- not covered +LL | V4, + | -- not covered +LL | V5, + | -- not covered = note: the matched value is of type `NonEmptyEnum5` = note: match arms with guards don't count towards exhaustivity help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms | -LL ~ _ if false => {}, -LL + _ => todo!() +LL ~ _ if false => {}, +LL + _ => todo!() | -error: aborting due to 23 previous errors +error: aborting due to 16 previous errors -Some errors have detailed explanations: E0004, E0005. -For more information about an error, try `rustc --explain E0004`. +For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs index fe5d0bce14f..321f24adc46 100644 --- a/tests/ui/pattern/usefulness/empty-match.rs +++ b/tests/ui/pattern/usefulness/empty-match.rs @@ -1,179 +1,65 @@ -// aux-build:empty.rs // revisions: normal exhaustive_patterns // // This tests a match with no arms on various types. #![feature(never_type)] -#![feature(never_type_fallback)] #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] #![deny(unreachable_patterns)] -//~^ NOTE the lint level is defined here -extern crate empty; - -enum EmptyEnum {} - -struct NonEmptyStruct1; -//~^ NOTE `NonEmptyStruct1` defined here -//~| NOTE `NonEmptyStruct1` defined here -struct NonEmptyStruct2(bool); -//~^ NOTE `NonEmptyStruct2` defined here -//~| NOTE `NonEmptyStruct2` defined here -union NonEmptyUnion1 { - //~^ NOTE `NonEmptyUnion1` defined here - //~| NOTE `NonEmptyUnion1` defined here - foo: (), -} -union NonEmptyUnion2 { - //~^ NOTE `NonEmptyUnion2` defined here - //~| NOTE `NonEmptyUnion2` defined here - foo: (), - bar: (), -} -enum NonEmptyEnum1 { - //~^ NOTE `NonEmptyEnum1` defined here - //~| NOTE `NonEmptyEnum1` defined here - Foo(bool), - //~^ NOTE not covered - //~| NOTE not covered -} -enum NonEmptyEnum2 { - //~^ NOTE `NonEmptyEnum2` defined here - //~| NOTE `NonEmptyEnum2` defined here - Foo(bool), - //~^ NOTE not covered - //~| NOTE not covered - Bar, - //~^ NOTE not covered - //~| NOTE not covered -} -enum NonEmptyEnum5 { - //~^ NOTE `NonEmptyEnum5` defined here - //~| NOTE `NonEmptyEnum5` defined here - V1, V2, V3, V4, V5, - //~^ NOTE not covered - //~| NOTE not covered - //~| NOTE not covered - //~| NOTE not covered - //~| NOTE not covered - //~| NOTE not covered - //~| NOTE not covered - //~| NOTE not covered - //~| NOTE not covered - //~| NOTE not covered -} - -fn empty_enum(x: EmptyEnum) { - match x {} // ok - match x { - _ => {}, //~ ERROR unreachable pattern +fn nonempty() { + macro_rules! match_no_arms { + ($e:expr) => { + match $e {} + }; } - match x { - _ if false => {}, //~ ERROR unreachable pattern + macro_rules! match_guarded_arm { + ($e:expr) => { + match $e { + _ if false => {} + } + }; } -} -fn empty_foreign_enum(x: empty::EmptyForeignEnum) { - match x {} // ok - match x { - _ => {}, //~ ERROR unreachable pattern + struct NonEmptyStruct1; + struct NonEmptyStruct2(bool); + union NonEmptyUnion1 { + foo: (), } - match x { - _ if false => {}, //~ ERROR unreachable pattern + union NonEmptyUnion2 { + foo: (), + bar: !, } -} - -fn empty_foreign_enum_private(x: Option<empty::SecretlyUninhabitedForeignStruct>) { - let None = x; - //~^ ERROR refutable pattern in local binding - //~| NOTE `let` bindings require an "irrefutable pattern" - //~| NOTE for more information, visit - //~| NOTE the matched value is of type - //~| NOTE pattern `Some(_)` not covered - //[exhaustive_patterns]~| NOTE currently uninhabited, but this variant contains private fields -} - -fn never(x: !) { - match x {} // ok - match x { - _ => {}, //~ ERROR unreachable pattern + enum NonEmptyEnum1 { + Foo(bool), } - match x { - _ if false => {}, //~ ERROR unreachable pattern + enum NonEmptyEnum2 { + Foo(bool), + Bar, + } + enum NonEmptyEnum5 { + V1, + V2, + V3, + V4, + V5, } -} - -macro_rules! match_no_arms { - ($e:expr) => { - match $e {} - }; -} -macro_rules! match_guarded_arm { - ($e:expr) => { - match $e { - _ if false => {} - } - }; -} -fn main() { match_no_arms!(0u8); //~ ERROR type `u8` is non-empty - //~| NOTE the matched value is of type match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty - //~| NOTE the matched value is of type match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty - //~| NOTE the matched value is of type match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty - //~| NOTE the matched value is of type match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty - //~| NOTE the matched value is of type match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered - //~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered - //~| NOTE the matched value is of type match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - //~| NOTE patterns `NonEmptyEnum2::Foo(_)` and - //~| NOTE the matched value is of type match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - //~| NOTE patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2` - //~| NOTE the matched value is of type match_guarded_arm!(0u8); //~ ERROR `_` not covered - //~| NOTE the matched value is of type - //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE pattern `_` not covered - //~| NOTE in this expansion of match_guarded_arm! match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered - //~| NOTE pattern `NonEmptyStruct1` not covered - //~| NOTE the matched value is of type - //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE in this expansion of match_guarded_arm! match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered - //~| NOTE the matched value is of type - //~| NOTE pattern `NonEmptyStruct2(_)` not covered - //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE in this expansion of match_guarded_arm! match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered - //~| NOTE the matched value is of type - //~| NOTE pattern `NonEmptyUnion1 { .. }` not covered - //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE in this expansion of match_guarded_arm! match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered - //~| NOTE the matched value is of type - //~| NOTE pattern `NonEmptyUnion2 { .. }` not covered - //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE in this expansion of match_guarded_arm! match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered - //~| NOTE the matched value is of type - //~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered - //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE in this expansion of match_guarded_arm! match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered - //~| NOTE the matched value is of type - //~| NOTE patterns `NonEmptyEnum2::Foo(_)` and - //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE in this expansion of match_guarded_arm! match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered - //~| NOTE the matched value is of type - //~| NOTE patterns `NonEmptyEnum5::V1`, - //~| NOTE match arms with guards don't count towards exhaustivity - //~| NOTE in this expansion of match_guarded_arm! } + +fn main() {} diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr new file mode 100644 index 00000000000..367aba3bdd6 --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr @@ -0,0 +1,393 @@ +error: unreachable pattern + --> $DIR/empty-types.rs:47:9 + | +LL | _ => {} + | ^ + | +note: the lint level is defined here + --> $DIR/empty-types.rs:13:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:50:9 + | +LL | _x => {} + | ^^ + +error[E0004]: non-exhaustive patterns: type `&!` is non-empty + --> $DIR/empty-types.rs:54:11 + | +LL | match ref_never {} + | ^^^^^^^^^ + | + = note: the matched value is of type `&!` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match ref_never { +LL + _ => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:69:9 + | +LL | (_, _) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:76:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:79:9 + | +LL | (_, _) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:83:9 + | +LL | _ => {} + | ^ + +error[E0004]: non-exhaustive patterns: `Ok(_)` not covered + --> $DIR/empty-types.rs:87:11 + | +LL | match res_u32_never {} + | ^^^^^^^^^^^^^ pattern `Ok(_)` not covered + | +note: `Result<u32, !>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result<u32, !>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ match res_u32_never { +LL + Ok(_) => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:95:9 + | +LL | Err(_) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:100:9 + | +LL | Err(_) => {} + | ^^^^^^ + +error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered + --> $DIR/empty-types.rs:97:11 + | +LL | match res_u32_never { + | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered + | +note: `Result<u32, !>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result<u32, !>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Err(_) => {}, +LL ~ Ok(1_u32..=u32::MAX) => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/empty-types.rs:104:9 + | +LL | let Ok(_x) = res_u32_never.as_ref(); + | ^^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Result<&u32, &!>` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; + | ++++++++++++++++ + +error: unreachable pattern + --> $DIR/empty-types.rs:115:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:119:9 + | +LL | Ok(_) => {} + | ^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:122:9 + | +LL | Ok(_) => {} + | ^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:123:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:126:9 + | +LL | Ok(_) => {} + | ^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:127:9 + | +LL | Err(_) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:136:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:139:13 + | +LL | _ if false => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:148:13 + | +LL | Some(_) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:152:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:204:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:209:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:214:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:219:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:225:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:284:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:287:9 + | +LL | (_, _) => {} + | ^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:290:9 + | +LL | Ok(_) => {} + | ^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:291:9 + | +LL | Err(_) => {} + | ^^^^^^ + +error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty + --> $DIR/empty-types.rs:323:11 + | +LL | match slice_never {} + | ^^^^^^^^^^^ + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match slice_never { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: `&[]` not covered + --> $DIR/empty-types.rs:334:11 + | +LL | match slice_never { + | ^^^^^^^^^^^ pattern `&[]` not covered + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [_, _, _, ..] => {}, +LL + &[] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` not covered + --> $DIR/empty-types.rs:347:11 + | +LL | match slice_never { + | ^^^^^^^^^^^ pattern `&[]` not covered + | + = note: the matched value is of type `&[!]` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ &[..] if false => {}, +LL + &[] => todo!() + | + +error[E0004]: non-exhaustive patterns: type `[!]` is non-empty + --> $DIR/empty-types.rs:353:11 + | +LL | match *slice_never {} + | ^^^^^^^^^^^^ + | + = note: the matched value is of type `[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *slice_never { +LL + _ => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:363:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:366:9 + | +LL | [_, _, _] => {} + | ^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:369:9 + | +LL | [_, ..] => {} + | ^^^^^^^ + +error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty + --> $DIR/empty-types.rs:383:11 + | +LL | match array_0_never {} + | ^^^^^^^^^^^^^ + | + = note: the matched value is of type `[!; 0]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match array_0_never { +LL + _ => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:390:9 + | +LL | _ => {} + | ^ + +error[E0004]: non-exhaustive patterns: `[]` not covered + --> $DIR/empty-types.rs:392:11 + | +LL | match array_0_never { + | ^^^^^^^^^^^^^ pattern `[]` not covered + | + = note: the matched value is of type `[!; 0]` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [..] if false => {}, +LL + [] => todo!() + | + +error: unreachable pattern + --> $DIR/empty-types.rs:411:9 + | +LL | Some(_) => {} + | ^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:416:9 + | +LL | Some(_a) => {} + | ^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:421:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:426:9 + | +LL | _a => {} + | ^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:598:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:601:9 + | +LL | _x => {} + | ^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:604:9 + | +LL | _ if false => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:607:9 + | +LL | _x if false => {} + | ^^ + +error: aborting due to 49 previous errors + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr new file mode 100644 index 00000000000..133a95a821b --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr @@ -0,0 +1,617 @@ +error: unreachable pattern + --> $DIR/empty-types.rs:47:9 + | +LL | _ => {} + | ^ + | +note: the lint level is defined here + --> $DIR/empty-types.rs:13:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:50:9 + | +LL | _x => {} + | ^^ + +error[E0004]: non-exhaustive patterns: type `&!` is non-empty + --> $DIR/empty-types.rs:54:11 + | +LL | match ref_never {} + | ^^^^^^^^^ + | + = note: the matched value is of type `&!` + = note: references are always considered inhabited +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match ref_never { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty + --> $DIR/empty-types.rs:66:11 + | +LL | match tuple_half_never {} + | ^^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `(u32, !)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match tuple_half_never { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty + --> $DIR/empty-types.rs:73:11 + | +LL | match tuple_never {} + | ^^^^^^^^^^^ + | + = note: the matched value is of type `(!, !)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match tuple_never { +LL + _ => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:83:9 + | +LL | _ => {} + | ^ + +error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered + --> $DIR/empty-types.rs:87:11 + | +LL | match res_u32_never {} + | ^^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered + | +note: `Result<u32, !>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result<u32, !>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ match res_u32_never { +LL + Ok(_) | Err(_) => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: `Err(_)` not covered + --> $DIR/empty-types.rs:89:11 + | +LL | match res_u32_never { + | ^^^^^^^^^^^^^ pattern `Err(_)` not covered + | +note: `Result<u32, !>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result<u32, !>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Ok(_) => {}, +LL + Err(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered + --> $DIR/empty-types.rs:97:11 + | +LL | match res_u32_never { + | ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered + | +note: `Result<u32, !>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result<u32, !>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Err(_) => {}, +LL ~ Ok(1_u32..=u32::MAX) => todo!() + | + +error[E0005]: refutable pattern in local binding + --> $DIR/empty-types.rs:102:9 + | +LL | let Ok(_x) = res_u32_never; + | ^^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Result<u32, !>` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Ok(_x) = res_u32_never else { todo!() }; + | ++++++++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/empty-types.rs:104:9 + | +LL | let Ok(_x) = res_u32_never.as_ref(); + | ^^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `Result<&u32, &!>` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Ok(_x) = res_u32_never.as_ref() else { todo!() }; + | ++++++++++++++++ + +error[E0005]: refutable pattern in local binding + --> $DIR/empty-types.rs:108:9 + | +LL | let Ok(_x) = &res_u32_never; + | ^^^^^^ pattern `&Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html + = note: the matched value is of type `&Result<u32, !>` +help: you might want to use `let else` to handle the variant that isn't matched + | +LL | let Ok(_x) = &res_u32_never else { todo!() }; + | ++++++++++++++++ + +error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered + --> $DIR/empty-types.rs:112:11 + | +LL | match result_never {} + | ^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered + | +note: `Result<!, !>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result<!, !>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ match result_never { +LL + Ok(_) | Err(_) => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: `Err(_)` not covered + --> $DIR/empty-types.rs:117:11 + | +LL | match result_never { + | ^^^^^^^^^^^^ pattern `Err(_)` not covered + | +note: `Result<!, !>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result<!, !>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL | Ok(_) => {}, Err(_) => todo!() + | +++++++++++++++++++ + +error: unreachable pattern + --> $DIR/empty-types.rs:136:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:139:13 + | +LL | _ if false => {} + | ^ + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/empty-types.rs:142:15 + | +LL | match opt_void { + | ^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option<Void>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<Void>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/empty-types.rs:161:15 + | +LL | match *ref_opt_void { + | ^^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option<Void>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<Void>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error: unreachable pattern + --> $DIR/empty-types.rs:204:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:209:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:214:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:219:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:225:13 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:284:9 + | +LL | _ => {} + | ^ + +error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty + --> $DIR/empty-types.rs:312:11 + | +LL | match *x {} + | ^^ + | + = note: the matched value is of type `(u32, !)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty + --> $DIR/empty-types.rs:314:11 + | +LL | match *x {} + | ^^ + | + = note: the matched value is of type `(!, !)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered + --> $DIR/empty-types.rs:316:11 + | +LL | match *x {} + | ^^ patterns `Ok(_)` and `Err(_)` not covered + | +note: `Result<!, !>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result<!, !>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ match *x { +LL + Ok(_) | Err(_) => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty + --> $DIR/empty-types.rs:318:11 + | +LL | match *x {} + | ^^ + | + = note: the matched value is of type `[!; 3]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *x { +LL + _ => todo!(), +LL ~ } + | + +error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty + --> $DIR/empty-types.rs:323:11 + | +LL | match slice_never {} + | ^^^^^^^^^^^ + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match slice_never { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered + --> $DIR/empty-types.rs:325:11 + | +LL | match slice_never { + | ^^^^^^^^^^^ pattern `&[_, ..]` not covered + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [] => {}, +LL + &[_, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered + --> $DIR/empty-types.rs:334:11 + | +LL | match slice_never { + | ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered + | + = note: the matched value is of type `&[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ [_, _, _, ..] => {}, +LL + &[] | &[_] | &[_, _] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered + --> $DIR/empty-types.rs:347:11 + | +LL | match slice_never { + | ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered + | + = note: the matched value is of type `&[!]` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms + | +LL ~ &[..] if false => {}, +LL + &[] | &[_, ..] => todo!() + | + +error[E0004]: non-exhaustive patterns: type `[!]` is non-empty + --> $DIR/empty-types.rs:353:11 + | +LL | match *slice_never {} + | ^^^^^^^^^^^^ + | + = note: the matched value is of type `[!]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *slice_never { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty + --> $DIR/empty-types.rs:360:11 + | +LL | match array_3_never {} + | ^^^^^^^^^^^^^ + | + = note: the matched value is of type `[!; 3]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match array_3_never { +LL + _ => todo!(), +LL + } + | + +error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty + --> $DIR/empty-types.rs:383:11 + | +LL | match array_0_never {} + | ^^^^^^^^^^^^^ + | + = note: the matched value is of type `[!; 0]` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match array_0_never { +LL + _ => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:390:9 + | +LL | _ => {} + | ^ + +error[E0004]: non-exhaustive patterns: `[]` not covered + --> $DIR/empty-types.rs:392:11 + | +LL | match array_0_never { + | ^^^^^^^^^^^^^ pattern `[]` not covered + | + = note: the matched value is of type `[!; 0]` + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ [..] if false => {}, +LL + [] => todo!() + | + +error[E0004]: non-exhaustive patterns: `&Some(_)` not covered + --> $DIR/empty-types.rs:446:11 + | +LL | match ref_opt_never { + | ^^^^^^^^^^^^^ pattern `&Some(_)` not covered + | +note: `Option<!>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `&Option<!>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ &None => {}, +LL + &Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/empty-types.rs:487:11 + | +LL | match *ref_opt_never { + | ^^^^^^^^^^^^^^ pattern `Some(_)` not covered + | +note: `Option<!>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<!>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Err(_)` not covered + --> $DIR/empty-types.rs:535:11 + | +LL | match *ref_res_never { + | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered + | +note: `Result<!, !>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result<!, !>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Ok(_) => {}, +LL + Err(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: `Err(_)` not covered + --> $DIR/empty-types.rs:546:11 + | +LL | match *ref_res_never { + | ^^^^^^^^^^^^^^ pattern `Err(_)` not covered + | +note: `Result<!, !>` defined here + --> $SRC_DIR/core/src/result.rs:LL:COL + ::: $SRC_DIR/core/src/result.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Result<!, !>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ Ok(_a) => {}, +LL + Err(_) => todo!() + | + +error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty + --> $DIR/empty-types.rs:565:11 + | +LL | match *ref_tuple_half_never {} + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `(u32, !)` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match *ref_tuple_half_never { +LL + _ => todo!(), +LL + } + | + +error: unreachable pattern + --> $DIR/empty-types.rs:598:9 + | +LL | _ => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:601:9 + | +LL | _x => {} + | ^^ + +error: unreachable pattern + --> $DIR/empty-types.rs:604:9 + | +LL | _ if false => {} + | ^ + +error: unreachable pattern + --> $DIR/empty-types.rs:607:9 + | +LL | _x if false => {} + | ^^ + +error[E0004]: non-exhaustive patterns: `&_` not covered + --> $DIR/empty-types.rs:631:11 + | +LL | match ref_never { + | ^^^^^^^^^ pattern `&_` not covered + | + = note: the matched value is of type `&!` + = note: references are always considered inhabited + = note: match arms with guards don't count towards exhaustivity +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ &_a if false => {}, +LL + &_ => todo!() + | + +error[E0004]: non-exhaustive patterns: `Some(_)` not covered + --> $DIR/empty-types.rs:659:11 + | +LL | match *x { + | ^^ pattern `Some(_)` not covered + | +note: `Option<Result<!, !>>` defined here + --> $SRC_DIR/core/src/option.rs:LL:COL + ::: $SRC_DIR/core/src/option.rs:LL:COL + | + = note: not covered + = note: the matched value is of type `Option<Result<!, !>>` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown + | +LL ~ None => {}, +LL + Some(_) => todo!() + | + +error: aborting due to 48 previous errors + +Some errors have detailed explanations: E0004, E0005. +For more information about an error, try `rustc --explain E0004`. diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs new file mode 100644 index 00000000000..1e1d23e446d --- /dev/null +++ b/tests/ui/pattern/usefulness/empty-types.rs @@ -0,0 +1,665 @@ +// revisions: normal exhaustive_patterns +// +// This tests correct handling of empty types in exhaustiveness checking. +// +// Most of the subtlety of this file happens in scrutinee places which are not required to hold +// valid data, namely dereferences and union field accesses. In these cases, empty arms can +// generally not be omitted, except with `exhaustive_patterns` which ignores this.. +#![feature(never_type)] +// This feature is useful to avoid `!` falling back to `()` all the time. +#![feature(never_type_fallback)] +#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))] +#![allow(dead_code, unreachable_code)] +#![deny(unreachable_patterns)] + +#[derive(Copy, Clone)] +enum Void {} + +/// A bunch of never situations that can't be normally constructed. +#[derive(Copy, Clone)] +struct NeverBundle { + never: !, + void: Void, + tuple_never: (!, !), + tuple_half_never: (u32, !), + array_3_never: [!; 3], + result_never: Result<!, !>, +} + +/// A simplified `MaybeUninit` to test union field accesses. +#[derive(Copy, Clone)] +union Uninit<T: Copy> { + value: T, + uninit: (), +} + +impl<T: Copy> Uninit<T> { + fn new() -> Self { + Self { uninit: () } + } +} + +// Simple cases of omitting empty arms, all with known_valid scrutinees. +fn basic(x: NeverBundle) { + let never: ! = x.never; + match never {} + match never { + _ => {} //~ ERROR unreachable pattern + } + match never { + _x => {} //~ ERROR unreachable pattern + } + + let ref_never: &! = &x.never; + match ref_never {} + //~^ ERROR non-empty + match ref_never { + // useful, reachable + _ => {} + } + match ref_never { + // useful, reachable + &_ => {} + } + + let tuple_half_never: (u32, !) = x.tuple_half_never; + match tuple_half_never {} + //[normal]~^ ERROR non-empty + match tuple_half_never { + (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + + let tuple_never: (!, !) = x.tuple_never; + match tuple_never {} + //[normal]~^ ERROR non-empty + match tuple_never { + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match tuple_never { + (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match tuple_never.0 {} + match tuple_never.0 { + _ => {} //~ ERROR unreachable pattern + } + + let res_u32_never: Result<u32, !> = Ok(0); + match res_u32_never {} + //~^ ERROR non-exhaustive + match res_u32_never { + //[normal]~^ ERROR non-exhaustive + Ok(_) => {} + } + match res_u32_never { + Ok(_) => {} + Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match res_u32_never { + //~^ ERROR non-exhaustive + Ok(0) => {} + Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + let Ok(_x) = res_u32_never; + //[normal]~^ ERROR refutable + let Ok(_x) = res_u32_never.as_ref(); + //~^ ERROR refutable + // Non-obvious difference: here there's an implicit dereference in the patterns, which makes the + // inner place !known_valid. `exhaustive_patterns` ignores this. + let Ok(_x) = &res_u32_never; + //[normal]~^ ERROR refutable + + let result_never: Result<!, !> = x.result_never; + match result_never {} + //[normal]~^ ERROR non-exhaustive + match result_never { + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match result_never { + //[normal]~^ ERROR non-exhaustive + Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match result_never { + Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match result_never { + Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } +} + +// Check for a few cases that `Void` and `!` are treated the same. +fn void_same_as_never(x: NeverBundle) { + unsafe { + match x.void {} + match x.void { + _ => {} //~ ERROR unreachable pattern + } + match x.void { + _ if false => {} //~ ERROR unreachable pattern + } + let opt_void: Option<Void> = None; + match opt_void { + //[normal]~^ ERROR non-exhaustive + None => {} + } + match opt_void { + None => {} + Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match opt_void { + None => {} + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + + let ref_void: &Void = &x.void; + match *ref_void {} + match *ref_void { + _ => {} + } + let ref_opt_void: &Option<Void> = &None; + match *ref_opt_void { + //[normal]~^ ERROR non-exhaustive + None => {} + } + match *ref_opt_void { + None => {} + Some(_) => {} + } + match *ref_opt_void { + None => {} + _ => {} + } + match *ref_opt_void { + None => {} + _a => {} + } + let union_void = Uninit::<Void>::new(); + match union_void.value {} + match union_void.value { + _ => {} + } + let ptr_void: *const Void = std::ptr::null(); + match *ptr_void {} + match *ptr_void { + _ => {} + } + } +} + +// Test if we correctly determine validity from the scrutinee expression. +fn invalid_scrutinees(x: NeverBundle) { + let ptr_never: *const ! = std::ptr::null(); + let never: ! = x.never; + let ref_never: &! = &never; + + struct NestedNeverBundle(NeverBundle); + let nested_x = NestedNeverBundle(x); + + // These should be considered known_valid and warn unreachable. + unsafe { + // A plain `!` value must be valid. + match never {} + match never { + _ => {} //~ ERROR unreachable pattern + } + // A block forces a copy. + match { *ptr_never } {} + match { *ptr_never } { + _ => {} //~ ERROR unreachable pattern + } + // This field access is not a dereference. + match x.never {} + match x.never { + _ => {} //~ ERROR unreachable pattern + } + // This nested field access is not a dereference. + match nested_x.0.never {} + match nested_x.0.never { + _ => {} //~ ERROR unreachable pattern + } + // Indexing is like a field access. This one does not access behind a reference. + let array_3_never: [!; 3] = x.array_3_never; + match array_3_never[0] {} + match array_3_never[0] { + _ => {} //~ ERROR unreachable pattern + } + } + + // These should be considered !known_valid and not warn unreachable. + unsafe { + // A pointer may point to a place with an invalid value. + match *ptr_never {} + match *ptr_never { + _ => {} + } + // A reference may point to a place with an invalid value. + match *ref_never {} + match *ref_never { + _ => {} + } + // This field access is a dereference. + let ref_x: &NeverBundle = &x; + match ref_x.never {} + match ref_x.never { + _ => {} + } + // This nested field access is a dereference. + let nested_ref_x: &NestedNeverBundle = &nested_x; + match nested_ref_x.0.never {} + match nested_ref_x.0.never { + _ => {} + } + // A cast does not load. + match (*ptr_never as Void) {} + match (*ptr_never as Void) { + _ => {} + } + // A union field may contain invalid data. + let union_never = Uninit::<!>::new(); + match union_never.value {} + match union_never.value { + _ => {} + } + // Indexing is like a field access. This one accesses behind a reference. + let slice_never: &[!] = &[]; + match slice_never[0] {} + match slice_never[0] { + _ => {} + } + } +} + +// Test we correctly track validity as we dig into patterns. Validity changes when we go under a +// dereference or a union field access, and it otherwise preserved. +fn nested_validity_tracking(bundle: NeverBundle) { + let never: ! = bundle.never; + let ref_never: &! = &never; + let tuple_never: (!, !) = bundle.tuple_never; + let result_never: Result<!, !> = bundle.result_never; + let union_never = Uninit::<!>::new(); + + // These should be considered known_valid and warn unreachable. + match never { + _ => {} //~ ERROR unreachable pattern + } + match tuple_never { + (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match result_never { + Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + + // These should be considered !known_valid and not warn unreachable. + match ref_never { + &_ => {} + } + match union_never { + Uninit { value: _ } => {} + } +} + +// Test we don't allow empty matches on empty types if the scrutinee is `!known_valid`. +fn invalid_empty_match(bundle: NeverBundle) { + // We allow these two for backwards-compability. + let x: &! = &bundle.never; + match *x {} + let x: &Void = &bundle.void; + match *x {} + + let x: &(u32, !) = &bundle.tuple_half_never; + match *x {} //[normal]~ ERROR non-exhaustive + let x: &(!, !) = &bundle.tuple_never; + match *x {} //[normal]~ ERROR non-exhaustive + let x: &Result<!, !> = &bundle.result_never; + match *x {} //[normal]~ ERROR non-exhaustive + let x: &[!; 3] = &bundle.array_3_never; + match *x {} //[normal]~ ERROR non-exhaustive +} + +fn arrays_and_slices(x: NeverBundle) { + let slice_never: &[!] = &[]; + match slice_never {} + //~^ ERROR non-empty + match slice_never { + //[normal]~^ ERROR not covered + [] => {} + } + match slice_never { + [] => {} + [_] => {} + [_, _, ..] => {} + } + match slice_never { + //[normal]~^ ERROR `&[]`, `&[_]` and `&[_, _]` not covered + //[exhaustive_patterns]~^^ ERROR `&[]` not covered + [_, _, _, ..] => {} + } + match slice_never { + [] => {} + _ => {} + } + match slice_never { + [] => {} + _x => {} + } + match slice_never { + //[normal]~^ ERROR `&[]` and `&[_, ..]` not covered + //[exhaustive_patterns]~^^ ERROR `&[]` not covered + &[..] if false => {} + } + + match *slice_never {} + //~^ ERROR non-empty + match *slice_never { + _ => {} + } + + let array_3_never: [!; 3] = x.array_3_never; + match array_3_never {} + //[normal]~^ ERROR non-empty + match array_3_never { + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match array_3_never { + [_, _, _] => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match array_3_never { + [_, ..] => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + + let ref_array_3_never: &[!; 3] = &array_3_never; + match ref_array_3_never { + // useful, reachable + &[_, _, _] => {} + } + match ref_array_3_never { + // useful, !reachable + &[_x, _, _] => {} + } + + let array_0_never: [!; 0] = []; + match array_0_never {} + //~^ ERROR non-empty + match array_0_never { + [] => {} + } + match array_0_never { + [] => {} + _ => {} //~ ERROR unreachable pattern + } + match array_0_never { + //~^ ERROR `[]` not covered + [..] if false => {} + } +} + +// The difference between `_` and `_a` patterns is that `_a` loads the value. In case of an empty +// type, this asserts validity of the value, and thus the binding is unreachable. We don't yet +// distinguish these cases since we don't lint "unreachable" on `useful && !reachable` arms. +// Once/if never patterns are a thing, we can warn that the `_a` cases should be never patterns. +fn bindings(x: NeverBundle) { + let opt_never: Option<!> = None; + let ref_never: &! = &x.never; + let ref_opt_never: &Option<!> = &None; + + // On a known_valid place. + match opt_never { + None => {} + // !useful, !reachable + Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match opt_never { + None => {} + // !useful, !reachable + Some(_a) => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match opt_never { + None => {} + // !useful, !reachable + _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + match opt_never { + None => {} + // !useful, !reachable + _a => {} //[exhaustive_patterns]~ ERROR unreachable pattern + } + + // The scrutinee is known_valid, but under the `&` isn't anymore. + match ref_never { + // useful, reachable + _ => {} + } + match ref_never { + // useful, reachable + &_ => {} + } + match ref_never { + // useful, reachable + _a => {} + } + match ref_never { + // useful, !reachable + &_a => {} + } + match ref_opt_never { + //[normal]~^ ERROR non-exhaustive + &None => {} + } + match ref_opt_never { + &None => {} + // useful, reachable + _ => {} + } + match ref_opt_never { + &None => {} + // useful, reachable + _a => {} + } + match ref_opt_never { + &None => {} + // useful, reachable + &_ => {} + } + match ref_opt_never { + &None => {} + // useful, !reachable + &_a => {} + } + + // On a !known_valid place. + match *ref_never {} + match *ref_never { + // useful, reachable + _ => {} + } + match *ref_never { + // useful, !reachable + _a => {} + } + // This is equivalent to `match ref_never { _a => {} }`. In other words, it asserts validity of + // `ref_never` but says nothing of the data at `*ref_never`. + match *ref_never { + // useful, reachable + ref _a => {} + } + match *ref_opt_never { + //[normal]~^ ERROR non-exhaustive + None => {} + } + match *ref_opt_never { + None => {} + // useful, reachable + Some(_) => {} + } + match *ref_opt_never { + None => {} + // useful, !reachable + Some(_a) => {} + } + match *ref_opt_never { + None => {} + // useful, reachable + _ => {} + } + match *ref_opt_never { + None => {} + // useful, !reachable + _a => {} + } + match *ref_opt_never { + None => {} + // useful, !reachable + _a @ Some(_) => {} + } + // This is equivalent to `match ref_opt_never { None => {}, _a => {} }`. In other words, it + // asserts validity of `ref_opt_never` but says nothing of the data at `*ref_opt_never`. + match *ref_opt_never { + None => {} + // useful, reachable + ref _a => {} + } + match *ref_opt_never { + None => {} + // useful, reachable + ref _a @ Some(_) => {} + } + match *ref_opt_never { + None => {} + // useful, !reachable + ref _a @ Some(_b) => {} + } + + let ref_res_never: &Result<!, !> = &x.result_never; + match *ref_res_never { + //[normal]~^ ERROR non-exhaustive + // useful, reachable + Ok(_) => {} + } + match *ref_res_never { + // useful, reachable + Ok(_) => {} + // useful, reachable + _ => {} + } + match *ref_res_never { + //[normal]~^ ERROR non-exhaustive + // useful, !reachable + Ok(_a) => {} + } + match *ref_res_never { + // useful, !reachable + Ok(_a) => {} + // useful, reachable + _ => {} + } + match *ref_res_never { + // useful, !reachable + Ok(_a) => {} + // useful, reachable + Err(_) => {} + } + + let ref_tuple_half_never: &(u32, !) = &x.tuple_half_never; + match *ref_tuple_half_never {} + //[normal]~^ ERROR non-empty + match *ref_tuple_half_never { + // useful, reachable + (_, _) => {} + } + match *ref_tuple_half_never { + // useful, reachable + (_x, _) => {} + } + match *ref_tuple_half_never { + // useful, !reachable + (_, _x) => {} + } + match *ref_tuple_half_never { + // useful, !reachable + (0, _x) => {} + // useful, reachable + (1.., _) => {} + } +} + +// When we execute the condition for a guard we loads from all bindings. This asserts validity at +// all places with bindings. Surprisingly this can make subsequent arms unreachable. We choose to +// not detect this in exhaustiveness because this is rather subtle. With never patterns, we would +// recommend using a never pattern instead. +fn guards_and_validity(x: NeverBundle) { + let never: ! = x.never; + let ref_never: &! = &never; + + // Basic guard behavior when known_valid. + match never {} + match never { + _ => {} //~ ERROR unreachable pattern + } + match never { + _x => {} //~ ERROR unreachable pattern + } + match never { + _ if false => {} //~ ERROR unreachable pattern + } + match never { + _x if false => {} //~ ERROR unreachable pattern + } + + // If the pattern under the guard doesn't load, all is normal. + match *ref_never { + // useful, reachable + _ if false => {} + // useful, reachable + _ => {} + } + // Now the madness commences. The guard caused a load of the value thus asserting validity. So + // there's no invalid value for `_` to catch. So the second pattern is unreachable despite the + // guard not being taken. + match *ref_never { + // useful, !reachable + _a if false => {} + // !useful, !reachable + _ => {} + } + // The above still applies to the implicit `_` pattern used for exhaustiveness. + match *ref_never { + // useful, !reachable + _a if false => {} + } + match ref_never { + //[normal]~^ ERROR non-exhaustive + // useful, !reachable + &_a if false => {} + } + + // Same but with subpatterns. + let ref_result_never: &Result<!, !> = &x.result_never; + match *ref_result_never { + // useful, !reachable + Ok(_x) if false => {} + // !useful, !reachable + Ok(_) => {} + // useful, !reachable + Err(_) => {} + } + let ref_tuple_never: &(!, !) = &x.tuple_never; + match *ref_tuple_never { + // useful, !reachable + (_, _x) if false => {} + // !useful, !reachable + (_, _) => {} + } +} + +fn diagnostics_subtlety(x: NeverBundle) { + // Regression test for diagnostics: don't report `Some(Ok(_))` and `Some(Err(_))`. + let x: &Option<Result<!, !>> = &None; + match *x { + //[normal]~^ ERROR `Some(_)` not covered + None => {} + } +} + +fn main() {} diff --git a/tests/ui/pattern/usefulness/slice_of_empty.rs b/tests/ui/pattern/usefulness/slice_of_empty.rs index fe068871195..3cbd0eba57f 100644 --- a/tests/ui/pattern/usefulness/slice_of_empty.rs +++ b/tests/ui/pattern/usefulness/slice_of_empty.rs @@ -11,12 +11,12 @@ fn foo(nevers: &[!]) { match nevers { &[] => (), - &[_] => (), //~ ERROR unreachable pattern - &[_, _, ..] => (), //~ ERROR unreachable pattern + &[_] => (), + &[_, _, ..] => (), }; match nevers { //~^ ERROR non-exhaustive patterns: `&[]` not covered - &[_] => (), //~ ERROR unreachable pattern + &[_] => (), }; } diff --git a/tests/ui/pattern/usefulness/slice_of_empty.stderr b/tests/ui/pattern/usefulness/slice_of_empty.stderr index 07bb6b3a67d..d56360d4cec 100644 --- a/tests/ui/pattern/usefulness/slice_of_empty.stderr +++ b/tests/ui/pattern/usefulness/slice_of_empty.stderr @@ -1,27 +1,3 @@ -error: unreachable pattern - --> $DIR/slice_of_empty.rs:14:9 - | -LL | &[_] => (), - | ^^^^ - | -note: the lint level is defined here - --> $DIR/slice_of_empty.rs:3:9 - | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - -error: unreachable pattern - --> $DIR/slice_of_empty.rs:15:9 - | -LL | &[_, _, ..] => (), - | ^^^^^^^^^^^ - -error: unreachable pattern - --> $DIR/slice_of_empty.rs:20:9 - | -LL | &[_] => (), - | ^^^^ - error[E0004]: non-exhaustive patterns: `&[]` not covered --> $DIR/slice_of_empty.rs:18:11 | @@ -31,9 +7,10 @@ LL | match nevers { = note: the matched value is of type `&[!]` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | &[_] => (), &[] => todo!(), - | ++++++++++++++++ +LL ~ &[_] => (), +LL ~ &[] => todo!(), + | -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/privacy/auxiliary/issue-117997.rs b/tests/ui/privacy/auxiliary/issue-117997.rs new file mode 100644 index 00000000000..6f71cc2ba35 --- /dev/null +++ b/tests/ui/privacy/auxiliary/issue-117997.rs @@ -0,0 +1,35 @@ +// no-prefer-dynamic +// compile-flags: --crate-type=rlib + +pub use impl_mod::TraitImplementer as Implementer; + +pub use trait_mod::get_assoc; + +mod impl_mod { + use crate::trait_mod::TraitWithAssocType; + + pub struct TraitImplementer {} + pub struct AssociatedType {} + + impl AssociatedType { + pub fn method_on_assoc(&self) -> i32 { + todo!() + } + } + + impl TraitWithAssocType for TraitImplementer { + type AssocType = AssociatedType; + } +} + +mod trait_mod { + use crate::Implementer; + + pub fn get_assoc() -> <Implementer as TraitWithAssocType>::AssocType { + todo!() + } + + pub trait TraitWithAssocType { + type AssocType; + } +} diff --git a/tests/ui/privacy/issue-117997.rs b/tests/ui/privacy/issue-117997.rs new file mode 100644 index 00000000000..d8284ef2997 --- /dev/null +++ b/tests/ui/privacy/issue-117997.rs @@ -0,0 +1,8 @@ +// aux-build:issue-117997.rs +// build-pass + +extern crate issue_117997; + +pub fn main() { + issue_117997::get_assoc().method_on_assoc(); +} diff --git a/tests/ui/privacy/private-in-public.rs b/tests/ui/privacy/private-in-public.rs index 3fff2d51710..7b8e0fbe6b6 100644 --- a/tests/ui/privacy/private-in-public.rs +++ b/tests/ui/privacy/private-in-public.rs @@ -106,6 +106,7 @@ mod aliases_pub { pub fn f3(arg: <Priv as PrivTr>::Assoc) {} //~^ WARNING type `aliases_pub::Priv` is more private than the item `aliases_pub::f3` //~| WARNING associated type `aliases_pub::PrivTr::Assoc` is more private than the item `aliases_pub::f3` + //~^^^ WARNING trait `aliases_pub::PrivTr` is more private than the item `aliases_pub::f3` impl PrivUseAlias { pub fn f(arg: Priv) {} @@ -135,6 +136,7 @@ mod aliases_priv { pub fn f3(arg: <Priv as PrivTr>::Assoc) {} //~^ WARNING type `aliases_priv::Priv` is more private than the item `aliases_priv::f3` //~| WARNING associated type `aliases_priv::PrivTr::Assoc` is more private than the item `aliases_priv::f3` + //~^^^ WARNING trait `aliases_priv::PrivTr` is more private than the item `aliases_priv::f3` } mod aliases_params { diff --git a/tests/ui/privacy/private-in-public.stderr b/tests/ui/privacy/private-in-public.stderr index 49cc2e19bf0..ff3061337ff 100644 --- a/tests/ui/privacy/private-in-public.stderr +++ b/tests/ui/privacy/private-in-public.stderr @@ -288,6 +288,18 @@ note: but associated type `aliases_pub::PrivTr::Assoc` is only usable at visibil LL | type Assoc = m::Pub3; | ^^^^^^^^^^ +warning: trait `aliases_pub::PrivTr` is more private than the item `aliases_pub::f3` + --> $DIR/private-in-public.rs:106:5 + | +LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_pub::f3` is reachable at visibility `pub(crate)` + | +note: but trait `aliases_pub::PrivTr` is only usable at visibility `pub(self)` + --> $DIR/private-in-public.rs:100:5 + | +LL | trait PrivTr { + | ^^^^^^^^^^^^ + warning: type `aliases_pub::Priv` is more private than the item `aliases_pub::f3` --> $DIR/private-in-public.rs:106:5 | @@ -301,76 +313,88 @@ LL | struct Priv; | ^^^^^^^^^^^ warning: type `Priv1` is more private than the item `aliases_priv::f1` - --> $DIR/private-in-public.rs:133:5 + --> $DIR/private-in-public.rs:134:5 | LL | pub fn f1(arg: PrivUseAlias) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f1` is reachable at visibility `pub(crate)` | note: but type `Priv1` is only usable at visibility `pub(self)` - --> $DIR/private-in-public.rs:118:5 + --> $DIR/private-in-public.rs:119:5 | LL | struct Priv1; | ^^^^^^^^^^^^ warning: type `Priv2` is more private than the item `aliases_priv::f2` - --> $DIR/private-in-public.rs:134:5 + --> $DIR/private-in-public.rs:135:5 | LL | pub fn f2(arg: PrivAlias) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f2` is reachable at visibility `pub(crate)` | note: but type `Priv2` is only usable at visibility `pub(self)` - --> $DIR/private-in-public.rs:119:5 + --> $DIR/private-in-public.rs:120:5 | LL | struct Priv2; | ^^^^^^^^^^^^ warning: associated type `aliases_priv::PrivTr::Assoc` is more private than the item `aliases_priv::f3` - --> $DIR/private-in-public.rs:135:5 + --> $DIR/private-in-public.rs:136:5 | LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f3` is reachable at visibility `pub(crate)` | note: but associated type `aliases_priv::PrivTr::Assoc` is only usable at visibility `pub(self)` - --> $DIR/private-in-public.rs:129:9 + --> $DIR/private-in-public.rs:130:9 | LL | type Assoc = Priv3; | ^^^^^^^^^^ +warning: trait `aliases_priv::PrivTr` is more private than the item `aliases_priv::f3` + --> $DIR/private-in-public.rs:136:5 + | +LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f3` is reachable at visibility `pub(crate)` + | +note: but trait `aliases_priv::PrivTr` is only usable at visibility `pub(self)` + --> $DIR/private-in-public.rs:129:5 + | +LL | trait PrivTr { + | ^^^^^^^^^^^^ + warning: type `aliases_priv::Priv` is more private than the item `aliases_priv::f3` - --> $DIR/private-in-public.rs:135:5 + --> $DIR/private-in-public.rs:136:5 | LL | pub fn f3(arg: <Priv as PrivTr>::Assoc) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f3` is reachable at visibility `pub(crate)` | note: but type `aliases_priv::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public.rs:116:5 + --> $DIR/private-in-public.rs:117:5 | LL | struct Priv; | ^^^^^^^^^^^ warning: type `aliases_params::Priv` is more private than the item `aliases_params::f2` - --> $DIR/private-in-public.rs:145:5 + --> $DIR/private-in-public.rs:147:5 | LL | pub fn f2(arg: PrivAliasGeneric) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_params::f2` is reachable at visibility `pub(crate)` | note: but type `aliases_params::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public.rs:141:5 + --> $DIR/private-in-public.rs:143:5 | LL | struct Priv; | ^^^^^^^^^^^ warning: type `aliases_params::Priv` is more private than the item `aliases_params::f3` - --> $DIR/private-in-public.rs:147:5 + --> $DIR/private-in-public.rs:149:5 | LL | pub fn f3(arg: Result<u8>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_params::f3` is reachable at visibility `pub(crate)` | note: but type `aliases_params::Priv` is only usable at visibility `pub(self)` - --> $DIR/private-in-public.rs:141:5 + --> $DIR/private-in-public.rs:143:5 | LL | struct Priv; | ^^^^^^^^^^^ -warning: 31 warnings emitted +warning: 33 warnings emitted diff --git a/tests/ui/range/issue-73553-misinterp-range-literal.stderr b/tests/ui/range/issue-73553-misinterp-range-literal.stderr index 52efa241d0b..15e55708c37 100644 --- a/tests/ui/range/issue-73553-misinterp-range-literal.stderr +++ b/tests/ui/range/issue-73553-misinterp-range-literal.stderr @@ -6,8 +6,8 @@ LL | demo(tell(1)..tell(10)); | | | arguments to this function are incorrect | - = note: expected reference `&std::ops::Range<usize>` - found struct `std::ops::Range<usize>` + = note: expected reference `&std::ops::Range<_>` + found struct `std::ops::Range<_>` note: function defined here --> $DIR/issue-73553-misinterp-range-literal.rs:3:4 | diff --git a/tests/ui/regions/issue-101280.stderr b/tests/ui/regions/issue-101280.stderr index 70953808b81..48deb99494b 100644 --- a/tests/ui/regions/issue-101280.stderr +++ b/tests/ui/regions/issue-101280.stderr @@ -6,8 +6,8 @@ LL | fn f<'r>(f: fn(Cell<(&'r i32, &i32)>)) -> Ty { LL | f | ^ one type is more general than the other | - = note: expected fn pointer `for<'r> fn(Cell<(&'r i32, &'r i32)>)` - found fn pointer `for<'a> fn(Cell<(&'r i32, &'a i32)>)` + = note: expected fn pointer `for<'r> fn(Cell<(&'r _, &'r _)>)` + found fn pointer `for<'a> fn(Cell<(&'r _, &'a _)>)` error: aborting due to 1 previous error diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr index 03d5a0be723..d8269514bef 100644 --- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr @@ -6,8 +6,8 @@ LL | let _: fn(&mut &isize, &mut &isize) = a; | | | expected due to this | - = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)` - found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}` + = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` + found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` error: aborting due to 1 previous error diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr index 250571f1556..e383f352b9e 100644 --- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr +++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr @@ -6,8 +6,8 @@ LL | let _: fn(&mut &isize, &mut &isize, &mut &isize) = a; | | | expected due to this | - = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)` - found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}` + = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)` + found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}` error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr index 31dd7efe067..989e91c702b 100644 --- a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr +++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr @@ -6,8 +6,8 @@ LL | let _: fn(&mut &isize, &mut &isize) = a; | | | expected due to this | - = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)` - found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}` + = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)` + found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}` error: aborting due to 1 previous error diff --git a/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr b/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr index c805c9eb125..6e44c280f75 100644 --- a/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr +++ b/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr @@ -62,8 +62,8 @@ LL | Opts::A(ref mut i) | Opts::B(ref i) => {} | | | first introduced with type `&mut isize` here | - = note: expected mutable reference `&mut isize` - found reference `&isize` + = note: expected mutable reference `&mut _` + found reference `&_` = note: in the same arm, a binding must have the same type in all alternatives error: aborting due to 6 previous errors diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs new file mode 100644 index 00000000000..e298112244a --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs @@ -0,0 +1,33 @@ +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum Void {} + +fn main() {} + +macro_rules! never { + () => { ! } +} + +fn no_arms_or_guards(x: Void) { + match None::<Void> { + Some(!) => {} + //~^ ERROR a never pattern is always unreachable + None => {} + } + match None::<Void> { + Some(!) if true, + //~^ ERROR guard on a never pattern + None => {} + } + match None::<Void> { + Some(!) if true => {} + //~^ ERROR a never pattern is always unreachable + None => {} + } + match None::<Void> { + Some(never!()) => {}, + //~^ ERROR a never pattern is always unreachable + None => {} + } +} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr new file mode 100644 index 00000000000..bfbc7a1b534 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr @@ -0,0 +1,35 @@ +error: a never pattern is always unreachable + --> $DIR/check.rs:14:20 + | +LL | Some(!) => {} + | ^^ + | | + | this will never be executed + | help: remove this expression + +error: a guard on a never pattern will never be run + --> $DIR/check.rs:19:20 + | +LL | Some(!) if true, + | ^^^^ help: remove this guard + +error: a never pattern is always unreachable + --> $DIR/check.rs:24:28 + | +LL | Some(!) if true => {} + | ^^ + | | + | this will never be executed + | help: remove this expression + +error: a never pattern is always unreachable + --> $DIR/check.rs:29:27 + | +LL | Some(never!()) => {}, + | ^^ + | | + | this will never be executed + | help: remove this expression + +error: aborting due to 4 previous errors + diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs new file mode 100644 index 00000000000..1b23e60e0ca --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs @@ -0,0 +1,71 @@ +#![feature(never_patterns)] +#![allow(incomplete_features)] + +enum Void {} + +fn main() {} + +macro_rules! never { + () => { ! } +} + +fn parse(x: Void) { + match None::<Void> { + None => {} + Some(!), + } + match None::<Void> { + Some(!), + None => {} + } + match None::<Void> { + None => {} + Some(!) + } + match None::<Void> { + Some(!) + //~^ ERROR expected `,` following `match` arm + None => {} + } + match None::<Void> { + Some(!) if true + //~^ ERROR expected `,` following `match` arm + //~| ERROR guard on a never pattern + None => {} + } + match None::<Void> { + Some(!) if true, + //~^ ERROR guard on a never pattern + None => {} + } + match None::<Void> { + Some(!) <= + //~^ ERROR expected one of + } + match x { + never!(), + } + match x { + never!() if true, + //~^ ERROR guard on a never pattern + } + match x { + never!() + } + match &x { + &never!(), + } + match None::<Void> { + Some(never!()), + None => {} + } + match x { ! } + match &x { &! } + + let res: Result<bool, Void> = Ok(false); + let Ok(_) = res; + let Ok(_) | Err(!) = &res; // Disallowed; see #82048. + //~^ ERROR top-level or-patterns are not allowed in `let` bindings + let (Ok(_) | Err(!)) = &res; + let (Ok(_) | Err(&!)) = res.as_ref(); +} diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr new file mode 100644 index 00000000000..e81a13a3967 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr @@ -0,0 +1,44 @@ +error: expected `,` following `match` arm + --> $DIR/parse.rs:26:16 + | +LL | Some(!) + | ^ help: missing a comma here to end this `match` arm: `,` + +error: expected `,` following `match` arm + --> $DIR/parse.rs:31:24 + | +LL | Some(!) if true + | ^ help: missing a comma here to end this `match` arm: `,` + +error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `<=` + --> $DIR/parse.rs:42:17 + | +LL | Some(!) <= + | ^^ expected one of `,`, `=>`, `if`, `|`, or `}` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/parse.rs:67:9 + | +LL | let Ok(_) | Err(!) = &res; // Disallowed; see #82048. + | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(_) | Err(!))` + +error: a guard on a never pattern will never be run + --> $DIR/parse.rs:31:20 + | +LL | Some(!) if true + | ^^^^ help: remove this guard + +error: a guard on a never pattern will never be run + --> $DIR/parse.rs:37:20 + | +LL | Some(!) if true, + | ^^^^ help: remove this guard + +error: a guard on a never pattern will never be run + --> $DIR/parse.rs:49:21 + | +LL | never!() if true, + | ^^^^ help: remove this guard + +error: aborting due to 7 previous errors + diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr index 181f57899a9..970a9c151c1 100644 --- a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr +++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr @@ -6,8 +6,8 @@ LL | match &s { LL | "abc" => true, | ^^^^^ expected `&&str`, found `&str` | - = note: expected reference `&&str` - found reference `&'static str` + = note: expected reference `&&_` + found reference `&'static _` error[E0308]: mismatched types --> $DIR/lit.rs:16:9 diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr index 61aae850a94..86f2d9b6ec8 100644 --- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr +++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | fn y(&self, y: f64) -> Self { P{y, .. self.clone() } } | ^^^^^^^^^^^^ expected `P<T>`, found `&P<T>` | - = note: expected struct `P<T>` - found reference `&P<T>` + = note: expected struct `P<_>` + found reference `&P<_>` error: aborting due to 1 previous error diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs index 2c6fd83484f..2a2e8cec3f0 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs @@ -1,3 +1,5 @@ +// check-pass + #![crate_type = "lib"] #![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs)] #![feature(fundamental)] @@ -6,8 +8,6 @@ #![no_std] #![no_core] -// known-bug: #110395 - #[lang = "sized"] trait Sized {} #[lang = "copy"] diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr deleted file mode 100644 index 3c1e6dda85c..00000000000 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0493]: destructor of `Self` cannot be evaluated at compile-time - --> $DIR/minicore.rs:501:9 - | -LL | *self = source.clone() - | ^^^^^ - | | - | the destructor for this type cannot be evaluated in constant functions - | value is dropped here - -error[E0493]: destructor of `T` cannot be evaluated at compile-time - --> $DIR/minicore.rs:511:35 - | -LL | const fn drop<T: ~const Destruct>(_: T) {} - | ^ - value is dropped here - | | - | the destructor for this type cannot be evaluated in constant functions - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0493`. diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs index a7e36b2233e..e20ca50b88f 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs Binary files differdiff --git a/tests/ui/simd/masked-load-store-build-fail.rs b/tests/ui/simd/masked-load-store-build-fail.rs new file mode 100644 index 00000000000..9b79b3bd6ea --- /dev/null +++ b/tests/ui/simd/masked-load-store-build-fail.rs @@ -0,0 +1,74 @@ +// build-fail +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T; + fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> (); +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd<T, const N: usize>([T; N]); + +fn main() { + unsafe { + let mut arr = [4u8, 5, 6, 7]; + let default = Simd::<u8, 4>([9; 4]); + + simd_masked_load( + Simd::<i8, 8>([-1, 0, -1, -1, 0, 0, 0, 0]), + arr.as_ptr(), + default + ); + //~^^^^^ ERROR expected third argument with length 8 (same as input type `Simd<i8, 8>`), found `Simd<u8, 4>` with length 4 + + simd_masked_load( + Simd::<i8, 4>([-1, 0, -1, -1]), + arr.as_ptr() as *const i8, + default + ); + //~^^^^^ ERROR expected element type `u8` of second argument `*const i8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*_ u8` + + simd_masked_load( + Simd::<i8, 4>([-1, 0, -1, -1]), + arr.as_ptr(), + Simd::<u32, 4>([9; 4]) + ); + //~^^^^^ ERROR expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*_ u32` + + simd_masked_load( + Simd::<u8, 4>([1, 0, 1, 1]), + arr.as_ptr(), + default + ); + //~^^^^^ ERROR expected element type `u8` of third argument `Simd<u8, 4>` to be a signed integer type + + simd_masked_store( + Simd([-1i8; 4]), + arr.as_ptr(), + Simd([5u32; 4]) + ); + //~^^^^^ ERROR expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*mut u32` + + simd_masked_store( + Simd([-1i8; 4]), + arr.as_ptr(), + Simd([5u8; 4]) + ); + //~^^^^^ ERROR expected element type `u8` of second argument `*const u8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*mut u8` + + simd_masked_store( + Simd([-1i8; 4]), + arr.as_mut_ptr(), + Simd([5u8; 2]) + ); + //~^^^^^ ERROR expected third argument with length 4 (same as input type `Simd<i8, 4>`), found `Simd<u8, 2>` with length 2 + + simd_masked_store( + Simd([1u32; 4]), + arr.as_mut_ptr(), + Simd([5u8; 4]) + ); + //~^^^^^ ERROR expected element type `u8` of third argument `Simd<u32, 4>` to be a signed integer type + } +} diff --git a/tests/ui/simd/masked-load-store-build-fail.stderr b/tests/ui/simd/masked-load-store-build-fail.stderr new file mode 100644 index 00000000000..59af83fe0e8 --- /dev/null +++ b/tests/ui/simd/masked-load-store-build-fail.stderr @@ -0,0 +1,83 @@ +error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected third argument with length 8 (same as input type `Simd<i8, 8>`), found `Simd<u8, 4>` with length 4 + --> $DIR/masked-load-store-build-fail.rs:18:9 + | +LL | / simd_masked_load( +LL | | Simd::<i8, 8>([-1, 0, -1, -1, 0, 0, 0, 0]), +LL | | arr.as_ptr(), +LL | | default +LL | | ); + | |_________^ + +error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u8` of second argument `*const i8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*_ u8` + --> $DIR/masked-load-store-build-fail.rs:25:9 + | +LL | / simd_masked_load( +LL | | Simd::<i8, 4>([-1, 0, -1, -1]), +LL | | arr.as_ptr() as *const i8, +LL | | default +LL | | ); + | |_________^ + +error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*_ u32` + --> $DIR/masked-load-store-build-fail.rs:32:9 + | +LL | / simd_masked_load( +LL | | Simd::<i8, 4>([-1, 0, -1, -1]), +LL | | arr.as_ptr(), +LL | | Simd::<u32, 4>([9; 4]) +LL | | ); + | |_________^ + +error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u8` of third argument `Simd<u8, 4>` to be a signed integer type + --> $DIR/masked-load-store-build-fail.rs:39:9 + | +LL | / simd_masked_load( +LL | | Simd::<u8, 4>([1, 0, 1, 1]), +LL | | arr.as_ptr(), +LL | | default +LL | | ); + | |_________^ + +error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*mut u32` + --> $DIR/masked-load-store-build-fail.rs:46:9 + | +LL | / simd_masked_store( +LL | | Simd([-1i8; 4]), +LL | | arr.as_ptr(), +LL | | Simd([5u32; 4]) +LL | | ); + | |_________^ + +error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u8` of second argument `*const u8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*mut u8` + --> $DIR/masked-load-store-build-fail.rs:53:9 + | +LL | / simd_masked_store( +LL | | Simd([-1i8; 4]), +LL | | arr.as_ptr(), +LL | | Simd([5u8; 4]) +LL | | ); + | |_________^ + +error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected third argument with length 4 (same as input type `Simd<i8, 4>`), found `Simd<u8, 2>` with length 2 + --> $DIR/masked-load-store-build-fail.rs:60:9 + | +LL | / simd_masked_store( +LL | | Simd([-1i8; 4]), +LL | | arr.as_mut_ptr(), +LL | | Simd([5u8; 2]) +LL | | ); + | |_________^ + +error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u8` of third argument `Simd<u32, 4>` to be a signed integer type + --> $DIR/masked-load-store-build-fail.rs:67:9 + | +LL | / simd_masked_store( +LL | | Simd([1u32; 4]), +LL | | arr.as_mut_ptr(), +LL | | Simd([5u8; 4]) +LL | | ); + | |_________^ + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0511`. diff --git a/tests/ui/simd/masked-load-store-check-fail.rs b/tests/ui/simd/masked-load-store-check-fail.rs new file mode 100644 index 00000000000..d4b35e211c8 --- /dev/null +++ b/tests/ui/simd/masked-load-store-check-fail.rs @@ -0,0 +1,32 @@ +// check-fail +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T; + fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> (); +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd<T, const N: usize>([T; N]); + +fn main() { + unsafe { + let mut arr = [4u8, 5, 6, 7]; + let default = Simd::<u8, 4>([9; 4]); + + let _x: Simd<u8, 2> = simd_masked_load( + Simd::<i8, 4>([-1, 0, -1, -1]), + arr.as_ptr(), + Simd::<u8, 4>([9; 4]) + ); + //~^^ ERROR mismatched types + + let _x: Simd<u32, 4> = simd_masked_load( + Simd::<u8, 4>([1, 0, 1, 1]), + arr.as_ptr(), + default + ); + //~^^ ERROR mismatched types + } +} diff --git a/tests/ui/simd/masked-load-store-check-fail.stderr b/tests/ui/simd/masked-load-store-check-fail.stderr new file mode 100644 index 00000000000..5d205d607c9 --- /dev/null +++ b/tests/ui/simd/masked-load-store-check-fail.stderr @@ -0,0 +1,59 @@ +error[E0308]: mismatched types + --> $DIR/masked-load-store-check-fail.rs:21:13 + | +LL | let _x: Simd<u8, 2> = simd_masked_load( + | ---------------- arguments to this function are incorrect +... +LL | Simd::<u8, 4>([9; 4]) + | ^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4` + | + = note: expected struct `Simd<_, 2>` + found struct `Simd<_, 4>` +help: the return type of this call is `Simd<u8, 4>` due to the type of the argument passed + --> $DIR/masked-load-store-check-fail.rs:18:31 + | +LL | let _x: Simd<u8, 2> = simd_masked_load( + | _______________________________^ +LL | | Simd::<i8, 4>([-1, 0, -1, -1]), +LL | | arr.as_ptr(), +LL | | Simd::<u8, 4>([9; 4]) + | | --------------------- this argument influences the return type of `simd_masked_load` +LL | | ); + | |_________^ +note: function defined here + --> $DIR/masked-load-store-check-fail.rs:5:8 + | +LL | fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T; + | ^^^^^^^^^^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/masked-load-store-check-fail.rs:28:13 + | +LL | let _x: Simd<u32, 4> = simd_masked_load( + | ---------------- arguments to this function are incorrect +... +LL | default + | ^^^^^^^ expected `Simd<u32, 4>`, found `Simd<u8, 4>` + | + = note: expected struct `Simd<u32, _>` + found struct `Simd<u8, _>` +help: the return type of this call is `Simd<u8, 4>` due to the type of the argument passed + --> $DIR/masked-load-store-check-fail.rs:25:32 + | +LL | let _x: Simd<u32, 4> = simd_masked_load( + | ________________________________^ +LL | | Simd::<u8, 4>([1, 0, 1, 1]), +LL | | arr.as_ptr(), +LL | | default + | | ------- this argument influences the return type of `simd_masked_load` +LL | | ); + | |_________^ +note: function defined here + --> $DIR/masked-load-store-check-fail.rs:5:8 + | +LL | fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/simd/masked-load-store.rs b/tests/ui/simd/masked-load-store.rs new file mode 100644 index 00000000000..74ee652ec6e --- /dev/null +++ b/tests/ui/simd/masked-load-store.rs @@ -0,0 +1,33 @@ +// run-pass +#![feature(repr_simd, platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T; + fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> (); +} + +#[derive(Copy, Clone)] +#[repr(simd)] +struct Simd<T, const N: usize>([T; N]); + +fn main() { + unsafe { + let a = Simd::<u8, 4>([0, 1, 2, 3]); + let b_src = [4u8, 5, 6, 7]; + let b_default = Simd::<u8, 4>([9; 4]); + let b: Simd::<u8, 4> = simd_masked_load( + Simd::<i8, 4>([-1, 0, -1, -1]), + b_src.as_ptr(), + b_default + ); + + assert_eq!(&b.0, &[4, 9, 6, 7]); + + let mut output = [u8::MAX; 5]; + + simd_masked_store(Simd::<i8, 4>([-1, -1, -1, 0]), output.as_mut_ptr(), a); + assert_eq!(&output, &[0, 1, 2, u8::MAX, u8::MAX]); + simd_masked_store(Simd::<i8, 4>([0, -1, -1, 0]), output[1..].as_mut_ptr(), b); + assert_eq!(&output, &[0, 1, 9, 6, u8::MAX]); + } +} diff --git a/tests/ui/static/static-reference-to-fn-1.stderr b/tests/ui/static/static-reference-to-fn-1.stderr index ce9b6a739cf..6bf64974ef5 100644 --- a/tests/ui/static/static-reference-to-fn-1.stderr +++ b/tests/ui/static/static-reference-to-fn-1.stderr @@ -4,8 +4,8 @@ error[E0308]: mismatched types LL | func: &foo, | ^^^^ expected `&fn() -> Option<isize>`, found `&fn() -> Option<isize> {foo}` | - = note: expected reference `&fn() -> Option<isize>` - found reference `&fn() -> Option<isize> {foo}` + = note: expected reference `&fn() -> Option<_>` + found reference `&fn() -> Option<_> {foo}` = note: fn items are distinct from fn pointers help: consider casting to a fn pointer | diff --git a/tests/ui/suggestions/as-ref.stderr b/tests/ui/suggestions/as-ref.stderr index c5b2bb1260f..a42e2af3164 100644 --- a/tests/ui/suggestions/as-ref.stderr +++ b/tests/ui/suggestions/as-ref.stderr @@ -78,8 +78,8 @@ LL | let y: Option<&usize> = x; | | | expected due to this | - = note: expected enum `Option<&usize>` - found reference `&Option<usize>` + = note: expected enum `Option<&_>` + found reference `&Option<_>` help: try using `.as_ref()` to convert `&Option<usize>` to `Option<&usize>` | LL | let y: Option<&usize> = x.as_ref(); @@ -93,8 +93,8 @@ LL | let y: Result<&usize, &usize> = x; | | | expected due to this | - = note: expected enum `Result<&usize, &usize>` - found reference `&Result<usize, usize>` + = note: expected enum `Result<&_, &_>` + found reference `&Result<_, _>` help: try using `.as_ref()` to convert `&Result<usize, usize>` to `Result<&usize, &usize>` | LL | let y: Result<&usize, &usize> = x.as_ref(); @@ -108,8 +108,8 @@ LL | let y: Result<&usize, usize> = x; | | | expected due to this | - = note: expected enum `Result<&usize, usize>` - found reference `&Result<usize, usize>` + = note: expected enum `Result<&_, _>` + found reference `&Result<_, _>` error[E0308]: mismatched types --> $DIR/as-ref.rs:22:42 diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr index 8c973995c34..afbb9c32d51 100644 --- a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr +++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr @@ -8,8 +8,8 @@ LL | fn wat<T>(t: &T) -> T { LL | t.clone() | ^^^^^^^^^ expected type parameter `T`, found `&T` | - = note: expected type parameter `T` - found reference `&T` + = note: expected type parameter `_` + found reference `&_` note: `T` does not implement `Clone`, so `&T` was cloned instead --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5 | diff --git a/tests/ui/suggestions/method-access-to-range-literal-typo.stderr b/tests/ui/suggestions/method-access-to-range-literal-typo.stderr index 54a16b8efa7..b1fb0254cd9 100644 --- a/tests/ui/suggestions/method-access-to-range-literal-typo.stderr +++ b/tests/ui/suggestions/method-access-to-range-literal-typo.stderr @@ -18,8 +18,8 @@ LL | fn method(&self) -> Option<&Vec<u8>> { LL | self.option..as_ref().map(|x| x) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<&Vec<u8>>`, found `Range<Option<Vec<u8>>>` | - = note: expected enum `Option<&Vec<u8>>` - found struct `std::ops::Range<Option<Vec<u8>>>` + = note: expected enum `Option<&Vec<_>>` + found struct `std::ops::Range<Option<Vec<_>>>` help: you likely meant to write a method call instead of a range | LL - self.option..as_ref().map(|x| x) diff --git a/tests/ui/suggestions/mut-ref-reassignment.stderr b/tests/ui/suggestions/mut-ref-reassignment.stderr index b86a04c7cd3..a225b34f8c3 100644 --- a/tests/ui/suggestions/mut-ref-reassignment.stderr +++ b/tests/ui/suggestions/mut-ref-reassignment.stderr @@ -32,8 +32,8 @@ LL | fn suggestion2(opt: &mut Option<String>) { LL | opt = Some(String::new()) | ^^^^^^^^^^^^^^^^^^^ expected `&mut Option<String>`, found `Option<String>` | - = note: expected mutable reference `&mut Option<String>` - found enum `Option<String>` + = note: expected mutable reference `&mut Option<_>` + found enum `Option<_>` help: consider dereferencing here to assign to the mutably borrowed value | LL | *opt = Some(String::new()) diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.fixed b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.fixed new file mode 100644 index 00000000000..61f06d802b6 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.fixed @@ -0,0 +1,30 @@ +// run-rustfix + +struct A {} + +impl A { + fn hello(_a: i32) {} + fn test(_a: Self, _b: i32) {} +} + +struct B<T> { + _b: T +} +impl<T> B<T> { + fn hello(_a: i32) {} + fn test(_a: Self, _b: i32) {} +} + +fn main() { + let _a = A {}; + A::hello(1); + //~^ ERROR no method named `hello` found + A::test(_a, 1); + //~^ ERROR no method named `test` found + + let _b = B {_b: ""}; + B::<&str>::hello(1); + //~^ ERROR no method named `hello` found + B::<&str>::test(_b, 1); + //~^ ERROR no method named `test` found +} diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.rs b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.rs new file mode 100644 index 00000000000..07e614f0c15 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.rs @@ -0,0 +1,30 @@ +// run-rustfix + +struct A {} + +impl A { + fn hello(_a: i32) {} + fn test(_a: Self, _b: i32) {} +} + +struct B<T> { + _b: T +} +impl<T> B<T> { + fn hello(_a: i32) {} + fn test(_a: Self, _b: i32) {} +} + +fn main() { + let _a = A {}; + _a.hello(1); + //~^ ERROR no method named `hello` found + _a.test(1); + //~^ ERROR no method named `test` found + + let _b = B {_b: ""}; + _b.hello(1); + //~^ ERROR no method named `hello` found + _b.test(1); + //~^ ERROR no method named `test` found +} diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.stderr new file mode 100644 index 00000000000..793595784d9 --- /dev/null +++ b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.stderr @@ -0,0 +1,79 @@ +error[E0599]: no method named `hello` found for struct `A` in the current scope + --> $DIR/suggest-assoc-fn-call-without-receiver.rs:20:8 + | +LL | struct A {} + | -------- method `hello` not found for this struct +... +LL | _a.hello(1); + | ---^^^^^--- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `A::hello(1)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `A` + --> $DIR/suggest-assoc-fn-call-without-receiver.rs:6:5 + | +LL | fn hello(_a: i32) {} + | ^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `test` found for struct `A` in the current scope + --> $DIR/suggest-assoc-fn-call-without-receiver.rs:22:8 + | +LL | struct A {} + | -------- method `test` not found for this struct +... +LL | _a.test(1); + | ---^^^^--- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `A::test(_a, 1)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `A` + --> $DIR/suggest-assoc-fn-call-without-receiver.rs:7:5 + | +LL | fn test(_a: Self, _b: i32) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `hello` found for struct `B<&str>` in the current scope + --> $DIR/suggest-assoc-fn-call-without-receiver.rs:26:8 + | +LL | struct B<T> { + | ----------- method `hello` not found for this struct +... +LL | _b.hello(1); + | ---^^^^^--- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `B::<&str>::hello(1)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `B<T>` + --> $DIR/suggest-assoc-fn-call-without-receiver.rs:14:5 + | +LL | fn hello(_a: i32) {} + | ^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `test` found for struct `B<&str>` in the current scope + --> $DIR/suggest-assoc-fn-call-without-receiver.rs:28:8 + | +LL | struct B<T> { + | ----------- method `test` not found for this struct +... +LL | _b.test(1); + | ---^^^^--- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `B::<&str>::test(_b, 1)` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `B<T>` + --> $DIR/suggest-assoc-fn-call-without-receiver.rs:15:5 + | +LL | fn test(_a: Self, _b: i32) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/thir-print/thir-flat-const-variant.stdout b/tests/ui/thir-print/thir-flat-const-variant.stdout index 7bddc925996..1840be7885b 100644 --- a/tests/ui/thir-print/thir-flat-const-variant.stdout +++ b/tests/ui/thir-print/thir-flat-const-variant.stdout @@ -66,18 +66,6 @@ Thir { ), span: $DIR/thir-flat-const-variant.rs:12:23: 12:35 (#0), }, - Expr { - kind: Scope { - region_scope: Destruction(3), - lint_level: Inherited, - value: e3, - }, - ty: Foo, - temp_lifetime: Some( - Node(3), - ), - span: $DIR/thir-flat-const-variant.rs:12:23: 12:35 (#0), - }, ], stmts: [], params: [], @@ -151,18 +139,6 @@ Thir { ), span: $DIR/thir-flat-const-variant.rs:13:23: 13:36 (#0), }, - Expr { - kind: Scope { - region_scope: Destruction(3), - lint_level: Inherited, - value: e3, - }, - ty: Foo, - temp_lifetime: Some( - Node(3), - ), - span: $DIR/thir-flat-const-variant.rs:13:23: 13:36 (#0), - }, ], stmts: [], params: [], @@ -236,18 +212,6 @@ Thir { ), span: $DIR/thir-flat-const-variant.rs:14:24: 14:36 (#0), }, - Expr { - kind: Scope { - region_scope: Destruction(3), - lint_level: Inherited, - value: e3, - }, - ty: Foo, - temp_lifetime: Some( - Node(3), - ), - span: $DIR/thir-flat-const-variant.rs:14:24: 14:36 (#0), - }, ], stmts: [], params: [], @@ -321,18 +285,6 @@ Thir { ), span: $DIR/thir-flat-const-variant.rs:15:24: 15:37 (#0), }, - Expr { - kind: Scope { - region_scope: Destruction(3), - lint_level: Inherited, - value: e3, - }, - ty: Foo, - temp_lifetime: Some( - Node(3), - ), - span: $DIR/thir-flat-const-variant.rs:15:24: 15:37 (#0), - }, ], stmts: [], params: [], @@ -348,7 +300,6 @@ Thir { Block { targeted_by_break: false, region_scope: Node(1), - opt_destruction_scope: None, span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0), stmts: [], expr: None, @@ -380,18 +331,6 @@ Thir { ), span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0), }, - Expr { - kind: Scope { - region_scope: Destruction(2), - lint_level: Inherited, - value: e1, - }, - ty: (), - temp_lifetime: Some( - Node(2), - ), - span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0), - }, ], stmts: [], params: [], diff --git a/tests/ui/thir-print/thir-flat.stdout b/tests/ui/thir-print/thir-flat.stdout index b0aa44b56aa..a31d08adab6 100644 --- a/tests/ui/thir-print/thir-flat.stdout +++ b/tests/ui/thir-print/thir-flat.stdout @@ -8,7 +8,6 @@ Thir { Block { targeted_by_break: false, region_scope: Node(1), - opt_destruction_scope: None, span: $DIR/thir-flat.rs:4:15: 4:17 (#0), stmts: [], expr: None, @@ -40,18 +39,6 @@ Thir { ), span: $DIR/thir-flat.rs:4:15: 4:17 (#0), }, - Expr { - kind: Scope { - region_scope: Destruction(2), - lint_level: Inherited, - value: e1, - }, - ty: (), - temp_lifetime: Some( - Node(2), - ), - span: $DIR/thir-flat.rs:4:15: 4:17 (#0), - }, ], stmts: [], params: [], diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout index 3fc130f0176..60c9283abcf 100644 --- a/tests/ui/thir-print/thir-tree-match.stdout +++ b/tests/ui/thir-print/thir-tree-match.stdout @@ -31,262 +31,217 @@ body: span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) kind: Scope { - region_scope: Destruction(26) - lint_level: Inherited + region_scope: Node(26) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).26)) value: Expr { ty: bool temp_lifetime: Some(Node(26)) span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) kind: - Scope { - region_scope: Node(26) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).26)) - value: + Block { + targeted_by_break: false + span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) + region_scope: Node(25) + safety_mode: Safe + stmts: [] + expr: Expr { ty: bool temp_lifetime: Some(Node(26)) - span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) + span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0) kind: - Block { - targeted_by_break: false - opt_destruction_scope: None - span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) - region_scope: Node(25) - safety_mode: Safe - stmts: [] - expr: + Scope { + region_scope: Node(3) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).3)) + value: Expr { ty: bool temp_lifetime: Some(Node(26)) span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0) kind: - Scope { - region_scope: Node(3) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).3)) - value: + Match { + scrutinee: Expr { - ty: bool + ty: Foo temp_lifetime: Some(Node(26)) - span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0) + span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) kind: - Match { - scrutinee: + Scope { + region_scope: Node(4) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).4)) + value: Expr { ty: Foo temp_lifetime: Some(Node(26)) span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) kind: - Scope { - region_scope: Node(4) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).4)) - value: - Expr { - ty: Foo - temp_lifetime: Some(Node(26)) - span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) - kind: - VarRef { - id: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).2)) - } - } + VarRef { + id: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).2)) } } - arms: [ - Arm { - pattern: + } + } + arms: [ + Arm { + pattern: + Pat: { + ty: Foo + span: $DIR/thir-tree-match.rs:17:9: 17:32 (#0) + kind: PatKind { + Variant { + adt_def: + AdtDef { + did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) + variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] + flags: IS_ENUM + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 } + args: [] + variant_index: 0 + subpatterns: [ Pat: { - ty: Foo - span: $DIR/thir-tree-match.rs:17:9: 17:32 (#0) + ty: Bar + span: $DIR/thir-tree-match.rs:17:21: 17:31 (#0) kind: PatKind { Variant { adt_def: AdtDef { - did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) - variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] + did: DefId(0:3 ~ thir_tree_match[fcf8]::Bar) + variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[fcf8]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[fcf8]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[fcf8]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[fcf8]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[fcf8]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[fcf8]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], flags: NO_VARIANT_FLAGS }] flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 } + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 10333377570083945360 } args: [] variant_index: 0 - subpatterns: [ - Pat: { - ty: Bar - span: $DIR/thir-tree-match.rs:17:21: 17:31 (#0) - kind: PatKind { - Variant { - adt_def: - AdtDef { - did: DefId(0:3 ~ thir_tree_match[fcf8]::Bar) - variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[fcf8]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[fcf8]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[fcf8]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[fcf8]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[fcf8]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[fcf8]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], flags: NO_VARIANT_FLAGS }] - flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 10333377570083945360 } - args: [] - variant_index: 0 - subpatterns: [] - } - } - } - ] + subpatterns: [] } } } - guard: None - body: + ] + } + } + } + guard: None + body: + Expr { + ty: bool + temp_lifetime: Some(Node(13)) + span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) + kind: + Scope { + region_scope: Node(13) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).13)) + value: Expr { ty: bool temp_lifetime: Some(Node(13)) span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) kind: - Scope { - region_scope: Destruction(13) - lint_level: Inherited - value: - Expr { - ty: bool - temp_lifetime: Some(Node(13)) - span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) - kind: - Scope { - region_scope: Node(13) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).13)) - value: - Expr { - ty: bool - temp_lifetime: Some(Node(13)) - span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) - kind: - Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false) + Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false) - } - } - } - } } - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).12)) - scope: Node(12) - span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0) } - Arm { - pattern: + } + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).12)) + scope: Node(12) + span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0) + } + Arm { + pattern: + Pat: { + ty: Foo + span: $DIR/thir-tree-match.rs:18:9: 18:23 (#0) + kind: PatKind { + Variant { + adt_def: + AdtDef { + did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) + variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] + flags: IS_ENUM + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 } + args: [] + variant_index: 0 + subpatterns: [ Pat: { - ty: Foo - span: $DIR/thir-tree-match.rs:18:9: 18:23 (#0) + ty: Bar + span: $DIR/thir-tree-match.rs:18:21: 18:22 (#0) kind: PatKind { - Variant { - adt_def: - AdtDef { - did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) - variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] - flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 } - args: [] - variant_index: 0 - subpatterns: [ - Pat: { - ty: Bar - span: $DIR/thir-tree-match.rs:18:21: 18:22 (#0) - kind: PatKind { - Wild - } - } - ] - } + Wild } } - guard: None - body: + ] + } + } + } + guard: None + body: + Expr { + ty: bool + temp_lifetime: Some(Node(19)) + span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) + kind: + Scope { + region_scope: Node(19) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).19)) + value: Expr { ty: bool temp_lifetime: Some(Node(19)) span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) kind: - Scope { - region_scope: Destruction(19) - lint_level: Inherited - value: - Expr { - ty: bool - temp_lifetime: Some(Node(19)) - span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) - kind: - Scope { - region_scope: Node(19) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).19)) - value: - Expr { - ty: bool - temp_lifetime: Some(Node(19)) - span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) - kind: - Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false) + Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false) - } - } - } - } } - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).18)) - scope: Node(18) - span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0) } - Arm { - pattern: - Pat: { - ty: Foo - span: $DIR/thir-tree-match.rs:19:9: 19:20 (#0) - kind: PatKind { - Variant { - adt_def: - AdtDef { - did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) - variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] - flags: IS_ENUM - repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 } - args: [] - variant_index: 1 - subpatterns: [] - } - } - } - guard: None - body: + } + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).18)) + scope: Node(18) + span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0) + } + Arm { + pattern: + Pat: { + ty: Foo + span: $DIR/thir-tree-match.rs:19:9: 19:20 (#0) + kind: PatKind { + Variant { + adt_def: + AdtDef { + did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo) + variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }] + flags: IS_ENUM + repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 } + args: [] + variant_index: 1 + subpatterns: [] + } + } + } + guard: None + body: + Expr { + ty: bool + temp_lifetime: Some(Node(24)) + span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) + kind: + Scope { + region_scope: Node(24) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).24)) + value: Expr { ty: bool temp_lifetime: Some(Node(24)) span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) kind: - Scope { - region_scope: Destruction(24) - lint_level: Inherited - value: - Expr { - ty: bool - temp_lifetime: Some(Node(24)) - span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) - kind: - Scope { - region_scope: Node(24) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).24)) - value: - Expr { - ty: bool - temp_lifetime: Some(Node(24)) - span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) - kind: - Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false) + Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false) - } - } - } - } } - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).23)) - scope: Node(23) - span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0) } - ] } + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).23)) + scope: Node(23) + span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0) } + ] } } } @@ -307,33 +262,21 @@ body: span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) kind: Scope { - region_scope: Destruction(2) - lint_level: Inherited + region_scope: Node(2) + lint_level: Explicit(HirId(DefId(0:17 ~ thir_tree_match[fcf8]::main).2)) value: Expr { ty: () temp_lifetime: Some(Node(2)) span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) kind: - Scope { - region_scope: Node(2) - lint_level: Explicit(HirId(DefId(0:17 ~ thir_tree_match[fcf8]::main).2)) - value: - Expr { - ty: () - temp_lifetime: Some(Node(2)) - span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) - kind: - Block { - targeted_by_break: false - opt_destruction_scope: None - span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) - region_scope: Node(1) - safety_mode: Safe - stmts: [] - expr: [] - } - } + Block { + targeted_by_break: false + span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0) + region_scope: Node(1) + safety_mode: Safe + stmts: [] + expr: [] } } } diff --git a/tests/ui/thir-print/thir-tree.stdout b/tests/ui/thir-print/thir-tree.stdout index 1b478dbef99..ef6db368dbe 100644 --- a/tests/ui/thir-print/thir-tree.stdout +++ b/tests/ui/thir-print/thir-tree.stdout @@ -8,33 +8,21 @@ body: span: $DIR/thir-tree.rs:4:15: 4:17 (#0) kind: Scope { - region_scope: Destruction(2) - lint_level: Inherited + region_scope: Node(2) + lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree[7aaa]::main).2)) value: Expr { ty: () temp_lifetime: Some(Node(2)) span: $DIR/thir-tree.rs:4:15: 4:17 (#0) kind: - Scope { - region_scope: Node(2) - lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree[7aaa]::main).2)) - value: - Expr { - ty: () - temp_lifetime: Some(Node(2)) - span: $DIR/thir-tree.rs:4:15: 4:17 (#0) - kind: - Block { - targeted_by_break: false - opt_destruction_scope: None - span: $DIR/thir-tree.rs:4:15: 4:17 (#0) - region_scope: Node(1) - safety_mode: Safe - stmts: [] - expr: [] - } - } + Block { + targeted_by_break: false + span: $DIR/thir-tree.rs:4:15: 4:17 (#0) + region_scope: Node(1) + safety_mode: Safe + stmts: [] + expr: [] } } } diff --git a/tests/ui/traits/impl-method-mismatch.stderr b/tests/ui/traits/impl-method-mismatch.stderr index 2655d465f23..2061fc78575 100644 --- a/tests/ui/traits/impl-method-mismatch.stderr +++ b/tests/ui/traits/impl-method-mismatch.stderr @@ -9,8 +9,8 @@ note: type in trait | LL | fn jumbo(&self, x: &usize) -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected signature `fn(&usize, &usize) -> usize` - found signature `unsafe fn(&usize, &usize)` + = note: expected signature `fn(&_, &_) -> usize` + found signature `unsafe fn(&_, &_)` error: aborting due to 1 previous error diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.rs b/tests/ui/traits/new-solver/alias-bound-unsound.rs index 825e874d71b..907a3010355 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.rs +++ b/tests/ui/traits/new-solver/alias-bound-unsound.rs @@ -23,7 +23,7 @@ fn main() { let x = String::from("hello, world"); drop(<() as Foo>::copy_me(&x)); //~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized` - //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _` + //~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _` //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed` //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item` //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed` diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.stderr b/tests/ui/traits/new-solver/alias-bound-unsound.stderr index ca4b5c90ff2..29d4d983c03 100644 --- a/tests/ui/traits/new-solver/alias-bound-unsound.stderr +++ b/tests/ui/traits/new-solver/alias-bound-unsound.stderr @@ -19,7 +19,7 @@ LL | drop(<() as Foo>::copy_me(&x)); | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`) -error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _` +error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _` --> $DIR/alias-bound-unsound.rs:24:10 | LL | drop(<() as Foo>::copy_me(&x)); diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs index 44e763ef990..07c7d4fb29c 100644 --- a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs +++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs @@ -3,8 +3,12 @@ // Proving `W<?0>: Trait` instantiates `?0` with `(W<?1>, W<?2>)` and then // proves `W<?1>: Trait` and `W<?2>: Trait`, resulting in a coinductive cycle. // -// Proving coinductive cycles runs until we reach a fixpoint. This fixpoint is -// never reached here and each step doubles the amount of nested obligations. +// Proving coinductive cycles runs until we reach a fixpoint. However, after +// computing `try_evaluate_added_goals` in the second fixpoint iteration, the +// self type already has a depth equal to the number of steps. This results +// in enormous constraints, causing the canonicalizer to hang without ever +// reaching the recursion limit. We currently avoid that by erasing the constraints +// from overflow. // // This previously caused a hang in the trait solver, see // https://github.com/rust-lang/trait-system-refactor-initiative/issues/13. diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr index 05aaf6108f1..150100f2c53 100644 --- a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr +++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr @@ -1,12 +1,12 @@ error[E0275]: overflow evaluating the requirement `W<_>: Trait` - --> $DIR/fixpoint-exponential-growth.rs:29:13 + --> $DIR/fixpoint-exponential-growth.rs:33:13 | LL | impls::<W<_>>(); | ^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`fixpoint_exponential_growth`) note: required by a bound in `impls` - --> $DIR/fixpoint-exponential-growth.rs:26:13 + --> $DIR/fixpoint-exponential-growth.rs:30:13 | LL | fn impls<T: Trait>() {} | ^^^^^ required by this bound in `impls` diff --git a/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.rs b/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.rs new file mode 100644 index 00000000000..062c6ae98d5 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.rs @@ -0,0 +1,33 @@ +// compile-flags: -Ztrait-solver=next + +// This currently hangs if we do not erase constraints from +// overflow. +// +// We set the provisional result of `W<?0>` to `?0 := W<_>`. +// The next iteration does not simply result in a `?0 := W<W<_>` constraint as +// one might expect, but instead each time we evaluate the nested `W<T>` goal we +// apply the previously returned constraints: the first fixpoint iteration goes +// as follows: `W<?1>: Trait` constrains `?1` to `W<?2>`, we then evaluate +// `W<W<?2>>: Trait` the next time we try to prove the nested goal. This results +// inn `W<W<W<?3>>>` and so on. This goes on until we reach overflow in +// `try_evaluate_added_goals`. This means the provisional result after the +// second fixpoint iteration is already `W<W<W<...>>>` with a size proportional +// to the number of steps in `try_evaluate_added_goals`. The size then continues +// to grow. The exponential blowup from having 2 nested goals per impl causes +// the solver to hang without hitting the recursion limit. +trait Trait {} + +struct W<T: ?Sized>(*const T); + +impl<T: ?Sized> Trait for W<W<T>> +where + W<T>: Trait, + W<T>: Trait, +{} + +fn impls_trait<T: Trait>() {} + +fn main() { + impls_trait::<W<_>>(); + //~^ ERROR overflow evaluating the requirement +} diff --git a/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.stderr b/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.stderr new file mode 100644 index 00000000000..42451920744 --- /dev/null +++ b/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.stderr @@ -0,0 +1,16 @@ +error[E0275]: overflow evaluating the requirement `W<_>: Trait` + --> $DIR/inductive-fixpoint-hang.rs:31:19 + | +LL | impls_trait::<W<_>>(); + | ^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_fixpoint_hang`) +note: required by a bound in `impls_trait` + --> $DIR/inductive-fixpoint-hang.rs:28:19 + | +LL | fn impls_trait<T: Trait>() {} + | ^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs index 94d645a9859..7fe242f4714 100644 --- a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs +++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs @@ -1,5 +1,7 @@ // compile-flags: -Ztrait-solver=next // known-bug: trait-system-refactor-initiative#60 +// dont-check-failure-status +// dont-check-compiler-stderr // Generalizing a projection containing an inference variable // which cannot be named by the `root_vid` can result in ambiguity. diff --git a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr index 34c2f0438c7..ad8b24a39c7 100644 --- a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr +++ b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr @@ -1,9 +1,11 @@ -error[E0271]: type mismatch resolving `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _` - --> $DIR/occurs-check-nested-alias.rs:35:9 +error[E0275]: overflow evaluating the requirement `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _` + --> $DIR/occurs-check-nested-alias.rs:36:9 | LL | x = y; - | ^ types differ + | ^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`occurs_check_nested_alias`) error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs index a2113b2a8b3..02ac091c0a8 100644 --- a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs +++ b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs @@ -1,7 +1,8 @@ // revisions: old next //[old] check-pass -// Need to emit an alias-relate instead of a `Projection` goal here. +// Currently always fails to generalize the outer alias, even if it +// is treated as rigid by `alias-relate`. //[next] compile-flags: -Ztrait-solver=next //[next] known-bug: trait-system-refactor-initiative#8 #![crate_type = "lib"] diff --git a/tests/ui/traits/new-solver/projection/param-env-trait-candidate-1.rs b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-1.rs new file mode 100644 index 00000000000..e36d574efe2 --- /dev/null +++ b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-1.rs @@ -0,0 +1,14 @@ +// check-pass +// compile-flags: -Ztrait-solver=next + +// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/1 +// a minimization of a pattern in core. +fn next<T: Iterator<Item = U>, U>(t: &mut T) -> Option<U> { + t.next() +} + +fn foo<T: Iterator>(t: &mut T) { + let _: Option<T::Item> = next(t); +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/projection/param-env-trait-candidate-2.rs b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-2.rs new file mode 100644 index 00000000000..c8050997a1d --- /dev/null +++ b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-2.rs @@ -0,0 +1,29 @@ +// check-pass +// compile-flags: -Ztrait-solver=next + +// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/1, +// a minimization of a pattern in core. + +trait Iterator { + type Item; +} + +struct Flatten<I>(I); + +impl<I, U> Iterator for Flatten<I> +where + I: Iterator<Item = U>, +{ + type Item = U; +} + +fn needs_iterator<I: Iterator>() {} + +fn environment<J>() +where + J: Iterator, +{ + needs_iterator::<Flatten<J>>(); +} + +fn main() {} diff --git a/tests/ui/traits/new-solver/specialization-transmute.stderr b/tests/ui/traits/new-solver/specialization-transmute.stderr index 18965a465b3..eaf32a475ac 100644 --- a/tests/ui/traits/new-solver/specialization-transmute.stderr +++ b/tests/ui/traits/new-solver/specialization-transmute.stderr @@ -8,13 +8,11 @@ LL | #![feature(specialization)] = help: consider using `min_specialization` instead, which is more stable and complete = note: `#[warn(incomplete_features)]` on by default -error[E0284]: type annotations needed +error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id normalizes-to _` --> $DIR/specialization-transmute.rs:15:23 | LL | fn intu(&self) -> &Self::Id { - | ^^^^^^^^^ cannot infer type - | - = note: cannot satisfy `<T as Default>::Id == _` + | ^^^^^^^^^ cannot satisfy `<T as Default>::Id normalizes-to _` error[E0282]: type annotations needed --> $DIR/specialization-transmute.rs:13:23 diff --git a/tests/ui/traits/wrong-mul-method-signature.stderr b/tests/ui/traits/wrong-mul-method-signature.stderr index 25a92f5ec12..91162cbc123 100644 --- a/tests/ui/traits/wrong-mul-method-signature.stderr +++ b/tests/ui/traits/wrong-mul-method-signature.stderr @@ -7,8 +7,8 @@ LL | fn mul(self, s: &f64) -> Vec1 { | expected `f64`, found `&f64` | help: change the parameter type to match the trait: `f64` | - = note: expected signature `fn(Vec1, f64) -> Vec1` - found signature `fn(Vec1, &f64) -> Vec1` + = note: expected signature `fn(Vec1, _) -> Vec1` + found signature `fn(Vec1, &_) -> Vec1` error[E0053]: method `mul` has an incompatible type for trait --> $DIR/wrong-mul-method-signature.rs:33:21 diff --git a/tests/ui/type/type-check/point-at-inference-2.stderr b/tests/ui/type/type-check/point-at-inference-2.stderr index 1d2777ad69a..8b559ffff7e 100644 --- a/tests/ui/type/type-check/point-at-inference-2.stderr +++ b/tests/ui/type/type-check/point-at-inference-2.stderr @@ -25,8 +25,8 @@ LL | bar(v); | | | arguments to this function are incorrect | - = note: expected struct `Vec<i32>` - found struct `Vec<&i32>` + = note: expected struct `Vec<_>` + found struct `Vec<&_>` note: function defined here --> $DIR/point-at-inference-2.rs:1:4 | @@ -43,8 +43,8 @@ LL | bar(v); | | | arguments to this function are incorrect | - = note: expected struct `Vec<i32>` - found struct `Vec<&i32>` + = note: expected struct `Vec<_>` + found struct `Vec<&_>` note: function defined here --> $DIR/point-at-inference-2.rs:1:4 | diff --git a/tests/ui/type/type-mismatch.stderr b/tests/ui/type/type-mismatch.stderr index ce6f29d354f..aca96978ac9 100644 --- a/tests/ui/type/type-mismatch.stderr +++ b/tests/ui/type/type-mismatch.stderr @@ -382,8 +382,8 @@ LL | want::<&Foo<foo>>(f); | | | arguments to this function are incorrect | - = note: expected reference `&Foo<foo>` - found struct `Foo<foo>` + = note: expected reference `&Foo<_>` + found struct `Foo<_>` note: function defined here --> $DIR/type-mismatch.rs:14:4 | @@ -402,8 +402,8 @@ LL | want::<&Foo<foo, B>>(f); | | | arguments to this function are incorrect | - = note: expected reference `&Foo<foo, B>` - found struct `Foo<foo>` + = note: expected reference `&Foo<_, B>` + found struct `Foo<_, A>` note: function defined here --> $DIR/type-mismatch.rs:14:4 | @@ -546,8 +546,8 @@ LL | want::<&Foo<foo>>(f); | | | arguments to this function are incorrect | - = note: expected reference `&Foo<foo>` - found struct `Foo<foo, B>` + = note: expected reference `&Foo<_, A>` + found struct `Foo<_, B>` note: function defined here --> $DIR/type-mismatch.rs:14:4 | @@ -562,8 +562,8 @@ LL | want::<&Foo<foo, B>>(f); | | | arguments to this function are incorrect | - = note: expected reference `&Foo<foo, B>` - found struct `Foo<foo, B>` + = note: expected reference `&Foo<_, _>` + found struct `Foo<_, _>` note: function defined here --> $DIR/type-mismatch.rs:14:4 | @@ -726,8 +726,8 @@ LL | want::<&Foo<foo>>(f); | | | arguments to this function are incorrect | - = note: expected reference `&Foo<foo>` - found struct `Foo<foo, B, A>` + = note: expected reference `&Foo<_, A, B>` + found struct `Foo<_, B, A>` note: function defined here --> $DIR/type-mismatch.rs:14:4 | @@ -742,8 +742,8 @@ LL | want::<&Foo<foo, B>>(f); | | | arguments to this function are incorrect | - = note: expected reference `&Foo<foo, B>` - found struct `Foo<foo, B, A>` + = note: expected reference `&Foo<_, _, B>` + found struct `Foo<_, _, A>` note: function defined here --> $DIR/type-mismatch.rs:14:4 | diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr index 0b705d467ff..bd7fd0392c3 100644 --- a/tests/ui/typeck/bad-index-due-to-nested.stderr +++ b/tests/ui/typeck/bad-index-due-to-nested.stderr @@ -44,8 +44,8 @@ LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { LL | map[k] | ^ expected `&K`, found type parameter `K` | - = note: expected reference `&K` - found type parameter `K` + = note: expected reference `&_` + found type parameter `_` help: consider borrowing here | LL | map[&k] @@ -59,8 +59,8 @@ LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V { LL | map[k] | ^^^^^^ expected `&V`, found type parameter `V` | - = note: expected reference `&'a V` - found type parameter `V` + = note: expected reference `&'a _` + found type parameter `_` help: consider borrowing here | LL | &map[k] diff --git a/tests/ui/typeck/mismatched-map-under-self.stderr b/tests/ui/typeck/mismatched-map-under-self.stderr index 41391720a28..13678b4b827 100644 --- a/tests/ui/typeck/mismatched-map-under-self.stderr +++ b/tests/ui/typeck/mismatched-map-under-self.stderr @@ -12,8 +12,8 @@ note: type in trait | LL | fn values(&self) -> Self::Values; | ^^^^^ - = note: expected signature `fn(&Option<T>)` - found signature `fn(Option<T>)` + = note: expected signature `fn(&Option<_>)` + found signature `fn(Option<_>)` error[E0631]: type mismatch in function arguments --> $DIR/mismatched-map-under-self.rs:12:18 diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.rs b/tests/ui/ufcs/ufcs-explicit-self-bad.rs index 9b0f99a189a..3bb3d906d11 100644 --- a/tests/ui/ufcs/ufcs-explicit-self-bad.rs +++ b/tests/ui/ufcs/ufcs-explicit-self-bad.rs @@ -39,12 +39,12 @@ impl<'a, T> SomeTrait for &'a Bar<T> { //~| ERROR has an incompatible type for trait fn dummy3(self: &&Bar<T>) {} //~^ ERROR mismatched `self` parameter type - //~| expected reference `&'a Bar<T>` - //~| found reference `&Bar<T>` + //~| expected reference `&'a Bar<_>` + //~| found reference `&Bar<_>` //~| lifetime mismatch //~| ERROR mismatched `self` parameter type - //~| expected reference `&'a Bar<T>` - //~| found reference `&Bar<T>` + //~| expected reference `&'a Bar<_>` + //~| found reference `&Bar<_>` //~| lifetime mismatch } diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr index 0efaa41d48a..4c2cb0eb753 100644 --- a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -31,8 +31,8 @@ error[E0308]: mismatched `self` parameter type LL | fn dummy2(self: &Bar<T>) {} | ^^^^^^^ lifetime mismatch | - = note: expected reference `&'a Bar<T>` - found reference `&Bar<T>` + = note: expected reference `&'a Bar<_>` + found reference `&Bar<_>` note: the anonymous lifetime defined here... --> $DIR/ufcs-explicit-self-bad.rs:37:21 | @@ -50,8 +50,8 @@ error[E0308]: mismatched `self` parameter type LL | fn dummy2(self: &Bar<T>) {} | ^^^^^^^ lifetime mismatch | - = note: expected reference `&'a Bar<T>` - found reference `&Bar<T>` + = note: expected reference `&'a Bar<_>` + found reference `&Bar<_>` note: the lifetime `'a` as defined here... --> $DIR/ufcs-explicit-self-bad.rs:35:6 | @@ -69,8 +69,8 @@ error[E0308]: mismatched `self` parameter type LL | fn dummy3(self: &&Bar<T>) {} | ^^^^^^^^ lifetime mismatch | - = note: expected reference `&'a Bar<T>` - found reference `&Bar<T>` + = note: expected reference `&'a Bar<_>` + found reference `&Bar<_>` note: the anonymous lifetime defined here... --> $DIR/ufcs-explicit-self-bad.rs:40:22 | @@ -88,8 +88,8 @@ error[E0308]: mismatched `self` parameter type LL | fn dummy3(self: &&Bar<T>) {} | ^^^^^^^^ lifetime mismatch | - = note: expected reference `&'a Bar<T>` - found reference `&Bar<T>` + = note: expected reference `&'a Bar<_>` + found reference `&Bar<_>` note: the lifetime `'a` as defined here... --> $DIR/ufcs-explicit-self-bad.rs:35:6 | @@ -115,8 +115,8 @@ note: type in trait | LL | fn dummy2(&self); | ^^^^^ - = note: expected signature `fn(&&'a Bar<T>)` - found signature `fn(&Bar<T>)` + = note: expected signature `fn(&&'a Bar<_>)` + found signature `fn(&Bar<_>)` error: aborting due to 8 previous errors diff --git a/tests/ui/uninhabited/uninhabited-patterns.rs b/tests/ui/uninhabited/uninhabited-patterns.rs index f1573b6adf0..4e90691e5c8 100644 --- a/tests/ui/uninhabited/uninhabited-patterns.rs +++ b/tests/ui/uninhabited/uninhabited-patterns.rs @@ -1,8 +1,6 @@ #![feature(box_patterns)] #![feature(never_type)] #![feature(exhaustive_patterns)] - - #![deny(unreachable_patterns)] mod foo { @@ -23,22 +21,22 @@ fn main() { let x: &[!] = &[]; match x { - &[] => (), - &[..] => (), //~ ERROR unreachable pattern + &[] => (), + &[..] => (), }; let x: Result<Box<NotSoSecretlyEmpty>, &[Result<!, !>]> = Err(&[]); match x { - Ok(box _) => (), //~ ERROR unreachable pattern + Ok(box _) => (), //~ ERROR unreachable pattern Err(&[]) => (), - Err(&[..]) => (), //~ ERROR unreachable pattern + Err(&[..]) => (), } let x: Result<foo::SecretlyEmpty, Result<NotSoSecretlyEmpty, u32>> = Err(Err(123)); match x { Ok(_y) => (), Err(Err(_y)) => (), - Err(Ok(_y)) => (), //~ ERROR unreachable pattern + Err(Ok(_y)) => (), //~ ERROR unreachable pattern } while let Some(_y) = foo() { diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr index 655569ad6e0..a6fda88f032 100644 --- a/tests/ui/uninhabited/uninhabited-patterns.stderr +++ b/tests/ui/uninhabited/uninhabited-patterns.stderr @@ -1,38 +1,26 @@ error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:27:9 + --> $DIR/uninhabited-patterns.rs:30:9 | -LL | &[..] => (), - | ^^^^^ +LL | Ok(box _) => (), + | ^^^^^^^^^ | note: the lint level is defined here - --> $DIR/uninhabited-patterns.rs:6:9 + --> $DIR/uninhabited-patterns.rs:4:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:32:9 - | -LL | Ok(box _) => (), - | ^^^^^^^^^ - -error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:34:9 - | -LL | Err(&[..]) => (), - | ^^^^^^^^^^ - -error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:41:9 + --> $DIR/uninhabited-patterns.rs:39:9 | LL | Err(Ok(_y)) => (), | ^^^^^^^^^^^ error: unreachable pattern - --> $DIR/uninhabited-patterns.rs:44:15 + --> $DIR/uninhabited-patterns.rs:42:15 | LL | while let Some(_y) = foo() { | ^^^^^^^^ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/unsafe/unsafe-trait-impl.rs b/tests/ui/unsafe/unsafe-trait-impl.rs index 1fc84ca0256..9fd9ff65288 100644 --- a/tests/ui/unsafe/unsafe-trait-impl.rs +++ b/tests/ui/unsafe/unsafe-trait-impl.rs @@ -7,8 +7,8 @@ trait Foo { impl Foo for u32 { fn len(&self) -> u32 { *self } //~^ ERROR method `len` has an incompatible type for trait - //~| expected signature `unsafe fn(&u32) -> _` - //~| found signature `fn(&u32) -> _` + //~| expected signature `unsafe fn(&_) -> _` + //~| found signature `fn(&_) -> _` } fn main() { } diff --git a/tests/ui/unsafe/unsafe-trait-impl.stderr b/tests/ui/unsafe/unsafe-trait-impl.stderr index db5200e1c20..5888b674d4f 100644 --- a/tests/ui/unsafe/unsafe-trait-impl.stderr +++ b/tests/ui/unsafe/unsafe-trait-impl.stderr @@ -9,8 +9,8 @@ note: type in trait | LL | unsafe fn len(&self) -> u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected signature `unsafe fn(&u32) -> _` - found signature `fn(&u32) -> _` + = note: expected signature `unsafe fn(&_) -> _` + found signature `fn(&_) -> _` error: aborting due to 1 previous error diff --git a/tests/ui/wf/unnormalized-projection-guides-inference.rs b/tests/ui/wf/unnormalized-projection-guides-inference.rs new file mode 100644 index 00000000000..ca2d6c2e882 --- /dev/null +++ b/tests/ui/wf/unnormalized-projection-guides-inference.rs @@ -0,0 +1,24 @@ +// The WF requirements of the *unnormalized* form of type annotations +// can guide inference. +// check-pass + +pub trait EqualTo { + type Ty; +} +impl<X> EqualTo for X { + type Ty = X; +} + +trait MyTrait<U: EqualTo<Ty = Self>> { + type Out; +} +impl<T, U: EqualTo<Ty = T>> MyTrait<U> for T { + type Out = (); +} + +fn main() { + let _: <_ as MyTrait<u8>>::Out; + // We shoud be able to infer a value for the inference variable above. + // The WF of the unnormalized projection requires `u8: EqualTo<Ty = _>`, + // which is sufficient to guide inference. +} |
