If it's a bug, it's by design. Note that this only happens with local variables (rather than instance, class or global variables) according to David Black's The Well-Grounded Rubyist, page 153 ("Assignment syntax in condition bodies and tests" - everything that follows, including emphasis is from the book):
Ruby doesn't draw as clear a line as compiled languages do between "compile time" and "run time," but the interpreter does parse your code before running it, and certain decisions are made during that process. An important one is the recognition and allocation of local variables.
When the Ruby parser sees the sequence identifier, equal-sign, value, as in this expression
x = 1
it allocates space for a local variable called x. The creation of the variable - not the assignment to it, but the internal creation of a variable - always takes place as a result of this kind of expression, even if the code isn't executed!Consider this example:
if false
x = 1
end
p x # Output: nil
p y # Fatal error: y is unknown
The assignment to x isn't executed, because it's wrapped in a failing conditional test. But the Ruby parser sees the sequence x = 1, from which it deduces that the program involves a local variable x. The parser doesn't care whether x is ever assigned a value. It's job is just to scour the code for local variables for which space needs to be allocated.The result is that x inhabits a strange kind of variable limbo. It has been brought into being and initialized to nil.