diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index 272c5958bdb0c..32e44919a161e 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -1015,19 +1015,19 @@ function platforms_match(a::AbstractPlatform, b::AbstractPlatform) # Throw an error if `a` and `b` have both set non-default comparison strategies for `k` # and they're not the same strategy. - if a_comp != compare_default && b_comp != compare_default && a_comp != b_comp + if a_comp !== compare_default && b_comp !== compare_default && a_comp !== b_comp throw(ArgumentError("Cannot compare Platform objects with two different non-default comparison strategies for the same key \"$(k)\"")) end # Select the custom comparator, if we have one. comparator = a_comp - if b_comp != compare_default + if b_comp !== compare_default comparator = b_comp end # Call the comparator, passing in which objects requested this comparison (one, the other, or both) # For some comparators this doesn't matter, but for non-symmetrical comparisons, it does. - if !(comparator(ak, bk, a_comp == comparator, b_comp == comparator)::Bool) + if !(comparator(ak, bk, a_comp === comparator, b_comp === comparator)::Bool) return false end end @@ -1073,7 +1073,9 @@ function select_platform(download_info::Dict, platform::AbstractPlatform = HostP # of generally choosing the latest release (e.g. a `libgfortran5` tarball # rather than a `libgfortran3` tarball) p = last(sort(ps, by = p -> triplet(p))) - return download_info[p] + + # @invokelatest here to not get invalidated by new defs of `==(::Function, ::Function)` + return @invokelatest getindex(download_info, p) end # precompiles to reduce latency (see https://github.com/JuliaLang/julia/pull/43990#issuecomment-1025692379) diff --git a/base/channels.jl b/base/channels.jl index aa4d913dcdadd..33365c03e5d3d 100644 --- a/base/channels.jl +++ b/base/channels.jl @@ -183,7 +183,8 @@ Close a channel. An exception (optionally given by `excp`), is thrown by: * [`put!`](@ref) on a closed channel. * [`take!`](@ref) and [`fetch`](@ref) on an empty, closed channel. """ -function close(c::Channel, excp::Exception=closed_exception()) +close(c::Channel) = close(c, closed_exception()) # nospecialize on default arg seems to confuse makedocs +function close(c::Channel, @nospecialize(excp::Exception)) lock(c) try c.excp = excp diff --git a/base/initdefs.jl b/base/initdefs.jl index 89ebecaefbdc4..002984b83dd97 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -353,6 +353,7 @@ end const atexit_hooks = Callable[ () -> Filesystem.temp_cleanup_purge(force=true) ] +const _atexit_hooks_lock = ReentrantLock() """ atexit(f) @@ -374,7 +375,7 @@ calls `exit(n)`, then Julia will exit with the exit code corresponding to the last called exit hook that calls `exit(n)`. (Because exit hooks are called in LIFO order, "last called" is equivalent to "first registered".) """ -atexit(f::Function) = (pushfirst!(atexit_hooks, f); nothing) +atexit(f::Function) = Base.@lock _atexit_hooks_lock (pushfirst!(atexit_hooks, f); nothing) function _atexit(exitcode::Cint) while !isempty(atexit_hooks) diff --git a/base/loading.jl b/base/loading.jl index cb60c6cd27117..cfed2091b6d4b 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -413,7 +413,9 @@ function locate_package_env(pkg::PkgId, stopenv::Union{String, Nothing}=nothing) @goto done end end - stopenv == env && @goto done + if !(loading_extension || precompiling_extension) + stopenv == env && @goto done + end end else for env in load_path() @@ -428,7 +430,9 @@ function locate_package_env(pkg::PkgId, stopenv::Union{String, Nothing}=nothing) path = entry_path(path, pkg.name) @goto done end - stopenv == env && break + if !(loading_extension || precompiling_extension) + stopenv == env && break + end end # Allow loading of stdlibs if the name/uuid are given # e.g. if they have been explicitly added to the project/manifest @@ -619,6 +623,24 @@ function manifest_deps_get(env::String, where::PkgId, name::String)::Union{Nothi pkg_uuid = explicit_project_deps_get(project_file, name) return PkgId(pkg_uuid, name) end + d = parsed_toml(project_file) + exts = get(d, "extensions", nothing)::Union{Dict{String, Any}, Nothing} + if exts !== nothing + # 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... + weakdeps = get(d, "weakdeps", nothing)::Union{Dict{String, Any}, Nothing} + if weakdeps !== nothing + wuuid = get(weakdeps, name, nothing)::Union{String, Nothing} + if wuuid !== nothing + return PkgId(UUID(wuuid), name) + end + end + # ... and they can load same deps as the project itself + mby_uuid = explicit_project_deps_get(project_file, name) + mby_uuid === nothing || return PkgId(mby_uuid, name) + end + end # look for manifest file and `where` stanza return explicit_manifest_deps_get(project_file, where, name) elseif project_file @@ -636,6 +658,8 @@ function manifest_uuid_path(env::String, pkg::PkgId)::Union{Nothing,String,Missi # if `pkg` matches the project, return the project itself return project_file_path(project_file) end + mby_ext = project_file_ext_path(project_file, pkg.name) + mby_ext === nothing || return mby_ext # look for manifest file and `where` stanza return explicit_manifest_uuid_path(project_file, pkg) elseif project_file @@ -645,6 +669,25 @@ function manifest_uuid_path(env::String, pkg::PkgId)::Union{Nothing,String,Missi return nothing end + +function find_ext_path(project_path::String, extname::String) + extfiledir = joinpath(project_path, "ext", extname, extname * ".jl") + isfile(extfiledir) && return extfiledir + return joinpath(project_path, "ext", extname * ".jl") +end + +function project_file_ext_path(project_file::String, name::String) + d = parsed_toml(project_file) + p = project_file_path(project_file) + exts = get(d, "extensions", nothing)::Union{Dict{String, Any}, Nothing} + if exts !== nothing + if name in keys(exts) + return find_ext_path(p, name) + end + end + return nothing +end + # find project file's top-level UUID entry (or nothing) function project_file_name_uuid(project_file::String, name::String)::PkgId d = parsed_toml(project_file) @@ -747,10 +790,10 @@ function explicit_project_deps_get(project_file::String, name::String)::Union{No return nothing end -function is_v1_format_manifest(raw_manifest::Dict) +function is_v1_format_manifest(raw_manifest::Dict{String}) if haskey(raw_manifest, "manifest_format") mf = raw_manifest["manifest_format"] - if mf isa Dict && haskey(mf, "uuid") + if mf isa Dict{String} && haskey(mf, "uuid") # the off-chance where an old format manifest has a dep called "manifest_format" return true end @@ -876,9 +919,7 @@ function explicit_manifest_uuid_path(project_file::String, pkg::PkgId)::Union{No error("failed to find source of parent package: \"$name\"") end p = normpath(dirname(parent_path), "..") - extfiledir = joinpath(p, "ext", pkg.name, pkg.name * ".jl") - isfile(extfiledir) && return extfiledir - return joinpath(p, "ext", pkg.name * ".jl") + return find_ext_path(p, pkg.name) end end end @@ -1126,6 +1167,20 @@ end function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missing} project_file = env_project_file(env) if project_file isa String + # Look in project for extensions to insert + proj_pkg = project_file_name_uuid(project_file, pkg.name) + if pkg == proj_pkg + d_proj = parsed_toml(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 + end + + # Now look in manifest manifest_file = project_file_manifest_path(project_file) manifest_file === nothing && return d = get_deps(parsed_toml(manifest_file)) @@ -1144,7 +1199,7 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi return _insert_extension_triggers(pkg, extensions, weakdeps) end - d_weakdeps = Dict{String, String}() + d_weakdeps = Dict{String, Any}() for (dep_name, entries) in d dep_name in weakdeps || continue entries::Vector{Any} @@ -1164,8 +1219,9 @@ 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}) - for (ext::String, triggers::Union{String, Vector{String}}) in extensions +function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}, weakdeps::Dict{String, Any}) + for (ext, triggers) in extensions + triggers = triggers::Union{String, Vector{String}} triggers isa String && (triggers = [triggers]) id = PkgId(uuid5(parent.uuid, ext), ext) if id in keys(EXT_PRIMED) || haskey(Base.loaded_modules, id) @@ -1190,6 +1246,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, <:An end loading_extension::Bool = false +precompiling_extension::Bool = false function run_extension_callbacks(extid::ExtensionId) assert_havelock(require_lock) succeeded = try @@ -1217,30 +1274,8 @@ function run_extension_callbacks(pkgid::PkgId) extids === nothing && return for extid in extids if extid.ntriggers > 0 - # It is possible that pkgid was loaded in an environment - # below the one of the parent. This will cause a load failure when the - # pkg ext tries to load the triggers. Therefore, check this first - # before loading the pkg ext. - pkgenv = identify_package_env(extid.id, pkgid.name) - ext_not_allowed_load = false - if pkgenv === nothing - ext_not_allowed_load = true - else - pkg, env = pkgenv - path = locate_package(pkg, env) - if path === nothing - ext_not_allowed_load = true - end - end - if ext_not_allowed_load - @debug "Extension $(extid.id.name) of $(extid.parentid.name) will not be loaded \ - since $(pkgid.name) loaded in environment lower in load path" - # indicate extid is expected to fail - extid.ntriggers *= -1 - else - # indicate pkgid is loaded - extid.ntriggers -= 1 - end + # indicate pkgid is loaded + extid.ntriggers -= 1 end if extid.ntriggers < 0 # indicate pkgid is loaded @@ -2066,6 +2101,7 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, output_o:: # write data over stdin to avoid the (unlikely) case of exceeding max command line size write(io.in, """ empty!(Base.EXT_DORMITORY) # If we have a custom sysimage with `EXT_DORMITORY` prepopulated + Base.precompiling_extension = $(loading_extension) Base.include_package_for_output($(pkg_str(pkg)), $(repr(abspath(input))), $(repr(depot_path)), $(repr(dl_load_path)), $(repr(load_path)), $deps, $(repr(source_path(nothing)))) """) diff --git a/base/mpfr.jl b/base/mpfr.jl index a07606f2aa81e..47c4c37e43f5d 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -1028,7 +1028,7 @@ function _string(x::BigFloat, fmt::String)::String isfinite(x) || return string(Float64(x)) _prettify_bigfloat(string_mpfr(x, fmt)) end -_string(x::BigFloat) = _string(x, "%.Re") +_string(x::BigFloat) = _string(x, "%Re") _string(x::BigFloat, k::Integer) = _string(x, "%.$(k)Re") string(b::BigFloat) = _string(b) diff --git a/base/range.jl b/base/range.jl index 9d12ae1001784..a2803c2cf6a56 100644 --- a/base/range.jl +++ b/base/range.jl @@ -1093,7 +1093,7 @@ show(io::IO, r::AbstractRange) = print(io, repr(first(r)), ':', repr(step(r)), ' show(io::IO, r::UnitRange) = print(io, repr(first(r)), ':', repr(last(r))) show(io::IO, r::OneTo) = print(io, "Base.OneTo(", r.stop, ")") function show(io::IO, r::StepRangeLen) - if step(r) != 0 + if !iszero(step(r)) print(io, repr(first(r)), ':', repr(step(r)), ':', repr(last(r))) else # ugly temporary printing, to avoid 0:0:0 etc. diff --git a/base/reinterpretarray.jl b/base/reinterpretarray.jl index 1fe0788a1739a..ebcb743729160 100644 --- a/base/reinterpretarray.jl +++ b/base/reinterpretarray.jl @@ -725,11 +725,18 @@ end @assume_effects :total function array_subpadding(S, T) lcm_size = lcm(sizeof(S), sizeof(T)) s, t = CyclePadding(S), CyclePadding(T) - isempty(t) && return true - isempty(s) && return false checked_size = 0 - ps, sstate = iterate(s) # use of Stateful harms inference and makes this vulnerable to invalidation - pad, tstate = iterate(t) + # use of Stateful harms inference and makes this vulnerable to invalidation + (pad, tstate) = let + it = iterate(t) + it === nothing && return true + it + end + (ps, sstate) = let + it = iterate(s) + it === nothing && return false + it + end while checked_size < lcm_size while true # See if there's corresponding padding in S diff --git a/cli/loader_lib.c b/cli/loader_lib.c index 295fa94a93bbb..2043473a9dad5 100644 --- a/cli/loader_lib.c +++ b/cli/loader_lib.c @@ -329,6 +329,8 @@ static char *libstdcxxprobe(void) free(path); return NULL; } + // Ensure that `path` is zero-terminated. + path[pathlen] = '\0'; return path; } } diff --git a/contrib/generate_precompile.jl b/contrib/generate_precompile.jl index 0a0941aa97651..11a9c1b552061 100644 --- a/contrib/generate_precompile.jl +++ b/contrib/generate_precompile.jl @@ -34,6 +34,8 @@ precompile(Tuple{typeof(push!), Vector{Function}, Function}) # miscellaneous precompile(Tuple{typeof(Base.require), Base.PkgId}) precompile(Tuple{typeof(Base.recursive_prefs_merge), Base.Dict{String, Any}}) +precompile(Tuple{typeof(Base.hashindex), Tuple{Base.PkgId, Nothing}, Int64}) +precompile(Tuple{typeof(Base.hashindex), Tuple{Base.PkgId, String}, Int64}) precompile(Tuple{typeof(isassigned), Core.SimpleVector, Int}) precompile(Tuple{typeof(getindex), Core.SimpleVector, Int}) precompile(Tuple{typeof(Base.Experimental.register_error_hint), Any, Type}) diff --git a/deps/blastrampoline.version b/deps/blastrampoline.version index faf2ecd0229c1..616300377e3e6 100644 --- a/deps/blastrampoline.version +++ b/deps/blastrampoline.version @@ -2,6 +2,6 @@ BLASTRAMPOLINE_JLL_NAME := libblastrampoline ## source build -BLASTRAMPOLINE_VER := 5.7.0 -BLASTRAMPOLINE_BRANCH=v5.7.0 -BLASTRAMPOLINE_SHA1=2272604bfb10b9e8a3ae5f1a4569899b99251a65 +BLASTRAMPOLINE_VER := 5.8.0 +BLASTRAMPOLINE_BRANCH=v5.8.0 +BLASTRAMPOLINE_SHA1=81316155d4838392e8462a92bcac3eebe9acd0c7 diff --git a/deps/checksums/Pkg-3ca88658d2bc23d877cc5829cdab2aa4dfdae564.tar.gz/md5 b/deps/checksums/Pkg-3ca88658d2bc23d877cc5829cdab2aa4dfdae564.tar.gz/md5 deleted file mode 100644 index b44f2085978fc..0000000000000 --- a/deps/checksums/Pkg-3ca88658d2bc23d877cc5829cdab2aa4dfdae564.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -22c8f1b80f9123b66a53ac3b8e193e8b diff --git a/deps/checksums/Pkg-3ca88658d2bc23d877cc5829cdab2aa4dfdae564.tar.gz/sha512 b/deps/checksums/Pkg-3ca88658d2bc23d877cc5829cdab2aa4dfdae564.tar.gz/sha512 deleted file mode 100644 index e100fcd8db0e9..0000000000000 --- a/deps/checksums/Pkg-3ca88658d2bc23d877cc5829cdab2aa4dfdae564.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -8b39baf6fac1426f3872c4abfeaba3ed8a5e8c005e7957003a928562088dcd22298f420b18d482936b9909678e3b88e2ec8c25456615277dd732d6ef799e4f24 diff --git a/deps/checksums/Pkg-3fa06b9f96fc8a180f9285447584c84e4d8d8278.tar.gz/md5 b/deps/checksums/Pkg-3fa06b9f96fc8a180f9285447584c84e4d8d8278.tar.gz/md5 new file mode 100644 index 0000000000000..1202ff6a2e2f9 --- /dev/null +++ b/deps/checksums/Pkg-3fa06b9f96fc8a180f9285447584c84e4d8d8278.tar.gz/md5 @@ -0,0 +1 @@ +203b01484d8550eeb8e08d18099b56e0 diff --git a/deps/checksums/Pkg-3fa06b9f96fc8a180f9285447584c84e4d8d8278.tar.gz/sha512 b/deps/checksums/Pkg-3fa06b9f96fc8a180f9285447584c84e4d8d8278.tar.gz/sha512 new file mode 100644 index 0000000000000..9fbec4bfd1ffd --- /dev/null +++ b/deps/checksums/Pkg-3fa06b9f96fc8a180f9285447584c84e4d8d8278.tar.gz/sha512 @@ -0,0 +1 @@ +e0818e7542a360668119cc7bc9f57a136f5fdcb0d0786bb02a98eceaf7d993790bd81c60915857baff84a3ec97a39eadb735d666bf12666e24fcad28035eddc0 diff --git a/deps/checksums/blastrampoline b/deps/checksums/blastrampoline index 38cb44236eb87..011b0f6e4704d 100644 --- a/deps/checksums/blastrampoline +++ b/deps/checksums/blastrampoline @@ -1,34 +1,34 @@ -blastrampoline-d00e6ca235bb747faae4c9f3a297016cae6959ed.tar.gz/md5/b49ebb89b7f9a1eaf85217c4a9dac744 -blastrampoline-d00e6ca235bb747faae4c9f3a297016cae6959ed.tar.gz/sha512/ac3a767fdb03cc0a9e12ae6df31229e6c5050f2b7ccaee47ef14d6bef34b37a20c2d79956b73bf74d72af1f01a3d1316931db264e1b00cb6cadd57fb842e6f2f -libblastrampoline.v5.7.0+0.aarch64-apple-darwin.tar.gz/md5/a28837b9838fef2b3831de3278ec7949 -libblastrampoline.v5.7.0+0.aarch64-apple-darwin.tar.gz/sha512/111ac2fe5f8f8102f2f7c9e9e6aa1d1a12d2db941238c949ff8e64b30335e8b2f6ecce0d5f577879c231eb839c06e259302b709f3d34e94a97047bfa984222f6 -libblastrampoline.v5.7.0+0.aarch64-linux-gnu.tar.gz/md5/3792c0a4443c0e2ebe88bea180a3beb1 -libblastrampoline.v5.7.0+0.aarch64-linux-gnu.tar.gz/sha512/d5ce0f9bb47f80d04e13bf90e48d6ab942cf7fd79b582f1496a83a1eca0db29e01315efa52bcb1099466a9037926a7a2cf3135395ac1322544cd7150b9687d7b -libblastrampoline.v5.7.0+0.aarch64-linux-musl.tar.gz/md5/45622c514e744282f996bacc26ca231b -libblastrampoline.v5.7.0+0.aarch64-linux-musl.tar.gz/sha512/790f7cf4d5f11be246c617694a7d617435627229f52c52ee49037c3650707ac1c0d8631b713d5b32ac76f97b19b18eacc1645fd0aecc296167439bfbb0514b5c -libblastrampoline.v5.7.0+0.armv6l-linux-gnueabihf.tar.gz/md5/f945fe9ee8472db8fe27409b7c028a57 -libblastrampoline.v5.7.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/96876374813acc9ae249ef3c7140e1e0eac9259a0b5c567e11843a17a9d5db4fe759e873d0e2c1dd944e9f9104b885a09cd8977634eaa7c24e580d391f23b75f -libblastrampoline.v5.7.0+0.armv6l-linux-musleabihf.tar.gz/md5/902b8ae755be3087002969377b0332d8 -libblastrampoline.v5.7.0+0.armv6l-linux-musleabihf.tar.gz/sha512/bda692349136d1b540e00458ba9ed689e762e9acdc60d0cc59203cefcdcc59611f3883f5050bf9186019003be726f3d798138dcf5929a64a4d1fab314c84e7a4 -libblastrampoline.v5.7.0+0.armv7l-linux-gnueabihf.tar.gz/md5/95058aaed39a095b6f50b04b335b1ff6 -libblastrampoline.v5.7.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/bb963ac3d9fd57e656e33177c01ae6cd0cfbe63826f79cd3ae04c38641c5a82fe9cae29a38f1a725ca11d93dd143aeb6a5213f26ceedb622f9ebb5c156b9ceac -libblastrampoline.v5.7.0+0.armv7l-linux-musleabihf.tar.gz/md5/f66178bcb8e159e7b022c54a917cd895 -libblastrampoline.v5.7.0+0.armv7l-linux-musleabihf.tar.gz/sha512/c92b0fe3e3f486d2f559d5f34fdcf59bf4db764b28dc1146a2559f236de48057832ba1b766d69bd5ffe91f6b0d13238e6ee3eb70d4508947b3235672cba60d6f -libblastrampoline.v5.7.0+0.i686-linux-gnu.tar.gz/md5/33bb177a7928a80ef888b51ff39eb724 -libblastrampoline.v5.7.0+0.i686-linux-gnu.tar.gz/sha512/c63c1511213ca89a540db2b7e8cbfae52e6433292b59a7f652ed28f2ad01603ece480ab3c3bb8860598def5c3a994dd0132fc0bf7f070efd458e7e9bbebb1118 -libblastrampoline.v5.7.0+0.i686-linux-musl.tar.gz/md5/65472af1f7b69695470c65eea92e237d -libblastrampoline.v5.7.0+0.i686-linux-musl.tar.gz/sha512/6e16059c68e19447aa6b37854ce7200ae7c7ecd4f016c5fcd120d4ad960377bd4b86ace7470277b785b61d68a915b5476568d876ea510b50a8bb7146a33ee431 -libblastrampoline.v5.7.0+0.i686-w64-mingw32.tar.gz/md5/0a945591dda93017836cdcc87095863a -libblastrampoline.v5.7.0+0.i686-w64-mingw32.tar.gz/sha512/26376cefbe8891907a2f6ee506edc9cb95289df52eaad3ac39135eade5486879da5733019d437dcfba6c286007a29a43b2aabdcc436db893910f6b2730517f12 -libblastrampoline.v5.7.0+0.powerpc64le-linux-gnu.tar.gz/md5/2d29aff294807c0b857adee62dbce7f5 -libblastrampoline.v5.7.0+0.powerpc64le-linux-gnu.tar.gz/sha512/414cc2971bbc7e635b7d1d68aa545ff23568dd7722b8fdd990439c0c55e4dc63420afaf191633fbcf54205fc11edb01fa7d5d4a712b8951775dcdd500f135231 -libblastrampoline.v5.7.0+0.x86_64-apple-darwin.tar.gz/md5/21beb51d448bd22e4608a16b3f4fde05 -libblastrampoline.v5.7.0+0.x86_64-apple-darwin.tar.gz/sha512/620ba64d93ef416e483f813617aa313957282d8361f920b5444702fa911ff0051d1f8a8814b5fa0b082fd4dc77d96cb8b763937c786959bbc97cbb6131617152 -libblastrampoline.v5.7.0+0.x86_64-linux-gnu.tar.gz/md5/43a9eb58e79131d9a8594a42c5b15c5f -libblastrampoline.v5.7.0+0.x86_64-linux-gnu.tar.gz/sha512/5b8dddd742a7742eef14025a859251d605b34a61de3e07ff696c168a88462602c35c5b3680da072e28a8bedc89df5b5ae622be61a5b0203000f9439558d423d9 -libblastrampoline.v5.7.0+0.x86_64-linux-musl.tar.gz/md5/5790c157871d03fcb8c14063303bfcf8 -libblastrampoline.v5.7.0+0.x86_64-linux-musl.tar.gz/sha512/8f82de757b66559cdcd8127946b50c1c5b479149966d53881bdae7c7b536a7c79a1b331d04425aeb57d47fabeb2946985edab23cc94e049240e1925320f03795 -libblastrampoline.v5.7.0+0.x86_64-unknown-freebsd.tar.gz/md5/bb676e6bc64ed1be85f95443e4366eca -libblastrampoline.v5.7.0+0.x86_64-unknown-freebsd.tar.gz/sha512/77ba2fb295f2765cd64ca7d00ee92230c467e056b1441eea63470dcb3491481174956b7058950a7fc2d7dad4b245283dca907b2dea96c8fe1b0e27e4375c0be4 -libblastrampoline.v5.7.0+0.x86_64-w64-mingw32.tar.gz/md5/58ab9512505a6b3eb2f7f2f2bf9a55cf -libblastrampoline.v5.7.0+0.x86_64-w64-mingw32.tar.gz/sha512/a58a7be8ef3ea958591c1cc9d9192efa08bb2aeb0de4cbd1e3f23ea57aa2b8f6048ab4db6bce4f9724a9f81f0e0356e66b884763ead5b309cb38bab9ea475e7f +blastrampoline-81316155d4838392e8462a92bcac3eebe9acd0c7.tar.gz/md5/0478361eac783b99002b1ad985182f05 +blastrampoline-81316155d4838392e8462a92bcac3eebe9acd0c7.tar.gz/sha512/2489ce5770a9861889a2d07e61440ba4f233a92efd4a3544747f83320e0e7a229a8fe01553d99f5f1d98713316f2506daf0adb7d024a46e32b3de1bb2966d637 +libblastrampoline.v5.8.0+0.aarch64-apple-darwin.tar.gz/md5/a28837b9838fef2b3831de3278ec7949 +libblastrampoline.v5.8.0+0.aarch64-apple-darwin.tar.gz/sha512/111ac2fe5f8f8102f2f7c9e9e6aa1d1a12d2db941238c949ff8e64b30335e8b2f6ecce0d5f577879c231eb839c06e259302b709f3d34e94a97047bfa984222f6 +libblastrampoline.v5.8.0+0.aarch64-linux-gnu.tar.gz/md5/9e781a026e03118df81347fb90f10d45 +libblastrampoline.v5.8.0+0.aarch64-linux-gnu.tar.gz/sha512/89469f32a666efd46437351a8fb16758c35e5aecc563d202b480c10ddf9fa5350a5a321076b79b0a1a07ec2cea0b73aa5c28979cc382a198fa96cca0b5899d25 +libblastrampoline.v5.8.0+0.aarch64-linux-musl.tar.gz/md5/b7acda2fdd157bbb183d0dd33643beef +libblastrampoline.v5.8.0+0.aarch64-linux-musl.tar.gz/sha512/cf4125a47334fe2ec0d5a4b11624b12e1366ec031500218f680ad5a53152b9d752c0c02a0b92d0e07f3eb21f2f8f58d0c587438a4869a72197bbd5e91531369d +libblastrampoline.v5.8.0+0.armv6l-linux-gnueabihf.tar.gz/md5/eafabd99fb1287d495acb8efb8091fde +libblastrampoline.v5.8.0+0.armv6l-linux-gnueabihf.tar.gz/sha512/63ff4e6bc400fa8ee713a1c5ae4af0a8e152d49860c6f5e94a17e426ad9f780d41cc0f84d33c75ea5347af1a53f07fc012798d603b6a94ea39f37cfd651a0719 +libblastrampoline.v5.8.0+0.armv6l-linux-musleabihf.tar.gz/md5/9788f74b375ef6b84c16c080f2be5bdd +libblastrampoline.v5.8.0+0.armv6l-linux-musleabihf.tar.gz/sha512/f00ebf794927404e2294a2fbb759b1e3e57836c7f683525fac0b2ac570da2c75904e43f154cf76fce310a624f9b35fbd40e6c7757882bb6f30db790f4221a543 +libblastrampoline.v5.8.0+0.armv7l-linux-gnueabihf.tar.gz/md5/4492bace63d8274d68ecdaa735e47e99 +libblastrampoline.v5.8.0+0.armv7l-linux-gnueabihf.tar.gz/sha512/8868283e6c5224b80145fdfd17f13f713053ba94e49c170f38f0cbf9f794185d7dec9c107ce65dc76121d3ac5b21d2f3857f619d8279bede86a906230ff59a71 +libblastrampoline.v5.8.0+0.armv7l-linux-musleabihf.tar.gz/md5/d66b6ed1d4e5f6a130f36791063e651d +libblastrampoline.v5.8.0+0.armv7l-linux-musleabihf.tar.gz/sha512/414ad07574a6e9aa670bbfea13eaea11da13129c9ccb4193cad708014c31493ff10ff427558b90cb16040fa64c8a325c2e375e3310c39fb37bb3e7fdb6a72a5f +libblastrampoline.v5.8.0+0.i686-linux-gnu.tar.gz/md5/595199a3a01174cfa4d9ce3407bf30dc +libblastrampoline.v5.8.0+0.i686-linux-gnu.tar.gz/sha512/02c3b0c3c0a411d5090a081f3bbbe38aaae40eaa5fe63d0690e0582e233cd9ce76483922557d4f65dc457e29a4e84d86ee5af20a60b082aec7bec4ca8607c1ca +libblastrampoline.v5.8.0+0.i686-linux-musl.tar.gz/md5/5832d0044842cb84f4e1e1b0a04b8205 +libblastrampoline.v5.8.0+0.i686-linux-musl.tar.gz/sha512/d28954d0feef6a33fa0bfeb59acb68821222d36a4e353eaf41936ee2c9aace719c2d0f0b0f080eafe2baecc67a29de4cacc0446aac776bbb615c4426d35c9c8f +libblastrampoline.v5.8.0+0.i686-w64-mingw32.tar.gz/md5/89c07640b6c7ed719199b0cd0a570961 +libblastrampoline.v5.8.0+0.i686-w64-mingw32.tar.gz/sha512/71241e83501ed473af0bf60a3223075e22a48788fdcf0ad5b2932861c89ec0741c61bf6a04c8a26e68b2f39d360b6009a79ea2502b5cccf28249738e7796be89 +libblastrampoline.v5.8.0+0.powerpc64le-linux-gnu.tar.gz/md5/5f76f5c6a88c0caaa6419ba212f8cb94 +libblastrampoline.v5.8.0+0.powerpc64le-linux-gnu.tar.gz/sha512/785071e682075b2cebd992394e66169f4ee2db3a8e23affb88dc05d9abf55f49d597b2a7400a13c83ad106ad825b5ee666b01f8625e51aec267132573273991e +libblastrampoline.v5.8.0+0.x86_64-apple-darwin.tar.gz/md5/21beb51d448bd22e4608a16b3f4fde05 +libblastrampoline.v5.8.0+0.x86_64-apple-darwin.tar.gz/sha512/620ba64d93ef416e483f813617aa313957282d8361f920b5444702fa911ff0051d1f8a8814b5fa0b082fd4dc77d96cb8b763937c786959bbc97cbb6131617152 +libblastrampoline.v5.8.0+0.x86_64-linux-gnu.tar.gz/md5/14c1045ba4d400f490ddea5343a46f04 +libblastrampoline.v5.8.0+0.x86_64-linux-gnu.tar.gz/sha512/0fdae83f4df93b28951521cf426736367f568c1e76fb68eea42b045cc9a288b6836abb3206a6d61e4f88adcf198553e911c45231aecb0f552e06de28eb3bec54 +libblastrampoline.v5.8.0+0.x86_64-linux-musl.tar.gz/md5/59b110676fcb2fcfdcf670a5d435d555 +libblastrampoline.v5.8.0+0.x86_64-linux-musl.tar.gz/sha512/57a5022e9fabc0637a29f3c32f6180cb4f6a90282191232e299df6cea5265b535e4a0af4fde15c8fe80e5a59edea0fae96dd3a510f5720ecd78e85a2a9ffbfe0 +libblastrampoline.v5.8.0+0.x86_64-unknown-freebsd.tar.gz/md5/cb1c14b4f8754561c5eaf8502582f09a +libblastrampoline.v5.8.0+0.x86_64-unknown-freebsd.tar.gz/sha512/d3b19a2a9b3dc674119590d920a2e99705de823e7d01a210485b31f8b1ce59253c4a70f2d8fb967f7fa05efb6ac376d94e79ffc6848607a366b2f0caa58b4208 +libblastrampoline.v5.8.0+0.x86_64-w64-mingw32.tar.gz/md5/34fdc53745245887f968f420b2f02ed9 +libblastrampoline.v5.8.0+0.x86_64-w64-mingw32.tar.gz/sha512/bbf478736b7bd57b340ccd5b6744d526a7a95fc524d30fdf9af6e9d79285641be26fae5f9e5302d71a5be76b05c379e969a829e259d8100ba9c6ce202b632b3d diff --git a/doc/src/base/parallel.md b/doc/src/base/parallel.md index ee84f4b8b445d..c9f24429fd0e5 100644 --- a/doc/src/base/parallel.md +++ b/doc/src/base/parallel.md @@ -26,8 +26,6 @@ Base.schedule ## [Synchronization](@id lib-task-sync) -## Synchronization - ```@docs Base.errormonitor Base.@sync diff --git a/doc/src/manual/calling-c-and-fortran-code.md b/doc/src/manual/calling-c-and-fortran-code.md index 0ebed7db009c9..9f655017e490e 100644 --- a/doc/src/manual/calling-c-and-fortran-code.md +++ b/doc/src/manual/calling-c-and-fortran-code.md @@ -1118,9 +1118,7 @@ For more details on how to pass callbacks to C libraries, see this [blog post](h ## C++ -For direct C++ interfacing, see the [Cxx](https://github.com/Keno/Cxx.jl) package. For tools to create C++ -bindings, see the [CxxWrap](https://github.com/JuliaInterop/CxxWrap.jl) package. - +For tools to create C++ bindings, see the [CxxWrap](https://github.com/JuliaInterop/CxxWrap.jl) package. [^1]: Non-library function calls in both C and Julia can be inlined and thus may have diff --git a/doc/src/manual/embedding.md b/doc/src/manual/embedding.md index d384880728e45..b32c6c6838ba5 100644 --- a/doc/src/manual/embedding.md +++ b/doc/src/manual/embedding.md @@ -6,7 +6,8 @@ calling Julia functions from C code. This can be used to integrate Julia code in C/C++ project, without the need to rewrite everything in C/C++. Julia has a C API to make this possible. As almost all programming languages have some way to call C functions, the Julia C API can also be used to build further language bridges (e.g. calling Julia from -Python or C#). +Python, Rust or C#). Even though Rust and C++ can use the C embedding API directly, both +have packages helping with it, for C++ [Jluna](https://github.com/Clemapfel/jluna) is useful. ## High-Level Embedding diff --git a/src/codegen.cpp b/src/codegen.cpp index 462e9c0fb93ef..bd024b791ce94 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7739,8 +7739,15 @@ static jl_llvm_functions_t Instruction &prologue_end = ctx.builder.GetInsertBlock()->back(); + // step 11a. For top-level code, load the world age + if (toplevel && !ctx.is_opaque_closure) { + LoadInst *load_world = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), + prepare_global_in(jl_Module, jlgetworld_global), Align(sizeof(size_t))); + load_world->setOrdering(AtomicOrdering::Acquire); + ctx.builder.CreateAlignedStore(load_world, world_age_field, Align(sizeof(size_t))); + } - // step 11. Do codegen in control flow order + // step 11b. Do codegen in control flow order std::vector workstack; std::map BB; std::map come_from_bb; @@ -8063,13 +8070,6 @@ static jl_llvm_functions_t ctx.builder.SetInsertPoint(tryblk); } else { - if (!jl_is_method(ctx.linfo->def.method) && !ctx.is_opaque_closure) { - // TODO: inference is invalid if this has any effect (which it often does) - LoadInst *world = ctx.builder.CreateAlignedLoad(getSizeTy(ctx.builder.getContext()), - prepare_global_in(jl_Module, jlgetworld_global), Align(sizeof(size_t))); - world->setOrdering(AtomicOrdering::Acquire); - ctx.builder.CreateAlignedStore(world, world_age_field, Align(sizeof(size_t))); - } emit_stmtpos(ctx, stmt, cursor); mallocVisitStmt(debuginfoloc, nullptr); } @@ -8295,12 +8295,12 @@ static jl_llvm_functions_t } // step 12. Perform any delayed instantiations - if (ctx.debug_enabled) { - bool in_prologue = true; - for (auto &BB : *ctx.f) { - for (auto &I : BB) { - CallBase *call = dyn_cast(&I); - if (call && !I.getDebugLoc()) { + bool in_prologue = true; + for (auto &BB : *ctx.f) { + for (auto &I : BB) { + CallBase *call = dyn_cast(&I); + if (call) { + if (ctx.debug_enabled && !I.getDebugLoc()) { // LLVM Verifier: inlinable function call in a function with debug info must have a !dbg location // make sure that anything we attempt to call has some inlining info, just in case optimization messed up // (except if we know that it is an intrinsic used in our prologue, which should never have its own debug subprogram) @@ -8309,12 +8309,24 @@ static jl_llvm_functions_t I.setDebugLoc(topdebugloc); } } - if (&I == &prologue_end) - in_prologue = false; + if (toplevel && !ctx.is_opaque_closure && !in_prologue) { + // we're at toplevel; insert an atomic barrier between every instruction + // TODO: inference is invalid if this has any effect (which it often does) + LoadInst *load_world = new LoadInst(getSizeTy(ctx.builder.getContext()), + prepare_global_in(jl_Module, jlgetworld_global), Twine(), + /*isVolatile*/false, Align(sizeof(size_t)), /*insertBefore*/&I); + load_world->setOrdering(AtomicOrdering::Acquire); + StoreInst *store_world = new StoreInst(load_world, world_age_field, + /*isVolatile*/false, Align(sizeof(size_t)), /*insertBefore*/&I); + (void)store_world; + } } + if (&I == &prologue_end) + in_prologue = false; } - dbuilder.finalize(); } + if (ctx.debug_enabled) + dbuilder.finalize(); if (ctx.vaSlot > 0) { // remove VA allocation if we never referenced it diff --git a/src/gf.c b/src/gf.c index cdbf2c724b514..33849dd5aa387 100644 --- a/src/gf.c +++ b/src/gf.c @@ -3599,7 +3599,7 @@ static jl_value_t *ml_matches(jl_methtable_t *mt, // now look for a third method m3 outside of this ambiguity group that fully resolves this intersection size_t k; for (k = agid; k > 0; k--) { - jl_method_match_t *matc3 = (jl_method_match_t*)jl_array_ptr_ref(env.t, k); + jl_method_match_t *matc3 = (jl_method_match_t*)jl_array_ptr_ref(env.t, k - 1); jl_method_t *m3 = matc3->method; if ((jl_subtype(ti, m3->sig) || (isect2 && jl_subtype(isect2, m3->sig))) && jl_type_morespecific((jl_value_t*)m3->sig, (jl_value_t*)m->sig) diff --git a/src/init.c b/src/init.c index 89f4153ff1538..522f16041d566 100644 --- a/src/init.c +++ b/src/init.c @@ -733,6 +733,11 @@ JL_DLLEXPORT void julia_init(JL_IMAGE_SEARCH rel) jl_init_intrinsic_properties(); jl_page_size = jl_getpagesize(); + + // Important offset for external codegen. + jl_task_gcstack_offset = offsetof(jl_task_t, gcstack); + jl_task_ptls_offset = offsetof(jl_task_t, ptls); + jl_prep_sanitizers(); void *stack_lo, *stack_hi; jl_init_stack_limits(1, &stack_lo, &stack_hi); diff --git a/src/jl_exported_data.inc b/src/jl_exported_data.inc index 6f0671ef0d6f7..fee57ed60dd7a 100644 --- a/src/jl_exported_data.inc +++ b/src/jl_exported_data.inc @@ -133,5 +133,7 @@ XX(jl_n_threadpools, int) \ XX(jl_n_threads, _Atomic(int)) \ XX(jl_options, jl_options_t) \ + XX(jl_task_gcstack_offset, int) \ + XX(jl_task_ptls_offset, int) \ // end of file diff --git a/src/julia.h b/src/julia.h index e39a8d66cacd3..ea83eaad9570c 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1969,6 +1969,9 @@ JL_DLLEXPORT void JL_NORETURN jl_no_exc_handler(jl_value_t *e, jl_task_t *ct); JL_DLLEXPORT JL_CONST_FUNC jl_gcframe_t **(jl_get_pgcstack)(void) JL_GLOBALLY_ROOTED JL_NOTSAFEPOINT; #define jl_current_task (container_of(jl_get_pgcstack(), jl_task_t, gcstack)) +extern JL_DLLIMPORT int jl_task_gcstack_offset; +extern JL_DLLIMPORT int jl_task_ptls_offset; + #include "julia_locks.h" // requires jl_task_t definition JL_DLLEXPORT void jl_enter_handler(jl_handler_t *eh); diff --git a/src/llvm-julia-licm.cpp b/src/llvm-julia-licm.cpp index d641d61ca126b..87a804c8f4995 100644 --- a/src/llvm-julia-licm.cpp +++ b/src/llvm-julia-licm.cpp @@ -51,13 +51,14 @@ static void eraseInstruction(Instruction &I, //Stolen and modified from LICM.cpp static void moveInstructionBefore(Instruction &I, Instruction &Dest, MemorySSAUpdater &MSSAU, - ScalarEvolution *SE) { + ScalarEvolution *SE, + MemorySSA::InsertionPlace Place = MemorySSA::BeforeTerminator) { I.moveBefore(&Dest); if (MSSAU.getMemorySSA()) if (MemoryUseOrDef *OldMemAcc = cast_or_null( MSSAU.getMemorySSA()->getMemoryAccess(&I))) MSSAU.moveToPlace(OldMemAcc, Dest.getParent(), - MemorySSA::BeforeTerminator); + Place); if (SE) SE->forgetValue(&I); } @@ -127,7 +128,6 @@ struct JuliaLICMPassLegacy : public LoopPass { getLoopAnalysisUsage(AU); } }; - struct JuliaLICM : public JuliaPassContext { function_ref GetDT; function_ref GetLI; @@ -228,7 +228,7 @@ struct JuliaLICM : public JuliaPassContext { continue; } ++SunkPreserveEnd; - moveInstructionBefore(*call, *exit_pts[0], MSSAU, SE); + moveInstructionBefore(*call, *exit_pts[0], MSSAU, SE, MemorySSA::Beginning); for (unsigned i = 1; i < exit_pts.size(); i++) { // Clone exit auto CI = CallInst::Create(call, {}, exit_pts[i]); @@ -276,6 +276,19 @@ struct JuliaLICM : public JuliaPassContext { if (valid) { ++HoistedAllocation; moveInstructionBefore(*call, *preheader->getTerminator(), MSSAU, SE); + IRBuilder<> builder(preheader->getTerminator()); + builder.SetCurrentDebugLocation(call->getDebugLoc()); + auto obj_i8 = builder.CreateBitCast(call, Type::getInt8PtrTy(call->getContext(), call->getType()->getPointerAddressSpace())); + // Note that this alignment is assuming the GC allocates at least pointer-aligned memory + auto align = Align(DL.getPointerSize(0)); + auto clear_obj = builder.CreateMemSet(obj_i8, ConstantInt::get(Type::getInt8Ty(call->getContext()), 0), call->getArgOperand(1), align); + if (MSSAU.getMemorySSA()) { + auto alloc_mdef = MSSAU.getMemorySSA()->getMemoryAccess(call); + assert(isa(alloc_mdef) && "Expected alloc to be associated with a memory def!"); + auto clear_mdef = MSSAU.createMemoryAccessAfter(clear_obj, nullptr, alloc_mdef); + assert(isa(clear_mdef) && "Expected memset to be associated with a memory def!"); + (void) clear_mdef; + } changed = true; } } @@ -331,6 +344,10 @@ PreservedAnalyses JuliaLICMPass::run(Loop &L, LoopAnalysisManager &AM, }; auto juliaLICM = JuliaLICM(GetDT, GetLI, GetMSSA, GetSE); if (juliaLICM.runOnLoop(&L)) { +#ifdef JL_DEBUG_BUILD + if (AR.MSSA) + AR.MSSA->verifyMemorySSA(); +#endif auto preserved = getLoopPassPreservedAnalyses(); preserved.preserveSet(); preserved.preserve(); diff --git a/src/llvm-remove-addrspaces.cpp b/src/llvm-remove-addrspaces.cpp index 1cc09018958af..9559ae5303794 100644 --- a/src/llvm-remove-addrspaces.cpp +++ b/src/llvm-remove-addrspaces.cpp @@ -356,11 +356,9 @@ bool removeAddrspaces(Module &M, AddrspaceRemapFunction ASRemapper) // Similarly, copy over and rewrite function bodies for (Function *F : Functions) { - if (F->isDeclaration()) - continue; - Function *NF = cast(VMap[F]); LLVM_DEBUG(dbgs() << "Processing function " << NF->getName() << "\n"); + // we also need this to run for declarations, or attributes won't be copied Function::arg_iterator DestI = NF->arg_begin(); for (Function::const_arg_iterator I = F->arg_begin(); I != F->arg_end(); @@ -385,8 +383,7 @@ bool removeAddrspaces(Module &M, AddrspaceRemapFunction ASRemapper) &TypeRemapper, &Materializer); - // CloneFunctionInto unconditionally copies the attributes from F to NF, - // without considering e.g. the byval attribute type. + // Update function attributes that contain types AttributeList Attrs = F->getAttributes(); LLVMContext &C = F->getContext(); for (unsigned i = 0; i < Attrs.getNumAttrSets(); ++i) { @@ -411,9 +408,6 @@ bool removeAddrspaces(Module &M, AddrspaceRemapFunction ASRemapper) } NF->setAttributes(Attrs); - if (F->hasPersonalityFn()) - NF->setPersonalityFn(MapValue(F->getPersonalityFn(), VMap)); - copyComdat(NF, F); RemoveNoopAddrSpaceCasts(NF); diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index 898eec579c0d9..2532546702545 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -178,7 +178,7 @@ static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited, int depth = stack->len; *bp = (void*)((char*)HT_NOTFOUND + 4 + depth); // preliminarily mark as in-progress size_t i = 0, n = jl_array_len(mi->backedges); - int cycle = 0; + int cycle = depth; while (i < n) { jl_method_instance_t *be; i = get_next_edge(mi->backedges, i, NULL, &be); @@ -194,7 +194,7 @@ static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited, assert(cycle); } } - if (!found && cycle && cycle != depth) + if (!found && cycle != depth) return cycle + 3; // If we are the top of the current cycle, now mark all other parts of // our cycle with what we found. @@ -983,6 +983,7 @@ static int jl_verify_graph_edge(size_t *maxvalids2_data, jl_array_t *edges, size assert(jl_typeis((jl_value_t*)callee_ids, jl_array_int32_type)); int32_t *idxs = (int32_t*)jl_array_data(callee_ids); size_t i, n = jl_array_len(callee_ids); + cycle = depth; for (i = idxs[0] + 1; i < n; i++) { int32_t childidx = idxs[i]; int child_cycle = jl_verify_graph_edge(maxvalids2_data, edges, childidx, visited, stack); @@ -1001,7 +1002,7 @@ static int jl_verify_graph_edge(size_t *maxvalids2_data, jl_array_t *edges, size } } size_t max_valid = maxvalids2_data[idx]; - if (max_valid != 0 && cycle && cycle != depth) + if (max_valid != 0 && cycle != depth) return cycle; // If we are the top of the current cycle, now mark all other parts of // our cycle with what we found. diff --git a/src/subtype.c b/src/subtype.c index fedaa6bcfabb9..9d1028af9c8a7 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1386,7 +1386,8 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t // Once limit_slow == 1, also skip it if // 1) `forall_exists_subtype` return false // 2) the left `Union` looks big - if (noRmore || (limit_slow && (count > 3 || !sub))) + // NOTE: altered to fix issue 49857 + if (noRmore || limit_slow) e->Runions.more = oldRmore; } else { diff --git a/stdlib/Artifacts/src/Artifacts.jl b/stdlib/Artifacts/src/Artifacts.jl index a9554c95f3151..47812fb993428 100644 --- a/stdlib/Artifacts/src/Artifacts.jl +++ b/stdlib/Artifacts/src/Artifacts.jl @@ -56,6 +56,23 @@ function artifacts_dirs(args...) end end +# Recursive function, let's not make this a closure because it then has to +# be boxed. +function parse_mapping(mapping::String, name::String, override_file::String) + if !isabspath(mapping) && !isempty(mapping) + mapping = tryparse(Base.SHA1, mapping) + if mapping === nothing + @error("Invalid override in '$(override_file)': entry '$(name)' must map to an absolute path or SHA1 hash!") + end + end + return mapping +end +function parse_mapping(mapping::Dict, name::String, override_file::String) + return Dict(k => parse_mapping(v, name, override_file) for (k, v) in mapping) +end +# Fallthrough for invalid Overrides.toml files +parse_mapping(mapping, name::String, override_file::String) = nothing + """ ARTIFACT_OVERRIDES @@ -103,24 +120,9 @@ function load_overrides(;force::Bool = false)::Dict{Symbol, Any} # Load the toml file depot_override_dict = parse_toml(override_file) - function parse_mapping(mapping::String, name::String) - if !isabspath(mapping) && !isempty(mapping) - mapping = tryparse(Base.SHA1, mapping) - if mapping === nothing - @error("Invalid override in '$(override_file)': entry '$(name)' must map to an absolute path or SHA1 hash!") - end - end - return mapping - end - function parse_mapping(mapping::Dict, name::String) - return Dict(k => parse_mapping(v, name) for (k, v) in mapping) - end - # Fallthrough for invalid Overrides.toml files - parse_mapping(mapping, name::String) = nothing - for (k, mapping) in depot_override_dict # First, parse the mapping. Is it an absolute path, a valid SHA1-hash, or neither? - mapping = parse_mapping(mapping, k) + mapping = parse_mapping(mapping, k, override_file) if mapping === nothing @error("Invalid override in '$(override_file)': failed to parse entry `$(k)`") continue @@ -743,5 +745,8 @@ artifact_slash_lookup(name::AbstractString, artifact_dict::Dict, artifacts_toml: precompile(load_artifacts_toml, (String,)) precompile(NamedTuple{(:pkg_uuid,)}, (Tuple{Base.UUID},)) precompile(Core.kwfunc(load_artifacts_toml), (NamedTuple{(:pkg_uuid,), Tuple{Base.UUID}}, typeof(load_artifacts_toml), String)) +precompile(parse_mapping, (String, String, String)) +precompile(parse_mapping, (Dict{String, Any}, String, String)) + end # module Artifacts diff --git a/stdlib/LinearAlgebra/src/lapack.jl b/stdlib/LinearAlgebra/src/lapack.jl index 9edaf77440750..bef018307fcf7 100644 --- a/stdlib/LinearAlgebra/src/lapack.jl +++ b/stdlib/LinearAlgebra/src/lapack.jl @@ -1010,6 +1010,9 @@ for (gels, gesv, getrs, getri, elty) in if n != size(B, 1) throw(DimensionMismatch("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")) + end nrhs = size(B, 2) info = Ref{BlasInt}() ccall((@blasfunc($getrs), libblastrampoline), Cvoid, diff --git a/stdlib/LinearAlgebra/test/lapack.jl b/stdlib/LinearAlgebra/test/lapack.jl index e0e75f0a88413..f8baceebaff52 100644 --- a/stdlib/LinearAlgebra/test/lapack.jl +++ b/stdlib/LinearAlgebra/test/lapack.jl @@ -709,4 +709,13 @@ a = zeros(2,0), zeros(0) @test LinearAlgebra.LAPACK.geqrf!(a...) === a @test LinearAlgebra.LAPACK.gerqf!(a...) === a +# Issue #49489: https://github.com/JuliaLang/julia/issues/49489 +# Dimension mismatch between A and ipiv causes segfaults +@testset "issue #49489" begin + A = randn(23,23) + b = randn(23) + ipiv = collect(1:20) + @test_throws DimensionMismatch LinearAlgebra.LAPACK.getrs!('N', A, ipiv, b) +end + end # module TestLAPACK diff --git a/stdlib/OpenBLAS_jll/Project.toml b/stdlib/OpenBLAS_jll/Project.toml index c117bf553bb73..130d7a85d7f7a 100644 --- a/stdlib/OpenBLAS_jll/Project.toml +++ b/stdlib/OpenBLAS_jll/Project.toml @@ -3,6 +3,7 @@ uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" version = "0.3.21+4" [deps] +# See note in `src/OpenBLAS_jll.jl` about this dependency. CompilerSupportLibraries_jll = "e66e0078-7015-5450-92f7-15fbd957f2ae" Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" diff --git a/stdlib/OpenBLAS_jll/src/OpenBLAS_jll.jl b/stdlib/OpenBLAS_jll/src/OpenBLAS_jll.jl index 2684a6b635cb4..96d16ca1263ef 100644 --- a/stdlib/OpenBLAS_jll/src/OpenBLAS_jll.jl +++ b/stdlib/OpenBLAS_jll/src/OpenBLAS_jll.jl @@ -2,7 +2,17 @@ ## dummy stub for https://github.com/JuliaBinaryWrappers/OpenBLAS_jll.jl baremodule OpenBLAS_jll -using Base, Libdl, CompilerSupportLibraries_jll, Base.BinaryPlatforms +using Base, Libdl, Base.BinaryPlatforms + +# We are explicitly NOT loading this at runtime, as it contains `libgomp` +# which conflicts with `libiomp5`, breaking things like MKL. In the future, +# we hope to transition to a JLL interface that provides a more granular +# interface than eagerly dlopen'ing all libraries provided in the JLL +# which will eliminate issues like this, where we avoid loading a JLL +# because we don't want to load a library that we don't even use yet. +# using CompilerSupportLibraries_jll +# Because of this however, we have to manually load the libraries we +# _do_ care about, namely libgfortran Base.Experimental.@compiler_options compile=min optimize=0 infer=false const PATH_list = String[] @@ -25,10 +35,13 @@ end if Sys.iswindows() const libopenblas = "libopenblas$(libsuffix).dll" + const _libgfortran = string("libgfortran-", libgfortran_version(HostPlatform()).major, ".dll") elseif Sys.isapple() const libopenblas = "@rpath/libopenblas$(libsuffix).dylib" + const _libgfortran = string("@rpath/", "libgfortran.", libgfortran_version(HostPlatform()).major, ".dylib") else const libopenblas = "libopenblas$(libsuffix).so" + const _libgfortran = string("libgfortran.so.", libgfortran_version(HostPlatform()).major) end function __init__() @@ -50,6 +63,10 @@ function __init__() ENV["OPENBLAS_DEFAULT_NUM_THREADS"] = "1" end + # As mentioned above, we are sneaking this in here so that we don't have to + # depend on CSL_jll and load _all_ of its libraries. + dlopen(_libgfortran) + global libopenblas_handle = dlopen(libopenblas) global libopenblas_path = dlpath(libopenblas_handle) global artifact_dir = dirname(Sys.BINDIR) diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 601753a0a04e2..d0e5ef33678c9 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = release-1.9 -PKG_SHA1 = 3ca88658d2bc23d877cc5829cdab2aa4dfdae564 +PKG_SHA1 = 3fa06b9f96fc8a180f9285447584c84e4d8d8278 PKG_GIT_URL := https://github.com/JuliaLang/Pkg.jl.git PKG_TAR_URL = https://api.github.com/repos/JuliaLang/Pkg.jl/tarball/$1 diff --git a/stdlib/Profile/src/Profile.jl b/stdlib/Profile/src/Profile.jl index ba2d7390a214c..6dd2a12205b66 100644 --- a/stdlib/Profile/src/Profile.jl +++ b/stdlib/Profile/src/Profile.jl @@ -264,11 +264,15 @@ function print(io::IO, elseif Sys.iswindows() && in(groupby, [:thread, [:task, :thread], [:thread, :task]]) @warn "Profiling on windows is limited to the main thread. Other threads have not been sampled and will not show in the report" end - any_nosamples = false - println(io, "Overhead ╎ [+additional indent] Count File:Line; Function") - println(io, "=========================================================") + any_nosamples = true + if format === :tree + Base.print(io, "Overhead ╎ [+additional indent] Count File:Line; Function\n") + Base.print(io, "=========================================================\n") + end if groupby == [:task, :thread] - for taskid in intersect(get_task_ids(data), tasks) + taskids = intersect(get_task_ids(data), tasks) + isempty(taskids) && (any_nosamples = true) + for taskid in taskids threadids = intersect(get_thread_ids(data, taskid), threads) if length(threadids) == 0 any_nosamples = true @@ -284,7 +288,9 @@ function print(io::IO, end end elseif groupby == [:thread, :task] - for threadid in intersect(get_thread_ids(data), threads) + threadids = intersect(get_thread_ids(data), threads) + isempty(threadids) && (any_nosamples = true) + for threadid in threadids taskids = intersect(get_task_ids(data, threadid), tasks) if length(taskids) == 0 any_nosamples = true @@ -301,7 +307,9 @@ function print(io::IO, end elseif groupby === :task threads = 1:typemax(Int) - for taskid in intersect(get_task_ids(data), tasks) + taskids = intersect(get_task_ids(data), tasks) + isempty(taskids) && (any_nosamples = true) + for taskid in taskids printstyled(io, "Task $(Base.repr(taskid)) "; bold=true, color=Base.debug_color()) nosamples = print(io, data, lidict, pf, format, threads, taskid, true) nosamples && (any_nosamples = true) @@ -309,7 +317,9 @@ function print(io::IO, end elseif groupby === :thread tasks = 1:typemax(UInt) - for threadid in intersect(get_thread_ids(data), threads) + threadids = intersect(get_thread_ids(data), threads) + isempty(threadids) && (any_nosamples = true) + for threadid in threadids printstyled(io, "Thread $threadid "; bold=true, color=Base.info_color()) nosamples = print(io, data, lidict, pf, format, threadid, tasks, true) nosamples && (any_nosamples = true) @@ -424,6 +434,7 @@ function getdict!(dict::LineInfoDict, data::Vector{UInt}) n_unique_ips = length(unique_ips) n_unique_ips == 0 && return dict iplookups = similar(unique_ips, Vector{StackFrame}) + sort!(unique_ips) # help each thread to get a disjoint set of libraries, as much if possible @sync for indexes_part in Iterators.partition(eachindex(unique_ips), div(n_unique_ips, Threads.threadpoolsize(), RoundUp)) Threads.@spawn begin for i in indexes_part @@ -690,7 +701,7 @@ function parse_flat(::Type{T}, data::Vector{UInt64}, lidict::Union{LineInfoDict, m = Int[] lilist_idx = Dict{T, Int}() recursive = Set{T}() - first = true + leaf = 0 totalshots = 0 startframe = length(data) skip = false @@ -714,12 +725,16 @@ function parse_flat(::Type{T}, data::Vector{UInt64}, lidict::Union{LineInfoDict, skip = false totalshots += 1 empty!(recursive) - first = true + if leaf != 0 + m[leaf] += 1 + end + leaf = 0 startframe = i elseif !skip frames = lidict[ip] nframes = (frames isa Vector ? length(frames) : 1) - for j = 1:nframes + # the last lookup is the non-inlined root frame, the first is the inlined leaf frame + for j = nframes:-1:1 frame = (frames isa Vector ? frames[j] : frames) !C && frame.from_c && continue key = (T === UInt64 ? ip : frame) @@ -733,10 +748,7 @@ function parse_flat(::Type{T}, data::Vector{UInt64}, lidict::Union{LineInfoDict, push!(recursive, key) n[idx] += 1 end - if first - m[idx] += 1 - first = false - end + leaf = idx end end end @@ -747,30 +759,31 @@ end function flat(io::IO, data::Vector{UInt64}, lidict::Union{LineInfoDict, LineInfoFlatDict}, cols::Int, fmt::ProfileFormat, threads::Union{Int,AbstractVector{Int}}, tasks::Union{UInt,AbstractVector{UInt}}, is_subsection::Bool) lilist, n, m, totalshots, nsleeping = parse_flat(fmt.combine ? StackFrame : UInt64, data, lidict, fmt.C, threads, tasks) + if false # optional: drop the "non-interpretable" ones + keep = map(frame -> frame != UNKNOWN && frame.line != 0, lilist) + lilist = lilist[keep] + n = n[keep] + m = m[keep] + end util_perc = (1 - (nsleeping / totalshots)) * 100 + filenamemap = Dict{Symbol,String}() if isempty(lilist) if is_subsection Base.print(io, "Total snapshots: ") printstyled(io, "$(totalshots)", color=Base.warn_color()) - Base.println(io, " (", round(Int, util_perc), "% utilization)") + Base.print(io, ". Utilization: ", round(Int, util_perc), "%\n") else warning_empty() end return true end - if false # optional: drop the "non-interpretable" ones - keep = map(frame -> frame != UNKNOWN && frame.line != 0, lilist) - lilist = lilist[keep] - n = n[keep] - m = m[keep] - end - filenamemap = Dict{Symbol,String}() - print_flat(io, lilist, n, m, cols, filenamemap, fmt) - Base.print(io, "Total snapshots: ", totalshots, " (", round(Int, util_perc), "% utilization") + is_subsection || print_flat(io, lilist, n, m, cols, filenamemap, fmt) + Base.print(io, "Total snapshots: ", totalshots, ". Utilization: ", round(Int, util_perc), "%") if is_subsection - println(io, ")") + println(io) + print_flat(io, lilist, n, m, cols, filenamemap, fmt) else - println(io, " across all threads and tasks. Use the `groupby` kwarg to break down by thread and/or task)") + Base.print(io, " across all threads and tasks. Use the `groupby` kwarg to break down by thread and/or task.\n") end return false end @@ -1091,8 +1104,8 @@ function print_tree(io::IO, bt::StackFrameTree{T}, cols::Int, fmt::ProfileFormat filenamemap = Dict{Symbol,String}() worklist = [(bt, 0, 0, "")] if !is_subsection - println(io, "Overhead ╎ [+additional indent] Count File:Line; Function") - println(io, "=========================================================") + Base.print(io, "Overhead ╎ [+additional indent] Count File:Line; Function\n") + Base.print(io, "=========================================================\n") end while !isempty(worklist) (bt, level, noisefloor, str) = popfirst!(worklist) @@ -1138,24 +1151,23 @@ function tree(io::IO, data::Vector{UInt64}, lidict::Union{LineInfoFlatDict, Line root, nsleeping = tree!(StackFrameTree{UInt64}(), data, lidict, fmt.C, fmt.recur, threads, tasks) end util_perc = (1 - (nsleeping / root.count)) * 100 - !is_subsection && print_tree(io, root, cols, fmt, is_subsection) + is_subsection || print_tree(io, root, cols, fmt, is_subsection) if isempty(root.down) if is_subsection Base.print(io, "Total snapshots: ") printstyled(io, "$(root.count)", color=Base.warn_color()) - Base.println(io, ". Utilization: ", round(Int, util_perc), "%") + Base.print(io, ". Utilization: ", round(Int, util_perc), "%\n") else warning_empty() end return true - else - Base.print(io, "Total snapshots: ", root.count, ". Utilization: ", round(Int, util_perc), "%") end + Base.print(io, "Total snapshots: ", root.count, ". Utilization: ", round(Int, util_perc), "%") if is_subsection - println(io) + Base.println(io) print_tree(io, root, cols, fmt, is_subsection) else - println(io, " across all threads and tasks. Use the `groupby` kwarg to break down by thread and/or task") + Base.print(io, " across all threads and tasks. Use the `groupby` kwarg to break down by thread and/or task.\n") end return false end diff --git a/stdlib/REPL/docs/src/index.md b/stdlib/REPL/docs/src/index.md index 8e9e19228ea3d..eab4f4174e365 100644 --- a/stdlib/REPL/docs/src/index.md +++ b/stdlib/REPL/docs/src/index.md @@ -623,6 +623,7 @@ It is possible to get an interface which is similar to the IPython REPL and the ```julia atreplinit() do repl + @eval import REPL if !isdefined(repl, :interface) repl.interface = REPL.setup_interface(repl) end @@ -645,6 +646,13 @@ Out[3]: Dict{Int64, Any} with 2 entries: 1 => 8 ``` +!!! note + Since all outputs from previous REPL evaluations are saved in the `Out` variable, one should be careful if they are returning many + large in-memory objects like arrays, since they will be protected from garbage collection so long as a reference to them remains in + `Out`. If you need to remove references to objects in `Out`, you can clear the entire history it stores with `empty!(Out)`, or clear + an individual entry with `Out[n] = nothing`. + + ## TerminalMenus TerminalMenus is a submodule of the Julia REPL and enables small, low-profile interactive menus in the terminal. diff --git a/stdlib/libblastrampoline_jll/Project.toml b/stdlib/libblastrampoline_jll/Project.toml index 42d49010019c3..4699baa7dad23 100644 --- a/stdlib/libblastrampoline_jll/Project.toml +++ b/stdlib/libblastrampoline_jll/Project.toml @@ -1,6 +1,6 @@ name = "libblastrampoline_jll" uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" -version = "5.7.0+0" +version = "5.8.0+0" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/test/channels.jl b/test/channels.jl index 36b89cdadcafe..e6b85e93b0226 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -628,3 +628,20 @@ end @test n_avail(c) == 0 end end + +# Issue #49507: stackoverflow in type inference caused by close(::Channel, ::Exception) +@testset "close(::Channel, ::StackOverflowError)" begin + ch = let result = Channel() + foo() = try + foo() + catch e; + close(result, e) + end + + foo() # This shouldn't fail with an internal stackoverflow error in inference. + + result + end + + @test (try take!(ch) catch e; e; end) isa StackOverflowError +end diff --git a/test/llvmpasses/julia-licm.ll b/test/llvmpasses/julia-licm.ll index 0c7cf9a640ef7..fd2a446da9677 100644 --- a/test/llvmpasses/julia-licm.ll +++ b/test/llvmpasses/julia-licm.ll @@ -25,13 +25,15 @@ L4: ; preds = %top %current_task112 = getelementptr inbounds {}**, {}*** %1, i64 -12 %current_task1 = bitcast {}*** %current_task112 to {}** ; CHECK: %3 = call noalias nonnull {} addrspace(10)* @julia.gc_alloc_obj({}** nonnull %current_task1, i64 8, {} addrspace(10)* @tag) + ; CHECK-NEXT: %4 = bitcast {} addrspace(10)* %3 to i8 addrspace(10)* + ; CHECK-NEXT: call void @llvm.memset.p10i8.i64(i8 addrspace(10)* align {{[0-9]+}} %4, i8 0, i64 8, i1 false) ; CHECK-NEXT: br label %L22 br label %L22 L22: ; preds = %L4, %L22 %value_phi5 = phi i64 [ 1, %L4 ], [ %5, %L22 ] - ; CHECK: %value_phi5 = phi i64 [ 1, %L4 ], [ %5, %L22 ] - ; CHECK-NEXT %4 = bitcast {} addrspace(10)* %3 to i64 addrspace(10)* + ; CHECK: %value_phi5 = phi i64 [ 1, %L4 ], [ %6, %L22 ] + ; CHECK-NEXT %5 = bitcast {} addrspace(10)* %3 to i64 addrspace(10)* %3 = call noalias nonnull {} addrspace(10)* @julia.gc_alloc_obj({}** nonnull %current_task1, i64 8, {} addrspace(10)* @tag) #1 %4 = bitcast {} addrspace(10)* %3 to i64 addrspace(10)* store i64 %value_phi5, i64 addrspace(10)* %4, align 8, !tbaa !2 diff --git a/test/llvmpasses/remove-addrspaces.ll b/test/llvmpasses/remove-addrspaces.ll index 77a8a5e815057..a748b3843bacb 100644 --- a/test/llvmpasses/remove-addrspaces.ll +++ b/test/llvmpasses/remove-addrspaces.ll @@ -47,7 +47,7 @@ top: %list = type { i64, %list* } ; COM: There's nothing to remove in this function; but remove-addrspaces shouldn't crash. -define i64 @sum.linked.list() #0 { +define i64 @sum.linked.list() { ; CHECK-LABEL: @sum.linked.list top: %a = alloca %list @@ -109,3 +109,9 @@ define void @byval_type([1 x {} addrspace(10)*] addrspace(11)* byval([1 x {} add ; CHECK: define void @byval_type([1 x {}*]* byval([1 x {}*]) %0) ret void } + + +; COM: check that function attributes are preserved on declarations too +declare void @convergent_function() #0 +attributes #0 = { convergent } +; CHECK: attributes #0 = { convergent } diff --git a/test/loading.jl b/test/loading.jl index 05f376f3f51a0..f14cf8d07563f 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -1032,7 +1032,6 @@ end cmd = gen_extension_cmd(compile) cmd = addenv(cmd, "JULIA_LOAD_PATH" => proj) cmd = pipeline(cmd; stdout, stderr) - @show compile @test success(cmd) end @@ -1054,8 +1053,6 @@ end envs = [joinpath(@__DIR__, "project", "Extensions", "EnvWithHasExtensionsv2"), joinpath(@__DIR__, "project", "Extensions", "EnvWithHasExtensions")] cmd = addenv(```$(Base.julia_cmd()) --startup-file=no -e ' begin - - push!(empty!(DEPOT_PATH), '$(repr(depot_path))') using HasExtensions using ExtDep @@ -1065,6 +1062,22 @@ end ' ```, "JULIA_LOAD_PATH" => join(envs, sep)) @test success(cmd) + + test_ext_proj = """ + begin + using HasExtensions + using ExtDep + 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") + end + """ + for compile in (`--compiled-modules=no`, ``) + cmd_proj_ext = `$(Base.julia_cmd()) $compile --startup-file=no -e $test_ext_proj` + proj = joinpath(@__DIR__, "project", "Extensions") + cmd_proj_ext = addenv(cmd_proj_ext, "JULIA_LOAD_PATH" => join([joinpath(proj, "HasExtensions.jl"), joinpath(proj, "EnvWithDeps")], sep)) + run(cmd_proj_ext) + end finally try rm(depot_path, force=true, recursive=true) diff --git a/test/precompile.jl b/test/precompile.jl index 006c0ae06ced4..1477001386f6b 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -383,7 +383,7 @@ precompile_test_harness(false) do dir Dict(let m = Base.root_module(Base, s) Base.PkgId(m) => Base.module_build_id(m) end for s in - [:ArgTools, :Artifacts, :Base64, :CompilerSupportLibraries_jll, :CRC32c, :Dates, + [:ArgTools, :Artifacts, :Base64, :CRC32c, :Dates, :Distributed, :Downloads, :FileWatching, :Future, :InteractiveUtils, :libblastrampoline_jll, :LazyArtifacts, :LibCURL, :LibCURL_jll, :LibGit2, :Libdl, :LinearAlgebra, :Logging, :Markdown, :Mmap, :MozillaCACerts_jll, :NetworkOptions, :OpenBLAS_jll, :Pkg, :Printf, diff --git a/test/project/Extensions/EnvWithDeps/Manifest.toml b/test/project/Extensions/EnvWithDeps/Manifest.toml new file mode 100644 index 0000000000000..85ff259f0a4d5 --- /dev/null +++ b/test/project/Extensions/EnvWithDeps/Manifest.toml @@ -0,0 +1,21 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.9.0-rc3" +manifest_format = "2.0" +project_hash = "ec25ff8df3a5e2212a173c3de2c7d716cc47cd36" + +[[deps.ExtDep]] +deps = ["SomePackage"] +path = "../ExtDep.jl" +uuid = "fa069be4-f60b-4d4c-8b95-f8008775090c" +version = "0.1.0" + +[[deps.ExtDep2]] +path = "../ExtDep2" +uuid = "55982ee5-2ad5-4c40-8cfe-5e9e1b01500d" +version = "0.1.0" + +[[deps.SomePackage]] +path = "../SomePackage" +uuid = "678608ae-7bb3-42c7-98b1-82102067a3d8" +version = "0.1.0" diff --git a/test/project/Extensions/EnvWithDeps/Project.toml b/test/project/Extensions/EnvWithDeps/Project.toml new file mode 100644 index 0000000000000..cf020b56fc2e8 --- /dev/null +++ b/test/project/Extensions/EnvWithDeps/Project.toml @@ -0,0 +1,4 @@ +[deps] +ExtDep = "fa069be4-f60b-4d4c-8b95-f8008775090c" +ExtDep2 = "55982ee5-2ad5-4c40-8cfe-5e9e1b01500d" +SomePackage = "678608ae-7bb3-42c7-98b1-82102067a3d8" diff --git a/test/ranges.jl b/test/ranges.jl index c4cd4664f5f95..0439a626dcac5 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -2392,3 +2392,16 @@ end @test test_firstindex(StepRange{Union{Int64,Int128},Int}(Int64(1), 1, Int128(1))) @test test_firstindex(StepRange{Union{Int64,Int128},Int}(Int64(1), 1, Int128(0))) end + +@testset "PR 49516" begin + struct PR49516 <: Signed + n::Int + end + PR49516(f::PR49516) = f + Base.:*(x::Integer, f::PR49516) = PR49516(*(x, f.n)) + Base.:+(f1::PR49516, f2::PR49516) = PR49516(+(f1.n, f2.n)) + Base.show(io::IO, f::PR49516) = print(io, "PR49516(", f.n, ")") + + srl = StepRangeLen(PR49516(1), PR49516(2), 10) + @test sprint(show, srl) == "PR49516(1):PR49516(2):PR49516(19)" +end diff --git a/test/subtype.jl b/test/subtype.jl index 4629eac5a9429..925c719031ee2 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -2272,8 +2272,9 @@ abstract type P47654{A} end @test_broken typeintersect(Tuple{Vector{VT}, Vector{VT}} where {N1, VT<:AbstractVector{N1}}, Tuple{Vector{VN} where {N, VN<:AbstractVector{N}}, Vector{Vector{Float64}}}) !== Union{} #issue 40865 - @test Tuple{Set{Ref{Int}}, Set{Ref{Int}}} <: Tuple{Set{KV}, Set{K}} where {K,KV<:Union{K,Ref{K}}} - @test Tuple{Set{Val{Int}}, Set{Val{Int}}} <: Tuple{Set{KV}, Set{K}} where {K,KV<:Union{K,Val{K}}} + #broken due to 49857 and 49875 + @test_broken Tuple{Set{Ref{Int}}, Set{Ref{Int}}} <: Tuple{Set{KV}, Set{K}} where {K,KV<:Union{K,Ref{K}}} + @test_broken Tuple{Set{Val{Int}}, Set{Val{Int}}} <: Tuple{Set{KV}, Set{K}} where {K,KV<:Union{K,Val{K}}} #issue 39099 A = Tuple{Tuple{Int, Int, Vararg{Int, N}}, Tuple{Int, Vararg{Int, N}}, Tuple{Vararg{Int, N}}} where N @@ -2310,7 +2311,8 @@ end # try to fool a greedy algorithm that picks X=Int, Y=String here @test Tuple{Ref{Union{Int,String}}, Ref{Union{Int,String}}} <: Tuple{Ref{Union{X,Y}}, Ref{X}} where {X,Y} -@test Tuple{Ref{Union{Int,String,Missing}}, Ref{Union{Int,String}}} <: Tuple{Ref{Union{X,Y}}, Ref{X}} where {X,Y} +# broken due to 49857 and 49875 +@test_broken Tuple{Ref{Union{Int,String,Missing}}, Ref{Union{Int,String}}} <: Tuple{Ref{Union{X,Y}}, Ref{X}} where {X,Y} @test !(Tuple{Any, Any, Any} <: Tuple{Any, Vararg{T}} where T) diff --git a/test/threads_exec.jl b/test/threads_exec.jl index 68ba9377cf955..a6c52484f023b 100644 --- a/test/threads_exec.jl +++ b/test/threads_exec.jl @@ -1067,3 +1067,23 @@ end popfirst!(LOAD_PATH) end end + +# issue #49746, thread safety in `atexit(f)` +@testset "atexit thread safety" begin + f = () -> nothing + before_len = length(Base.atexit_hooks) + @sync begin + for _ in 1:1_000_000 + Threads.@spawn begin + atexit(f) + end + end + end + @test length(Base.atexit_hooks) == before_len + 1_000_000 + @test all(hook -> hook === f, Base.atexit_hooks[1 : 1_000_000]) + + # cleanup + Base.@lock Base._atexit_hooks_lock begin + deleteat!(Base.atexit_hooks, 1:1_000_000) + end +end