This tuple struct has the constructor with the same name:
let h: Holder = Holder(&123);
But I cannot figure out what type this constructor has (except it is a function). The following code compiles, but I want to substitute gaps with real types.
let ctor: fn(_) -> _ = Holder;
let h: Holder = ctor(&123);
I tried to use for<'a>, but it doesn't work the way I thought:
let ctor: for<'a> fn(&'a u8) -> Holder<'a> = Holder;
let h: Holder = ctor(&123);
The error hints that "concrete lifetime" != "bound lifetime":
|
6 | let ctor: for<'a> fn(&'a u8) -> Holder<'a> = Holder;
| ^^^^^^ expected concrete lifetime, found bound lifetime parameter 'a
|
= note: expected type `for<'a> fn(&'a u8) -> Holder<'a>`
found type `fn(&u8) -> Holder<'_> {Holder::<'_>}`
But I still don't have a clue how to solve the puzzle.
Initially, I wanted to accept the ctor as a (generic) function parameter, so I needed to fill Fn(_) -> _ with some types too. I'm pretty sure that doesn't differ from function pointer significantly, does it?
The constructor will like all other functions and closures have its own unique type. As for the for<'a> conversion, normally these unique types will coerce into function pointers, but the coercion doesn't seem to properly work when for<'a> is involved.
Initially I needed a way to wrap a reference into a generic holder so that
holder's lifetime ≠ referenced object's lifetime
holder constructor (aka struct initializer) is a generic function parameter
That's why I was trying to figure out the type of that function parameter. And faced with a lifetime problem.
From @jonh's answer I got the idea that I had to introduce an extra function specifically to solve this lifetime stuck, since "function with lifetime parameters" is exactly the thing to specify lifetimes =)
So I can introduce the function:
fn foo<'a, F>(x: &'a u8, ctor: F)
where F: FnOnce(&'a u8) -> Holder<'a> {
let h = ctor(x);
// use this "h" somehow
}
and then replace
let ctor: fn(_) -> _ = Holder;
let h: Holder = ctor(&123);
with
foo(&123, Holder);
Now I see that I had to call this function with both reference and struct ctor, otherwise compiler won't guess the (elided) lifetime of that second argument Holder of foo.
As far as I understand, there is no way to do something like this:
fn foo<F>(ctor: F)
where F: for<'a> FnOnce(&'a u8) -> Holder<'a> {
let x = 123;
let h = ctor(&x);
}
fn main() {
foo(Holder); // mean some Holder<'_> instead of Holder<'concrete>
}