Ah -- your -> impl Key<'b>
threw me off.
Let's ignore the lifetimes for a second and indicate we're returning the same type otherwise:
-fn make_new_key<'a, 'b, K : Key<'a>>(template : &K, lifetime_holder : &'b usize) -> impl Key<'b>
+fn make_new_key<'a, 'b, K : Key<'a>>(template : &K, lifetime_holder : &'b usize) -> K
{
let new_key = template.clone();
- unsafe { transmute::<K, ????>(new_key) }
+ unsafe { transmute::<K, _>(new_key) }
}
We still get "error[E0512]: cannot transmute between types of different sizes, or dependently-sized types". Which I take to mean, transmuting a generic is expressly forbidden. We could just stop there, but let's continue exploring some...
What if transmute
wasn't limited like this? You're still not really trying to change the lifetime of K
as written. The 'a
on make_new_key
fills a type parameter on the Key
trait. But
// the lifetime of the implementer (`&'a str`)
// and the lifetime of the trait implementation (`Key<'a>`)
// are the same
impl<'a> Key<'a> for &'a str {}
is not the only possibility. For example,
impl<'a> Key<'static> for &'a i32 {}
impl<'a, 'b> Key<'a> for &'b usize {}
impl<'a> Key<'a> for &'static Vec<bool> {}
So there's not necessarily a direct correlation between the lifetimes. And you can't change what a type is or isn't implemented for. So maybe you meant something closer to this:
fn make_new_key<'a, 'b, K: 'a + Key<'a>>(template : &K, lifetime_holder : &'b usize) -> K: 'b
// new ^^^^ new ^^^^
{ todo!() }
You'll get an error about the return type: it doesn't know what to make of that bound.
And it turns out, this approach cannot work either, because lifetime bounds are descriptive and not prescriptive. There's not a way to change the bound that the compiler has calculated.
So when can you change the lifetime (ignoring soundness)? When the lifetime is part of the type, and not a bound.
I don't think there's any way to do it with a generic which may or may not have a lifetime parameter (or many!) as part of its type, depending on the caller.