Skip to content

Commit 6a64501

Browse files
do not materialise X in [X; 0] when X is unsizing a const
1 parent fce0e74 commit 6a64501

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_middle::middle::region;
88
use rustc_middle::mir::interpret::Scalar;
99
use rustc_middle::mir::*;
1010
use rustc_middle::thir::*;
11+
use rustc_middle::ty::adjustment::PointerCoercion;
1112
use rustc_middle::ty::cast::{CastTy, mir_cast_kind};
1213
use rustc_middle::ty::util::IntTypeExt;
1314
use rustc_middle::ty::{self, Ty, UpvarArgs};
@@ -656,6 +657,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
656657
block.and(rvalue)
657658
}
658659

660+
/// Recursively inspect a THIR expression and probe through unsizing
661+
/// operations that can be const-folded today.
662+
fn check_constness(&self, mut ek: &'a ExprKind<'tcx>) -> bool {
663+
loop {
664+
match ek {
665+
&ExprKind::PointerCoercion {
666+
cast: PointerCoercion::Unsize,
667+
source: eid,
668+
is_from_as_cast: _,
669+
}
670+
| &ExprKind::Scope { region_scope: _, lint_level: _, value: eid } => {
671+
ek = &self.thir[eid].kind
672+
}
673+
_ => return matches!(Category::of(&ek), Some(Category::Constant)),
674+
}
675+
}
676+
}
677+
659678
fn build_zero_repeat(
660679
&mut self,
661680
mut block: BasicBlock,
@@ -666,7 +685,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
666685
let this = self;
667686
let value_expr = &this.thir[value];
668687
let elem_ty = value_expr.ty;
669-
if let Some(Category::Constant) = Category::of(&value_expr.kind) {
688+
if this.check_constness(&value_expr.kind) {
670689
// Repeating a const does nothing
671690
} else {
672691
// For a non-const, we may need to generate an appropriate `Drop`

tests/ui/coercion/issue-143671.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//@ run-pass
2+
3+
#![feature(unsize)]
4+
#![feature(coerce_unsized)]
5+
6+
use std::fmt::Display;
7+
use std::marker::Unsize;
8+
use std::ops::CoerceUnsized;
9+
10+
#[repr(transparent)]
11+
struct X<'a, T: ?Sized> {
12+
f: &'a T,
13+
}
14+
15+
impl<'a, T: ?Sized> Drop for X<'a, T> {
16+
fn drop(&mut self) {
17+
panic!()
18+
}
19+
}
20+
21+
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<X<'a, U>> for X<'a, T> where
22+
&'a T: CoerceUnsized<&'a U>
23+
{
24+
}
25+
26+
const Y: X<'static, i32> = X { f: &0 };
27+
28+
fn main() {
29+
let _: [X<'static, dyn Display>; 0] = [Y; 0];
30+
}

0 commit comments

Comments
 (0)