Compiler issue with non-existent NIL conditions

This compiles|runs using loop do ... versus (2..).each do |pow|.
WHY?
They are functionally equivalent (to a user), but obviously not to the compiler.

def palindromegen(digit, count)
  nums = [] of UInt64
  nn  = digit * 11
  num = 0.to_u64
  pow = 1
  loop do pow += 1        # replaces: (2..).each do |pow|
    base = 10_u64**(pow >> 1)
    n1   = base * digit
    n2   = base * (digit + 1)
    n1.step(to: n2 - 1, by: 10) do |n1|
      ns = (n1 // 10).to_s
      (n1..n1 + 9).each_with_index do |pal, i|
        num = (pal.to_s + pal.to_s.reverse).to_u64      if pow.odd?
        num = (ns + "0" + ns.reverse).to_u64 + base * i if pow.even?
        nums << num if num % nn  == 0
        return nums if nums.size == count
      end
    end
  end
end

count = 20
puts "First 20 palindromic gapful numbers 100 ending with:"
(1..9).each { |digit| print "#{digit} : #{palindromegen(digit, count)}\n" }
count = 100
puts "\nLast 15 of first 100 palindromic gapful numbers ending in:"
(1..9).each { |digit| print "#{digit} : #{palindromegen(digit, count).last(15)}\n"

This also compiles|runs using (2..).select do |pow|

def palindromegen(digit, count)
  nums = [] of UInt64
  nn  = digit * 11
  num = 0.to_u64
  (2..).select do |pow|
    base = 10_u64**(pow >> 1)
    n1   = base * digit
    n2   = base * (digit + 1)
    n1.step(to: n2 - 1, by: 10) do |n1|
      ns = (n1 // 10).to_s
      (n1..n1 + 9).each_with_index do |pal, i|
        num = (pal.to_s + pal.to_s.reverse).to_u64      if pow.odd?
        num = (ns + "0" + ns.reverse).to_u64 + base * i if pow.even?
        nums << num if num % nn  == 0
        return nums if nums.size == count
      end
    end
  end
end

This also works.

def palindromegen(digit, count)
  nums = [] of UInt64
  nn  = digit * 11
  num = 0.to_u64
  pow = 1
  while true
    pow += 1
    base = 10_u64**(pow >> 1)
    n1   = base * digit
    n2   = base * (digit + 1)
    n1.step(to: n2 - 1, by: 10) do |n1|
      ns = (n1 // 10).to_s
      (n1..n1 + 9).each_with_index do |pal, i|
        num = (pal.to_s + pal.to_s.reverse).to_u64      if pow.odd?
        num = (ns + "0" + ns.reverse).to_u64 + base * i if pow.even?
        nums << num if num % nn  == 0
        return nums if nums.size == count
      end
    end
  end
end

So there’s something intrinsically different to the compiler about (2..).each.