for
class Y
def initialize(@a : String)
end
getter a
end
class X
macro test(name)
@{{name}} = y.{{name}}
end
@a : String
def initialize(y : Y)
test a
end
end
I got
instance variable '@a' of X was not initialized directly in all of the 'initialize' methods, rendering it nilable. Indirect initialization is not supported.
why? and set @a to nil did solve the problem but that's not a good workaround in my opinion.
Is it a bug, a design limit or just I'm not doing the right thing?
Yes, currently this is a design limitation. Quoting Ary from https://github.com/crystal-lang/crystal/issues/2731
Yes, this is expected behaviour. initialize must be simple enough for the compiler to analyze. A macro might be redefined in a subclass so resolving init is not trivial for a first pass.
This is a "won't fix" for me, or maybe we can mark it as an enhancement, but it won't happen soon (maybe never)
There's a hack I introduced to make initialization via macro possible: if
{{@type}}
is mentioned then the compiler will lazily check the method on call. It's not documented, though. And it has several bugs. But for now it might be okay.