Tuple in a loop

I’m just experimenting, so this is nothing which needs a solution. It’s asbout understanding and learning things.

I was building an array in a loop, and compiling took ~10s.
I changed the array to a tuple and maybe it took a tiny bit longer, but if the compiler actually need more time then it was nothing one would immediately recognise. So, the compiler comes up with:
Error: tuple size cannot be greater than 300 (size is 301)
I was surprised it would actually do the loop during compile time (and the actual amount of loops is unknown during compile time), but okay, it probably checks the worst cases.

I just added a break if i==300, that should satisfy the compiler (while also thinking about how to probably deal with cases I would like to have more than 300 objects in a tuple - but that’s not the question here).

So far I haven’t gotten another error, but crystal has been already compiling for more than 38 minutes.

The item which I actually end up putting in the tuple, might be a tuple itself (exactly the same stuff which gets put into the tuple). So did I produce an endless loop for the compiler? Even though each tuple can have max 300 items, each of those could possibly also have 300 items and so on and so on. So if the compiler tried to play it through before, it might actually run exactly into this issue, wouldn’t it?

If not, what else is happening right now? And will the compiler eventually finish or is it really in an endless loop?

Could this be considered a bug? Not that my code is supposed to work, but it probably shouldn’t be able to do this to the compiler.

I’m actually surprised it tries to build the tuple at all (but it probably hasn’t figured out yet, that it’s content will be unknown till run-time)

The answer to this will be hard to know without any code to see.

1 Like
def v (x : V)  
  case t= SomeLib.whatTypeIsMyX? x         # unknown during compilation
  when :array
    a= Tuple.new
    getLengthOf(t).times do |i|            # unknown during compilation
      break if a==300
      a+= Tuple.new item(x)[i].v           # .v as in THIS method
    end
    a
  when … # v can return also a lot of others types  
  when … # including pointers
  when … # and nil
  else … # 
  end
end

# v can return also a lot of others types

Just in case again: it’s nothing which needs a solution (I’ll just return an Array(V) instead).
I just try to understand why it’s behaving this way (=meanwhile the compiler crashed with an Arithmetic overflow but only after compiling for almost an hour). Did it end up in an endless loop?

I don’t think the above should compile. The check for a == 300 doesn’t matter, the compiler will try to type the block will all possible tuple types that happen because of that code. So maybe that code isn’t exactly that.

It’s hard to know because I can’t copy and paste code and try it locally to see what’s going on (it’s still incomplete code, sorry!)

1 Like

Without the check the compiler says a tuple can’t have more than 300 elements but would have 301 already.
That’s why I got the idea the compiler would actually try to solve it (but fails to do so)

Edit: I’ll send the full code within the next 30 minutes. Just making pancakes right now :sweat_smile:

# cat foobar.cr 
#require "symbolx"
require "big"
@[Link(ldflags: "-lruby -dynamic -bundle")]
lib Rb
  fun defineGlobalFunction="rb_define_global_function"(LibC::Char*, PV, LibC::Int) : Void
  fun string="rb_string_value_ptr"(V*): UInt8*
  fun symbol="rb_sym2str"(V) : V
  fun hashKeys="rb_hash_keys"(V) : V
  fun hashValue="rb_hash_fetch"(V, V) : V
  fun raise="rb_raise"(V, V)
  fun error= "rb_invalid_str"(LibC::Char*, LibC::Char*) : V
  fun getConst="rb_const_get"(V, V) : V
  fun outString="rb_str_new_cstr"(LibC::Char*) : V
  fun id="rb_to_id"(V) : V #it's actually an ID
  fun big="rb_big2str"(V, Int32) : V

  struct Two
    a : V
    b : V
  end
end

struct Five
  property a= V.null
  property b= V.null
  property c= V.null
  property d= V.null
  property e= V.null

  def inspect
    "Fiver: a 0x#{a.address.to_s 16} b 0x#{b.address.to_s 16} c 0x#{c.address.to_s 16} d 0x#{d.address.to_s 16} e 0x#{e.address.to_s 16}"
  end

  def inspect (io)
    io << inspect
  end
end

class Sym
  def initialize (@s : String)    
  end
  
  def inspect
    ":#{@s}"
  end
  
  def to_s
    @s
  end
  
  def inspect (io)
    io.print inspect
  end
end

class String
  def to_sym
    Sym.new self
  end
  
  def v
    Rb.outString self
  end
end

struct Pointer(T)
  def inspect
    return "'#{v(self).inspect}" if self.is_a? V
    "Pointer(#{T})"
  end

  def v
    return v self if self.is_a? V
    V.new self.address
  end
  
  def inspect (io)
    io << inspect
  end
end

struct UInt64
  def v
    V.new self
  end
end

def § (s)
  return Sym.new s if s.is_a? String
  raise "damn"
end

enum RbType
  None
  Object
  Class
  Module
  Float
  String
  Regexp
  Array
  Hash
  Struct
  Bignum
  File
  Data
  Math
  Complex
  Rational= 15

  Nil= 17
  True
  False
  Symbol
  Fixnum
  Undef= 22

  IMemo= 26
  Node
  IClass
  Zombie
  Moved
  Mask= 31
end

alias PV= Proc(V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V*, V)
alias V= Pointer(Void)
Qnil=Pointer(Void).new(8)

