Really not useful output when {{ @type.instance_vars.map &.name }}

# 1.cr

class A
  @x = 100

  def x
    {{ @type.instance_vars.map &.name }}
  end
end

a = A.new
p! a.x
 ╰─ $ cr 1.cr 
Showing last frame. Use --error-trace for full trace.

There was a problem expanding macro 'macro_139646571531328'

Code in 1.cr:5:5

 5 | {{ @type.instance_vars.map &.name }}
     ^
Called macro defined in 1.cr:5:5

 5 | {{ @type.instance_vars.map &.name }}

Which expanded to:

 > 1 | [x]
       ^
Error: generic type too nested: Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(Array(NoReturn)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))

I guess this strange error message caused by the returned [name](file:///home/zw963/Crystal/docs/Crystal/Macros/MetaVar.html#name%3AMacroId-instance-method) is a macro id, right?

Because following code work well when print instance vars type.

class A
  @x = 100

  def x
    {{ @type.instance_vars.map &.type }}
  end
end

a = A.new
p! a.x

a.x # => [Int32]

Maybe i should create a issue?

I don’t see anything wrong happening here. Your macro just results in infinite recursion and thus breaks the code. The compiler is already quite helpful to show you why your code fails. It explains what the macro expression expanded to [x] which in method x indicates a recursive call chain. The code calls x over and over again, nesting it in ever deeper arrays.

1 Like

Thank you, i see it basically same effect like this now.

class A
  def x
    [x]
  end
end

a = A.new
p! a.x

# Error: generic type too nested: Array(Array(Array(Array(Array .... )))))

Though, i still consider we can give a more friendly error output? like ruby?

 ╰─ $ ruby 1.cr 
1.cr:5:in `x': stack level too deep (SystemStackError)
        from 1.cr:5:in `x'
        from 1.cr:5:in `x'
        from 1.cr:5:in `x'
        from 1.cr:5:in `x'
        from 1.cr:5:in `x'
        from 1.cr:5:in `x'
        from 1.cr:5:in `x'
        from 1.cr:5:in `x'
         ... 10908 levels...
        from 1.cr:5:in `x'
        from 1.cr:5:in `x'
        from 1.cr:5:in `x'
        from 1.cr:10:in `<main>'

I don’t think having the compiler segfault is better than giving a precise error message.

1 Like