I think this is working as expected. You declare the ivar as @x : X? so to the compiler @x can be nil. However, def initialize(@x : X) is short for doing @x = x in the method body. So I think you really could just do
def initialize(@x : X)
@x_y = x.y
and it should just work. since it’ll be using the implicit x argument to initialize that is not nilable versus the @x instance var which is nilable.
Or just make @x not nilable like it is in the constructor via @x : X.
The compiler does this because, generally speaking, it has to account for times where the instance variable can change between two lines of code because that change can occur in another fiber/thread.
On one hand, it makes a lot of sense for the compiler to be extra safe. On the other hand, I don’t know that it makes sense to apply this particular safeguard to initialize specifically. Other fibers/threads aren’t going to change my object while it’s being initialized because they can’t possibly hold a reference to it because even my current call stack won’t have a reference to it until after the initialize method returns.
Unfortunately (for this case, at least — it’s arguably a good thing in general), there is no guarantee that initialize will only be called during object initialization. There is nothing stopping you from calling it later. In fact, that’s exactly how my Redis client implements self-healing — if you get disconnected from the server, it will reconnect and retry the command.
So it seems unintuitive, but the compiler is doing the best thing (or least bad, depending on your perspective) considering all other aspects of the current compiler implementation. Maybe the compiler could detect that initialize is only ever called downstream from new and relax that constraint a bit, but the implicit local variable is a pretty solid workaround.
You can absolutely do this by redefining .new to use the newly allocated blob of memory before calling #initialize on it. Your .new might not even call #initialize at all. I don’t think #initialize should be specially handled in this regard