def v (x : V)
  x= x.address
  if x==0
    false
  elsif x==8
    nil
  elsif x==20
    true
  elsif x&1==1
    (x.unsafe_as Int64)>>1
  elsif x&3==2
    b= x>>63
    n= ((b^1)<<1)|b|(x&~0x03)
    Box(Float64).unbox Box.box((n>>3)|((n&7)<<61))
  elsif x&12==12              # that's ONE type of symbol (it was used first via :symbol)
 #   § v Rb.symbol V.new x
   nil
  else
    t= RbType.from_value? Pointer(UInt64).new(x).value&0x1F
    if t== RbType::String
      s= Pointer(Five).new(x).value
      ptr= Pointer(Void).new x
      String.new Pointer(UInt8).new((Rb.string pointerof(ptr)).address), (s.a.address&8192>0 ? s.c.address : (s.a.address&0x7c000)>>14)
    elsif t== RbType::Symbol  # that's ANOTHER type of symbol (it was used first via 'symbol'.to_sym)
 #     s= (v Rb.symbol V.new x)
 #     s.to_sym if s.is_a? String
nil
    elsif t==RbType::Array      
      a= Tuple.new
      s= Pointer(Five).new(x).value 
      if s.a.address&8192>0
        (s.a.address>>15).times{|i| a+= Tuple.new Pointer(V).new(x+(i+2)*8).value.v}
      else
        s.c.address.times{|i| a+= Tuple.new Pointer(V).new(s.e.address+i*8).value.v}
      end
#      if s.a.address&8192>0
#        (s.a.address>>15).times{|i| a<< Pointer(V).new(x+(i+2)*8).value}
#      else
#        s.c.address.times{|i| a<< Pointer(V).new(s.e.address+i*8).value}
#      end
      a
    elsif t==RbType::Hash
      a= Hash(V, V).new
      Rb.hashKeys(x.v).v.unsafe_as(Array(V)).each{|k| a[k]= Rb.hashValue x.v, k}
      a
    elsif t==RbType::Bignum
      BigInt.new Rb.big(x.v, 10).v.unsafe_as String
    else
      p x
      Rb.error "not implemented", "argument of type #{t}. crubystal doesn't handle them and right now there are no plans to do so in the future either. If you think this type should be implemented, you can try to convince me and I might do so. Error"
      nil
    end
  end
end


def rv (x) : Pointer(Void)
  if x.nil?
    Pointer(Void).new 8
  elsif x==true
    Pointer(Void).new 20
  elsif x==false
    Pointer(Void).new 0
  else
    Box.box x
  end
end

fun extInit="Init_foobar"
  main 0, Pointer(Pointer(UInt8)).null
end

def addGlobalMethod(name, &b : PV)
  Rb.defineGlobalFunction name, b, -2
end



###### 👇 below this line the real stuff happens

addGlobalMethod "foo" do |_, a, b, c|
  p a.v
  rv true
end

Like this it should give you Error: tuple size cannot be greater than 300 (size is 301) after just a few seconds of compiling

Insert “break if i==300;” into the blocks in lines 160 and 164 and the compiler accepts it but crashes after try so hard for almost an hour.

Did you mean break if a.size>=300 or break if i > = 300?

1 Like

No, I meant i, as the index of the array. So it stops adding elements to the tuple (or: to stop creating a new tuple consisting of the elements of existing one and the content of a new one with the new element).

Although - it should basically be no difference, as it should have the same value anyway.

I managed to reduce it to this:

struct Pointer
  def v
    if 1
      v self
    else
      Pointer(Void).new(0)
    end
  end
end

def doit
  yield
end

def v(x : Pointer(Void))
  a = Tuple.new
  doit do
    break if 1 == 2
    a += Tuple.new x.v
  end
  a
end

Pointer(Void).new(0).v

It doesn’t end compiling but only because it’s producing a very nested type that doesn’t reach size 300 because it’s nested in a different way.

If we change += to = we get this:

Error: tuple type too nested: Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple() | Tuple(Pointer(Void) | Tuple()))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))

Regardless, it seems you are trying to create a tuple whose size isn’t known at compile time. For that you should use an Array.

To be honest, I never liked having + in Tuple for this reason, as this can be abused. I never liked merging that PR. For me + in tuple doesn’t make sense. Similar to how you can’t add data to a Slice or a StaticArray.

1 Like

Yeah, that fits exactly what I assumed to have happened (but wanted to know for sure).

I actually was quite surprised to see + for tuples, for the “most be known at compile time” reason. But thought I give it a try - there is always something one can learn from trying.

Thanks!!

EDIT: Oh, but if you don’t mind an extra question: IF tuple wasn’t to be known at runtime, the compiler wouldn’t have tried so hard to solve it, and the issues would have happened only at run-time - is this correct? Because I was the most surprised about what my code did to the compiler (I didn’t expect it to work right from the beginning).

I’m not sure what “at runtime” means here.

To be a bit more clear: I don’t understand what would move from compile time to runtime regarding tuples. Breaking our of a loop makes no difference. The compiler sees just a loop that could break or never finish, and types things accordingly. I don’t fully understand what why adding a break makes it take longer, though.

The arithmetic overflow the compiler crashedwith, would have then happened, if one started the application and if such a deeply nested tuple would have been created (which likely wouldn’t have happened, but it would have been possible).

But there’s no way to create such a deeply nested tuple without the compiler first knowing about that type. You can’t create a tuple of size 200 at runtime without the compiler giving something a type that’s a tuple of size 200.