Reputation: 908
I am trying to create a macro which initializes a struct T
using P::Child
from struct P
where P: Parent<Child = T>
.
macro_rules! init {
($t:tt, { $( $k:ident => $v:expr ),* }) => {
<$t as Parent>::Child {
$( $k: $v ),*
}
};
}
This macro passes the props as a map which is passed onto the struct's given constructor. Expanded, it would look like this:
#[derive(Debug)]
struct Apple {
a: i32
}
trait Parent {
type Child;
}
struct Mango;
impl Parent for Mango {
type Child = Apple;
}
fn main() {
let a = <Mango as Parent>::Child {
a: 4
};
println!("{:?}", a);
}
Compiling this has the error:
error: expected one of `.`, `::`, `;`, `?`, or an operator, found `{`
--> src/main.rs:25:38
|
25 | let a = <Mango as Parent>::Child {
| ^ expected one of `.`, `::`, `;`, `?`, or an operator here
I have created a macro to initialize a struct in a similar way but I am not able to do it with associated types. I think the compiler does not support it for some reason. Even so, I want to create a macro with such an API.
How could I approach this problem?
Upvotes: 4
Views: 362
Reputation: 1562
I don't think it is possible to initialize an associated type.
What you could do is perhaps have the Child: K
with K
being a trait having some known constructor (::new
etc ...), Then call that constructor instead.
Alternatively you can probably initialize a T
directly instead of Child
.
Upvotes: -1
Reputation: 59005
Like so:
macro_rules! init {
($t:ty, { $( $k:ident => $v:expr ),* }) => {
{
type T = <$t as Parent>::Child;
T {
$( $k: $v ),*
}
}
};
}
My assumption would be that this is a limitation of the parser, not of the compiler's type analysis.
Upvotes: 6