Skip to content

Backports for julia 1.11.6 #58224

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

Merged
merged 46 commits into from
Jul 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
3c15710
fix zero-dimensional `reverse!` (#58086)
nsajko Apr 13, 2025
fcf0174
prevent allocation of Memory (layout and object) when not concrete (#…
vtjnash Apr 15, 2025
16832c1
Switch from segfault to `zip` behavior for mismatched indices in `map…
adienes Apr 19, 2025
0840c0c
subtype: save some union stack space for ∃ free cases. (#58159)
N5N3 Apr 20, 2025
5ad6ee6
Narrow `@inbounds` annotations in `accumulate.jl` to only indexing ca…
adienes Apr 24, 2025
3997241
[release-1.11] malloc: use jl_get_current_task to fix null check (#58…
benlorenz Apr 28, 2025
33786cf
Backport of 088bb90
gbaraldi May 12, 2025
066228c
Fix typo in unsafe_wrap method (#54582)
jakobnissen May 27, 2024
63aaa30
Logging: Improve threadsafety (#57591)
IanButterworth Apr 4, 2025
f497d62
Subtype: enable more Tuple related fast path. (#58196)
N5N3 Apr 27, 2025
4715983
doc: cross-reference `bind` in `Channel` method doc string (#58113)
nsajko Apr 29, 2025
ec2763b
Make build_id.lo more random (#58258)
gbaraldi May 3, 2025
fcb5a66
Fix removal of globals with addrspaces in removeAddrspaces (#58322)
gbaraldi May 6, 2025
bb6dc83
fix `hasmethod` with kwargs to exclude positional arg names (#58410)
JeffBezanson May 14, 2025
0aac5db
[REPL] fix type confusion resulting in nonsensical errors (#58414)
vtjnash May 15, 2025
9c02bf3
fix Markdown in the `Lockable` doc strings (#58603)
nsajko Jun 2, 2025
75aebb6
Update readlines(::Cmd) test to not rely on the filesystem (#58607)
fredrikekre Jun 2, 2025
0eb762c
Update install link in warning (#58638)
IanButterworth Jun 5, 2025
6a832a6
Try workaround for https://github.com/JuliaLang/www.julialang.org/iss…
staticfloat Jun 8, 2025
b180986
Adjust applescript workaround
staticfloat Jun 8, 2025
40f6d6b
Unicode: Force-inline isgraphemebreak! (#58674)
Keno Jun 10, 2025
520c4c1
Test: Fix failfast for for loops (#58695)
IanButterworth Jun 11, 2025
a021713
Increment state conditionally in `CartesianIndices` iteration (#58742)
jishnub Jun 17, 2025
af00075
Test: Hide REPL internals in backtraces (#58732)
IanButterworth Jun 20, 2025
56f233f
Add 0 predecessor to entry basic block and handle it in inlining (#58…
gbaraldi Jun 10, 2025
010a829
Make more types jl_static_show unambiguously (#58512)
xal-0 May 29, 2025
17457e7
Fix tbaa usage when storing into heap allocated immutable structs (#5…
gbaraldi May 22, 2025
f97790d
Fix layout flags for types that have oddly sized primitive type field…
gbaraldi May 19, 2025
a1c6607
check that hashing of types does not foreigncall (`jl_type_hash` is c…
KristofferC May 14, 2025
da8a55a
clarify that time_ns is monotonic (#57129)
stevengj Apr 29, 2025
8165029
Update command line options (#54066)
gitboy16 Apr 22, 2024
973d116
Fix `--project=@script` when outside script directory (#56351)
awadell1 Apr 15, 2025
5d0d0e9
docs: fix scope type of a `struct` to hard (#56755)
ArnoStrouwen Dec 18, 2024
99c3aff
Remove try-finally scope from `@time_imports` `@trace_compile` `@trac…
IanButterworth Apr 10, 2025
9707342
remove unnecessary edge from `exp_impl` to `pow` (#58062)
oscardssmith Apr 14, 2025
647b7bf
[DOC] Update installation docs: /downloads/ => /install/ (#58127)
StefanKarpinski Apr 15, 2025
f3cd329
add showing a string to REPL precompile workload (#58157)
KristofferC Apr 22, 2025
8b02eb4
Base.get_extension & Dates.format made public (#58108)
GHTaarn May 8, 2025
346ff93
Don't filter `Core` methods from newly-inferred list (#58510)
topolarity May 27, 2025
600efd6
Make `Ptr` values static-show w/ type-information (#58584)
topolarity May 30, 2025
e765e46
relax dispatch for the `IteratorSize` method for `Generator` (#58110)
nsajko May 31, 2025
803bb01
fixup! Fix layout flags for types that have oddly sized primitive typ…
Jun 25, 2025
8e497ad
fixup! Don't filter `Core` methods from newly-inferred list (#58510)
Jun 25, 2025
5876222
add julia half functions to header
Jun 25, 2025
32ac370
Fix llvmpasses error
gbaraldi Jun 25, 2025
ca6e7bd
remove allocation test that doesn't work on 1.11
KristofferC Jun 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ and installing Julia, below.
## Resources

- **Homepage:** <https://julialang.org>
- **Binaries:** <https://julialang.org/downloads/>
- **Install:** <https://julialang.org/install/>
- **Source code:** <https://github.com/JuliaLang/julia>
- **Documentation:** <https://docs.julialang.org>
- **Packages:** <https://julialang.org/packages/>
Expand All @@ -65,17 +65,22 @@ helpful to start contributing to the Julia codebase.

## Binary Installation

If you would rather not compile the latest Julia from source,
platform-specific tarballs with pre-compiled binaries are also
[available for download](https://julialang.org/downloads/). The
downloads page also provides details on the
[different tiers of support](https://julialang.org/downloads/#supported_platforms)
for OS and platform combinations.

If everything works correctly, you will see a Julia banner and an
interactive prompt into which you can enter expressions for
evaluation. You can read about [getting
started](https://docs.julialang.org/en/v1/manual/getting-started/) in the manual.
The recommended way of installing Julia is to use `juliaup` which will install
the latest stable `julia` for you and help keep it up to date. It can also let
you install and run different Julia versions simultaneously. Instructions for
this can be find [here](https://julialang.org/install/). If you want to manually
download specific Julia binaries, you can find those on the [downloads
page](https://julialang.org/downloads/). The downloads page also provides
details on the [different tiers of
support](https://julialang.org/downloads/#supported_platforms) for OS and
platform combinations.

If everything works correctly, you will get a `julia` program and when you run
it in a terminal or command prompt, you will see a Julia banner and an
interactive prompt into which you can enter expressions for evaluation. You can
read about [getting
started](https://docs.julialang.org/en/v1/manual/getting-started/) in the
manual.

**Note**: Although some OS package managers provide Julia, such
installations are neither maintained nor endorsed by the Julia
Expand Down
7 changes: 6 additions & 1 deletion base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,12 @@ end
"""
time_ns() -> UInt64
Get the time in nanoseconds. The time corresponding to 0 is undefined, and wraps every 5.8 years.
Get the time in nanoseconds relative to some machine-specific arbitrary time in the past.
The primary use is for measuring elapsed times during program execution. The return value is guaranteed to
be monotonic (mod 2⁶⁴) while the system is running, and is unaffected by clock drift or changes to local calendar time,
but it may change arbitrarily across system reboots or suspensions.
(Although the returned time is always in nanoseconds, the timing resolution is platform-dependent.)
"""
time_ns() = ccall(:jl_hrtime, UInt64, ())

Expand Down
19 changes: 13 additions & 6 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3420,12 +3420,19 @@ function ith_all(i, as)
end

function map_n!(f::F, dest::AbstractArray, As) where F
idxs1 = LinearIndices(As[1])
@boundscheck LinearIndices(dest) == idxs1 && all(x -> LinearIndices(x) == idxs1, As)
for i = idxs1
@inbounds I = ith_all(i, As)
val = f(I...)
@inbounds dest[i] = val
idxs = LinearIndices(dest)
if all(x -> LinearIndices(x) == idxs, As)
for i in idxs
@inbounds as = ith_all(i, As)
val = f(as...)
@inbounds dest[i] = val
end
else
for (i, Is...) in zip(eachindex(dest), map(eachindex, As)...)
as = ntuple(j->getindex(As[j], Is[j]), length(As))
val = f(as...)
dest[i] = val
end
end
return dest
end
Expand Down
55 changes: 32 additions & 23 deletions base/accumulate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
# it does double the number of operations compared to accumulate,
# though for cheap operations like + this does not have much impact (20%)
function _accumulate_pairwise!(op::Op, c::AbstractVector{T}, v::AbstractVector, s, i1, n)::T where {T,Op}
@inbounds if n < 128
s_ = v[i1]
c[i1] = op(s, s_)
if n < 128
@inbounds s_ = v[i1]
ci1 = op(s, s_)
@inbounds c[i1] = ci1
for i = i1+1:i1+n-1
s_ = op(s_, v[i])
c[i] = op(s, s_)
s_ = op(s_, @inbounds(v[i]))
ci = op(s, s_)
@inbounds c[i] = ci
end
else
n2 = n >> 1
Expand All @@ -26,7 +28,8 @@ function accumulate_pairwise!(op::Op, result::AbstractVector, v::AbstractVector)
n = length(li)
n == 0 && return result
i1 = first(li)
@inbounds result[i1] = v1 = reduce_first(op,v[i1])
v1 = reduce_first(op, @inbounds(v[i1]))
@inbounds result[i1] = v1
n == 1 && return result
_accumulate_pairwise!(op, result, v, v1, i1+1, n-1)
return result
Expand Down Expand Up @@ -379,16 +382,16 @@ function _accumulate!(op, B, A, dims::Integer, init::Union{Nothing, Some})
# We can accumulate to a temporary variable, which allows
# register usage and will be slightly faster
ind1 = inds_t[1]
@inbounds for I in CartesianIndices(tail(inds_t))
for I in CartesianIndices(tail(inds_t))
if init === nothing
tmp = reduce_first(op, A[first(ind1), I])
tmp = reduce_first(op, @inbounds(A[first(ind1), I]))
else
tmp = op(something(init), A[first(ind1), I])
tmp = op(something(init), @inbounds(A[first(ind1), I]))
end
B[first(ind1), I] = tmp
@inbounds B[first(ind1), I] = tmp
for i_1 = first(ind1)+1:last(ind1)
tmp = op(tmp, A[i_1, I])
B[i_1, I] = tmp
tmp = op(tmp, @inbounds(A[i_1, I]))
@inbounds B[i_1, I] = tmp
end
end
else
Expand All @@ -402,25 +405,31 @@ end
@noinline function _accumulaten!(op, B, A, R1, ind, R2, init::Nothing)
# Copy the initial element in each 1d vector along dimension `dim`
ii = first(ind)
@inbounds for J in R2, I in R1
B[I, ii, J] = reduce_first(op, A[I, ii, J])
for J in R2, I in R1
tmp = reduce_first(op, @inbounds(A[I, ii, J]))
@inbounds B[I, ii, J] = tmp
end
# Accumulate
@inbounds for J in R2, i in first(ind)+1:last(ind), I in R1
B[I, i, J] = op(B[I, i-1, J], A[I, i, J])
for J in R2, i in first(ind)+1:last(ind), I in R1
@inbounds Bv, Av = B[I, i-1, J], A[I, i, J]
tmp = op(Bv, Av)
@inbounds B[I, i, J] = tmp
end
B
end

@noinline function _accumulaten!(op, B, A, R1, ind, R2, init::Some)
# Copy the initial element in each 1d vector along dimension `dim`
ii = first(ind)
@inbounds for J in R2, I in R1
B[I, ii, J] = op(something(init), A[I, ii, J])
for J in R2, I in R1
tmp = op(something(init), @inbounds(A[I, ii, J]))
@inbounds B[I, ii, J] = tmp
end
# Accumulate
@inbounds for J in R2, i in first(ind)+1:last(ind), I in R1
B[I, i, J] = op(B[I, i-1, J], A[I, i, J])
for J in R2, i in first(ind)+1:last(ind), I in R1
@inbounds Bv, Av = B[I, i-1, J], A[I, i, J]
tmp = op(Bv, Av)
@inbounds B[I, i, J] = tmp
end
B
end
Expand All @@ -434,10 +443,10 @@ function _accumulate1!(op, B, v1, A::AbstractVector, dim::Integer)
cur_val = v1
B[i1] = cur_val
next = iterate(inds, state)
@inbounds while next !== nothing
while next !== nothing
(i, state) = next
cur_val = op(cur_val, A[i])
B[i] = cur_val
cur_val = op(cur_val, @inbounds(A[i]))
@inbounds B[i] = cur_val
next = iterate(inds, state)
end
return B
Expand Down
2 changes: 1 addition & 1 deletion base/arraymath.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ _reverse!(A::AbstractArray{<:Any,N}, ::Colon) where {N} = _reverse!(A, ntuple(id
_reverse!(A, dim::Integer) = _reverse!(A, (Int(dim),))
_reverse!(A, dims::NTuple{M,Integer}) where {M} = _reverse!(A, Int.(dims))
function _reverse!(A::AbstractArray{<:Any,N}, dims::NTuple{M,Int}) where {N,M}
dims === () && return A # nothing to reverse
dimrev = ntuple(k -> k in dims, Val{N}()) # boolean tuple indicating reversed dims

if N < M || M != sum(dimrev)
throw(ArgumentError("invalid dimensions $dims in reverse!"))
end
M == 0 && return A # nothing to reverse

# swapping loop only needs to traverse ≈half of the array
halfsz = ntuple(k -> k == dims[1] ? size(A,k) ÷ 2 : size(A,k), Val{N}())
Expand Down
2 changes: 1 addition & 1 deletion base/channels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Channel(sz=0) = Channel{Any}(sz)
"""
Channel{T=Any}(func::Function, size=0; taskref=nothing, spawn=false, threadpool=nothing)
Create a new task from `func`, bind it to a new channel of type
Create a new task from `func`, [`bind`](@ref) it to a new channel of type
`T` and size `size`, and schedule the task, all in a single call.
The channel is automatically closed when the task terminates.
Expand Down
19 changes: 11 additions & 8 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,11 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn
block = block_for_inst(ir, idx)
inline_into_block!(state, block)

if !isempty(inlinee_cfg.blocks[1].preds)
if length(inlinee_cfg.blocks[1].preds) > 1
need_split_before = true
else
@assert inlinee_cfg.blocks[1].preds[1] == 0
end

last_block_idx = last(state.cfg.blocks[block].stmts)
if false # TODO: ((idx+1) == last_block_idx && isa(ir[SSAValue(last_block_idx)], GotoNode))
need_split = false
Expand Down Expand Up @@ -168,12 +169,18 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn
end
new_block_range = (length(state.new_cfg_blocks)-length(inlinee_cfg.blocks)+1):length(state.new_cfg_blocks)

# Fixup the edges of the newely added blocks
# Fixup the edges of the newly added blocks
for (old_block, new_block) in enumerate(bb_rename_range)
if old_block != 1 || need_split_before
p = state.new_cfg_blocks[new_block].preds
let bb_rename_range = bb_rename_range
map!(p, p) do old_pred_block
# the meaning of predecessor 0 depends on the block we encounter it:
# - in the first block, it represents the function entry and so needs to be re-mapped
if old_block == 1 && old_pred_block == 0
return first(bb_rename_range) - 1
end
# - elsewhere, it represents external control-flow from a caught exception which is un-affected by inlining
return old_pred_block == 0 ? 0 : bb_rename_range[old_pred_block]
end
end
Expand All @@ -188,10 +195,6 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn
end
end

if need_split_before
push!(state.new_cfg_blocks[first(bb_rename_range)].preds, first(bb_rename_range)-1)
end

any_edges = false
for (old_block, new_block) in enumerate(bb_rename_range)
if (length(state.new_cfg_blocks[new_block].succs) == 0)
Expand Down Expand Up @@ -437,7 +440,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
else
bb_offset, post_bb_id = popfirst!(todo_bbs)
# This implements the need_split_before flag above
need_split_before = !isempty(item.ir.cfg.blocks[1].preds)
need_split_before = length(item.ir.cfg.blocks[1].preds) > 1
if need_split_before
finish_current_bb!(compact, 0)
end
Expand Down
3 changes: 3 additions & 0 deletions base/compiler/ssair/ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ function compute_basic_blocks(stmts::Vector{Any})
end
# Compute successors/predecessors
for (num, b) in enumerate(blocks)
if b.stmts.start == 1
push!(b.preds, 0) # the entry block has a virtual predecessor
end
terminator = stmts[last(b.stmts)]
if isa(terminator, ReturnNode)
# return never has any successors
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ function cache_result!(interp::AbstractInterpreter, result::InferenceResult)
code_cache(interp)[mi] = ci = CodeInstance(interp, result, valid_worlds)
if track_newly_inferred[]
m = mi.def
if isa(m, Method) && m.module != Core
if isa(m, Method)
ccall(:jl_push_newly_inferred, Cvoid, (Any,), ci)
end
end
Expand Down
1 change: 1 addition & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,7 @@ public
DL_LOAD_PATH,
load_path,
active_project,
get_extension,

# Reflection and introspection
isambiguous,
Expand Down
2 changes: 1 addition & 1 deletion base/generator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ IteratorSize(::Type{Any}) = SizeUnknown()

IteratorSize(::Type{<:Tuple}) = HasLength()
IteratorSize(::Type{<:AbstractArray{<:Any,N}}) where {N} = HasShape{N}()
IteratorSize(::Type{Generator{I,F}}) where {I,F} = IteratorSize(I)
IteratorSize(::Type{<:Generator{I}}) where {I} = (@isdefined I) ? IteratorSize(I) : SizeUnknown()

haslength(iter) = IteratorSize(iter) isa Union{HasShape, HasLength}

Expand Down
3 changes: 2 additions & 1 deletion base/hashing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ hash(x::Any) = hash(x, zero(UInt))
hash(w::WeakRef, h::UInt) = hash(w.value, h)

# Types can't be deleted, so marking as total allows the compiler to look up the hash
hash(T::Type, h::UInt) = hash_uint(3h - @assume_effects :total ccall(:jl_type_hash, UInt, (Any,), T))
@noinline _jl_type_hash(T::Type) = @assume_effects :total ccall(:jl_type_hash, UInt, (Any,), T)
hash(T::Type, h::UInt) = hash_uint(3h - _jl_type_hash(T))

## hashing general objects ##

Expand Down
24 changes: 8 additions & 16 deletions base/initdefs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -276,22 +276,14 @@ function load_path_expand(env::AbstractString)::Union{String, Nothing}
env == "@." && return current_project()
env == "@stdlib" && return Sys.STDLIB
if startswith(env, "@script")
if @isdefined(PROGRAM_FILE)
dir = dirname(PROGRAM_FILE)
else
cmds = unsafe_load_commands(opts.commands)
if any((cmd, arg)->cmd_suppresses_program(cmd), cmds)
# Usage error. The user did not pass a script.
return nothing
end
dir = dirname(ARGS[1])
end
if env == "@script" # complete match, not startswith, so search upwards
return current_project(dir)
else
# starts with, so assume relative path is after
return abspath(replace(env, "@script" => dir))
end
program_file = JLOptions().program_file
program_file = program_file != C_NULL ? unsafe_string(program_file) : nothing
isnothing(program_file) && return nothing # User did not pass a script

# Expand trailing relative path
dir = dirname(program_file)
dir = env != "@script" ? (dir * env[length("@script")+1:end]) : dir
return current_project(dir)
end
env = replace(env, '#' => VERSION.major, count=1)
env = replace(env, '#' => VERSION.minor, count=1)
Expand Down
4 changes: 2 additions & 2 deletions base/lock.jl
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ macro lock_nofail(l, expr)
end

"""
Lockable(value, lock = ReentrantLock())
Lockable(value, lock = ReentrantLock())
Creates a `Lockable` object that wraps `value` and
associates it with the provided `lock`. This object
Expand Down Expand Up @@ -328,7 +328,7 @@ Lockable(value) = Lockable(value, ReentrantLock())
getindex(l::Lockable) = (assert_havelock(l.lock); l.value)

"""
lock(f::Function, l::Lockable)
lock(f::Function, l::Lockable)
Acquire the lock associated with `l`, execute `f` with the lock held,
and release the lock when `f` returns. `f` will receive one positional
Expand Down
Loading