# Type bug?

**URL:** <https://forum.crystal-lang.org/t/type-bug/6512>\
**Category:** Help & Support\
**Created:** [February 3, 2024, 9:25pm UTC](https://forum.crystal-lang.org/t/type-bug/6512 "2024-02-03T21:25:32Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Xen](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/xen/32/2288_2.png) [@Xen](https://forum.crystal-lang.org/u/Xen)\
**Post date:** [February 3, 2024, 9:25pm UTC](https://forum.crystal-lang.org/t/type-bug/6512/1 "2024-02-03T21:25:33Z")

</div>

Take this:

```auto
class X
  property y : String
  
  def initialize(@y) end
end

class Test
  @x : X?
  @x_y: String
  
  def initialize(@x : X)
    @x_y = @x.y
  end
end

Test.new(X.new("test"))

```

And we get

```auto
Error: undefined method 'y' for Nil (compile-time type is (X | Nil))

```

Obviously, the compiler is looking at the type of the instance var, but ought this not work?

Of course it can be fixed with

```auto
  def initialize(x : X)
    @x = x
    @x_y = x.y
  end

```

but that feels a bit stupid.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [February 3, 2024, 10:33pm UTC](https://forum.crystal-lang.org/t/type-bug/6512/2 "2024-02-03T22:33:43Z")

</div>

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

```crystal
  def initialize(@x : X)
    @x_y = x.y
  end

```

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`.

---

<div class="post-metadata">

**Author:** ![jgaskins](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jgaskins/32/2449_2.png) [@jgaskins](https://forum.crystal-lang.org/u/jgaskins)\
**Post date:** [February 3, 2024, 11:23pm UTC](https://forum.crystal-lang.org/t/type-bug/6512/3 "2024-02-03T23:23:37Z")

</div>

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](https://jgaskins.dev/redis/) implements self-healing — if you get disconnected from the server, it will [reconnect and retry the command](https://github.com/jgaskins/redis/blob/v0.9.0/src/connection.cr#L363).

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.

---

<div class="post-metadata">

**Author:** ![Xen](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/xen/32/2288_2.png) [@Xen](https://forum.crystal-lang.org/u/Xen)\
**Post date:** [February 3, 2024, 11:50pm UTC](https://forum.crystal-lang.org/t/type-bug/6512/4 "2024-02-03T23:50:36Z")

</div>

> [@jgaskins](#):
>
> implicit local variable

Oho, didn’t realize that `@x` still defines a local variable with the type of the parameter. Works for me!

---

<div class="post-metadata">

**Author:** ![HertzDevil](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hertzdevil/32/1023_2.png) [@HertzDevil](https://forum.crystal-lang.org/u/HertzDevil)\
**Post date:** [February 3, 2024, 11:51pm UTC](https://forum.crystal-lang.org/t/type-bug/6512/5 "2024-02-03T23:51:58Z")

</div>

> [@jgaskins](#):
>
> 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.

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

---

<div class="post-metadata">

**Author:** ![jgaskins](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jgaskins/32/2449_2.png) [@jgaskins](https://forum.crystal-lang.org/u/jgaskins)\
**Post date:** [February 4, 2024, 12:36am UTC](https://forum.crystal-lang.org/t/type-bug/6512/6 "2024-02-04T00:36:52Z")

</div>

> [@HertzDevil](#):
>
> You can absolutely do this by redefining `.new` to use the newly allocated blob of memory before calling `#initialize` on it

One of the hard parts about static languages is providing guarantees for all the weird stuff that _shouldn’t_ happen but can because there’s nothing preventing someone from doing them.
