Skip to content

#[derive(CoercePointee)] causes [SOME_CONST; 0] to execute Drop, but only if type is annotated. #143671

Open
@theemathas

Description

@theemathas

I tried this code:

#![feature(derive_coerce_pointee)]

use std::marker::CoercePointee;
use std::any::type_name;

trait Trait {}
impl Trait for i32 {}

#[derive(CoercePointee)]
#[repr(transparent)]
struct WithCoerce<T: ?Sized + 'static> {
    value: &'static T
}

impl<T: ?Sized + 'static> Drop for WithCoerce<T> {
    fn drop(&mut self) {
        println!("dropping {}", type_name::<Self>());
    }
}

struct NoCoerce<T: ?Sized + 'static> {
    value: &'static T
}

impl<T: ?Sized + 'static> Drop for NoCoerce<T> {
    fn drop(&mut self) {
        println!("dropping {}", type_name::<Self>());
    }
}

const X: WithCoerce<dyn Trait> = WithCoerce { value: &1 };
const Y: NoCoerce<dyn Trait> = NoCoerce { value: &1 };

fn main() {
    println!("Runs Drop for some reason:");
    let _a: [WithCoerce<dyn Trait>; 0] = [X; 0];
    println!("Without type annotation (no Drop):");
    let _b = [X; 0];
    println!("Without CoercePointee (no Drop):");
    let _c: [NoCoerce<dyn Trait>; 0] = [Y; 0];
    println!("Done");
}

I expected to see this happen: Either all three arrays cause a Drop, or none of them cause a Drop

Instead, this happened: Only the _a line caused a Drop, with the following output:

Runs Drop for some reason:
dropping playground::WithCoerce<dyn playground::Trait>
Without type annotation (no Drop):
Without CoercePointee (no Drop):
Done

Related to #79580, which talks about the behavior of [SOME_CONST; 0] in general being weird.

Possibly related to #140123, where, among other things, annotating the type of a variable causes an extra no-op unsize coercion to be inserted before constructing the array.

Tracking issue for CoercePointee: #123430

Meta

Reproducible on the playground with 1.90.0-nightly (2025-07-08 ab68b0fb26485ab1fa69)

@rustbot labels +A-const-eval +A-destructors +A-zst +F-derive_coerce_pointee

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)A-destructorsArea: Destructors (`Drop`, …)A-zstArea: Zero-sized types (ZSTs).C-bugCategory: This is a bug.F-derive_coerce_pointeeFeature: RFC 3621's oft-renamed implementationneeds-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions