Skip to content

Unsize-coercible type 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

Labels

A-ZSTArea: Zero-sized types (ZSTs).A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)A-destructorsArea: Destructors (`Drop`, …)C-bugCategory: This is a bug.F-derive_coerce_pointeeFeature: RFC 3621's oft-renamed implementationT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions