- 
                Notifications
    You must be signed in to change notification settings 
- Fork 13.9k
Description
I tried this code, before #145277, courtesy of @traviscross in a comment:
use core::{mem, ptr, sync::atomic::{AtomicU64, Ordering}};
static COUNT: AtomicU64 = AtomicU64::new(0);
struct S;
impl Drop for S {
    fn drop(&mut self) {
        COUNT.fetch_add(1, Ordering::Relaxed);
    }
}
trait Tr {}
impl Tr for S {}
const X: Box<dyn Tr> = unsafe {
    mem::transmute::<_, Box<S>>(ptr::dangling_mut::<S>())
};
const fn x() -> Box<dyn Tr> { X }
fn main() {
    assert_eq!(0, COUNT.load(Ordering::Relaxed));
    let _: [Box<dyn Tr>; 0] = [X as Box<dyn Tr>; 0]; //~ Drops.
    assert_eq!(1, COUNT.load(Ordering::Relaxed));
    let _ = [X as Box<dyn Tr>; 0]; //~ Drops.
    assert_eq!(2, COUNT.load(Ordering::Relaxed));
    let _: [Box<dyn Tr>; 0] = [X; 0]; //~ Drops.
    assert_eq!(3, COUNT.load(Ordering::Relaxed));
    let _: [Box<dyn Tr>; 0] = [x(); 0]; //~ Drops.
    assert_eq!(4, COUNT.load(Ordering::Relaxed));
    let _ = [x(); 0]; //~ Drops.
    assert_eq!(5, COUNT.load(Ordering::Relaxed));
    let _ = [const { x() }; 0]; //~ Doesn't drop.
    assert_eq!(5, COUNT.load(Ordering::Relaxed));
    let _ = [const { x() as Box<dyn Tr> }; 0]; //~ Doesn't drop.
    assert_eq!(5, COUNT.load(Ordering::Relaxed));
    let _ = [const { x() } as Box<dyn Tr>; 0]; //~ Drops.
    assert_eq!(6, COUNT.load(Ordering::Relaxed));
}I expected to see this happen: every assert_eq! should trigger
Instead, this happened: execution passes
The reason I am opening this issue is to discuss a comprehensive plan to resolve the remaining concern over #145277. We would discover more corner cases and it would become unmanagable if we have to fix these cases one at a time.
Problem statement
Current MIR building from THIR, when repeat expression [$expr; $const] is concerned, needs to know the following information to decide how this kind of expression would be lowered:
- whether the constant $consttakes a value of0,1or anything else
- whether $exprhas aCopytype
- whether $expris a const-promotable
 The prominent feature of the lowering is whether$exprshall be "built" for evaluation. If$expris materialised, it has significance such that adropis mandatory. However, the materialisation can be superfluous if the value would not end up used in the repeat expression because$constcould be statically evaluated to0; or thedropis unnecessary because$constcould be statically evaluated to1.
| type of $expr\ compile-time value of$const | 0 | 1 | any | 
|---|---|---|---|
| .. is const-promotable or implements Copy | should not materialise | materialise once | materialise multiple times | 
| otherwise | materialise and drop | materialise exactly once | reject | 
However, determine whether $expr is const-promotable happens after the MIR building. The MIR builder has to apply a simple, but not satisfyingly comprehensive, check to decide which case in the table above shall be applicable.