I'm writing a test that checks coordinates of a point to have a certain value, e.g.:
it "should work" do
p = do_something # returns a Point(x, y)
p.x.should eq 0 # errors (see below)
end
But it fails to compile with the following error:
Error: undefined method 'x' for Nil (compile-time type is (Point | Nil))
I was able to reduce the issue to the following minimal example which does not compile:
struct Point
property x : Int32
property y : Int32
def initialize(@x, @y)
end
end
begin
p = Point.new 0, 0
ensure
p.x == 0
end
Which throws the same error:
❯ crystal src/debug.cr
Showing last frame. Use --error-trace for full trace.
In src/debug.cr:11:7
11 | p.x == 0
^
Error: undefined method 'x' for Nil (compile-time type is (Point | Nil))
Now, I came across a similar bug report on the programming language Github tracker: Nil type check fails when using ensure, apparently this is an issue that has to be addressed by the Crystal language.
My question is, how can I check the value of p.x
without triggering this error in an ensure
block? I'm kind of clueless how to access this.
For context, I'm writing a cryptographic library which operates on points on the an elliptic curve, so it's everything about checking the coordinates here.
There is a couple of possibilities here, e.g. you can replace the line p.x == 0
with either of:
p.try &.x == 0
- p
will be checked for being Nil
, and only when it's not Nil
, the comparison will run.p.not_nil!.x == 0
- you command the compiler that p
can never be Nil
, but if it actually happens to be nil
, the line will raise at runtime.