@allocated does not work on Julia 1.12rc1

Example:

julia> @allocated x=rand(3)
80

julia> x
ERROR: UndefVarError: `x` not defined in `Main`
Suggestion: check for spelling errors or missing imports.

Works fine on 1.11.

Any known workaround?

1 Like
1 Like

I tried and failed to argue it’s a breaking change

For context, the reason I put the @allocated in the front is because without assignment Julia would elide the whole allocation

2 Likes

Of course it is a breaking change. But I don’t care as long as there is a viable work-around. Is there any?

Try following the links I post. EDIT: no, sorry, the workaround does not actually work.

1 Like

So far, there is no viable work-around. Nothing I could apply with search-and-replace to make my code work again. Not even a way to globally disable the @allocated macros for Julia 1.12 so that my code runs again. So this is a breaking change with no workaround. So I am annoyed.

4 Likes

Edit: Modified to do what was originally requested:

This example cooked up from the referenced links:

julia> versioninfo()
Julia Version 1.12.0-rc1
Commit 228edd6610 (2025-07-12 20:11 UTC)
Build Info:
  Official https://julialang.org release
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 28 Ă— Intel(R) Core(TM) i7-14700
  WORD_SIZE: 64
  LLVM: libLLVM-18.1.7 (ORCJIT, alderlake)
  GC: Built with stock GC
Threads: 1 default, 1 interactive, 1 GC (on 28 virtual cores)
Environment:
  JULIA_EDITOR = "C:\Program Files\Microsoft VS Code\Code.exe"

julia> @allocated b = rand(3)
80

julia> b
ERROR: UndefVarError: `b` not defined in `Main`
Suggestion: check for spelling errors or missing imports.

julia> (@timed b = rand(3)).bytes
6432

julia> b
3-element Vector{Float64}:
 0.919023234169286
 0.8775570945524694
 0.5680251057883124

Is @timed a satisfactory work-around?

julia> (@timed a=rand(3)).bytes
512

julia> @allocated a=rand(3)
80

OK, you could argue the values from @allocated are wrong anyways. But why does this macro then exists in the first place?

But in this test case, @allocated seams to be correct:

julia> function aa()
       @allocated a=rand(3)
       end
aa (generic function with 1 method)

julia> aa()
80

julia> function att()
       (@timed a=rand(3)).bytes
       end
att (generic function with 1 method)

julia> att()
80

Any idea how to apply this work-around using a regular expression or a script?

2 Likes

Edited my previous post to show your use-case.

In Emacs I would use a keyboard macro, since my regular expression-foo is pretty weak.

I think that’s just global vs local scope, and it only appears as a @timed vs @allocated discrepancy because @allocated is introducing local scope now:

julia> (@timed a=rand(3)).bytes
512

julia> @allocated a=rand(3)
80

julia> (@timed let; a=rand(3) end).bytes
80

but this global vs local allocation discrepancy didn’t exist in 1.11, so maybe the changes to variables had an effect

julia> (@timed a=rand(3)).bytes
80

julia> @allocated a=rand(3)
80

julia> (@timed let; a=rand(3) end).bytes
80

I kind of assumed it was for accessing parts of @timed without setting the field names in stone or typing out an additional name on top of a macro call, but then what’s the point if the behavior diverges…

I mean, if @timed is able to let newly assigned variables appear in the global (or local) scope, why is @allocated not able to achieve that any longer? This really looks like a bug to me, that probably could be fixed quite easily (well, I cannot do it due to lack of knowledge how to write macros).

Or is there any principle reason why @allocated cannot work as it did in Julia 1.11 now in in Julia 1.12?

If it’s really as simple as the bytes field of the result of @timed (though the actual v1.11.6 implementation skips the other work and diverges on more internals I don’t really understand), per PeterSimon’s suggestion:

julia> module Revert
         macro allocated(ex)
           esc(:((@timed $ex).bytes))
         end
       end;

julia> Revert.@allocated a = rand(3)
7880024

julia> Revert.@allocated a = rand(3)
512

julia> a
3-element Vector{Float64}:
 0.045194614659499255
 0.42666750407367626
 0.7327696792728946

julia> Base.@allocated b = rand(3)
80

julia> b
ERROR: UndefVarError: `b` not defined in `Main`
Suggestion: check for spelling errors or missing imports.

using .Revert: @allocated could be added to the top of preexisting tests to revert the behavior of the @allocated calls.

I don’t know, it’s just bizarre to me because we already had the option of manually introducing scopes in the expression, and there was always the option to make a new macro, even one in a separate package, for new behavior. It’s also apparently calling a closure, not just putting things in a let block, which can involve the headaches of capturing variables.

2 Likes

The issue was re-opened and is on the 1.12 milestone now.

Who makes a pull request? Your chance to become Julia contributor.

Just to highlight nsajko’s observation in the issue back here, the results of @timed and thus Revert.@allocate depend on surrounding code, and Base.@allocated is not observed to. It appears so far that involving global variables increases allocations in 1.12, even if the @timed expression only involves local variables and consts:

julia> let b = @timed rand(3); a = b.value; b.bytes end
80

julia> let b = @timed rand(3); global a=b.value; b.bytes end
512

julia> let b = Base.@allocated rand(3); a = b; b end
80

julia> let b = Base.@allocated rand(3); global a = b; b end
80

Both 80 in v1.11.6 and 1.9.4, though a similar effect can be replicated with a nested function outside the @timed expression, and @time can be tried to observe a different allocation discrepancy. Even if it’s worth letting the implementations diverge as they do, it’s not apparent why the reported allocations differ among supposedly equivalent methods and should be hashed out before trying to substituting them with each other. Open to start a different thread if these discrepancies are considered a distraction from the @allocated scoping change.

1 Like