Skip to content

Commit 21b0e12

Browse files
authored
Rollup merge of #145277 - dingxiangfei2009:fold-coercion-into-const, r=nnethercote
Do not materialise X in [X; 0] when X is unsizing a const Fix#143671 It turns out that MIR builder materialise `X` in `[X; 0]` into a temporary local when `X` is unsizing a `const`. This led to a confusing call to destructor of `X` when such a destructor is declared. [Playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=8dfc933af89efeb89c881bc77498ba63) This patch may miss out other cases that we should avoid materialisation in case of `[X; 0]`. Suggestions to include is most welcome!
2 parents 2acd80c + b77de83 commit 21b0e12

2 files changed

Lines changed: 69 additions & 1 deletion

File tree

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

Lines changed: 23 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,27 @@ 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+
fncheck_constness(&self,mutkind:&'aExprKind<'tcx>) -> bool{
663+
loop{
664+
debug!(?kind,"check_constness");
665+
match kind {
666+
&ExprKind::ValueTypeAscription{source: eid,user_ty: _,user_ty_span: _ }
667+
| &ExprKind::Use{source: eid }
668+
| &ExprKind::PointerCoercion{
669+
cast:PointerCoercion::Unsize,
670+
source: eid,
671+
is_from_as_cast: _,
672+
}
673+
| &ExprKind::Scope{region_scope: _,lint_level: _,value: eid } => {
674+
kind = &self.thir[eid].kind
675+
}
676+
_ => returnmatches!(Category::of(&kind),Some(Category::Constant)),
677+
}
678+
}
679+
}
680+
659681
fnbuild_zero_repeat(
660682
&mutself,
661683
mutblock:BasicBlock,
@@ -666,7 +688,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
666688
let this = self;
667689
let value_expr = &this.thir[value];
668690
let elem_ty = value_expr.ty;
669-
ifletSome(Category::Constant) = Category::of(&value_expr.kind){
691+
ifthis.check_constness(&value_expr.kind){
670692
// Repeating a const does nothing
671693
}else{
672694
// For a non-const, we may need to generate an appropriate `Drop`
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
use std::rc::Weak;
10+
11+
#[repr(transparent)]
12+
structX<'a,T: ?Sized>{
13+
f:&'aT,
14+
}
15+
16+
impl<'a,T: ?Sized>DropforX<'a,T>{
17+
fndrop(&mutself){
18+
panic!()
19+
}
20+
}
21+
22+
impl<'a,T: ?Sized + Unsize<U>,U: ?Sized>CoerceUnsized<X<'a,U>>forX<'a,T>where
23+
&'aT:CoerceUnsized<&'aU>
24+
{
25+
}
26+
27+
constY:X<'static,i32> = X{f:&0};
28+
29+
fnmain(){
30+
let _:[X<'static,dynDisplay>;0] = [Y;0];
31+
coercion_on_weak_in_const();
32+
coercion_on_weak_as_cast();
33+
}
34+
35+
fncoercion_on_weak_in_const(){
36+
constX:Weak<i32> = Weak::new();
37+
constY:[Weak<dynSend>;0] = [X;0];
38+
let _ = Y;
39+
}
40+
41+
fncoercion_on_weak_as_cast(){
42+
constY:X<'static,i32> = X{f:&0};
43+
// What happens in the following code is that
44+
// a constant is explicitly coerced into
45+
let _a:[X<'static,dynDisplay>;0] = [YasX<'static,dynDisplay>;0];
46+
}

0 commit comments

Comments
 (0)