Return type only checked if the function is called

I was just playing with return types so I wrote this:

def is_odd(n : Int32) : Bool
  return n
end
x = is_odd(2)

This gave me the expected error: Error: method top-level is_odd must return Bool but it is returning Int32

but if I comment out the call of the function

def is_odd(n : Int32) : Bool
  return n
end
#x = is_odd(2)

then it compiles and runs fine.

Even though the problem is in the function and not in the call.

I wonder if this behavior is intentional?

Only body of used methods are included in the type check, add a call to is_odd even without using its return value and you will see a compilation error.

TL;DR; If you don’t use the function, why the compiler would bother checking if you wrote it right?

2 Likes

Thanks for the reply.

Theoretically, tests with good code coverage might help find wrong return types… so like if you have a test for every method… and if/when we again have a working code coverage tool. (See: Code Coverage Shard for Crystal - #7 by drhuffman12)

1 Like

The examples have type restrictions in the parameters so the reader think all the information is there. But parameters might not have type information, or it might not be a concrete type (eg: : Enumerable(T) vs : Array(T), or unbounded : Array).

So you need some call site to have concrete type for them.

In some places it could make sense to have a typeof(is_odd(uninitialized Int32)) as a test if you want to make sure it type checks. But is better if you have actual tests :see_no_evil:

1 Like

I guess if I use the function in a test then crystal will already complain so this question won’t be relevant then.

1 Like