"applicable method may be too new" error

I am trying to write a generated function which creates a function from within the generated body (to then pass to broadcast). In 0.5 this used to be fine, but in 0.6 you get the error that the “generated function body is not pure”. Since I don’t actually need a closure (just a global function is fine), I thought as a workaround I just create a global function and use that. So basically I have,

julia> @generated function foo()
           quote
               bar = global $(gensym())() = "hi"
               bar()
           end
       end
foo (generic function with 1 method)

Calling this, however, gives me,

julia> foo()
ERROR: MethodError: no method matching ##681()
The applicable method may be too new: running in world age 21570, while current world is 21571.
Closest candidates are:
  ##681() at REPL[1]:3 (method too new to be called from this world context.)
Stacktrace:
 [1] macro expansion at ./REPL[1]:4 [inlined]
 [2] foo() at ./REPL[1]:2

Calling it a second time from the REPL works,

julia> foo()
"hi"

I’m not sure what to make of this, bug, feature, something else? Any workarounds? (Note I can’t put the definition inside the @generated function itself since in my real case, the function signature depends on the arguments received by the generated function)

More generally, is there any hope we lose the new 0.6 restrictions on @generated functions? A related / unfortunate side-effect which is essentially what got me here is that you can’t use the awesome new loop fusion in generated function bodies.

This isn’t unique to generated functions:

julia> function foo()
           global bar() = "hi"
           bar()
       end
foo (generic function with 1 method)

julia> foo()
ERROR: MethodError: no method matching bar()
The applicable method may be too new: running in world age 21583, while current world is 21584.
Closest candidates are:
  bar() at REPL[1]:2 (method too new to be called from this world context.)
Stacktrace:
 [1] foo() at ./REPL[1]:3

julia> foo()
"hi"

This is basically the exact case that is documented in the Redefining Methods section.

1 Like

Interesting, thanks, I had not seen that section. And if you attempt to use the workaround using a closure mentioned there, it doesn’t work because inside a @generated function (in 0.6 at least) you can’t have a closure.

julia> @generated function foo()
           quote
              global bar() = "hi"
              res = eval(Expr(:call,
                  function()
                      return bar()
                  end))
              return res
           end
       end
foo (generic function with 1 method)

julia> foo()
ERROR: generated function body is not pure. this likely means it contains a closure or comprehension.

So I suppose this is just not possible?

1 Like