Skip to content

Shadowing in closures in let blocks influences bindings in neighboring functions #56002

Open
@Seelengrab

Description

@Seelengrab

MWE:

julia> let; 
           function a()
               b()
           end
           function b()
               b = 1
               return b
           end
           @show a()
           @show a()
       end
a() = 1
ERROR: MethodError: objects of type Int64 are not callable
The object of type `Int64` exists, but no method is defined for this combination of argument types when trying to treat it as a callable object.
Maybe you forgot to use an operator such as *, ^, %, / etc. ?
Stacktrace:
 [1] (::var"#a#a##6")()
   @ Main ./REPL[9]:3
 [2] top-level scope
   @ REPL[9]:10
 [3] macro expansion
   @ show.jl:1229 [inlined]

As far as I can tell, what's going on is that a() and b() end up sharing the closed-over b in b(); either that, or the assignment in b() ends up overwriting the binding to b in the let block, after which the call to b() in a() fails due to the new object not being a function.

I'd expect this to behave the same as without the let block, that is, just print a() = 1 twice. This was found by a user of Supposition.jl, downstream issue is Seelengrab/Supposition.jl#54. To be clear, the shadowing in b() is fine, it's just surprising/unexpected/undesirable to have that shadowing influence what happens in a() (which shouldn't care about the shadowing in b, and just call the function).

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingThis change will break codedesignDesign of APIs or of the language itself

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions