Skip to content

Casting away lifetimes using closures #65700

Open
@alecmocatta

Description

@alecmocatta

The following code compiles on stable and nightly. I'm not sure it should as it's effectively casting a Struct::<'a> to a Struct::<'static> in safe code.

use std::{any::Any, marker::PhantomData};

fn main() {
    bad();
}

fn bad<'a>() -> Struct<'static> {
    make_static(|| Struct::<'a>(PhantomData))
}

struct Struct<'a>(PhantomData<&'a ()>);

fn make_static<A, B>(a: A) -> B
where
    A: FnOnce0 + 'static,
    B: 'static,
{
    let boxed: Box<dyn Any + 'static> = Box::new(a.call());
    *Box::<dyn Any + 'static>::downcast(boxed).unwrap()
}

trait FnOnce0 {
    type Output;
    fn call(self) -> Self::Output;
}

impl<F, O> FnOnce0 for F
where
    F: FnOnce() -> O,
{
    type Output = F::Output;
    fn call(self) -> Self::Output {
        self()
    }
}

(Playground)

It seems lifetime and type parameters that are used in the closure don't affect the lifetime of the closure itself. I stumbled upon this after noticing that || T::default() is 'static whereas T::default() is not.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)A-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions