From 853504df238835208d8a565cbb532918d84492c6 Mon Sep 17 00:00:00 2001 From: Ethan Brierley <ethanboxx@gmail.com> Date: Fri, 5 Jan 2024 22:34:43 +0000 Subject: [PATCH 01/31] Remove feature not required by `Ipv6Addr::to_cononical` doctest The feature does not seem to be required by this doctest. --- library/core/src/net/ip_addr.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs index 1ef876a3163c9..762d1caad4b38 100644 --- a/library/core/src/net/ip_addr.rs +++ b/library/core/src/net/ip_addr.rs @@ -1860,7 +1860,6 @@ impl Ipv6Addr { /// # Examples /// /// ``` - /// #![feature(ip)] /// use std::net::Ipv6Addr; /// /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x7f00, 0x1).is_loopback(), false); From 1eaeaaf08b7135fd8d41339b90fdb6d189c89d69 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Sun, 7 Jan 2024 21:16:22 -0800 Subject: [PATCH 02/31] Add FileCheck for array_index.rs, boolean_identities.rs and cast.rs --- tests/mir-opt/dataflow-const-prop/array_index.rs | 12 +++++++++++- .../dataflow-const-prop/boolean_identities.rs | 5 ++++- tests/mir-opt/dataflow-const-prop/cast.rs | 8 +++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index 3d420f930076d..42c99df969e37 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -1,9 +1,19 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR array_index.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main() -> () { fn main() { + // CHECK: let mut [[array_lit:_.*]]: [u32; 4]; + // CHECK: debug x => [[x:_.*]]; + let x: u32 = [0, 1, 2, 3][2]; + // CHECK: bb{{[0-9]+}}: { + // CHECK: [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; + // CHECK: [[index:_.*]] = const 2_usize; + // CHECK: bb{{[0-9]+}}: { + // CHECK-NOT: [[x]] = [[array_lit]][[[index]]]; + // CHECK: [[x]] = [[array_lit]][2 of 3]; } diff --git a/tests/mir-opt/dataflow-const-prop/boolean_identities.rs b/tests/mir-opt/dataflow-const-prop/boolean_identities.rs index 2605c7019e6f4..93e9b8d52fc2e 100644 --- a/tests/mir-opt/dataflow-const-prop/boolean_identities.rs +++ b/tests/mir-opt/dataflow-const-prop/boolean_identities.rs @@ -1,11 +1,14 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR boolean_identities.test.DataflowConstProp.diff + +// CHECK-LABEL: fn test( pub fn test(x: bool, y: bool) -> bool { (y | true) & (x & false) + // CHECK: _0 = const false; } +// CHECK-LABEL: fn main( fn main() { test(true, false); } diff --git a/tests/mir-opt/dataflow-const-prop/cast.rs b/tests/mir-opt/dataflow-const-prop/cast.rs index c87872609dcf7..298ff49803936 100644 --- a/tests/mir-opt/dataflow-const-prop/cast.rs +++ b/tests/mir-opt/dataflow-const-prop/cast.rs @@ -1,8 +1,14 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR cast.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + + // CHECK: [[a]] = const 257_i32; let a = 257; + // CHECK: [[b]] = const 2_u8; let b = a as u8 + 1; } From e05c779ee30fc7d2bdbb41ae95dd7e5b7d404621 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Sun, 7 Jan 2024 21:16:55 -0800 Subject: [PATCH 03/31] Add FileCheck for checked.rs and default_boxed_slice.rs. --- tests/mir-opt/dataflow-const-prop/checked.rs | 17 ++++++++++++++++- .../dataflow-const-prop/default_boxed_slice.rs | 13 ++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index f7fac8890a057..7350e5fb3d83a 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -1,15 +1,30 @@ -// skip-filecheck // unit-test: DataflowConstProp // compile-flags: -Coverflow-checks=on // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR checked.main.DataflowConstProp.diff #[allow(arithmetic_overflow)] + +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug d => [[d:_.*]]; + // CHECK: debug e => [[e:_.*]]; + + // CHECK: [[a]] = const 1_i32; let a = 1; + + // CHECK: [[b]] = const 2_i32; let b = 2; + + // CHECK: [[c]] = const 3_i32; let c = a + b; + // CHECK: [[d]] = const _; let d = i32::MAX; + + // CHECK: [[e]] = const i32::MIN; let e = d + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index 8006bd510e150..5917403450356 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // compile-flags: -Zmir-enable-passes=+GVN,+Inline // ignore-debug assertions change the output MIR @@ -11,8 +10,20 @@ struct A { // EMIT_MIR default_boxed_slice.main.GVN.diff // EMIT_MIR default_boxed_slice.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main( fn main() { // ConstProp will create a constant of type `Box<[bool]>`. // Verify that `DataflowConstProp` does not ICE trying to dereference it directly. + + // CHECK: debug a => [[a:_.*]]; + // CHECK: scope {{[0-9]+}} (inlined <Box<[bool]> as Default>::default) { + // CHECK: scope {{[0-9]+}} (inlined Unique::<[bool; 0]>::dangling) { + // CHECK: scope {{[0-9]+}} (inlined NonNull::<[bool; 0]>::dangling) { + // We may check other inlined functions as well... + + // CHECK: bb{{[0-9]+}}: { + // CHECK: [[box_obj:_.*]] = Box::<[bool]>(_3, const std::alloc::Global); + // CHECK: [[a]] = A { foo: move [[box_obj]] }; let a: A = A { foo: Box::default() }; } From 33e5d851a923ab46544d2cda70f80a59e4c1398c Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Sun, 7 Jan 2024 22:03:42 -0800 Subject: [PATCH 04/31] Add FileCheck for enum.rs --- ...enum.constant.DataflowConstProp.64bit.diff | 4 +- ...enum.multiple.DataflowConstProp.32bit.diff | 2 +- ...enum.multiple.DataflowConstProp.64bit.diff | 2 +- tests/mir-opt/dataflow-const-prop/enum.rs | 72 ++++++++++++++++--- .../enum.simple.DataflowConstProp.32bit.diff | 4 +- .../enum.simple.DataflowConstProp.64bit.diff | 4 +- .../enum.statics.DataflowConstProp.32bit.diff | 16 ++--- .../enum.statics.DataflowConstProp.64bit.diff | 16 ++--- 8 files changed, 86 insertions(+), 34 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff index 07ac5b72e244c..f50a763ef9a05 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff index 775325c4d0626..6bf702b856815 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.32bit.diff @@ -14,7 +14,7 @@ let _6: u8; let _8: u8; scope 2 { - debug x => _6; + debug x2 => _6; let _9: u8; scope 4 { debug y => _9; diff --git a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff index 775325c4d0626..6bf702b856815 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.multiple.DataflowConstProp.64bit.diff @@ -14,7 +14,7 @@ let _6: u8; let _8: u8; scope 2 { - debug x => _6; + debug x2 => _6; let _9: u8; scope 4 { debug y => _9; diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index e35c0e6e85bed..f33e424034440 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH @@ -13,27 +12,66 @@ enum E { } // EMIT_MIR enum.simple.DataflowConstProp.diff + +// CHECK-LABEL: fn simple( fn simple() { + // CHECK: debug e => [[e:_.*]]; + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[e]] = const E::V1(0_i32); let e = E::V1(0); - let x = match e { E::V1(x) => x, E::V2(x) => x }; + + // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb:[0-9]+]], 1: bb1, otherwise: bb2]; + // CHECK: bb[[target_bb]]: { + // CHECK: [[x]] = const 0_i32; + let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; } // EMIT_MIR enum.constant.DataflowConstProp.diff + +// CHECK-LABEL: fn constant( fn constant() { + // CHECK: debug e => [[e:_.*]]; + // CHECK: debug x => [[x:_.*]]; const C: E = E::V1(0); + + // CHECK: [[e]] = const _; let e = C; - let x = match e { E::V1(x) => x, E::V2(x) => x }; + // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb:[0-9]+]], 1: bb1, otherwise: bb2]; + // CHECK: bb[[target_bb]]: { + // CHECK: [[x]] = const 0_i32; + let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; } // EMIT_MIR enum.statics.DataflowConstProp.diff + +// CHECK-LABEL: fn statics( fn statics() { + // CHECK: debug e1 => [[e1:_.*]]; + // CHECK: debug x1 => [[x1:_.*]]; + // CHECK: debug e2 => [[e2:_.*]]; + // CHECK: debug x2 => [[x2:_.*]]; + static C: E = E::V1(0); - let e = C; - let x = match e { E::V1(x) => x, E::V2(x) => x }; + + // CHECK: [[e1]] = const E::V1(0_i32); + let e1 = C; + // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb1:[0-9]+]], 1: bb1, otherwise: bb2]; + // CHECK: bb[[target_bb]]: { + // CHECK: [[x1]] = const 0_i32; + let x1 = match e1 { E::V1(x11) => x11, E::V2(x12) => x12 }; static RC: &E = &E::V2(4); - let e = RC; - let x = match e { E::V1(x) => x, E::V2(x) => x }; + + // CHECK: [[t:_.*]] = const {alloc2: &&E}; + // CHECK: [[e2]] = (*[[t]]); + let e2 = RC; + // CHECK: switchInt(move _{{[0-9]+}}) -> [0: bb{{[0-9]+}}, 1: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}]; + // FIXME: add checks for x2. Currently, their MIRs are not symmetric in the two + // switch branches. + // One is `_9 = &(*_12) and another is `_9 = _11`. It is different from what we can + // get by printing MIR directly. It is better to check if there are any bugs in the + // MIR passes around this stage. + let x2 = match e2 { E::V1(x21) => x21, E::V2(x22) => x22 }; } #[rustc_layout_scalar_valid_range_start(1)] @@ -41,6 +79,8 @@ fn statics() { struct NonZeroUsize(usize); // EMIT_MIR enum.mutate_discriminant.DataflowConstProp.diff + +// CHECK-LABEL: fn mutate_discriminant( #[custom_mir(dialect = "runtime", phase = "post-cleanup")] fn mutate_discriminant() -> u8 { mir!( @@ -50,7 +90,11 @@ fn mutate_discriminant() -> u8 { // This assignment overwrites the niche in which the discriminant is stored. place!(Field(Field(Variant(x, 1), 0), 0)) = 0_usize; // So we cannot know the value of this discriminant. + + // CHECK: [[a:_.*]] = discriminant(_{{[0-9]*}}); let a = Discriminant(x); + + // CHECK: switchInt([[a]]) -> [0: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}]; match a { 0 => bb1, _ => bad, @@ -68,18 +112,26 @@ fn mutate_discriminant() -> u8 { } // EMIT_MIR enum.multiple.DataflowConstProp.diff +// CHECK-LABEL: fn multiple( fn multiple(x: bool, i: u8) { + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug e => [[e:_.*]]; + // CHECK: debug x2 => [[x2:_.*]]; let e = if x { + // CHECK: [[e]] = Option::<u8>::Some(move _{{[0-9]+}}); Some(i) } else { + // CHECK: [[e]] = Option::<u8>::None; None }; // The dataflow state must have: // discriminant(e) => Top // (e as Some).0 => Top - let x = match e { Some(i) => i, None => 0 }; - // Therefore, `x` should be `Top` here, and no replacement shall happen. - let y = x; + // CHECK: [[x2]] = const 0_u8; + // CHECK: [[x2]] = _{{[0-9]+}} + let x2 = match e { Some(i) => i, None => 0 }; + // Therefore, `x2` should be `Top` here, and no replacement shall happen. + let y = x2; } fn main() { diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff index 798b0c041b4ec..b31f98460e45b 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff index 798b0c041b4ec..b31f98460e45b 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index 053981abea3ec..44e8d39cca333 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -9,34 +9,34 @@ let mut _8: &&E; let mut _10: isize; scope 1 { - debug e => _1; + debug e1 => _1; let _3: i32; let _5: i32; let _6: i32; scope 2 { - debug x => _3; + debug x1 => _3; let _7: &E; scope 5 { - debug e => _7; + debug e2 => _7; let _9: &i32; let _11: &i32; let _12: &i32; scope 6 { - debug x => _9; + debug x2 => _9; } scope 7 { - debug x => _11; + debug x21 => _11; } scope 8 { - debug x => _12; + debug x22 => _12; } } } scope 3 { - debug x => _5; + debug x11 => _5; } scope 4 { - debug x => _6; + debug x12 => _6; } } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index d862bd93ff577..ac4ca086d0fed 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -9,34 +9,34 @@ let mut _8: &&E; let mut _10: isize; scope 1 { - debug e => _1; + debug e1 => _1; let _3: i32; let _5: i32; let _6: i32; scope 2 { - debug x => _3; + debug x1 => _3; let _7: &E; scope 5 { - debug e => _7; + debug e2 => _7; let _9: &i32; let _11: &i32; let _12: &i32; scope 6 { - debug x => _9; + debug x2 => _9; } scope 7 { - debug x => _11; + debug x21 => _11; } scope 8 { - debug x => _12; + debug x22 => _12; } } } scope 3 { - debug x => _5; + debug x11 => _5; } scope 4 { - debug x => _6; + debug x12 => _6; } } From 24aefa0e5d134526c8e29c5603dcb4d42637968a Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Mon, 8 Jan 2024 16:58:58 -0800 Subject: [PATCH 05/31] Add FileCheck for if.rs, inherit_overflow.rs, issue_81605.rs --- tests/mir-opt/dataflow-const-prop/if.rs | 18 +++++++++++++++++- .../dataflow-const-prop/inherit_overflow.rs | 5 ++++- .../mir-opt/dataflow-const-prop/issue_81605.rs | 5 ++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/if.rs b/tests/mir-opt/dataflow-const-prop/if.rs index 72aabbccf56c8..28e0ee9c622f5 100644 --- a/tests/mir-opt/dataflow-const-prop/if.rs +++ b/tests/mir-opt/dataflow-const-prop/if.rs @@ -1,12 +1,28 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR if.main.DataflowConstProp.diff +// CHECK-LABEL: fn main( fn main() { + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug d => [[d:_.*]]; + // CHECK: debug e => [[e:_.*]]; + let a = 1; + + // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: [[bb_first_true:bb[0-9]+]]]; + // CHECK: [[bb_first_true]]: { + // CHECK: [[b]] = const 2_i32; let b = if a == 1 { 2 } else { 3 }; + + // CHECK: [[c]] = const 3_i32; let c = b + 1; + // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: [[bb_second_true:bb[0-9]+]]]; + // CHECK: [[bb_second_true]]: { + // CHECK: [[d]] = const 1_i32; let d = if a == 1 { a } else { a + 1 }; + + // CHECK: [[e]] = const 2_i32; let e = d + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs index 664cbcb2c259f..0a2774c782009 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs @@ -1,11 +1,14 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // compile-flags: -Zmir-enable-passes=+Inline // EMIT_MIR inherit_overflow.main.DataflowConstProp.diff +// CHECK-LABEL: fn main( fn main() { // After inlining, this will contain a `CheckedBinaryOp`. // Propagating the overflow is ok as codegen will just skip emitting the panic. + + // CHECK: {{_.*}} = const (0_u8, true); + // CHECK-LABEL: assert(!const true, let _ = <u8 as std::ops::Add>::add(255, 1); } diff --git a/tests/mir-opt/dataflow-const-prop/issue_81605.rs b/tests/mir-opt/dataflow-const-prop/issue_81605.rs index 7c5eceb8a2b68..e8a00c72eb66b 100644 --- a/tests/mir-opt/dataflow-const-prop/issue_81605.rs +++ b/tests/mir-opt/dataflow-const-prop/issue_81605.rs @@ -1,9 +1,12 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR issue_81605.f.DataflowConstProp.diff + +// CHECK-LABEL: fn f fn f() -> usize { + // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: {{bb[0-9]+}}]; 1 + if true { 1 } else { 2 } + // CHECK: _0 = const 2_usize; } fn main() { From 9452d7ed1acd62c44dbec775d42f41b508c572bf Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Mon, 8 Jan 2024 20:18:59 -0800 Subject: [PATCH 06/31] Add FileCheck to 3 tests: large_array_index, mult_by_zero, and offset_of --- .../dataflow-const-prop/large_array_index.rs | 10 ++++++- .../dataflow-const-prop/mult_by_zero.rs | 3 +- .../mir-opt/dataflow-const-prop/offset_of.rs | 29 ++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.rs b/tests/mir-opt/dataflow-const-prop/large_array_index.rs index d611a54ba71a2..6b8a0248d19bc 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.rs @@ -1,10 +1,18 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR large_array_index.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { // check that we don't propagate this, because it's too large + + // CHECK: debug x => [[x:_.*]]; + // CHECK: [[array_lit:_.*]] = [const 0_u8; 5000]; + // CHECK: {{_.*}} = const 5000_usize; + // CHECK: {{_.*}} = const true; + // CHECK-LABEL: assert(const true + // CHECK: [[x]] = [[array_lit]][2 of 3]; let x: u8 = [0_u8; 5000][2]; } diff --git a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs index 16a45c8e9fb59..c7e05579e4005 100644 --- a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs +++ b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs @@ -1,9 +1,10 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR mult_by_zero.test.DataflowConstProp.diff +// CHECK-LABEL: fn test fn test(x : i32) -> i32 { x * 0 + // CHECK: _0 = const 0_i32; } fn main() { diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index e71b3f59ecab3..a2032ea996edd 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY @@ -29,18 +28,46 @@ struct Delta<T> { } // EMIT_MIR offset_of.concrete.DataflowConstProp.diff + +// CHECK-LABEL: fn concrete fn concrete() { + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + // CHECK: debug z0 => [[z0:_.*]]; + // CHECK: debug z1 => [[z1:_.*]]; + + // CHECK: [[x]] = must_use::<usize>(const 4_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let x = offset_of!(Alpha, x); + + // CHECK: [[y]] = must_use::<usize>(const 0_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let y = offset_of!(Alpha, y); + + // CHECK: [[z0]] = must_use::<usize>(const 2_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let z0 = offset_of!(Alpha, z.0); + + // CHECK: [[z1]] = must_use::<usize>(const 3_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let z1 = offset_of!(Alpha, z.1); } // EMIT_MIR offset_of.generic.DataflowConstProp.diff + +// CHECK-LABEL: generic fn generic<T>() { + // CHECK: debug gx => [[gx:_.*]]; + // CHECK: debug gy => [[gy:_.*]]; + // CHECK: debug dx => [[dx:_.*]]; + // CHECK: debug dy => [[dy:_.*]]; + + // CHECK: [[gx]] = must_use::<usize>(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; let gx = offset_of!(Gamma<T>, x); + + // CHECK: [[gy]] = must_use::<usize>(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; let gy = offset_of!(Gamma<T>, y); + + // CHECK: [[dx]] = must_use::<usize>(const 0_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let dx = offset_of!(Delta<T>, x); + + // CHECK: [[dy]] = must_use::<usize>(const 2_usize) -> [return: {{bb[0-9]+}}, unwind continue]; let dy = offset_of!(Delta<T>, y); } From e9152e2b6c95aad0f3c89af8b0f98a0cbf4f45c7 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Mon, 8 Jan 2024 20:19:59 -0800 Subject: [PATCH 07/31] Add FileCheck to 3 tests: ref_without_sb, repeat, repr_transparent --- tests/mir-opt/dataflow-const-prop/ref_without_sb.rs | 11 ++++++++++- tests/mir-opt/dataflow-const-prop/repeat.rs | 10 +++++++++- tests/mir-opt/dataflow-const-prop/repr_transparent.rs | 9 ++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs index 2851c0590ad5f..fb66cda38ddbd 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp @@ -9,11 +8,21 @@ fn escape<T>(x: &T) {} fn some_function() {} // EMIT_MIR ref_without_sb.main.DataflowConstProp.diff +// CHECK-LABEL: fn main fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + let mut a = 0; + + // CHECK: {{_[0-9]+}} = escape::<i32>(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; escape(&a); a = 1; + + // CHECK: {{_[0-9]+}} = some_function() -> [return: {{bb[0-9]+}}, unwind continue]; some_function(); // This should currently not be propagated. + + // CHECK: [[b]] = [[a]]; let b = a; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.rs b/tests/mir-opt/dataflow-const-prop/repeat.rs index b824481948116..5d1c1a3edb695 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.rs +++ b/tests/mir-opt/dataflow-const-prop/repeat.rs @@ -1,9 +1,17 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR repeat.main.DataflowConstProp.diff +// CHECK-LABEL: fn main fn main() { + // CHECK: debug x => [[x:_.*]]; + + // CHECK: {{_[0-9]+}} = const 8_usize; + // CHECK: {{_[0-9]+}} = const true; + // CHECK-LABEL: assert(const true + + // CHECK: {{_[0-9]+}} = {{_[0-9]+}}[2 of 3]; + // CHECK: [[x]] = Add(move {{_[0-9]+}}, const 0_u32); let x: u32 = [42; 8][2] + 0; } diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.rs b/tests/mir-opt/dataflow-const-prop/repr_transparent.rs index 8cbed6fbb624d..d007301e568b1 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.rs +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // The struct has scalar ABI, but is not a scalar type. @@ -7,7 +6,15 @@ struct I32(i32); // EMIT_MIR repr_transparent.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug x => [[x:_.*]]; + // CHECK: debug y => [[y:_.*]]; + + // CHECK: [[x]] = const I32(0_i32); let x = I32(0); + + // CHECK: [[y]] = const I32(0_i32); let y = I32(x.0 + x.0); } From 3ab1d5d4506924b6d020c8edf539d2be6b7bb9e9 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Mon, 8 Jan 2024 20:20:27 -0800 Subject: [PATCH 08/31] Add FileCheck to 3 tests: self_assign_add, self_assign, and sibling_ptr --- tests/mir-opt/dataflow-const-prop/self_assign.rs | 15 ++++++++++++++- .../dataflow-const-prop/self_assign_add.rs | 8 +++++++- tests/mir-opt/dataflow-const-prop/sibling_ptr.rs | 7 ++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/self_assign.rs b/tests/mir-opt/dataflow-const-prop/self_assign.rs index c5866c4a9fd98..7d58b972d655b 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign.rs +++ b/tests/mir-opt/dataflow-const-prop/self_assign.rs @@ -1,13 +1,26 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR self_assign.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + let mut a = 0; + + // CHECK: [[a]] = Add(move {{_[0-9]+}}, const 1_i32); a = a + 1; + + // CHECK: [[a]] = move {{_[0-9]+}}; a = a; + // CHECK: [[b]] = &[[a]]; let mut b = &a; + + // CHECK: [[b]] = move {{_[0-9]+}}; b = b; + + // CHECK: [[a]] = move {{_[0-9]+}}; a = *b; } diff --git a/tests/mir-opt/dataflow-const-prop/self_assign_add.rs b/tests/mir-opt/dataflow-const-prop/self_assign_add.rs index cfe1458e44be7..09be3865d60b3 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign_add.rs +++ b/tests/mir-opt/dataflow-const-prop/self_assign_add.rs @@ -1,9 +1,15 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR self_assign_add.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug a => [[a:_.*]]; let mut a = 0; + + // CHECK: [[a]] = const 1_i32; a += 1; + + // CHECK: [[a]] = const 2_i32; a += 1; } diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs index 68aff528695d5..6e39e39839410 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs @@ -1,4 +1,3 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // This attempts to modify `x.1` via a pointer derived from `addr_of_mut!(x.0)`. // According to Miri, that is UB. However, T-opsem has not finalized that @@ -10,11 +9,17 @@ // unit-test: DataflowConstProp // EMIT_MIR sibling_ptr.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug x1 => [[x1:_[0-9]+]]; + let mut x: (u8, u8) = (0, 0); unsafe { let p = std::ptr::addr_of_mut!(x.0); *p.add(1) = 1; } + + // CHECK: [[x1]] = ({{_[0-9]+}}.1: u8); let x1 = x.1; // should not be propagated } From d765e3ae1faf4786b56da542c9dc5fbfc18162d8 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Mon, 8 Jan 2024 20:20:53 -0800 Subject: [PATCH 09/31] Add FileCheck to slice_len.rs --- tests/mir-opt/dataflow-const-prop/slice_len.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs index 86266ef5d4e60..cd63980949638 100644 --- a/tests/mir-opt/dataflow-const-prop/slice_len.rs +++ b/tests/mir-opt/dataflow-const-prop/slice_len.rs @@ -1,13 +1,23 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // compile-flags: -Zmir-enable-passes=+InstSimplify // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR slice_len.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug local => [[local:_[0-9]+]]; + // CHECK: debug constant => [[constant:_[0-9]+]]; + + // CHECK: {{_[0-9]+}} = const 3_usize; + // CHECK: {{_[0-9]+}} = const true; + + // CHECK: [[local]] = (*{{_[0-9]+}})[1 of 2]; let local = (&[1u32, 2, 3] as &[u32])[1]; const SLICE: &[u32] = &[1, 2, 3]; + + // CHECK: [[constant]] = (*{{_[0-9]+}})[1 of 2]; let constant = SLICE[1]; } From 732f6a1303c4e3f9a354221e76e065571b2f1e37 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Mon, 8 Jan 2024 20:21:06 -0800 Subject: [PATCH 10/31] Add FileCheck to struct.rs --- .../struct.main.DataflowConstProp.32bit.diff | 24 ++++---- .../struct.main.DataflowConstProp.64bit.diff | 24 ++++---- tests/mir-opt/dataflow-const-prop/struct.rs | 55 ++++++++++++++++--- 3 files changed, 72 insertions(+), 31 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 0f461f515fdd0..c486281d6f8d7 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -37,16 +37,16 @@ let _8: std::option::Option<S>; let _9: &[f32]; scope 4 { - debug a => _7; - debug b => _8; - debug c => _9; + debug a1 => _7; + debug b1 => _8; + debug c1 => _9; let _11: f32; let _12: std::option::Option<S>; let _13: &[f32]; scope 5 { - debug a => _11; - debug b => _12; - debug c => _13; + debug a2 => _11; + debug b2 => _12; + debug c2 => _13; let _15: SmallStruct; scope 6 { debug ss => _15; @@ -54,16 +54,16 @@ let _20: std::option::Option<S>; let _21: &[f32]; scope 7 { - debug a => _19; - debug b => _20; - debug c => _21; + debug a3 => _19; + debug b3 => _20; + debug c3 => _21; let _23: f32; let _24: std::option::Option<S>; let _25: &[f32]; scope 8 { - debug a => _23; - debug b => _24; - debug c => _25; + debug a4 => _23; + debug b4 => _24; + debug c4 => _25; let _27: BigStruct; scope 9 { debug bs => _27; diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index 3c40ec8bfb450..7ea53d157334d 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -37,16 +37,16 @@ let _8: std::option::Option<S>; let _9: &[f32]; scope 4 { - debug a => _7; - debug b => _8; - debug c => _9; + debug a1 => _7; + debug b1 => _8; + debug c1 => _9; let _11: f32; let _12: std::option::Option<S>; let _13: &[f32]; scope 5 { - debug a => _11; - debug b => _12; - debug c => _13; + debug a2 => _11; + debug b2 => _12; + debug c2 => _13; let _15: SmallStruct; scope 6 { debug ss => _15; @@ -54,16 +54,16 @@ let _20: std::option::Option<S>; let _21: &[f32]; scope 7 { - debug a => _19; - debug b => _20; - debug c => _21; + debug a3 => _19; + debug b3 => _20; + debug c3 => _21; let _23: f32; let _24: std::option::Option<S>; let _25: &[f32]; scope 8 { - debug a => _23; - debug b => _24; - debug c => _25; + debug a4 => _23; + debug b4 => _24; + debug c4 => _25; let _27: BigStruct; scope 9 { debug bs => _27; diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 043981a295484..4eec15a7f1630 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -1,4 +1,3 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH @@ -12,27 +11,69 @@ struct SmallStruct(f32, Option<S>, &'static [f32]); struct BigStruct(f32, Option<S>, &'static [f32]); // EMIT_MIR struct.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug s => [[s:_[0-9]+]]; + // CHECK: debug a => [[a:_[0-9]+]]; + // CHECK: debug b => [[b:_[0-9]+]]; + // CHECK: debug a1 => [[a1:_[0-9]+]]; + // CHECK: debug b1 => [[b1:_[0-9]+]]; + // CHECK: debug c1 => [[c1:_[0-9]+]]; + // CHECK: debug a2 => [[a2:_[0-9]+]]; + // CHECK: debug b2 => [[b2:_[0-9]+]]; + // CHECK: debug c2 => [[c2:_[0-9]+]]; + // CHECK: debug ss => [[ss:_[0-9]+]]; + // CHECK: debug a3 => [[a3:_[0-9]+]]; + // CHECK: debug b3 => [[b3:_[0-9]+]]; + // CHECK: debug c3 => [[c3:_[0-9]+]]; + // CHECK: debug a4 => [[a4:_[0-9]+]]; + // CHECK: debug b4 => [[b4:_[0-9]+]]; + // CHECK: debug c4 => [[c4:_[0-9]+]]; + // CHECK: debug bs => [[bs:_[0-9]+]]; + + // CHECK: [[s]] = const S(1_i32); let mut s = S(1); + + // CHECK: [[a]] = const 3_i32; let a = s.0 + 2; s.0 = 3; + + // CHECK: [[b]] = const 6_i32; let b = a + s.0; const SMALL_VAL: SmallStruct = SmallStruct(4., Some(S(1)), &[]); - let SmallStruct(a, b, c) = SMALL_VAL; + + // CHECK: [[a1]] = const 4f32; + // CHECK: [[b1]] = const Option::<S>::Some(S(1_i32)); + // CHECK: [[c1]] = ({{_[0-9]+}}.2: &[f32]); + let SmallStruct(a1, b1, c1) = SMALL_VAL; static SMALL_STAT: &SmallStruct = &SmallStruct(9., None, &[13.]); - let SmallStruct(a, b, c) = *SMALL_STAT; - let ss = SmallStruct(a, b, c); + // CHECK: [[a2]] = const 9f32; + // CHECK: [[b2]] = ((*{{_[0-9]+}}).1: std::option::Option<S>); + // CHECK: [[c2]] = ((*{{_[0-9]+}}).2: &[f32]); + let SmallStruct(a2, b2, c2) = *SMALL_STAT; + + // CHECK: [[ss]] = SmallStruct(const 9f32, move {{_[0-9]+}}, move {{_[0-9]+}}); + let ss = SmallStruct(a2, b2, c2); const BIG_VAL: BigStruct = BigStruct(25., None, &[]); - let BigStruct(a, b, c) = BIG_VAL; + + // CHECK: [[a3]] = const 25f32; + // CHECK: [[b3]] = ({{_[0-9]+}}.1: std::option::Option<S>); + // CHECK: [[c3]] = ({{_[0-9]+}}.2: &[f32]); + let BigStruct(a3, b3, c3) = BIG_VAL; static BIG_STAT: &BigStruct = &BigStruct(82., Some(S(35)), &[45., 72.]); - let BigStruct(a, b, c) = *BIG_STAT; + // CHECK: [[a4]] = const 82f32; + // CHECK: [[b4]] = const Option::<S>::Some(S(35_i32)); + // CHECK: [[c4]] = ((*{{_[0-9]+}}).2: &[f32]); + let BigStruct(a4, b4, c4) = *BIG_STAT; // We arbitrarily limit the size of synthetized values to 4 pointers. // `BigStruct` can be read, but we will keep a MIR aggregate for this. - let bs = BigStruct(a, b, c); + // CHECK: [[bs]] = BigStruct(const 82f32, const Option::<S>::Some(S(35_i32)), move {{_[0-9]+}}); + let bs = BigStruct(a4, b4, c4); } From 1adda9a170085823f43672e60c19be29a4deb18f Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Mon, 8 Jan 2024 20:21:23 -0800 Subject: [PATCH 11/31] Add FileCheck to terminator.rs and tuple.rs --- tests/mir-opt/dataflow-const-prop/terminator.rs | 4 +++- tests/mir-opt/dataflow-const-prop/tuple.rs | 16 +++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/terminator.rs b/tests/mir-opt/dataflow-const-prop/terminator.rs index 92a42f22c218f..985eddad26440 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.rs +++ b/tests/mir-opt/dataflow-const-prop/terminator.rs @@ -1,12 +1,14 @@ -// skip-filecheck // EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp fn foo(n: i32) {} // EMIT_MIR terminator.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { let a = 1; // Checks that we propagate into terminators. + // CHECK: {{_[0-9]+}} = foo(const 2_i32) -> [return: {{bb[0-9]+}}, unwind continue]; foo(a + 1); } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.rs b/tests/mir-opt/dataflow-const-prop/tuple.rs index bb706eafe8885..bd5adeda8b3dc 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.rs +++ b/tests/mir-opt/dataflow-const-prop/tuple.rs @@ -1,13 +1,27 @@ -// skip-filecheck // unit-test: DataflowConstProp // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR tuple.main.DataflowConstProp.diff + +// CHECK-LABEL: fn main fn main() { + // CHECK: debug a => [[a:_[0-9]+]]; + // CHECK: debug b => [[b:_[0-9]+]]; + // CHECK: debug c => [[c:_[0-9]+]]; + // CHECK: debug d => [[d:_[0-9]+]]; + + // CHECK: [[a]] = const (1_i32, 2_i32); let mut a = (1, 2); + + // CHECK: [[b]] = const 6_i32; let b = a.0 + a.1 + 3; + + // CHECK: [[a]] = const (2_i32, 3_i32); a = (2, 3); + + // CHECK: [[c]] = const 11_i32; let c = a.0 + a.1 + b; + // CHECK: [[d]] = (const 6_i32, const (2_i32, 3_i32), const 11_i32); let d = (b, a, c); } From 7135168d0874ee5e0485bb31d89ab69966a48337 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Sun, 7 Jan 2024 22:03:42 -0800 Subject: [PATCH 12/31] Add FileCheck for enum.rs --- .../enum.constant.DataflowConstProp.32bit.diff | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff index 07ac5b72e244c..f50a763ef9a05 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff @@ -14,10 +14,10 @@ debug x => _2; } scope 3 { - debug x => _4; + debug x1 => _4; } scope 4 { - debug x => _5; + debug x2 => _5; } } From d63f10b7addc4f5c5528b76cedb41433a275eed3 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Thu, 11 Jan 2024 23:22:33 -0800 Subject: [PATCH 13/31] resolve code reviews --- .../dataflow-const-prop/array_index.rs | 7 +-- .../dataflow-const-prop/boolean_identities.rs | 4 ++ tests/mir-opt/dataflow-const-prop/checked.rs | 2 + .../default_boxed_slice.rs | 5 +- tests/mir-opt/dataflow-const-prop/enum.rs | 23 ++++---- tests/mir-opt/dataflow-const-prop/if.rs | 6 +-- .../dataflow-const-prop/issue_81605.rs | 10 +++- .../dataflow-const-prop/large_array_index.rs | 2 +- .../dataflow-const-prop/mult_by_zero.rs | 2 +- .../mir-opt/dataflow-const-prop/offset_of.rs | 20 +++---- .../dataflow-const-prop/ref_without_sb.rs | 8 +-- tests/mir-opt/dataflow-const-prop/repeat.rs | 14 +++-- .../dataflow-const-prop/repr_transparent.rs | 2 +- .../dataflow-const-prop/self_assign.rs | 10 ++-- .../dataflow-const-prop/self_assign_add.rs | 2 +- .../dataflow-const-prop/sibling_ptr.rs | 6 +-- .../mir-opt/dataflow-const-prop/slice_len.rs | 25 ++++++--- tests/mir-opt/dataflow-const-prop/struct.rs | 52 +++++++++---------- .../mir-opt/dataflow-const-prop/terminator.rs | 4 +- tests/mir-opt/dataflow-const-prop/tuple.rs | 10 ++-- 20 files changed, 118 insertions(+), 96 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index 42c99df969e37..4b070e1d6d6f6 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -10,10 +10,7 @@ fn main() { // CHECK: debug x => [[x:_.*]]; let x: u32 = [0, 1, 2, 3][2]; - // CHECK: bb{{[0-9]+}}: { - // CHECK: [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; - // CHECK: [[index:_.*]] = const 2_usize; - // CHECK: bb{{[0-9]+}}: { - // CHECK-NOT: [[x]] = [[array_lit]][[[index]]]; + // CHECK: [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; + // CHECK-LABEL: assert(const true, // CHECK: [[x]] = [[array_lit]][2 of 3]; } diff --git a/tests/mir-opt/dataflow-const-prop/boolean_identities.rs b/tests/mir-opt/dataflow-const-prop/boolean_identities.rs index 93e9b8d52fc2e..c9be1d65b0302 100644 --- a/tests/mir-opt/dataflow-const-prop/boolean_identities.rs +++ b/tests/mir-opt/dataflow-const-prop/boolean_identities.rs @@ -4,8 +4,12 @@ // CHECK-LABEL: fn test( pub fn test(x: bool, y: bool) -> bool { + // CHECK-NOT: BitAnd( + // CHECK-NOT: BitOr( (y | true) & (x & false) // CHECK: _0 = const false; + // CHECK-NOT: BitAnd( + // CHECK-NOT: BitOr( } // CHECK-LABEL: fn main( diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index 7350e5fb3d83a..45331f91323e4 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -19,12 +19,14 @@ fn main() { // CHECK: [[b]] = const 2_i32; let b = 2; + // CHECK-LABEL: assert(!const false, // CHECK: [[c]] = const 3_i32; let c = a + b; // CHECK: [[d]] = const _; let d = i32::MAX; + // CHECK-LABEL: assert(!const true, // CHECK: [[e]] = const i32::MIN; let e = d + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index 5917403450356..b15809f2510ff 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -17,13 +17,10 @@ fn main() { // Verify that `DataflowConstProp` does not ICE trying to dereference it directly. // CHECK: debug a => [[a:_.*]]; - // CHECK: scope {{[0-9]+}} (inlined <Box<[bool]> as Default>::default) { - // CHECK: scope {{[0-9]+}} (inlined Unique::<[bool; 0]>::dangling) { - // CHECK: scope {{[0-9]+}} (inlined NonNull::<[bool; 0]>::dangling) { // We may check other inlined functions as well... - // CHECK: bb{{[0-9]+}}: { // CHECK: [[box_obj:_.*]] = Box::<[bool]>(_3, const std::alloc::Global); // CHECK: [[a]] = A { foo: move [[box_obj]] }; + // FIXME: we do not have `const Box::<[bool]>` after constprop right now. let a: A = A { foo: Box::default() }; } diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index f33e424034440..26fdda2664a95 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -20,8 +20,8 @@ fn simple() { // CHECK: [[e]] = const E::V1(0_i32); let e = E::V1(0); - // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb:[0-9]+]], 1: bb1, otherwise: bb2]; - // CHECK: bb[[target_bb]]: { + // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb1, otherwise: bb2]; + // CHECK: [[target_bb]]: { // CHECK: [[x]] = const 0_i32; let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; } @@ -36,8 +36,8 @@ fn constant() { // CHECK: [[e]] = const _; let e = C; - // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb:[0-9]+]], 1: bb1, otherwise: bb2]; - // CHECK: bb[[target_bb]]: { + // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb1, otherwise: bb2]; + // CHECK: [[target_bb]]: { // CHECK: [[x]] = const 0_i32; let x = match e { E::V1(x1) => x1, E::V2(x2) => x2 }; } @@ -55,8 +55,8 @@ fn statics() { // CHECK: [[e1]] = const E::V1(0_i32); let e1 = C; - // CHECK: switchInt(const 0_isize) -> [0: bb[[target_bb1:[0-9]+]], 1: bb1, otherwise: bb2]; - // CHECK: bb[[target_bb]]: { + // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb1, otherwise: bb2]; + // CHECK: [[target_bb]]: { // CHECK: [[x1]] = const 0_i32; let x1 = match e1 { E::V1(x11) => x11, E::V2(x12) => x12 }; @@ -65,7 +65,8 @@ fn statics() { // CHECK: [[t:_.*]] = const {alloc2: &&E}; // CHECK: [[e2]] = (*[[t]]); let e2 = RC; - // CHECK: switchInt(move _{{[0-9]+}}) -> [0: bb{{[0-9]+}}, 1: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}]; + + // CHECK: switchInt({{move _.*}}) -> {{.*}} // FIXME: add checks for x2. Currently, their MIRs are not symmetric in the two // switch branches. // One is `_9 = &(*_12) and another is `_9 = _11`. It is different from what we can @@ -91,10 +92,10 @@ fn mutate_discriminant() -> u8 { place!(Field(Field(Variant(x, 1), 0), 0)) = 0_usize; // So we cannot know the value of this discriminant. - // CHECK: [[a:_.*]] = discriminant(_{{[0-9]*}}); + // CHECK: [[a:_.*]] = discriminant({{_.*}}); let a = Discriminant(x); - // CHECK: switchInt([[a]]) -> [0: bb{{[0-9]+}}, otherwise: bb{{[0-9]+}}]; + // CHECK: switchInt([[a]]) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; match a { 0 => bb1, _ => bad, @@ -118,7 +119,7 @@ fn multiple(x: bool, i: u8) { // CHECK: debug e => [[e:_.*]]; // CHECK: debug x2 => [[x2:_.*]]; let e = if x { - // CHECK: [[e]] = Option::<u8>::Some(move _{{[0-9]+}}); + // CHECK: [[e]] = Option::<u8>::Some(move {{_.*}}); Some(i) } else { // CHECK: [[e]] = Option::<u8>::None; @@ -128,7 +129,7 @@ fn multiple(x: bool, i: u8) { // discriminant(e) => Top // (e as Some).0 => Top // CHECK: [[x2]] = const 0_u8; - // CHECK: [[x2]] = _{{[0-9]+}} + // CHECK: [[x2]] = {{_.*}}; let x2 = match e { Some(i) => i, None => 0 }; // Therefore, `x2` should be `Top` here, and no replacement shall happen. let y = x2; diff --git a/tests/mir-opt/dataflow-const-prop/if.rs b/tests/mir-opt/dataflow-const-prop/if.rs index 28e0ee9c622f5..3400068baba2a 100644 --- a/tests/mir-opt/dataflow-const-prop/if.rs +++ b/tests/mir-opt/dataflow-const-prop/if.rs @@ -10,16 +10,14 @@ fn main() { let a = 1; - // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: [[bb_first_true:bb[0-9]+]]]; - // CHECK: [[bb_first_true]]: { + // CHECK: switchInt(const true) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; // CHECK: [[b]] = const 2_i32; let b = if a == 1 { 2 } else { 3 }; // CHECK: [[c]] = const 3_i32; let c = b + 1; - // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: [[bb_second_true:bb[0-9]+]]]; - // CHECK: [[bb_second_true]]: { + // CHECK: switchInt(const true) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; // CHECK: [[d]] = const 1_i32; let d = if a == 1 { a } else { a + 1 }; diff --git a/tests/mir-opt/dataflow-const-prop/issue_81605.rs b/tests/mir-opt/dataflow-const-prop/issue_81605.rs index e8a00c72eb66b..f13c364279d41 100644 --- a/tests/mir-opt/dataflow-const-prop/issue_81605.rs +++ b/tests/mir-opt/dataflow-const-prop/issue_81605.rs @@ -2,9 +2,15 @@ // EMIT_MIR issue_81605.f.DataflowConstProp.diff -// CHECK-LABEL: fn f +// Plese find the original issue [here](https://github.com/rust-lang/rust/issues/81605). +// This test program comes directly from the issue. Prior to this issue, +// the compiler cannot simplify the return value of `f` into 2. This was +// solved by adding a new MIR constant propagation based on dataflow +// analysis in [#101168](https://github.com/rust-lang/rust/pull/101168). + +// CHECK-LABEL: fn f( fn f() -> usize { - // CHECK: switchInt(const true) -> [0: {{bb[0-9]+}}, otherwise: {{bb[0-9]+}}]; + // CHECK: switchInt(const true) -> [0: {{bb.*}}, otherwise: {{bb.*}}]; 1 + if true { 1 } else { 2 } // CHECK: _0 = const 2_usize; } diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.rs b/tests/mir-opt/dataflow-const-prop/large_array_index.rs index 6b8a0248d19bc..fbca411e204d1 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.rs @@ -4,7 +4,7 @@ // EMIT_MIR large_array_index.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // check that we don't propagate this, because it's too large diff --git a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs index c7e05579e4005..be8ce7310564c 100644 --- a/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs +++ b/tests/mir-opt/dataflow-const-prop/mult_by_zero.rs @@ -1,7 +1,7 @@ // unit-test: DataflowConstProp // EMIT_MIR mult_by_zero.test.DataflowConstProp.diff -// CHECK-LABEL: fn test +// CHECK-LABEL: fn test( fn test(x : i32) -> i32 { x * 0 // CHECK: _0 = const 0_i32; diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs index a2032ea996edd..ff9fe7f2fbd25 100644 --- a/tests/mir-opt/dataflow-const-prop/offset_of.rs +++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs @@ -29,45 +29,45 @@ struct Delta<T> { // EMIT_MIR offset_of.concrete.DataflowConstProp.diff -// CHECK-LABEL: fn concrete +// CHECK-LABEL: fn concrete( fn concrete() { // CHECK: debug x => [[x:_.*]]; // CHECK: debug y => [[y:_.*]]; // CHECK: debug z0 => [[z0:_.*]]; // CHECK: debug z1 => [[z1:_.*]]; - // CHECK: [[x]] = must_use::<usize>(const 4_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[x]] = must_use::<usize>(const 4_usize) -> {{.*}} let x = offset_of!(Alpha, x); - // CHECK: [[y]] = must_use::<usize>(const 0_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[y]] = must_use::<usize>(const 0_usize) -> {{.*}} let y = offset_of!(Alpha, y); - // CHECK: [[z0]] = must_use::<usize>(const 2_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[z0]] = must_use::<usize>(const 2_usize) -> {{.*}} let z0 = offset_of!(Alpha, z.0); - // CHECK: [[z1]] = must_use::<usize>(const 3_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[z1]] = must_use::<usize>(const 3_usize) -> {{.*}} let z1 = offset_of!(Alpha, z.1); } // EMIT_MIR offset_of.generic.DataflowConstProp.diff -// CHECK-LABEL: generic +// CHECK-LABEL: fn generic( fn generic<T>() { // CHECK: debug gx => [[gx:_.*]]; // CHECK: debug gy => [[gy:_.*]]; // CHECK: debug dx => [[dx:_.*]]; // CHECK: debug dy => [[dy:_.*]]; - // CHECK: [[gx]] = must_use::<usize>(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[gx]] = must_use::<usize>(move {{_.*}}) -> {{.*}} let gx = offset_of!(Gamma<T>, x); - // CHECK: [[gy]] = must_use::<usize>(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[gy]] = must_use::<usize>(move {{_.*}}) -> {{.*}} let gy = offset_of!(Gamma<T>, y); - // CHECK: [[dx]] = must_use::<usize>(const 0_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[dx]] = must_use::<usize>(const 0_usize) -> {{.*}} let dx = offset_of!(Delta<T>, x); - // CHECK: [[dy]] = must_use::<usize>(const 2_usize) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: [[dy]] = must_use::<usize>(const 2_usize) -> {{.*}} let dy = offset_of!(Delta<T>, y); } diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs index fb66cda38ddbd..7bf2b18407854 100644 --- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs +++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs @@ -8,21 +8,23 @@ fn escape<T>(x: &T) {} fn some_function() {} // EMIT_MIR ref_without_sb.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // CHECK: debug a => [[a:_.*]]; // CHECK: debug b => [[b:_.*]]; let mut a = 0; - // CHECK: {{_[0-9]+}} = escape::<i32>(move {{_[0-9]+}}) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: {{_.*}} = escape::<i32>(move {{_.*}}) -> {{.*}} escape(&a); a = 1; - // CHECK: {{_[0-9]+}} = some_function() -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: {{_.*}} = some_function() -> {{.*}} some_function(); // This should currently not be propagated. + // CHECK-NOT: [[b]] = const // CHECK: [[b]] = [[a]]; + // CHECK-NOT: [[b]] = const let b = a; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.rs b/tests/mir-opt/dataflow-const-prop/repeat.rs index 5d1c1a3edb695..80eb14dedea3a 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.rs +++ b/tests/mir-opt/dataflow-const-prop/repeat.rs @@ -3,15 +3,19 @@ // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR repeat.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // CHECK: debug x => [[x:_.*]]; - // CHECK: {{_[0-9]+}} = const 8_usize; - // CHECK: {{_[0-9]+}} = const true; + // CHECK: [[array_lit:_.*]] = [const 42_u32; 8]; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK: {{_.*}} = const 8_usize; + // CHECK: {{_.*}} = const true; // CHECK-LABEL: assert(const true - // CHECK: {{_[0-9]+}} = {{_[0-9]+}}[2 of 3]; - // CHECK: [[x]] = Add(move {{_[0-9]+}}, const 0_u32); + // CHECK-NOT: [[t:_.*]] = [[array_lit]][_ + // CHECK: [[t:_.*]] = [[array_lit]][2 of 3]; + // CHECK: [[x]] = Add(move [[t]], const 0_u32); let x: u32 = [42; 8][2] + 0; } diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.rs b/tests/mir-opt/dataflow-const-prop/repr_transparent.rs index d007301e568b1..39a2b357193ad 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.rs +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.rs @@ -7,7 +7,7 @@ struct I32(i32); // EMIT_MIR repr_transparent.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // CHECK: debug x => [[x:_.*]]; // CHECK: debug y => [[y:_.*]]; diff --git a/tests/mir-opt/dataflow-const-prop/self_assign.rs b/tests/mir-opt/dataflow-const-prop/self_assign.rs index 7d58b972d655b..a5b232131286f 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign.rs +++ b/tests/mir-opt/dataflow-const-prop/self_assign.rs @@ -2,25 +2,25 @@ // EMIT_MIR self_assign.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // CHECK: debug a => [[a:_.*]]; // CHECK: debug b => [[b:_.*]]; let mut a = 0; - // CHECK: [[a]] = Add(move {{_[0-9]+}}, const 1_i32); + // CHECK: [[a]] = Add(move {{_.*}}, const 1_i32); a = a + 1; - // CHECK: [[a]] = move {{_[0-9]+}}; + // CHECK: [[a]] = move {{_.*}}; a = a; // CHECK: [[b]] = &[[a]]; let mut b = &a; - // CHECK: [[b]] = move {{_[0-9]+}}; + // CHECK: [[b]] = move {{_.*}}; b = b; - // CHECK: [[a]] = move {{_[0-9]+}}; + // CHECK: [[a]] = move {{_.*}}; a = *b; } diff --git a/tests/mir-opt/dataflow-const-prop/self_assign_add.rs b/tests/mir-opt/dataflow-const-prop/self_assign_add.rs index 09be3865d60b3..7bfbda7a96c61 100644 --- a/tests/mir-opt/dataflow-const-prop/self_assign_add.rs +++ b/tests/mir-opt/dataflow-const-prop/self_assign_add.rs @@ -2,7 +2,7 @@ // EMIT_MIR self_assign_add.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { // CHECK: debug a => [[a:_.*]]; let mut a = 0; diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs index 6e39e39839410..9c610aabe821a 100644 --- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs +++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs @@ -10,9 +10,9 @@ // EMIT_MIR sibling_ptr.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { - // CHECK: debug x1 => [[x1:_[0-9]+]]; + // CHECK: debug x1 => [[x1:_.*]]; let mut x: (u8, u8) = (0, 0); unsafe { @@ -20,6 +20,6 @@ fn main() { *p.add(1) = 1; } - // CHECK: [[x1]] = ({{_[0-9]+}}.1: u8); + // CHECK: [[x1]] = ({{_.*}}.1: u8); let x1 = x.1; // should not be propagated } diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.rs b/tests/mir-opt/dataflow-const-prop/slice_len.rs index cd63980949638..65c87580330fc 100644 --- a/tests/mir-opt/dataflow-const-prop/slice_len.rs +++ b/tests/mir-opt/dataflow-const-prop/slice_len.rs @@ -5,19 +5,30 @@ // EMIT_MIR slice_len.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { - // CHECK: debug local => [[local:_[0-9]+]]; - // CHECK: debug constant => [[constant:_[0-9]+]]; + // CHECK: debug local => [[local:_.*]]; + // CHECK: debug constant => [[constant:_.*]]; - // CHECK: {{_[0-9]+}} = const 3_usize; - // CHECK: {{_[0-9]+}} = const true; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ + // CHECK: {{_.*}} = const 3_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true, - // CHECK: [[local]] = (*{{_[0-9]+}})[1 of 2]; + // CHECK: [[local]] = (*{{_.*}})[1 of 2]; let local = (&[1u32, 2, 3] as &[u32])[1]; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ const SLICE: &[u32] = &[1, 2, 3]; + // CHECK: {{_.*}} = const 3_usize; + // CHECK: {{_.*}} = const true; + // CHECK: assert(const true, - // CHECK: [[constant]] = (*{{_[0-9]+}})[1 of 2]; + // CHECK-NOT: [[constant]] = (*{{_.*}})[_ + // CHECK: [[constant]] = (*{{_.*}})[1 of 2]; let constant = SLICE[1]; } diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 4eec15a7f1630..a7e0f6a987d5a 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -12,25 +12,25 @@ struct BigStruct(f32, Option<S>, &'static [f32]); // EMIT_MIR struct.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { - // CHECK: debug s => [[s:_[0-9]+]]; - // CHECK: debug a => [[a:_[0-9]+]]; - // CHECK: debug b => [[b:_[0-9]+]]; - // CHECK: debug a1 => [[a1:_[0-9]+]]; - // CHECK: debug b1 => [[b1:_[0-9]+]]; - // CHECK: debug c1 => [[c1:_[0-9]+]]; - // CHECK: debug a2 => [[a2:_[0-9]+]]; - // CHECK: debug b2 => [[b2:_[0-9]+]]; - // CHECK: debug c2 => [[c2:_[0-9]+]]; - // CHECK: debug ss => [[ss:_[0-9]+]]; - // CHECK: debug a3 => [[a3:_[0-9]+]]; - // CHECK: debug b3 => [[b3:_[0-9]+]]; - // CHECK: debug c3 => [[c3:_[0-9]+]]; - // CHECK: debug a4 => [[a4:_[0-9]+]]; - // CHECK: debug b4 => [[b4:_[0-9]+]]; - // CHECK: debug c4 => [[c4:_[0-9]+]]; - // CHECK: debug bs => [[bs:_[0-9]+]]; + // CHECK: debug s => [[s:_.*]]; + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug a1 => [[a1:_.*]]; + // CHECK: debug b1 => [[b1:_.*]]; + // CHECK: debug c1 => [[c1:_.*]]; + // CHECK: debug a2 => [[a2:_.*]]; + // CHECK: debug b2 => [[b2:_.*]]; + // CHECK: debug c2 => [[c2:_.*]]; + // CHECK: debug ss => [[ss:_.*]]; + // CHECK: debug a3 => [[a3:_.*]]; + // CHECK: debug b3 => [[b3:_.*]]; + // CHECK: debug c3 => [[c3:_.*]]; + // CHECK: debug a4 => [[a4:_.*]]; + // CHECK: debug b4 => [[b4:_.*]]; + // CHECK: debug c4 => [[c4:_.*]]; + // CHECK: debug bs => [[bs:_.*]]; // CHECK: [[s]] = const S(1_i32); let mut s = S(1); @@ -46,34 +46,34 @@ fn main() { // CHECK: [[a1]] = const 4f32; // CHECK: [[b1]] = const Option::<S>::Some(S(1_i32)); - // CHECK: [[c1]] = ({{_[0-9]+}}.2: &[f32]); + // CHECK: [[c1]] = ({{_.*}}.2: &[f32]); let SmallStruct(a1, b1, c1) = SMALL_VAL; static SMALL_STAT: &SmallStruct = &SmallStruct(9., None, &[13.]); // CHECK: [[a2]] = const 9f32; - // CHECK: [[b2]] = ((*{{_[0-9]+}}).1: std::option::Option<S>); - // CHECK: [[c2]] = ((*{{_[0-9]+}}).2: &[f32]); + // CHECK: [[b2]] = ((*{{_.*}}).1: std::option::Option<S>); + // CHECK: [[c2]] = ((*{{_.*}}).2: &[f32]); let SmallStruct(a2, b2, c2) = *SMALL_STAT; - // CHECK: [[ss]] = SmallStruct(const 9f32, move {{_[0-9]+}}, move {{_[0-9]+}}); + // CHECK: [[ss]] = SmallStruct(const 9f32, move {{_.*}}, move {{_.*}}); let ss = SmallStruct(a2, b2, c2); const BIG_VAL: BigStruct = BigStruct(25., None, &[]); // CHECK: [[a3]] = const 25f32; - // CHECK: [[b3]] = ({{_[0-9]+}}.1: std::option::Option<S>); - // CHECK: [[c3]] = ({{_[0-9]+}}.2: &[f32]); + // CHECK: [[b3]] = ({{_.*}}.1: std::option::Option<S>); + // CHECK: [[c3]] = ({{_.*}}.2: &[f32]); let BigStruct(a3, b3, c3) = BIG_VAL; static BIG_STAT: &BigStruct = &BigStruct(82., Some(S(35)), &[45., 72.]); // CHECK: [[a4]] = const 82f32; // CHECK: [[b4]] = const Option::<S>::Some(S(35_i32)); - // CHECK: [[c4]] = ((*{{_[0-9]+}}).2: &[f32]); + // CHECK: [[c4]] = ((*{{_.*}}).2: &[f32]); let BigStruct(a4, b4, c4) = *BIG_STAT; // We arbitrarily limit the size of synthetized values to 4 pointers. // `BigStruct` can be read, but we will keep a MIR aggregate for this. - // CHECK: [[bs]] = BigStruct(const 82f32, const Option::<S>::Some(S(35_i32)), move {{_[0-9]+}}); + // CHECK: [[bs]] = BigStruct(const 82f32, const Option::<S>::Some(S(35_i32)), move {{_.*}}); let bs = BigStruct(a4, b4, c4); } diff --git a/tests/mir-opt/dataflow-const-prop/terminator.rs b/tests/mir-opt/dataflow-const-prop/terminator.rs index 985eddad26440..37bf3b3347024 100644 --- a/tests/mir-opt/dataflow-const-prop/terminator.rs +++ b/tests/mir-opt/dataflow-const-prop/terminator.rs @@ -5,10 +5,10 @@ fn foo(n: i32) {} // EMIT_MIR terminator.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { let a = 1; // Checks that we propagate into terminators. - // CHECK: {{_[0-9]+}} = foo(const 2_i32) -> [return: {{bb[0-9]+}}, unwind continue]; + // CHECK: {{_.*}} = foo(const 2_i32) -> [return: {{bb.*}}, unwind continue]; foo(a + 1); } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.rs b/tests/mir-opt/dataflow-const-prop/tuple.rs index bd5adeda8b3dc..563558da04a5d 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.rs +++ b/tests/mir-opt/dataflow-const-prop/tuple.rs @@ -3,12 +3,12 @@ // EMIT_MIR tuple.main.DataflowConstProp.diff -// CHECK-LABEL: fn main +// CHECK-LABEL: fn main( fn main() { - // CHECK: debug a => [[a:_[0-9]+]]; - // CHECK: debug b => [[b:_[0-9]+]]; - // CHECK: debug c => [[c:_[0-9]+]]; - // CHECK: debug d => [[d:_[0-9]+]]; + // CHECK: debug a => [[a:_.*]]; + // CHECK: debug b => [[b:_.*]]; + // CHECK: debug c => [[c:_.*]]; + // CHECK: debug d => [[d:_.*]]; // CHECK: [[a]] = const (1_i32, 2_i32); let mut a = (1, 2); From 1c886d794c1772eb6a51e84939ef1093e9e10e17 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Thu, 11 Jan 2024 23:22:33 -0800 Subject: [PATCH 14/31] resolve code reviews --- tests/mir-opt/dataflow-const-prop/array_index.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index 4b070e1d6d6f6..e21388ff5d211 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -9,8 +9,13 @@ fn main() { // CHECK: let mut [[array_lit:_.*]]: [u32; 4]; // CHECK: debug x => [[x:_.*]]; - let x: u32 = [0, 1, 2, 3][2]; // CHECK: [[array_lit]] = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; - // CHECK-LABEL: assert(const true, - // CHECK: [[x]] = [[array_lit]][2 of 3]; + // CHECK-NOT: {{_.*}} = Len( + // CHECK-NOT: {{_.*}} = Lt( + // CHECK-NOT: assert(move _ + // CHECK: {{_.*}} = const 4_usize; + // CHECK: {{_.*}} = const true; + // CHECK-LABEL: assert(const true + // CHECK: [[x]] = [[array_lit]][2 of 3]; + let x: u32 = [0, 1, 2, 3][2]; } From cd77d59f97cba2909b457b2ebb36f201b9dcb532 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Fri, 12 Jan 2024 20:50:28 -0800 Subject: [PATCH 15/31] update enum.rs for code review --- tests/mir-opt/dataflow-const-prop/enum.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index 26fdda2664a95..8a6fe3a3fdaa1 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -118,6 +118,7 @@ fn multiple(x: bool, i: u8) { // CHECK: debug x => [[x:_.*]]; // CHECK: debug e => [[e:_.*]]; // CHECK: debug x2 => [[x2:_.*]]; + // CHECK: debug y => [[y:_.*]]; let e = if x { // CHECK: [[e]] = Option::<u8>::Some(move {{_.*}}); Some(i) @@ -128,10 +129,18 @@ fn multiple(x: bool, i: u8) { // The dataflow state must have: // discriminant(e) => Top // (e as Some).0 => Top + // CHECK-NOT: [[x2]] = const 5 // CHECK: [[x2]] = const 0_u8; - // CHECK: [[x2]] = {{_.*}}; + // CHECK-NOT: [[x2]] = const 5 + // CHECK: [[some:_.*]] = (({{_.*}} as Some + // CHECK: [[x2]] = [[some]]; let x2 = match e { Some(i) => i, None => 0 }; + // Therefore, `x2` should be `Top` here, and no replacement shall happen. + + // CHECK-NOT: [[y]] = const + // CHECK: [[y]] = [[x2]]; + // CHECK-NOT: [[y]] = const let y = x2; } From 5747eceef859c6e1ac74c04723ac9e2b5e039e1f Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Sun, 14 Jan 2024 22:35:00 -0800 Subject: [PATCH 16/31] add FIXME for default_boxed_slice.rs --- tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index b15809f2510ff..bfa52b694d0ec 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -4,6 +4,8 @@ // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// This test is to check ICE in issue [#115789](https://github.com/rust-lang/rust/issues/115789). + struct A { foo: Box<[bool]>, } @@ -14,13 +16,14 @@ struct A { // CHECK-LABEL: fn main( fn main() { // ConstProp will create a constant of type `Box<[bool]>`. + // FIXME: it is not yet a constant. + // Verify that `DataflowConstProp` does not ICE trying to dereference it directly. // CHECK: debug a => [[a:_.*]]; // We may check other inlined functions as well... - // CHECK: [[box_obj:_.*]] = Box::<[bool]>(_3, const std::alloc::Global); - // CHECK: [[a]] = A { foo: move [[box_obj]] }; - // FIXME: we do not have `const Box::<[bool]>` after constprop right now. + // CHECK-LABEL: _.* = Box::<[bool]>( + // FIXME: should be `_.* = const Box::<[bool]>` let a: A = A { foo: Box::default() }; } From edba94907d2f84f35f8e5673a363bf2d42e1c29a Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Sat, 20 Jan 2024 08:09:14 -0800 Subject: [PATCH 17/31] update misuse of check-label --- tests/mir-opt/dataflow-const-prop/array_index.rs | 2 +- tests/mir-opt/dataflow-const-prop/checked.rs | 4 ++-- tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs | 4 ++-- tests/mir-opt/dataflow-const-prop/inherit_overflow.rs | 2 +- tests/mir-opt/dataflow-const-prop/large_array_index.rs | 2 +- tests/mir-opt/dataflow-const-prop/repeat.rs | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/array_index.rs b/tests/mir-opt/dataflow-const-prop/array_index.rs index e21388ff5d211..8f0cc489a5bb7 100644 --- a/tests/mir-opt/dataflow-const-prop/array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/array_index.rs @@ -15,7 +15,7 @@ fn main() { // CHECK-NOT: assert(move _ // CHECK: {{_.*}} = const 4_usize; // CHECK: {{_.*}} = const true; - // CHECK-LABEL: assert(const true + // CHECK: assert(const true // CHECK: [[x]] = [[array_lit]][2 of 3]; let x: u32 = [0, 1, 2, 3][2]; } diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index 45331f91323e4..30b0afa8334dd 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -19,14 +19,14 @@ fn main() { // CHECK: [[b]] = const 2_i32; let b = 2; - // CHECK-LABEL: assert(!const false, + // CHECK: assert(!const false, // CHECK: [[c]] = const 3_i32; let c = a + b; // CHECK: [[d]] = const _; let d = i32::MAX; - // CHECK-LABEL: assert(!const true, + // CHECK: assert(!const true, // CHECK: [[e]] = const i32::MIN; let e = d + 1; } diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs index bfa52b694d0ec..fb708e5084bb9 100644 --- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs +++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.rs @@ -23,7 +23,7 @@ fn main() { // CHECK: debug a => [[a:_.*]]; // We may check other inlined functions as well... - // CHECK-LABEL: _.* = Box::<[bool]>( - // FIXME: should be `_.* = const Box::<[bool]>` + // CHECK: {{_.*}} = Box::<[bool]>( + // FIXME: should be `{{_.*}} = const Box::<[bool]>` let a: A = A { foo: Box::default() }; } diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs index 0a2774c782009..b0acc31e0dbcc 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs @@ -9,6 +9,6 @@ fn main() { // Propagating the overflow is ok as codegen will just skip emitting the panic. // CHECK: {{_.*}} = const (0_u8, true); - // CHECK-LABEL: assert(!const true, + // CHECK: assert(!const true, let _ = <u8 as std::ops::Add>::add(255, 1); } diff --git a/tests/mir-opt/dataflow-const-prop/large_array_index.rs b/tests/mir-opt/dataflow-const-prop/large_array_index.rs index fbca411e204d1..62be2c3824fa5 100644 --- a/tests/mir-opt/dataflow-const-prop/large_array_index.rs +++ b/tests/mir-opt/dataflow-const-prop/large_array_index.rs @@ -12,7 +12,7 @@ fn main() { // CHECK: [[array_lit:_.*]] = [const 0_u8; 5000]; // CHECK: {{_.*}} = const 5000_usize; // CHECK: {{_.*}} = const true; - // CHECK-LABEL: assert(const true + // CHECK: assert(const true // CHECK: [[x]] = [[array_lit]][2 of 3]; let x: u8 = [0_u8; 5000][2]; } diff --git a/tests/mir-opt/dataflow-const-prop/repeat.rs b/tests/mir-opt/dataflow-const-prop/repeat.rs index 80eb14dedea3a..daa8dbaf07655 100644 --- a/tests/mir-opt/dataflow-const-prop/repeat.rs +++ b/tests/mir-opt/dataflow-const-prop/repeat.rs @@ -12,7 +12,7 @@ fn main() { // CHECK-NOT: {{_.*}} = Lt( // CHECK: {{_.*}} = const 8_usize; // CHECK: {{_.*}} = const true; - // CHECK-LABEL: assert(const true + // CHECK: assert(const true // CHECK-NOT: [[t:_.*]] = [[array_lit]][_ // CHECK: [[t:_.*]] = [[array_lit]][2 of 3]; From 7ad307dc9d014fb8d06e42d495c88328455510c1 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Sat, 20 Jan 2024 08:22:07 -0800 Subject: [PATCH 18/31] finish a pattern in `enum.rs` --- tests/mir-opt/dataflow-const-prop/enum.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index 8a6fe3a3fdaa1..86288020bab45 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -132,7 +132,7 @@ fn multiple(x: bool, i: u8) { // CHECK-NOT: [[x2]] = const 5 // CHECK: [[x2]] = const 0_u8; // CHECK-NOT: [[x2]] = const 5 - // CHECK: [[some:_.*]] = (({{_.*}} as Some + // CHECK: [[some:_.*]] = (({{_.*}} as Some).0: u8) // CHECK: [[x2]] = [[some]]; let x2 = match e { Some(i) => i, None => 0 }; From 65b10839d6cc033d65831666565ffda5077793f8 Mon Sep 17 00:00:00 2001 From: sfzhu93 <zhushuofei@gmail.com> Date: Mon, 22 Jan 2024 17:34:49 -0800 Subject: [PATCH 19/31] update enum.rs --- tests/mir-opt/dataflow-const-prop/enum.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs index 86288020bab45..7ad64d05be434 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.rs +++ b/tests/mir-opt/dataflow-const-prop/enum.rs @@ -129,9 +129,7 @@ fn multiple(x: bool, i: u8) { // The dataflow state must have: // discriminant(e) => Top // (e as Some).0 => Top - // CHECK-NOT: [[x2]] = const 5 // CHECK: [[x2]] = const 0_u8; - // CHECK-NOT: [[x2]] = const 5 // CHECK: [[some:_.*]] = (({{_.*}} as Some).0: u8) // CHECK: [[x2]] = [[some]]; let x2 = match e { Some(i) => i, None => 0 }; From f9259d1b73f01c4c690dfd7429bb3ce25a34874f Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan <YuriAstrakhan@gmail.com> Date: Tue, 9 May 2023 01:04:32 -0400 Subject: [PATCH 20/31] Boost intersperse(_with) performance I did some benchmark digging into the `intersperse` and `intersperse_with` code as part of the https://internals.rust-lang.org/t/add-iterate-with-separators-iterator-function/18781/13 discussion, and as a result I optimized them a bit, without relying on the peekable iterator. --- library/core/src/iter/adapters/intersperse.rs | 126 ++++++++++-------- 1 file changed, 74 insertions(+), 52 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index d8bbd424cf258..654e30777719c 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -1,4 +1,5 @@ -use super::Peekable; +use core::fmt; +use core::iter::{Fuse, FusedIterator}; /// An iterator adapter that places a separator between all elements. /// @@ -11,8 +12,16 @@ where I::Item: Clone, { separator: I::Item, - iter: Peekable<I>, - needs_sep: bool, + next_item: Option<I::Item>, + iter: Fuse<I>, +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl<I> FusedIterator for Intersperse<I> +where + I: FusedIterator, + I::Item: Clone, +{ } impl<I: Iterator> Intersperse<I> @@ -20,7 +29,8 @@ where I::Item: Clone, { pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self { - Self { iter: iter.peekable(), separator, needs_sep: false } + let mut iter = iter.fuse(); + Self { separator, next_item: iter.next(), iter } } } @@ -33,27 +43,31 @@ where type Item = I::Item; #[inline] - fn next(&mut self) -> Option<I::Item> { - if self.needs_sep && self.iter.peek().is_some() { - self.needs_sep = false; - Some(self.separator.clone()) + fn next(&mut self) -> Option<Self::Item> { + if let Some(v) = self.next_item.take() { + Some(v) } else { - self.needs_sep = true; - self.iter.next() + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some(self.separator.clone()) + } else { + None + } } } + fn size_hint(&self) -> (usize, Option<usize>) { + intersperse_size_hint(&self.iter, self.next_item.is_some()) + } + fn fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { let separator = self.separator; - intersperse_fold(self.iter, init, f, move || separator.clone(), self.needs_sep) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - intersperse_size_hint(&self.iter, self.needs_sep) + intersperse_fold(self.iter, init, f, move || separator.clone(), self.next_item) } } @@ -67,38 +81,46 @@ where I: Iterator, { separator: G, - iter: Peekable<I>, - needs_sep: bool, + next_item: Option<I::Item>, + iter: Fuse<I>, +} + +#[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] +impl<I, G> FusedIterator for IntersperseWith<I, G> +where + I: FusedIterator, + G: FnMut() -> I::Item, +{ } #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] -impl<I, G> crate::fmt::Debug for IntersperseWith<I, G> +impl<I, G> fmt::Debug for IntersperseWith<I, G> where - I: Iterator + crate::fmt::Debug, - I::Item: crate::fmt::Debug, - G: crate::fmt::Debug, + I: Iterator + fmt::Debug, + I::Item: fmt::Debug, + G: fmt::Debug, { - fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("IntersperseWith") .field("separator", &self.separator) .field("iter", &self.iter) - .field("needs_sep", &self.needs_sep) + .field("next_item", &self.next_item) .finish() } } #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] -impl<I, G> crate::clone::Clone for IntersperseWith<I, G> +impl<I, G> Clone for IntersperseWith<I, G> where - I: Iterator + crate::clone::Clone, - I::Item: crate::clone::Clone, + I: Iterator + Clone, + I::Item: Clone, G: Clone, { fn clone(&self) -> Self { - IntersperseWith { + Self { separator: self.separator.clone(), iter: self.iter.clone(), - needs_sep: self.needs_sep.clone(), + next_item: self.next_item.clone(), } } } @@ -109,7 +131,8 @@ where G: FnMut() -> I::Item, { pub(in crate::iter) fn new(iter: I, separator: G) -> Self { - Self { iter: iter.peekable(), separator, needs_sep: false } + let mut iter = iter.fuse(); + Self { separator, next_item: iter.next(), iter } } } @@ -122,47 +145,50 @@ where type Item = I::Item; #[inline] - fn next(&mut self) -> Option<I::Item> { - if self.needs_sep && self.iter.peek().is_some() { - self.needs_sep = false; - Some((self.separator)()) + fn next(&mut self) -> Option<Self::Item> { + if let Some(v) = self.next_item.take() { + Some(v) } else { - self.needs_sep = true; - self.iter.next() + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some((self.separator)()) + } else { + None + } } } + fn size_hint(&self) -> (usize, Option<usize>) { + intersperse_size_hint(&self.iter, self.next_item.is_some()) + } + fn fold<B, F>(self, init: B, f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { - intersperse_fold(self.iter, init, f, self.separator, self.needs_sep) - } - - fn size_hint(&self) -> (usize, Option<usize>) { - intersperse_size_hint(&self.iter, self.needs_sep) + intersperse_fold(self.iter, init, f, self.separator, self.next_item) } } -fn intersperse_size_hint<I>(iter: &I, needs_sep: bool) -> (usize, Option<usize>) +fn intersperse_size_hint<I>(iter: &I, next_is_elem: bool) -> (usize, Option<usize>) where I: Iterator, { let (lo, hi) = iter.size_hint(); - let next_is_elem = !needs_sep; ( - lo.saturating_sub(next_is_elem as usize).saturating_add(lo), - hi.and_then(|hi| hi.saturating_sub(next_is_elem as usize).checked_add(hi)), + lo.saturating_add(next_is_elem as usize).saturating_add(lo), + hi.map(|hi| hi.saturating_add(next_is_elem as usize).saturating_add(hi)), ) } fn intersperse_fold<I, B, F, G>( - mut iter: I, + iter: I, init: B, mut f: F, mut separator: G, - needs_sep: bool, + mut next_item: Option<I::Item>, ) -> B where I: Iterator, @@ -171,12 +197,8 @@ where { let mut accum = init; - if !needs_sep { - if let Some(x) = iter.next() { - accum = f(accum, x); - } else { - return accum; - } + if let Some(x) = next_item.take() { + accum = f(accum, x); } iter.fold(accum, |mut accum, x| { From b8d245e7490be49fedf0609bd9763adc1116b725 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan <YuriAstrakhan@gmail.com> Date: Tue, 9 May 2023 18:31:56 -0400 Subject: [PATCH 21/31] Postpone .next() call until iteration --- library/core/src/iter/adapters/intersperse.rs | 78 ++++++++++++------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index 654e30777719c..2ff24cd7792f9 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -11,6 +11,7 @@ pub struct Intersperse<I: Iterator> where I::Item: Clone, { + started: bool, separator: I::Item, next_item: Option<I::Item>, iter: Fuse<I>, @@ -29,8 +30,7 @@ where I::Item: Clone, { pub(in crate::iter) fn new(iter: I, separator: I::Item) -> Self { - let mut iter = iter.fuse(); - Self { separator, next_item: iter.next(), iter } + Self { started: false, separator, next_item: None, iter: iter.fuse() } } } @@ -44,21 +44,26 @@ where #[inline] fn next(&mut self) -> Option<Self::Item> { - if let Some(v) = self.next_item.take() { - Some(v) - } else { - let next_item = self.iter.next(); - if next_item.is_some() { - self.next_item = next_item; - Some(self.separator.clone()) + if self.started { + if let Some(v) = self.next_item.take() { + Some(v) } else { - None + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some(self.separator.clone()) + } else { + None + } } + } else { + self.started = true; + self.iter.next() } } fn size_hint(&self) -> (usize, Option<usize>) { - intersperse_size_hint(&self.iter, self.next_item.is_some()) + intersperse_size_hint(&self.iter, self.started, self.next_item.is_some()) } fn fold<B, F>(self, init: B, f: F) -> B @@ -67,7 +72,7 @@ where F: FnMut(B, Self::Item) -> B, { let separator = self.separator; - intersperse_fold(self.iter, init, f, move || separator.clone(), self.next_item) + intersperse_fold(self.iter, init, f, move || separator.clone(), self.started,self.next_item) } } @@ -80,6 +85,7 @@ pub struct IntersperseWith<I, G> where I: Iterator, { + started: bool, separator: G, next_item: Option<I::Item>, iter: Fuse<I>, @@ -102,6 +108,7 @@ where { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("IntersperseWith") + .field("started", &self.started) .field("separator", &self.separator) .field("iter", &self.iter) .field("next_item", &self.next_item) @@ -118,6 +125,7 @@ where { fn clone(&self) -> Self { Self { + started: self.started, separator: self.separator.clone(), iter: self.iter.clone(), next_item: self.next_item.clone(), @@ -131,8 +139,7 @@ where G: FnMut() -> I::Item, { pub(in crate::iter) fn new(iter: I, separator: G) -> Self { - let mut iter = iter.fuse(); - Self { separator, next_item: iter.next(), iter } + Self { started: false, separator, next_item: None, iter: iter.fuse() } } } @@ -146,21 +153,26 @@ where #[inline] fn next(&mut self) -> Option<Self::Item> { - if let Some(v) = self.next_item.take() { - Some(v) - } else { - let next_item = self.iter.next(); - if next_item.is_some() { - self.next_item = next_item; - Some((self.separator)()) + if self.started { + if let Some(v) = self.next_item.take() { + Some(v) } else { - None + let next_item = self.iter.next(); + if next_item.is_some() { + self.next_item = next_item; + Some((self.separator)()) + } else { + None + } } + } else { + self.started = true; + self.iter.next() } } fn size_hint(&self) -> (usize, Option<usize>) { - intersperse_size_hint(&self.iter, self.next_item.is_some()) + intersperse_size_hint(&self.iter, self.started, self.next_item.is_some()) } fn fold<B, F>(self, init: B, f: F) -> B @@ -168,26 +180,33 @@ where Self: Sized, F: FnMut(B, Self::Item) -> B, { - intersperse_fold(self.iter, init, f, self.separator, self.next_item) + intersperse_fold(self.iter, init, f, self.separator, self.started, self.next_item) } } -fn intersperse_size_hint<I>(iter: &I, next_is_elem: bool) -> (usize, Option<usize>) +fn intersperse_size_hint<I>(iter: &I, started: bool, next_is_some: bool) -> (usize, Option<usize>) where I: Iterator, { let (lo, hi) = iter.size_hint(); ( - lo.saturating_add(next_is_elem as usize).saturating_add(lo), - hi.map(|hi| hi.saturating_add(next_is_elem as usize).saturating_add(hi)), + lo.saturating_sub(!started as usize) + .saturating_add(next_is_some as usize) + .saturating_add(lo), + hi.map(|hi| { + hi.saturating_sub(!started as usize) + .saturating_add(next_is_some as usize) + .saturating_add(hi) + }), ) } fn intersperse_fold<I, B, F, G>( - iter: I, + mut iter: I, init: B, mut f: F, mut separator: G, + started: bool, mut next_item: Option<I::Item>, ) -> B where @@ -197,7 +216,8 @@ where { let mut accum = init; - if let Some(x) = next_item.take() { + let first = if started { next_item.take() } else { iter.next() }; + if let Some(x) = first { accum = f(accum, x); } From f1dbc7b35ed70847237046a5a61af1ba88eae31d Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan <YuriAstrakhan@gmail.com> Date: Tue, 9 May 2023 18:40:54 -0400 Subject: [PATCH 22/31] fmt --- library/core/src/iter/adapters/intersperse.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index 2ff24cd7792f9..aab3743a51af2 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -72,7 +72,14 @@ where F: FnMut(B, Self::Item) -> B, { let separator = self.separator; - intersperse_fold(self.iter, init, f, move || separator.clone(), self.started,self.next_item) + intersperse_fold( + self.iter, + init, + f, + move || separator.clone(), + self.started, + self.next_item, + ) } } From 8cbff0b426b0f8821c6852545b8ed6aa74bfeffe Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan <yuriastrakhan@gmail.com> Date: Thu, 25 Jan 2024 20:33:06 -0500 Subject: [PATCH 23/31] Update library/core/src/iter/adapters/intersperse.rs Co-authored-by: Josh Stone <cuviper@gmail.com> --- library/core/src/iter/adapters/intersperse.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index aab3743a51af2..f436fe02dca93 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -1,5 +1,5 @@ -use core::fmt; -use core::iter::{Fuse, FusedIterator}; +use crate::fmt; +use crate::iter::{Fuse, FusedIterator}; /// An iterator adapter that places a separator between all elements. /// From 77f31ef2b29e0ff16b9db8907327741c057bea8e Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan <YuriAstrakhan@gmail.com> Date: Thu, 25 Jan 2024 20:56:52 -0500 Subject: [PATCH 24/31] use checked_add for upper bound --- library/core/src/iter/adapters/intersperse.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index f436fe02dca93..c97a59b614f9d 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -200,10 +200,10 @@ where lo.saturating_sub(!started as usize) .saturating_add(next_is_some as usize) .saturating_add(lo), - hi.map(|hi| { + hi.and_then(|hi| { hi.saturating_sub(!started as usize) .saturating_add(next_is_some as usize) - .saturating_add(hi) + .checked_add(hi) }), ) } From bdf7404b43d683accd29c20c880c51c85ceaaccd Mon Sep 17 00:00:00 2001 From: Nikita Popov <npopov@redhat.com> Date: Fri, 26 Jan 2024 14:46:17 +0100 Subject: [PATCH 25/31] Update codegen test for LLVM 18 --- tests/codegen/pow_of_two.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/codegen/pow_of_two.rs b/tests/codegen/pow_of_two.rs index a8c0550e33263..372360dfd12c7 100644 --- a/tests/codegen/pow_of_two.rs +++ b/tests/codegen/pow_of_two.rs @@ -4,7 +4,7 @@ #[no_mangle] pub fn a(exp: u32) -> u64 { // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64 - // CHECK: %{{[^ ]+}} = zext i32 %exp to i64 + // CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64 // CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}} // CHECK: ret i64 %{{[^ ]+}} 2u64.pow(exp) @@ -14,7 +14,7 @@ pub fn a(exp: u32) -> u64 { #[no_mangle] pub fn b(exp: u32) -> i64 { // CHECK: %{{[^ ]+}} = icmp ugt i32 %exp, 64 - // CHECK: %{{[^ ]+}} = zext i32 %exp to i64 + // CHECK: %{{[^ ]+}} = zext{{( nneg)?}} i32 %exp to i64 // CHECK: %{{[^ ]+}} = shl nuw i64 {{[^ ]+}}, %{{[^ ]+}} // CHECK: ret i64 %{{[^ ]+}} 2i64.pow(exp) From 90254cd55fcdc3fc7101300398b6e715d99b9c3e Mon Sep 17 00:00:00 2001 From: klensy <klensy@users.noreply.github.com> Date: Fri, 26 Jan 2024 19:45:00 +0300 Subject: [PATCH 26/31] ScopeTree: remove destruction_scopes as unused last usages removed by https://github.com/rust-lang/rust/pull/116170 --- compiler/rustc_middle/src/middle/region.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compiler/rustc_middle/src/middle/region.rs b/compiler/rustc_middle/src/middle/region.rs index 5d6a7f75df843..b9914f6cb7a00 100644 --- a/compiler/rustc_middle/src/middle/region.rs +++ b/compiler/rustc_middle/src/middle/region.rs @@ -221,9 +221,6 @@ pub struct ScopeTree { /// variable is declared. var_map: FxIndexMap<hir::ItemLocalId, Scope>, - /// Maps from a `NodeId` to the associated destruction scope (if any). - destruction_scopes: FxIndexMap<hir::ItemLocalId, Scope>, - /// Identifies expressions which, if captured into a temporary, ought to /// have a temporary whose lifetime extends to the end of the enclosing *block*, /// and not the enclosing *statement*. Expressions that are not present in this @@ -336,11 +333,6 @@ impl ScopeTree { let prev = self.parent_map.insert(child, p); assert!(prev.is_none()); } - - // Record the destruction scopes for later so we can query them. - if let ScopeData::Destruction = child.data { - self.destruction_scopes.insert(child.item_local_id(), child); - } } pub fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: Scope) { From 304361a10c2a1c550e47f89efc55901ff3b4cf2a Mon Sep 17 00:00:00 2001 From: Urgau <urgau@numericable.fr> Date: Fri, 26 Jan 2024 20:32:55 +0100 Subject: [PATCH 27/31] Improve handling of numbers in IntoDiagnosticArg --- compiler/rustc_errors/src/diagnostic_impls.rs | 47 +++++++++---------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index f6679ae9bb352..d18be69900c82 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -58,16 +58,29 @@ macro_rules! into_diagnostic_arg_using_display { } } +macro_rules! into_diagnostic_arg_for_number { + ($( $ty:ty ),+ $(,)?) => { + $( + impl IntoDiagnosticArg for $ty { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + // HACK: `FluentNumber` the underline backing struct represent + // numbers using a f64 which can represent all the i128 numbers + // So in order to be able to use fluent selectors and still + // have all the numbers representable we only convert numbers + // below a certain threshold. + if let Ok(n) = TryInto::<i128>::try_into(self) && n >= -100 && n <= 100 { + DiagnosticArgValue::Number(n) + } else { + self.to_string().into_diagnostic_arg() + } + } + } + )+ + } +} + into_diagnostic_arg_using_display!( ast::ParamKindOrd, - i8, - u8, - i16, - u16, - u32, - i64, - i128, - u128, std::io::Error, Box<dyn std::error::Error>, std::num::NonZeroU32, @@ -82,17 +95,7 @@ into_diagnostic_arg_using_display!( ExitStatus, ); -impl IntoDiagnosticArg for i32 { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - DiagnosticArgValue::Number(self.into()) - } -} - -impl IntoDiagnosticArg for u64 { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - DiagnosticArgValue::Number(self.into()) - } -} +into_diagnostic_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize); impl IntoDiagnosticArg for bool { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { @@ -154,12 +157,6 @@ impl IntoDiagnosticArg for PathBuf { } } -impl IntoDiagnosticArg for usize { - fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { - DiagnosticArgValue::Number(self as i128) - } -} - impl IntoDiagnosticArg for PanicStrategy { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Owned(self.desc().to_string())) From 93ff4a4f4806965a0ea19a0441e2e9ec8e2404f9 Mon Sep 17 00:00:00 2001 From: Urgau <3616612+Urgau@users.noreply.github.com> Date: Fri, 26 Jan 2024 21:01:45 +0100 Subject: [PATCH 28/31] Fix typo Co-authored-by: Michael Goulet <michael@errs.io> --- compiler/rustc_errors/src/diagnostic_impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index d18be69900c82..d58d05095cdcb 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -64,7 +64,7 @@ macro_rules! into_diagnostic_arg_for_number { impl IntoDiagnosticArg for $ty { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { // HACK: `FluentNumber` the underline backing struct represent - // numbers using a f64 which can represent all the i128 numbers + // numbers using a f64 which can't represent all the i128 numbers // So in order to be able to use fluent selectors and still // have all the numbers representable we only convert numbers // below a certain threshold. From 169c72861fc932cea1ce832ae932ad3effe91f12 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni <thom@shift.click> Date: Fri, 26 Jan 2024 12:31:46 -0800 Subject: [PATCH 29/31] Remove myself from review rotation --- triagebot.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 264f6efd982c7..3b4e01f4a0fd7 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -662,7 +662,6 @@ libs = [ "@joshtriplett", "@Mark-Simulacrum", "@m-ou-se", - "@thomcc", ] bootstrap = [ "@Mark-Simulacrum", @@ -802,7 +801,7 @@ project-stable-mir = [ "/library/panic_unwind" = ["libs"] "/library/proc_macro" = ["@petrochenkov"] "/library/std" = ["libs"] -"/library/std/src/sys/pal/windows" = ["@ChrisDenton", "@thomcc"] +"/library/std/src/sys/pal/windows" = ["@ChrisDenton"] "/library/stdarch" = ["libs"] "/library/test" = ["libs"] "/src/bootstrap" = ["bootstrap"] From a5d9def321df76de6fb90ed836bf062b557636d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Wed, 22 Nov 2023 19:53:24 +0000 Subject: [PATCH 30/31] Properly recover from trailing attr in body When encountering an attribute in a body, we try to recover from an attribute on an expression (as opposed to a statement). We need to properly clean up when the attribute is at the end of the body where a tail expression would be. Fix #118164. --- .../rustc_parse/src/parser/diagnostics.rs | 19 +++++++++++-- ...r-from-trailing-outer-attribute-in-body.rs | 9 +++++++ ...om-trailing-outer-attribute-in-body.stderr | 27 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs create mode 100644 tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 720a610fdf518..1924d28d91c9c 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -792,13 +792,28 @@ impl<'a> Parser<'a> { && let [segment] = &attr_kind.item.path.segments[..] && segment.ident.name == sym::cfg && let Some(args_span) = attr_kind.item.args.span() - && let Ok(next_attr) = snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None)) + && let next_attr = match snapshot.parse_attribute(InnerAttrPolicy::Forbidden(None)) + { + Ok(next_attr) => next_attr, + Err(inner_err) => { + err.cancel(); + inner_err.cancel(); + return; + } + } && let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind && let Some(next_attr_args_span) = next_attr_kind.item.args.span() && let [next_segment] = &next_attr_kind.item.path.segments[..] && segment.ident.name == sym::cfg - && let Ok(next_expr) = snapshot.parse_expr() { + let next_expr = match snapshot.parse_expr() { + Ok(next_expr) => next_expr, + Err(inner_err) => { + err.cancel(); + inner_err.cancel(); + return; + } + }; // We have for sure // #[cfg(..)] // expr diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs new file mode 100644 index 0000000000000..a7412f51782fb --- /dev/null +++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.rs @@ -0,0 +1,9 @@ +// Issue #118164: recovery path leaving unemitted error behind +fn bar() -> String { + #[cfg(feature = )] + [1, 2, 3].iter().map().collect::<String>() //~ ERROR expected `;`, found `#` + #[attr] //~ ERROR expected statement after outer attribute +} +fn main() { + let _ = bar(); +} diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr new file mode 100644 index 0000000000000..dd0081cc2dff9 --- /dev/null +++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body.stderr @@ -0,0 +1,27 @@ +error: expected `;`, found `#` + --> $DIR/properly-recover-from-trailing-outer-attribute-in-body.rs:4:47 + | +LL | #[cfg(feature = )] + | ------------------ only `;` terminated statements or tail expressions are allowed after this attribute +LL | [1, 2, 3].iter().map().collect::<String>() + | ^ expected `;` here +LL | #[attr] + | - unexpected token + | +help: add `;` here + | +LL | [1, 2, 3].iter().map().collect::<String>(); + | + +help: alternatively, consider surrounding the expression with a block + | +LL | { [1, 2, 3].iter().map().collect::<String>() } + | + + + +error: expected statement after outer attribute + --> $DIR/properly-recover-from-trailing-outer-attribute-in-body.rs:5:5 + | +LL | #[attr] + | ^^^^^^^ + +error: aborting due to 2 previous errors + From 3022c769ab9d19c7bf68f7ebd753cac3495cc0a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= <esteban@kuber.com.ar> Date: Tue, 23 Jan 2024 18:24:40 +0000 Subject: [PATCH 31/31] Avoid ICE in trait without `dyn` lint Do not attempt to provide an accurate suggestion for `impl Trait` in bare trait types when linting. Instead, only do the object safety check when an E0782 is already going to be emitted in the 2021 edition. Fix #120241. --- .../rustc_hir_analysis/src/astconv/lint.rs | 10 +-- .../avoid-ice-on-warning-2.new.stderr | 12 +++ ...derr => avoid-ice-on-warning-2.old.stderr} | 28 ++----- .../object-safety/avoid-ice-on-warning-2.rs | 13 +-- .../avoid-ice-on-warning-3.new.stderr | 47 +++++++++++ ...derr => avoid-ice-on-warning-3.old.stderr} | 84 +++++++------------ .../object-safety/avoid-ice-on-warning-3.rs | 31 +++---- .../avoid-ice-on-warning.new.stderr | 15 ++++ ...stderr => avoid-ice-on-warning.old.stderr} | 12 +-- .../ui/object-safety/avoid-ice-on-warning.rs | 7 +- .../bare-trait-dont-suggest-dyn.fixed | 9 -- .../bare-trait-dont-suggest-dyn.new.fixed | 16 ++++ ...=> bare-trait-dont-suggest-dyn.new.stderr} | 2 +- .../bare-trait-dont-suggest-dyn.old.stderr | 39 +++++++++ .../bare-trait-dont-suggest-dyn.rs | 9 +- .../ui/traits/bound/not-on-bare-trait.stderr | 14 +--- 16 files changed, 222 insertions(+), 126 deletions(-) create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr rename tests/ui/object-safety/{avoid-ice-on-warning-2.stderr => avoid-ice-on-warning-2.old.stderr} (60%) create mode 100644 tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr rename tests/ui/object-safety/{avoid-ice-on-warning-3.stderr => avoid-ice-on-warning-3.old.stderr} (63%) create mode 100644 tests/ui/object-safety/avoid-ice-on-warning.new.stderr rename tests/ui/object-safety/{avoid-ice-on-warning.stderr => avoid-ice-on-warning.old.stderr} (71%) delete mode 100644 tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed create mode 100644 tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed rename tests/ui/object-safety/{bare-trait-dont-suggest-dyn.stderr => bare-trait-dont-suggest-dyn.new.stderr} (95%) create mode 100644 tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index 33e782abc68ed..553c8a698619c 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -132,7 +132,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ], Applicability::MachineApplicable, ); - } else if diag.is_error() && is_downgradable { + } else if is_downgradable { // We'll emit the object safety error already, with a structured suggestion. diag.downgrade_to_delayed_bug(); } @@ -158,7 +158,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if !is_object_safe { diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); - if diag.is_error() && is_downgradable { + if is_downgradable { // We'll emit the object safety error already, with a structured suggestion. diag.downgrade_to_delayed_bug(); } @@ -241,13 +241,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { let msg = "trait objects without an explicit `dyn` are deprecated"; tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| { - if self_ty.span.can_be_used_for_suggestions() - && !self.maybe_lint_impl_trait(self_ty, lint) - { + if self_ty.span.can_be_used_for_suggestions() { lint.multipart_suggestion_verbose( "use `dyn`", sugg, - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); } self.maybe_lint_blanket_trait_impl(self_ty, lint); diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr new file mode 100644 index 0000000000000..7aec3a73fe964 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.new.stderr @@ -0,0 +1,12 @@ +error[E0038]: the trait `Copy` cannot be made into an object + --> $DIR/avoid-ice-on-warning-2.rs:4:13 + | +LL | fn id<F>(f: Copy) -> usize { + | ^^^^ `Copy` cannot be made into an object + | + = note: the trait cannot be made into an object because it requires `Self: Sized` + = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.stderr b/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr similarity index 60% rename from tests/ui/object-safety/avoid-ice-on-warning-2.stderr rename to tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr index 2755eee6f3529..41c09b7df6289 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-2.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.old.stderr @@ -1,43 +1,33 @@ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-2.rs:1:13 + --> $DIR/avoid-ice-on-warning-2.rs:4:13 | LL | fn id<F>(f: Copy) -> usize { | ^^^^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: `Copy` it is not object safe, so it can't be `dyn` = note: `#[warn(bare_trait_objects)]` on by default -help: use a new generic type parameter, constrained by `Copy` +help: use `dyn` | -LL | fn id<F, T: Copy>(f: T) -> usize { - | +++++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn id<F>(f: impl Copy) -> usize { - | ++++ +LL | fn id<F>(f: dyn Copy) -> usize { + | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-2.rs:1:13 + --> $DIR/avoid-ice-on-warning-2.rs:4:13 | LL | fn id<F>(f: Copy) -> usize { | ^^^^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: `Copy` it is not object safe, so it can't be `dyn` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use a new generic type parameter, constrained by `Copy` - | -LL | fn id<F, T: Copy>(f: T) -> usize { - | +++++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference +help: use `dyn` | -LL | fn id<F>(f: impl Copy) -> usize { - | ++++ +LL | fn id<F>(f: dyn Copy) -> usize { + | +++ error[E0038]: the trait `Copy` cannot be made into an object - --> $DIR/avoid-ice-on-warning-2.rs:1:13 + --> $DIR/avoid-ice-on-warning-2.rs:4:13 | LL | fn id<F>(f: Copy) -> usize { | ^^^^ `Copy` cannot be made into an object diff --git a/tests/ui/object-safety/avoid-ice-on-warning-2.rs b/tests/ui/object-safety/avoid-ice-on-warning-2.rs index cd34362d3dd52..9a6a4378fa383 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-2.rs +++ b/tests/ui/object-safety/avoid-ice-on-warning-2.rs @@ -1,9 +1,12 @@ +// revisions: old new +//[old] edition:2015 +//[new] edition:2021 fn id<F>(f: Copy) -> usize { -//~^ WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! -//~| ERROR the trait `Copy` cannot be made into an object +//~^ ERROR the trait `Copy` cannot be made into an object +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! f() } fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr new file mode 100644 index 0000000000000..fd92d43ef9a24 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.new.stderr @@ -0,0 +1,47 @@ +error[E0038]: the trait `A` cannot be made into an object + --> $DIR/avoid-ice-on-warning-3.rs:4:19 + | +LL | trait B { fn f(a: A) -> A; } + | ^ `A` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/avoid-ice-on-warning-3.rs:12:14 + | +LL | trait A { fn g(b: B) -> B; } + | - ^ ...because associated function `g` has no `self` parameter + | | + | this trait cannot be made into an object... +help: consider turning `g` into a method by giving it a `&self` argument + | +LL | trait A { fn g(&self, b: B) -> B; } + | ++++++ +help: alternatively, consider constraining `g` so it does not apply to trait objects + | +LL | trait A { fn g(b: B) -> B where Self: Sized; } + | +++++++++++++++++ + +error[E0038]: the trait `B` cannot be made into an object + --> $DIR/avoid-ice-on-warning-3.rs:12:19 + | +LL | trait A { fn g(b: B) -> B; } + | ^ `B` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/avoid-ice-on-warning-3.rs:4:14 + | +LL | trait B { fn f(a: A) -> A; } + | - ^ ...because associated function `f` has no `self` parameter + | | + | this trait cannot be made into an object... +help: consider turning `f` into a method by giving it a `&self` argument + | +LL | trait B { fn f(&self, a: A) -> A; } + | ++++++ +help: alternatively, consider constraining `f` so it does not apply to trait objects + | +LL | trait B { fn f(a: A) -> A where Self: Sized; } + | +++++++++++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.stderr b/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr similarity index 63% rename from tests/ui/object-safety/avoid-ice-on-warning-3.stderr rename to tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr index 0fc67770b96dd..a36e2519c804d 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-3.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.old.stderr @@ -1,93 +1,78 @@ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:9:19 + --> $DIR/avoid-ice-on-warning-3.rs:4:19 | -LL | trait A { fn g(b: B) -> B; } +LL | trait B { fn f(a: A) -> A; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: `B` it is not object safe, so it can't be `dyn` = note: `#[warn(bare_trait_objects)]` on by default -help: use a new generic type parameter, constrained by `B` - | -LL | trait A { fn g<T: B>(b: T) -> B; } - | ++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference +help: use `dyn` | -LL | trait A { fn g(b: impl B) -> B; } - | ++++ +LL | trait B { fn f(a: dyn A) -> A; } + | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:9:25 + --> $DIR/avoid-ice-on-warning-3.rs:4:25 | -LL | trait A { fn g(b: B) -> B; } +LL | trait B { fn f(a: A) -> A; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> -help: `B` is not object safe, use `impl B` to return an opaque type, as long as you return a single underlying type +help: use `dyn` | -LL | trait A { fn g(b: B) -> impl B; } - | ++++ +LL | trait B { fn f(a: A) -> dyn A; } + | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:1:19 + --> $DIR/avoid-ice-on-warning-3.rs:12:19 | -LL | trait B { fn f(a: A) -> A; } +LL | trait A { fn g(b: B) -> B; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: `A` it is not object safe, so it can't be `dyn` -help: use a new generic type parameter, constrained by `A` - | -LL | trait B { fn f<T: A>(a: T) -> A; } - | ++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference +help: use `dyn` | -LL | trait B { fn f(a: impl A) -> A; } - | ++++ +LL | trait A { fn g(b: dyn B) -> B; } + | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:1:25 + --> $DIR/avoid-ice-on-warning-3.rs:12:25 | -LL | trait B { fn f(a: A) -> A; } +LL | trait A { fn g(b: B) -> B; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> -help: `A` is not object safe, use `impl A` to return an opaque type, as long as you return a single underlying type +help: use `dyn` | -LL | trait B { fn f(a: A) -> impl A; } - | ++++ +LL | trait A { fn g(b: B) -> dyn B; } + | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:1:19 + --> $DIR/avoid-ice-on-warning-3.rs:4:19 | LL | trait B { fn f(a: A) -> A; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: `A` it is not object safe, so it can't be `dyn` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use a new generic type parameter, constrained by `A` - | -LL | trait B { fn f<T: A>(a: T) -> A; } - | ++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference +help: use `dyn` | -LL | trait B { fn f(a: impl A) -> A; } - | ++++ +LL | trait B { fn f(a: dyn A) -> A; } + | +++ error[E0038]: the trait `A` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:1:19 + --> $DIR/avoid-ice-on-warning-3.rs:4:19 | LL | trait B { fn f(a: A) -> A; } | ^ `A` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/avoid-ice-on-warning-3.rs:9:14 + --> $DIR/avoid-ice-on-warning-3.rs:12:14 | LL | trait A { fn g(b: B) -> B; } | - ^ ...because associated function `g` has no `self` parameter @@ -103,32 +88,27 @@ LL | trait A { fn g(b: B) -> B where Self: Sized; } | +++++++++++++++++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning-3.rs:9:19 + --> $DIR/avoid-ice-on-warning-3.rs:12:19 | LL | trait A { fn g(b: B) -> B; } | ^ | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> - = note: `B` it is not object safe, so it can't be `dyn` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: use a new generic type parameter, constrained by `B` - | -LL | trait A { fn g<T: B>(b: T) -> B; } - | ++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference +help: use `dyn` | -LL | trait A { fn g(b: impl B) -> B; } - | ++++ +LL | trait A { fn g(b: dyn B) -> B; } + | +++ error[E0038]: the trait `B` cannot be made into an object - --> $DIR/avoid-ice-on-warning-3.rs:9:19 + --> $DIR/avoid-ice-on-warning-3.rs:12:19 | LL | trait A { fn g(b: B) -> B; } | ^ `B` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> - --> $DIR/avoid-ice-on-warning-3.rs:1:14 + --> $DIR/avoid-ice-on-warning-3.rs:4:14 | LL | trait B { fn f(a: A) -> A; } | - ^ ...because associated function `f` has no `self` parameter diff --git a/tests/ui/object-safety/avoid-ice-on-warning-3.rs b/tests/ui/object-safety/avoid-ice-on-warning-3.rs index caaf4d0fd99aa..40563e233dec6 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning-3.rs +++ b/tests/ui/object-safety/avoid-ice-on-warning-3.rs @@ -1,17 +1,20 @@ +// revisions: old new +//[old] edition:2015 +//[new] edition:2021 trait B { fn f(a: A) -> A; } -//~^ WARN trait objects without an explicit `dyn` are deprecated -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN this is accepted in the current edition -//~| WARN this is accepted in the current edition -//~| ERROR the trait `A` cannot be made into an object +//~^ ERROR the trait `A` cannot be made into an object +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN this is accepted in the current edition +//[old]~| WARN this is accepted in the current edition +//[old]~| WARN this is accepted in the current edition trait A { fn g(b: B) -> B; } -//~^ WARN trait objects without an explicit `dyn` are deprecated -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition -//~| WARN this is accepted in the current edition -//~| WARN this is accepted in the current edition -//~| ERROR the trait `B` cannot be made into an object +//~^ ERROR the trait `B` cannot be made into an object +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN this is accepted in the current edition +//[old]~| WARN this is accepted in the current edition +//[old]~| WARN this is accepted in the current edition fn main() {} diff --git a/tests/ui/object-safety/avoid-ice-on-warning.new.stderr b/tests/ui/object-safety/avoid-ice-on-warning.new.stderr new file mode 100644 index 0000000000000..517f910080de7 --- /dev/null +++ b/tests/ui/object-safety/avoid-ice-on-warning.new.stderr @@ -0,0 +1,15 @@ +error: return types are denoted using `->` + --> $DIR/avoid-ice-on-warning.rs:4:23 + | +LL | fn call_this<F>(f: F) : Fn(&str) + call_that {} + | ^ help: use `->` instead + +error[E0405]: cannot find trait `call_that` in this scope + --> $DIR/avoid-ice-on-warning.rs:4:36 + | +LL | fn call_this<F>(f: F) : Fn(&str) + call_that {} + | ^^^^^^^^^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0405`. diff --git a/tests/ui/object-safety/avoid-ice-on-warning.stderr b/tests/ui/object-safety/avoid-ice-on-warning.old.stderr similarity index 71% rename from tests/ui/object-safety/avoid-ice-on-warning.stderr rename to tests/ui/object-safety/avoid-ice-on-warning.old.stderr index 1046f177e8296..7c7af9682800f 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning.stderr +++ b/tests/ui/object-safety/avoid-ice-on-warning.old.stderr @@ -1,17 +1,17 @@ error: return types are denoted using `->` - --> $DIR/avoid-ice-on-warning.rs:1:23 + --> $DIR/avoid-ice-on-warning.rs:4:23 | LL | fn call_this<F>(f: F) : Fn(&str) + call_that {} | ^ help: use `->` instead error[E0405]: cannot find trait `call_that` in this scope - --> $DIR/avoid-ice-on-warning.rs:1:36 + --> $DIR/avoid-ice-on-warning.rs:4:36 | LL | fn call_this<F>(f: F) : Fn(&str) + call_that {} | ^^^^^^^^^ not found in this scope warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/avoid-ice-on-warning.rs:1:25 + --> $DIR/avoid-ice-on-warning.rs:4:25 | LL | fn call_this<F>(f: F) : Fn(&str) + call_that {} | ^^^^^^^^^^^^^^^^^^^^ @@ -19,10 +19,10 @@ LL | fn call_this<F>(f: F) : Fn(&str) + call_that {} = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> = note: `#[warn(bare_trait_objects)]` on by default -help: `Fn(&str) + call_that` is not object safe, use `impl Fn(&str) + call_that` to return an opaque type, as long as you return a single underlying type +help: use `dyn` | -LL | fn call_this<F>(f: F) : impl Fn(&str) + call_that {} - | ++++ +LL | fn call_this<F>(f: F) : dyn Fn(&str) + call_that {} + | +++ error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/object-safety/avoid-ice-on-warning.rs b/tests/ui/object-safety/avoid-ice-on-warning.rs index d2a1eeb5286b0..5192da94216e1 100644 --- a/tests/ui/object-safety/avoid-ice-on-warning.rs +++ b/tests/ui/object-safety/avoid-ice-on-warning.rs @@ -1,6 +1,9 @@ +// revisions: old new +//[old] edition:2015 +//[new] edition:2021 fn call_this<F>(f: F) : Fn(&str) + call_that {} //~^ ERROR return types are denoted using `->` //~| ERROR cannot find trait `call_that` in this scope -//~| WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! +//[old]~| WARN trait objects without an explicit `dyn` are deprecated +//[old]~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! fn main() {} diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed deleted file mode 100644 index e95b982966d0b..0000000000000 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.fixed +++ /dev/null @@ -1,9 +0,0 @@ -// run-rustfix -#![deny(bare_trait_objects)] -fn ord_prefer_dot(s: String) -> impl Ord { - //~^ ERROR the trait `Ord` cannot be made into an object - (s.starts_with("."), s) -} -fn main() { - let _ = ord_prefer_dot(String::new()); -} diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed new file mode 100644 index 0000000000000..301c36c619139 --- /dev/null +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.fixed @@ -0,0 +1,16 @@ +// revisions: old new +//[old] edition:2015 +//[new] edition:2021 +//[new] run-rustfix +// FIXME: the test suite tries to create a crate called `bare_trait_dont_suggest_dyn.new` +#![crate_name="bare_trait_dont_suggest_dyn"] +#![deny(bare_trait_objects)] +fn ord_prefer_dot(s: String) -> impl Ord { + //~^ ERROR the trait `Ord` cannot be made into an object + //[old]~| ERROR trait objects without an explicit `dyn` are deprecated + //[old]~| WARNING this is accepted in the current edition (Rust 2015) + (s.starts_with("."), s) +} +fn main() { + let _ = ord_prefer_dot(String::new()); +} diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr similarity index 95% rename from tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr rename to tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr index 2c499d240ab0b..52db31d620c3d 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.stderr +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.new.stderr @@ -1,5 +1,5 @@ error[E0038]: the trait `Ord` cannot be made into an object - --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33 + --> $DIR/bare-trait-dont-suggest-dyn.rs:8:33 | LL | fn ord_prefer_dot(s: String) -> Ord { | ^^^ `Ord` cannot be made into an object diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr new file mode 100644 index 0000000000000..274d5a639a43b --- /dev/null +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.old.stderr @@ -0,0 +1,39 @@ +error: trait objects without an explicit `dyn` are deprecated + --> $DIR/bare-trait-dont-suggest-dyn.rs:8:33 + | +LL | fn ord_prefer_dot(s: String) -> Ord { + | ^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> +note: the lint level is defined here + --> $DIR/bare-trait-dont-suggest-dyn.rs:7:9 + | +LL | #![deny(bare_trait_objects)] + | ^^^^^^^^^^^^^^^^^^ +help: use `dyn` + | +LL | fn ord_prefer_dot(s: String) -> dyn Ord { + | +++ + +error[E0038]: the trait `Ord` cannot be made into an object + --> $DIR/bare-trait-dont-suggest-dyn.rs:8:33 + | +LL | fn ord_prefer_dot(s: String) -> Ord { + | ^^^ `Ord` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: the trait cannot be made into an object because it uses `Self` as a type parameter + ::: $SRC_DIR/core/src/cmp.rs:LL:COL + | + = note: the trait cannot be made into an object because it uses `Self` as a type parameter +help: consider using an opaque type instead + | +LL | fn ord_prefer_dot(s: String) -> impl Ord { + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs index fdf7e0a77aa34..64586b77b8c2b 100644 --- a/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs +++ b/tests/ui/object-safety/bare-trait-dont-suggest-dyn.rs @@ -1,7 +1,14 @@ -// run-rustfix +// revisions: old new +//[old] edition:2015 +//[new] edition:2021 +//[new] run-rustfix +// FIXME: the test suite tries to create a crate called `bare_trait_dont_suggest_dyn.new` +#![crate_name="bare_trait_dont_suggest_dyn"] #![deny(bare_trait_objects)] fn ord_prefer_dot(s: String) -> Ord { //~^ ERROR the trait `Ord` cannot be made into an object + //[old]~| ERROR trait objects without an explicit `dyn` are deprecated + //[old]~| WARNING this is accepted in the current edition (Rust 2015) (s.starts_with("."), s) } fn main() { diff --git a/tests/ui/traits/bound/not-on-bare-trait.stderr b/tests/ui/traits/bound/not-on-bare-trait.stderr index 8d0e40be788c1..6d56851bf3495 100644 --- a/tests/ui/traits/bound/not-on-bare-trait.stderr +++ b/tests/ui/traits/bound/not-on-bare-trait.stderr @@ -7,18 +7,10 @@ LL | fn foo(_x: Foo + Send) { = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html> = note: `#[warn(bare_trait_objects)]` on by default -help: use a new generic type parameter, constrained by `Foo + Send` +help: use `dyn` | -LL | fn foo<T: Foo + Send>(_x: T) { - | +++++++++++++++ ~ -help: you can also use an opaque type, but users won't be able to specify the type parameter when calling the `fn`, having to rely exclusively on type inference - | -LL | fn foo(_x: impl Foo + Send) { - | ++++ -help: alternatively, use a trait object to accept any type that implements `Foo + Send`, accessing its methods at runtime using dynamic dispatch - | -LL | fn foo(_x: &(dyn Foo + Send)) { - | +++++ + +LL | fn foo(_x: dyn Foo + Send) { + | +++ error[E0277]: the size for values of type `(dyn Foo + Send + 'static)` cannot be known at compilation time --> $DIR/not-on-bare-trait.rs:7:8