PhantomData and the drop check

This question is inspired by a question that came up on @jonhoo 's recent stream on the drop check. Why do these two functions behave differently? (playground link) As far as I can tell, both Wrap<T> types should have the same variance and drop check behavior, but one of them causes a drop check error and the other doesn't. (Note that adding drop(_it) at the end of the function makes them both fail.)

use std::marker::PhantomData;

struct Droppy<'a>(&'a mut i32);
impl<'a> Drop for Droppy<'a> { fn drop(&mut self) {} }

fn works() {
    struct Wrap<T>(PhantomData<T>);
    fn wrap<T>(_: T) -> Wrap<T> { Wrap(PhantomData) }

    let mut a = 42;
    let _it = wrap(Droppy(&mut a));
    println!("{}", a);
}

fn fails() {
    struct Wrap<T>(T);
    fn wrap<T>(t: T) -> Wrap<T> { Wrap(t) }

    let mut a = 42;
    let _it = wrap(Droppy(&mut a));
    println!("{}", a);
}
3 Likes

Hmm, in fails, Wrap<Droppy<&mut i32>> actually has drop glue, whereas in works, it doesn't. PhantomData doesn't actually implement Drop.

Also noteworthy that both work with #[may_dangle]

2 Likes

See issue 70841.

4 Likes