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?
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?
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
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.
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.
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?
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.
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 const
s:
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.