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?

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)

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:

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