6
votes

I'm trying to write a Rust function that casts an input from one lifetime constraint to a same-typed output with a global lifetime constraint (conceptually something like unsafe fn foo<'a, T1, T2>(x: T1) -> T2 where T1: 'a, T2 = T1 + 'static), but I can't quite figure out how to write it without adding indirection layers like Box. Any ideas?

More generally, I'm trying to implement an unsafe thread::scoped in terms of mem::transmute and thread::spawn. spawn requires 'static bounds on its T and F parameters, but scoped does/should not.

2
unsafe fn foo<'a, T>(x: T + 'a) -> T + 'static doesn’t make sense—it’s not syntactically valid. What are you actually writing?Chris Morgan
It should take an input of some type with some lifetime constraint, and return an output of the same type with a global lifetime constraint. I've tried to clarify the post, but if I knew the correct syntax for the signature, I wouldn't have a problem - I could just mem::transmute.bfops
Are you talking about things like Box<Any + 'static>? Those only make sense for trait objects. Or do you mean bounds such as fn no_borrows<T: 'static>(x: T) -> T { x }?user395760
More like the latter. I want to cast from a version of T with one lifetime to a version of T with a greater lifetime. (unsafely, of course).bfops
@bfops: what you are describing now is simply not possible. A type satisfies a certain lifetime requirement, which is known statically. There can be no transmutation or such things between them. For the concept of your T2 to exist, T1 must be 'static already. What you seem to be trying to implement is flatly impossible and always will be.Chris Morgan

2 Answers

9
votes

Although I had a similar problem, I do not recommend extending lifetime constraints. It's almost certain that a different approach is in order for situations where this comes up.

That said, you can extend a lifetime in the latest Rust stable (1.29.0 as of this writing) via std::mem::transmute.

Example from the docs (with the caveat "This is advanced, very unsafe Rust!"):

struct R<'a>(&'a i32);
unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
    std::mem::transmute::<R<'b>, R<'static>>(r)
}
2
votes

What you are describing now is simply not possible. A type satisfies a certain lifetime requirement, which is known statically. There can be no transmutation or such things between them. For the concept of your T2 to exist, T1 must be 'static already. What you seem to be trying to implement is flatly impossible and always will be.

It is possible to implement scoped using unsafe code, but it is not possible to implement it in terms of thread::spawn. You can take a look at the source code of thread::scoped in Rust 1.3.0 to see how this was done. Be aware that thread::scoped was removed because it had soundness issues, so it isn't a perfect example to copy wholesale.