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

stackoverflow anonymous function #37868

Open
maartenvd opened this issue Oct 3, 2020 · 3 comments
Open

stackoverflow anonymous function #37868

maartenvd opened this issue Oct 3, 2020 · 3 comments
Assignees
Labels
compiler:lowering Syntax lowering (compiler front end, 2nd stage) kind:bug Indicates an unexpected problem or unintended behavior

Comments

@maartenvd
Copy link

julia> function fun(a)
           a::typeof(a) = a
           function helper(b)
               a=b+a
           end
           
           helper(3.5)
           a
       end
ERROR: StackOverflowError:

julia> versioninfo()
Julia Version 1.5.1
Commit 697e782ab8 (2020-08-25 20:08 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-9.0.1 (ORCJIT, skylake)
Environment:
  JULIA_NUM_THREADS = 2

While there are a number of bug reports open about stackoverflows when defining functions (so this issue is possibly a duplicate), the examples looked quite different : #36185 , #36804,#36544

The issue I'm actually trying to solve is that when inference fails, it causes really significant startup overhead (possibly because the packages I'm using are template heavy ?). I often lose type stability because I use anonymous functions, which depend on variables outside their scope (so like in the example). This is really annoying, and the only workaround I found so far was to sprinkle let blocks everywhere. Of course - ideally - the workaround shouldn't be necessary and julia would simply stop failing to infer those things. I was trying out the following macro as a workaround, which would then fix the types of the variables it get's passed to:

macro type_stabilize(var)
          if isa(var,Symbol)
              return esc(:($var::typeof($var)=$var))
          else
              (isa(var,Expr) && var.head == :tuple) || throw(ArgumentError("bad format"))
              expr = :()
              for symbol in var.args
                  expr = :($expr; $symbol::typeof($symbol) = $symbol);
              end
              return esc(expr)
          end
       end

If anyone knows another way to get this to work, I would be very grateful.

@KristofferC
Copy link
Sponsor Member

If anyone knows another way to get this to work, I would be very grateful.

You could take a look at https://github.com/c42f/FastClosures.jl.

@maartenvd
Copy link
Author

maartenvd commented Oct 3, 2020

I tried it out, but the allowed syntax is quite limited. For example, I usually write things like


eigsolve(x,1,:LM) do v
#some multiline function that applies a linear map
end

This is annoying to rewrite to use fastclosures, I think I would have to do things like


@closure function apply_map(v)
#transform v
end
eigsolve(apply_map,x,1;LM)

I also had problems where type stability was still incorrectly lost, and it will never be able to correct for the case where the closure changes a variable outside it's scope, but keeps the type.

EDIT : I was wrong about the syntax, fastclosures supports do blocks

@JeffBezanson JeffBezanson self-assigned this Oct 5, 2020
@JeffBezanson JeffBezanson added kind:bug Indicates an unexpected problem or unintended behavior compiler:lowering Syntax lowering (compiler front end, 2nd stage) labels Oct 5, 2020
@JeffBezanson
Copy link
Sponsor Member

A good workaround for now is:

function f(a::T) where T
    a::T = a
    ...

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

No branches or pull requests

3 participants