Skip to content

Cornercase where closure boxing fails in function bodies #55191

Open
@MasonProtter

Description

@MasonProtter

Typically, we box any captured variable that the frontend thinks might get rebound and affect the result of a closure, but here is a funny corner case where it fails:

julia> (function (a=1, count=0)
           @label start
           a = a + 1 # lexical rebinding of a before the definition of f
           
           if count == 0
               f() = a # define f only once, capturing a
           end
           count += 1
           if count <= 5
               @goto start # basically a while loop
           end
           f.a, a # compare the captured version of a against the local variable a
       end)()
(2, 7)

interestingly, this only occurs in functions that produce closures, not let blocks:

julia> let a=1, count=0
           local f
           while count <= 5
               a = a + 1 # lexical rebinding of a before the definition of f
               if count == 0
                   f() = a # define f only once, capturing a
               end
               count += 1
           end
           f.a, a # compare the captured version of a against the local variable a
       end
(Core.Box(7), 7)

This behaviour seems to have been introduced in version 1.6:

❯ julia +1.5 --startup=no -q
julia> (function (a=1, count=0)
           local f
           while count <= 5
               a = a + 1 # lexical rebinding of a before the definition of f
               if count == 0
                   f() = a # define f only once, capturing a
               end
               count += 1
           end
           f.a, a # compare the captured version of a against the local variable a
       end)()
(Core.Box(7), 7)

❯ julia +1.6 --startup=no -q
julia> (function (a=1, count=0)
           local f
           while count <= 5
               a = a + 1 # lexical rebinding of a before the definition of f
               if count == 0
                   f() = a # define f only once, capturing a
               end
               count += 1
           end
           f.a, a # compare the captured version of a against the local variable a
       end)()
(2, 7)

cc @c42f this might be relevant for the rewrite of lowering.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIndicates an unexpected problem or unintended behaviorcompiler:loweringSyntax lowering (compiler front end, 2nd stage)regressionRegression in behavior compared to a previous version

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions