Skip to content

Commit e6378ea

Browse files
authored
[release-1.10] Backports for Julia 1.10.0-x (#50971)
Backported PRs: - [x] #48625 <!-- add replace(io, str, patterns...) --> - [x] #48387 <!-- Improve documentation of sort-related functions --> - [x] #48363 <!-- Revise sort.md and docstrings in sort.jl --> - [x] #48977 <!-- Update SparseArrays.jl stdlib for SuiteSparse 7 --> - [x] #50719 <!-- fix `CyclePadding(::DataType)` --> - [x] #50694 <!-- inference: permit recursive type traits --> - [x] #50860 <!-- Add `Base.get_extension` to docs/API --> - [x] #50594 <!-- Disallow non-index Integer types in isassigned --> - [x] #50802 <!-- Makes IntrusiveLinkedListSynchronized mutable to avoid allocation on poptask --> - [x] #50858 <!-- Add a `threadpool` parameter to `Channel` constructor --> - [x] #50874 <!-- Restrict COFF to a single thread when symbol count is high --> - [x] #50822 <!-- Add default method for setmodifiers! --> - [x] #50730 <!-- Fix integer overflow in `isapprox` --> - [x] #50850 <!-- Remove weird Rational dispatch and add pi functions to list --> - [x] #50809 <!-- Limit type-printing in MethodError --> - [x] #50915 <!-- Add note the `Task` about sticky bit --> - [x] #50929 <!-- when widening tuple types in tmerge, only widen the complex parts --> - [x] #50928 <!-- Bump JuliaSyntax to 0.4.6 --> - [x] #50959 <!-- Update libssh2 patches --> - [x] #50823 <!-- Make ranges more robust with unsigned indexes. --> - [x] #48542 <!-- Add docs on task-specific buffering using multithreading --> - [x] #50912 <!-- Separate foreign threads into a :foreign threadpool --> - [x] #51010 <!-- Add ORIGIN to SuiteSparse rpath on Linux/FreeBSD --> - [x] #50753 <!-- cat: remove unused promote_eltype methods that confuse inference --> - [x] #51027 <!-- Implement realloc accounting correctly --> - [x] #51019 <!-- fix a case of potentially use of undefined variable when handling error in distributed message processing --> - [x] #51039 <!-- Revert "Optimize findall(f, ::AbstractArray{Bool}) (#42202)" --> - [x] #51036 <!-- add missing invoke edge for nospecialize targets --> - [x] #51042 <!-- inference: fix return_type_tfunc modeling of concrete functions --> - [x] #51114 <!-- Workaround upstream FreeBSD issue #272992 --> - [x] #50892 <!-- Add `JL_DLLIMPORT` to `small_typeof` declaration --> - [x] #51154 <!-- broadcast: use recursion rather than ntuple to map over a tuple --> - [x] #51153 <!-- fix debug typo in "add missing invoke edge for nospecialize targets (#51036)" --> - [x] #51222 <!-- Check again if the tty is open inside the IO lock --> - [x] #51236 <!-- Add lock around uv_unref during init --> - [x] #51243 <!-- GMP: Gracefully handle more overflows. --> - [x] #51254 <!-- Ryu: make sure adding zeros does not overwrite trailing dot --> - [x] #51175 <!-- shorten stale_age for cachefile lock --> - [x] #51300 <!-- fix method definition error for bad vararg --> - [x] #51307 <!-- fix force-throw ctrl-C on Windows --> - [x] #51303 <!-- ensure revising structs is safe --> - [x] #51393 - [x] #51403 Need manual backport: - [x] #51009 <!-- fix #50562, regression in `in` of tuple of Symbols --> - [x] #51053 <!-- Bump Statistics stdlib --> - [x] #51013 <!-- fix #50709, type bound error due to free typevar in sparam env --> - [x] #51305 <!-- reduce test time for rounding and floatfuncs --> Contains multiple commits, manual intervention needed: - [ ] #50663 <!-- Fix Expr(:loopinfo) codegen --> - [ ] #51035 <!-- refactor GC scanning code to reflect jl_binding_t are now first class --> - [ ] #51092 <!-- inference: fix bad effects for recursion --> - [x] #51247 <!-- Check if malloc has succeeded before incrementing gc stats --> - [x] #51294 <!-- use LibGit2_jll for LibGit2 library --> Non-merged PRs with backport label: - [ ] #51132 <!-- Handle `AbstractQ` in concatenation --> - [x] #51029 <!-- testdefs: make sure that if a test set changes the active project, they change it back when they're done --> - [ ] #50919 <!-- Code loading: do the "skipping mtime check for stdlib" check regardless of the value of `ispath(f)` --> - [ ] #50824 <!-- Add some aliasing warnings to docstrings for mutating functions --> - [x] #50385 <!-- Precompile pidlocks: add to NEWS and docs --> - [ ] #49805 <!-- Limit TimeType subtraction to AbstractDateTime -->
2 parents a468aa1 + e084a40 commit e6378ea

File tree

132 files changed

+1357
-780
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+1357
-780
lines changed

Make.inc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1171,7 +1171,7 @@ endif
11711171

11721172
# We need python for things like BB triplet recognition. We don't really care
11731173
# about version, generally, so just find something that works:
1174-
PYTHON := "$(shell which python 2>/dev/null || which python3 2>/dev/null || which python2 2>/dev/null || echo not found)"
1174+
PYTHON := $(shell which python 2>/dev/null || which python3 2>/dev/null || which python2 2>/dev/null || echo not found)
11751175
PYTHON_SYSTEM := $(shell $(PYTHON) -c 'from __future__ import print_function; import platform; print(platform.system())')
11761176

11771177
# If we're running on Cygwin, but using a native-windows Python, we need to use cygpath -w

NEWS.md

+3
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ Compiler/Runtime improvements
3737
* The mark phase of the garbage collector is now multi-threaded ([#48600]).
3838
* [JITLink](https://llvm.org/docs/JITLink.html) is enabled by default on Linux aarch64 when Julia is linked to LLVM 15 or later versions ([#49745]).
3939
This should resolve many segmentation faults previously observed on this platform.
40+
* The precompilation process now uses pidfile locks and orchestrates multiple julia processes to only have one process
41+
spend effort precompiling while the others wait. Previously all would do the work and race to overwrite the cache files.
42+
([#49052])
4043

4144
Command-line option changes
4245
---------------------------

base/abstractarray.jl

+4-2
Original file line numberDiff line numberDiff line change
@@ -1584,10 +1584,12 @@ replace_in_print_matrix(A::AbstractVector,i::Integer,j::Integer,s::AbstractStrin
15841584
eltypeof(x) = typeof(x)
15851585
eltypeof(x::AbstractArray) = eltype(x)
15861586

1587-
promote_eltypeof() = Bottom
1587+
promote_eltypeof() = error()
1588+
promote_eltypeof(v1) = eltypeof(v1)
15881589
promote_eltypeof(v1, vs...) = promote_type(eltypeof(v1), promote_eltypeof(vs...))
15891590

1590-
promote_eltype() = Bottom
1591+
promote_eltype() = error()
1592+
promote_eltype(v1) = eltype(v1)
15911593
promote_eltype(v1, vs...) = promote_type(eltype(v1), promote_eltype(vs...))
15921594

15931595
#TODO: ERROR CHECK

base/array.jl

+8-31
Original file line numberDiff line numberDiff line change
@@ -2487,42 +2487,19 @@ function findall(A)
24872487
end
24882488

24892489
# Allocating result upfront is faster (possible only when collection can be iterated twice)
2490-
function _findall(f::Function, A::AbstractArray{Bool})
2491-
n = count(f, A)
2490+
function findall(A::AbstractArray{Bool})
2491+
n = count(A)
24922492
I = Vector{eltype(keys(A))}(undef, n)
2493-
isempty(I) && return I
2494-
_findall(f, I, A)
2495-
end
2496-
2497-
function _findall(f::Function, I::Vector, A::AbstractArray{Bool})
2498-
cnt = 1
2499-
len = length(I)
2500-
for (k, v) in pairs(A)
2501-
@inbounds I[cnt] = k
2502-
cnt += f(v)
2503-
cnt > len && return I
2504-
end
2505-
# In case of impure f, this line could potentially be hit. In that case,
2506-
# we can't assume I is the correct length.
2507-
resize!(I, cnt - 1)
2508-
end
2509-
2510-
function _findall(f::Function, I::Vector, A::AbstractVector{Bool})
2511-
i = firstindex(A)
25122493
cnt = 1
2513-
len = length(I)
2514-
while cnt len
2515-
@inbounds I[cnt] = i
2516-
cnt += f(@inbounds A[i])
2517-
i = nextind(A, i)
2494+
for (i,a) in pairs(A)
2495+
if a
2496+
I[cnt] = i
2497+
cnt += 1
2498+
end
25182499
end
2519-
cnt - 1 == len ? I : resize!(I, cnt - 1)
2500+
I
25202501
end
25212502

2522-
findall(f::Function, A::AbstractArray{Bool}) = _findall(f, A)
2523-
findall(f::Fix2{typeof(in)}, A::AbstractArray{Bool}) = _findall(f, A)
2524-
findall(A::AbstractArray{Bool}) = _findall(identity, A)
2525-
25262503
findall(x::Bool) = x ? [1] : Vector{Int}()
25272504
findall(testf::Function, x::Number) = testf(x) ? [1] : Vector{Int}()
25282505
findall(p::Fix2{typeof(in)}, x::Number) = x in p.x ? [1] : Vector{Int}()

base/broadcast.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -750,8 +750,8 @@ _broadcast_getindex_eltype(A) = eltype(A) # Tuple, Array, etc.
750750
eltypes(::Tuple{}) = Tuple{}
751751
eltypes(t::Tuple{Any}) = Iterators.TupleOrBottom(_broadcast_getindex_eltype(t[1]))
752752
eltypes(t::Tuple{Any,Any}) = Iterators.TupleOrBottom(_broadcast_getindex_eltype(t[1]), _broadcast_getindex_eltype(t[2]))
753-
# eltypes(t::Tuple) = (TT = eltypes(tail(t)); TT === Union{} ? Union{} : Iterators.TupleOrBottom(_broadcast_getindex_eltype(t[1]), TT.parameters...))
754-
eltypes(t::Tuple) = Iterators.TupleOrBottom(ntuple(i -> _broadcast_getindex_eltype(t[i]), Val(length(t)))...)
753+
eltypes(t::Tuple) = (TT = eltypes(tail(t)); TT === Union{} ? Union{} : Iterators.TupleOrBottom(_broadcast_getindex_eltype(t[1]), TT.parameters...))
754+
# eltypes(t::Tuple) = Iterators.TupleOrBottom(ntuple(i -> _broadcast_getindex_eltype(t[i]), Val(length(t)))...)
755755

756756
# Inferred eltype of result of broadcast(f, args...)
757757
function combine_eltypes(f, args::Tuple)

base/channels.jl

+21-7
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ Channel(sz=0) = Channel{Any}(sz)
5959

6060
# special constructors
6161
"""
62-
Channel{T=Any}(func::Function, size=0; taskref=nothing, spawn=false)
62+
Channel{T=Any}(func::Function, size=0; taskref=nothing, spawn=false, threadpool=nothing)
6363
6464
Create a new task from `func`, bind it to a new channel of type
6565
`T` and size `size`, and schedule the task, all in a single call.
@@ -70,9 +70,14 @@ The channel is automatically closed when the task terminates.
7070
If you need a reference to the created task, pass a `Ref{Task}` object via
7171
the keyword argument `taskref`.
7272
73-
If `spawn = true`, the Task created for `func` may be scheduled on another thread
73+
If `spawn=true`, the `Task` created for `func` may be scheduled on another thread
7474
in parallel, equivalent to creating a task via [`Threads.@spawn`](@ref).
7575
76+
If `spawn=true` and the `threadpool` argument is not set, it defaults to `:default`.
77+
78+
If the `threadpool` argument is set (to `:default` or `:interactive`), this implies
79+
that `spawn=true` and the new Task is spawned to the specified threadpool.
80+
7681
Return a `Channel`.
7782
7883
# Examples
@@ -117,6 +122,9 @@ true
117122
In earlier versions of Julia, Channel used keyword arguments to set `size` and `T`, but
118123
those constructors are deprecated.
119124
125+
!!! compat "Julia 1.9"
126+
The `threadpool=` argument was added in Julia 1.9.
127+
120128
```jldoctest
121129
julia> chnl = Channel{Char}(1, spawn=true) do ch
122130
for c in "hello world"
@@ -129,12 +137,18 @@ julia> String(collect(chnl))
129137
"hello world"
130138
```
131139
"""
132-
function Channel{T}(func::Function, size=0; taskref=nothing, spawn=false) where T
140+
function Channel{T}(func::Function, size=0; taskref=nothing, spawn=false, threadpool=nothing) where T
133141
chnl = Channel{T}(size)
134142
task = Task(() -> func(chnl))
143+
if threadpool === nothing
144+
threadpool = :default
145+
else
146+
spawn = true
147+
end
135148
task.sticky = !spawn
136149
bind(chnl, task)
137150
if spawn
151+
Threads._spawn_set_thrpool(task, threadpool)
138152
schedule(task) # start it on (potentially) another thread
139153
else
140154
yield(task) # immediately start it, yielding the current thread
@@ -149,17 +163,17 @@ Channel(func::Function, args...; kwargs...) = Channel{Any}(func, args...; kwargs
149163
# of course not deprecated.)
150164
# We use `nothing` default values to check which arguments were set in order to throw the
151165
# deprecation warning if users try to use `spawn=` with `ctype=` or `csize=`.
152-
function Channel(func::Function; ctype=nothing, csize=nothing, taskref=nothing, spawn=nothing)
166+
function Channel(func::Function; ctype=nothing, csize=nothing, taskref=nothing, spawn=nothing, threadpool=nothing)
153167
# The spawn= keyword argument was added in Julia v1.3, and cannot be used with the
154168
# deprecated keyword arguments `ctype=` or `csize=`.
155-
if (ctype !== nothing || csize !== nothing) && spawn !== nothing
156-
throw(ArgumentError("Cannot set `spawn=` in the deprecated constructor `Channel(f; ctype=Any, csize=0)`. Please use `Channel{T=Any}(f, size=0; taskref=nothing, spawn=false)` instead!"))
169+
if (ctype !== nothing || csize !== nothing) && (spawn !== nothing || threadpool !== nothing)
170+
throw(ArgumentError("Cannot set `spawn=` or `threadpool=` in the deprecated constructor `Channel(f; ctype=Any, csize=0)`. Please use `Channel{T=Any}(f, size=0; taskref=nothing, spawn=false, threadpool=nothing)` instead!"))
157171
end
158172
# Set the actual default values for the arguments.
159173
ctype === nothing && (ctype = Any)
160174
csize === nothing && (csize = 0)
161175
spawn === nothing && (spawn = false)
162-
return Channel{ctype}(func, csize; taskref=taskref, spawn=spawn)
176+
return Channel{ctype}(func, csize; taskref=taskref, spawn=spawn, threadpool=threadpool)
163177
end
164178

165179
closed_exception() = InvalidStateException("Channel is closed.", :closed)

base/client.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ scrub_repl_backtrace(stack::ExceptionStack) =
103103
ExceptionStack(Any[(;x.exception, backtrace = scrub_repl_backtrace(x.backtrace)) for x in stack])
104104

105105
istrivialerror(stack::ExceptionStack) =
106-
length(stack) == 1 && length(stack[1].backtrace) 1
107-
# frame 1 = top level; assumes already went through scrub_repl_backtrace
106+
length(stack) == 1 && length(stack[1].backtrace) 1 && !isa(stack[1].exception, MethodError)
107+
# frame 1 = top level; assumes already went through scrub_repl_backtrace; MethodError see #50803
108108

109109
function display_error(io::IO, stack::ExceptionStack)
110110
printstyled(io, "ERROR: "; bold=true, color=Base.error_color())

base/compiler/abstractinterpretation.jl

+41-24
Original file line numberDiff line numberDiff line change
@@ -1869,39 +1869,50 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs
18691869
end
18701870

18711871
function abstract_call_unionall(interp::AbstractInterpreter, argtypes::Vector{Any})
1872-
if length(argtypes) == 3
1873-
canconst = true
1872+
na = length(argtypes)
1873+
if isvarargtype(argtypes[end])
1874+
if na 2
1875+
return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
1876+
elseif na > 4
1877+
return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo())
1878+
end
1879+
a2 = argtypes[2]
1880+
a3 = unwrapva(argtypes[3])
1881+
nothrow = false
1882+
elseif na == 3
18741883
a2 = argtypes[2]
18751884
a3 = argtypes[3]
18761885
= (typeinf_lattice(interp))
18771886
nothrow = a2 ᵢ TypeVar && (a3 ᵢ Type || a3 ᵢ TypeVar)
1878-
if isa(a3, Const)
1879-
body = a3.val
1880-
elseif isType(a3)
1881-
body = a3.parameters[1]
1887+
else
1888+
return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo())
1889+
end
1890+
canconst = true
1891+
if isa(a3, Const)
1892+
body = a3.val
1893+
elseif isType(a3)
1894+
body = a3.parameters[1]
1895+
canconst = false
1896+
else
1897+
return CallMeta(Any, Effects(EFFECTS_TOTAL; nothrow), NoCallInfo())
1898+
end
1899+
if !(isa(body, Type) || isa(body, TypeVar))
1900+
return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
1901+
end
1902+
if has_free_typevars(body)
1903+
if isa(a2, Const)
1904+
tv = a2.val
1905+
elseif isa(a2, PartialTypeVar)
1906+
tv = a2.tv
18821907
canconst = false
18831908
else
1884-
return CallMeta(Any, Effects(EFFECTS_TOTAL; nothrow), NoCallInfo())
1885-
end
1886-
if !(isa(body, Type) || isa(body, TypeVar))
18871909
return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
18881910
end
1889-
if has_free_typevars(body)
1890-
if isa(a2, Const)
1891-
tv = a2.val
1892-
elseif isa(a2, PartialTypeVar)
1893-
tv = a2.tv
1894-
canconst = false
1895-
else
1896-
return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
1897-
end
1898-
isa(tv, TypeVar) || return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
1899-
body = UnionAll(tv, body)
1900-
end
1901-
ret = canconst ? Const(body) : Type{body}
1902-
return CallMeta(ret, Effects(EFFECTS_TOTAL; nothrow), NoCallInfo())
1911+
isa(tv, TypeVar) || return CallMeta(Any, EFFECTS_THROWS, NoCallInfo())
1912+
body = UnionAll(tv, body)
19031913
end
1904-
return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo())
1914+
ret = canconst ? Const(body) : Type{body}
1915+
return CallMeta(ret, Effects(EFFECTS_TOTAL; nothrow), NoCallInfo())
19051916
end
19061917

19071918
function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgInfo, si::StmtInfo, sv::AbsIntState)
@@ -2182,6 +2193,12 @@ function sp_type_rewrap(@nospecialize(T), linfo::MethodInstance, isreturn::Bool)
21822193
T = UnionAll(v, T)
21832194
end
21842195
end
2196+
if has_free_typevars(T)
2197+
fv = ccall(:jl_find_free_typevars, Vector{Any}, (Any,), T)
2198+
for v in fv
2199+
T = UnionAll(v, T)
2200+
end
2201+
end
21852202
else
21862203
T = rewrap_unionall(T, spsig)
21872204
end

base/compiler/ssair/inlining.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -817,8 +817,8 @@ end
817817
function compileable_specialization(mi::MethodInstance, effects::Effects,
818818
et::InliningEdgeTracker, @nospecialize(info::CallInfo); compilesig_invokes::Bool=true)
819819
mi_invoke = mi
820+
method, atype, sparams = mi.def::Method, mi.specTypes, mi.sparam_vals
820821
if compilesig_invokes
821-
method, atype, sparams = mi.def::Method, mi.specTypes, mi.sparam_vals
822822
new_atype = get_compileable_sig(method, atype, sparams)
823823
new_atype === nothing && return nothing
824824
if atype !== new_atype
@@ -836,7 +836,8 @@ function compileable_specialization(mi::MethodInstance, effects::Effects,
836836
return nothing
837837
end
838838
end
839-
add_inlining_backedge!(et, mi)
839+
add_inlining_backedge!(et, mi) # to the dispatch lookup
840+
push!(et.edges, method.sig, mi_invoke) # add_inlining_backedge to the invoke call
840841
return InvokeCase(mi_invoke, effects, info)
841842
end
842843

base/compiler/tfuncs.jl

+7-6
Original file line numberDiff line numberDiff line change
@@ -2620,13 +2620,15 @@ function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, s
26202620

26212621
if length(argtypes) == 3
26222622
aft = widenslotwrapper(argtypes[2])
2623-
if !isa(aft, Const) && !(isType(aft) && !has_free_typevars(aft)) &&
2624-
!(isconcretetype(aft) && !(aft <: Builtin))
2625-
return UNKNOWN
2626-
end
26272623
argtypes_vec = Any[aft, af_argtype.parameters...]
26282624
else
26292625
argtypes_vec = Any[af_argtype.parameters...]
2626+
isempty(argtypes_vec) && push!(argtypes_vec, Union{})
2627+
aft = argtypes_vec[1]
2628+
end
2629+
if !(isa(aft, Const) || (isType(aft) && !has_free_typevars(aft)) ||
2630+
(isconcretetype(aft) && !(aft <: Builtin) && !iskindtype(aft)))
2631+
return UNKNOWN
26302632
end
26312633

26322634
if contains_is(argtypes_vec, Union{})
@@ -2659,8 +2661,7 @@ function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, s
26592661
# in two ways: both as being a subtype of this, and
26602662
# because of LimitedAccuracy causes
26612663
return CallMeta(Type{<:rt}, EFFECTS_TOTAL, info)
2662-
elseif (isa(tt, Const) || isconstType(tt)) &&
2663-
(isa(aft, Const) || isconstType(aft))
2664+
elseif isa(tt, Const) || isconstType(tt)
26642665
# input arguments were known for certain
26652666
# XXX: this doesn't imply we know anything about rt
26662667
return CallMeta(Const(rt), EFFECTS_TOTAL, info)

0 commit comments

Comments
 (0)