Skip to content

Commit 85d852d

Browse files
authored
Backports for 1.10.0. (#52622)
2 parents b6dd527 + 3fd8bae commit 85d852d

File tree

13 files changed

+235
-59
lines changed

13 files changed

+235
-59
lines changed

NEWS.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ Language changes
3232
Compiler/Runtime improvements
3333
-----------------------------
3434

35-
* Updated GC heuristics to count allocated pages instead of object sizes ([#50144]). This should help
36-
some programs that consumed excessive memory before.
3735
* The mark phase of the garbage collector is now multi-threaded ([#48600]).
3836
* [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]).
3937
This should resolve many segmentation faults previously observed on this platform.
@@ -158,6 +156,7 @@ Deprecated or removed
158156
[#48899]: https://github.com/JuliaLang/julia/issues/48899
159157
[#48979]: https://github.com/JuliaLang/julia/issues/48979
160158
[#49020]: https://github.com/JuliaLang/julia/issues/49020
159+
[#49052]: https://github.com/JuliaLang/julia/issues/49052
161160
[#49110]: https://github.com/JuliaLang/julia/issues/49110
162161
[#49266]: https://github.com/JuliaLang/julia/issues/49266
163162
[#49405]: https://github.com/JuliaLang/julia/issues/49405
@@ -167,5 +166,4 @@ Deprecated or removed
167166
[#49745]: https://github.com/JuliaLang/julia/issues/49745
168167
[#49795]: https://github.com/JuliaLang/julia/issues/49795
169168
[#49959]: https://github.com/JuliaLang/julia/issues/49959
170-
[#50144]: https://github.com/JuliaLang/julia/issues/50144
171169
[#50218]: https://github.com/JuliaLang/julia/issues/50218

base/compiler/tfuncs.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -1731,7 +1731,7 @@ const _tvarnames = Symbol[:_A, :_B, :_C, :_D, :_E, :_F, :_G, :_H, :_I, :_J, :_K,
17311731
end
17321732
return allconst ? Const(ty) : Type{ty}
17331733
end
1734-
istuple = isa(headtype, Type) && (headtype == Tuple)
1734+
istuple = headtype === Tuple
17351735
if !istuple && !isa(headtype, UnionAll) && !isvarargtype(headtype)
17361736
return Union{}
17371737
end

base/methodshow.jl

+24-13
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,29 @@ function show_method_list_header(io::IO, ms::MethodList, namefmt::Function)
286286
!iszero(n) && print(io, ":")
287287
end
288288

289+
# Determine the `modulecolor` value to pass to `show_method`
290+
function _modulecolor(method::Method)
291+
mmt = get_methodtable(method)
292+
if mmt === nothing || mmt.module === parentmodule(method)
293+
return nothing
294+
end
295+
# `mmt` is only particularly relevant for external method tables. Since the primary
296+
# method table is shared, we now need to distinguish "primary" methods by trying to
297+
# check if there is a primary `DataType` to identify it with. c.f. how `jl_method_def`
298+
# would derive this same information (for the name).
299+
ft = argument_datatype((unwrap_unionall(method.sig)::DataType).parameters[1])
300+
# `ft` should be the type associated with the first argument in the method signature.
301+
# If it's `Type`, try to unwrap it again.
302+
if isType(ft)
303+
ft = argument_datatype(ft.parameters[1])
304+
end
305+
if ft === nothing || parentmodule(method) === parentmodule(ft) !== Core
306+
return nothing
307+
end
308+
m = parentmodule_before_main(method)
309+
return get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m)
310+
end
311+
289312
function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=true)
290313
mt = ms.mt
291314
name = mt.name
@@ -300,12 +323,6 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru
300323
last_shown_line_infos = get(io, :last_shown_line_infos, nothing)
301324
last_shown_line_infos === nothing || empty!(last_shown_line_infos)
302325

303-
modul = if mt === _TYPE_NAME.mt && length(ms) > 0 # type constructor
304-
which(ms.ms[1].module, ms.ms[1].name)
305-
else
306-
mt.module
307-
end
308-
309326
digit_align_width = length(string(max > 0 ? max : length(ms)))
310327

311328
for meth in ms
@@ -315,13 +332,7 @@ function show_method_table(io::IO, ms::MethodList, max::Int=-1, header::Bool=tru
315332

316333
print(io, " ", lpad("[$n]", digit_align_width + 2), " ")
317334

318-
modulecolor = if parentmodule(meth) == modul
319-
nothing
320-
else
321-
m = parentmodule_before_main(meth)
322-
get!(() -> popfirst!(STACKTRACE_MODULECOLORS), STACKTRACE_FIXEDCOLORS, m)
323-
end
324-
show_method(io, meth; modulecolor)
335+
show_method(io, meth; modulecolor=_modulecolor(meth))
325336

326337
file, line = updated_methodloc(meth)
327338
if last_shown_line_infos !== nothing

base/reflection.jl

+5-1
Original file line numberDiff line numberDiff line change
@@ -2033,7 +2033,11 @@ function delete_method(m::Method)
20332033
end
20342034

20352035
function get_methodtable(m::Method)
2036-
return ccall(:jl_method_get_table, Any, (Any,), m)::Core.MethodTable
2036+
mt = ccall(:jl_method_get_table, Any, (Any,), m)
2037+
if mt === nothing
2038+
return nothing
2039+
end
2040+
return mt::Core.MethodTable
20372041
end
20382042

20392043
"""

doc/src/manual/environment-variables.md

+9
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,15 @@ If set to `true`, Pkg operations which use the git protocol will use an external
240240

241241
The accuracy of the package resolver. This should be a positive integer, the default is `1`.
242242

243+
### [`JULIA_PKG_PRESERVE_TIERED_INSTALLED`](@id JULIA_PKG_PRESERVE_TIERED_INSTALLED)
244+
245+
Change the default package installation strategy to `Pkg.PRESERVE_TIERED_INSTALLED`
246+
to let the package manager try to install versions of packages while keeping as many
247+
versions of packages already installed as possible.
248+
249+
!!! compat "Julia 1.9"
250+
This only affects Julia 1.9 and above.
251+
243252
## Network transport
244253

245254
### `JULIA_NO_VERIFY_HOSTS` / `JULIA_SSL_NO_VERIFY_HOSTS` / `JULIA_SSH_NO_VERIFY_HOSTS` / `JULIA_ALWAYS_VERIFY_HOSTS`

src/julia-syntax.scm

+1-1
Original file line numberDiff line numberDiff line change
@@ -3580,7 +3580,7 @@ f(x) = yt(x)
35803580
(rhs (convert-for-type-decl rhs1 (cl-convert vt fname lam #f #f #f interp opaq (table) locals) #t lam))
35813581
(ex (cond (closed `(call (core setfield!)
35823582
,(if interp
3583-
`($ ,var)
3583+
`($ (call (core QuoteNode) ,var))
35843584
(capt-var-access var fname opaq))
35853585
(inert contents)
35863586
,rhs))

stdlib/REPL/src/REPLCompletions.jl

+23-27
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export completions, shell_completions, bslash_completions, completion_text
77
using Core: CodeInfo, MethodInstance, CodeInstance, Const
88
const CC = Core.Compiler
99
using Base.Meta
10-
using Base: propertynames, something
10+
using Base: propertynames, something, IdSet
1111

1212
abstract type Completion end
1313

@@ -659,6 +659,26 @@ function complete_methods(ex_org::Expr, context_module::Module=Main, shift::Bool
659659
end
660660

661661
MAX_ANY_METHOD_COMPLETIONS::Int = 10
662+
function recursive_explore_names!(seen::IdSet, callee_module::Module, initial_module::Module, exploredmodules::IdSet{Module}=IdSet{Module}())
663+
push!(exploredmodules, callee_module)
664+
for name in names(callee_module; all=true, imported=true)
665+
if !Base.isdeprecated(callee_module, name) && !startswith(string(name), '#') && isdefined(initial_module, name)
666+
func = getfield(callee_module, name)
667+
if !isa(func, Module)
668+
funct = Core.Typeof(func)
669+
push!(seen, funct)
670+
elseif isa(func, Module) && func exploredmodules
671+
recursive_explore_names!(seen, func, initial_module, exploredmodules)
672+
end
673+
end
674+
end
675+
end
676+
function recursive_explore_names(callee_module::Module, initial_module::Module)
677+
seen = IdSet{Any}()
678+
recursive_explore_names!(seen, callee_module, initial_module)
679+
seen
680+
end
681+
662682
function complete_any_methods(ex_org::Expr, callee_module::Module, context_module::Module, moreargs::Bool, shift::Bool)
663683
out = Completion[]
664684
args_ex, kwargs_ex, kwargs_flag = try
@@ -674,32 +694,8 @@ function complete_any_methods(ex_org::Expr, callee_module::Module, context_modul
674694
# semicolon for the ".?(" syntax
675695
moreargs && push!(args_ex, Vararg{Any})
676696

677-
seen = Base.IdSet()
678-
for name in names(callee_module; all=true)
679-
if !Base.isdeprecated(callee_module, name) && isdefined(callee_module, name) && !startswith(string(name), '#')
680-
func = getfield(callee_module, name)
681-
if !isa(func, Module)
682-
funct = Core.Typeof(func)
683-
if !in(funct, seen)
684-
push!(seen, funct)
685-
complete_methods!(out, funct, args_ex, kwargs_ex, MAX_ANY_METHOD_COMPLETIONS, false)
686-
end
687-
elseif callee_module === Main && isa(func, Module)
688-
callee_module2 = func
689-
for name in names(callee_module2)
690-
if !Base.isdeprecated(callee_module2, name) && isdefined(callee_module2, name) && !startswith(string(name), '#')
691-
func = getfield(callee_module, name)
692-
if !isa(func, Module)
693-
funct = Core.Typeof(func)
694-
if !in(funct, seen)
695-
push!(seen, funct)
696-
complete_methods!(out, funct, args_ex, kwargs_ex, MAX_ANY_METHOD_COMPLETIONS, false)
697-
end
698-
end
699-
end
700-
end
701-
end
702-
end
697+
for seen_name in recursive_explore_names(callee_module, callee_module)
698+
complete_methods!(out, seen_name, args_ex, kwargs_ex, MAX_ANY_METHOD_COMPLETIONS, false)
703699
end
704700

705701
if !shift

stdlib/REPL/test/replcompletions.jl

+7
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ let ex = quote
140140
struct WeirdNames end
141141
Base.propertynames(::WeirdNames) = (Symbol("oh no!"), Symbol("oh yes!"))
142142

143+
# https://github.com/JuliaLang/julia/issues/52551#issuecomment-1858543413
144+
export exported_symbol
145+
exported_symbol(::WeirdNames) = nothing
146+
143147
end # module CompletionFoo
144148
test_repl_comp_dict = CompletionFoo.test_dict
145149
test_repl_comp_customdict = CompletionFoo.test_customdict
@@ -740,6 +744,9 @@ end
740744

741745
#TODO: @test_nocompletion("CompletionFoo.?(3; len2=5; ")
742746

747+
# https://github.com/JuliaLang/julia/issues/52551
748+
@test !isempty(test_complete("?("))
749+
743750
#################################################################
744751

745752
# Test method completion with varargs

stdlib/Unicode/src/Unicode.jl

+70-11
Original file line numberDiff line numberDiff line change
@@ -208,12 +208,19 @@ end
208208

209209
using Base.Unicode: utf8proc_error, UTF8PROC_DECOMPOSE, UTF8PROC_CASEFOLD, UTF8PROC_STRIPMARK
210210

211-
function _decompose_char!(codepoint::Union{Integer,Char}, dest::Vector{UInt32}, options::Integer)
212-
ret = @ccall utf8proc_decompose_char(codepoint::UInt32, dest::Ptr{UInt32}, length(dest)::Int, options::Cint, C_NULL::Ptr{Cint})::Int
211+
function _decompose_char!(codepoint::Union{Integer,Char}, dest::Vector{UInt32}, offset::Integer, options::Integer)
212+
ret = GC.@preserve dest @ccall utf8proc_decompose_char(codepoint::UInt32, pointer(dest, 1+offset)::Ptr{UInt32}, (length(dest)-offset)::Int, options::Cint, C_NULL::Ptr{Cint})::Int
213213
ret < 0 && utf8proc_error(ret)
214214
return ret
215215
end
216216

217+
# would be good to have higher-level accessor functions in utf8proc. alternatively,
218+
# we could mirror the whole utf8proc_property_t struct in Julia, but that is annoying
219+
# because of the bitfields.
220+
combining_class(uc::Integer) =
221+
0x000301 uc 0x10ffff ? unsafe_load(ccall(:utf8proc_get_property, Ptr{UInt16}, (UInt32,), uc), 2) : 0x0000
222+
combining_class(c::AbstractChar) = ismalformed(c) ? 0x0000 : combining_class(UInt32(c))
223+
217224
"""
218225
isequal_normalized(s1::AbstractString, s2::AbstractString; casefold=false, stripmark=false, chartransform=identity)
219226
@@ -225,6 +232,9 @@ As with [`Unicode.normalize`](@ref), you can also pass an arbitrary
225232
function via the `chartransform` keyword (mapping `Integer` codepoints to codepoints)
226233
to perform custom normalizations, such as [`Unicode.julia_chartransform`](@ref).
227234
235+
!!! compat "Julia 1.8"
236+
The `isequal_normalized` function was added in Julia 1.8.
237+
228238
# Examples
229239
230240
For example, the string `"noël"` can be constructed in two canonically equivalent ways
@@ -251,29 +261,78 @@ julia> isequal_normalized(s1, "NOËL", casefold=true)
251261
true
252262
```
253263
"""
254-
function isequal_normalized(s1::AbstractString, s2::AbstractString; casefold::Bool=false, stripmark::Bool=false, chartransform=identity)
255-
function decompose_next_char!(c, state, d, options, s)
256-
n = _decompose_char!(c, d, options)
257-
if n > length(d) # may be possible in future Unicode versions?
258-
n = _decompose_char!(c, resize!(d, n), options)
264+
isequal_normalized(s1::AbstractString, s2::AbstractString; casefold::Bool=false, stripmark::Bool=false, chartransform=identity) =
265+
_isequal_normalized!(s1, s2, Vector{UInt32}(undef, 4), Vector{UInt32}(undef, 4), chartransform; casefold, stripmark)
266+
267+
# like isequal_normalized, but takes pre-allocated codepoint buffers as arguments, and chartransform is a positional argument
268+
function _isequal_normalized!(s1::AbstractString, s2::AbstractString,
269+
d1::Vector{UInt32}, d2::Vector{UInt32}, chartransform::F=identity;
270+
casefold::Bool=false, stripmark::Bool=false) where {F}
271+
function decompose_next_chars!(state, d, options, s)
272+
local n
273+
offset = 0
274+
@inbounds while true
275+
# read a char and decompose it to d
276+
c = chartransform(UInt32(state[1]))
277+
state = iterate(s, state[2])
278+
if c < 0x80 # fast path for common ASCII case
279+
n = 1 + offset
280+
n > length(d) && resize!(d, 2n)
281+
d[n] = casefold ? (0x41 c 0x5A ? c+0x20 : c) : c
282+
break # ASCII characters are all zero combining class
283+
else
284+
while true
285+
n = _decompose_char!(c, d, offset, options) + offset
286+
if n > length(d)
287+
resize!(d, 2n)
288+
continue
289+
end
290+
break
291+
end
292+
end
293+
294+
# decomposed chars must be sorted in ascending order of combining class,
295+
# which means we need to keep fetching chars until we get to non-combining
296+
(iszero(combining_class(d[n])) || isnothing(state)) && break # non-combining
297+
offset = n
259298
end
260-
return 1, n, iterate(s, state)
299+
300+
# sort by combining class
301+
if n < 32 # almost always true
302+
for j1 = 2:n # insertion sort
303+
cc = combining_class(d[j1])
304+
iszero(cc) && continue # don't re-order non-combiners
305+
for j2 = j1:-1:2
306+
combining_class(d[j2-1]) cc && break
307+
d[j2-1], d[j2] = d[j2], d[j2-1]
308+
end
309+
end
310+
else # avoid n^2 complexity in crazy large-n case
311+
j = 1
312+
@views while j < n
313+
j₀ = j + something(findnext(iszero combining_class, d[j+1:n], 1), n+1-j)
314+
sort!(d[j:j₀-1], by=combining_class)
315+
j = j₀
316+
end
317+
end
318+
319+
# split return statement to help type inference:
320+
return state === nothing ? (1, n, nothing) : (1, n, state)
261321
end
262322
options = UTF8PROC_DECOMPOSE
263323
casefold && (options |= UTF8PROC_CASEFOLD)
264324
stripmark && (options |= UTF8PROC_STRIPMARK)
265325
i1,i2 = iterate(s1),iterate(s2)
266-
d1,d2 = Vector{UInt32}(undef, 4), Vector{UInt32}(undef, 4) # codepoint buffers
267326
n1 = n2 = 0 # lengths of codepoint buffers
268327
j1 = j2 = 1 # indices in d1, d2
269328
while true
270329
if j1 > n1
271330
i1 === nothing && return i2 === nothing && j2 > n2
272-
j1, n1, i1 = decompose_next_char!(chartransform(UInt32(i1[1])), i1[2], d1, options, s1)
331+
j1, n1, i1 = decompose_next_chars!(i1, d1, options, s1)
273332
end
274333
if j2 > n2
275334
i2 === nothing && return false
276-
j2, n2, i2 = decompose_next_char!(chartransform(UInt32(i2[1])), i2[2], d2, options, s2)
335+
j2, n2, i2 = decompose_next_chars!(i2, d2, options, s2)
277336
end
278337
d1[j1] == d2[j2] || return false
279338
j1 += 1; j2 += 1

0 commit comments

Comments
 (0)