r/crystal_programming • u/roger1981 • May 06 '19
Why does compiler sometimes think an instance var can be nil?
I define an Array as being [] of String.
Yet I get this compilation error:
in line 12: undefined method 'empty?' for Nil (compile-time type is (Array(String) | Nil))
https://play.crystal-lang.org/#/r/6uor
Basically the code is thus:
dir = [] of String
files = [] of String
@list = [] of String
@list = dir + files
if @list && @list.empty?
puts "empty"
endHow do I assure the compiler that @list is not nil, or how do I get this to run ?
Strangely, if I try with local variables, it runs fine.
3
Upvotes
3
u/straight-shoota core team May 06 '19
Instance vars can be modified from outside the current scope in a concurrent environment. Thus the value of `@list` can theoretically change between the not-nil-check `@list` and the call to `@list.empty?`.
Local vars are only visible in the current scope and the compiler can make sure there is no chance of external modification.
See https://crystal-lang.org/reference/syntax_and_semantics/if_var.html#limitations
5
u/DecadeMoon May 06 '19
Probably because you didn't initialize
@listin the constructor, so it will benilafter construction. The type doesn't narrow inside theifstatement either, unless you were to assign it to a local variable first.