From c1ab3edcc4304c12ecf12e57c5b60fac9b5b109a Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Tue, 12 Aug 2025 06:39:50 +0800 Subject: [PATCH 1/2] do not materialise X in [X; 0] when X is unsizing a const --- .../src/builder/expr/as_rvalue.rs | 21 ++++++++++++- ...no_local_for_coerced_const-issue-143671.rs | 30 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 tests/ui/coercion/no_local_for_coerced_const-issue-143671.rs diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs index a4ef6e9273921..d6dc12e5955a5 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs @@ -8,6 +8,7 @@ use rustc_middle::middle::region; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::*; use rustc_middle::thir::*; +use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::cast::{CastTy, mir_cast_kind}; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, Ty, UpvarArgs}; @@ -656,6 +657,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(rvalue) } + /// Recursively inspect a THIR expression and probe through unsizing + /// operations that can be const-folded today. + fn check_constness(&self, mut kind: &'a ExprKind<'tcx>) -> bool { + loop { + match kind { + &ExprKind::PointerCoercion { + cast: PointerCoercion::Unsize, + source: eid, + is_from_as_cast: _, + } + | &ExprKind::Scope { region_scope: _, lint_level: _, value: eid } => { + kind = &self.thir[eid].kind + } + _ => return matches!(Category::of(&kind), Some(Category::Constant)), + } + } + } + fn build_zero_repeat( &mut self, mut block: BasicBlock, @@ -666,7 +685,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let this = self; let value_expr = &this.thir[value]; let elem_ty = value_expr.ty; - if let Some(Category::Constant) = Category::of(&value_expr.kind) { + if this.check_constness(&value_expr.kind) { // Repeating a const does nothing } else { // For a non-const, we may need to generate an appropriate `Drop` diff --git a/tests/ui/coercion/no_local_for_coerced_const-issue-143671.rs b/tests/ui/coercion/no_local_for_coerced_const-issue-143671.rs new file mode 100644 index 0000000000000..eb814e9723c1c --- /dev/null +++ b/tests/ui/coercion/no_local_for_coerced_const-issue-143671.rs @@ -0,0 +1,30 @@ +//@ run-pass + +#![feature(unsize)] +#![feature(coerce_unsized)] + +use std::fmt::Display; +use std::marker::Unsize; +use std::ops::CoerceUnsized; + +#[repr(transparent)] +struct X<'a, T: ?Sized> { + f: &'a T, +} + +impl<'a, T: ?Sized> Drop for X<'a, T> { + fn drop(&mut self) { + panic!() + } +} + +impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized> for X<'a, T> where + &'a T: CoerceUnsized<&'a U> +{ +} + +const Y: X<'static, i32> = X { f: &0 }; + +fn main() { + let _: [X<'static, dyn Display>; 0] = [Y; 0]; +} From 8444dde8f1c5e7f911d728a4a1542437382164f6 Mon Sep 17 00:00:00 2001 From: Ding Xiang Fei Date: Wed, 13 Aug 2025 02:26:04 +0800 Subject: [PATCH 2/2] add test fixture for newly allowed const expr Signed-off-by: Ding Xiang Fei Co-authored-by: Theemathas Chirananthavat --- .../coercion/no_local_for_coerced_const-issue-143671.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/ui/coercion/no_local_for_coerced_const-issue-143671.rs b/tests/ui/coercion/no_local_for_coerced_const-issue-143671.rs index eb814e9723c1c..5924809f34c85 100644 --- a/tests/ui/coercion/no_local_for_coerced_const-issue-143671.rs +++ b/tests/ui/coercion/no_local_for_coerced_const-issue-143671.rs @@ -6,6 +6,7 @@ use std::fmt::Display; use std::marker::Unsize; use std::ops::CoerceUnsized; +use std::rc::Weak; #[repr(transparent)] struct X<'a, T: ?Sized> { @@ -27,4 +28,11 @@ const Y: X<'static, i32> = X { f: &0 }; fn main() { let _: [X<'static, dyn Display>; 0] = [Y; 0]; + coercion_on_weak_in_const(); +} + +fn coercion_on_weak_in_const() { + const X: Weak = Weak::new(); + const Y: [Weak; 0] = [X; 0]; + let _ = Y; }