From c2f49e9edf2bae4eaede9af13f5dfb80aacb04d1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 31 Oct 2023 11:31:08 +0000 Subject: [PATCH 1/6] Do not assert in op_to_const. --- .../rustc_const_eval/src/const_eval/eval_queries.rs | 4 ++-- tests/ui/mir/issue-117368-print-invalid-constant.rs | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 tests/ui/mir/issue-117368-print-invalid-constant.rs diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 669838308a558..cc8b10bd07d78 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -132,8 +132,8 @@ pub(super) fn op_to_const<'tcx>( // functionality.) _ => false, }; - let immediate = if force_as_immediate { - Right(ecx.read_immediate(op).expect("normalization works on validated constants")) + let immediate = if force_as_immediate && let Ok(imm) = ecx.read_immediate(op) { + Right(imm) } else { op.as_mplace_or_imm() }; diff --git a/tests/ui/mir/issue-117368-print-invalid-constant.rs b/tests/ui/mir/issue-117368-print-invalid-constant.rs new file mode 100644 index 0000000000000..d96103919410d --- /dev/null +++ b/tests/ui/mir/issue-117368-print-invalid-constant.rs @@ -0,0 +1,11 @@ +// build-pass +// compile-flags:-Zmir-opt-level=4 --emit=mir + +#![feature(allocator_api)] + +use std::alloc::{Allocator, Global, Layout}; + +fn main() { + let layout: Layout = None.unwrap(); + let ptr: *mut u8 = Global.allocate(layout).unwrap().as_ptr() as _; +} From a2e151ca4b3a90d3314997bc895fe9ce95a3ae0e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 31 Oct 2023 17:34:06 +0000 Subject: [PATCH 2/6] Make ui into mir-opt test. --- ...d_constant.main.GVN.32bit.panic-abort.diff | 127 ++++++++++++++++++ ..._constant.main.GVN.32bit.panic-unwind.diff | 92 +++++++++++++ ...d_constant.main.GVN.64bit.panic-abort.diff | 127 ++++++++++++++++++ ..._constant.main.GVN.64bit.panic-unwind.diff | 92 +++++++++++++ .../issue_117368_print_invalid_constant.rs | 15 +++ .../issue-117368-print-invalid-constant.rs | 11 -- 6 files changed, 453 insertions(+), 11 deletions(-) create mode 100644 tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff create mode 100644 tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff create mode 100644 tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff create mode 100644 tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff create mode 100644 tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs delete mode 100644 tests/ui/mir/issue-117368-print-invalid-constant.rs diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff new file mode 100644 index 0000000000000..e521b789b6007 --- /dev/null +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -0,0 +1,127 @@ +- // MIR for `main` before GVN ++ // MIR for `main` after GVN + + fn main() -> () { + let mut _0: (); + let _1: std::alloc::Layout; + let mut _2: std::option::Option; + let mut _3: *mut u8; + let mut _4: *mut [u8]; + let mut _5: std::ptr::NonNull<[u8]>; + let mut _6: std::result::Result, std::alloc::AllocError>; + let mut _7: &std::alloc::Global; + let mut _8: std::alloc::Layout; + scope 1 { + debug layout => _1; + let mut _9: &std::alloc::Global; + scope 2 { + debug ptr => _3; + } + scope 5 (inlined ::allocate) { + debug self => _9; + debug layout => _1; + } + scope 6 (inlined #[track_caller] Result::, std::alloc::AllocError>::unwrap) { + debug self => _6; + let mut _12: isize; + let _13: std::alloc::AllocError; + let mut _14: !; + let _15: &str; + let mut _16: &dyn std::fmt::Debug; + let mut _17: &std::alloc::AllocError; + scope 7 { + debug t => _5; + } + scope 8 { + debug e => const std::alloc::AllocError; + } + } + scope 9 (inlined NonNull::<[u8]>::as_ptr) { + debug self => _5; + let mut _18: *const [u8]; + } + } + scope 3 (inlined #[track_caller] Option::::unwrap) { + debug self => _2; + let mut _10: isize; + let mut _11: !; + scope 4 { + debug val => _1; + } + } + + bb0: { + StorageLive(_2); +- _2 = Option::::None; ++ _2 = const Option::::None; + StorageLive(_10); + _10 = const 0_isize; + switchInt(const 0_isize) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { + _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind unreachable; + } + + bb2: { + unreachable; + } + + bb3: { +- _1 = move ((_2 as Some).0: std::alloc::Layout); ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): ptr::alignment::AlignmentEnum32) }}; + StorageDead(_10); + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + _9 = const _; +- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageLive(_12); + StorageLive(_15); + _12 = discriminant(_6); + switchInt(move _12) -> [0: bb7, 1: bb5, otherwise: bb6]; + } + + bb5: { + _15 = const "called `Result::unwrap()` on an `Err` value"; + StorageLive(_16); + StorageLive(_17); + _17 = &_13; + _16 = move _17 as &dyn std::fmt::Debug (PointerCoercion(Unsize)); + StorageDead(_17); + _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable; + } + + bb6: { + unreachable; + } + + bb7: { + _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); + StorageDead(_15); + StorageDead(_12); + StorageDead(_6); + StorageLive(_18); + _18 = (_5.0: *const [u8]); + _4 = move _18 as *mut [u8] (PtrToPtr); + StorageDead(_18); + StorageDead(_5); + _3 = move _4 as *mut u8 (PtrToPtr); + StorageDead(_4); + StorageDead(_3); + return; + } + } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 00 __ __ __ __ │ ....░░░░ ++ } ++ ++ ALLOC1 (size: 0, align: 1) {} + diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff new file mode 100644 index 0000000000000..6966762a1b84f --- /dev/null +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff @@ -0,0 +1,92 @@ +- // MIR for `main` before GVN ++ // MIR for `main` after GVN + + fn main() -> () { + let mut _0: (); + let _1: std::alloc::Layout; + let mut _2: std::option::Option; + let mut _3: *mut u8; + let mut _4: *mut [u8]; + let mut _5: std::ptr::NonNull<[u8]>; + let mut _6: std::result::Result, std::alloc::AllocError>; + let mut _7: &std::alloc::Global; + let mut _8: std::alloc::Layout; + scope 1 { + debug layout => _1; + let mut _9: &std::alloc::Global; + scope 2 { + debug ptr => _3; + } + scope 5 (inlined ::allocate) { + debug self => _9; + debug layout => _1; + } + scope 6 (inlined NonNull::<[u8]>::as_ptr) { + debug self => _5; + let mut _12: *const [u8]; + } + } + scope 3 (inlined #[track_caller] Option::::unwrap) { + debug self => _2; + let mut _10: isize; + let mut _11: !; + scope 4 { + debug val => _1; + } + } + + bb0: { + StorageLive(_2); +- _2 = Option::::None; ++ _2 = const Option::::None; + StorageLive(_10); + _10 = const 0_isize; + switchInt(const 0_isize) -> [0: bb2, 1: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_6); + StorageLive(_12); + _12 = (_5.0: *const [u8]); + _4 = move _12 as *mut [u8] (PtrToPtr); + StorageDead(_12); + StorageDead(_5); + _3 = move _4 as *mut u8 (PtrToPtr); + StorageDead(_4); + StorageDead(_3); + return; + } + + bb2: { + _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; + } + + bb3: { + unreachable; + } + + bb4: { +- _1 = move ((_2 as Some).0: std::alloc::Layout); ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): ptr::alignment::AlignmentEnum32) }}; + StorageDead(_10); + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + _9 = const _; +- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb5, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(4 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x00000000): ptr::alignment::AlignmentEnum32) }}, const false) -> [return: bb5, unwind continue]; + } + + bb5: { + _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; + } + } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 00 __ __ __ __ │ ....░░░░ ++ } ++ ++ ALLOC1 (size: 0, align: 1) {} + diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff new file mode 100644 index 0000000000000..f6c4b785bf1ba --- /dev/null +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -0,0 +1,127 @@ +- // MIR for `main` before GVN ++ // MIR for `main` after GVN + + fn main() -> () { + let mut _0: (); + let _1: std::alloc::Layout; + let mut _2: std::option::Option; + let mut _3: *mut u8; + let mut _4: *mut [u8]; + let mut _5: std::ptr::NonNull<[u8]>; + let mut _6: std::result::Result, std::alloc::AllocError>; + let mut _7: &std::alloc::Global; + let mut _8: std::alloc::Layout; + scope 1 { + debug layout => _1; + let mut _9: &std::alloc::Global; + scope 2 { + debug ptr => _3; + } + scope 5 (inlined ::allocate) { + debug self => _9; + debug layout => _1; + } + scope 6 (inlined #[track_caller] Result::, std::alloc::AllocError>::unwrap) { + debug self => _6; + let mut _12: isize; + let _13: std::alloc::AllocError; + let mut _14: !; + let _15: &str; + let mut _16: &dyn std::fmt::Debug; + let mut _17: &std::alloc::AllocError; + scope 7 { + debug t => _5; + } + scope 8 { + debug e => const std::alloc::AllocError; + } + } + scope 9 (inlined NonNull::<[u8]>::as_ptr) { + debug self => _5; + let mut _18: *const [u8]; + } + } + scope 3 (inlined #[track_caller] Option::::unwrap) { + debug self => _2; + let mut _10: isize; + let mut _11: !; + scope 4 { + debug val => _1; + } + } + + bb0: { + StorageLive(_2); +- _2 = Option::::None; ++ _2 = const Option::::None; + StorageLive(_10); + _10 = const 0_isize; + switchInt(const 0_isize) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { + _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind unreachable; + } + + bb2: { + unreachable; + } + + bb3: { +- _1 = move ((_2 as Some).0: std::alloc::Layout); ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): ptr::alignment::AlignmentEnum64) }}; + StorageDead(_10); + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + _9 = const _; +- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb4, unwind unreachable]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageLive(_12); + StorageLive(_15); + _12 = discriminant(_6); + switchInt(move _12) -> [0: bb7, 1: bb5, otherwise: bb6]; + } + + bb5: { + _15 = const "called `Result::unwrap()` on an `Err` value"; + StorageLive(_16); + StorageLive(_17); + _17 = &_13; + _16 = move _17 as &dyn std::fmt::Debug (PointerCoercion(Unsize)); + StorageDead(_17); + _14 = result::unwrap_failed(move _15, move _16) -> unwind unreachable; + } + + bb6: { + unreachable; + } + + bb7: { + _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); + StorageDead(_15); + StorageDead(_12); + StorageDead(_6); + StorageLive(_18); + _18 = (_5.0: *const [u8]); + _4 = move _18 as *mut [u8] (PtrToPtr); + StorageDead(_18); + StorageDead(_5); + _3 = move _4 as *mut u8 (PtrToPtr); + StorageDead(_4); + StorageDead(_3); + return; + } + } ++ ++ ALLOC0 (size: 16, align: 8) { ++ 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ ++ } ++ ++ ALLOC1 (size: 0, align: 1) {} + diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff new file mode 100644 index 0000000000000..6501cb85e8a02 --- /dev/null +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff @@ -0,0 +1,92 @@ +- // MIR for `main` before GVN ++ // MIR for `main` after GVN + + fn main() -> () { + let mut _0: (); + let _1: std::alloc::Layout; + let mut _2: std::option::Option; + let mut _3: *mut u8; + let mut _4: *mut [u8]; + let mut _5: std::ptr::NonNull<[u8]>; + let mut _6: std::result::Result, std::alloc::AllocError>; + let mut _7: &std::alloc::Global; + let mut _8: std::alloc::Layout; + scope 1 { + debug layout => _1; + let mut _9: &std::alloc::Global; + scope 2 { + debug ptr => _3; + } + scope 5 (inlined ::allocate) { + debug self => _9; + debug layout => _1; + } + scope 6 (inlined NonNull::<[u8]>::as_ptr) { + debug self => _5; + let mut _12: *const [u8]; + } + } + scope 3 (inlined #[track_caller] Option::::unwrap) { + debug self => _2; + let mut _10: isize; + let mut _11: !; + scope 4 { + debug val => _1; + } + } + + bb0: { + StorageLive(_2); +- _2 = Option::::None; ++ _2 = const Option::::None; + StorageLive(_10); + _10 = const 0_isize; + switchInt(const 0_isize) -> [0: bb2, 1: bb4, otherwise: bb3]; + } + + bb1: { + StorageDead(_6); + StorageLive(_12); + _12 = (_5.0: *const [u8]); + _4 = move _12 as *mut [u8] (PtrToPtr); + StorageDead(_12); + StorageDead(_5); + _3 = move _4 as *mut u8 (PtrToPtr); + StorageDead(_4); + StorageDead(_3); + return; + } + + bb2: { + _11 = core::panicking::panic(const "called `Option::unwrap()` on a `None` value") -> unwind continue; + } + + bb3: { + unreachable; + } + + bb4: { +- _1 = move ((_2 as Some).0: std::alloc::Layout); ++ _1 = const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): ptr::alignment::AlignmentEnum64) }}; + StorageDead(_10); + StorageDead(_2); + StorageLive(_3); + StorageLive(_4); + StorageLive(_5); + StorageLive(_6); + _9 = const _; +- _6 = std::alloc::Global::alloc_impl(_9, _1, const false) -> [return: bb5, unwind continue]; ++ _6 = std::alloc::Global::alloc_impl(const {ALLOC1: &std::alloc::Global}, const Layout {{ size: Indirect { alloc_id: ALLOC0, offset: Size(8 bytes) }: usize, align: std::ptr::Alignment(Scalar(0x0000000000000000): ptr::alignment::AlignmentEnum64) }}, const false) -> [return: bb5, unwind continue]; + } + + bb5: { + _5 = Result::, std::alloc::AllocError>::unwrap(move _6) -> [return: bb1, unwind continue]; + } + } ++ ++ ALLOC0 (size: 16, align: 8) { ++ 00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░ ++ } ++ ++ ALLOC1 (size: 0, align: 1) {} + diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs new file mode 100644 index 0000000000000..c92424f298314 --- /dev/null +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs @@ -0,0 +1,15 @@ +// Verify that we do not ICE when printing an invalid constant. +// EMIT_MIR_FOR_EACH_BIT_WIDTH +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +#![feature(allocator_api)] + +use std::alloc::{Allocator, Global, Layout}; + +// EMIT_MIR issue_117368_print_invalid_constant.main.GVN.diff +fn main() { + // CHECK-LABEL: fn main( + // CHECK: debug layout => const Layout + let layout: Layout = None.unwrap(); + let ptr: *mut u8 = Global.allocate(layout).unwrap().as_ptr() as _; +} diff --git a/tests/ui/mir/issue-117368-print-invalid-constant.rs b/tests/ui/mir/issue-117368-print-invalid-constant.rs deleted file mode 100644 index d96103919410d..0000000000000 --- a/tests/ui/mir/issue-117368-print-invalid-constant.rs +++ /dev/null @@ -1,11 +0,0 @@ -// build-pass -// compile-flags:-Zmir-opt-level=4 --emit=mir - -#![feature(allocator_api)] - -use std::alloc::{Allocator, Global, Layout}; - -fn main() { - let layout: Layout = None.unwrap(); - let ptr: *mut u8 = Global.allocate(layout).unwrap().as_ptr() as _; -} From 3a55c283d0c050dc946fc799766f1c8b05df1572 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 31 Oct 2023 17:38:41 +0000 Subject: [PATCH 3/6] Rename hook. --- compiler/rustc_const_eval/src/const_eval/mod.rs | 2 +- compiler/rustc_const_eval/src/lib.rs | 4 ++-- compiler/rustc_middle/src/hooks/mod.rs | 2 +- compiler/rustc_middle/src/mir/pretty.rs | 2 +- src/tools/clippy/clippy_utils/src/consts.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index d6ee6975cddd5..6b85a1276f29d 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -72,7 +72,7 @@ pub(crate) fn eval_to_valtree<'tcx>( } #[instrument(skip(tcx), level = "debug")] -pub(crate) fn try_destructure_mir_constant_for_diagnostics<'tcx>( +pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>( tcx: TyCtxtAt<'tcx>, val: mir::ConstValue<'tcx>, ty: Ty<'tcx>, diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index 7d36e2eaefed6..1e21c49407074 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -54,8 +54,8 @@ pub fn provide(providers: &mut Providers) { let (param_env, raw) = param_env_and_value.into_parts(); const_eval::eval_to_valtree(tcx, param_env, raw) }; - providers.hooks.try_destructure_mir_constant_for_diagnostics = - const_eval::try_destructure_mir_constant_for_diagnostics; + providers.hooks.try_destructure_mir_constant_for_user_output = + const_eval::try_destructure_mir_constant_for_user_output; providers.valtree_to_const_val = |tcx, (ty, valtree)| { const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree) }; diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs index 34838ca4302f3..8588ae2033613 100644 --- a/compiler/rustc_middle/src/hooks/mod.rs +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -66,7 +66,7 @@ macro_rules! declare_hooks { declare_hooks! { /// Tries to destructure an `mir::Const` ADT or array into its variant index /// and its field values. This should only be used for pretty printing. - hook try_destructure_mir_constant_for_diagnostics(val: mir::ConstValue<'tcx>, ty: Ty<'tcx>) -> Option>; + hook try_destructure_mir_constant_for_user_output(val: mir::ConstValue<'tcx>, ty: Ty<'tcx>) -> Option>; /// Getting a &core::panic::Location referring to a span. hook const_caller_location(file: rustc_span::Symbol, line: u32, col: u32) -> mir::ConstValue<'tcx>; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 5f4ff22bc49ca..debd85dad2e02 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1713,7 +1713,7 @@ fn pretty_print_const_value_tcx<'tcx>( (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => { let ct = tcx.lift(ct).unwrap(); let ty = tcx.lift(ty).unwrap(); - if let Some(contents) = tcx.try_destructure_mir_constant_for_diagnostics(ct, ty) { + if let Some(contents) = tcx.try_destructure_mir_constant_for_user_output(ct, ty) { let fields: Vec<(ConstValue<'_>, Ty<'_>)> = contents.fields.to_vec(); match *ty.kind() { ty::Array(..) => { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 79c04c7c7f4a3..50a73745acb86 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -710,7 +710,7 @@ fn field_of_struct<'tcx>( field: &Ident, ) -> Option> { if let mir::Const::Val(result, ty) = result - && let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_diagnostics(result, ty) + && let Some(dc) = lcx.tcx.try_destructure_mir_constant_for_user_output(result, ty) && let Some(dc_variant) = dc.variant && let Some(variant) = adt_def.variants().get(dc_variant) && let Some(field_idx) = variant.fields.iter().position(|el| el.name == field.name) From 0f8f77fcc20cc5c44b5aa56b5e43620c0c44128e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 1 Nov 2023 16:55:18 +0000 Subject: [PATCH 4/6] Rebase fallout. --- ...8_print_invalid_constant.main.GVN.32bit.panic-abort.diff | 6 +----- ...8_print_invalid_constant.main.GVN.64bit.panic-abort.diff | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff index e521b789b6007..50189d192ceb2 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff @@ -85,7 +85,7 @@ StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); - switchInt(move _12) -> [0: bb7, 1: bb5, otherwise: bb6]; + switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb2]; } bb5: { @@ -99,10 +99,6 @@ } bb6: { - unreachable; - } - - bb7: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); StorageDead(_15); StorageDead(_12); diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff index f6c4b785bf1ba..08a185bad9cdb 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff @@ -85,7 +85,7 @@ StorageLive(_12); StorageLive(_15); _12 = discriminant(_6); - switchInt(move _12) -> [0: bb7, 1: bb5, otherwise: bb6]; + switchInt(move _12) -> [0: bb6, 1: bb5, otherwise: bb2]; } bb5: { @@ -99,10 +99,6 @@ } bb6: { - unreachable; - } - - bb7: { _5 = move ((_6 as Ok).0: std::ptr::NonNull<[u8]>); StorageDead(_15); StorageDead(_12); From 224e29030a2b576e011eace91e023aa64e99e454 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 1 Nov 2023 18:36:38 +0000 Subject: [PATCH 5/6] Specify diagnostic path. --- .../rustc_const_eval/src/const_eval/eval_queries.rs | 13 ++++++++++--- compiler/rustc_const_eval/src/const_eval/mod.rs | 2 +- .../rustc_const_eval/src/const_eval/valtrees.rs | 4 ++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index cc8b10bd07d78..b325814bcd77c 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -110,6 +110,7 @@ pub(crate) fn mk_eval_cx<'mir, 'tcx>( pub(super) fn op_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, 'tcx>, op: &OpTy<'tcx>, + for_diagnostics: bool, ) -> ConstValue<'tcx> { // Handle ZST consistently and early. if op.layout.is_zst() { @@ -132,8 +133,14 @@ pub(super) fn op_to_const<'tcx>( // functionality.) _ => false, }; - let immediate = if force_as_immediate && let Ok(imm) = ecx.read_immediate(op) { - Right(imm) + let immediate = if force_as_immediate { + match ecx.read_immediate(op) { + Ok(imm) => Right(imm), + Err(err) if !for_diagnostics => { + panic!("normalization works on validated constants: {err:?}") + } + _ => op.as_mplace_or_imm(), + } } else { op.as_mplace_or_imm() }; @@ -205,7 +212,7 @@ pub(crate) fn turn_into_const_value<'tcx>( ); // Turn this into a proper constant. - op_to_const(&ecx, &mplace.into()) + op_to_const(&ecx, &mplace.into(), /* for diagnostics */ false) } #[instrument(skip(tcx), level = "debug")] diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 6b85a1276f29d..e53282ffaeb66 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -99,7 +99,7 @@ pub(crate) fn try_destructure_mir_constant_for_user_output<'tcx>( let fields_iter = (0..field_count) .map(|i| { let field_op = ecx.project_field(&down, i).ok()?; - let val = op_to_const(&ecx, &field_op); + let val = op_to_const(&ecx, &field_op, /* for diagnostics */ true); Some((val, field_op.layout.ty)) }) .collect::>>()?; diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index d6dc1a62f4d0d..3aaaf08c85600 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -232,7 +232,7 @@ pub fn valtree_to_const_value<'tcx>( let mut ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, CanAccessStatics::No); let imm = valtree_to_ref(&mut ecx, valtree, *inner_ty); let imm = ImmTy::from_immediate(imm, tcx.layout_of(param_env_ty).unwrap()); - op_to_const(&ecx, &imm.into()) + op_to_const(&ecx, &imm.into(), /* for diagnostics */ false) } ty::Tuple(_) | ty::Array(_, _) | ty::Adt(..) => { let layout = tcx.layout_of(param_env_ty).unwrap(); @@ -265,7 +265,7 @@ pub fn valtree_to_const_value<'tcx>( dump_place(&ecx, &place); intern_const_alloc_recursive(&mut ecx, InternKind::Constant, &place).unwrap(); - op_to_const(&ecx, &place.into()) + op_to_const(&ecx, &place.into(), /* for diagnostics */ false) } ty::Never | ty::Error(_) From f512f91258a8df420598c968b604a922d277ea99 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 1 Nov 2023 19:01:55 +0000 Subject: [PATCH 6/6] Comment `for_diagnostics` flag. --- compiler/rustc_const_eval/src/const_eval/eval_queries.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index b325814bcd77c..7782cb8fd3850 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -106,6 +106,11 @@ pub(crate) fn mk_eval_cx<'mir, 'tcx>( } /// This function converts an interpreter value into a MIR constant. +/// +/// The `for_diagnostics` flag turns the usual rules for returning `ConstValue::Scalar` into a +/// best-effort attempt. This is not okay for use in const-eval sine it breaks invariants rustc +/// relies on, but it is okay for diagnostics which will just give up gracefully when they +/// encounter an `Indirect` they cannot handle. #[instrument(skip(ecx), level = "debug")] pub(super) fn op_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, 'tcx>,