Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated functions as closures #18747

Open
fcard opened this issue Sep 30, 2016 · 9 comments
Open

Generated functions as closures #18747

fcard opened this issue Sep 30, 2016 · 9 comments
Labels
bug Indicates an unexpected problem or unintended behavior compiler:lowering Syntax lowering (compiler front end, 2nd stage)

Comments

@fcard
Copy link
Contributor

fcard commented Sep 30, 2016

f(x) = @generated g() = x
julia> f(1)()
ERROR: type DataType has no field x
 in g(...) at ./REPL[1]:1

As performed in 0.5.0 and 0.6.0-dev.826.
:?

julia> @code_lowered f(1)()
CodeInfo(:(begin 
        nothing
        return (Core.getfield)(#self#,:x)
    end))
@simonster
Copy link
Member

This issue seems to apply to inner generated functions generally:

julia> function f(x)
       @generated g() = x
       g
       end;

julia> f(1)()
ERROR: type DataType has no field x
 in g(...) at ./REPL[1]:2

@simonster
Copy link
Member

This may be similar to #15602 and #18674, in that it is no longer permitted but doesn't have an appropriate error message.

@fcard
Copy link
Contributor Author

fcard commented Sep 30, 2016

Oh, that's nice to know. I just tried something like this and it worked:

function f(x)
  @generated function()
    x
  end
end
julia> f(1)()
1

So I assumed it was a macro thing. I will update the issue, then.

@fcard fcard changed the title Generated Functions inside macros Generated functions as closures Sep 30, 2016
@vtjnash vtjnash added bug Indicates an unexpected problem or unintended behavior compiler:lowering Syntax lowering (compiler front end, 2nd stage) labels Sep 30, 2016
@vtjnash
Copy link
Member

vtjnash commented Sep 30, 2016

I'm not sure how easily this can be fixed, but the correct answer should have been Int in all of the above examples (since the function generator capture types, not values).

@fcard
Copy link
Contributor Author

fcard commented Sep 30, 2016

@vtjnash yeah, I later realized that the above gave a 1 because @generated function() ... end doesn't create a generated function at all, it just returns the function itself. That's a separate issue I guess.

f = @generated function() end
g = @generated function h() end
julia> methods(f).ms[1].isstaged
false

julia> methods(g).ms[1].isstaged
true

@fcard
Copy link
Contributor Author

fcard commented Sep 30, 2016

@vtjnash hey wait, you sure? The "@generated function() end doesn't work" issue is true, but the "generated closure captures types" isn't consistent with other outside variables:

x = 1
@generated f() = x
julia> f()
1

julia> methods(f).ms[1].isstaged
true

@JeffBezanson
Copy link
Member

JeffBezanson commented Sep 30, 2016

Yes, I think it would be reasonable for generated functions to still capture variables by value. Arguably @generated only causes the generator's arguments to be bound to types, and nothing else.

To give a reason, functions are not specialized on the types of captured variables, unless those are reflected in the type of the function itself, which is already an argument. So generated functions do not need their captured variables to become types.

@vtjnash
Copy link
Member

vtjnash commented Oct 1, 2016

True, this is perhaps one way we could allow inner generated functions to capture variables, by requiring that the generator also reference that variable? The implementation of such sounds quite annoying.

However, the following would need to hold in order for the cached code to have only depended on the type #g#f{typeof(x)}, which is why in the above example, the correct answer would be Int:

function g(x)
   @generated f()
       return :(x :: $x)
   end
   return f
end

@vtjnash
Copy link
Member

vtjnash commented Oct 1, 2016

In your code example,

x = 1
@generated f() = x

you are missing a const declaration before the x for this to be a valid usage of generated functions. This is not capturing x, but creating a new const reference to it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Indicates an unexpected problem or unintended behavior compiler:lowering Syntax lowering (compiler front end, 2nd stage)
Projects
None yet
Development

No branches or pull requests

4 participants