From 8f76c69cdc3f85c7d29265dfe749f900094a01a3 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Tue, 19 Mar 2024 14:42:23 +0900 Subject: [PATCH 001/123] minor refactoring on `find_method_matches` (#53741) So that it can be tested in isolation easier. --- base/compiler/abstractinterpretation.jl | 135 ++++++++++++------------ base/compiler/tfuncs.jl | 3 +- 2 files changed, 71 insertions(+), 67 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 443b4beba315dd..ba8f0b6709f8ff 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -22,8 +22,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f), end argtypes = arginfo.argtypes - matches = find_matching_methods(๐•ƒแตข, argtypes, atype, method_table(interp), - InferenceParams(interp).max_union_splitting, max_methods) + matches = find_method_matches(interp, argtypes, atype; max_methods) if isa(matches, FailedMethodMatch) add_remark!(interp, sv, matches.reason) return CallMeta(Any, Any, Effects(), NoCallInfo()) @@ -255,73 +254,79 @@ struct UnionSplitMethodMatches end any_ambig(m::UnionSplitMethodMatches) = any(any_ambig, m.info.matches) -function find_matching_methods(๐•ƒ::AbstractLattice, - argtypes::Vector{Any}, @nospecialize(atype), method_table::MethodTableView, - max_union_splitting::Int, max_methods::Int) - # NOTE this is valid as far as any "constant" lattice element doesn't represent `Union` type - if 1 < unionsplitcost(๐•ƒ, argtypes) <= max_union_splitting - split_argtypes = switchtupleunion(๐•ƒ, argtypes) - infos = MethodMatchInfo[] - applicable = Any[] - applicable_argtypes = Vector{Any}[] # arrays like `argtypes`, including constants, for each match - valid_worlds = WorldRange() - mts = MethodTable[] - fullmatches = Bool[] - for i in 1:length(split_argtypes) - arg_n = split_argtypes[i]::Vector{Any} - sig_n = argtypes_to_type(arg_n) - mt = ccall(:jl_method_table_for, Any, (Any,), sig_n) - mt === nothing && return FailedMethodMatch("Could not identify method table for call") - mt = mt::MethodTable - matches = findall(sig_n, method_table; limit = max_methods) - if matches === nothing - return FailedMethodMatch("For one of the union split cases, too many methods matched") - end - push!(infos, MethodMatchInfo(matches)) - for m in matches - push!(applicable, m) - push!(applicable_argtypes, arg_n) - end - valid_worlds = intersect(valid_worlds, matches.valid_worlds) - thisfullmatch = any(match::MethodMatch->match.fully_covers, matches) - found = false - for (i, mtโ€ฒ) in enumerate(mts) - if mtโ€ฒ === mt - fullmatches[i] &= thisfullmatch - found = true - break - end - end - if !found - push!(mts, mt) - push!(fullmatches, thisfullmatch) - end - end - return UnionSplitMethodMatches(applicable, - applicable_argtypes, - UnionSplitInfo(infos), - valid_worlds, - mts, - fullmatches) - else - mt = ccall(:jl_method_table_for, Any, (Any,), atype) - if mt === nothing - return FailedMethodMatch("Could not identify method table for call") - end +function find_method_matches(interp::AbstractInterpreter, argtypes::Vector{Any}, @nospecialize(atype); + max_union_splitting::Int = InferenceParams(interp).max_union_splitting, + max_methods::Int = InferenceParams(interp).max_methods) + if is_union_split_eligible(typeinf_lattice(interp), argtypes, max_union_splitting) + return find_union_split_method_matches(interp, argtypes, atype, max_methods) + end + return find_simple_method_matches(interp, atype, max_methods) +end + +# NOTE this is valid as far as any "constant" lattice element doesn't represent `Union` type +is_union_split_eligible(๐•ƒ::AbstractLattice, argtypes::Vector{Any}, max_union_splitting::Int) = + 1 < unionsplitcost(๐•ƒ, argtypes) <= max_union_splitting + +function find_union_split_method_matches(interp::AbstractInterpreter, argtypes::Vector{Any}, + @nospecialize(atype), max_methods::Int) + split_argtypes = switchtupleunion(typeinf_lattice(interp), argtypes) + infos = MethodMatchInfo[] + applicable = Any[] + applicable_argtypes = Vector{Any}[] # arrays like `argtypes`, including constants, for each match + valid_worlds = WorldRange() + mts = MethodTable[] + fullmatches = Bool[] + for i in 1:length(split_argtypes) + arg_n = split_argtypes[i]::Vector{Any} + sig_n = argtypes_to_type(arg_n) + mt = ccall(:jl_method_table_for, Any, (Any,), sig_n) + mt === nothing && return FailedMethodMatch("Could not identify method table for call") mt = mt::MethodTable - matches = findall(atype, method_table; limit = max_methods) + matches = findall(sig_n, method_table(interp); limit = max_methods) if matches === nothing - # this means too many methods matched - # (assume this will always be true, so we don't compute / update valid age in this case) - return FailedMethodMatch("Too many methods matched") + return FailedMethodMatch("For one of the union split cases, too many methods matched") + end + push!(infos, MethodMatchInfo(matches)) + for m in matches + push!(applicable, m) + push!(applicable_argtypes, arg_n) + end + valid_worlds = intersect(valid_worlds, matches.valid_worlds) + thisfullmatch = any(match::MethodMatch->match.fully_covers, matches) + found = false + for (i, mtโ€ฒ) in enumerate(mts) + if mtโ€ฒ === mt + fullmatches[i] &= thisfullmatch + found = true + break + end end - fullmatch = any(match::MethodMatch->match.fully_covers, matches) - return MethodMatches(matches.matches, - MethodMatchInfo(matches), - matches.valid_worlds, - mt, - fullmatch) + if !found + push!(mts, mt) + push!(fullmatches, thisfullmatch) + end + end + info = UnionSplitInfo(infos) + return UnionSplitMethodMatches( + applicable, applicable_argtypes, info, valid_worlds, mts, fullmatches) +end + +function find_simple_method_matches(interp::AbstractInterpreter, @nospecialize(atype), max_methods::Int) + mt = ccall(:jl_method_table_for, Any, (Any,), atype) + if mt === nothing + return FailedMethodMatch("Could not identify method table for call") + end + mt = mt::MethodTable + matches = findall(atype, method_table(interp); limit = max_methods) + if matches === nothing + # this means too many methods matched + # (assume this will always be true, so we don't compute / update valid age in this case) + return FailedMethodMatch("Too many methods matched") end + info = MethodMatchInfo(matches) + fullmatch = any(match::MethodMatch->match.fully_covers, matches) + return MethodMatches( + matches.matches, info, matches.valid_worlds, mt, fullmatch) end """ diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index b817c2af9c49c4..d697ec56bf55fe 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -3019,8 +3019,7 @@ function abstract_applicable(interp::AbstractInterpreter, argtypes::Vector{Any}, isvarargtype(argtypes[2]) && return CallMeta(Bool, Any, EFFECTS_UNKNOWN, NoCallInfo()) argtypes = argtypes[2:end] atype = argtypes_to_type(argtypes) - matches = find_matching_methods(typeinf_lattice(interp), argtypes, atype, method_table(interp), - InferenceParams(interp).max_union_splitting, max_methods) + matches = find_method_matches(interp, argtypes, atype; max_methods) if isa(matches, FailedMethodMatch) rt = Bool # too many matches to analyze else From 2775c9a0dc42436fb4c6013c3037eaad335a7bd3 Mon Sep 17 00:00:00 2001 From: Cody Tapscott <84105208+topolarity@users.noreply.github.com> Date: Tue, 19 Mar 2024 04:20:16 -0400 Subject: [PATCH 002/123] Fix handling of virtual exit node in `PostDomTree` (#53739) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is an alternative to https://github.com/JuliaLang/julia/pull/53642 The `dom_edges()` for an exit block in the CFG are empty when computing the PostDomTree so the loop below this may not actually run. In that case, the right semidominator is the ancestor from the DFSTree, which is the "virtual" -1 block. This resolves half of the issue in https://github.com/JuliaLang/julia/issues/53613: ```julia julia> let code = Any[ # block 1 GotoIfNot(Argument(2), 3), # block 2 ReturnNode(Argument(3)), # block 3 (we should visit this block) Expr(:call, throw, "potential throw"), ReturnNode(), # unreachable ] ir = make_ircode(code; slottypes=Any[Any,Bool,Bool]) visited = BitSet() @test !Core.Compiler.visit_conditional_successors(CC.LazyPostDomtree(ir), ir, #=bb=#1) do succ::Int push!(visited, succ) return false end @test 2 โˆˆ visited @test 3 โˆˆ visited end Test Passed ``` This needs some tests (esp. since I don't think we have any DomTree tests at all right now), but otherwise should be good to go. --- base/compiler/ssair/domtree.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/base/compiler/ssair/domtree.jl b/base/compiler/ssair/domtree.jl index dfe0550d7a06dc..bbae3a4d8c0fc7 100644 --- a/base/compiler/ssair/domtree.jl +++ b/base/compiler/ssair/domtree.jl @@ -345,10 +345,7 @@ function SNCA!(domtree::GenericDomTree{IsPostDom}, blocks::Vector{BasicBlock}, m ancestors = copy(D.to_parent_pre) relevant_blocks = IsPostDom ? (1:max_pre) : (2:max_pre) for w::PreNumber in reverse(relevant_blocks) - # LLVM initializes this to the parent, the paper initializes this to - # `w`, but it doesn't really matter (the parent is a predecessor, so at - # worst we'll discover it below). Save a memory reference here. - semi_w = typemax(PreNumber) + semi_w = ancestors[w] last_linked = PreNumber(w + 1) for v โˆˆ dom_edges(domtree, blocks, D.from_pre[w]) # For the purpose of the domtree, ignore virtual predecessors into From 9df47f238c44a92ca0962efbc4c42173d0c5ce54 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Tue, 19 Mar 2024 20:10:11 +0900 Subject: [PATCH 003/123] post-opt: add more test cases for `visit_conditional_successors` (#53642) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fixes the first problem that was found while digging into JuliaLang/julia#53613. It turns out that the post-domtree constructed from regular `IRCode` doesn't work for visiting conditional successors for post-opt analysis in cases like: ```julia julia> let code = Any[ # block 1 GotoIfNot(Argument(2), 3), # block 2 ReturnNode(Argument(3)), # block 3 (we should visit this block) Expr(:call, throw, "potential throw"), ReturnNode(), # unreachable ] ir = make_ircode(code; slottypes=Any[Any,Bool,Bool]) visited = BitSet() @test !Core.Compiler.visit_conditional_successors(CC.LazyPostDomtree(ir), ir, #=bb=#1) do succ::Int push!(visited, succ) return false end @test 2 โˆ‰ visited @test 3 โˆˆ visited end Test Failed at REPL[14]:16 Expression: 2 โˆ‰ visited Evaluated: 2 โˆ‰ BitSet([2]) ``` This might mean that we need to fix on the `postdominates` end, but for now, this commit tries to get around it by using the augmented post domtree in `visit_conditional_successors`. Since the augmented post domtree is enforced to have a single return, we can keep using the current `postdominates` to fix the issue. However, this commit isn't enough to fix the NeuralNetworkReachability segfault as reported in #53613, and we need to tackle the second issue reported there too (https://github.com/JuliaLang/julia/issues/53613#issuecomment-1983243419). --- base/compiler/optimize.jl | 2 ++ test/compiler/effects.jl | 10 ++++++ test/compiler/ssair.jl | 66 ++++++++++++++++++++++++++++++++------- 3 files changed, 67 insertions(+), 11 deletions(-) diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 81b025e588f7fc..325ba3eca01704 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -527,6 +527,8 @@ function any_stmt_may_throw(ir::IRCode, bb::Int) return false end +visit_conditional_successors(callback, ir::IRCode, bb::Int) = # used for test + visit_conditional_successors(callback, LazyPostDomtree(ir), ir, bb) function visit_conditional_successors(callback, lazypostdomtree::LazyPostDomtree, ir::IRCode, bb::Int) visited = BitSet((bb,)) worklist = Int[bb] diff --git a/test/compiler/effects.jl b/test/compiler/effects.jl index fa70c8de9d8538..cdf797fb2a77b4 100644 --- a/test/compiler/effects.jl +++ b/test/compiler/effects.jl @@ -1387,3 +1387,13 @@ let; Base.Experimental.@force_compile; func52843(); end # https://github.com/JuliaLang/julia/issues/53508 @test !Core.Compiler.is_consistent(Base.infer_effects(getindex, (UnitRange{Int},Int))) @test !Core.Compiler.is_consistent(Base.infer_effects(getindex, (Base.OneTo{Int},Int))) + +@noinline f53613() = @assert isdefined(@__MODULE__, :v53613) +g53613() = f53613() +@test !Core.Compiler.is_consistent(Base.infer_effects(f53613)) +@test_broken !Core.Compiler.is_consistent(Base.infer_effects(g53613)) +@test_throws AssertionError f53613() +@test_throws AssertionError g53613() +global v53613 = nothing +@test f53613() === nothing +@test g53613() === nothing diff --git a/test/compiler/ssair.jl b/test/compiler/ssair.jl index 70a2ab4a3acd97..9082d1640e3be5 100644 --- a/test/compiler/ssair.jl +++ b/test/compiler/ssair.jl @@ -233,35 +233,79 @@ let code = Any[ end # issue #37919 -let ci = code_lowered(()->@isdefined(_not_def_37919_), ())[1] +let ci = only(code_lowered(()->@isdefined(_not_def_37919_), ())) ir = Core.Compiler.inflate_ir(ci) @test Core.Compiler.verify_ir(ir) === nothing end let code = Any[ # block 1 - GotoIfNot(Argument(2), 4), + GotoIfNot(Argument(2), 4) # block 2 - GotoNode(3), + Expr(:call, throw, "potential throw") + ReturnNode() # unreachable # block 3 - Expr(:call, throw, "potential throw"), + ReturnNode(Argument(3)) + ] + ir = make_ircode(code; slottypes=Any[Any,Bool,Int]) + visited = BitSet() + @test !Core.Compiler.visit_conditional_successors(ir, #=bb=#1) do succ::Int + push!(visited, succ) + return false + end + @test 2 โˆˆ visited + @test 3 โˆˆ visited + oc = Core.OpaqueClosure(ir) + @test oc(false, 1) == 1 + @test_throws "potential throw" oc(true, 1) +end + +let code = Any[ + # block 1 + GotoIfNot(Argument(2), 3) + # block 2 + ReturnNode(Argument(3)) + # block 3 + Expr(:call, throw, "potential throw") + ReturnNode() # unreachable + ] + ir = make_ircode(code; slottypes=Any[Any,Bool,Int]) + visited = BitSet() + @test !Core.Compiler.visit_conditional_successors(ir, #=bb=#1) do succ::Int + push!(visited, succ) + return false + end + @test 2 โˆˆ visited + @test 3 โˆˆ visited + oc = Core.OpaqueClosure(ir) + @test oc(true, 1) == 1 + @test_throws "potential throw" oc(false, 1) +end + +let code = Any[ + # block 1 + GotoIfNot(Argument(2), 5) + # block 2 + GotoNode(3) + # block 3 + Expr(:call, throw, "potential throw") + ReturnNode() # block 4 - Expr(:call, Core.Intrinsics.add_int, Argument(3), Argument(4)), - GotoNode(6), + Expr(:call, Core.Intrinsics.add_int, Argument(3), Argument(4)) + GotoNode(7) # block 5 - ReturnNode(SSAValue(4)) + ReturnNode(SSAValue(5)) ] ir = make_ircode(code; slottypes=Any[Any,Bool,Int,Int]) - lazypostdomtree = Core.Compiler.LazyPostDomtree(ir) visited = BitSet() - @test !Core.Compiler.visit_conditional_successors(lazypostdomtree, ir, #=bb=#1) do succ::Int + @test !Core.Compiler.visit_conditional_successors(ir, #=bb=#1) do succ::Int push!(visited, succ) return false end @test 2 โˆˆ visited @test 3 โˆˆ visited - @test 4 โˆ‰ visited - @test 5 โˆ‰ visited + @test 4 โˆˆ visited + @test 5 โˆˆ visited oc = Core.OpaqueClosure(ir) @test oc(false, 1, 1) == 2 @test_throws "potential throw" oc(true, 1, 1) From 5c891de4bc718c27a52bba306411bd10bc1bd71c Mon Sep 17 00:00:00 2001 From: Kiran Pamnany Date: Tue, 19 Mar 2024 10:39:25 -0400 Subject: [PATCH 004/123] Remove some duplicates from emitted compilation traces (#53774) When multiple threads concurrently attempt to compile the same method, `--trace-compile` could emit duplicate `precompile` statements. This small tweak eliminates one source of these duplicates. --- src/codegen-stubs.c | 3 ++- src/gf.c | 4 ++-- src/jitlayers.cpp | 7 +++++-- src/julia_internal.h | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/codegen-stubs.c b/src/codegen-stubs.c index dda9bbee184a08..e67ae3b75ea764 100644 --- a/src/codegen-stubs.c +++ b/src/codegen-stubs.c @@ -43,10 +43,11 @@ JL_DLLEXPORT void jl_generate_fptr_for_unspecialized_fallback(jl_code_instance_t jl_atomic_store_release(&unspec->invoke, &jl_fptr_interpret_call); } -JL_DLLEXPORT void jl_compile_codeinst_fallback(jl_code_instance_t *unspec) +JL_DLLEXPORT int jl_compile_codeinst_fallback(jl_code_instance_t *unspec) { // Do nothing. The caller will notice that we failed to provide a an ->invoke and trigger // appropriate fallbacks. + return 0; } JL_DLLEXPORT uint32_t jl_get_LLVM_VERSION_fallback(void) diff --git a/src/gf.c b/src/gf.c index 53496c8feca58f..2bab2b2271e0be 100644 --- a/src/gf.c +++ b/src/gf.c @@ -2568,12 +2568,12 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t } JL_GC_PUSH1(&codeinst); - jl_compile_codeinst(codeinst); + int did_compile = jl_compile_codeinst(codeinst); if (jl_atomic_load_relaxed(&codeinst->invoke) == NULL) { // Something went wrong. Bail to the fallback path. codeinst = NULL; - } else { + } else if (did_compile) { record_precompile_statement(mi); } JL_GC_POP(); diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index b7fb975515eb40..5f9d7f8a3c6cf4 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -461,10 +461,11 @@ void jl_extern_c_impl(jl_value_t *declrt, jl_tupletype_t *sigt) } extern "C" JL_DLLEXPORT_CODEGEN -void jl_compile_codeinst_impl(jl_code_instance_t *ci) +int jl_compile_codeinst_impl(jl_code_instance_t *ci) { + int newly_compiled = 0; if (jl_atomic_load_relaxed(&ci->invoke) != NULL) { - return; + return newly_compiled; } JL_LOCK(&jl_codegen_lock); if (jl_atomic_load_relaxed(&ci->invoke) == NULL) { @@ -472,8 +473,10 @@ void jl_compile_codeinst_impl(jl_code_instance_t *ci) uint64_t start = jl_typeinf_timing_begin(); _jl_compile_codeinst(ci, NULL, *jl_ExecutionEngine->getContext()); jl_typeinf_timing_end(start, 0); + newly_compiled = 1; } JL_UNLOCK(&jl_codegen_lock); // Might GC + return newly_compiled; } extern "C" JL_DLLEXPORT_CODEGEN diff --git a/src/julia_internal.h b/src/julia_internal.h index 79f9e1fba0703f..dc93e522b0c4d4 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1727,7 +1727,7 @@ JL_DLLEXPORT uint32_t jl_crc32c(uint32_t crc, const char *buf, size_t len); #define IR_FLAG_INBOUNDS 0x01 JL_DLLIMPORT void jl_generate_fptr_for_unspecialized(jl_code_instance_t *unspec); -JL_DLLIMPORT void jl_compile_codeinst(jl_code_instance_t *unspec); +JL_DLLIMPORT int jl_compile_codeinst(jl_code_instance_t *unspec); JL_DLLIMPORT int jl_compile_extern_c(LLVMOrcThreadSafeModuleRef llvmmod, void *params, void *sysimg, jl_value_t *declrt, jl_value_t *sigt); typedef struct { From 1c2b9ad0049f8bd23b32ac5d4744898babab7e83 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 19 Mar 2024 17:09:27 -0700 Subject: [PATCH 005/123] compileall: Print error on failure (#53770) This test appears to be failing intermittently on aarch64 darwin, so stop suppressing any errors that might be happening. --- test/compileall.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/compileall.jl b/test/compileall.jl index 464dea51e4497d..914b0fc8a4d9e9 100644 --- a/test/compileall.jl +++ b/test/compileall.jl @@ -3,7 +3,7 @@ # with the rest of the tests. mktempdir() do dir - @test success(`$(Base.julia_cmd()) --compile=all --strip-ir --output-o $(dir)/sys.o.a -e 'exit()'`) broken=(Sys.iswindows() && Sys.WORD_SIZE == 32) + @test success(pipeline(`$(Base.julia_cmd()) --compile=all --strip-ir --output-o $(dir)/sys.o.a -e 'exit()'`, stderr=stderr)) broken=(Sys.iswindows() && Sys.WORD_SIZE == 32) if isfile(joinpath(dir, "sys.o.a")) Base.Linking.link_image(joinpath(dir, "sys.o.a"), joinpath(dir, "sys.so")) # TODO: Broken on Windows due to From cc27a7b665c0d27a44b099e77ce291d63a47751d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 20 Mar 2024 01:36:10 +0100 Subject: [PATCH 006/123] Add two missing whitespaces to error messages (#53782) --- base/intfuncs.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 916cd28a32c6f0..f5185b0a9fd176 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -302,12 +302,12 @@ to_power_type(x) = convert(Base._return_type(*, Tuple{typeof(x), typeof(x)}), x) @noinline throw_domerr_powbysq(::Integer, p) = throw(DomainError(p, LazyString( "Cannot raise an integer x to a negative power ", p, ".", "\nMake x or ", p, " a float by adding a zero decimal ", - "(e.g., 2.0^", p, " or 2^", float(p), " instead of 2^", p, ")", + "(e.g., 2.0^", p, " or 2^", float(p), " instead of 2^", p, ") ", "or write 1/x^", -p, ", float(x)^", p, ", x^float(", p, ") or (x//1)^", p, "."))) @noinline throw_domerr_powbysq(::AbstractMatrix, p) = throw(DomainError(p, LazyString( "Cannot raise an integer matrix x to a negative power ", p, ".", "\nMake x a float matrix by adding a zero decimal ", - "(e.g., [2.0 1.0;1.0 0.0]^", p, " instead of [2 1;1 0]^", p, ")", + "(e.g., [2.0 1.0;1.0 0.0]^", p, " instead of [2 1;1 0]^", p, ") ", "or write float(x)^", p, " or Rational.(x)^", p, "."))) # The * keyword supports `*=checked_mul` for `checked_pow` @assume_effects :terminates_locally function power_by_squaring(x_, p::Integer; mul=*) From e0bb95aabdd9126cd5c1665e5cb49864c4c32c86 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Tue, 19 Mar 2024 20:38:51 -0400 Subject: [PATCH 007/123] small changes to make Base more statically compileable (#53778) This makes it easier to fully-statically-type Base and init methods. The changes are from gb/small-image2. --- base/boot.jl | 2 +- base/compiler/utilities.jl | 2 -- base/error.jl | 10 +++++----- base/errorshow.jl | 2 +- base/initdefs.jl | 4 ++-- base/iostream.jl | 13 ++++++++----- base/libuv.jl | 6 +++--- base/loading.jl | 7 +++---- base/reflection.jl | 2 ++ base/show.jl | 2 +- base/threadingconstructs.jl | 2 +- stdlib/FileWatching/src/FileWatching.jl | 5 +++++ stdlib/LinearAlgebra/src/blas.jl | 5 ++--- 13 files changed, 34 insertions(+), 28 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index fc00f571171c92..a3c5c03bdf721e 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -769,7 +769,7 @@ function is_top_bit_set(x::Union{Int8,UInt8}) end # n.b. This function exists for CUDA to overload to configure error behavior (see #48097) -throw_inexacterror(args...) = throw(InexactError(args...)) +throw_inexacterror(func::Symbol, to, val) = throw(InexactError(func, to, val)) function check_sign_bit(::Type{To}, x) where {To} @inline diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index c2c36920bd574f..1f74db620b7f71 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -504,8 +504,6 @@ end # options # ########### -is_root_module(m::Module) = false - inlining_enabled() = (JLOptions().can_inline == 1) function coverage_enabled(m::Module) diff --git a/base/error.jl b/base/error.jl index fc294b3cb3eb04..07782fce5f52ea 100644 --- a/base/error.jl +++ b/base/error.jl @@ -228,15 +228,15 @@ macro assert(ex, msgs...) msg = Main.Base.string(msg) else # string() might not be defined during bootstrap - msg = quote - msg = $(Expr(:quote,msg)) - isdefined(Main, :Base) ? Main.Base.string(msg) : - (Core.println(msg); "Error during bootstrap. See stdout.") - end + msg = :(_assert_tostring($(Expr(:quote,msg)))) end return :($(esc(ex)) ? $(nothing) : throw(AssertionError($msg))) end +# this may be overridden in contexts where `string(::Expr)` doesn't work +_assert_tostring(msg) = isdefined(Main, :Base) ? Main.Base.string(msg) : + (Core.println(msg); "Error during bootstrap. See stdout.") + struct ExponentialBackOff n::Int first_delay::Float64 diff --git a/base/errorshow.jl b/base/errorshow.jl index abc8083f38266e..b06052433ffc43 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -400,7 +400,7 @@ end #Show an error by directly calling jl_printf. #Useful in Base submodule __init__ functions where stderr isn't defined yet. -function showerror_nostdio(err, msg::AbstractString) +function showerror_nostdio(@nospecialize(err), msg::AbstractString) stderr_stream = ccall(:jl_stderr_stream, Ptr{Cvoid}, ()) ccall(:jl_printf, Cint, (Ptr{Cvoid},Cstring), stderr_stream, msg) ccall(:jl_printf, Cint, (Ptr{Cvoid},Cstring), stderr_stream, ":\n") diff --git a/base/initdefs.jl b/base/initdefs.jl index 56c2c0c5872728..2b2916fc804ade 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -9,7 +9,7 @@ A string containing the script name passed to Julia from the command line. Note script name remains unchanged from within included files. Alternatively see [`@__FILE__`](@ref). """ -global PROGRAM_FILE = "" +global PROGRAM_FILE::String = "" """ ARGS @@ -480,7 +480,7 @@ end ## hook for disabling threaded libraries ## -library_threading_enabled = true +library_threading_enabled::Bool = true const disable_library_threading_hooks = [] function at_disable_library_threading(f) diff --git a/base/iostream.jl b/base/iostream.jl index 5d972945e00e0f..bea6612ebc220c 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -292,12 +292,15 @@ function open(fname::String; lock = true, if !lock s._dolock = false end - systemerror("opening file $(repr(fname))", - ccall(:ios_file, Ptr{Cvoid}, - (Ptr{UInt8}, Cstring, Cint, Cint, Cint, Cint), - s.ios, fname, flags.read, flags.write, flags.create, flags.truncate) == C_NULL) + if ccall(:ios_file, Ptr{Cvoid}, + (Ptr{UInt8}, Cstring, Cint, Cint, Cint, Cint), + s.ios, fname, flags.read, flags.write, flags.create, flags.truncate) == C_NULL + systemerror("opening file \"$fname\"") + end if flags.append - systemerror("seeking to end of file $fname", ccall(:ios_seek_end, Int64, (Ptr{Cvoid},), s.ios) != 0) + if ccall(:ios_seek_end, Int64, (Ptr{Cvoid},), s.ios) != 0 + systemerror("seeking to end of file \"$fname\"") + end end return s end diff --git a/base/libuv.jl b/base/libuv.jl index 66dfcfb3414ad1..35424ad3eda3ed 100644 --- a/base/libuv.jl +++ b/base/libuv.jl @@ -134,9 +134,9 @@ function uv_asynccb end function uv_timercb end function reinit_stdio() - global stdin = init_stdio(ccall(:jl_stdin_stream, Ptr{Cvoid}, ())) - global stdout = init_stdio(ccall(:jl_stdout_stream, Ptr{Cvoid}, ())) - global stderr = init_stdio(ccall(:jl_stderr_stream, Ptr{Cvoid}, ())) + global stdin = init_stdio(ccall(:jl_stdin_stream, Ptr{Cvoid}, ()))::IO + global stdout = init_stdio(ccall(:jl_stdout_stream, Ptr{Cvoid}, ()))::IO + global stderr = init_stdio(ccall(:jl_stderr_stream, Ptr{Cvoid}, ()))::IO opts = JLOptions() if opts.color != 0 have_color = (opts.color == 1) diff --git a/base/loading.jl b/base/loading.jl index 883e980b4000a2..986efc1e1e5fbe 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2205,7 +2205,6 @@ const explicit_loaded_modules = Dict{PkgId,Module}() const loaded_modules_order = Vector{Module}() const module_keys = IdDict{Module,PkgId}() # the reverse -is_root_module(m::Module) = @lock require_lock haskey(module_keys, m) root_module_key(m::Module) = @lock require_lock module_keys[m] @constprop :none function register_root_module(m::Module) @@ -3416,9 +3415,9 @@ function check_clone_targets(clone_targets) end # Set by FileWatching.__init__() -global mkpidlock_hook -global trymkpidlock_hook -global parse_pidfile_hook +global mkpidlock_hook::Any +global trymkpidlock_hook::Any +global parse_pidfile_hook::Any # The preferences hash is only known after precompilation so just assume no preferences. # Also ignore the active project, which means that if all other conditions are equal, diff --git a/base/reflection.jl b/base/reflection.jl index 446e5825a16cce..39ad62fb1680b5 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -20,6 +20,8 @@ Base """ parentmodule(m::Module) = ccall(:jl_module_parent, Ref{Module}, (Any,), m) +is_root_module(m::Module) = parentmodule(m) === m || (isdefined(Main, :Base) && m === Main.Base) + """ moduleroot(m::Module) -> Module diff --git a/base/show.jl b/base/show.jl index f7846e316c3301..8f52fefdd71520 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1056,7 +1056,7 @@ function show_type_name(io::IO, tn::Core.TypeName) # IOContext If :module is not set, default to Main (or current active module). # nothing can be used to force printing prefix from = get(io, :module, active_module()) - if isdefined(tn, :module) && (from === nothing || !isvisible(sym, tn.module, from)) + if isdefined(tn, :module) && (from === nothing || !isvisible(sym, tn.module, from::Module)) show(io, tn.module) print(io, ".") if globfunc && !is_id_start_char(first(string(sym))) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 60aea04ddba645..acab7cf7b8299c 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -79,7 +79,7 @@ function _sym_to_tpid(tp::Symbol) elseif tp == :foreign return Int8(-1) else - throw(ArgumentError("Unrecognized threadpool name `$(repr(tp))`")) + throw(ArgumentError("Unrecognized threadpool name `$tp`")) end end diff --git a/stdlib/FileWatching/src/FileWatching.jl b/stdlib/FileWatching/src/FileWatching.jl index 0ee572ec47d92c..0c987ad01c828e 100644 --- a/stdlib/FileWatching/src/FileWatching.jl +++ b/stdlib/FileWatching/src/FileWatching.jl @@ -468,6 +468,11 @@ function uv_fspollcb(handle::Ptr{Cvoid}, status::Int32, prev::Ptr, curr::Ptr) nothing end +global uv_jl_pollcb::Ptr{Cvoid} +global uv_jl_fspollcb::Ptr{Cvoid} +global uv_jl_fseventscb_file::Ptr{Cvoid} +global uv_jl_fseventscb_folder::Ptr{Cvoid} + function __init__() global uv_jl_pollcb = @cfunction(uv_pollcb, Cvoid, (Ptr{Cvoid}, Cint, Cint)) global uv_jl_fspollcb = @cfunction(uv_fspollcb, Cvoid, (Ptr{Cvoid}, Cint, Ptr{Cvoid}, Ptr{Cvoid})) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 8903aaddcc11bc..413b7866c54448 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -159,9 +159,8 @@ function check() interface = USE_BLAS64 ? :ilp64 : :lp64 if !any(lib.interface == interface for lib in config.loaded_libs) interfacestr = uppercase(string(interface)) - @error("No loaded BLAS libraries were built with $(interfacestr) support") - println("Quitting.") - exit() + @error("No loaded BLAS libraries were built with $interfacestr support.") + exit(1) end end From bc7ba3d5c8b2dab1c0e19537739b67c2da902d11 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 19 Mar 2024 23:35:46 -0700 Subject: [PATCH 008/123] compiler: Refactor `concrete_eval_invoke` (#53771) This passes slightly more information into this function (the full `inst` rather than just the `stmt`) in order to allow external absint to access additional fields (the flags and the info) if necessary to make concrete evaluation decisions. It also splits out the actual concrete evaluation from the part that just maps the `inst` to a CodeInstance. --- base/compiler/ssair/irinterp.jl | 43 ++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/base/compiler/ssair/irinterp.jl b/base/compiler/ssair/irinterp.jl index cda590b07d23c5..f68006ed686b50 100644 --- a/base/compiler/ssair/irinterp.jl +++ b/base/compiler/ssair/irinterp.jl @@ -5,39 +5,44 @@ function collect_limitations!(@nospecialize(typ), ::IRInterpretationState) return typ end -function concrete_eval_invoke(interp::AbstractInterpreter, - inst::Expr, mi::MethodInstance, irsv::IRInterpretationState) - world = frame_world(irsv) - mi_cache = WorldView(code_cache(interp), world) - code = get(mi_cache, mi, nothing) - code === nothing && return Pair{Any,Tuple{Bool,Bool}}(nothing, (false, false)) - argtypes = collect_argtypes(interp, inst.args[2:end], nothing, irsv) - argtypes === nothing && return Pair{Any,Tuple{Bool,Bool}}(Bottom, (false, false)) - effects = decode_effects(code.ipo_purity_bits) +function concrete_eval_invoke(interp::AbstractInterpreter, ci::CodeInstance, argtypes::Vector{Any}, parent::IRInterpretationState) + world = frame_world(parent) + effects = decode_effects(ci.ipo_purity_bits) if (is_foldable(effects) && is_all_const_arg(argtypes, #=start=#1) && (is_nonoverlayed(interp) || is_nonoverlayed(effects))) args = collect_const_args(argtypes, #=start=#1) - value = let world = get_inference_world(interp) - try - Core._call_in_world_total(world, args...) - catch - return Pair{Any,Tuple{Bool,Bool}}(Bottom, (false, is_noub(effects))) - end + value = try + Core._call_in_world_total(world, args...) + catch + return Pair{Any,Tuple{Bool,Bool}}(Bottom, (false, is_noub(effects))) end return Pair{Any,Tuple{Bool,Bool}}(Const(value), (true, true)) else - if is_constprop_edge_recursed(mi, irsv) + mi = ci.def + if is_constprop_edge_recursed(mi, parent) return Pair{Any,Tuple{Bool,Bool}}(nothing, (is_nothrow(effects), is_noub(effects))) end - newirsv = IRInterpretationState(interp, code, mi, argtypes, world) + newirsv = IRInterpretationState(interp, ci, mi, argtypes, world) if newirsv !== nothing - newirsv.parent = irsv + newirsv.parent = parent return ir_abstract_constant_propagation(interp, newirsv) end return Pair{Any,Tuple{Bool,Bool}}(nothing, (is_nothrow(effects), is_noub(effects))) end end +function abstract_eval_invoke_inst(interp::AbstractInterpreter, inst::Instruction, irsv::IRInterpretationState) + stmt = inst[:stmt] + mi = stmt.args[1]::MethodInstance + world = frame_world(irsv) + mi_cache = WorldView(code_cache(interp), world) + code = get(mi_cache, mi, nothing) + code === nothing && return Pair{Any,Tuple{Bool,Bool}}(nothing, (false, false)) + argtypes = collect_argtypes(interp, stmt.args[2:end], nothing, irsv) + argtypes === nothing && return Pair{Any,Tuple{Bool,Bool}}(Bottom, (false, false)) + return concrete_eval_invoke(interp, code, argtypes, irsv) +end + abstract_eval_ssavalue(s::SSAValue, sv::IRInterpretationState) = abstract_eval_ssavalue(s, sv.ir) function abstract_eval_phi_stmt(interp::AbstractInterpreter, phi::PhiNode, ::Int, irsv::IRInterpretationState) @@ -141,7 +146,7 @@ function reprocess_instruction!(interp::AbstractInterpreter, inst::Instruction, (; rt, effects) = abstract_eval_statement_expr(interp, stmt, nothing, irsv) add_flag!(inst, flags_for_effects(effects)) elseif head === :invoke - rt, (nothrow, noub) = concrete_eval_invoke(interp, stmt, stmt.args[1]::MethodInstance, irsv) + rt, (nothrow, noub) = abstract_eval_invoke_inst(interp, inst, irsv) if nothrow add_flag!(inst, IR_FLAG_NOTHROW) end From a30feec5094f040c3e19834acd8e4129b1433056 Mon Sep 17 00:00:00 2001 From: gitboy16 <82724369+gitboy16@users.noreply.github.com> Date: Wed, 20 Mar 2024 22:07:33 +0000 Subject: [PATCH 009/123] Update LICENSE.md - update copyright years (#53758) --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index d4125f4fba221d..da8b6920491cc1 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2009-2023: Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors: https://github.com/JuliaLang/julia/contributors +Copyright (c) 2009-2024: Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors: https://github.com/JuliaLang/julia/contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the From 55afecccffe5f981443ee8b1b139133b2a7c1f81 Mon Sep 17 00:00:00 2001 From: "John M. Kuhn" Date: Wed, 20 Mar 2024 18:10:23 -0400 Subject: [PATCH 010/123] Printf: don't zero pad Inf or NaN (#53785) We currently have ``` julia> @sprintf("%07f", -Inf) "-000Inf" julia> @sprintf("%07f", NaN) "0000NaN" ``` With this PR ``` julia> @sprintf("%07f", -Inf) " -Inf" julia> @sprintf("%07f", NaN) " NaN" ``` which is the same as Julia 1.5.4 and agrees with the C standard. --- stdlib/Printf/src/Printf.jl | 2 +- stdlib/Printf/test/runtests.jl | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/stdlib/Printf/src/Printf.jl b/stdlib/Printf/src/Printf.jl index 860ef3610f728d..9b636d11805989 100644 --- a/stdlib/Printf/src/Printf.jl +++ b/stdlib/Printf/src/Printf.jl @@ -654,7 +654,7 @@ const __BIG_FLOAT_MAX__ = 8192 else # right aligned n = width - (newpos - pos) - if zero + if zero && isfinite(x) ex = (arg < 0 || (plus | space)) + (T <: Union{Val{'a'}, Val{'A'}} ? 2 : 0) so = pos + ex len = (newpos - pos) - ex diff --git a/stdlib/Printf/test/runtests.jl b/stdlib/Printf/test/runtests.jl index f00d7abe362c57..abe547c00ed0d0 100644 --- a/stdlib/Printf/test/runtests.jl +++ b/stdlib/Printf/test/runtests.jl @@ -116,12 +116,15 @@ end @test (Printf.@sprintf "%+f" Inf) == "+Inf" @test (Printf.@sprintf "% f" Inf) == " Inf" @test (Printf.@sprintf "% #f" Inf) == " Inf" + @test (Printf.@sprintf "%07f" Inf) == " Inf" @test (Printf.@sprintf "%f" -Inf) == "-Inf" @test (Printf.@sprintf "%+f" -Inf) == "-Inf" + @test (Printf.@sprintf "%07f" -Inf) == " -Inf" @test (Printf.@sprintf "%f" NaN) == "NaN" @test (Printf.@sprintf "%+f" NaN) == "+NaN" @test (Printf.@sprintf "% f" NaN) == " NaN" @test (Printf.@sprintf "% #f" NaN) == " NaN" + @test (Printf.@sprintf "%07f" NaN) == " NaN" @test (Printf.@sprintf "%e" big"Inf") == "Inf" @test (Printf.@sprintf "%e" big"NaN") == "NaN" @@ -169,12 +172,15 @@ end @test (Printf.@sprintf "%+e" Inf) == "+Inf" @test (Printf.@sprintf "% e" Inf) == " Inf" @test (Printf.@sprintf "% #e" Inf) == " Inf" + @test (Printf.@sprintf "%07e" Inf) == " Inf" @test (Printf.@sprintf "%e" -Inf) == "-Inf" @test (Printf.@sprintf "%+e" -Inf) == "-Inf" + @test (Printf.@sprintf "%07e" -Inf) == " -Inf" @test (Printf.@sprintf "%e" NaN) == "NaN" @test (Printf.@sprintf "%+e" NaN) == "+NaN" @test (Printf.@sprintf "% e" NaN) == " NaN" @test (Printf.@sprintf "% #e" NaN) == " NaN" + @test (Printf.@sprintf "%07e" NaN) == " NaN" @test (Printf.@sprintf "%e" big"Inf") == "Inf" @test (Printf.@sprintf "%e" big"NaN") == "NaN" From 72b1c9e24101183a6bad20b71f8212a5342933f9 Mon Sep 17 00:00:00 2001 From: Lasse Peters Date: Thu, 21 Mar 2024 03:55:02 +0100 Subject: [PATCH 011/123] Document LazyString in performance tips (#53779) Does what it says. Doc-changes only. Recent motivating example: https://github.com/FluxML/Flux.jl/issues/2399 --- doc/src/manual/performance-tips.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/src/manual/performance-tips.md b/doc/src/manual/performance-tips.md index a3e9ab1b8739e0..1b7e2e76c722b5 100644 --- a/doc/src/manual/performance-tips.md +++ b/doc/src/manual/performance-tips.md @@ -1239,6 +1239,34 @@ versus: println(file, f(a), f(b)) ``` +## Avoid eager string materialization + +In settings where a string representation of an object is only needed +conditionally (e.g. in error paths of functions or conditional warnings such as +deprecations), it is advisable to avoid the overhead of eagerly materializing +the string. Since Julia 1.8, this can be achieved via +[`LazyString`](@ref) and the corresponding string macro [`@lazy_str`](@ref). + +For example, instead of: + +```julia +Base.depwarn("`foo` is deprecated for type $(typeof(x))", :bar) +``` + +use: + +```julia +Base.depwarn(lazy"`foo` is deprecated for type $(typeof(x))", :bar) +``` + +or the equivalent macro-free version: + +```julia +Base.depwarn(LazyString("`foo` is deprecated for type ", typeof(x)), :bar) +``` + +Through this approach, the interpolated string will only be constructed when it is actually displayed. + ## Optimize network I/O during parallel execution When executing a remote function in parallel: From 8e8b533229e2554a83741ade6398e2ec02dff6e0 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Thu, 21 Mar 2024 12:14:52 +0900 Subject: [PATCH 012/123] minor followups on recent `CodeInstance` refactors (#53581) - ~~simplifies the signature of `transform_result_for_cache`~~ - ~~make `jl_uncompress_ir` take `MethodInstance` instead of `CodeInstance` and simplifies the inlining algorithm~~ - renames of `codeinst::CodeInstace` objects - removal of dead code --- base/compiler/inferencestate.jl | 10 +++---- base/compiler/typeinfer.jl | 46 +++++++++++++++------------------ base/compiler/utilities.jl | 18 +++++-------- base/reflection.jl | 5 +++- 4 files changed, 36 insertions(+), 43 deletions(-) diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 31bc8d4e201052..0102f042ba2baf 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -803,18 +803,18 @@ mutable struct IRInterpretationState end function IRInterpretationState(interp::AbstractInterpreter, - code::CodeInstance, mi::MethodInstance, argtypes::Vector{Any}, world::UInt) - @assert code.def === mi - src = @atomic :monotonic code.inferred + codeinst::CodeInstance, mi::MethodInstance, argtypes::Vector{Any}, world::UInt) + @assert codeinst.def === mi "method instance is not synced with code instance" + src = @atomic :monotonic codeinst.inferred if isa(src, String) - src = _uncompressed_ir(code, src) + src = _uncompressed_ir(codeinst, src) else isa(src, CodeInfo) || return nothing end method_info = MethodInfo(src) ir = inflate_ir(src, mi) return IRInterpretationState(interp, method_info, ir, mi, argtypes, world, - code.min_world, code.max_world) + codeinst.min_world, codeinst.max_world) end # AbsIntState diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 4b6525f886888c..b77d2e83d57803 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -230,13 +230,6 @@ function finish!(interp::AbstractInterpreter, caller::InferenceState) if opt isa OptimizationState result.src = opt = ir_to_codeinf!(opt) end - if opt isa CodeInfo - caller.src = opt - else - # In this case `caller.src` is invalid for clients (such as `typeinf_ext`) to use - # but that is what's permitted by `caller.cache_mode`. - # This is hopefully unreachable from such clients using `NativeInterpreter`. - end return nothing end @@ -277,7 +270,7 @@ function is_result_constabi_eligible(result::InferenceResult) return isa(result_type, Const) && is_foldable_nothrow(result.ipo_effects) && is_inlineable_constant(result_type.val) end function CodeInstance(interp::AbstractInterpreter, result::InferenceResult; - can_discard_trees::Bool=may_discard_trees(interp)) + can_discard_trees::Bool=may_discard_trees(interp)) local const_flags::Int32 result_type = result.result @assert !(result_type === nothing || result_type isa LimitedAccuracy) @@ -351,13 +344,13 @@ function transform_result_for_cache(interp::AbstractInterpreter, return result.src end -function maybe_compress_codeinfo(interp::AbstractInterpreter, linfo::MethodInstance, ci::CodeInfo, - can_discard_trees::Bool=may_discard_trees(interp)) - def = linfo.def +function maybe_compress_codeinfo(interp::AbstractInterpreter, mi::MethodInstance, ci::CodeInfo, + can_discard_trees::Bool=may_discard_trees(interp)) + def = mi.def isa(def, Method) || return ci # don't compress toplevel code cache_the_tree = true if can_discard_trees - cache_the_tree = is_inlineable(ci) || isa_compileable_sig(linfo.specTypes, linfo.sparam_vals, def) + cache_the_tree = is_inlineable(ci) || isa_compileable_sig(mi.specTypes, mi.sparam_vals, def) end if cache_the_tree if may_compress(interp) @@ -576,13 +569,13 @@ function finish(me::InferenceState, interp::AbstractInterpreter) # annotate fulltree with type information, # either because we are the outermost code, or we might use this later type_annotate!(interp, me) - doopt = (me.cache_mode != CACHE_MODE_NULL || me.parent !== nothing) - # Disable the optimizer if we've already determined that there's nothing for - # it to do. - if may_discard_trees(interp) && is_result_constabi_eligible(me.result) - doopt = false - end - if doopt && may_optimize(interp) + mayopt = may_optimize(interp) + doopt = mayopt && + # disable optimization if we don't use this later + (me.cache_mode != CACHE_MODE_NULL || me.parent !== nothing) && + # disable optimization if we've already obtained very accurate result + !result_is_constabi(interp, me.result, mayopt) + if doopt me.result.src = OptimizationState(me, interp) else me.result.src = me.src # for reflection etc. @@ -952,7 +945,8 @@ function codeinstance_for_const_with_code(interp::AbstractInterpreter, code::Cod code.relocatability, src.debuginfo) end -result_is_constabi(interp::AbstractInterpreter, run_optimizer::Bool, result::InferenceResult) = +result_is_constabi(interp::AbstractInterpreter, result::InferenceResult, + run_optimizer::Bool=may_optimize(interp)) = run_optimizer && may_discard_trees(interp) && is_result_constabi_eligible(result) # compute an inferred AST and return type @@ -965,7 +959,7 @@ function typeinf_code(interp::AbstractInterpreter, mi::MethodInstance, run_optim frame = typeinf_frame(interp, mi, run_optimizer) frame === nothing && return nothing, Any is_inferred(frame) || return nothing, Any - if result_is_constabi(interp, run_optimizer, frame.result) + if result_is_constabi(interp, frame.result, run_optimizer) rt = frame.result.result::Const return codeinfo_for_const(interp, frame.linfo, rt.val), widenconst(rt) end @@ -1095,7 +1089,8 @@ function ci_meets_requirement(code::CodeInstance, source_mode::UInt8, ci_is_cach return false end -_uncompressed_ir(ci::Core.CodeInstance, s::String) = ccall(:jl_uncompress_ir, Any, (Any, Any, Any), ci.def.def::Method, ci, s)::CodeInfo +_uncompressed_ir(codeinst::CodeInstance, s::String) = + ccall(:jl_uncompress_ir, Ref{CodeInfo}, (Any, Any, Any), codeinst.def.def::Method, codeinst, s) # compute (and cache) an inferred AST and return type function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance, source_mode::UInt8) @@ -1143,9 +1138,10 @@ function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance, source_mod # Inference result is not cacheable or is was cacheable, but we do not want to # store the source in the cache, but the caller wanted it anyway (e.g. for reflection). # We construct a new CodeInstance for it that is not part of the cache hierarchy. - code = CodeInstance(interp, result, can_discard_trees=( - source_mode != SOURCE_MODE_FORCE_SOURCE && source_mode != SOURCE_MODE_FORCE_SOURCE_UNCACHED && - is_result_constabi_eligible(result))) + can_discard_trees = source_mode โ‰  SOURCE_MODE_FORCE_SOURCE && + source_mode โ‰  SOURCE_MODE_FORCE_SOURCE_UNCACHED && + is_result_constabi_eligible(result) + code = CodeInstance(interp, result; can_discard_trees) # If the caller cares about the code and this is constabi, still use our synthesis function # anyway, because we will have not finished inferring the code inside the CodeInstance once diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index 1f74db620b7f71..1e002f8dad5a6d 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -127,29 +127,23 @@ function get_staged(mi::MethodInstance, world::UInt) end end -function retrieve_code_info(linfo::MethodInstance, world::UInt) - def = linfo.def - if !isa(def, Method) - return linfo.uninferred - end - c = nothing - if isdefined(def, :generator) - # user code might throw errors โ€“ ignore them - c = get_staged(linfo, world) - end +function retrieve_code_info(mi::MethodInstance, world::UInt) + def = mi.def + isa(def, Method) || return mi.uninferred + c = isdefined(def, :generator) ? get_staged(mi, world) : nothing if c === nothing && isdefined(def, :source) src = def.source if src === nothing # can happen in images built with --strip-ir return nothing elseif isa(src, String) - c = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), def, C_NULL, src) + c = ccall(:jl_uncompress_ir, Ref{CodeInfo}, (Any, Ptr{Cvoid}, Any), def, C_NULL, src) else c = copy(src::CodeInfo) end end if c isa CodeInfo - c.parent = linfo + c.parent = mi return c end return nothing diff --git a/base/reflection.jl b/base/reflection.jl index 39ad62fb1680b5..63909b4159877b 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1324,9 +1324,12 @@ uncompressed_ir(m::Method) = isdefined(m, :source) ? _uncompressed_ir(m) : error("Code for this Method is not available.") function _uncompressed_ir(m::Method) s = m.source - s isa String && (s = ccall(:jl_uncompress_ir, Any, (Any, Ptr{Cvoid}, Any), m, C_NULL, s)) + if s isa String + s = ccall(:jl_uncompress_ir, Ref{CodeInfo}, (Any, Ptr{Cvoid}, Any), m, C_NULL, s) + end return s::CodeInfo end + # for backwards compat const uncompressed_ast = uncompressed_ir const _uncompressed_ast = _uncompressed_ir From 09400e4f5c3e31ba528c2dbcf8e1ccef2a66ce3d Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Thu, 21 Mar 2024 13:10:08 +0100 Subject: [PATCH 013/123] Switch LLVM codegen of Ptr{T} to an actual pointer type. (#53687) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR switches our code generation for `Ptr{T}` from `i64` to an actual LLVM pointer type (`ptr` when using opaque pointers, an untyped `i8*` otherwise). The main motivation is to simplify `llvmcall` usage (doing away with the `inttoptr`/`ptrtoint` conversions), and also make it possible to simply use `ccall` to call intrinsics with `Ptr`-valued arguments (where we currently always need `llvmcall` for converting to an actual pointer). Changing codegen like this is a breaking change for `llvmcall` users, but I've added backwards compatibility and a deprecation warning. Before: ```llvm julia> @code_llvm pointer([]) define i64 @julia_pointer_1542(ptr noundef nonnull align 8 dereferenceable(24) %"x::Array") #0 { top: ; โ”Œ @ pointer.jl:65 within `cconvert` %0 = load ptr, ptr %"x::Array", align 8 ; โ”” ; โ”Œ @ pointer.jl:90 within `unsafe_convert` ; โ”‚โ”Œ @ pointer.jl:30 within `convert` %bitcast_coercion = ptrtoint ptr %0 to i64 ret i64 %bitcast_coercion ; โ””โ”” } ``` After: ```llvm julia> @code_llvm pointer([]) define ptr @julia_pointer_3880(ptr noundef nonnull align 8 dereferenceable(24) %"x::Array") #0 { top: ; โ”Œ @ pointer.jl:65 within `cconvert` %0 = load ptr, ptr %"x::Array", align 8 ; โ”” ; โ”Œ @ pointer.jl:90 within `unsafe_convert` ; โ”‚โ”Œ @ pointer.jl:30 within `convert` ret ptr %0 ; โ””โ”” } ``` This also simplifies "real code", e.g., when `ccall` converts an Array to a pointer, resulting in some more optimization opportunities. --- NEWS.md | 5 + base/atomics.jl | 12 +- base/compiler/tfuncs.jl | 7 +- base/pointer.jl | 4 +- base/task.jl | 3 +- src/ccall.cpp | 214 ++++++++++++++++++++++++--------- src/cgutils.cpp | 2 + src/codegen.cpp | 4 +- src/intrinsics.cpp | 67 +++++++---- src/intrinsics.h | 5 +- src/llvm-remove-addrspaces.cpp | 9 +- src/runtime_intrinsics.c | 18 ++- 12 files changed, 253 insertions(+), 97 deletions(-) diff --git a/NEWS.md b/NEWS.md index 695427d7eba8e9..72b4629fe41747 100644 --- a/NEWS.md +++ b/NEWS.md @@ -26,6 +26,11 @@ Language changes Compiler/Runtime improvements ----------------------------- +- Generated LLVM IR now uses actual pointer types instead of passing pointers as integers. + This affects `llvmcall`: Inline LLVM IR should be updated to use `i8*` or `ptr` instead of + `i32` or `i64`, and remove unneeded `ptrtoint`/`inttoptr` conversions. For compatibility, + IR with integer pointers is still supported, but generates a deprecation warning. ([#53687]) + Command-line option changes --------------------------- diff --git a/base/atomics.jl b/base/atomics.jl index dde981b8c0e6af..e6f3a5654cbf73 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -364,13 +364,13 @@ for typ in atomictypes irt = "$ilt, $ilt*" @eval getindex(x::Atomic{$typ}) = GC.@preserve x llvmcall($""" - %ptr = inttoptr i$WORD_SIZE %0 to $lt* + %ptr = bitcast i8* %0 to $lt* %rv = load atomic $rt %ptr acquire, align $(gc_alignment(typ)) ret $lt %rv """, $typ, Tuple{Ptr{$typ}}, unsafe_convert(Ptr{$typ}, x)) @eval setindex!(x::Atomic{$typ}, v::$typ) = GC.@preserve x llvmcall($""" - %ptr = inttoptr i$WORD_SIZE %0 to $lt* + %ptr = bitcast i8* %0 to $lt* store atomic $lt %1, $lt* %ptr release, align $(gc_alignment(typ)) ret void """, Cvoid, Tuple{Ptr{$typ}, $typ}, unsafe_convert(Ptr{$typ}, x), v) @@ -379,7 +379,7 @@ for typ in atomictypes if typ <: Integer @eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) = GC.@preserve x llvmcall($""" - %ptr = inttoptr i$WORD_SIZE %0 to $lt* + %ptr = bitcast i8* %0 to $lt* %rs = cmpxchg $lt* %ptr, $lt %1, $lt %2 acq_rel acquire %rv = extractvalue { $lt, i1 } %rs, 0 ret $lt %rv @@ -388,7 +388,7 @@ for typ in atomictypes else @eval atomic_cas!(x::Atomic{$typ}, cmp::$typ, new::$typ) = GC.@preserve x llvmcall($""" - %iptr = inttoptr i$WORD_SIZE %0 to $ilt* + %iptr = bitcast i8* %0 to $ilt* %icmp = bitcast $lt %1 to $ilt %inew = bitcast $lt %2 to $ilt %irs = cmpxchg $ilt* %iptr, $ilt %icmp, $ilt %inew acq_rel acquire @@ -411,7 +411,7 @@ for typ in atomictypes if typ <: Integer @eval $fn(x::Atomic{$typ}, v::$typ) = GC.@preserve x llvmcall($""" - %ptr = inttoptr i$WORD_SIZE %0 to $lt* + %ptr = bitcast i8* %0 to $lt* %rv = atomicrmw $rmw $lt* %ptr, $lt %1 acq_rel ret $lt %rv """, $typ, Tuple{Ptr{$typ}, $typ}, unsafe_convert(Ptr{$typ}, x), v) @@ -419,7 +419,7 @@ for typ in atomictypes rmwop === :xchg || continue @eval $fn(x::Atomic{$typ}, v::$typ) = GC.@preserve x llvmcall($""" - %iptr = inttoptr i$WORD_SIZE %0 to $ilt* + %iptr = bitcast i8* %0 to $ilt* %ival = bitcast $lt %1 to $ilt %irv = atomicrmw $rmw $ilt* %iptr, $ilt %ival acq_rel %rv = bitcast $ilt %irv to $lt diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index d697ec56bf55fe..090be7e91fad9f 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -184,8 +184,6 @@ add_tfunc(sdiv_int, 2, 2, math_tfunc, 20) add_tfunc(udiv_int, 2, 2, math_tfunc, 20) add_tfunc(srem_int, 2, 2, math_tfunc, 20) add_tfunc(urem_int, 2, 2, math_tfunc, 20) -add_tfunc(add_ptr, 2, 2, math_tfunc, 1) -add_tfunc(sub_ptr, 2, 2, math_tfunc, 1) add_tfunc(neg_float, 1, 1, math_tfunc, 1) add_tfunc(add_float, 2, 2, math_tfunc, 2) add_tfunc(sub_float, 2, 2, math_tfunc, 2) @@ -662,6 +660,9 @@ function pointer_eltype(@nospecialize(ptr)) return Any end +@nospecs function pointerarith_tfunc(๐•ƒ::AbstractLattice, ptr, offset) + return ptr +end @nospecs function pointerref_tfunc(๐•ƒ::AbstractLattice, a, i, align) return pointer_eltype(a) end @@ -705,6 +706,8 @@ end end return ccall(:jl_apply_cmpswap_type, Any, (Any,), T) where T end +add_tfunc(add_ptr, 2, 2, pointerarith_tfunc, 1) +add_tfunc(sub_ptr, 2, 2, pointerarith_tfunc, 1) add_tfunc(pointerref, 3, 3, pointerref_tfunc, 4) add_tfunc(pointerset, 4, 4, pointerset_tfunc, 5) add_tfunc(atomic_fence, 1, 1, atomic_fence_tfunc, 4) diff --git a/base/pointer.jl b/base/pointer.jl index 2f67c8a6757cb2..494e87996355c0 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -313,8 +313,8 @@ isless(x::Ptr{T}, y::Ptr{T}) where {T} = x < y <(x::Ptr, y::Ptr) = UInt(x) < UInt(y) -(x::Ptr, y::Ptr) = UInt(x) - UInt(y) -+(x::Ptr, y::Integer) = oftype(x, add_ptr(UInt(x), (y % UInt) % UInt)) --(x::Ptr, y::Integer) = oftype(x, sub_ptr(UInt(x), (y % UInt) % UInt)) ++(x::Ptr, y::Integer) = add_ptr(x, (y % UInt) % UInt) +-(x::Ptr, y::Integer) = sub_ptr(x, (y % UInt) % UInt) +(x::Integer, y::Ptr) = y + x unsigned(x::Ptr) = UInt(x) diff --git a/base/task.jl b/base/task.jl index 2b758d342b169f..90f74441c7fbda 100644 --- a/base/task.jl +++ b/base/task.jl @@ -154,8 +154,7 @@ const _state_index = findfirst(==(:_state), fieldnames(Task)) @eval function load_state_acquire(t) # TODO: Replace this by proper atomic operations when available @GC.preserve t llvmcall($(""" - %ptr = inttoptr i$(Sys.WORD_SIZE) %0 to i8* - %rv = load atomic i8, i8* %ptr acquire, align 8 + %rv = load atomic i8, i8* %0 acquire, align 8 ret i8 %rv """), UInt8, Tuple{Ptr{UInt8}}, Ptr{UInt8}(pointer_from_objref(t) + fieldoffset(Task, _state_index))) diff --git a/src/ccall.cpp b/src/ccall.cpp index 53714cebcbe2ab..2d4343a00a2a52 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -616,7 +616,7 @@ static void interpret_symbol_arg(jl_codectx_t &ctx, native_sym_arg_t &out, jl_va emit_cpointercheck(ctx, arg1, errmsg); } arg1 = update_julia_type(ctx, arg1, (jl_value_t*)jl_voidpointer_type); - jl_ptr = emit_unbox(ctx, ctx.types().T_size, arg1, (jl_value_t*)jl_voidpointer_type); + jl_ptr = emit_unbox(ctx, ctx.types().T_ptr, arg1, (jl_value_t*)jl_voidpointer_type); } else { out.gcroot = ptr; @@ -696,7 +696,7 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg else { rt = (jl_value_t*)jl_voidpointer_type; } - Type *lrt = ctx.types().T_size; + Type *lrt = ctx.types().T_ptr; assert(lrt == julia_type_to_llvm(ctx, rt)); interpret_symbol_arg(ctx, sym, args[1], /*ccall=*/false, false); @@ -723,7 +723,6 @@ static jl_cgval_t emit_cglobal(jl_codectx_t &ctx, jl_value_t **args, size_t narg } else /*if (ctx.emission_context.imaging) */{ res = runtime_sym_lookup(ctx, cast(getInt8PtrTy(ctx.builder.getContext())), sym.f_lib, NULL, sym.f_name, ctx.f); - res = ctx.builder.CreatePtrToInt(res, lrt); } } @@ -814,18 +813,13 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar JL_TYPECHK(llvmcall, type, rt); JL_TYPECHK(llvmcall, type, at); - // Generate arguments - std::string arguments; - raw_string_ostream argstream(arguments); - jl_svec_t *tt = ((jl_datatype_t*)at)->parameters; - jl_value_t *rtt = rt; + // Determine argument types + // + // Semantics for arguments are as follows: + // If the argument type is immutable (including bitstype), we pass the loaded llvm value + // type. Otherwise we pass a pointer to a jl_value_t. + jl_svec_t *tt = ((jl_datatype_t *)at)->parameters; size_t nargt = jl_svec_len(tt); - - /* - * Semantics for arguments are as follows: - * If the argument type is immutable (including bitstype), we pass the loaded llvm value - * type. Otherwise we pass a pointer to a jl_value_t. - */ SmallVector argtypes; SmallVector argvals(nargt); for (size_t i = 0; i < nargt; ++i) { @@ -846,45 +840,87 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar argvals[i] = llvm_type_rewrite(ctx, v, t, issigned); } + // Determine return type + jl_value_t *rtt = rt; bool retboxed; Type *rettype = julia_type_to_llvm(ctx, rtt, &retboxed); // Make sure to find a unique name std::string ir_name; while (true) { - raw_string_ostream(ir_name) << (ctx.f->getName().str()) << "u" << jl_atomic_fetch_add_relaxed(&globalUniqueGeneratedNames, 1); + raw_string_ostream(ir_name) + << (ctx.f->getName().str()) << "u" + << jl_atomic_fetch_add_relaxed(&globalUniqueGeneratedNames, 1); if (jl_Module->getFunction(ir_name) == NULL) break; } // generate a temporary module that contains our IR std::unique_ptr Mod; + Function *f; if (entry == NULL) { // we only have function IR, which we should put in a function - bool first = true; + // stringify arguments + std::string arguments; + raw_string_ostream argstream(arguments); for (SmallVector::iterator it = argtypes.begin(); it != argtypes.end(); ++it) { - if (!first) + if (it != argtypes.begin()) argstream << ","; - else - first = false; (*it)->print(argstream); argstream << " "; } + // stringify return type std::string rstring; raw_string_ostream rtypename(rstring); rettype->print(rtypename); - std::map localDecls; + // generate IR function definition std::string ir_string; raw_string_ostream ir_stream(ir_string); - ir_stream << "; Number of arguments: " << nargt << "\n" - << "define "< 0) + compat_argstream << ","; + jl_value_t *tti = jl_svecref(tt, i); + Type *t; + if (jl_is_cpointer_type(tti)) + t = ctx.types().T_size; + else + t = argtypes[i]; + t->print(compat_argstream); + compat_argstream << " "; + } + + std::string compat_rstring; + raw_string_ostream compat_rtypename(compat_rstring); + if (jl_is_cpointer_type(rtt)) + ctx.types().T_size->print(compat_rtypename); + else + rettype->print(compat_rtypename); + + std::string compat_ir_string; + raw_string_ostream compat_ir_stream(compat_ir_string); + compat_ir_stream << "define " << compat_rtypename.str() << " @\"" << ir_name + << "\"(" << compat_argstream.str() << ") {\n" + << jl_string_data(ir) << "\n}"; + + SMDiagnostic Err = SMDiagnostic(); + Mod = + parseAssemblyString(compat_ir_stream.str(), Err, ctx.builder.getContext()); + } + if (!Mod) { std::string message = "Failed to parse LLVM assembly: \n"; raw_string_ostream stream(message); @@ -894,7 +930,7 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar return jl_cgval_t(); } - Function *f = Mod->getFunction(ir_name); + f = Mod->getFunction(ir_name); f->addFnAttr(Attribute::AlwaysInline); } else { @@ -932,21 +968,96 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar Mod = std::move(ModuleOrErr.get()); } - Function *f = Mod->getFunction(jl_string_data(entry)); + f = Mod->getFunction(jl_string_data(entry)); if (!f) { emit_error(ctx, "Module IR does not contain specified entry function"); JL_GC_POP(); return jl_cgval_t(); } + assert(!f->isDeclaration()); f->setName(ir_name); + } - // verify the function type - assert(!f->isDeclaration()); - assert(f->getReturnType() == rettype); - int i = 0; - for (SmallVector::iterator it = argtypes.begin(); - it != argtypes.end(); ++it, ++i) - assert(*it == f->getFunctionType()->getParamType(i)); + // backwards compatibility: support for IR with integer pointers + bool mismatched_pointers = false; + for (size_t i = 0; i < nargt; ++i) { + jl_value_t *tti = jl_svecref(tt, i); + if (jl_is_cpointer_type(tti) && + !f->getFunctionType()->getParamType(i)->isPointerTy()) { + mismatched_pointers = true; + break; + } + } + if (mismatched_pointers) { + if (jl_options.depwarn) { + if (jl_options.depwarn == JL_OPTIONS_DEPWARN_ERROR) + jl_error("llvmcall with integer pointers is deprecated, " + "use an actual pointer type instead."); + + // ensure we only depwarn once per method + // TODO: lift this into a reusable codegen-level depwarn utility + static std::set llvmcall_depwarns; + jl_method_t *m = ctx.linfo->def.method; + if (llvmcall_depwarns.find(m) == llvmcall_depwarns.end()) { + llvmcall_depwarns.insert(m); + jl_printf(JL_STDERR, + "WARNING: llvmcall with integer pointers is deprecated.\n" + "Use actual pointers instead, replacing i32 or i64 with i8* or ptr\n" + "in "); + jl_static_show(JL_STDERR, (jl_value_t*) ctx.linfo->def.method); + jl_printf(JL_STDERR, " at %s\n", ctx.file.str().c_str()); + } + } + + // wrap the function, performing the necessary pointer conversion + + Function *inner = f; + inner->setName(ir_name + ".inner"); + + FunctionType *wrapper_ft = FunctionType::get(rettype, argtypes, false); + Function *wrapper = + Function::Create(wrapper_ft, inner->getLinkage(), ir_name, *Mod); + + wrapper->copyAttributesFrom(inner); + inner->addFnAttr(Attribute::AlwaysInline); + + BasicBlock *entry = BasicBlock::Create(ctx.builder.getContext(), "", wrapper); + IRBuilder<> irbuilder(entry); + SmallVector wrapper_args; + for (size_t i = 0; i < nargt; ++i) { + jl_value_t *tti = jl_svecref(tt, i); + Value *v = wrapper->getArg(i); + if (jl_is_cpointer_type(tti)) + v = irbuilder.CreatePtrToInt(v, ctx.types().T_size); + wrapper_args.push_back(v); + } + Value *call = irbuilder.CreateCall(inner, wrapper_args); + // check if void + if (rettype->isVoidTy()) + irbuilder.CreateRetVoid(); + else { + if (jl_is_cpointer_type(rtt)) + call = irbuilder.CreateIntToPtr(call, ctx.types().T_ptr); + irbuilder.CreateRet(call); + } + + f = wrapper; + } + + // verify the function type + assert(f->getReturnType() == rettype); + int i = 0; + for (SmallVector::iterator it = argtypes.begin(); it != argtypes.end(); + ++it, ++i) { + if (*it != f->getFunctionType()->getParamType(i)) { + std::string message; + raw_string_ostream stream(message); + stream << "Malformed llvmcall: argument " << i + 1 << " type " + << *f->getFunctionType()->getParamType(i) + << " does not match expected argument type " << **it; + emit_error(ctx, stream.str()); + return jl_cgval_t(); + } } // copy module properties that should always match @@ -984,7 +1095,7 @@ static jl_cgval_t emit_llvmcall(jl_codectx_t &ctx, jl_value_t **args, size_t nar if (inst->getType() != rettype) { std::string message; raw_string_ostream stream(message); - stream << "llvmcall return type " << *inst->getType() + stream << "Malformed llvmcall: return type " << *inst->getType() << " does not match declared return type" << *rettype; emit_error(ctx, stream.str()); return jl_cgval_t(); @@ -1462,14 +1573,14 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) (void)isVa; // prevent compiler warning if (is_libjulia_func(jl_value_ptr)) { ++CCALL_STAT(jl_value_ptr); - assert(retboxed ? lrt == ctx.types().T_prjlvalue : lrt == ctx.types().T_size); + assert(retboxed ? lrt == ctx.types().T_prjlvalue : lrt == ctx.types().T_ptr); assert(!isVa && !llvmcall && nccallargs == 1); jl_value_t *tti = jl_svecref(at, 0); Type *largty; bool isboxed; if (jl_is_abstract_ref_type(tti)) { tti = (jl_value_t*)jl_voidpointer_type; - largty = ctx.types().T_size; + largty = ctx.types().T_ptr; isboxed = false; } else { @@ -1482,7 +1593,6 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) } else { retval = emit_unbox(ctx, largty, argv[0], tti); - retval = emit_inttoptr(ctx, retval, ctx.types().T_pjlvalue); } // retval is now an untracked jl_value_t* if (retboxed) @@ -1561,9 +1671,7 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) assert(lrt == ctx.types().T_size); assert(!isVa && !llvmcall && nccallargs == 0); JL_GC_POP(); - return mark_or_box_ccall_result(ctx, - ctx.builder.CreatePtrToInt(get_current_ptls(ctx), lrt), - retboxed, rt, unionall, static_rt); + return mark_or_box_ccall_result(ctx, get_current_ptls(ctx), retboxed, rt, unionall, static_rt); } else if (is_libjulia_func(jl_threadid)) { ++CCALL_STAT(jl_threadid); @@ -1683,21 +1791,20 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) } else if (is_libjulia_func(jl_string_ptr)) { ++CCALL_STAT(jl_string_ptr); - assert(lrt == ctx.types().T_size); + assert(lrt == ctx.types().T_ptr); assert(!isVa && !llvmcall && nccallargs == 1); auto obj = emit_bitcast(ctx, emit_pointer_from_objref(ctx, boxed(ctx, argv[0])), ctx.types().T_pprjlvalue); // The inbounds gep makes it more clear to LLVM that the resulting value is not // a null pointer. auto strp = ctx.builder.CreateConstInBoundsGEP1_32(ctx.types().T_prjlvalue, obj, 1); - strp = ctx.builder.CreatePtrToInt(strp, ctx.types().T_size); setName(ctx.emission_context, strp, "string_ptr"); JL_GC_POP(); return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt); } else if (is_libjulia_func(jl_symbol_name)) { ++CCALL_STAT(jl_symbol_name); - assert(lrt == ctx.types().T_size); + assert(lrt == ctx.types().T_ptr); assert(!isVa && !llvmcall && nccallargs == 1); auto obj = emit_bitcast(ctx, emit_pointer_from_objref(ctx, boxed(ctx, argv[0])), ctx.types().T_pprjlvalue); @@ -1705,7 +1812,6 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) // a null pointer. auto strp = ctx.builder.CreateConstInBoundsGEP1_32( ctx.types().T_prjlvalue, obj, (sizeof(jl_sym_t) + sizeof(void*) - 1) / sizeof(void*)); - strp = ctx.builder.CreatePtrToInt(strp, ctx.types().T_size); setName(ctx.emission_context, strp, "symbol_name"); JL_GC_POP(); return mark_or_box_ccall_result(ctx, strp, retboxed, rt, unionall, static_rt); @@ -1750,14 +1856,12 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) const jl_cgval_t &dst = argv[0]; const jl_cgval_t &src = argv[1]; const jl_cgval_t &n = argv[2]; - Value *destp = emit_unbox(ctx, ctx.types().T_size, dst, (jl_value_t*)jl_voidpointer_type); + Value *destp = emit_unbox(ctx, ctx.types().T_ptr, dst, (jl_value_t*)jl_voidpointer_type); ctx.builder.CreateMemCpy( - emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())), + destp, MaybeAlign(1), - emit_inttoptr(ctx, - emit_unbox(ctx, ctx.types().T_size, src, (jl_value_t*)jl_voidpointer_type), - getInt8PtrTy(ctx.builder.getContext())), + emit_unbox(ctx, ctx.types().T_ptr, src, (jl_value_t*)jl_voidpointer_type), MaybeAlign(1), emit_unbox(ctx, ctx.types().T_size, n, (jl_value_t*)jl_ulong_type), false); @@ -1770,11 +1874,11 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) const jl_cgval_t &dst = argv[0]; const jl_cgval_t &val = argv[1]; const jl_cgval_t &n = argv[2]; - Value *destp = emit_unbox(ctx, ctx.types().T_size, dst, (jl_value_t*)jl_voidpointer_type); + Value *destp = emit_unbox(ctx, ctx.types().T_ptr, dst, (jl_value_t*)jl_voidpointer_type); Value *val32 = emit_unbox(ctx, getInt32Ty(ctx.builder.getContext()), val, (jl_value_t*)jl_uint32_type); Value *val8 = ctx.builder.CreateTrunc(val32, getInt8Ty(ctx.builder.getContext()), "memset_val"); ctx.builder.CreateMemSet( - emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())), + destp, val8, emit_unbox(ctx, ctx.types().T_size, n, (jl_value_t*)jl_ulong_type), MaybeAlign(1) @@ -1788,14 +1892,12 @@ static jl_cgval_t emit_ccall(jl_codectx_t &ctx, jl_value_t **args, size_t nargs) const jl_cgval_t &dst = argv[0]; const jl_cgval_t &src = argv[1]; const jl_cgval_t &n = argv[2]; - Value *destp = emit_unbox(ctx, ctx.types().T_size, dst, (jl_value_t*)jl_voidpointer_type); + Value *destp = emit_unbox(ctx, ctx.types().T_ptr, dst, (jl_value_t*)jl_voidpointer_type); ctx.builder.CreateMemMove( - emit_inttoptr(ctx, destp, getInt8PtrTy(ctx.builder.getContext())), + destp, MaybeAlign(0), - emit_inttoptr(ctx, - emit_unbox(ctx, ctx.types().T_size, src, (jl_value_t*)jl_voidpointer_type), - getInt8PtrTy(ctx.builder.getContext())), + emit_unbox(ctx, ctx.types().T_ptr, src, (jl_value_t*)jl_voidpointer_type), MaybeAlign(0), emit_unbox(ctx, ctx.types().T_size, n, (jl_value_t*)jl_ulong_type), false); @@ -1999,7 +2101,7 @@ jl_cgval_t function_sig_t::emit_a_ccall( ++LiteralCCalls; null_pointer_check(ctx, symarg.jl_ptr, nullptr); Type *funcptype = PointerType::get(functype, 0); - llvmf = emit_inttoptr(ctx, symarg.jl_ptr, funcptype); + llvmf = ctx.builder.CreateBitCast(symarg.jl_ptr, funcptype); } else if (symarg.fptr != NULL) { ++LiteralCCalls; diff --git a/src/cgutils.cpp b/src/cgutils.cpp index b17b174dd8a8de..8385b5682a0bcc 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -690,6 +690,8 @@ static Type *bitstype_to_llvm(jl_value_t *bt, LLVMContext &ctxt, bool llvmcall = return getDoubleTy(ctxt); if (bt == (jl_value_t*)jl_bfloat16_type) return getBFloatTy(ctxt); + if (jl_is_cpointer_type(bt)) + return PointerType::get(getInt8Ty(ctxt), 0); if (jl_is_llvmpointer_type(bt)) { jl_value_t *as_param = jl_tparam1(bt); int as; diff --git a/src/codegen.cpp b/src/codegen.cpp index cf5122df295ebd..2e2afc02080a18 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -283,6 +283,7 @@ extern void _chkstk(void); // types struct jl_typecache_t { + Type *T_ptr; Type *T_size; Type *T_jlvalue; Type *T_pjlvalue; @@ -304,7 +305,7 @@ struct jl_typecache_t { bool initialized; jl_typecache_t() : - T_jlvalue(nullptr), T_pjlvalue(nullptr), T_prjlvalue(nullptr), + T_ptr(nullptr), T_jlvalue(nullptr), T_pjlvalue(nullptr), T_prjlvalue(nullptr), T_ppjlvalue(nullptr), T_pprjlvalue(nullptr), T_jlgenericmemory(nullptr), T_jlarray(nullptr), T_pjlarray(nullptr), T_jlfunc(nullptr), T_jlfuncparams(nullptr), T_sigatomic(nullptr), T_ppint8(nullptr), @@ -315,6 +316,7 @@ struct jl_typecache_t { return; } initialized = true; + T_ptr = getInt8PtrTy(context); T_ppint8 = PointerType::get(getInt8PtrTy(context), 0); T_sigatomic = Type::getIntNTy(context, sizeof(sig_atomic_t) * 8); T_size = DL.getIntPtrType(context); diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp index 3a98850ddca68d..c2450d359be45f 100644 --- a/src/intrinsics.cpp +++ b/src/intrinsics.cpp @@ -17,6 +17,7 @@ STATISTIC(EmittedRuntimeCalls, "Number of runtime intrinsic calls emitted"); STATISTIC(EmittedIntrinsics, "Number of intrinsic calls emitted"); STATISTIC(Emitted_pointerref, "Number of pointerref calls emitted"); STATISTIC(Emitted_pointerset, "Number of pointerset calls emitted"); +STATISTIC(Emitted_pointerarith, "Number of pointer arithmetic calls emitted"); STATISTIC(Emitted_atomic_fence, "Number of atomic_fence calls emitted"); STATISTIC(Emitted_atomic_pointerref, "Number of atomic_pointerref calls emitted"); STATISTIC(Emitted_atomic_pointerop, "Number of atomic_pointerop calls emitted"); @@ -625,10 +626,14 @@ static jl_cgval_t generic_bitcast(jl_codectx_t &ctx, ArrayRef argv) vx = ctx.builder.CreateZExt(vx, llvmt); } else if (vxt->isPointerTy() && !llvmt->isPointerTy()) { vx = ctx.builder.CreatePtrToInt(vx, llvmt); - setName(ctx.emission_context, vx, "bitcast_coercion"); + if (isa(vx) && !vx->hasName()) + // CreatePtrToInt may undo an IntToPtr + setName(ctx.emission_context, vx, "bitcast_coercion"); } else if (!vxt->isPointerTy() && llvmt->isPointerTy()) { vx = emit_inttoptr(ctx, vx, llvmt); - setName(ctx.emission_context, vx, "bitcast_coercion"); + if (isa(vx) && !vx->hasName()) + // emit_inttoptr may undo an PtrToInt + setName(ctx.emission_context, vx, "bitcast_coercion"); } else { vx = emit_bitcast(ctx, vx, llvmt); setName(ctx.emission_context, vx, "bitcast_coercion"); @@ -741,7 +746,8 @@ static jl_cgval_t emit_pointerref(jl_codectx_t &ctx, ArrayRef argv) if (ety == (jl_value_t*)jl_any_type) { Value *thePtr = emit_unbox(ctx, ctx.types().T_pprjlvalue, e, e.typ); - setName(ctx.emission_context, thePtr, "unbox_any_ptr"); + if (isa(thePtr) && !thePtr->hasName()) + setName(ctx.emission_context, thePtr, "unbox_any_ptr"); LoadInst *load = ctx.builder.CreateAlignedLoad(ctx.types().T_prjlvalue, ctx.builder.CreateInBoundsGEP(ctx.types().T_prjlvalue, thePtr, im1), Align(align_nb)); setName(ctx.emission_context, load, "any_unbox"); jl_aliasinfo_t ai = jl_aliasinfo_t::fromTBAA(ctx, ctx.tbaa().tbaa_data); @@ -853,6 +859,34 @@ static jl_cgval_t emit_pointerset(jl_codectx_t &ctx, ArrayRef argv) return e; } +// ptr + offset +// ptr - offset +static jl_cgval_t emit_pointerarith(jl_codectx_t &ctx, intrinsic f, + ArrayRef argv) +{ + jl_value_t *ptrtyp = argv[0].typ; + jl_value_t *offtyp = argv[1].typ; + if (!jl_is_cpointer_type(ptrtyp) || offtyp != (jl_value_t *)jl_ulong_type) + return emit_runtime_call(ctx, f, argv, argv.size()); + assert(f == add_ptr || f == sub_ptr); + + Value *ptr = emit_unbox(ctx, ctx.types().T_ptr, argv[0], ptrtyp); + Value *off = emit_unbox(ctx, ctx.types().T_size, argv[1], offtyp); + if (f == sub_ptr) + off = ctx.builder.CreateNeg(off); + Value *ans = ctx.builder.CreateGEP(getInt8Ty(ctx.builder.getContext()), ptr, off); + + if (jl_is_concrete_type(ptrtyp)) { + return mark_julia_type(ctx, ans, false, ptrtyp); + } + else { + Value *box = emit_allocobj(ctx, (jl_datatype_t *)ptrtyp, true); + setName(ctx.emission_context, box, "ptr_box"); + init_bits_value(ctx, box, ans, ctx.tbaa().tbaa_immut); + return mark_julia_type(ctx, box, true, (jl_datatype_t *)ptrtyp); + } +} + static jl_cgval_t emit_atomicfence(jl_codectx_t &ctx, ArrayRef argv) { const jl_cgval_t &ord = argv[0]; @@ -1270,6 +1304,13 @@ static jl_cgval_t emit_intrinsic(jl_codectx_t &ctx, intrinsic f, jl_value_t **ar ++Emitted_pointerset; assert(nargs == 4); return emit_pointerset(ctx, argv); + + case add_ptr: + case sub_ptr: + ++Emitted_pointerarith; + assert(nargs == 2); + return emit_pointerarith(ctx, f, argv); + case atomic_fence: ++Emitted_atomic_fence; assert(nargs == 1); @@ -1437,26 +1478,6 @@ static Value *emit_untyped_intrinsic(jl_codectx_t &ctx, intrinsic f, ArrayRefreplaceAllUsesWith(ASC->getOperand(0)); + if (ASC->getType() == ASC->getOperand(0)->getType()) { + ASC->replaceAllUsesWith(ASC->getOperand(0)); + } else { + // uncanonicalized addrspacecast; demote to bitcast + llvm::IRBuilder<> builder(ASC); + auto BC = builder.CreateBitCast(ASC->getOperand(0), ASC->getType()); + ASC->replaceAllUsesWith(BC); + } NoopCasts.push_back(ASC); } } diff --git a/src/runtime_intrinsics.c b/src/runtime_intrinsics.c index ff479a4d309598..9abe9828fb07fd 100644 --- a/src/runtime_intrinsics.c +++ b/src/runtime_intrinsics.c @@ -1384,10 +1384,8 @@ JL_DLLEXPORT jl_value_t *jl_##name(jl_value_t *a, jl_value_t *b, jl_value_t *c) un_iintrinsic_fast(LLVMNeg, neg, neg_int, u) #define add(a,b) a + b bi_iintrinsic_fast(LLVMAdd, add, add_int, u) -bi_iintrinsic_fast(LLVMAdd, add, add_ptr, u) #define sub(a,b) a - b bi_iintrinsic_fast(LLVMSub, sub, sub_int, u) -bi_iintrinsic_fast(LLVMSub, sub, sub_ptr, u) #define mul(a,b) a * b bi_iintrinsic_fast(LLVMMul, mul, mul_int, u) #define div(a,b) a / b @@ -1696,3 +1694,19 @@ JL_DLLEXPORT jl_value_t *jl_have_fma(jl_value_t *typ) else return jl_false; } + +JL_DLLEXPORT jl_value_t *jl_add_ptr(jl_value_t *ptr, jl_value_t *offset) +{ + JL_TYPECHK(add_ptr, pointer, ptr); + JL_TYPECHK(add_ptr, ulong, offset); + char *ptrval = (char*)jl_unbox_long(ptr) + jl_unbox_ulong(offset); + return jl_new_bits(jl_typeof(ptr), &ptrval); +} + +JL_DLLEXPORT jl_value_t *jl_sub_ptr(jl_value_t *ptr, jl_value_t *offset) +{ + JL_TYPECHK(sub_ptr, pointer, ptr); + JL_TYPECHK(sub_ptr, ulong, offset); + char *ptrval = (char*)jl_unbox_long(ptr) - jl_unbox_ulong(offset); + return jl_new_bits(jl_typeof(ptr), &ptrval); +} From 52fc79696e0b08fe1793a001daaefd1d91d59f0c Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Thu, 21 Mar 2024 20:32:17 -0400 Subject: [PATCH 014/123] Add missing GC_POP() in emit_cfunction (#53809) ~~Apparently somewhere in codegen inside `emit_codeinst`some piece of code is relying on the implicit try catch gcstack restoring. I haven't got the analyzer working on that file yet (it has hundreds of issues and it doesn't like C++ code that much + the file is tens of thousands of lines after includes so it struggles).~~ This fixes the compileall segfault in apple-aarch64 ci. https://github.com/JuliaLang/julia/issues/53811 --- src/codegen.cpp | 1 + src/rtutils.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index 2e2afc02080a18..f1b0c570acc336 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7379,6 +7379,7 @@ static jl_cgval_t emit_cfunction(jl_codectx_t &ctx, jl_value_t *output_type, con if (ctx.emission_context.TargetTriple.isAArch64() || ctx.emission_context.TargetTriple.isARM() || ctx.emission_context.TargetTriple.isPPC64()) { if (nest) { emit_error(ctx, "cfunction: closures are not supported on this platform"); + JL_GC_POP(); return jl_cgval_t(); } } diff --git a/src/rtutils.c b/src/rtutils.c index b7e79993201000..88109374cf0611 100644 --- a/src/rtutils.c +++ b/src/rtutils.c @@ -297,6 +297,7 @@ JL_DLLEXPORT void jl_eh_restore_state(jl_task_t *ct, jl_handler_t *eh) JL_DLLEXPORT void jl_eh_restore_state_noexcept(jl_task_t *ct, jl_handler_t *eh) { + assert(ct->gcstack == eh->gcstack && "Incorrect GC usage under try catch"); ct->eh = eh->prev; ct->ptls->defer_signal = eh->defer_signal; // optional, but certain try-finally (in stream.jl) may be slightly harder to write without this } From 6c22dfd3180b82566cc3fce2cea5782623d6e1e9 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 21 Mar 2024 21:04:28 -0400 Subject: [PATCH 015/123] Remove fl_julia_current_{file, line} (#53797) These flisp accessor functions make use of the `jl_filename` and `jl_lineno` globals. I was looking at removing these globals for unrelated reasons, when I saw that one of the primary uses was in these flisp accessor, which appear entirely unnecessary. They are only used to provide a default for an error message, but the place that puts the error message into a list to return to julia does actually already have access to this information, so there's no need for these to look at the globals. While we're at it, also add a test for this code path, which was otherwise unexercised in our test suite. --- src/ast.c | 12 ------------ src/jlfrontend.scm | 7 ++++--- src/julia-syntax.scm | 6 ++---- test/syntax.jl | 10 ++++++++++ 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/ast.c b/src/ast.c index 8cd483748bc94c..d39ee35e807ae9 100644 --- a/src/ast.c +++ b/src/ast.c @@ -215,16 +215,6 @@ static value_t fl_current_module_counter(fl_context_t *fl_ctx, value_t *args, ui return fixnum(jl_module_next_counter(ctx->module)); } -static value_t fl_julia_current_file(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) JL_NOTSAFEPOINT -{ - return symbol(fl_ctx, jl_filename); -} - -static value_t fl_julia_current_line(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) JL_NOTSAFEPOINT -{ - return fixnum(jl_lineno); -} - static int jl_is_number(jl_value_t *v) { jl_datatype_t *t = (jl_datatype_t*)jl_typeof(v); @@ -257,8 +247,6 @@ static const builtinspec_t julia_flisp_ast_ext[] = { { "nothrow-julia-global", fl_nothrow_julia_global }, { "current-julia-module-counter", fl_current_module_counter }, { "julia-scalar?", fl_julia_scalar }, - { "julia-current-file", fl_julia_current_file }, - { "julia-current-line", fl_julia_current_line }, { NULL, NULL } }; diff --git a/src/jlfrontend.scm b/src/jlfrontend.scm index b46663c5603468..2c5f42eda5ce8e 100644 --- a/src/jlfrontend.scm +++ b/src/jlfrontend.scm @@ -32,8 +32,6 @@ ;; this is overwritten when we run in actual julia (define (defined-julia-global v) #f) (define (nothrow-julia-global v) #f) -(define (julia-current-file) 'none) -(define (julia-current-line) 0) ;; parser entry points @@ -182,7 +180,10 @@ ;; Abuse scm_to_julia here to convert arguments to warn. This is meant for ;; `Expr`s but should be good enough provided we're only passing simple ;; numbers, symbols and strings. - ((lowering-warning (lambda lst (set! warnings (cons (cons 'warn lst) warnings))))) + ((lowering-warning (lambda (level group warn_file warn_line . lst) + (let ((line (if (= warn_line 0) line warn_line)) + (file (if (eq? warn_file 'none) file warn_file))) + (set! warnings (cons (list* 'warn level group (symbol (string file line)) file line lst) warnings)))))) (let ((thunk (if stmt (expand-to-thunk-stmt- expr file line) (expand-to-thunk- expr file line)))) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index abe8165c427878..f1ae6c90bda6a3 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -3241,11 +3241,9 @@ (warn-var?! (cadr e) scope) (= *scopewarn-opt* 1)) (let* ((v (cadr e)) - (loc (extract-line-file loc)) - (line (if (= (car loc) 0) (julia-current-line) (car loc))) - (file (if (eq? (cadr loc) 'none) (julia-current-file) (cadr loc)))) + (loc (extract-line-file loc))) (lowering-warning - 1000 'warn (symbol (string file line)) file line + 1000 'warn (cadr loc) (car loc) (string "Assignment to `" v "` in soft scope is ambiguous " "because a global variable by the same name exists: " "`" v "` will be treated as a new local. " diff --git a/test/syntax.jl b/test/syntax.jl index 9c26ea97594d06..985f5c9000fbed 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -2189,6 +2189,16 @@ end end @test z28789 == 42 +const warn28789 = "Assignment to `s28789` in soft scope is ambiguous because a global variable by the same name exists: "* + "`s28789` will be treated as a new local. Disambiguate by using `local s28789` to suppress this warning or "* + "`global s28789` to assign to the existing global variable." +@test_logs (:warn, warn28789) @test_throws UndefVarError @eval begin + s28789 = 0 + for i = 1:10 + s28789 += i + end +end + # issue #38650, `struct` should always be a hard scope f38650() = 0 @eval begin From 91455710f38f226e45591203b0d4cd8e392131fd Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 22 Mar 2024 05:37:18 -0400 Subject: [PATCH 016/123] Use jl_filename/jl_lineno less (#53799) I don't like `jl_filename`/`jl_lineno`. They are weird internal state, and they are also not thread safe, so if different threads are evaling different things at the same time, line numbers can get confused. This PR changes the core function `jl_toplevel_eval_flex` to keep track of its current file/line context on the stack, so at least there is no confusion within one call to this function. With this PR and #53797, the global `jl_filename`/`jl_lineno` are used for three purposes: 1. To initialize the filename/lineno used by lowering from `Core.eval`. 2. To give binding deprecation warnings. 3. For `jl_critical_error`. 4. By humans in the debugger. I think 3 and 4 are fine, they are exceptional cases. Case 2, I think could be changed to plumb through locations explicitly, but it's a bit annoying, so I didn't tackle it here. Case 1, I think can probably just be changed to consistently initialize, and if you want a proper line number, you need to put it in there explicitly. However, I didn't change that in this PR, because I think it could be slightly breaking, so should be pkgeval'd. --- src/julia_internal.h | 2 +- src/toplevel.c | 73 ++++++++++++++++++++++++++------------------ test/backtrace.jl | 9 ++++++ 3 files changed, 53 insertions(+), 31 deletions(-) diff --git a/src/julia_internal.h b/src/julia_internal.h index dc93e522b0c4d4..7df996d888909a 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -790,7 +790,7 @@ JL_DLLEXPORT int jl_datatype_isinlinealloc(jl_datatype_t *ty, int pointerfree); int jl_type_equality_is_identity(jl_value_t *t1, jl_value_t *t2) JL_NOTSAFEPOINT; void jl_eval_global_expr(jl_module_t *m, jl_expr_t *ex, int set_type); -jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int expanded); +JL_DLLEXPORT jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int expanded, const char **toplevel_filename, int *toplevel_lineno); jl_value_t *jl_eval_global_var(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *e); jl_value_t *jl_interpret_opaque_closure(jl_opaque_closure_t *clos, jl_value_t **args, size_t nargs); diff --git a/src/toplevel.c b/src/toplevel.c index 8715a955e7fb2f..d7d4b04c3e67b6 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -203,16 +203,16 @@ static jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex } // add `eval` function form = jl_call_scm_on_ast_and_loc("module-default-defs", (jl_value_t*)name, newm, filename, lineno); - jl_toplevel_eval_flex(newm, form, 0, 1); + jl_toplevel_eval_flex(newm, form, 0, 1, &filename, &lineno); form = NULL; } for (int i = 0; i < jl_array_nrows(exprs); i++) { // process toplevel form ct->world_age = jl_atomic_load_acquire(&jl_world_counter); - form = jl_expand_stmt_with_loc(jl_array_ptr_ref(exprs, i), newm, jl_filename, jl_lineno); + form = jl_expand_stmt_with_loc(jl_array_ptr_ref(exprs, i), newm, filename, lineno); ct->world_age = jl_atomic_load_acquire(&jl_world_counter); - (void)jl_toplevel_eval_flex(newm, form, 1, 1); + (void)jl_toplevel_eval_flex(newm, form, 1, 1, &filename, &lineno); } ct->world_age = last_age; @@ -286,13 +286,13 @@ static jl_value_t *jl_eval_module_expr(jl_module_t *parent_module, jl_expr_t *ex return (jl_value_t*)newm; } -static jl_value_t *jl_eval_dot_expr(jl_module_t *m, jl_value_t *x, jl_value_t *f, int fast) +static jl_value_t *jl_eval_dot_expr(jl_module_t *m, jl_value_t *x, jl_value_t *f, int fast, const char **toplevel_filename, int *toplevel_lineno) { jl_task_t *ct = jl_current_task; jl_value_t **args; JL_GC_PUSHARGS(args, 3); - args[1] = jl_toplevel_eval_flex(m, x, fast, 0); - args[2] = jl_toplevel_eval_flex(m, f, fast, 0); + args[1] = jl_toplevel_eval_flex(m, x, fast, 0, toplevel_filename, toplevel_lineno); + args[2] = jl_toplevel_eval_flex(m, f, fast, 0, toplevel_filename, toplevel_lineno); if (jl_is_module(args[1])) { JL_TYPECHK(getglobal, symbol, args[2]); args[0] = jl_eval_global_var((jl_module_t*)args[1], (jl_sym_t*)args[2]); @@ -666,46 +666,49 @@ static void check_macro_rename(jl_sym_t *from, jl_sym_t *to, const char *keyword // Eval `throw(ErrorException(msg)))` in module `m`. // Used in `jl_toplevel_eval_flex` instead of `jl_throw` so that the error // location in julia code gets into the backtrace. -static void jl_eval_throw(jl_module_t *m, jl_value_t *exc) +static void jl_eval_throw(jl_module_t *m, jl_value_t *exc, const char *filename, int lineno) { jl_value_t *throw_ex = (jl_value_t*)jl_exprn(jl_call_sym, 2); JL_GC_PUSH1(&throw_ex); jl_exprargset(throw_ex, 0, jl_builtin_throw); jl_exprargset(throw_ex, 1, exc); - jl_toplevel_eval_flex(m, throw_ex, 0, 0); + jl_toplevel_eval_flex(m, throw_ex, 0, 0, &filename, &lineno); JL_GC_POP(); } // Format error message and call jl_eval -static void jl_eval_errorf(jl_module_t *m, const char* fmt, ...) +static void jl_eval_errorf(jl_module_t *m, const char *filename, int lineno, const char* fmt, ...) { va_list args; va_start(args, fmt); jl_value_t *exc = jl_vexceptionf(jl_errorexception_type, fmt, args); va_end(args); JL_GC_PUSH1(&exc); - jl_eval_throw(m, exc); + jl_eval_throw(m, exc, filename, lineno); JL_GC_POP(); } -jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int fast, int expanded) +JL_DLLEXPORT jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int fast, int expanded, const char **toplevel_filename, int *toplevel_lineno) { jl_task_t *ct = jl_current_task; if (!jl_is_expr(e)) { if (jl_is_linenode(e)) { - jl_lineno = jl_linenode_line(e); + *toplevel_lineno = jl_linenode_line(e); jl_value_t *file = jl_linenode_file(e); if (file != jl_nothing) { assert(jl_is_symbol(file)); - jl_filename = jl_symbol_name((jl_sym_t*)file); + *toplevel_filename = jl_symbol_name((jl_sym_t*)file); } + // Not thread safe. For debugging and last resort error messages (jl_critical_error) only. + jl_filename = *toplevel_filename; + jl_lineno = *toplevel_lineno; return jl_nothing; } if (jl_is_symbol(e)) { char *n = jl_symbol_name((jl_sym_t*)e), *n0 = n; while (*n == '_') ++n; if (*n == 0 && n > n0) - jl_eval_errorf(m, "all-underscore identifiers are write-only and their values cannot be used in expressions"); + jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, "all-underscore identifiers are write-only and their values cannot be used in expressions"); } return jl_interpret_toplevel_expr_in(m, e, NULL, NULL); } @@ -714,12 +717,12 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int if (ex->head == jl_dot_sym && jl_expr_nargs(ex) != 1) { if (jl_expr_nargs(ex) != 2) - jl_eval_errorf(m, "syntax: malformed \".\" expression"); + jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, "syntax: malformed \".\" expression"); jl_value_t *lhs = jl_exprarg(ex, 0); jl_value_t *rhs = jl_exprarg(ex, 1); // only handle `a.b` syntax here, so qualified names can be eval'd in pure contexts if (jl_is_quotenode(rhs) && jl_is_symbol(jl_fieldref(rhs, 0))) { - return jl_eval_dot_expr(m, lhs, rhs, fast); + return jl_eval_dot_expr(m, lhs, rhs, fast, toplevel_filename, toplevel_lineno); } } @@ -734,7 +737,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int size_t last_age = ct->world_age; if (!expanded && jl_needs_lowering(e)) { ct->world_age = jl_atomic_load_acquire(&jl_world_counter); - ex = (jl_expr_t*)jl_expand_with_loc_warn(e, m, jl_filename, jl_lineno); + ex = (jl_expr_t*)jl_expand_with_loc_warn(e, m, *toplevel_filename, *toplevel_lineno); ct->world_age = last_age; } jl_sym_t *head = jl_is_expr(ex) ? ex->head : NULL; @@ -766,7 +769,8 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int } else { if (!jl_is_module(u)) - jl_eval_errorf(m, "invalid using path: \"%s\" does not name a module", + jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, + "invalid using path: \"%s\" does not name a module", jl_symbol_name(name)); // `using A` and `using A.B` syntax jl_module_using(m, u); @@ -792,7 +796,8 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int continue; } } - jl_eval_errorf(m, "syntax: malformed \"using\" statement"); + jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, + "syntax: malformed \"using\" statement"); } JL_GC_POP(); return jl_nothing; @@ -839,7 +844,8 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int continue; } } - jl_eval_errorf(m, "syntax: malformed \"import\" statement"); + jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, + "syntax: malformed \"import\" statement"); } JL_GC_POP(); return jl_nothing; @@ -849,8 +855,9 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int for (size_t i = 0; i < jl_array_nrows(ex->args); i++) { jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(ex->args, i); if (!jl_is_symbol(name)) - jl_eval_errorf(m, exp ? "syntax: malformed \"export\" statement" : - "syntax: malformed \"public\" statement"); + jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, + exp ? "syntax: malformed \"export\" statement" : + "syntax: malformed \"public\" statement"); jl_module_public(m, name, exp); } JL_GC_POP(); @@ -883,17 +890,19 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int jl_value_t *res = jl_nothing; int i; for (i = 0; i < jl_array_nrows(ex->args); i++) { - res = jl_toplevel_eval_flex(m, jl_array_ptr_ref(ex->args, i), fast, 0); + res = jl_toplevel_eval_flex(m, jl_array_ptr_ref(ex->args, i), fast, 0, toplevel_filename, toplevel_lineno); } JL_GC_POP(); return res; } else if (head == jl_error_sym || head == jl_incomplete_sym) { if (jl_expr_nargs(ex) == 0) - jl_eval_errorf(m, "malformed \"%s\" expression", jl_symbol_name(head)); + jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, + "malformed \"%s\" expression", jl_symbol_name(head)); if (jl_is_string(jl_exprarg(ex, 0))) - jl_eval_errorf(m, "syntax: %s", jl_string_data(jl_exprarg(ex, 0))); - jl_eval_throw(m, jl_exprarg(ex, 0)); + jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, + "syntax: %s", jl_string_data(jl_exprarg(ex, 0))); + jl_eval_throw(m, jl_exprarg(ex, 0), *toplevel_filename, *toplevel_lineno); } else if (jl_is_symbol(ex)) { JL_GC_POP(); @@ -908,7 +917,8 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int assert(head == jl_thunk_sym); thk = (jl_code_info_t*)jl_exprarg(ex, 0); if (!jl_is_code_info(thk) || !jl_typetagis(thk->code, jl_array_any_type)) { - jl_eval_errorf(m, "malformed \"thunk\" statement"); + jl_eval_errorf(m, *toplevel_filename, *toplevel_lineno, + "malformed \"thunk\" statement"); } body_attributes((jl_array_t*)thk->code, &has_ccall, &has_defs, &has_loops, &has_opaque, &forced_compile); @@ -949,7 +959,9 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int JL_DLLEXPORT jl_value_t *jl_toplevel_eval(jl_module_t *m, jl_value_t *v) { - return jl_toplevel_eval_flex(m, v, 1, 0); + const char *filename = jl_filename; + int lieno = jl_lineno; + return jl_toplevel_eval_flex(m, v, 1, 0, &filename, &lieno); } // Check module `m` is open for `eval/include`, or throw an error. @@ -1049,7 +1061,8 @@ static jl_value_t *jl_parse_eval_all(jl_module_t *module, jl_value_t *text, size_t last_age = ct->world_age; int lineno = 0; jl_lineno = 0; - jl_filename = jl_string_data(filename); + const char *filename_str = jl_string_data(filename); + jl_filename = filename_str; int err = 0; JL_TRY { @@ -1064,7 +1077,7 @@ static jl_value_t *jl_parse_eval_all(jl_module_t *module, jl_value_t *text, expression = jl_expand_with_loc_warn(expression, module, jl_string_data(filename), lineno); ct->world_age = jl_atomic_load_acquire(&jl_world_counter); - result = jl_toplevel_eval_flex(module, expression, 1, 1); + result = jl_toplevel_eval_flex(module, expression, 1, 1, &filename_str, &lineno); } } JL_CATCH { diff --git a/test/backtrace.jl b/test/backtrace.jl index 50a50100488c43..aa10720316a5df 100644 --- a/test/backtrace.jl +++ b/test/backtrace.jl @@ -202,6 +202,15 @@ let trace = try end @test trace[1].func === Symbol("top-level scope") end +let trace = try + eval(Expr(:toplevel, LineNumberNode(3, :a_filename), Expr(:error, 1))) + catch + stacktrace(catch_backtrace()) + end + @test trace[1].func === Symbol("top-level scope") + @test trace[1].file === :a_filename + @test trace[1].line == 3 +end let trace = try include_string(@__MODULE__, """ From 3e37e175d3c2c18de6927db7a4f5ae1d446f6b23 Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 22 Mar 2024 14:39:21 +0100 Subject: [PATCH 017/123] also check that UUID of project is non-null when treating it as a package (#53789) Fixes https://github.com/JuliaLang/julia/issues/53788 --- base/precompilation.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/precompilation.jl b/base/precompilation.jl index 80648299b13fd8..4f9b53e1c1ae81 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -171,7 +171,7 @@ function ExplicitEnv(envpath::String=Base.active_project()) sizehint!(weakdeps_expanded, length(deps)) sizehint!(extensions_expanded, length(deps)) - if proj_name !== nothing + if proj_name !== nothing && proj_uuid !== nothing deps_expanded[proj_uuid] = filter!(!=(proj_uuid), collect(values(project_deps))) extensions_expanded[proj_uuid] = project_extensions path = get(project_d, "path", nothing) From 92918457e31e3696fff9fa3ea91aaa5e8159a23a Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Fri, 22 Mar 2024 09:40:53 -0400 Subject: [PATCH 018/123] precompilepkgs: simplify custom config printing if only one (#53805) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently it's a bit excessive in the `Pkg.test` precompile job ![Screenshot 2024-03-20 at 12 04 03โ€ฏPM](https://github.com/JuliaLang/julia/assets/1694067/7600f0b8-6e4b-43b2-9c42-c8d5d16b8d57) This PR ``` Precompiling project for configuration --code-coverage=none --color=yes --check-bounds=yes --warn-overwrite=yes --depwarn=yes --inline=yes --startup-file=no --track-allocation=none... 354.9 ms โœ“ RFFT 1 dependency successfully precompiled in 1 seconds. 38 already precompiled. ``` Pkg could also just set the non-default flags to minimize the list. --- base/precompilation.jl | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/base/precompilation.jl b/base/precompilation.jl index 4f9b53e1c1ae81..50b84ad829d0ac 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -551,11 +551,14 @@ function precompilepkgs(pkgs::Vector{String}=String[]; else target = "project" end - nconfig = length(configs) - if nconfig > 1 - target *= " for $nconfig compilation configurations..." - else + nconfigs = length(configs) + if nconfigs == 1 + if !isempty(only(configs)[1]) + target *= " for configuration $(join(only(configs)[1], " "))" + end target *= "..." + else + target *= " for $nconfigs compilation configurations..." end @debug "precompile: packages filtered" @@ -677,7 +680,7 @@ function precompilepkgs(pkgs::Vector{String}=String[]; loaded = warn_loaded && haskey(Base.loaded_modules, dep) _name = haskey(exts, dep) ? string(exts[dep], " โ†’ ", dep.name) : dep.name name = dep in direct_deps ? _name : string(color_string(_name, :light_black)) - if !isempty(config[1]) + if nconfigs > 1 && !isempty(config[1]) config_str = "$(join(config[1], " "))" name *= color_string(" $(config_str)", :light_black) end @@ -769,7 +772,7 @@ function precompilepkgs(pkgs::Vector{String}=String[]; _name = haskey(exts, pkg) ? string(exts[pkg], " โ†’ ", pkg.name) : pkg.name name = is_direct_dep ? _name : string(color_string(_name, :light_black)) - if !isempty(flags) + if nconfigs > 1 && !isempty(flags) config_str = "$(join(flags, " "))" name *= color_string(" $(config_str)", :light_black) end From d68a04ee9cc9f5479cf729b1bda17d950d4951ba Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Fri, 22 Mar 2024 12:10:24 -0400 Subject: [PATCH 019/123] Revert "small changes to make Base more statically compileable" (#53808) Reverts JuliaLang/julia#53778 which appears to have introduced a windows failure See https://github.com/JuliaLang/julia/pull/53778#issuecomment-2013100312 --- base/boot.jl | 2 +- base/compiler/utilities.jl | 2 ++ base/error.jl | 10 +++++----- base/errorshow.jl | 2 +- base/initdefs.jl | 4 ++-- base/iostream.jl | 13 +++++-------- base/libuv.jl | 6 +++--- base/loading.jl | 7 ++++--- base/reflection.jl | 2 -- base/show.jl | 2 +- base/threadingconstructs.jl | 2 +- stdlib/FileWatching/src/FileWatching.jl | 5 ----- stdlib/LinearAlgebra/src/blas.jl | 5 +++-- 13 files changed, 28 insertions(+), 34 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index a3c5c03bdf721e..fc00f571171c92 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -769,7 +769,7 @@ function is_top_bit_set(x::Union{Int8,UInt8}) end # n.b. This function exists for CUDA to overload to configure error behavior (see #48097) -throw_inexacterror(func::Symbol, to, val) = throw(InexactError(func, to, val)) +throw_inexacterror(args...) = throw(InexactError(args...)) function check_sign_bit(::Type{To}, x) where {To} @inline diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index 1e002f8dad5a6d..00c4c9d4e3ec4e 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -498,6 +498,8 @@ end # options # ########### +is_root_module(m::Module) = false + inlining_enabled() = (JLOptions().can_inline == 1) function coverage_enabled(m::Module) diff --git a/base/error.jl b/base/error.jl index 07782fce5f52ea..fc294b3cb3eb04 100644 --- a/base/error.jl +++ b/base/error.jl @@ -228,15 +228,15 @@ macro assert(ex, msgs...) msg = Main.Base.string(msg) else # string() might not be defined during bootstrap - msg = :(_assert_tostring($(Expr(:quote,msg)))) + msg = quote + msg = $(Expr(:quote,msg)) + isdefined(Main, :Base) ? Main.Base.string(msg) : + (Core.println(msg); "Error during bootstrap. See stdout.") + end end return :($(esc(ex)) ? $(nothing) : throw(AssertionError($msg))) end -# this may be overridden in contexts where `string(::Expr)` doesn't work -_assert_tostring(msg) = isdefined(Main, :Base) ? Main.Base.string(msg) : - (Core.println(msg); "Error during bootstrap. See stdout.") - struct ExponentialBackOff n::Int first_delay::Float64 diff --git a/base/errorshow.jl b/base/errorshow.jl index b06052433ffc43..abc8083f38266e 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -400,7 +400,7 @@ end #Show an error by directly calling jl_printf. #Useful in Base submodule __init__ functions where stderr isn't defined yet. -function showerror_nostdio(@nospecialize(err), msg::AbstractString) +function showerror_nostdio(err, msg::AbstractString) stderr_stream = ccall(:jl_stderr_stream, Ptr{Cvoid}, ()) ccall(:jl_printf, Cint, (Ptr{Cvoid},Cstring), stderr_stream, msg) ccall(:jl_printf, Cint, (Ptr{Cvoid},Cstring), stderr_stream, ":\n") diff --git a/base/initdefs.jl b/base/initdefs.jl index 2b2916fc804ade..56c2c0c5872728 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -9,7 +9,7 @@ A string containing the script name passed to Julia from the command line. Note script name remains unchanged from within included files. Alternatively see [`@__FILE__`](@ref). """ -global PROGRAM_FILE::String = "" +global PROGRAM_FILE = "" """ ARGS @@ -480,7 +480,7 @@ end ## hook for disabling threaded libraries ## -library_threading_enabled::Bool = true +library_threading_enabled = true const disable_library_threading_hooks = [] function at_disable_library_threading(f) diff --git a/base/iostream.jl b/base/iostream.jl index bea6612ebc220c..5d972945e00e0f 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -292,15 +292,12 @@ function open(fname::String; lock = true, if !lock s._dolock = false end - if ccall(:ios_file, Ptr{Cvoid}, - (Ptr{UInt8}, Cstring, Cint, Cint, Cint, Cint), - s.ios, fname, flags.read, flags.write, flags.create, flags.truncate) == C_NULL - systemerror("opening file \"$fname\"") - end + systemerror("opening file $(repr(fname))", + ccall(:ios_file, Ptr{Cvoid}, + (Ptr{UInt8}, Cstring, Cint, Cint, Cint, Cint), + s.ios, fname, flags.read, flags.write, flags.create, flags.truncate) == C_NULL) if flags.append - if ccall(:ios_seek_end, Int64, (Ptr{Cvoid},), s.ios) != 0 - systemerror("seeking to end of file \"$fname\"") - end + systemerror("seeking to end of file $fname", ccall(:ios_seek_end, Int64, (Ptr{Cvoid},), s.ios) != 0) end return s end diff --git a/base/libuv.jl b/base/libuv.jl index 35424ad3eda3ed..66dfcfb3414ad1 100644 --- a/base/libuv.jl +++ b/base/libuv.jl @@ -134,9 +134,9 @@ function uv_asynccb end function uv_timercb end function reinit_stdio() - global stdin = init_stdio(ccall(:jl_stdin_stream, Ptr{Cvoid}, ()))::IO - global stdout = init_stdio(ccall(:jl_stdout_stream, Ptr{Cvoid}, ()))::IO - global stderr = init_stdio(ccall(:jl_stderr_stream, Ptr{Cvoid}, ()))::IO + global stdin = init_stdio(ccall(:jl_stdin_stream, Ptr{Cvoid}, ())) + global stdout = init_stdio(ccall(:jl_stdout_stream, Ptr{Cvoid}, ())) + global stderr = init_stdio(ccall(:jl_stderr_stream, Ptr{Cvoid}, ())) opts = JLOptions() if opts.color != 0 have_color = (opts.color == 1) diff --git a/base/loading.jl b/base/loading.jl index 986efc1e1e5fbe..883e980b4000a2 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2205,6 +2205,7 @@ const explicit_loaded_modules = Dict{PkgId,Module}() const loaded_modules_order = Vector{Module}() const module_keys = IdDict{Module,PkgId}() # the reverse +is_root_module(m::Module) = @lock require_lock haskey(module_keys, m) root_module_key(m::Module) = @lock require_lock module_keys[m] @constprop :none function register_root_module(m::Module) @@ -3415,9 +3416,9 @@ function check_clone_targets(clone_targets) end # Set by FileWatching.__init__() -global mkpidlock_hook::Any -global trymkpidlock_hook::Any -global parse_pidfile_hook::Any +global mkpidlock_hook +global trymkpidlock_hook +global parse_pidfile_hook # The preferences hash is only known after precompilation so just assume no preferences. # Also ignore the active project, which means that if all other conditions are equal, diff --git a/base/reflection.jl b/base/reflection.jl index 63909b4159877b..b1d41b4d68621d 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -20,8 +20,6 @@ Base """ parentmodule(m::Module) = ccall(:jl_module_parent, Ref{Module}, (Any,), m) -is_root_module(m::Module) = parentmodule(m) === m || (isdefined(Main, :Base) && m === Main.Base) - """ moduleroot(m::Module) -> Module diff --git a/base/show.jl b/base/show.jl index 8f52fefdd71520..f7846e316c3301 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1056,7 +1056,7 @@ function show_type_name(io::IO, tn::Core.TypeName) # IOContext If :module is not set, default to Main (or current active module). # nothing can be used to force printing prefix from = get(io, :module, active_module()) - if isdefined(tn, :module) && (from === nothing || !isvisible(sym, tn.module, from::Module)) + if isdefined(tn, :module) && (from === nothing || !isvisible(sym, tn.module, from)) show(io, tn.module) print(io, ".") if globfunc && !is_id_start_char(first(string(sym))) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index acab7cf7b8299c..60aea04ddba645 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -79,7 +79,7 @@ function _sym_to_tpid(tp::Symbol) elseif tp == :foreign return Int8(-1) else - throw(ArgumentError("Unrecognized threadpool name `$tp`")) + throw(ArgumentError("Unrecognized threadpool name `$(repr(tp))`")) end end diff --git a/stdlib/FileWatching/src/FileWatching.jl b/stdlib/FileWatching/src/FileWatching.jl index 0c987ad01c828e..0ee572ec47d92c 100644 --- a/stdlib/FileWatching/src/FileWatching.jl +++ b/stdlib/FileWatching/src/FileWatching.jl @@ -468,11 +468,6 @@ function uv_fspollcb(handle::Ptr{Cvoid}, status::Int32, prev::Ptr, curr::Ptr) nothing end -global uv_jl_pollcb::Ptr{Cvoid} -global uv_jl_fspollcb::Ptr{Cvoid} -global uv_jl_fseventscb_file::Ptr{Cvoid} -global uv_jl_fseventscb_folder::Ptr{Cvoid} - function __init__() global uv_jl_pollcb = @cfunction(uv_pollcb, Cvoid, (Ptr{Cvoid}, Cint, Cint)) global uv_jl_fspollcb = @cfunction(uv_fspollcb, Cvoid, (Ptr{Cvoid}, Cint, Ptr{Cvoid}, Ptr{Cvoid})) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 413b7866c54448..8903aaddcc11bc 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -159,8 +159,9 @@ function check() interface = USE_BLAS64 ? :ilp64 : :lp64 if !any(lib.interface == interface for lib in config.loaded_libs) interfacestr = uppercase(string(interface)) - @error("No loaded BLAS libraries were built with $interfacestr support.") - exit(1) + @error("No loaded BLAS libraries were built with $(interfacestr) support") + println("Quitting.") + exit() end end From 5ed51d33c50f665200e562fe0cfb8ff70e566d59 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Fri, 22 Mar 2024 23:31:30 -0400 Subject: [PATCH 020/123] Bump libuv (#53822) Fixes https://github.com/JuliaDebug/Cthulhu.jl/issues/541 by picking up https://github.com/libuv/libuv/commit/3ecce914105590e6112cd0c6d4f6b30ac6a6c24f. --- deps/checksums/libuv | 68 +++++++++++++++++------------------ deps/libuv.version | 2 +- stdlib/LibUV_jll/Project.toml | 2 +- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/deps/checksums/libuv b/deps/checksums/libuv index 7ac93952b8b34c..41a9a5bdf97222 100644 --- a/deps/checksums/libuv +++ b/deps/checksums/libuv @@ -1,34 +1,34 @@ -LibUV.v2.0.1+15.aarch64-apple-darwin.tar.gz/md5/f12ee08b8d5721bd88b651ac573c59ed -LibUV.v2.0.1+15.aarch64-apple-darwin.tar.gz/sha512/b3c53e04624d9c60e664db2eaaf3add696f95c52e55db0c577547f7bf7e045ce30cffa0e38c3451f483dcdb7ddcac1b7f43b694dfadb37282773ce416af1030a -LibUV.v2.0.1+15.aarch64-linux-gnu.tar.gz/md5/8cb9f4d6c6a4013fa9ed9ae120058275 -LibUV.v2.0.1+15.aarch64-linux-gnu.tar.gz/sha512/d4213ee47ebdcab4cc4719478608ffa461a5543a16656c2881587364c8ed1b39a2f418d5c3c6a04d7e6dd3df349f0afa72cd1df0e06db6146512356b37637024 -LibUV.v2.0.1+15.aarch64-linux-musl.tar.gz/md5/e23a0d7162fc3f09f0ea92d24cba3f4d -LibUV.v2.0.1+15.aarch64-linux-musl.tar.gz/sha512/f4a13eee72575092ab673777a53d43ce999a7a8bf847daa0a86b39bbfd3f6c1575f105a0bb629766268921ff94f10d354a0e53d32623f6ad35fca44e7bac25f8 -LibUV.v2.0.1+15.armv6l-linux-gnueabihf.tar.gz/md5/70ed0616cd3737a357b7571ab648d239 -LibUV.v2.0.1+15.armv6l-linux-gnueabihf.tar.gz/sha512/25a4b8a90b7bb62e31c1c2bb1d7e137050de26f311daa9f77be932ab3d9a2b92c82ce82ed37cc74a2b1cd5a60bd0dc412e92d31013d36ad35af2d4f376fbc0b0 -LibUV.v2.0.1+15.armv6l-linux-musleabihf.tar.gz/md5/e4320c51c8904a59c105f7b63d086c79 -LibUV.v2.0.1+15.armv6l-linux-musleabihf.tar.gz/sha512/bbc39d800277a66298c56849c1131a6f1958a2c8b2465b59527965a1bd3f36a4c87c1d7ad4be59ec0f4ca8f94ec1804a619eb963d956b77e645e0e00effc6613 -LibUV.v2.0.1+15.armv7l-linux-gnueabihf.tar.gz/md5/d5436552dc177fc3fd0cf4f575cc03b4 -LibUV.v2.0.1+15.armv7l-linux-gnueabihf.tar.gz/sha512/8d3722290151ecf65f4e3fe3440828492a7b115810b87c8711c5592f4dea69727e516228a5a1bdac430c74b288f12de390daf0a9408274aa27cdd69efc81cfee -LibUV.v2.0.1+15.armv7l-linux-musleabihf.tar.gz/md5/67e1ba03ddf2d2bdd79fef25a5976350 -LibUV.v2.0.1+15.armv7l-linux-musleabihf.tar.gz/sha512/535565657b5714da0db5c622b65b261a77f21f407b1166eee99f35ba3bb9c6fab4c7d1f3db70528767cef7c66c856c5101b01423be05efb9219ec4c76df0be6a -LibUV.v2.0.1+15.i686-linux-gnu.tar.gz/md5/ba1432ecd75e6a43ff197d51ba76446c -LibUV.v2.0.1+15.i686-linux-gnu.tar.gz/sha512/dc8940284d4ba05098037fcf4b3bada199878794ef34ad09d8992ef58e4c829b00a3fcca29c4f65b49edcab4274092232ff5d7619b3535333125043f89503cfc -LibUV.v2.0.1+15.i686-linux-musl.tar.gz/md5/237080cf5d1286a3d2f35d134a285d28 -LibUV.v2.0.1+15.i686-linux-musl.tar.gz/sha512/834f16a16cf6b765dfd094037c8a45ccdedc2eb9e45f527c6721eb0f60f4e56dc4f9b90a2a35e3ed10da4a937d8555e97034e0a29d733cac5352061ebe286799 -LibUV.v2.0.1+15.i686-w64-mingw32.tar.gz/md5/8a5261a6ce4200d272b5eda4fe9ecb31 -LibUV.v2.0.1+15.i686-w64-mingw32.tar.gz/sha512/b372b9368a9ac92775a8d6ee39b492905dc5f58f16d7edf792e0c2ffbd4507ede79139a24fe852dfa26068d0f076a4abf3c3b868a8a057b23fdbad80999d315f -LibUV.v2.0.1+15.powerpc64le-linux-gnu.tar.gz/md5/53db7b763af204477ce8f0bfae0ce15c -LibUV.v2.0.1+15.powerpc64le-linux-gnu.tar.gz/sha512/bbfe2518d4dc84fe73b7d3f3bcaf5aeef0db0d284c0e205e3e3670b8ce6f3ea593a0e52d125fd9a79cd098dba0d35f151cb46469fa25dfeef62ebcc966f94d4f -LibUV.v2.0.1+15.x86_64-apple-darwin.tar.gz/md5/b4699192c098564edc5589e90c47324e -LibUV.v2.0.1+15.x86_64-apple-darwin.tar.gz/sha512/2505e4060712143d3213747d4276c0b99dec78579d2ab0b71c5d7edf15ae80e0178138a11470c976d97de14e44b153dcb00c08c864523d7ee0ead8e48cf15d14 -LibUV.v2.0.1+15.x86_64-linux-gnu.tar.gz/md5/f5515c50106a0748b9a1986c912a00f3 -LibUV.v2.0.1+15.x86_64-linux-gnu.tar.gz/sha512/5822396039e14a5d919f2612559a8d62a925c4319e66eb05ed20faed754318762f5653851684701cd4ddb1edf10bfe25d252c3d9cd84228e498e825ba61146b1 -LibUV.v2.0.1+15.x86_64-linux-musl.tar.gz/md5/1962e6f21080e874d2ca0275c5b569b2 -LibUV.v2.0.1+15.x86_64-linux-musl.tar.gz/sha512/4702e13633d77a6c0aeb1e7cd252471a779177e20c68485130f420cc4878c8f7de7f0f51730008ba9dc0f275875a5947629d39aff200691e26f31d42e388d53d -LibUV.v2.0.1+15.x86_64-unknown-freebsd.tar.gz/md5/928a789c3cd3b4cefcc1cf13f5f179ac -LibUV.v2.0.1+15.x86_64-unknown-freebsd.tar.gz/sha512/ee58667b19fdf7ec0218b4645b3f5bed2e9fc01cc29eab8473ee02aaa044f94a48eb220c6427200aaf56eacf52d0f72156712d17017cfecbc25d3c1b71a4bd2f -LibUV.v2.0.1+15.x86_64-w64-mingw32.tar.gz/md5/d3b84729ee9d5a6e6a1e29357e25cced -LibUV.v2.0.1+15.x86_64-w64-mingw32.tar.gz/sha512/43ca5999d8e8ff820722b1a548bd4e277e95c739c3363ed6159d080dd06842316f5370e8e4f4a886bf76010f4aed2bbf01f6091845b0e84b75f709277c561649 -libuv-afa1c67fa496eb49ade1e520f76fd018a1409eaa.tar.gz/md5/3863ccd5a51f85cf76679070c99be6cd -libuv-afa1c67fa496eb49ade1e520f76fd018a1409eaa.tar.gz/sha512/bf4c705e05e730139b62de799331653eea2767898d654b8890ca2623db3adb9a1efcfcfab38af22e8ac44c67a9c5c018f1f7847a3703bee5f05657169a67d817 +LibUV.v2.0.1+16.aarch64-apple-darwin.tar.gz/md5/132266a501144f34eb9b8d5199db43c0 +LibUV.v2.0.1+16.aarch64-apple-darwin.tar.gz/sha512/e466ba8a2fe916f0e2dccb1d1075a6a20fcc5d5068d2375c940353a63522332fa8f665461adbb47ad4d30dabaea011b8e72a603601da29a071d98c7d7d130f46 +LibUV.v2.0.1+16.aarch64-linux-gnu.tar.gz/md5/1ae3018d9ab8bb293dbf6277c2c209cc +LibUV.v2.0.1+16.aarch64-linux-gnu.tar.gz/sha512/6e56876cdf0fdad1aade6435edf980b286438ee9fa695fa4e262b47f7ada6ff69535c59d216daee3eb1d061a90c2c16fd70d21438776c54addda93cf275ef1be +LibUV.v2.0.1+16.aarch64-linux-musl.tar.gz/md5/08243e727c7e957f5972a200b5d89113 +LibUV.v2.0.1+16.aarch64-linux-musl.tar.gz/sha512/4a684f248704b16b882d66ed7af60e2217a0b98f476bfdd1cb545d3e2adb17f6a410bf09e270c1e2623e550b36639c9282a562ab415850dfea98736ec03fd000 +LibUV.v2.0.1+16.armv6l-linux-gnueabihf.tar.gz/md5/c4dfccf5a899782715cbb0ca0197938c +LibUV.v2.0.1+16.armv6l-linux-gnueabihf.tar.gz/sha512/ecdcd655865a532187e4e98cb21ca68e62303813cad585de83382aa226d965213f24fe7a684e1189fad11b0e5f2f4b318c122f557a6117f61bb2948b51e16a76 +LibUV.v2.0.1+16.armv6l-linux-musleabihf.tar.gz/md5/5382dae963f3003aefdb119377a45e82 +LibUV.v2.0.1+16.armv6l-linux-musleabihf.tar.gz/sha512/f901c2965e8f9ca52900180c32cdb70d8adc13f12f076c1b109d57b749cac1ecaac3c72e22531e6fcb79c8f2c7cf952ff563779d3764b015b73db079f2b171cb +LibUV.v2.0.1+16.armv7l-linux-gnueabihf.tar.gz/md5/9c4cd82249c03ebeac670e2c7c8c1078 +LibUV.v2.0.1+16.armv7l-linux-gnueabihf.tar.gz/sha512/ee4b7f866e3f63df303d00d48d36680c490570979bb7174c12cfcf9efaf48ea7ae90aa05b41da8ab686de93c910c5a761f31da22845ad48fd980e9c16437cbfb +LibUV.v2.0.1+16.armv7l-linux-musleabihf.tar.gz/md5/5255d7e320ef37eb63d0e85c4b86d20d +LibUV.v2.0.1+16.armv7l-linux-musleabihf.tar.gz/sha512/5bcd3d22b1e2398879e654bb550fd093891775c64cb48bd179c4f9ff8dcbff23eda91a66ea14852ef5945d5c114732957075e3b3fded4cbd3cca559fead842db +LibUV.v2.0.1+16.i686-linux-gnu.tar.gz/md5/7f0fc52beb13dad773c6ab54deee7a62 +LibUV.v2.0.1+16.i686-linux-gnu.tar.gz/sha512/cb1736eab4fa1be89018b3c77c3551a99d0fa761ad2f1947587c215d87d963d43198ce87574b6eb9d1fb8a93abf1ae89e74fb8a3f3fb9c4fd08a49e04b4335f4 +LibUV.v2.0.1+16.i686-linux-musl.tar.gz/md5/ed22ccd7eaa09ed9c71afc0c6affa423 +LibUV.v2.0.1+16.i686-linux-musl.tar.gz/sha512/7f3ff061c3d7d0c3c0c0be3e4052aeed39f35e1ba0b92f3ee3d9f266f26d064acc153c08054a22d090167f00fef3c27ec54e836de35f348e4849baab301f7fa4 +LibUV.v2.0.1+16.i686-w64-mingw32.tar.gz/md5/7f1fe93df0b741ca30c4fb64ff9ac9bd +LibUV.v2.0.1+16.i686-w64-mingw32.tar.gz/sha512/9d71722c538d8232d8510fa2a43e7a52271b078401dfa838de9eedcfc34a2483aa3b1c221b17c41353b54554fe76d86b4973c5261b288228a91f0cc92820ad93 +LibUV.v2.0.1+16.powerpc64le-linux-gnu.tar.gz/md5/b796de6c75f18f318823e3e1cdd316c8 +LibUV.v2.0.1+16.powerpc64le-linux-gnu.tar.gz/sha512/f8dbb98cb49edfa06a0b48fbe1e658ca5a9bca13fe33d21872a012deaa1052a495faf74f90c0dfa48378b9f4f51f1045e01e563aec427d8c89d50e4eef0e4938 +LibUV.v2.0.1+16.x86_64-apple-darwin.tar.gz/md5/f2d55b315fa1f77b632a461530bb6b3b +LibUV.v2.0.1+16.x86_64-apple-darwin.tar.gz/sha512/eb40a193c3bca5e822a417879e854877b353a2a04b03a721ef4125360f1189a3685d2751e2f975360a2ad4c37e6043485a54b5349b3da423b8aae73d4a095d04 +LibUV.v2.0.1+16.x86_64-linux-gnu.tar.gz/md5/a573ded4f78f8677ef73594be9629638 +LibUV.v2.0.1+16.x86_64-linux-gnu.tar.gz/sha512/c5809635be3ab5dc53c37a028e58695d89ea91eee850af22a0e8db10ea021640f1e618a553848332ee6df66eecd08d34605e335aad46ece82365a3525b69c42f +LibUV.v2.0.1+16.x86_64-linux-musl.tar.gz/md5/5bdad561b5db7d19f198ef090ae3ec84 +LibUV.v2.0.1+16.x86_64-linux-musl.tar.gz/sha512/6662c8226f22f79f8c40857a5a531841f013031dd2e9536568498bfd536f133976ff71d0cc5f56f1e0c0b7f2403a35c2ccef9117d9e0d7819771bd492194f20d +LibUV.v2.0.1+16.x86_64-unknown-freebsd.tar.gz/md5/f4ad9e445e4b14e2b59b2b77c9ed72ad +LibUV.v2.0.1+16.x86_64-unknown-freebsd.tar.gz/sha512/a78deac6d8321f274a229961620da4d069ff2accf7d1ed9edfb01c21ad47eb33d364ba2f310ff4a93b2732dcd16f6d481843dbcb273770d731fd528f9c7a9ddc +LibUV.v2.0.1+16.x86_64-w64-mingw32.tar.gz/md5/72caa067cf24e304955405dcb4de195a +LibUV.v2.0.1+16.x86_64-w64-mingw32.tar.gz/sha512/de80ca98d199d3c5626ebc771325806ce3aae5927220201c2351207c10ff67791d2865f76e41519df88f0be3da534342965e7ba0d055d807c4b2b6c78bd2427d +libuv-ca3a5a431a1c37859b6508e6b2a288092337029a.tar.gz/md5/d1fbca8bcc5819037b8b81ae4f61c357 +libuv-ca3a5a431a1c37859b6508e6b2a288092337029a.tar.gz/sha512/e735861923c0fc597b53eb2efb56b26acec29e3fcae7e76d349fc08f8b9d340df9ac60a1cd245e46a434aa357ed8e377734c1c97bf08bd044c9ba0c02b082a6a diff --git a/deps/libuv.version b/deps/libuv.version index 9ae54aa7be91a7..bc8e2e57c95179 100644 --- a/deps/libuv.version +++ b/deps/libuv.version @@ -4,4 +4,4 @@ LIBUV_JLL_NAME := LibUV ## source build LIBUV_VER := 2 LIBUV_BRANCH=julia-uv2-1.48.0 -LIBUV_SHA1=afa1c67fa496eb49ade1e520f76fd018a1409eaa +LIBUV_SHA1=ca3a5a431a1c37859b6508e6b2a288092337029a diff --git a/stdlib/LibUV_jll/Project.toml b/stdlib/LibUV_jll/Project.toml index 8089516c1df148..7c61fdf89df702 100644 --- a/stdlib/LibUV_jll/Project.toml +++ b/stdlib/LibUV_jll/Project.toml @@ -1,6 +1,6 @@ name = "LibUV_jll" uuid = "183b4373-6708-53ba-ad28-60e28bb38547" -version = "2.0.1+15" +version = "2.0.1+16" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" From 61720208c95daae5922f5d2e655651a4e614a239 Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Sat, 23 Mar 2024 00:23:21 -0400 Subject: [PATCH 021/123] reland "small changes to make Base more statically compileable (#53778)" (#53820) This makes it easier to fully-statically-type Base and init methods. The changes are from gb/small-image2. --- base/boot.jl | 2 +- base/compiler/utilities.jl | 2 -- base/error.jl | 10 +++++----- base/errorshow.jl | 2 +- base/initdefs.jl | 4 ++-- base/iostream.jl | 13 ++++++++----- base/libuv.jl | 6 +++--- base/loading.jl | 7 +++---- base/reflection.jl | 2 ++ base/show.jl | 2 +- base/threadingconstructs.jl | 2 +- stdlib/FileWatching/src/FileWatching.jl | 5 +++++ stdlib/LinearAlgebra/src/blas.jl | 5 ++--- 13 files changed, 34 insertions(+), 28 deletions(-) diff --git a/base/boot.jl b/base/boot.jl index fc00f571171c92..a3c5c03bdf721e 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -769,7 +769,7 @@ function is_top_bit_set(x::Union{Int8,UInt8}) end # n.b. This function exists for CUDA to overload to configure error behavior (see #48097) -throw_inexacterror(args...) = throw(InexactError(args...)) +throw_inexacterror(func::Symbol, to, val) = throw(InexactError(func, to, val)) function check_sign_bit(::Type{To}, x) where {To} @inline diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index 00c4c9d4e3ec4e..1e002f8dad5a6d 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -498,8 +498,6 @@ end # options # ########### -is_root_module(m::Module) = false - inlining_enabled() = (JLOptions().can_inline == 1) function coverage_enabled(m::Module) diff --git a/base/error.jl b/base/error.jl index fc294b3cb3eb04..07782fce5f52ea 100644 --- a/base/error.jl +++ b/base/error.jl @@ -228,15 +228,15 @@ macro assert(ex, msgs...) msg = Main.Base.string(msg) else # string() might not be defined during bootstrap - msg = quote - msg = $(Expr(:quote,msg)) - isdefined(Main, :Base) ? Main.Base.string(msg) : - (Core.println(msg); "Error during bootstrap. See stdout.") - end + msg = :(_assert_tostring($(Expr(:quote,msg)))) end return :($(esc(ex)) ? $(nothing) : throw(AssertionError($msg))) end +# this may be overridden in contexts where `string(::Expr)` doesn't work +_assert_tostring(msg) = isdefined(Main, :Base) ? Main.Base.string(msg) : + (Core.println(msg); "Error during bootstrap. See stdout.") + struct ExponentialBackOff n::Int first_delay::Float64 diff --git a/base/errorshow.jl b/base/errorshow.jl index abc8083f38266e..b06052433ffc43 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -400,7 +400,7 @@ end #Show an error by directly calling jl_printf. #Useful in Base submodule __init__ functions where stderr isn't defined yet. -function showerror_nostdio(err, msg::AbstractString) +function showerror_nostdio(@nospecialize(err), msg::AbstractString) stderr_stream = ccall(:jl_stderr_stream, Ptr{Cvoid}, ()) ccall(:jl_printf, Cint, (Ptr{Cvoid},Cstring), stderr_stream, msg) ccall(:jl_printf, Cint, (Ptr{Cvoid},Cstring), stderr_stream, ":\n") diff --git a/base/initdefs.jl b/base/initdefs.jl index 56c2c0c5872728..2b2916fc804ade 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -9,7 +9,7 @@ A string containing the script name passed to Julia from the command line. Note script name remains unchanged from within included files. Alternatively see [`@__FILE__`](@ref). """ -global PROGRAM_FILE = "" +global PROGRAM_FILE::String = "" """ ARGS @@ -480,7 +480,7 @@ end ## hook for disabling threaded libraries ## -library_threading_enabled = true +library_threading_enabled::Bool = true const disable_library_threading_hooks = [] function at_disable_library_threading(f) diff --git a/base/iostream.jl b/base/iostream.jl index 5d972945e00e0f..0ee51b9b98efd7 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -292,12 +292,15 @@ function open(fname::String; lock = true, if !lock s._dolock = false end - systemerror("opening file $(repr(fname))", - ccall(:ios_file, Ptr{Cvoid}, - (Ptr{UInt8}, Cstring, Cint, Cint, Cint, Cint), - s.ios, fname, flags.read, flags.write, flags.create, flags.truncate) == C_NULL) + if ccall(:ios_file, Ptr{Cvoid}, + (Ptr{UInt8}, Cstring, Cint, Cint, Cint, Cint), + s.ios, fname, flags.read, flags.write, flags.create, flags.truncate) == C_NULL + systemerror("opening file $(repr(fname))") + end if flags.append - systemerror("seeking to end of file $fname", ccall(:ios_seek_end, Int64, (Ptr{Cvoid},), s.ios) != 0) + if ccall(:ios_seek_end, Int64, (Ptr{Cvoid},), s.ios) != 0 + systemerror("seeking to end of file $fname") + end end return s end diff --git a/base/libuv.jl b/base/libuv.jl index 66dfcfb3414ad1..35424ad3eda3ed 100644 --- a/base/libuv.jl +++ b/base/libuv.jl @@ -134,9 +134,9 @@ function uv_asynccb end function uv_timercb end function reinit_stdio() - global stdin = init_stdio(ccall(:jl_stdin_stream, Ptr{Cvoid}, ())) - global stdout = init_stdio(ccall(:jl_stdout_stream, Ptr{Cvoid}, ())) - global stderr = init_stdio(ccall(:jl_stderr_stream, Ptr{Cvoid}, ())) + global stdin = init_stdio(ccall(:jl_stdin_stream, Ptr{Cvoid}, ()))::IO + global stdout = init_stdio(ccall(:jl_stdout_stream, Ptr{Cvoid}, ()))::IO + global stderr = init_stdio(ccall(:jl_stderr_stream, Ptr{Cvoid}, ()))::IO opts = JLOptions() if opts.color != 0 have_color = (opts.color == 1) diff --git a/base/loading.jl b/base/loading.jl index 883e980b4000a2..986efc1e1e5fbe 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2205,7 +2205,6 @@ const explicit_loaded_modules = Dict{PkgId,Module}() const loaded_modules_order = Vector{Module}() const module_keys = IdDict{Module,PkgId}() # the reverse -is_root_module(m::Module) = @lock require_lock haskey(module_keys, m) root_module_key(m::Module) = @lock require_lock module_keys[m] @constprop :none function register_root_module(m::Module) @@ -3416,9 +3415,9 @@ function check_clone_targets(clone_targets) end # Set by FileWatching.__init__() -global mkpidlock_hook -global trymkpidlock_hook -global parse_pidfile_hook +global mkpidlock_hook::Any +global trymkpidlock_hook::Any +global parse_pidfile_hook::Any # The preferences hash is only known after precompilation so just assume no preferences. # Also ignore the active project, which means that if all other conditions are equal, diff --git a/base/reflection.jl b/base/reflection.jl index b1d41b4d68621d..63909b4159877b 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -20,6 +20,8 @@ Base """ parentmodule(m::Module) = ccall(:jl_module_parent, Ref{Module}, (Any,), m) +is_root_module(m::Module) = parentmodule(m) === m || (isdefined(Main, :Base) && m === Main.Base) + """ moduleroot(m::Module) -> Module diff --git a/base/show.jl b/base/show.jl index f7846e316c3301..8f52fefdd71520 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1056,7 +1056,7 @@ function show_type_name(io::IO, tn::Core.TypeName) # IOContext If :module is not set, default to Main (or current active module). # nothing can be used to force printing prefix from = get(io, :module, active_module()) - if isdefined(tn, :module) && (from === nothing || !isvisible(sym, tn.module, from)) + if isdefined(tn, :module) && (from === nothing || !isvisible(sym, tn.module, from::Module)) show(io, tn.module) print(io, ".") if globfunc && !is_id_start_char(first(string(sym))) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 60aea04ddba645..acab7cf7b8299c 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -79,7 +79,7 @@ function _sym_to_tpid(tp::Symbol) elseif tp == :foreign return Int8(-1) else - throw(ArgumentError("Unrecognized threadpool name `$(repr(tp))`")) + throw(ArgumentError("Unrecognized threadpool name `$tp`")) end end diff --git a/stdlib/FileWatching/src/FileWatching.jl b/stdlib/FileWatching/src/FileWatching.jl index 0ee572ec47d92c..0c987ad01c828e 100644 --- a/stdlib/FileWatching/src/FileWatching.jl +++ b/stdlib/FileWatching/src/FileWatching.jl @@ -468,6 +468,11 @@ function uv_fspollcb(handle::Ptr{Cvoid}, status::Int32, prev::Ptr, curr::Ptr) nothing end +global uv_jl_pollcb::Ptr{Cvoid} +global uv_jl_fspollcb::Ptr{Cvoid} +global uv_jl_fseventscb_file::Ptr{Cvoid} +global uv_jl_fseventscb_folder::Ptr{Cvoid} + function __init__() global uv_jl_pollcb = @cfunction(uv_pollcb, Cvoid, (Ptr{Cvoid}, Cint, Cint)) global uv_jl_fspollcb = @cfunction(uv_fspollcb, Cvoid, (Ptr{Cvoid}, Cint, Ptr{Cvoid}, Ptr{Cvoid})) diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 8903aaddcc11bc..413b7866c54448 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -159,9 +159,8 @@ function check() interface = USE_BLAS64 ? :ilp64 : :lp64 if !any(lib.interface == interface for lib in config.loaded_libs) interfacestr = uppercase(string(interface)) - @error("No loaded BLAS libraries were built with $(interfacestr) support") - println("Quitting.") - exit() + @error("No loaded BLAS libraries were built with $interfacestr support.") + exit(1) end end From 63e365feb8692b9d7cb5298954c26ab7af268171 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 23 Mar 2024 01:18:55 -0400 Subject: [PATCH 022/123] REPL: Expand macros before looking for `using` statements (#53821) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, in order to give the nice prompt for missing packages, we look for any `using`/`import` statements in the AST before evaluation. However, this misses any `using` statements introduced by macros: ``` julia> using Pkg julia> using BenchmarkTools โ”‚ Package BenchmarkTools not found, but a package named BenchmarkTools is โ”‚ available from a registry. โ”‚ Install package? โ”‚ (@v1.11) pkg> add BenchmarkTools โ”” (y/n/o) [y]: n ERROR: ArgumentError: Package BenchmarkTools not found in current path. - Run `import Pkg; Pkg.add("BenchmarkTools")` to install the BenchmarkTools package. Stacktrace: [1] macro expansion @ Base ./loading.jl:1781 [inlined] [2] macro expansion @ Base ./lock.jl:267 [inlined] [3] __require(into::Module, mod::Symbol) @ Base ./loading.jl:1762 [4] #invoke_in_world#3 @ Base ./essentials.jl:963 [inlined] [5] invoke_in_world @ Base ./essentials.jl:960 [inlined] [6] require(into::Module, mod::Symbol) @ Base ./loading.jl:1755 julia> macro foo() :(using BenchmarkTools) end @foo (macro with 1 method) julia> @foo ERROR: ArgumentError: Package BenchmarkTools not found in current path. - Run `import Pkg; Pkg.add("BenchmarkTools")` to install the BenchmarkTools package. Stacktrace: [1] macro expansion @ Base ./loading.jl:1781 [inlined] [2] macro expansion @ Base ./lock.jl:267 [inlined] [3] __require(into::Module, mod::Symbol) @ Base ./loading.jl:1762 [4] #invoke_in_world#3 @ Base ./essentials.jl:963 [inlined] [5] invoke_in_world @ Base ./essentials.jl:960 [inlined] [6] require(into::Module, mod::Symbol) @ Base ./loading.jl:1755 [7] top-level scope @ REPL[4]:1 ``` Generally, it doesn't matter, but embedded DSLs may want to do this kind of thing, so we might as well try to support it. --- base/client.jl | 2 +- stdlib/REPL/src/REPL.jl | 46 ++++++++++++++++++++++++++++++++++------ stdlib/REPL/test/repl.jl | 29 +++++++++++++++++++++++++ test/precompile.jl | 2 +- 4 files changed, 70 insertions(+), 9 deletions(-) diff --git a/base/client.jl b/base/client.jl index 087efe3d3b99c6..3ca2d547452907 100644 --- a/base/client.jl +++ b/base/client.jl @@ -95,7 +95,7 @@ function scrub_repl_backtrace(bt) if bt !== nothing && !(bt isa Vector{Any}) # ignore our sentinel value types bt = bt isa Vector{StackFrame} ? copy(bt) : stacktrace(bt) # remove REPL-related frames from interactive printing - eval_ind = findlast(frame -> !frame.from_c && frame.func === :eval, bt) + eval_ind = findlast(frame -> !frame.from_c && startswith(String(frame.func), "__repl_entry"), bt) eval_ind === nothing || deleteat!(bt, eval_ind:length(bt)) end return bt diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 0c88c84b3cbc2f..789def3d317bf5 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -212,6 +212,27 @@ const repl_ast_transforms = Any[softscope] # defaults for new REPL backends # to e.g. install packages on demand const install_packages_hooks = Any[] +# N.B.: Any functions starting with __repl_entry cut off backtraces when printing in the REPL. +# We need to do this for both the actual eval and macroexpand, since the latter can cause custom macro +# code to run (and error). +__repl_entry_lower_with_loc(mod::Module, @nospecialize(ast), toplevel_file::Ref{Ptr{UInt8}}, toplevel_line::Ref{Cint}) = + ccall(:jl_expand_with_loc, Any, (Any, Any, Ptr{UInt8}, Cint), ast, mod, toplevel_file[], toplevel_line[]) +__repl_entry_eval_expanded_with_loc(mod::Module, @nospecialize(ast), toplevel_file::Ref{Ptr{UInt8}}, toplevel_line::Ref{Cint}) = + ccall(:jl_toplevel_eval_flex, Any, (Any, Any, Cint, Cint, Ptr{Ptr{UInt8}}, Ptr{Cint}), mod, ast, 1, 1, toplevel_file, toplevel_line) + +function toplevel_eval_with_hooks(mod::Module, @nospecialize(ast), toplevel_file=Ref{Ptr{UInt8}}(Base.unsafe_convert(Ptr{UInt8}, :REPL)), toplevel_line=Ref{Cint}(1)) + if !isexpr(ast, :toplevel) + ast = __repl_entry_lower_with_loc(mod, ast, toplevel_file, toplevel_line) + check_for_missing_packages_and_run_hooks(ast) + return __repl_entry_eval_expanded_with_loc(mod, ast, toplevel_file, toplevel_line) + end + local value=nothing + for i = 1:length(ast.args) + value = toplevel_eval_with_hooks(mod, ast.args[i], toplevel_file, toplevel_line) + end + return value +end + function eval_user_input(@nospecialize(ast), backend::REPLBackend, mod::Module) lasterr = nothing Base.sigatomic_begin() @@ -222,11 +243,10 @@ function eval_user_input(@nospecialize(ast), backend::REPLBackend, mod::Module) put!(backend.response_channel, Pair{Any, Bool}(lasterr, true)) else backend.in_eval = true - check_for_missing_packages_and_run_hooks(ast) for xf in backend.ast_transforms ast = Base.invokelatest(xf, ast) end - value = Core.eval(mod, ast) + value = toplevel_eval_with_hooks(mod, ast) backend.in_eval = false setglobal!(Base.MainInclude, :ans, value) put!(backend.response_channel, Pair{Any, Bool}(value, false)) @@ -256,7 +276,7 @@ function check_for_missing_packages_and_run_hooks(ast) end end -function modules_to_be_loaded(ast::Expr, mods::Vector{Symbol} = Symbol[]) +function _modules_to_be_loaded!(ast::Expr, mods::Vector{Symbol}) ast.head === :quote && return mods # don't search if it's not going to be run during this eval if ast.head === :using || ast.head === :import for arg in ast.args @@ -271,12 +291,24 @@ function modules_to_be_loaded(ast::Expr, mods::Vector{Symbol} = Symbol[]) end end end - for arg in ast.args - if isexpr(arg, (:block, :if, :using, :import)) - modules_to_be_loaded(arg, mods) + if ast.head !== :thunk + for arg in ast.args + if isexpr(arg, (:block, :if, :using, :import)) + _modules_to_be_loaded!(arg, mods) + end + end + else + code = ast.args[1] + for arg in code.code + isa(arg, Expr) || continue + _modules_to_be_loaded!(arg, mods) end end - filter!(mod -> !in(String(mod), ["Base", "Main", "Core"]), mods) # Exclude special non-package modules +end + +function modules_to_be_loaded(ast::Expr, mods::Vector{Symbol} = Symbol[]) + _modules_to_be_loaded!(ast, mods) + filter!(mod::Symbol -> !in(mod, (:Base, :Main, :Core)), mods) # Exclude special non-package modules return unique(mods) end diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 12f3f8956122e0..1d0caab7d0e573 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -1480,6 +1480,35 @@ end end end +# Test that the REPL can find `using` statements inside macro expansions +global packages_requested = Any[] +old_hooks = copy(REPL.install_packages_hooks) +empty!(REPL.install_packages_hooks) +push!(REPL.install_packages_hooks, function(pkgs) + append!(packages_requested, pkgs) +end) + +fake_repl() do stdin_write, stdout_read, repl + repltask = @async begin + REPL.run_repl(repl) + end + + # Just consume all the output - we only test that the callback ran + read_resp_task = @async while !eof(stdout_read) + readavailable(stdout_read) + end + + write(stdin_write, "macro usingfoo(); :(using FooNotFound); end\n") + write(stdin_write, "@usingfoo\n") + write(stdin_write, "\x4") + Base.wait(repltask) + close(stdin_write) + close(stdout_read) + Base.wait(read_resp_task) +end +@test packages_requested == Any[:FooNotFound] +empty!(REPL.install_packages_hooks); append!(REPL.install_packages_hooks, old_hooks) + # err should reprint error if deeper than top-level fake_repl() do stdin_write, stdout_read, repl repltask = @async begin diff --git a/test/precompile.jl b/test/precompile.jl index 5994ee44beb0c6..a830a3af3ea7dc 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -641,7 +641,7 @@ precompile_test_harness(false) do dir error("break me") end """) - @test_warn r"LoadError: break me\nStacktrace:\n \[1\] [\e01m\[]*error" try + @test_warn r"LoadError: break me\nStacktrace:\n[ ]*\[1\] [\e01m\[]*error" try Base.require(Main, :FooBar2) error("the \"break me\" test failed") catch exc From 243f67db8f25a4601efe2a13727a3527ce6c90af Mon Sep 17 00:00:00 2001 From: danik292 <116908854+danik292@users.noreply.github.com> Date: Sat, 23 Mar 2024 16:49:07 +0100 Subject: [PATCH 023/123] Add docstring for Base.Sort.SMALL_ALGORITHM (#53807) Co-authored-by: Lilith Orion Hafner Co-authored-by: Steven G. Johnson --- base/sort.jl | 10 ++++++++++ test/sorting.jl | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/sort.jl b/base/sort.jl index eb57da376f4ab8..281a75cac309ed 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -812,6 +812,16 @@ Characteristics: it is well-suited to small collections but should not be used for large ones. """ const InsertionSort = InsertionSortAlg() + +""" + SMALL_ALGORITHM + +Default sorting algorithm for small arrays. + +This is an alias for a simple low-overhead algorithm that does not scale well +to large arrays, unlike high-overhead recursive algorithms used for larger arrays. +`SMALL_ALGORITHM` is a good choice for the base case of a recursive algorithm. +""" const SMALL_ALGORITHM = InsertionSortAlg() function _sort!(v::AbstractVector, ::InsertionSortAlg, o::Ordering, kw) diff --git a/test/sorting.jl b/test/sorting.jl index d1875c9727a299..2714197f58823a 100644 --- a/test/sorting.jl +++ b/test/sorting.jl @@ -12,7 +12,7 @@ using .Main.OffsetArrays @testset "Base.Sort docstrings" begin undoc = Docs.undocumented_names(Base.Sort) @test_broken isempty(undoc) - @test undoc == [:Algorithm, :SMALL_ALGORITHM, :SMALL_THRESHOLD, :Sort] + @test undoc == [:Algorithm, :SMALL_THRESHOLD, :Sort] end @testset "Order" begin From 9bd7343fab5059fc00450d2e0f582f5c03f79cd5 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Sat, 23 Mar 2024 17:12:32 -0400 Subject: [PATCH 024/123] Retry downloads in toml tests (#53828) --- stdlib/TOML/test/utils/utils.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/TOML/test/utils/utils.jl b/stdlib/TOML/test/utils/utils.jl index c484a61cee25aa..b01acf04a72feb 100644 --- a/stdlib/TOML/test/utils/utils.jl +++ b/stdlib/TOML/test/utils/utils.jl @@ -33,7 +33,7 @@ end function get_data() tmp = mktempdir() path = joinpath(tmp, basename(url)) - Downloads.download(url, path) + retry(Downloads.download, delays=fill(10,5))(url, path) Tar.extract(`$(exe7z()) x $path -so`, joinpath(tmp, "testfiles")) return joinpath(tmp, "testfiles", "toml-test-julia-$version", "testfiles") end From 4a2c59333946c5450c73f4c5ba7d2d28529db8de Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Sat, 23 Mar 2024 22:32:02 +0100 Subject: [PATCH 025/123] add code loading + precompilation support for workspaces (#53653) This is similar to workspaces in cargo where multiple projects share a manifest https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html and upon resolving the dependencies and compat of all projects in the workspace is adhered to. The idea is to use this for e.g. test, doc environments where you want to "overlay" a dependency graph on top of a base one. The code change in Base adds support for the code loading and precompilation part of this, those changes are: - Finding the manifest from any active project in the workspace - Merge preferences among projects in a workspace. - Allowing one to pass `manifest=true` to `precompilepkgs` to compile every package in the manifest. - The effect of giving no packages to `precompilepkgs` was changed from compiling all packages in the manifest to only those in the active project (which is equivalent in case of no workspace being used but different when it is used). --- base/loading.jl | 69 ++++++++++++++++--- base/precompilation.jl | 50 ++++++++------ doc/src/manual/code-loading.md | 22 ++++++ test/loading.jl | 58 ++++++++++++++++ test/project/SubProject/Devved/Project.toml | 3 + test/project/SubProject/Devved/src/Devved.jl | 5 ++ test/project/SubProject/Devved2/Project.toml | 3 + .../project/SubProject/Devved2/src/Devved2.jl | 5 ++ test/project/SubProject/Manifest.toml | 68 ++++++++++++++++++ .../SubProject/PackageThatIsSub/Project.toml | 14 ++++ .../PackageThatIsSub/src/PackageThatIsSub.jl | 5 ++ .../PackageThatIsSub/test/Project.toml | 8 +++ test/project/SubProject/Project.toml | 13 ++++ test/project/SubProject/src/MyPkg.jl | 3 + test/project/SubProject/sub/Project.toml | 3 + test/project/SubProject/test/Project.toml | 4 ++ 16 files changed, 304 insertions(+), 29 deletions(-) create mode 100644 test/project/SubProject/Devved/Project.toml create mode 100644 test/project/SubProject/Devved/src/Devved.jl create mode 100644 test/project/SubProject/Devved2/Project.toml create mode 100644 test/project/SubProject/Devved2/src/Devved2.jl create mode 100644 test/project/SubProject/Manifest.toml create mode 100644 test/project/SubProject/PackageThatIsSub/Project.toml create mode 100644 test/project/SubProject/PackageThatIsSub/src/PackageThatIsSub.jl create mode 100644 test/project/SubProject/PackageThatIsSub/test/Project.toml create mode 100644 test/project/SubProject/Project.toml create mode 100644 test/project/SubProject/src/MyPkg.jl create mode 100644 test/project/SubProject/sub/Project.toml create mode 100644 test/project/SubProject/test/Project.toml diff --git a/base/loading.jl b/base/loading.jl index 986efc1e1e5fbe..fd8eba6bed4602 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -611,6 +611,23 @@ function env_project_file(env::String)::Union{Bool,String} end end +function base_project(project_file) + base_dir = abspath(joinpath(dirname(project_file), "..")) + base_project_file = env_project_file(base_dir) + base_project_file isa String || return nothing + d = parsed_toml(base_project_file) + workspace = get(d, "workspace", nothing)::Union{Dict{String, Any}, Nothing} + if workspace === nothing + return nothing + end + projects = get(workspace, "projects", nothing)::Union{Vector{String}, Nothing, String} + projects === nothing && return nothing + if projects isa Vector && basename(dirname(project_file)) in projects + return base_project_file + end + return nothing +end + function project_deps_get(env::String, name::String)::Union{Nothing,PkgId} project_file = env_project_file(env) if project_file isa String @@ -622,21 +639,27 @@ function project_deps_get(env::String, name::String)::Union{Nothing,PkgId} return nothing end +function package_get(project_file, where::PkgId, name::String) + proj = project_file_name_uuid(project_file, where.name) + if proj == where + # if `where` matches the project, use [deps] section as manifest, and stop searching + pkg_uuid = explicit_project_deps_get(project_file, name) + return PkgId(pkg_uuid, name) + end + return nothing +end + function manifest_deps_get(env::String, where::PkgId, name::String)::Union{Nothing,PkgId} uuid = where.uuid @assert uuid !== nothing project_file = env_project_file(env) if project_file isa String - # first check if `where` names the Project itself - proj = project_file_name_uuid(project_file, where.name) - if proj == where - # if `where` matches the project, use [deps] section as manifest, and stop searching - pkg_uuid = explicit_project_deps_get(project_file, name) - return PkgId(pkg_uuid, name) - end + pkg = package_get(project_file, where, name) + pkg === nothing || return pkg d = parsed_toml(project_file) exts = get(d, "extensions", nothing)::Union{Dict{String, Any}, Nothing} if exts !== nothing + proj = project_file_name_uuid(project_file, where.name) # Check if `where` is an extension of the project if where.name in keys(exts) && where.uuid == uuid5(proj.uuid::UUID, where.name) # Extensions can load weak deps... @@ -726,6 +749,14 @@ function project_file_path(project_file::String) joinpath(dirname(project_file), get(d, "path", "")::String) end +function workspace_manifest(project_file) + base = base_project(project_file) + if base !== nothing + return project_file_manifest_path(base) + end + return nothing +end + # find project file's corresponding manifest file function project_file_manifest_path(project_file::String)::Union{Nothing,String} @lock require_lock begin @@ -736,6 +767,10 @@ function project_file_manifest_path(project_file::String)::Union{Nothing,String} end dir = abspath(dirname(project_file)) d = parsed_toml(project_file) + base_manifest = workspace_manifest(project_file) + if base_manifest !== nothing + return base_manifest + end explicit_manifest = get(d, "manifest", nothing)::Union{String, Nothing} manifest_path = nothing if explicit_manifest !== nothing @@ -3355,9 +3390,27 @@ function recursive_prefs_merge(base::Dict{String, Any}, overrides::Dict{String, return new_base end +function get_projects_workspace_to_root(project_file) + projects = String[project_file] + while true + project_file = base_project(project_file) + if project_file === nothing + return projects + end + push!(projects, project_file) + end +end + function get_preferences(uuid::Union{UUID,Nothing} = nothing) merged_prefs = Dict{String,Any}() - for env in reverse(load_path()) + loadpath = load_path() + projects_to_merge_prefs = String[] + append!(projects_to_merge_prefs, Iterators.drop(loadpath, 1)) + if length(loadpath) >= 1 + prepend!(projects_to_merge_prefs, get_projects_workspace_to_root(first(loadpath))) + end + + for env in reverse(projects_to_merge_prefs) project_toml = env_project_file(env) if !isa(project_toml, String) continue diff --git a/base/precompilation.jl b/base/precompilation.jl index 50b84ad829d0ac..a823b2b5798527 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -1,7 +1,8 @@ module Precompilation using Base: PkgId, UUID, SHA1, parsed_toml, project_file_name_uuid, project_names, - project_file_manifest_path, get_deps, preferences_names, isaccessibledir, isfile_casesensitive + project_file_manifest_path, get_deps, preferences_names, isaccessibledir, isfile_casesensitive, + base_project # This is currently only used for pkgprecompile but the plan is to use this in code loading in the future # see the `kc/codeloading2.0` branch @@ -59,6 +60,19 @@ function ExplicitEnv(envpath::String=Base.active_project()) delete!(project_deps, name) end + # This project might be a package, in that case, that is also a "dependency" + # of the project. + proj_name = get(project_d, "name", nothing)::Union{String, Nothing} + _proj_uuid = get(project_d, "uuid", nothing)::Union{String, Nothing} + proj_uuid = _proj_uuid === nothing ? nothing : UUID(_proj_uuid) + + project_is_package = proj_name !== nothing && proj_uuid !== nothing + if project_is_package + # TODO: Error on missing uuid? + project_deps[proj_name] = UUID(proj_uuid) + names[UUID(proj_uuid)] = proj_name + end + project_extensions = Dict{String, Vector{UUID}}() # Collect all extensions of the project for (name, triggers::Union{String, Vector{String}}) in get(Dict{String, Any}, project_d, "extensions")::Dict{String, Any} @@ -76,18 +90,6 @@ function ExplicitEnv(envpath::String=Base.active_project()) project_extensions[name] = uuids end - # This project might be a package, in that case, that is also a "dependency" - # of the project. - proj_name = get(project_d, "name", nothing)::Union{String, Nothing} - _proj_uuid = get(project_d, "uuid", nothing)::Union{String, Nothing} - proj_uuid = _proj_uuid === nothing ? nothing : UUID(_proj_uuid) - - if proj_name !== nothing && proj_uuid !== nothing - # TODO: Error on missing uuid? - project_deps[proj_name] = UUID(proj_uuid) - names[UUID(proj_uuid)] = proj_name - end - manifest = project_file_manifest_path(envpath) manifest_d = manifest === nothing ? Dict{String, Any}() : parsed_toml(manifest) @@ -355,8 +357,8 @@ function precompilepkgs(pkgs::Vector{String}=String[]; configs::Union{Config,Vector{Config}}=(``=>Base.CacheFlags()), io::IO=stderr, # asking for timing disables fancy mode, as timing is shown in non-fancy mode - fancyprint::Bool = can_fancyprint(io) && !timing - ) + fancyprint::Bool = can_fancyprint(io) && !timing, + manifest::Bool=false,) configs = configs isa Config ? [configs] : configs @@ -512,9 +514,15 @@ function precompilepkgs(pkgs::Vector{String}=String[]; end @debug "precompile: circular dep check done" - # if a list of packages is given, restrict to dependencies of given packages - if !isempty(pkgs) - function collect_all_deps(depsmap, dep, alldeps=Set{Base.PkgId}()) + if !manifest + if isempty(pkgs) + pkgs = [pkg.name for pkg in direct_deps] + target = "all packages" + else + target = join(pkgs, ", ") + end + # restrict to dependencies of given packages + function collect_all_deps(depsmap, dep, alldeps=Set{Base.PkgId}()) for _dep in depsmap[dep] if !(_dep in alldeps) push!(alldeps, _dep) @@ -544,13 +552,13 @@ function precompilepkgs(pkgs::Vector{String}=String[]; # TODO: actually handle packages from other envs in the stack return else - error("No direct dependencies outside of the sysimage found matching $(repr(pkgs))") + return end end - target = join(pkgs, ", ") else - target = "project" + target = "manifest" end + nconfigs = length(configs) if nconfigs == 1 if !isempty(only(configs)[1]) diff --git a/doc/src/manual/code-loading.md b/doc/src/manual/code-loading.md index 25ebf3475f34ca..9e753d2a7de337 100644 --- a/doc/src/manual/code-loading.md +++ b/doc/src/manual/code-loading.md @@ -394,6 +394,28 @@ are stored in the manifest file in the section for that package. The dependency a package are the same as for its "parent" except that the listed extension dependencies are also considered as dependencies. +### [Workspaces](@id workspaces) + +A project file can define a workspace by giving a set of projects that is part of that workspace: + +```toml +[workspace] +projects = ["test", "benchmarks", "docs", "SomePackage"] +``` + +Each subfolder contains its own `Project.toml` file, which may include additional dependencies and compatibility constraints. In such cases, the package manager gathers all dependency information from all the projects in the workspace generating a single manifest file that combines the versions of all dependencies. + +Furthermore, workspaces can be "nested", meaning a project defining a workspace can also be part of another workspace. In this scenario, a single manifest file is still utilized, stored alongside the "root project" (the project that doesn't have another workspace including it). An example file structure could look like this: + +``` +Project.toml # projects = ["MyPackage"] +Manifest.toml +MyPackage/ + Project.toml # projects = ["test"] + test/ + Project.toml +``` + ### [Package/Environment Preferences](@id preferences) Preferences are dictionaries of metadata that influence package behavior within an environment. diff --git a/test/loading.jl b/test/loading.jl index 8ba2cf3026120f..872ccd197f0f88 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -1550,3 +1550,61 @@ end rot13proj = joinpath(@__DIR__, "project", "Rot13") @test readchomp(`$(Base.julia_cmd()) --startup-file=no --project=$rot13proj -m Rot13 --project nowhere ABJURER`) == "--cebwrpg abjurer NOWHERE " end + +@testset "workspace loading" begin + old_load_path = copy(LOAD_PATH) + try + empty!(LOAD_PATH) + push!(LOAD_PATH, joinpath(@__DIR__, "project", "SubProject")) + @test Base.get_preferences()["value"] == 1 + @test Base.get_preferences()["x"] == 1 + + empty!(LOAD_PATH) + push!(LOAD_PATH, joinpath(@__DIR__, "project", "SubProject", "sub")) + id = Base.identify_package("Devved") + @test isfile(Base.locate_package(id)) + @test Base.identify_package("Devved2") === nothing + id3 = Base.identify_package("MyPkg") + @test isfile(Base.locate_package(id3)) + + empty!(LOAD_PATH) + push!(LOAD_PATH, joinpath(@__DIR__, "project", "SubProject", "PackageThatIsSub")) + id_pkg = Base.identify_package("PackageThatIsSub") + @test Base.identify_package(id_pkg, "Devved") === nothing + id_dev2 = Base.identify_package(id_pkg, "Devved2") + @test isfile(Base.locate_package(id_dev2)) + id_mypkg = Base.identify_package("MyPkg") + @test isfile(Base.locate_package(id_mypkg)) + id_dev = Base.identify_package(id_mypkg, "Devved") + @test isfile(Base.locate_package(id_dev)) + @test Base.get_preferences()["value"] == 2 + @test Base.get_preferences()["x"] == 1 + @test Base.get_preferences()["y"] == 2 + + empty!(LOAD_PATH) + push!(LOAD_PATH, joinpath(@__DIR__, "project", "SubProject", "PackageThatIsSub", "test")) + id_pkg = Base.identify_package("PackageThatIsSub") + @test isfile(Base.locate_package(id_pkg)) + @test Base.identify_package(id_pkg, "Devved") === nothing + id_dev2 = Base.identify_package(id_pkg, "Devved2") + @test isfile(Base.locate_package(id_dev2)) + id_mypkg = Base.identify_package("MyPkg") + @test isfile(Base.locate_package(id_mypkg)) + id_dev = Base.identify_package(id_mypkg, "Devved") + @test isfile(Base.locate_package(id_dev)) + @test Base.get_preferences()["value"] == 3 + @test Base.get_preferences()["x"] == 1 + @test Base.get_preferences()["y"] == 2 + @test Base.get_preferences()["z"] == 3 + + empty!(LOAD_PATH) + push!(LOAD_PATH, joinpath(@__DIR__, "project", "SubProject", "test")) + id_mypkg = Base.identify_package("MyPkg") + id_dev = Base.identify_package(id_mypkg, "Devved") + @test isfile(Base.locate_package(id_dev)) + @test Base.identify_package("Devved2") === nothing + + finally + copy!(LOAD_PATH, old_load_path) + end +end diff --git a/test/project/SubProject/Devved/Project.toml b/test/project/SubProject/Devved/Project.toml new file mode 100644 index 00000000000000..63088a132cb773 --- /dev/null +++ b/test/project/SubProject/Devved/Project.toml @@ -0,0 +1,3 @@ +name = "Devved" +uuid = "cbce3a6e-7a3d-4e84-8e6d-b87208df7599" +version = "0.1.0" diff --git a/test/project/SubProject/Devved/src/Devved.jl b/test/project/SubProject/Devved/src/Devved.jl new file mode 100644 index 00000000000000..f3eb267409ece7 --- /dev/null +++ b/test/project/SubProject/Devved/src/Devved.jl @@ -0,0 +1,5 @@ +module Devved + +greet() = print("Hello World!") + +end # module Devved diff --git a/test/project/SubProject/Devved2/Project.toml b/test/project/SubProject/Devved2/Project.toml new file mode 100644 index 00000000000000..c761630566116e --- /dev/null +++ b/test/project/SubProject/Devved2/Project.toml @@ -0,0 +1,3 @@ +name = "Devved2" +uuid = "08f74b90-50f5-462f-80b9-a72b1258a17b" +version = "0.1.0" diff --git a/test/project/SubProject/Devved2/src/Devved2.jl b/test/project/SubProject/Devved2/src/Devved2.jl new file mode 100644 index 00000000000000..9bd5df2793671d --- /dev/null +++ b/test/project/SubProject/Devved2/src/Devved2.jl @@ -0,0 +1,5 @@ +module Devved2 + +greet() = print("Hello World!") + +end # module Devved2 diff --git a/test/project/SubProject/Manifest.toml b/test/project/SubProject/Manifest.toml new file mode 100644 index 00000000000000..5d791a74652d48 --- /dev/null +++ b/test/project/SubProject/Manifest.toml @@ -0,0 +1,68 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.12.0-DEV" +manifest_format = "2.0" +project_hash = "620b9377bc807ff657e6618c8ccc24887eb40285" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +version = "1.11.0" + +[[deps.Devved]] +path = "Devved" +uuid = "cbce3a6e-7a3d-4e84-8e6d-b87208df7599" +version = "0.1.0" + +[[deps.Devved2]] +path = "Devved2" +uuid = "08f74b90-50f5-462f-80b9-a72b1258a17b" +version = "0.1.0" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +version = "1.11.0" + +[[deps.Logging]] +deps = ["StyledStrings"] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" +version = "1.11.0" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" +version = "1.11.0" + +[[deps.MyPkg]] +deps = ["Devved", "Devved2"] +path = "." +uuid = "0cafdeb2-d7a2-40d0-8d22-4411fcc2c4ee" +version = "0.0.0" + +[[deps.PackageThatIsSub]] +deps = ["Devved2", "MyPkg"] +path = "PackageThatIsSub" +uuid = "1efb588c-9412-4e40-90a4-710420bd84aa" +version = "0.1.0" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +version = "1.11.0" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" +version = "1.11.0" + +[[deps.StyledStrings]] +uuid = "f489334b-da3d-4c2e-b8f0-e476e12c162b" +version = "1.11.0" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +version = "1.11.0" diff --git a/test/project/SubProject/PackageThatIsSub/Project.toml b/test/project/SubProject/PackageThatIsSub/Project.toml new file mode 100644 index 00000000000000..e41dd998c5a1c3 --- /dev/null +++ b/test/project/SubProject/PackageThatIsSub/Project.toml @@ -0,0 +1,14 @@ +name = "PackageThatIsSub" +uuid = "1efb588c-9412-4e40-90a4-710420bd84aa" +version = "0.1.0" + +[workspace] +projects = ["test"] + +[deps] +Devved2 = "08f74b90-50f5-462f-80b9-a72b1258a17b" +MyPkg = "0cafdeb2-d7a2-40d0-8d22-4411fcc2c4ee" + +[preferences] +value = 2 +y = 2 diff --git a/test/project/SubProject/PackageThatIsSub/src/PackageThatIsSub.jl b/test/project/SubProject/PackageThatIsSub/src/PackageThatIsSub.jl new file mode 100644 index 00000000000000..7f9ea94ccb156d --- /dev/null +++ b/test/project/SubProject/PackageThatIsSub/src/PackageThatIsSub.jl @@ -0,0 +1,5 @@ +module PackageThatIsSub + +greet() = print("Hello World!") + +end # module PackageThatIsSub diff --git a/test/project/SubProject/PackageThatIsSub/test/Project.toml b/test/project/SubProject/PackageThatIsSub/test/Project.toml new file mode 100644 index 00000000000000..dc8186e2b735eb --- /dev/null +++ b/test/project/SubProject/PackageThatIsSub/test/Project.toml @@ -0,0 +1,8 @@ +[deps] +MyPkg = "0cafdeb2-d7a2-40d0-8d22-4411fcc2c4ee" +PackageThatIsSub = "1efb588c-9412-4e40-90a4-710420bd84aa" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[preferences] +value = 3 +z = 3 diff --git a/test/project/SubProject/Project.toml b/test/project/SubProject/Project.toml new file mode 100644 index 00000000000000..dcb84d865ac853 --- /dev/null +++ b/test/project/SubProject/Project.toml @@ -0,0 +1,13 @@ +name = "MyPkg" +uuid = "0cafdeb2-d7a2-40d0-8d22-4411fcc2c4ee" + +[workspace] +projects = ["sub", "PackageThatIsSub", "test"] + +[deps] +Devved = "cbce3a6e-7a3d-4e84-8e6d-b87208df7599" +Devved2 = "08f74b90-50f5-462f-80b9-a72b1258a17b" + +[preferences] +value = 1 +x = 1 diff --git a/test/project/SubProject/src/MyPkg.jl b/test/project/SubProject/src/MyPkg.jl new file mode 100644 index 00000000000000..6d84954645d553 --- /dev/null +++ b/test/project/SubProject/src/MyPkg.jl @@ -0,0 +1,3 @@ +module MyPkg + +end diff --git a/test/project/SubProject/sub/Project.toml b/test/project/SubProject/sub/Project.toml new file mode 100644 index 00000000000000..50aa238e91d572 --- /dev/null +++ b/test/project/SubProject/sub/Project.toml @@ -0,0 +1,3 @@ +[deps] +Devved = "cbce3a6e-7a3d-4e84-8e6d-b87208df7599" +MyPkg = "0cafdeb2-d7a2-40d0-8d22-4411fcc2c4ee" diff --git a/test/project/SubProject/test/Project.toml b/test/project/SubProject/test/Project.toml new file mode 100644 index 00000000000000..b64312e4b1ee29 --- /dev/null +++ b/test/project/SubProject/test/Project.toml @@ -0,0 +1,4 @@ +[deps] +MyPkg = "0cafdeb2-d7a2-40d0-8d22-4411fcc2c4ee" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +Devved = "cbce3a6e-7a3d-4e84-8e6d-b87208df7599" From 9636ef72eebe0155710471fb79eb5c75cc26949b Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Mon, 25 Mar 2024 10:23:54 -0300 Subject: [PATCH 026/123] create phantom task for GC threads (#53815) A common idiom used throughout the codebase is to get a pointer to thread-local-state through `jl_current_task->ptls`. Create a phantom task for GC threads so that we can make use of this idiom when running in the GC threads as well. Idea originally suggested by @vchuravy, bugs are mine. --- src/scheduler.c | 10 ++++++++++ src/task.c | 1 + 2 files changed, 11 insertions(+) diff --git a/src/scheduler.c b/src/scheduler.c index 1b6a20a36887a6..a04320beec00da 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -129,6 +129,11 @@ void jl_parallel_gc_threadfun(void *arg) // initialize this thread (set tid and create heap) jl_ptls_t ptls = jl_init_threadtls(targ->tid); + void *stack_lo, *stack_hi; + jl_init_stack_limits(0, &stack_lo, &stack_hi); + // warning: this changes `jl_current_task`, so be careful not to call that from this function + jl_task_t *ct = jl_init_root_task(ptls, stack_lo, stack_hi); + JL_GC_PROMISE_ROOTED(ct); (void)jl_atomic_fetch_add_relaxed(&nrunning, -1); // wait for all threads jl_gc_state_set(ptls, JL_GC_STATE_WAITING, JL_GC_STATE_UNSAFE); @@ -158,6 +163,11 @@ void jl_concurrent_gc_threadfun(void *arg) // initialize this thread (set tid and create heap) jl_ptls_t ptls = jl_init_threadtls(targ->tid); + void *stack_lo, *stack_hi; + jl_init_stack_limits(0, &stack_lo, &stack_hi); + // warning: this changes `jl_current_task`, so be careful not to call that from this function + jl_task_t *ct = jl_init_root_task(ptls, stack_lo, stack_hi); + JL_GC_PROMISE_ROOTED(ct); (void)jl_atomic_fetch_add_relaxed(&nrunning, -1); // wait for all threads jl_gc_state_set(ptls, JL_GC_STATE_WAITING, JL_GC_STATE_UNSAFE); diff --git a/src/task.c b/src/task.c index a7250c36832ea9..5f28c3c243bfe5 100644 --- a/src/task.c +++ b/src/task.c @@ -1649,6 +1649,7 @@ jl_task_t *jl_init_root_task(jl_ptls_t ptls, void *stack_lo, void *stack_hi) JL_GC_PROMISE_ROOTED(ct); jl_set_pgcstack(&ct->gcstack); assert(jl_current_task == ct); + assert(jl_current_task->ptls == ptls); #ifdef _COMPILER_TSAN_ENABLED_ ct->ctx.tsan_state = __tsan_get_current_fiber(); From 944f1809185455a1c57207983c1d0f8904343503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bogumi=C5=82=20Kami=C5=84ski?= Date: Mon, 25 Mar 2024 16:18:44 +0100 Subject: [PATCH 027/123] Add Xoshiro reference to Random module docstring (#53784) Since currently `Xoshiro` is a default random number generator I propose to add it to the docstring of `Random` module. --- stdlib/Random/src/Random.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/Random/src/Random.jl b/stdlib/Random/src/Random.jl index 432e32a4de6918..9ce0896d0d1253 100644 --- a/stdlib/Random/src/Random.jl +++ b/stdlib/Random/src/Random.jl @@ -4,7 +4,7 @@ Random Support for generating random numbers. Provides [`rand`](@ref), [`randn`](@ref), -[`AbstractRNG`](@ref), [`MersenneTwister`](@ref), and [`RandomDevice`](@ref). +[`AbstractRNG`](@ref), [`Xoshiro`](@ref), [`MersenneTwister`](@ref), and [`RandomDevice`](@ref). """ module Random From 61caaa886afe18273e2f7b7d09a714298a62a9b3 Mon Sep 17 00:00:00 2001 From: FX Coudert Date: Mon, 25 Mar 2024 18:54:09 +0100 Subject: [PATCH 028/123] update MPFR to 4.2.1 (#53837) MPFR 4.2.1 was released on 22 August 2023. It contains bugfixes. --- deps/checksums/mpfr | 68 ++++++++++++++++---------------- deps/mpfr.version | 2 +- stdlib/MPFR_jll/Project.toml | 2 +- stdlib/MPFR_jll/test/runtests.jl | 2 +- stdlib/Manifest.toml | 2 +- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/deps/checksums/mpfr b/deps/checksums/mpfr index 1bb4eca6bf4ad2..050e9cbd8d5a8b 100644 --- a/deps/checksums/mpfr +++ b/deps/checksums/mpfr @@ -1,34 +1,34 @@ -MPFR.v4.2.0+1.aarch64-apple-darwin.tar.gz/md5/f9393a636497b19c846343b456b2dd7e -MPFR.v4.2.0+1.aarch64-apple-darwin.tar.gz/sha512/a77a0387e84f572ef5558977096e70da8eb7b3674a8198cc6ae35462971f76d684145ffae7c2ddca32e2bd1c8b2ccb33e4447eb8606d5d5cd5958298472b3ea9 -MPFR.v4.2.0+1.aarch64-linux-gnu.tar.gz/md5/ade253017d195de694780c32f9161dcf -MPFR.v4.2.0+1.aarch64-linux-gnu.tar.gz/sha512/1b68de5f8e557b7434c8c1bc016227b58683b56c0977b763422ea85a673bec446fcfee3a4f69e1d4689abb9bb6bf47f2a50fbb56ecac6a9d40096e66bd0f2080 -MPFR.v4.2.0+1.aarch64-linux-musl.tar.gz/md5/7dbd121c7192ccaf7191de5ab8d91afb -MPFR.v4.2.0+1.aarch64-linux-musl.tar.gz/sha512/8614e3cb28491b24a0ec5060b44abaf264b61c91ddd29d70105ff583bd3112cff1b9bd5ed45e39f186265333982d5eeb8bf35fedc3b51b2a009cc7a51046b50b -MPFR.v4.2.0+1.armv6l-linux-gnueabihf.tar.gz/md5/adb2b7fdf111c8b19df1516cfb278bb1 -MPFR.v4.2.0+1.armv6l-linux-gnueabihf.tar.gz/sha512/0c47aeffd05a194802f6c4e0e2779d56fb46007e6c3e145ee6992854a21a317a9d51512c59a0ce4ddcd314c387945225c6557d6c2ab6961ae4848875e8983de8 -MPFR.v4.2.0+1.armv6l-linux-musleabihf.tar.gz/md5/c30358bdeffcff65ba9be906cd35889b -MPFR.v4.2.0+1.armv6l-linux-musleabihf.tar.gz/sha512/2857ec27ae2d53a451d62dd241ce9b43f7ee182bee180ecd9ad92c907c66d0b0ab2d1ea3b20fe61cc176ae44ecbe6041305cc8a9343b396c9cb54dd77a1e2868 -MPFR.v4.2.0+1.armv7l-linux-gnueabihf.tar.gz/md5/a1e30436bade2150c9dc924177f0c321 -MPFR.v4.2.0+1.armv7l-linux-gnueabihf.tar.gz/sha512/d2f4662c494fefda66847e7a085edda3ce396383aafb4e17fc2e176191b0f530541726c261cac3467f13136e8ec728c8a7cf0e352f3e9ebf960d153cbfe766b8 -MPFR.v4.2.0+1.armv7l-linux-musleabihf.tar.gz/md5/857e3c82804e7c853d21603f18caa715 -MPFR.v4.2.0+1.armv7l-linux-musleabihf.tar.gz/sha512/86cf3e940fd66820b5269e9aa2a49c3fc3077857bec037a08e0d301b0bf3cc5c79ac331cc6370d852e20f4acf8f601c49d5dbe24e96652e4411b3f33a11e3f45 -MPFR.v4.2.0+1.i686-linux-gnu.tar.gz/md5/5a432be79a112e67e970980f4bde13a0 -MPFR.v4.2.0+1.i686-linux-gnu.tar.gz/sha512/94198b23ac94dcb9dca95938a46b9899c3ef329bafbb13b32076cd3415b89f11908632c7c07e90549c01bd9ed7fc9a002dae07a645f85b8509234c49be729621 -MPFR.v4.2.0+1.i686-linux-musl.tar.gz/md5/4ce71dc250c2469f844a02c6ee6571a1 -MPFR.v4.2.0+1.i686-linux-musl.tar.gz/sha512/134b67b23de75ab172594cd0fac55b5c265730bfea195978698e3e6fbc47d65617652bd72d90ba092ed1bac4c29d5b2c109df5d8dc60b5d8f91159fd58575b67 -MPFR.v4.2.0+1.i686-w64-mingw32.tar.gz/md5/be7239432e8a26c59e2d418d310bd6e3 -MPFR.v4.2.0+1.i686-w64-mingw32.tar.gz/sha512/3144d84d41996fc19bfc9ed4f36755838470e17dce79895b37d93e32ae1cb1da428f2136948f939b19548d7dd62830ae43c434f88efbe192ed3184bae2df5970 -MPFR.v4.2.0+1.powerpc64le-linux-gnu.tar.gz/md5/d818894054b38232ba02ee0e129f6fe0 -MPFR.v4.2.0+1.powerpc64le-linux-gnu.tar.gz/sha512/0e73ca926f3e06466d1899f0b3e9ae4abe15102804dce6716ce23154344a571773c40d276f0038a0ae4e626799867ee715428e1d961334a01ad3091745367e8e -MPFR.v4.2.0+1.x86_64-apple-darwin.tar.gz/md5/9652148df4e771be39713c4f43d3ff61 -MPFR.v4.2.0+1.x86_64-apple-darwin.tar.gz/sha512/91a0219fd1880dfa90d196fa403f4e1df0347ced58a4772492196b94476f346d80696885a4f3520424494bc09679cca0c0ccf2f6e9247d60b52ebdf564485e72 -MPFR.v4.2.0+1.x86_64-linux-gnu.tar.gz/md5/4de39327a792be708119ac7b43957628 -MPFR.v4.2.0+1.x86_64-linux-gnu.tar.gz/sha512/447b59d5589a8517061627668e8baed4366408cacc9d8e063528b9b795de6d27e4005844578310185f03f568f4948bc4a794624235875fb61b6187264b6f483b -MPFR.v4.2.0+1.x86_64-linux-musl.tar.gz/md5/f9b8c3c094b339341b19828cc5e1d47c -MPFR.v4.2.0+1.x86_64-linux-musl.tar.gz/sha512/c661e7c5bded3bdf11b2bd5e5ef4ad8e446934d9b82dfe26f0be1b83cea98d7e56e0903bfc1075f91c8d23401cc6b3b722f2d60f46d73cab884e81fe518aba27 -MPFR.v4.2.0+1.x86_64-unknown-freebsd.tar.gz/md5/e402dceae753abbdd8b11f3c8d96e0dd -MPFR.v4.2.0+1.x86_64-unknown-freebsd.tar.gz/sha512/235f001f3b0101a6bafaeb45fb49d2992549b6c2f42a4e7ba38e1fa8c59246fe7463598e7cfda5ead50c9805dda0b82a23b5ae2af4ec993bb771611163e58907 -MPFR.v4.2.0+1.x86_64-w64-mingw32.tar.gz/md5/c5bbd2217060491e2773bdd84b055e5c -MPFR.v4.2.0+1.x86_64-w64-mingw32.tar.gz/sha512/74b059b22990ab79f243284687f571f47447457ac2c1cb4c4548ea1f3d8ea01b7466281f48429cb39e2d11394fb86650bfada7acab639c6537a143a95bd6e7ca -mpfr-4.2.0.tar.bz2/md5/f8c66d737283fd35f9fe433fb419b05f -mpfr-4.2.0.tar.bz2/sha512/cb2a9314b94e34a4ea49ce2619802e9420c982e55258a4bc423f802740632646a3d420e7fcf373b19618385b8b2b412abfa127e8f473053863424cac233893c0 +MPFR.v4.2.1+0.aarch64-apple-darwin.tar.gz/md5/816f9ff59070f21f1df2f310e2606c06 +MPFR.v4.2.1+0.aarch64-apple-darwin.tar.gz/sha512/dad9adba7a8867d1ce26d77efb5c33b602b920a2cdbec84ea58a054cfab3ab7df54d2bda101de72b71604e7844993f1e216b002ba092e69277d0764040216c81 +MPFR.v4.2.1+0.aarch64-linux-gnu.tar.gz/md5/c1e3c9619af6454d8adae9bcbd911dba +MPFR.v4.2.1+0.aarch64-linux-gnu.tar.gz/sha512/5d916492aa73d11e022a7ca3f31940ceb8f8667bdf878ba29d6256736a380a2f6a11ac90cd8de3f1d3454a79165db240a1b971b9794fd21692ed64502ec34b9a +MPFR.v4.2.1+0.aarch64-linux-musl.tar.gz/md5/8ada267e2d23eb0c65ab2d2df02362d5 +MPFR.v4.2.1+0.aarch64-linux-musl.tar.gz/sha512/0c7f18e6d0f3e2052541e3279dfa9a74eb34067ac4fea0b17ab805cd73010cc83f8d7cb4eda8f4a904da398268d1c0d638c35521a9f339f8c7c3b5f159f27277 +MPFR.v4.2.1+0.armv6l-linux-gnueabihf.tar.gz/md5/42bdb78eee83f496d7da699ad9603913 +MPFR.v4.2.1+0.armv6l-linux-gnueabihf.tar.gz/sha512/edaa9ece1404a606d6b635406ad5e721c8d094ffa1c73ce19222afc2b4ea7b3b9e23e7c5589ae10fd9f4c4aefa265773bcfce6c510efbca57782115d43daeb13 +MPFR.v4.2.1+0.armv6l-linux-musleabihf.tar.gz/md5/2213207772b8a50de4768816fdc20e2f +MPFR.v4.2.1+0.armv6l-linux-musleabihf.tar.gz/sha512/d24debc38b8135ac5c10c4ea19de0c69126b6881940b4e182118e12cc2c7cf0aca2db065620f0cca636742da32eddec5bda3b4f449a035274f05120c977ed449 +MPFR.v4.2.1+0.armv7l-linux-gnueabihf.tar.gz/md5/a0d9fe20c9ff0027b6816ee0102b1f9a +MPFR.v4.2.1+0.armv7l-linux-gnueabihf.tar.gz/sha512/97ce02898dc0d29a616048fd7ecee3100a710f7a30a21f2276c01675749034a5241be88bd46dff3dbf9ea0adca98a4357bd16e43fa9520e7a02477494c2d072e +MPFR.v4.2.1+0.armv7l-linux-musleabihf.tar.gz/md5/7898b9047c914b290b5928af5df63030 +MPFR.v4.2.1+0.armv7l-linux-musleabihf.tar.gz/sha512/cbefa9588752c65751630832417c1c42e4819d49ff9a505f61c2567ef4271097e585542fa898efd61409a43e439d827bb79f693a0937d0a3a427b39535979588 +MPFR.v4.2.1+0.i686-linux-gnu.tar.gz/md5/15fa598e5c1c723ff6cd2ad3ea51e437 +MPFR.v4.2.1+0.i686-linux-gnu.tar.gz/sha512/2ec4cf0c88363bc9fb39522bbcd6a9c2311c38efb166f604aab118fed39712beea68367ff5c4cabb2b7b3f5a53469414b8552fd22a70a637cbbfc936f0c4851b +MPFR.v4.2.1+0.i686-linux-musl.tar.gz/md5/6dc6a00d3ea22e2c60374d49926598d6 +MPFR.v4.2.1+0.i686-linux-musl.tar.gz/sha512/4a90356091b53d7238dda59f6e9c5c420614f16460dc67310e581611ad46a2dd3324d6164cfecf1bcd660b8f2e473f0afe137aac954c608b11be3acbda648e14 +MPFR.v4.2.1+0.i686-w64-mingw32.tar.gz/md5/bda99a916573607716c61473153a1927 +MPFR.v4.2.1+0.i686-w64-mingw32.tar.gz/sha512/ed3f45ff5ac8f4588584dd80036d9f3623651c87276a9b624955c831009dc33f8804c2845bd187ba750515725c29d65ac5d70c71db1b953c618cd771d2b066d0 +MPFR.v4.2.1+0.powerpc64le-linux-gnu.tar.gz/md5/ac70f716bddd5323b4add663b473b52d +MPFR.v4.2.1+0.powerpc64le-linux-gnu.tar.gz/sha512/ebb0f5ea76c892b7a4e4636706e71f476aaea58bb88e1734a7966c44495fda8c81318e0e8629e208185f0fc8d0c73b6f3463034cd831dfb5fbbd493a0689bc06 +MPFR.v4.2.1+0.x86_64-apple-darwin.tar.gz/md5/ff13e865e3be717b0fffc16296cb2f56 +MPFR.v4.2.1+0.x86_64-apple-darwin.tar.gz/sha512/98479210910945714da0285a40803674242581894a731ba4709c70dc1341849e736a88aa4914df0ff536c15f8848c417e712ff6abeb25047d300f8b215fd131f +MPFR.v4.2.1+0.x86_64-linux-gnu.tar.gz/md5/48194b9f92ad01b168e8b9612f4c9559 +MPFR.v4.2.1+0.x86_64-linux-gnu.tar.gz/sha512/638eb40d23fd492972809cdc3326ad4c2c99d3eae1ca5f7c0da6e0e335bb596de2899da5b3e65153225654b2cd9a805298e7241a21395e07d0b333eb1f101b5d +MPFR.v4.2.1+0.x86_64-linux-musl.tar.gz/md5/0babbb823964ccebf63b42fd07f08936 +MPFR.v4.2.1+0.x86_64-linux-musl.tar.gz/sha512/880b685d9b456fa2bf78e707273783423f9ff00791b529eba00c5e1b94ff96f4ba01e680152a4d6b45b695e3c1169d07f793db42c5a4120861813d5458dfc828 +MPFR.v4.2.1+0.x86_64-unknown-freebsd.tar.gz/md5/f11d634e5a19177fe36b2b2f6f5727ca +MPFR.v4.2.1+0.x86_64-unknown-freebsd.tar.gz/sha512/291245c06edf31b2e39b6774359ebd4f95b924f19d2a7e8581822a5bf908426d00f0452c061a027da0d7d4bb2fa1bb7ef8ab6d8e49bc848d6d7450a8d5c8a9c4 +MPFR.v4.2.1+0.x86_64-w64-mingw32.tar.gz/md5/e6d1347d5da312f7301d578ce9d7c4d9 +MPFR.v4.2.1+0.x86_64-w64-mingw32.tar.gz/sha512/3ea4b944172be250677ef271f1e10c2b95861755f203795a50b8d0f76f72498897059271e44e038625c3b73cccbd0165685d60afa994180d42e912bffbe86729 +mpfr-4.2.1.tar.bz2/md5/7765afa036e4ce7fb0e02bce0fef894b +mpfr-4.2.1.tar.bz2/sha512/c81842532ecc663348deb7400d911ad71933d3b525a2f9e5adcd04265c9c0fdd1f22eca229f482703ac7f222ef209fc9e339dd1fa47d72ae57f7f70b2336a76f diff --git a/deps/mpfr.version b/deps/mpfr.version index e4f1c8a45aeb05..ec109e181ecdcf 100644 --- a/deps/mpfr.version +++ b/deps/mpfr.version @@ -2,4 +2,4 @@ MPFR_JLL_NAME := MPFR ## source build -MPFR_VER := 4.2.0 +MPFR_VER := 4.2.1 diff --git a/stdlib/MPFR_jll/Project.toml b/stdlib/MPFR_jll/Project.toml index e4b24d070db550..eaa8d0988b2ca5 100644 --- a/stdlib/MPFR_jll/Project.toml +++ b/stdlib/MPFR_jll/Project.toml @@ -1,6 +1,6 @@ name = "MPFR_jll" uuid = "3a97d323-0669-5f0c-9066-3539efd106a3" -version = "4.2.0+1" +version = "4.2.1+0" [deps] GMP_jll = "781609d7-10c4-51f6-84f2-b8444358ff6d" diff --git a/stdlib/MPFR_jll/test/runtests.jl b/stdlib/MPFR_jll/test/runtests.jl index 81b6e06ed7b49d..fc931b462fa9c4 100644 --- a/stdlib/MPFR_jll/test/runtests.jl +++ b/stdlib/MPFR_jll/test/runtests.jl @@ -4,5 +4,5 @@ using Test, Libdl, MPFR_jll @testset "MPFR_jll" begin vn = VersionNumber(unsafe_string(ccall((:mpfr_get_version,libmpfr), Cstring, ()))) - @test vn == v"4.2.0" + @test vn == v"4.2.1" end diff --git a/stdlib/Manifest.toml b/stdlib/Manifest.toml index f2ae43f231db52..456eee252e7740 100644 --- a/stdlib/Manifest.toml +++ b/stdlib/Manifest.toml @@ -137,7 +137,7 @@ version = "1.11.0" [[deps.MPFR_jll]] deps = ["Artifacts", "GMP_jll", "Libdl"] uuid = "3a97d323-0669-5f0c-9066-3539efd106a3" -version = "4.2.0+1" +version = "4.2.1+0" [[deps.Markdown]] deps = ["Base64"] From cd523fec76507b9c55a4b99072389f563043c041 Mon Sep 17 00:00:00 2001 From: FX Coudert Date: Tue, 26 Mar 2024 02:21:39 +0100 Subject: [PATCH 029/123] Update nghttp2 to 1.60.0 (#53842) Released 1st March 2024: https://github.com/nghttp2/nghttp2/releases/tag/v1.60.0 --- deps/checksums/nghttp2 | 68 ++++++++++++++--------------- deps/nghttp2.version | 2 +- stdlib/Manifest.toml | 2 +- stdlib/nghttp2_jll/Project.toml | 2 +- stdlib/nghttp2_jll/test/runtests.jl | 2 +- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/deps/checksums/nghttp2 b/deps/checksums/nghttp2 index cfe5dbbab17eed..f8226d4f68b3de 100644 --- a/deps/checksums/nghttp2 +++ b/deps/checksums/nghttp2 @@ -1,34 +1,34 @@ -nghttp2-1.59.0.tar.bz2/md5/ed847a9f718b0bed4491a51344e8e6c8 -nghttp2-1.59.0.tar.bz2/sha512/63c497afdebb98a3a38fe41ff9ef0027d670231fbd118cef22b6340829df5de91df3d4f503135d54e54f9ee056f71efbda640b78f4fbb9ff56ba085177bb41f8 -nghttp2.v1.59.0+0.aarch64-apple-darwin.tar.gz/md5/531f9c56fe3d2d4e4457cf4245fc8a81 -nghttp2.v1.59.0+0.aarch64-apple-darwin.tar.gz/sha512/497b26a66da86ad8d0a28323a18b4ee9cd9682b6ff8ef681d760cd17bc3e82ea98385e2d621e8060a706b50531afdf6f63fa3717005446c4159780f73d17f8da -nghttp2.v1.59.0+0.aarch64-linux-gnu.tar.gz/md5/9e853f884f638534b5ce88112c7b1fbd -nghttp2.v1.59.0+0.aarch64-linux-gnu.tar.gz/sha512/72da4843e3b2b01f568d61894a7c83ace1f175667e0b64663f8bcca9a7315509f5b91f96b21508aba6009d7d33ccdf75f4aed8a8dc45ed0934654512ef2200f0 -nghttp2.v1.59.0+0.aarch64-linux-musl.tar.gz/md5/25f1489b3cc3a5bef92af5bf136e62b5 -nghttp2.v1.59.0+0.aarch64-linux-musl.tar.gz/sha512/abe1f8c5faa2a1ae6308d1c13850cc6288b13f744576de574fa6e0871f372da9121059814b467b9d5763c2bdd54ef4a38ba842a394e23735a2cc5b9c7fec13fe -nghttp2.v1.59.0+0.armv6l-linux-gnueabihf.tar.gz/md5/33448bd8e19b63811f07e7f8f6d84fbd -nghttp2.v1.59.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/b327d63e3742528f2d3b17dc97923429acd71156e4b688118295f7e7257c6313869e742b2475ee2540436d5cd68ac9224298c9ca0be4ec7c8a8b9741b65d210e -nghttp2.v1.59.0+0.armv6l-linux-musleabihf.tar.gz/md5/8e6836af6f1e7532b1ada585a31bc9ad -nghttp2.v1.59.0+0.armv6l-linux-musleabihf.tar.gz/sha512/db17877b4bafd608fe844959e1640060161a6e36ba762053b9f7153d075c3c3eadea61d72dd9f9683cec3c4b0564f284eb0b443d1715a5af77afa6f8abfa2ed4 -nghttp2.v1.59.0+0.armv7l-linux-gnueabihf.tar.gz/md5/f537e4776bbb1d9e85f8eea76df99679 -nghttp2.v1.59.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/60bb3612a8021c194a0766775583b137f5f48ed3c7d4e1afbbeeef617a5a959494c35df34d2e9a68e53b8bb676b67de5b0b47f6e98543ecccd8fe10cee2ea3dd -nghttp2.v1.59.0+0.armv7l-linux-musleabihf.tar.gz/md5/ffecbf49f667cd0a2c09919299ffa54e -nghttp2.v1.59.0+0.armv7l-linux-musleabihf.tar.gz/sha512/c34cdbe0074012c6889dfb9c93c44a4b1b0ed86197428f97b1d7b1bcd829f384121b8fc60f2c608e4206dc203739df9382a0653e75362eef282616c65251de24 -nghttp2.v1.59.0+0.i686-linux-gnu.tar.gz/md5/bb8b7668b5de15e3cdab955f905b6681 -nghttp2.v1.59.0+0.i686-linux-gnu.tar.gz/sha512/42be179bbe6a9b4c9a7f086177a23bfa0d99ec3b8ff4741a7656bcd302de9613cdb1bf556e483d924a3362c150d3286de30531d226ac402ca4a464fad3271175 -nghttp2.v1.59.0+0.i686-linux-musl.tar.gz/md5/298fb89147eb458a5f948ac6298213c1 -nghttp2.v1.59.0+0.i686-linux-musl.tar.gz/sha512/693b41d8e764f1475b79aff74c036697779dc82ac5dc79cd4d25c15ef9627e398c50cc43ad4296b96c3b6fdbb4c7514a041396570b82b3d35ef27c6c2286e8e1 -nghttp2.v1.59.0+0.i686-w64-mingw32.tar.gz/md5/b69df3b2a034b0309b5ae97ecf6e803a -nghttp2.v1.59.0+0.i686-w64-mingw32.tar.gz/sha512/1c349ccb0799942f117f56f0e2f83f898b5913071651e4bb8d1750d7ab6fdc9b6e3e894ee760623b27ae23ba7910a6674b5bbda7db3a8388fef68c0908e2ec7d -nghttp2.v1.59.0+0.powerpc64le-linux-gnu.tar.gz/md5/fc101f34e22f8885ed4141514572f2ea -nghttp2.v1.59.0+0.powerpc64le-linux-gnu.tar.gz/sha512/c7377429fcf47a0a7e9c2a1ca78d4eeba819f6f7f2fb1191fa46b7ce516db6a489994993abe50e2848cc7ab600a747cbc13e8e6484077cb8ca8fe37775bd0016 -nghttp2.v1.59.0+0.x86_64-apple-darwin.tar.gz/md5/9f81d5bd0aa9b1b4e1536020f59496ee -nghttp2.v1.59.0+0.x86_64-apple-darwin.tar.gz/sha512/c8a0641b5255a70e305b4baf5689914fc4abf795ade4ddb636243d40828195bdf2d2df394e4f8680beb70f0e497d5ceae90f6453b32ebf5d77ed03239bbb64c4 -nghttp2.v1.59.0+0.x86_64-linux-gnu.tar.gz/md5/954ef507adf403630588734a5c1ec42e -nghttp2.v1.59.0+0.x86_64-linux-gnu.tar.gz/sha512/e4de84a962e2a9a4b9b61fa69d0816db5daa271fa3440f01eb116856e5f8c9cdd0cf0aa63ff9fffd51073548ee81e94d83b4d3fd096efa6c38983047ac8a556a -nghttp2.v1.59.0+0.x86_64-linux-musl.tar.gz/md5/d14e89c0473ccbfa0ccb6291069f605b -nghttp2.v1.59.0+0.x86_64-linux-musl.tar.gz/sha512/5255c8e9b501b636fd78b90b46c7e46d583f1ec3328a512153f2460c3f5136ac024e9c9f05c44be8efb8eee687b95080154c6c086358755c167ff9defac37146 -nghttp2.v1.59.0+0.x86_64-unknown-freebsd.tar.gz/md5/3a396ec020b3e9f067ffbe36315f250a -nghttp2.v1.59.0+0.x86_64-unknown-freebsd.tar.gz/sha512/bfc14de5851428548816f289032dce4adcfd17d3ffddd77785777f573df5950ae40df006164ef256eda19a9402101c05dcd994e8bf4f566ddb73a51b8cc1a641 -nghttp2.v1.59.0+0.x86_64-w64-mingw32.tar.gz/md5/300bf8563122e081a17a836fd0d62b6e -nghttp2.v1.59.0+0.x86_64-w64-mingw32.tar.gz/sha512/7967faa9ff64897e4ea6cddff8e70c823472b9b0a814055b7032546cdada76904b28d4b3d0408377108e54b5aac67b83177c03afd71424bb2d4a5bd1d3f96827 +nghttp2-1.60.0.tar.bz2/md5/ec20d9a6df7cc006894f72f81f9f2b42 +nghttp2-1.60.0.tar.bz2/sha512/95b76dd492dad490640469c4b806dd1a446f11143bc990220ff106fe4bfb76cdc4dfb112e0297c543b2d828f2870aa09ba820d88e3e9dedb29c8f3d3c9741af8 +nghttp2.v1.60.0+0.aarch64-apple-darwin.tar.gz/md5/dbf9f8161a124dc88ba44b54094b96e4 +nghttp2.v1.60.0+0.aarch64-apple-darwin.tar.gz/sha512/1997f473ea802afb09d7e13feb4eec9c11ad1d161cf83659ef6059a7c81639e00f8a3461c3538c81ea025e359b0927c3a362cef4a57e6544ad27588683142203 +nghttp2.v1.60.0+0.aarch64-linux-gnu.tar.gz/md5/d2e821a693d7d0720f0158b3e19ef7fa +nghttp2.v1.60.0+0.aarch64-linux-gnu.tar.gz/sha512/4165a1282d125b461d670d7d953c8a06b6508d1b97383a4126bc2fa9641454a9e0be749dbbaf772f2c2e6ea8cc3e64eb980cb0e09ac3d2fe5533eb3e6f7fa9e8 +nghttp2.v1.60.0+0.aarch64-linux-musl.tar.gz/md5/61ecc91336fcddb0f58af6af167e9a81 +nghttp2.v1.60.0+0.aarch64-linux-musl.tar.gz/sha512/802c7455e8f1ddfea74d3de3ceb937d1d10312f51594257cd406aedd67c181ada6ee5115bca00f8ee340a1471e2903bbe0159a0c08b80c556188647345e2c85b +nghttp2.v1.60.0+0.armv6l-linux-gnueabihf.tar.gz/md5/2998ae8d24d1bd540a29e0c6054bfcc8 +nghttp2.v1.60.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/5b2235a0c8bded57adcbab11dbe97b85a7d6d8a083c155bd74b0ac5546aa861730e88b615f1cbfa1071fcc2eb252aae8508e926ad3d5a1ddf0374536c260217e +nghttp2.v1.60.0+0.armv6l-linux-musleabihf.tar.gz/md5/7ebec92e3b340e25b952ccc4e714aa2e +nghttp2.v1.60.0+0.armv6l-linux-musleabihf.tar.gz/sha512/eb0e5c584527182816203ce9bfc35688a969803104ffd17dd4ac3720c27a4fcde3b3b471bf66fda8ac83ec8a56aa82d6d40f492ce06cbf6af39fafc60f35574d +nghttp2.v1.60.0+0.armv7l-linux-gnueabihf.tar.gz/md5/8c124c0daf59c622aedc7b9f1423d522 +nghttp2.v1.60.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/6e03246d1bfef7f184da68ac0eacc975dcb99172f2f352ce4ea5f5ae77536812163874d7ffc4fcb2df65dc51079880fdb83afc8988b73edb241cb641dc72f1fb +nghttp2.v1.60.0+0.armv7l-linux-musleabihf.tar.gz/md5/79968e1cb68c3b0518db528933251b0e +nghttp2.v1.60.0+0.armv7l-linux-musleabihf.tar.gz/sha512/f40790aa9a86fa2f44072c36a33416a7a8b4778881233989f8ed64ccb84f59ccdf3632b7a9d48d3e434e26cbd48c020e5d208da8fcb96e4e4ad41757e050213a +nghttp2.v1.60.0+0.i686-linux-gnu.tar.gz/md5/1580bf21084fa62ec26020f5c89430a1 +nghttp2.v1.60.0+0.i686-linux-gnu.tar.gz/sha512/cf83afe1bb796c57e220c0ba32a6990830df50cd91f82c781f2722d7b0ca5e5fbd8b708a0204be65bb8838c85b548f867c97e85941d124b81c67e01738f1db1a +nghttp2.v1.60.0+0.i686-linux-musl.tar.gz/md5/605eb6cd67b6fe3a1ba2d95413635831 +nghttp2.v1.60.0+0.i686-linux-musl.tar.gz/sha512/2c626b76898b4d782038661601fe34580c3cd560a519a46c4f6bc62d94ab987c7f2984350fc65933c00850cd2fe0b942fc64fcb23d2fb7db29bfed5866291b1a +nghttp2.v1.60.0+0.i686-w64-mingw32.tar.gz/md5/5b5694f36addbc503bc1e78e57159e5a +nghttp2.v1.60.0+0.i686-w64-mingw32.tar.gz/sha512/e70069b1dde2cf4dd041c4cc1c1ff40f67c20a8954b88d997fd7bf03d925b08148bc55293380dffce8c3b550a0e5768c94066e1a3b881ce4109ee94076c9a8b8 +nghttp2.v1.60.0+0.powerpc64le-linux-gnu.tar.gz/md5/1d073bba8e90c970bf1325a3d150d129 +nghttp2.v1.60.0+0.powerpc64le-linux-gnu.tar.gz/sha512/7e6f3895316d47a701944e8ee192b56f66aa05bf212c41164d25a0507f0e54c4c58c856e1c464fe3ec3eae78e0fe09ba8cf8b595c246faa3300a797750677180 +nghttp2.v1.60.0+0.x86_64-apple-darwin.tar.gz/md5/27d405bf53d4d438f74f91176d638741 +nghttp2.v1.60.0+0.x86_64-apple-darwin.tar.gz/sha512/59c4b4cca09e9a99e2e9ccc765068870824b907577c385313568ea29cd395caa3352bda230238888412b625e4a428a24c9ae0e59d122730cbd8025c6edbf0196 +nghttp2.v1.60.0+0.x86_64-linux-gnu.tar.gz/md5/ed1fe996e4c3e51d9ea8f724883dd3bc +nghttp2.v1.60.0+0.x86_64-linux-gnu.tar.gz/sha512/0b20db04ef7b2cc470b9abaab05d0e1e7ea3d674c1ed47c63e1cda00b98a6f10ce19ceb77ebd5ece28f6e4a2cf46227f5858f767ff0f04feed867c57941793ee +nghttp2.v1.60.0+0.x86_64-linux-musl.tar.gz/md5/cf3fcdb5720633700e4f9a9d8cd0cfc0 +nghttp2.v1.60.0+0.x86_64-linux-musl.tar.gz/sha512/d8f87b354de0f47be21b8e3aab6c2b05ee2af377e4bcc7df692fc4dd361ee5b731a190a0d9b4d4fdedf9c3a6a8a300f43338b38ac096da39ec13d4b79b544144 +nghttp2.v1.60.0+0.x86_64-unknown-freebsd.tar.gz/md5/b83aba7b3bd97ed7de770a597d6ec374 +nghttp2.v1.60.0+0.x86_64-unknown-freebsd.tar.gz/sha512/e40e47835bb0d5d548fbcfb28a64124323422bcdab411bcee7d4288cea765c6c82d7f4586980ee28b6ff310c6c7313aa4185ede192cd94839fbe708ab1ed14a7 +nghttp2.v1.60.0+0.x86_64-w64-mingw32.tar.gz/md5/37ba862c196b4d7c063cddc87722f7ff +nghttp2.v1.60.0+0.x86_64-w64-mingw32.tar.gz/sha512/ce0b70b4ad5cb30b83e672c3875fac7bcc8fc039506f05fef552a9d9cb53f053187dd02da4550dd7e5ef9aaaf8d587cee331eace0335f663d4190bacbc4ff9a2 diff --git a/deps/nghttp2.version b/deps/nghttp2.version index a893c5ee8085e7..e9587297d0e322 100644 --- a/deps/nghttp2.version +++ b/deps/nghttp2.version @@ -3,4 +3,4 @@ NGHTTP2_JLL_NAME := nghttp2 ## source build -NGHTTP2_VER := 1.59.0 +NGHTTP2_VER := 1.60.0 diff --git a/stdlib/Manifest.toml b/stdlib/Manifest.toml index 456eee252e7740..ac271b14c90480 100644 --- a/stdlib/Manifest.toml +++ b/stdlib/Manifest.toml @@ -292,7 +292,7 @@ version = "5.8.0+1" [[deps.nghttp2_jll]] deps = ["Artifacts", "Libdl"] uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.59.0+0" +version = "1.60.0+0" [[deps.p7zip_jll]] deps = ["Artifacts", "Libdl"] diff --git a/stdlib/nghttp2_jll/Project.toml b/stdlib/nghttp2_jll/Project.toml index ea7ca1615f0501..88e60941f65ee8 100644 --- a/stdlib/nghttp2_jll/Project.toml +++ b/stdlib/nghttp2_jll/Project.toml @@ -1,6 +1,6 @@ name = "nghttp2_jll" uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" -version = "1.59.0+0" +version = "1.60.0+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/nghttp2_jll/test/runtests.jl b/stdlib/nghttp2_jll/test/runtests.jl index daa848d19f9b67..b6ddefb8222cd3 100644 --- a/stdlib/nghttp2_jll/test/runtests.jl +++ b/stdlib/nghttp2_jll/test/runtests.jl @@ -11,5 +11,5 @@ end @testset "nghttp2_jll" begin info = unsafe_load(ccall((:nghttp2_version,libnghttp2), Ptr{nghttp2_info}, (Cint,), 0)) - @test VersionNumber(unsafe_string(info.version_str)) == v"1.59.0" + @test VersionNumber(unsafe_string(info.version_str)) == v"1.60.0" end From 324e353a07db80676622606ba4afc5bc9793004c Mon Sep 17 00:00:00 2001 From: FX Coudert Date: Tue, 26 Mar 2024 02:23:27 +0100 Subject: [PATCH 030/123] Update patchelf to 0.18.0 (#53845) Released Apr 23, 2023: https://github.com/NixOS/patchelf/releases/tag/0.18.0 --- deps/checksums/patchelf | 4 ++-- deps/patchelf.version | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deps/checksums/patchelf b/deps/checksums/patchelf index a7122c400749a2..e2029b83f14fc2 100644 --- a/deps/checksums/patchelf +++ b/deps/checksums/patchelf @@ -1,2 +1,2 @@ -patchelf-0.13.tar.bz2/md5/d387eee9325414be0b1a80c8fbd2745f -patchelf-0.13.tar.bz2/sha512/43c3f99fe922e2f34d860389165bcc2b0f3f3317e124eb8443017f71b1f223d96a7c815dc81f51b14958b7dc316f75c4ab367ccc287cd99c82abe890b09a478d +patchelf-0.18.0.tar.bz2/md5/9b091a689583fdc7c3206679586322d5 +patchelf-0.18.0.tar.bz2/sha512/bf26194ca3435b141dd330890fcc0c9d805d0ad6a537901dabe6707a13cd28e7e6217462f3ebb3cb4861302dd8632342ec988fc18246c35332a94f2b349d4f4f diff --git a/deps/patchelf.version b/deps/patchelf.version index bbeaa87d25136a..9038338d45faf4 100644 --- a/deps/patchelf.version +++ b/deps/patchelf.version @@ -1,3 +1,3 @@ ## source build # Patchelf (we don't ship this or even use a JLL, we just always build it) -PATCHELF_VER := 0.13 +PATCHELF_VER := 0.18.0 From bf9079afb05829f51e60db888cb29a7c45296ee1 Mon Sep 17 00:00:00 2001 From: FX Coudert Date: Tue, 26 Mar 2024 02:30:06 +0100 Subject: [PATCH 031/123] update PCRE2 to 10.43.0 (#53838) Released on 16 February 2024. Among the changes is support for Unicode 15.0.0 --- deps/checksums/pcre | 68 +++++++++++++++---------------- deps/pcre.version | 2 +- stdlib/Manifest.toml | 2 +- stdlib/PCRE2_jll/Project.toml | 2 +- stdlib/PCRE2_jll/test/runtests.jl | 2 +- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/deps/checksums/pcre b/deps/checksums/pcre index 9b9717b61688b2..744d16540d6c86 100644 --- a/deps/checksums/pcre +++ b/deps/checksums/pcre @@ -1,34 +1,34 @@ -PCRE2.v10.42.0+1.aarch64-apple-darwin.tar.gz/md5/667a570d341396c3213749ee1e5b5fda -PCRE2.v10.42.0+1.aarch64-apple-darwin.tar.gz/sha512/c1bb99e8928efded9b0ea3f294ceb41daea7254204ca30c0ff88686110ccd58138d8ea8b20b9a9d6d16a6d8d3f34e27e74e7b57d3c8fe6b051c9d8fa6f86431a -PCRE2.v10.42.0+1.aarch64-linux-gnu.tar.gz/md5/1a758f275ff3306fbad7698df7b9b7be -PCRE2.v10.42.0+1.aarch64-linux-gnu.tar.gz/sha512/d09508c0b255366d01f1b4d1ae6748a8e47f18c451498d30715f5f968784990949dab7540cd086396abd912f61b5f7c44c8c72a27efaba0a7fc08b71a167c057 -PCRE2.v10.42.0+1.aarch64-linux-musl.tar.gz/md5/e61147579fdc9b57a61b814bdf9c84bb -PCRE2.v10.42.0+1.aarch64-linux-musl.tar.gz/sha512/eecaf4c1937fc04210b910ac65318524c02d690e8c4894c38e74eaba36d26c87a1fd9e1cc36f4307a11ff3552a79f081fa8f05085435eb34872dc2fdecce2d18 -PCRE2.v10.42.0+1.armv6l-linux-gnueabihf.tar.gz/md5/b4c484a3b87923c0e2e4d9cc5f140eb7 -PCRE2.v10.42.0+1.armv6l-linux-gnueabihf.tar.gz/sha512/5931cf13d340971356a9b87f62c9efdb3656ba649e7b25f1722127a3fd70973d94c815a37b43cecab8eb0ed8d1ae02ef1a0c0a12051852c1b9242c3eaa01c496 -PCRE2.v10.42.0+1.armv6l-linux-musleabihf.tar.gz/md5/bc7b5bb1c5b0b99c121bad5a89299ca7 -PCRE2.v10.42.0+1.armv6l-linux-musleabihf.tar.gz/sha512/86b5ad4fa6f4b5bd1a76ad68ddff4b39916d0ed0acc03a3fee8eab5256aaed53abc0ff4ce9d9d9f8b9203c087211684da92fe6aa06ff5bc331ba1b3da2cba57e -PCRE2.v10.42.0+1.armv7l-linux-gnueabihf.tar.gz/md5/3541eb26fa5a4d13e2c7d063dbd900d8 -PCRE2.v10.42.0+1.armv7l-linux-gnueabihf.tar.gz/sha512/872181f931662edaf653351486c5e2a700e94cfa0966ca90eca893fdc75dd46eb40d9d45737c198aa4b9ad8ebab33fd78697ef35906985e4e1c9748ddf58d363 -PCRE2.v10.42.0+1.armv7l-linux-musleabihf.tar.gz/md5/fe059feb18fcc9312f1033362070fe34 -PCRE2.v10.42.0+1.armv7l-linux-musleabihf.tar.gz/sha512/5a96acf3908c964ccb4f296c449499388ed447d9a094c2760c979e02ef656fa710ede3926b9626e89fb5b0545c111e6eedff21e48416e923c17fc9ff129d0519 -PCRE2.v10.42.0+1.i686-linux-gnu.tar.gz/md5/d6c804ae6cc661d039ee3edd2f1dbcb6 -PCRE2.v10.42.0+1.i686-linux-gnu.tar.gz/sha512/256ca677b169854686ca34cf30af5a6709758b41b65f2c66d497c552858770a69a49834fd16daa2f7d481964b21a2e3ec68ff1b1fbd08f4e2257ec46b85c0063 -PCRE2.v10.42.0+1.i686-linux-musl.tar.gz/md5/092af10d8182cb4240cdd975efce4d7c -PCRE2.v10.42.0+1.i686-linux-musl.tar.gz/sha512/79a48f4fd50ffdf49c8d57581e01ace38c1b3d7edd86d44db44b8efd93074d16faf035131a0d60c6631b8bf22f0fd8296acedba45908da56e8096c296122f047 -PCRE2.v10.42.0+1.i686-w64-mingw32.tar.gz/md5/bafc5fc1621d0f4fb2b7b271e2f66db1 -PCRE2.v10.42.0+1.i686-w64-mingw32.tar.gz/sha512/a5ac2b788fb2e4baf129fb339f28da04e9a5c9b7dbba0a1f43da2a7193917d361d961ba48abd0aeec30d2352ebaa401d667c8eec81c5f40859ef8adf8487edca -PCRE2.v10.42.0+1.powerpc64le-linux-gnu.tar.gz/md5/0de1215b2a1e9c0efd131355e9fbf2c1 -PCRE2.v10.42.0+1.powerpc64le-linux-gnu.tar.gz/sha512/69dae12627685ae665db8c91264a79aba7c60ae97eccdc79ef889f2a5f69b465fa333aba298fc90bbb95710cfc324e3630bc427a97577855e8fb6c8fe227cfec -PCRE2.v10.42.0+1.x86_64-apple-darwin.tar.gz/md5/c5c52b399921c5ab81a5f598b350d2ca -PCRE2.v10.42.0+1.x86_64-apple-darwin.tar.gz/sha512/e6c8ba3aa3fbf54b37079301ab317104c6852812b23835f52ca40f31f0831678172d32e077fbaa712a8a2cb16d62bb97d475827004353e7807922a2d6e049b28 -PCRE2.v10.42.0+1.x86_64-linux-gnu.tar.gz/md5/b074dd1f85e24e723349e566350e2c78 -PCRE2.v10.42.0+1.x86_64-linux-gnu.tar.gz/sha512/236017e02c9f32b913b772dbf22897c8460e5791f196c86f8a073e329ad8925f6859afe48f3bf18ca057c265f08fedbde255360d8f859e2303c6569ab1b0e1bb -PCRE2.v10.42.0+1.x86_64-linux-musl.tar.gz/md5/9f32ca77e79843fc9c4b5fc8ed336d11 -PCRE2.v10.42.0+1.x86_64-linux-musl.tar.gz/sha512/334a31724e9d69c6517568d922717ce76d85cf87dbc863b7262b25ab43c79734b457833cd42674eb6a004864e5c74da3ae1d0a45794b4cd459eea24d9669fac5 -PCRE2.v10.42.0+1.x86_64-unknown-freebsd.tar.gz/md5/76cde3c509ed39ca67a18fe58e728821 -PCRE2.v10.42.0+1.x86_64-unknown-freebsd.tar.gz/sha512/219c82067a242554c523be5be2b5561cd955609eac1addc336004df64a2a12e815ea40ff94d3f610970f7d0215b410f098d4baaa2c722f5cf21dab175b288b7e -PCRE2.v10.42.0+1.x86_64-w64-mingw32.tar.gz/md5/b0771d5b0132b554776e7cee0e1374e6 -PCRE2.v10.42.0+1.x86_64-w64-mingw32.tar.gz/sha512/d4435ff703e51c88df7764a732d6b67b1ee4d3b09b915ac822af05a33347642691837818d4c389226ef1d70cd69dbac792ebe1e7de1d8900443fe162051916ae -pcre2-10.42.tar.bz2/md5/a8e9ab2935d428a4807461f183034abe -pcre2-10.42.tar.bz2/sha512/72fbde87fecec3aa4b47225dd919ea1d55e97f2cbcf02aba26e5a0d3b1ffb58c25a80a9ef069eb99f9cf4e41ba9604ad06a7ec159870e1e875d86820e12256d3 +PCRE2.v10.43.0+0.aarch64-apple-darwin.tar.gz/md5/f1bee27b8d9465c14eaf9362701fb795 +PCRE2.v10.43.0+0.aarch64-apple-darwin.tar.gz/sha512/33b8f6e3703f0a52cd2d57897c28e35fb3c63af459296a2fef4e414dc99239617833b2ab176068d6aab690122a34a9ab9b6042dfff54b5a30ad60429a809818d +PCRE2.v10.43.0+0.aarch64-linux-gnu.tar.gz/md5/c55a569260e302f315f4a1bd185346ab +PCRE2.v10.43.0+0.aarch64-linux-gnu.tar.gz/sha512/be4d2883e69d562898a157424b2baa146fe79545a8c10935cf25b54e498ca2c14fae026fa0d958d175895fe2cb695d0f96ef7f09fecbf54e1cee4a55b81a382b +PCRE2.v10.43.0+0.aarch64-linux-musl.tar.gz/md5/fb041ccace415ccc26263968c6435a47 +PCRE2.v10.43.0+0.aarch64-linux-musl.tar.gz/sha512/06672ebe18e0f6bfa1dd2d5c02e10d9fd67236a73fd38ee2e8f4496d98f297f7866760f0be3b9cebeca348a5d748a3719e416b84cec96a90c71eac55afbbd905 +PCRE2.v10.43.0+0.armv6l-linux-gnueabihf.tar.gz/md5/4f303a4cbf26abb7bf4ffb8bfe3d636d +PCRE2.v10.43.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/dddb3b227ee48d8329f6c65c5d0fce9f460eccaec98594a05bf28d1d9af01397cf7ef86c96e88b0e96030a7f6d8406461f78dd5fa558db8fc8f7bfb3b522ed54 +PCRE2.v10.43.0+0.armv6l-linux-musleabihf.tar.gz/md5/eade1fff90404bf3584fd15b62be0cfa +PCRE2.v10.43.0+0.armv6l-linux-musleabihf.tar.gz/sha512/351f6fa11c39b90fcc4086bd00b1b1126ed92272595f0b745757ca4e7e360c84d244446a871029245c3bcf838b23f42d908f858e44fae7deb9002a36cb76753c +PCRE2.v10.43.0+0.armv7l-linux-gnueabihf.tar.gz/md5/daa0a34b2cf0b71a6f8e1f9456cd4b06 +PCRE2.v10.43.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/ae72956ae7a9a5f315bfc816fdbb500937a170dfea306a28289ec9eac57d883cf2fa5a467ce9406eea80546b632a272c63bbb48b89ebe6d9f69d30366fd84180 +PCRE2.v10.43.0+0.armv7l-linux-musleabihf.tar.gz/md5/90bfb9e4efd7c92a2bb6a1a48fd88ecb +PCRE2.v10.43.0+0.armv7l-linux-musleabihf.tar.gz/sha512/147ac98d82fec4695de0c43c87d3d9242b9c024bc6df7ad7504d17ef6a12a029ed703c4deade0e2b24faf5283d66309f880d62f8c4834f27b2cc8889587d7abe +PCRE2.v10.43.0+0.i686-linux-gnu.tar.gz/md5/6fde649bf449c4122438fff32c0706ab +PCRE2.v10.43.0+0.i686-linux-gnu.tar.gz/sha512/edfaa15490497723c095eaa5df26194637b0606e9dce7b89b400024ef8ac42e21f010bb31c2cee5c735ce82fc8de0c42bf2b35b095a1e70a9a111d3bfba6da64 +PCRE2.v10.43.0+0.i686-linux-musl.tar.gz/md5/73aa8d13cc48338a5071e30b3a899109 +PCRE2.v10.43.0+0.i686-linux-musl.tar.gz/sha512/200e2d3ffd68f49b76c70a5be80cb0ae9703049214674485a2ab24abaaea7aefd6dec2042a14bd48cc52b04379f57322ec1e1788dc8c00896e1074921725d9cc +PCRE2.v10.43.0+0.i686-w64-mingw32.tar.gz/md5/4ddf0f31c97463e5216ed71afc4fb014 +PCRE2.v10.43.0+0.i686-w64-mingw32.tar.gz/sha512/75903d81668a66a5c4d830e31657391d507883943d86245998f224655406dcc6a95ba4f5fad20dcf608a98d6ccf49abe50107993448669b03c42a878d8466611 +PCRE2.v10.43.0+0.powerpc64le-linux-gnu.tar.gz/md5/64cb71080da1c97eba3a440ff53d298c +PCRE2.v10.43.0+0.powerpc64le-linux-gnu.tar.gz/sha512/16348b96a45c7a7d86775cb1d082b4d1c060e5a8acfb37554885d8da0db87430d8a40f834f008a90f4a7b1c07b8329df96836ba0430ecec506a143b7347bb101 +PCRE2.v10.43.0+0.x86_64-apple-darwin.tar.gz/md5/31bbb2485f5e06c3616fb061ffb2f022 +PCRE2.v10.43.0+0.x86_64-apple-darwin.tar.gz/sha512/3284ee63ed1e5631267efacb354a1d90bd1b7db0bc81d7233c9580eee4a9af06093c1c4f240786c34299df89a36a17ed92598fc302074f5a200c56cc96081bf1 +PCRE2.v10.43.0+0.x86_64-linux-gnu.tar.gz/md5/2fb7e0e9bbc32dddf543f4d395b50d3f +PCRE2.v10.43.0+0.x86_64-linux-gnu.tar.gz/sha512/5a533a3a01f817689077377835dc88edf914459ed0df7323f8f4dba602a47fd6af700075feb1f448221366b1cf7e2d717c615a5c506eb4ca2db9c600fd290fb0 +PCRE2.v10.43.0+0.x86_64-linux-musl.tar.gz/md5/b432063c93aa477dd0883428191041f8 +PCRE2.v10.43.0+0.x86_64-linux-musl.tar.gz/sha512/36475e90e29d7324046fe1da669fb37f667245a680df23f3978394964e14eb9bda3fd56703ad62cd56e27a5af77d8b6b9612516457ae803cef0627bd919e4628 +PCRE2.v10.43.0+0.x86_64-unknown-freebsd.tar.gz/md5/6124870a991e70c2ed8a64d8f3258760 +PCRE2.v10.43.0+0.x86_64-unknown-freebsd.tar.gz/sha512/4645a2d05af149467f2e4ce5e48853b57c585d6a5950c70726d04bc71a5d82f50809af141ad98e99671e764ac74965651ecad1c49a849caa8fd077c7f4911c7c +PCRE2.v10.43.0+0.x86_64-w64-mingw32.tar.gz/md5/cc4e9f45471f538c1fefa657ab99b878 +PCRE2.v10.43.0+0.x86_64-w64-mingw32.tar.gz/sha512/eed45e621263cb307b6e8ab42e2c12cf9e1d61ad523760fd721a85765c359b74d580752ca7c3d222e0cba26a74e872a6d43dbf2dbf08e4733a3e709417e48651 +pcre2-10.43.tar.bz2/md5/c8e2043cbc4abb80e76dba323f7c409f +pcre2-10.43.tar.bz2/sha512/8ac1520c32e9e5672404aaf6104e23c9ee5c3c28ad28ff101435599d813cbb20e0491a3fd34e012b4411b3e0366a4c6dfa3f02d093acaa6ff0ab25478bb7ade9 diff --git a/deps/pcre.version b/deps/pcre.version index ce27921435e1d7..e3ea5073761054 100644 --- a/deps/pcre.version +++ b/deps/pcre.version @@ -2,4 +2,4 @@ PCRE_JLL_NAME := PCRE2 ## source build -PCRE_VER := 10.42 +PCRE_VER := 10.43 diff --git a/stdlib/Manifest.toml b/stdlib/Manifest.toml index ac271b14c90480..88a91a8db0bd68 100644 --- a/stdlib/Manifest.toml +++ b/stdlib/Manifest.toml @@ -174,7 +174,7 @@ version = "0.8.1+2" [[deps.PCRE2_jll]] deps = ["Artifacts", "Libdl"] uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" -version = "10.42.0+1" +version = "10.43.0+0" [[deps.Pkg]] deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] diff --git a/stdlib/PCRE2_jll/Project.toml b/stdlib/PCRE2_jll/Project.toml index 788d6b733234fa..f9b3affb51b632 100644 --- a/stdlib/PCRE2_jll/Project.toml +++ b/stdlib/PCRE2_jll/Project.toml @@ -1,6 +1,6 @@ name = "PCRE2_jll" uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" -version = "10.42.0+1" +version = "10.43.0+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/PCRE2_jll/test/runtests.jl b/stdlib/PCRE2_jll/test/runtests.jl index d593b07af31ce8..af0ed9434d2b60 100644 --- a/stdlib/PCRE2_jll/test/runtests.jl +++ b/stdlib/PCRE2_jll/test/runtests.jl @@ -6,5 +6,5 @@ using Test, Libdl, PCRE2_jll vstr = zeros(UInt8, 32) @test ccall((:pcre2_config_8, libpcre2_8), Cint, (UInt32, Ref{UInt8}), 11, vstr) > 0 vn = VersionNumber(split(unsafe_string(pointer(vstr)), " ")[1]) - @test vn == v"10.42.0" + @test vn == v"10.43.0" end From 018152fc21470362a4ddb14c649c0dd6964115dc Mon Sep 17 00:00:00 2001 From: FX Coudert Date: Tue, 26 Mar 2024 04:46:12 +0100 Subject: [PATCH 032/123] Update zlib to 1.3.1 (#53841) Released January 22, 2024 --- deps/checksums/zlib | 68 ++++++++++++++++---------------- deps/zlib.version | 6 +-- stdlib/Manifest.toml | 2 +- stdlib/Zlib_jll/Project.toml | 2 +- stdlib/Zlib_jll/test/runtests.jl | 2 +- 5 files changed, 40 insertions(+), 40 deletions(-) diff --git a/deps/checksums/zlib b/deps/checksums/zlib index 72fd884183e47c..b6fc106747c67e 100644 --- a/deps/checksums/zlib +++ b/deps/checksums/zlib @@ -1,34 +1,34 @@ -Zlib.v1.2.13+1.aarch64-apple-darwin.tar.gz/md5/bc44b2016065fb20cbd639b3cd5dbb88 -Zlib.v1.2.13+1.aarch64-apple-darwin.tar.gz/sha512/9cfecc16a29b0a13282846ed7d4c17c420b3f62379777d3fac61a8c9c4eeaf4214b826cd9f7479f480e951617b22c96e6ca2976a709345e16fbe7f81e9bdd83f -Zlib.v1.2.13+1.aarch64-linux-gnu.tar.gz/md5/a2d3265543017db03bc47b9d9778d99d -Zlib.v1.2.13+1.aarch64-linux-gnu.tar.gz/sha512/c8143445222e151d7f522a98ee8f2742571542f4e71d515e88086c9d7f27b952662ced93f40c795e0de42e3a07c0cb5e1d9d8e792347f3c068cb07ccc144a640 -Zlib.v1.2.13+1.aarch64-linux-musl.tar.gz/md5/c1f2a1c562f72c7aa4b228f57c2346d4 -Zlib.v1.2.13+1.aarch64-linux-musl.tar.gz/sha512/7ed89bc7696690c03617c7413f5456ff5a1caa0dd600880ae67132f6c9190672ae451a06d23956a1969be00bf5c8f29bfa4f5bc4ab646b3b375c350f67c993e5 -Zlib.v1.2.13+1.armv6l-linux-gnueabihf.tar.gz/md5/7dff966f7bc5dd2902fa9ce20444235b -Zlib.v1.2.13+1.armv6l-linux-gnueabihf.tar.gz/sha512/49e7b4a7c84996b697cf944b11ce06ce6064983a6a911c4539587385afa1e0119e3b1dbf816703a2c132acc90f7f114ec10631647638b59b14954382c1a82014 -Zlib.v1.2.13+1.armv6l-linux-musleabihf.tar.gz/md5/6982f19d2446559c0fd369afe84ebe4a -Zlib.v1.2.13+1.armv6l-linux-musleabihf.tar.gz/sha512/8f69dfb7fb91cd6f7c934e1acddd83f77c2ebcc1732553f41ae1adcb7805a3304d16062133ce5094a8aea18ff5eca5f7a2df5724ae5a5cb9137caee732c1bf36 -Zlib.v1.2.13+1.armv7l-linux-gnueabihf.tar.gz/md5/30579a91f8f1c96752fe9a82bc053523 -Zlib.v1.2.13+1.armv7l-linux-gnueabihf.tar.gz/sha512/64f6a0e66ee13b086609e0d070c8742de20052e1ef43da201be0007e478c65b2f0a28a3c19ca5be6537b7c8bbeb6a4b2886c15a1e47bb2bd1cfe9d5e1590a620 -Zlib.v1.2.13+1.armv7l-linux-musleabihf.tar.gz/md5/b052ad151dbc3bad78762bc06164d667 -Zlib.v1.2.13+1.armv7l-linux-musleabihf.tar.gz/sha512/b5d2de09a4d65d898cf9ba0db34327c712f42a78cd1fd0f1d77fd8798910502049be63ccfed23de5fe3b499d9e0fe3d4cbb07c72765fd54db275e92f8f1e4dc4 -Zlib.v1.2.13+1.i686-linux-gnu.tar.gz/md5/3074702010889f586b43aa3dbbda4ceb -Zlib.v1.2.13+1.i686-linux-gnu.tar.gz/sha512/92aa87c5aa3831155305276c2f0da091b5be4e8a396772e1a28650c2837ceb116dd2207329732b653a97c011abd7dd6ac1fc9574ac64cb3049ccd36fa6700748 -Zlib.v1.2.13+1.i686-linux-musl.tar.gz/md5/eff02476825ea7a53ab26b346d58f96e -Zlib.v1.2.13+1.i686-linux-musl.tar.gz/sha512/14b72607d524948198e999e3919ee01046c049b3ec441bc581c77642cf37c3d28cc3c5500a3c073d62e9b8dc1efc9661b23bb925ed9c80b5e69abaddbcb59115 -Zlib.v1.2.13+1.i686-w64-mingw32.tar.gz/md5/138cb27334b8f6f9e818131ac394bf43 -Zlib.v1.2.13+1.i686-w64-mingw32.tar.gz/sha512/07fbf4a21f6cb5a6120be253e5769b8bbdf60658f9f3705222307fbe203d8710de59fd3dab7a35714ebe1a7385600d4e1b01eae0b1addca47f9d8d862173e667 -Zlib.v1.2.13+1.powerpc64le-linux-gnu.tar.gz/md5/bc69de101d9159b22b7a334e2700faa6 -Zlib.v1.2.13+1.powerpc64le-linux-gnu.tar.gz/sha512/174eb4f154594d268d970d23eb6144dd2f6be41ddcfb9bc756b2ff48f0781ad0ed6571e2ead64dab0967da91517a02cd8db2b0e33a0bde9400103b5204f78e85 -Zlib.v1.2.13+1.x86_64-apple-darwin.tar.gz/md5/60279d648bce4801cd0e311ea95a6481 -Zlib.v1.2.13+1.x86_64-apple-darwin.tar.gz/sha512/921fc557317f87012d76f5d2cb0a7bbed29cdfdb2274ed6d37577f8e99dda2afb2a8dd4725d720eb8fb0a93c0d3afe68dd54fdd3a6e7cb07c15607a8aed72f82 -Zlib.v1.2.13+1.x86_64-linux-gnu.tar.gz/md5/b192d547d56124262e2ae744f385efd6 -Zlib.v1.2.13+1.x86_64-linux-gnu.tar.gz/sha512/c6dca3c0a713ef2e2296bc9e9afa75e103a4cc4f00b5c905ebc5cff688904d6a454f83ab5ef3b6c66bdf425daa2fcd25825e50a3534c0ff109b13affbb686179 -Zlib.v1.2.13+1.x86_64-linux-musl.tar.gz/md5/f2a466b38b2ff1c895f630982147a950 -Zlib.v1.2.13+1.x86_64-linux-musl.tar.gz/sha512/191261d37fc501591005bf680d76bf518da261252456c4fef1c12bc572f9200a855fbd1b125bb8ad10d803eedbc53d4c9d7a2861e9a35d629fb40f87e5306f5f -Zlib.v1.2.13+1.x86_64-unknown-freebsd.tar.gz/md5/36e53efdafdb8b8e1fb18817ea40c9ab -Zlib.v1.2.13+1.x86_64-unknown-freebsd.tar.gz/sha512/3067eace2a46b45c071dd1d2c046ab21e3f4a34b87346905bf4c00ef4ea57f41c4c30e32cbd5d4b60a560fa45aeeba7b0ce95566c0889f06f00f7a25de771cb1 -Zlib.v1.2.13+1.x86_64-w64-mingw32.tar.gz/md5/4c14730c6e89a3b05dcf352007f9c1e5 -Zlib.v1.2.13+1.x86_64-w64-mingw32.tar.gz/sha512/b6fbfe93d0c4fc6ebb740dbe0aebaa31aa5ecf352589452f6baac3ee28514531a1d0de9795634f97774ebb492dd23dee9f7865c2b8ba3f70c7f03cdc5430e85a -zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc.tar.gz/md5/60a49c89b9409dd91c1b039266f7bd0c -zlib-04f42ceca40f73e2978b50e93806c2a18c1281fc.tar.gz/sha512/83122539da9399ce5f51c2ecbc38a627405334a9a6d53a024341353c1263a1e3aef7498f30ee281a49b3022be70e992eae475691e33da7a9c6a59b83207bd688 +Zlib.v1.3.1+0.aarch64-apple-darwin.tar.gz/md5/50b48e14f0b3578e3f398d130749a25d +Zlib.v1.3.1+0.aarch64-apple-darwin.tar.gz/sha512/d970e183035b3615b410f7b0da2c7a1d516234744491d65ed1ebc3800b55732f20bf00fcbb0cf91289b8b4660915282873fb23788896713cf8dfae2984a8fd85 +Zlib.v1.3.1+0.aarch64-linux-gnu.tar.gz/md5/ee42c0bae86fc39968c8cd6a77a801bf +Zlib.v1.3.1+0.aarch64-linux-gnu.tar.gz/sha512/5d21cbeab03d44008c6cbad114d45c917ebee2fe98de6b19686f4f6ba1fc67eeedf968b94ed1c2d4efb89e93be9efa342bcc8a57cb8a505085d177abae14bc2d +Zlib.v1.3.1+0.aarch64-linux-musl.tar.gz/md5/9091d1288736b218f7b016791dc1a9c8 +Zlib.v1.3.1+0.aarch64-linux-musl.tar.gz/sha512/b49cbfe734beb2af9ef8e847542d006765345cbb08aee0854779e35e03c98df25c93539b046547c6b66029987c49499ddf6cb207824b1e376900bfceaa79691a +Zlib.v1.3.1+0.armv6l-linux-gnueabihf.tar.gz/md5/b686c85047b7dad2c2f08d1d16e7978a +Zlib.v1.3.1+0.armv6l-linux-gnueabihf.tar.gz/sha512/511fda619519dccedb264988e3b59a0e0fbf8f73d3ae290f238346209ebc0202a22f945257cea19afef64246574285e0322901a46bb48d7b48364c1e2eacd801 +Zlib.v1.3.1+0.armv6l-linux-musleabihf.tar.gz/md5/374be5cb926876f3f0492cfe0e193220 +Zlib.v1.3.1+0.armv6l-linux-musleabihf.tar.gz/sha512/4d3a2cc0c7c48146e63ed098da5a5acad75517197adc965550c123f7f8bcee0811a27be76fa37b6b0515eee4b5ba1c1a85c854e7b23bea36b5e21671805bedce +Zlib.v1.3.1+0.armv7l-linux-gnueabihf.tar.gz/md5/9febbc6a3d492e34c9ed53c95f3b799f +Zlib.v1.3.1+0.armv7l-linux-gnueabihf.tar.gz/sha512/4cee0e2cf572eb91028a09ef356e1aa6360949e046ceec03bd37574295ddcc4a7cefca9276f7565f152697d55b35f62af2ab107cdbf402b42846818629fea9c7 +Zlib.v1.3.1+0.armv7l-linux-musleabihf.tar.gz/md5/5d0d59a6cbbd1e63193ba6f7dbb755f9 +Zlib.v1.3.1+0.armv7l-linux-musleabihf.tar.gz/sha512/ee3f48b354168342ef63509b19a26aca3301fb3e5f4f6898afe2d3b44ee3380515efd6ced5d4e06e69736d851d19352deb9595bad82c051caccaee8c55e629d8 +Zlib.v1.3.1+0.i686-linux-gnu.tar.gz/md5/834350a64b2302a9caf0250a8f6068e5 +Zlib.v1.3.1+0.i686-linux-gnu.tar.gz/sha512/63dc158c4dfc42db97875893fcdd9784d9487af855bd576dbe04d1b967ad64510222df74a4cfb1b7e67386329d2a5686d7931b81720883fc1924f0d706a0a711 +Zlib.v1.3.1+0.i686-linux-musl.tar.gz/md5/e4f96efdeafa3d74c7c348059a8dc46a +Zlib.v1.3.1+0.i686-linux-musl.tar.gz/sha512/b47a571d94887ddcab8d7b50c6dce3afed3f56513a9d1859feaefebfad4a271d428b440df1d19ef3c2ed01ca4c8fd121ffc1572f5e252f27d0930f616cb47f18 +Zlib.v1.3.1+0.i686-w64-mingw32.tar.gz/md5/6bc27bd7dbbe17243dbbfaff225d3b23 +Zlib.v1.3.1+0.i686-w64-mingw32.tar.gz/sha512/5777661682831519875fffbb114c62596bf7bdb62011667c0f3dc5da9910e14de2285200a0a05187769b9c68c99b07024caafc16fef03c76e96e618f77149790 +Zlib.v1.3.1+0.powerpc64le-linux-gnu.tar.gz/md5/27dcad8557994cfd89d6fa7072bb843c +Zlib.v1.3.1+0.powerpc64le-linux-gnu.tar.gz/sha512/3b388dd286b273881d4344cff61c7da316c2bd2bab93072bf47ce4cb1cf9662158351b8febb0d5b1f8dfd9bc73cd32f7cae37fdd19b0ca91531bd3375df104bb +Zlib.v1.3.1+0.x86_64-apple-darwin.tar.gz/md5/9187319377191ae8b34162b375baa5db +Zlib.v1.3.1+0.x86_64-apple-darwin.tar.gz/sha512/895203434f161926978be52a223dd49a99454651a79c1c5e0529fa064f3f7ac2d7a069fed47a577b32523df22afadd6eb97d564dbd59c5d67ed90083add13c00 +Zlib.v1.3.1+0.x86_64-linux-gnu.tar.gz/md5/55d4d982d60cb643aa8688eb031b07ee +Zlib.v1.3.1+0.x86_64-linux-gnu.tar.gz/sha512/d8f94d22ffc37df027de23b2408c2000014c8b7b6c8539feca669ac1f2dbbe1679ca534c3be4d32c90fe38bbba27c795689226962fb067346b5ca213e64b9c4b +Zlib.v1.3.1+0.x86_64-linux-musl.tar.gz/md5/95d735bba178da4b8bee23903419919c +Zlib.v1.3.1+0.x86_64-linux-musl.tar.gz/sha512/370370f08133a720e3fbedcc434f102dc95225fda3ec8a399e782851bd4be57fb2b64a3ed62dc0559fb0c58d2e28db9b9e960efafd940982e4cb6652be0e81f1 +Zlib.v1.3.1+0.x86_64-unknown-freebsd.tar.gz/md5/df158f50fdb8ac1179fe6dad3bc62713 +Zlib.v1.3.1+0.x86_64-unknown-freebsd.tar.gz/sha512/f4ba4ccfeaf3fd2e172a2d5b3b1ae083ee9854022e71e062e29423e4179cb1fc49b2b99df49b3f5f231e2a0c5becc59b89644e9dcaf0fda9c97e83af7ea1c25d +Zlib.v1.3.1+0.x86_64-w64-mingw32.tar.gz/md5/9cc735c54ddf5d1ea0db60e05d6631ea +Zlib.v1.3.1+0.x86_64-w64-mingw32.tar.gz/sha512/8a2fd20944866cb7f717517ea0b80a134466e063f85bec87ffba56ca844f983f91060dfdc65f8faee1981d7329348c827b723aaad4fea36041e710b9e35c43de +zlib-51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf.tar.gz/md5/7ce1b2766499af7d948130113b649028 +zlib-51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf.tar.gz/sha512/79d032b8c93260ce6b9806f2289cdccce67e9d80865b5bb39ac46dadffc8ee009da51c551eead59c56249c7adfa164c1d5ebcf2b10a8645e0b11b5650176cb24 diff --git a/deps/zlib.version b/deps/zlib.version index 89a304c49b6dcb..27d862a4cc35b4 100644 --- a/deps/zlib.version +++ b/deps/zlib.version @@ -3,6 +3,6 @@ ZLIB_JLL_NAME := Zlib ## source build -ZLIB_VER := 1.2.13 -ZLIB_BRANCH=v1.2.13 -ZLIB_SHA1=04f42ceca40f73e2978b50e93806c2a18c1281fc +ZLIB_VER := 1.3.1 +ZLIB_BRANCH=v1.3.1 +ZLIB_SHA1=51b7f2abdade71cd9bb0e7a373ef2610ec6f9daf diff --git a/stdlib/Manifest.toml b/stdlib/Manifest.toml index 88a91a8db0bd68..a9491702f62ad8 100644 --- a/stdlib/Manifest.toml +++ b/stdlib/Manifest.toml @@ -272,7 +272,7 @@ version = "1.11.0" [[deps.Zlib_jll]] deps = ["Libdl"] uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.13+1" +version = "1.3.1+0" [[deps.dSFMT_jll]] deps = ["Artifacts", "Libdl"] diff --git a/stdlib/Zlib_jll/Project.toml b/stdlib/Zlib_jll/Project.toml index b1fa9576af3ecb..bb5771654430b6 100644 --- a/stdlib/Zlib_jll/Project.toml +++ b/stdlib/Zlib_jll/Project.toml @@ -1,6 +1,6 @@ name = "Zlib_jll" uuid = "83775a58-1f1d-513f-b197-d71354ab007a" -version = "1.2.13+1" +version = "1.3.1+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/Zlib_jll/test/runtests.jl b/stdlib/Zlib_jll/test/runtests.jl index f04f9c70a70548..81eb742a172feb 100644 --- a/stdlib/Zlib_jll/test/runtests.jl +++ b/stdlib/Zlib_jll/test/runtests.jl @@ -3,5 +3,5 @@ using Test, Zlib_jll @testset "Zlib_jll" begin - @test VersionNumber(unsafe_string(ccall((:zlibVersion, libz), Cstring, ()))) == v"1.2.13" + @test VersionNumber(unsafe_string(ccall((:zlibVersion, libz), Cstring, ()))) == v"1.3.1" end From 4607d53e5b3fd5ba067b98fda10dc0b7bb341548 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 26 Mar 2024 04:51:28 -0400 Subject: [PATCH 033/123] lowering: Don't bother rewrapping bare linenumbers in hygienic-scope (#53850) JuliaInterpreter tries to do some very questionable pre-lowering introspection to find line numbers, but doesn't properly handle hygienic scope. That should be fixed, but as I was about to put in a hack there, I figured we might as well not bother re-wrapping bare LineNumberNodes in hygienic scopes. They just get discarded again immediately anyway. No functional change in that this is semantically equivalent to what we had before, just with a slightly more compact lowering result and additional JuliaInterpreter test passing. --- src/macroexpand.scm | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/macroexpand.scm b/src/macroexpand.scm index 403df1f3d9ef05..74d47aec45479c 100644 --- a/src/macroexpand.scm +++ b/src/macroexpand.scm @@ -386,6 +386,9 @@ (cdr ranges) (list ranges)))) +(define (just-line? ex) + (and (pair? ex) (eq? (car ex) 'line) (atom? (cadr ex)) (or (atom? (caddr ex)) (nothing? (caddr ex))))) + (define (resolve-expansion-vars- e env m lno parent-scope inarg) (cond ((or (eq? e 'begin) (eq? e 'end) (eq? e 'ccall) (eq? e 'cglobal) (underscore-symbol? e)) e) @@ -417,11 +420,15 @@ ((toplevel) ; re-wrap Expr(:toplevel) in the current hygienic-scope(s) `(toplevel ,@(map (lambda (arg) - (let loop ((parent-scope parent-scope) (m m) (lno lno) (arg arg)) - (let ((wrapped `(hygienic-scope ,arg ,m ,@lno))) - (if (null? parent-scope) wrapped - (loop (cdr parent-scope) (cadar parent-scope) (caddar parent-scope) wrapped))))) - (cdr e)))) + ;; Minor optimization: A lot of toplevel exprs have just bare line numbers in them. + ;; don't bother with the full rewrapping in that case (even though + ;; this would be semantically legal) - lowering won't touch them anyways. + (if (just-line? arg) arg + (let loop ((parent-scope parent-scope) (m m) (lno lno) (arg arg)) + (let ((wrapped `(hygienic-scope ,arg ,m ,@lno))) + (if (null? parent-scope) wrapped + (loop (cdr parent-scope) (cadar parent-scope) (caddar parent-scope) wrapped)))))) + (cdr e)))) ((using import export meta line inbounds boundscheck loopinfo inline noinline purity) (map unescape e)) ((macrocall) e) ; invalid syntax anyways, so just act like it's quoted. ((symboliclabel) e) From 86a697c7fea4e1ed2c2a9487d883b84dd31e8899 Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Tue, 26 Mar 2024 05:20:13 -0400 Subject: [PATCH 034/123] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?Pkg=20stdlib=20from=206859d6857=20to=20162634c56=20(#53846)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: Pkg URL: https://github.com/JuliaLang/Pkg.jl.git Stdlib branch: master Julia branch: master Old commit: 6859d6857 New commit: 162634c56 Julia version: 1.12.0-DEV Pkg version: 1.12.0 Bump invoked by: @KristofferC Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaLang/Pkg.jl/compare/6859d68579e7970daf00720901cf487563dca0da...162634c5615d12b889e4b64f3cff95d1c377f189 ``` $ git log --oneline 6859d6857..162634c56 162634c56 Add workspace feature (#3841) a4ec712eb Remove outdated UUID instructions (#3855) 9c6356fa9 collect e.g. weak deps from project even if it is not a package (#3852) ``` Co-authored-by: Dilum Aluthge --- .../Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/md5 | 1 + .../Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/sha512 | 1 + .../Pkg-6859d68579e7970daf00720901cf487563dca0da.tar.gz/md5 | 1 - .../Pkg-6859d68579e7970daf00720901cf487563dca0da.tar.gz/sha512 | 1 - stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/md5 create mode 100644 deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/sha512 delete mode 100644 deps/checksums/Pkg-6859d68579e7970daf00720901cf487563dca0da.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-6859d68579e7970daf00720901cf487563dca0da.tar.gz/sha512 diff --git a/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/md5 b/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/md5 new file mode 100644 index 00000000000000..c27b9894015ce0 --- /dev/null +++ b/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/md5 @@ -0,0 +1 @@ +4bd123b9499b46a859d5bba5ae2228a5 diff --git a/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/sha512 b/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/sha512 new file mode 100644 index 00000000000000..d4c2d6b185137c --- /dev/null +++ b/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/sha512 @@ -0,0 +1 @@ +5f743255cee291185094bfa86e48f65160bc1ad170f052644b79d90d2f1d3c6c3e2be3c4da25925f3ec4b3f87179f946252cdab199ca510b78064afb0b0df039 diff --git a/deps/checksums/Pkg-6859d68579e7970daf00720901cf487563dca0da.tar.gz/md5 b/deps/checksums/Pkg-6859d68579e7970daf00720901cf487563dca0da.tar.gz/md5 deleted file mode 100644 index d8e436d51267c9..00000000000000 --- a/deps/checksums/Pkg-6859d68579e7970daf00720901cf487563dca0da.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -16cb4d2bcc0bc1c13aa5f1ee02f5f8ee diff --git a/deps/checksums/Pkg-6859d68579e7970daf00720901cf487563dca0da.tar.gz/sha512 b/deps/checksums/Pkg-6859d68579e7970daf00720901cf487563dca0da.tar.gz/sha512 deleted file mode 100644 index 43b4ed2a684567..00000000000000 --- a/deps/checksums/Pkg-6859d68579e7970daf00720901cf487563dca0da.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -e92cb66a66bcdb9c717c868912b0b53e25f4a04ce380714f619e5be36e07ff21f457c87c2a2af23460f6703fdfd9f931ad65a47c0ff96a39a3075f1ca54275ae diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 2fcaa62d4d3982..0fcf00277a6f8a 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = 6859d68579e7970daf00720901cf487563dca0da +PKG_SHA1 = 162634c5615d12b889e4b64f3cff95d1c377f189 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 From 64de065a183ac70bb049f7f9e30d790f8845dd2b Mon Sep 17 00:00:00 2001 From: FX Coudert Date: Tue, 26 Mar 2024 13:56:03 +0100 Subject: [PATCH 035/123] Update libgit2 to 1.8.0 (#53840) According to the release notes, three breaking (ABI) changes are handled here: - `GIT_CONFIG_LEVEL_WORKTREE` constant (and modification to value of `GIT_CONFIG_LEVEL_APP`) - `git_config_entry` structure - `git_push_options` structure https://github.com/libgit2/libgit2/releases/tag/v1.8.0 --- deps/checksums/cacert-2023-12-12.pem/md5 | 1 - deps/checksums/cacert-2023-12-12.pem/sha512 | 1 - deps/checksums/cacert-2024-03-11.pem/md5 | 1 + deps/checksums/cacert-2024-03-11.pem/sha512 | 1 + deps/checksums/libgit2 | 68 ++++++++++----------- deps/libgit2.version | 6 +- stdlib/LibGit2/src/consts.jl | 27 +++++++- stdlib/LibGit2/src/types.jl | 14 ++++- stdlib/LibGit2_jll/Project.toml | 2 +- stdlib/LibGit2_jll/src/LibGit2_jll.jl | 4 +- stdlib/LibGit2_jll/test/runtests.jl | 2 +- stdlib/Manifest.toml | 2 +- stdlib/MozillaCACerts_jll/Project.toml | 2 +- 13 files changed, 84 insertions(+), 47 deletions(-) delete mode 100644 deps/checksums/cacert-2023-12-12.pem/md5 delete mode 100644 deps/checksums/cacert-2023-12-12.pem/sha512 create mode 100644 deps/checksums/cacert-2024-03-11.pem/md5 create mode 100644 deps/checksums/cacert-2024-03-11.pem/sha512 diff --git a/deps/checksums/cacert-2023-12-12.pem/md5 b/deps/checksums/cacert-2023-12-12.pem/md5 deleted file mode 100644 index fa4b90b0b2dddd..00000000000000 --- a/deps/checksums/cacert-2023-12-12.pem/md5 +++ /dev/null @@ -1 +0,0 @@ -1e305b4e910d204ab7b4c18ec0cf0f27 diff --git a/deps/checksums/cacert-2023-12-12.pem/sha512 b/deps/checksums/cacert-2023-12-12.pem/sha512 deleted file mode 100644 index 8ce26f24dffd9e..00000000000000 --- a/deps/checksums/cacert-2023-12-12.pem/sha512 +++ /dev/null @@ -1 +0,0 @@ -dcbfe08d39efdd8de555b31e1050757900d08448c61f8a67c055f14514e5d47e734f6874b5ae628021c35ebc8dabdfdac5808df0b3a073d4f9246cca4b725fe8 diff --git a/deps/checksums/cacert-2024-03-11.pem/md5 b/deps/checksums/cacert-2024-03-11.pem/md5 new file mode 100644 index 00000000000000..618b6c74efdd4d --- /dev/null +++ b/deps/checksums/cacert-2024-03-11.pem/md5 @@ -0,0 +1 @@ +594084120d27f482b1dc48f558d12d48 diff --git a/deps/checksums/cacert-2024-03-11.pem/sha512 b/deps/checksums/cacert-2024-03-11.pem/sha512 new file mode 100644 index 00000000000000..441b8e84707b04 --- /dev/null +++ b/deps/checksums/cacert-2024-03-11.pem/sha512 @@ -0,0 +1 @@ +31f03cc19566d007c4cffdad2ada71d99b4734ad7b13bc4f30d73d321f40cbe13b87a801aa61d9788207a851cc1f95a8af8ac732a372d45edb932f204bce3744 diff --git a/deps/checksums/libgit2 b/deps/checksums/libgit2 index 78b82572f3898a..629a5f0601fcd8 100644 --- a/deps/checksums/libgit2 +++ b/deps/checksums/libgit2 @@ -1,34 +1,34 @@ -LibGit2.v1.7.2+0.aarch64-apple-darwin.tar.gz/md5/069fa8cbd69e98a6196bd24bb427ff47 -LibGit2.v1.7.2+0.aarch64-apple-darwin.tar.gz/sha512/bacaf03e8aa28a55af2ae031f09a22f0a9cecb20257ee9778f37d87eb4ed21ff25dbb33ac342b134edc2a9584c0c57e6eabf7dbe78b031e9e45c2448bd8a317c -LibGit2.v1.7.2+0.aarch64-linux-gnu.tar.gz/md5/3bc5dfb163045c335aec05097702ddd4 -LibGit2.v1.7.2+0.aarch64-linux-gnu.tar.gz/sha512/c8055e51713f6fe6f064c7e4626db7a70d07af6e5c8cb031e88ef8ea728accdb92a449f738fb248c0afbc9698d30d0670fa5cf640df564886887c7ce4dbc7124 -LibGit2.v1.7.2+0.aarch64-linux-musl.tar.gz/md5/23440824a3ec0a0d82fa8adccac63534 -LibGit2.v1.7.2+0.aarch64-linux-musl.tar.gz/sha512/040874d092d7a11c5bfa284e95b86335792ffa6b868e8c7165ca304647d82ffbc7a72b65bb92038abd1bfa545e831d5b2a658b3f5891377735f85d3e4ddff7b2 -LibGit2.v1.7.2+0.armv6l-linux-gnueabihf.tar.gz/md5/3ffc0954875a20f610f6852c522311f2 -LibGit2.v1.7.2+0.armv6l-linux-gnueabihf.tar.gz/sha512/35767e10a36a0025539a354ef5be2ec4031457c0c1121a07f4616c774e48bb85425732935a12718d23627b4bdf1fb5c7fe6b220cb4e2bcb94b9d26c743af0004 -LibGit2.v1.7.2+0.armv6l-linux-musleabihf.tar.gz/md5/73acea595fc31967d7fe1e808f4cc47c -LibGit2.v1.7.2+0.armv6l-linux-musleabihf.tar.gz/sha512/e124681a7b7b1ff64a1ca073ee6fcc75fc2b11ab0a3404b0a2bc9944854c4048e576697254cd8efed1d6c7103ac2e1bd574a75c6c3d8a383775d48170ef6d474 -LibGit2.v1.7.2+0.armv7l-linux-gnueabihf.tar.gz/md5/b710035b0be0c7e4810b9282912369a0 -LibGit2.v1.7.2+0.armv7l-linux-gnueabihf.tar.gz/sha512/e34b2956a869303a5b6bed059f326989e4e95f039fa3d1b75fc6f80c6d1170df96e2ea809df05aad59685751eb4666a0a05e0c3b456bcace2b0570b174b2b541 -LibGit2.v1.7.2+0.armv7l-linux-musleabihf.tar.gz/md5/aa4c7374dda73266cd387596fa31c258 -LibGit2.v1.7.2+0.armv7l-linux-musleabihf.tar.gz/sha512/54f6c9bd7dd1ee0438b817b1b18a94ce6f18838613524f146cf37f7d01319dd7c05d19d352376454ed2658e9dd839fede32db05748d9c352b56c3f0fe01edebc -LibGit2.v1.7.2+0.i686-linux-gnu.tar.gz/md5/2cf407e8cf5f7c7c984b48704935afaa -LibGit2.v1.7.2+0.i686-linux-gnu.tar.gz/sha512/44224ccf773b9f77979c1130cbb893d80c934918940ab9357bff7d92b97bdf1671d4263d121a603a6c12e60375bafc38b4bcac9a12cb0abb4665b5848d12946a -LibGit2.v1.7.2+0.i686-linux-musl.tar.gz/md5/742b947992f9f003a49c480165df1c87 -LibGit2.v1.7.2+0.i686-linux-musl.tar.gz/sha512/4d1a0c5c119f391be76d93ee7e82c6e38c8cda5c172c3d431bed6c6923776d4ad194c88509203332bed23f4c42581255a319a2ca45b6433b3fb68b3dc0aa1f02 -LibGit2.v1.7.2+0.i686-w64-mingw32.tar.gz/md5/476c290758970376ddfdcad25ba74c7c -LibGit2.v1.7.2+0.i686-w64-mingw32.tar.gz/sha512/dc76e0563b45aead1187fd7abfe411e3fbc21ff45983b693c11db4265d39fc3f51d167fe447f6a7efb1f3ec1e35a9d0edb1c3444ed50be62770dfea545fbddae -LibGit2.v1.7.2+0.powerpc64le-linux-gnu.tar.gz/md5/3ce536ea1ad7facca14c19c84106e8e5 -LibGit2.v1.7.2+0.powerpc64le-linux-gnu.tar.gz/sha512/d52d400249c7ed16084b13fde81f784cbf3b13b7081944872986b216b7faf186b7c8ff28626504d461c6059c7b4962acde0b15dc2e36007492210568a0f425f7 -LibGit2.v1.7.2+0.x86_64-apple-darwin.tar.gz/md5/c59af177b7ebdcfd52312a40d7832ee8 -LibGit2.v1.7.2+0.x86_64-apple-darwin.tar.gz/sha512/5bae0efc71421f28e4a3b2aca70ef1810b5810ed3df3d3577b8a7e956ea895f4b9efdabf17a32130e1f71fede4ceae7246d099b71147686e5722abdf56d50778 -LibGit2.v1.7.2+0.x86_64-linux-gnu.tar.gz/md5/1a55eb14294730b0ba7a23df3aac27ee -LibGit2.v1.7.2+0.x86_64-linux-gnu.tar.gz/sha512/21f7aea927bed22da1b974eab4d6f3413cc41e47b5a5e5bbfff6690474d6f374952b81549345a68c9227d1f3ef9e76578c81776cd1c41e75330c9f2dd1437c7b -LibGit2.v1.7.2+0.x86_64-linux-musl.tar.gz/md5/33a9bfb5a805ca6ca695196c2e94183e -LibGit2.v1.7.2+0.x86_64-linux-musl.tar.gz/sha512/924c2c2cd9baad369b21c17364164dbff7ecda153cb1ed89a4a7539407f3bdc54e87304ed2b7e26ba8046077cb0b3645e9263d53eb4b220436a2e150a77109c3 -LibGit2.v1.7.2+0.x86_64-unknown-freebsd.tar.gz/md5/8d27555b9a1bc086c4c3056cda876bd2 -LibGit2.v1.7.2+0.x86_64-unknown-freebsd.tar.gz/sha512/8ca7a589a328908ee10490230c963ae1292f9cb7c2c427c26ca5d6e4985d56ef76d02f98e05e4fc655cc5e92e2e405d63896a180bc33ebd4b852d2ff355c0339 -LibGit2.v1.7.2+0.x86_64-w64-mingw32.tar.gz/md5/3d7ac5a2af376a2ba0b335cb84710874 -LibGit2.v1.7.2+0.x86_64-w64-mingw32.tar.gz/sha512/5bdbb1110fa7c5bfaac0ba63002f9b1f480abab1cf3e284146352c30027381c23919745a0c490e202e8d856503f5c2bb2390a6bc32af533def7d31f8d6f7be31 -libgit2-a418d9d4ab87bae16b87d8f37143a4687ae0e4b2.tar.gz/md5/c67e5a2358f01d26b78269639ba20148 -libgit2-a418d9d4ab87bae16b87d8f37143a4687ae0e4b2.tar.gz/sha512/c82dc18bacb45f82c72f09e5525fd47191c8673a553df9faa05290c33dfdadfff9784341e68790130a14b12267c795f4ca166481fdf9674d2b70e8228bbeb11d +LibGit2.v1.8.0+0.aarch64-apple-darwin.tar.gz/md5/c19f3a4f6567b7504f607fc6f328312f +LibGit2.v1.8.0+0.aarch64-apple-darwin.tar.gz/sha512/0a776ab3eb4593abe0f2198a7371cbcf653ac5cf71ab7af9d5520c2bbbbbc981cf07ba3afa70f1ef6ea56f81e2d4b33b1be1482f9e215e61178b3dd1149ecb80 +LibGit2.v1.8.0+0.aarch64-linux-gnu.tar.gz/md5/8137d530bea16d41a614983068c1909d +LibGit2.v1.8.0+0.aarch64-linux-gnu.tar.gz/sha512/bdcb6249acd8df887a8af7c084d409132694a39f5e9f90bd70bba0f3eba2bad3eab6958cce9f060b2a4392d99352ccda8be92000f24ed4498c85ba55e0cbf13f +LibGit2.v1.8.0+0.aarch64-linux-musl.tar.gz/md5/4b9508ea58d4b1bd99f8471bd7c9a839 +LibGit2.v1.8.0+0.aarch64-linux-musl.tar.gz/sha512/e0996627a3d3ab9b3b1d103bbdd3e1179ede5479816f6b1be54471f120f76fe0495d3c7587c382985173c0614b634903b58c67ac3badbead82b4d797cc5915d7 +LibGit2.v1.8.0+0.armv6l-linux-gnueabihf.tar.gz/md5/02d6fae1745562cf724190929383688e +LibGit2.v1.8.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/11c14c5f395252143218a495c7dd2817c8f18f73320200a521f5ccd5f0c3c87403dee2c3b9e8166022fde1a67e83cbb83e6f222aac38b41efa43a6c0254548a9 +LibGit2.v1.8.0+0.armv6l-linux-musleabihf.tar.gz/md5/afa7b90751565b865f443b5a0a870d8b +LibGit2.v1.8.0+0.armv6l-linux-musleabihf.tar.gz/sha512/3594c223883a7da3bc0c78ae656fb15e47cc9dd196cf08f0abc0a1fb5f799842261e125440c07e92ba82896ad7427814bb43b63ba64d9b72ba38e9149132c26b +LibGit2.v1.8.0+0.armv7l-linux-gnueabihf.tar.gz/md5/ead27583a1cc5748c84d58a07fa6fc7e +LibGit2.v1.8.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/c81c3582fda7b299aaed72de07e9d0bd06c0c231aed73bb980c12c89b2b7593b2fb7990421bc2e45173f3d107ab50660842289675efa31f24ff752f0ebc63875 +LibGit2.v1.8.0+0.armv7l-linux-musleabihf.tar.gz/md5/71e38f112e8629682cc383c510f1f13f +LibGit2.v1.8.0+0.armv7l-linux-musleabihf.tar.gz/sha512/0b4b2677bdfc4f8e2a5ef3b9adf8fa2c0c1e76bd240b2173c268835b59cda29cbffc4241319fe36dcd63d1507ecf0e0e843f48fca80e3fbe4d3df53601ad7dec +LibGit2.v1.8.0+0.i686-linux-gnu.tar.gz/md5/b54cdd02201c1481746ab81db6f39aac +LibGit2.v1.8.0+0.i686-linux-gnu.tar.gz/sha512/0496a607b0d6841fc0c87477274b61eb95afa24d48d2624f8aaf230028a24d0248336902b01a326010fdbc45d8d73eecedb14c82313e1b1a94b3b6a4296e2607 +LibGit2.v1.8.0+0.i686-linux-musl.tar.gz/md5/b8946f9c1b83a7c22b2a8ca6da05b23b +LibGit2.v1.8.0+0.i686-linux-musl.tar.gz/sha512/931ff27da4e35749a5c020af72b750dce0b1d672cd98c04ad5a340f4f33ddb61c4df6711c36c6601063262fb733d45a3bb24eb1141e9d2fd2e0ab7b9bfbf54c8 +LibGit2.v1.8.0+0.i686-w64-mingw32.tar.gz/md5/cb9db0b590efe0c60f6e2f9558de4e5b +LibGit2.v1.8.0+0.i686-w64-mingw32.tar.gz/sha512/b9f637ec10cd751dfb2156e154a68809af400cdecbf0d25910792937c63ea56e60b703c7b78e3038ab34b1100bb20df79dce6346f40f1d24e5188fefe9517ccc +LibGit2.v1.8.0+0.powerpc64le-linux-gnu.tar.gz/md5/4ac1fa6b1ca43d3f6e97d590d1d27127 +LibGit2.v1.8.0+0.powerpc64le-linux-gnu.tar.gz/sha512/5cc3b9b9d85068bb3c6711c63ccb2672be765888a114147f70cae0eebf96f5bde00a40f163202c20e18a4cf4af2488fd1c304060daa3dd35748b30ab5a1fdb1d +LibGit2.v1.8.0+0.x86_64-apple-darwin.tar.gz/md5/26c2d1dcf68bc7b9919dfd24eb2fabc7 +LibGit2.v1.8.0+0.x86_64-apple-darwin.tar.gz/sha512/9c3ba94c438682f321cb2130f71028587a4a21b960f94f8c3f633dbe007210ff1b7b5e0b0bc4972e818458843a47a9e8d50d88f1bd3fb03a8fe129fa66332a38 +LibGit2.v1.8.0+0.x86_64-linux-gnu.tar.gz/md5/8d48ad388cca20d6338095cf8a36c3c9 +LibGit2.v1.8.0+0.x86_64-linux-gnu.tar.gz/sha512/9ddf4dc7420a9129ff8c34eb07ee94d9213c1a1c22700521199032a773353ab2413fd70d002b273a06dd951558128cd5577b7e917de6575d379911831d737bed +LibGit2.v1.8.0+0.x86_64-linux-musl.tar.gz/md5/5d9fd50bdf38ec99311e9627f254b95d +LibGit2.v1.8.0+0.x86_64-linux-musl.tar.gz/sha512/eae36cc70cb414e15924c22c9b03a98949b89fd8ca429fbe23fa215253266ed4cd11530adb2feccc9a19299ebf2048f1f5929c1faffba463b593b6c3e1808bee +LibGit2.v1.8.0+0.x86_64-unknown-freebsd.tar.gz/md5/af9e9d4bbe0df291f07f41416809a6f2 +LibGit2.v1.8.0+0.x86_64-unknown-freebsd.tar.gz/sha512/859786f13ba1fb5cd448dd5f22ebdf3381f5290d4875d65840fb31567ccd012f283a1849a82f2b2f58c3d73eda4c748d3da07d84a99665e0f50aeb39c37a4fb2 +LibGit2.v1.8.0+0.x86_64-w64-mingw32.tar.gz/md5/b51e3e238d776d52e396dd749f895e4f +LibGit2.v1.8.0+0.x86_64-w64-mingw32.tar.gz/sha512/2581d4b1d6fd4d0f15b406f050bd8a2a41e13dc2a1699a9b956e56426778beb994e6552988bf50ddad682349209a8694eace9450dab0570434cdfbed9c9f0b24 +libgit2-d74d491481831ddcd23575d376e56d2197e95910.tar.gz/md5/2420def04a290dd7ad0e67f93789f106 +libgit2-d74d491481831ddcd23575d376e56d2197e95910.tar.gz/sha512/496c6640d2453c58b66bc53c6e4e9e84f48d89eb8f240aefc1eea7e2d19b6c601614764590f2d2ca9e51e7e1de8fcdd5bf67f27f32bab628eae40d26ed382048 diff --git a/deps/libgit2.version b/deps/libgit2.version index 65f3e7670e4af1..d51beb34c27f51 100644 --- a/deps/libgit2.version +++ b/deps/libgit2.version @@ -3,12 +3,12 @@ LIBGIT2_JLL_NAME := LibGit2 ## source build -LIBGIT2_BRANCH=v1.7.2 -LIBGIT2_SHA1=a418d9d4ab87bae16b87d8f37143a4687ae0e4b2 +LIBGIT2_BRANCH=v1.8.0 +LIBGIT2_SHA1=d74d491481831ddcd23575d376e56d2197e95910 ## Other deps # Specify the version of the Mozilla CA Certificate Store to obtain. # The versions of cacert.pem are identified by the date (YYYY-MM-DD) of their changes. # See https://curl.haxx.se/docs/caextract.html for more details. # Keep in sync with `stdlib/MozillaCACerts_jll/Project.toml`. -MOZILLA_CACERT_VERSION := 2023-12-12 +MOZILLA_CACERT_VERSION := 2024-03-11 diff --git a/stdlib/LibGit2/src/consts.jl b/stdlib/LibGit2/src/consts.jl index 5a5b8b74e7127c..8c140e8c2aa30f 100644 --- a/stdlib/LibGit2/src/consts.jl +++ b/stdlib/LibGit2/src/consts.jl @@ -417,7 +417,32 @@ Option flags for `GitRepo`. FEATURE_SSH = Cuint(1 << 2), FEATURE_NSEC = Cuint(1 << 3)) -if version() >= v"0.24.0" +if version() >= v"1.8.0" + @doc """ + Priority level of a config file. + + These priority levels correspond to the natural escalation logic (from higher to lower) when searching for config entries in git. + + * `CONFIG_LEVEL_DEFAULT` - Open the global, XDG and system configuration files if any available. + * `CONFIG_LEVEL_PROGRAMDATA` - System-wide on Windows, for compatibility with portable git + * `CONFIG_LEVEL_SYSTEM` - System-wide configuration file; `/etc/gitconfig` on Linux systems + * `CONFIG_LEVEL_XDG` - XDG compatible configuration file; typically `~/.config/git/config` + * `CONFIG_LEVEL_GLOBAL` - User-specific configuration file (also called Global configuration file); typically `~/.gitconfig` + * `CONFIG_LEVEL_LOCAL` - Repository specific configuration file; `\$WORK_DIR/.git/config` on non-bare repos + * `CONFIG_LEVEL_WORKTREE` - Worktree specific configuration file; `\$GIT_DIR/config.worktree` + * `CONFIG_LEVEL_APP` - Application specific configuration file; freely defined by applications + * `CONFIG_HIGHEST_LEVEL` - Represents the highest level available config file (i.e. the most specific config file available that actually is loaded) + """ + @enum(GIT_CONFIG, CONFIG_LEVEL_DEFAULT = 0, + CONFIG_LEVEL_PROGRAMDATA = 1, + CONFIG_LEVEL_SYSTEM = 2, + CONFIG_LEVEL_XDG = 3, + CONFIG_LEVEL_GLOBAL = 4, + CONFIG_LEVEL_LOCAL = 5, + CONFIG_LEVEL_WORKTREE = 6, + CONFIG_LEVEL_APP = 7, + CONFIG_HIGHEST_LEVEL =-1) +elseif version() >= v"0.24.0" @doc """ Priority level of a config file. diff --git a/stdlib/LibGit2/src/types.jl b/stdlib/LibGit2/src/types.jl index 96cea96d013e5a..b0b463c69e2f1d 100644 --- a/stdlib/LibGit2/src/types.jl +++ b/stdlib/LibGit2/src/types.jl @@ -678,6 +678,8 @@ The fields represent: for more information. * `custom_headers`: only relevant if the LibGit2 version is greater than or equal to `0.24.0`. Extra headers needed for the push operation. + * `remote_push_options`: only relevant if the LibGit2 version is greater than or equal to `1.8.0`. + "Push options" to deliver to the remote. """ @kwdef struct PushOptions version::Cuint = Cuint(1) @@ -692,6 +694,9 @@ The fields represent: @static if LibGit2.VERSION >= v"0.24.0" custom_headers::StrArrayStruct = StrArrayStruct() end + @static if LibGit2.VERSION >= v"1.8.0" + remote_push_options::StrArrayStruct = StrArrayStruct() + end end @assert Base.allocatedinline(PushOptions) @@ -913,10 +918,17 @@ Matches the [`git_config_entry`](https://libgit2.org/libgit2/#HEAD/type/git_conf struct ConfigEntry name::Cstring value::Cstring + @static if LibGit2.VERSION >= v"1.8.0" + backend_type::Cstring + origin_path::Cstring + end include_depth::Cuint level::GIT_CONFIG free::Ptr{Cvoid} - payload::Ptr{Cvoid} # User is not permitted to read or write this field + @static if LibGit2.VERSION < v"1.8.0" + # In 1.8.0, the unused payload value has been removed + payload::Ptr{Cvoid} + end end @assert Base.allocatedinline(ConfigEntry) diff --git a/stdlib/LibGit2_jll/Project.toml b/stdlib/LibGit2_jll/Project.toml index 1e13d0228488f5..ceeb394f262318 100644 --- a/stdlib/LibGit2_jll/Project.toml +++ b/stdlib/LibGit2_jll/Project.toml @@ -1,6 +1,6 @@ name = "LibGit2_jll" uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" -version = "1.7.2+0" +version = "1.8.0+0" [deps] MbedTLS_jll = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" diff --git a/stdlib/LibGit2_jll/src/LibGit2_jll.jl b/stdlib/LibGit2_jll/src/LibGit2_jll.jl index c24d3c20f428ec..15d303dfea6eee 100644 --- a/stdlib/LibGit2_jll/src/LibGit2_jll.jl +++ b/stdlib/LibGit2_jll/src/LibGit2_jll.jl @@ -20,9 +20,9 @@ libgit2_path::String = "" if Sys.iswindows() const libgit2 = "libgit2.dll" elseif Sys.isapple() - const libgit2 = "@rpath/libgit2.1.7.dylib" + const libgit2 = "@rpath/libgit2.1.8.dylib" else - const libgit2 = "libgit2.so.1.7" + const libgit2 = "libgit2.so.1.8" end function __init__() diff --git a/stdlib/LibGit2_jll/test/runtests.jl b/stdlib/LibGit2_jll/test/runtests.jl index 6d83f6e447453f..5bc74760b1603d 100644 --- a/stdlib/LibGit2_jll/test/runtests.jl +++ b/stdlib/LibGit2_jll/test/runtests.jl @@ -7,5 +7,5 @@ using Test, Libdl, LibGit2_jll minor = Ref{Cint}(0) patch = Ref{Cint}(0) @test ccall((:git_libgit2_version, libgit2), Cint, (Ref{Cint}, Ref{Cint}, Ref{Cint}), major, minor, patch) == 0 - @test VersionNumber(major[], minor[], patch[]) == v"1.7.2" + @test VersionNumber(major[], minor[], patch[]) == v"1.8.0" end diff --git a/stdlib/Manifest.toml b/stdlib/Manifest.toml index a9491702f62ad8..a715cf141481be 100644 --- a/stdlib/Manifest.toml +++ b/stdlib/Manifest.toml @@ -103,7 +103,7 @@ version = "1.11.0" [[deps.LibGit2_jll]] deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" -version = "1.7.2+0" +version = "1.8.0+0" [[deps.LibSSH2_jll]] deps = ["Artifacts", "Libdl", "MbedTLS_jll"] diff --git a/stdlib/MozillaCACerts_jll/Project.toml b/stdlib/MozillaCACerts_jll/Project.toml index b4f667b9747365..181171a4c04c1d 100644 --- a/stdlib/MozillaCACerts_jll/Project.toml +++ b/stdlib/MozillaCACerts_jll/Project.toml @@ -1,7 +1,7 @@ name = "MozillaCACerts_jll" uuid = "14a3606d-f60d-562e-9121-12d972cd8159" # Keep in sync with `deps/libgit2.version`. -version = "2023.12.12" +version = "2024.03.11" [extras] Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" From 653c0ae986493a68f9fe4ad8a8981baacf9f9e92 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Tue, 26 Mar 2024 19:22:36 -0400 Subject: [PATCH 036/123] precompilepkgs: don't confuse single package in project with requesting single package (#53865) Followup to https://github.com/JuliaLang/julia/pull/53653 Separate from #53862 because this one is just broken on master Without this if you precompile a project with a single dep it thought the user was calling `precompile Dep` or `using Dep` so went into live print mode, which is confusing. --- base/precompilation.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/precompilation.jl b/base/precompilation.jl index a823b2b5798527..a835b6974d4339 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -361,6 +361,7 @@ function precompilepkgs(pkgs::Vector{String}=String[]; manifest::Bool=false,) configs = configs isa Config ? [configs] : configs + requested_pkgs = copy(pkgs) # for understanding user intent time_start = time_ns() @@ -748,7 +749,7 @@ function precompilepkgs(pkgs::Vector{String}=String[]; for (pkg, deps) in depsmap cachepaths = Base.find_all_in_cache_path(pkg) sourcepath = Base.locate_package(pkg) - single_requested_pkg = length(pkgs) == 1 && only(pkgs) == pkg.name + single_requested_pkg = length(requested_pkgs) == 1 && only(requested_pkgs) == pkg.name for config in configs pkg_config = (pkg, config) if sourcepath === nothing From fc2d3af5bd8b6a0ba8d057c31129e9318b19f2c5 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Tue, 26 Mar 2024 20:37:46 -0400 Subject: [PATCH 037/123] precompilepkgs: fix error reporting (#53862) --- base/precompilation.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/base/precompilation.jl b/base/precompilation.jl index a835b6974d4339..8185fe8e8230bd 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -333,6 +333,8 @@ struct PkgPrecompileError <: Exception msg::String end Base.showerror(io::IO, err::PkgPrecompileError) = print(io, err.msg) +Base.showerror(io::IO, err::PkgPrecompileError, bt; kw...) = Base.showerror(io, err) # hide stacktrace + # This needs a show method to make `julia> err` show nicely Base.show(io::IO, err::PkgPrecompileError) = print(io, "PkgPrecompileError: ", err.msg) @@ -821,7 +823,7 @@ function precompilepkgs(pkgs::Vector{String}=String[]; close(std_pipe.in) # close pipe to end the std output monitor wait(t_monitor) if err isa ErrorException || (err isa ArgumentError && startswith(err.msg, "Invalid header in cache file")) - failed_deps[pkg_config] = (strict || is_direct_dep) ? string(sprint(showerror, err), "\n", strip(get(std_outputs, pkg, ""))) : "" + failed_deps[pkg_config] = (strict || is_direct_dep) ? string(sprint(showerror, err), "\n", strip(get(std_outputs, pkg_config, ""))) : "" delete!(std_outputs, pkg_config) # so it's not shown as warnings, given error report !fancyprint && lock(print_lock) do println(io, " "^9, color_string(" โœ— ", Base.error_color()), name) @@ -944,7 +946,7 @@ function precompilepkgs(pkgs::Vector{String}=String[]; end else println(io) - error(err_msg) + throw(PkgPrecompileError(err_msg)) end end end From d4d34b9639ba2fa66f52aff422c34c60c080ab19 Mon Sep 17 00:00:00 2001 From: crazeteam <164632007+crazeteam@users.noreply.github.com> Date: Wed, 27 Mar 2024 08:44:31 +0800 Subject: [PATCH 038/123] chore: fix some comments (#53861) Signed-off-by: crazeteam --- base/sort.jl | 2 +- stdlib/LinearAlgebra/src/triangular.jl | 2 +- stdlib/REPL/test/repl.jl | 2 +- stdlib/Test/test/runtests.jl | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/base/sort.jl b/base/sort.jl index 281a75cac309ed..38e89e3d3a0ce3 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -528,7 +528,7 @@ no scratch space is present. A returned scratch space will be a `Vector{T}` where `T` is usually the eltype of `v`. There are some exceptions, for example if `eltype(v) == Union{Missing, T}` then the scratch space -may be be a `Vector{T}` due to `MissingOptimization` changing the eltype of `v` to `T`. +may be a `Vector{T}` due to `MissingOptimization` changing the eltype of `v` to `T`. `t` is an appropriate scratch space for the algorithm at hand, to be accessed as `t[i + offset]`. `t` is used for an algorithm to pass a scratch space back to itself in diff --git a/stdlib/LinearAlgebra/src/triangular.jl b/stdlib/LinearAlgebra/src/triangular.jl index aff87e3ae50ba2..97ae07e12e9791 100644 --- a/stdlib/LinearAlgebra/src/triangular.jl +++ b/stdlib/LinearAlgebra/src/triangular.jl @@ -2663,7 +2663,7 @@ end Bแตขโฑผโฝยนโพ = M_Bแตขโฑผโฝยนโพ[1:sโ‚, 1:sโ‚‚] # Compute Bแตขโฑผโฝโฐโพ and Bแตขโฑผโฝยนโพ mul!(Bแตขโฑผโฝโฐโพ, A[iโ‚:iโ‚‚,kโ‚:kโ‚‚], A[kโ‚:kโ‚‚,jโ‚:jโ‚‚]) - # Retreive Rแตข,แตขโ‚Šโ‚– as A[i+k,i]' + # Retrieve Rแตข,แตขโ‚Šโ‚– as A[i+k,i]' mul!(Bแตขโฑผโฝยนโพ, A[iโ‚:iโ‚‚,kโ‚:kโ‚‚], A[jโ‚:jโ‚‚,kโ‚:kโ‚‚]') # Solve Uแตข,แตขโ‚Šโ‚– using Reference [1, (4.10)] kron!(Lโ‚€, ฮ”[1:sโ‚‚,1:sโ‚‚], S[1:sโ‚,iโ‚:iโ‚‚]) diff --git a/stdlib/REPL/test/repl.jl b/stdlib/REPL/test/repl.jl index 1d0caab7d0e573..09ff10e770e844 100644 --- a/stdlib/REPL/test/repl.jl +++ b/stdlib/REPL/test/repl.jl @@ -114,7 +114,7 @@ fake_repl() do stdin_write, stdout_read, repl Base.wait(repltask) end -# These are integration tests. If you want to unit test test e.g. completion, or +# These are integration tests. If you want to unit test e.g. completion, or # exact LineEdit behavior, put them in the appropriate test files. # Furthermore since we are emulating an entire terminal, there may be control characters # in the mix. If verification needs to be done, keep it to the bare minimum. Basically diff --git a/stdlib/Test/test/runtests.jl b/stdlib/Test/test/runtests.jl index 460e2eadf42b73..fc4838caf4ef4d 100644 --- a/stdlib/Test/test/runtests.jl +++ b/stdlib/Test/test/runtests.jl @@ -162,7 +162,7 @@ let fails = @testset NoThrowTestSet begin @test_throws "A test" error("a test") @test_throws r"sqrt\([Cc]omplx" sqrt(-1) @test_throws str->occursin("a T", str) error("a test") - @test_throws ["BoundsError", "aquire", "1-element", "at index [2]"] [1][2] + @test_throws ["BoundsError", "acquire", "1-element", "at index [2]"] [1][2] end for fail in fails @test fail isa Test.Fail @@ -294,7 +294,7 @@ let fails = @testset NoThrowTestSet begin end let str = sprint(show, fails[26]) - @test occursin("Expected: [\"BoundsError\", \"aquire\", \"1-element\", \"at index [2]\"]", str) + @test occursin("Expected: [\"BoundsError\", \"acquire\", \"1-element\", \"at index [2]\"]", str) @test occursin(r"Message: \"BoundsError.* 1-element.*at index \[2\]", str) end From 6737a1de25a835870641d8d1f3c507ee60e24cc0 Mon Sep 17 00:00:00 2001 From: FX Coudert Date: Wed, 27 Mar 2024 01:45:27 +0100 Subject: [PATCH 039/123] Update SuiteSparse to 7.6.1 (#53864) Following https://github.com/JuliaPackaging/Yggdrasil/pull/8355 --- deps/checksums/suitesparse | 68 ++++++++++++++--------------- deps/libsuitesparse.version | 4 +- stdlib/Manifest.toml | 2 +- stdlib/SuiteSparse_jll/Project.toml | 2 +- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/deps/checksums/suitesparse b/deps/checksums/suitesparse index 88f5195bb021a5..537ec7dd6d3faf 100644 --- a/deps/checksums/suitesparse +++ b/deps/checksums/suitesparse @@ -1,34 +1,34 @@ -SuiteSparse-7.6.0.tar.gz/md5/79a68c2eca2d4b213a304bd08180c630 -SuiteSparse-7.6.0.tar.gz/sha512/6cffb283e7620afd31c6f7517ca9d28c2927515af582680d346e0e8a4ee1289daec0b4d83660f88f309e53e54a87403291fc4b0b45fe50dffd59781ec0129a8f -SuiteSparse.v7.6.0+0.aarch64-apple-darwin.tar.gz/md5/dd7cb2ded54840648d9bb28099dfbc66 -SuiteSparse.v7.6.0+0.aarch64-apple-darwin.tar.gz/sha512/64edba78b463dffebf7a1dbcc21665a8229fc795f22ea669e648b03595bb2bc646d0e5d8d9326adca525f325523f50bb8aeb1f1d6da12ba2c465f16f87ed6726 -SuiteSparse.v7.6.0+0.aarch64-linux-gnu.tar.gz/md5/f7e30ff16e597cae91031dd84fcc790a -SuiteSparse.v7.6.0+0.aarch64-linux-gnu.tar.gz/sha512/a3bfdaef6a2108d0179de3a3fa56c58af4a6cc36d12f987baa6ce15842bff2473c5ea92e5ce0e28d97744c5b8ffae5fb178c14a2e504f8d0291d5dc67370836d -SuiteSparse.v7.6.0+0.aarch64-linux-musl.tar.gz/md5/763d9208eb9a8d134d8a0fcdf01745c2 -SuiteSparse.v7.6.0+0.aarch64-linux-musl.tar.gz/sha512/657d78d577dade8ddb6b863208c3baf9e15e4cae83853f3730dce49a5f227eb48164f60b39cfd4a22f1d4bcf6d9c6e4b3fcf340bdc6c36345c60fb235bc2cfd7 -SuiteSparse.v7.6.0+0.armv6l-linux-gnueabihf.tar.gz/md5/7c71369a2edfe3eca0061339b8a30e3a -SuiteSparse.v7.6.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/bc197a50a1031e17721a63405438c2705da456c5ad97dcae0ccc538b0a5d46fa474b49e14a8d3db3d32402e7234e4d9523659a0ec2318901b5e6cd8a5fe7ea8f -SuiteSparse.v7.6.0+0.armv6l-linux-musleabihf.tar.gz/md5/2933e936ec3cdbbbd015206124d2a98e -SuiteSparse.v7.6.0+0.armv6l-linux-musleabihf.tar.gz/sha512/d3e3382b982198b5d37928ca0e2354bb110b327069b9dfeb72e9aef1d82e79e5a1536679112c0c82c20acf7e005269f0168c84d498b4ef87c5521bd18b133134 -SuiteSparse.v7.6.0+0.armv7l-linux-gnueabihf.tar.gz/md5/df109c03141c3c34dcbcee180c255539 -SuiteSparse.v7.6.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/cbffe6e5c023f3efbb60a78d6c403feb2b2ca0ff4cac4586c82ffba65d87a4bd1cff63370abfff91882d64e6cf2bb2e10e792ab21f4b7380f413c6a78b89f242 -SuiteSparse.v7.6.0+0.armv7l-linux-musleabihf.tar.gz/md5/5a82f651831d0e83214791156637c38b -SuiteSparse.v7.6.0+0.armv7l-linux-musleabihf.tar.gz/sha512/0436c0a83d2fb40f21cdd49817182a12824b903050fb47a717a55040445393e5312596e27654a0dabe059059b8dabf82c37e4754a71f189ee1561ddeb11098dc -SuiteSparse.v7.6.0+0.i686-linux-gnu.tar.gz/md5/b58d6186f54c4f10d1e37ac1b82ebd1c -SuiteSparse.v7.6.0+0.i686-linux-gnu.tar.gz/sha512/7d3f1cdd2f9786fa072d8820e4ec424d282595051aa2355c84de0530c957459408f7a4d7eb213863fe91a78c03b96346f8c6f8c088ee6e2bad91c576a5e7e39c -SuiteSparse.v7.6.0+0.i686-linux-musl.tar.gz/md5/c43f347674f1d983d76d453a1ce26c63 -SuiteSparse.v7.6.0+0.i686-linux-musl.tar.gz/sha512/467a4e3af813c7a550b097699ca45083fcdad4ad04689bf53c302b2cf769962c23b62bc39a7afa851c4a1226cd6fbb37e1e8590fd1dbca3c680f7138eb029a8b -SuiteSparse.v7.6.0+0.i686-w64-mingw32.tar.gz/md5/cd92ad4bef9109ab60357b78ae3c444b -SuiteSparse.v7.6.0+0.i686-w64-mingw32.tar.gz/sha512/41557b4e4254469bd1f264f0bea4335761ee18328e22d3626dd9ddb69ab8501c40d31c2848ac3c28b361454d80b8d97514478b8db96a335aa4b8580eba22de93 -SuiteSparse.v7.6.0+0.powerpc64le-linux-gnu.tar.gz/md5/8ba38d83ee767ef1a3108ad2fbdc9edf -SuiteSparse.v7.6.0+0.powerpc64le-linux-gnu.tar.gz/sha512/37ae98d9557ae8d2ce6edbcf2b18f49690b98daa5a19fab2cda747d2f19c735430031414fc8f23bca35899cb21995170e6fe72623dc6dae25b207870b9396698 -SuiteSparse.v7.6.0+0.x86_64-apple-darwin.tar.gz/md5/21cedd18cf9f5aa83b1bdaaf2d4253af -SuiteSparse.v7.6.0+0.x86_64-apple-darwin.tar.gz/sha512/e86ea34ac3d1d1123be7d6989893948d26a98ae28198740272c108c434650d1616f89c9176ea51c0dbc3550a1a4f0611935eec29b2aafd96d80717c99916a2b1 -SuiteSparse.v7.6.0+0.x86_64-linux-gnu.tar.gz/md5/10674b26e56d1cb4345012b965cac926 -SuiteSparse.v7.6.0+0.x86_64-linux-gnu.tar.gz/sha512/d1dba73e5449768ac728923edf665f1c11e6d54654ab14190fa3c7cd128642b2dac5b21f3c2d91313ab35e5054e6406542e074b6de2b8c0bce49269a9ab89dd4 -SuiteSparse.v7.6.0+0.x86_64-linux-musl.tar.gz/md5/9f2b78216d7474b064c710f6966b15d9 -SuiteSparse.v7.6.0+0.x86_64-linux-musl.tar.gz/sha512/32a3c124ca8041390b0e6d4ebcfe536d25c88fee28e178fb78279e52428613cb6e109ec99b3801331740985226dd40684bf20f75dd5c99c4c74335177d3a8307 -SuiteSparse.v7.6.0+0.x86_64-unknown-freebsd.tar.gz/md5/724ee53946f949618be56ded74c15d29 -SuiteSparse.v7.6.0+0.x86_64-unknown-freebsd.tar.gz/sha512/2fc9b2fdcabfe8e98a14f74ad1f94689cbde704e9f5635f6e5677af9090920627e46e903790231edb4de998eea3a732ad88b0c3ebc2ae5a158433b487e739340 -SuiteSparse.v7.6.0+0.x86_64-w64-mingw32.tar.gz/md5/57c4bd66dfd1bdf824017150d798f8aa -SuiteSparse.v7.6.0+0.x86_64-w64-mingw32.tar.gz/sha512/26d9c15de1b5b68b9f01775a758f322b5a9f8600c66fa713b5de1009a90cec8e6db755305c19485406f9a9e88d752871b70fff5e336d09fca9bdf61bcb4de3ba +SuiteSparse-7.6.1.tar.gz/md5/566fa42263477c0b4e2f9abc2e01173e +SuiteSparse-7.6.1.tar.gz/sha512/cef8a8aa0624876dd8882eb3960dd22682eaae6c255e54d3c696d4b5760d04463a445560f956115eae06a04d9ae6b9227755ce0b375f8e55e979409b23fffd54 +SuiteSparse.v7.6.1+0.aarch64-apple-darwin.tar.gz/md5/ece087d641de1f41ba2deec6471c9b1c +SuiteSparse.v7.6.1+0.aarch64-apple-darwin.tar.gz/sha512/31402f1906f7af17deac749930a997aac0b90436cdd80b30ff2c5b8148feaf5077fff8480f33cd7aa4fac41f098535f256de8e26599b39d88676f505518e8e3a +SuiteSparse.v7.6.1+0.aarch64-linux-gnu.tar.gz/md5/94a615dac1459aa8f19e46e2954ae761 +SuiteSparse.v7.6.1+0.aarch64-linux-gnu.tar.gz/sha512/b02cc3b9c24af3e90ab9711b980c60faaa7fc7e01b7c076f3b2fb03189b87143ea91c29f8a816cf71370a6c42f58a794c7774da793157ba99dfbc0c3deb1d59f +SuiteSparse.v7.6.1+0.aarch64-linux-musl.tar.gz/md5/35e2ce86179b26d3129a2c63a81fb033 +SuiteSparse.v7.6.1+0.aarch64-linux-musl.tar.gz/sha512/5d512986178b8140eb99be1e319ec787396d8806be158181fe97d99b788f895b596dcc0f70457d46167c9391dbfeb484411ddbca40f13b943c6c29956382ca45 +SuiteSparse.v7.6.1+0.armv6l-linux-gnueabihf.tar.gz/md5/3616cbe1e8badbbb2c3671d092821d2c +SuiteSparse.v7.6.1+0.armv6l-linux-gnueabihf.tar.gz/sha512/aab2e86f2d25d305ae79595e02db4e04365e96d374915b390970f58272faa34eee0ce374ab3dc8fab7e6a89e1375e7ec1658bb5d485e3ab7ae3b7d3f03ae7461 +SuiteSparse.v7.6.1+0.armv6l-linux-musleabihf.tar.gz/md5/4db750ef1f63484a0e78e7e36bde5835 +SuiteSparse.v7.6.1+0.armv6l-linux-musleabihf.tar.gz/sha512/3ff7d45d98e5f99062d8ebead1ec26c72025d2623129da1999ea1e7efcae5cb4c5bc66bcb2e2fc7f7f31dc8b5824f4b8f6ea61147564056bb8daa45a5d53dee6 +SuiteSparse.v7.6.1+0.armv7l-linux-gnueabihf.tar.gz/md5/170612f9ebd79ea013bf13a884e7ef9f +SuiteSparse.v7.6.1+0.armv7l-linux-gnueabihf.tar.gz/sha512/d53e9984f64b2dcbe76ea1b7d24703dbead785b987782b73881869b07cf3513149b576d2c537684cda48ad7c4447048c885413a2861e878c2026cb83875aa5d7 +SuiteSparse.v7.6.1+0.armv7l-linux-musleabihf.tar.gz/md5/d9f67600dcd77960a858a1e243009392 +SuiteSparse.v7.6.1+0.armv7l-linux-musleabihf.tar.gz/sha512/1222c095f4b1368d22e8b0bf00753714afc60062f9550414f59f71d26cf29b414ed91bb6ed8d2aa5152ea875280f620db7d6e7aaa459088c9bdd95f3c5afa237 +SuiteSparse.v7.6.1+0.i686-linux-gnu.tar.gz/md5/f0c81cd95e8b06541541f676c020bb01 +SuiteSparse.v7.6.1+0.i686-linux-gnu.tar.gz/sha512/da0dff1b38ae2d20cac3af6d43a3f2b9dfb6c7ee0d120ff2500cffafe9b851a2ccfeb8857a831a306cc8ae61108cdd2090cb66abcd8071a3503e514176f4b848 +SuiteSparse.v7.6.1+0.i686-linux-musl.tar.gz/md5/d9584256d6c8fe5631727c6947233dab +SuiteSparse.v7.6.1+0.i686-linux-musl.tar.gz/sha512/a3e58f21dcae3e4eaa59cbc5846f4036be891753b1152423b5530ca2aba655c6283f982fe9d68e6304d6ef4629437e02f9850b142c8b7b62094a94125438cd80 +SuiteSparse.v7.6.1+0.i686-w64-mingw32.tar.gz/md5/92d639cf624c22db2f64f3cce94f1a9e +SuiteSparse.v7.6.1+0.i686-w64-mingw32.tar.gz/sha512/e26188190fe2fa95535df220f8cc6da0f54dbcbffb8c3d5fe9cf9dac9865825a483ba2e6ed7a603f49b94ca3b4973adbabbf2b9d96f4837b5e27a716d98ed9bf +SuiteSparse.v7.6.1+0.powerpc64le-linux-gnu.tar.gz/md5/8fb15955fb750dd38b18615855afd2f3 +SuiteSparse.v7.6.1+0.powerpc64le-linux-gnu.tar.gz/sha512/369e29a19f087982e74f083bc550b60e22705571ac29f0b92565c68c31068d32ee037c4af3114b1856558a4d35e338d575e2b8a382a14afbf8d37c5d8fa78117 +SuiteSparse.v7.6.1+0.x86_64-apple-darwin.tar.gz/md5/a52d9799e0c6a7fa704b4ef684f1151e +SuiteSparse.v7.6.1+0.x86_64-apple-darwin.tar.gz/sha512/89ce162803afdd2626a202eb6c83fb2ec79c606d46343ecaf4e15cb5b3c191a5303cc5571384433f8e70b3c548de2d274d660acaa144f9357fd890172fb3f08d +SuiteSparse.v7.6.1+0.x86_64-linux-gnu.tar.gz/md5/fb03e7f53715f17c07853151ccccc869 +SuiteSparse.v7.6.1+0.x86_64-linux-gnu.tar.gz/sha512/43490679d3c748850a9d052f92ef7ed7a002c18c014acc9c82e605576ae088c810a01bf05e7f0934dea9890a3cf6dcb45d76b1b2fc1249fc7f36d8b989a7f044 +SuiteSparse.v7.6.1+0.x86_64-linux-musl.tar.gz/md5/ee56d6cbf18b6e1da363d0ff3bdfd6a8 +SuiteSparse.v7.6.1+0.x86_64-linux-musl.tar.gz/sha512/31c33d29ad5cd153b37afed6560ba2903a77293ddb536f31effd217ec5953c1adc3217d1eb65a6bad78013e1da9fdb713c3d9537daae836cc560e648787a53ef +SuiteSparse.v7.6.1+0.x86_64-unknown-freebsd.tar.gz/md5/78d819e5712b2ac9d254fdeb9e72e733 +SuiteSparse.v7.6.1+0.x86_64-unknown-freebsd.tar.gz/sha512/5effdb7f1808d82ed73b1ad380e82016c46965146098c503c90fef3834b919d50b7419e6d9b856f462786d4314b6e34194612fbbd83e4b76d04e5f1a19b7f774 +SuiteSparse.v7.6.1+0.x86_64-w64-mingw32.tar.gz/md5/72876b211640159db2a0e149ca9e4bae +SuiteSparse.v7.6.1+0.x86_64-w64-mingw32.tar.gz/sha512/be80559f2fd19e1c0f8305e03dc7256202110e4e0c91757fc911e8c15e5e0706210d5323cd2c4fe759e35dc27d9469f40e5a49f0f562ca6fec03adad068962af diff --git a/deps/libsuitesparse.version b/deps/libsuitesparse.version index 2602a449e3a4e3..98e27d9125700e 100644 --- a/deps/libsuitesparse.version +++ b/deps/libsuitesparse.version @@ -4,5 +4,5 @@ LIBSUITESPARSE_JLL_NAME := SuiteSparse ## source build -LIBSUITESPARSE_VER := 7.6.0 -LIBSUITESPARSE_SHA1=1a4d4fb0c399b261f4ed11aa980c6bab754aefa6 +LIBSUITESPARSE_VER := 7.6.1 +LIBSUITESPARSE_SHA1=d4dad6c1d0b5cb3e7c5d7d01ef55653713567662 diff --git a/stdlib/Manifest.toml b/stdlib/Manifest.toml index a715cf141481be..d95447c0a25807 100644 --- a/stdlib/Manifest.toml +++ b/stdlib/Manifest.toml @@ -243,7 +243,7 @@ version = "1.11.0" [[deps.SuiteSparse_jll]] deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "7.6.0+0" +version = "7.6.1+0" [[deps.TOML]] deps = ["Dates"] diff --git a/stdlib/SuiteSparse_jll/Project.toml b/stdlib/SuiteSparse_jll/Project.toml index 24d2e42dbaea93..ee284bc3220f70 100644 --- a/stdlib/SuiteSparse_jll/Project.toml +++ b/stdlib/SuiteSparse_jll/Project.toml @@ -1,6 +1,6 @@ name = "SuiteSparse_jll" uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" -version = "7.6.0+0" +version = "7.6.1+0" [deps] libblastrampoline_jll = "8e850b90-86db-534c-a0d3-1478176c7d93" From f413b016c5486034ce1f83631129d6d7d2f01445 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Wed, 27 Mar 2024 08:18:58 -0500 Subject: [PATCH 040/123] Remove duplicate small integer union constants (#53866) --- base/reduce.jl | 32 ++++++++++++-------------------- test/reducedim.jl | 4 ++-- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index 6a0d46c61fcd94..d73aeeeee46ec8 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -4,14 +4,6 @@ ###### Generic (map)reduce functions ###### -if Int === Int32 - const SmallSigned = Union{Int8,Int16} - const SmallUnsigned = Union{UInt8,UInt16} -else - const SmallSigned = Union{Int8,Int16,Int32} - const SmallUnsigned = Union{UInt8,UInt16,UInt32} -end - abstract type AbstractBroadcasted end const AbstractArrayOrBroadcasted = Union{AbstractArray, AbstractBroadcasted} @@ -22,8 +14,8 @@ The reduction operator used in `sum`. The main difference from [`+`](@ref) is th integers are promoted to `Int`/`UInt`. """ add_sum(x, y) = x + y -add_sum(x::SmallSigned, y::SmallSigned) = Int(x) + Int(y) -add_sum(x::SmallUnsigned, y::SmallUnsigned) = UInt(x) + UInt(y) +add_sum(x::BitSignedSmall, y::BitSignedSmall) = Int(x) + Int(y) +add_sum(x::BitUnsignedSmall, y::BitUnsignedSmall) = UInt(x) + UInt(y) add_sum(x::Real, y::Real)::Real = x + y """ @@ -33,8 +25,8 @@ The reduction operator used in `prod`. The main difference from [`*`](@ref) is t integers are promoted to `Int`/`UInt`. """ mul_prod(x, y) = x * y -mul_prod(x::SmallSigned, y::SmallSigned) = Int(x) * Int(y) -mul_prod(x::SmallUnsigned, y::SmallUnsigned) = UInt(x) * UInt(y) +mul_prod(x::BitSignedSmall, y::BitSignedSmall) = Int(x) * Int(y) +mul_prod(x::BitUnsignedSmall, y::BitUnsignedSmall) = UInt(x) * UInt(y) mul_prod(x::Real, y::Real)::Real = x * y ## foldl && mapfoldl @@ -348,11 +340,11 @@ reduce_empty(::typeof(&), ::Type{Bool}) = true reduce_empty(::typeof(|), ::Type{Bool}) = false reduce_empty(::typeof(add_sum), ::Type{T}) where {T} = reduce_empty(+, T) -reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:SmallSigned} = zero(Int) -reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:SmallUnsigned} = zero(UInt) +reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:BitSignedSmall} = zero(Int) +reduce_empty(::typeof(add_sum), ::Type{T}) where {T<:BitUnsignedSmall} = zero(UInt) reduce_empty(::typeof(mul_prod), ::Type{T}) where {T} = reduce_empty(*, T) -reduce_empty(::typeof(mul_prod), ::Type{T}) where {T<:SmallSigned} = one(Int) -reduce_empty(::typeof(mul_prod), ::Type{T}) where {T<:SmallUnsigned} = one(UInt) +reduce_empty(::typeof(mul_prod), ::Type{T}) where {T<:BitSignedSmall} = one(Int) +reduce_empty(::typeof(mul_prod), ::Type{T}) where {T<:BitUnsignedSmall} = one(UInt) reduce_empty(op::BottomRF, ::Type{T}) where {T} = reduce_empty(op.rf, T) reduce_empty(op::MappingRF, ::Type{T}) where {T} = mapreduce_empty(op.f, op.rf, T) @@ -402,11 +394,11 @@ reduce_first(::typeof(+), x::Bool) = Int(x) reduce_first(::typeof(*), x::AbstractChar) = string(x) reduce_first(::typeof(add_sum), x) = reduce_first(+, x) -reduce_first(::typeof(add_sum), x::SmallSigned) = Int(x) -reduce_first(::typeof(add_sum), x::SmallUnsigned) = UInt(x) +reduce_first(::typeof(add_sum), x::BitSignedSmall) = Int(x) +reduce_first(::typeof(add_sum), x::BitUnsignedSmall) = UInt(x) reduce_first(::typeof(mul_prod), x) = reduce_first(*, x) -reduce_first(::typeof(mul_prod), x::SmallSigned) = Int(x) -reduce_first(::typeof(mul_prod), x::SmallUnsigned) = UInt(x) +reduce_first(::typeof(mul_prod), x::BitSignedSmall) = Int(x) +reduce_first(::typeof(mul_prod), x::BitUnsignedSmall) = UInt(x) """ Base.mapreduce_first(f, op, x) diff --git a/test/reducedim.jl b/test/reducedim.jl index 77ed94664539fa..8f629fa83f28d4 100644 --- a/test/reducedim.jl +++ b/test/reducedim.jl @@ -576,8 +576,8 @@ end @testset "type of sum(::Array{$T}" for T in [UInt8, Int8, Int32, Int64, BigInt] result = sum(T[1 2 3; 4 5 6; 7 8 9], dims=2) @test result == hcat([6, 15, 24]) - @test eltype(result) === (T <: Base.SmallSigned ? Int : - T <: Base.SmallUnsigned ? UInt : + @test eltype(result) === (T <: Base.BitSignedSmall ? Int : + T <: Base.BitUnsignedSmall ? UInt : T) end From 7a62dffe784a4ced9372d987e9b9b4a990a4d5d1 Mon Sep 17 00:00:00 2001 From: Steve Kelly Date: Wed, 27 Mar 2024 09:38:29 -0400 Subject: [PATCH 041/123] Harmonize and add docs for `--math-mode` (#53818) The behavior was changed and the CLI doc was removed in #41638, though we current still allow users to selectively use the `@fastmath` macro. This adds back the CLI docs and makes a minor clarification about behavior. Co-authored-by: Matt Bauman --- doc/man/julia.1 | 4 ++-- doc/src/manual/command-line-interface.md | 2 +- src/jloptions.c | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/man/julia.1 b/doc/man/julia.1 index a7d16abe3f85cf..2d7f41b2217bc9 100644 --- a/doc/man/julia.1 +++ b/doc/man/julia.1 @@ -200,8 +200,8 @@ Control whether inlining is permitted, including overriding @inline declarations Emit bounds checks always, never, or respect @inbounds declarations .TP ---math-mode={ieee|user} -Disallow or enable unsafe floating point optimizations (overrides @fastmath declaration) +--math-mode={ieee|user*} +Always follow `ieee` floating point semantics or respect `@fastmath` declarations .TP --code-coverage[={none*|user|all}] diff --git a/doc/src/manual/command-line-interface.md b/doc/src/manual/command-line-interface.md index 448964bf1ef8a2..1bb9507756aec9 100644 --- a/doc/src/manual/command-line-interface.md +++ b/doc/src/manual/command-line-interface.md @@ -195,7 +195,7 @@ The following is a complete list of command-line switches available when launchi |`-g`, `--debug-info={0,1*,2}` |Set the level of debug info generation (level is 2 if `-g` is used without a level) ($)| |`--inline={yes\|no}` |Control whether inlining is permitted, including overriding `@inline` declarations| |`--check-bounds={yes\|no\|auto*}` |Emit bounds checks always, never, or respect `@inbounds` declarations ($)| -|`--math-mode={ieee,fast}` |Disallow or enable unsafe floating point optimizations (overrides `@fastmath` declaration)| +|`--math-mode={ieee\|user*}` |Always follow `ieee` floating point semantics or respect `@fastmath` declarations| |`--code-coverage[={none*\|user\|all}]` |Count executions of source lines (omitting setting is equivalent to `user`)| |`--code-coverage=@` |Count executions but only in files that fall under the given file path/directory. The `@` prefix is required to select this option. A `@` with no path will track the current directory.| |`--code-coverage=tracefile.info` |Append coverage information to the LCOV tracefile (filename supports format tokens).| diff --git a/src/jloptions.c b/src/jloptions.c index 085e5f365ac46a..9020404e707813 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -177,6 +177,7 @@ static const char opts[] = #ifdef USE_POLLY " --polly={yes*|no} Enable or disable the polyhedral optimizer Polly (overrides @polly declaration)\n" #endif + " --math-mode={ieee|user*} Always follow `ieee` floating point semantics or respect `@fastmath` declarations\n\n" // instrumentation options " --code-coverage[={none*|user|all}]\n" @@ -782,7 +783,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) else if (!strcmp(optarg,"user")) jl_options.fast_math = JL_OPTIONS_FAST_MATH_DEFAULT; else - jl_errorf("julia: invalid argument to --math-mode (%s)", optarg); + jl_errorf("julia: invalid argument to --math-mode={ieee|user} (%s)", optarg); break; case opt_worker: jl_options.worker = 1; From a3616a8ff21aaee31b0b4353f3cdcb4e4a119e9e Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 27 Mar 2024 10:02:22 -0400 Subject: [PATCH 042/123] Print more info when backtrace test fails (#53874) This test fails intermittently on win32. Let's try to print some more info in that case to see if we can find out anything. --- test/backtrace.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/backtrace.jl b/test/backtrace.jl index aa10720316a5df..68873678df57b1 100644 --- a/test/backtrace.jl +++ b/test/backtrace.jl @@ -262,10 +262,14 @@ let code = """ if ip isa Base.InterpreterIP && ip.code isa Core.MethodInstance] num_fs = sum(meth_names .== :f29695) num_gs = sum(meth_names .== :g29695) - print(num_fs, ' ', num_gs) + if num_fs != 1000 || num_gs != 1000 + Base.show_backtrace(stderr, bt) + error("Expected 1000 frames each, got \$num_fs, \$num_fs") + end + exit() """ - @test read(`$(Base.julia_cmd()) --startup-file=no --compile=min -e $code`, String) == "1000 1000" + @test success(pipeline(`$(Base.julia_cmd()) --startup-file=no --compile=min -e $code`; stderr)) end # Test that modules make it into InterpreterIP for top-level code From 0e2409aff821288ac078b1116fe9ae56ef93b7a5 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 27 Mar 2024 10:29:46 -0400 Subject: [PATCH 043/123] inference: Fix handling of :throw_undef_if_not (#53875) This stmt type doesn't usually get introduced until IR conversion, but we do allow it in inference (to allow it to be emitted by packages like Diffractor). However, we didn't have a test for it, so the code path grew a bug. Fix that and also allow this as a frontend form, so it can be tested without resorting to generated functions. --- base/compiler/abstractinterpretation.jl | 2 +- src/julia-syntax.scm | 2 +- test/compiler/inference.jl | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index ba8f0b6709f8ff..836147d4e502b1 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -2625,7 +2625,7 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp effects = EFFECTS_UNKNOWN end elseif ehead === :throw_undef_if_not - condt = argextype(stmt.args[2], ir) + condt = abstract_eval_value(interp, e.args[2], vtypes, sv) condval = maybe_extract_const_bool(condt) t = Nothing exct = UndefVarError diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index f1ae6c90bda6a3..899476afc093a9 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -4839,7 +4839,7 @@ f(x) = yt(x) (set! global-const-error current-loc)) (emit e)))) ((atomic) (error "misplaced atomic declaration")) - ((isdefined) (if tail (emit-return tail e) e)) + ((isdefined throw_undef_if_not) (if tail (emit-return tail e) e)) ((boundscheck) (if tail (emit-return tail e) e)) ((method) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 30c5c306faa94d..07797d8b9f0574 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5640,6 +5640,13 @@ end @test issue53590(false, false) == Float64 @test issue53590(false, true) == Real +# Expr(:throw_undef_if_not) handling +@eval function has_tuin() + $(Expr(:throw_undef_if_not, :x, false)) +end +@test Core.Compiler.return_type(has_tuin, Tuple{}) === Union{} +@test_throws UndefVarError has_tuin() + # issue #53585 let t = ntuple(i -> i % 8 == 1 ? Int64 : Float64, 4000) @test only(Base.return_types(Base.promote_typeof, t)) == Type{Float64} From bb3b09de50720d4b47c34fd53638e292c50c695e Mon Sep 17 00:00:00 2001 From: Jeff Bezanson Date: Wed, 27 Mar 2024 11:20:10 -0400 Subject: [PATCH 044/123] add invokelatest to on_done callback in bracketed paste (#53696) fixes #52120 --- stdlib/REPL/src/REPL.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 789def3d317bf5..f75e91da67be2e 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -1379,7 +1379,7 @@ function setup_interface( # execute the statement terminal = LineEdit.terminal(s) # This is slightly ugly but ok for now raw!(terminal, false) && disable_bracketed_paste(terminal) - LineEdit.mode(s).on_done(s, LineEdit.buffer(s), true) + @invokelatest LineEdit.mode(s).on_done(s, LineEdit.buffer(s), true) raw!(terminal, true) && enable_bracketed_paste(terminal) LineEdit.push_undo(s) # when the last line is incomplete end From f4866b7617a3d214e6e4437e13fd8b389c64b078 Mon Sep 17 00:00:00 2001 From: FX Coudert Date: Wed, 27 Mar 2024 16:40:54 +0100 Subject: [PATCH 045/123] Update p7zip to 17.05 (#53863) Following https://github.com/JuliaPackaging/Yggdrasil/pull/8352 --- deps/checksums/p7zip | 68 +++++++++++++++++------------------ deps/p7zip.version | 2 +- stdlib/Manifest.toml | 2 +- stdlib/p7zip_jll/Project.toml | 2 +- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/deps/checksums/p7zip b/deps/checksums/p7zip index 3a3986977e3cfb..272f1d768161f9 100644 --- a/deps/checksums/p7zip +++ b/deps/checksums/p7zip @@ -1,34 +1,34 @@ -p7zip-17.04.tar.gz/md5/00acfd6be87848231722d2d53f89e4a5 -p7zip-17.04.tar.gz/sha512/ad176db5b657b1c39584f6792c47978d94f2f1ccb1cf5bdb0f52ab31a7356b3822f4a922152c4253f4aa7e79166ba052b6592530b7a38f548cd555fe9c008be3 -p7zip.v17.4.0+2.aarch64-apple-darwin.tar.gz/md5/b418adbae6512a13e04407c120ba78e0 -p7zip.v17.4.0+2.aarch64-apple-darwin.tar.gz/sha512/818f7afb0d3ffbff8079f5f4b8e9745a847148ac9cb5a261b6ca2f2f3a1dd722fa93f798645129bc9bc4a48f756bf2e55605791abb394a32635dfaef31f21e70 -p7zip.v17.4.0+2.aarch64-linux-gnu.tar.gz/md5/3f976d6514e6327a9aee4a3f21a25a64 -p7zip.v17.4.0+2.aarch64-linux-gnu.tar.gz/sha512/a4dd8be97c53b864e81aae40e248759f97249fbd6d8c5b91f0ac115a84126cbfc4825ffa3876f5e8b66652b014a78ba04e3ffc1ba1d9c96786b914b1279682c0 -p7zip.v17.4.0+2.aarch64-linux-musl.tar.gz/md5/b31699d7ea671c689fa9194913fbe7ee -p7zip.v17.4.0+2.aarch64-linux-musl.tar.gz/sha512/5c8d95df66055ab8027b047b23534743ac929befd37dc8a8e591deece22006209f94524f7951de580a5ded9530ead2ce7ec3370c482865554830b53d09f41bf1 -p7zip.v17.4.0+2.armv6l-linux-gnueabihf.tar.gz/md5/fbe2ebeeaa6e5b33dcb71662fb7040f1 -p7zip.v17.4.0+2.armv6l-linux-gnueabihf.tar.gz/sha512/6ca1d7eb1d3f6a7c4dc9860ac3d5a835abce92cddcda015a93086ecde44ed1b3d9f83a3c1e1eddc510af429ec269716dde6bc5fae4aa6bbbc3dcfc9a51326786 -p7zip.v17.4.0+2.armv6l-linux-musleabihf.tar.gz/md5/dae4b1e6060bf4431d3ead53e6b3e167 -p7zip.v17.4.0+2.armv6l-linux-musleabihf.tar.gz/sha512/856c2283c63728d8c542ce5a3d58e38c985f190774c407fc421dd30f05e0ae3467e2844cb7d535aa8a6b8fb24b21b29af75b736fbd9af67c24340609ad6b5841 -p7zip.v17.4.0+2.armv7l-linux-gnueabihf.tar.gz/md5/42b6b9b19158303c4399d651ee5b14cf -p7zip.v17.4.0+2.armv7l-linux-gnueabihf.tar.gz/sha512/4f8792639db8599af026f592496a8c594c0fd6a62dc949965add55b1b85a95d4edc2f99960cf5b21e7beeb8e1bca1d9c1a1a34600103df04dc20d0509410c486 -p7zip.v17.4.0+2.armv7l-linux-musleabihf.tar.gz/md5/e34f5585a50c0cfce29c79e9ece60cf4 -p7zip.v17.4.0+2.armv7l-linux-musleabihf.tar.gz/sha512/87f72568f5a877008d3a8a032a85f69c29d3af4293d7b42d70419bb4c9ca7e99dc13c6b22621ca83886d07f765118451ee9f2a3aee63979d8070910887bf7cdd -p7zip.v17.4.0+2.i686-linux-gnu.tar.gz/md5/d917247133b1c62663334b6a908e30e9 -p7zip.v17.4.0+2.i686-linux-gnu.tar.gz/sha512/4839bec129b7fbd68c61d35fd3b3af9863c757d9fec0220926d45f1f58174d88d0bbb4a472d259d1d77775b906e9c58ba707fc20e2a4a060ca9030722609182d -p7zip.v17.4.0+2.i686-linux-musl.tar.gz/md5/951614fc7597de8c12e0109cbd81bfa9 -p7zip.v17.4.0+2.i686-linux-musl.tar.gz/sha512/f0420ddd6df82d2b3e1ece9cc5cf537cb0803d291d274a495bb9a575bb253a4241cdae38a88e43ddafaab7f6911b310a30c1b874b0a0a9bc447f8c42c5a24652 -p7zip.v17.4.0+2.i686-w64-mingw32.tar.gz/md5/cc81daf0e40990c48db178cb53a95d08 -p7zip.v17.4.0+2.i686-w64-mingw32.tar.gz/sha512/ae5bcbcf32dad20db95319c3c2f874fdbb0cd41054d6c192f2ab106e0aece1b4b0b591055b37c2c909b07b303204a75dec5c4b3c224243c2041da811f99cd7e5 -p7zip.v17.4.0+2.powerpc64le-linux-gnu.tar.gz/md5/e97d74ac4dacfaa215c3119e055a2df0 -p7zip.v17.4.0+2.powerpc64le-linux-gnu.tar.gz/sha512/8b0596ebd84fa9947e8f15f63c426339980e08c81eb4c1474b4a66af6329f0a2fe1bd31eef964d147bf9cf0213e85bdc143fab1a4f1dbfa09da5ebd9e73a3d8d -p7zip.v17.4.0+2.x86_64-apple-darwin.tar.gz/md5/4d9a26dbfc0a02a812c8f7de20ea5440 -p7zip.v17.4.0+2.x86_64-apple-darwin.tar.gz/sha512/3cba51ba9742b616afec13a14e8e3bd3c73c835256af8f6a49d4abf32f5ddf3f86ac8ae08ffd9bc331caa8a711dd1b63f4cd082443a7863e3d512f6ca2152bcd -p7zip.v17.4.0+2.x86_64-linux-gnu.tar.gz/md5/37b7570712ecb8677059f4280a346201 -p7zip.v17.4.0+2.x86_64-linux-gnu.tar.gz/sha512/9445add6a475bdfc2924dc52c07917c2746b07a41a2dbfdab8ad4b4e5b87b0192c13f4da5da64e5d3544bbf9c79fda3c633664eecb372e8475031789770c41ee -p7zip.v17.4.0+2.x86_64-linux-musl.tar.gz/md5/04d6ae950d05c81c6b165721de2ba7e7 -p7zip.v17.4.0+2.x86_64-linux-musl.tar.gz/sha512/524d8ed80a1af903b572d5e32710b384702175cacc83ce2305d7f7a35d45aae7d08e2afc14a9e40c934ba4eb578787afa9bece4f820e96e4b624869cb2bcec26 -p7zip.v17.4.0+2.x86_64-unknown-freebsd.tar.gz/md5/e2a3361e91258e39db541c9dec5a73fe -p7zip.v17.4.0+2.x86_64-unknown-freebsd.tar.gz/sha512/ecc1db9a1823ebdac290548f6e001688b5d111caede4cbfab4e2ef492dbb31844690e9b69360ed9c6ebb2affded7f352d57c0e5cfe67be951876d1fc5e87d92d -p7zip.v17.4.0+2.x86_64-w64-mingw32.tar.gz/md5/2b5f77bb31526c469e0fd48399d0cf9a -p7zip.v17.4.0+2.x86_64-w64-mingw32.tar.gz/sha512/a3a17af4db98b82b71c8d4d09e5315dc4fa77b38cc19f0593654b63744bc7489383d40032e48c2141d6b55e330d1538c527819378a2575a245de436bc6daf532 +p7zip-17.05.tar.gz/md5/de921a08f37242a8eed8e4a758fbcb58 +p7zip-17.05.tar.gz/sha512/97a7cfd15287998eb049c320548477be496c4ddf6b45c833c42adca4ab88719b07a442ae2e71cf2dc3b30a0777a3acab0a1a30f01fd85bacffa3fa9bd22c3f7d +p7zip.v17.5.0+0.aarch64-apple-darwin.tar.gz/md5/2a254e251901b3d1ddfd7aff23a6e5eb +p7zip.v17.5.0+0.aarch64-apple-darwin.tar.gz/sha512/8efb9a2c9bcab388e523adba3dc0b876e8ae34e2440c3eee01fd780eb87c8619c7a7bbdc46d703ccefff6aa6ad64c4e4b45b723136ab1f6fd6de4f52e75ebbbf +p7zip.v17.5.0+0.aarch64-linux-gnu.tar.gz/md5/bb1f3773fd409dbb91a10f7d9d2e99b5 +p7zip.v17.5.0+0.aarch64-linux-gnu.tar.gz/sha512/e95ccc342be644570d218d25403b91a7db9ee983fbf8cce3deff453355d68d426f9301eaac865a98691025b596b8cd77ebebf6184c0eaf8b2f294bc6763b9a4b +p7zip.v17.5.0+0.aarch64-linux-musl.tar.gz/md5/3fac518a6a70412294d71ca510958cf2 +p7zip.v17.5.0+0.aarch64-linux-musl.tar.gz/sha512/fc127790739bf8a8b918b2e83753d86f5e79ee8706bde4cc79d74d9f7d846aae99a109da4b2b3cc92ccedc1eef4d52a555a65a95f588e173e0fecc11f2ca21e6 +p7zip.v17.5.0+0.armv6l-linux-gnueabihf.tar.gz/md5/355410848192de3b02d12fd663867f4b +p7zip.v17.5.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/8f103b41e755d157d70dacca89a0ef4610bea109686b4005e8edd5f79ed2e6419c00c2625d0ab90e6e33fa389e670490d8de263c0bdae952cc34cbbf440e275f +p7zip.v17.5.0+0.armv6l-linux-musleabihf.tar.gz/md5/34363b227306fce34a728af54b71064f +p7zip.v17.5.0+0.armv6l-linux-musleabihf.tar.gz/sha512/8dd7b37ce6223c9fedcaa999eb806eb6dec8c4a3133d3c07e2456cb8543b8e4f5b881c1bff2d2e25f19b1312b18673e9013aeff87d6a274eec6c451b1ba0d6b9 +p7zip.v17.5.0+0.armv7l-linux-gnueabihf.tar.gz/md5/dbb1fc0cf3bea674442ff8cc932a94cd +p7zip.v17.5.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/c4d71d905fa420391417786ed206a0c334475dd0df8baa1fc3f6560ce548db11805003d0d0b35bb622fe818c761f2b0abe0796d1cbfce2a922da69e697f056a2 +p7zip.v17.5.0+0.armv7l-linux-musleabihf.tar.gz/md5/d188b5dd453faedb616ba9c48fdeab6b +p7zip.v17.5.0+0.armv7l-linux-musleabihf.tar.gz/sha512/ea30a775370502ca9e271b87cbda528d0c51d63ce0df41883d4dbc1527a32f251d797f3692fcf9b883b5fbaaad80515b971a8f8fe09ba102978b19a0ecb58528 +p7zip.v17.5.0+0.i686-linux-gnu.tar.gz/md5/dc02bdde045a0b6b22cf14d6960e63ed +p7zip.v17.5.0+0.i686-linux-gnu.tar.gz/sha512/d2d0dd14a5fc1163fea2276e0925bfa8d075d5dba1d8018e4e3160977d3b09642b2e521d8e57d049abaf0e2ea391a846f0b0136b3c59e8b476c8c52ac5210447 +p7zip.v17.5.0+0.i686-linux-musl.tar.gz/md5/0b8658147938a8ec109ee2b3b0a0665f +p7zip.v17.5.0+0.i686-linux-musl.tar.gz/sha512/411b2950f5928c537b87ba0651c09c08e57afed765db9fee89eda8b12939ef0da94c8ba38c0a24ba46b4513a0e4cca798eb09f2b20a011099ed3cf14455dd19e +p7zip.v17.5.0+0.i686-w64-mingw32.tar.gz/md5/98bdd8767c77a35f71303ff490a3d363 +p7zip.v17.5.0+0.i686-w64-mingw32.tar.gz/sha512/14f08071af74297df8bfe1d9f7efa3c0212e62ace573848f17b729e4c36dc3861110f3c5cc9315364c318e5b040736443a24492e86d76161993653a309996eb3 +p7zip.v17.5.0+0.powerpc64le-linux-gnu.tar.gz/md5/b18c917b9852898a9b9d6d24bcc6863e +p7zip.v17.5.0+0.powerpc64le-linux-gnu.tar.gz/sha512/0148dc8a0bc9c95212d7f8e2f92ee24e968eb7290fe72c7ae02e286bf5c05dd6b1f10b32350a7ff37777ed5a8cc21f3303f464620f3394c7a4690ae98bf77299 +p7zip.v17.5.0+0.x86_64-apple-darwin.tar.gz/md5/da31752a2556644d39e48649bb0111de +p7zip.v17.5.0+0.x86_64-apple-darwin.tar.gz/sha512/0695ad111263d2fadfdf9a46ce7ee80def0bf60db7d1c2585ed2af6fc945fb169311a9f1ffc6f95fb43b0b03694d2d1be9136d3d78ba2ef2b19228987883a385 +p7zip.v17.5.0+0.x86_64-linux-gnu.tar.gz/md5/2fb55d86e4eaccb0488bd637d088b996 +p7zip.v17.5.0+0.x86_64-linux-gnu.tar.gz/sha512/38ac355157d59c09f308fc29964d0e9c1466c9633efd8d3c6ff3c738abce2af45ebc6b92a29f56d5e7baa4871f9f39b14ecfcbedd4e2f4ca7c0fe6627c6b13e7 +p7zip.v17.5.0+0.x86_64-linux-musl.tar.gz/md5/f0bd567a851d2dd9d306552ffafbca3a +p7zip.v17.5.0+0.x86_64-linux-musl.tar.gz/sha512/e60047a6e7e3496cb6658f87c8c88676f399cd9f3d0d7daa880b6be09cd5525f7f22776896f1375722b47555514ff8c018f02ce800ec3fd0ed922e16e8a6d657 +p7zip.v17.5.0+0.x86_64-unknown-freebsd.tar.gz/md5/d37bd26e39a3ec84f262636f70624341 +p7zip.v17.5.0+0.x86_64-unknown-freebsd.tar.gz/sha512/0604a880c19f9d72d5828edd75be641625c29f230b3a5e7d70ec3812c014c96b76ee7b45e0e80f49be63f109a48700e75d1e5be01b5ae7b46d42dafda9885e8c +p7zip.v17.5.0+0.x86_64-w64-mingw32.tar.gz/md5/f02c7b2481dee880b096340a8735350f +p7zip.v17.5.0+0.x86_64-w64-mingw32.tar.gz/sha512/08b717c1b072d1309f6af8973eb09b1a482abb7ae7d01fba79873d4310a7c11292e2e8779029f99cc60627ed0d064224bc87782e587c520f970b840b7b838052 diff --git a/deps/p7zip.version b/deps/p7zip.version index d4a13155d9162f..0fcde938eeb95c 100644 --- a/deps/p7zip.version +++ b/deps/p7zip.version @@ -2,4 +2,4 @@ P7ZIP_JLL_NAME := p7zip ## source build -P7ZIP_VER := 17.04 +P7ZIP_VER := 17.05 diff --git a/stdlib/Manifest.toml b/stdlib/Manifest.toml index d95447c0a25807..4df442c6833d1c 100644 --- a/stdlib/Manifest.toml +++ b/stdlib/Manifest.toml @@ -297,4 +297,4 @@ version = "1.60.0+0" [[deps.p7zip_jll]] deps = ["Artifacts", "Libdl"] uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" -version = "17.4.0+2" +version = "17.5.0+0" diff --git a/stdlib/p7zip_jll/Project.toml b/stdlib/p7zip_jll/Project.toml index b1bd4bc9e0a1a2..6bca9d1d0545b3 100644 --- a/stdlib/p7zip_jll/Project.toml +++ b/stdlib/p7zip_jll/Project.toml @@ -1,6 +1,6 @@ name = "p7zip_jll" uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" -version = "17.4.0+2" +version = "17.5.0+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" From 4ee10228176c960fc3d0046390ab2ef4df7ab08a Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 27 Mar 2024 15:44:33 -0400 Subject: [PATCH 046/123] opaque_closure: Lookup optimized oc source inside code instance (#53878) This is an alternative to #53852. I don't think it's semantically legal to put optimized source into the :source field of a method, but it should be fine to just look it up from the CodeInstance. That said, this is a bit of an unusual configuration. In particular it wasn't even reachable with the surface APIs, which assumed that inferred IR was always supposed to be compiled. --- base/opaque_closure.jl | 12 ++++++------ src/interpreter.c | 14 +++++++++++++- test/opaque_closure.jl | 5 +++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/base/opaque_closure.jl b/base/opaque_closure.jl index 83a364646ad391..b00955e7a0ca0e 100644 --- a/base/opaque_closure.jl +++ b/base/opaque_closure.jl @@ -59,7 +59,7 @@ end function Core.OpaqueClosure(ir::IRCode, @nospecialize env...; isva::Bool = false, slotnames::Union{Nothing,Vector{Symbol}}=nothing, - do_compile::Bool = true) + kwargs...) # NOTE: we need ir.argtypes[1] == typeof(env) ir = Core.Compiler.copy(ir) # if the user didn't specify a definition MethodInstance or filename Symbol to use for the debuginfo, set a filename now @@ -78,11 +78,11 @@ function Core.OpaqueClosure(ir::IRCode, @nospecialize env...; src.slotflags = fill(zero(UInt8), nargtypes) src.slottypes = copy(ir.argtypes) src = Core.Compiler.ir_to_codeinf!(src, ir) - return generate_opaque_closure(sig, Union{}, rt, src, nargs, isva, env...; do_compile) + return generate_opaque_closure(sig, Union{}, rt, src, nargs, isva, env...; kwargs...) end -function Core.OpaqueClosure(src::CodeInfo, @nospecialize env...; rettype, sig, nargs, isva=false) - return generate_opaque_closure(sig, Union{}, rettype, src, nargs, isva, env...) +function Core.OpaqueClosure(src::CodeInfo, @nospecialize env...; rettype, sig, nargs, isva=false, kwargs...) + return generate_opaque_closure(sig, Union{}, rettype, src, nargs, isva, env...; kwargs...) end function generate_opaque_closure(@nospecialize(sig), @nospecialize(rt_lb), @nospecialize(rt_ub), @@ -90,8 +90,8 @@ function generate_opaque_closure(@nospecialize(sig), @nospecialize(rt_lb), @nosp mod::Module=@__MODULE__, lineno::Int=0, file::Union{Nothing,Symbol}=nothing, - isinferred::Bool=true, - do_compile::Bool=true) + do_compile::Bool=true, + isinferred::Bool=true) return ccall(:jl_new_opaque_closure_from_code_info, Any, (Any, Any, Any, Any, Any, Cint, Any, Cint, Cint, Any, Cint, Cint), sig, rt_lb, rt_ub, mod, src, lineno, file, nargs, isva, env, do_compile, isinferred) end diff --git a/src/interpreter.c b/src/interpreter.c index 2fb4b91927496f..c7d7fa88ea447f 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -760,7 +760,19 @@ JL_DLLEXPORT const jl_callptr_t jl_fptr_interpret_call_addr = &jl_fptr_interpret jl_value_t *jl_interpret_opaque_closure(jl_opaque_closure_t *oc, jl_value_t **args, size_t nargs) { jl_method_t *source = oc->source; - jl_code_info_t *code = jl_uncompress_ir(source, NULL, (jl_value_t*)source->source); + jl_code_info_t *code = NULL; + if (source->source) { + code = jl_uncompress_ir(source, NULL, (jl_value_t*)source->source); + } + else { + // OC constructed from optimized IR. It'll have a single specialization with optimized code + // in it that we'll try to interpret. + jl_svec_t *specializations = (jl_svec_t*)jl_atomic_load_relaxed(&source->specializations); + assert(jl_is_method_instance(specializations)); + jl_method_instance_t *mi = (jl_method_instance_t *)specializations; + jl_code_instance_t *ci = jl_atomic_load_relaxed(&mi->cache); + code = jl_uncompress_ir(source, ci, jl_atomic_load_relaxed(&ci->inferred)); + } interpreter_state *s; unsigned nroots = jl_source_nslots(code) + jl_source_nssavalues(code) + 2; jl_task_t *ct = jl_current_task; diff --git a/test/opaque_closure.jl b/test/opaque_closure.jl index 8378d8ae0d3dda..cb7576ee656be6 100644 --- a/test/opaque_closure.jl +++ b/test/opaque_closure.jl @@ -358,3 +358,8 @@ let ir = first(only(Base.code_ircode(sin, (Int,)))) oc = Core.OpaqueClosure(ir) @test (Base.show_method(IOBuffer(), oc.source::Method); true) end + +let ir = first(only(Base.code_ircode(sin, (Int,)))) + oc = Core.OpaqueClosure(ir; do_compile=false) + @test oc(1) == sin(1) +end From e07c0f1ddbfc89ad1ac4dda7246d8ed5d0d57c19 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 27 Mar 2024 23:09:07 -0400 Subject: [PATCH 047/123] inference: Fix correctness and ensure termination in the presence of PhiNodes (#53876) There's two related, but distinct, issues here: 1. We were not using `tmerge` for merging SSA results inside loops, which could cause infinite looping. In the absence of PhiNodes, things usually have to go through a slot to be able to make the round trip, which would usually put a PhiNode on the path, but it's possible there may be other ways to smuggle things around (e.g. through exception handling). 2. We were not properly accounting for the fact that PhiNode uses do not need to be linearly ordered in the same BB, so we were getting the type of the testcase here incorrect by failing to re-schedule the PhiNode. The first of these shows up in the Diffractor test suite, the second was found by writing the test case. --- base/compiler/abstractinterpretation.jl | 12 +++++++++-- base/compiler/inferencestate.jl | 5 +---- test/compiler/inference.jl | 28 +++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 836147d4e502b1..ce8494b1feff09 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -2731,7 +2731,8 @@ function abstract_eval_phi(interp::AbstractInterpreter, phi::PhiNode, vtypes::Un val = phi.values[i] # N.B.: Phi arguments are restricted to not have effects, so we can drop # them here safely. - rt = tmerge(typeinf_lattice(interp), rt, abstract_eval_special_value(interp, val, vtypes, sv).rt) + thisval = abstract_eval_special_value(interp, val, vtypes, sv).rt + rt = tmerge(typeinf_lattice(interp), rt, thisval) end return rt end @@ -2745,7 +2746,14 @@ function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), if !isa(e, Expr) if isa(e, PhiNode) add_curr_ssaflag!(sv, IR_FLAGS_REMOVABLE) - return RTEffects(abstract_eval_phi(interp, e, vtypes, sv), Union{}, EFFECTS_TOTAL) + # Implement convergence for PhiNodes. In particular, PhiNodes need to tmerge over + # the incoming values from all iterations, but `abstract_eval_phi` will only tmerge + # over the first and last iterations. By tmerging in the current old_rt, we ensure that + # we will not lose an intermediate value. + rt = abstract_eval_phi(interp, e, vtypes, sv) + old_rt = sv.ssavaluetypes[sv.currpc] + rt = old_rt === NOT_FOUND ? rt : tmerge(typeinf_lattice(interp), old_rt, rt) + return RTEffects(rt, Union{}, EFFECTS_TOTAL) end (; rt, exct, effects) = abstract_eval_special_value(interp, e, vtypes, sv) else diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 0102f042ba2baf..38fb13495ad851 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -691,10 +691,7 @@ function record_ssa_assign!(๐•ƒแตข::AbstractLattice, ssa_id::Int, @nospecialize for r in frame.ssavalue_uses[ssa_id] if was_reached(frame, r) usebb = block_for_inst(frame.cfg, r) - # We're guaranteed to visit the statement if it's in the current - # basic block, since SSA values can only ever appear after their - # def. - if usebb != frame.currbb + if usebb != frame.currbb || r < ssa_id push!(W, usebb) end end diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 07797d8b9f0574..62c134e58c2a62 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5652,3 +5652,31 @@ let t = ntuple(i -> i % 8 == 1 ? Int64 : Float64, 4000) @test only(Base.return_types(Base.promote_typeof, t)) == Type{Float64} @test only(Base.return_types(vcat, t)) == Vector{Float64} end + +# Infinite loop in inference on SSA assignment +const stop_infinite_loop::Base.Threads.Atomic{Bool} = Base.Threads.Atomic{Bool}(false) +function gen_infinite_loop_ssa_generator(world::UInt, source, _) + ci = make_codeinfo(Any[ + # Block 1 + (), + # Block 2 + PhiNode(Int32[1, 5], Any[SSAValue(1), SSAValue(3)]), + Expr(:call, tuple, SSAValue(2)), + Expr(:call, getindex, GlobalRef(@__MODULE__, :stop_infinite_loop)), + GotoIfNot(SSAValue(4), 2), + # Block 3 + ReturnNode(SSAValue(2)) + ]; slottypes=Any[Any]) + ci.slotnames = Symbol[:var"#self#"] + ci +end + +@eval function gen_infinite_loop_ssa() + $(Expr(:meta, :generated, gen_infinite_loop_ssa_generator)) + $(Expr(:meta, :generated_only)) + #= no body =# +end + +# We want to make sure that both this returns `Tuple` and that +# it doesn't infinite loop inside inference. +@test Core.Compiler.return_type(gen_infinite_loop_ssa, Tuple{}) === Tuple From 2a944fa336e4391a2f821e986675c5ac7e7a1fb6 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Thu, 28 Mar 2024 11:20:54 -0400 Subject: [PATCH 048/123] RNG reproducibility discussion - rm confusing ref to MenneTwister (#53879) There was an odd phrase "in particular if `MersenneTwister` is used" in the reproducibility discussion, which made it seem like the discussion was specific to `MersenneTwister` (which we don't even use by default anymore). I just deleted this clause. --- stdlib/Random/docs/src/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/Random/docs/src/index.md b/stdlib/Random/docs/src/index.md index 96320ee2161989..9ef86bb0d94f80 100644 --- a/stdlib/Random/docs/src/index.md +++ b/stdlib/Random/docs/src/index.md @@ -350,8 +350,8 @@ DocTestSetup = nothing By using an RNG parameter initialized with a given seed, you can reproduce the same pseudorandom number sequence when running your program multiple times. However, a minor release of Julia (e.g. -1.3 to 1.4) *may change* the sequence of pseudorandom numbers generated from a specific seed, in -particular if `MersenneTwister` is used. (Even if the sequence produced by a low-level function like +1.3 to 1.4) *may change* the sequence of pseudorandom numbers generated from a specific seed. +(Even if the sequence produced by a low-level function like [`rand`](@ref) does not change, the output of higher-level functions like [`randsubseq`](@ref) may change due to algorithm updates.) Rationale: guaranteeing that pseudorandom streams never change prohibits many algorithmic improvements. From 6f51966bf76c8e6b05dd0cd6f84c01aa5bb087c4 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Thu, 28 Mar 2024 11:00:19 -0500 Subject: [PATCH 049/123] Improve error message when source length is wrong in reshape (#53883) --- base/bitarray.jl | 2 +- base/reshapedarray.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 4411fc93238260..079dbefe03a94c 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -482,7 +482,7 @@ end reshape(B::BitArray, dims::Tuple{Vararg{Int}}) = _bitreshape(B, dims) function _bitreshape(B::BitArray, dims::NTuple{N,Int}) where N prod(dims) == length(B) || - throw(DimensionMismatch("new dimensions $(dims) must be consistent with array size $(length(B))")) + throw(DimensionMismatch("new dimensions $(dims) must be consistent with array length $(length(B))")) Br = BitArray{N}(undef, ntuple(i->0,Val(N))...) Br.chunks = B.chunks Br.len = prod(dims) diff --git a/base/reshapedarray.jl b/base/reshapedarray.jl index 63e508e8835dee..f1bcc9fe303a74 100644 --- a/base/reshapedarray.jl +++ b/base/reshapedarray.jl @@ -39,7 +39,7 @@ eltype(::Type{<:ReshapedArrayIterator{I}}) where {I} = @isdefined(I) ? ReshapedI # reshaping to same # of dimensions @eval function reshape(a::Array{T,M}, dims::NTuple{N,Int}) where {T,N,M} throw_dmrsa(dims, len) = - throw(DimensionMismatch("new dimensions $(dims) must be consistent with array size $len")) + throw(DimensionMismatch("new dimensions $(dims) must be consistent with array length $len")) len = Core.checked_dims(dims...) # make sure prod(dims) doesn't overflow (and because of the comparison to length(a)) if len != length(a) throw_dmrsa(dims, length(a)) From 89d59a91790b8fe6155c8cca16ac801e0bd4c863 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 28 Mar 2024 13:59:05 -0400 Subject: [PATCH 050/123] optimize: Delete incoming unreachable edges from PhiNode (#53877) Incoming IR very rarely contains PhiNodes, but we do allow it to make things easier on downstream packages like Diffractor that want to generate the same code structures in both typed and untyped mode. However, this does of course mean that once inference is finished, any PhiNodes in the original source must be adjusted to maintain IRCode invariants. One particular important invariant here is that the edges list in a PhiNode must match the predecessor list, so in particular if a predecessor becomes unreachable during inference, we must filter that edge before passing it on to the optimizer. --------- Co-authored-by: Shuhei Kadowaki --- base/compiler/optimize.jl | 14 +++++++ test/compiler/ssair.jl | 82 ++++++++++++++++++++++++++++++++++----- 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 325ba3eca01704..fbdd726a81e9a5 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -1104,6 +1104,20 @@ function convert_to_ircode(ci::CodeInfo, sv::OptimizationState) code[i] = nothing end end + elseif isa(expr, PhiNode) + new_edges = Int32[] + new_vals = Any[] + for j = 1:length(expr.edges) + edge = expr.edges[j] + (edge in sv.unreachable || (ssavaluetypes[edge] === Union{} && !isa(code[edge], PhiNode))) && continue + push!(new_edges, edge) + if isassigned(expr.values, j) + push!(new_vals, expr.values[j]) + else + resize!(new_vals, length(new_edges)) + end + end + code[i] = PhiNode(new_edges, new_vals) end end end diff --git a/test/compiler/ssair.jl b/test/compiler/ssair.jl index 9082d1640e3be5..9d5f7b617080d2 100644 --- a/test/compiler/ssair.jl +++ b/test/compiler/ssair.jl @@ -9,16 +9,6 @@ include("irutils.jl") make_bb(preds, succs) = BasicBlock(Compiler.StmtRange(0, 0), preds, succs) -function make_ci(code) - ci = (Meta.@lower 1 + 1).args[1] - ci.code = code - nstmts = length(ci.code) - ci.ssavaluetypes = nstmts - ci.codelocs = fill(Int32(1), nstmts) - ci.ssaflags = fill(Int32(0), nstmts) - return ci -end - # TODO: this test is broken #let code = Any[ # GotoIfNot(SlotNumber(2), 4), @@ -763,3 +753,75 @@ end end end end + +# Test that things don't break if one branch of the frontend PhiNode becomes unreachable +const global_error_switch_const1::Bool = false +function gen_unreachable_phinode_edge1(world::UInt, source, args...) + ci = make_codeinfo(Any[ + # block 1 + GlobalRef(@__MODULE__, :global_error_switch_const1), + GotoIfNot(SSAValue(1), 4), + # block 2 + Expr(:call, identity, Argument(3)), + # block 3 + PhiNode(Int32[2, 3], Any[Argument(2), SSAValue(3)]), + ReturnNode(SSAValue(4)) + ]; slottypes=Any[Any,Int,Int]) + ci.slotnames = Symbol[:var"#self#", :x, :y] + return ci +end +@eval function f_unreachable_phinode_edge1(x, y) + $(Expr(:meta, :generated, gen_unreachable_phinode_edge1)) + $(Expr(:meta, :generated_only)) + #= no body =# +end +@test f_unreachable_phinode_edge1(1, 2) == 1 + +const global_error_switch_const2::Bool = true +function gen_unreachable_phinode_edge2(world::UInt, source, args...) + ci = make_codeinfo(Any[ + # block 1 + GlobalRef(@__MODULE__, :global_error_switch_const2), + GotoIfNot(SSAValue(1), 4), + # block 2 + Expr(:call, identity, Argument(3)), + # block 3 + PhiNode(Int32[2, 3], Any[Argument(2), SSAValue(3)]), + ReturnNode(SSAValue(4)) + ]; slottypes=Any[Any,Int,Int]) + ci.slotnames = Symbol[:var"#self#", :x, :y] + return ci +end +@eval function f_unreachable_phinode_edge2(x, y) + $(Expr(:meta, :generated, gen_unreachable_phinode_edge2)) + $(Expr(:meta, :generated_only)) + #= no body =# +end +@test f_unreachable_phinode_edge2(1, 2) == 2 + +global global_error_switch::Bool = true +function gen_must_throw_phinode_edge(world::UInt, source, _) + ci = make_codeinfo(Any[ + # block 1 + GlobalRef(@__MODULE__, :global_error_switch), + GotoIfNot(SSAValue(1), 4), + # block 2 + Expr(:call, error, "This error is expected"), + # block 3 + PhiNode(Int32[2, 3], Any[1, 2]), + ReturnNode(SSAValue(4)) + ]; slottypes=Any[Any]) + ci.slotnames = Symbol[:var"#self#"] + return ci +end +@eval function f_must_throw_phinode_edge() + $(Expr(:meta, :generated, gen_must_throw_phinode_edge)) + $(Expr(:meta, :generated_only)) + #= no body =# +end +let ir = first(only(Base.code_ircode(f_must_throw_phinode_edge))) + @test !any(@nospecialize(x)->isa(x,PhiNode), ir.stmts.stmt) +end +@test_throws ErrorException f_must_throw_phinode_edge() +global global_error_switch = false +@test f_must_throw_phinode_edge() == 1 From 3530c8f1774e41c51b88bed4d4a77f7ea7f871c0 Mon Sep 17 00:00:00 2001 From: Gabriele Bozzola Date: Thu, 28 Mar 2024 11:35:45 -0700 Subject: [PATCH 051/123] Consistently format Julia in the docstring for Base.DEPOT_PATH (#53873) It is unclear what `Julia` exactly means in this docstring, but the two occurences of the word have different formatting. The guidelines say > in docstrings refer to the language as "Julia" and the executable as "`julia`". Given that we are not talking about the executable here, I removed the backticks. --- base/initdefs.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/initdefs.jl b/base/initdefs.jl index 2b2916fc804ade..182984ae01d561 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -75,11 +75,11 @@ Here is an overview of some of the subdirectories that may exist in a depot: * `artifacts`: Contains content that packages use for which Pkg manages the installation of. * `clones`: Contains full clones of package repos. Maintained by `Pkg.jl` and used as a cache. -* `config`: Contains julia-level configuration such as a `startup.jl` +* `config`: Contains julia-level configuration such as a `startup.jl`. * `compiled`: Contains precompiled `*.ji` files for packages. Maintained by Julia. * `dev`: Default directory for `Pkg.develop`. Maintained by `Pkg.jl` and the user. * `environments`: Default package environments. For instance the global environment for a specific julia version. Maintained by `Pkg.jl`. -* `logs`: Contains logs of `Pkg` and `REPL` operations. Maintained by `Pkg.jl` and `Julia`. +* `logs`: Contains logs of `Pkg` and `REPL` operations. Maintained by `Pkg.jl` and Julia. * `packages`: Contains packages, some of which were explicitly installed and some which are implicit dependencies. Maintained by `Pkg.jl`. * `registries`: Contains package registries. By default only `General`. Maintained by `Pkg.jl`. * `scratchspaces`: Contains content that a package itself installs via the [`Scratch.jl`](https://github.com/JuliaPackaging/Scratch.jl) package. `Pkg.gc()` will delete content that is known to be unused. From 1e50a99fd6cdce69ed819b587709151df9d227a2 Mon Sep 17 00:00:00 2001 From: Gabriel Baraldi Date: Thu, 28 Mar 2024 15:27:52 -0400 Subject: [PATCH 052/123] Utilize bitshifts correctly in signals-mach.c when storing/reading the previous GC state (#53868) I have not succeed in writing a test for this, but this was found on a CI hang together with @keno and @vtjnash. In essence if we hit a safepoint while GC_SAFE things can go wrong image --- src/signals-mach.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/signals-mach.c b/src/signals-mach.c index 56f7c0d7505f48..2191dc32687210 100644 --- a/src/signals-mach.c +++ b/src/signals-mach.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "mach_excServer.c" #ifdef MAC_OS_X_VERSION_10_9 @@ -47,14 +48,31 @@ static arraylist_t suspended_threads; extern uv_mutex_t safepoint_lock; extern uv_cond_t safepoint_cond_begin; +#define GC_STATE_SHIFT 8*sizeof(int16_t) +static inline int8_t decode_gc_state(uintptr_t item) +{ + return (int8_t)(item >> GC_STATE_SHIFT); +} + +static inline int16_t decode_tid(uintptr_t item) +{ + return (int16_t)item; +} + +static inline uintptr_t encode_item(int16_t tid, int8_t gc_state) +{ + return (uintptr_t)tid | ((uintptr_t)gc_state << GC_STATE_SHIFT); +} + // see jl_safepoint_wait_thread_resume void jl_safepoint_resume_thread_mach(jl_ptls_t ptls2, int16_t tid2) { // must be called with uv_mutex_lock(&safepoint_lock) and uv_mutex_lock(&ptls2->sleep_lock) held (in that order) for (size_t i = 0; i < suspended_threads.len; i++) { uintptr_t item = (uintptr_t)suspended_threads.items[i]; - int16_t tid = (int16_t)item; - int8_t gc_state = (int8_t)(item >> 8); + + int16_t tid = decode_tid(item); + int8_t gc_state = decode_gc_state(item); if (tid != tid2) continue; jl_atomic_store_release(&ptls2->gc_state, gc_state); @@ -71,8 +89,8 @@ void jl_mach_gc_end(void) size_t j = 0; for (size_t i = 0; i < suspended_threads.len; i++) { uintptr_t item = (uintptr_t)suspended_threads.items[i]; - int16_t tid = (int16_t)item; - int8_t gc_state = (int8_t)(item >> 8); + int16_t tid = decode_tid(item); + int8_t gc_state = decode_gc_state(item); jl_ptls_t ptls2 = jl_atomic_load_relaxed(&jl_all_tls_states)[tid]; uv_mutex_lock(&ptls2->sleep_lock); if (jl_atomic_load_relaxed(&ptls2->suspend_count) == 0) { @@ -117,7 +135,7 @@ static void jl_mach_gc_wait(jl_ptls_t ptls2, mach_port_t thread, int16_t tid) // triggers a SIGSEGV and gets handled by the usual codepath for unix. int8_t gc_state = jl_atomic_load_acquire(&ptls2->gc_state); jl_atomic_store_release(&ptls2->gc_state, JL_GC_STATE_WAITING); - uintptr_t item = tid | (((uintptr_t)gc_state) << 16); + uintptr_t item = encode_item(tid, gc_state); arraylist_push(&suspended_threads, (void*)item); thread_suspend(thread); } From b18d2cc7046bee7b4a03842d709236ac1c081305 Mon Sep 17 00:00:00 2001 From: Matt Bauman Date: Thu, 28 Mar 2024 16:41:19 -0400 Subject: [PATCH 053/123] use flisp cprimitives for lowering large longs (#53860) This addresses the previous limitation to `Base.literal_pow`, where it would only apply to literals between $\pm2\^{61}$ (or 29). --- src/ast.c | 16 ++++++++++++++-- src/flisp/cvalues.c | 2 +- src/flisp/flisp.h | 1 + test/numbers.jl | 14 ++++++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/ast.c b/src/ast.c index d39ee35e807ae9..0971f4ab16e64b 100644 --- a/src/ast.c +++ b/src/ast.c @@ -717,8 +717,20 @@ static int julia_to_scm_noalloc1(fl_context_t *fl_ctx, jl_value_t *v, value_t *r static value_t julia_to_scm_noalloc2(fl_context_t *fl_ctx, jl_value_t *v, int check_valid) JL_NOTSAFEPOINT { - if (jl_is_long(v) && fits_fixnum(jl_unbox_long(v))) - return fixnum(jl_unbox_long(v)); + if (jl_is_long(v)) { + if (fits_fixnum(jl_unbox_long(v))) { + return fixnum(jl_unbox_long(v)); + } else { +#ifdef _P64 + value_t prim = cprim(fl_ctx, fl_ctx->int64type, sizeof(int64_t)); + *((int64_t*)cp_data((cprim_t*)ptr(prim))) = jl_unbox_long(v); +#else + value_t prim = cprim(fl_ctx, fl_ctx->int32type, sizeof(int32_t)); + *((int32_t*)cp_data((cprim_t*)ptr(prim))) = jl_unbox_long(v); +#endif + return prim; + } + } if (check_valid) { if (jl_is_ssavalue(v)) lerror(fl_ctx, symbol(fl_ctx, "error"), "SSAValue objects should not occur in an AST"); diff --git a/src/flisp/cvalues.c b/src/flisp/cvalues.c index a5635c238ba3c3..749b8802dfe82c 100644 --- a/src/flisp/cvalues.c +++ b/src/flisp/cvalues.c @@ -101,7 +101,7 @@ void cv_autorelease(fl_context_t *fl_ctx, cvalue_t *cv) autorelease(fl_ctx, cv); } -static value_t cprim(fl_context_t *fl_ctx, fltype_t *type, size_t sz) +value_t cprim(fl_context_t *fl_ctx, fltype_t *type, size_t sz) { cprim_t *pcp = (cprim_t*)alloc_words(fl_ctx, CPRIM_NWORDS-1+NWORDS(sz)); pcp->type = type; diff --git a/src/flisp/flisp.h b/src/flisp/flisp.h index b031e456cd3fe3..669753a9f5302c 100644 --- a/src/flisp/flisp.h +++ b/src/flisp/flisp.h @@ -328,6 +328,7 @@ typedef float fl_float_t; typedef value_t (*builtin_t)(fl_context_t*, value_t*, uint32_t); value_t cvalue(fl_context_t *fl_ctx, fltype_t *type, size_t sz) JL_NOTSAFEPOINT; +value_t cprim(fl_context_t *fl_ctx, fltype_t *type, size_t sz) JL_NOTSAFEPOINT; value_t cvalue_no_finalizer(fl_context_t *fl_ctx, fltype_t *type, size_t sz) JL_NOTSAFEPOINT; void add_finalizer(fl_context_t *fl_ctx, cvalue_t *cv); void cv_autorelease(fl_context_t *fl_ctx, cvalue_t *cv); diff --git a/test/numbers.jl b/test/numbers.jl index 47d7e87753b112..4f5893da0d091d 100644 --- a/test/numbers.jl +++ b/test/numbers.jl @@ -2776,6 +2776,20 @@ Base.literal_pow(::typeof(^), ::PR20530, ::Val{p}) where {p} = 2 @test [2,4,8].^-2 == [0.25, 0.0625, 0.015625] @test [2, 4, 8].^-2 .* 4 == [1.0, 0.25, 0.0625] # nested literal_pow @test โ„ฏ^-2 == exp(-2) โ‰ˆ inv(โ„ฏ^2) โ‰ˆ (โ„ฏ^-1)^2 โ‰ˆ sqrt(โ„ฏ^-4) + + if Int === Int32 + p = 2147483647 + @test x^p == 1 + @test x^2147483647 == 2 + @test (@fastmath x^p) == 1 + @test (@fastmath x^2147483647) == 2 + elseif Int === Int64 + p = 9223372036854775807 + @test x^p == 1 + @test x^9223372036854775807 == 2 + @test (@fastmath x^p) == 1 + @test (@fastmath x^9223372036854775807) == 2 + end end module M20889 # do we get the expected behavior without importing Base.^? using Test From a3438d0af710f1876a2a0eecc11782ab8fa20eab Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Fri, 29 Mar 2024 17:49:09 +0900 Subject: [PATCH 054/123] fix `NoMethodError` of `changed_lineinfo` (#53890) I will add a test case for this later. xref: https://github.com/JuliaDiff/Diffractor.jl/actions/runs/8476871477/job/23226991456 --- base/compiler/optimize.jl | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index fbdd726a81e9a5..d8b307a1b7a7c4 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -1035,20 +1035,22 @@ end function changed_lineinfo(di::DebugInfo, codeloc::Int, prevloc::Int) while true next = getdebugidx(di, codeloc) - next[1] < 0 && return false # invalid info - next[1] == 0 && next[2] == 0 && return false # no new info + line = next[1] + line < 0 && return false # invalid info + line == 0 && next[2] == 0 && return false # no new info prevloc <= 0 && return true # no old info prev = getdebugidx(di, prevloc) next === prev && return false # exactly identical - prev[1] < 0 && return true # previous invalid info, now valid + prevline = prev[1] + prevline < 0 && return true # previous invalid info, now valid edge = next[2] edge === prev[2] || return true # change to this edge linetable = di.linetable # check for change to line number here - if linetable === nothing || next[1] == 0 - next[1] == prev[1] || return true + if linetable === nothing || line == 0 + line == prevline || return true else - changed_lineinfo(linetable, next[1], prev[1]) && return true + changed_lineinfo(linetable::DebugInfo, Int(line), Int(prevline)) && return true end # check for change to edge here edge == 0 && return false # no edge here From 11517f2df30cc55644dacdb054ffd981e3a76102 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Fri, 29 Mar 2024 19:42:09 +0900 Subject: [PATCH 055/123] fix typos in codegen.cpp (#53888) Not sure why this typo didn't mess up the CI, but it looks like a clear problem, let's correct it. I'd appreciate any idea on how to exercise this change. - fixes JuliaDebug/JuliaInterpreter.jl#621 --- src/codegen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index f1b0c570acc336..46e51785899a91 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1617,9 +1617,9 @@ static const auto &builtin_func_map() { { jl_f_memoryref_addr, new JuliaFunction<>{XSTR(jl_f_memoryref), get_func_sig, get_func_attrs} }, { jl_f_memoryrefoffset_addr, new JuliaFunction<>{XSTR(jl_f_memoryrefoffset), get_func_sig, get_func_attrs} }, { jl_f_memoryrefset_addr, new JuliaFunction<>{XSTR(jl_f_memoryrefset), get_func_sig, get_func_attrs} }, - { jl_f_memoryrefswap_addr, new JuliaFunction<>{XSTR(jl_f_memoryswapset), get_func_sig, get_func_attrs} }, - { jl_f_memoryrefreplace_addr, new JuliaFunction<>{XSTR(jl_f_memoryreplaceset), get_func_sig, get_func_attrs} }, - { jl_f_memoryrefmodify_addr, new JuliaFunction<>{XSTR(jl_f_memorymodifyset), get_func_sig, get_func_attrs} }, + { jl_f_memoryrefswap_addr, new JuliaFunction<>{XSTR(jl_f_memoryrefswap), get_func_sig, get_func_attrs} }, + { jl_f_memoryrefreplace_addr, new JuliaFunction<>{XSTR(jl_f_memoryrefreplace), get_func_sig, get_func_attrs} }, + { jl_f_memoryrefmodify_addr, new JuliaFunction<>{XSTR(jl_f_memoryrefmodify), get_func_sig, get_func_attrs} }, { jl_f_memoryrefsetonce_addr, new JuliaFunction<>{XSTR(jl_f_memoryrefsetonce), get_func_sig, get_func_attrs} }, { jl_f_memoryref_isassigned_addr,new JuliaFunction<>{XSTR(jl_f_memoryref_isassigned), get_func_sig, get_func_attrs} }, { jl_f_apply_type_addr, new JuliaFunction<>{XSTR(jl_f_apply_type), get_func_sig, get_func_attrs} }, From b2e8eb2253c4641c058f61f3bd5cb3447484b7ed Mon Sep 17 00:00:00 2001 From: Zentrik Date: Fri, 29 Mar 2024 12:28:12 +0000 Subject: [PATCH 056/123] Revert change to checksum for llvm-julia (#53870) Should fix #53399. I think this is the correct fix. Makes it so you can build Julia with `USE_BINARYBUILDER=0`. --- deps/checksums/llvm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deps/checksums/llvm b/deps/checksums/llvm index 7effa4955a5f3e..f54ddc7379b6e1 100644 --- a/deps/checksums/llvm +++ b/deps/checksums/llvm @@ -246,7 +246,7 @@ libLLVM.v16.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+16.asserts.tar.gz/md5/f6 libLLVM.v16.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+16.asserts.tar.gz/sha512/45930e3ae3bf3922c8b3096474cbe22035432e80d2b0f4ccbd424c69e874a76acf4a724e055a5ef73ce40ae00ee6ede60b210b8847c30239a6ec242550a3e464 libLLVM.v16.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+16.tar.gz/md5/344f2a9d2b85a6c527fd6fa024d6763e libLLVM.v16.0.6+4.x86_64-w64-mingw32-cxx11-llvm_version+16.tar.gz/sha512/73909c58087568d8654d48ed5fc952289d8b3a4e26e956e9220cf254b8fb2c4b6630ebc9258502a6c3b67ed3cfe0cbe3a92ee3d346b228d842af03f0a42794c7 -llvm-julia-16.0.6-2.tar.gz/md5/71ca2225b042ec5ae666c99fa1bd19b1 -llvm-julia-16.0.6-2.tar.gz/sha512/6f2513adea1b939229c9be171e7ce41e488b3cfaa2e615912c4bc1ddaf0ab2e75df213a5d5db80105d6473a8017b0656016bbbb085ef00a38073519668885884 +llvm-julia-16.0.6-2.tar.gz/md5/f05607b71ac8d1e7c30430d2a9efa0a6 +llvm-julia-16.0.6-2.tar.gz/sha512/5f2f88b4673b13780fa819c78cb27fc5dab77c2976768ae4f7863b904c911e39fc18ee85d212e512a7c60081c74efd1fa2e7142b78002982533b7326ff808f24 llvmunwind-12.0.1.tar.xz/md5/4ec327cee517fdb1f6a20e83748e2c7b llvmunwind-12.0.1.tar.xz/sha512/847b6ba03010a43f4fdbfdc49bf16d18fd18474d01584712e651b11191814bf7c1cf53475021d9ee447ed78413202b4ed97973d7bdd851d3e49f8d06f55a7af4 From 09b356f0eaf2e0570167b86fb674777cf435cb7e Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Fri, 29 Mar 2024 09:27:51 -0400 Subject: [PATCH 057/123] fix relocatable upgrades test (#53889) Fixes https://github.com/JuliaLang/julia/issues/53885 Not the first time MacOS serving tempdir via a symlink has caused obscure issues.. --- test/loading.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/loading.jl b/test/loading.jl index 872ccd197f0f88..94f27ecf888bb2 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -1337,7 +1337,10 @@ end @testset "relocatable upgrades #51989" begin mktempdir() do depot - project_path = joinpath(depot, "project") + # realpath is needed because Pkg is used for one of the precompile paths below, and Pkg calls realpath on the + # project path so the cache file slug will be different if the tempdir is given as a symlink + # (which it often is on MacOS) which would break the test. + project_path = joinpath(realpath(depot), "project") mkpath(project_path) # Create fake `Foo.jl` package with two files: From e26d14084cb11d1bf0f05096ef0887059ba0b52f Mon Sep 17 00:00:00 2001 From: Sebastien Marie Date: Fri, 29 Mar 2024 17:47:07 +0100 Subject: [PATCH 058/123] add initial support for OpenBSD (#53633) These commits add initial support of OpenBSD in julia. It isn't strictly enough to make julia runable on OpenBSD (see #53632), but it covers the larger part. --------- Co-authored-by: Max Horn Co-authored-by: Oscar Smith --- Make.inc | 19 +++++++++++++--- base/binaryplatforms.jl | 18 +++++++++++---- base/sysinfo.jl | 2 +- cli/Makefile | 4 +++- cli/loader_lib.c | 2 +- contrib/normalize_triplet.py | 2 ++ deps/Makefile | 4 +++- deps/libgit2.mk | 6 ++++- deps/libssh2.mk | 6 ++++- deps/libsuitesparse.mk | 6 ++--- deps/mbedtls.mk | 2 +- deps/patchelf.mk | 2 +- deps/pcre.mk | 3 +++ src/Makefile | 2 ++ src/aotcompile.cpp | 2 +- src/cgmemmgr.cpp | 3 +++ src/codegen.cpp | 2 +- src/gc-stacks.c | 11 +++++++++ src/jitlayers.cpp | 22 +++++++++++++++++- src/julia.expmap.in | 2 +- src/julia_threads.h | 10 ++++++++ src/signals-unix.c | 39 ++++++++++++++++++++++++++++++-- src/support/dtypes.h | 2 +- src/support/platform.h | 3 +++ src/support/strtod.c | 2 +- src/support/utf8.c | 4 ++-- src/sys.c | 44 ++++++++++++++++++++++++++++++++++-- 27 files changed, 194 insertions(+), 30 deletions(-) diff --git a/Make.inc b/Make.inc index 2a23bd3d37b51d..56558e17bb2f43 100644 --- a/Make.inc +++ b/Make.inc @@ -670,7 +670,7 @@ JL_MAJOR_SHLIB_EXT := $(SHLIB_EXT).$(SOMAJOR) endif endif -ifeq ($(OS), FreeBSD) +ifneq ($(findstring $(OS),FreeBSD OpenBSD),) LOCALBASE ?= /usr/local else LOCALBASE ?= /usr @@ -726,7 +726,7 @@ SANITIZE_LDFLAGS := ifeq ($(SANITIZE_MEMORY),1) SANITIZE_OPTS += -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer SANITIZE_LDFLAGS += $(SANITIZE_OPTS) -ifneq ($(findstring $(OS),Linux FreeBSD),) +ifneq ($(findstring $(OS),Linux FreeBSD OpenBSD),) SANITIZE_LDFLAGS += -Wl,--warn-unresolved-symbols endif # OS Linux or FreeBSD endif # SANITIZE_MEMORY=1 @@ -1069,7 +1069,7 @@ JCFLAGS+=-DSYSTEM_LIBUNWIND JCPPFLAGS+=-DSYSTEM_LIBUNWIND endif else -ifeq ($(OS),Darwin) +ifneq ($(findstring $(OS),Darwin OpenBSD),) LIBUNWIND:=-lunwind JCPPFLAGS+=-DLLVMLIBUNWIND else @@ -1380,6 +1380,19 @@ OSLIBS += -Wl,--export-dynamic -Wl,--version-script=$(BUILDROOT)/src/julia.expma $(NO_WHOLE_ARCHIVE) endif +ifeq ($(OS), OpenBSD) +JLDFLAGS += -Wl,--Bdynamic +ifneq ($(SANITIZE),1) +JLDFLAGS += -Wl,-no-undefined +endif + +JLIBLDFLAGS += -Wl,-Bsymbolic-functions + +OSLIBS += -Wl,--no-as-needed -lpthread -lm -lc++abi -lc +OSLIBS += -Wl,--whole-archive -lcompiler_rt -Wl,--no-whole-archive +OSLIBS += -Wl,--export-dynamic,--as-needed,--version-script=$(BUILDROOT)/src/julia.expmap +endif + ifeq ($(OS), Darwin) SHLIB_EXT := dylib OSLIBS += -framework CoreFoundation diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index 9e45275f026366..8c6fa2a5f4a034 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -198,7 +198,7 @@ function validate_tags(tags::Dict) throw_invalid_key("arch") end # Validate `os` - if tags["os"] โˆ‰ ("linux", "macos", "freebsd", "windows") + if tags["os"] โˆ‰ ("linux", "macos", "freebsd", "openbsd", "windows") throw_invalid_key("os") end # Validate `os`/`arch` combination @@ -375,8 +375,10 @@ function os() return "windows" elseif Sys.isapple() return "macos" - elseif Sys.isbsd() + elseif Sys.isfreebsd() return "freebsd" + elseif Sys.isopenbsd() + return "openbsd" else return "linux" end @@ -422,6 +424,7 @@ const platform_names = Dict( "macos" => "macOS", "windows" => "Windows", "freebsd" => "FreeBSD", + "openbsd" => "OpenBSD", nothing => "Unknown", ) @@ -556,6 +559,8 @@ function os_str(p::AbstractPlatform) else return "-unknown-freebsd" end + elseif os(p) == "openbsd" + return "-unknown-openbsd" else return "-unknown" end @@ -581,7 +586,8 @@ Sys.isapple(p::AbstractPlatform) = os(p) == "macos" Sys.islinux(p::AbstractPlatform) = os(p) == "linux" Sys.iswindows(p::AbstractPlatform) = os(p) == "windows" Sys.isfreebsd(p::AbstractPlatform) = os(p) == "freebsd" -Sys.isbsd(p::AbstractPlatform) = os(p) โˆˆ ("freebsd", "macos") +Sys.isopenbsd(p::AbstractPlatform) = os(p) == "openbsd" +Sys.isbsd(p::AbstractPlatform) = os(p) โˆˆ ("freebsd", "openbsd", "macos") Sys.isunix(p::AbstractPlatform) = Sys.isbsd(p) || Sys.islinux(p) const arch_mapping = Dict( @@ -632,6 +638,7 @@ end const os_mapping = Dict( "macos" => "-apple-darwin[\\d\\.]*", "freebsd" => "-(.*-)?freebsd[\\d\\.]*", + "openbsd" => "-(.*-)?openbsd[\\d\\.]*", "windows" => "-w64-mingw32", "linux" => "-(.*-)?linux", ) @@ -745,6 +752,9 @@ function Base.parse(::Type{Platform}, triplet::String; validate_strict::Bool = f if os == "freebsd" os_version = extract_os_version("freebsd", r".*freebsd([\d.]+)"sa) end + if os == "openbsd" + os_version = extract_os_version("openbsd", r".*openbsd([\d.]+)"sa) + end tags["os_version"] = os_version return Platform(arch, os, tags; validate_strict) @@ -802,7 +812,7 @@ function parse_dl_name_version(path::String, os::String) # On OSX, libraries look like `libnettle.6.3.dylib` dlregex = r"^(.*?)((?:\.[\d]+)*)\.dylib$"sa else - # On Linux and FreeBSD, libraries look like `libnettle.so.6.3.0` + # On Linux and others BSD, libraries look like `libnettle.so.6.3.0` dlregex = r"^(.*?)\.so((?:\.[\d]+)*)$"sa end diff --git a/base/sysinfo.jl b/base/sysinfo.jl index 9bdff3673477fd..484ac4d01d104d 100644 --- a/base/sysinfo.jl +++ b/base/sysinfo.jl @@ -399,7 +399,7 @@ end Get the maximum resident set size utilized in bytes. See also: - - man page of `getrusage`(2) on Linux and FreeBSD. + - man page of `getrusage`(2) on Linux and BSD. - Windows API `GetProcessMemoryInfo`. """ maxrss() = ccall(:jl_maxrss, Csize_t, ()) diff --git a/cli/Makefile b/cli/Makefile index 4e32c53b9a6f0e..017f713446e1a9 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -24,6 +24,8 @@ else ifeq ($(OS),Linux) LOADER_LDFLAGS += -Wl,--no-as-needed -ldl -lpthread -rdynamic -lc -Wl,--as-needed -Wl,-z,notext else ifeq ($(OS),FreeBSD) LOADER_LDFLAGS += -Wl,--no-as-needed -ldl -lpthread -rdynamic -lc -Wl,--as-needed +else ifeq ($(OS),OpenBSD) +LOADER_LDFLAGS += -Wl,--no-as-needed -lpthread -rdynamic -lc -Wl,--as-needed else ifeq ($(OS),Darwin) LOADER_LDFLAGS += -lSystem endif @@ -107,7 +109,7 @@ julia-debug: $(build_bindir)/julia-debug$(EXE) libjulia-release: $(build_shlibdir)/libjulia.$(SHLIB_EXT) libjulia-debug: $(build_shlibdir)/libjulia-debug.$(SHLIB_EXT) -ifneq (,$(filter $(OS), Linux FreeBSD)) +ifneq (,$(filter $(OS), Linux FreeBSD OpenBSD)) VERSIONSCRIPT := -Wl,--version-script=$(BUILDDIR)/julia.expmap endif diff --git a/cli/loader_lib.c b/cli/loader_lib.c index 02030cf2717a54..d09d21e10abd1a 100644 --- a/cli/loader_lib.c +++ b/cli/loader_lib.c @@ -520,7 +520,7 @@ __attribute__((constructor)) void jl_load_libjulia_internal(void) { (*jl_codegen_exported_func_addrs[symbol_idx]) = addr; } // Next, if we're on Linux/FreeBSD, set up fast TLS. -#if !defined(_OS_WINDOWS_) && !defined(_OS_DARWIN_) +#if !defined(_OS_WINDOWS_) && !defined(_OS_DARWIN_) && !defined(_OS_OPENBSD_) void (*jl_pgcstack_setkey)(void*, void*(*)(void)) = lookup_symbol(libjulia_internal, "jl_pgcstack_setkey"); if (jl_pgcstack_setkey == NULL) { jl_loader_print_stderr("ERROR: Cannot find jl_pgcstack_setkey() function within libjulia-internal!\n"); diff --git a/contrib/normalize_triplet.py b/contrib/normalize_triplet.py index 77c047b360b76a..b1bab29487b8fc 100755 --- a/contrib/normalize_triplet.py +++ b/contrib/normalize_triplet.py @@ -19,6 +19,7 @@ platform_mapping = { 'darwin': "-apple-darwin[\\d\\.]*", 'freebsd': "-(.*-)?freebsd[\\d\\.]*", + 'openbsd': "-(.*-)?openbsd[\\d\\.]*", 'windows': "-w64-mingw32", 'linux': "-(.*-)?linux", } @@ -96,6 +97,7 @@ def p(x): 'darwin': 'apple-darwin', 'windows': 'w64-mingw32', 'freebsd': 'unknown-freebsd', + 'openbsd': 'unknown-openbsd', } x = r(x) if x: diff --git a/deps/Makefile b/deps/Makefile index 27f5fdbb693d52..fd8f5267e9d7e5 100644 --- a/deps/Makefile +++ b/deps/Makefile @@ -64,13 +64,15 @@ ifeq ($(OS), Linux) DEP_LIBS += unwind else ifeq ($(OS), FreeBSD) DEP_LIBS += unwind +else ifeq ($(OS), OpenBSD) +DEP_LIBS += llvmunwind else ifeq ($(OS), Darwin) DEP_LIBS += llvmunwind endif endif endif -ifneq (,$(findstring $(OS),Linux FreeBSD)) +ifneq (,$(findstring $(OS),Linux FreeBSD OpenBSD)) ifeq ($(USE_SYSTEM_PATCHELF), 0) DEP_LIBS += patchelf PATCHELF:=$(build_depsbindir)/patchelf diff --git a/deps/libgit2.mk b/deps/libgit2.mk index d68a7a80d6d5b0..b65ac022885a39 100644 --- a/deps/libgit2.mk +++ b/deps/libgit2.mk @@ -33,8 +33,12 @@ LIBGIT2_OPTS += -DBUILD_TESTS=OFF -DDLLTOOL=`which $(CROSS_COMPILE)dlltool` LIBGIT2_OPTS += -DCMAKE_FIND_ROOT_PATH=/usr/$(XC_HOST) -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY endif endif +ifeq ($(OS),OpenBSD) +# iconv.h is third-party +LIBGIT2_OPTS += -DCMAKE_C_FLAGS="-I/usr/local/include" +endif -ifneq (,$(findstring $(OS),Linux FreeBSD)) +ifneq (,$(findstring $(OS),Linux FreeBSD OpenBSD)) LIBGIT2_OPTS += -DUSE_HTTPS="mbedTLS" -DUSE_SHA1="CollisionDetection" -DCMAKE_INSTALL_RPATH="\$$ORIGIN" endif diff --git a/deps/libssh2.mk b/deps/libssh2.mk index 3f9738515e4a12..c293d8309d2bc1 100644 --- a/deps/libssh2.mk +++ b/deps/libssh2.mk @@ -11,6 +11,10 @@ endif LIBSSH2_OPTS := $(CMAKE_COMMON) -DBUILD_SHARED_LIBS=ON -DBUILD_EXAMPLES=OFF \ -DCMAKE_BUILD_TYPE=Release +ifneq ($(fPIC),) +LIBSSH2_OPTS += -DCMAKE_C_FLAGS="-fPIC" +endif + ifeq ($(OS),WINNT) LIBSSH2_OPTS += -DCRYPTO_BACKEND=WinCNG -DENABLE_ZLIB_COMPRESSION=OFF ifeq ($(BUILD_OS),WINNT) @@ -20,7 +24,7 @@ else LIBSSH2_OPTS += -DCRYPTO_BACKEND=mbedTLS -DENABLE_ZLIB_COMPRESSION=OFF endif -ifneq (,$(findstring $(OS),Linux FreeBSD)) +ifneq (,$(findstring $(OS),Linux FreeBSD OpenBSD)) LIBSSH2_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" endif diff --git a/deps/libsuitesparse.mk b/deps/libsuitesparse.mk index 7e36bce8f4f9d4..0207c5ef7c099a 100644 --- a/deps/libsuitesparse.mk +++ b/deps/libsuitesparse.mk @@ -36,7 +36,7 @@ else LIBSUITESPARSE_CMAKE_FLAGS += -DSUITESPARSE_USE_64BIT_BLAS=NO endif -ifneq (,$(findstring $(OS),Linux FreeBSD)) +ifneq (,$(findstring $(OS),Linux FreeBSD OpenBSD)) LIBSUITESPARSE_CMAKE_FLAGS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" endif @@ -59,8 +59,8 @@ $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: | $(build_prefix)/ $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/build-compiled: $(BUILDDIR)/SuiteSparse-$(LIBSUITESPARSE_VER)/source-patched cd $(dir $<) && $(CMAKE) . $(LIBSUITESPARSE_CMAKE_FLAGS) - make -C $(dir $<) - make -C $(dir $<) install + $(MAKE) -C $(dir $<) + $(MAKE) -C $(dir $<) install echo 1 > $@ ifeq ($(OS),WINNT) diff --git a/deps/mbedtls.mk b/deps/mbedtls.mk index b4147c2c2684e1..39cf817d706589 100644 --- a/deps/mbedtls.mk +++ b/deps/mbedtls.mk @@ -13,7 +13,7 @@ ifeq ($(BUILD_OS),WINNT) MBEDTLS_OPTS += -G"MSYS Makefiles" endif -ifneq (,$(findstring $(OS),Linux FreeBSD)) +ifneq (,$(findstring $(OS),Linux FreeBSD OpenBSD)) MBEDTLS_OPTS += -DCMAKE_INSTALL_RPATH="\$$ORIGIN" endif diff --git a/deps/patchelf.mk b/deps/patchelf.mk index 9b4947f183117a..c019892058d0eb 100644 --- a/deps/patchelf.mk +++ b/deps/patchelf.mk @@ -20,7 +20,7 @@ $(BUILDDIR)/patchelf-$(PATCHELF_VER)/build-configured: XC_HOST:=$(BUILD_MACHINE) $(BUILDDIR)/patchelf-$(PATCHELF_VER)/build-configured: $(SRCCACHE)/patchelf-$(PATCHELF_VER)/source-extracted mkdir -p $(dir $@) cd $(dir $@) && \ - $(dir $<)/configure $(CONFIGURE_COMMON) LDFLAGS="$(CXXLDFLAGS)" CPPFLAGS="$(CPPFLAGS)" + $(dir $<)/configure $(CONFIGURE_COMMON) LDFLAGS="$(CXXLDFLAGS)" CPPFLAGS="$(CPPFLAGS)" MAKE=$(MAKE) echo 1 > $@ $(BUILDDIR)/patchelf-$(PATCHELF_VER)/build-compiled: $(BUILDDIR)/patchelf-$(PATCHELF_VER)/build-configured diff --git a/deps/pcre.mk b/deps/pcre.mk index cd1180d9928858..3ff85d5569ad9d 100644 --- a/deps/pcre.mk +++ b/deps/pcre.mk @@ -9,6 +9,9 @@ PCRE_LDFLAGS := $(RPATH_ESCAPED_ORIGIN) ifeq ($(OS),emscripten) PCRE_CFLAGS += -fPIC PCRE_JIT = --disable-jit +else ifeq ($(OS),OpenBSD) +# jit will need RWX memory +PCRE_JIT = --disable-jit else PCRE_JIT = --enable-jit endif diff --git a/src/Makefile b/src/Makefile index 72895e9a8080c4..323aaea61c47d9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -474,6 +474,8 @@ $(build_shlibdir)/lib%Plugin.$(SHLIB_EXT): $(SRCDIR)/clangsa/%.cpp $(LLVM_CONFIG ANALYSIS_DEPS := llvm clang llvm-tools libuv utf8proc ifeq ($(OS),Darwin) ANALYSIS_DEPS += llvmunwind +else ifeq ($(OS),OpenBSD) +ANALYSIS_DEPS += llvmunwind else ifneq ($(OS),WINNT) ANALYSIS_DEPS += unwind endif diff --git a/src/aotcompile.cpp b/src/aotcompile.cpp index 880d193ea157c4..edef391af6708e 100644 --- a/src/aotcompile.cpp +++ b/src/aotcompile.cpp @@ -1605,7 +1605,7 @@ void jl_dump_native_impl(void *native_code, TheTriple.setOSName(Str); } Optional RelocModel; - if (TheTriple.isOSLinux() || TheTriple.isOSFreeBSD()) { + if (TheTriple.isOSLinux() || TheTriple.isOSFreeBSD() || TheTriple.isOSOpenBSD()) { RelocModel = Reloc::PIC_; } diff --git a/src/cgmemmgr.cpp b/src/cgmemmgr.cpp index b627224e027a97..c78e6092ca5db0 100644 --- a/src/cgmemmgr.cpp +++ b/src/cgmemmgr.cpp @@ -25,6 +25,9 @@ # include # include #endif +#ifdef _OS_OPENBSD_ +# include +#endif #include "julia_assert.h" namespace { diff --git a/src/codegen.cpp b/src/codegen.cpp index 46e51785899a91..5d1dda3e735dc1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -86,7 +86,7 @@ static bool jl_fpo_disabled(const Triple &TT) { // MSAN doesn't support FPO return true; #endif - if (TT.isOSLinux() || TT.isOSWindows() || TT.isOSFreeBSD()) { + if (TT.isOSLinux() || TT.isOSWindows() || TT.isOSFreeBSD() || TT.isOSOpenBSD()) { return true; } return false; diff --git a/src/gc-stacks.c b/src/gc-stacks.c index 2d0fc011802c96..e42b2fddaf8aa3 100644 --- a/src/gc-stacks.c +++ b/src/gc-stacks.c @@ -50,6 +50,16 @@ static void free_stack(void *stkbuf, size_t bufsz) #else +# ifdef _OS_OPENBSD_ +static void *malloc_stack(size_t bufsz) JL_NOTSAFEPOINT +{ + void* stk = mmap(0, bufsz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); + if (stk == MAP_FAILED) + return MAP_FAILED; + jl_atomic_fetch_add(&num_stack_mappings, 1); + return stk; +} +# else static void *malloc_stack(size_t bufsz) JL_NOTSAFEPOINT { void* stk = mmap(0, bufsz, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); @@ -65,6 +75,7 @@ static void *malloc_stack(size_t bufsz) JL_NOTSAFEPOINT jl_atomic_fetch_add_relaxed(&num_stack_mappings, 1); return stk; } +# endif static void free_stack(void *stkbuf, size_t bufsz) { diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index 5f9d7f8a3c6cf4..eee2879ef0ed79 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -113,6 +113,15 @@ static void *getTLSAddress(void *control) } #endif +#ifdef _OS_OPENBSD_ +extern "C" { + __int128 __divti3(__int128, __int128); + __int128 __modti3(__int128, __int128); + unsigned __int128 __udivti3(unsigned __int128, unsigned __int128); + unsigned __int128 __umodti3(unsigned __int128, unsigned __int128); +} +#endif + // Snooping on which functions are being compiled, and how long it takes extern "C" JL_DLLEXPORT_CODEGEN void jl_dump_compiles_impl(void *s) @@ -1732,6 +1741,17 @@ JuliaOJIT::JuliaOJIT() }; cantFail(GlobalJD.define(orc::symbolAliases(jl_crt))); +#ifdef _OS_OPENBSD_ + orc::SymbolMap i128_crt; + + i128_crt[mangle("__divti3")] = JITEvaluatedSymbol::fromPointer(&__divti3, JITSymbolFlags::Exported); + i128_crt[mangle("__modti3")] = JITEvaluatedSymbol::fromPointer(&__modti3, JITSymbolFlags::Exported); + i128_crt[mangle("__udivti3")] = JITEvaluatedSymbol::fromPointer(&__udivti3, JITSymbolFlags::Exported); + i128_crt[mangle("__umodti3")] = JITEvaluatedSymbol::fromPointer(&__umodti3, JITSymbolFlags::Exported); + + cantFail(GlobalJD.define(orc::absoluteSymbols(i128_crt))); +#endif + #ifdef MSAN_EMUTLS_WORKAROUND orc::SymbolMap msan_crt; msan_crt[mangle("__emutls_get_address")] = JITEvaluatedSymbol::fromPointer(msan_workaround::getTLSAddress, JITSymbolFlags::Exported); @@ -1808,7 +1828,7 @@ void JuliaOJIT::addModule(orc::ThreadSafeModule TSM) auto Lookups = ES.lookup({{&JD, orc::JITDylibLookupFlags::MatchExportedSymbolsOnly}}, NewExports); if (!Lookups) { ES.reportError(Lookups.takeError()); - errs() << "Failed to lookup symbols in module!"; + errs() << "Failed to lookup symbols in module!\n"; if (CurrentlyCompiling) { CurrentlyCompiling.withModuleDo([](Module &M) JL_NOTSAFEPOINT { errs() << "Dumping failing module\n" << M << "\n"; }); } else { diff --git a/src/julia.expmap.in b/src/julia.expmap.in index 213d087fdc2ad9..e5f9ee890205fe 100644 --- a/src/julia.expmap.in +++ b/src/julia.expmap.in @@ -1,7 +1,7 @@ @JULIA_SHLIB_SYMBOL_VERSION@ { global: pthread*; - __stack_chk_guard; + __stack_chk_*; asprintf; bitvector_*; ios_*; diff --git a/src/julia_threads.h b/src/julia_threads.h index 3f8f5391919b48..3a4e9a66cf5a79 100644 --- a/src/julia_threads.h +++ b/src/julia_threads.h @@ -37,6 +37,16 @@ JL_DLLEXPORT int8_t jl_threadpoolid(int16_t tid) JL_NOTSAFEPOINT; #define JL_HAVE_UCONTEXT typedef win32_ucontext_t jl_stack_context_t; typedef jl_stack_context_t _jl_ucontext_t; + +#elif defined(_OS_OPENBSD_) +#define JL_HAVE_UNW_CONTEXT +#define UNW_LOCAL_ONLY +#include +typedef unw_context_t _jl_ucontext_t; +typedef struct { + jl_jmp_buf uc_mcontext; +} jl_stack_context_t; + #else typedef struct { jl_jmp_buf uc_mcontext; diff --git a/src/signals-unix.c b/src/signals-unix.c index eb51a5fccfaba2..91c47421669f20 100644 --- a/src/signals-unix.c +++ b/src/signals-unix.c @@ -24,10 +24,12 @@ #endif // Figure out the best signals/timers to use for this platform -#ifdef __APPLE__ // Darwin's mach ports allow signal-free thread management +#if defined(__APPLE__) // Darwin's mach ports allow signal-free thread management #define HAVE_MACH #define HAVE_KEVENT -#else // generic Linux or BSD +#elif defined(__OpenBSD__) +#define HAVE_KEVENT +#else // generic Linux or FreeBSD #define HAVE_TIMER #endif @@ -83,6 +85,9 @@ static inline __attribute__((unused)) uintptr_t jl_get_rsp_from_ctx(const void * #elif defined(_OS_FREEBSD_) && defined(_CPU_X86_64_) const ucontext_t *ctx = (const ucontext_t*)_ctx; return ctx->uc_mcontext.mc_rsp; +#elif defined(_OS_OPENBSD_) && defined(_CPU_X86_64_) + const struct sigcontext *ctx = (const struct sigcontext *)_ctx; + return ctx->sc_rsp; #else // TODO Add support for PowerPC(64)? return 0; @@ -145,6 +150,11 @@ JL_NO_ASAN static void jl_call_in_ctx(jl_ptls_t ptls, void (*fptr)(void), int si rsp -= sizeof(void*); ctx->uc_mcontext.mc_esp = rsp; ctx->uc_mcontext.mc_eip = (uintptr_t)fptr; +#elif defined(_OS_OPENBSD_) && defined(_CPU_X86_64_) + struct sigcontext *ctx = (struct sigcontext *)_ctx; + rsp -= sizeof(void*); + ctx->sc_rsp = rsp; + ctx->sc_rip = fptr; #elif defined(_OS_LINUX_) && defined(_CPU_AARCH64_) ucontext_t *ctx = (ucontext_t*)_ctx; ctx->uc_mcontext.sp = rsp; @@ -237,8 +247,12 @@ static void sigdie_handler(int sig, siginfo_t *info, void *context) info->si_code == SI_KERNEL || #endif info->si_code == SI_QUEUE || +#ifdef SI_MESGQ info->si_code == SI_MESGQ || +#endif +#ifdef SI_ASYNCIO info->si_code == SI_ASYNCIO || +#endif #ifdef SI_SIGIO info->si_code == SI_SIGIO || #endif @@ -336,6 +350,11 @@ int is_write_fault(void *context) { ucontext_t *ctx = (ucontext_t*)context; return exc_reg_is_write_fault(ctx->uc_mcontext.mc_err); } +#elif defined(_OS_OPENBSD_) && defined(_CPU_X86_64_) +int is_write_fault(void *context) { + struct sigcontext *ctx = (struct sigcontext *)context; + return exc_reg_is_write_fault(ctx->sc_err); +} #else #pragma message("Implement this query for consistent PROT_NONE handling") int is_write_fault(void *context) { @@ -615,6 +634,17 @@ JL_DLLEXPORT void jl_profile_stop_timer(void) } } +#elif defined(__OpenBSD__) + +JL_DLLEXPORT int jl_profile_start_timer(void) +{ + return -1; +} + +JL_DLLEXPORT void jl_profile_stop_timer(void) +{ +} + #else #error no profile tools available @@ -653,6 +683,9 @@ void jl_install_thread_signal_handler(jl_ptls_t ptls) ss.ss_flags = 0; ss.ss_size = ssize; assert(ssize != 0); + +#ifndef _OS_OPENBSD_ + /* fallback to malloc(), but it isn't possible on OpenBSD */ if (signal_stack == NULL) { signal_stack = malloc(ssize); ssize = 0; @@ -661,6 +694,8 @@ void jl_install_thread_signal_handler(jl_ptls_t ptls) else jl_safe_printf("\nwarning: julia signal stack allocated without guard page (launch foreign threads earlier to avoid this warning).\n"); } +#endif + if (signal_stack != NULL) { ss.ss_sp = signal_stack; if (sigaltstack(&ss, NULL) < 0) diff --git a/src/support/dtypes.h b/src/support/dtypes.h index 4e9868ed45c232..57f4fa99f00168 100644 --- a/src/support/dtypes.h +++ b/src/support/dtypes.h @@ -99,7 +99,7 @@ typedef intptr_t ssize_t; #define BYTE_ORDER __BYTE_ORDER #endif -#if defined(__APPLE__) || defined(__FreeBSD__) +#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) #include #define __LITTLE_ENDIAN LITTLE_ENDIAN #define __BIG_ENDIAN BIG_ENDIAN diff --git a/src/support/platform.h b/src/support/platform.h index 9ab28ac1c70c38..a0dd84c9c20b66 100644 --- a/src/support/platform.h +++ b/src/support/platform.h @@ -16,6 +16,7 @@ * _COMPILER_GCC_ * OS: * _OS_FREEBSD_ + * _OS_OPENBSD_ * _OS_LINUX_ * _OS_WINDOWS_ * _OS_DARWIN_ @@ -81,6 +82,8 @@ #if defined(__FreeBSD__) #define _OS_FREEBSD_ +#elif defined(__OpenBSD__) +#define _OS_OPENBSD_ #elif defined(__linux__) #define _OS_LINUX_ #elif defined(_WIN32) || defined(_WIN64) diff --git a/src/support/strtod.c b/src/support/strtod.c index 24f556d0c086bb..e0ad1bf33435a8 100644 --- a/src/support/strtod.c +++ b/src/support/strtod.c @@ -11,7 +11,7 @@ extern "C" { #endif -#if !defined(_OS_WINDOWS_) +#if !defined(_OS_WINDOWS_) && !defined(__OpenBSD__) // This code path should be used for systems that support the strtod_l function // Cache locale object diff --git a/src/support/utf8.c b/src/support/utf8.c index 17dcf5f1efd511..02f541492b0f0a 100644 --- a/src/support/utf8.c +++ b/src/support/utf8.c @@ -29,9 +29,9 @@ #include #define snprintf _snprintf #else -#ifndef __FreeBSD__ +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) #include -#endif /* __FreeBSD__ */ +#endif /* !__FreeBSD__ && !__OpenBSD__ */ #endif #include diff --git a/src/sys.c b/src/sys.c index 0c0016ee076574..107a8f76377633 100644 --- a/src/sys.c +++ b/src/sys.c @@ -635,6 +635,38 @@ JL_DLLEXPORT long jl_SC_CLK_TCK(void) #endif } +#ifdef _OS_OPENBSD_ +// Helper for jl_pathname_for_handle() +struct dlinfo_data { + void *searched; + const char *result; +}; + +static int dlinfo_helper(struct dl_phdr_info *info, size_t size, void *vdata) +{ + struct dlinfo_data *data = (struct dlinfo_data *)vdata; + void *handle; + + /* ensure dl_phdr_info at compile-time to be compatible with the one at runtime */ + if (sizeof(*info) < size) + return -1; + + /* dlopen the name */ + handle = dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD); + if (handle == NULL) + return 0; + + /* check if the opened library is the same as the searched handle */ + if (data->searched == handle) + data->result = info->dlpi_name; + + dlclose(handle); + + /* continue if still not found */ + return (data->result != NULL); +} +#endif + // Takes a handle (as returned from dlopen()) and returns the absolute path to the image loaded JL_DLLEXPORT const char *jl_pathname_for_handle(void *handle) { @@ -677,6 +709,14 @@ JL_DLLEXPORT const char *jl_pathname_for_handle(void *handle) free(pth16); return filepath; +#elif defined(_OS_OPENBSD_) + struct dlinfo_data data = { + .searched = handle, + .result = NULL, + }; + dl_iterate_phdr(&dlinfo_helper, &data); + return data.result; + #else // Linux, FreeBSD, ... struct link_map *map; @@ -754,11 +794,11 @@ JL_DLLEXPORT size_t jl_maxrss(void) // FIXME: `rusage` is available on OpenBSD, DragonFlyBSD and NetBSD as well. // All of them return `ru_maxrss` in kilobytes. -#elif defined(_OS_LINUX_) || defined(_OS_DARWIN_) || defined (_OS_FREEBSD_) +#elif defined(_OS_LINUX_) || defined(_OS_DARWIN_) || defined (_OS_FREEBSD_) || defined (_OS_OPENBSD_) struct rusage rusage; getrusage( RUSAGE_SELF, &rusage ); -#if defined(_OS_LINUX_) || defined(_OS_FREEBSD_) +#if defined(_OS_LINUX_) || defined(_OS_FREEBSD_) || defined (_OS_OPENBSD_) return (size_t)(rusage.ru_maxrss * 1024); #else return (size_t)rusage.ru_maxrss; From d10a0fbcfe7e339e5d9bab161ff64dd022b44418 Mon Sep 17 00:00:00 2001 From: FX Coudert Date: Fri, 29 Mar 2024 17:51:02 +0100 Subject: [PATCH 059/123] curl: fix RPATH to find nghttp2 and libssh2 (#53894) Fixes https://github.com/JuliaLang/julia/issues/48820 I think this is the proper fix, and there might be a configure option to curl or nghttp2 to set it, but I haven't been found it. So we'll do it that way. --- deps/curl.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/curl.mk b/deps/curl.mk index 8454ec5f38b1e6..4314bb89cc7392 100644 --- a/deps/curl.mk +++ b/deps/curl.mk @@ -14,7 +14,7 @@ $(BUILDDIR)/curl-$(CURL_VER)/build-configured: | $(build_prefix)/manifest/nghttp endif ifneq ($(USE_BINARYBUILDER_CURL),1) -CURL_LDFLAGS := $(RPATH_ESCAPED_ORIGIN) +CURL_LDFLAGS := $(RPATH_ESCAPED_ORIGIN) -Wl,-rpath,$(build_shlibdir) # On older Linuces (those that use OpenSSL < 1.1) we include `libpthread` explicitly. # It doesn't hurt to include it explicitly elsewhere, so we do so. From 24ff6f4c9596953245d311bfffb96a7108c8c9d0 Mon Sep 17 00:00:00 2001 From: Diogo Netto <61364108+d-netto@users.noreply.github.com> Date: Sat, 30 Mar 2024 01:18:49 -0300 Subject: [PATCH 060/123] no need to check whether mq_master is nil in the GC work-stealing loop (#53899) This is not needed after https://github.com/JuliaLang/julia/pull/53355. --- src/gc.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/gc.c b/src/gc.c index 4aae5e22c6678b..06a41393953b9a 100644 --- a/src/gc.c +++ b/src/gc.c @@ -2976,11 +2976,10 @@ JL_EXTENSION NOINLINE void gc_mark_loop_serial(jl_ptls_t ptls) void gc_mark_and_steal(jl_ptls_t ptls) { - jl_gc_markqueue_t *mq = &ptls->mark_queue; - jl_gc_markqueue_t *mq_master = NULL; int master_tid = jl_atomic_load(&gc_master_tid); assert(master_tid != -1); - mq_master = &gc_all_tls_states[master_tid]->mark_queue; + jl_gc_markqueue_t *mq = &ptls->mark_queue; + jl_gc_markqueue_t *mq_master = &gc_all_tls_states[master_tid]->mark_queue; void *new_obj; jl_gc_chunk_t c; pop : { @@ -3024,12 +3023,10 @@ void gc_mark_and_steal(jl_ptls_t ptls) } } // Try to steal chunk from master thread - if (mq_master != NULL) { - c = gc_chunkqueue_steal_from(mq_master); - if (c.cid != GC_empty_chunk) { - gc_mark_chunk(ptls, mq, &c); - goto pop; - } + c = gc_chunkqueue_steal_from(mq_master); + if (c.cid != GC_empty_chunk) { + gc_mark_chunk(ptls, mq, &c); + goto pop; } // Try to steal pointer from random GC thread for (int i = 0; i < 4 * jl_n_markthreads; i++) { @@ -3047,11 +3044,9 @@ void gc_mark_and_steal(jl_ptls_t ptls) goto mark; } // Try to steal pointer from master thread - if (mq_master != NULL) { - new_obj = gc_ptr_queue_steal_from(mq_master); - if (new_obj != NULL) - goto mark; - } + new_obj = gc_ptr_queue_steal_from(mq_master); + if (new_obj != NULL) + goto mark; } } From 313f933370aff4edf1eb8f972964b2e459451066 Mon Sep 17 00:00:00 2001 From: FX Coudert Date: Sat, 30 Mar 2024 15:04:42 +0100 Subject: [PATCH 061/123] curl: remove patch (#53892) This upstream patch needs to be removed because in latest curl, it's already applied. This currently prevents a build from source. (And I am wondering why that was not caught?) --- deps/curl.mk | 11 +---------- deps/patches/curl-memdup.patch | 24 ------------------------ 2 files changed, 1 insertion(+), 34 deletions(-) delete mode 100644 deps/patches/curl-memdup.patch diff --git a/deps/curl.mk b/deps/curl.mk index 4314bb89cc7392..444334b581fedc 100644 --- a/deps/curl.mk +++ b/deps/curl.mk @@ -57,16 +57,7 @@ CURL_TLS_CONFIGURE_FLAGS := --with-mbedtls=$(build_prefix) endif CURL_CONFIGURE_FLAGS += $(CURL_TLS_CONFIGURE_FLAGS) -$(BUILDDIR)/curl-$(CURL_VER)/source-extracted/curl-memdup.patch-applied: $(SRCCACHE)/curl-$(CURL_VER)/source-extracted - mkdir -p $(dir $@) - cd $(SRCCACHE)/curl-$(CURL_VER) && \ - patch -p1 -f < $(SRCDIR)/patches/curl-memdup.patch - echo 1 > $@ - -$(SRCCACHE)/curl-$(CURL_VER)/source-patched: $(BUILDDIR)/curl-$(CURL_VER)/source-extracted/curl-memdup.patch-applied - echo 1 > $@ - -$(BUILDDIR)/curl-$(CURL_VER)/build-configured: $(SRCCACHE)/curl-$(CURL_VER)/source-patched +$(BUILDDIR)/curl-$(CURL_VER)/build-configured: $(SRCCACHE)/curl-$(CURL_VER)/source-extracted mkdir -p $(dir $@) cd $(dir $@) && \ $(dir $<)/configure $(CURL_CONFIGURE_FLAGS) \ diff --git a/deps/patches/curl-memdup.patch b/deps/patches/curl-memdup.patch deleted file mode 100644 index 596606027c4477..00000000000000 --- a/deps/patches/curl-memdup.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 5cc2b016c36aaf5a08e2feb7c068fca5bb0a8052 Mon Sep 17 00:00:00 2001 -From: Daniel Stenberg -Date: Mon, 5 Feb 2024 15:22:08 +0100 -Subject: [PATCH] md4: include strdup.h for the memdup proto - -Reported-by: Erik Schnetter -Fixes #12849 -Closes #12863 ---- - lib/md4.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/lib/md4.c b/lib/md4.c -index 067c211e420afd..58dd1166cf924f 100644 ---- a/lib/md4.c -+++ b/lib/md4.c -@@ -28,6 +28,7 @@ - - #include - -+#include "strdup.h" - #include "curl_md4.h" - #include "warnless.h" - From a3f710e2a35402bb7f7f96f874e6c696dfc911da Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sun, 31 Mar 2024 07:26:46 +0530 Subject: [PATCH 062/123] Copy for `CartesianIndices`/`LinearIndices` need not materialize (#53901) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, ```julia julia> C = CartesianIndices((1:2, 1:2)) CartesianIndices((1:2, 1:2)) julia> copy(C) 2ร—2 Matrix{CartesianIndex{2}}: CartesianIndex(1, 1) CartesianIndex(1, 2) CartesianIndex(2, 1) CartesianIndex(2, 2) ``` However, seeing that a `CartesianIndices` is equivalent to an n-D range, there doesn't seem to be a need to materialize the result. This PR also ensures that `copy(C)` returns the same type as `C`. After this PR: ```julia julia> C = CartesianIndices((1:2, 1:2)) CartesianIndices((1:2, 1:2)) julia> copy(C) CartesianIndices((1:2, 1:2)) ``` Also, a similar change for `LinearIndices` is added. --- base/indices.jl | 1 + base/multidimensional.jl | 4 +++- test/abstractarray.jl | 7 +++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/base/indices.jl b/base/indices.jl index 9fadff1cdb5de5..e629d2d6a03ff3 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -565,6 +565,7 @@ function getindex(iter::LinearIndices, i::AbstractRange{<:Integer}) @boundscheck checkbounds(iter, i) @inbounds isa(iter, LinearIndices{1}) ? iter.indices[1][i] : (first(iter):last(iter))[i] end +copy(iter::LinearIndices) = iter # More efficient iteration โ€” predominantly for non-vector LinearIndices # but one-dimensional LinearIndices must be special-cased to support OffsetArrays iterate(iter::LinearIndices{1}, s...) = iterate(axes1(iter.indices[1]), s...) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 04274cd79c1aa8..5fb2bf8cad5827 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -4,7 +4,7 @@ module IteratorsMD import .Base: eltype, length, size, first, last, in, getindex, setindex!, min, max, zero, oneunit, isless, eachindex, - convert, show, iterate, promote_rule, to_indices + convert, show, iterate, promote_rule, to_indices, copy import .Base: +, -, *, (:) import .Base: simd_outer_range, simd_inner_length, simd_index, setindex @@ -476,6 +476,8 @@ module IteratorsMD @inline in(i::CartesianIndex, r::CartesianIndices) = false @inline in(i::CartesianIndex{N}, r::CartesianIndices{N}) where {N} = all(map(in, i.I, r.indices)) + copy(iter::CartesianIndices) = iter + simd_outer_range(iter::CartesianIndices{0}) = iter function simd_outer_range(iter::CartesianIndices) CartesianIndices(tail(iter.indices)) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 48451d43d79c4d..a0a6ba6b2229aa 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -332,6 +332,13 @@ end end end +@testset "copy for LinearIndices/CartesianIndices" begin + C = CartesianIndices((1:2, 1:4)) + @test copy(C) === C + L = LinearIndices((1:2, 1:4)) + @test copy(L) === L +end + # token type on which to dispatch testing methods in order to avoid potential # name conflicts elsewhere in the base test suite mutable struct TestAbstractArray end From e9d25ca09382b0f67a4c7770cba08bff3db3cb38 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 1 Apr 2024 07:34:51 +0200 Subject: [PATCH 063/123] Add `Base.isrelocatable(pkg)` (#53906) This PR adds a utility function `isrelocatable(pkg)` that can be used to check if `pkg` is already precompiled and if the associated cachefile is relocatable. The reason to implicitly perform the `isprecompiled` check is that the exact same computation needs to be done to find the right `.ji`. A `pkg` is said to be relocatable if 1. all `include()` paths are relocatable (they start with `@depot`), 2. all `include_dependency()` paths are relocatable (they start with `@depot` and `track_content=true` was used to include them). --- base/loading.jl | 83 ++++++++++++++++++++++++++++++++++--------- test/relocatedepot.jl | 13 +++++++ 2 files changed, 79 insertions(+), 17 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index fd8eba6bed4602..a58d3e7502b74c 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1678,25 +1678,13 @@ end # should sync with the types of arguments of `stale_cachefile` const StaleCacheKey = Tuple{Base.PkgId, UInt128, String, String} -""" - Base.isprecompiled(pkg::PkgId; ignore_loaded::Bool=false) - -Returns whether a given PkgId within the active project is precompiled. - -By default this check observes the same approach that code loading takes -with respect to when different versions of dependencies are currently loaded -to that which is expected. To ignore loaded modules and answer as if in a -fresh julia session specify `ignore_loaded=true`. - -!!! compat "Julia 1.10" - This function requires at least Julia 1.10. -""" -function isprecompiled(pkg::PkgId; +function compilecache_path(pkg::PkgId; ignore_loaded::Bool=false, stale_cache::Dict{StaleCacheKey,Bool}=Dict{StaleCacheKey, Bool}(), cachepaths::Vector{String}=Base.find_all_in_cache_path(pkg), sourcepath::Union{String,Nothing}=Base.locate_package(pkg), flags::CacheFlags=CacheFlags()) + path = nothing isnothing(sourcepath) && error("Cannot locate source for $(repr("text/plain", pkg))") for path_to_try in cachepaths staledeps = stale_cachefile(sourcepath, path_to_try, ignore_loaded = true, requested_flags=flags) @@ -1728,10 +1716,64 @@ function isprecompiled(pkg::PkgId; # file might be read-only and then we fail to update timestamp, which is fine ex isa IOError || rethrow() end - return true + path = path_to_try + break @label check_next_path end - return false + return path +end + +""" + Base.isprecompiled(pkg::PkgId; ignore_loaded::Bool=false) + +Returns whether a given PkgId within the active project is precompiled. + +By default this check observes the same approach that code loading takes +with respect to when different versions of dependencies are currently loaded +to that which is expected. To ignore loaded modules and answer as if in a +fresh julia session specify `ignore_loaded=true`. + +!!! compat "Julia 1.10" + This function requires at least Julia 1.10. +""" +function isprecompiled(pkg::PkgId; + ignore_loaded::Bool=false, + stale_cache::Dict{StaleCacheKey,Bool}=Dict{StaleCacheKey, Bool}(), + cachepaths::Vector{String}=Base.find_all_in_cache_path(pkg), + sourcepath::Union{String,Nothing}=Base.locate_package(pkg), + flags::CacheFlags=CacheFlags()) + path = compilecache_path(pkg; ignore_loaded, stale_cache, cachepaths, sourcepath, flags) + return !isnothing(path) +end + +""" + Base.isrelocatable(pkg::PkgId) + +Returns whether a given PkgId within the active project is precompiled and the +associated cache is relocatable. + +!!! compat "Julia 1.11" + This function requires at least Julia 1.11. +""" +function isrelocatable(pkg::PkgId) + path = compilecache_path(pkg) + isnothing(path) && return false + io = open(path, "r") + try + iszero(isvalid_cache_header(io)) && throw(ArgumentError("Invalid header in cache file $cachefile.")) + _, (includes, includes_srcfiles, _), _... = _parse_cache_header(io, path) + for inc in includes + !startswith(inc.filename, "@depot") && return false + if inc โˆ‰ includes_srcfiles + # its an include_dependency + track_content = inc.mtime == -1.0 + track_content || return false + end + end + finally + close(io) + end + return true end # search for a precompile cache file to load, after some various checks @@ -3064,7 +3106,7 @@ function resolve_depot(inc::AbstractString) end -function parse_cache_header(f::IO, cachefile::AbstractString) +function _parse_cache_header(f::IO, cachefile::AbstractString) flags = read(f, UInt8) modules = Vector{Pair{PkgId, UInt64}}() while true @@ -3148,6 +3190,13 @@ function parse_cache_header(f::IO, cachefile::AbstractString) srcfiles = srctext_files(f, srctextpos, includes) + return modules, (includes, srcfiles, requires), required_modules, srctextpos, prefs, prefs_hash, clone_targets, flags +end + +function parse_cache_header(f::IO, cachefile::AbstractString) + modules, (includes, srcfiles, requires), required_modules, + srctextpos, prefs, prefs_hash, clone_targets, flags = _parse_cache_header(f, cachefile) + includes_srcfiles = CacheHeaderIncludes[] includes_depfiles = CacheHeaderIncludes[] for (i, inc) in enumerate(includes) diff --git a/test/relocatedepot.jl b/test/relocatedepot.jl index b2a539ac330d33..c9c8bd38a245f8 100644 --- a/test/relocatedepot.jl +++ b/test/relocatedepot.jl @@ -78,8 +78,10 @@ if !test_relocated_depot cachefiles = Base.find_all_in_cache_path(pkg) rm.(cachefiles, force=true) @test Base.isprecompiled(pkg) == false + @test Base.isrelocatable(pkg) == false # because not precompiled Base.require(pkg) @test Base.isprecompiled(pkg, ignore_loaded=true) == true + @test Base.isrelocatable(pkg) == true end end @@ -93,10 +95,12 @@ if !test_relocated_depot rm.(cachefiles, force=true) rm(joinpath(@__DIR__, pkgname, "src", "foodir"), force=true, recursive=true) @test Base.isprecompiled(pkg) == false + @test Base.isrelocatable(pkg) == false # because not precompiled touch(joinpath(@__DIR__, pkgname, "src", "foo.txt")) mkdir(joinpath(@__DIR__, pkgname, "src", "foodir")) Base.require(pkg) @test Base.isprecompiled(pkg, ignore_loaded=true) == true + @test Base.isrelocatable(pkg) == false # because tracked by mtime end end @@ -110,10 +114,12 @@ if !test_relocated_depot rm.(cachefiles, force=true) rm(joinpath(@__DIR__, pkgname, "src", "bardir"), force=true, recursive=true) @test Base.isprecompiled(pkg) == false + @test Base.isrelocatable(pkg) == false # because not precompiled touch(joinpath(@__DIR__, pkgname, "src", "bar.txt")) mkdir(joinpath(@__DIR__, pkgname, "src", "bardir")) Base.require(pkg) @test Base.isprecompiled(pkg, ignore_loaded=true) == true + @test Base.isrelocatable(pkg) == true end end @@ -202,6 +208,7 @@ else # stdlib should be already precompiled pkg = Base.identify_package("DelimitedFiles") @test Base.isprecompiled(pkg) == true + @test Base.isrelocatable(pkg) == true end end @@ -213,6 +220,7 @@ else push!(DEPOT_PATH, joinpath(@__DIR__, "relocatedepot", "julia")) # contains cache file pkg = Base.identify_package(pkgname) @test Base.isprecompiled(pkg) == true + @test Base.isrelocatable(pkg) == true end end @@ -224,10 +232,13 @@ else push!(DEPOT_PATH, joinpath(@__DIR__, "relocatedepot", "julia")) # contains cache file pkg = Base.identify_package(pkgname) @test Base.isprecompiled(pkg) == false # moving depot changes mtime of include_dependency + @test Base.isrelocatable(pkg) == false # because not precompiled Base.require(pkg) @test Base.isprecompiled(pkg) == true + @test Base.isrelocatable(pkg) == false # because tracked by mtime touch(joinpath(@__DIR__, "relocatedepot", "RelocationTestPkg2", "src", "foodir", "foofoo")) @test Base.isprecompiled(pkg) == false + @test Base.isrelocatable(pkg) == false # because tracked by mtime end end @@ -239,8 +250,10 @@ else push!(DEPOT_PATH, joinpath(@__DIR__, "relocatedepot", "julia")) # contains cache file pkg = Base.identify_package(pkgname) @test Base.isprecompiled(pkg) == true + @test Base.isrelocatable(pkg) == true touch(joinpath(@__DIR__, "relocatedepot", "RelocationTestPkg3", "src", "bardir", "barbar")) @test Base.isprecompiled(pkg) == false + @test Base.isrelocatable(pkg) == false # because not precompiled end end From 657ce0482d54f9658c9cf4fd3560ca51aafdb03b Mon Sep 17 00:00:00 2001 From: Zentrik Date: Mon, 1 Apr 2024 19:13:18 +0100 Subject: [PATCH 064/123] Fix calling LLVM_SIZE on windows (#53902) Per https://github.com/JuliaCI/julia-buildkite/pull/224#issuecomment-1474914609, the path needs to be updated so that `llvm-size` can find `libLLVM.dll`. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d7d25998688c57..0c27216d2f9fb6 100644 --- a/Makefile +++ b/Makefile @@ -653,7 +653,7 @@ win-extras: ifeq ($(USE_SYSTEM_LLVM), 1) LLVM_SIZE := llvm-size$(EXE) else -LLVM_SIZE := $(build_depsbindir)/llvm-size$(EXE) +LLVM_SIZE := PATH=$(build_bindir):$$PATH; $(build_depsbindir)/llvm-size$(EXE) endif build-stats: ifeq ($(USE_BINARYBUILDER_LLVM),1) From 1fedcab78123f41d285e465632f37f5c85e7701b Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Tue, 2 Apr 2024 03:29:32 +0900 Subject: [PATCH 065/123] optimizer: allow multiple inlining again (#53911) Before JuliaLang/julia#52415 we could do multiple rounds of inlining on IR that had already been inlined, but this was no longer possible. By removing the assertion that was introduced in JuliaLang/julia#52415, this commit makes it possible to do multi-inlining once more. Note that to fully solve this, though, we need to enhance `ir_inline_linetable!` so it can add new linetables to an inner linetable that's already been inlined. This commit notes that enhancement as something we need to do later, leaving it with a TODO comment. --- base/compiler/ssair/inlining.jl | 18 +++++------ base/compiler/ssair/passes.jl | 2 +- test/compiler/inline.jl | 54 ++++++++++++++++++++++++++------- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index 164102758a88f1..e54d3fd834a27c 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -300,7 +300,8 @@ function finish_cfg_inline!(state::CFGInliningState) end end -function ir_inline_linetable!(debuginfo::DebugInfoStream, inlinee_debuginfo::DebugInfo, inlinee::MethodInstance) +# TODO append `inlinee_debuginfo` to inner linetable when `inlined_at[2] โ‰  0` +function ir_inline_linetable!(debuginfo::DebugInfoStream, inlinee_debuginfo::DebugInfo, inlined_at::NTuple{3,Int32}) # Append the linetable of the inlined function to our edges table linetable_offset = 1 while true @@ -312,16 +313,14 @@ function ir_inline_linetable!(debuginfo::DebugInfoStream, inlinee_debuginfo::Deb end linetable_offset += 1 end - return Int32(linetable_offset) + return (inlined_at[1], Int32(linetable_offset), Int32(0)) end function ir_prepare_inlining!(insert_node!::Inserter, inline_target::Union{IRCode, IncrementalCompact}, - ir::IRCode, di::DebugInfo, mi::MethodInstance, inlined_at::Int32, argexprs::Vector{Any}) + ir::IRCode, di::DebugInfo, mi::MethodInstance, inlined_at::NTuple{3,Int32}, argexprs::Vector{Any}) def = mi.def::Method debuginfo = inline_target isa IRCode ? inline_target.debuginfo : inline_target.ir.debuginfo - - linetable_offset = ir_inline_linetable!(debuginfo, di, mi) - topline = (inlined_at, linetable_offset, Int32(0)) + topline = new_inlined_at = ir_inline_linetable!(debuginfo, di, inlined_at) if should_insert_coverage(def.module, di) insert_node!(NewInstruction(Expr(:code_coverage_effect), Nothing, topline)) end @@ -343,7 +342,7 @@ function ir_prepare_inlining!(insert_node!::Inserter, inline_target::Union{IRCod NewInstruction(Expr(:call, GlobalRef(Core, :getfield), argexprs[1], QuoteNode(:captures)), ir.argtypes[1], topline)) end - return SSASubstitute(mi, argexprs, spvals_ssa, (inlined_at, linetable_offset)) + return SSASubstitute(mi, argexprs, spvals_ssa, new_inlined_at) end function adjust_boundscheck!(inline_compact::IncrementalCompact, idxโ€ฒ::Int, stmt::Expr, boundscheck::Symbol) @@ -359,8 +358,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector item::InliningTodo, boundscheck::Symbol, todo_bbs::Vector{Tuple{Int, Int}}) # Ok, do the inlining here inlined_at = compact.result[idx][:line] - @assert inlined_at[2] == 0 "already inlined this instruction" - ssa_substitute = ir_prepare_inlining!(InsertHere(compact), compact, item.ir, item.di, item.mi, inlined_at[1], argexprs) + ssa_substitute = ir_prepare_inlining!(InsertHere(compact), compact, item.ir, item.di, item.mi, inlined_at, argexprs) boundscheck = has_flag(compact.result[idx], IR_FLAG_INBOUNDS) ? :off : boundscheck # If the iterator already moved on to the next basic block, @@ -1771,7 +1769,7 @@ struct SSASubstitute mi::MethodInstance arg_replacements::Vector{Any} spvals_ssa::Union{Nothing,SSAValue} - inlined_at::NTuple{2,Int32} # TODO: add a map also, so that ssaidx doesn't need to equal inlined_idx? + inlined_at::NTuple{3,Int32} # TODO: add a map also, so that ssaidx doesn't need to equal inlined_idx? end function insert_spval!(insert_node!::Inserter, spvals_ssa::SSAValue, spidx::Int, do_isdefined::Bool) diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index 946ba9633d3663..328f7164a7b935 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -1516,7 +1516,7 @@ function try_inline_finalizer!(ir::IRCode, argexprs::Vector{Any}, idx::Int, add_inlining_backedge!(et, mi) # TODO: Should there be a special line number node for inlined finalizers? - inline_at = ir[SSAValue(idx)][:line][1] + inline_at = ir[SSAValue(idx)][:line] ssa_substitute = ir_prepare_inlining!(InsertBefore(ir, SSAValue(idx)), ir, src, di, mi, inline_at, argexprs) # TODO: Use the actual inliner here rather than open coding this special purpose inliner. diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 2f916c375218a1..3c408b06a87ae2 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -1818,23 +1818,55 @@ let src = code_typed1((AtomicMemoryRef{Int},)) do a @test count(isinvokemodify(:+), src.code) == 1 end - - # apply `ssa_inlining_pass` multiple times -let interp = Core.Compiler.NativeInterpreter() +func_mul_int(a::Int, b::Int) = Core.Intrinsics.mul_int(a, b) +multi_inlining1(a::Int, b::Int) = @noinline func_mul_int(a, b) +let i::Int, continue_::Bool + interp = Core.Compiler.NativeInterpreter() # check if callsite `@noinline` annotation works - ir, = Base.code_ircode((Int,Int); optimize_until="inlining", interp) do a, b - @noinline a*b - end |> only - i = findfirst(isinvoke(:*), ir.stmts.stmt) + ir, = only(Base.code_ircode(multi_inlining1, (Int,Int); optimize_until="inlining", interp)) + i = findfirst(isinvoke(:func_mul_int), ir.stmts.stmt) @test i !== nothing - - # ok, now delete the callsite flag, and see the second inlining pass can inline the call + # now delete the callsite flag, and see the second inlining pass can inline the call @eval Core.Compiler $ir.stmts[$i][:flag] &= ~IR_FLAG_NOINLINE inlining = Core.Compiler.InliningState(interp) ir = Core.Compiler.ssa_inlining_pass!(ir, inlining, false) - @test count(isinvoke(:*), ir.stmts.stmt) == 0 - @test count(iscall((ir, Core.Intrinsics.mul_int)), ir.stmts.stmt) == 1 + @test findfirst(isinvoke(:func_mul_int), ir.stmts.stmt) === nothing + @test (i = findfirst(iscall((ir, Core.Intrinsics.mul_int)), ir.stmts.stmt)) !== nothing + lins = Base.IRShow.buildLineInfoNode(ir.debuginfo, nothing, i) + @test (continue_ = length(lins) == 2) # :multi_inlining1 -> :func_mul_int + if continue_ + def1 = lins[1].method + @test def1 isa Core.MethodInstance && def1.def.name === :multi_inlining1 + def2 = lins[2].method + @test def2 isa Core.MethodInstance && def2.def.name === :func_mul_int + end +end + +call_func_mul_int(a::Int, b::Int) = @noinline func_mul_int(a, b) +multi_inlining2(a::Int, b::Int) = call_func_mul_int(a, b) +let i::Int, continue_::Bool + interp = Core.Compiler.NativeInterpreter() + # check if callsite `@noinline` annotation works + ir, = only(Base.code_ircode(multi_inlining2, (Int,Int); optimize_until="inlining", interp)) + i = findfirst(isinvoke(:func_mul_int), ir.stmts.stmt) + @test i !== nothing + # now delete the callsite flag, and see the second inlining pass can inline the call + @eval Core.Compiler $ir.stmts[$i][:flag] &= ~IR_FLAG_NOINLINE + inlining = Core.Compiler.InliningState(interp) + ir = Core.Compiler.ssa_inlining_pass!(ir, inlining, false) + @test findfirst(isinvoke(:func_mul_int), ir.stmts.stmt) === nothing + @test (i = findfirst(iscall((ir, Core.Intrinsics.mul_int)), ir.stmts.stmt)) !== nothing + lins = Base.IRShow.buildLineInfoNode(ir.debuginfo, nothing, i) + @test_broken (continue_ = length(lins) == 3) # see TODO in `ir_inline_linetable!` + if continue_ + def1 = lins[1].method + @test def1 isa Core.MethodInstance && def1.def.name === :multi_inlining2 + def2 = lins[2].method + @test def2 isa Core.MethodInstance && def2.def.name === :call_func_mul_int + def3 = lins[3].method + @test def3 isa Core.MethodInstance && def3.def.name === :call_func_mul_int + end end # Test special purpose inliner for Core.ifelse From 0ac60b736a26f4b92b67edad16f3e90e1eb32cd8 Mon Sep 17 00:00:00 2001 From: Fons van der Plas Date: Mon, 1 Apr 2024 23:06:16 +0200 Subject: [PATCH 066/123] =?UTF-8?q?More=20emoji=20completions!=20?= =?UTF-8?q?=F0=9F=AB=A0=20(#53913)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Happy April fools day! ๐Ÿชฟ Let's celebrate with a very important PR ๐Ÿฉต This PR updates the REPL completion list with all the fun new emoji from unicode 15.1! This makes Julia ready for the up-and-coming programmzers who want the latest trends in emoji coding! ๐Ÿซถ๐Ÿซถ Fresh new emoji for fresh new ideas! ๐Ÿซถ๐Ÿซถ Some of the new emoji include: - `\:biting_lip:` ๐Ÿซฆ for when the IO code gets *spicy* - `\:beans:` ๐Ÿซ˜ beanssss - `\:mirror_ball:` ๐Ÿชฉ for parties! - `\:playground_slide:` ๐Ÿ› for really fun code :) Thanks to @oxinabox for the future-proof script! Enjoy!! --- stdlib/REPL/src/emoji_symbols.jl | 58 ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/stdlib/REPL/src/emoji_symbols.jl b/stdlib/REPL/src/emoji_symbols.jl index 49a55c97f6564c..d6d4a03321d0a4 100644 --- a/stdlib/REPL/src/emoji_symbols.jl +++ b/stdlib/REPL/src/emoji_symbols.jl @@ -27,6 +27,7 @@ result = mapfoldr(emoji_data, merge, [ # overwrite the old with names that changed but still keep old ones that were removed "https://raw.githubusercontent.com/iamcal/emoji-data/0f0cf4ea8845eb52d26df2a48c3c31c3b8cad14e/emoji_pretty.json", "https://raw.githubusercontent.com/iamcal/emoji-data/e512953312c012f6bd00e3f2ef6bf152ca3710f8/emoji_pretty.json", + "https://raw.githubusercontent.com/iamcal/emoji-data/a8174c74675355c8c6a9564516b2e961fe7257ef/emoji_pretty.json", ]; init=Dict() ) @@ -132,6 +133,7 @@ const emoji_symbols = Dict( "\\:bath:" => "๐Ÿ›€", "\\:bathtub:" => "๐Ÿ›", "\\:battery:" => "๐Ÿ”‹", + "\\:beans:" => "๐Ÿซ˜", "\\:bear:" => "๐Ÿป", "\\:bearded_person:" => "๐Ÿง”", "\\:beaver:" => "๐Ÿฆซ", @@ -151,6 +153,7 @@ const emoji_symbols = Dict( "\\:bird:" => "๐Ÿฆ", "\\:birthday:" => "๐ŸŽ‚", "\\:bison:" => "๐Ÿฆฌ", + "\\:biting_lip:" => "๐Ÿซฆ", "\\:black_circle:" => "โšซ", "\\:black_heart:" => "๐Ÿ–ค", "\\:black_joker:" => "๐Ÿƒ", @@ -198,6 +201,7 @@ const emoji_symbols = Dict( "\\:broom:" => "๐Ÿงน", "\\:brown_heart:" => "๐ŸคŽ", "\\:bubble_tea:" => "๐Ÿง‹", + "\\:bubbles:" => "๐Ÿซง", "\\:bucket:" => "๐Ÿชฃ", "\\:bug:" => "๐Ÿ›", "\\:bulb:" => "๐Ÿ’ก", @@ -309,6 +313,7 @@ const emoji_symbols = Dict( "\\:cool:" => "๐Ÿ†’", "\\:cop:" => "๐Ÿ‘ฎ", "\\:copyright:" => "ยฉ", + "\\:coral:" => "๐Ÿชธ", "\\:corn:" => "๐ŸŒฝ", "\\:couple:" => "๐Ÿ‘ซ", "\\:couple_with_heart:" => "๐Ÿ’‘", @@ -325,6 +330,7 @@ const emoji_symbols = Dict( "\\:crossed_fingers:" => "๐Ÿคž", "\\:crossed_flags:" => "๐ŸŽŒ", "\\:crown:" => "๐Ÿ‘‘", + "\\:crutch:" => "๐Ÿฉผ", "\\:cry:" => "๐Ÿ˜ข", "\\:crying_cat_face:" => "๐Ÿ˜ฟ", "\\:crystal_ball:" => "๐Ÿ”ฎ", @@ -367,7 +373,9 @@ const emoji_symbols = Dict( "\\:dollar:" => "๐Ÿ’ต", "\\:dolls:" => "๐ŸŽŽ", "\\:dolphin:" => "๐Ÿฌ", + "\\:donkey:" => "๐Ÿซ", "\\:door:" => "๐Ÿšช", + "\\:dotted_line_face:" => "๐Ÿซฅ", "\\:doughnut:" => "๐Ÿฉ", "\\:dragon:" => "๐Ÿ‰", "\\:dragon_face:" => "๐Ÿฒ", @@ -397,6 +405,7 @@ const emoji_symbols = Dict( "\\:elevator:" => "๐Ÿ›—", "\\:elf:" => "๐Ÿง", "\\:email:" => "โœ‰", + "\\:empty_nest:" => "๐Ÿชน", "\\:end:" => "๐Ÿ”š", "\\:envelope_with_arrow:" => "๐Ÿ“ฉ", "\\:euro:" => "๐Ÿ’ถ", @@ -408,12 +417,16 @@ const emoji_symbols = Dict( "\\:expressionless:" => "๐Ÿ˜‘", "\\:eyeglasses:" => "๐Ÿ‘“", "\\:eyes:" => "๐Ÿ‘€", + "\\:face_holding_back_tears:" => "๐Ÿฅน", "\\:face_palm:" => "๐Ÿคฆ", "\\:face_vomiting:" => "๐Ÿคฎ", "\\:face_with_cowboy_hat:" => "๐Ÿค ", + "\\:face_with_diagonal_mouth:" => "๐Ÿซค", "\\:face_with_hand_over_mouth:" => "๐Ÿคญ", "\\:face_with_head_bandage:" => "๐Ÿค•", "\\:face_with_monocle:" => "๐Ÿง", + "\\:face_with_open_eyes_and_hand_over_mouth:" => "๐Ÿซข", + "\\:face_with_peeking_eye:" => "๐Ÿซฃ", "\\:face_with_raised_eyebrow:" => "๐Ÿคจ", "\\:face_with_rolling_eyes:" => "๐Ÿ™„", "\\:face_with_symbols_on_mouth:" => "๐Ÿคฌ", @@ -452,10 +465,12 @@ const emoji_symbols = Dict( "\\:floppy_disk:" => "๐Ÿ’พ", "\\:flower_playing_cards:" => "๐ŸŽด", "\\:flushed:" => "๐Ÿ˜ณ", + "\\:flute:" => "๐Ÿชˆ", "\\:fly:" => "๐Ÿชฐ", "\\:flying_disc:" => "๐Ÿฅ", "\\:flying_saucer:" => "๐Ÿ›ธ", "\\:foggy:" => "๐ŸŒ", + "\\:folding_hand_fan:" => "๐Ÿชญ", "\\:fondue:" => "๐Ÿซ•", "\\:foot:" => "๐Ÿฆถ", "\\:football:" => "๐Ÿˆ", @@ -482,6 +497,7 @@ const emoji_symbols = Dict( "\\:ghost:" => "๐Ÿ‘ป", "\\:gift:" => "๐ŸŽ", "\\:gift_heart:" => "๐Ÿ’", + "\\:ginger_root:" => "๐Ÿซš", "\\:giraffe_face:" => "๐Ÿฆ’", "\\:girl:" => "๐Ÿ‘ง", "\\:glass_of_milk:" => "๐Ÿฅ›", @@ -491,6 +507,7 @@ const emoji_symbols = Dict( "\\:goat:" => "๐Ÿ", "\\:goggles:" => "๐Ÿฅฝ", "\\:golf:" => "โ›ณ", + "\\:goose:" => "๐Ÿชฟ", "\\:gorilla:" => "๐Ÿฆ", "\\:grapes:" => "๐Ÿ‡", "\\:green_apple:" => "๐Ÿ", @@ -498,6 +515,7 @@ const emoji_symbols = Dict( "\\:green_heart:" => "๐Ÿ’š", "\\:green_salad:" => "๐Ÿฅ—", "\\:grey_exclamation:" => "โ•", + "\\:grey_heart:" => "๐Ÿฉถ", "\\:grey_question:" => "โ”", "\\:grimacing:" => "๐Ÿ˜ฌ", "\\:grin:" => "๐Ÿ˜", @@ -506,11 +524,14 @@ const emoji_symbols = Dict( "\\:guide_dog:" => "๐Ÿฆฎ", "\\:guitar:" => "๐ŸŽธ", "\\:gun:" => "๐Ÿ”ซ", + "\\:hair_pick:" => "๐Ÿชฎ", "\\:haircut:" => "๐Ÿ’‡", "\\:hamburger:" => "๐Ÿ”", "\\:hammer:" => "๐Ÿ”จ", + "\\:hamsa:" => "๐Ÿชฌ", "\\:hamster:" => "๐Ÿน", "\\:hand:" => "โœ‹", + "\\:hand_with_index_finger_and_thumb_crossed:" => "๐Ÿซฐ", "\\:handbag:" => "๐Ÿ‘œ", "\\:handball:" => "๐Ÿคพ", "\\:handshake:" => "๐Ÿค", @@ -524,12 +545,14 @@ const emoji_symbols = Dict( "\\:heart_decoration:" => "๐Ÿ’Ÿ", "\\:heart_eyes:" => "๐Ÿ˜", "\\:heart_eyes_cat:" => "๐Ÿ˜ป", + "\\:heart_hands:" => "๐Ÿซถ", "\\:heartbeat:" => "๐Ÿ’“", "\\:heartpulse:" => "๐Ÿ’—", "\\:hearts:" => "โ™ฅ", "\\:heavy_check_mark:" => "โœ”", "\\:heavy_division_sign:" => "โž—", "\\:heavy_dollar_sign:" => "๐Ÿ’ฒ", + "\\:heavy_equals_sign:" => "๐ŸŸฐ", "\\:heavy_minus_sign:" => "โž–", "\\:heavy_multiplication_x:" => "โœ–", "\\:heavy_plus_sign:" => "โž•", @@ -559,16 +582,19 @@ const emoji_symbols = Dict( "\\:hugging_face:" => "๐Ÿค—", "\\:hushed:" => "๐Ÿ˜ฏ", "\\:hut:" => "๐Ÿ›–", + "\\:hyacinth:" => "๐Ÿชป", "\\:i_love_you_hand_sign:" => "๐ŸคŸ", "\\:ice_cream:" => "๐Ÿจ", "\\:ice_cube:" => "๐ŸงŠ", "\\:ice_hockey_stick_and_puck:" => "๐Ÿ’", "\\:icecream:" => "๐Ÿฆ", "\\:id:" => "๐Ÿ†”", + "\\:identification_card:" => "๐Ÿชช", "\\:ideograph_advantage:" => "๐Ÿ‰", "\\:imp:" => "๐Ÿ‘ฟ", "\\:inbox_tray:" => "๐Ÿ“ฅ", "\\:incoming_envelope:" => "๐Ÿ“จ", + "\\:index_pointing_at_the_viewer:" => "๐Ÿซต", "\\:information_desk_person:" => "๐Ÿ’", "\\:information_source:" => "โ„น", "\\:innocent:" => "๐Ÿ˜‡", @@ -580,7 +606,9 @@ const emoji_symbols = Dict( "\\:japanese_castle:" => "๐Ÿฏ", "\\:japanese_goblin:" => "๐Ÿ‘บ", "\\:japanese_ogre:" => "๐Ÿ‘น", + "\\:jar:" => "๐Ÿซ™", "\\:jeans:" => "๐Ÿ‘–", + "\\:jellyfish:" => "๐Ÿชผ", "\\:jigsaw:" => "๐Ÿงฉ", "\\:joy:" => "๐Ÿ˜‚", "\\:joy_cat:" => "๐Ÿ˜น", @@ -589,6 +617,7 @@ const emoji_symbols = Dict( "\\:kangaroo:" => "๐Ÿฆ˜", "\\:key:" => "๐Ÿ”‘", "\\:keycap_ten:" => "๐Ÿ”Ÿ", + "\\:khanda:" => "๐Ÿชฏ", "\\:kimono:" => "๐Ÿ‘˜", "\\:kiss:" => "๐Ÿ’‹", "\\:kissing:" => "๐Ÿ˜—", @@ -631,11 +660,14 @@ const emoji_symbols = Dict( "\\:left_luggage:" => "๐Ÿ›…", "\\:left_right_arrow:" => "โ†”", "\\:leftwards_arrow_with_hook:" => "โ†ฉ", + "\\:leftwards_hand:" => "๐Ÿซฒ", + "\\:leftwards_pushing_hand:" => "๐Ÿซท", "\\:leg:" => "๐Ÿฆต", "\\:lemon:" => "๐Ÿ‹", "\\:leo:" => "โ™Œ", "\\:leopard:" => "๐Ÿ†", "\\:libra:" => "โ™Ž", + "\\:light_blue_heart:" => "๐Ÿฉต", "\\:light_rail:" => "๐Ÿšˆ", "\\:link:" => "๐Ÿ”—", "\\:lion_face:" => "๐Ÿฆ", @@ -650,10 +682,12 @@ const emoji_symbols = Dict( "\\:long_drum:" => "๐Ÿช˜", "\\:loop:" => "โžฟ", "\\:lotion_bottle:" => "๐Ÿงด", + "\\:lotus:" => "๐Ÿชท", "\\:loud_sound:" => "๐Ÿ”Š", "\\:loudspeaker:" => "๐Ÿ“ข", "\\:love_hotel:" => "๐Ÿฉ", "\\:love_letter:" => "๐Ÿ’Œ", + "\\:low_battery:" => "๐Ÿชซ", "\\:low_brightness:" => "๐Ÿ”…", "\\:luggage:" => "๐Ÿงณ", "\\:lungs:" => "๐Ÿซ", @@ -679,6 +713,7 @@ const emoji_symbols = Dict( "\\:mans_shoe:" => "๐Ÿ‘ž", "\\:manual_wheelchair:" => "๐Ÿฆฝ", "\\:maple_leaf:" => "๐Ÿ", + "\\:maracas:" => "๐Ÿช‡", "\\:martial_arts_uniform:" => "๐Ÿฅ‹", "\\:mask:" => "๐Ÿ˜ท", "\\:massage:" => "๐Ÿ’†", @@ -688,6 +723,7 @@ const emoji_symbols = Dict( "\\:mechanical_leg:" => "๐Ÿฆฟ", "\\:mega:" => "๐Ÿ“ฃ", "\\:melon:" => "๐Ÿˆ", + "\\:melting_face:" => "๐Ÿซ ", "\\:memo:" => "๐Ÿ“", "\\:menorah_with_nine_branches:" => "๐Ÿ•Ž", "\\:mens:" => "๐Ÿšน", @@ -702,6 +738,7 @@ const emoji_symbols = Dict( "\\:minibus:" => "๐Ÿš", "\\:minidisc:" => "๐Ÿ’ฝ", "\\:mirror:" => "๐Ÿชž", + "\\:mirror_ball:" => "๐Ÿชฉ", "\\:mobile_phone_off:" => "๐Ÿ“ด", "\\:money_mouth_face:" => "๐Ÿค‘", "\\:money_with_wings:" => "๐Ÿ’ธ", @@ -711,6 +748,7 @@ const emoji_symbols = Dict( "\\:monorail:" => "๐Ÿš", "\\:moon:" => "๐ŸŒ”", "\\:moon_cake:" => "๐Ÿฅฎ", + "\\:moose:" => "๐ŸซŽ", "\\:mortar_board:" => "๐ŸŽ“", "\\:mosque:" => "๐Ÿ•Œ", "\\:mosquito:" => "๐ŸฆŸ", @@ -739,6 +777,7 @@ const emoji_symbols = Dict( "\\:necktie:" => "๐Ÿ‘”", "\\:negative_squared_cross_mark:" => "โŽ", "\\:nerd_face:" => "๐Ÿค“", + "\\:nest_with_eggs:" => "๐Ÿชบ", "\\:nesting_dolls:" => "๐Ÿช†", "\\:neutral_face:" => "๐Ÿ˜", "\\:new:" => "๐Ÿ†•", @@ -800,7 +839,9 @@ const emoji_symbols = Dict( "\\:page_facing_up:" => "๐Ÿ“„", "\\:page_with_curl:" => "๐Ÿ“ƒ", "\\:pager:" => "๐Ÿ“Ÿ", + "\\:palm_down_hand:" => "๐Ÿซณ", "\\:palm_tree:" => "๐ŸŒด", + "\\:palm_up_hand:" => "๐Ÿซด", "\\:palms_up_together:" => "๐Ÿคฒ", "\\:pancakes:" => "๐Ÿฅž", "\\:panda_face:" => "๐Ÿผ", @@ -812,6 +853,7 @@ const emoji_symbols = Dict( "\\:partly_sunny:" => "โ›…", "\\:partying_face:" => "๐Ÿฅณ", "\\:passport_control:" => "๐Ÿ›‚", + "\\:pea_pod:" => "๐Ÿซ›", "\\:peach:" => "๐Ÿ‘", "\\:peacock:" => "๐Ÿฆš", "\\:peanuts:" => "๐Ÿฅœ", @@ -829,6 +871,7 @@ const emoji_symbols = Dict( "\\:person_in_steamy_room:" => "๐Ÿง–", "\\:person_in_tuxedo:" => "๐Ÿคต", "\\:person_with_blond_hair:" => "๐Ÿ‘ฑ", + "\\:person_with_crown:" => "๐Ÿซ…", "\\:person_with_headscarf:" => "๐Ÿง•", "\\:person_with_pouting_face:" => "๐Ÿ™Ž", "\\:petri_dish:" => "๐Ÿงซ", @@ -843,10 +886,12 @@ const emoji_symbols = Dict( "\\:pinched_fingers:" => "๐ŸคŒ", "\\:pinching_hand:" => "๐Ÿค", "\\:pineapple:" => "๐Ÿ", + "\\:pink_heart:" => "๐Ÿฉท", "\\:pisces:" => "โ™“", "\\:pizza:" => "๐Ÿ•", "\\:placard:" => "๐Ÿชง", "\\:place_of_worship:" => "๐Ÿ›", + "\\:playground_slide:" => "๐Ÿ›", "\\:pleading_face:" => "๐Ÿฅบ", "\\:plunger:" => "๐Ÿช ", "\\:point_down:" => "๐Ÿ‘‡", @@ -866,9 +911,12 @@ const emoji_symbols = Dict( "\\:pouch:" => "๐Ÿ‘", "\\:poultry_leg:" => "๐Ÿ—", "\\:pound:" => "๐Ÿ’ท", + "\\:pouring_liquid:" => "๐Ÿซ—", "\\:pouting_cat:" => "๐Ÿ˜พ", "\\:pray:" => "๐Ÿ™", "\\:prayer_beads:" => "๐Ÿ“ฟ", + "\\:pregnant_man:" => "๐Ÿซƒ", + "\\:pregnant_person:" => "๐Ÿซ„", "\\:pregnant_woman:" => "๐Ÿคฐ", "\\:pretzel:" => "๐Ÿฅจ", "\\:prince:" => "๐Ÿคด", @@ -914,7 +962,10 @@ const emoji_symbols = Dict( "\\:rice_cracker:" => "๐Ÿ˜", "\\:rice_scene:" => "๐ŸŽ‘", "\\:right-facing_fist:" => "๐Ÿคœ", + "\\:rightwards_hand:" => "๐Ÿซฑ", + "\\:rightwards_pushing_hand:" => "๐Ÿซธ", "\\:ring:" => "๐Ÿ’", + "\\:ring_buoy:" => "๐Ÿ›Ÿ", "\\:ringed_planet:" => "๐Ÿช", "\\:robot_face:" => "๐Ÿค–", "\\:rock:" => "๐Ÿชจ", @@ -937,6 +988,7 @@ const emoji_symbols = Dict( "\\:sagittarius:" => "โ™", "\\:sake:" => "๐Ÿถ", "\\:salt:" => "๐Ÿง‚", + "\\:saluting_face:" => "๐Ÿซก", "\\:sandal:" => "๐Ÿ‘ก", "\\:sandwich:" => "๐Ÿฅช", "\\:santa:" => "๐ŸŽ…", @@ -964,6 +1016,7 @@ const emoji_symbols = Dict( "\\:seedling:" => "๐ŸŒฑ", "\\:selfie:" => "๐Ÿคณ", "\\:sewing_needle:" => "๐Ÿชก", + "\\:shaking_face:" => "๐Ÿซจ", "\\:shallow_pan_of_food:" => "๐Ÿฅ˜", "\\:shark:" => "๐Ÿฆˆ", "\\:shaved_ice:" => "๐Ÿง", @@ -1124,6 +1177,7 @@ const emoji_symbols = Dict( "\\:triangular_ruler:" => "๐Ÿ“", "\\:trident:" => "๐Ÿ”ฑ", "\\:triumph:" => "๐Ÿ˜ค", + "\\:troll:" => "๐ŸงŒ", "\\:trolleybus:" => "๐ŸšŽ", "\\:trophy:" => "๐Ÿ†", "\\:tropical_drink:" => "๐Ÿน", @@ -1188,6 +1242,7 @@ const emoji_symbols = Dict( "\\:wedding:" => "๐Ÿ’’", "\\:whale2:" => "๐Ÿ‹", "\\:whale:" => "๐Ÿณ", + "\\:wheel:" => "๐Ÿ›ž", "\\:wheelchair:" => "โ™ฟ", "\\:white_check_mark:" => "โœ…", "\\:white_circle:" => "โšช", @@ -1202,7 +1257,9 @@ const emoji_symbols = Dict( "\\:wind_chime:" => "๐ŸŽ", "\\:window:" => "๐ŸชŸ", "\\:wine_glass:" => "๐Ÿท", + "\\:wing:" => "๐Ÿชฝ", "\\:wink:" => "๐Ÿ˜‰", + "\\:wireless:" => "๐Ÿ›œ", "\\:wolf:" => "๐Ÿบ", "\\:woman:" => "๐Ÿ‘ฉ", "\\:womans_clothes:" => "๐Ÿ‘š", @@ -1215,6 +1272,7 @@ const emoji_symbols = Dict( "\\:worried:" => "๐Ÿ˜Ÿ", "\\:wrench:" => "๐Ÿ”ง", "\\:wrestlers:" => "๐Ÿคผ", + "\\:x-ray:" => "๐Ÿฉป", "\\:x:" => "โŒ", "\\:yarn:" => "๐Ÿงถ", "\\:yawning_face:" => "๐Ÿฅฑ", From 718b98843ffae71309456a03603376ce6bbe58a8 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Tue, 2 Apr 2024 11:31:42 +0900 Subject: [PATCH 067/123] documentation followup for "invert linetable representation (#52415)" (#53781) - fix up added documents: eb05b4f2acec6ac0ecbc34547716cc77f6cff719 - ~~set up a specific type to capture the 3-set data of `codelocs`: 6afde4b740960f39f49afbd8a8d138e7df3a4fdf~~ (moved to a separate PR) --- doc/src/devdocs/ast.md | 47 +++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index 09361f37541841..a87929e6ff4d6c 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -696,14 +696,10 @@ A (usually temporary) container for holding lowered source code. Statement-level 32 bits flags for each expression in the function. See the definition of `jl_code_info_t` in julia.h for more details. - * `linetable` - - An array of source location objects - - * `codelocs` + * `debuginfo` - An array of integer indices into the `linetable`, giving the location associated - with each statement. + An object to retrieve source information for each statements, see + [How to interpret line numbers in a `CodeInfo` object](@ref). Optional Fields: @@ -769,7 +765,7 @@ Boolean properties: See the documentation of `Base.@assume_effects` for more details. -How to interpret line numbers in a `CodeInfo` object: +#### How to interpret line numbers in a `CodeInfo` object There are 2 common forms for this data: one used internally that compresses the data somewhat and one used in the compiler. They contain the same basic info, but the compiler version is all mutable while the version used internally is not. @@ -780,7 +776,7 @@ Many consumers may be able to call `Base.IRShow.buildLineInfoNode`, The definitions of each of these are: -``` +```julia struct Core.DebugInfo @noinline def::Union{Method,MethodInstance,Symbol} @@ -801,11 +797,11 @@ end ``` - * `def` : where this DebugInfo was defined (the Method, MethodInstance, or file scope, for example) + * `def` : where this `DebugInfo` was defined (the `Method`, `MethodInstance`, or `Symbol` of file scope, for example) * `linetable` - Another debuginfo that this was derived from, which contains the actual line numbers, + Another `DebugInfo` that this was derived from, which contains the actual line numbers, such that this DebugInfo contains only the indexes into it. This avoids making copies, as well as makes it possible to track how each individual statement transformed from source to optimized, not just the separate line numbers. If `def` is not a Symbol, then @@ -820,27 +816,26 @@ end * `firstline` (when uncompressed to DebugInfoStream) The line number associated with the `begin` statement (or other keyword such as - `function` or `quote`) that delinated where this code definition "starts". + `function` or `quote`) that delineates where this code definition "starts". - * `codelocs` (when uncompressed to DebugInfoStream) + * `codelocs` (when uncompressed to `DebugInfoStream`) A vector of indices, with 3 values for each statement in the IR plus one for the starting point of the block, that describe the stacktrace from that point: 1. the integer index into the `linetable.codelocs` field, giving the original location associated with each statement (including its syntactic edges), or zero indicating no change to the line number from the previously - executed statement (which is not necessarily syntactic or lexical prior). - or - the line number itself if the `linetable` field is `nothing` - 2. the integer index into edges, giving the DebugInfo inlined there (or zero if there - are no edges). - 3. (if entry 2 is non-zero) the integer index into edges[].codelocs, to interpret - recursively for each function in the inlining stack, or zero indicating to use - `edges[].firstline` as the line number. - - Special codes include: - - (zero, zero, *) : no change to the line number or edges from the previous statement + executed statement (which is not necessarily syntactic or lexical prior), + or the line number itself if the `linetable` field is `nothing`. + 2. the integer index into `edges`, giving the `DebugInfo` inlined there, + or zero if there are no edges. + 3. (if entry 2 is non-zero) the integer index into `edges[].codelocs`, + to interpret recursively for each function in the inlining stack, + or zero indicating to use `edges[].firstline` as the line number. + + Special codes include: + - `(zero, zero, *) `: no change to the line number or edges from the previous statement (you may choose to interpret this either syntactically or lexically). The inlining depth also might have changed, though most callers should ignore that. - - (zero, non-zero, *) : no line number, just edges (usually because of macro-expansion into - top-level code) + - `(zero, non-zero, *)` : no line number, just edges (usually because of + macro-expansion into top-level code). From d8d384278d6a706e0dc4602bdae1ec1a08908394 Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 2 Apr 2024 12:25:09 +0200 Subject: [PATCH 068/123] Avoid repeated precompilation when loading from non-relocatable cachefiles (#53905) Fixes https://github.com/JuliaLang/julia/issues/53859#issuecomment-2027352004, which was actually fixed before in https://github.com/JuliaLang/julia/pull/52346, but https://github.com/JuliaLang/julia/pull/52750 undid that fix. This PR does not directly address #53859, because I can not reproduce it atm. --- The `@depot` resolution logic for `include()` files is adjusted as follows: 1. (new behavior) If the cache is not relocatable because of an absolute path, we ignore that path for the depot search. Recompilation will be triggered by `stale_cachefile()` if that absolute path does not exist. Previously this caused any `@depot` tags to be not resolved and so trigger recompilation. 2. (new behavior) If we can't find a depot for a relocatable path, we still replace it with the depot we found from other files. Recompilation will be triggered by `stale_cachefile()` because the resolved path does not exist. 3. (this behavior is kept) We require that relocatable paths all resolve to the same depot. 4. (new behavior) We no longer use the first matching depot for replacement, but instead we explicitly check that all resolve to the same depot. This has two reasons: - We want to scan all source files anyways in order to provide logs for 1. and 2. above, so the check is free. - It is possible that a depot might be missing source files. Assume that we have two depots on `DEPOT_PATH`, `depot_complete` and `depot_incomplete`. If `DEPOT_PATH=["depot_complete","depot_incomplete"]` then no recompilation shall happen, because `depot_complete` will be picked. If `DEPOT_PATH=["depot_incomplete","depot_complete"]` we trigger recompilation and hopefully a meaningful error about missing files is thrown. If we were to just select the first depot we find, then whether recompilation happens would depend on whether the first relocatable file resolves to `depot_complete` or `depot_incomplete`. --- base/loading.jl | 62 +++++++++++++++---- test/.gitignore | 1 + test/Makefile | 2 + test/RelocationTestPkg4/Project.toml | 6 ++ .../src/RelocationTestPkg4.jl | 5 ++ test/relocatedepot.jl | 46 ++++++++++++-- 6 files changed, 106 insertions(+), 16 deletions(-) create mode 100644 test/RelocationTestPkg4/Project.toml create mode 100644 test/RelocationTestPkg4/src/RelocationTestPkg4.jl diff --git a/base/loading.jl b/base/loading.jl index a58d3e7502b74c..882ae3a68a836b 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -3199,7 +3199,7 @@ function parse_cache_header(f::IO, cachefile::AbstractString) includes_srcfiles = CacheHeaderIncludes[] includes_depfiles = CacheHeaderIncludes[] - for (i, inc) in enumerate(includes) + for inc in includes if inc.filename โˆˆ srcfiles push!(includes_srcfiles, inc) else @@ -3207,23 +3207,63 @@ function parse_cache_header(f::IO, cachefile::AbstractString) end end - # determine depot for @depot replacement for include() files and include_dependency() files separately - srcfiles_depot = resolve_depot(first(srcfiles)) - if srcfiles_depot === :no_depot_found - @debug("Unable to resolve @depot tag include() files from cache file $cachefile", srcfiles, _group=:relocatable) - elseif srcfiles_depot === :not_relocatable - @debug("include() files from $cachefile are not relocatable", srcfiles, _group=:relocatable) - else + + # The @depot resolution logic for include() files: + # 1. If the cache is not relocatable because of an absolute path, + # we ignore that path for the depot search. + # Recompilation will be triggered by stale_cachefile() if that absolute path does not exist. + # 2. If we can't find a depot for a relocatable path, + # we still replace it with the depot we found from other files. + # Recompilation will be triggered by stale_cachefile() because the resolved path does not exist. + # 3. We require that relocatable paths all resolve to the same depot. + # 4. We explicitly check that all relocatable paths resolve to the same depot. This has two reasons: + # - We want to scan all source files in order to provide logs for 1. and 2. above. + # - It is possible that a depot might be missing source files. + # Assume that we have two depots on DEPOT_PATH, depot_complete and depot_incomplete. + # If DEPOT_PATH=["depot_complete","depot_incomplete"] then no recompilation shall happen, + # because depot_complete will be picked. + # If DEPOT_PATH=["depot_incomplete","depot_complete"] we trigger recompilation and + # hopefully a meaningful error about missing files is thrown. + # If we were to just select the first depot we find, then whether recompilation happens would + # depend on whether the first relocatable file resolves to depot_complete or depot_incomplete. + srcdepot = nothing + any_not_relocatable = false + any_no_depot_found = false + multiple_depots_found = false + for src in srcfiles + depot = resolve_depot(src) + if depot === :not_relocatable + any_not_relocatable = true + elseif depot === :no_depot_found + any_no_depot_found = true + elseif isnothing(srcdepot) + srcdepot = depot + elseif depot != srcdepot + multiple_depots_found = true + end + end + if any_no_depot_found + @debug("Unable to resolve @depot tag for at least one include() file from cache file $cachefile", srcfiles, _group=:relocatable) + end + if any_not_relocatable + @debug("At least one include() file from $cachefile is not relocatable", srcfiles, _group=:relocatable) + end + if multiple_depots_found + @debug("Some include() files from $cachefile are distributed over multiple depots", srcfiles, _group=:relocatable) + elseif !isnothing(srcdepot) for inc in includes_srcfiles - inc.filename = restore_depot_path(inc.filename, srcfiles_depot) + inc.filename = restore_depot_path(inc.filename, srcdepot) end end + + # unlike include() files, we allow each relocatable include_dependency() file to resolve + # to a separate depot, #52161 for inc in includes_depfiles depot = resolve_depot(inc.filename) if depot === :no_depot_found - @debug("Unable to resolve @depot tag for include_dependency() file $(inc.filename) from cache file $cachefile", srcfiles, _group=:relocatable) + @debug("Unable to resolve @depot tag for include_dependency() file $(inc.filename) from cache file $cachefile", _group=:relocatable) elseif depot === :not_relocatable - @debug("include_dependency() file $(inc.filename) from $cachefile is not relocatable", srcfiles, _group=:relocatable) + @debug("include_dependency() file $(inc.filename) from $cachefile is not relocatable", _group=:relocatable) else inc.filename = restore_depot_path(inc.filename, depot) end diff --git a/test/.gitignore b/test/.gitignore index fc55a0df3a1735..20bf199b87c749 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -4,3 +4,4 @@ /libccalltest.* /relocatedepot /RelocationTestPkg2/src/foo.txt +/RelocationTestPkg*/Manifest.toml diff --git a/test/Makefile b/test/Makefile index 31f8f20615d7af..1b9cb377c943d4 100644 --- a/test/Makefile +++ b/test/Makefile @@ -43,6 +43,7 @@ relocatedepot: @cp -R $(SRCDIR)/RelocationTestPkg1 $(SRCDIR)/relocatedepot @cp -R $(SRCDIR)/RelocationTestPkg2 $(SRCDIR)/relocatedepot @cp -R $(SRCDIR)/RelocationTestPkg3 $(SRCDIR)/relocatedepot + @cp -R $(SRCDIR)/RelocationTestPkg4 $(SRCDIR)/relocatedepot @cd $(SRCDIR) && \ $(call PRINT_JULIA, $(call spawn,RELOCATEDEPOT="" $(JULIA_EXECUTABLE)) --check-bounds=yes --startup-file=no --depwarn=error ./runtests.jl $@) @@ -55,6 +56,7 @@ revise-relocatedepot: revise-% : @cp -R $(SRCDIR)/RelocationTestPkg1 $(SRCDIR)/relocatedepot @cp -R $(SRCDIR)/RelocationTestPkg2 $(SRCDIR)/relocatedepot @cp -R $(SRCDIR)/RelocationTestPkg3 $(SRCDIR)/relocatedepot + @cp -R $(SRCDIR)/RelocationTestPkg4 $(SRCDIR)/relocatedepot @cd $(SRCDIR) && \ $(call PRINT_JULIA, $(call spawn,RELOCATEDEPOT="" $(JULIA_EXECUTABLE)) --check-bounds=yes --startup-file=no --depwarn=error ./runtests.jl --revise $*) diff --git a/test/RelocationTestPkg4/Project.toml b/test/RelocationTestPkg4/Project.toml new file mode 100644 index 00000000000000..8334a684f064e5 --- /dev/null +++ b/test/RelocationTestPkg4/Project.toml @@ -0,0 +1,6 @@ +name = "RelocationTestPkg4" +uuid = "d423d817-d7e9-49ac-b245-9d9d6db0b429" +version = "0.1.0" + +[deps] +RelocationTestPkg1 = "854e1adb-5a97-46bf-a391-1cfe05ac726d" diff --git a/test/RelocationTestPkg4/src/RelocationTestPkg4.jl b/test/RelocationTestPkg4/src/RelocationTestPkg4.jl new file mode 100644 index 00000000000000..d24a51d19a9187 --- /dev/null +++ b/test/RelocationTestPkg4/src/RelocationTestPkg4.jl @@ -0,0 +1,5 @@ +module RelocationTestPkg4 + +greet() = print("Hello World!") + +end # module RelocationTestPkg4 diff --git a/test/relocatedepot.jl b/test/relocatedepot.jl index c9c8bd38a245f8..039d422c35e25d 100644 --- a/test/relocatedepot.jl +++ b/test/relocatedepot.jl @@ -17,10 +17,12 @@ function test_harness(@nospecialize(fn); empty_load_path=true, empty_depot_path= end end -# We test relocation with three dummy pkgs: -# - RelocationTestPkg1 - no include_dependency -# - RelocationTestPkg2 - with include_dependency tracked by `mtime` -# - RelocationTestPkg3 - with include_dependency tracked by content +# We test relocation with these dummy pkgs: +# - RelocationTestPkg1 - pkg with no include_dependency +# - RelocationTestPkg2 - pkg with include_dependency tracked by `mtime` +# - RelocationTestPkg3 - pkg with include_dependency tracked by content +# - RelocationTestPkg4 - pkg with no dependencies; will be compiled such that the pkgimage is +# not relocatable, but no repeated recompilation happens upon loading if !test_relocated_depot @@ -123,6 +125,27 @@ if !test_relocated_depot end end + @testset "precompile RelocationTestPkg4" begin + # test for #52346 and https://github.com/JuliaLang/julia/issues/53859#issuecomment-2027352004 + # If a pkgimage is not relocatable, no repeated precompilation should occur. + pkgname = "RelocationTestPkg4" + test_harness(empty_depot_path=false) do + push!(LOAD_PATH, @__DIR__) + # skip this dir to make the pkgimage not relocatable + filter!(DEPOT_PATH) do depot + !startswith(@__DIR__, depot) + end + pkg = Base.identify_package(pkgname) + cachefiles = Base.find_all_in_cache_path(pkg) + rm.(cachefiles, force=true) + @test Base.isprecompiled(pkg) == false + @test Base.isrelocatable(pkg) == false # because not precompiled + Base.require(pkg) + @test Base.isprecompiled(pkg, ignore_loaded=true) == true + @test Base.isrelocatable(pkg) == false + end + end + @testset "#52161" begin # Take the src files from two pkgs Example1 and Example2, # which are each located in depot1 and depot2, respectively, and @@ -246,7 +269,7 @@ else pkgname = "RelocationTestPkg3" test_harness() do push!(LOAD_PATH, joinpath(@__DIR__, "relocatedepot")) - push!(DEPOT_PATH, joinpath(@__DIR__, "relocatedepot")) + push!(DEPOT_PATH, joinpath(@__DIR__, "relocatedepot")) # required to find src files push!(DEPOT_PATH, joinpath(@__DIR__, "relocatedepot", "julia")) # contains cache file pkg = Base.identify_package(pkgname) @test Base.isprecompiled(pkg) == true @@ -257,4 +280,17 @@ else end end + @testset "load RelocationTestPkg4 from test/relocatedepot" begin + pkgname = "RelocationTestPkg4" + test_harness() do + push!(LOAD_PATH, @__DIR__, "relocatedepot") + push!(DEPOT_PATH, joinpath(@__DIR__, "relocatedepot")) # required to find src files + push!(DEPOT_PATH, joinpath(@__DIR__, "relocatedepot", "julia")) # contains cache file + pkg = Base.identify_package(pkgname) + # precompiled but not relocatable + @test Base.isprecompiled(pkg) == true + @test Base.isrelocatable(pkg) == false + end + end + end From e99627f0d13846de93bc7f11c50e4b5414b1b1e4 Mon Sep 17 00:00:00 2001 From: Nicholas Bauer Date: Tue, 2 Apr 2024 18:04:14 -0400 Subject: [PATCH 069/123] Explicitly call out reverse ranges in `:` and `range` docstring (#53626) --- base/range.jl | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/base/range.jl b/base/range.jl index 4f92b305564cd5..b987e5f50c7f7c 100644 --- a/base/range.jl +++ b/base/range.jl @@ -32,7 +32,7 @@ _colon(::Any, ::Any, start::T, step, stop::T) where {T} = (:)(start, [step], stop) Range operator. `a:b` constructs a range from `a` to `b` with a step size -equal to 1, which produces: +equal to +1, which produces: * a [`UnitRange`](@ref) when `a` and `b` are integers, or * a [`StepRange`](@ref) when `a` and `b` are characters, or @@ -41,6 +41,9 @@ equal to 1, which produces: `a:s:b` is similar but uses a step size of `s` (a [`StepRange`](@ref) or [`StepRangeLen`](@ref)). See also [`range`](@ref) for more control. +To create a descending range, use `reverse(a:b)` or a negative step size, e.g. `b:-1:a`. +Otherwise, when `b < a`, an empty range will be constructed and normalized to `a:a-1`. + The operator `:` is also used in indexing to select whole dimensions, e.g. in `A[:, 1]`. `:` is also used to [`quote`](@ref) code, e.g. `:(x + y) isa Expr` and `:x isa Symbol`. @@ -66,8 +69,12 @@ Mathematically a range is uniquely determined by any three of `start`, `step`, ` Valid invocations of range are: * Call `range` with any three of `start`, `step`, `stop`, `length`. * Call `range` with two of `start`, `stop`, `length`. In this case `step` will be assumed - to be one. If both arguments are Integers, a [`UnitRange`](@ref) will be returned. -* Call `range` with one of `stop` or `length`. `start` and `step` will be assumed to be one. + to be positive one. If both arguments are Integers, a [`UnitRange`](@ref) will be returned. +* Call `range` with one of `stop` or `length`. `start` and `step` will be assumed to be positive one. + +To construct a descending range, specify a negative step size, e.g. `range(5, 1; step = -1)` => [5,4,3,2,1]. Otherwise, +a `stop` value less than the `start` value, with the default `step` of `+1`, constructs an empty range. Empty ranges +are normalized such that the `stop` is one less than the `start`, e.g. `range(5, 1) == 5:4`. See Extended Help for additional details on the returned type. See also [`logrange`](@ref) for logarithmically spaced points. From b70e1aec6b10b9a1d678b24d41d83ada55a70941 Mon Sep 17 00:00:00 2001 From: Paul Annesley Date: Wed, 3 Apr 2024 10:15:04 +1030 Subject: [PATCH 070/123] Buildkite typos in tests/buildkitetestjson.jl etc fixed --- test/buildkitetestjson.jl | 4 ++-- test/runtests.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/buildkitetestjson.jl b/test/buildkitetestjson.jl index 8410913e48ef22..dc3b13ebf4e89c 100644 --- a/test/buildkitetestjson.jl +++ b/test/buildkitetestjson.jl @@ -1,9 +1,9 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -# Convert test(set) results to a Buildkit-compatible JSON representation. +# Convert test(set) results to a Buildkite-compatible JSON representation. # Based on . -module BuildKiteTestJSON +module BuildkiteTestJSON using Test using Dates diff --git a/test/runtests.jl b/test/runtests.jl index 7c6fa8480d98e0..c46472ac93fa85 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -11,7 +11,7 @@ include("choosetests.jl") include("testenv.jl") include("buildkitetestjson.jl") -using .BuildKiteTestJSON +using .BuildkiteTestJSON (; tests, net_on, exit_on_error, use_revise, seed) = choosetests(ARGS) tests = unique(tests) From 1256e3eb4f497c21fd40aef44feb6f41f893896e Mon Sep 17 00:00:00 2001 From: Paul Annesley Date: Tue, 12 Mar 2024 22:45:02 +1030 Subject: [PATCH 071/123] Buildkite Test Analytics: fix failure_expanded The `failure_expanded` attribute of a test result is an _array_ of objects, not a single object. I believe this is to support the possibility of multiple failure reasons in a single test case, although I'm not sure if that's used anywhere. https://buildkite.com/docs/test-analytics/importing-json#json-test-results-data-reference-test-result-objects --- test/buildkitetestjson.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/buildkitetestjson.jl b/test/buildkitetestjson.jl index dc3b13ebf4e89c..49c47e0d8f1511 100644 --- a/test/buildkitetestjson.jl +++ b/test/buildkitetestjson.jl @@ -105,9 +105,9 @@ function add_failure_info!(data::Dict{String, Any}, result::Test.Result) data["failure_reason"] = if result.test_type === :test_error if occursin("\nStacktrace:\n", result.backtrace) err, trace = split(result.backtrace, "\nStacktrace:\n", limit=2) - data["failure_expanded"] = Dict{String, Any}( - "expanded" => split(err, '\n'), - "backtrace" => split(trace, '\n')) + data["failure_expanded"] = + [Dict{String,Any}("expanded" => split(err, '\n'), + "backtrace" => split(trace, '\n'))] end "Exception (unexpectedly) thrown during test" elseif result.test_type === :test_nonbool From 94f887bb5cdeb61a648b05bf8bfe5d37ecbe00a4 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 2 Apr 2024 21:00:42 -0500 Subject: [PATCH 072/123] note that REPL doesn't show "nothing" values (#53930) It seemed worth documenting that display of `nothing` is suppressed by the REPL (and similar environments, e.g. IJulia). --- base/docs/basedocs.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index 447cbe000faa6d..cc2d32f6b3debb 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -1521,6 +1521,8 @@ Nothing The singleton instance of type [`Nothing`](@ref), used by convention when there is no value to return (as in a C `void` function) or when a variable or field holds no value. +A return value of `nothing` is not displayed by the REPL and similar interactive environments. + See also: [`isnothing`](@ref), [`something`](@ref), [`missing`](@ref). """ nothing From 854170a092bc800090357e89d81fc2e672269551 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Wed, 3 Apr 2024 13:16:03 +0900 Subject: [PATCH 073/123] minor followups on the linetable changes (#53921) - remove unnecessary `Core.` accessors to `DebugInfo` within `Core.Compiler` - improve the type of `DebugInfoStream`'s `edges` field --- base/compiler/ssair/ir.jl | 25 +++++++++++++------------ base/compiler/ssair/show.jl | 6 +++--- base/compiler/typeinfer.jl | 4 ++-- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/base/compiler/ssair/ir.jl b/base/compiler/ssair/ir.jl index c23f89e01f6646..222ec91f7c01ac 100644 --- a/base/compiler/ssair/ir.jl +++ b/base/compiler/ssair/ir.jl @@ -177,40 +177,41 @@ end # mutable version of the compressed DebugInfo mutable struct DebugInfoStream def::Union{MethodInstance,Symbol,Nothing} - linetable::Union{Nothing,Core.DebugInfo} - edges::Vector{Any} # Vector{Core.DebugInfo} + linetable::Union{Nothing,DebugInfo} + edges::Vector{DebugInfo} firstline::Int32 # the starting line for this block (specified by having an index of 0) codelocs::Vector{Int32} # for each statement: # index into linetable (if defined), else a line number (in the file represented by def) # then index into edges # then index into edges[linetable] function DebugInfoStream(codelocs::Vector{Int32}) - return new(nothing, nothing, [], 0, codelocs) + return new(nothing, nothing, DebugInfo[], 0, codelocs) end - #DebugInfoStream(def::Union{MethodInstance,Nothing}, di::DebugInfo, nstmts::Int) = - # if debuginfo_file1(di.def) === debuginfo_file1(di.def) - # new(def, di.linetable, Core.svec(di.edges...), getdebugidx(di, 0), - # ccall(:jl_uncompress_codelocs, Any, (Any, Int), di.codelocs, nstmts)::Vector{Int32}) - # else + # DebugInfoStream(def::Union{MethodInstance,Nothing}, di::DebugInfo, nstmts::Int) = + # if debuginfo_file1(di.def) === debuginfo_file1(di.def) + # new(def, di.linetable, Core.svec(di.edges...), getdebugidx(di, 0), + # ccall(:jl_uncompress_codelocs, Any, (Any, Int), di.codelocs, nstmts)::Vector{Int32}) + # else function DebugInfoStream(def::Union{MethodInstance,Nothing}, di::DebugInfo, nstmts::Int) codelocs = zeros(Int32, nstmts * 3) for i = 1:nstmts codelocs[3i - 2] = i end - return new(def, di, Vector{Any}(), 0, codelocs) + return new(def, di, DebugInfo[], 0, codelocs) end global copy(di::DebugInfoStream) = new(di.def, di.linetable, di.edges, di.firstline, di.codelocs) end Core.DebugInfo(di::DebugInfoStream, nstmts::Int) = - Core.DebugInfo(something(di.def), di.linetable, Core.svec(di.edges...), + DebugInfo(something(di.def), di.linetable, Core.svec(di.edges...), ccall(:jl_compress_codelocs, Any, (Int32, Any, Int), di.firstline, di.codelocs, nstmts)::String) -getdebugidx(debuginfo::Core.DebugInfo, pc::Int) = ccall(:jl_uncompress1_codeloc, NTuple{3,Int32}, (Any, Int), debuginfo.codelocs, pc) +getdebugidx(debuginfo::DebugInfo, pc::Int) = + ccall(:jl_uncompress1_codeloc, NTuple{3,Int32}, (Any, Int), debuginfo.codelocs, pc) function getdebugidx(debuginfo::DebugInfoStream, pc::Int) if 3 <= 3pc <= length(debuginfo.codelocs) - return (debuginfo.codelocs[3pc - 2], debuginfo.codelocs[3pc - 1], debuginfo.codelocs[3pc - 0]) + return (debuginfo.codelocs[3pc-2], debuginfo.codelocs[3pc-1], debuginfo.codelocs[3pc-0]) elseif pc == 0 return (Int32(debuginfo.firstline), Int32(0), Int32(0)) else diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index 2c0385a8088014..cfcd2ce8f3d2bd 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -327,7 +327,7 @@ Base.show(io::IO, code::Union{IRCode, IncrementalCompact}) = show_ir(io, code) lineinfo_disabled(io::IO, linestart::String, idx::Int) = "" # utility function to extract the file name from a DebugInfo object -function debuginfo_file1(debuginfo::Union{Core.DebugInfo,DebugInfoStream}) +function debuginfo_file1(debuginfo::Union{DebugInfo,DebugInfoStream}) def = debuginfo.def if def isa MethodInstance def = def.def @@ -342,7 +342,7 @@ function debuginfo_file1(debuginfo::Union{Core.DebugInfo,DebugInfoStream}) end # utility function to extract the first line number and file of a block of code -function debuginfo_firstline(debuginfo::Union{Core.DebugInfo,DebugInfoStream}) +function debuginfo_firstline(debuginfo::Union{DebugInfo,DebugInfoStream}) linetable = debuginfo.linetable while linetable != nothing debuginfo = linetable @@ -375,7 +375,7 @@ function append_scopes!(scopes::Vector{LineInfoNode}, pc::Int, debuginfo, @nospe line < 0 && (doupdate = false; line = 0) # broken debug info push!(scopes, LineInfoNode(def, debuginfo_file1(debuginfo), Int32(line))) else - doupdate = append_scopes!(scopes, line, debuginfo.linetable::Core.DebugInfo, def) && doupdate + doupdate = append_scopes!(scopes, line, debuginfo.linetable::DebugInfo, def) && doupdate end inl_to == 0 && return doupdate def = :var"macro expansion" diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index b77d2e83d57803..02ec583316de0f 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -328,7 +328,7 @@ function CodeInstance(interp::AbstractInterpreter, result::InferenceResult; end # n.b. relocatability = (isa(inferred_result, String) && inferred_result[end]) || inferred_result === nothing if !@isdefined edges - edges = Core.DebugInfo(result.linfo) + edges = DebugInfo(result.linfo) end return CodeInstance(result.linfo, owner, widenconst(result_type), widenconst(result.exc_result), rettype_const, inferred_result, @@ -923,7 +923,7 @@ function codeinfo_for_const(interp::AbstractInterpreter, mi::MethodInstance, @no tree.slotnames = ccall(:jl_uncompress_argnames, Vector{Symbol}, (Any,), method.slot_syms) tree.slotflags = fill(0x00, nargs) tree.ssavaluetypes = 1 - tree.debuginfo = Core.DebugInfo(mi) + tree.debuginfo = DebugInfo(mi) tree.ssaflags = UInt32[0] set_inlineable!(tree, true) tree.parent = mi From a69aa30478ac9beda594235ff6f2e39549fdb752 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 3 Apr 2024 05:24:45 -0400 Subject: [PATCH 074/123] oc: code_typed support for optimized opaque closures (#53929) Reflection version of #53878. --------- Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Co-authored-by: Shuhei Kadowaki --- base/reflection.jl | 38 ++++++++++++++++++------- stdlib/InteractiveUtils/src/codeview.jl | 6 ++-- test/opaque_closure.jl | 9 +++++- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index 63909b4159877b..2df713a531faef 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1584,7 +1584,7 @@ julia> code_typed(+, (Float64, Float64)) """ function code_typed(@nospecialize(f), @nospecialize(types=default_tt(f)); kwargs...) if isa(f, Core.OpaqueClosure) - return code_typed_opaque_closure(f; kwargs...) + return code_typed_opaque_closure(f, types; kwargs...) end tt = signature_type(f, types) return code_typed_by_type(tt; kwargs...) @@ -1639,20 +1639,38 @@ function code_typed_by_type(@nospecialize(tt::Type); return asts end -function get_oc_code_rt(@nospecialize(oc::Core.OpaqueClosure)) - ccall(:jl_is_in_pure_context, Bool, ()) && error("code reflection cannot be used from generated functions") +function get_oc_code_rt(oc::Core.OpaqueClosure, types, optimize::Bool) + @nospecialize oc types + ccall(:jl_is_in_pure_context, Bool, ()) && + error("code reflection cannot be used from generated functions") m = oc.source if isa(m, Method) - code = _uncompressed_ir(m) - return Pair{CodeInfo,Any}(code, typeof(oc).parameters[2]) + if isdefined(m, :source) + if optimize + tt = Tuple{typeof(oc.captures), to_tuple_type(types).parameters...} + mi = Core.Compiler.specialize_method(m, tt, Core.svec()) + interp = Core.Compiler.NativeInterpreter(m.primary_world) + return Core.Compiler.typeinf_code(interp, mi, optimize) + else + code = _uncompressed_ir(m) + return Pair{CodeInfo,Any}(code, typeof(oc).parameters[2]) + end + else + # OC constructed from optimized IR + codeinst = m.specializations.cache + return Pair{CodeInfo, Any}(codeinst.inferred, codeinst.rettype) + end else error("encountered invalid Core.OpaqueClosure object") end end -function code_typed_opaque_closure(@nospecialize(oc::Core.OpaqueClosure); - debuginfo::Symbol=:default, _...) - (code, rt) = get_oc_code_rt(oc) +function code_typed_opaque_closure(oc::Core.OpaqueClosure, types; + debuginfo::Symbol=:default, + optimize::Bool=true, + _...) + @nospecialize oc types + (code, rt) = get_oc_code_rt(oc, types, optimize) debuginfo === :none && remove_linenums!(code) return Any[Pair{CodeInfo,Any}(code, rt)] end @@ -1807,7 +1825,7 @@ function return_types(@nospecialize(f), @nospecialize(types=default_tt(f)); interp::Core.Compiler.AbstractInterpreter=Core.Compiler.NativeInterpreter(world)) check_generated_context(world) if isa(f, Core.OpaqueClosure) - _, rt = only(code_typed_opaque_closure(f)) + _, rt = only(code_typed_opaque_closure(f, types)) return Any[rt] end if isa(f, Core.Builtin) @@ -1876,7 +1894,7 @@ function infer_return_type(@nospecialize(f), @nospecialize(types=default_tt(f)); interp::Core.Compiler.AbstractInterpreter=Core.Compiler.NativeInterpreter(world)) check_generated_context(world) if isa(f, Core.OpaqueClosure) - return last(only(code_typed_opaque_closure(f))) + return last(only(code_typed_opaque_closure(f, types))) end if isa(f, Core.Builtin) return _builtin_return_type(interp, f, types) diff --git a/stdlib/InteractiveUtils/src/codeview.jl b/stdlib/InteractiveUtils/src/codeview.jl index d03e2b27a22865..b242dea8e006e4 100644 --- a/stdlib/InteractiveUtils/src/codeview.jl +++ b/stdlib/InteractiveUtils/src/codeview.jl @@ -143,7 +143,7 @@ See the [`@code_warntype`](@ref man-code-warntype) section in the Performance Ti See also: [`@code_warntype`](@ref), [`code_typed`](@ref), [`code_lowered`](@ref), [`code_llvm`](@ref), [`code_native`](@ref). """ -function code_warntype(io::IO, @nospecialize(f), @nospecialize(t=Base.default_tt(f)); +function code_warntype(io::IO, @nospecialize(f), @nospecialize(tt=Base.default_tt(f)); world=Base.get_world_counter(), interp::Core.Compiler.AbstractInterpreter=Core.Compiler.NativeInterpreter(world), debuginfo::Symbol=:default, optimize::Bool=false, kwargs...) @@ -154,10 +154,10 @@ function code_warntype(io::IO, @nospecialize(f), @nospecialize(t=Base.default_tt nargs::Int = 0 if isa(f, Core.OpaqueClosure) isa(f.source, Method) && (nargs = f.nargs) - print_warntype_codeinfo(io, Base.code_typed_opaque_closure(f)[1]..., nargs; lineprinter) + print_warntype_codeinfo(io, Base.code_typed_opaque_closure(f, tt)[1]..., nargs; lineprinter) return nothing end - matches = Base._methods_by_ftype(Base.signature_type(f, t), #=lim=#-1, world)::Vector + matches = Base._methods_by_ftype(Base.signature_type(f, tt), #=lim=#-1, world)::Vector for match in matches match = match::Core.MethodMatch (src, rettype) = Core.Compiler.typeinf_code(interp, match, optimize) diff --git a/test/opaque_closure.jl b/test/opaque_closure.jl index cb7576ee656be6..490ff282b7a530 100644 --- a/test/opaque_closure.jl +++ b/test/opaque_closure.jl @@ -239,7 +239,13 @@ let foo::Int = 42 end let oc = @opaque a->sin(a) - @test length(code_typed(oc, (Int,))) == 1 + let opt = code_typed(oc, (Int,)) + @test length(opt) == 1 + @test opt[1][2] === Float64 + end + let unopt = code_typed(oc, (Int,); optimize=false) + @test length(unopt) == 1 + end end # constructing an opaque closure from IRCode @@ -257,6 +263,7 @@ end let ir = first(only(Base.code_ircode(sin, (Int,)))) @test OpaqueClosure(ir)(42) == sin(42) @test OpaqueClosure(ir)(42) == sin(42) # the `OpaqueClosure(::IRCode)` constructor should be non-destructive + @test length(code_typed(OpaqueClosure(ir))) == 1 ir = first(only(Base.code_ircode(sin, (Float64,)))) @test OpaqueClosure(ir)(42.) == sin(42.) @test OpaqueClosure(ir)(42.) == sin(42.) # the `OpaqueClosure(::IRCode)` constructor should be non-destructive From c74914776e8db17f129a858bd15b784aa765a4bf Mon Sep 17 00:00:00 2001 From: crazehang <165746307+crazehang@users.noreply.github.com> Date: Wed, 3 Apr 2024 22:51:59 +0800 Subject: [PATCH 075/123] fix typo in comment (#53936) Signed-off-by: crazehang --- src/subtype.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/subtype.c b/src/subtype.c index 61946968beba6c..f9bdf9d3982d82 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -2853,7 +2853,7 @@ static jl_value_t *finish_unionall(jl_value_t *res JL_MAYBE_UNROOTED, jl_varbind if (!varval && (vb->lb != vb->var->lb || vb->ub != vb->var->ub)) newvar = jl_new_typevar(vb->var->name, vb->lb, vb->ub); - // flatten all innervar into a (revered) list + // flatten all innervar into a (reversed) list size_t icount = 0; if (vb->innervars) icount += jl_array_nrows(vb->innervars); From d7dc9a8cc8f2aebf04d5cecc8625be250169644b Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Wed, 3 Apr 2024 17:06:13 +0200 Subject: [PATCH 076/123] make @fastmath mirror how lowering applies literal_pow (#53819) The expressions `a^x` and `@fastmath a^x` are now producing equivalent results (apart from floating point accuracy) in the case of literal integer `x`. The logic in the `fastmath` macro, trying to mimic the behaviour of the compiler is fixed. Fixes #53817 --------- Co-authored-by: Oscar Smith --- base/fastmath.jl | 13 ++++++++++--- test/fastmath.jl | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/base/fastmath.jl b/base/fastmath.jl index a34a4ca66e06bc..28a7852640ba93 100644 --- a/base/fastmath.jl +++ b/base/fastmath.jl @@ -101,9 +101,12 @@ const rewrite_op = function make_fastmath(expr::Expr) if expr.head === :quote return expr - elseif expr.head === :call && expr.args[1] === :^ && expr.args[3] isa Integer - # mimic Julia's literal_pow lowering of literal integer powers - return Expr(:call, :(Base.FastMath.pow_fast), make_fastmath(expr.args[2]), Val{expr.args[3]}()) + elseif expr.head === :call && expr.args[1] === :^ + ea = expr.args + if length(ea) >= 3 && isa(ea[3], Int) + # mimic Julia's literal_pow lowering of literal integer powers + return Expr(:call, :(Base.FastMath.pow_fast), make_fastmath(ea[2]), Val(ea[3])) + end end op = get(rewrite_op, expr.head, :nothing) if op !== :nothing @@ -364,6 +367,10 @@ for f in (:^, :atan, :hypot, :log) # fall-back implementation that applies after promotion $f_fast(x::T, y::T) where {T<:Number} = $f(x, y) end + # Issue 53886 - avoid promotion of Int128 etc to be consistent with non-fastmath + if f === :^ + @eval $f_fast(x::Number, y::Integer) = $f(x, y) + end end # Reductions diff --git a/test/fastmath.jl b/test/fastmath.jl index 34744f325ad7fe..120c0ece685bbd 100644 --- a/test/fastmath.jl +++ b/test/fastmath.jl @@ -256,6 +256,22 @@ end @testset "literal powers" begin @test @fastmath(2^-2) == @fastmath(2.0^-2) == 0.25 + # Issue #53817 + # Note that exponent -2^63 fails testing because of issue #53881 + # Therefore we test with -(2^63-1). For Int == Int32 there is an analogue restriction. + # See also PR #53860. + if Int == Int64 + @test @fastmath(2^-9223372036854775807) === 0.0 + @test_throws DomainError @fastmath(2^-9223372036854775809) + @test @fastmath(1^-9223372036854775807) isa Float64 + @test @fastmath(1^-9223372036854775809) isa Int + elseif Int == Int32 + @test @fastmath(2^-2147483647) === 0.0 + @test_throws DomainError @fastmath(2^-2147483649) + @test @fastmath(1^-2147483647) isa Float64 + @test @fastmath(1^-2147483649) isa Int + end + @test_throws MethodError @fastmath(^(2)) end @testset "sincos fall-backs" begin From 12c93910344d34d65222f7c52932b592d74299f2 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 3 Apr 2024 21:51:04 +0200 Subject: [PATCH 077/123] =?UTF-8?q?=E2=80=9CFix=E2=80=9D=20#53451=20--=20a?= =?UTF-8?q?llow=20zero-row=20QR=20factorization=20bypassing=20LAPACK=20(#5?= =?UTF-8?q?3578)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stdlib/LinearAlgebra/src/lapack.jl | 4 ++-- stdlib/LinearAlgebra/test/qr.jl | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/lapack.jl b/stdlib/LinearAlgebra/src/lapack.jl index 02dfa0079038b9..875ed3ed4e3da0 100644 --- a/stdlib/LinearAlgebra/src/lapack.jl +++ b/stdlib/LinearAlgebra/src/lapack.jl @@ -470,7 +470,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty end lda = max(1, stride(A,2)) work = Vector{$elty}(undef, nb*n) - if n > 0 + if minmn > 0 info = Ref{BlasInt}() ccall((@blasfunc($geqrt), libblastrampoline), Cvoid, (Ref{BlasInt}, Ref{BlasInt}, Ref{BlasInt}, Ptr{$elty}, @@ -496,7 +496,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty if p != n || q != n throw(DimensionMismatch("block reflector T has dimensions ($p,$q), but should have dimensions ($n,$n)")) end - if n > 0 + if n > 0 # this implies `m > 0` because of `m >= n` info = Ref{BlasInt}() ccall((@blasfunc($geqrt3), libblastrampoline), Cvoid, (Ref{BlasInt}, Ref{BlasInt}, Ptr{$elty}, Ref{BlasInt}, diff --git a/stdlib/LinearAlgebra/test/qr.jl b/stdlib/LinearAlgebra/test/qr.jl index 184971da304f73..e339706598a8ae 100644 --- a/stdlib/LinearAlgebra/test/qr.jl +++ b/stdlib/LinearAlgebra/test/qr.jl @@ -504,4 +504,28 @@ end @test x โ‰ˆ xf end +@testset "issue #53451" begin + # in the issue it was noted that QR factorizations of zero-column matrices + # were possible, but zero row-matrices errored, because LAPACK does not + # accept these empty matrices. now, the `geqrt!` call should be forwarded only + # if both matrix dimensions are positive. + + for dimA in (0, 1, 2, 4) + for F in (Float32, Float64, ComplexF32, ComplexF64, BigFloat) + # this should have worked before, Q is square, and R is 0 ร— 0: + A_zero_cols = rand(F, dimA, 0) + qr_zero_cols = qr(A_zero_cols) + @test size(qr_zero_cols.Q) ==โ€ฏ(dimA, dimA) + @test size(qr_zero_cols.R) == (0, 0) + @test qr_zero_cols.Q == LinearAlgebra.I(dimA) + + # this should work now, Q is 0 ร— 0, and R has `dimA` columns: + A_zero_rows = rand(F, 0, dimA) + qr_zero_rows = qr(A_zero_rows) + @test size(qr_zero_rows.Q) == (0, 0) + @test size(qr_zero_rows.R) == (0, dimA) + end + end +end + end # module TestQR From 286e3393fe5102f9f4f1578b3bae863e72f85cbd Mon Sep 17 00:00:00 2001 From: Klaus Crusius Date: Wed, 3 Apr 2024 23:14:17 +0200 Subject: [PATCH 078/123] fix macros `@which`, `@edit`, `@functionloc`, `@less` for `literal_pow` case. (#53713) The macros `@which`, `@edit`, `@functionloc`, `@less` from `InteractiveUtils`, if applied to the case of literal powers, like `a^12` or `2^-1` used to direct the user to function `^`, while the compiler generates code for `Base.literal_pow`. Now the user is shown the code the compiler generates. Fixes #53691 Fixes #43337 Fixes #21014 Co-authored-by: Matt Bauman --- stdlib/InteractiveUtils/src/macros.jl | 5 ++++ stdlib/InteractiveUtils/test/runtests.jl | 38 +++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/stdlib/InteractiveUtils/src/macros.jl b/stdlib/InteractiveUtils/src/macros.jl index 939098464e1480..bb56c47b4f9ca8 100644 --- a/stdlib/InteractiveUtils/src/macros.jl +++ b/stdlib/InteractiveUtils/src/macros.jl @@ -106,6 +106,11 @@ function gen_call_with_extracted_types(__module__, fcn, ex0, kws=Expr[]) $(kws...)) end elseif ex0.head === :call + if ex0.args[1] === :^ && length(ex0.args) >= 3 && isa(ex0.args[3], Int) + return Expr(:call, fcn, :(Base.literal_pow), + Expr(:call, typesof, esc(ex0.args[1]), esc(ex0.args[2]), + esc(Val(ex0.args[3])))) + end return Expr(:call, fcn, esc(ex0.args[1]), Expr(:call, typesof, map(esc, ex0.args[2:end])...), kws...) diff --git a/stdlib/InteractiveUtils/test/runtests.jl b/stdlib/InteractiveUtils/test/runtests.jl index ef1cd6e230818d..22789be2c54952 100644 --- a/stdlib/InteractiveUtils/test/runtests.jl +++ b/stdlib/InteractiveUtils/test/runtests.jl @@ -279,6 +279,43 @@ let x..y = 0 @test (@which 1..2).name === :.. end +# issue #53691 +let a = -1 + @test (@which 2^a).name === :^ + @test (@which 2^0x1).name === :^ +end + +let w = Vector{Any}(undef, 9) + @testset "@which x^literal" begin + w[1] = @which 2^0 + w[2] = @which 2^1 + w[3] = @which 2^2 + w[4] = @which 2^3 + w[5] = @which 2^-1 + w[6] = @which 2^-2 + w[7] = @which 2^10 + w[8] = @which big(2.0)^1 + w[9] = @which big(2.0)^-1 + @test all(getproperty.(w, :name) .=== :literal_pow) + @test length(Set(w)) == length(w) # all methods distinct + end +end + +# PR 53713 +if Int === Int64 + # literal_pow only for exponents x: -2^63 <= x < 2^63 #53860 (all Int) + @test (@which 2^-9223372036854775809).name === :^ + @test (@which 2^-9223372036854775808).name === :literal_pow + @test (@which 2^9223372036854775807).name === :literal_pow + @test (@which 2^9223372036854775808).name === :^ +elseif Int === Int32 + # literal_pow only for exponents x: -2^31 <= x < 2^31 #53860 (all Int) + @test (@which 2^-2147483649).name === :^ + @test (@which 2^-2147483648).name === :literal_pow + @test (@which 2^2147483647).name === :literal_pow + @test (@which 2^2147483648).name === :^ +end + # issue #13464 try @which x = 1 @@ -286,7 +323,6 @@ try catch err13464 @test startswith(err13464.msg, "expression is not a function call") end - module MacroTest export @macrotest macro macrotest(x::Int, y::Symbol) end From 19919b70d342250c69b59e006d2b1e1dd704c06a Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 4 Apr 2024 08:26:24 +0530 Subject: [PATCH 079/123] Use `copyto!` in converting `Diagonal`/`Bidiagonal`/`Tridiagonal` to `Matrix` (#53912) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this, we may convert a structured matrix to `Matrix` even if its `eltype` doesn't support `zero(T)`, as long as we may index into the matrix and the elements have `zero` defined for themselves. This makes the following work: ```julia julia> D = Diagonal(fill(Diagonal([1,3]), 2)) 2ร—2 Diagonal{Diagonal{Int64, Vector{Int64}}, Vector{Diagonal{Int64, Vector{Int64}}}}: [1 0; 0 3] โ‹… โ‹… [1 0; 0 3] julia> Matrix{eltype(D)}(D) 2ร—2 Matrix{Diagonal{Int64, Vector{Int64}}}: [1 0; 0 3] [0 0; 0 0] [0 0; 0 0] [1 0; 0 3] ``` We also may materialize partly initialized matrices: ```julia julia> D = Diagonal(Vector{BigInt}(undef, 2)) 2ร—2 Diagonal{BigInt, Vector{BigInt}}: #undef โ‹… โ‹… #undef julia> Matrix{eltype(D)}(D) 2ร—2 Matrix{BigInt}: #undef 0 0 #undef ``` The performance seems identical for numeric matrices. --- stdlib/LinearAlgebra/src/bidiag.jl | 19 ++++++--------- stdlib/LinearAlgebra/src/diagonal.jl | 11 +++++---- stdlib/LinearAlgebra/src/tridiag.jl | 33 +++++++++++++++------------ stdlib/LinearAlgebra/test/bidiag.jl | 13 +++++++++++ stdlib/LinearAlgebra/test/diagonal.jl | 13 +++++++++++ stdlib/LinearAlgebra/test/special.jl | 2 ++ stdlib/LinearAlgebra/test/tridiag.jl | 8 +++++++ 7 files changed, 67 insertions(+), 32 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 00c972f7f990b0..b805d0ca309b9e 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -195,19 +195,14 @@ end #Converting from Bidiagonal to dense Matrix function Matrix{T}(A::Bidiagonal) where T - n = size(A, 1) - B = Matrix{T}(undef, n, n) - n == 0 && return B - n > 1 && fill!(B, zero(T)) - @inbounds for i = 1:n - 1 - B[i,i] = A.dv[i] - if A.uplo == 'U' - B[i,i+1] = A.ev[i] - else - B[i+1,i] = A.ev[i] - end + B = Matrix{T}(undef, size(A)) + if haszero(T) # optimized path for types with zero(T) defined + size(B,1) > 1 && fill!(B, zero(T)) + copyto!(view(B, diagind(B)), A.dv) + copyto!(view(B, diagind(B, A.uplo == 'U' ? 1 : -1)), A.ev) + else + copyto!(B, A) end - B[n,n] = A.dv[n] return B end Matrix(A::Bidiagonal{T}) where {T} = Matrix{promote_type(T, typeof(zero(T)))}(A) diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index cd93a771c30adb..8cee4a91d4696e 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -116,11 +116,12 @@ AbstractMatrix{T}(D::Diagonal{T}) where {T} = copy(D) Matrix(D::Diagonal{T}) where {T} = Matrix{promote_type(T, typeof(zero(T)))}(D) Array(D::Diagonal{T}) where {T} = Matrix(D) function Matrix{T}(D::Diagonal) where {T} - n = size(D, 1) - B = Matrix{T}(undef, n, n) - n > 1 && fill!(B, zero(T)) - @inbounds for i in 1:n - B[i,i] = D.diag[i] + B = Matrix{T}(undef, size(D)) + if haszero(T) # optimized path for types with zero(T) defined + size(B,1) > 1 && fill!(B, zero(T)) + copyto!(view(B, diagind(B)), D.diag) + else + copyto!(B, D) end return B end diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index 07c2fe410769dc..90142dd941f28d 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -135,13 +135,17 @@ function Matrix{T}(M::SymTridiagonal) where T n = size(M, 1) Mf = Matrix{T}(undef, n, n) n == 0 && return Mf - n > 2 && fill!(Mf, zero(T)) - @inbounds for i = 1:n-1 - Mf[i,i] = symmetric(M.dv[i], :U) - Mf[i+1,i] = transpose(M.ev[i]) - Mf[i,i+1] = M.ev[i] + if haszero(T) # optimized path for types with zero(T) defined + n > 2 && fill!(Mf, zero(T)) + @inbounds for i = 1:n-1 + Mf[i,i] = symmetric(M.dv[i], :U) + Mf[i+1,i] = transpose(M.ev[i]) + Mf[i,i+1] = M.ev[i] + end + Mf[n,n] = symmetric(M.dv[n], :U) + else + copyto!(Mf, M) end - Mf[n,n] = symmetric(M.dv[n], :U) return Mf end Matrix(M::SymTridiagonal{T}) where {T} = Matrix{promote_type(T, typeof(zero(T)))}(M) @@ -586,15 +590,14 @@ axes(M::Tridiagonal) = (ax = axes(M.d,1); (ax, ax)) function Matrix{T}(M::Tridiagonal) where {T} A = Matrix{T}(undef, size(M)) - n = length(M.d) - n == 0 && return A - n > 2 && fill!(A, zero(T)) - for i in 1:n-1 - A[i,i] = M.d[i] - A[i+1,i] = M.dl[i] - A[i,i+1] = M.du[i] - end - A[n,n] = M.d[n] + if haszero(T) # optimized path for types with zero(T) defined + size(A,1) > 2 && fill!(A, zero(T)) + copyto!(view(A, diagind(A)), M.d) + copyto!(view(A, diagind(A,1)), M.du) + copyto!(view(A, diagind(A,-1)), M.dl) + else + copyto!(A, M) + end A end Matrix(M::Tridiagonal{T}) where {T} = Matrix{promote_type(T, typeof(zero(T)))}(M) diff --git a/stdlib/LinearAlgebra/test/bidiag.jl b/stdlib/LinearAlgebra/test/bidiag.jl index 8d48c42a7f7ea0..f9c4f09c474fe2 100644 --- a/stdlib/LinearAlgebra/test/bidiag.jl +++ b/stdlib/LinearAlgebra/test/bidiag.jl @@ -884,4 +884,17 @@ end @test mul!(C1, B, sv, 1, 2) == mul!(C2, B, v, 1 ,2) end +@testset "Matrix conversion for non-numeric and undef" begin + B = Bidiagonal(Vector{BigInt}(undef, 4), fill(big(3), 3), :U) + M = Matrix(B) + B[diagind(B)] .= 4 + M[diagind(M)] .= 4 + @test diag(B) == diag(M) + + B = Bidiagonal(fill(Diagonal([1,3]), 3), fill(Diagonal([1,3]), 2), :U) + M = Matrix{eltype(B)}(B) + @test M isa Matrix{eltype(B)} + @test M == B +end + end # module TestBidiagonal diff --git a/stdlib/LinearAlgebra/test/diagonal.jl b/stdlib/LinearAlgebra/test/diagonal.jl index 3f5cd34a543b64..aa960aaa53193f 100644 --- a/stdlib/LinearAlgebra/test/diagonal.jl +++ b/stdlib/LinearAlgebra/test/diagonal.jl @@ -1292,4 +1292,17 @@ end @test yadj == x' end +@testset "Matrix conversion for non-numeric and undef" begin + D = Diagonal(Vector{BigInt}(undef, 4)) + M = Matrix(D) + D[diagind(D)] .= 4 + M[diagind(M)] .= 4 + @test diag(D) == diag(M) + + D = Diagonal(fill(Diagonal([1,3]), 2)) + M = Matrix{eltype(D)}(D) + @test M isa Matrix{eltype(D)} + @test M == D +end + end # module TestDiagonal diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 7e96af369e3107..6465927db5235a 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -113,6 +113,8 @@ Random.seed!(1) Base.convert(::Type{TypeWithZero}, ::TypeWithoutZero) = TypeWithZero() Base.zero(::Type{<:Union{TypeWithoutZero, TypeWithZero}}) = TypeWithZero() LinearAlgebra.symmetric(::TypeWithoutZero, ::Symbol) = TypeWithoutZero() + LinearAlgebra.symmetric_type(::Type{TypeWithoutZero}) = TypeWithoutZero + Base.copy(A::TypeWithoutZero) = A Base.transpose(::TypeWithoutZero) = TypeWithoutZero() d = fill(TypeWithoutZero(), 3) du = fill(TypeWithoutZero(), 2) diff --git a/stdlib/LinearAlgebra/test/tridiag.jl b/stdlib/LinearAlgebra/test/tridiag.jl index 487f8080767079..4878ab689985c9 100644 --- a/stdlib/LinearAlgebra/test/tridiag.jl +++ b/stdlib/LinearAlgebra/test/tridiag.jl @@ -830,4 +830,12 @@ end @test axes(B) === (ax, ax) end +@testset "Matrix conversion for non-numeric and undef" begin + T = Tridiagonal(fill(big(3), 3), Vector{BigInt}(undef, 4), fill(big(3), 3)) + M = Matrix(T) + T[diagind(T)] .= 4 + M[diagind(M)] .= 4 + @test diag(T) == diag(M) +end + end # module TestTridiagonal From cb4e107e37e11f65459d79ea6c3722970c22c562 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 4 Apr 2024 08:32:36 +0530 Subject: [PATCH 080/123] Add `zero` for `Base.TwicePrecision` (#53787) Since `zero` exists for a `TwicePrecision` type, it makes sense for a method to exist for an instance as well. Fixes #52713, which was a regression from v1.9.1. After this, the following may be displayed without errors: ```julia julia> r = 1.0*(1:5) .+ im 1.0 + 1.0im:Base.TwicePrecision{Float64}(1.0, 0.0):5.0 + 1.0im ``` However, in this case, the step is a `Base.TwicePrecision`, which seems to be an implementation detail that's leaking out, although addressing this may be a separate PR. --- base/twiceprecision.jl | 1 + test/ranges.jl | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/base/twiceprecision.jl b/base/twiceprecision.jl index 0de6270cafb2d4..6928d420a3860b 100644 --- a/base/twiceprecision.jl +++ b/base/twiceprecision.jl @@ -278,6 +278,7 @@ big(x::TwicePrecision) = big(x.hi) + big(x.lo) -(x::TwicePrecision) = TwicePrecision(-x.hi, -x.lo) +zero(x::TwicePrecision) = zero(typeof(x)) function zero(::Type{TwicePrecision{T}}) where {T} z = zero(T) TwicePrecision{T}(z, z) diff --git a/test/ranges.jl b/test/ranges.jl index 9284c898bcbfb9..9599128739488a 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -314,6 +314,13 @@ end twiceprecision_is_normalized(Base.TwicePrecision{Float64}(rand_twiceprecision(Float32))) end end + + @testset "displaying a complex range (#52713)" begin + r = 1.0*(1:5) .+ im + @test startswith(repr(r), repr(first(r))) + @test endswith(repr(r), repr(last(r))) + @test occursin(repr(step(r)), repr(r)) + end end @testset "ranges" begin @test size(10:1:0) == (0,) From 0cd3164862633649bb121933600803c9a54d533c Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Thu, 4 Apr 2024 09:10:57 +0530 Subject: [PATCH 081/123] Update stable version in README.md (#53947) [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c5c4f3f2730ac0..9ca71313f5483c 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ and then use the command prompt to change into the resulting julia directory. By Julia. However, most users should use the [most recent stable version](https://github.com/JuliaLang/julia/releases) of Julia. You can get this version by running: - git checkout v1.10.0 + git checkout v1.10.2 To build the `julia` executable, run `make` from within the julia directory. From 19fffe1976f900648431b268b8aeaef22ec09f9a Mon Sep 17 00:00:00 2001 From: Paul Berg Date: Thu, 4 Apr 2024 10:54:55 +0200 Subject: [PATCH 082/123] Fixes for allowing `:throw_undef_if_not` on the frontend (#53944) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/JuliaLang/julia/pull/53875 allowed `:throw_undef_if_not` as a frontend form. However, the `UndefVarError` being tested is thrown because the first argument is resolved to a global ref: ```julia julia> @eval function has_tuin() $(Expr(:throw_undef_if_not, :x, false)) end has_tuin (generic function with 1 method) julia> @code_lowered has_tuin() # master CodeInfo( 1 โ”€ %1 = $(Expr(:throw_undef_if_not, :(Main.x), false)) โ””โ”€โ”€ return %1 ) julia> @code_lowered has_tuin() # this pr CodeInfo( 1 โ”€ %1 = $(Expr(:throw_undef_if_not, :x, false)) โ””โ”€โ”€ return %1 ) ``` This change skips this global ref resolution for the first argument and fixes a typo which would throw an error in case of non-const second argument. --- base/compiler/abstractinterpretation.jl | 2 +- src/method.c | 2 +- test/compiler/inference.jl | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index ce8494b1feff09..51794e9e1eb7cf 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -2637,7 +2637,7 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp else t = Union{} end - elseif !hasintersect(windenconst(condt), Bool) + elseif !hasintersect(widenconst(condt), Bool) t = Union{} end elseif ehead === :boundscheck diff --git a/src/method.c b/src/method.c index a97dccf53e1e24..e3b19a5007b584 100644 --- a/src/method.c +++ b/src/method.c @@ -212,7 +212,7 @@ static jl_value_t *resolve_globals(jl_value_t *expr, jl_module_t *module, jl_sve jl_exprargset(e, 0, resolve_globals(jl_exprarg(e, 0), module, sparam_vals, binding_effects, 1)); i++; } - if (e->head == jl_method_sym || e->head == jl_module_sym) { + if (e->head == jl_method_sym || e->head == jl_module_sym || e->head == jl_throw_undef_if_not_sym) { i++; } for (; i < nargs; i++) { diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 62c134e58c2a62..01c4687a26caa7 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5647,6 +5647,22 @@ end @test Core.Compiler.return_type(has_tuin, Tuple{}) === Union{} @test_throws UndefVarError has_tuin() +function gen_tuin_from_arg(world::UInt, source, _, _) + ci = make_codeinfo(Any[ + Expr(:throw_undef_if_not, :x, Core.Argument(2)), + ReturnNode(true), + ]; slottypes=Any[Any, Bool]) + ci.slotnames = Symbol[:var"#self#", :def] + ci +end + +@eval function has_tuin2(def) + $(Expr(:meta, :generated, gen_tuin_from_arg)) + $(Expr(:meta, :generated_only)) +end +@test_throws UndefVarError has_tuin2(false) +@test has_tuin2(true) + # issue #53585 let t = ntuple(i -> i % 8 == 1 ? Int64 : Float64, 4000) @test only(Base.return_types(Base.promote_typeof, t)) == Type{Float64} From c371e4cac4e571cbdda7576e3fc40e54344175f8 Mon Sep 17 00:00:00 2001 From: Matt Stinson <11094799+mestinso@users.noreply.github.com> Date: Thu, 4 Apr 2024 07:21:31 -0700 Subject: [PATCH 083/123] Fix negative tolerance documentation issue in cholesky.jl (#53918) --- stdlib/LinearAlgebra/src/cholesky.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/LinearAlgebra/src/cholesky.jl b/stdlib/LinearAlgebra/src/cholesky.jl index 528eca5c3d8a34..c28613041e18a6 100644 --- a/stdlib/LinearAlgebra/src/cholesky.jl +++ b/stdlib/LinearAlgebra/src/cholesky.jl @@ -427,7 +427,7 @@ The following functions are available for `CholeskyPivoted` objects: [`size`](@ref), [`\\`](@ref), [`inv`](@ref), [`det`](@ref), and [`rank`](@ref). The argument `tol` determines the tolerance for determining the rank. -For negative values, the tolerance is the machine precision. +For negative values, the tolerance is equal to `eps()*size(A,1)*maximum(diag(A))`. If you have a matrix `A` that is slightly non-Hermitian due to roundoff errors in its construction, wrap it in `Hermitian(A)` before passing it to `cholesky` in order to treat it as perfectly Hermitian. From a931fbedc4f10776ba53eaaf1df7256eb55e3fba Mon Sep 17 00:00:00 2001 From: Hossein Pourbozorg Date: Thu, 4 Apr 2024 22:05:52 +0330 Subject: [PATCH 084/123] Make all command-line options documented in all related files (#53826) I checked and updated the three related files to make sure command-line documentations are the same in all of them. Previously mentioned in https://github.com/JuliaLang/julia/pull/52645#issuecomment-1870571454 --------- Co-authored-by: Matt Bauman --- doc/man/julia.1 | 67 ++++++++++++++---------- doc/src/manual/command-line-interface.md | 27 +++++----- src/jloptions.c | 30 ++++++----- 3 files changed, 72 insertions(+), 52 deletions(-) diff --git a/doc/man/julia.1 b/doc/man/julia.1 index 2d7f41b2217bc9..6320536cbbc74b 100644 --- a/doc/man/julia.1 +++ b/doc/man/julia.1 @@ -59,7 +59,7 @@ Display version information .TP -h, --help -Print help message +Print command-line options (this message) .TP --help-hidden @@ -77,7 +77,7 @@ Start up with the given system image file .TP -H, --home -Set location of julia executable +Set location of `julia` executable .TP --startup-file={yes*|no} @@ -95,39 +95,42 @@ Use native code from system image if available .TP --compiled-modules={yes*|no|existing|strict} Enable or disable incremental precompilation of modules. -The "existing" option allows use of existing compiled modules that were previously precompiled, but disallows creation of new precompile files. -The "strict" option is similar, but will error if no precompile file is found. +The `existing` option allows use of existing compiled modules that were +previously precompiled, but disallows creation of new precompile files. +The `strict` option is similar, but will error if no precompile file is found. .TP --pkgimages={yes*|no|existing} Enable or disable usage of native code caching in the form of pkgimages +The `existing` option allows use of existing pkgimages but disallows creation of new ones .TP -e, --eval Evaluate -.TP --m, --module [args] -Run entry point of `Package` (`@main` function) with `args'. - - .TP -E, --print Evaluate and display the result +.TP +-m, --module [args] +Run entry point of `Package` (`@main` function) with `args' + .TP -L, --load Load immediately on all processors .TP --t, --threads -Enable n threads; "auto" tries to infer a useful default number -of threads to use but the exact behavior might change in the future. -Currently, "auto" uses the number of CPUs assigned to this julia -process based on the OS-specific affinity assignment interface, if -supported (Linux and Windows). If this is not supported (macOS) or -process affinity is not configured, it uses the number of CPU -threads. +-t, --threads {auto|N[,auto|M]} +Enable N[+M] threads; N threads are assigned to the `default` +threadpool, and if M is specified, M threads are assigned to the +`interactive` threadpool; `auto` tries to infer a useful +default number of threads to use but the exact behavior might change +in the future. Currently sets N to the number of CPUs assigned to +this Julia process based on the OS-specific affinity assignment +interface if supported (Linux and Windows) or to the number of CPU +threads if not supported (MacOS) or if process affinity is not +configured, and sets M to 1. .TP --gcthreads=N[,M] @@ -144,7 +147,7 @@ as the number of local CPU threads (logical cores) Run processes on hosts listed in .TP --i +-i, --interactive Interactive mode; REPL runs and `isinteractive()` is true .TP @@ -152,7 +155,7 @@ Interactive mode; REPL runs and `isinteractive()` is true Quiet startup: no banner, suppress REPL warnings .TP ---banner={yes|no|auto*} +--banner={yes|no|short|auto*} Enable or disable startup banner .TP @@ -180,15 +183,15 @@ Enable or disable warning for ambiguous top-level scope Limit usage of CPU features up to ; set to `help` to see the available options .TP --O, --optimize={0,1,2*,3} +-O, --optimize={0|1|2*|3} Set the optimization level (level 3 if `-O` is used without a level) .TP ---min-optlevel={0*,1,2,3} +--min-optlevel={0*|1|2|3} Set a lower bound on the optimization level .TP --g {0,1*,2} +-g, --debug-info={0|1*|2} Set the level of debug info generation (level 2 if `-g` is used without a level) .TP @@ -203,6 +206,10 @@ Emit bounds checks always, never, or respect @inbounds declarations --math-mode={ieee|user*} Always follow `ieee` floating point semantics or respect `@fastmath` declarations +.TP +--polly={yes*|no} +Enable or disable the polyhedral optimizer Polly (overrides @polly declaration) + .TP --code-coverage[={none*|user|all}] Count executions of source lines (omitting setting is equivalent to `user`) @@ -213,8 +220,8 @@ Count executions of source lines in a file or files under a given directory. A ` be placed before the path to indicate this option. A `@` with no path will track the current directory. .TP - --code-coverage=tracefile.info - Append coverage information to the LCOV tracefile (filename supports format tokens) +--code-coverage=tracefile.info +Append coverage information to the LCOV tracefile (filename supports format tokens) .TP --track-allocation[={none*|user|all}] @@ -222,8 +229,8 @@ Count bytes allocated by each source line (omitting setting is equivalent to `us .TP --track-allocation=@ -Count bytes allocated by each source line in a file or files under a given directory. A `@` -must be placed before the path to indicate this option. A `@` with no path will track the current directory. +Count bytes but only in files that fall under the given file path/directory. +The `@` prefix is required to select this option. A `@` with no path will track the current directory. .TP --bug-report=KIND @@ -233,7 +240,7 @@ fallbacks to the latest compatible BugReporting.jl if not. For more information, --bug-report=help. .TP ---heap-size-hint= +--heap-size-hint= Forces garbage collection if memory usage is higher than the given value. The value may be specified as a number of bytes, optionally in units of KB, MB, GB, or TB, or as a percentage of physical memory with %. @@ -275,13 +282,17 @@ Generate an assembly file (.s) Generate an incremental output file (rather than complete) .TP ---trace-compile={stderr,name} +--trace-compile={stderr|name} Print precompile statements for methods compiled during execution or save to a path .TP -image-codegen Force generate code in imaging mode +.TP +--permalloc-pkgimg={yes|no*} +Copy the data section of package images into memory + .SH FILES AND ENVIRONMENT See https://docs.julialang.org/en/v1/manual/environment-variables/ diff --git a/doc/src/manual/command-line-interface.md b/doc/src/manual/command-line-interface.md index 1bb9507756aec9..50002801e06f8b 100644 --- a/doc/src/manual/command-line-interface.md +++ b/doc/src/manual/command-line-interface.md @@ -164,44 +164,47 @@ The following is a complete list of command-line switches available when launchi |Switch |Description| |:--- |:---| |`-v`, `--version` |Display version information| -|`-h`, `--help` |Print command-line options (this message).| -|`--help-hidden` |Uncommon options not shown by `-h`| +|`-h`, `--help` |Print command-line options (this message)| +|`--help-hidden` |Print uncommon options not shown by `-h`| |`--project[={\|@.}]` |Set `` as the active project/environment. The default `@.` option will search through parent directories until a `Project.toml` or `JuliaProject.toml` file is found.| |`-J`, `--sysimage ` |Start up with the given system image file| |`-H`, `--home ` |Set location of `julia` executable| |`--startup-file={yes*\|no}` |Load `JULIA_DEPOT_PATH/config/startup.jl`; if [`JULIA_DEPOT_PATH`](@ref JULIA_DEPOT_PATH) environment variable is unset, load `~/.julia/config/startup.jl`| |`--handle-signals={yes*\|no}` |Enable or disable Julia's default signal handlers| |`--sysimage-native-code={yes*\|no}` |Use native code from system image if available| -|`--compiled-modules={yes*\|no\|existing|strict}` |Enable or disable incremental precompilation of modules. The `existing` option allows use of existing compiled modules that were previously precompiled, but disallows creation of new precompile files. The `strict` option is similar, but will error if no precompile file is found. | -|`--pkgimages={yes*\|no|existing}` |Enable or disable usage of native code caching in the form of pkgimages. The `existing` option allows use of existing pkgimages but disallows creation of new ones| +|`--compiled-modules={yes*\|no\|existing\|strict}` |Enable or disable incremental precompilation of modules. The `existing` option allows use of existing compiled modules that were previously precompiled, but disallows creation of new precompile files. The `strict` option is similar, but will error if no precompile file is found. | +|`--pkgimages={yes*\|no\|existing}` |Enable or disable usage of native code caching in the form of pkgimages. The `existing` option allows use of existing pkgimages but disallows creation of new ones| |`-e`, `--eval ` |Evaluate ``| |`-E`, `--print ` |Evaluate `` and display the result| +|`-m`, `--module [args]` |Run entry point of `Package` (`@main` function) with `args'| |`-L`, `--load ` |Load `` immediately on all processors| -|`-t`, `--threads {N\|auto}` |Enable N threads; `auto` tries to infer a useful default number of threads to use but the exact behavior might change in the future. Currently, `auto` uses the number of CPUs assigned to this julia process based on the OS-specific affinity assignment interface, if supported (Linux and Windows). If this is not supported (macOS) or process affinity is not configured, it uses the number of CPU threads.| +|`-t`, `--threads {auto\|N[,auto\|M]}` |Enable N[+M] threads; N threads are assigned to the `default` threadpool, and if M is specified, M threads are assigned to the `interactive` threadpool; `auto` tries to infer a useful default number of threads to use but the exact behavior might change in the future. Currently sets N to the number of CPUs assigned to this Julia process based on the OS-specific affinity assignment interface if supported (Linux and Windows) or to the number of CPU threads if not supported (MacOS) or if process affinity is not configured, and sets M to 1.| | `--gcthreads=N[,M]` |Use N threads for the mark phase of GC and M (0 or 1) threads for the concurrent sweeping phase of GC. N is set to half of the number of compute threads and M is set to 0 if unspecified.| |`-p`, `--procs {N\|auto}` |Integer value N launches N additional local worker processes; `auto` launches as many workers as the number of local CPU threads (logical cores)| |`--machine-file ` |Run processes on hosts listed in ``| -|`-i` |Interactive mode; REPL runs and `isinteractive()` is true| +|`-i`, `--interactive` |Interactive mode; REPL runs and `isinteractive()` is true| |`-q`, `--quiet` |Quiet startup: no banner, suppress REPL warnings| -|`--banner={yes\|no\|auto*}` |Enable or disable startup banner| +|`--banner={yes\|no\|short\|auto*}` |Enable or disable startup banner| |`--color={yes\|no\|auto*}` |Enable or disable color text| |`--history-file={yes*\|no}` |Load or save history| |`--depwarn={yes\|no*\|error}` |Enable or disable syntax and method deprecation warnings (`error` turns warnings into errors)| |`--warn-overwrite={yes\|no*}` |Enable or disable method overwrite warnings| |`--warn-scope={yes*\|no}` |Enable or disable warning for ambiguous top-level scope| |`-C`, `--cpu-target ` |Limit usage of CPU features up to ``; set to `help` to see the available options| -|`-O`, `--optimize={0,1,2*,3}` |Set the optimization level (level is 3 if `-O` is used without a level) ($)| -|`--min-optlevel={0*,1,2,3}` |Set the lower bound on per-module optimization| -|`-g`, `--debug-info={0,1*,2}` |Set the level of debug info generation (level is 2 if `-g` is used without a level) ($)| +|`-O`, `--optimize={0\|1\|2*\|3}` |Set the optimization level (level is 3 if `-O` is used without a level) ($)| +|`--min-optlevel={0*\|1\|2\|3}` |Set the lower bound on per-module optimization| +|`-g`, `--debug-info={0\|1*\|2}` |Set the level of debug info generation (level is 2 if `-g` is used without a level) ($)| |`--inline={yes\|no}` |Control whether inlining is permitted, including overriding `@inline` declarations| |`--check-bounds={yes\|no\|auto*}` |Emit bounds checks always, never, or respect `@inbounds` declarations ($)| |`--math-mode={ieee\|user*}` |Always follow `ieee` floating point semantics or respect `@fastmath` declarations| +|`--polly={yes*\|no}` |Enable or disable the polyhedral optimizer Polly (overrides @polly declaration)| |`--code-coverage[={none*\|user\|all}]` |Count executions of source lines (omitting setting is equivalent to `user`)| |`--code-coverage=@` |Count executions but only in files that fall under the given file path/directory. The `@` prefix is required to select this option. A `@` with no path will track the current directory.| |`--code-coverage=tracefile.info` |Append coverage information to the LCOV tracefile (filename supports format tokens).| |`--track-allocation[={none*\|user\|all}]` |Count bytes allocated by each source line (omitting setting is equivalent to "user")| |`--track-allocation=@` |Count bytes but only in files that fall under the given file path/directory. The `@` prefix is required to select this option. A `@` with no path will track the current directory.| |`--bug-report=KIND` |Launch a bug report session. It can be used to start a REPL, run a script, or evaluate expressions. It first tries to use BugReporting.jl installed in current environment and falls back to the latest compatible BugReporting.jl if not. For more information, see `--bug-report=help`.| +|`--heap-size-hint=` |Forces garbage collection if memory usage is higher than the given value. The value may be specified as a number of bytes, optionally in units of KB, MB, GB, or TB, or as a percentage of physical memory with %.| |`--compile={yes*\|no\|all\|min}` |Enable or disable JIT compiler, or request exhaustive or minimal compilation| |`--output-o ` |Generate an object file (including system image data)| |`--output-ji ` |Generate a system image data file (.ji)| @@ -211,9 +214,9 @@ The following is a complete list of command-line switches available when launchi |`--output-bc ` |Generate LLVM bitcode (.bc)| |`--output-asm ` |Generate an assembly file (.s)| |`--output-incremental={yes\|no*}` |Generate an incremental output file (rather than complete)| -|`--trace-compile={stderr,name}` |Print precompile statements for methods compiled during execution or save to a path| +|`--trace-compile={stderr\|name}` |Print precompile statements for methods compiled during execution or save to a path| |`--image-codegen` |Force generate code in imaging mode| -|`--heap-size-hint=` |Forces garbage collection if memory usage is higher than the given value. The value may be specified as a number of bytes, optionally in units of KB, MB, GB, or TB, or as a percentage of physical memory with %.| +|`--permalloc-pkgimg={yes\|no*}` |Copy the data section of package images into memory| !!! compat "Julia 1.1" diff --git a/src/jloptions.c b/src/jloptions.c index 9020404e707813..6980d4b8b235cb 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -108,11 +108,13 @@ static const char usage[] = "\n julia [switches] -- [programfile] [args...]\n static const char opts[] = "Switches (a '*' marks the default value, if applicable; settings marked '($)' may trigger package precompilation):\n\n" " -v, --version Display version information\n" - " -h, --help Print this message (--help-hidden for more)\n" - " --help-hidden Uncommon options not shown by `-h`\n\n" + " -h, --help Print command-line options (this message)\n" + " --help-hidden Print uncommon options not shown by `-h`\n\n" // startup options - " --project[={|@.}] Set as the active project/environment\n" + " --project[={|@.}] Set as the active project/environment.\n" + " The default @. option will search through parent directories\n" + " until a Project.toml or JuliaProject.toml file is found.\n" " -J, --sysimage Start up with the given system image file\n" " -H, --home Set location of `julia` executable\n" " --startup-file={yes*|no} Load `JULIA_DEPOT_PATH/config/startup.jl`; if `JULIA_DEPOT_PATH`\n" @@ -122,8 +124,12 @@ static const char opts[] = " Use native code from system image if available\n" " --compiled-modules={yes*|no|existing|strict}\n" " Enable or disable incremental precompilation of modules\n" + " The `existing` option allows use of existing compiled modules that were\n" + " previously precompiled, but disallows creation of new precompile files.\n" + " The `strict` option is similar, but will error if no precompile file is found.\n" " --pkgimages={yes*|no|existing}\n" - " Enable or disable usage of native code caching in the form of pkgimages ($)\n\n" + " Enable or disable usage of native code caching in the form of pkgimages\n" + " The `existing` option allows use of existing pkgimages but disallows creation of new ones ($)\n\n" // actions " -e, --eval Evaluate \n" @@ -136,7 +142,7 @@ static const char opts[] = " -t, --threads {auto|N[,auto|M]}\n" " Enable N[+M] threads; N threads are assigned to the `default`\n" " threadpool, and if M is specified, M threads are assigned to the\n" - " `interactive` threadpool; \"auto\" tries to infer a useful\n" + " `interactive` threadpool; `auto` tries to infer a useful\n" " default number of threads to use but the exact behavior might change\n" " in the future. Currently sets N to the number of CPUs assigned to\n" " this Julia process based on the OS-specific affinity assignment\n" @@ -146,7 +152,7 @@ static const char opts[] = " --gcthreads=N[,M] Use N threads for the mark phase of GC and M (0 or 1) threads for the concurrent sweeping phase of GC.\n" " N is set to half of the number of compute threads and M is set to 0 if unspecified.\n" " -p, --procs {N|auto} Integer value N launches N additional local worker processes\n" - " \"auto\" launches as many workers as the number of local CPU threads (logical cores)\n" + " `auto` launches as many workers as the number of local CPU threads (logical cores)\n" " --machine-file Run processes on hosts listed in \n\n" // interactive options @@ -164,20 +170,20 @@ static const char opts[] = // code generation options " -C, --cpu-target Limit usage of CPU features up to ; set to `help` to see the available options\n" - " -O, --optimize={0,1,2*,3} Set the optimization level (level 3 if `-O` is used without a level) ($)\n" - " --min-optlevel={0*,1,2,3} Set a lower bound on the optimization level\n" + " -O, --optimize={0|1|2*|3} Set the optimization level (level 3 if `-O` is used without a level) ($)\n" + " --min-optlevel={0*|1|2|3} Set a lower bound on the optimization level\n" #ifdef JL_DEBUG_BUILD - " -g, --debug-info=[{0,1,2*}] Set the level of debug info generation in the julia-debug build ($)\n" + " -g, --debug-info=[{0|1|2*}] Set the level of debug info generation in the julia-debug build ($)\n" #else - " -g, --debug-info=[{0,1*,2}] Set the level of debug info generation (level 2 if `-g` is used without a level) ($)\n" + " -g, --debug-info=[{0|1*|2}] Set the level of debug info generation (level 2 if `-g` is used without a level) ($)\n" #endif " --inline={yes*|no} Control whether inlining is permitted, including overriding @inline declarations\n" " --check-bounds={yes|no|auto*}\n" " Emit bounds checks always, never, or respect @inbounds declarations ($)\n" + " --math-mode={ieee|user*} Always follow `ieee` floating point semantics or respect `@fastmath` declarations\n\n" #ifdef USE_POLLY " --polly={yes*|no} Enable or disable the polyhedral optimizer Polly (overrides @polly declaration)\n" #endif - " --math-mode={ieee|user*} Always follow `ieee` floating point semantics or respect `@fastmath` declarations\n\n" // instrumentation options " --code-coverage[={none*|user|all}]\n" @@ -223,7 +229,7 @@ static const char opts_hidden[] = " --output-asm Generate an assembly file (.s)\n" " --output-incremental={yes|no*}\n" " Generate an incremental output file (rather than complete)\n" - " --trace-compile={stderr,name}\n" + " --trace-compile={stderr|name}\n" " Print precompile statements for methods compiled during execution or save to a path\n" " --image-codegen Force generate code in imaging mode\n" " --permalloc-pkgimg={yes|no*} Copy the data section of package images into memory\n" From e64fa86a7f2c0347cfbf8abc3b5db32168fea2bf Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Fri, 5 Apr 2024 07:17:06 +0530 Subject: [PATCH 085/123] Add missing methods for UniformScaling (#53949) The methods `float`, `cis`, `sincos` and `sincosd` are defined for matrices, so it makes sense for these to be defined for a `UniformScaling` as well. E.g.: ```julia julia> float(2I) UniformScaling{Float64} 2.0*I julia> sincos(2I) (UniformScaling{Float64}(0.9092974268256817), UniformScaling{Float64}(-0.4161468365471424)) ``` --- stdlib/LinearAlgebra/src/uniformscaling.jl | 9 +++++++-- stdlib/LinearAlgebra/test/uniformscaling.jl | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/stdlib/LinearAlgebra/src/uniformscaling.jl b/stdlib/LinearAlgebra/src/uniformscaling.jl index 5c052df1ff48ec..b75886b8d99fb0 100644 --- a/stdlib/LinearAlgebra/src/uniformscaling.jl +++ b/stdlib/LinearAlgebra/src/uniformscaling.jl @@ -1,6 +1,6 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -import Base: copy, adjoint, getindex, show, transpose, one, zero, inv, +import Base: copy, adjoint, getindex, show, transpose, one, zero, inv, float, hcat, vcat, hvcat, ^ """ @@ -124,6 +124,8 @@ conj(J::UniformScaling) = UniformScaling(conj(J.ฮป)) real(J::UniformScaling) = UniformScaling(real(J.ฮป)) imag(J::UniformScaling) = UniformScaling(imag(J.ฮป)) +float(J::UniformScaling) = UniformScaling(float(J.ฮป)) + transpose(J::UniformScaling) = J adjoint(J::UniformScaling) = UniformScaling(conj(J.ฮป)) @@ -159,7 +161,7 @@ isposdef(J::UniformScaling) = isposdef(J.ฮป) (-)(A::AbstractMatrix, J::UniformScaling) = A + (-J) # matrix functions -for f in ( :exp, :log, +for f in ( :exp, :log, :cis, :expm1, :log1p, :sqrt, :cbrt, :sin, :cos, :tan, @@ -172,6 +174,9 @@ for f in ( :exp, :log, :acsch, :asech, :acoth ) @eval Base.$f(J::UniformScaling) = UniformScaling($f(J.ฮป)) end +for f in (:sincos, :sincosd) + @eval Base.$f(J::UniformScaling) = map(UniformScaling, $f(J.ฮป)) +end # Unit{Lower/Upper}Triangular matrices become {Lower/Upper}Triangular under # addition with a UniformScaling diff --git a/stdlib/LinearAlgebra/test/uniformscaling.jl b/stdlib/LinearAlgebra/test/uniformscaling.jl index 6719714049b1e3..92547e8648d8ab 100644 --- a/stdlib/LinearAlgebra/test/uniformscaling.jl +++ b/stdlib/LinearAlgebra/test/uniformscaling.jl @@ -24,6 +24,7 @@ Random.seed!(1234543) @test -one(UniformScaling(2)) == UniformScaling(-1) @test opnorm(UniformScaling(1+im)) โ‰ˆ sqrt(2) @test convert(UniformScaling{Float64}, 2I) === 2.0I + @test float(2I) === 2.0*I end @testset "getindex" begin @@ -67,7 +68,7 @@ end # on complex plane J = UniformScaling(randn(ComplexF64)) - for f in ( exp, log, + for f in ( exp, log, cis, sqrt, sin, cos, tan, asin, acos, atan, @@ -80,6 +81,10 @@ end @test f(J) โ‰ˆ f(M(J)) end + for f in (sincos, sincosd) + @test all(splat(โ‰ˆ), zip(f(J), f(M(J)))) + end + # on real axis for (ฮป, fs) in ( # functions defined for x โˆˆ โ„ From 57bbff63b8e74c78ffe185296eaba5fd781bc254 Mon Sep 17 00:00:00 2001 From: Ian Butterworth Date: Thu, 4 Apr 2024 22:00:13 -0400 Subject: [PATCH 086/123] Profile: make heap snapshots viewable in vscode viewer (#53833) --- src/gc-heap-snapshot.cpp | 24 ++++++++++++++--- stdlib/Manifest.toml | 13 +++++----- stdlib/Profile/Project.toml | 6 +++++ stdlib/Profile/src/Profile.jl | 1 + stdlib/Profile/src/heapsnapshot_reassemble.jl | 26 ++++++++++++++++--- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/gc-heap-snapshot.cpp b/src/gc-heap-snapshot.cpp index 5007f889397016..77a6e70a127e6e 100644 --- a/src/gc-heap-snapshot.cpp +++ b/src/gc-heap-snapshot.cpp @@ -606,7 +606,9 @@ void _record_gc_just_edge(const char *edge_type, size_t from_idx, size_t to_idx, void final_serialize_heap_snapshot(ios_t *json, ios_t *strings, HeapSnapshot &snapshot, char all_one) { // mimicking https://github.com/nodejs/node/blob/5fd7a72e1c4fbaf37d3723c4c81dce35c149dc84/deps/v8/src/profiler/heap-snapshot-generator.cc#L2567-L2567 + // also https://github.com/microsoft/vscode-v8-heap-tools/blob/c5b34396392397925ecbb4ecb904a27a2754f2c1/v8-heap-parser/src/decoder.rs#L43-L51 ios_printf(json, "{\"snapshot\":{"); + ios_printf(json, "\"meta\":{"); ios_printf(json, "\"node_fields\":[\"type\",\"name\",\"id\",\"self_size\",\"edge_count\",\"trace_node_id\",\"detachedness\"],"); ios_printf(json, "\"node_types\":["); @@ -617,10 +619,26 @@ void final_serialize_heap_snapshot(ios_t *json, ios_t *strings, HeapSnapshot &sn ios_printf(json, "\"edge_types\":["); snapshot.edge_types.print_json_array(json, false); ios_printf(json, ","); - ios_printf(json, "\"string_or_number\",\"from_node\"]"); + ios_printf(json, "\"string_or_number\",\"from_node\"],"); + // not used. Required by microsoft/vscode-v8-heap-tools + ios_printf(json, "\"trace_function_info_fields\":[\"function_id\",\"name\",\"script_name\",\"script_id\",\"line\",\"column\"],"); + ios_printf(json, "\"trace_node_fields\":[\"id\",\"function_info_index\",\"count\",\"size\",\"children\"],"); + ios_printf(json, "\"sample_fields\":[\"timestamp_us\",\"last_assigned_id\"],"); + ios_printf(json, "\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]"); + // end not used ios_printf(json, "},\n"); // end "meta" + ios_printf(json, "\"node_count\":%zu,", snapshot.num_nodes); - ios_printf(json, "\"edge_count\":%zu", snapshot.num_edges); - ios_printf(json, "}\n"); // end "snapshot" + ios_printf(json, "\"edge_count\":%zu,", snapshot.num_edges); + ios_printf(json, "\"trace_function_count\":0"); // not used. Required by microsoft/vscode-v8-heap-tools + ios_printf(json, "},\n"); // end "snapshot" + + // not used. Required by microsoft/vscode-v8-heap-tools + ios_printf(json, "\"trace_function_infos\":[],"); + ios_printf(json, "\"trace_tree\":[],"); + ios_printf(json, "\"samples\":[],"); + ios_printf(json, "\"locations\":[]"); + // end not used + ios_printf(json, "}"); } diff --git a/stdlib/Manifest.toml b/stdlib/Manifest.toml index 4df442c6833d1c..858e5ea6513393 100644 --- a/stdlib/Manifest.toml +++ b/stdlib/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.12.0-DEV" manifest_format = "2.0" -project_hash = "13f2dd600364a1e8b659dc5796bf185b37d1c95d" +project_hash = "d3a1f6b706609fe0c59521e1d770be6e2b8c489d" [[deps.ArgTools]] uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" @@ -23,7 +23,7 @@ version = "1.11.0" [[deps.CompilerSupportLibraries_jll]] deps = ["Artifacts", "Libdl"] uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" -version = "1.1.0+0" +version = "1.1.1+0" [[deps.Dates]] deps = ["Printf"] @@ -113,7 +113,7 @@ version = "1.11.0+1" [[deps.LibUV_jll]] deps = ["Artifacts", "Libdl"] uuid = "183b4373-6708-53ba-ad28-60e28bb38547" -version = "2.0.1+15" +version = "2.0.1+16" [[deps.LibUnwind_jll]] deps = ["Artifacts", "Libdl"] @@ -155,7 +155,7 @@ version = "1.11.0" [[deps.MozillaCACerts_jll]] uuid = "14a3606d-f60d-562e-9121-12d972cd8159" -version = "2023.12.12" +version = "2024.3.11" [[deps.NetworkOptions]] uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" @@ -177,9 +177,9 @@ uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" version = "10.43.0+0" [[deps.Pkg]] -deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" -version = "1.11.0" +version = "1.12.0" weakdeps = ["REPL"] [deps.Pkg.extensions] @@ -191,6 +191,7 @@ uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" version = "1.11.0" [[deps.Profile]] +deps = ["Unicode"] uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79" version = "1.11.0" diff --git a/stdlib/Profile/Project.toml b/stdlib/Profile/Project.toml index ad0107ecf94043..ede7ccd66bc8ed 100644 --- a/stdlib/Profile/Project.toml +++ b/stdlib/Profile/Project.toml @@ -2,6 +2,12 @@ name = "Profile" uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79" version = "1.11.0" +[deps] +Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[compat] +Unicode = "1.11.0" + [extras] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" diff --git a/stdlib/Profile/src/Profile.jl b/stdlib/Profile/src/Profile.jl index 17e903ed373b1e..062b608b25c59a 100644 --- a/stdlib/Profile/src/Profile.jl +++ b/stdlib/Profile/src/Profile.jl @@ -1286,6 +1286,7 @@ function take_heap_snapshot(filepath::AbstractString, all_one::Bool=false; strea prefix = filepath _stream_heap_snapshot(prefix, all_one) Profile.HeapSnapshot.assemble_snapshot(prefix, filepath) + Profile.HeapSnapshot.cleanup_streamed_files(prefix) end return filepath end diff --git a/stdlib/Profile/src/heapsnapshot_reassemble.jl b/stdlib/Profile/src/heapsnapshot_reassemble.jl index b39f53a8bda039..27d7d12318ed18 100644 --- a/stdlib/Profile/src/heapsnapshot_reassemble.jl +++ b/stdlib/Profile/src/heapsnapshot_reassemble.jl @@ -2,6 +2,8 @@ module HeapSnapshot +using Unicode + """ assemble_snapshot(filepath::AbstractString, out_file::AbstractString) @@ -92,7 +94,7 @@ function assemble_snapshot(in_prefix, io::IO) node_count = parse(Int, String(@view preamble[pos:endpos])) pos = last(findnext("edge_count\":", preamble, endpos)) + 1 - endpos = findnext(==('}'), preamble, pos) - 1 + endpos = findnext(==(','), preamble, pos) - 1 edge_count = parse(Int, String(@view preamble[pos:endpos])) nodes = Nodes(node_count, edge_count) @@ -137,7 +139,8 @@ function assemble_snapshot(in_prefix, io::IO) end _digits_buf = zeros(UInt8, ndigits(typemax(UInt))) - println(io, @view(preamble[1:end-2]), ",") # remove trailing "}\n", we don't end the snapshot here + println(io, @view(preamble[1:end-1]), ",") # remove trailing "}" to reopen the object + println(io, "\"nodes\":[") for i in 1:length(nodes) i > 1 && println(io, ",") @@ -182,12 +185,11 @@ function assemble_snapshot(in_prefix, io::IO) str_bytes = read(strings_io, str_size) str = String(str_bytes) if first - print_str_escape_json(io, str) first = false else print(io, ",\n") - print_str_escape_json(io, str) end + print_str_escape_json(io, str) end end print(io, "]}") @@ -202,6 +204,19 @@ function assemble_snapshot(in_prefix, io::IO) return nothing end +""" + cleanup_streamed_files(prefix::AbstractString) + +Remove files streamed during `take_heap_snapshot` in streaming mode. +""" +function cleanup_streamed_files(prefix::AbstractString) + rm(string(prefix, ".metadata.json")) + rm(string(prefix, ".nodes")) + rm(string(prefix, ".edges")) + rm(string(prefix, ".strings")) + return nothing +end + function print_str_escape_json(stream::IO, s::AbstractString) print(stream, '"') for c in s @@ -221,6 +236,9 @@ function print_str_escape_json(stream::IO, s::AbstractString) print(stream, "\\t") elseif '\x00' <= c <= '\x1f' print(stream, "\\u", lpad(string(UInt16(c), base=16), 4, '0')) + elseif !Unicode.isassigned(c) + # we have to do this because vscode's viewer doesn't like the replace character + print(stream, "[invalid unicode character]") else print(stream, c) end From 6ea67a944501d16d5939f60d63cdb1fc779fec40 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Fri, 5 Apr 2024 11:12:46 +0900 Subject: [PATCH 087/123] change the variable name `linfo::MethodInstance` to `mi::MethodInstance` (#53952) --- base/compiler/abstractinterpretation.jl | 22 ++++---- base/compiler/inferenceresult.jl | 68 +++++++++++++------------ base/compiler/inferencestate.jl | 28 +++++----- base/compiler/optimize.jl | 14 ++--- base/compiler/ssair/show.jl | 4 +- base/compiler/tfuncs.jl | 4 +- base/compiler/typeinfer.jl | 2 +- base/compiler/types.jl | 16 +++--- base/compiler/validation.jl | 10 ++-- 9 files changed, 85 insertions(+), 83 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 51794e9e1eb7cf..75c8e841b7e101 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1292,20 +1292,20 @@ struct ConditionalArgtypes <: ForwardableArgtypes end """ - matching_cache_argtypes(๐•ƒ::AbstractLattice, linfo::MethodInstance, + matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, conditional_argtypes::ConditionalArgtypes) The implementation is able to forward `Conditional` of `conditional_argtypes`, as well as the other general extended lattice information. """ -function matching_cache_argtypes(๐•ƒ::AbstractLattice, linfo::MethodInstance, +function matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, conditional_argtypes::ConditionalArgtypes) (; arginfo, sv) = conditional_argtypes (; fargs, argtypes) = arginfo given_argtypes = Vector{Any}(undef, length(argtypes)) - def = linfo.def::Method + def = mi.def::Method nargs = Int(def.nargs) - cache_argtypes, overridden_by_const = matching_cache_argtypes(๐•ƒ, linfo) + cache_argtypes, overridden_by_const = matching_cache_argtypes(๐•ƒ, mi) local condargs = nothing for i in 1:length(argtypes) argtype = argtypes[i] @@ -1336,7 +1336,7 @@ function matching_cache_argtypes(๐•ƒ::AbstractLattice, linfo::MethodInstance, end if condargs !== nothing given_argtypes = let condargs=condargs - va_process_argtypes(๐•ƒ, given_argtypes, linfo) do isva_given_argtypes::Vector{Any}, last::Int + va_process_argtypes(๐•ƒ, given_argtypes, mi) do isva_given_argtypes::Vector{Any}, last::Int # invalidate `Conditional` imposed on varargs for (slotid, i) in condargs if slotid โ‰ฅ last && (1 โ‰ค i โ‰ค length(isva_given_argtypes)) # `Conditional` is already widened to vararg-tuple otherwise @@ -1346,7 +1346,7 @@ function matching_cache_argtypes(๐•ƒ::AbstractLattice, linfo::MethodInstance, end end else - given_argtypes = va_process_argtypes(๐•ƒ, given_argtypes, linfo) + given_argtypes = va_process_argtypes(๐•ƒ, given_argtypes, mi) end return pick_const_args!(๐•ƒ, cache_argtypes, overridden_by_const, given_argtypes) end @@ -2278,7 +2278,7 @@ function abstract_call(interp::AbstractInterpreter, arginfo::ArgInfo, si::StmtIn return abstract_call_known(interp, f, arginfo, si, sv, max_methods) end -function sp_type_rewrap(@nospecialize(T), linfo::MethodInstance, isreturn::Bool) +function sp_type_rewrap(@nospecialize(T), mi::MethodInstance, isreturn::Bool) isref = false if unwrapva(T) === Bottom return Bottom @@ -2293,12 +2293,12 @@ function sp_type_rewrap(@nospecialize(T), linfo::MethodInstance, isreturn::Bool) else return Any end - if isa(linfo.def, Method) - spsig = linfo.def.sig + if isa(mi.def, Method) + spsig = mi.def.sig if isa(spsig, UnionAll) - if !isempty(linfo.sparam_vals) + if !isempty(mi.sparam_vals) sparam_vals = Any[isvarargtype(v) ? TypeVar(:N, Union{}, Any) : - v for v in linfo.sparam_vals] + v for v in mi.sparam_vals] T = ccall(:jl_instantiate_type_in_env, Any, (Any, Any, Ptr{Any}), T, spsig, sparam_vals) isref && isreturn && T === Any && return Bottom # catch invalid return Ref{T} where T = Any for v in sparam_vals diff --git a/base/compiler/inferenceresult.jl b/base/compiler/inferenceresult.jl index 86eed13686ae9c..06fbffaa7aa042 100644 --- a/base/compiler/inferenceresult.jl +++ b/base/compiler/inferenceresult.jl @@ -1,31 +1,32 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license """ - matching_cache_argtypes(๐•ƒ::AbstractLattice, linfo::MethodInstance) -> + matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance) -> (cache_argtypes::Vector{Any}, overridden_by_const::BitVector) -Returns argument types `cache_argtypes::Vector{Any}` for `linfo` that are in the native +Returns argument types `cache_argtypes::Vector{Any}` for `mi` that are in the native Julia type domain. `overridden_by_const::BitVector` is all `false` meaning that there is no additional extended lattice information there. - matching_cache_argtypes(๐•ƒ::AbstractLattice, linfo::MethodInstance, argtypes::ForwardableArgtypes) -> + matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, argtypes::ForwardableArgtypes) -> (cache_argtypes::Vector{Any}, overridden_by_const::BitVector) Returns cache-correct extended lattice argument types `cache_argtypes::Vector{Any}` -for `linfo` given some `argtypes` accompanied by `overridden_by_const::BitVector` +for `mi` given some `argtypes` accompanied by `overridden_by_const::BitVector` that marks which argument contains additional extended lattice information. In theory, there could be a `cache` containing a matching `InferenceResult` -for the provided `linfo` and `given_argtypes`. The purpose of this function is -to return a valid value for `cache_lookup(๐•ƒ, linfo, argtypes, cache).argtypes`, +for the provided `mi` and `given_argtypes`. The purpose of this function is +to return a valid value for `cache_lookup(๐•ƒ, mi, argtypes, cache).argtypes`, so that we can construct cache-correct `InferenceResult`s in the first place. """ function matching_cache_argtypes end -function matching_cache_argtypes(๐•ƒ::AbstractLattice, linfo::MethodInstance) - mthd = isa(linfo.def, Method) ? linfo.def::Method : nothing - cache_argtypes = most_general_argtypes(mthd, linfo.specTypes) - return cache_argtypes, falses(length(cache_argtypes)) +function matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance) + method = isa(mi.def, Method) ? mi.def::Method : nothing + cache_argtypes = most_general_argtypes(method, mi.specTypes) + overridden_by_const = falses(length(cache_argtypes)) + return cache_argtypes, overridden_by_const end struct SimpleArgtypes <: ForwardableArgtypes @@ -33,25 +34,25 @@ struct SimpleArgtypes <: ForwardableArgtypes end """ - matching_cache_argtypes(๐•ƒ::AbstractLattice, linfo::MethodInstance, argtypes::SimpleArgtypes) + matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, argtypes::SimpleArgtypes) The implementation for `argtypes` with general extended lattice information. This is supposed to be used for debugging and testing or external `AbstractInterpreter` usages and in general `matching_cache_argtypes(::MethodInstance, ::ConditionalArgtypes)` is more preferred it can forward `Conditional` information. """ -function matching_cache_argtypes(๐•ƒ::AbstractLattice, linfo::MethodInstance, simple_argtypes::SimpleArgtypes) +function matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, simple_argtypes::SimpleArgtypes) (; argtypes) = simple_argtypes given_argtypes = Vector{Any}(undef, length(argtypes)) for i = 1:length(argtypes) given_argtypes[i] = widenslotwrapper(argtypes[i]) end - given_argtypes = va_process_argtypes(๐•ƒ, given_argtypes, linfo) - return pick_const_args(๐•ƒ, linfo, given_argtypes) + given_argtypes = va_process_argtypes(๐•ƒ, given_argtypes, mi) + return pick_const_args(๐•ƒ, mi, given_argtypes) end -function pick_const_args(๐•ƒ::AbstractLattice, linfo::MethodInstance, given_argtypes::Vector{Any}) - cache_argtypes, overridden_by_const = matching_cache_argtypes(๐•ƒ, linfo) +function pick_const_args(๐•ƒ::AbstractLattice, mi::MethodInstance, given_argtypes::Vector{Any}) + cache_argtypes, overridden_by_const = matching_cache_argtypes(๐•ƒ, mi) return pick_const_args!(๐•ƒ, cache_argtypes, overridden_by_const, given_argtypes) end @@ -60,7 +61,7 @@ function pick_const_args!(๐•ƒ::AbstractLattice, cache_argtypes::Vector{Any}, ov given_argtype = given_argtypes[i] cache_argtype = cache_argtypes[i] if !is_argtype_match(๐•ƒ, given_argtype, cache_argtype, false) - # prefer the argtype we were given over the one computed from `linfo` + # prefer the argtype we were given over the one computed from `mi` if (isa(given_argtype, PartialStruct) && isa(cache_argtype, Type) && !โŠ(๐•ƒ, given_argtype, cache_argtype)) # if the type information of this `PartialStruct` is less strict than @@ -80,8 +81,9 @@ function is_argtype_match(๐•ƒ::AbstractLattice, overridden_by_const::Bool) if is_forwardable_argtype(๐•ƒ, given_argtype) return is_lattice_equal(๐•ƒ, given_argtype, cache_argtype) + else + return !overridden_by_const end - return !overridden_by_const end va_process_argtypes(๐•ƒ::AbstractLattice, given_argtypes::Vector{Any}, mi::MethodInstance) = @@ -114,24 +116,24 @@ function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(spe withfirst::Bool = true) toplevel = method === nothing isva = !toplevel && method.isva - linfo_argtypes = Any[(unwrap_unionall(specTypes)::DataType).parameters...] + mi_argtypes = Any[(unwrap_unionall(specTypes)::DataType).parameters...] nargs::Int = toplevel ? 0 : method.nargs # For opaque closure, the closure environment is processed elsewhere withfirst || (nargs -= 1) cache_argtypes = Vector{Any}(undef, nargs) # First, if we're dealing with a varargs method, then we set the last element of `args` # to the appropriate `Tuple` type or `PartialStruct` instance. + mi_argtypes_length = length(mi_argtypes) if !toplevel && isva if specTypes::Type == Tuple - linfo_argtypes = Any[Any for i = 1:nargs] + mi_argtypes = Any[Any for i = 1:nargs] if nargs > 1 - linfo_argtypes[end] = Tuple + mi_argtypes[end] = Tuple end vargtype = Tuple else - linfo_argtypes_length = length(linfo_argtypes) - if nargs > linfo_argtypes_length - va = linfo_argtypes[linfo_argtypes_length] + if nargs > mi_argtypes_length + va = mi_argtypes[mi_argtypes_length] if isvarargtype(va) new_va = rewrap_unionall(unconstrain_vararg_length(va), specTypes) vargtype = Tuple{new_va} @@ -140,8 +142,8 @@ function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(spe end else vargtype_elements = Any[] - for i in nargs:linfo_argtypes_length - p = linfo_argtypes[i] + for i in nargs:mi_argtypes_length + p = mi_argtypes[i] p = unwraptv(isvarargtype(p) ? unconstrain_vararg_length(p) : p) push!(vargtype_elements, elim_free_typevars(rewrap_unionall(p, specTypes))) end @@ -164,13 +166,12 @@ function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(spe # type info as we go (where possible). Note that if we're dealing with a varargs method, # we already handled the last element of `cache_argtypes` (and decremented `nargs` so that # we don't overwrite the result of that work here). - linfo_argtypes_length = length(linfo_argtypes) - if linfo_argtypes_length > 0 - n = linfo_argtypes_length > nargs ? nargs : linfo_argtypes_length + if mi_argtypes_length > 0 + n = mi_argtypes_length > nargs ? nargs : mi_argtypes_length tail_index = n local lastatype for i = 1:n - atyp = linfo_argtypes[i] + atyp = mi_argtypes[i] if i == n && isvarargtype(atyp) atyp = unwrapva(atyp) tail_index -= 1 @@ -209,13 +210,14 @@ function elim_free_typevars(@nospecialize t) end end -function cache_lookup(๐•ƒ::AbstractLattice, linfo::MethodInstance, given_argtypes::Vector{Any}, cache::Vector{InferenceResult}) - method = linfo.def::Method +function cache_lookup(๐•ƒ::AbstractLattice, mi::MethodInstance, given_argtypes::Vector{Any}, + cache::Vector{InferenceResult}) + method = mi.def::Method nargs = Int(method.nargs) method.isva && (nargs -= 1) length(given_argtypes) โ‰ฅ nargs || return nothing for cached_result in cache - cached_result.linfo === linfo || continue + cached_result.linfo === mi || continue cache_argtypes = cached_result.argtypes cache_overridden_by_const = cached_result.overridden_by_const for i in 1:nargs diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 38fb13495ad851..3c71a88ab8a80a 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -276,14 +276,14 @@ mutable struct InferenceState # src is assumed to be a newly-allocated CodeInfo, that can be modified in-place to contain intermediate results function InferenceState(result::InferenceResult, src::CodeInfo, cache_mode::UInt8, interp::AbstractInterpreter) - linfo = result.linfo + mi = result.linfo world = get_inference_world(interp) if world == typemax(UInt) error("Entering inference from a generated function with an invalid world") end - def = linfo.def + def = mi.def mod = isa(def, Method) ? def.module : def - sptypes = sptypes_from_meth_instance(linfo) + sptypes = sptypes_from_meth_instance(mi) code = src.code::Vector{Any} cfg = compute_basic_blocks(code) method_info = MethodInfo(src) @@ -339,7 +339,7 @@ mutable struct InferenceState !iszero(cache_mode & CACHE_MODE_LOCAL) && push!(get_inference_cache(interp), result) this = new( - linfo, world, mod, sptypes, slottypes, src, cfg, method_info, + mi, world, mod, sptypes, slottypes, src, cfg, method_info, currbb, currpc, ip, handlers, handler_at, ssavalue_uses, bb_vartables, ssavaluetypes, stmt_edges, stmt_info, pclimitations, limitations, cycle_backedges, callers_in_cycle, dont_work_on_me, parent, result, unreachable, valid_worlds, bestguess, exc_bestguess, ipo_effects, @@ -582,13 +582,13 @@ end const EMPTY_SPTYPES = VarState[] -function sptypes_from_meth_instance(linfo::MethodInstance) - def = linfo.def +function sptypes_from_meth_instance(mi::MethodInstance) + def = mi.def isa(def, Method) || return EMPTY_SPTYPES # toplevel sig = def.sig - if isempty(linfo.sparam_vals) + if isempty(mi.sparam_vals) isa(sig, UnionAll) || return EMPTY_SPTYPES - # linfo is unspecialized + # mi is unspecialized spvals = Any[] sigโ€ฒ = sig while isa(sigโ€ฒ, UnionAll) @@ -596,7 +596,7 @@ function sptypes_from_meth_instance(linfo::MethodInstance) sigโ€ฒ = sigโ€ฒ.body end else - spvals = linfo.sparam_vals + spvals = mi.sparam_vals end nvals = length(spvals) sptypes = Vector{VarState}(undef, nvals) @@ -614,7 +614,7 @@ function sptypes_from_meth_instance(linfo::MethodInstance) if isType(sโฑผ) && sโฑผ.parameters[1] === vแตข # if this parameter came from `arg::Type{T}`, # then `arg` is more precise than `Type{T} where lb<:T<:ub` - ty = fieldtype(linfo.specTypes, j) + ty = fieldtype(mi.specTypes, j) @goto ty_computed elseif (va = va_from_vatuple(sโฑผ)) !== nothing # if this parameter came from `::Tuple{.., Vararg{T,vแตข}}`, @@ -645,8 +645,8 @@ function sptypes_from_meth_instance(linfo::MethodInstance) # type variables, we can use it for a more accurate analysis of whether `v` # is constrained or not, otherwise we should use `def.sig` which always # doesn't contain any free type variables - if !has_free_typevars(linfo.specTypes) - sig = linfo.specTypes + if !has_free_typevars(mi.specTypes) + sig = mi.specTypes end @assert !has_free_typevars(sig) constrains_param(v, sig, #=covariant=#true) @@ -858,8 +858,8 @@ function is_effect_overridden(sv::AbsIntState, effect::Symbol) end return false end -function is_effect_overridden(linfo::MethodInstance, effect::Symbol) - def = linfo.def +function is_effect_overridden(mi::MethodInstance, effect::Symbol) + def = mi.def return isa(def, Method) && is_effect_overridden(def, effect) end is_effect_overridden(method::Method, effect::Symbol) = is_effect_overridden(decode_effects_override(method.purity), effect) diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index d8b307a1b7a7c4..fa1bf2f1ee1526 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -156,7 +156,7 @@ function OptimizationState(sv::InferenceState, interp::AbstractInterpreter) sv.sptypes, sv.slottypes, inlining, sv.cfg, sv.unreachable, sv.bb_vartables, sv.insert_coverage) end -function OptimizationState(linfo::MethodInstance, src::CodeInfo, interp::AbstractInterpreter) +function OptimizationState(mi::MethodInstance, src::CodeInfo, interp::AbstractInterpreter) # prepare src for running optimization passes if it isn't already nssavalues = src.ssavaluetypes if nssavalues isa Int @@ -164,7 +164,7 @@ function OptimizationState(linfo::MethodInstance, src::CodeInfo, interp::Abstrac else nssavalues = length(src.ssavaluetypes::Vector{Any}) end - sptypes = sptypes_from_meth_instance(linfo) + sptypes = sptypes_from_meth_instance(mi) nslots = length(src.slotflags) slottypes = src.slottypes if slottypes === nothing @@ -172,7 +172,7 @@ function OptimizationState(linfo::MethodInstance, src::CodeInfo, interp::Abstrac end stmt_info = CallInfo[ NoCallInfo() for i = 1:nssavalues ] # cache some useful state computations - def = linfo.def + def = mi.def mod = isa(def, Method) ? def.module : def # Allow using the global MI cache, but don't track edges. # This method is mostly used for unit testing the optimizer @@ -186,13 +186,13 @@ function OptimizationState(linfo::MethodInstance, src::CodeInfo, interp::Abstrac for slot = 1:nslots ]) end - return OptimizationState(linfo, src, nothing, stmt_info, mod, sptypes, slottypes, inlining, cfg, unreachable, bb_vartables, false) + return OptimizationState(mi, src, nothing, stmt_info, mod, sptypes, slottypes, inlining, cfg, unreachable, bb_vartables, false) end -function OptimizationState(linfo::MethodInstance, interp::AbstractInterpreter) +function OptimizationState(mi::MethodInstance, interp::AbstractInterpreter) world = get_inference_world(interp) - src = retrieve_code_info(linfo, world) + src = retrieve_code_info(mi, world) src === nothing && return nothing - return OptimizationState(linfo, src, interp) + return OptimizationState(mi, src, interp) end function argextype end # imported by EscapeAnalysis diff --git a/base/compiler/ssair/show.jl b/base/compiler/ssair/show.jl index cfcd2ce8f3d2bd..7f2854959ce5e0 100644 --- a/base/compiler/ssair/show.jl +++ b/base/compiler/ssair/show.jl @@ -52,12 +52,12 @@ function print_stmt(io::IO, idx::Int, @nospecialize(stmt), used::BitSet, maxleng stmt = stmt::Expr # TODO: why is this here, and not in Base.show_unquoted print(io, "invoke ") - linfo = stmt.args[1]::Core.MethodInstance + mi = stmt.args[1]::Core.MethodInstance show_unquoted(io, stmt.args[2], indent) print(io, "(") # XXX: this is wrong if `sig` is not a concretetype method # more correct would be to use `fieldtype(sig, i)`, but that would obscure / discard Varargs information in show - sig = linfo.specTypes == Tuple ? Core.svec() : Base.unwrap_unionall(linfo.specTypes).parameters::Core.SimpleVector + sig = mi.specTypes == Tuple ? Core.svec() : Base.unwrap_unionall(mi.specTypes).parameters::Core.SimpleVector print_arg(i) = sprint(; context=io) do io show_unquoted(io, stmt.args[i], indent) if (i - 1) <= length(sig) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 090be7e91fad9f..07fb6215540494 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -2137,7 +2137,7 @@ end return Type end -@nospecs function opaque_closure_tfunc(๐•ƒ::AbstractLattice, arg, lb, ub, source, env::Vector{Any}, linfo::MethodInstance) +@nospecs function opaque_closure_tfunc(๐•ƒ::AbstractLattice, arg, lb, ub, source, env::Vector{Any}, mi::MethodInstance) argt, argt_exact = instanceof_tfunc(arg) lbt, lb_exact = instanceof_tfunc(lb) if !lb_exact @@ -2151,7 +2151,7 @@ end (isa(source, Const) && isa(source.val, Method)) || return t - return PartialOpaque(t, tuple_tfunc(๐•ƒ, env), linfo, source.val) + return PartialOpaque(t, tuple_tfunc(๐•ƒ, env), mi, source.val) end # whether getindex for the elements can potentially throw UndefRef diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 02ec583316de0f..825045670e3500 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -339,7 +339,7 @@ function CodeInstance(interp::AbstractInterpreter, result::InferenceResult; end function transform_result_for_cache(interp::AbstractInterpreter, - linfo::MethodInstance, valid_worlds::WorldRange, result::InferenceResult, + ::MethodInstance, valid_worlds::WorldRange, result::InferenceResult, can_discard_trees::Bool=may_discard_trees(interp)) return result.src end diff --git a/base/compiler/types.jl b/base/compiler/types.jl index 64410d231adda0..3017976b669491 100644 --- a/base/compiler/types.jl +++ b/base/compiler/types.jl @@ -70,7 +70,7 @@ end const NULL_ANALYSIS_RESULTS = AnalysisResults(nothing) """ - InferenceResult(linfo::MethodInstance, [argtypes::ForwardableArgtypes, ๐•ƒ::AbstractLattice]) + InferenceResult(mi::MethodInstance, [argtypes::ForwardableArgtypes, ๐•ƒ::AbstractLattice]) A type that represents the result of running type inference on a chunk of code. @@ -89,18 +89,18 @@ mutable struct InferenceResult analysis_results::AnalysisResults # AnalysisResults with e.g. result::ArgEscapeCache if optimized, otherwise NULL_ANALYSIS_RESULTS is_src_volatile::Bool # `src` has been cached globally as the compressed format already, allowing `src` to be used destructively ci::CodeInstance # CodeInstance if this result has been added to the cache - function InferenceResult(linfo::MethodInstance, cache_argtypes::Vector{Any}, overridden_by_const::BitVector) - # def = linfo.def + function InferenceResult(mi::MethodInstance, cache_argtypes::Vector{Any}, overridden_by_const::BitVector) + # def = mi.def # nargs = def isa Method ? Int(def.nargs) : 0 # @assert length(cache_argtypes) == nargs - return new(linfo, cache_argtypes, overridden_by_const, nothing, nothing, nothing, + return new(mi, cache_argtypes, overridden_by_const, nothing, nothing, nothing, WorldRange(), Effects(), Effects(), NULL_ANALYSIS_RESULTS, false) end end -InferenceResult(linfo::MethodInstance, ๐•ƒ::AbstractLattice=fallback_lattice) = - InferenceResult(linfo, matching_cache_argtypes(๐•ƒ, linfo)...) -InferenceResult(linfo::MethodInstance, argtypes::ForwardableArgtypes, ๐•ƒ::AbstractLattice=fallback_lattice) = - InferenceResult(linfo, matching_cache_argtypes(๐•ƒ, linfo, argtypes)...) +InferenceResult(mi::MethodInstance, ๐•ƒ::AbstractLattice=fallback_lattice) = + InferenceResult(mi, matching_cache_argtypes(๐•ƒ, mi)...) +InferenceResult(mi::MethodInstance, argtypes::ForwardableArgtypes, ๐•ƒ::AbstractLattice=fallback_lattice) = + InferenceResult(mi, matching_cache_argtypes(๐•ƒ, mi, argtypes)...) function stack_analysis_result!(inf_result::InferenceResult, @nospecialize(result)) return inf_result.analysis_results = AnalysisResults(result, inf_result.analysis_results) diff --git a/base/compiler/validation.jl b/base/compiler/validation.jl index fe3d002a43d6e1..3d0db1a09afcc5 100644 --- a/base/compiler/validation.jl +++ b/base/compiler/validation.jl @@ -64,17 +64,17 @@ struct InvalidCodeError <: Exception end InvalidCodeError(kind::AbstractString) = InvalidCodeError(kind, nothing) -function maybe_validate_code(linfo::MethodInstance, src::CodeInfo, kind::String) +function maybe_validate_code(mi::MethodInstance, src::CodeInfo, kind::String) if is_asserts() - errors = validate_code(linfo, src) + errors = validate_code(mi, src) if !isempty(errors) for e in errors - if linfo.def isa Method + if mi.def isa Method println(stderr, "WARNING: Encountered invalid ", kind, " code for method ", - linfo.def, ": ", e) + mi.def, ": ", e) else println(stderr, "WARNING: Encountered invalid ", kind, " code for top level expression in ", - linfo.def, ": ", e) + mi.def, ": ", e) end end error("") From 5f4dec10a3564a8ba6e007cde5f719b015fe6e6c Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Fri, 5 Apr 2024 10:44:53 +0200 Subject: [PATCH 088/123] make loading work with a `entryfile` entry in the manifest file (#53939) also soft deprecate the `path` entry in project file in favour of using `entryfile` instead Fixes the Julia Base part of #53937 --- base/loading.jl | 41 +++++++++++-------- doc/src/manual/code-loading.md | 12 +++--- test/loading.jl | 17 +++++++- test/project/ProjectPath/CustomPath.jl | 5 +++ test/project/ProjectPath/Manifest.toml | 18 ++++++++ test/project/ProjectPath/Project.toml | 7 ++++ .../ProjectPath/ProjectPathDep/CustomPath.jl | 5 +++ .../ProjectPath/ProjectPathDep/Project.toml | 4 ++ 8 files changed, 85 insertions(+), 24 deletions(-) create mode 100644 test/project/ProjectPath/CustomPath.jl create mode 100644 test/project/ProjectPath/Manifest.toml create mode 100644 test/project/ProjectPath/Project.toml create mode 100644 test/project/ProjectPath/ProjectPathDep/CustomPath.jl create mode 100644 test/project/ProjectPath/ProjectPathDep/Project.toml diff --git a/base/loading.jl b/base/loading.jl index 882ae3a68a836b..d49c8aa91e3b79 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -426,7 +426,6 @@ function locate_package_env(pkg::PkgId, stopenv::Union{String, Nothing}=nothing) @goto done end if path !== nothing - path = entry_path(path, pkg.name) envโ€ฒ = env @goto done end @@ -438,12 +437,15 @@ function locate_package_env(pkg::PkgId, stopenv::Union{String, Nothing}=nothing) # e.g. if they have been explicitly added to the project/manifest mbypath = manifest_uuid_path(Sys.STDLIB, pkg) if mbypath isa String - path = entry_path(mbypath, pkg.name) + path = mbypath envโ€ฒ = Sys.STDLIB @goto done end end @label done + if path !== nothing && !isfile_casesensitive(path) + path = nothing + end if cache !== nothing cache.located[(pkg, stopenv)] = path === nothing ? nothing : (path, something(envโ€ฒ)) end @@ -690,7 +692,7 @@ function manifest_uuid_path(env::String, pkg::PkgId)::Union{Nothing,String,Missi proj = project_file_name_uuid(project_file, pkg.name) if proj == pkg # if `pkg` matches the project, return the project itself - return project_file_path(project_file) + return project_file_path(project_file, pkg.name) end mby_ext = project_file_ext_path(project_file, pkg.name) mby_ext === nothing || return mby_ext @@ -725,7 +727,7 @@ end function project_file_ext_path(project_file::String, name::String) d = parsed_toml(project_file) - p = project_file_path(project_file) + p = dirname(project_file) exts = get(d, "extensions", nothing)::Union{Dict{String, Any}, Nothing} if exts !== nothing if name in keys(exts) @@ -744,9 +746,14 @@ function project_file_name_uuid(project_file::String, name::String)::PkgId return PkgId(uuid, name) end -function project_file_path(project_file::String) +function project_file_path(project_file::String, name::String) d = parsed_toml(project_file) - joinpath(dirname(project_file), get(d, "path", "")::String) + entryfile = get(d, "path", nothing)::Union{String, Nothing} + # "path" entry in project file is soft deprecated + if entryfile === nothing + entryfile = get(d, "entryfile", nothing)::Union{String, Nothing} + end + return entry_path(dirname(project_file), name, entryfile) end function workspace_manifest(project_file) @@ -837,12 +844,11 @@ function implicit_env_project_file_extension(dir::String, ext::PkgId) return nothing, nothing end -# given a path and a name, return the entry point -function entry_path(path::String, name::String)::Union{Nothing,String} +# given a path, name, and possibly an entryfile, return the entry point +function entry_path(path::String, name::String, entryfile::Union{Nothing,String})::String isfile_casesensitive(path) && return normpath(path) - path = normpath(joinpath(path, "src", "$name.jl")) - isfile_casesensitive(path) && return path - return nothing # source not found + entrypoint = entryfile === nothing ? joinpath("src", "$name.jl") : entryfile + return normpath(joinpath(path, entrypoint)) end ## explicit project & manifest API ## @@ -1016,15 +1022,16 @@ end function explicit_manifest_entry_path(manifest_file::String, pkg::PkgId, entry::Dict{String,Any}) path = get(entry, "path", nothing)::Union{Nothing, String} + entryfile = get(entry, "entryfile", nothing)::Union{Nothing, String} if path !== nothing - path = normpath(abspath(dirname(manifest_file), path)) + path = entry_path(normpath(abspath(dirname(manifest_file), path)), pkg.name, entryfile) return path end hash = get(entry, "git-tree-sha1", nothing)::Union{Nothing, String} if hash === nothing mbypath = manifest_uuid_path(Sys.STDLIB, pkg) - if mbypath isa String - return entry_path(mbypath, pkg.name) + if mbypath isa String && isfile(mbypath) + return mbypath end return nothing end @@ -1034,7 +1041,7 @@ function explicit_manifest_entry_path(manifest_file::String, pkg::PkgId, entry:: for slug in (version_slug(uuid, hash), version_slug(uuid, hash, 4)) for depot in DEPOT_PATH path = joinpath(depot, "packages", pkg.name, slug) - ispath(path) && return abspath(path) + ispath(path) && return entry_path(abspath(path), pkg.name, entryfile) end end # no depot contains the package, return missing to stop looking @@ -2504,8 +2511,8 @@ function require_stdlib(uuidkey::PkgId, ext::Union{Nothing, String}=nothing) uuidkey = PkgId(uuid5(uuidkey.uuid, ext), ext) end #mbypath = manifest_uuid_path(env, uuidkey) - #if mbypath isa String - # sourcepath = entry_path(mbypath, uuidkey.name) + #if mbypath isa String && isfile_casesensitive(mbypath) + # sourcepath = mbypath #else # # if the user deleted the stdlib folder, we next try using their environment # sourcepath = locate_package_env(uuidkey) diff --git a/doc/src/manual/code-loading.md b/doc/src/manual/code-loading.md index 9e753d2a7de337..35d88ed13bc896 100644 --- a/doc/src/manual/code-loading.md +++ b/doc/src/manual/code-loading.md @@ -160,11 +160,12 @@ What happens if `import Zebra` is evaluated in the main `App` code base? Since ` **The paths map** of a project environment is extracted from the manifest file. The path of a package `uuid` named `X` is determined by these rules (in order): 1. If the project file in the directory matches `uuid` and name `X`, then either: - - It has a toplevel `path` entry, then `uuid` will be mapped to that path, interpreted relative to the directory containing the project file. - - Otherwise, `uuid` is mapped to `src/X.jl` relative to the directory containing the project file. -2. If the above is not the case and the project file has a corresponding manifest file and the manifest contains a stanza matching `uuid` then: - - If it has a `path` entry, use that path (relative to the directory containing the manifest file). - - If it has a `git-tree-sha1` entry, compute a deterministic hash function of `uuid` and `git-tree-sha1`โ€”call it `slug`โ€”and look for a directory named `packages/X/$slug` in each directory in the Julia `DEPOT_PATH` global array. Use the first such directory that exists. + - It has a toplevel `entryfile` entry, then `uuid` will be mapped to that path, interpreted relative to the directory containing the project file. + - Otherwise, `uuid` is mapped to `src/X.jl` relative to the directory containing the project file. +2. 1. If the above is not the case and the project file has a corresponding manifest file and the manifest contains a stanza matching `uuid` then: + - If it has a `path` entry, use that path (relative to the directory containing the manifest file). + - If it has a `git-tree-sha1` entry, compute a deterministic hash function of `uuid` and `git-tree-sha1`โ€”call it `slug`โ€”and look for a directory named `packages/X/$slug` in each directory in the Julia `DEPOT_PATH` global array. Use the first such directory that exists. + 2. If this is a directory then `uuid` is mapped to `src/X.jl` unless the matching manifest stanza has an `entryfile` entry in which case this is used. In both cases, these are relative to the directory in 2.1. If any of these result in success, the path to the source code entry point will be either that result, the relative path from that result plus `src/X.jl`; otherwise, there is no path mapping for `uuid`. When loading `X`, if no source code path is found, the lookup will fail, and the user may be prompted to install the appropriate package version or to take other corrective action (e.g. declaring `X` as a dependency). @@ -208,7 +209,6 @@ This example map includes three different kinds of package locations (the first 2. The public `Priv` and `Zebra` packages are in the system depot, where packages installed and managed by the system administrator live. These are available to all users on the system. 3. The `Pub` package is in the user depot, where packages installed by the user live. These are only available to the user who installed them. - ### Package directories Package directories provide a simpler kind of environment without the ability to handle name collisions. In a package directory, the set of top-level packages is the set of subdirectories that "look like" packages. A package `X` exists in a package directory if the directory contains one of the following "entry point" files: diff --git a/test/loading.jl b/test/loading.jl index 94f27ecf888bb2..182db7c4a6d15b 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -1609,5 +1609,20 @@ end finally copy!(LOAD_PATH, old_load_path) - end + end +end + +@testset "project path handling" begin + old_load_path = copy(LOAD_PATH) + try + push!(LOAD_PATH, joinpath(@__DIR__, "project", "ProjectPath")) + id_project = Base.identify_package("ProjectPath") + Base.locate_package(id_project) + @test Base.locate_package(id_project) == joinpath(@__DIR__, "project", "ProjectPath", "CustomPath.jl") + + id_dep = Base.identify_package("ProjectPathDep") + @test Base.locate_package(id_dep) == joinpath(@__DIR__, "project", "ProjectPath", "ProjectPathDep", "CustomPath.jl") + finally + copy!(LOAD_PATH, old_load_path) + end end diff --git a/test/project/ProjectPath/CustomPath.jl b/test/project/ProjectPath/CustomPath.jl new file mode 100644 index 00000000000000..8fe764fa066dc6 --- /dev/null +++ b/test/project/ProjectPath/CustomPath.jl @@ -0,0 +1,5 @@ +module ProjectPath + +greet() = print("Hello World!") + +end # module ProjectPath diff --git a/test/project/ProjectPath/Manifest.toml b/test/project/ProjectPath/Manifest.toml new file mode 100644 index 00000000000000..123e7f575062a3 --- /dev/null +++ b/test/project/ProjectPath/Manifest.toml @@ -0,0 +1,18 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.12.0-DEV" +manifest_format = "2.0" +project_hash = "51ade905d618e4aa369bc869841376219cc36cb1" + +[[deps.ProjectPath]] +deps = ["ProjectPathDep"] +path = "." +entryfile = "CustomPath.jl" +uuid = "32833bde-7fc1-4d28-8365-9d01e1bcbc1b" +version = "0.1.0" + +[[deps.ProjectPathDep]] +path = "ProjectPathDep" +entryfile = "CustomPath.jl" +uuid = "f18633fc-8799-43ff-aa06-99ed830dc572" +version = "0.1.0" diff --git a/test/project/ProjectPath/Project.toml b/test/project/ProjectPath/Project.toml new file mode 100644 index 00000000000000..a434f78e9c2116 --- /dev/null +++ b/test/project/ProjectPath/Project.toml @@ -0,0 +1,7 @@ +name = "ProjectPath" +uuid = "32833bde-7fc1-4d28-8365-9d01e1bcbc1b" +entryfile = "CustomPath.jl" +version = "0.1.0" + +[deps] +ProjectPathDep = "f18633fc-8799-43ff-aa06-99ed830dc572" diff --git a/test/project/ProjectPath/ProjectPathDep/CustomPath.jl b/test/project/ProjectPath/ProjectPathDep/CustomPath.jl new file mode 100644 index 00000000000000..adbe508f0c7f9b --- /dev/null +++ b/test/project/ProjectPath/ProjectPathDep/CustomPath.jl @@ -0,0 +1,5 @@ +module ProjectPathDep + +greet() = print("Hello World!") + +end # module ProjectPathDep diff --git a/test/project/ProjectPath/ProjectPathDep/Project.toml b/test/project/ProjectPath/ProjectPathDep/Project.toml new file mode 100644 index 00000000000000..c69e54e8c9390f --- /dev/null +++ b/test/project/ProjectPath/ProjectPathDep/Project.toml @@ -0,0 +1,4 @@ +name = "ProjectPathDep" +uuid = "f18633fc-8799-43ff-aa06-99ed830dc572" +version = "0.1.0" +entryfile = "CustomPath.jl" From d505c8cdafa79387139f6cf3bf3aa43f0118c087 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Fri, 5 Apr 2024 23:18:05 +0530 Subject: [PATCH 089/123] `LazyString` in `LinearAlgebra.checksquare` error message (#53961) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reduces dynamic dispatch and makes JET happier. Testing on v1.11: ```julia julia> import LinearAlgebra: checksquare julia> using JET julia> @report_opt checksquare(rand(2,2), rand(2,2)) โ•โ•โ•โ•โ• 4 possible errors found โ•โ•โ•โ•โ• โ”Œ checksquare(::Matrix{Float64}, ::Matrix{Float64}) @ LinearAlgebra /cache/build/builder-amdci4-1/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/LinearAlgebra/src/LinearAlgebra.jl:307 โ”‚โ”Œ string(::String, ::Tuple{Int64, Int64}) @ Base ./strings/io.jl:189 โ”‚โ”‚โ”Œ print_to_string(::String, ::Tuple{Int64, Int64}) @ Base ./strings/io.jl:150 โ”‚โ”‚โ”‚โ”Œ _unsafe_take!(io::IOBuffer) @ Base ./iobuffer.jl:494 โ”‚โ”‚โ”‚โ”‚โ”Œ wrap(::Type{Array}, m::MemoryRef{UInt8}, l::Int64) @ Base ./array.jl:3101 โ”‚โ”‚โ”‚โ”‚โ”‚ failed to optimize due to recursion: wrap(::Type{Array}, ::MemoryRef{UInt8}, ::Int64) โ”‚โ”‚โ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚โ”‚โ”‚โ”Œ print_to_string(::String, ::Vararg{Any}) @ Base ./strings/io.jl:143 โ”‚โ”‚โ”‚โ”‚ runtime dispatch detected: Base._str_sizehint(%17::Any)::Int64 โ”‚โ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚โ”‚โ”‚โ”Œ print_to_string(::String, ::Vararg{Any}) @ Base ./strings/io.jl:148 โ”‚โ”‚โ”‚โ”‚ runtime dispatch detected: print(%59::IOBuffer, %97::Any)::Any โ”‚โ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚โ”‚โ”‚โ”Œ string(::String, ::Int64, ::String, ::Tuple{Int64}, ::String, ::Int64, ::String, ::Int64, ::String) @ Base ./strings/io.jl:189 โ”‚โ”‚โ”‚โ”‚ failed to optimize due to recursion: string(::String, ::Int64, ::String, ::Tuple{Int64}, ::String, ::Int64, ::String, ::Int64, ::String) โ”‚โ”‚โ”‚โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ julia> function checksquare(A...) # This PR sizes = Int[] for a in A size(a,1)==size(a,2) || throw(DimensionMismatch(lazy"matrix is not square: dimensions are $(size(a))")) push!(sizes, size(a,1)) end return sizes end checksquare (generic function with 2 methods) julia> @report_opt checksquare(rand(2,2), rand(2,2)) No errors detected ``` --- stdlib/LinearAlgebra/src/LinearAlgebra.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/LinearAlgebra.jl b/stdlib/LinearAlgebra/src/LinearAlgebra.jl index d8dd730779c265..6ed272ab42f023 100644 --- a/stdlib/LinearAlgebra/src/LinearAlgebra.jl +++ b/stdlib/LinearAlgebra/src/LinearAlgebra.jl @@ -297,14 +297,14 @@ julia> LinearAlgebra.checksquare(A, B) """ function checksquare(A) m,n = size(A) - m == n || throw(DimensionMismatch("matrix is not square: dimensions are $(size(A))")) + m == n || throw(DimensionMismatch(lazy"matrix is not square: dimensions are $(size(A))")) m end function checksquare(A...) sizes = Int[] for a in A - size(a,1)==size(a,2) || throw(DimensionMismatch("matrix is not square: dimensions are $(size(a))")) + size(a,1)==size(a,2) || throw(DimensionMismatch(lazy"matrix is not square: dimensions are $(size(a))")) push!(sizes, size(a,1)) end return sizes From 0e59c9eea225ed186671de1e5fd0c249b1495c1d Mon Sep 17 00:00:00 2001 From: Zentrik Date: Fri, 5 Apr 2024 19:12:48 +0100 Subject: [PATCH 090/123] Use StringMemory instead of StringVector where possible (#53962) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On `1.11.0-alpha2` Old: ```julia @benchmark Base.dec($0x1, $0, $false) BenchmarkTools.Trial: 10000 samples with 994 evaluations. Range (min โ€ฆ max): 33.702 ns โ€ฆ 4.242 ฮผs โ”Š GC (min โ€ฆ max): 0.00% โ€ฆ 97.61% Time (median): 37.626 ns โ”Š GC (median): 0.00% Time (mean ยฑ ฯƒ): 45.787 ns ยฑ 147.794 ns โ”Š GC (mean ยฑ ฯƒ): 14.53% ยฑ 4.47% โ–„โ–…โ–†โ–‡โ–ˆโ–‡โ–‡โ–…โ–ƒโ–ƒโ–‚โ–‚โ–‚โ– โ–โ–‚โ–โ–โ– โ–โ– โ– โ–‚ โ–„โ–‡โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‡โ–‡โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‡โ–ˆโ–†โ–†โ–„โ–„โ–ƒโ–„โ–…โ–„โ–†โ–‡โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–†โ–…โ–…โ–‡โ–†โ–…โ–†โ–„โ–„โ–…โ–„โ–„โ–„โ–โ–… โ–ˆ 33.7 ns Histogram: log(frequency) by time 67.5 ns < Memory estimate: 88 bytes, allocs estimate: 3. ``` New: ```julia BenchmarkTools.Trial: 10000 samples with 995 evaluations. Range (min โ€ฆ max): 27.538 ns โ€ฆ 3.397 ฮผs โ”Š GC (min โ€ฆ max): 0.00% โ€ฆ 97.86% Time (median): 30.151 ns โ”Š GC (median): 0.00% Time (mean ยฑ ฯƒ): 34.547 ns ยฑ 105.101 ns โ”Š GC (mean ยฑ ฯƒ): 10.37% ยฑ 3.39% โ– โ–ˆโ–†โ–ƒ โ– โ–‚โ–‚โ–ƒโ–ƒโ–…โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–†โ–ˆโ–ˆโ–ˆโ–ˆโ–†โ–„โ–„โ–ƒโ–ƒโ–ƒโ–ƒโ–ƒโ–ƒโ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–โ–‚โ–‚โ–‚โ–‚โ–‚โ–โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚โ–‚ โ–ƒ 27.5 ns Histogram: frequency by time 43.8 ns < Memory estimate: 56 bytes, allocs estimate: 2. ``` Fixes #53950, actually now even faster than `1.10.2`. It doesn't look like the length is ever changed and we don't return these `StringMemory`s so this change should be fine. --- base/gmp.jl | 2 +- base/intfuncs.jl | 12 ++++++------ base/strings/util.jl | 2 +- base/uuid.jl | 2 +- stdlib/FileWatching/src/pidfile.jl | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index beeec879ed4873..a7caa8dfcdafde 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -754,7 +754,7 @@ function string(n::BigInt; base::Integer = 10, pad::Integer = 1) iszero(n) && pad < 1 && return "" nd1 = ndigits(n, base=base) nd = max(nd1, pad) - sv = Base.StringVector(nd + isneg(n)) + sv = Base.StringMemory(nd + isneg(n)) GC.@preserve sv MPZ.get_str!(pointer(sv) + nd - nd1, base, n) @inbounds for i = (1:nd-nd1) .+ isneg(n) sv[i] = '0' % UInt8 diff --git a/base/intfuncs.jl b/base/intfuncs.jl index f5185b0a9fd176..a89d45eb55fc11 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -742,7 +742,7 @@ ndigits(x::Integer; base::Integer=10, pad::Integer=1) = max(pad, ndigits0z(x, ba function bin(x::Unsigned, pad::Int, neg::Bool) m = top_set_bit(x) n = neg + max(pad, m) - a = StringVector(n) + a = StringMemory(n) # for i in 0x0:UInt(n-1) # automatic vectorization produces redundant codes # @inbounds a[n - i] = 0x30 + (((x >> i) % UInt8)::UInt8 & 0x1) # end @@ -769,7 +769,7 @@ end function oct(x::Unsigned, pad::Int, neg::Bool) m = div(top_set_bit(x) + 2, 3) n = neg + max(pad, m) - a = StringVector(n) + a = StringMemory(n) i = n while i > neg @inbounds a[i] = 0x30 + ((x % UInt8)::UInt8 & 0x7) @@ -844,7 +844,7 @@ end function dec(x::Unsigned, pad::Int, neg::Bool) n = neg + ndigits(x, pad=pad) - a = StringVector(n) + a = StringMemory(n) append_c_digits_fast(n, x, a, 1) neg && (@inbounds a[1] = 0x2d) # UInt8('-') String(a) @@ -853,7 +853,7 @@ end function hex(x::Unsigned, pad::Int, neg::Bool) m = 2 * sizeof(x) - (leading_zeros(x) >> 2) n = neg + max(pad, m) - a = StringVector(n) + a = StringMemory(n) i = n while i >= 2 b = (x % UInt8)::UInt8 @@ -880,7 +880,7 @@ function _base(base::Integer, x::Integer, pad::Int, neg::Bool) b = (base % Int)::Int digits = abs(b) <= 36 ? base36digits : base62digits n = neg + ndigits(x, base=b, pad=pad) - a = StringVector(n) + a = StringMemory(n) i = n @inbounds while i > neg if b > 0 @@ -956,7 +956,7 @@ julia> bitstring(2.2) function bitstring(x::T) where {T} isprimitivetype(T) || throw(ArgumentError("$T not a primitive type")) sz = sizeof(T) * 8 - str = StringVector(sz) + str = StringMemory(sz) i = sz @inbounds while i >= 4 b = UInt32(sizeof(T) == 1 ? bitcast(UInt8, x) : trunc_int(UInt8, x)) diff --git a/base/strings/util.jl b/base/strings/util.jl index 219b329d7924d1..4b701001a86763 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -1061,7 +1061,7 @@ function bytes2hex end function bytes2hex(itr) eltype(itr) === UInt8 || throw(ArgumentError("eltype of iterator not UInt8")) - b = Base.StringVector(2*length(itr)) + b = Base.StringMemory(2*length(itr)) @inbounds for (i, x) in enumerate(itr) b[2i - 1] = hex_chars[1 + x >> 4] b[2i ] = hex_chars[1 + x & 0xf] diff --git a/base/uuid.jl b/base/uuid.jl index 1ed0b81b3f178e..9b2da3c6409db7 100644 --- a/base/uuid.jl +++ b/base/uuid.jl @@ -90,7 +90,7 @@ let groupings = [36:-1:25; 23:-1:20; 18:-1:15; 13:-1:10; 8:-1:1] global string function string(u::UUID) u = u.value - a = Base.StringVector(36) + a = Base.StringMemory(36) for i in groupings @inbounds a[i] = hex_chars[1 + u & 0xf] u >>= 4 diff --git a/stdlib/FileWatching/src/pidfile.jl b/stdlib/FileWatching/src/pidfile.jl index 0ee86e70f84656..4c821a3d897e47 100644 --- a/stdlib/FileWatching/src/pidfile.jl +++ b/stdlib/FileWatching/src/pidfile.jl @@ -280,7 +280,7 @@ function open_exclusive(path::String; end function _rand_filename(len::Int=4) # modified from Base.Libc - slug = Base.StringVector(len) + slug = Base.StringMemory(len) chars = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" for i = 1:len slug[i] = chars[(Libc.rand() % length(chars)) + 1] From 59c3c71c6e75e2ea6872d6feb75f830c5e5c0b4d Mon Sep 17 00:00:00 2001 From: Cody Tapscott <84105208+topolarity@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:50:20 -0400 Subject: [PATCH 091/123] TOML: Improve type-stability of BigInt/UInt support (#53955) From a type-stability perspective, this restores a lot of our behavior before #47903. As it turns out, 10 of the 11 uses of `parse_int` (now called `parse_integer`) introduced in that PR are unnecessary since the TOML format already requires the parsed value to be within a very limited range. Note that this change does not actually revert any functionality (in contrast to #49576) --- base/toml_parser.jl | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/base/toml_parser.jl b/base/toml_parser.jl index 23fc14a894c069..b31e256517a1e2 100644 --- a/base/toml_parser.jl +++ b/base/toml_parser.jl @@ -854,7 +854,7 @@ function parse_number_or_date_start(l::Parser) ate, contains_underscore = @try accept_batch_underscore(l, isdigit, readed_zero) read_underscore |= contains_underscore if (read_digit || ate) && ok_end_value(peek(l)) - return parse_int(l, contains_underscore) + return parse_integer(l, contains_underscore) end # Done with integers here @@ -904,7 +904,18 @@ function parse_float(l::Parser, contains_underscore)::Err{Float64} return v end -for (name, T1, T2, n1, n2) in (("int", Int64, Int128, 17, 33), +function parse_int(l::Parser, contains_underscore, base=nothing)::Err{Int64} + s = take_string_or_substring(l, contains_underscore) + v = try + Base.parse(Int64, s; base=base) + catch e + e isa Base.OverflowError && return(ParserError(ErrOverflowError)) + error("internal parser error: did not correctly discredit $(repr(s)) as an int") + end + return v +end + +for (name, T1, T2, n1, n2) in (("integer", Int64, Int128, 17, 33), ("hex", UInt64, UInt128, 18, 34), ("oct", UInt64, UInt128, 24, 45), ("bin", UInt64, UInt128, 66, 130), @@ -1103,7 +1114,7 @@ function _parse_local_time(l::Parser, skip_hour=false)::Err{NTuple{4, Int64}} end # DateTime in base only manages 3 significant digits in fractional # second - fractional_second = parse_int(l, false) + fractional_second = parse_int(l, false)::Int64 # Truncate off the rest eventual digits accept_batch(l, isdigit) end From d963a3469d742c633bc4d6f0279dd55f19e6c353 Mon Sep 17 00:00:00 2001 From: Neven Sajko Date: Fri, 5 Apr 2024 21:02:33 +0200 Subject: [PATCH 092/123] profile: doc: update the `Allocs.@profile` doc string (#53825) --- stdlib/Profile/src/Allocs.jl | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/stdlib/Profile/src/Allocs.jl b/stdlib/Profile/src/Allocs.jl index a1cee988710115..31d703a151ad88 100644 --- a/stdlib/Profile/src/Allocs.jl +++ b/stdlib/Profile/src/Allocs.jl @@ -54,18 +54,17 @@ julia> last(sort(results.allocs, by=x->x.size)) Profile.Allocs.Alloc(Vector{Any}, Base.StackTraces.StackFrame[_new_array_ at array.c:127, ...], 5576) ``` -The best way to visualize these is currently with the -[PProf.jl](https://github.com/JuliaPerf/PProf.jl) package, -by invoking `PProf.Allocs.pprof`. - -!!! note - The current implementation of the Allocations Profiler does not - capture types for all allocations. Allocations for which the profiler - could not capture the type are represented as having type - `Profile.Allocs.UnknownType`. - - You can read more about the missing types and the plan to improve this, here: - . +See the profiling tutorial in the Julia documentation for more information. + +!!! compat "Julia 1.11" + + Older versions of Julia could not capture types in all cases. In older versions of + Julia, if you see an allocation of type `Profile.Allocs.UnknownType`, it means that + the profiler doesn't know what type of object was allocated. This mainly happened when + the allocation was coming from generated code produced by the compiler. See + [issue #43688](https://github.com/JuliaLang/julia/issues/43688) for more info. + + Since Julia 1.11, all allocations should have a type reported. !!! compat "Julia 1.8" The allocation profiler was added in Julia 1.8. From c707a53fe6bc6f9dec10f3a8b7ecceb61cc110fb Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sat, 6 Apr 2024 17:33:33 +0530 Subject: [PATCH 093/123] Explicit namespaces in sort-related docstrings (#53968) This represents the unexported names by the fully qualified namespace, which makes it simpler to interpret the keyword arguments. Otherwise, for example, it's not obvious where `Forward` comes from in the `sort` docstring. Also, replaces some occurrences of `instance <: Algorithm` by `instance isa Algorithm`, which is the correct relation. This is also closer to English, which helps with readability. --------- Co-authored-by: Lilith Orion Hafner --- base/sort.jl | 58 ++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/base/sort.jl b/base/sort.jl index 38e89e3d3a0ce3..37b05d7c8397a9 100644 --- a/base/sort.jl +++ b/base/sort.jl @@ -62,7 +62,7 @@ function issorted(itr, order::Ordering) end """ - issorted(v, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) + issorted(v, lt=isless, by=identity, rev::Bool=false, order::Base.Order.Ordering=Base.Order.Forward) Test whether a collection is in sorted order. The keywords modify what order is considered sorted, as described in the [`sort!`](@ref) documentation. @@ -514,7 +514,7 @@ end ## sorting algorithm components ## """ - _sort!(v::AbstractVector, a::Algorithm, o::Ordering, kw; t, offset) + _sort!(v::AbstractVector, a::Base.Sort.Algorithm, o::Base.Order.Ordering, kw; t, offset) An internal function that sorts `v` using the algorithm `a` under the ordering `o`, subject to specifications provided in `kw` (such as `lo` and `hi` in which case it only @@ -539,7 +539,7 @@ function _sort! end # TODO: delete this optimization when views have no overhead. const UnwrappableSubArray = SubArray{T, 1, <:AbstractArray{T}, <:Tuple{AbstractUnitRange, Vararg{Number}}, true} where T """ - SubArrayOptimization(next) <: Algorithm + SubArrayOptimization(next) isa Base.Sort.Algorithm Unwrap certain known SubArrays because views have a performance overhead ๐Ÿ˜ข @@ -566,7 +566,7 @@ function _sort!(v::UnwrappableSubArray, a::SubArrayOptimization, o::Ordering, kw end """ - MissingOptimization(next) <: Algorithm + MissingOptimization(next) isa Base.Sort.Algorithm Filter out missing values. @@ -625,7 +625,7 @@ function send_to_end!(f::F, v::AbstractVector; lo=firstindex(v), hi=lastindex(v) i - 1 end """ - send_to_end!(f::Function, v::AbstractVector, o::DirectOrdering[, end_stable]; lo, hi) + send_to_end!(f::Function, v::AbstractVector, o::Base.Order.DirectOrdering[, end_stable]; lo, hi) Return `(a, b)` where `v[a:b]` are the elements that are not sent to the end. @@ -679,7 +679,7 @@ end """ - IEEEFloatOptimization(next) <: Algorithm + IEEEFloatOptimization(next) isa Base.Sort.Algorithm Move NaN values to the end, partition by sign, and reinterpret the rest as unsigned integers. @@ -724,7 +724,7 @@ end """ - BoolOptimization(next) <: Algorithm + BoolOptimization(next) isa Base.Sort.Algorithm Sort `AbstractVector{Bool}`s using a specialized version of counting sort. @@ -751,7 +751,7 @@ end """ - IsUIntMappable(yes, no) <: Algorithm + IsUIntMappable(yes, no) isa Base.Sort.Algorithm Determines if the elements of a vector can be mapped to unsigned integers while preserving their order under the specified ordering. @@ -773,7 +773,7 @@ end """ - Small{N}(small=SMALL_ALGORITHM, big) <: Algorithm + Small{N}(small=SMALL_ALGORITHM, big) isa Base.Sort.Algorithm Sort inputs with `length(lo:hi) <= N` using the `small` algorithm. Otherwise use the `big` algorithm. @@ -845,7 +845,7 @@ end """ - CheckSorted(next) <: Algorithm + CheckSorted(next) isa Base.Sort.Algorithm Check if the input is already sorted and for large inputs, also check if it is reverse-sorted. The reverse-sorted check is unstable. @@ -872,7 +872,7 @@ end """ - ComputeExtrema(next) <: Algorithm + ComputeExtrema(next) isa Base.Sort.Algorithm Compute the extrema of the input under the provided order. @@ -898,7 +898,7 @@ end """ - ConsiderCountingSort(counting=CountingSort(), next) <: Algorithm + ConsiderCountingSort(counting=CountingSort(), next) isa Base.Sort.Algorithm If the input's range is small enough, use the `counting` algorithm. Otherwise, dispatch to the `next` algorithm. @@ -926,7 +926,7 @@ _sort!(v::AbstractVector, a::ConsiderCountingSort, o::Ordering, kw) = _sort!(v, """ - CountingSort <: Algorithm + CountingSort() isa Base.Sort.Algorithm Use the counting sort algorithm. @@ -962,7 +962,7 @@ end """ - ConsiderRadixSort(radix=RadixSort(), next) <: Algorithm + ConsiderRadixSort(radix=RadixSort(), next) isa Base.Sort.Algorithm If the number of bits in the input's range is small enough and the input supports efficient bitshifts, use the `radix` algorithm. Otherwise, dispatch to the `next` algorithm. @@ -985,7 +985,7 @@ end """ - RadixSort <: Algorithm + RadixSort() isa Base.Sort.Algorithm Use the radix sort algorithm. @@ -1040,8 +1040,8 @@ end """ - ScratchQuickSort(next::Algorithm=SMALL_ALGORITHM) <: Algorithm - ScratchQuickSort(lo::Union{Integer, Missing}, hi::Union{Integer, Missing}=lo, next::Algorithm=SMALL_ALGORITHM) <: Algorithm + ScratchQuickSort(next::Base.Sort.Algorithm=Base.Sort.SMALL_ALGORITHM) isa Base.Sort.Algorithm + ScratchQuickSort(lo::Union{Integer, Missing}, hi::Union{Integer, Missing}=lo, next::Base.Sort.Algorithm=Base.Sort.SMALL_ALGORITHM) isa Base.Sort.Algorithm Use the `ScratchQuickSort` algorithm with the `next` algorithm as a base case. @@ -1157,7 +1157,7 @@ end """ - BracketedSort(target[, next::Algorithm]) <: Algorithm + BracketedSort(target[, next::Algorithm]) isa Base.Sort.Algorithm Perform a partialsort for the elements that fall into the indices specified by the `target` using BracketedSort with the `next` algorithm for subproblems. @@ -1346,7 +1346,7 @@ end """ - StableCheckSorted(next) <: Algorithm + StableCheckSorted(next) isa Base.Sort.Algorithm Check if an input is sorted and/or reverse-sorted. @@ -1446,7 +1446,7 @@ end ## default sorting policy ## """ - InitialOptimizations(next) <: Algorithm + InitialOptimizations(next) isa Base.Sort.Algorithm Attempt to apply a suite of low-cost optimizations to the input vector before sorting. These optimizations may be automatically applied by the `sort!` family of functions when @@ -1593,7 +1593,7 @@ defalg(v::AbstractArray{Missing}) = DEFAULT_UNSTABLE # for method disambiguation defalg(v::AbstractArray{Union{}}) = DEFAULT_UNSTABLE # for method disambiguation """ - sort!(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) + sort!(v; alg::Base.Sort.Algorithm=Base.Sort.defalg(v), lt=isless, by=identity, rev::Bool=false, order::Base.Order.Ordering=Base.Order.Forward) Sort the vector `v` in place. A stable algorithm is used by default: the ordering of elements that compare equal is preserved. A specific algorithm can @@ -1706,7 +1706,7 @@ function sort!(v::AbstractVector{T}; end """ - sort(v; alg::Algorithm=defalg(v), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) + sort(v; alg::Base.Sort.Algorithm=Base.Sort.defalg(v), lt=isless, by=identity, rev::Bool=false, order::Base.Order.Ordering=Base.Order.Forward) Variant of [`sort!`](@ref) that returns a sorted copy of `v` leaving `v` itself unmodified. @@ -1829,7 +1829,7 @@ end ## sortperm: the permutation to sort an array ## """ - sortperm(A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, [dims::Integer]) + sortperm(A; alg::Base.Sort.Algorithm=Base.Sort.DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Base.Order.Ordering=Base.Order.Forward, [dims::Integer]) Return a permutation vector or array `I` that puts `A[I]` in sorted order along the given dimension. If `A` has more than one dimension, then the `dims` keyword argument must be specified. The order is specified @@ -1907,7 +1907,7 @@ end """ - sortperm!(ix, A; alg::Algorithm=DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward, [dims::Integer]) + sortperm!(ix, A; alg::Base.Sort.Algorithm=Base.Sort.DEFAULT_UNSTABLE, lt=isless, by=identity, rev::Bool=false, order::Base.Order.Ordering=Base.Order.Forward, [dims::Integer]) Like [`sortperm`](@ref), but accepts a preallocated index vector or array `ix` with the same `axes` as `A`. `ix` is initialized to contain the values `LinearIndices(A)`. @@ -1995,7 +1995,7 @@ end ## sorting multi-dimensional arrays ## """ - sort(A; dims::Integer, alg::Algorithm=defalg(A), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) + sort(A; dims::Integer, alg::Base.Sort.Algorithm=Base.Sort.defalg(A), lt=isless, by=identity, rev::Bool=false, order::Base.Order.Ordering=Base.Order.Forward) Sort a multidimensional array `A` along the given dimension. See [`sort!`](@ref) for a description of possible @@ -2067,7 +2067,7 @@ end """ - sort!(A; dims::Integer, alg::Algorithm=defalg(A), lt=isless, by=identity, rev::Bool=false, order::Ordering=Forward) + sort!(A; dims::Integer, alg::Base.Sort.Algorithm=Base.Sort.defalg(A), lt=isless, by=identity, rev::Bool=false, order::Base.Order.Ordering=Base.Order.Forward) Sort the multidimensional array `A` along dimension `dims`. See the one-dimensional version of [`sort!`](@ref) for a description of @@ -2139,7 +2139,7 @@ get_value(::Val{x}) where x = x ## uint mapping to allow radix sorting primitives other than UInts ## """ - UIntMappable(T::Type, order::Ordering) + UIntMappable(T::Type, order::Base.Order.Ordering) Return `typeof(uint_map(x::T, order))` if [`uint_map`](@ref) and [`uint_unmap`](@ref) are implemented. @@ -2149,7 +2149,7 @@ If either is not implemented, return `nothing`. UIntMappable(T::Type, order::Ordering) = nothing """ - uint_map(x, order::Ordering)::Unsigned + uint_map(x, order::Base.Order.Ordering)::Unsigned Map `x` to an un unsigned integer, maintaining sort order. @@ -2163,7 +2163,7 @@ See also: [`UIntMappable`](@ref) [`uint_unmap`](@ref) function uint_map end """ - uint_unmap(T::Type, u::Unsigned, order::Ordering) + uint_unmap(T::Type, u::Unsigned, order::Base.Order.Ordering) Reconstruct the unique value `x::T` that uint_maps to `u`. Satisfies `x === uint_unmap(T, uint_map(x::T, order), order)` for all `x <: T`. From 273d91e0dab8ff08d427eaebd58627b2bbd4d807 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Sat, 6 Apr 2024 08:12:39 -0500 Subject: [PATCH 094/123] Make reshape and view on Memory produce Arrays and delete wrap (#53896) - Make reshape and view with one based indexing on Memory produce Arrays - delete wrap Implements https://github.com/JuliaLang/julia/issues/53552#issuecomment-2024288283 --------- Co-authored-by: Jameson Nash --- HISTORY.md | 1 - base/array.jl | 51 ------------------------------------------ base/exports.jl | 1 - base/genericmemory.jl | 24 ++++++++++++++++++++ base/iobuffer.jl | 12 ++++------ base/strings/string.jl | 5 ++++- doc/src/base/arrays.md | 1 - test/arrayops.jl | 48 +++++++++++++++++++++++++-------------- 8 files changed, 63 insertions(+), 80 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 3eaec3c6d07746..55bbfa1335a0ed 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -86,7 +86,6 @@ New library functions * `copyuntil(out, io, delim)` and `copyline(out, io)` copy data into an `out::IO` stream ([#48273]). * `eachrsplit(string, pattern)` iterates split substrings right to left. * `Sys.username()` can be used to return the current user's username ([#51897]). -* `wrap(Array, m::Union{MemoryRef{T}, Memory{T}}, dims)` is the safe counterpart to `unsafe_wrap` ([#52049]). * `GC.logging_enabled()` can be used to test whether GC logging has been enabled via `GC.enable_logging` ([#51647]). * `IdSet` is now exported from Base and considered public ([#53262]). diff --git a/base/array.jl b/base/array.jl index ef91077dd6e96b..7676b380923ee8 100644 --- a/base/array.jl +++ b/base/array.jl @@ -3080,54 +3080,3 @@ intersect(r::AbstractRange, v::AbstractVector) = intersect(v, r) _getindex(v, i) end end - -""" - wrap(Array, m::Union{Memory{T}, MemoryRef{T}}, dims) - -Create an array of size `dims` using `m` as the underlying memory. This can be thought of as a safe version -of [`unsafe_wrap`](@ref) utilizing `Memory` or `MemoryRef` instead of raw pointers. -""" -function wrap end - -# validity checking for _wrap calls, separate from allocation of Array so that it can be more likely to inline into the caller -function _wrap(ref::MemoryRef{T}, dims::NTuple{N, Int}) where {T, N} - mem = ref.mem - mem_len = length(mem) + 1 - memoryrefoffset(ref) - len = Core.checked_dims(dims...) - @boundscheck mem_len >= len || invalid_wrap_err(mem_len, dims, len) - if N != 1 && !(ref === GenericMemoryRef(mem) && len === mem_len) - mem = ccall(:jl_genericmemory_slice, Memory{T}, (Any, Ptr{Cvoid}, Int), mem, ref.ptr_or_offset, len) - ref = MemoryRef(mem) - end - return ref -end - -@noinline invalid_wrap_err(len, dims, proddims) = throw(DimensionMismatch( - "Attempted to wrap a MemoryRef of length $len with an Array of size dims=$dims, which is invalid because prod(dims) = $proddims > $len, so that the array would have more elements than the underlying memory can store.")) - -@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, dims::NTuple{N, Integer}) where {T, N} - dims = convert(Dims, dims) - ref = _wrap(m, dims) - $(Expr(:new, :(Array{T, N}), :ref, :dims)) -end - -@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, dims::NTuple{N, Integer}) where {T, N} - dims = convert(Dims, dims) - ref = _wrap(MemoryRef(m), dims) - $(Expr(:new, :(Array{T, N}), :ref, :dims)) -end -@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, l::Integer) where {T} - dims = (Int(l),) - ref = _wrap(m, dims) - $(Expr(:new, :(Array{T, 1}), :ref, :dims)) -end -@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, l::Integer) where {T} - dims = (Int(l),) - ref = _wrap(MemoryRef(m), (l,)) - $(Expr(:new, :(Array{T, 1}), :ref, :dims)) -end -@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}) where {T} - ref = MemoryRef(m) - dims = (length(m),) - $(Expr(:new, :(Array{T, 1}), :ref, :dims)) -end diff --git a/base/exports.jl b/base/exports.jl index 3044f9d162d41f..fc2ee86a8d0d48 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -460,7 +460,6 @@ export vcat, vec, view, - wrap, zeros, # search, find, match and related functions diff --git a/base/genericmemory.jl b/base/genericmemory.jl index b5f519a0f854d3..a6f002b9c6175d 100644 --- a/base/genericmemory.jl +++ b/base/genericmemory.jl @@ -288,3 +288,27 @@ function indcopy(sz::Dims, I::GenericMemory) src = eltype(I)[I[i][_findin(I[i], i < n ? (1:sz[i]) : (1:s))] for i = 1:n] dst, src end + +# Wrapping a memory region in an Array +@eval begin # @eval for the Array construction. Block for the docstring. + function reshape(m::GenericMemory{M, T}, dims::Vararg{Int, N}) where {M, T, N} + len = Core.checked_dims(dims...) + length(m) == len || throw(DimensionMismatch("parent has $(length(m)) elements, which is incompatible with size $(dims)")) + ref = MemoryRef(m) + $(Expr(:new, :(Array{T, N}), :ref, :dims)) + end + + """ + view(m::GenericMemory{M, T}, inds::Union{UnitRange, OneTo}) + + Create a vector `v::Vector{T}` backed by the specified indices of `m`. It is only safe to + resize `v` if `m` is subseqently not used. + """ + function view(m::GenericMemory{M, T}, inds::Union{UnitRange, OneTo}) where {M, T} + isempty(inds) && return T[] # needed to allow view(Memory{T}(undef, 0), 2:1) + @boundscheck checkbounds(m, inds) + ref = MemoryRef(m, first(inds)) # @inbounds would be safe here but does not help performance. + dims = (length(inds),) + $(Expr(:new, :(Array{T, 1}), :ref, :dims)) + end +end diff --git a/base/iobuffer.jl b/base/iobuffer.jl index dadb13e1f1e6a3..109eaa96a3de40 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -42,7 +42,7 @@ end # allocate Vector{UInt8}s for IOBuffer storage that can efficiently become Strings StringMemory(n::Integer) = unsafe_wrap(Memory{UInt8}, _string_n(n)) -StringVector(n::Integer) = wrap(Array, StringMemory(n)) +StringVector(n::Integer) = view(StringMemory(n), 1:n)::Vector{UInt8} # IOBuffers behave like Files. They are typically readable and writable. They are seekable. (They can be appendable). @@ -456,7 +456,7 @@ function take!(io::IOBuffer) if nbytes == 0 || io.reinit data = StringVector(0) elseif io.writable - data = wrap(Array, MemoryRef(io.data, io.offset + 1), nbytes) + data = view(io.data, io.offset+1:nbytes+io.offset) else data = copyto!(StringVector(io.size), 1, io.data, io.offset + 1, nbytes) end @@ -465,7 +465,7 @@ function take!(io::IOBuffer) if nbytes == 0 data = StringVector(0) elseif io.writable - data = wrap(Array, MemoryRef(io.data, io.ptr), nbytes) + data = view(io.data, io.ptr:io.ptr+nbytes-1) else data = read!(io, data) end @@ -491,11 +491,7 @@ state. This should only be used internally for performance-critical It might save an allocation compared to `take!` (if the compiler elides the Array allocation), as well as omits some checks. """ -_unsafe_take!(io::IOBuffer) = - wrap(Array, io.size == io.offset ? - MemoryRef(Memory{UInt8}()) : - MemoryRef(io.data, io.offset + 1), - io.size - io.offset) +_unsafe_take!(io::IOBuffer) = view(io.data, io.offset+1:io.size) function write(to::IO, from::GenericIOBuffer) written::Int = bytesavailable(from) diff --git a/base/strings/string.jl b/base/strings/string.jl index b2afce897a937f..d091baeb6c6637 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -117,7 +117,10 @@ String(s::AbstractString) = print_to_string(s) @assume_effects :total String(s::Symbol) = unsafe_string(unsafe_convert(Ptr{UInt8}, s)) unsafe_wrap(::Type{Memory{UInt8}}, s::String) = ccall(:jl_string_to_genericmemory, Ref{Memory{UInt8}}, (Any,), s) -unsafe_wrap(::Type{Vector{UInt8}}, s::String) = wrap(Array, unsafe_wrap(Memory{UInt8}, s)) +function unsafe_wrap(::Type{Vector{UInt8}}, s::String) + mem = unsafe_wrap(Memory{UInt8}, s) + view(mem, eachindex(mem)) +end Vector{UInt8}(s::CodeUnits{UInt8,String}) = copyto!(Vector{UInt8}(undef, length(s)), s) Vector{UInt8}(s::String) = Vector{UInt8}(codeunits(s)) diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index f7ea23ad3b5560..20e8e81614b9e7 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -139,7 +139,6 @@ Base.reshape Base.dropdims Base.vec Base.SubArray -Base.wrap ``` ## Concatenation and permutation diff --git a/test/arrayops.jl b/test/arrayops.jl index 566dd44b8dcd9e..65a9ecbd5e2a2c 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -3187,23 +3187,37 @@ end end end -@testset "Wrapping Memory into Arrays" begin - mem = Memory{Int}(undef, 10) .= 1 - memref = MemoryRef(mem) - @test_throws DimensionMismatch wrap(Array, mem, (10, 10)) - @test wrap(Array, mem, (5,)) == ones(Int, 5) - @test wrap(Array, mem, 2) == ones(Int, 2) - @test wrap(Array, memref, 10) == ones(Int, 10) - @test wrap(Array, memref, (2,2,2)) == ones(Int,2,2,2) - @test wrap(Array, mem, (5, 2)) == ones(Int, 5, 2) - - memref2 = MemoryRef(mem, 3) - @test wrap(Array, memref2, (5,)) == ones(Int, 5) - @test wrap(Array, memref2, 2) == ones(Int, 2) - @test wrap(Array, memref2, (2,2,2)) == ones(Int,2,2,2) - @test wrap(Array, memref2, (3, 2)) == ones(Int, 3, 2) - @test_throws DimensionMismatch wrap(Array, memref2, 9) - @test_throws DimensionMismatch wrap(Array, memref2, 10) +@testset "Wrapping Memory into Arrays with view and reshape" begin + mem::Memory{Int} = Memory{Int}(undef, 10) .= 11:20 + + @test_throws DimensionMismatch reshape(mem, 10, 10) + @test_throws DimensionMismatch reshape(mem, 5) + @test_throws BoundsError view(mem, 1:10, 1:10) + @test_throws BoundsError view(mem, 1:11) + @test_throws BoundsError view(mem, 3:11) + @test_throws BoundsError view(mem, 0:4) + + @test @inferred(view(mem, 1:5))::Vector{Int} == 11:15 + @test @inferred(view(mem, 1:2))::Vector{Int} == 11:12 + @test @inferred(view(mem, 1:10))::Vector{Int} == 11:20 + @test @inferred(view(mem, 3:8))::Vector{Int} == 13:18 + @test @inferred(view(mem, 20:19))::Vector{Int} == [] + @test @inferred(view(mem, -5:-7))::Vector{Int} == [] + @test @inferred(reshape(mem, 5, 2))::Matrix{Int} == reshape(11:20, 5, 2) + + empty_mem = Memory{Module}(undef, 0) + @test_throws BoundsError view(empty_mem, 0:1) + @test_throws BoundsError view(empty_mem, 1:2) + @test_throws DimensionMismatch reshape(empty_mem, 1) + @test_throws DimensionMismatch reshape(empty_mem, 1, 2, 3) + @test_throws ArgumentError reshape(empty_mem, 2^16, 2^16, 2^16, 2^16) + + @test @inferred(view(empty_mem, 1:0))::Vector{Module} == [] + @test @inferred(view(empty_mem, 10:3))::Vector{Module} == [] + @test isempty(@inferred(reshape(empty_mem, 0, 7, 1))::Array{Module, 3}) + + offset_inds = OffsetArrays.IdOffsetRange(values=3:6, indices=53:56) + @test @inferred(view(collect(mem), offset_inds)) == view(mem, offset_inds) end @testset "Memory size" begin From f7c7410b8f7d526dad499b87896f92fb39b4e56c Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sat, 6 Apr 2024 19:50:47 +0530 Subject: [PATCH 095/123] `LazyString` in `DimensionMismatch` error messages in broadcasting (#53975) This reduces dynamic dispatch, and makes JET happier. Something similar is already used in line 523. --- base/broadcast.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/base/broadcast.jl b/base/broadcast.jl index d26613233a2716..30c982ae051179 100644 --- a/base/broadcast.jl +++ b/base/broadcast.jl @@ -517,8 +517,8 @@ function _bcs(shape::Tuple, newshape::Tuple) return (_bcs1(shape[1], newshape[1]), _bcs(tail(shape), tail(newshape))...) end # _bcs1 handles the logic for a single dimension -_bcs1(a::Integer, b::Integer) = a == 1 ? b : (b == 1 ? a : (a == b ? a : throw(DimensionMismatch("arrays could not be broadcast to a common size; got a dimension with lengths $a and $b")))) -_bcs1(a::Integer, b) = a == 1 ? b : (first(b) == 1 && last(b) == a ? b : throw(DimensionMismatch("arrays could not be broadcast to a common size; got a dimension with lengths $a and $(length(b))"))) +_bcs1(a::Integer, b::Integer) = a == 1 ? b : (b == 1 ? a : (a == b ? a : throw(DimensionMismatch(LazyString("arrays could not be broadcast to a common size; got a dimension with lengths ", a, " and ", b))))) +_bcs1(a::Integer, b) = a == 1 ? b : (first(b) == 1 && last(b) == a ? b : throw(DimensionMismatch(LazyString("arrays could not be broadcast to a common size; got a dimension with lengths ", a, " and ", length(b))))) _bcs1(a, b::Integer) = _bcs1(b, a) _bcs1(a, b) = _bcsm(b, a) ? axistype(b, a) : _bcsm(a, b) ? axistype(a, b) : throw(DimensionMismatch(LazyString("arrays could not be broadcast to a common size: a has axes ", a, " and b has axes ", b))) # _bcsm tests whether the second index is consistent with the first @@ -1057,7 +1057,7 @@ end @noinline throwdm(axdest, axsrc) = - throw(DimensionMismatch("destination axes $axdest are not compatible with source axes $axsrc")) + throw(DimensionMismatch(LazyString("destination axes ", axdest, " are not compatible with source axes ", axsrc))) function restart_copyto_nonleaf!(newdest, dest, bc, val, I, iter, state, count) # Function barrier that makes the copying to newdest type stable From 4e5bd66ce6b6a4f4299d7be7762d6d7e11d33560 Mon Sep 17 00:00:00 2001 From: nathan musoke Date: Sat, 6 Apr 2024 13:20:21 -0400 Subject: [PATCH 096/123] fix minor typo in mktempdir docs (#53977) This is a minor change, just adding a missing word to a docstring for `Base.Filesystem.mktempdir` --- base/file.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/file.jl b/base/file.jl index b7adb8e1a3fbd0..727b97abd36f13 100644 --- a/base/file.jl +++ b/base/file.jl @@ -821,7 +821,7 @@ end mktempdir(f::Function, parent=tempdir(); prefix=$(repr(temp_prefix))) Apply the function `f` to the result of [`mktempdir(parent; prefix)`](@ref) and remove the -temporary directory all of its contents upon completion. +temporary directory and all of its contents upon completion. See also: [`mktemp`](@ref), [`mkdir`](@ref). From 821c608ffeeb7bfc470270df2006c549b7672473 Mon Sep 17 00:00:00 2001 From: Viriato5 <120762182+Viriato5@users.noreply.github.com> Date: Sat, 6 Apr 2024 18:24:11 +0100 Subject: [PATCH 097/123] Fix #52989: DateTime parser would return an error when parsing a year string (#53954) Issue #52989. Originally checked on version 1.10.0 but still relevant in the current version in master Bug: When executing the method DateTime to create a DateTime value with a string input only containing a year (ex: "2000") the method returns an 'ArgumentError: Invalid DateTime string' when it should, from what I understood, return a DateTime like 2000-01-01T00:00:00 seeing as if you call the same method with a number indicating a year (ex: 2000) the method returns correctly. Fix: The fix was simple, on the first tryparsenext_base10 block (line 207-211) where a year is parsed from the string the exit condition i > end_pos should jump into 'done' so it returns a correct value instead of 'error' --- stdlib/Dates/src/parse.jl | 2 +- stdlib/Dates/test/io.jl | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/stdlib/Dates/src/parse.jl b/stdlib/Dates/src/parse.jl index 62d44177de877c..49c0234c7c9fa9 100644 --- a/stdlib/Dates/src/parse.jl +++ b/stdlib/Dates/src/parse.jl @@ -207,7 +207,7 @@ function Base.parse(::Type{DateTime}, s::AbstractString, df::typeof(ISODateTimeF let val = tryparsenext_base10(s, i, end_pos, 1) val === nothing && @goto error dy, i = val - i > end_pos && @goto error + i > end_pos && @goto done end c, i = iterate(s, i)::Tuple{Char, Int} diff --git a/stdlib/Dates/test/io.jl b/stdlib/Dates/test/io.jl index 092a58d5d70d18..ee102288acd3e3 100644 --- a/stdlib/Dates/test/io.jl +++ b/stdlib/Dates/test/io.jl @@ -470,6 +470,9 @@ end # Issue #44003 @test tryparse(Dates.Date, "2017", Dates.DateFormat(".s")) === nothing +# Issue #52989 +@test Dates.DateTime("2000") == Dates.DateTime(2000) + @testset "parse milliseconds, Issue #22100" begin @test Dates.DateTime("2017-Mar-17 00:00:00.0000", "y-u-d H:M:S.s") == Dates.DateTime(2017, 3, 17) @test Dates.parse_components(".1", Dates.DateFormat(".s")) == [Dates.Millisecond(100)] From 1febcd609fa2689a0578aa8a47a7bddc598b669a Mon Sep 17 00:00:00 2001 From: "Lance (Weiqing) Xu" <47257262+lanceXwq@users.noreply.github.com> Date: Sun, 7 Apr 2024 00:37:27 -0700 Subject: [PATCH 098/123] Fix typos in docstrings (#53986) --- base/reduce.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index d73aeeeee46ec8..c4020faf4c85f0 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -1118,7 +1118,7 @@ If the input contains [`missing`](@ref) values, return `missing` if all non-miss values are `false` (or equivalently, if the input contains no `true` value), following [three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic). -See also: [`all`](@ref), [`count`](@ref), [`sum`](@ref), [`|`](@ref), , [`||`](@ref). +See also: [`all`](@ref), [`count`](@ref), [`sum`](@ref), [`|`](@ref), [`||`](@ref). # Examples ```jldoctest @@ -1156,7 +1156,7 @@ If the input contains [`missing`](@ref) values, return `missing` if all non-miss values are `true` (or equivalently, if the input contains no `false` value), following [three-valued logic](https://en.wikipedia.org/wiki/Three-valued_logic). -See also: [`all!`](@ref), [`any`](@ref), [`count`](@ref), [`&`](@ref), , [`&&`](@ref), [`allunique`](@ref). +See also: [`all!`](@ref), [`any`](@ref), [`count`](@ref), [`&`](@ref), [`&&`](@ref), [`allunique`](@ref). # Examples ```jldoctest From 243ebc389eec78f060a47c53375b3fd48c462d76 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Sun, 7 Apr 2024 19:52:09 +0530 Subject: [PATCH 099/123] Support broadcasting over structured block matrices (#53909) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix https://github.com/JuliaLang/julia/issues/48664 After this, broadcasting over structured block matrices with matrix-valued elements works: ```julia julia> D = Diagonal([[1 2; 3 4], [5 6; 7 8]]) 2ร—2 Diagonal{Matrix{Int64}, Vector{Matrix{Int64}}}: [1 2; 3 4] โ‹… โ‹… [5 6; 7 8] julia> D .+ D 2ร—2 Diagonal{Matrix{Int64}, Vector{Matrix{Int64}}}: [2 4; 6 8] โ‹… โ‹… [10 12; 14 16] julia> cos.(D) 2ร—2 Matrix{Matrix{Float64}}: [0.855423 -0.110876; -0.166315 0.689109] [1.0 0.0; 0.0 1.0] [1.0 0.0; 0.0 1.0] [0.928384 -0.069963; -0.0816235 0.893403] ``` Such operations show up when using `BlockArrays`. The implementation is a bit hacky as it uses `0I` as the zero element in `fzero`, which isn't really the correct zero if the blocks are rectangular. Nonetheless, this works, as `fzero` is only used to determine if the structure is preserved. --- .../LinearAlgebra/src/structuredbroadcast.jl | 6 +- stdlib/LinearAlgebra/test/special.jl | 1 + .../LinearAlgebra/test/structuredbroadcast.jl | 58 +++++++++++++++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/stdlib/LinearAlgebra/src/structuredbroadcast.jl b/stdlib/LinearAlgebra/src/structuredbroadcast.jl index dfc58aabc63ece..6114c9a7963909 100644 --- a/stdlib/LinearAlgebra/src/structuredbroadcast.jl +++ b/stdlib/LinearAlgebra/src/structuredbroadcast.jl @@ -8,8 +8,8 @@ struct StructuredMatrixStyle{T} <: Broadcast.AbstractArrayStyle{2} end StructuredMatrixStyle{T}(::Val{2}) where {T} = StructuredMatrixStyle{T}() StructuredMatrixStyle{T}(::Val{N}) where {T,N} = Broadcast.DefaultArrayStyle{N}() -const StructuredMatrix = Union{Diagonal,Bidiagonal,SymTridiagonal,Tridiagonal,LowerTriangular,UnitLowerTriangular,UpperTriangular,UnitUpperTriangular} -for ST in Base.uniontypes(StructuredMatrix) +const StructuredMatrix{T} = Union{Diagonal{T},Bidiagonal{T},SymTridiagonal{T},Tridiagonal{T},LowerTriangular{T},UnitLowerTriangular{T},UpperTriangular{T},UnitUpperTriangular{T}} +for ST in (Diagonal,Bidiagonal,SymTridiagonal,Tridiagonal,LowerTriangular,UnitLowerTriangular,UpperTriangular,UnitUpperTriangular) @eval Broadcast.BroadcastStyle(::Type{<:$ST}) = $(StructuredMatrixStyle{ST}()) end @@ -133,6 +133,7 @@ fails as `zero(::Tuple{Int})` is not defined. However, iszerodefined(::Type) = false iszerodefined(::Type{<:Number}) = true iszerodefined(::Type{<:AbstractArray{T}}) where T = iszerodefined(T) +iszerodefined(::Type{<:UniformScaling{T}}) where T = iszerodefined(T) fzeropreserving(bc) = (v = fzero(bc); !ismissing(v) && (iszerodefined(typeof(v)) ? iszero(v) : v == 0)) # Like sparse matrices, we assume that the zero-preservation property of a broadcasted @@ -144,6 +145,7 @@ fzero(::Type{T}) where T = T fzero(r::Ref) = r[] fzero(t::Tuple{Any}) = t[1] fzero(S::StructuredMatrix) = zero(eltype(S)) +fzero(::StructuredMatrix{<:AbstractMatrix{T}}) where {T<:Number} = haszero(T) ? zero(T)*I : missing fzero(x) = missing function fzero(bc::Broadcast.Broadcasted) args = map(fzero, bc.args) diff --git a/stdlib/LinearAlgebra/test/special.jl b/stdlib/LinearAlgebra/test/special.jl index 6465927db5235a..a5198892ff995c 100644 --- a/stdlib/LinearAlgebra/test/special.jl +++ b/stdlib/LinearAlgebra/test/special.jl @@ -111,6 +111,7 @@ Random.seed!(1) struct TypeWithZero end Base.promote_rule(::Type{TypeWithoutZero}, ::Type{TypeWithZero}) = TypeWithZero Base.convert(::Type{TypeWithZero}, ::TypeWithoutZero) = TypeWithZero() + Base.zero(x::Union{TypeWithoutZero, TypeWithZero}) = zero(typeof(x)) Base.zero(::Type{<:Union{TypeWithoutZero, TypeWithZero}}) = TypeWithZero() LinearAlgebra.symmetric(::TypeWithoutZero, ::Symbol) = TypeWithoutZero() LinearAlgebra.symmetric_type(::Type{TypeWithoutZero}) = TypeWithoutZero diff --git a/stdlib/LinearAlgebra/test/structuredbroadcast.jl b/stdlib/LinearAlgebra/test/structuredbroadcast.jl index 02d7ead55af179..3767fc10055f24 100644 --- a/stdlib/LinearAlgebra/test/structuredbroadcast.jl +++ b/stdlib/LinearAlgebra/test/structuredbroadcast.jl @@ -280,4 +280,62 @@ end # structured broadcast with function returning non-number type @test tuple.(Diagonal([1, 2])) == [(1,) (0,); (0,) (2,)] +@testset "broadcast over structured matrices with matrix elements" begin + function standardbroadcastingtests(D, T) + M = [x for x in D] + Dsum = D .+ D + @test Dsum isa T + @test Dsum == M .+ M + Dcopy = copy.(D) + @test Dcopy isa T + @test Dcopy == D + Df = float.(D) + @test Df isa T + @test Df == D + @test eltype(eltype(Df)) <: AbstractFloat + @test (x -> (x,)).(D) == (x -> (x,)).(M) + @test (x -> 1).(D) == ones(Int,size(D)) + @test all(==(2), ndims.(D)) + @test_throws MethodError size.(D) + end + @testset "Diagonal" begin + @testset "square" begin + A = [1 3; 2 4] + D = Diagonal([A, A]) + standardbroadcastingtests(D, Diagonal) + @test sincos.(D) == sincos.(Matrix{eltype(D)}(D)) + M = [x for x in D] + @test cos.(D) == cos.(M) + end + + @testset "different-sized square blocks" begin + D = Diagonal([ones(3,3), fill(3.0,2,2)]) + standardbroadcastingtests(D, Diagonal) + end + + @testset "rectangular blocks" begin + D = Diagonal([ones(Bool,3,4), ones(Bool,2,3)]) + standardbroadcastingtests(D, Diagonal) + end + + @testset "incompatible sizes" begin + A = reshape(1:12, 4, 3) + B = reshape(1:12, 3, 4) + D1 = Diagonal(fill(A, 2)) + D2 = Diagonal(fill(B, 2)) + @test_throws DimensionMismatch D1 .+ D2 + end + end + @testset "Bidiagonal" begin + A = [1 3; 2 4] + B = Bidiagonal(fill(A,3), fill(A,2), :U) + standardbroadcastingtests(B, Bidiagonal) + end + @testset "UpperTriangular" begin + A = [1 3; 2 4] + U = UpperTriangular([(i+j)*A for i in 1:3, j in 1:3]) + standardbroadcastingtests(U, UpperTriangular) + end +end + end From c5a3b653353318607534fe9642c9e9476ff7d625 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Sun, 7 Apr 2024 11:36:34 -0500 Subject: [PATCH 100/123] Remove trailing slash in "Official https://julialang.org/ release" (#53978) --- doc/src/devdocs/probes.md | 4 ++-- stdlib/InteractiveUtils/src/InteractiveUtils.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/devdocs/probes.md b/doc/src/devdocs/probes.md index e75e7f6bb01565..5a1af0d897bc67 100644 --- a/doc/src/devdocs/probes.md +++ b/doc/src/devdocs/probes.md @@ -188,7 +188,7 @@ Julia session and get the PID and REPL's task address: _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 1.6.2 (2021-07-14) - _/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release + _/ |\__'_|_|_|\__'_| | Official https://julialang.org release |__/ | 1> getpid() @@ -264,7 +264,7 @@ We can see this problem illustrated with `bpftrace` quite easily. First, in one _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help. | | | | | | |/ _` | | | | |_| | | | (_| | | Version 1.6.2 (2021-07-14) - _/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release + _/ |\__'_|_|_|\__'_| | Official https://julialang.org release |__/ | 1> getpid() diff --git a/stdlib/InteractiveUtils/src/InteractiveUtils.jl b/stdlib/InteractiveUtils/src/InteractiveUtils.jl index a0020090e451df..835988ddf149ff 100644 --- a/stdlib/InteractiveUtils/src/InteractiveUtils.jl +++ b/stdlib/InteractiveUtils/src/InteractiveUtils.jl @@ -104,7 +104,7 @@ function versioninfo(io::IO=stdout; verbose::Bool=false) if !isempty(Base.GIT_VERSION_INFO.commit_short) println(io, "Commit $(Base.GIT_VERSION_INFO.commit_short) ($(Base.GIT_VERSION_INFO.date_string))") end - official_release = Base.TAGGED_RELEASE_BANNER == "Official https://julialang.org/ release" + official_release = Base.TAGGED_RELEASE_BANNER == "Official https://julialang.org release" if Base.isdebugbuild() || !isempty(Base.TAGGED_RELEASE_BANNER) || (Base.GIT_VERSION_INFO.tagged_commit && !official_release) println(io, "Build Info:") if Base.isdebugbuild() From e4f2124e08a14fdfa2c0e569ceb4412b2f666868 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Sun, 7 Apr 2024 22:46:14 -0500 Subject: [PATCH 101/123] Test and fix non-int-length bug in `view(::Memory, ::Union{UnitRange, Base.OneTo})` (#53991) We assumed, falsely, that `length(inds) isa Int`. The length must be convertible to an `Int` or we throw, but that conversion may need to be explicitly performed. Fixes #53990 CC @oscardssmith @vtjnash @odow --- base/genericmemory.jl | 2 +- test/arrayops.jl | 3 +++ test/core.jl | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/base/genericmemory.jl b/base/genericmemory.jl index a6f002b9c6175d..3463be456ea591 100644 --- a/base/genericmemory.jl +++ b/base/genericmemory.jl @@ -308,7 +308,7 @@ end isempty(inds) && return T[] # needed to allow view(Memory{T}(undef, 0), 2:1) @boundscheck checkbounds(m, inds) ref = MemoryRef(m, first(inds)) # @inbounds would be safe here but does not help performance. - dims = (length(inds),) + dims = (Int(length(inds)),) $(Expr(:new, :(Array{T, 1}), :ref, :dims)) end end diff --git a/test/arrayops.jl b/test/arrayops.jl index 65a9ecbd5e2a2c..a31d373a65a386 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -3205,6 +3205,9 @@ end @test @inferred(view(mem, -5:-7))::Vector{Int} == [] @test @inferred(reshape(mem, 5, 2))::Matrix{Int} == reshape(11:20, 5, 2) + # 53990 + @test @inferred(view(mem, unsigned(1):10))::Vector{Int} == 11:20 + empty_mem = Memory{Module}(undef, 0) @test_throws BoundsError view(empty_mem, 0:1) @test_throws BoundsError view(empty_mem, 1:2) diff --git a/test/core.jl b/test/core.jl index 173526d3b21287..ed1e1fc6757d22 100644 --- a/test/core.jl +++ b/test/core.jl @@ -5524,6 +5524,9 @@ let a = Base.StringVector(2^17) @test sizeof(c) == 0 end +# issue #53990 / https://github.com/JuliaLang/julia/pull/53896#discussion_r1555087951 +@test Base.StringVector(UInt64(2)) isa Vector{UInt8} + @test_throws ArgumentError eltype(Bottom) # issue #16424, re-evaluating type definitions From 62df400ddb3001bf4d6aaca06dd47c99c0b93969 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki Date: Thu, 4 Apr 2024 22:26:44 +0900 Subject: [PATCH 102/123] inference: fixes cache lookup with extended lattice elements The previous local cache lookup system wasn't working well for caches with extended lattice elements that are transformed from the caller context to the callee context by `matching_cache_argtypes`. To address this, the current commit moves the call to `matching_cache_argtypes` right before `cache_lookup`, instead of within the `InferenceResult` constructor. Note that this adjustment leads to `given_argtypes` being allocated even when there's a cache hit, potentially affecting performance negatively. I'm looking to further optimize `matching_cache_argtypes` in an upcoming commit. --- base/compiler/abstractinterpretation.jl | 7 ++++--- base/compiler/types.jl | 2 -- test/compiler/inference.jl | 22 ++++++++++++++++++++++ 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 75c8e841b7e101..a113d028248db9 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1248,7 +1248,9 @@ function const_prop_call(interp::AbstractInterpreter, concrete_eval_result::Union{Nothing, ConstCallResults}=nothing) inf_cache = get_inference_cache(interp) ๐•ƒแตข = typeinf_lattice(interp) - inf_result = cache_lookup(๐•ƒแตข, mi, arginfo.argtypes, inf_cache) + argtypes = has_conditional(๐•ƒแตข, sv) ? ConditionalArgtypes(arginfo, sv) : SimpleArgtypes(arginfo.argtypes) + given_argtypes, overridden_by_const = matching_cache_argtypes(๐•ƒแตข, mi, argtypes) + inf_result = cache_lookup(๐•ƒแตข, mi, given_argtypes, inf_cache) if inf_result !== nothing # found the cache for this constant prop' if inf_result.result === nothing @@ -1259,8 +1261,7 @@ function const_prop_call(interp::AbstractInterpreter, return return_cached_result(interp, inf_result, sv) end # perform fresh constant prop' - argtypes = has_conditional(๐•ƒแตข, sv) ? ConditionalArgtypes(arginfo, sv) : SimpleArgtypes(arginfo.argtypes) - inf_result = InferenceResult(mi, argtypes, typeinf_lattice(interp)) + inf_result = InferenceResult(mi, given_argtypes, overridden_by_const) if !any(inf_result.overridden_by_const) add_remark!(interp, sv, "[constprop] Could not handle constant info in matching_cache_argtypes") return nothing diff --git a/base/compiler/types.jl b/base/compiler/types.jl index 3017976b669491..12c747d0c57075 100644 --- a/base/compiler/types.jl +++ b/base/compiler/types.jl @@ -99,8 +99,6 @@ mutable struct InferenceResult end InferenceResult(mi::MethodInstance, ๐•ƒ::AbstractLattice=fallback_lattice) = InferenceResult(mi, matching_cache_argtypes(๐•ƒ, mi)...) -InferenceResult(mi::MethodInstance, argtypes::ForwardableArgtypes, ๐•ƒ::AbstractLattice=fallback_lattice) = - InferenceResult(mi, matching_cache_argtypes(๐•ƒ, mi, argtypes)...) function stack_analysis_result!(inf_result::InferenceResult, @nospecialize(result)) return inf_result.analysis_results = AnalysisResults(result, inf_result.analysis_results) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 01c4687a26caa7..3accb1edf54e03 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5696,3 +5696,25 @@ end # We want to make sure that both this returns `Tuple` and that # it doesn't infinite loop inside inference. @test Core.Compiler.return_type(gen_infinite_loop_ssa, Tuple{}) === Tuple + +# inference local cache lookup with extended lattice elements that may be transformed +# by `matching_cache_argtypes` +@newinterp CachedConditionalInterp +Base.@constprop :aggressive function func_cached_conditional(x, y) + if x + @noinline sin(y) + else + 0.0 + end +end; +function test_func_cached_conditional(y) + yโ‚ = func_cached_conditional(isa(y, Float64), y) + yโ‚‚ = func_cached_conditional(isa(y, Float64), y) + return yโ‚, yโ‚‚ +end; +let interp = CachedConditionalInterp(); + @test Base.infer_return_type(test_func_cached_conditional, (Any,); interp) == Tuple{Float64, Float64} + @test count(interp.inf_cache) do result + result.linfo.def.name === :func_cached_conditional + end == 1 +end From 41347f58f2df934602d84244414596d7cd4b922c Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Mon, 8 Apr 2024 08:17:03 +0000 Subject: [PATCH 103/123] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?StyledStrings=20stdlib=20from=20e0ca0f8=20to=20bfdb4c3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../md5 | 1 + .../sha512 | 1 + .../md5 | 1 - .../sha512 | 1 - stdlib/StyledStrings.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 deps/checksums/StyledStrings-bfdb4c3f73a93a956ad48b0f06f89eb1cd40ff6b.tar.gz/md5 create mode 100644 deps/checksums/StyledStrings-bfdb4c3f73a93a956ad48b0f06f89eb1cd40ff6b.tar.gz/sha512 delete mode 100644 deps/checksums/StyledStrings-e0ca0f85412ea5cafabfeaaec4d62ca26c3959d2.tar.gz/md5 delete mode 100644 deps/checksums/StyledStrings-e0ca0f85412ea5cafabfeaaec4d62ca26c3959d2.tar.gz/sha512 diff --git a/deps/checksums/StyledStrings-bfdb4c3f73a93a956ad48b0f06f89eb1cd40ff6b.tar.gz/md5 b/deps/checksums/StyledStrings-bfdb4c3f73a93a956ad48b0f06f89eb1cd40ff6b.tar.gz/md5 new file mode 100644 index 00000000000000..511b60c7e2217d --- /dev/null +++ b/deps/checksums/StyledStrings-bfdb4c3f73a93a956ad48b0f06f89eb1cd40ff6b.tar.gz/md5 @@ -0,0 +1 @@ +8fc4fd7e90d35e7d8d06a6b7c312ec03 diff --git a/deps/checksums/StyledStrings-bfdb4c3f73a93a956ad48b0f06f89eb1cd40ff6b.tar.gz/sha512 b/deps/checksums/StyledStrings-bfdb4c3f73a93a956ad48b0f06f89eb1cd40ff6b.tar.gz/sha512 new file mode 100644 index 00000000000000..d5e2302499a2cf --- /dev/null +++ b/deps/checksums/StyledStrings-bfdb4c3f73a93a956ad48b0f06f89eb1cd40ff6b.tar.gz/sha512 @@ -0,0 +1 @@ +137360872c9b75276426efa9e9096e442115a554b7e00dc98ce02904fa1a535f76e48ba1366fc517794490a494cccc3238d006ebb43dadb5594e5099a2c36f55 diff --git a/deps/checksums/StyledStrings-e0ca0f85412ea5cafabfeaaec4d62ca26c3959d2.tar.gz/md5 b/deps/checksums/StyledStrings-e0ca0f85412ea5cafabfeaaec4d62ca26c3959d2.tar.gz/md5 deleted file mode 100644 index 2ab79799cca0ee..00000000000000 --- a/deps/checksums/StyledStrings-e0ca0f85412ea5cafabfeaaec4d62ca26c3959d2.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -fc3a846400107c432d20da6cfdd19ccf diff --git a/deps/checksums/StyledStrings-e0ca0f85412ea5cafabfeaaec4d62ca26c3959d2.tar.gz/sha512 b/deps/checksums/StyledStrings-e0ca0f85412ea5cafabfeaaec4d62ca26c3959d2.tar.gz/sha512 deleted file mode 100644 index 70b0ef6f5cb3a3..00000000000000 --- a/deps/checksums/StyledStrings-e0ca0f85412ea5cafabfeaaec4d62ca26c3959d2.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -22da8964cc4c09f7c7a3da44be14c953f520ce6d395cf0f9ccf9c17777d6d968b0a874b35c072801ef7a1f4eee40f96ea0e2fc5ed5b3a63ad0b6b776a9c14ebb diff --git a/stdlib/StyledStrings.version b/stdlib/StyledStrings.version index 19a5a24514f2ff..8e489a5daf2892 100644 --- a/stdlib/StyledStrings.version +++ b/stdlib/StyledStrings.version @@ -1,4 +1,4 @@ STYLEDSTRINGS_BRANCH = main -STYLEDSTRINGS_SHA1 = e0ca0f85412ea5cafabfeaaec4d62ca26c3959d2 +STYLEDSTRINGS_SHA1 = bfdb4c3f73a93a956ad48b0f06f89eb1cd40ff6b STYLEDSTRINGS_GIT_URL := https://github.com/JuliaLang/StyledStrings.jl.git STYLEDSTRINGS_TAR_URL = https://api.github.com/repos/JuliaLang/StyledStrings.jl/tarball/$1 From a5356a4b4e6ab8b8cb4de452c1e044773aa405dc Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki Date: Fri, 5 Apr 2024 01:36:45 +0900 Subject: [PATCH 104/123] optimize construction of `InferenceResult` for constant inference --- base/compiler/abstractinterpretation.jl | 40 +++++---- base/compiler/compiler.jl | 2 +- base/compiler/inferenceresult.jl | 110 +++++++----------------- base/compiler/inferencestate.jl | 5 +- base/compiler/ssair/legacy.jl | 2 +- base/compiler/typeinfer.jl | 8 +- base/compiler/types.jl | 29 ++++--- test/compiler/inference.jl | 2 +- 8 files changed, 82 insertions(+), 116 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index a113d028248db9..a396e281c1bf73 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1239,7 +1239,7 @@ const_prop_result(inf_result::InferenceResult) = ConstCallResults(inf_result.result, inf_result.exc_result, ConstPropResult(inf_result), inf_result.ipo_effects, inf_result.linfo) -# return cached constant analysis result +# return cached result of constant analysis return_cached_result(::AbstractInterpreter, inf_result::InferenceResult, ::AbsIntState) = const_prop_result(inf_result) @@ -1249,8 +1249,15 @@ function const_prop_call(interp::AbstractInterpreter, inf_cache = get_inference_cache(interp) ๐•ƒแตข = typeinf_lattice(interp) argtypes = has_conditional(๐•ƒแตข, sv) ? ConditionalArgtypes(arginfo, sv) : SimpleArgtypes(arginfo.argtypes) - given_argtypes, overridden_by_const = matching_cache_argtypes(๐•ƒแตข, mi, argtypes) - inf_result = cache_lookup(๐•ƒแตข, mi, given_argtypes, inf_cache) + # use `cache_argtypes` that has been constructed for fresh regular inference if available + volatile_inf_result = result.volatile_inf_result + if volatile_inf_result !== nothing + cache_argtypes = volatile_inf_result.inf_result.argtypes + else + cache_argtypes = matching_cache_argtypes(๐•ƒแตข, mi) + end + argtypes = matching_cache_argtypes(๐•ƒแตข, mi, argtypes, cache_argtypes) + inf_result = cache_lookup(๐•ƒแตข, mi, argtypes, inf_cache) if inf_result !== nothing # found the cache for this constant prop' if inf_result.result === nothing @@ -1260,12 +1267,18 @@ function const_prop_call(interp::AbstractInterpreter, @assert inf_result.linfo === mi "MethodInstance for cached inference result does not match" return return_cached_result(interp, inf_result, sv) end - # perform fresh constant prop' - inf_result = InferenceResult(mi, given_argtypes, overridden_by_const) - if !any(inf_result.overridden_by_const) + overridden_by_const = falses(length(argtypes)) + for i = 1:length(argtypes) + if argtypes[i] !== cache_argtypes[i] + overridden_by_const[i] = true + end + end + if !any(overridden_by_const) add_remark!(interp, sv, "[constprop] Could not handle constant info in matching_cache_argtypes") return nothing end + # perform fresh constant prop' + inf_result = InferenceResult(mi, argtypes, overridden_by_const) frame = InferenceState(inf_result, #=cache_mode=#:local, interp) if frame === nothing add_remark!(interp, sv, "[constprop] Could not retrieve the source") @@ -1287,26 +1300,19 @@ end # TODO implement MustAlias forwarding -struct ConditionalArgtypes <: ForwardableArgtypes +struct ConditionalArgtypes arginfo::ArgInfo sv::InferenceState end -""" - matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, - conditional_argtypes::ConditionalArgtypes) - -The implementation is able to forward `Conditional` of `conditional_argtypes`, -as well as the other general extended lattice information. -""" function matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, - conditional_argtypes::ConditionalArgtypes) + conditional_argtypes::ConditionalArgtypes, + cache_argtypes::Vector{Any}) (; arginfo, sv) = conditional_argtypes (; fargs, argtypes) = arginfo given_argtypes = Vector{Any}(undef, length(argtypes)) def = mi.def::Method nargs = Int(def.nargs) - cache_argtypes, overridden_by_const = matching_cache_argtypes(๐•ƒ, mi) local condargs = nothing for i in 1:length(argtypes) argtype = argtypes[i] @@ -1349,7 +1355,7 @@ function matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, else given_argtypes = va_process_argtypes(๐•ƒ, given_argtypes, mi) end - return pick_const_args!(๐•ƒ, cache_argtypes, overridden_by_const, given_argtypes) + return pick_const_args!(๐•ƒ, given_argtypes, cache_argtypes) end # This is only for use with `Conditional`. diff --git a/base/compiler/compiler.jl b/base/compiler/compiler.jl index 8b9c26be2ec818..12d6d5eb38764b 100644 --- a/base/compiler/compiler.jl +++ b/base/compiler/compiler.jl @@ -203,6 +203,7 @@ include("compiler/ssair/ir.jl") include("compiler/ssair/tarjan.jl") include("compiler/abstractlattice.jl") +include("compiler/stmtinfo.jl") include("compiler/inferenceresult.jl") include("compiler/inferencestate.jl") @@ -210,7 +211,6 @@ include("compiler/typeutils.jl") include("compiler/typelimits.jl") include("compiler/typelattice.jl") include("compiler/tfuncs.jl") -include("compiler/stmtinfo.jl") include("compiler/abstractinterpretation.jl") include("compiler/typeinfer.jl") diff --git a/base/compiler/inferenceresult.jl b/base/compiler/inferenceresult.jl index 06fbffaa7aa042..574685c1e38d65 100644 --- a/base/compiler/inferenceresult.jl +++ b/base/compiler/inferenceresult.jl @@ -1,63 +1,30 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -""" - matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance) -> - (cache_argtypes::Vector{Any}, overridden_by_const::BitVector) - -Returns argument types `cache_argtypes::Vector{Any}` for `mi` that are in the native -Julia type domain. `overridden_by_const::BitVector` is all `false` meaning that -there is no additional extended lattice information there. - - matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, argtypes::ForwardableArgtypes) -> - (cache_argtypes::Vector{Any}, overridden_by_const::BitVector) - -Returns cache-correct extended lattice argument types `cache_argtypes::Vector{Any}` -for `mi` given some `argtypes` accompanied by `overridden_by_const::BitVector` -that marks which argument contains additional extended lattice information. - -In theory, there could be a `cache` containing a matching `InferenceResult` -for the provided `mi` and `given_argtypes`. The purpose of this function is -to return a valid value for `cache_lookup(๐•ƒ, mi, argtypes, cache).argtypes`, -so that we can construct cache-correct `InferenceResult`s in the first place. -""" -function matching_cache_argtypes end - function matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance) - method = isa(mi.def, Method) ? mi.def::Method : nothing - cache_argtypes = most_general_argtypes(method, mi.specTypes) - overridden_by_const = falses(length(cache_argtypes)) - return cache_argtypes, overridden_by_const + (; def, specTypes) = mi + return most_general_argtypes(isa(def, Method) ? def : nothing, specTypes) end -struct SimpleArgtypes <: ForwardableArgtypes +struct SimpleArgtypes argtypes::Vector{Any} end -""" - matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, argtypes::SimpleArgtypes) - -The implementation for `argtypes` with general extended lattice information. -This is supposed to be used for debugging and testing or external `AbstractInterpreter` -usages and in general `matching_cache_argtypes(::MethodInstance, ::ConditionalArgtypes)` -is more preferred it can forward `Conditional` information. -""" -function matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, simple_argtypes::SimpleArgtypes) +function matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, + simple_argtypes::SimpleArgtypes, + cache_argtypes::Vector{Any}) (; argtypes) = simple_argtypes given_argtypes = Vector{Any}(undef, length(argtypes)) for i = 1:length(argtypes) given_argtypes[i] = widenslotwrapper(argtypes[i]) end given_argtypes = va_process_argtypes(๐•ƒ, given_argtypes, mi) - return pick_const_args(๐•ƒ, mi, given_argtypes) + return pick_const_args!(๐•ƒ, given_argtypes, cache_argtypes) end -function pick_const_args(๐•ƒ::AbstractLattice, mi::MethodInstance, given_argtypes::Vector{Any}) - cache_argtypes, overridden_by_const = matching_cache_argtypes(๐•ƒ, mi) - return pick_const_args!(๐•ƒ, cache_argtypes, overridden_by_const, given_argtypes) -end - -function pick_const_args!(๐•ƒ::AbstractLattice, cache_argtypes::Vector{Any}, overridden_by_const::BitVector, given_argtypes::Vector{Any}) - for i = 1:length(given_argtypes) +function pick_const_args!(๐•ƒ::AbstractLattice, given_argtypes::Vector{Any}, cache_argtypes::Vector{Any}) + nargtypes = length(given_argtypes) + @assert nargtypes == length(cache_argtypes) #= == nargs =# "invalid `given_argtypes` for `mi`" + for i = 1:nargtypes given_argtype = given_argtypes[i] cache_argtype = cache_argtypes[i] if !is_argtype_match(๐•ƒ, given_argtype, cache_argtype, false) @@ -66,13 +33,13 @@ function pick_const_args!(๐•ƒ::AbstractLattice, cache_argtypes::Vector{Any}, ov !โŠ(๐•ƒ, given_argtype, cache_argtype)) # if the type information of this `PartialStruct` is less strict than # declared method signature, narrow it down using `tmeet` - given_argtype = tmeet(๐•ƒ, given_argtype, cache_argtype) + given_argtypes[i] = tmeet(๐•ƒ, given_argtype, cache_argtype) end - cache_argtypes[i] = given_argtype - overridden_by_const[i] = true + else + given_argtypes[i] = cache_argtype end end - return cache_argtypes, overridden_by_const + return given_argtypes end function is_argtype_match(๐•ƒ::AbstractLattice, @@ -89,9 +56,9 @@ end va_process_argtypes(๐•ƒ::AbstractLattice, given_argtypes::Vector{Any}, mi::MethodInstance) = va_process_argtypes(Returns(nothing), ๐•ƒ, given_argtypes, mi) function va_process_argtypes(@specialize(va_handler!), ๐•ƒ::AbstractLattice, given_argtypes::Vector{Any}, mi::MethodInstance) - def = mi.def - isva = isa(def, Method) ? def.isva : false - nargs = isa(def, Method) ? Int(def.nargs) : length(mi.specTypes.parameters) + def = mi.def::Method + isva = def.isva + nargs = Int(def.nargs) if isva || isvarargtype(given_argtypes[end]) isva_given_argtypes = Vector{Any}(undef, nargs) for i = 1:(nargs-isva) @@ -112,14 +79,11 @@ function va_process_argtypes(@specialize(va_handler!), ๐•ƒ::AbstractLattice, gi return given_argtypes end -function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(specTypes), - withfirst::Bool = true) +function most_general_argtypes(method::Union{Method,Nothing}, @nospecialize(specTypes)) toplevel = method === nothing isva = !toplevel && method.isva mi_argtypes = Any[(unwrap_unionall(specTypes)::DataType).parameters...] nargs::Int = toplevel ? 0 : method.nargs - # For opaque closure, the closure environment is processed elsewhere - withfirst || (nargs -= 1) cache_argtypes = Vector{Any}(undef, nargs) # First, if we're dealing with a varargs method, then we set the last element of `args` # to the appropriate `Tuple` type or `PartialStruct` instance. @@ -162,17 +126,16 @@ function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(spe cache_argtypes[nargs] = vargtype nargs -= 1 end - # Now, we propagate type info from `linfo_argtypes` into `cache_argtypes`, improving some + # Now, we propagate type info from `mi_argtypes` into `cache_argtypes`, improving some # type info as we go (where possible). Note that if we're dealing with a varargs method, # we already handled the last element of `cache_argtypes` (and decremented `nargs` so that # we don't overwrite the result of that work here). if mi_argtypes_length > 0 - n = mi_argtypes_length > nargs ? nargs : mi_argtypes_length - tail_index = n + tail_index = nargtypes = min(mi_argtypes_length, nargs) local lastatype - for i = 1:n + for i = 1:nargtypes atyp = mi_argtypes[i] - if i == n && isvarargtype(atyp) + if i == nargtypes && isvarargtype(atyp) atyp = unwrapva(atyp) tail_index -= 1 end @@ -185,16 +148,16 @@ function most_general_argtypes(method::Union{Method, Nothing}, @nospecialize(spe else atyp = elim_free_typevars(rewrap_unionall(atyp, specTypes)) end - i == n && (lastatype = atyp) + i == nargtypes && (lastatype = atyp) cache_argtypes[i] = atyp end - for i = (tail_index + 1):nargs + for i = (tail_index+1):nargs cache_argtypes[i] = lastatype end else @assert nargs == 0 "invalid specialization of method" # wrong number of arguments end - cache_argtypes + return cache_argtypes end # eliminate free `TypeVar`s in order to make the life much easier down the road: @@ -213,22 +176,15 @@ end function cache_lookup(๐•ƒ::AbstractLattice, mi::MethodInstance, given_argtypes::Vector{Any}, cache::Vector{InferenceResult}) method = mi.def::Method - nargs = Int(method.nargs) - method.isva && (nargs -= 1) - length(given_argtypes) โ‰ฅ nargs || return nothing + nargtypes = length(given_argtypes) + @assert nargtypes == Int(method.nargs) "invalid `given_argtypes` for `mi`" for cached_result in cache - cached_result.linfo === mi || continue + cached_result.linfo === mi || @goto next_cache cache_argtypes = cached_result.argtypes - cache_overridden_by_const = cached_result.overridden_by_const - for i in 1:nargs - if !is_argtype_match(๐•ƒ, widenmustalias(given_argtypes[i]), - cache_argtypes[i], cache_overridden_by_const[i]) - @goto next_cache - end - end - if method.isva - if !is_argtype_match(๐•ƒ, tuple_tfunc(๐•ƒ, given_argtypes[(nargs + 1):end]), - cache_argtypes[end], cache_overridden_by_const[end]) + @assert length(cache_argtypes) == nargtypes "invalid `cache_argtypes` for `mi`" + cache_overridden_by_const = cached_result.overridden_by_const::BitVector + for i in 1:nargtypes + if !is_argtype_match(๐•ƒ, given_argtypes[i], cache_argtypes[i], cache_overridden_by_const[i]) @goto next_cache end end diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 3c71a88ab8a80a..73c697d81b1845 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -832,7 +832,10 @@ end frame_parent(sv::InferenceState) = sv.parent::Union{Nothing,AbsIntState} frame_parent(sv::IRInterpretationState) = sv.parent::Union{Nothing,AbsIntState} -is_constproped(sv::InferenceState) = any(sv.result.overridden_by_const) +function is_constproped(sv::InferenceState) + (;overridden_by_const) = sv.result + return overridden_by_const !== nothing +end is_constproped(::IRInterpretationState) = true is_cached(sv::InferenceState) = !iszero(sv.cache_mode & CACHE_MODE_GLOBAL) diff --git a/base/compiler/ssair/legacy.jl b/base/compiler/ssair/legacy.jl index f5181691cdf7bd..b45db03875801c 100644 --- a/base/compiler/ssair/legacy.jl +++ b/base/compiler/ssair/legacy.jl @@ -10,7 +10,7 @@ the original `ci::CodeInfo` are modified. """ function inflate_ir!(ci::CodeInfo, mi::MethodInstance) sptypes = sptypes_from_meth_instance(mi) - argtypes, _ = matching_cache_argtypes(fallback_lattice, mi) + argtypes = matching_cache_argtypes(fallback_lattice, mi) return inflate_ir!(ci, sptypes, argtypes) end function inflate_ir!(ci::CodeInfo, sptypes::Vector{VarState}, argtypes::Vector{Any}) diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 825045670e3500..22b0afc9b03c14 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -810,7 +810,7 @@ struct EdgeCallResult end end -# return cached regular inference result +# return cached result of regular inference function return_cached_result(::AbstractInterpreter, codeinst::CodeInstance, caller::AbsIntState) rt = cached_return_type(codeinst) effects = ipo_effects(codeinst) @@ -869,10 +869,8 @@ function typeinf_edge(interp::AbstractInterpreter, method::Method, @nospecialize effects = isinferred ? frame.result.ipo_effects : adjust_effects(Effects(), method) # effects are adjusted already within `finish` for ipo_effects exc_bestguess = refine_exception_type(frame.exc_bestguess, effects) # propagate newly inferred source to the inliner, allowing efficient inlining w/o deserialization: - # note that this result is cached globally exclusively, we can use this local result destructively - volatile_inf_result = (isinferred && (force_inline || - src_inlining_policy(interp, result.src, NoCallInfo(), IR_FLAG_NULL))) ? - VolatileInferenceResult(result) : nothing + # note that this result is cached globally exclusively, so we can use this local result destructively + volatile_inf_result = isinferred ? VolatileInferenceResult(result) : nothing return EdgeCallResult(frame.bestguess, exc_bestguess, edge, effects, volatile_inf_result) elseif frame === true # unresolvable cycle diff --git a/base/compiler/types.jl b/base/compiler/types.jl index 12c747d0c57075..30cb0fb0f39c55 100644 --- a/base/compiler/types.jl +++ b/base/compiler/types.jl @@ -57,8 +57,6 @@ struct VarState VarState(@nospecialize(typ), undef::Bool) = new(typ, undef) end -abstract type ForwardableArgtypes end - struct AnalysisResults result next::AnalysisResults @@ -70,16 +68,19 @@ end const NULL_ANALYSIS_RESULTS = AnalysisResults(nothing) """ - InferenceResult(mi::MethodInstance, [argtypes::ForwardableArgtypes, ๐•ƒ::AbstractLattice]) + result::InferenceResult A type that represents the result of running type inference on a chunk of code. - -See also [`matching_cache_argtypes`](@ref). +There are two constructor available: +- `InferenceResult(mi::MethodInstance, [๐•ƒ::AbstractLattice])` for regular inference, + without extended lattice information included in `result.argtypes`. +- `InferenceResult(mi::MethodInstance, argtypes::Vector{Any}, overridden_by_const::BitVector)` + for constant inference, with extended lattice information included in `result.argtypes`. """ mutable struct InferenceResult const linfo::MethodInstance const argtypes::Vector{Any} - const overridden_by_const::BitVector + const overridden_by_const::Union{Nothing,BitVector} result # extended lattice element if inferred, nothing otherwise exc_result # like `result`, but for the thrown value src # ::Union{CodeInfo, IRCode, OptimizationState} if inferred copy is available, nothing otherwise @@ -89,16 +90,18 @@ mutable struct InferenceResult analysis_results::AnalysisResults # AnalysisResults with e.g. result::ArgEscapeCache if optimized, otherwise NULL_ANALYSIS_RESULTS is_src_volatile::Bool # `src` has been cached globally as the compressed format already, allowing `src` to be used destructively ci::CodeInstance # CodeInstance if this result has been added to the cache - function InferenceResult(mi::MethodInstance, cache_argtypes::Vector{Any}, overridden_by_const::BitVector) - # def = mi.def - # nargs = def isa Method ? Int(def.nargs) : 0 - # @assert length(cache_argtypes) == nargs - return new(mi, cache_argtypes, overridden_by_const, nothing, nothing, nothing, + function InferenceResult(mi::MethodInstance, argtypes::Vector{Any}, overridden_by_const::Union{Nothing,BitVector}) + def = mi.def + nargs = def isa Method ? Int(def.nargs) : 0 + @assert length(argtypes) == nargs "invalid `argtypes` for `mi`" + return new(mi, argtypes, overridden_by_const, nothing, nothing, nothing, WorldRange(), Effects(), Effects(), NULL_ANALYSIS_RESULTS, false) end end -InferenceResult(mi::MethodInstance, ๐•ƒ::AbstractLattice=fallback_lattice) = - InferenceResult(mi, matching_cache_argtypes(๐•ƒ, mi)...) +function InferenceResult(mi::MethodInstance, ๐•ƒ::AbstractLattice=fallback_lattice) + argtypes = matching_cache_argtypes(๐•ƒ, mi) + return InferenceResult(mi, argtypes, #=overridden_by_const=#nothing) +end function stack_analysis_result!(inf_result::InferenceResult, @nospecialize(result)) return inf_result.analysis_results = AnalysisResults(result, inf_result.analysis_results) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 3accb1edf54e03..7bc1032828c80d 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -4485,7 +4485,7 @@ let # Vararg #=va=# Bound, unbound, # => Tuple{Integer,Integer} (invalid `TypeVar` widened beforehand) } where Bound<:Integer - argtypes = Core.Compiler.most_general_argtypes(method, specTypes, true) + argtypes = Core.Compiler.most_general_argtypes(method, specTypes) popfirst!(argtypes) @test argtypes[1] == Integer @test argtypes[2] == Integer From 26070ca33417a16cb5e000e3e953793e0a87b937 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Tue, 9 Apr 2024 10:32:00 -0400 Subject: [PATCH 105/123] irinterp: Don't try to access mi.def if it's not a Method (#54003) I don't believe this is reachable from the base compiler pipeline, since we don't run irinterp on toplevel things, but I am seeing this in downstream packages. --- base/compiler/inferencestate.jl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 73c697d81b1845..48784378ef7c10 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -783,9 +783,13 @@ mutable struct IRInterpretationState for i = 1:length(given_argtypes) given_argtypes[i] = widenslotwrapper(argtypes[i]) end - given_argtypes = va_process_argtypes(optimizer_lattice(interp), given_argtypes, mi) - argtypes_refined = Bool[!โŠ‘(optimizer_lattice(interp), ir.argtypes[i], given_argtypes[i]) - for i = 1:length(given_argtypes)] + if isa(mi.def, Method) + given_argtypes = va_process_argtypes(optimizer_lattice(interp), given_argtypes, mi) + argtypes_refined = Bool[!โŠ‘(optimizer_lattice(interp), ir.argtypes[i], given_argtypes[i]) + for i = 1:length(given_argtypes)] + else + argtypes_refined = Bool[false for i = 1:length(given_argtypes)] + end empty!(ir.argtypes) append!(ir.argtypes, given_argtypes) tpdum = TwoPhaseDefUseMap(length(ir.stmts)) From 7099bddd5f0b430b5e2fe7e12e64384fbcf5b724 Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Tue, 9 Apr 2024 21:25:26 +0530 Subject: [PATCH 106/123] LinearAlgebra: LazyString in interpolated error messages (#53976) --- stdlib/LinearAlgebra/src/abstractq.jl | 22 +- stdlib/LinearAlgebra/src/adjtrans.jl | 2 +- stdlib/LinearAlgebra/src/bidiag.jl | 20 +- stdlib/LinearAlgebra/src/dense.jl | 4 +- stdlib/LinearAlgebra/src/diagonal.jl | 34 +- stdlib/LinearAlgebra/src/generic.jl | 22 +- stdlib/LinearAlgebra/src/hessenberg.jl | 6 +- stdlib/LinearAlgebra/src/lapack.jl | 312 +++++++++--------- stdlib/LinearAlgebra/src/lbt.jl | 4 +- stdlib/LinearAlgebra/src/ldlt.jl | 2 +- stdlib/LinearAlgebra/src/lu.jl | 6 +- stdlib/LinearAlgebra/src/qr.jl | 4 +- stdlib/LinearAlgebra/src/special.jl | 2 +- .../LinearAlgebra/src/structuredbroadcast.jl | 2 +- stdlib/LinearAlgebra/src/symmetric.jl | 2 +- stdlib/LinearAlgebra/src/triangular.jl | 58 ++-- stdlib/LinearAlgebra/src/tridiag.jl | 40 +-- 17 files changed, 271 insertions(+), 271 deletions(-) diff --git a/stdlib/LinearAlgebra/src/abstractq.jl b/stdlib/LinearAlgebra/src/abstractq.jl index b0d53320f4aa39..d6e251e6203091 100644 --- a/stdlib/LinearAlgebra/src/abstractq.jl +++ b/stdlib/LinearAlgebra/src/abstractq.jl @@ -149,13 +149,13 @@ end # generically, treat AbstractQ like a matrix with its definite size qsize_check(Q::AbstractQ, B::AbstractVecOrMat) = size(Q, 2) == size(B, 1) || - throw(DimensionMismatch("second dimension of Q, $(size(Q,2)), must coincide with first dimension of B, $(size(B,1))")) + throw(DimensionMismatch(lazy"second dimension of Q, $(size(Q,2)), must coincide with first dimension of B, $(size(B,1))")) qsize_check(A::AbstractVecOrMat, Q::AbstractQ) = size(A, 2) == size(Q, 1) || - throw(DimensionMismatch("second dimension of A, $(size(A,2)), must coincide with first dimension of Q, $(size(Q,1))")) + throw(DimensionMismatch(lazy"second dimension of A, $(size(A,2)), must coincide with first dimension of Q, $(size(Q,1))")) qsize_check(Q::AbstractQ, P::AbstractQ) = size(Q, 2) == size(P, 1) || - throw(DimensionMismatch("second dimension of A, $(size(Q,2)), must coincide with first dimension of B, $(size(P,1))")) + throw(DimensionMismatch(lazy"second dimension of A, $(size(Q,2)), must coincide with first dimension of B, $(size(P,1))")) # mimic the AbstractArray fallback *(Q::AbstractQ{<:Number}) = Q @@ -317,7 +317,7 @@ function lmul!(A::QRPackedQ, B::AbstractVecOrMat) mA, nA = size(A.factors) mB, nB = size(B,1), size(B,2) if mA != mB - throw(DimensionMismatch("matrix A has dimensions ($mA,$nA) but B has dimensions ($mB, $nB)")) + throw(DimensionMismatch(lazy"matrix A has dimensions ($mA,$nA) but B has dimensions ($mB, $nB)")) end Afactors = A.factors @inbounds begin @@ -353,7 +353,7 @@ function lmul!(adjA::AdjointQ{<:Any,<:QRPackedQ}, B::AbstractVecOrMat) mA, nA = size(A.factors) mB, nB = size(B,1), size(B,2) if mA != mB - throw(DimensionMismatch("matrix A has dimensions ($mA,$nA) but B has dimensions ($mB, $nB)")) + throw(DimensionMismatch(lazy"matrix A has dimensions ($mA,$nA) but B has dimensions ($mB, $nB)")) end Afactors = A.factors @inbounds begin @@ -384,7 +384,7 @@ function rmul!(A::AbstractVecOrMat, Q::QRPackedQ) mQ, nQ = size(Q.factors) mA, nA = size(A,1), size(A,2) if nA != mQ - throw(DimensionMismatch("matrix A has dimensions ($mA,$nA) but matrix Q has dimensions ($mQ, $nQ)")) + throw(DimensionMismatch(lazy"matrix A has dimensions ($mA,$nA) but matrix Q has dimensions ($mQ, $nQ)")) end Qfactors = Q.factors @inbounds begin @@ -420,7 +420,7 @@ function rmul!(A::AbstractVecOrMat, adjQ::AdjointQ{<:Any,<:QRPackedQ}) mQ, nQ = size(Q.factors) mA, nA = size(A,1), size(A,2) if nA != mQ - throw(DimensionMismatch("matrix A has dimensions ($mA,$nA) but matrix Q has dimensions ($mQ, $nQ)")) + throw(DimensionMismatch(lazy"matrix A has dimensions ($mA,$nA) but matrix Q has dimensions ($mQ, $nQ)")) end Qfactors = Q.factors @inbounds begin @@ -521,10 +521,10 @@ rmul!(X::Adjoint{T,<:StridedVecOrMat{T}}, adjQ::AdjointQ{<:Any,<:HessenbergQ{T}} # flexible left-multiplication (and adjoint right-multiplication) qsize_check(Q::Union{QRPackedQ,QRCompactWYQ,HessenbergQ}, B::AbstractVecOrMat) = size(B, 1) in size(Q.factors) || - throw(DimensionMismatch("first dimension of B, $(size(B,1)), must equal one of the dimensions of Q, $(size(Q.factors))")) + throw(DimensionMismatch(lazy"first dimension of B, $(size(B,1)), must equal one of the dimensions of Q, $(size(Q.factors))")) qsize_check(A::AbstractVecOrMat, adjQ::AdjointQ{<:Any,<:Union{QRPackedQ,QRCompactWYQ,HessenbergQ}}) = (Q = adjQ.Q; size(A, 2) in size(Q.factors) || - throw(DimensionMismatch("second dimension of A, $(size(A,2)), must equal one of the dimensions of Q, $(size(Q.factors))"))) + throw(DimensionMismatch(lazy"second dimension of A, $(size(A,2)), must equal one of the dimensions of Q, $(size(Q.factors))"))) det(Q::HessenbergQ) = _det_tau(Q.ฯ„) @@ -560,10 +560,10 @@ size(Q::LQPackedQ) = (n = size(Q.factors, 2); return n, n) qsize_check(adjQ::AdjointQ{<:Any,<:LQPackedQ}, B::AbstractVecOrMat) = size(B, 1) in size(adjQ.Q.factors) || - throw(DimensionMismatch("first dimension of B, $(size(B,1)), must equal one of the dimensions of Q, $(size(adjQ.Q.factors))")) + throw(DimensionMismatch(lazy"first dimension of B, $(size(B,1)), must equal one of the dimensions of Q, $(size(adjQ.Q.factors))")) qsize_check(A::AbstractVecOrMat, Q::LQPackedQ) = size(A, 2) in size(Q.factors) || - throw(DimensionMismatch("second dimension of A, $(size(A,2)), must equal one of the dimensions of Q, $(size(Q.factors))")) + throw(DimensionMismatch(lazy"second dimension of A, $(size(A,2)), must equal one of the dimensions of Q, $(size(Q.factors))")) # in-place right-application of LQPackedQs # these methods require that the applied-to matrix's (A's) number of columns diff --git a/stdlib/LinearAlgebra/src/adjtrans.jl b/stdlib/LinearAlgebra/src/adjtrans.jl index 24ad7960f00b4a..f52460a870ca07 100644 --- a/stdlib/LinearAlgebra/src/adjtrans.jl +++ b/stdlib/LinearAlgebra/src/adjtrans.jl @@ -465,7 +465,7 @@ tr(A::Transpose) = transpose(tr(parent(A))) function _dot_nonrecursive(u, v) lu = length(u) if lu != length(v) - throw(DimensionMismatch("first array has length $(lu) which does not match the length of the second, $(length(v)).")) + throw(DimensionMismatch(lazy"first array has length $(lu) which does not match the length of the second, $(length(v)).")) end if lu == 0 zero(eltype(u)) * zero(eltype(v)) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index b805d0ca309b9e..323edd5ad45c64 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -8,7 +8,7 @@ struct Bidiagonal{T,V<:AbstractVector{T}} <: AbstractMatrix{T} function Bidiagonal{T,V}(dv, ev, uplo::AbstractChar) where {T,V<:AbstractVector{T}} require_one_based_indexing(dv, ev) if length(ev) != max(length(dv)-1, 0) - throw(DimensionMismatch("length of diagonal vector is $(length(dv)), length of off-diagonal vector is $(length(ev))")) + throw(DimensionMismatch(lazy"length of diagonal vector is $(length(dv)), length of off-diagonal vector is $(length(ev))")) end (uplo != 'U' && uplo != 'L') && throw_uplo() new{T,V}(dv, ev, uplo) @@ -438,11 +438,11 @@ function check_A_mul_B!_sizes(C, A, B) mB, nB = size(B) mC, nC = size(C) if mA != mC - throw(DimensionMismatch("first dimension of A, $mA, and first dimension of output C, $mC, must match")) + throw(DimensionMismatch(lazy"first dimension of A, $mA, and first dimension of output C, $mC, must match")) elseif nA != mB - throw(DimensionMismatch("second dimension of A, $nA, and first dimension of B, $mB, must match")) + throw(DimensionMismatch(lazy"second dimension of A, $nA, and first dimension of B, $mB, must match")) elseif nB != nC - throw(DimensionMismatch("second dimension of output C, $nC, and second dimension of B, $nB, must match")) + throw(DimensionMismatch(lazy"second dimension of output C, $nC, and second dimension of B, $nB, must match")) end end @@ -562,10 +562,10 @@ function _mul!(C::AbstractVecOrMat, A::BiTriSym, B::AbstractVecOrMat, _add::MulA nA = size(A,1) nB = size(B,2) if !(size(C,1) == size(B,1) == nA) - throw(DimensionMismatch("A has first dimension $nA, B has $(size(B,1)), C has $(size(C,1)) but all must match")) + throw(DimensionMismatch(lazy"A has first dimension $nA, B has $(size(B,1)), C has $(size(C,1)) but all must match")) end if size(C,2) != nB - throw(DimensionMismatch("A has second dimension $nA, B has $(size(B,2)), C has $(size(C,2)) but all must match")) + throw(DimensionMismatch(lazy"A has second dimension $nA, B has $(size(B,2)), C has $(size(C,2)) but all must match")) end iszero(nA) && return C iszero(_add.alpha) && return _rmul_or_fill!(C, _add.beta) @@ -763,11 +763,11 @@ function ldiv!(c::AbstractVecOrMat, A::Bidiagonal, b::AbstractVecOrMat) N = size(A, 2) mb, nb = size(b, 1), size(b, 2) if N != mb - throw(DimensionMismatch("second dimension of A, $N, does not match first dimension of b, $mb")) + throw(DimensionMismatch(lazy"second dimension of A, $N, does not match first dimension of b, $mb")) end mc, nc = size(c, 1), size(c, 2) if mc != mb || nc != nb - throw(DimensionMismatch("size of result, ($mc, $nc), does not match the size of b, ($mb, $nb)")) + throw(DimensionMismatch(lazy"size of result, ($mc, $nc), does not match the size of b, ($mb, $nb)")) end if N == 0 @@ -833,11 +833,11 @@ function _rdiv!(C::AbstractMatrix, A::AbstractMatrix, B::Bidiagonal) require_one_based_indexing(C, A, B) m, n = size(A) if size(B, 1) != n - throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) + throw(DimensionMismatch(lazy"right hand side B needs first dimension of size $n, has size $(size(B,1))")) end mc, nc = size(C) if mc != m || nc != n - throw(DimensionMismatch("expect output to have size ($m, $n), but got ($mc, $nc)")) + throw(DimensionMismatch(lazy"expect output to have size ($m, $n), but got ($mc, $nc)")) end zi = findfirst(iszero, B.dv) diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index 72c3792d7867c8..97a64aee3e7213 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/dense.jl @@ -336,7 +336,7 @@ function diagm_size(size::Tuple{Int,Int}, kv::Pair{<:Integer,<:AbstractVector}.. mmax = mapreduce(x -> length(x.second) - min(0,Int(x.first)), max, kv; init=0) nmax = mapreduce(x -> length(x.second) + max(0,Int(x.first)), max, kv; init=0) m, n = size - (m โ‰ฅ mmax && n โ‰ฅ nmax) || throw(DimensionMismatch("invalid size=$size")) + (m โ‰ฅ mmax && n โ‰ฅ nmax) || throw(DimensionMismatch(lazy"invalid size=$size")) return m, n end function diagm_container(size, kv::Pair{<:Integer,<:AbstractVector}...) @@ -1645,7 +1645,7 @@ function cond(A::AbstractMatrix, p::Real=2) end end end - throw(ArgumentError("p-norm must be 1, 2 or Inf, got $p")) + throw(ArgumentError(lazy"p-norm must be 1, 2 or Inf, got $p")) end ## Lyapunov and Sylvester equation diff --git a/stdlib/LinearAlgebra/src/diagonal.jl b/stdlib/LinearAlgebra/src/diagonal.jl index 8cee4a91d4696e..070edc39eab3a1 100644 --- a/stdlib/LinearAlgebra/src/diagonal.jl +++ b/stdlib/LinearAlgebra/src/diagonal.jl @@ -191,7 +191,7 @@ function setindex!(D::Diagonal, v, i::Int, j::Int) if i == j @inbounds D.diag[i] = v elseif !iszero(v) - throw(ArgumentError("cannot set off-diagonal entry ($i, $j) to a nonzero value ($v)")) + throw(ArgumentError(lazy"cannot set off-diagonal entry ($i, $j) to a nonzero value ($v)")) end return v end @@ -280,13 +280,13 @@ Base.literal_pow(::typeof(^), D::Diagonal, ::Val{-1}) = inv(D) # for disambiguat function _muldiag_size_check(A, B) nA = size(A, 2) mB = size(B, 1) - @noinline throw_dimerr(::AbstractMatrix, nA, mB) = throw(DimensionMismatch("second dimension of A, $nA, does not match first dimension of B, $mB")) - @noinline throw_dimerr(::AbstractVector, nA, mB) = throw(DimensionMismatch("second dimension of D, $nA, does not match length of V, $mB")) + @noinline throw_dimerr(::AbstractMatrix, nA, mB) = throw(DimensionMismatch(lazy"second dimension of A, $nA, does not match first dimension of B, $mB")) + @noinline throw_dimerr(::AbstractVector, nA, mB) = throw(DimensionMismatch(lazy"second dimension of D, $nA, does not match length of V, $mB")) nA == mB || throw_dimerr(B, nA, mB) return nothing end # the output matrix should have the same size as the non-diagonal input matrix or vector -@noinline throw_dimerr(szC, szA) = throw(DimensionMismatch("output matrix has size: $szC, but should have size $szA")) +@noinline throw_dimerr(szC, szA) = throw(DimensionMismatch(lazy"output matrix has size: $szC, but should have size $szA")) _size_check_out(C, ::Diagonal, A) = _size_check_out(C, A) _size_check_out(C, A, ::Diagonal) = _size_check_out(C, A) _size_check_out(C, A::Diagonal, ::Diagonal) = _size_check_out(C, A) @@ -432,7 +432,7 @@ function _rdiv!(B::AbstractVecOrMat, A::AbstractVecOrMat, D::Diagonal) dd = D.diag m, n = size(A, 1), size(A, 2) if (k = length(dd)) != n - throw(DimensionMismatch("left hand side has $n columns but D is $k by $k")) + throw(DimensionMismatch(lazy"left hand side has $n columns but D is $k by $k")) end @inbounds for j in 1:n ddj = dd[j] @@ -458,8 +458,8 @@ function ldiv!(B::AbstractVecOrMat, D::Diagonal, A::AbstractVecOrMat) d = length(dd) m, n = size(A, 1), size(A, 2) mโ€ฒ, nโ€ฒ = size(B, 1), size(B, 2) - m == d || throw(DimensionMismatch("right hand side has $m rows but D is $d by $d")) - (m, n) == (mโ€ฒ, nโ€ฒ) || throw(DimensionMismatch("expect output to be $m by $n, but got $mโ€ฒ by $nโ€ฒ")) + m == d || throw(DimensionMismatch(lazy"right hand side has $m rows but D is $d by $d")) + (m, n) == (mโ€ฒ, nโ€ฒ) || throw(DimensionMismatch(lazy"expect output to be $m by $n, but got $mโ€ฒ by $nโ€ฒ")) j = findfirst(iszero, D.diag) isnothing(j) || throw(SingularException(j)) @inbounds for j = 1:n, i = 1:m @@ -470,7 +470,7 @@ end function _rdiv!(Dc::Diagonal, Db::Diagonal, Da::Diagonal) n, k = length(Db.diag), length(Da.diag) - n == k || throw(DimensionMismatch("left hand side has $n columns but D is $k by $k")) + n == k || throw(DimensionMismatch(lazy"left hand side has $n columns but D is $k by $k")) j = findfirst(iszero, Da.diag) isnothing(j) || throw(SingularException(j)) Dc.diag .= Db.diag ./ Da.diag @@ -498,10 +498,10 @@ function ldiv!(T::Tridiagonal, D::Diagonal, S::Union{SymTridiagonal,Tridiagonal} m = size(S, 1) dd = D.diag if (k = length(dd)) != m - throw(DimensionMismatch("diagonal matrix is $k by $k but right hand side has $m rows")) + throw(DimensionMismatch(lazy"diagonal matrix is $k by $k but right hand side has $m rows")) end if length(T.d) != m - throw(DimensionMismatch("target matrix size $(size(T)) does not match input matrix size $(size(S))")) + throw(DimensionMismatch(lazy"target matrix size $(size(T)) does not match input matrix size $(size(S))")) end m == 0 && return T j = findfirst(iszero, dd) @@ -535,10 +535,10 @@ function _rdiv!(T::Tridiagonal, S::Union{SymTridiagonal,Tridiagonal}, D::Diagona n = size(S, 2) dd = D.diag if (k = length(dd)) != n - throw(DimensionMismatch("left hand side has $n columns but D is $k by $k")) + throw(DimensionMismatch(lazy"left hand side has $n columns but D is $k by $k")) end if length(T.d) != n - throw(DimensionMismatch("target matrix size $(size(T)) does not match input matrix size $(size(S))")) + throw(DimensionMismatch(lazy"target matrix size $(size(T)) does not match input matrix size $(size(S))")) end n == 0 && return T j = findfirst(iszero, dd) @@ -608,7 +608,7 @@ end valB = B.diag; nB = length(valB) nC = checksquare(C) @boundscheck nC == nA*nB || - throw(DimensionMismatch("expect C to be a $(nA*nB)x$(nA*nB) matrix, got size $(nC)x$(nC)")) + throw(DimensionMismatch(lazy"expect C to be a $(nA*nB)x$(nA*nB) matrix, got size $(nC)x$(nC)")) isempty(A) || isempty(B) || fill!(C, zero(A[1,1] * B[1,1])) @inbounds for i = 1:nA, j = 1:nB idx = (i-1)*nB+j @@ -639,7 +639,7 @@ end (mB, nB) = size(B) (mC, nC) = size(C) @boundscheck (mC, nC) == (mA * mB, nA * nB) || - throw(DimensionMismatch("expect C to be a $(mA * mB)x$(nA * nB) matrix, got size $(mC)x$(nC)")) + throw(DimensionMismatch(lazy"expect C to be a $(mA * mB)x$(nA * nB) matrix, got size $(mC)x$(nC)")) isempty(A) || isempty(B) || fill!(C, zero(A[1,1] * B[1,1])) m = 1 @inbounds for j = 1:nA @@ -662,7 +662,7 @@ end (mB, nB) = size(B) (mC, nC) = size(C) @boundscheck (mC, nC) == (mA * mB, nA * nB) || - throw(DimensionMismatch("expect C to be a $(mA * mB)x$(nA * nB) matrix, got size $(mC)x$(nC)")) + throw(DimensionMismatch(lazy"expect C to be a $(mA * mB)x$(nA * nB) matrix, got size $(mC)x$(nC)")) isempty(A) || isempty(B) || fill!(C, zero(A[1,1] * B[1,1])) m = 1 @inbounds for j = 1:nA @@ -875,7 +875,7 @@ dot(x::AbstractVector, D::Diagonal, y::AbstractVector) = _mapreduce_prod(dot, x, dot(A::Diagonal, B::Diagonal) = dot(A.diag, B.diag) function dot(D::Diagonal, B::AbstractMatrix) - size(D) == size(B) || throw(DimensionMismatch("Matrix sizes $(size(D)) and $(size(B)) differ")) + size(D) == size(B) || throw(DimensionMismatch(lazy"Matrix sizes $(size(D)) and $(size(B)) differ")) return dot(D.diag, view(B, diagind(B, IndexStyle(B)))) end @@ -883,7 +883,7 @@ dot(A::AbstractMatrix, B::Diagonal) = conj(dot(B, A)) function _mapreduce_prod(f, x, D::Diagonal, y) if !(length(x) == length(D.diag) == length(y)) - throw(DimensionMismatch("x has length $(length(x)), D has size $(size(D)), and y has $(length(y))")) + throw(DimensionMismatch(lazy"x has length $(length(x)), D has size $(size(D)), and y has $(length(y))")) end if isempty(x) && isempty(D) && isempty(y) return zero(promote_op(f, eltype(x), eltype(D), eltype(y))) diff --git a/stdlib/LinearAlgebra/src/generic.jl b/stdlib/LinearAlgebra/src/generic.jl index 023f2a1147febc..35014cd5206302 100644 --- a/stdlib/LinearAlgebra/src/generic.jl +++ b/stdlib/LinearAlgebra/src/generic.jl @@ -110,7 +110,7 @@ end function generic_mul!(C::AbstractArray, X::AbstractArray, s::Number, _add::MulAddMul) if length(C) != length(X) - throw(DimensionMismatch("first array has length $(length(C)) which does not match the length of the second, $(length(X)).")) + throw(DimensionMismatch(lazy"first array has length $(length(C)) which does not match the length of the second, $(length(X)).")) end for (IC, IX) in zip(eachindex(C), eachindex(X)) @inbounds _modify!(_add, X[IX] * s, C, IC) @@ -120,7 +120,7 @@ end function generic_mul!(C::AbstractArray, s::Number, X::AbstractArray, _add::MulAddMul) if length(C) != length(X) - throw(DimensionMismatch("first array has length $(length(C)) which does not + throw(DimensionMismatch(lazy"first array has length $(length(C)) which does not match the length of the second, $(length(X)).")) end for (IC, IX) in zip(eachindex(C), eachindex(X)) @@ -748,7 +748,7 @@ function opnorm(A::AbstractMatrix, p::Real=2) elseif p == Inf return opnormInf(A) else - throw(ArgumentError("invalid p-norm p=$p. Valid: 1, 2, Inf")) + throw(ArgumentError(lazy"invalid p-norm p=$p. Valid: 1, 2, Inf")) end end @@ -886,7 +886,7 @@ dot(x::Number, y::Number) = conj(x) * y function dot(x::AbstractArray, y::AbstractArray) lx = length(x) if lx != length(y) - throw(DimensionMismatch("first array has length $(lx) which does not match the length of the second, $(length(y)).")) + throw(DimensionMismatch(lazy"first array has length $(lx) which does not match the length of the second, $(length(y)).")) end if lx == 0 return dot(zero(eltype(x)), zero(eltype(y))) @@ -1464,7 +1464,7 @@ julia> axpy!(2, x, y) function axpy!(ฮฑ, x::AbstractArray, y::AbstractArray) n = length(x) if n != length(y) - throw(DimensionMismatch("x has length $n, but y has length $(length(y))")) + throw(DimensionMismatch(lazy"x has length $n, but y has length $(length(y))")) end iszero(ฮฑ) && return y for (IY, IX) in zip(eachindex(y), eachindex(x)) @@ -1475,7 +1475,7 @@ end function axpy!(ฮฑ, x::AbstractArray, rx::AbstractArray{<:Integer}, y::AbstractArray, ry::AbstractArray{<:Integer}) if length(rx) != length(ry) - throw(DimensionMismatch("rx has length $(length(rx)), but ry has length $(length(ry))")) + throw(DimensionMismatch(lazy"rx has length $(length(rx)), but ry has length $(length(ry))")) elseif !checkindex(Bool, eachindex(IndexLinear(), x), rx) throw(BoundsError(x, rx)) elseif !checkindex(Bool, eachindex(IndexLinear(), y), ry) @@ -1509,7 +1509,7 @@ julia> axpby!(2, x, 2, y) """ function axpby!(ฮฑ, x::AbstractArray, ฮฒ, y::AbstractArray) if length(x) != length(y) - throw(DimensionMismatch("x has length $(length(x)), but y has length $(length(y))")) + throw(DimensionMismatch(lazy"x has length $(length(x)), but y has length $(length(y))")) end iszero(ฮฑ) && isone(ฮฒ) && return y for (IX, IY) in zip(eachindex(x), eachindex(y)) @@ -1549,7 +1549,7 @@ function rotate!(x::AbstractVector, y::AbstractVector, c, s) require_one_based_indexing(x, y) n = length(x) if n != length(y) - throw(DimensionMismatch("x has length $(length(x)), but y has length $(length(y))")) + throw(DimensionMismatch(lazy"x has length $(length(x)), but y has length $(length(y))")) end @inbounds for i = 1:n xi, yi = x[i], y[i] @@ -1572,7 +1572,7 @@ function reflect!(x::AbstractVector, y::AbstractVector, c, s) require_one_based_indexing(x, y) n = length(x) if n != length(y) - throw(DimensionMismatch("x has length $(length(x)), but y has length $(length(y))")) + throw(DimensionMismatch(lazy"x has length $(length(x)), but y has length $(length(y))")) end @inbounds for i = 1:n xi, yi = x[i], y[i] @@ -1613,7 +1613,7 @@ Multiplies `A` in-place by a Householder reflection on the left. It is equivalen require_one_based_indexing(x) m, n = size(A, 1), size(A, 2) if length(x) != m - throw(DimensionMismatch("reflector has length $(length(x)), which must match the first dimension of matrix A, $m")) + throw(DimensionMismatch(lazy"reflector has length $(length(x)), which must match the first dimension of matrix A, $m")) end m == 0 && return A @inbounds for j = 1:n @@ -1943,7 +1943,7 @@ function copytrito!(B::AbstractMatrix, A::AbstractMatrix, uplo::AbstractChar) BLAS.chkuplo(uplo) m,n = size(A) m1,n1 = size(B) - (m1 < m || n1 < n) && throw(DimensionMismatch("B of size ($m1,$n1) should have at least the same number of rows and columns than A of size ($m,$n)")) + (m1 < m || n1 < n) && throw(DimensionMismatch(lazy"B of size ($m1,$n1) should have at least the same number of rows and columns than A of size ($m,$n)")) if uplo == 'U' for j=1:n for i=1:min(j,m) diff --git a/stdlib/LinearAlgebra/src/hessenberg.jl b/stdlib/LinearAlgebra/src/hessenberg.jl index 3be41baf24b244..f20d76e727b349 100644 --- a/stdlib/LinearAlgebra/src/hessenberg.jl +++ b/stdlib/LinearAlgebra/src/hessenberg.jl @@ -90,7 +90,7 @@ Base.@propagate_inbounds getindex(H::UpperHessenberg{T}, i::Integer, j::Integer) Base.@propagate_inbounds function setindex!(A::UpperHessenberg, x, i::Integer, j::Integer) if i > j+1 x == 0 || throw(ArgumentError("cannot set index in the lower triangular part " * - "($i, $j) of an UpperHessenberg matrix to a nonzero value ($x)")) + lazy"($i, $j) of an UpperHessenberg matrix to a nonzero value ($x)")) else A.data[i,j] = x end @@ -180,7 +180,7 @@ end function ldiv!(F::UpperHessenberg, B::AbstractVecOrMat; shift::Number=false) checksquare(F) m = size(F,1) - m != size(B,1) && throw(DimensionMismatch("wrong right-hand-side # rows != $m")) + m != size(B,1) && throw(DimensionMismatch(lazy"wrong right-hand-side # rows != $m")) require_one_based_indexing(B) n = size(B,2) H = F.data @@ -230,7 +230,7 @@ end function rdiv!(B::AbstractMatrix, F::UpperHessenberg; shift::Number=false) checksquare(F) m = size(F,1) - m != size(B,2) && throw(DimensionMismatch("wrong right-hand-side # cols != $m")) + m != size(B,2) && throw(DimensionMismatch(lazy"wrong right-hand-side # cols != $m")) require_one_based_indexing(B) n = size(B,1) H = F.data diff --git a/stdlib/LinearAlgebra/src/lapack.jl b/stdlib/LinearAlgebra/src/lapack.jl index 875ed3ed4e3da0..cf9a47073abd08 100644 --- a/stdlib/LinearAlgebra/src/lapack.jl +++ b/stdlib/LinearAlgebra/src/lapack.jl @@ -26,7 +26,7 @@ Handle only negative LAPACK error codes """ function chkargsok(ret::BlasInt) if ret < 0 - throw(ArgumentError("invalid argument #$(-ret) to LAPACK call")) + throw(ArgumentError(lazy"invalid argument #$(-ret) to LAPACK call")) end end @@ -35,7 +35,7 @@ function chklapackerror(ret::BlasInt, f...) if ret == 0 return elseif ret < 0 - throw(ArgumentError("invalid argument #$(-ret) to LAPACK call")) + throw(ArgumentError(lazy"invalid argument #$(-ret) to LAPACK call")) else # ret > 0 chklapackerror_positive(ret, f...) end @@ -63,7 +63,7 @@ end function chkvalidparam(position::Int, var::String, val, validvals) if val โˆ‰ validvals throw(ArgumentError( - "argument #$position: $var must be one of $validvals, but $(repr(val)) was passed")) + lazy"argument #$position: $var must be one of $validvals, but $(repr(val)) was passed")) end return val end @@ -71,7 +71,7 @@ end "Check that {c}transpose is correctly specified" function chktrans(trans::AbstractChar) if !(trans == 'N' || trans == 'C' || trans == 'T') - throw(ArgumentError("trans argument must be 'N' (no transpose), 'T' (transpose), or 'C' (conjugate transpose), got '$trans'")) + throw(ArgumentError(lazy"trans argument must be 'N' (no transpose), 'T' (transpose), or 'C' (conjugate transpose), got '$trans'")) end trans end @@ -79,7 +79,7 @@ end "Check that left/right hand side multiply is correctly specified" function chkside(side::AbstractChar) if !(side == 'L' || side == 'R') - throw(ArgumentError("side argument must be 'L' (left hand multiply) or 'R' (right hand multiply), got '$side'")) + throw(ArgumentError(lazy"side argument must be 'L' (left hand multiply) or 'R' (right hand multiply), got '$side'")) end side end @@ -87,7 +87,7 @@ end "Check that unit diagonal flag is correctly specified" function chkdiag(diag::AbstractChar) if !(diag == 'U' || diag =='N') - throw(ArgumentError("diag argument must be 'U' (unit diagonal) or 'N' (non-unit diagonal), got '$diag'")) + throw(ArgumentError(lazy"diag argument must be 'U' (unit diagonal) or 'N' (non-unit diagonal), got '$diag'")) end diag end @@ -178,7 +178,7 @@ for (gbtrf, gbtrs, elty) in info = Ref{BlasInt}() n = size(AB,2) if m != n || m != size(B,1) - throw(DimensionMismatch("matrix AB has dimensions $(size(AB)), but right hand side matrix B has dimensions $(size(B))")) + throw(DimensionMismatch(lazy"matrix AB has dimensions $(size(AB)), but right hand side matrix B has dimensions $(size(B))")) end ccall((@blasfunc($gbtrs), libblastrampoline), Cvoid, (Ref{UInt8}, Ref{BlasInt}, Ref{BlasInt}, Ref{BlasInt}, Ref{BlasInt}, @@ -355,7 +355,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty n = BlasInt(size(A, 2)) lda = BlasInt(max(1,stride(A, 2))) if length(tau) != min(m,n) - throw(DimensionMismatch("tau has length $(length(tau)), but needs length $(min(m,n))")) + throw(DimensionMismatch(lazy"tau has length $(length(tau)), but needs length $(min(m,n))")) end lwork = BlasInt(-1) work = Vector{$elty}(undef, 1) @@ -386,7 +386,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty n = BlasInt(size(A, 2)) lda = BlasInt(max(1,stride(A, 2))) if length(tau) != min(m,n) - throw(DimensionMismatch("tau has length $(length(tau)), but needs length $(min(m,n))")) + throw(DimensionMismatch(lazy"tau has length $(length(tau)), but needs length $(min(m,n))")) end lwork = BlasInt(-1) work = Vector{$elty}(undef, 1) @@ -416,10 +416,10 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chkstride1(A,jpvt,tau) m,n = size(A) if length(tau) != min(m,n) - throw(DimensionMismatch("tau has length $(length(tau)), but needs length $(min(m,n))")) + throw(DimensionMismatch(lazy"tau has length $(length(tau)), but needs length $(min(m,n))")) end if length(jpvt) != n - throw(DimensionMismatch("jpvt has length $(length(jpvt)), but needs length $n")) + throw(DimensionMismatch(lazy"jpvt has length $(length(jpvt)), but needs length $n")) end lda = stride(A,2) if lda == 0 @@ -466,7 +466,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty minmn = min(m, n) nb = size(T, 1) if nb > minmn - throw(ArgumentError("block size $nb > $minmn too large")) + throw(ArgumentError(lazy"block size $nb > $minmn too large")) end lda = max(1, stride(A,2)) work = Vector{$elty}(undef, nb*n) @@ -491,10 +491,10 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty m, n = size(A) p, q = size(T) if m < n - throw(DimensionMismatch("input matrix A has dimensions ($m,$n), but should have more rows than columns")) + throw(DimensionMismatch(lazy"input matrix A has dimensions ($m,$n), but should have more rows than columns")) end if p != n || q != n - throw(DimensionMismatch("block reflector T has dimensions ($p,$q), but should have dimensions ($n,$n)")) + throw(DimensionMismatch(lazy"block reflector T has dimensions ($p,$q), but should have dimensions ($n,$n)")) end if n > 0 # this implies `m > 0` because of `m >= n` info = Ref{BlasInt}() @@ -519,7 +519,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chkstride1(A,tau) m, n = size(A) if length(tau) != min(m,n) - throw(DimensionMismatch("tau has length $(length(tau)), but needs length $(min(m,n))")) + throw(DimensionMismatch(lazy"tau has length $(length(tau)), but needs length $(min(m,n))")) end work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -548,7 +548,7 @@ for (gebrd, gelqf, geqlf, geqrf, geqp3, geqrt, geqrt3, gerqf, getrf, elty, relty chkstride1(A,tau) m, n = size(A) if length(tau) != min(m,n) - throw(DimensionMismatch("tau has length $(length(tau)), but needs length $(min(m,n))")) + throw(DimensionMismatch(lazy"tau has length $(length(tau)), but needs length $(min(m,n))")) end lwork = BlasInt(-1) work = Vector{$elty}(undef, 1) @@ -869,7 +869,7 @@ for (tzrzf, ormrz, elty) in chkstride1(A) m, n = size(A) if n < m - throw(DimensionMismatch("input matrix A has dimensions ($m,$n), but cannot have fewer columns than rows")) + throw(DimensionMismatch(lazy"input matrix A has dimensions ($m,$n), but cannot have fewer columns than rows")) end lda = max(1, stride(A,2)) tau = similar(A, $elty, m) @@ -974,7 +974,7 @@ for (gels, gesv, getrs, getri, elty) in btrn = trans == 'T' m, n = size(A) if size(B,1) != (btrn ? n : m) - throw(DimensionMismatch("matrix A has dimensions ($m,$n), transposed: $btrn, but leading dimension of B is $(size(B,1))")) + throw(DimensionMismatch(lazy"matrix A has dimensions ($m,$n), transposed: $btrn, but leading dimension of B is $(size(B,1))")) end info = Ref{BlasInt}() work = Vector{$elty}(undef, 1) @@ -1017,7 +1017,7 @@ for (gels, gesv, getrs, getri, elty) in chkstride1(A, B) n = checksquare(A) if size(B,1) != n - throw(DimensionMismatch("B has leading dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has leading dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) info = Ref{BlasInt}() @@ -1042,10 +1042,10 @@ for (gels, gesv, getrs, getri, elty) in chkstride1(A, B, ipiv) n = checksquare(A) if n != size(B, 1) - throw(DimensionMismatch("B has leading dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has leading dimension $(size(B,1)), but needs $n")) end if n != length(ipiv) - throw(DimensionMismatch("ipiv has length $(length(ipiv)), but needs to be $n")) + throw(DimensionMismatch(lazy"ipiv has length $(length(ipiv)), but needs to be $n")) end nrhs = size(B, 2) info = Ref{BlasInt}() @@ -1068,7 +1068,7 @@ for (gels, gesv, getrs, getri, elty) in chkstride1(A, ipiv) n = checksquare(A) if n != length(ipiv) - throw(DimensionMismatch("ipiv has length $(length(ipiv)), but needs $n")) + throw(DimensionMismatch(lazy"ipiv has length $(length(ipiv)), but needs $n")) end lda = max(1,stride(A, 2)) lwork = BlasInt(-1) @@ -1331,7 +1331,7 @@ for (gelsd, gelsy, elty) in chkstride1(A, B) m, n = size(A) if size(B, 1) != m - throw(DimensionMismatch("B has leading dimension $(size(B,1)) but needs $m")) + throw(DimensionMismatch(lazy"B has leading dimension $(size(B,1)) but needs $m")) end newB = [B; zeros($elty, max(0, n - size(B, 1)), size(B, 2))] s = similar(A, $elty, min(m, n)) @@ -1376,7 +1376,7 @@ for (gelsd, gelsy, elty) in n = size(A, 2) nrhs = size(B, 2) if size(B, 1) != m - throw(DimensionMismatch("B has leading dimension $(size(B,1)) but needs $m")) + throw(DimensionMismatch(lazy"B has leading dimension $(size(B,1)) but needs $m")) end newB = [B; zeros($elty, max(0, n - size(B, 1)), size(B, 2))] lda = max(1, stride(A,2)) @@ -1426,7 +1426,7 @@ for (gelsd, gelsy, elty, relty) in chkstride1(A, B) m, n = size(A) if size(B, 1) != m - throw(DimensionMismatch("B has leading dimension $(size(B,1)) but needs $m")) + throw(DimensionMismatch(lazy"B has leading dimension $(size(B,1)) but needs $m")) end newB = [B; zeros($elty, max(0, n - size(B, 1)), size(B, 2))] s = similar(A, $relty, min(m, n)) @@ -1473,7 +1473,7 @@ for (gelsd, gelsy, elty, relty) in m, n = size(A) nrhs = size(B, 2) if size(B, 1) != m - throw(DimensionMismatch("B has leading dimension $(size(B,1)) but needs $m")) + throw(DimensionMismatch(lazy"B has leading dimension $(size(B,1)) but needs $m")) end newB = [B; zeros($elty, max(0, n - size(B, 1)), size(B, 2))] lda = max(1, m) @@ -1547,13 +1547,13 @@ for (gglse, elty) in ((:dgglse_, :Float64), m, n = size(A) p = size(B, 1) if size(B, 2) != n - throw(DimensionMismatch("B has second dimension $(size(B,2)), needs $n")) + throw(DimensionMismatch(lazy"B has second dimension $(size(B,2)), needs $n")) end if length(c) != m - throw(DimensionMismatch("c has length $(length(c)), needs $m")) + throw(DimensionMismatch(lazy"c has length $(length(c)), needs $m")) end if length(d) != p - throw(DimensionMismatch("d has length $(length(d)), needs $p")) + throw(DimensionMismatch(lazy"d has length $(length(d)), needs $p")) end X = zeros($elty, n) info = Ref{BlasInt}() @@ -1823,7 +1823,7 @@ for (geev, gesvd, gesdd, ggsvd, elty, relty) in @chkvalidparam 3 jobq ('Q', 'N') m, n = size(A) if size(B, 2) != n - throw(DimensionMismatch("B has second dimension $(size(B,2)) but needs $n")) + throw(DimensionMismatch(lazy"B has second dimension $(size(B,2)) but needs $n")) end p = size(B, 1) k = Vector{BlasInt}(undef, 1) @@ -1953,7 +1953,7 @@ for (f, elty) in ((:dggsvd3_, :Float64), @chkvalidparam 3 jobq ('Q', 'N') m, n = size(A) if size(B, 2) != n - throw(DimensionMismatch("B has second dimension $(size(B,2)) but needs $n")) + throw(DimensionMismatch(lazy"B has second dimension $(size(B,2)) but needs $n")) end p = size(B, 1) k = Ref{BlasInt}() @@ -2015,7 +2015,7 @@ for (f, elty, relty) in ((:zggsvd3_, :ComplexF64, :Float64), @chkvalidparam 3 jobq ('Q', 'N') m, n = size(A) if size(B, 2) != n - throw(DimensionMismatch("B has second dimension $(size(B,2)) but needs $n")) + throw(DimensionMismatch(lazy"B has second dimension $(size(B,2)) but needs $n")) end p = size(B, 1) k = Vector{BlasInt}(undef, 1) @@ -2103,7 +2103,7 @@ for (geevx, ggev, ggev3, elty) in @chkvalidparam 1 balanc ('N', 'P', 'S', 'B') @chkvalidparam 4 sense ('N', 'E', 'V', 'B') if sense โˆˆ ('E', 'B') && !(jobvl == jobvr == 'V') - throw(ArgumentError("sense = '$sense' requires jobvl = 'V' and jobvr = 'V'")) + throw(ArgumentError(lazy"sense = '$sense' requires jobvl = 'V' and jobvr = 'V'")) end n = checksquare(A) ldvl = 0 @@ -2112,7 +2112,7 @@ for (geevx, ggev, ggev3, elty) in elseif jobvl == 'N' ldvl = 0 else - throw(ArgumentError("jobvl must be 'V' or 'N', but $jobvl was passed")) + throw(ArgumentError(lazy"jobvl must be 'V' or 'N', but $jobvl was passed")) end ldvr = 0 if jobvr == 'V' @@ -2120,7 +2120,7 @@ for (geevx, ggev, ggev3, elty) in elseif jobvr == 'N' ldvr = 0 else - throw(ArgumentError("jobvr must be 'V' or 'N', but $jobvr was passed")) + throw(ArgumentError(lazy"jobvr must be 'V' or 'N', but $jobvr was passed")) end chkfinite(A) # balancing routines don't support NaNs and Infs lda = max(1,stride(A,2)) @@ -2142,7 +2142,7 @@ for (geevx, ggev, ggev3, elty) in elseif sense == 'V' || sense == 'B' iworksize = 2*n - 2 else - throw(ArgumentError("sense must be 'N', 'E', 'V' or 'B', but $sense was passed")) + throw(ArgumentError(lazy"sense must be 'N', 'E', 'V' or 'B', but $sense was passed")) end iwork = Vector{BlasInt}(undef, iworksize) info = Ref{BlasInt}() @@ -2186,7 +2186,7 @@ for (geevx, ggev, ggev3, elty) in chkstride1(A,B) n, m = checksquare(A,B) if n != m - throw(DimensionMismatch("A has dimensions $(size(A)), and B has dimensions $(size(B)), but A and B must have the same size")) + throw(DimensionMismatch(lazy"A has dimensions $(size(A)), and B has dimensions $(size(B)), but A and B must have the same size")) end ldvl = 0 if jobvl == 'V' @@ -2194,7 +2194,7 @@ for (geevx, ggev, ggev3, elty) in elseif jobvl == 'N' ldvl = 1 else - throw(ArgumentError("jobvl must be 'V' or 'N', but $jobvl was passed")) + throw(ArgumentError(lazy"jobvl must be 'V' or 'N', but $jobvl was passed")) end ldvr = 0 if jobvr == 'V' @@ -2202,7 +2202,7 @@ for (geevx, ggev, ggev3, elty) in elseif jobvr == 'N' ldvr = 1 else - throw(ArgumentError("jobvr must be 'V' or 'N', but $jobvr was passed")) + throw(ArgumentError(lazy"jobvr must be 'V' or 'N', but $jobvr was passed")) end lda = max(1, stride(A, 2)) ldb = max(1, stride(B, 2)) @@ -2250,7 +2250,7 @@ for (geevx, ggev, ggev3, elty) in chkstride1(A,B) n, m = checksquare(A,B) if n != m - throw(DimensionMismatch("A has dimensions $(size(A)), and B has dimensions $(size(B)), but A and B must have the same size")) + throw(DimensionMismatch(lazy"A has dimensions $(size(A)), and B has dimensions $(size(B)), but A and B must have the same size")) end ldvl = 0 if jobvl == 'V' @@ -2258,7 +2258,7 @@ for (geevx, ggev, ggev3, elty) in elseif jobvl == 'N' ldvl = 1 else - throw(ArgumentError("jobvl must be 'V' or 'N', but $jobvl was passed")) + throw(ArgumentError(lazy"jobvl must be 'V' or 'N', but $jobvl was passed")) end ldvr = 0 if jobvr == 'V' @@ -2266,7 +2266,7 @@ for (geevx, ggev, ggev3, elty) in elseif jobvr == 'N' ldvr = 1 else - throw(ArgumentError("jobvr must be 'V' or 'N', but $jobvr was passed")) + throw(ArgumentError(lazy"jobvr must be 'V' or 'N', but $jobvr was passed")) end lda = max(1, stride(A, 2)) ldb = max(1, stride(B, 2)) @@ -2322,13 +2322,13 @@ for (geevx, ggev, ggev3, elty, relty) in function geevx!(balanc::AbstractChar, jobvl::AbstractChar, jobvr::AbstractChar, sense::AbstractChar, A::AbstractMatrix{$elty}) require_one_based_indexing(A) if balanc โˆ‰ ('N', 'P', 'S', 'B') - throw(ArgumentError("balanc must be 'N', 'P', 'S', or 'B', but $balanc was passed")) + throw(ArgumentError(lazy"balanc must be 'N', 'P', 'S', or 'B', but $balanc was passed")) end if sense โˆ‰ ('N','E','V','B') - throw(ArgumentError("sense must be 'N', 'E', 'V' or 'B', but $sense was passed")) + throw(ArgumentError(lazy"sense must be 'N', 'E', 'V' or 'B', but $sense was passed")) end if sense โˆˆ ('E', 'B') && !(jobvl == jobvr == 'V') - throw(ArgumentError("sense = '$sense' requires jobvl = 'V' and jobvr = 'V'")) + throw(ArgumentError(lazy"sense = '$sense' requires jobvl = 'V' and jobvr = 'V'")) end n = checksquare(A) ldvl = 0 @@ -2337,7 +2337,7 @@ for (geevx, ggev, ggev3, elty, relty) in elseif jobvl == 'N' ldvl = 0 else - throw(ArgumentError("jobvl must be 'V' or 'N', but $jobvl was passed")) + throw(ArgumentError(lazy"jobvl must be 'V' or 'N', but $jobvl was passed")) end ldvr = 0 if jobvr == 'V' @@ -2345,7 +2345,7 @@ for (geevx, ggev, ggev3, elty, relty) in elseif jobvr == 'N' ldvr = 0 else - throw(ArgumentError("jobvr must be 'V' or 'N', but $jobvr was passed")) + throw(ArgumentError(lazy"jobvr must be 'V' or 'N', but $jobvr was passed")) end chkfinite(A) # balancing routines don't support NaNs and Infs lda = max(1,stride(A,2)) @@ -2401,7 +2401,7 @@ for (geevx, ggev, ggev3, elty, relty) in chkstride1(A, B) n, m = checksquare(A, B) if n != m - throw(DimensionMismatch("A has dimensions $(size(A)), and B has dimensions $(size(B)), but A and B must have the same size")) + throw(DimensionMismatch(lazy"A has dimensions $(size(A)), and B has dimensions $(size(B)), but A and B must have the same size")) end ldvl = 0 if jobvl == 'V' @@ -2409,7 +2409,7 @@ for (geevx, ggev, ggev3, elty, relty) in elseif jobvl == 'N' ldvl = 1 else - throw(ArgumentError("jobvl must be 'V' or 'N', but $jobvl was passed")) + throw(ArgumentError(lazy"jobvl must be 'V' or 'N', but $jobvl was passed")) end ldvr = 0 if jobvr == 'V' @@ -2417,7 +2417,7 @@ for (geevx, ggev, ggev3, elty, relty) in elseif jobvr == 'N' ldvr = 1 else - throw(ArgumentError("jobvr must be 'V' or 'N', but $jobvr was passed")) + throw(ArgumentError(lazy"jobvr must be 'V' or 'N', but $jobvr was passed")) end lda = max(1, stride(A, 2)) ldb = max(1, stride(B, 2)) @@ -2466,7 +2466,7 @@ for (geevx, ggev, ggev3, elty, relty) in chkstride1(A, B) n, m = checksquare(A, B) if n != m - throw(DimensionMismatch("A has dimensions $(size(A)), and B has dimensions $(size(B)), but A and B must have the same size")) + throw(DimensionMismatch(lazy"A has dimensions $(size(A)), and B has dimensions $(size(B)), but A and B must have the same size")) end ldvl = 0 if jobvl == 'V' @@ -2474,7 +2474,7 @@ for (geevx, ggev, ggev3, elty, relty) in elseif jobvl == 'N' ldvl = 1 else - throw(ArgumentError("jobvl must be 'V' or 'N', but $jobvl was passed")) + throw(ArgumentError(lazy"jobvl must be 'V' or 'N', but $jobvl was passed")) end ldvr = 0 if jobvr == 'V' @@ -2482,7 +2482,7 @@ for (geevx, ggev, ggev3, elty, relty) in elseif jobvr == 'N' ldvr = 1 else - throw(ArgumentError("jobvr must be 'V' or 'N', but $jobvr was passed")) + throw(ArgumentError(lazy"jobvr must be 'V' or 'N', but $jobvr was passed")) end lda = max(1, stride(A, 2)) ldb = max(1, stride(B, 2)) @@ -2576,7 +2576,7 @@ for (laic1, elty) in @chkvalidparam 1 job (1,2) j = length(x) if j != length(w) - throw(DimensionMismatch("vectors must have same length, but length of x is $j and length of w is $(length(w))")) + throw(DimensionMismatch(lazy"vectors must have same length, but length of x is $j and length of w is $(length(w))")) end sestpr = Ref{$elty}() s = Ref{$elty}() @@ -2611,7 +2611,7 @@ for (laic1, elty, relty) in @chkvalidparam 1 job (1,2) j = length(x) if j != length(w) - throw(DimensionMismatch("vectors must have same length, but length of x is $j and length of w is $(length(w))")) + throw(DimensionMismatch(lazy"vectors must have same length, but length of x is $j and length of w is $(length(w))")) end sestpr = Ref{$relty}() s = Ref{$elty}() @@ -2646,13 +2646,13 @@ for (gtsv, gttrf, gttrs, elty) in chkstride1(B, dl, d, du) n = length(d) if !(n >= length(dl) >= n - 1) - throw(DimensionMismatch("subdiagonal has length $(length(dl)), but should be $n or $(n - 1)")) + throw(DimensionMismatch(lazy"subdiagonal has length $(length(dl)), but should be $n or $(n - 1)")) end if !(n >= length(du) >= n - 1) - throw(DimensionMismatch("superdiagonal has length $(length(du)), but should be $n or $(n - 1)")) + throw(DimensionMismatch(lazy"superdiagonal has length $(length(du)), but should be $n or $(n - 1)")) end if n != size(B,1) - throw(DimensionMismatch("B has leading dimension $(size(B,1)), but should have $n")) + throw(DimensionMismatch(lazy"B has leading dimension $(size(B,1)), but should have $n")) end if n == 0 return B # Early exit if possible @@ -2677,10 +2677,10 @@ for (gtsv, gttrf, gttrs, elty) in chkstride1(dl,d,du) n = length(d) if length(dl) != n - 1 - throw(DimensionMismatch("subdiagonal has length $(length(dl)), but should be $(n - 1)")) + throw(DimensionMismatch(lazy"subdiagonal has length $(length(dl)), but should be $(n - 1)")) end if length(du) != n - 1 - throw(DimensionMismatch("superdiagonal has length $(length(du)), but should be $(n - 1)")) + throw(DimensionMismatch(lazy"superdiagonal has length $(length(du)), but should be $(n - 1)")) end du2 = similar(d, $elty, n-2) ipiv = similar(d, BlasInt, n) @@ -2708,13 +2708,13 @@ for (gtsv, gttrf, gttrs, elty) in chkstride1(B, ipiv, dl, d, du, du2) n = length(d) if length(dl) != n - 1 - throw(DimensionMismatch("subdiagonal has length $(length(dl)), but should be $(n - 1)")) + throw(DimensionMismatch(lazy"subdiagonal has length $(length(dl)), but should be $(n - 1)")) end if length(du) != n - 1 - throw(DimensionMismatch("superdiagonal has length $(length(du)), but should be $(n - 1)")) + throw(DimensionMismatch(lazy"superdiagonal has length $(length(du)), but should be $(n - 1)")) end if n != size(B,1) - throw(DimensionMismatch("B has leading dimension $(size(B,1)), but should have $n")) + throw(DimensionMismatch(lazy"B has leading dimension $(size(B,1)), but should have $n")) end info = Ref{BlasInt}() ccall((@blasfunc($gttrs), libblastrampoline), Cvoid, @@ -2778,7 +2778,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in n = size(A, 2) m = min(n, size(A, 1)) if k > m - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= m = $m")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= m = $m")) end work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -2812,7 +2812,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in m = size(A, 1) n = min(m, size(A, 2)) if k > n - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= n = $n")) end work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -2848,7 +2848,7 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in m = size(A, 1) n = min(m, size(A, 2)) if k > n - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= n = $n")) end work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -2883,10 +2883,10 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in chkstride1(A,tau) m, n = size(A) if n < m - throw(DimensionMismatch("input matrix A has dimensions ($m,$n), but cannot have fewer columns than rows")) + throw(DimensionMismatch(lazy"input matrix A has dimensions ($m,$n), but cannot have fewer columns than rows")) end if k > n - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= n = $n")) end work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -2924,16 +2924,16 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in nA = size(A, 2) k = length(tau) if side == 'L' && m != nA - throw(DimensionMismatch("for a left-sided multiplication, the first dimension of C, $m, must equal the second dimension of A, $nA")) + throw(DimensionMismatch(lazy"for a left-sided multiplication, the first dimension of C, $m, must equal the second dimension of A, $nA")) end if side == 'R' && n != nA - throw(DimensionMismatch("for a right-sided multiplication, the second dimension of C, $n, must equal the second dimension of A, $nA")) + throw(DimensionMismatch(lazy"for a right-sided multiplication, the second dimension of C, $n, must equal the second dimension of A, $nA")) end if side == 'L' && k > m - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= m = $m")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= m = $m")) end if side == 'R' && k > n - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= n = $n")) end work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -2971,16 +2971,16 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in mA = size(A, 1) k = length(tau) if side == 'L' && m != mA - throw(DimensionMismatch("for a left-sided multiplication, the first dimension of C, $m, must equal the second dimension of A, $mA")) + throw(DimensionMismatch(lazy"for a left-sided multiplication, the first dimension of C, $m, must equal the second dimension of A, $mA")) end if side == 'R' && n != mA - throw(DimensionMismatch("for a right-sided multiplication, the second dimension of C, $m, must equal the second dimension of A, $mA")) + throw(DimensionMismatch(lazy"for a right-sided multiplication, the second dimension of C, $m, must equal the second dimension of A, $mA")) end if side == 'L' && k > m - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= m = $m")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= m = $m")) end if side == 'R' && k > n - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= n = $n")) end work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -3021,16 +3021,16 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in mA = size(A, 1) k = length(tau) if side == 'L' && m != mA - throw(DimensionMismatch("for a left-sided multiplication, the first dimension of C, $m, must equal the second dimension of A, $mA")) + throw(DimensionMismatch(lazy"for a left-sided multiplication, the first dimension of C, $m, must equal the second dimension of A, $mA")) end if side == 'R' && n != mA - throw(DimensionMismatch("for a right-sided multiplication, the second dimension of C, $m, must equal the second dimension of A, $mA")) + throw(DimensionMismatch(lazy"for a right-sided multiplication, the second dimension of C, $m, must equal the second dimension of A, $mA")) end if side == 'L' && k > m - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= m = $m")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= m = $m")) end if side == 'R' && k > n - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= n = $n")) end work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -3071,16 +3071,16 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in nA = size(A, 2) k = length(tau) if side == 'L' && m != nA - throw(DimensionMismatch("for a left-sided multiplication, the first dimension of C, $m, must equal the second dimension of A, $nA")) + throw(DimensionMismatch(lazy"for a left-sided multiplication, the first dimension of C, $m, must equal the second dimension of A, $nA")) end if side == 'R' && n != nA - throw(DimensionMismatch("for a right-sided multiplication, the second dimension of C, $m, must equal the second dimension of A, $nA")) + throw(DimensionMismatch(lazy"for a right-sided multiplication, the second dimension of C, $m, must equal the second dimension of A, $nA")) end if side == 'L' && k > m - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= m = $m")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= m = $m")) end if side == 'R' && k > n - throw(DimensionMismatch("invalid number of reflectors: k = $k should be <= n = $n")) + throw(DimensionMismatch(lazy"invalid number of reflectors: k = $k should be <= n = $n")) end work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -3113,31 +3113,31 @@ for (orglq, orgqr, orgql, orgrq, ormlq, ormqr, ormql, ormrq, gemqrt, elty) in end if side == 'L' if !(0 <= k <= m) - throw(DimensionMismatch("wrong value for k = $k: must be between 0 and $m")) + throw(DimensionMismatch(lazy"wrong value for k = $k: must be between 0 and $m")) end if m != size(V,1) - throw(DimensionMismatch("first dimensions of C, $m, and V, $(size(V,1)) must match")) + throw(DimensionMismatch(lazy"first dimensions of C, $m, and V, $(size(V,1)) must match")) end ldv = stride(V,2) if ldv < max(1, m) - throw(DimensionMismatch("Q and C don't fit! The stride of V, $ldv, is too small")) + throw(DimensionMismatch(lazy"Q and C don't fit! The stride of V, $ldv, is too small")) end wss = n*k elseif side == 'R' if !(0 <= k <= n) - throw(DimensionMismatch("wrong value for k = $k: must be between 0 and $n")) + throw(DimensionMismatch(lazy"wrong value for k = $k: must be between 0 and $n")) end if n != size(V,1) - throw(DimensionMismatch("second dimension of C, $n, and first dimension of V, $(size(V,1)) must match")) + throw(DimensionMismatch(lazy"second dimension of C, $n, and first dimension of V, $(size(V,1)) must match")) end ldv = stride(V,2) if ldv < max(1, n) - throw(DimensionMismatch("Q and C don't fit! The stride of V, $ldv, is too small")) + throw(DimensionMismatch(lazy"Q and C don't fit! The stride of V, $ldv, is too small")) end wss = m*k end if !(1 <= nb <= k) - throw(DimensionMismatch("wrong value for nb = $nb, which must be between 1 and $k")) + throw(DimensionMismatch(lazy"wrong value for nb = $nb, which must be between 1 and $k")) end ldc = stride(C, 2) work = Vector{$elty}(undef, wss) @@ -3258,7 +3258,7 @@ for (posv, potrf, potri, potrs, pstrf, elty, rtyp) in n = checksquare(A) chkuplo(uplo) if size(B,1) != n - throw(DimensionMismatch("first dimension of B, $(size(B,1)), and size of A, ($n,$n), must match!")) + throw(DimensionMismatch(lazy"first dimension of B, $(size(B,1)), and size of A, ($n,$n), must match!")) end info = Ref{BlasInt}() ccall((@blasfunc($posv), libblastrampoline), Cvoid, @@ -3328,7 +3328,7 @@ for (posv, potrf, potri, potrs, pstrf, elty, rtyp) in chkuplo(uplo) nrhs = size(B,2) if size(B,1) != n - throw(DimensionMismatch("first dimension of B, $(size(B,1)), and size of A, ($n,$n), must match!")) + throw(DimensionMismatch(lazy"first dimension of B, $(size(B,1)), and size of A, ($n,$n), must match!")) end lda = max(1,stride(A,2)) if lda == 0 || nrhs == 0 @@ -3445,10 +3445,10 @@ for (ptsv, pttrf, elty, relty) in chkstride1(B, D, E) n = length(D) if length(E) != n - 1 - throw(DimensionMismatch("E has length $(length(E)), but needs $(n - 1)")) + throw(DimensionMismatch(lazy"E has length $(length(E)), but needs $(n - 1)")) end if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)) but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)) but needs $n")) end info = Ref{BlasInt}() ccall((@blasfunc($ptsv), libblastrampoline), Cvoid, @@ -3469,7 +3469,7 @@ for (ptsv, pttrf, elty, relty) in chkstride1(D, E) n = length(D) if length(E) != n - 1 - throw(DimensionMismatch("E has length $(length(E)), but needs $(n - 1)")) + throw(DimensionMismatch(lazy"E has length $(length(E)), but needs $(n - 1)")) end info = Ref{BlasInt}() ccall((@blasfunc($pttrf), libblastrampoline), Cvoid, @@ -3513,10 +3513,10 @@ for (pttrs, elty, relty) in chkstride1(B, D, E) n = length(D) if length(E) != n - 1 - throw(DimensionMismatch("E has length $(length(E)), but needs $(n - 1)")) + throw(DimensionMismatch(lazy"E has length $(length(E)), but needs $(n - 1)")) end if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)) but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)) but needs $n")) end info = Ref{BlasInt}() ccall((@blasfunc($pttrs), libblastrampoline), Cvoid, @@ -3547,10 +3547,10 @@ for (pttrs, elty, relty) in chkuplo(uplo) n = length(D) if length(E) != n - 1 - throw(DimensionMismatch("E has length $(length(E)), but needs $(n - 1)")) + throw(DimensionMismatch(lazy"E has length $(length(E)), but needs $(n - 1)")) end if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)) but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)) but needs $n")) end info = Ref{BlasInt}() ccall((@blasfunc($pttrs), libblastrampoline), Cvoid, @@ -3616,7 +3616,7 @@ for (trtri, trtrs, elty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)) but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)) but needs $n")) end info = Ref{BlasInt}() ccall((@blasfunc($trtrs), libblastrampoline), Cvoid, @@ -3707,7 +3707,7 @@ for (trcon, trevc, trrfs, elty) in require_one_based_indexing(select, T, VL, VR) # Extract if side โˆ‰ ('L','R','B') - throw(ArgumentError("side argument must be 'L' (left eigenvectors), 'R' (right eigenvectors), or 'B' (both), got $side")) + throw(ArgumentError(lazy"side argument must be 'L' (left eigenvectors), 'R' (right eigenvectors), or 'B' (both), got $side")) end @chkvalidparam 2 howmny ('A', 'B', 'S') n, mm = checksquare(T), size(VL, 2) @@ -3773,7 +3773,7 @@ for (trcon, trevc, trrfs, elty) in n = size(A,2) nrhs = size(B,2) if nrhs != size(X,2) - throw(DimensionMismatch("second dimensions of B, $nrhs, and X, $(size(X,2)), must match")) + throw(DimensionMismatch(lazy"second dimensions of B, $nrhs, and X, $(size(X,2)), must match")) end work = Vector{$elty}(undef, 3n) iwork = Vector{BlasInt}(undef, n) @@ -3849,7 +3849,7 @@ for (trcon, trevc, trrfs, elty, relty) in # Check chkstride1(T, select, VL, VR) if side โˆ‰ ('L','R','B') - throw(ArgumentError("side argument must be 'L' (left eigenvectors), 'R' (right eigenvectors), or 'B' (both), got $side")) + throw(ArgumentError(lazy"side argument must be 'L' (left eigenvectors), 'R' (right eigenvectors), or 'B' (both), got $side")) end @chkvalidparam 2 howmny ('A', 'B', 'S') @@ -3910,7 +3910,7 @@ for (trcon, trevc, trrfs, elty, relty) in n = size(A,2) nrhs = size(B,2) if nrhs != size(X,2) - throw(DimensionMismatch("second dimensions of B, $nrhs, and X, $(size(X,2)), must match")) + throw(DimensionMismatch(lazy"second dimensions of B, $nrhs, and X, $(size(X,2)), must match")) end work = Vector{$elty}(undef, 2n) rwork = Vector{$relty}(undef, n) @@ -3982,7 +3982,7 @@ for (stev, stebz, stegr, stein, elty) in chkstride1(dv, ev) n = length(dv) if length(ev) != n - 1 && length(ev) != n - throw(DimensionMismatch("ev has length $(length(ev)) but needs one less than or equal to dv's length, $n)")) + throw(DimensionMismatch(lazy"ev has length $(length(ev)) but needs one less than or equal to dv's length, $n)")) end Zmat = similar(dv, $elty, (n, job != 'N' ? n : 0)) work = Vector{$elty}(undef, max(1, 2n-2)) @@ -4006,7 +4006,7 @@ for (stev, stebz, stegr, stein, elty) in chkstride1(dv, ev) n = length(dv) if length(ev) != n - 1 - throw(DimensionMismatch("ev has length $(length(ev)) but needs one less than dv's length, $n)")) + throw(DimensionMismatch(lazy"ev has length $(length(ev)) but needs one less than dv's length, $n)")) end m = Ref{BlasInt}() nsplit = Vector{BlasInt}(undef, 1) @@ -4045,7 +4045,7 @@ for (stev, stebz, stegr, stein, elty) in eev = copy(ev) eev[n] = zero($elty) else - throw(DimensionMismatch("ev has length $ne but needs one less than or equal to dv's length, $n)")) + throw(DimensionMismatch(lazy"ev has length $ne but needs one less than or equal to dv's length, $n)")) end abstol = Vector{$elty}(undef, 1) @@ -4095,12 +4095,12 @@ for (stev, stebz, stegr, stein, elty) in ev = copy(ev_in) ev[n] = zero($elty) else - throw(DimensionMismatch("ev_in has length $ne but needs one less than or equal to dv's length, $n)")) + throw(DimensionMismatch(lazy"ev_in has length $ne but needs one less than or equal to dv's length, $n)")) end ldz = n #Leading dimension #Number of eigenvalues to find if !(1 <= length(w_in) <= n) - throw(DimensionMismatch("w_in has length $(length(w_in)), but needs to be between 1 and $n")) + throw(DimensionMismatch(lazy"w_in has length $(length(w_in)), but needs to be between 1 and $n")) end m = length(w_in) #If iblock and isplit are invalid input, assume worst-case block partitioning, @@ -4236,7 +4236,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) work = Vector{$elty}(undef, 1) @@ -4365,7 +4365,7 @@ for (syconv, sysv, sytrf, sytri, sytrs, elty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end info = Ref{BlasInt}() ccall((@blasfunc($sytrs), libblastrampoline), Cvoid, @@ -4397,7 +4397,7 @@ for (sysv, sytrf, sytri, sytrs, syconvf, elty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) work = Vector{$elty}(undef, 1) @@ -4490,7 +4490,7 @@ for (sysv, sytrf, sytri, sytrs, syconvf, elty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end info = Ref{BlasInt}() ccall((@blasfunc($sytrs), libblastrampoline), Cvoid, @@ -4524,10 +4524,10 @@ for (sysv, sytrf, sytri, sytrs, syconvf, elty) in throw(ArgumentError("way must be C or R")) end if length(ipiv) != n - throw(ArgumentError("length of pivot vector was $(length(ipiv)) but should have been $n")) + throw(ArgumentError(lazy"length of pivot vector was $(length(ipiv)) but should have been $n")) end if length(e) != n - throw(ArgumentError("length of e vector was $(length(e)) but should have been $n")) + throw(ArgumentError(lazy"length of e vector was $(length(e)) but should have been $n")) end # allocate @@ -4591,7 +4591,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) work = Vector{$elty}(undef, 1) @@ -4718,7 +4718,7 @@ for (syconv, hesv, hetrf, hetri, hetrs, elty, relty) in chkstride1(A,B,ipiv) n = checksquare(A) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end info = Ref{BlasInt}() ccall((@blasfunc($hetrs), libblastrampoline), Cvoid, @@ -4749,7 +4749,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) work = Vector{$elty}(undef, 1) @@ -4839,7 +4839,7 @@ for (hesv, hetrf, hetri, hetrs, elty, relty) in chkuplo(uplo) n = checksquare(A) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end info = Ref{BlasInt}() ccall((@blasfunc($hetrs), libblastrampoline), Cvoid, @@ -4871,7 +4871,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) work = Vector{$elty}(undef, 1) @@ -5001,7 +5001,7 @@ for (sysv, sytrf, sytri, sytrs, elty, relty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end info = Ref{BlasInt}() ccall((@blasfunc($sytrs), libblastrampoline), Cvoid, @@ -5033,7 +5033,7 @@ for (sysv, sytrf, sytri, sytrs, syconvf, elty, relty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end ipiv = similar(A, BlasInt, n) work = Vector{$elty}(undef, 1) @@ -5127,7 +5127,7 @@ for (sysv, sytrf, sytri, sytrs, syconvf, elty, relty) in n = checksquare(A) chkuplo(uplo) if n != size(B,1) - throw(DimensionMismatch("B has first dimension $(size(B,1)), but needs $n")) + throw(DimensionMismatch(lazy"B has first dimension $(size(B,1)), but needs $n")) end info = Ref{BlasInt}() ccall((@blasfunc($sytrs), libblastrampoline), Cvoid, @@ -5160,13 +5160,13 @@ for (sysv, sytrf, sytri, sytrs, syconvf, elty, relty) in # check chkuplo(uplo) if way != 'C' && way != 'R' - throw(ArgumentError("way must be 'C' or 'R'")) + throw(ArgumentError(lazy"way must be 'C' or 'R'")) end if length(ipiv) != n - throw(ArgumentError("length of pivot vector was $(length(ipiv)) but should have been $n")) + throw(ArgumentError(lazy"length of pivot vector was $(length(ipiv)) but should have been $n")) end if length(e) != n - throw(ArgumentError("length of e vector was $(length(e)) but should have been $n")) + throw(ArgumentError(lazy"length of e vector was $(length(e)) but should have been $n")) end # allocate @@ -5368,10 +5368,10 @@ for (syev, syevr, syevd, sygvd, elty) in chkstride1(A) n = checksquare(A) if range == 'I' && !(1 <= il <= iu <= n) - throw(ArgumentError("illegal choice of eigenvalue indices (il = $il, iu = $iu), which must be between 1 and n = $n")) + throw(ArgumentError(lazy"illegal choice of eigenvalue indices (il = $il, iu = $iu), which must be between 1 and n = $n")) end if range == 'V' && vl >= vu - throw(ArgumentError("lower boundary, $vl, must be less than upper boundary, $vu")) + throw(ArgumentError(lazy"lower boundary, $vl, must be less than upper boundary, $vu")) end chkuplofinite(A, uplo) lda = stride(A,2) @@ -5476,7 +5476,7 @@ for (syev, syevr, syevd, sygvd, elty) in chkstride1(A, B) n, m = checksquare(A, B) if n != m - throw(DimensionMismatch("dimensions of A, ($n,$n), and B, ($m,$m), must match")) + throw(DimensionMismatch(lazy"dimensions of A, ($n,$n), and B, ($m,$m), must match")) end lda = max(1, stride(A, 2)) ldb = max(1, stride(B, 2)) @@ -5571,10 +5571,10 @@ for (syev, syevr, syevd, sygvd, elty, relty) in chkuplofinite(A, uplo) n = checksquare(A) if range == 'I' && !(1 <= il <= iu <= n) - throw(ArgumentError("illegal choice of eigenvalue indices (il = $il, iu=$iu), which must be between 1 and n = $n")) + throw(ArgumentError(lazy"illegal choice of eigenvalue indices (il = $il, iu=$iu), which must be between 1 and n = $n")) end if range == 'V' && vl >= vu - throw(ArgumentError("lower boundary, $vl, must be less than upper boundary, $vu")) + throw(ArgumentError(lazy"lower boundary, $vl, must be less than upper boundary, $vu")) end lda = max(1,stride(A,2)) m = Ref{BlasInt}() @@ -5691,7 +5691,7 @@ for (syev, syevr, syevd, sygvd, elty, relty) in chkuplofinite(B, uplo) n, m = checksquare(A, B) if n != m - throw(DimensionMismatch("dimensions of A, ($n,$n), and B, ($m,$m), must match")) + throw(DimensionMismatch(lazy"dimensions of A, ($n,$n), and B, ($m,$m), must match")) end lda = max(1, stride(A, 2)) ldb = max(1, stride(B, 2)) @@ -5802,19 +5802,19 @@ for (bdsqr, relty, elty) in # Do checks chkuplo(uplo) if length(e_) != n - 1 - throw(DimensionMismatch("off-diagonal has length $(length(e_)) but should have length $(n - 1)")) + throw(DimensionMismatch(lazy"off-diagonal has length $(length(e_)) but should have length $(n - 1)")) end if ncvt > 0 && ldvt < n - throw(DimensionMismatch("leading dimension of Vt, $ldvt, must be at least $n")) + throw(DimensionMismatch(lazy"leading dimension of Vt, $ldvt, must be at least $n")) end if ldu < nru - throw(DimensionMismatch("leading dimension of U, $ldu, must be at least $nru")) + throw(DimensionMismatch(lazy"leading dimension of U, $ldu, must be at least $nru")) end if size(U, 2) != n - throw(DimensionMismatch("U must have $n columns but has $(size(U, 2))")) + throw(DimensionMismatch(lazy"U must have $n columns but has $(size(U, 2))")) end if ncc > 0 && ldc < n - throw(DimensionMismatch("leading dimension of C, $ldc, must be at least $n")) + throw(DimensionMismatch(lazy"leading dimension of C, $ldc, must be at least $n")) end # Allocate work = Vector{$relty}(undef, 4n) @@ -5881,7 +5881,7 @@ for (bdsdc, elty) in ldvt=ldu=max(1, n) lwork=3*n^2 + 4*n else - throw(ArgumentError("COMPQ argument must be 'N', 'P' or 'I', got $(repr(compq))")) + throw(ArgumentError(lazy"COMPQ argument must be 'N', 'P' or 'I', got $(repr(compq))")) end u = similar(d, $elty, (ldu, n)) vt = similar(d, $elty, (ldvt, n)) @@ -6069,7 +6069,7 @@ for (orghr, elty) in chkstride1(A, tau) n = checksquare(A) if n - length(tau) != 1 - throw(DimensionMismatch("tau has length $(length(tau)), needs $(n - 1)")) + throw(DimensionMismatch(lazy"tau has length $(length(tau)), needs $(n - 1)")) end work = Vector{$elty}(undef, 1) lwork = BlasInt(-1) @@ -6124,7 +6124,7 @@ for (ormhr, elty) in mC, nC = size(C, 1), size(C, 2) if n - length(tau) != 1 - throw(DimensionMismatch("tau has length $(length(tau)), needs $(n - 1)")) + throw(DimensionMismatch(lazy"tau has length $(length(tau)), needs $(n - 1)")) end if (side == 'L' && mC != n) || (side == 'R' && nC != n) throw(DimensionMismatch("A and C matrices are not conformable")) @@ -6326,7 +6326,7 @@ for (orgtr, elty) in chkstride1(A, tau) n = checksquare(A) if n - length(tau) != 1 - throw(DimensionMismatch("tau has length $(length(tau)), needs $(n - 1)")) + throw(DimensionMismatch(lazy"tau has length $(length(tau)), needs $(n - 1)")) end chkuplo(uplo) work = Vector{$elty}(undef, 1) @@ -6383,10 +6383,10 @@ for (ormtr, elty) in mC, nC = size(C, 1), size(C, 2) if n - length(tau) != 1 - throw(DimensionMismatch("tau has length $(length(tau)), needs $(n - 1)")) + throw(DimensionMismatch(lazy"tau has length $(length(tau)), needs $(n - 1)")) end if (side == 'L' && mC != n) || (side == 'R' && nC != n) - throw(DimensionMismatch("A and C matrices are not conformable")) + throw(DimensionMismatch(lazy"A and C matrices are not conformable")) end work = Vector{$elty}(undef, 1) @@ -6473,7 +6473,7 @@ for (gees, gges, gges3, elty) in chkstride1(A, B) n, m = checksquare(A, B) if n != m - throw(DimensionMismatch("dimensions of A, ($n,$n), and B, ($m,$m), must match")) + throw(DimensionMismatch(lazy"dimensions of A, ($n,$n), and B, ($m,$m), must match")) end sdim = BlasInt(0) alphar = similar(A, $elty, n) @@ -6525,7 +6525,7 @@ for (gees, gges, gges3, elty) in chkstride1(A, B) n, m = checksquare(A, B) if n != m - throw(DimensionMismatch("dimensions of A, ($n,$n), and B, ($m,$m), must match")) + throw(DimensionMismatch(lazy"dimensions of A, ($n,$n), and B, ($m,$m), must match")) end sdim = BlasInt(0) alphar = similar(A, $elty, n) @@ -6625,7 +6625,7 @@ for (gees, gges, gges3, elty, relty) in chkstride1(A, B) n, m = checksquare(A, B) if n != m - throw(DimensionMismatch("dimensions of A, ($n,$n), and B, ($m,$m), must match")) + throw(DimensionMismatch(lazy"dimensions of A, ($n,$n), and B, ($m,$m), must match")) end sdim = BlasInt(0) alpha = similar(A, $elty, n) @@ -6678,7 +6678,7 @@ for (gees, gges, gges3, elty, relty) in chkstride1(A, B) n, m = checksquare(A, B) if n != m - throw(DimensionMismatch("dimensions of A, ($n,$n), and B, ($m,$m), must match")) + throw(DimensionMismatch(lazy"dimensions of A, ($n,$n), and B, ($m,$m), must match")) end sdim = BlasInt(0) alpha = similar(A, $elty, n) @@ -6859,13 +6859,13 @@ for (trexc, trsen, tgsen, elty) in chkstride1(select, S, T, Q, Z) n, nt, nq, nz = checksquare(S, T, Q, Z) if n != nt - throw(DimensionMismatch("dimensions of S, ($n,$n), and T, ($nt,$nt), must match")) + throw(DimensionMismatch(lazy"dimensions of S, ($n,$n), and T, ($nt,$nt), must match")) end if n != nq - throw(DimensionMismatch("dimensions of S, ($n,$n), and Q, ($nq,$nq), must match")) + throw(DimensionMismatch(lazy"dimensions of S, ($n,$n), and Q, ($nq,$nq), must match")) end if n != nz - throw(DimensionMismatch("dimensions of S, ($n,$n), and Z, ($nz,$nz), must match")) + throw(DimensionMismatch(lazy"dimensions of S, ($n,$n), and Z, ($nz,$nz), must match")) end lds = max(1, stride(S, 2)) ldt = max(1, stride(T, 2)) @@ -7010,13 +7010,13 @@ for (trexc, trsen, tgsen, elty, relty) in chkstride1(select, S, T, Q, Z) n, nt, nq, nz = checksquare(S, T, Q, Z) if n != nt - throw(DimensionMismatch("dimensions of S, ($n,$n), and T, ($nt,$nt), must match")) + throw(DimensionMismatch(lazy"dimensions of S, ($n,$n), and T, ($nt,$nt), must match")) end if n != nq - throw(DimensionMismatch("dimensions of S, ($n,$n), and Q, ($nq,$nq), must match")) + throw(DimensionMismatch(lazy"dimensions of S, ($n,$n), and Q, ($nq,$nq), must match")) end if n != nz - throw(DimensionMismatch("dimensions of S, ($n,$n), and Z, ($nz,$nz), must match")) + throw(DimensionMismatch(lazy"dimensions of S, ($n,$n), and Z, ($nz,$nz), must match")) end lds = max(1, stride(S, 2)) ldt = max(1, stride(T, 2)) @@ -7115,7 +7115,7 @@ for (fn, elty, relty) in ((:dtrsyl_, :Float64, :Float64), ldb = max(1, stride(B, 2)) m1, n1 = size(C) if m != m1 || n != n1 - throw(DimensionMismatch("dimensions of A, ($m,$n), and C, ($m1,$n1), must match")) + throw(DimensionMismatch(lazy"dimensions of A, ($m,$n), and C, ($m1,$n1), must match")) end ldc = max(1, stride(C, 2)) scale = Ref{$relty}() @@ -7165,7 +7165,7 @@ for (fn, elty) in ((:dlacpy_, :Float64), chkstride1(A, B) m,n = size(A) m1,n1 = size(B) - (m1 < m || n1 < n) && throw(DimensionMismatch("B of size ($m1,$n1) should have at least the same number of rows and columns than A of size ($m,$n)")) + (m1 < m || n1 < n) && throw(DimensionMismatch(lazy"B of size ($m1,$n1) should have at least the same number of rows and columns than A of size ($m,$n)")) lda = max(1, stride(A, 2)) ldb = max(1, stride(B, 2)) ccall((@blasfunc($fn), libblastrampoline), Cvoid, diff --git a/stdlib/LinearAlgebra/src/lbt.jl b/stdlib/LinearAlgebra/src/lbt.jl index b133741611adc5..aadcb45d606a34 100644 --- a/stdlib/LinearAlgebra/src/lbt.jl +++ b/stdlib/LinearAlgebra/src/lbt.jl @@ -247,11 +247,11 @@ If the given `symbol_name` is not contained within the list of exported symbols, function lbt_find_backing_library(symbol_name, interface::Symbol; config::LBTConfig = lbt_get_config()) if interface โˆ‰ (:ilp64, :lp64) - throw(ArgumentError("Invalid interface specification: '$(interface)'")) + throw(ArgumentError(lazy"Invalid interface specification: '$(interface)'")) end symbol_idx = findfirst(s -> s == symbol_name, config.exported_symbols) if symbol_idx === nothing - throw(ArgumentError("Invalid exported symbol name '$(symbol_name)'")) + throw(ArgumentError(lazy"Invalid exported symbol name '$(symbol_name)'")) end # Convert to zero-indexed symbol_idx -= 1 diff --git a/stdlib/LinearAlgebra/src/ldlt.jl b/stdlib/LinearAlgebra/src/ldlt.jl index d3d6234961c440..89e57d0dd27ebe 100644 --- a/stdlib/LinearAlgebra/src/ldlt.jl +++ b/stdlib/LinearAlgebra/src/ldlt.jl @@ -175,7 +175,7 @@ function ldiv!(S::LDLt{<:Any,<:SymTridiagonal}, B::AbstractVecOrMat) require_one_based_indexing(B) n, nrhs = size(B, 1), size(B, 2) if size(S,1) != n - throw(DimensionMismatch("Matrix has dimensions $(size(S)) but right hand side has first dimension $n")) + throw(DimensionMismatch(lazy"Matrix has dimensions $(size(S)) but right hand side has first dimension $n")) end d = S.data.dv l = S.data.ev diff --git a/stdlib/LinearAlgebra/src/lu.jl b/stdlib/LinearAlgebra/src/lu.jl index be32f1e863ff11..72755e0eb67998 100644 --- a/stdlib/LinearAlgebra/src/lu.jl +++ b/stdlib/LinearAlgebra/src/lu.jl @@ -680,7 +680,7 @@ function ldiv!(A::LU{T,Tridiagonal{T,V}}, B::AbstractVecOrMat) where {T,V} require_one_based_indexing(B) n = size(A,1) if n != size(B,1) - throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) + throw(DimensionMismatch(lazy"matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) end nrhs = size(B,2) dl = A.factors.dl @@ -713,7 +713,7 @@ function ldiv!(transA::TransposeFactorization{<:Any,<:LU{T,Tridiagonal{T,V}}}, B A = transA.parent n = size(A,1) if n != size(B,1) - throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) + throw(DimensionMismatch(lazy"matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) end nrhs = size(B,2) dl = A.factors.dl @@ -750,7 +750,7 @@ function ldiv!(adjA::AdjointFactorization{<:Any,<:LU{T,Tridiagonal{T,V}}}, B::Ab A = adjA.parent n = size(A,1) if n != size(B,1) - throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) + throw(DimensionMismatch(lazy"matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) end nrhs = size(B,2) dl = A.factors.dl diff --git a/stdlib/LinearAlgebra/src/qr.jl b/stdlib/LinearAlgebra/src/qr.jl index 782e4778c56c92..06c2fba2932f57 100644 --- a/stdlib/LinearAlgebra/src/qr.jl +++ b/stdlib/LinearAlgebra/src/qr.jl @@ -541,7 +541,7 @@ function ldiv!(A::QRPivoted{T,<:StridedMatrix}, B::AbstractMatrix{T}, rcond::Rea m, n = size(A) if m > size(B, 1) || n > size(B, 1) - throw(DimensionMismatch("B has leading dimension $(size(B, 1)) but needs at least $(max(m, n))")) + throw(DimensionMismatch(lazy"B has leading dimension $(size(B, 1)) but needs at least $(max(m, n))")) end if length(A.factors) == 0 || length(B) == 0 @@ -734,7 +734,7 @@ _ret_size(A::Factorization, B::AbstractMatrix) = (max(size(A, 2), size(B, 1)), s function (\)(A::Union{QR{T},QRCompactWY{T},QRPivoted{T}}, BIn::VecOrMat{Complex{T}}) where T<:BlasReal require_one_based_indexing(BIn) m, n = size(A) - m == size(BIn, 1) || throw(DimensionMismatch("left hand side has $m rows, but right hand side has $(size(BIn,1)) rows")) + m == size(BIn, 1) || throw(DimensionMismatch(lazy"left hand side has $m rows, but right hand side has $(size(BIn,1)) rows")) # |z1|z3| reinterpret |x1|x2|x3|x4| transpose |x1|y1| reshape |x1|y1|x3|y3| # |z2|z4| -> |y1|y2|y3|y4| -> |x2|y2| -> |x2|y2|x4|y4| diff --git a/stdlib/LinearAlgebra/src/special.jl b/stdlib/LinearAlgebra/src/special.jl index 136f566f68447f..1363708fb515fb 100644 --- a/stdlib/LinearAlgebra/src/special.jl +++ b/stdlib/LinearAlgebra/src/special.jl @@ -287,7 +287,7 @@ _small_enough(A::SymTridiagonal) = size(A, 1) <= 2 function fill!(A::Union{Diagonal,Bidiagonal,Tridiagonal,SymTridiagonal}, x) xT = convert(eltype(A), x) (iszero(xT) || _small_enough(A)) && return fillstored!(A, xT) - throw(ArgumentError("array of type $(typeof(A)) and size $(size(A)) can + throw(ArgumentError(lazy"array of type $(typeof(A)) and size $(size(A)) can not be filled with $x, since some of its entries are constrained.")) end diff --git a/stdlib/LinearAlgebra/src/structuredbroadcast.jl b/stdlib/LinearAlgebra/src/structuredbroadcast.jl index 6114c9a7963909..476d9e3e5cd020 100644 --- a/stdlib/LinearAlgebra/src/structuredbroadcast.jl +++ b/stdlib/LinearAlgebra/src/structuredbroadcast.jl @@ -211,7 +211,7 @@ function copyto!(dest::SymTridiagonal, bc::Broadcasted{<:StructuredMatrixStyle}) end for i = 1:size(dest, 1)-1 v = @inbounds Broadcast._broadcast_getindex(bc, CartesianIndex(i, i+1)) - v == (@inbounds Broadcast._broadcast_getindex(bc, CartesianIndex(i+1, i))) || throw(ArgumentError("broadcasted assignment breaks symmetry between locations ($i, $(i+1)) and ($(i+1), $i)")) + v == (@inbounds Broadcast._broadcast_getindex(bc, CartesianIndex(i+1, i))) || throw(ArgumentError(lazy"broadcasted assignment breaks symmetry between locations ($i, $(i+1)) and ($(i+1), $i)")) dest.ev[i] = v end return dest diff --git a/stdlib/LinearAlgebra/src/symmetric.jl b/stdlib/LinearAlgebra/src/symmetric.jl index 21047dad8fcd91..07240fb9afb22a 100644 --- a/stdlib/LinearAlgebra/src/symmetric.jl +++ b/stdlib/LinearAlgebra/src/symmetric.jl @@ -483,7 +483,7 @@ for (T, trans, real) in [(:Symmetric, :transpose, :identity), (:(Hermitian{<:Uni function dot(A::$T, B::$T) n = size(A, 2) if n != size(B, 2) - throw(DimensionMismatch("A has dimensions $(size(A)) but B has dimensions $(size(B))")) + throw(DimensionMismatch(lazy"A has dimensions $(size(A)) but B has dimensions $(size(B))")) end dotprod = $real(zero(dot(first(A), first(B)))) diff --git a/stdlib/LinearAlgebra/src/triangular.jl b/stdlib/LinearAlgebra/src/triangular.jl index 97ae07e12e9791..9be82f8dab29a4 100644 --- a/stdlib/LinearAlgebra/src/triangular.jl +++ b/stdlib/LinearAlgebra/src/triangular.jl @@ -272,7 +272,7 @@ Base.isstored(A::UpperTriangular, i::Int, j::Int) = @propagate_inbounds function setindex!(A::UpperTriangular, x, i::Integer, j::Integer) if i > j iszero(x) || throw(ArgumentError("cannot set index in the lower triangular part " * - "($i, $j) of an UpperTriangular matrix to a nonzero value ($x)")) + lazy"($i, $j) of an UpperTriangular matrix to a nonzero value ($x)")) else A.data[i,j] = x end @@ -282,10 +282,10 @@ end @propagate_inbounds function setindex!(A::UnitUpperTriangular, x, i::Integer, j::Integer) if i > j iszero(x) || throw(ArgumentError("cannot set index in the lower triangular part " * - "($i, $j) of a UnitUpperTriangular matrix to a nonzero value ($x)")) + lazy"($i, $j) of a UnitUpperTriangular matrix to a nonzero value ($x)")) elseif i == j - x == oneunit(x) || throw(ArgumentError("cannot set index on the diagonal ($i, $j) " * - "of a UnitUpperTriangular matrix to a non-unit value ($x)")) + x == oneunit(x) || throw(ArgumentError(lazy"cannot set index on the diagonal ($i, $j) " * + lazy"of a UnitUpperTriangular matrix to a non-unit value ($x)")) else A.data[i,j] = x end @@ -295,7 +295,7 @@ end @propagate_inbounds function setindex!(A::LowerTriangular, x, i::Integer, j::Integer) if i < j iszero(x) || throw(ArgumentError("cannot set index in the upper triangular part " * - "($i, $j) of a LowerTriangular matrix to a nonzero value ($x)")) + lazy"($i, $j) of a LowerTriangular matrix to a nonzero value ($x)")) else A.data[i,j] = x end @@ -305,10 +305,10 @@ end @propagate_inbounds function setindex!(A::UnitLowerTriangular, x, i::Integer, j::Integer) if i < j iszero(x) || throw(ArgumentError("cannot set index in the upper triangular part " * - "($i, $j) of a UnitLowerTriangular matrix to a nonzero value ($x)")) + lazy"($i, $j) of a UnitLowerTriangular matrix to a nonzero value ($x)")) elseif i == j - x == oneunit(x) || throw(ArgumentError("cannot set index on the diagonal ($i, $j) " * - "of a UnitLowerTriangular matrix to a non-unit value ($x)")) + x == oneunit(x) || throw(ArgumentError(lazy"cannot set index on the diagonal ($i, $j) " * + lazy"of a UnitLowerTriangular matrix to a non-unit value ($x)")) else A.data[i,j] = x end @@ -317,7 +317,7 @@ end @inline function fill!(A::UpperTriangular, x) iszero(x) || throw(ArgumentError("cannot set indices in the lower triangular part " * - "of an UpperTriangular matrix to a nonzero value ($x)")) + lazy"of an UpperTriangular matrix to a nonzero value ($x)")) for col in axes(A,2), row in firstindex(A,1):col @inbounds A.data[row, col] = x end @@ -325,7 +325,7 @@ end end @inline function fill!(A::LowerTriangular, x) iszero(x) || throw(ArgumentError("cannot set indices in the upper triangular part " * - "of a LowerTriangular matrix to a nonzero value ($x)")) + lazy"of a LowerTriangular matrix to a nonzero value ($x)")) for col in axes(A,2), row in col:lastindex(A,1) @inbounds A.data[row, col] = x end @@ -540,7 +540,7 @@ end function checksize1(A, B) szA, szB = size(A), size(B) - szA == szB || throw(DimensionMismatch("size of A, $szA, does not match size of B, $szB")) + szA == szB || throw(DimensionMismatch(lazy"size of A, $szA, does not match size of B, $szB")) checksquare(B) end @@ -1003,11 +1003,11 @@ function generic_trimatmul!(C::AbstractVecOrMat, uploc, isunitc, tfun::Function, m, n = size(B, 1), size(B, 2) N = size(A, 1) if m != N - throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) + throw(DimensionMismatch(lazy"right hand side B needs first dimension of size $(size(A,1)), has size $m")) end mc, nc = size(C, 1), size(C, 2) if mc != N || nc != n - throw(DimensionMismatch("output has dimensions ($mc,$nc), should have ($N,$n)")) + throw(DimensionMismatch(lazy"output has dimensions ($mc,$nc), should have ($N,$n)")) end oA = oneunit(eltype(A)) unit = isunitc == 'U' @@ -1065,11 +1065,11 @@ function generic_trimatmul!(C::AbstractVecOrMat, uploc, isunitc, ::Function, xA: m, n = size(B, 1), size(B, 2) N = size(A, 1) if m != N - throw(DimensionMismatch("right hand side B needs first dimension of size $(size(A,1)), has size $m")) + throw(DimensionMismatch(lazy"right hand side B needs first dimension of size $(size(A,1)), has size $m")) end mc, nc = size(C, 1), size(C, 2) if mc != N || nc != n - throw(DimensionMismatch("output has dimensions ($mc,$nc), should have ($N,$n)")) + throw(DimensionMismatch(lazy"output has dimensions ($mc,$nc), should have ($N,$n)")) end oA = oneunit(eltype(A)) unit = isunitc == 'U' @@ -1102,11 +1102,11 @@ function generic_mattrimul!(C::AbstractMatrix, uploc, isunitc, tfun::Function, A m, n = size(A, 1), size(A, 2) N = size(B, 1) if n != N - throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $N")) + throw(DimensionMismatch(lazy"right hand side B needs first dimension of size $n, has size $N")) end mc, nc = size(C, 1), size(C, 2) if mc != m || nc != N - throw(DimensionMismatch("output has dimensions ($mc,$nc), should have ($m,$N)")) + throw(DimensionMismatch(lazy"output has dimensions ($mc,$nc), should have ($m,$N)")) end oB = oneunit(eltype(B)) unit = isunitc == 'U' @@ -1164,11 +1164,11 @@ function generic_mattrimul!(C::AbstractMatrix, uploc, isunitc, ::Function, A::Ab m, n = size(A, 1), size(A, 2) N = size(B, 1) if n != N - throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $N")) + throw(DimensionMismatch(lazy"right hand side B needs first dimension of size $n, has size $N")) end mc, nc = size(C, 1), size(C, 2) if mc != m || nc != N - throw(DimensionMismatch("output has dimensions ($mc,$nc), should have ($m,$N)")) + throw(DimensionMismatch(lazy"output has dimensions ($mc,$nc), should have ($m,$N)")) end oB = oneunit(eltype(B)) unit = isunitc == 'U' @@ -1212,10 +1212,10 @@ function generic_trimatdiv!(C::AbstractVecOrMat, uploc, isunitc, tfun::Function, mA, nA = size(A) m, n = size(B, 1), size(B,2) if nA != m - throw(DimensionMismatch("second dimension of left hand side A, $nA, and first dimension of right hand side B, $m, must be equal")) + throw(DimensionMismatch(lazy"second dimension of left hand side A, $nA, and first dimension of right hand side B, $m, must be equal")) end if size(C) != size(B) - throw(DimensionMismatch("size of output, $(size(C)), does not match size of right hand side, $(size(B))")) + throw(DimensionMismatch(lazy"size of output, $(size(C)), does not match size of right hand side, $(size(B))")) end oA = oneunit(eltype(A)) @inbounds if uploc == 'U' @@ -1348,10 +1348,10 @@ function generic_trimatdiv!(C::AbstractVecOrMat, uploc, isunitc, ::Function, xA: mA, nA = size(A) m, n = size(B, 1), size(B,2) if nA != m - throw(DimensionMismatch("second dimension of left hand side A, $nA, and first dimension of right hand side B, $m, must be equal")) + throw(DimensionMismatch(lazy"second dimension of left hand side A, $nA, and first dimension of right hand side B, $m, must be equal")) end if size(C) != size(B) - throw(DimensionMismatch("size of output, $(size(C)), does not match size of right hand side, $(size(B))")) + throw(DimensionMismatch(lazy"size of output, $(size(C)), does not match size of right hand side, $(size(B))")) end oA = oneunit(eltype(A)) @inbounds if uploc == 'U' @@ -1430,10 +1430,10 @@ function generic_mattridiv!(C::AbstractMatrix, uploc, isunitc, tfun::Function, A require_one_based_indexing(C, A, B) m, n = size(A) if size(B, 1) != n - throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) + throw(DimensionMismatch(lazy"right hand side B needs first dimension of size $n, has size $(size(B,1))")) end if size(C) != size(A) - throw(DimensionMismatch("size of output, $(size(C)), does not match size of left hand side, $(size(A))")) + throw(DimensionMismatch(lazy"size of output, $(size(C)), does not match size of left hand side, $(size(A))")) end oB = oneunit(eltype(B)) unit = isunitc == 'U' @@ -1493,10 +1493,10 @@ function generic_mattridiv!(C::AbstractMatrix, uploc, isunitc, ::Function, A::Ab require_one_based_indexing(C, A, B) m, n = size(A) if size(B, 1) != n - throw(DimensionMismatch("right hand side B needs first dimension of size $n, has size $(size(B,1))")) + throw(DimensionMismatch(lazy"right hand side B needs first dimension of size $n, has size $(size(B,1))")) end if size(C) != size(A) - throw(DimensionMismatch("size of output, $(size(C)), does not match size of left hand side, $(size(A))")) + throw(DimensionMismatch(lazy"size of output, $(size(C)), does not match size of left hand side, $(size(A))")) end oB = oneunit(eltype(B)) unit = isunitc == 'U' @@ -1618,7 +1618,7 @@ end # 34(3), (2013) 1341โ€“1360. function powm!(A0::UpperTriangular, p::Real) if abs(p) >= 1 - throw(ArgumentError("p must be a real number in (-1,1), got $p")) + throw(ArgumentError(lazy"p must be a real number in (-1,1), got $p")) end normA0 = opnorm(A0, 1) @@ -2548,7 +2548,7 @@ function eigvecs(A::AbstractTriangular{T}) where T if TT <: BlasFloat return eigvecs(convert(AbstractMatrix{TT}, A)) else - throw(ArgumentError("eigvecs type $(typeof(A)) not supported. Please submit a pull request.")) + throw(ArgumentError(lazy"eigvecs type $(typeof(A)) not supported. Please submit a pull request.")) end end det(A::UnitUpperTriangular{T}) where {T} = one(T) diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index 90142dd941f28d..431e349d42da24 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -9,7 +9,7 @@ struct SymTridiagonal{T, V<:AbstractVector{T}} <: AbstractMatrix{T} function SymTridiagonal{T, V}(dv, ev) where {T, V<:AbstractVector{T}} require_one_based_indexing(dv, ev) if !(length(dv) - 1 <= length(ev) <= length(dv)) - throw(DimensionMismatch("subdiagonal has wrong length. Has length $(length(ev)), but should be either $(length(dv) - 1) or $(length(dv)).")) + throw(DimensionMismatch(lazy"subdiagonal has wrong length. Has length $(length(ev)), but should be either $(length(dv) - 1) or $(length(dv)).")) end new{T, V}(dv, ev) end @@ -191,8 +191,8 @@ function diag(M::SymTridiagonal{T}, n::Integer=0) where T<:Number elseif absn <= size(M,1) return fill!(similar(M.dv, size(M,1)-absn), zero(T)) else - throw(ArgumentError(string("requested diagonal, $n, must be at least $(-size(M, 1)) ", - "and at most $(size(M, 2)) for an $(size(M, 1))-by-$(size(M, 2)) matrix"))) + throw(ArgumentError(string(lazy"requested diagonal, $n, must be at least $(-size(M, 1)) ", + lazy"and at most $(size(M, 2)) for an $(size(M, 1))-by-$(size(M, 2)) matrix"))) end end function diag(M::SymTridiagonal, n::Integer=0) @@ -207,8 +207,8 @@ function diag(M::SymTridiagonal, n::Integer=0) elseif n <= size(M,1) throw(ArgumentError("requested diagonal contains undefined zeros of an array type")) else - throw(ArgumentError(string("requested diagonal, $n, must be at least $(-size(M, 1)) ", - "and at most $(size(M, 2)) for an $(size(M, 1))-by-$(size(M, 2)) matrix"))) + throw(ArgumentError(string(lazy"requested diagonal, $n, must be at least $(-size(M, 1)) ", + lazy"and at most $(size(M, 2)) for an $(size(M, 1))-by-$(size(M, 2)) matrix"))) end end @@ -350,8 +350,8 @@ isdiag(M::SymTridiagonal) = iszero(_evview(M)) function tril!(M::SymTridiagonal{T}, k::Integer=0) where T n = length(M.dv) if !(-n - 1 <= k <= n - 1) - throw(ArgumentError(string("the requested diagonal, $k, must be at least ", - "$(-n - 1) and at most $(n - 1) in an $n-by-$n matrix"))) + throw(ArgumentError(string(lazy"the requested diagonal, $k, must be at least ", + lazy"$(-n - 1) and at most $(n - 1) in an $n-by-$n matrix"))) elseif k < -1 fill!(M.ev, zero(T)) fill!(M.dv, zero(T)) @@ -369,8 +369,8 @@ end function triu!(M::SymTridiagonal{T}, k::Integer=0) where T n = length(M.dv) if !(-n + 1 <= k <= n + 1) - throw(ArgumentError(string("the requested diagonal, $k, must be at least ", - "$(-n + 1) and at most $(n + 1) in an $n-by-$n matrix"))) + throw(ArgumentError(string(lazy"the requested diagonal, $k, must be at least ", + lazy"$(-n + 1) and at most $(n + 1) in an $n-by-$n matrix"))) elseif k > 1 fill!(M.ev, zero(T)) fill!(M.dv, zero(T)) @@ -463,7 +463,7 @@ end if i == j @inbounds A.dv[i] = x else - throw(ArgumentError("cannot set off-diagonal entry ($i, $j)")) + throw(ArgumentError(lazy"cannot set off-diagonal entry ($i, $j)")) end return x end @@ -480,7 +480,7 @@ struct Tridiagonal{T,V<:AbstractVector{T}} <: AbstractMatrix{T} if (length(dl) != n-1 || length(du) != n-1) && !(length(d) == 0 && length(dl) == 0 && length(du) == 0) throw(ArgumentError(string("cannot construct Tridiagonal from incompatible ", "lengths of subdiagonal, diagonal and superdiagonal: ", - "($(length(dl)), $(length(d)), $(length(du)))"))) + lazy"($(length(dl)), $(length(d)), $(length(du)))"))) end new{T,V}(dl, d, Base.unalias(dl, du)) end @@ -645,8 +645,8 @@ function diag(M::Tridiagonal{T}, n::Integer=0) where T elseif abs(n) <= size(M,1) return fill!(similar(M.d, size(M,1)-abs(n)), zero(T)) else - throw(ArgumentError(string("requested diagonal, $n, must be at least $(-size(M, 1)) ", - "and at most $(size(M, 2)) for an $(size(M, 1))-by-$(size(M, 2)) matrix"))) + throw(ArgumentError(string(lazy"requested diagonal, $n, must be at least $(-size(M, 1)) ", + lazy"and at most $(size(M, 2)) for an $(size(M, 1))-by-$(size(M, 2)) matrix"))) end end @@ -698,8 +698,8 @@ end elseif j - i == 1 @inbounds A.du[i] = x elseif !iszero(x) - throw(ArgumentError(string("cannot set entry ($i, $j) off ", - "the tridiagonal band to a nonzero value ($x)"))) + throw(ArgumentError(string(lazy"cannot set entry ($i, $j) off ", + lazy"the tridiagonal band to a nonzero value ($x)"))) end return x end @@ -741,8 +741,8 @@ isdiag(M::Tridiagonal) = iszero(M.dl) && iszero(M.du) function tril!(M::Tridiagonal{T}, k::Integer=0) where T n = length(M.d) if !(-n - 1 <= k <= n - 1) - throw(ArgumentError(string("the requested diagonal, $k, must be at least ", - "$(-n - 1) and at most $(n - 1) in an $n-by-$n matrix"))) + throw(ArgumentError(string(lazy"the requested diagonal, $k, must be at least ", + lazy"$(-n - 1) and at most $(n - 1) in an $n-by-$n matrix"))) elseif k < -1 fill!(M.dl, zero(T)) fill!(M.d, zero(T)) @@ -759,8 +759,8 @@ end function triu!(M::Tridiagonal{T}, k::Integer=0) where T n = length(M.d) if !(-n + 1 <= k <= n + 1) - throw(ArgumentError(string("the requested diagonal, $k, must be at least ", - "$(-n + 1) and at most $(n + 1) in an $n-by-$n matrix"))) + throw(ArgumentError(string(lazy"the requested diagonal, $k, must be at least ", + lazy"$(-n + 1) and at most $(n + 1) in an $n-by-$n matrix"))) elseif k > 1 fill!(M.dl, zero(T)) fill!(M.d, zero(T)) @@ -928,7 +928,7 @@ function ldiv!(A::Tridiagonal, B::AbstractVecOrMat) LinearAlgebra.require_one_based_indexing(B) n = size(A, 1) if n != size(B,1) - throw(DimensionMismatch("matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) + throw(DimensionMismatch(lazy"matrix has dimensions ($n,$n) but right hand side has $(size(B,1)) rows")) end nrhs = size(B, 2) From 97ac3ecc707888bd1c9344ed8386aea40d14c346 Mon Sep 17 00:00:00 2001 From: Lilith Orion Hafner Date: Tue, 9 Apr 2024 11:44:50 -0500 Subject: [PATCH 107/123] make `view(::Memory, ::Colon)` produce a Vector (#54005) --- base/genericmemory.jl | 1 + test/arrayops.jl | 2 ++ 2 files changed, 3 insertions(+) diff --git a/base/genericmemory.jl b/base/genericmemory.jl index 3463be456ea591..c1dc215a68d332 100644 --- a/base/genericmemory.jl +++ b/base/genericmemory.jl @@ -312,3 +312,4 @@ end $(Expr(:new, :(Array{T, 1}), :ref, :dims)) end end +view(m::GenericMemory, inds::Colon) = view(m, eachindex(m)) diff --git a/test/arrayops.jl b/test/arrayops.jl index a31d373a65a386..1c36453a6adaed 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -3203,6 +3203,7 @@ end @test @inferred(view(mem, 3:8))::Vector{Int} == 13:18 @test @inferred(view(mem, 20:19))::Vector{Int} == [] @test @inferred(view(mem, -5:-7))::Vector{Int} == [] + @test @inferred(view(mem, :))::Vector{Int} == mem @test @inferred(reshape(mem, 5, 2))::Matrix{Int} == reshape(11:20, 5, 2) # 53990 @@ -3217,6 +3218,7 @@ end @test @inferred(view(empty_mem, 1:0))::Vector{Module} == [] @test @inferred(view(empty_mem, 10:3))::Vector{Module} == [] + @test @inferred(view(empty_mem, :))::Vector{Module} == empty_mem @test isempty(@inferred(reshape(empty_mem, 0, 7, 1))::Array{Module, 3}) offset_inds = OffsetArrays.IdOffsetRange(values=3:6, indices=53:56) From f870ea0a1ef2351afb5ec025223172f9936e9a21 Mon Sep 17 00:00:00 2001 From: Mike Boyle Date: Tue, 9 Apr 2024 16:09:41 -0400 Subject: [PATCH 108/123] Correct return types in docstrings of sincos* (#54006) Just a tiny correction to the return types noted in the docstrings, and include a phrase in `sincosd` that's present in the other two. --- base/special/trig.jl | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/base/special/trig.jl b/base/special/trig.jl index 15ecb0ca0492fc..66e4b46d7d4893 100644 --- a/base/special/trig.jl +++ b/base/special/trig.jl @@ -165,7 +165,7 @@ end @noinline sincos_domain_error(x) = throw(DomainError(x, "sincos(x) is only defined for finite x.")) """ - sincos(x::T) where T -> float(T) + sincos(x::T) where T -> Tuple{float(T),float(T)} Simultaneously compute the sine and cosine of `x`, where `x` is in radians, returning a tuple `(sine, cosine)`. @@ -850,7 +850,7 @@ function cospi(x::T) where T<:IEEEFloat end end """ - sincospi(x::T) where T -> float(T) + sincospi(x::T) where T -> Tuple{float(T),float(T)} Simultaneously compute [`sinpi(x)`](@ref) and [`cospi(x)`](@ref) (the sine and cosine of `ฯ€*x`, where `x` is in radians), returning a tuple `(sine, cosine)`. @@ -1266,9 +1266,10 @@ end tand(x::Real) = sind(x) / cosd(x) """ - sincosd(x::T) where T -> float(T) + sincosd(x::T) where T -> Tuple{float(T),float(T)} -Simultaneously compute the sine and cosine of `x`, where `x` is in degrees. +Simultaneously compute the sine and cosine of `x`, where `x` is in degrees, returning +a tuple `(sine, cosine)`. Throw a [`DomainError`](@ref) if `isinf(x)`, return a `(T(NaN), T(NaN))` tuple if `isnan(x)`. From d183ee1bc0f65312bbc9406af7dafd0333aa5aa6 Mon Sep 17 00:00:00 2001 From: Sukera <11753998+Seelengrab@users.noreply.github.com> Date: Tue, 9 Apr 2024 23:06:49 +0200 Subject: [PATCH 109/123] Improve performance of `ncodeunits(::Char)` (#54001) This improves performance of `ncodeunits(::Char)` by simply counting the number of non-zero bytes (except for `\0`, which is encoded as all zero bytes). For a performance comparison, see [this gist]( https://gist.github.com/Seelengrab/ebb02d4b8d754700c2869de8daf88cad); there's an up to 10x improvement here for collections of `Char`, with a minor improvement for single `Char` (with much smaller spread). The version in this PR is called `nbytesencoded` in the benchmarks. Correctness has been verified with Supposition.jl, using the existing implementation as an oracle: ```julia julia> using Supposition julia> const chars = Data.Characters() julia> @check max_examples=1_000_000 function bytesenc(i=Data.Integers{UInt32}()) c = reinterpret(Char, i) ncodeunits(c) == nbytesdiv(c) end; Test Summary: | Pass Total Time bytesenc | 1 1 1.0s julia> ncodeunits('\0') == nbytesencoded('\0') true ``` Let's see if CI agrees! Notably, neither the existing nor the new implementation check whether the given `Char` is valid or not, since the only thing that matters is how many bytes are written out. --------- Co-authored-by: Sukera --- base/char.jl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/base/char.jl b/base/char.jl index 08d661c41de560..bc68a672ce0ca1 100644 --- a/base/char.jl +++ b/base/char.jl @@ -62,7 +62,14 @@ to an output stream, or `ncodeunits(string(c))` but computed efficiently. This method requires at least Julia 1.1. In Julia 1.0 consider using `ncodeunits(string(c))`. """ -ncodeunits(c::Char) = write(devnull, c) # this is surprisingly efficient +function ncodeunits(c::Char) + u = reinterpret(UInt32, c) + # We care about how many trailing bytes are all zero + # subtract that from the total number of bytes + n_nonzero_bytes = sizeof(UInt32) - div(trailing_zeros(u), 0x8) + # Take care of '\0', which has an all-zero bitpattern + n_nonzero_bytes + iszero(u) +end """ codepoint(c::AbstractChar) -> Integer From e9a24d4cee4153023a7841a75fc4285229f26720 Mon Sep 17 00:00:00 2001 From: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Date: Wed, 10 Apr 2024 09:11:43 -0400 Subject: [PATCH 110/123] =?UTF-8?q?=F0=9F=A4=96=20[master]=20Bump=20the=20?= =?UTF-8?q?Pkg=20stdlib=20from=20162634c56=20to=208f772ffa7=20(#54018)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stdlib: Pkg URL: https://github.com/JuliaLang/Pkg.jl.git Stdlib branch: master Julia branch: master Old commit: 162634c56 New commit: 8f772ffa7 Julia version: 1.12.0-DEV Pkg version: 1.12.0 Bump invoked by: @KristofferC Powered by: [BumpStdlibs.jl](https://github.com/JuliaLang/BumpStdlibs.jl) Diff: https://github.com/JuliaLang/Pkg.jl/compare/162634c5615d12b889e4b64f3cff95d1c377f189...8f772ffa72d86c81f03cddce2e779d6b330414e3 ``` $ git log --oneline 162634c56..8f772ffa7 8f772ffa7 prune manifest after the set of some deps have been "demoted" to weakdeps (#3864) 88c38b2cd make `add` and `dev` on a package remove it from the set of weak dependencies (#3865) 9210a1da5 fix how entry point to package is computed with `path` provided in project file (#3850) 77620a945 extensions: fixup entire manifest (#3720) 8cc835c7d Report failures to download artifacts as failures (#3860) 2f318cf66 remove unused PkgPrecompileError type (#3858) ``` Co-authored-by: Dilum Aluthge --- .../Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/md5 | 1 - .../Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/sha512 | 1 - .../Pkg-8f772ffa72d86c81f03cddce2e779d6b330414e3.tar.gz/md5 | 1 + .../Pkg-8f772ffa72d86c81f03cddce2e779d6b330414e3.tar.gz/sha512 | 1 + stdlib/Pkg.version | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/md5 delete mode 100644 deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/sha512 create mode 100644 deps/checksums/Pkg-8f772ffa72d86c81f03cddce2e779d6b330414e3.tar.gz/md5 create mode 100644 deps/checksums/Pkg-8f772ffa72d86c81f03cddce2e779d6b330414e3.tar.gz/sha512 diff --git a/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/md5 b/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/md5 deleted file mode 100644 index c27b9894015ce0..00000000000000 --- a/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -4bd123b9499b46a859d5bba5ae2228a5 diff --git a/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/sha512 b/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/sha512 deleted file mode 100644 index d4c2d6b185137c..00000000000000 --- a/deps/checksums/Pkg-162634c5615d12b889e4b64f3cff95d1c377f189.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -5f743255cee291185094bfa86e48f65160bc1ad170f052644b79d90d2f1d3c6c3e2be3c4da25925f3ec4b3f87179f946252cdab199ca510b78064afb0b0df039 diff --git a/deps/checksums/Pkg-8f772ffa72d86c81f03cddce2e779d6b330414e3.tar.gz/md5 b/deps/checksums/Pkg-8f772ffa72d86c81f03cddce2e779d6b330414e3.tar.gz/md5 new file mode 100644 index 00000000000000..89baf14afbcc21 --- /dev/null +++ b/deps/checksums/Pkg-8f772ffa72d86c81f03cddce2e779d6b330414e3.tar.gz/md5 @@ -0,0 +1 @@ +b1b74c19867026be19c77c3ab94b11e4 diff --git a/deps/checksums/Pkg-8f772ffa72d86c81f03cddce2e779d6b330414e3.tar.gz/sha512 b/deps/checksums/Pkg-8f772ffa72d86c81f03cddce2e779d6b330414e3.tar.gz/sha512 new file mode 100644 index 00000000000000..cb6d2098d0f104 --- /dev/null +++ b/deps/checksums/Pkg-8f772ffa72d86c81f03cddce2e779d6b330414e3.tar.gz/sha512 @@ -0,0 +1 @@ +c1834ec2c41c201224d58928053d94fdb1972dbafa59b5d80bc43ac60f22eeb4287d57d519fe7d0e9f69c430e39e7eafc26aa0c2994ea417cab32725301cb39d diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 0fcf00277a6f8a..499b6b9174c440 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = master -PKG_SHA1 = 162634c5615d12b889e4b64f3cff95d1c377f189 +PKG_SHA1 = 8f772ffa72d86c81f03cddce2e779d6b330414e3 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 From f46cb4c67cd2ce7f88da778f5c0355c1100b5ccd Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 10 Apr 2024 20:08:10 +0200 Subject: [PATCH 111/123] allow extensions to trigger from packages in [deps] (#54009) There is a use case where you have a weak dependency (for one of your extensions) that is misbehaving and you quickly want to try debug that issue. A workflow that feels reasonable for this could be: ``` pkg> dev WeakDependency # do some fixes in this dependency julia> using Package, WeakDependency # this loads the extension of Package triggered by loading WeakDependency # check that things work ok now ``` This doesn't work right now for two reasons: 1. Doing the `dev WeakDependency` will add the dependency to `[deps]` but not remove it from `[weakdeps]` which means you all of a sudden are in the scenario described in https://pkgdocs.julialang.org/v1/creating-packages/#Transition-from-normal-dependency-to-extension which is not what is desired. 2. The extension will not actually load because you can right now only trigger extensions from weak deps getting loaded, not from deps getting loaded. Point 1. is fixed by https://github.com/JuliaLang/Pkg.jl/pull/3865 Point 2. is fixed by this PR. --- base/loading.jl | 53 +++++++++++-------- base/precompilation.jl | 2 +- doc/src/manual/code-loading.md | 12 ++--- test/loading.jl | 6 ++- .../EnvWithHasExtensions/Manifest.toml | 6 ++- .../Extensions/ExtDep3.jl/Project.toml | 4 ++ .../Extensions/ExtDep3.jl/src/ExtDep3.jl | 5 ++ .../HasDepWithExtensions.jl/Manifest.toml | 11 +++- .../HasDepWithExtensions.jl/Project.toml | 1 + .../Extensions/HasExtensions.jl/Manifest.toml | 9 ++-- .../Extensions/HasExtensions.jl/Project.toml | 4 ++ .../HasExtensions.jl/ext/ExtensionDep.jl | 9 ++++ .../HasExtensions.jl/src/HasExtensions.jl | 1 + 13 files changed, 85 insertions(+), 38 deletions(-) create mode 100644 test/project/Extensions/ExtDep3.jl/Project.toml create mode 100644 test/project/Extensions/ExtDep3.jl/src/ExtDep3.jl create mode 100644 test/project/Extensions/HasExtensions.jl/ext/ExtensionDep.jl diff --git a/base/loading.jl b/base/loading.jl index d49c8aa91e3b79..ee6c47c7ce1559 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1388,13 +1388,12 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi proj_pkg = project_file_name_uuid(implicit_project_file, pkg.name) if pkg == proj_pkg d_proj = parsed_toml(implicit_project_file) - weakdeps = get(d_proj, "weakdeps", nothing)::Union{Nothing, Vector{String}, Dict{String,Any}} extensions = get(d_proj, "extensions", nothing)::Union{Nothing, Dict{String, Any}} extensions === nothing && return - weakdeps === nothing && return - if weakdeps isa Dict{String, Any} - return _insert_extension_triggers(pkg, extensions, weakdeps) - end + weakdeps = get(Dict{String, Any}, d_proj, "weakdeps")::Dict{String,Any} + deps = get(Dict{String, Any}, d_proj, "deps")::Dict{String,Any} + total_deps = merge(weakdeps, deps) + return _insert_extension_triggers(pkg, extensions, total_deps) end # Now look in manifest @@ -1409,27 +1408,35 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi uuid = get(entry, "uuid", nothing)::Union{String, Nothing} uuid === nothing && continue if UUID(uuid) == pkg.uuid - weakdeps = get(entry, "weakdeps", nothing)::Union{Nothing, Vector{String}, Dict{String,Any}} extensions = get(entry, "extensions", nothing)::Union{Nothing, Dict{String, Any}} extensions === nothing && return - weakdeps === nothing && return - if weakdeps isa Dict{String, Any} - return _insert_extension_triggers(pkg, extensions, weakdeps) + weakdeps = get(Dict{String, Any}, entry, "weakdeps")::Union{Vector{String}, Dict{String,Any}} + deps = get(Dict{String, Any}, entry, "deps")::Union{Vector{String}, Dict{String,Any}} + + function expand_deps_list(depsโ€ฒ::Vector{String}) + depsโ€ฒ_expanded = Dict{String, Any}() + for (dep_name, entries) in d + dep_name in depsโ€ฒ || continue + entries::Vector{Any} + if length(entries) != 1 + error("expected a single entry for $(repr(dep_name)) in $(repr(project_file))") + end + entry = first(entries)::Dict{String, Any} + uuid = entry["uuid"]::String + depsโ€ฒ_expanded[dep_name] = uuid + end + return depsโ€ฒ_expanded end - d_weakdeps = Dict{String, Any}() - for (dep_name, entries) in d - dep_name in weakdeps || continue - entries::Vector{Any} - if length(entries) != 1 - error("expected a single entry for $(repr(dep_name)) in $(repr(project_file))") - end - entry = first(entries)::Dict{String, Any} - uuid = entry["uuid"]::String - d_weakdeps[dep_name] = uuid + if weakdeps isa Vector{String} + weakdeps = expand_deps_list(weakdeps) + end + if deps isa Vector{String} + deps = expand_deps_list(deps) end - @assert length(d_weakdeps) == length(weakdeps) - return _insert_extension_triggers(pkg, extensions, d_weakdeps) + + total_deps = merge(weakdeps, deps) + return _insert_extension_triggers(pkg, extensions, total_deps) end end end @@ -1437,7 +1444,7 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi return nothing end -function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}, weakdeps::Dict{String, Any}) +function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}, totaldeps::Dict{String, Any}) for (ext, triggers) in extensions triggers = triggers::Union{String, Vector{String}} triggers isa String && (triggers = [triggers]) @@ -1451,7 +1458,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any} push!(trigger1, gid) for trigger in triggers # TODO: Better error message if this lookup fails? - uuid_trigger = UUID(weakdeps[trigger]::String) + uuid_trigger = UUID(totaldeps[trigger]::String) trigger_id = PkgId(uuid_trigger, trigger) if !haskey(explicit_loaded_modules, trigger_id) || haskey(package_locks, trigger_id) trigger1 = get!(Vector{ExtensionId}, EXT_DORMITORY, trigger_id) diff --git a/base/precompilation.jl b/base/precompilation.jl index 8185fe8e8230bd..9acbd2a11f2026 100644 --- a/base/precompilation.jl +++ b/base/precompilation.jl @@ -409,7 +409,7 @@ function precompilepkgs(pkgs::Vector{String}=String[]; all_extdeps_available = true for extdep_uuid in extdep_uuids extdep_name = env.names[extdep_uuid] - if extdep_uuid in keys(env.deps) || Base.in_sysimage(Base.PkgId(extdep_uuid, extdep_name)) + if extdep_uuid in keys(env.deps) push!(ext_deps, Base.PkgId(extdep_uuid, extdep_name)) else all_extdeps_available = false diff --git a/doc/src/manual/code-loading.md b/doc/src/manual/code-loading.md index 35d88ed13bc896..5c8315693c71ec 100644 --- a/doc/src/manual/code-loading.md +++ b/doc/src/manual/code-loading.md @@ -351,7 +351,7 @@ Since the primary environment is typically the environment of a project you're w ### [Package Extensions](@id man-extensions) -A package "extension" is a module that is automatically loaded when a specified set of other packages (its "extension dependencies") are loaded in the current Julia session. Extensions are defined under the `[extensions]` section in the project file. The extension dependencies of an extension are a subset of those packages listed under the `[weakdeps]` section of the project file. Those packages can have compat entries like other packages. +A package "extension" is a module that is automatically loaded when a specified set of other packages (its "triggers") are loaded in the current Julia session. Extensions are defined under the `[extensions]` section in the project file. The triggers of an extension are a subset of those packages listed under the `[weakdeps]` (and possibly, but uncommonly the `[deps]`) section of the project file. Those packages can have compat entries like other packages. ```toml name = "MyPackage" @@ -371,8 +371,8 @@ FooExt = "ExtDep" ``` The keys under `extensions` are the names of the extensions. -They are loaded when all the packages on the right hand side (the extension dependencies) of that extension are loaded. -If an extension only has one extension dependency the list of extension dependencies can be written as just a string for brevity. +They are loaded when all the packages on the right hand side (the triggers) of that extension are loaded. +If an extension only has one trigger the list of triggers can be written as just a string for brevity. The location for the entry point of the extension is either in `ext/FooExt.jl` or `ext/FooExt/FooExt.jl` for extension `FooExt`. The content of an extension is often structured as: @@ -380,10 +380,10 @@ The content of an extension is often structured as: ``` module FooExt -# Load main package and extension dependencies +# Load main package and triggers using MyPackage, ExtDep -# Extend functionality in main package with types from the extension dependencies +# Extend functionality in main package with types from the triggers MyPackage.func(x::ExtDep.SomeStruct) = ... end @@ -391,7 +391,7 @@ end When a package with extensions is added to an environment, the `weakdeps` and `extensions` sections are stored in the manifest file in the section for that package. The dependency lookup rules for -a package are the same as for its "parent" except that the listed extension dependencies are also considered as +a package are the same as for its "parent" except that the listed triggers are also considered as dependencies. ### [Workspaces](@id workspaces) diff --git a/test/loading.jl b/test/loading.jl index 182db7c4a6d15b..4cd0cb7dac8238 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -1057,7 +1057,9 @@ end $ew HasDepWithExtensions.do_something() || error("do_something errored") using ExtDep2 $ew using ExtDep2 - $ew HasExtensions.ext_folder_loaded || error("ext_folder_loaded not set") + using ExtDep3 + $ew using ExtDep3 + $ew HasExtensions.ext_dep_loaded || error("ext_dep_loaded not set") end """ return `$(Base.julia_cmd()) $compile --startup-file=no -e $cmd` @@ -1105,6 +1107,8 @@ end Base.get_extension(HasExtensions, :Extension) isa Module || error("expected extension to load") using ExtDep2 Base.get_extension(HasExtensions, :ExtensionFolder) isa Module || error("expected extension to load") + using ExtDep3 + Base.get_extension(HasExtensions, :ExtensionDep) isa Module || error("expected extension to load") end """ for compile in (`--compiled-modules=no`, ``) diff --git a/test/project/Extensions/EnvWithHasExtensions/Manifest.toml b/test/project/Extensions/EnvWithHasExtensions/Manifest.toml index 8ac961fa1a9a97..004ef7892c1733 100644 --- a/test/project/Extensions/EnvWithHasExtensions/Manifest.toml +++ b/test/project/Extensions/EnvWithHasExtensions/Manifest.toml @@ -1,8 +1,8 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.9.0-beta4" +julia_version = "1.12.0-DEV" manifest_format = "2.0" -project_hash = "caa716752e6dff3d77c3de929ebbb5d2024d04ef" +project_hash = "a4c480cfa7da9610333d5c42623bf746bd286c5f" [[deps.ExtDep]] deps = ["SomePackage"] @@ -18,10 +18,12 @@ version = "0.1.0" [deps.HasExtensions.extensions] Extension = "ExtDep" ExtensionFolder = ["ExtDep", "ExtDep2"] + LinearAlgebraExt = "LinearAlgebra" [deps.HasExtensions.weakdeps] ExtDep = "fa069be4-f60b-4d4c-8b95-f8008775090c" ExtDep2 = "55982ee5-2ad5-4c40-8cfe-5e9e1b01500d" + LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [[deps.SomePackage]] path = "../SomePackage" diff --git a/test/project/Extensions/ExtDep3.jl/Project.toml b/test/project/Extensions/ExtDep3.jl/Project.toml new file mode 100644 index 00000000000000..690b2f1cffff42 --- /dev/null +++ b/test/project/Extensions/ExtDep3.jl/Project.toml @@ -0,0 +1,4 @@ +name = "ExtDep3" +uuid = "a5541f1e-a556-4fdc-af15-097880d743a1" +version = "0.1.0" +authors = ["Kristoffer "] diff --git a/test/project/Extensions/ExtDep3.jl/src/ExtDep3.jl b/test/project/Extensions/ExtDep3.jl/src/ExtDep3.jl new file mode 100644 index 00000000000000..96a0b472d06c50 --- /dev/null +++ b/test/project/Extensions/ExtDep3.jl/src/ExtDep3.jl @@ -0,0 +1,5 @@ +module ExtDep3 + +greet() = print("Hello World!") + +end # module ExtDep3 diff --git a/test/project/Extensions/HasDepWithExtensions.jl/Manifest.toml b/test/project/Extensions/HasDepWithExtensions.jl/Manifest.toml index 15f068f250ce3f..5706aba59d1e0b 100644 --- a/test/project/Extensions/HasDepWithExtensions.jl/Manifest.toml +++ b/test/project/Extensions/HasDepWithExtensions.jl/Manifest.toml @@ -1,8 +1,8 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.10.0" +julia_version = "1.12.0-DEV" manifest_format = "2.0" -project_hash = "d523b3401f72a1ed34b7b43749fd2655c6b78542" +project_hash = "4e196b07f2ee7adc48ac9d528d42b3cf3737c7a0" [[deps.ExtDep]] deps = ["SomePackage"] @@ -15,13 +15,20 @@ path = "../ExtDep2" uuid = "55982ee5-2ad5-4c40-8cfe-5e9e1b01500d" version = "0.1.0" +[[deps.ExtDep3]] +path = "../ExtDep3.jl" +uuid = "a5541f1e-a556-4fdc-af15-097880d743a1" +version = "0.1.0" + [[deps.HasExtensions]] +deps = ["ExtDep3"] path = "../HasExtensions.jl" uuid = "4d3288b3-3afc-4bb6-85f3-489fffe514c8" version = "0.1.0" [deps.HasExtensions.extensions] Extension = "ExtDep" + ExtensionDep = "ExtDep3" ExtensionFolder = ["ExtDep", "ExtDep2"] LinearAlgebraExt = "LinearAlgebra" diff --git a/test/project/Extensions/HasDepWithExtensions.jl/Project.toml b/test/project/Extensions/HasDepWithExtensions.jl/Project.toml index 8f308a9fbee727..aa4956caada742 100644 --- a/test/project/Extensions/HasDepWithExtensions.jl/Project.toml +++ b/test/project/Extensions/HasDepWithExtensions.jl/Project.toml @@ -5,4 +5,5 @@ version = "0.1.0" [deps] ExtDep = "fa069be4-f60b-4d4c-8b95-f8008775090c" ExtDep2 = "55982ee5-2ad5-4c40-8cfe-5e9e1b01500d" +ExtDep3 = "a5541f1e-a556-4fdc-af15-097880d743a1" HasExtensions = "4d3288b3-3afc-4bb6-85f3-489fffe514c8" diff --git a/test/project/Extensions/HasExtensions.jl/Manifest.toml b/test/project/Extensions/HasExtensions.jl/Manifest.toml index 55f7958701a75a..429c6598fc4f49 100644 --- a/test/project/Extensions/HasExtensions.jl/Manifest.toml +++ b/test/project/Extensions/HasExtensions.jl/Manifest.toml @@ -1,7 +1,10 @@ # This file is machine-generated - editing it directly is not advised -julia_version = "1.10.0-DEV" +julia_version = "1.12.0-DEV" manifest_format = "2.0" -project_hash = "c87947f1f1f070eea848950c304d668a112dec3d" +project_hash = "c0bb526b75939a74a6195ee4819e598918a22ad7" -[deps] +[[deps.ExtDep3]] +path = "../ExtDep3.jl" +uuid = "a5541f1e-a556-4fdc-af15-097880d743a1" +version = "0.1.0" diff --git a/test/project/Extensions/HasExtensions.jl/Project.toml b/test/project/Extensions/HasExtensions.jl/Project.toml index a5f9bb1e42d299..fe21a1423f5437 100644 --- a/test/project/Extensions/HasExtensions.jl/Project.toml +++ b/test/project/Extensions/HasExtensions.jl/Project.toml @@ -2,6 +2,9 @@ name = "HasExtensions" uuid = "4d3288b3-3afc-4bb6-85f3-489fffe514c8" version = "0.1.0" +[deps] +ExtDep3 = "a5541f1e-a556-4fdc-af15-097880d743a1" + [weakdeps] ExtDep = "fa069be4-f60b-4d4c-8b95-f8008775090c" ExtDep2 = "55982ee5-2ad5-4c40-8cfe-5e9e1b01500d" @@ -9,5 +12,6 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" [extensions] Extension = "ExtDep" +ExtensionDep = "ExtDep3" ExtensionFolder = ["ExtDep", "ExtDep2"] LinearAlgebraExt = "LinearAlgebra" diff --git a/test/project/Extensions/HasExtensions.jl/ext/ExtensionDep.jl b/test/project/Extensions/HasExtensions.jl/ext/ExtensionDep.jl new file mode 100644 index 00000000000000..e2710d4d89bbbb --- /dev/null +++ b/test/project/Extensions/HasExtensions.jl/ext/ExtensionDep.jl @@ -0,0 +1,9 @@ +module ExtensionDep + +using HasExtensions, ExtDep3 + +function __init__() + HasExtensions.ext_dep_loaded = true +end + +end diff --git a/test/project/Extensions/HasExtensions.jl/src/HasExtensions.jl b/test/project/Extensions/HasExtensions.jl/src/HasExtensions.jl index dbfaeec4f88120..9d9785f87f7902 100644 --- a/test/project/Extensions/HasExtensions.jl/src/HasExtensions.jl +++ b/test/project/Extensions/HasExtensions.jl/src/HasExtensions.jl @@ -6,5 +6,6 @@ foo(::HasExtensionsStruct) = 1 ext_loaded = false ext_folder_loaded = false +ext_dep_loaded = false end # module From 3357d1b52c9db4a71b192fb08d6c04657f03e95c Mon Sep 17 00:00:00 2001 From: Kristoffer Carlsson Date: Wed, 10 Apr 2024 23:02:45 +0200 Subject: [PATCH 112/123] revert moving "creating packages" from Pkg.jl (#53509) As mentioned in https://github.com/JuliaLang/julia/pull/52102#issuecomment-1845523326, having this information be moved from Pkg to Base creates a quite uncomfortable split between information about the package manager between the Pkg docs and Base. Pkg PR: https://github.com/JuliaLang/Pkg.jl/pull/3818 --- doc/make.jl | 1 - doc/src/tutorials/creating-packages.md | 647 ------------------------- stdlib/Test/docs/src/index.md | 4 +- 3 files changed, 2 insertions(+), 650 deletions(-) delete mode 100644 doc/src/tutorials/creating-packages.md diff --git a/doc/make.jl b/doc/make.jl index e06fa1deb8f422..15205d6c2f89de 100644 --- a/doc/make.jl +++ b/doc/make.jl @@ -193,7 +193,6 @@ BaseDocs = [ StdlibDocs = [stdlib.targetfile for stdlib in STDLIB_DOCS] Tutorials = [ - "tutorials/creating-packages.md", "tutorials/profile.md", "tutorials/external.md", ] diff --git a/doc/src/tutorials/creating-packages.md b/doc/src/tutorials/creating-packages.md deleted file mode 100644 index c5cd1f4f92f482..00000000000000 --- a/doc/src/tutorials/creating-packages.md +++ /dev/null @@ -1,647 +0,0 @@ -# [Creating Packages](@id creating-packages-tutorial) - -## Generating files for a package - -!!! note - The [PkgTemplates](https://github.com/invenia/PkgTemplates.jl) package offers an easy, repeatable, and - customizable way to generate the files for a new package. It can also generate files needed for Documentation, CI, etc. - We recommend that you use PkgTemplates for creating - new packages instead of using the minimal `pkg> generate` functionality described below. - -To generate the bare minimum files for a new package, use `pkg> generate`. - -```julia-repl -(@v1.8) pkg> generate HelloWorld -``` - -This creates a new project `HelloWorld` in a subdirectory by the same name, with the following files (visualized with the external [`tree` command](https://linux.die.net/man/1/tree)): - -```julia-repl -shell> tree HelloWorld/ -HelloWorld/ -โ”œโ”€โ”€ Project.toml -โ””โ”€โ”€ src - โ””โ”€โ”€ HelloWorld.jl - -2 directories, 2 files -``` - -The `Project.toml` file contains the name of the package, its unique UUID, its version, the authors and potential dependencies: - -```toml -name = "HelloWorld" -uuid = "b4cd1eb8-1e24-11e8-3319-93036a3eb9f3" -version = "0.1.0" -authors = ["Some One "] - -[deps] -``` - -The content of `src/HelloWorld.jl` is: - -```julia -module HelloWorld - -greet() = print("Hello World!") - -end # module -``` - -We can now activate the project by using the path to the directory where it is installed, and load the package: - -```julia-repl -pkg> activate ./HelloWorld - -julia> import HelloWorld - -julia> HelloWorld.greet() -Hello World! -``` - -For the rest of the tutorial we enter inside the directory of the project, for convenience: - -```julia-repl -julia> cd("HelloWorld") -``` - -## Adding dependencies to the project - -Letโ€™s say we want to use the standard library package `Random` and the registered package `JSON` in our project. -We simply `add` these packages (note how the prompt now shows the name of the newly generated project, -since we `activate`d it): - -```julia-repl -(HelloWorld) pkg> add Random JSON - Resolving package versions... - Updating `~/HelloWorld/Project.toml` - [682c06a0] + JSON v0.21.3 - [9a3f8284] + Random - Updating `~/HelloWorld/Manifest.toml` - [682c06a0] + JSON v0.21.3 - [69de0a69] + Parsers v2.4.0 - [ade2ca70] + Dates - ... -``` - -Both `Random` and `JSON` got added to the projectโ€™s `Project.toml` file, and the resulting dependencies got added to the `Manifest.toml` file. -The resolver has installed each package with the highest possible version, while still respecting the compatibility that each package enforces on its dependencies. - -We can now use both `Random` and `JSON` in our project. Changing `src/HelloWorld.jl` to - -```julia -module HelloWorld - -import Random -import JSON - -greet() = print("Hello World!") -greet_alien() = print("Hello ", Random.randstring(8)) - -end # module -``` - -and reloading the package, the new `greet_alien` function that uses `Random` can be called: - -```julia-repl -julia> HelloWorld.greet_alien() -Hello aT157rHV -``` - -## Defining a public API - -If you want your package to be useful to other packages and you want folks to be able to -easily update to newer version of your package when they come out, it is important to -document what behavior will stay consistent across updates. - -Unless you note otherwise, the public API of your package is defined as all the behavior you -describe about public symbols. A public symbol is a symbol that is exported from your -package with the `export` keyword or marked as public with the `public` keyword. When you -change the behavior of something that was previously public so that the new -version no longer conforms to the specifications provided in the old version, you should -adjust your package version number according to [Julia's variant on SemVer](#Version-specifier-format). -If you would like to include a symbol in your public API without exporting it into the -global namespace of folks who call `using YourPackage`, you should mark that symbol as -public with `public that_symbol`. Symbols marked as public with the `public` keyword are -just as public as those marked as public with the `export` keyword, but when folks call -`using YourPackage`, they will still have to qualify access to those symbols with -`YourPackage.that_symbol`. - -Let's say we would like our `greet` function to be part of the public API, but not the -`greet_alien` function. We could the write the following and release it as version `1.0.0`. - -```julia -module HelloWorld - -export greet - -import Random -import JSON - -"Writes a friendly message." -greet() = print("Hello World!") - -"Greet an alien by a randomly generated name." -greet_alien() = print("Hello ", Random.randstring(8)) - -end # module -``` - -Then, if we change `greet` to - -```julia -"Writes a friendly message that is exactly three words long." -greet() = print("Hello Lovely World!") -``` - -We would release the new version as `1.1.0`. This is not breaking -because the new implementation conforms to the old documentation, but -it does add a new feature, that the message must be three words long. - -Later, we may wish to change `greet_alien` to - -```julia -"Greet an alien by the name of \"Zork\"." -greet_alien() = print("Hello Zork") -``` - -And also export it by changing - -```julia -export greet -``` - -to - -```julia -export greet, greet_alien -``` - -We should release this new version as `1.2.0` because it adds a new feature -`greet_alien` to the public API. Even though `greet_alien` was documented before -and the new version does not conform to the old documentation, this is not breaking -because the old documentation was not attached to a symbol that was exported -at the time so that documentation does not apply across released versions. - -However, if we now wish to change `greet` to - -```julia -"Writes a friendly message that is exactly four words long." -greet() = print("Hello very lovely world") -``` - -we would need to release the new version as `2.0.0`. In version `1.1.0`, we specified that -the greeting would be three words long, and because `greet` was exported, that description -also applies to all future versions until the next breaking release. Because this new -version does not conform to the old specification, it must be tagged as a breaking change. - -Please note that version numbers are free and unlimited. It is okay to use lots of them -(e.g. version `6.62.8`). - -## Adding a build step to the package - -The build step is executed the first time a package is installed or when explicitly invoked with `build`. -A package is built by executing the file `deps/build.jl`. - -```julia-repl -julia> mkpath("deps"); - -julia> write("deps/build.jl", - """ - println("I am being built...") - """); - -(HelloWorld) pkg> build - Building HelloWorld โ†’ `deps/build.log` - Resolving package versions... - -julia> print(readchomp("deps/build.log")) -I am being built... -``` - -If the build step fails, the output of the build step is printed to the console - -```julia-repl -julia> write("deps/build.jl", - """ - error("Ooops") - """); - -(HelloWorld) pkg> build - Building HelloWorld โ†’ `~/HelloWorld/deps/build.log` -ERROR: Error building `HelloWorld`: -ERROR: LoadError: Ooops -Stacktrace: - [1] error(s::String) - @ Base ./error.jl:35 - [2] top-level scope - @ ~/HelloWorld/deps/build.jl:1 - [3] include(fname::String) - @ Base.MainInclude ./client.jl:476 - [4] top-level scope - @ none:5 -in expression starting at /home/kc/HelloWorld/deps/build.jl:1 -``` - -!!! warning - A build step should generally not create or modify any files in the package directory. If you need to store some files - from the build step, use the [Scratch.jl](https://github.com/JuliaPackaging/Scratch.jl) package. - -## [Adding tests to the package](@id adding-tests-to-packages) - -When a package is tested the file `test/runtests.jl` is executed: - -```julia-repl -julia> mkpath("test"); - -julia> write("test/runtests.jl", - """ - println("Testing...") - """); - -(HelloWorld) pkg> test - Testing HelloWorld - Resolving package versions... -Testing... - Testing HelloWorld tests passed -``` - -Tests are run in a new Julia process, where the package itself, and any -test-specific dependencies, are available, see below. - - -!!! warning - Tests should generally not create or modify any files in the package directory. If you need to store some files - from the build step, use the [Scratch.jl](https://github.com/JuliaPackaging/Scratch.jl) package. - -### Test-specific dependencies - -There are two ways of adding test-specific dependencies (dependencies that are not dependencies of the package but will still be available to -load when the package is tested). - -#### `target` based test specific dependencies - -Using this method of adding test-specific dependencies, the packages are added under an `[extras]` section and to a test target, -e.g. to add `Markdown` and `Test` as test dependencies, add the following to the `Project.toml` file: - -```toml -[extras] -Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[targets] -test = ["Markdown", "Test"] -``` - -Note that the only supported targets are `test` and `build`, the latter of which (not recommended) can be used -for any `deps/build.jl` scripts. - -#### Alternative approach: `test/Project.toml` file test specific dependencies - -!!! note - The exact interaction between `Project.toml`, `test/Project.toml` and their corresponding - `Manifest.toml`s are not fully worked out and may be subject to change in future versions. - The older method of adding test-specific dependencies, described in the previous section, - will therefore be supported throughout all Julia 1.X releases. - -In Julia 1.2 and later test dependencies can be declared in `test/Project.toml`. When running -tests, Pkg will automatically merge this and the package Projects to create the test environment. - -!!! note - If no `test/Project.toml` exists Pkg will use the `target` based test specific dependencies. - -To add a test-specific dependency, i.e. a dependency that is available only when testing, -it is thus enough to add this dependency to the `test/Project.toml` project. This can be -done from the Pkg REPL by activating this environment, and then use `add` as one normally -does. Let's add the `Test` standard library as a test dependency: - -```julia-repl -(HelloWorld) pkg> activate ./test -[ Info: activating environment at `~/HelloWorld/test/Project.toml`. - -(test) pkg> add Test - Resolving package versions... - Updating `~/HelloWorld/test/Project.toml` - [8dfed614] + Test - Updating `~/HelloWorld/test/Manifest.toml` - [...] -``` - -We can now use `Test` in the test script and we can see that it gets installed when testing: - -```julia-repl -julia> write("test/runtests.jl", - """ - using Test - @test 1 == 1 - """); - -(test) pkg> activate . - -(HelloWorld) pkg> test - Testing HelloWorld - Resolving package versions... - Updating `/var/folders/64/76tk_g152sg6c6t0b4nkn1vw0000gn/T/tmpPzUPPw/Project.toml` - [d8327f2a] + HelloWorld v0.1.0 [`~/.julia/dev/Pkg/HelloWorld`] - [8dfed614] + Test - Updating `/var/folders/64/76tk_g152sg6c6t0b4nkn1vw0000gn/T/tmpPzUPPw/Manifest.toml` - [d8327f2a] + HelloWorld v0.1.0 [`~/.julia/dev/Pkg/HelloWorld`] - Testing HelloWorld tests passed``` -``` - -## Compatibility on dependencies - -Every dependency should in general have a compatibility constraint on it. -This is an important topic so there is a chapter in the package docs about it: -[Compatibility](https://pkgdocs.julialang.org/v1/compatibility). - -## Weak dependencies - -!!! note - This is a somewhat advanced usage of Pkg which can be skipped for people new to Julia and Julia packages. - -!!! compat - The described feature requires Julia 1.9+. - -A weak dependency is a dependency that will not automatically install when the package is installed but -you can still control what versions of that package are allowed to be installed by setting compatibility on it. -These are listed in the project file under the `[weakdeps]` section: - -```toml -[weakdeps] -SomePackage = "b3785f31-9d33-4cdf-bc73-f646780f1739" - -[compat] -SomePackage = "1.2" -``` - -The current usage of this is almost solely limited to "extensions" which is described in the next section. - -## Conditional loading of code in packages (Extensions) - -!!! note - This is a somewhat advanced usage of Pkg which can be skipped for people new to Julia and Julia packages. - -!!! compat - The described feature requires Julia 1.9+. - -Sometimes one wants to make two or more packages work well together, but may be reluctant (perhaps due to increased load times) to make one an unconditional dependency of the other. -A package *extension* is a module in a file (similar to a package) that is automatically loaded when *some other set of packages* are -loaded into the Julia session. This is very similar to functionality that the external package -[Requires.jl](https://github.com/JuliaPackaging/Requires.jl) provides, but which is now available directly through Julia, -and provides added benefits such as being able to precompile the extension. - -### Code structure - -A useful application of extensions could be for a plotting package that should be able to plot -objects from a wide variety of different Julia packages. -Adding all those different Julia packages as dependencies of the plotting package -could be expensive since they would end up getting loaded even if they were never used. -Instead, the code required to plot objects for specific packages can be put into separate files -(extensions) and these are loaded only when the packages that define the type(s) we want to plot -are loaded. - -Below is an example of how the code can be structured for a use case in which a -`Plotting` package wants to be able to display objects defined in the external package `Contour`. -The file and folder structure shown below is found in the `Plotting` package. - - `Project.toml`: - ```toml -name = "Plotting" -version = "0.1.0" -uuid = "..." - -[weakdeps] -Contour = "d38c429a-6771-53c6-b99e-75d170b6e991" - -[extensions] -# name of extension to the left -# extension dependencies required to load the extension to the right -# use a list for multiple extension dependencies -PlottingContourExt = "Contour" - -[compat] -Contour = "0.6.2" -``` - -`src/Plotting.jl`: -```julia -module Plotting - -function plot(x::Vector) - # Some functionality for plotting a vector here -end - -end # module -``` - -`ext/PlottingContourExt.jl` (can also be in `ext/PlottingContourExt/PlottingContourExt.jl`): -```julia -module PlottingContourExt # Should be same name as the file (just like a normal package) - -using Plotting, Contour - -function Plotting.plot(c::Contour.ContourCollection) - # Some functionality for plotting a contour here -end - -end # module -``` - -Extensions can have any arbitrary name (here `PlottingContourExt`), but using something similar to the format of -this example that makes the extended functionality and dependency of the extension clear is likely a good idea. - -!!! compat - Often you will put the extension dependencies into the `test` target so they are loaded when running e.g. `Pkg.test()`. On earlier Julia versions - this requires you to also put the package in the `[extras]` section. This is unfortunate but the project verifier on older Julia versions will - complain if this is not done. - -!!! note - If you use a manifest generated by a Julia version that does not know about extensions with a Julia version that does - know about them, the extensions will not load. This is because the manifest lacks some information that tells Julia - when it should load these packages. So make sure you use a manifest generated at least the Julia version you are using. - -### Behavior of extensions - -A user that depends only on `Plotting` will not pay the cost of the "extension" inside the `PlottingContourExt` module. -It is only when the `Contour` package actually gets loaded that the `PlottingContourExt` extension is loaded too -and provides the new functionality. - -In our example, the new functionality is an additional _method_, which we add to an existing _function_ from the parent package `Plotting`. -Implementing such methods is among the most standard use cases of package extensions. -Within the parent package, the function to extend can even be defined with zero methods, as follows: - -```julia -function plot end -``` - -!!! note - If one considers `PlottingContourExt` as a completely separate package, it could be argued that defining `Plotting.plot(c::Contour.ContourCollection)` is - [type piracy](@ref avoid-type-piracy) since `PlottingContourExt` _owns_ neither the function `Plotting.plot` nor the type `Contour.ContourCollection`. - However, for extensions, it is ok to assume that the extension owns the functions in its parent package. - -In other situations, one may need to define new symbols in the extension (types, structs, functions, etc.) instead of reusing those from the parent package. -Such symbols are created in a separate module corresponding to the extension, namely `PlottingContourExt`, and thus not in `Plotting` itself. -If extension symbols are needed in the parent package, one must call `Base.get_extension` to retrieve them. -Here is an example showing how a custom type defined in `PlottingContourExt` can be accessed in `Plotting`: - -```julia -ext = Base.get_extension(@__MODULE__, :PlottingContourExt) -if !isnothing(ext) - ContourPlotType = ext.ContourPlotType -end -``` - -On the other hand, accessing extension symbols from a third-party package (i.e. not the parent) is not a recommended practice at the moment. - -### Backwards compatibility - -This section discusses various methods for using extensions on Julia versions that support them, -while simultaneously providing similar functionality on older Julia versions. - -#### Requires.jl - -This section is relevant if you are currently using Requires.jl but want to transition to using extensions (while still having Requires be used on Julia versions that do not support extensions). -This is done by making the following changes (using the example above): - -- Add the following to the package file. This makes it so that Requires.jl loads and inserts the - callback only when extensions are not supported - ```julia - # This symbol is only defined on Julia versions that support extensions - if !isdefined(Base, :get_extension) - using Requires - end - - @static if !isdefined(Base, :get_extension) - function __init__() - @require Contour = "d38c429a-6771-53c6-b99e-75d170b6e991" include("../ext/PlottingContourExt.jl") - end - end - ``` - or if you have other things in your `__init__()` function: - ```julia - if !isdefined(Base, :get_extension) - using Requires - end - - function __init__() - # Other init functionality here - - @static if !isdefined(Base, :get_extension) - @require Contour = "d38c429a-6771-53c6-b99e-75d170b6e991" include("../ext/PlottingContourExt.jl") - end - end - ``` -- Make the following change in the conditionally-loaded code: - ```julia - isdefined(Base, :get_extension) ? (using Contour) : (using ..Contour) - ``` -- Add `Requires` to `[weakdeps]` in your `Project.toml` file, so that it is listed in both `[deps]` and `[weakdeps]`. - Julia 1.9+ knows to not install it as a regular dependency, whereas earlier versions will consider it a dependency. - -The package should now work with Requires.jl on Julia versions before extensions were introduced -and with extensions on more recent Julia versions. - -#### Transition from normal dependency to extension - -This section is relevant if you have a normal dependency that you want to transition be an extension (while still having the dependency be a normal dependency on Julia versions that do not support extensions). -This is done by making the following changes (using the example above): - -- Make sure that the package is **both** in the `[deps]` and `[weakdeps]` section. Newer Julia versions will ignore dependencies in `[deps]` that are also in `[weakdeps]`. -- Add the following to your main package file (typically at the bottom): - ```julia - if !isdefined(Base, :get_extension) - include("../ext/PlottingContourExt.jl") - end - ``` - -#### Using an extension while supporting older Julia versions - -In the case where one wants to use an extension (without worrying about the -feature of the extension being available on older Julia versions) while still -supporting older Julia versions the packages under `[weakdeps]` should be -duplicated into `[extras]`. This is an unfortunate duplication, but without -doing this the project verifier under older Julia versions will throw an error -if it finds packages under `[compat]` that is not listed in `[extras]`. - -## Package naming rules - -Package names should be sensible to most Julia users, *even to those who are not domain experts*. -The following rules apply to the `General` registry but may be useful for other package -registries as well. - -Since the `General` registry belongs to the entire community, people may have opinions about -your package name when you publish it, especially if it's ambiguous or can be confused with -something other than what it is. Usually, you will then get suggestions for a new name that -may fit your package better. - -1. Avoid jargon. In particular, avoid acronyms unless there is minimal possibility of confusion. - - * It's ok to say `USA` if you're talking about the USA. - * It's not ok to say `PMA`, even if you're talking about positive mental attitude. -2. Avoid using `Julia` in your package name or prefixing it with `Ju`. - - * It is usually clear from context and to your users that the package is a Julia package. - * Package names already have a `.jl` extension, which communicates to users that `Package.jl` is a Julia package. - * Having Julia in the name can imply that the package is connected to, or endorsed by, contributors - to the Julia language itself. -3. Packages that provide most of their functionality in association with a new type should have pluralized - names. - - * `DataFrames` provides the `DataFrame` type. - * `BloomFilters` provides the `BloomFilter` type. - * In contrast, `JuliaParser` provides no new type, but instead new functionality in the `JuliaParser.parse()` - function. -4. Err on the side of clarity, even if clarity seems long-winded to you. - - * `RandomMatrices` is a less ambiguous name than `RndMat` or `RMT`, even though the latter are shorter. -5. A less systematic name may suit a package that implements one of several possible approaches to - its domain. - - * Julia does not have a single comprehensive plotting package. Instead, `Gadfly`, `PyPlot`, `Winston` - and other packages each implement a unique approach based on a particular design philosophy. - * In contrast, `SortingAlgorithms` provides a consistent interface to use many well-established - sorting algorithms. -6. Packages that wrap external libraries or programs can be named after those libraries or programs. - - * `CPLEX.jl` wraps the `CPLEX` library, which can be identified easily in a web search. - * `MATLAB.jl` provides an interface to call the MATLAB engine from within Julia. - -7. Avoid naming a package closely to an existing package - * `Websocket` is too close to `WebSockets` and can be confusing to users. Rather use a new name such as `SimpleWebsockets`. - -8. Avoid using a distinctive name that is already in use in a well known, unrelated project. - * Don't use the names `Tkinter.jl`, `TkinterGUI.jl`, etc. for a package that is unrelated - to the popular `tkinter` python package, even if it provides bindings to Tcl/Tk. - A package name of `Tkinter.jl` would only be appropriate if the package used Python's - library to accomplish its work or was spearheaded by the same community of developers. - * It's okay to name a package `HTTP.jl` even though it is unrelated to the popular rust - crate `http` because in most usages the name "http" refers to the hypertext transfer - protocol, not to the `http` rust crate. - * It's okay to name a package `OpenSSL.jl` if it provides an interface to the OpenSSL - library, even without explicit affiliation with the creators of the OpenSSL (provided - there's no copyright or trademark infringement etc.) - -## Registering packages - -Once a package is ready it can be registered with the [General Registry](https://github.com/JuliaRegistries/General#registering-a-package-in-general) (see also the [FAQ](https://github.com/JuliaRegistries/General#faq)). -Currently, packages are submitted via [`Registrator`](https://juliaregistrator.github.io/). -In addition to `Registrator`, [`TagBot`](https://github.com/marketplace/actions/julia-tagbot) helps manage the process of tagging releases. - -## Best Practices - -Packages should avoid mutating their own state (writing to files within their package directory). -Packages should, in general, not assume that they are located in a writable location (e.g. if installed as part of a system-wide depot) or even a stable one (e.g. if they are bundled into a system image by [PackageCompiler.jl](https://github.com/JuliaLang/PackageCompiler.jl)). -To support the various use cases in the Julia package ecosystem, the Pkg developers have created a number of auxiliary packages and techniques to help package authors create self-contained, immutable, and relocatable packages: - -* [`Artifacts`](https://pkgdocs.julialang.org/v1/artifacts/) can be used to bundle chunks of data alongside your package, or even allow them to be downloaded on-demand. - Prefer artifacts over attempting to open a file via a path such as `joinpath(@__DIR__, "data", "my_dataset.csv")` as this is non-relocatable. - Once your package has been precompiled, the result of `@__DIR__` will have been baked into your precompiled package data, and if you attempt to distribute this package, it will attempt to load files at the wrong location. - Artifacts can be bundled and accessed easily using the `artifact"name"` string macro. - -* [`Scratch.jl`](https://github.com/JuliaPackaging/Scratch.jl) provides the notion of "scratch spaces", mutable containers of data for packages. - Scratch spaces are designed for data caches that are completely managed by a package and should be removed when the package itself is uninstalled. - For important user-generated data, packages should continue to write out to a user-specified path that is not managed by Julia or Pkg. - -* [`Preferences.jl`](https://github.com/JuliaPackaging/Preferences.jl) allows packages to read and write preferences to the top-level `Project.toml`. - These preferences can be read at runtime or compile-time, to enable or disable different aspects of package behavior. - Packages previously would write out files to their own package directories to record options set by the user or environment, but this is highly discouraged now that `Preferences` is available. diff --git a/stdlib/Test/docs/src/index.md b/stdlib/Test/docs/src/index.md index e68efdfb6ebf5a..949c2591474a6e 100644 --- a/stdlib/Test/docs/src/index.md +++ b/stdlib/Test/docs/src/index.md @@ -24,7 +24,7 @@ The `Test` module provides simple *unit testing* functionality. Unit testing is see if your code is correct by checking that the results are what you expect. It can be helpful to ensure your code still works after you make changes, and can be used when developing as a way of specifying the behaviors your code should have when complete. You may also want to look at the -documentation for [adding tests to your Julia Package](@ref adding-tests-to-packages). +documentation for [adding tests to your Julia Package](https://pkgdocs.julialang.org/dev/creating-packages/#Adding-tests-to-the-package). Simple unit testing can be performed with the `@test` and `@test_throws` macros: @@ -469,7 +469,7 @@ end We will need to create those two included files, `math_tests.jl` and `greeting_tests.jl`, and add some tests to them. > **Note:** Notice how we did not have to specify add `Example` into the `test` environment's `Project.toml`. -> This is a benefit of Julia's testing system that you could [read about more here](@ref adding-tests-to-packages). +> This is a benefit of Julia's testing system that you could [read about more here](https://pkgdocs.julialang.org/dev/creating-packages/). #### Writing Tests for `math_tests.jl` From 45fb084873b56dc555dd442cda3485c6175344b5 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Thu, 11 Apr 2024 08:55:08 +0900 Subject: [PATCH 113/123] inlining: remove unused `allow_abstract::Bool` keyword argument (#53601) --- base/compiler/ssair/inlining.jl | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index e54d3fd834a27c..d6853d83b61bcc 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -1294,16 +1294,16 @@ end function handle_any_const_result!(cases::Vector{InliningCase}, @nospecialize(result), match::MethodMatch, argtypes::Vector{Any}, @nospecialize(info::CallInfo), flag::UInt32, state::InliningState; - allow_abstract::Bool, allow_typevars::Bool) + allow_typevars::Bool) if isa(result, ConcreteResult) return handle_concrete_result!(cases, result, match, info, state) elseif isa(result, SemiConcreteResult) - return handle_semi_concrete_result!(cases, result, match, info, flag, state; allow_abstract) + return handle_semi_concrete_result!(cases, result, match, info, flag, state) elseif isa(result, ConstPropResult) - return handle_const_prop_result!(cases, result, match, info, flag, state; allow_abstract, allow_typevars) + return handle_const_prop_result!(cases, result, match, info, flag, state; allow_typevars) else @assert result === nothing || result isa VolatileInferenceResult - return handle_match!(cases, match, argtypes, info, flag, state; allow_abstract, allow_typevars, volatile_inf_result = result) + return handle_match!(cases, match, argtypes, info, flag, state; allow_typevars, volatile_inf_result = result) end end @@ -1368,7 +1368,7 @@ function compute_inlining_cases(@nospecialize(info::CallInfo), flag::UInt32, sig handled_all_cases = false else handled_all_cases &= handle_any_const_result!(cases, - result, match, argtypes, info, flag, state; allow_abstract=true, allow_typevars=false) + result, match, argtypes, info, flag, state; allow_typevars=false) end end fully_covered &= split_fully_covered @@ -1384,7 +1384,7 @@ function compute_inlining_cases(@nospecialize(info::CallInfo), flag::UInt32, sig match = getsplit(info, i)[j] result = getresult(info, k) handled_all_cases &= handle_any_const_result!(cases, - result, match, argtypes, info, flag, state; allow_abstract=true, allow_typevars=true) + result, match, argtypes, info, flag, state; allow_typevars=true) end elseif !isempty(cases) # if we've not seen all candidates, union split is valid only for dispatch tuples @@ -1407,10 +1407,8 @@ end function handle_match!(cases::Vector{InliningCase}, match::MethodMatch, argtypes::Vector{Any}, @nospecialize(info::CallInfo), flag::UInt32, state::InliningState; - allow_abstract::Bool, allow_typevars::Bool, - volatile_inf_result::Union{Nothing,VolatileInferenceResult}) + allow_typevars::Bool, volatile_inf_result::Union{Nothing,VolatileInferenceResult}) spec_types = match.spec_types - allow_abstract || isdispatchtuple(spec_types) || return false # We may see duplicated dispatch signatures here when a signature gets widened # during abstract interpretation: for the purpose of inlining, we can just skip # processing this dispatch candidate (unless unmatched type parameters are present) @@ -1423,10 +1421,9 @@ end function handle_const_prop_result!(cases::Vector{InliningCase}, result::ConstPropResult, match::MethodMatch, @nospecialize(info::CallInfo), flag::UInt32, state::InliningState; - allow_abstract::Bool, allow_typevars::Bool) + allow_typevars::Bool) mi = result.result.linfo spec_types = match.spec_types - allow_abstract || isdispatchtuple(spec_types) || return false if !validate_sparams(mi.sparam_vals) (allow_typevars && !may_have_fcalls(mi.def::Method)) || return false end @@ -1460,11 +1457,9 @@ function semiconcrete_result_item(result::SemiConcreteResult, end function handle_semi_concrete_result!(cases::Vector{InliningCase}, result::SemiConcreteResult, - match::MethodMatch, @nospecialize(info::CallInfo), flag::UInt32, state::InliningState; - allow_abstract::Bool) + match::MethodMatch, @nospecialize(info::CallInfo), flag::UInt32, state::InliningState) mi = result.mi spec_types = match.spec_types - allow_abstract || isdispatchtuple(spec_types) || return false validate_sparams(mi.sparam_vals) || return false item = semiconcrete_result_item(result, info, flag, state) item === nothing && return false From 630f7545a4a1a91caffc391ab463c437de721998 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 10 Apr 2024 23:54:41 -0400 Subject: [PATCH 114/123] Fix comparison base for line table compression (#54032) I'm not entirely sure what the original intent of this statement was, but the effect ends up being that some codeloc entries end up negative in the compressed representation, but the code always assumes unsigned integers, so things roundtripped badly, leading to badly corrupted stack traces. I guess this might have been a rebase mistake, since the same line exists (correctly) a few lines prior. Fixes #54031. --- src/ircode.c | 1 - test/compiler/ssair.jl | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ircode.c b/src/ircode.c index 196f9f7b413ada..2e16d1b5b24208 100644 --- a/src/ircode.c +++ b/src/ircode.c @@ -1234,7 +1234,6 @@ JL_DLLEXPORT jl_string_t *jl_compress_codelocs(int32_t firstline, jl_value_t *co #undef SETMIN #undef SETMAX } - min.line = min.to = min.pc = firstline <= 0 ? INT32_MAX : firstline; int32_t header[3]; header[0] = min.line > max.line ? 0 : min.line; header[1] = min.line > max.line ? 0 : max.line - min.line; diff --git a/test/compiler/ssair.jl b/test/compiler/ssair.jl index 9d5f7b617080d2..9ff4d3d8a42201 100644 --- a/test/compiler/ssair.jl +++ b/test/compiler/ssair.jl @@ -825,3 +825,10 @@ end @test_throws ErrorException f_must_throw_phinode_edge() global global_error_switch = false @test f_must_throw_phinode_edge() == 1 + +# Test roundtrip of debuginfo compression +let cl = Int32[32, 1, 1, 1000, 240, 230] + str = ccall(:jl_compress_codelocs, Any, (Int32, Any, Int), 378, cl, 2)::String; + cl2 = ccall(:jl_uncompress_codelocs, Any, (Any, Int), str, 2) + @test cl == cl2 +end From dc8857a86f0102b2e935057ac38eb5068833ac44 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 11 Apr 2024 08:05:30 -0400 Subject: [PATCH 115/123] ir: Add version of compute_trycatch for IRCode (#54035) For ir transform passes that need to be aware of current_scope. Currently no users in Base, but available for external absint. --------- Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> --- base/compiler/inferencestate.jl | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 48784378ef7c10..3f2ec4734cc210 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -368,7 +368,21 @@ is_inferred(result::InferenceResult) = result.result !== nothing was_reached(sv::InferenceState, pc::Int) = sv.ssavaluetypes[pc] !== NOT_FOUND -function compute_trycatch(code::Vector{Any}, ip::BitSet) +compute_trycatch(ir::IRCode, ip::BitSet) = compute_trycatch(ir.stmts.stmt, ip, ir.cfg.blocks) + +""" + compute_trycatch(code, ip [, bbs]) -> (handler_at, handlers) + +Given the code of a function, compute, at every statement, the current +try/catch handler, and the current exception stack top. This function returns +a tuple of: + + 1. `handler_at`: A statement length vector of tuples `(catch_handler, exception_stack)`, + which are indices into `handlers` + + 2. `handlers`: A `TryCatchFrame` vector of handlers +""" +function compute_trycatch(code::Vector{Any}, ip::BitSet, bbs::Union{Vector{BasicBlock}, Nothing}=nothing) # The goal initially is to record the frame like this for the state at exit: # 1: (enter 3) # == 0 # 3: (expr) # == 1 @@ -388,6 +402,7 @@ function compute_trycatch(code::Vector{Any}, ip::BitSet) stmt = code[pc] if isa(stmt, EnterNode) l = stmt.catch_dest + (bbs !== nothing) && (l = first(bbs[l].stmts)) push!(handlers, TryCatchFrame(Bottom, isdefined(stmt, :scope) ? Bottom : nothing, pc)) handler_id = length(handlers) handler_at[pc + 1] = (handler_id, 0) @@ -412,8 +427,10 @@ function compute_trycatch(code::Vector{Any}, ip::BitSet) stmt = code[pc] if isa(stmt, GotoNode) pcยด = stmt.label + (bbs !== nothing) && (pcยด = first(bbs[pcยด].stmts)) elseif isa(stmt, GotoIfNot) l = stmt.dest::Int + (bbs !== nothing) && (l = first(bbs[l].stmts)) if handler_at[l] != cur_stacks @assert handler_at[l][1] == 0 || handler_at[l][1] == cur_stacks[1] "unbalanced try/catch" handler_at[l] = cur_stacks @@ -424,6 +441,7 @@ function compute_trycatch(code::Vector{Any}, ip::BitSet) break elseif isa(stmt, EnterNode) l = stmt.catch_dest + (bbs !== nothing) && (l = first(bbs[l].stmts)) # We assigned a handler number above. Here we just merge that # with out current handler information. if l != 0 From a7fd6a76f43262c02e83d809500b98e649490dbc Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 11 Apr 2024 08:05:43 -0400 Subject: [PATCH 116/123] Allow mutable-for-identity-only types to be inlined into IR (#54034) This extends the value-inability predicate to allow mutable structs that do not have any mutable fields. The motivating example for this is ScopedValue, which is mutable only for identity. By allowing it in this predicate, more of the ScopedValue support code becomes concrete-eval eligible, rather than attempting to constprop for every single ScopedValue, saving compilation time. --------- Co-authored-by: Shuhei Kadowaki --- base/compiler/utilities.jl | 22 +++++++++++++++++++++- test/scopedvalues.jl | 9 +++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index 1e002f8dad5a6d..75e8f84dc4c33d 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -83,7 +83,27 @@ const MAX_INLINE_CONST_SIZE = 256 function count_const_size(@nospecialize(x), count_self::Bool = true) (x isa Type || x isa Core.TypeName || x isa Symbol) && return 0 - ismutable(x) && return MAX_INLINE_CONST_SIZE + 1 + if ismutable(x) + # No definite size + (isa(x, GenericMemory) || isa(x, String) || isa(x, SimpleVector)) && + return MAX_INLINE_CONST_SIZE + 1 + if isa(x, Module) + # We allow modules, because we already assume they are externally + # rooted, so we count their contents as 0 size. + return sizeof(Ptr{Cvoid}) + end + # We allow mutable types with no mutable fields (i.e. those mutable + # types used for identity only). The intent of this function is to + # prevent the rooting of large amounts of data that may have been + # speculatively computed. If the struct can get mutated later, we + # cannot assess how much data we might end up rooting. However, if + # the struct is mutable only for identity, the query still works. + for i = 1:nfields(x) + if !isconst(typeof(x), i) + return MAX_INLINE_CONST_SIZE + 1 + end + end + end isbits(x) && return Core.sizeof(x) dt = typeof(x) sz = count_self ? sizeof(dt) : 0 diff --git a/test/scopedvalues.jl b/test/scopedvalues.jl index 3af6a3f065c8b1..61b10c557c4555 100644 --- a/test/scopedvalues.jl +++ b/test/scopedvalues.jl @@ -1,6 +1,9 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license + using Base.ScopedValues +include("compiler/irutils.jl") + @testset "errors" begin @test ScopedValue{Float64}(1)[] == 1.0 @test_throws InexactError ScopedValue{Int}(1.5) @@ -160,3 +163,9 @@ end let code = code_typed(with_macro_slot_cross)[1][1].code @test !any(x->isa(x, Core.PhiCNode), code) end + +# inline constant scoped values +const inlineable_const_sv = ScopedValue(1) +@test fully_eliminated(; retval=(inlineable_const_sv => 1)) do + inlineable_const_sv => 1 +end From f085913ba188b825f7e669a80783244e852d20ad Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 11 Apr 2024 10:11:55 -0400 Subject: [PATCH 117/123] constprop: Add facility for widening arguments before constprop (#54036) There are various situations where we may want to constprop with something other than the most precise concrete arguments in order to make the resulting cache more useful to other call sites. One particular example of this might be a method where non-concrete inference already discovered that one argument is unused: ``` function foo(a, b::DispatchOnly) expensive_to_compile(a) end ``` Right now, we will generally perform constprop for every different value of `b`, even though we already have the information that `b` is unused. Another example is external absints that may want to treat certain types fully symbolically. They may want to substitute concrete values for an abstract domain. This adds the facility to do both of these things by 1. Adding an appropriate interp hook in the constprop path 2. Adding a WidendedSimpleArgtypes wrapper that's like SimpleArgtypes but works around an issue where we would override cache information using values from concrete eval, which is not legal if the argtypes were widened. --- base/compiler/abstractinterpretation.jl | 18 +++++++++++++----- base/compiler/inferenceresult.jl | 9 ++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index a396e281c1bf73..930439ad3500b7 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1243,12 +1243,17 @@ const_prop_result(inf_result::InferenceResult) = return_cached_result(::AbstractInterpreter, inf_result::InferenceResult, ::AbsIntState) = const_prop_result(inf_result) +function compute_forwarded_argtypes(interp::AbstractInterpreter, arginfo::ArgInfo, sv::AbsIntState) + ๐•ƒแตข = typeinf_lattice(interp) + return has_conditional(๐•ƒแตข, sv) ? ConditionalSimpleArgtypes(arginfo, sv) : SimpleArgtypes(arginfo.argtypes) +end + function const_prop_call(interp::AbstractInterpreter, mi::MethodInstance, result::MethodCallResult, arginfo::ArgInfo, sv::AbsIntState, concrete_eval_result::Union{Nothing, ConstCallResults}=nothing) inf_cache = get_inference_cache(interp) ๐•ƒแตข = typeinf_lattice(interp) - argtypes = has_conditional(๐•ƒแตข, sv) ? ConditionalArgtypes(arginfo, sv) : SimpleArgtypes(arginfo.argtypes) + forwarded_argtypes = compute_forwarded_argtypes(interp, arginfo, sv) # use `cache_argtypes` that has been constructed for fresh regular inference if available volatile_inf_result = result.volatile_inf_result if volatile_inf_result !== nothing @@ -1256,7 +1261,7 @@ function const_prop_call(interp::AbstractInterpreter, else cache_argtypes = matching_cache_argtypes(๐•ƒแตข, mi) end - argtypes = matching_cache_argtypes(๐•ƒแตข, mi, argtypes, cache_argtypes) + argtypes = matching_cache_argtypes(๐•ƒแตข, mi, forwarded_argtypes, cache_argtypes) inf_result = cache_lookup(๐•ƒแตข, mi, argtypes, inf_cache) if inf_result !== nothing # found the cache for this constant prop' @@ -1290,7 +1295,10 @@ function const_prop_call(interp::AbstractInterpreter, return nothing end @assert inf_result.result !== nothing - if concrete_eval_result !== nothing + # ConditionalSimpleArgtypes is allowed, because the only case in which it modifies + # the argtypes is when one of the argtypes is a `Conditional`, which case + # concrete_eval_result will not be available. + if concrete_eval_result !== nothing && isa(forwarded_argtypes, Union{SimpleArgtypes, ConditionalSimpleArgtypes}) # override return type and effects with concrete evaluation result if available inf_result.result = concrete_eval_result.rt inf_result.ipo_effects = concrete_eval_result.effects @@ -1300,13 +1308,13 @@ end # TODO implement MustAlias forwarding -struct ConditionalArgtypes +struct ConditionalSimpleArgtypes arginfo::ArgInfo sv::InferenceState end function matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, - conditional_argtypes::ConditionalArgtypes, + conditional_argtypes::ConditionalSimpleArgtypes, cache_argtypes::Vector{Any}) (; arginfo, sv) = conditional_argtypes (; fargs, argtypes) = arginfo diff --git a/base/compiler/inferenceresult.jl b/base/compiler/inferenceresult.jl index 574685c1e38d65..2575429fbf924f 100644 --- a/base/compiler/inferenceresult.jl +++ b/base/compiler/inferenceresult.jl @@ -9,8 +9,15 @@ struct SimpleArgtypes argtypes::Vector{Any} end +# Like `SimpleArgtypes`, but allows the argtypes to be wider than the current call. +# As a result, it is not legal to refine the cache result with information more +# precise than was it deducible from the `WidenedSimpleArgtypes`. +struct WidenedArgtypes + argtypes::Vector{Any} +end + function matching_cache_argtypes(๐•ƒ::AbstractLattice, mi::MethodInstance, - simple_argtypes::SimpleArgtypes, + simple_argtypes::Union{SimpleArgtypes, WidenedArgtypes}, cache_argtypes::Vector{Any}) (; argtypes) = simple_argtypes given_argtypes = Vector{Any}(undef, length(argtypes)) From db247ce88fbd585c67b38be909d3a0411dc4865a Mon Sep 17 00:00:00 2001 From: Jishnu Bhattacharya Date: Fri, 12 Apr 2024 00:52:45 +0530 Subject: [PATCH 118/123] LinearAlgebra: Remove unnecessary adjoint/transpose for bidiag/tridiag (#54024) These should be unnecessary, as the fallback methods do the same. --- stdlib/LinearAlgebra/src/bidiag.jl | 2 -- stdlib/LinearAlgebra/src/tridiag.jl | 3 --- 2 files changed, 5 deletions(-) diff --git a/stdlib/LinearAlgebra/src/bidiag.jl b/stdlib/LinearAlgebra/src/bidiag.jl index 323edd5ad45c64..145cce562991f7 100644 --- a/stdlib/LinearAlgebra/src/bidiag.jl +++ b/stdlib/LinearAlgebra/src/bidiag.jl @@ -275,8 +275,6 @@ for func in (:conj, :copy, :real, :imag) @eval ($func)(M::Bidiagonal) = Bidiagonal(($func)(M.dv), ($func)(M.ev), M.uplo) end -adjoint(B::Bidiagonal) = Adjoint(B) -transpose(B::Bidiagonal) = Transpose(B) adjoint(B::Bidiagonal{<:Number}) = Bidiagonal(conj(B.dv), conj(B.ev), B.uplo == 'U' ? :L : :U) transpose(B::Bidiagonal{<:Number}) = Bidiagonal(B.dv, B.ev, B.uplo == 'U' ? :L : :U) permutedims(B::Bidiagonal) = Bidiagonal(B.dv, B.ev, B.uplo == 'U' ? 'L' : 'U') diff --git a/stdlib/LinearAlgebra/src/tridiag.jl b/stdlib/LinearAlgebra/src/tridiag.jl index 431e349d42da24..9403b44538b11f 100644 --- a/stdlib/LinearAlgebra/src/tridiag.jl +++ b/stdlib/LinearAlgebra/src/tridiag.jl @@ -167,7 +167,6 @@ end transpose(S::SymTridiagonal) = S adjoint(S::SymTridiagonal{<:Real}) = S -adjoint(S::SymTridiagonal) = Adjoint(S) permutedims(S::SymTridiagonal) = S function permutedims(S::SymTridiagonal, perm) Base.checkdims_perm(S, S, perm) @@ -616,8 +615,6 @@ for func in (:conj, :copy, :real, :imag) end end -adjoint(S::Tridiagonal) = Adjoint(S) -transpose(S::Tridiagonal) = Transpose(S) adjoint(S::Tridiagonal{<:Real}) = Tridiagonal(S.du, S.d, S.dl) transpose(S::Tridiagonal{<:Number}) = Tridiagonal(S.du, S.d, S.dl) permutedims(T::Tridiagonal) = Tridiagonal(T.du, T.d, T.dl) From 6e5c4e9d760c1efe2778e1c58a0b91dc8ead6496 Mon Sep 17 00:00:00 2001 From: K Pamnany Date: Wed, 9 Aug 2023 12:57:35 -0400 Subject: [PATCH 119/123] RAI: Change task ordering behavior to prioritize older tasks --- base/partr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/partr.jl b/base/partr.jl index 8c95e3668ee74a..3cdcd6914295dc 100644 --- a/base/partr.jl +++ b/base/partr.jl @@ -44,7 +44,7 @@ function multiq_sift_down(heap::taskheap, idx::Int32) child = Int(child) child > length(heap.tasks) && break if isassigned(heap.tasks, child) && - heap.tasks[child].priority < heap.tasks[idx].priority + heap.tasks[child].priority <= heap.tasks[idx].priority t = heap.tasks[idx] heap.tasks[idx] = heap.tasks[child] heap.tasks[child] = t From e322667673d761268bece0106c2ada7f175e5314 Mon Sep 17 00:00:00 2001 From: Nick Robinson Date: Wed, 20 Sep 2023 22:15:00 +0100 Subject: [PATCH 120/123] Add PR template and labels (#62) labeler workflow fixes (#64) * Try fix labeler * Update labeler workflow triggers * fixup! Update labeler workflow triggers --- .github/labeler.yml | 4 ++++ .github/pull_request_template.md | 13 +++++++++++++ .github/workflows/labeler.yml | 17 +++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 .github/labeler.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/labeler.yml diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000000000..46b32f84a77d5b --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,4 @@ +# See https://github.com/actions/labeler +port-to-master: '**' +port-to-v1.10: '**' +port-to-v1.9: '**' diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000000000..b197aeb9adfab1 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ + +## PR Description + +_What does this PR do?_ + +## Checklist + +Requirements for merging: +- [ ] I have opened an issue or PR upstream on JuliaLang/julia: +- [ ] I have removed the `port-to-*` labels that don't apply. diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 00000000000000..2141a906e96cdd --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,17 @@ +# See https://github.com/actions/labeler +name: "Pull Request Labeler" +on: + pull_request_target: + types: + - opened + +jobs: + triage: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v4 + with: + dot: true From 878f6a4bbabb900a933cc25fdbaaa8a52be8f39c Mon Sep 17 00:00:00 2001 From: K Pamnany Date: Sat, 7 Oct 2023 18:30:01 -0400 Subject: [PATCH 121/123] Add heartbeat capability Presence is controlled by a build-time option. Start a separate thread which simply sleeps. When heartbeats are enabled, this thread wakes up at specified intervals to verify that user code is heartbeating as requested and if not, prints task backtraces. Also fixes the call to `maxthreadid` in `generate_precompile.jl`. --- contrib/generate_precompile.jl | 2 +- src/init.c | 4 + src/options.h | 3 + src/threading.c | 221 +++++++++++++++++++++++++++++++++ 4 files changed, 229 insertions(+), 1 deletion(-) diff --git a/contrib/generate_precompile.jl b/contrib/generate_precompile.jl index 92dde676244e4f..9f36e28353c971 100644 --- a/contrib/generate_precompile.jl +++ b/contrib/generate_precompile.jl @@ -4,7 +4,7 @@ @eval Core.Module() begin if Threads.maxthreadid() != 1 - @warn "Running this file with multiple Julia threads may lead to a build error" Threads.maxthreadid() + @warn "Running this file with multiple Julia threads may lead to a build error" Base.Threads.maxthreadid() end if Base.isempty(Base.ARGS) || Base.ARGS[1] !== "0" diff --git a/src/init.c b/src/init.c index 2c1ad618948f85..2b4ebd18fe9ead 100644 --- a/src/init.c +++ b/src/init.c @@ -843,6 +843,8 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel) _finish_julia_init(rel, ptls, ct); } +void jl_init_heartbeat(void); + static NOINLINE void _finish_julia_init(JL_IMAGE_SEARCH rel, jl_ptls_t ptls, jl_task_t *ct) { JL_TIMING(JULIA_INIT, JULIA_INIT); @@ -890,6 +892,8 @@ static NOINLINE void _finish_julia_init(JL_IMAGE_SEARCH rel, jl_ptls_t ptls, jl_ } jl_start_threads(); + jl_init_heartbeat(); + jl_gc_enable(1); if (jl_options.image_file && (!jl_generating_output() || jl_options.incremental) && jl_module_init_order) { diff --git a/src/options.h b/src/options.h index 69b31ea9180080..fc382cd0a0dd6d 100644 --- a/src/options.h +++ b/src/options.h @@ -144,6 +144,9 @@ #define MACHINE_EXCLUSIVE_NAME "JULIA_EXCLUSIVE" #define DEFAULT_MACHINE_EXCLUSIVE 0 +// heartbeats +#define JL_HEARTBEAT_THREAD + // sanitizer defaults --------------------------------------------------------- // Automatically enable MEMDEBUG and KEEP_BODIES for the sanitizers diff --git a/src/threading.c b/src/threading.c index eb76ac579b5389..b78cfc826d836a 100644 --- a/src/threading.c +++ b/src/threading.c @@ -984,6 +984,227 @@ JL_DLLEXPORT int jl_alignment(size_t sz) return jl_gc_alignment(sz); } +// Heartbeat mechanism for Julia's task scheduler +// --- +// Start a thread that does not participate in running Julia's tasks. This +// thread simply sleeps until the heartbeat mechanism is enabled. When +// enabled, the heartbeat thread enters a loop in which it blocks waiting +// for the specified heartbeat interval. If, within that interval, +// `jl_heartbeat()` is *not* called at least once, then the thread calls +// `jl_print_task_backtraces(0)`. + +#ifdef JL_HEARTBEAT_THREAD + +#include + +volatile int heartbeat_enabled; +uv_sem_t heartbeat_on_sem, // jl_heartbeat_enable -> thread + heartbeat_off_sem; // thread -> jl_heartbeat_enable +int heartbeat_interval_s, + n_loss_reports, + reset_reporting_s; +int last_report_s, report_interval_s, n_reported; +_Atomic(int) heartbeats; + +JL_DLLEXPORT void jl_print_task_backtraces(int show_done) JL_NOTSAFEPOINT; +void jl_heartbeat_threadfun(void *arg); + +// start the heartbeat thread with heartbeats disabled +void jl_init_heartbeat(void) +{ + uv_thread_t uvtid; + heartbeat_enabled = 0; + uv_sem_init(&heartbeat_on_sem, 0); + uv_sem_init(&heartbeat_off_sem, 0); + uv_thread_create(&uvtid, jl_heartbeat_threadfun, NULL); + uv_thread_detach(&uvtid); +} + +// enable/disable heartbeats +// heartbeat_s: interval within which jl_heartbeat() must be called +// n_reports: for one heartbeat loss interval, how many times to report +// reset_reporting_after_s: how long to wait after a heartbeat loss +// interval and a return to steady heartbeats, before resetting +// reporting behavior +// +// When disabling heartbeats, the heartbeat thread must wake up, +// find out that heartbeats are now diabled, and reset. For now, we +// handle this by preventing re-enabling of heartbeats until this +// completes. +JL_DLLEXPORT int jl_heartbeat_enable(int heartbeat_s, int n_reports, + int reset_reporting_after_s) +{ + if (heartbeat_s <= 0) { + heartbeat_enabled = 0; + heartbeat_interval_s = n_loss_reports = reset_reporting_s = 0; + } + else { + // must disable before enabling + if (heartbeat_enabled) { + return -1; + } + // heartbeat thread must be ready + if (uv_sem_trywait(&heartbeat_off_sem) != 0) { + return -1; + } + + jl_atomic_store_relaxed(&heartbeats, 0); + heartbeat_interval_s = heartbeat_s; + n_loss_reports = n_reports; + reset_reporting_s = reset_reporting_after_s; + last_report_s = 0; + report_interval_s = heartbeat_interval_s; + heartbeat_enabled = 1; + uv_sem_post(&heartbeat_on_sem); // wake the heartbeat thread + } + return 0; +} + +// heartbeat +JL_DLLEXPORT void jl_heartbeat(void) +{ + jl_atomic_fetch_add(&heartbeats, 1); +} + +// sleep the thread for the specified interval +void sleep_for(int secs, int nsecs) +{ + struct timespec rqtp, rmtp; + rqtp.tv_sec = secs; + rqtp.tv_nsec = nsecs; + rmtp.tv_sec = 0; + rmtp.tv_nsec = 0; + for (; ;) { + // this suspends the thread so we aren't using CPU + if (nanosleep(&rqtp, &rmtp) == 0) { + return; + } + // TODO: else if (errno == EINTR) + // this could be SIGTERM and we should shutdown but how to find out? + rqtp = rmtp; + } +} + +// check for heartbeats and maybe report loss +uint8_t check_heartbeats(uint8_t gc_state) +{ + int hb = jl_atomic_exchange(&heartbeats, 0); + uint64_t curr_s = jl_hrtime() / 1e9; + + if (hb <= 0) { + // we didn't get a heartbeat in the last interval; should we report? + if (n_reported < n_loss_reports && + curr_s - last_report_s >= report_interval_s) { + jl_task_t *ct = jl_current_task; + jl_ptls_t ptls = ct->ptls; + + // exit GC-safe region to report then re-enter + jl_gc_safe_leave(ptls, gc_state); + jl_safe_printf("==== heartbeat loss ====\n"); + jl_print_task_backtraces(0); + gc_state = jl_gc_safe_enter(ptls); + + // we've reported + n_reported++; + + // record the reporting time _after_ the report + last_report_s = jl_hrtime() / 1e9; + + // double the reporting interval up to a maximum + if (report_interval_s < 60 * heartbeat_interval_s) { + report_interval_s *= 2; + } + } + // no heartbeats, don't change reporting state + return gc_state; + } + else { + // we got a heartbeat; reset the report count + n_reported = 0; + } + + // reset the reporting interval only once we're steadily getting + // heartbeats for the requested reset interval + if (curr_s - reset_reporting_s > last_report_s) { + report_interval_s = heartbeat_interval_s; + } + + return gc_state; +} + +// heartbeat thread function +void jl_heartbeat_threadfun(void *arg) +{ + int s, ns = 1e9 - 1, rs; + uint64_t t0, tchb; + + // We need a TLS because backtraces are accumulated into ptls->bt_size + // and ptls->bt_data, so we need to call jl_adopt_thread(). + jl_adopt_thread(); + jl_task_t *ct = jl_current_task; + jl_ptls_t ptls = ct->ptls; + + // Don't hold up GC, this thread doesn't participate. + uint8_t gc_state = jl_gc_safe_enter(ptls); + + for (;;) { + if (!heartbeat_enabled) { + // post the off semaphore to indicate we're ready to enable + uv_sem_post(&heartbeat_off_sem); + + // sleep the thread here; this semaphore is posted in + // jl_heartbeat_enable() + uv_sem_wait(&heartbeat_on_sem); + + // Set the sleep duration. + s = heartbeat_interval_s - 1; + ns = 1e9 - 1; + continue; + } + + // heartbeat is enabled; sleep, waiting for the desired interval + sleep_for(s, ns); + + // if heartbeats were turned off while we were sleeping, reset + if (!heartbeat_enabled) { + continue; + } + + // check if any heartbeats have happened, report as appropriate + t0 = jl_hrtime(); + gc_state = check_heartbeats(gc_state); + tchb = jl_hrtime() - t0; + + // adjust the next sleep duration based on how long the heartbeat + // check took + rs = 1; + while (tchb > 1e9) { + rs++; + tchb -= 1e9; + } + s = heartbeat_interval_s - rs; + ns = 1e9 - tchb; + } +} + +#else // !JL_HEARTBEAT_THREAD + +void jl_init_heartbeat(void) +{ +} + +JL_DLLEXPORT int jl_heartbeat_enable(int heartbeat_s, int n_reports, + int reset_reporting_after_s) +{ + return -1; +} + +JL_DLLEXPORT void jl_heartbeat(void) +{ +} + +#endif // JL_HEARTBEAT_THREAD + #ifdef __cplusplus } #endif From ee2831c077b87c29cb602b2179dac8b54b526364 Mon Sep 17 00:00:00 2001 From: K Pamnany Date: Sun, 12 Nov 2023 17:12:54 -0500 Subject: [PATCH 122/123] Change heartbeat thread controls When enabling heartbeats, the user must specify: - heartbeat_s: jl_heartbeat() must be called at least once every heartbeat_s; if it isn't, a one-line heartbeat loss report is printed - show_tasks_after_n: after these many heartbeat_s have passed without jl_heartbeat() being called, print task backtraces and stop all reporting - reset_after_n: after these many heartbeat_s have passed with jl_heartbeat() being called, print a heartbeats recovered message and reset reporting --- src/threading.c | 95 ++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 49 deletions(-) diff --git a/src/threading.c b/src/threading.c index b78cfc826d836a..c2f55109818d53 100644 --- a/src/threading.c +++ b/src/threading.c @@ -1001,9 +1001,9 @@ volatile int heartbeat_enabled; uv_sem_t heartbeat_on_sem, // jl_heartbeat_enable -> thread heartbeat_off_sem; // thread -> jl_heartbeat_enable int heartbeat_interval_s, - n_loss_reports, - reset_reporting_s; -int last_report_s, report_interval_s, n_reported; + tasks_after_n, + reset_tasks_after_n; +int tasks_showed, n_hbs_missed, n_hbs_recvd; _Atomic(int) heartbeats; JL_DLLEXPORT void jl_print_task_backtraces(int show_done) JL_NOTSAFEPOINT; @@ -1022,21 +1022,19 @@ void jl_init_heartbeat(void) // enable/disable heartbeats // heartbeat_s: interval within which jl_heartbeat() must be called -// n_reports: for one heartbeat loss interval, how many times to report -// reset_reporting_after_s: how long to wait after a heartbeat loss -// interval and a return to steady heartbeats, before resetting -// reporting behavior +// show_tasks_after_n: number of heartbeats missed before printing task backtraces +// reset_after_n: number of heartbeats after which to reset // // When disabling heartbeats, the heartbeat thread must wake up, // find out that heartbeats are now diabled, and reset. For now, we // handle this by preventing re-enabling of heartbeats until this // completes. -JL_DLLEXPORT int jl_heartbeat_enable(int heartbeat_s, int n_reports, - int reset_reporting_after_s) +JL_DLLEXPORT int jl_heartbeat_enable(int heartbeat_s, int show_tasks_after_n, + int reset_after_n) { if (heartbeat_s <= 0) { heartbeat_enabled = 0; - heartbeat_interval_s = n_loss_reports = reset_reporting_s = 0; + heartbeat_interval_s = tasks_after_n = reset_tasks_after_n = 0; } else { // must disable before enabling @@ -1050,10 +1048,11 @@ JL_DLLEXPORT int jl_heartbeat_enable(int heartbeat_s, int n_reports, jl_atomic_store_relaxed(&heartbeats, 0); heartbeat_interval_s = heartbeat_s; - n_loss_reports = n_reports; - reset_reporting_s = reset_reporting_after_s; - last_report_s = 0; - report_interval_s = heartbeat_interval_s; + tasks_after_n = show_tasks_after_n; + reset_tasks_after_n = reset_after_n; + tasks_showed = 0; + n_hbs_missed = 0; + n_hbs_recvd = 0; heartbeat_enabled = 1; uv_sem_post(&heartbeat_on_sem); // wake the heartbeat thread } @@ -1089,44 +1088,42 @@ void sleep_for(int secs, int nsecs) uint8_t check_heartbeats(uint8_t gc_state) { int hb = jl_atomic_exchange(&heartbeats, 0); - uint64_t curr_s = jl_hrtime() / 1e9; if (hb <= 0) { - // we didn't get a heartbeat in the last interval; should we report? - if (n_reported < n_loss_reports && - curr_s - last_report_s >= report_interval_s) { - jl_task_t *ct = jl_current_task; - jl_ptls_t ptls = ct->ptls; - - // exit GC-safe region to report then re-enter - jl_gc_safe_leave(ptls, gc_state); - jl_safe_printf("==== heartbeat loss ====\n"); - jl_print_task_backtraces(0); - gc_state = jl_gc_safe_enter(ptls); - - // we've reported - n_reported++; - - // record the reporting time _after_ the report - last_report_s = jl_hrtime() / 1e9; - - // double the reporting interval up to a maximum - if (report_interval_s < 60 * heartbeat_interval_s) { - report_interval_s *= 2; + // we didn't get a heartbeat + n_hbs_recvd = 0; + n_hbs_missed++; + + // if we've printed task backtraces already, do nothing + if (!tasks_showed) { + // otherwise, at least show this message + jl_safe_printf("==== heartbeat loss (%ds) ====\n", + n_hbs_missed * heartbeat_interval_s); + // if we've missed enough heartbeats, print task backtraces + if (n_hbs_missed >= tasks_after_n) { + jl_task_t *ct = jl_current_task; + jl_ptls_t ptls = ct->ptls; + + // exit GC-safe region to report then re-enter + jl_gc_safe_leave(ptls, gc_state); + jl_print_task_backtraces(0); + gc_state = jl_gc_safe_enter(ptls); + + // we printed task backtraces + tasks_showed = 1; } } - // no heartbeats, don't change reporting state - return gc_state; } else { - // we got a heartbeat; reset the report count - n_reported = 0; - } - - // reset the reporting interval only once we're steadily getting - // heartbeats for the requested reset interval - if (curr_s - reset_reporting_s > last_report_s) { - report_interval_s = heartbeat_interval_s; + // got a heartbeat + n_hbs_recvd++; + // if we'd printed task backtraces, check for reset + if (tasks_showed && n_hbs_recvd >= reset_tasks_after_n) { + tasks_showed = 0; + jl_safe_printf("==== heartbeats recovered (lost for %ds) ====\n", + n_hbs_missed * heartbeat_interval_s); + } + n_hbs_missed = 0; } return gc_state; @@ -1135,7 +1132,7 @@ uint8_t check_heartbeats(uint8_t gc_state) // heartbeat thread function void jl_heartbeat_threadfun(void *arg) { - int s, ns = 1e9 - 1, rs; + int s = 59, ns = 1e9 - 1, rs; uint64_t t0, tchb; // We need a TLS because backtraces are accumulated into ptls->bt_size @@ -1193,8 +1190,8 @@ void jl_init_heartbeat(void) { } -JL_DLLEXPORT int jl_heartbeat_enable(int heartbeat_s, int n_reports, - int reset_reporting_after_s) +JL_DLLEXPORT int jl_heartbeat_enable(int heartbeat_s, int show_tasks_after_n, + int reset_after_n) { return -1; } From 18c0aa9b36550a78b18d07dcca7c336a6dd1cf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Drvo=C5=A1t=C4=9Bp?= Date: Tue, 19 Mar 2024 18:34:21 +0100 Subject: [PATCH 123/123] Add GitHub template and workflows needed on the default branch (#136) --- .github/pull_request_template.md | 1 + .github/workflows/stale.yml | 16 ++++++++++ .../workflows/update-upstream-branches.yml | 29 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 .github/workflows/stale.yml create mode 100644 .github/workflows/update-upstream-branches.yml diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b197aeb9adfab1..7ed825781c53ba 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -11,3 +11,4 @@ _What does this PR do?_ Requirements for merging: - [ ] I have opened an issue or PR upstream on JuliaLang/julia: - [ ] I have removed the `port-to-*` labels that don't apply. +- [ ] I have opened a PR on raicode to test these changes: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000000000..3df20934917536 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,16 @@ +name: "Close stale PRs" +on: + schedule: + - cron: "0 0 * * *" # every night at midnight + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v8 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-pr-message: 'This PR is stale because it has been open 30 days with no activity. Comment or remove stale label, or this PR will be closed in 5 days.' + days-before-stale: 30 + days-before-close: 5 + stale-pr-label: 'stale' diff --git a/.github/workflows/update-upstream-branches.yml b/.github/workflows/update-upstream-branches.yml new file mode 100644 index 00000000000000..242d59bd4edbc6 --- /dev/null +++ b/.github/workflows/update-upstream-branches.yml @@ -0,0 +1,29 @@ +name: "Update upstream branches" +on: + schedule: + - cron: "0 0 * * *" # every night at midnight + workflow_dispatch: + +jobs: + PullUpstream: + runs-on: ubuntu-latest + strategy: + fail-fast: false # run all jobs in the matrix even if one fails + matrix: + branch: + - "master" + - "backports-release-1.10" + - "backports-release-1.9" + steps: + - name: Checkout RAI/julia + uses: actions/checkout@v3 + with: + ref: ${{ matrix.branch }} + - name: Update ${{ matrix.branch }} + run: | + git config --global user.email "julia-engineering@relational.ai" + git config --global user.name "RAI CI (GitHub Action Automation)" + + git remote add upstream https://github.com/JuliaLang/julia + git pull upstream ${{ matrix.branch }} + git push origin ${{ matrix.branch }}