Skip to content

Commit 4745ef8

Browse files
authored
Backports release 1.10 (#53201)
A few stragglers. Backported PRs: - [x] #53091 <!-- Ensure elision of `require_one_based_indexing` with high-dim array views --> - [x] #53117 <!-- Try to fix incorrect documentation of `nthreads` --> - [x] #52855 <!-- Fix variable name in scaling an `AbstractTriangular` with zero alpha --> - [x] #52952 <!-- [REPLCompletions] enable completions for `using Module.Inner|` --> - [x] #53101 <!-- Inplace transpose for unit Triangular may skip diagonal --> Need manual backport: - [ ] #52505 <!-- fix alignment of emit_unbox_store copy --> Non-merged PRs with backport label: - [ ] #53125 <!-- coverage: count coverage where explicitly requested by inference only --> - [ ] #52694 <!-- Reinstate similar for AbstractQ for backward compatibility --> - [ ] #51479 <!-- prevent code loading from lookin in the versioned environment when building Julia -->
2 parents 1dfdf66 + 6fcff37 commit 4745ef8

File tree

8 files changed

+160
-31
lines changed

8 files changed

+160
-31
lines changed

base/abstractarray.jl

+7-4
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,20 @@ end
103103
has_offset_axes(A, B, ...)
104104
105105
Return `true` if the indices of `A` start with something other than 1 along any axis.
106-
If multiple arguments are passed, equivalent to `has_offset_axes(A) | has_offset_axes(B) | ...`.
106+
If multiple arguments are passed, equivalent to `has_offset_axes(A) || has_offset_axes(B) || ...`.
107107
108108
See also [`require_one_based_indexing`](@ref).
109109
"""
110+
has_offset_axes() = false
110111
has_offset_axes(A) = _any_tuple(x->Int(first(x))::Int != 1, false, axes(A)...)
111112
has_offset_axes(A::AbstractVector) = Int(firstindex(A))::Int != 1 # improve performance of a common case (ranges)
112-
# Use `_any_tuple` to avoid unneeded invoke.
113-
# note: this could call `any` directly if the compiler can infer it
114-
has_offset_axes(As...) = _any_tuple(has_offset_axes, false, As...)
115113
has_offset_axes(::Colon) = false
116114
has_offset_axes(::Array) = false
115+
# note: this could call `any` directly if the compiler can infer it. We don't use _any_tuple
116+
# here because it stops full elision in some cases (#49332) and we don't need handling of
117+
# `missing` (has_offset_axes(A) always returns a Bool)
118+
has_offset_axes(A, As...) = has_offset_axes(A) || has_offset_axes(As...)
119+
117120

118121
"""
119122
require_one_based_indexing(A::AbstractArray)

base/threadingconstructs.jl

+3-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ maxthreadid() = Int(Core.Intrinsics.atomic_pointerref(cglobal(:jl_n_threads, Cin
4444
"""
4545
Threads.nthreads(:default | :interactive) -> Int
4646
47-
Get the current number of threads within the specified thread pool. The threads in default
48-
have id numbers `1:nthreads(:default)`.
47+
Get the current number of threads within the specified thread pool. The threads in `:interactive`
48+
have id numbers `1:nthreads(:interactive)`, and the threads in `:default` have id numbers in
49+
`nthreads(:interactive) .+ (1:nthreads(:default))`.
4950
5051
See also `BLAS.get_num_threads` and `BLAS.set_num_threads` in the [`LinearAlgebra`](@ref
5152
man-linalg) standard library, and `nprocs()` in the [`Distributed`](@ref man-distributed)

stdlib/LinearAlgebra/src/triangular.jl

+14-14
Original file line numberDiff line numberDiff line change
@@ -406,13 +406,13 @@ transpose(A::UnitLowerTriangular) = UnitUpperTriangular(transpose(A.data))
406406
transpose(A::UnitUpperTriangular) = UnitLowerTriangular(transpose(A.data))
407407

408408
transpose!(A::LowerTriangular) = UpperTriangular(copytri!(A.data, 'L', false, true))
409-
transpose!(A::UnitLowerTriangular) = UnitUpperTriangular(copytri!(A.data, 'L', false, true))
409+
transpose!(A::UnitLowerTriangular) = UnitUpperTriangular(copytri!(A.data, 'L', false, false))
410410
transpose!(A::UpperTriangular) = LowerTriangular(copytri!(A.data, 'U', false, true))
411-
transpose!(A::UnitUpperTriangular) = UnitLowerTriangular(copytri!(A.data, 'U', false, true))
411+
transpose!(A::UnitUpperTriangular) = UnitLowerTriangular(copytri!(A.data, 'U', false, false))
412412
adjoint!(A::LowerTriangular) = UpperTriangular(copytri!(A.data, 'L' , true, true))
413-
adjoint!(A::UnitLowerTriangular) = UnitUpperTriangular(copytri!(A.data, 'L' , true, true))
413+
adjoint!(A::UnitLowerTriangular) = UnitUpperTriangular(copytri!(A.data, 'L' , true, false))
414414
adjoint!(A::UpperTriangular) = LowerTriangular(copytri!(A.data, 'U' , true, true))
415-
adjoint!(A::UnitUpperTriangular) = UnitLowerTriangular(copytri!(A.data, 'U' , true, true))
415+
adjoint!(A::UnitUpperTriangular) = UnitLowerTriangular(copytri!(A.data, 'U' , true, false))
416416

417417
diag(A::LowerTriangular) = diag(A.data)
418418
diag(A::UnitLowerTriangular) = fill(oneunit(eltype(A)), size(A,1))
@@ -471,7 +471,7 @@ end
471471

472472
function _triscale!(A::UpperTriangular, B::UpperTriangular, c::Number, _add)
473473
n = checksquare(B)
474-
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
474+
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
475475
for j = 1:n
476476
for i = 1:j
477477
@inbounds _modify!(_add, B.data[i,j] * c, A.data, (i,j))
@@ -481,8 +481,8 @@ function _triscale!(A::UpperTriangular, B::UpperTriangular, c::Number, _add)
481481
end
482482
function _triscale!(A::UpperTriangular, c::Number, B::UpperTriangular, _add)
483483
n = checksquare(B)
484-
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
485-
for j = 1:n
484+
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
485+
for j = 1:n
486486
for i = 1:j
487487
@inbounds _modify!(_add, c * B.data[i,j], A.data, (i,j))
488488
end
@@ -491,7 +491,7 @@ function _triscale!(A::UpperTriangular, c::Number, B::UpperTriangular, _add)
491491
end
492492
function _triscale!(A::UpperOrUnitUpperTriangular, B::UnitUpperTriangular, c::Number, _add)
493493
n = checksquare(B)
494-
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
494+
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
495495
for j = 1:n
496496
@inbounds _modify!(_add, c, A, (j,j))
497497
for i = 1:(j - 1)
@@ -502,7 +502,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, B::UnitUpperTriangular, c::Nu
502502
end
503503
function _triscale!(A::UpperOrUnitUpperTriangular, c::Number, B::UnitUpperTriangular, _add)
504504
n = checksquare(B)
505-
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
505+
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
506506
for j = 1:n
507507
@inbounds _modify!(_add, c, A, (j,j))
508508
for i = 1:(j - 1)
@@ -513,7 +513,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, c::Number, B::UnitUpperTriang
513513
end
514514
function _triscale!(A::LowerTriangular, B::LowerTriangular, c::Number, _add)
515515
n = checksquare(B)
516-
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
516+
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
517517
for j = 1:n
518518
for i = j:n
519519
@inbounds _modify!(_add, B.data[i,j] * c, A.data, (i,j))
@@ -523,8 +523,8 @@ function _triscale!(A::LowerTriangular, B::LowerTriangular, c::Number, _add)
523523
end
524524
function _triscale!(A::LowerTriangular, c::Number, B::LowerTriangular, _add)
525525
n = checksquare(B)
526-
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
527-
for j = 1:n
526+
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
527+
for j = 1:n
528528
for i = j:n
529529
@inbounds _modify!(_add, c * B.data[i,j], A.data, (i,j))
530530
end
@@ -533,7 +533,7 @@ function _triscale!(A::LowerTriangular, c::Number, B::LowerTriangular, _add)
533533
end
534534
function _triscale!(A::LowerOrUnitLowerTriangular, B::UnitLowerTriangular, c::Number, _add)
535535
n = checksquare(B)
536-
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
536+
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
537537
for j = 1:n
538538
@inbounds _modify!(_add, c, A, (j,j))
539539
for i = (j + 1):n
@@ -544,7 +544,7 @@ function _triscale!(A::LowerOrUnitLowerTriangular, B::UnitLowerTriangular, c::Nu
544544
end
545545
function _triscale!(A::LowerOrUnitLowerTriangular, c::Number, B::UnitLowerTriangular, _add)
546546
n = checksquare(B)
547-
iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta)
547+
iszero(_add.alpha) && return _rmul_or_fill!(A, _add.beta)
548548
for j = 1:n
549549
@inbounds _modify!(_add, c, A, (j,j))
550550
for i = (j + 1):n

stdlib/LinearAlgebra/test/triangular.jl

+14-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ debug && println("Test basic type functionality")
1818
@test LowerTriangular(randn(3, 3)) |> t -> [size(t, i) for i = 1:3] == [size(Matrix(t), i) for i = 1:3]
1919

2020
# The following test block tries to call all methods in base/linalg/triangular.jl in order for a combination of input element types. Keep the ordering when adding code.
21-
for elty1 in (Float32, Float64, BigFloat, ComplexF32, ComplexF64, Complex{BigFloat}, Int)
21+
@testset for elty1 in (Float32, Float64, BigFloat, ComplexF32, ComplexF64, Complex{BigFloat}, Int)
2222
# Begin loop for first Triangular matrix
2323
for (t1, uplo1) in ((UpperTriangular, :U),
2424
(UnitUpperTriangular, :U),
@@ -239,6 +239,11 @@ for elty1 in (Float32, Float64, BigFloat, ComplexF32, ComplexF64, Complex{BigFlo
239239
A2tmp = unitt(A1)
240240
mul!(A1tmp, cr, A2tmp)
241241
@test A1tmp == cr * A2tmp
242+
243+
A1tmp .= A1
244+
@test mul!(A1tmp, A2tmp, cr, 0, 2) == 2A1
245+
A1tmp .= A1
246+
@test mul!(A1tmp, cr, A2tmp, 0, 2) == 2A1
242247
else
243248
A1tmp = copy(A1)
244249
rmul!(A1tmp, ci)
@@ -866,4 +871,12 @@ end
866871
end
867872
end
868873

874+
@testset "transpose triangular diagonal" begin
875+
M = Matrix{BigFloat}(undef, 2, 2);
876+
M[1,2] = 3;
877+
U = UnitUpperTriangular(M)
878+
Ut = transpose(U)
879+
@test transpose!(U) == Ut
880+
end
881+
869882
end # module TestTriangular

stdlib/Mmap/src/Mmap.jl

+28-3
Original file line numberDiff line numberDiff line change
@@ -208,18 +208,43 @@ function mmap(io::IO,
208208
mmaplen = (offset - offset_page) + len
209209

210210
file_desc = gethandle(io)
211+
szfile = convert(Csize_t, len + offset)
212+
requestedSizeLarger = false
213+
if !(io isa Mmap.Anonymous)
214+
@static if !Sys.isapple()
215+
requestedSizeLarger = szfile > filesize(io)
216+
end
217+
end
211218
# platform-specific mmapping
212219
@static if Sys.isunix()
213220
prot, flags, iswrite = settings(file_desc, shared)
214-
iswrite && grow && grow!(io, offset, len)
221+
if requestedSizeLarger
222+
if iswrite
223+
if grow
224+
grow!(io, offset, len)
225+
else
226+
throw(ArgumentError("requested size $szfile larger than file size $(filesize(io)), but requested not to grow"))
227+
end
228+
else
229+
throw(ArgumentError("unable to increase file size to $szfile due to read-only permissions"))
230+
end
231+
end
232+
@static if Sys.isapple()
233+
iswrite && grow && grow!(io, offset, len)
234+
end
215235
# mmap the file
216236
ptr = ccall(:jl_mmap, Ptr{Cvoid}, (Ptr{Cvoid}, Csize_t, Cint, Cint, RawFD, Int64),
217237
C_NULL, mmaplen, prot, flags, file_desc, offset_page)
218238
systemerror("memory mapping failed", reinterpret(Int, ptr) == -1)
219239
else
220240
name, readonly, create = settings(io)
221-
szfile = convert(Csize_t, len + offset)
222-
readonly && szfile > filesize(io) && throw(ArgumentError("unable to increase file size to $szfile due to read-only permissions"))
241+
if requestedSizeLarger
242+
if readonly
243+
throw(ArgumentError("unable to increase file size to $szfile due to read-only permissions"))
244+
elseif !grow
245+
throw(ArgumentError("requested size $szfile larger than file size $(filesize(io)), but requested not to grow"))
246+
end
247+
end
223248
handle = create ? ccall(:CreateFileMappingW, stdcall, Ptr{Cvoid}, (OS_HANDLE, Ptr{Cvoid}, DWORD, DWORD, DWORD, Cwstring),
224249
file_desc, C_NULL, readonly ? PAGE_READONLY : PAGE_READWRITE, szfile >> 32, szfile & typemax(UInt32), name) :
225250
ccall(:OpenFileMappingW, stdcall, Ptr{Cvoid}, (DWORD, Cint, Cwstring),

stdlib/REPL/src/REPLCompletions.jl

+46-7
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,10 @@ function project_deps_get_completion_candidates(pkgstarts::String, project_file:
980980
return Completion[PackageCompletion(name) for name in loading_candidates]
981981
end
982982

983-
function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ffunc::Function), context_module::Module, string::String, name::String, pos::Int, dotpos::Int, startpos::Int, comp_keywords=false)
983+
function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ffunc),
984+
context_module::Module, string::String, name::String,
985+
pos::Int, dotpos::Int, startpos::Int;
986+
comp_keywords=false)
984987
ex = nothing
985988
if comp_keywords
986989
append!(suggestions, complete_keyword(name))
@@ -1022,10 +1025,41 @@ function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ff
10221025
if something(findlast(in(non_identifier_chars), s), 0) < something(findlast(isequal('.'), s), 0)
10231026
lookup_name, name = rsplit(s, ".", limit=2)
10241027
name = String(name)
1025-
10261028
ex = Meta.parse(lookup_name, raise=false, depwarn=false)
10271029
end
10281030
isexpr(ex, :incomplete) && (ex = nothing)
1031+
elseif isexpr(ex, (:using, :import))
1032+
arg1 = ex.args[1]
1033+
if isexpr(arg1, :.)
1034+
# We come here for cases like:
1035+
# - `string`: "using Mod1.Mod2.M"
1036+
# - `ex`: :(using Mod1.Mod2)
1037+
# - `name`: "M"
1038+
# Now we transform `ex` to `:(Mod1.Mod2)` to allow `complete_symbol` to
1039+
# complete for inner modules whose name starts with `M`.
1040+
# Note that `ffunc` is set to `module_filter` within `completions`
1041+
ex = nothing
1042+
firstdot = true
1043+
for arg = arg1.args
1044+
if arg === :.
1045+
# override `context_module` if multiple `.` accessors are used
1046+
if firstdot
1047+
firstdot = false
1048+
else
1049+
context_module = parentmodule(context_module)
1050+
end
1051+
elseif arg isa Symbol
1052+
if ex === nothing
1053+
ex = arg
1054+
else
1055+
ex = Expr(:., out, QuoteNode(arg))
1056+
end
1057+
else # invalid expression
1058+
ex = nothing
1059+
break
1060+
end
1061+
end
1062+
end
10291063
elseif isexpr(ex, :call) && length(ex.args) > 1
10301064
isinfix = s[end] != ')'
10311065
# A complete call expression that does not finish with ')' is an infix call.
@@ -1106,8 +1140,9 @@ function completions(string::String, pos::Int, context_module::Module=Main, shif
11061140
ok && return ret
11071141
startpos = first(varrange) + 4
11081142
dotpos = something(findprev(isequal('.'), string, first(varrange)-1), 0)
1109-
return complete_identifiers!(Completion[], ffunc, context_module, string,
1110-
string[startpos:pos], pos, dotpos, startpos)
1143+
name = string[startpos:pos]
1144+
return complete_identifiers!(Completion[], ffunc, context_module, string, name, pos,
1145+
dotpos, startpos)
11111146
elseif inc_tag === :cmd
11121147
# TODO: should this call shell_completions instead of partially reimplementing it?
11131148
let m = match(r"[\t\n\r\"`><=*?|]| (?!\\)", reverse(partial)) # fuzzy shell_parse in reverse
@@ -1255,16 +1290,20 @@ function completions(string::String, pos::Int, context_module::Module=Main, shif
12551290
end
12561291
end
12571292
end
1258-
ffunc = (mod,x)->(Base.isbindingresolved(mod, x) && isdefined(mod, x) && isa(getfield(mod, x), Module))
1293+
ffunc = module_filter
12591294
comp_keywords = false
12601295
end
12611296

12621297
startpos == 0 && (pos = -1)
12631298
dotpos < startpos && (dotpos = startpos - 1)
1264-
return complete_identifiers!(suggestions, ffunc, context_module, string,
1265-
name, pos, dotpos, startpos, comp_keywords)
1299+
return complete_identifiers!(suggestions, ffunc, context_module, string, name, pos,
1300+
dotpos, startpos;
1301+
comp_keywords)
12661302
end
12671303

1304+
module_filter(mod::Module, x::Symbol) =
1305+
Base.isbindingresolved(mod, x) && isdefined(mod, x) && isa(getglobal(mod, x), Module)
1306+
12681307
function shell_completions(string, pos)
12691308
# First parse everything up to the current position
12701309
scs = string[1:pos]

stdlib/REPL/test/replcompletions.jl

+44
Original file line numberDiff line numberDiff line change
@@ -1939,3 +1939,47 @@ let s = "@issue51827 Base.ac"
19391939
@test res
19401940
@test "acquire" in c
19411941
end
1942+
1943+
# JuliaLang/julia#52922
1944+
let s = "using Base.Th"
1945+
c, r, res = test_complete_context(s)
1946+
@test res
1947+
@test "Threads" in c
1948+
end
1949+
let s = "using Base."
1950+
c, r, res = test_complete_context(s)
1951+
@test res
1952+
@test "BinaryPlatforms" in c
1953+
end
1954+
# test cases with the `.` accessor
1955+
module Issue52922
1956+
module Inner1
1957+
module Inner12 end
1958+
end
1959+
module Inner2 end
1960+
end
1961+
let s = "using .Iss"
1962+
c, r, res = test_complete_context(s)
1963+
@test res
1964+
@test "Issue52922" in c
1965+
end
1966+
let s = "using .Issue52922.Inn"
1967+
c, r, res = test_complete_context(s)
1968+
@test res
1969+
@test "Inner1" in c
1970+
end
1971+
let s = "using .Inner1.Inn"
1972+
c, r, res = test_complete_context(s, Issue52922)
1973+
@test res
1974+
@test "Inner12" in c
1975+
end
1976+
let s = "using ..Issue52922.Inn"
1977+
c, r, res = test_complete_context(s, Issue52922.Inner1)
1978+
@test res
1979+
@test "Inner2" in c
1980+
end
1981+
let s = "using ...Issue52922.Inn"
1982+
c, r, res = test_complete_context(s, Issue52922.Inner1.Inner12)
1983+
@test res
1984+
@test "Inner2" in c
1985+
end

test/abstractarray.jl

+4
Original file line numberDiff line numberDiff line change
@@ -1825,13 +1825,17 @@ end
18251825

18261826
@testset "type-based offset axes check" begin
18271827
a = randn(ComplexF64, 10)
1828+
b = randn(ComplexF64, 4, 4, 4, 4)
18281829
ta = reinterpret(Float64, a)
18291830
tb = reinterpret(Float64, view(a, 1:2:10))
18301831
tc = reinterpret(Float64, reshape(view(a, 1:3:10), 2, 2, 1))
1832+
td = view(b, :, :, 1, 1)
18311833
# Issue #44040
18321834
@test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(ta, tc))
18331835
@test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(tc, tc))
18341836
@test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(ta, tc, tb))
1837+
# Issue #49332
1838+
@test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(td, td, td))
18351839
# Ranges && CartesianIndices
18361840
@test IRUtils.fully_eliminated(Base.require_one_based_indexing, Base.typesof(1:10, Base.OneTo(10), 1.0:2.0, LinRange(1.0, 2.0, 2), 1:2:10, CartesianIndices((1:2:10, 1:2:10))))
18371841
# Remind us to call `any` in `Base.has_offset_axes` once our compiler is ready.

0 commit comments

Comments
 (0)