diff --git a/base/abstractdict.jl b/base/abstractdict.jl index 9dba5369a2a66..ec6cb35982d3d 100644 --- a/base/abstractdict.jl +++ b/base/abstractdict.jl @@ -86,8 +86,8 @@ Return an iterator over all keys in a dictionary. When the keys are stored internally in a hash table, as is the case for `Dict`, the order in which they are returned may vary. -But `keys(a)` and `values(a)` both iterate `a` and -return the elements in the same order. +But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a` +and return the elements in the same order. # Examples ```jldoctest @@ -112,8 +112,8 @@ Return an iterator over all values in a collection. When the values are stored internally in a hash table, as is the case for `Dict`, the order in which they are returned may vary. -But `keys(a)` and `values(a)` both iterate `a` and -return the elements in the same order. +But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a` +and return the elements in the same order. # Examples ```jldoctest @@ -136,6 +136,10 @@ values(a::AbstractDict) = ValueIterator(a) Return an iterator over `key => value` pairs for any collection that maps a set of keys to a set of values. This includes arrays, where the keys are the array indices. +When the entries are stored internally in a hash table, +as is the case for `Dict`, the order in which they are returned may vary. +But `keys(a)`, `values(a)` and `pairs(a)` all iterate `a` +and return the elements in the same order. # Examples ```jldoctest diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index f96887d554af0..57cf568402396 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -593,6 +593,7 @@ const arch_mapping = Dict( "armv7l" => "arm(v7l)?", # if we just see `arm-linux-gnueabihf`, we assume it's `armv7l` "armv6l" => "armv6l", "powerpc64le" => "p(ower)?pc64le", + "riscv64" => "(rv64|riscv64)", ) # Keep this in sync with `CPUID.ISAs_by_family` # These are the CPUID side of the microarchitectures targeted by GCC flags in BinaryBuilder.jl diff --git a/base/compiler/ssair/domtree.jl b/base/compiler/ssair/domtree.jl index 2f22da04f9804..c249ac84b9f64 100644 --- a/base/compiler/ssair/domtree.jl +++ b/base/compiler/ssair/domtree.jl @@ -644,6 +644,8 @@ end Compute the nearest common (post-)dominator of `a` and `b`. """ function nearest_common_dominator(domtree::GenericDomTree, a::BBNumber, b::BBNumber) + a == 0 && return a + b == 0 && return b alevel = domtree.nodes[a].level blevel = domtree.nodes[b].level # W.l.g. assume blevel <= alevel diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index 39f1445d8c02d..afdc0fd0b9ab2 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -1294,6 +1294,7 @@ function try_resolve_finalizer!(ir::IRCode, idx::Int, finalizer_idx::Int, defuse end all(check_defuse, defuse.uses) || return nothing all(check_defuse, defuse.defs) || return nothing + bb_insert_block != 0 || return nothing # verify post-dominator of all uses exists # Check #3 dominates(domtree, finalizer_bb, bb_insert_block) || return nothing diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index b5b5abb88e0d9..b45560287edd0 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -1441,7 +1441,7 @@ kw"new" """ where -The `where` keyword creates a type that is an iterated union of other types, over all +The `where` keyword creates a [`UnionAll`](@ref) type, which may be thought of as an iterated union of other types, over all values of some variable. For example `Vector{T} where T<:Real` includes all [`Vector`](@ref)s where the element type is some kind of `Real` number. @@ -3296,6 +3296,9 @@ unused and delete the entire benchmark code). !!! compat "Julia 1.8" This method was added in Julia 1.8. +!!! compat "Julia 1.8" + This method was added in Julia 1.8. + # Examples ```julia diff --git a/base/loading.jl b/base/loading.jl index c708c81a0b8ae..7c918a1f4a83a 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -613,7 +613,12 @@ end ## generic project & manifest API ## const project_names = ("JuliaProject.toml", "Project.toml") -const manifest_names = ("JuliaManifest.toml", "Manifest.toml") +const manifest_names = ( + "JuliaManifest-v$(VERSION.major).$(VERSION.minor).toml", + "Manifest-v$(VERSION.major).$(VERSION.minor).toml", + "JuliaManifest.toml", + "Manifest.toml", +) const preferences_names = ("JuliaLocalPreferences.toml", "LocalPreferences.toml") function locate_project_file(env::String) @@ -1215,6 +1220,7 @@ function run_module_init(mod::Module, i::Int=1) end function run_package_callbacks(modkey::PkgId) + (modkey == precompilation_target) && return nothing run_extension_callbacks(modkey) assert_havelock(require_lock) unlock(require_lock) @@ -1338,7 +1344,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any} # TODO: Better error message if this lookup fails? uuid_trigger = UUID(totaldeps[trigger]::String) trigger_id = PkgId(uuid_trigger, trigger) - if !haskey(Base.loaded_modules, trigger_id) || haskey(package_locks, trigger_id) + if !haskey(Base.loaded_modules, trigger_id) || haskey(package_locks, trigger_id) || (trigger_id == precompilation_target) trigger1 = get!(Vector{ExtensionId}, EXT_DORMITORY, trigger_id) push!(trigger1, gid) else @@ -1350,6 +1356,7 @@ end loading_extension::Bool = false precompiling_extension::Bool = false +precompilation_target::Union{Nothing,PkgId} = nothing function run_extension_callbacks(extid::ExtensionId) assert_havelock(require_lock) succeeded = try @@ -2342,6 +2349,7 @@ function create_expr_cache(pkg::PkgId, input::String, output::String, output_o:: write(io.in, """ empty!(Base.EXT_DORMITORY) # If we have a custom sysimage with `EXT_DORMITORY` prepopulated Base.precompiling_extension = $(loading_extension) + Base.precompilation_target = $(pkg_str(pkg)) 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/mathconstants.jl b/base/mathconstants.jl index de6b98cea634d..d26f5115b5ccb 100644 --- a/base/mathconstants.jl +++ b/base/mathconstants.jl @@ -29,7 +29,7 @@ end Base.@assume_effects :foldable function (::Type{T})(x::_KnownIrrational, r::RoundingMode) where {T<:Union{Float32,Float64}} Base._irrational_to_float(T, x, r) end -Base.@assume_effects :foldable function rationalize(::Type{T}, x::_KnownIrrational; tol::Real=0) where {T<:Integer} +Base.@assume_effects :foldable function Base.rationalize(::Type{T}, x::_KnownIrrational; tol::Real=0) where {T<:Integer} Base._rationalize_irrational(T, x, tol) end Base.@assume_effects :foldable function Base.lessrational(rx::Rational, x::_KnownIrrational) diff --git a/base/meta.jl b/base/meta.jl index 31fef1b9697e3..171ae574ab5ec 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -365,10 +365,15 @@ function _partially_inline!(@nospecialize(x), slot_replacements::Vector{Any}, return x end if isa(x, Core.ReturnNode) + # Unreachable doesn't have val defined + if !isdefined(x, :val) + return x + else return Core.ReturnNode( _partially_inline!(x.val, slot_replacements, type_signature, static_param_values, slot_offset, statement_offset, boundscheck), ) + end end if isa(x, Core.GotoIfNot) return Core.GotoIfNot( diff --git a/base/special/exp.jl b/base/special/exp.jl index 8e940a4d85ad9..32de6b9be296d 100644 --- a/base/special/exp.jl +++ b/base/special/exp.jl @@ -216,6 +216,7 @@ end small_part = muladd(jU, expm1b_kernel(base, r), jL) + jU if !(abs(x) <= SUBNORM_EXP(base, T)) + isnan(x) && return x x >= MAX_EXP(base, T) && return Inf x <= MIN_EXP(base, T) && return 0.0 if k <= -53 @@ -243,6 +244,7 @@ end hi, lo = Base.canonicalize2(1.0, kern) small_part = fma(jU, hi, muladd(jU, (lo+xlo), very_small)) if !(abs(x) <= SUBNORM_EXP(base, T)) + isnan(x) && return x x >= MAX_EXP(base, T) && return Inf x <= MIN_EXP(base, T) && return 0.0 if k <= -53 diff --git a/deps/checksums/Pkg-06f7a7e5bb0fedc20455060d6778f5a66851c026.tar.gz/md5 b/deps/checksums/Pkg-06f7a7e5bb0fedc20455060d6778f5a66851c026.tar.gz/md5 deleted file mode 100644 index a9fa84908f5e6..0000000000000 --- a/deps/checksums/Pkg-06f7a7e5bb0fedc20455060d6778f5a66851c026.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -334d6ce5ca5650e513d1893f6d4e0a93 diff --git a/deps/checksums/Pkg-06f7a7e5bb0fedc20455060d6778f5a66851c026.tar.gz/sha512 b/deps/checksums/Pkg-06f7a7e5bb0fedc20455060d6778f5a66851c026.tar.gz/sha512 deleted file mode 100644 index 87638e7d07d55..0000000000000 --- a/deps/checksums/Pkg-06f7a7e5bb0fedc20455060d6778f5a66851c026.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -0f53341502469153b60143989e6066298e04f9d8c2d6e31d47ac424ad3dc9a46857d22b1c9f322a98f8620741c6dbb3a694d63b8227e9e52488f609a86975012 diff --git a/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 b/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 new file mode 100644 index 0000000000000..8132509853c1a --- /dev/null +++ b/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 @@ -0,0 +1 @@ +220272702d818b059c86d96e5d7b6483 diff --git a/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 b/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 new file mode 100644 index 0000000000000..38f3fc48e8ffb --- /dev/null +++ b/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 @@ -0,0 +1 @@ +f87ae5aee2c875028cca1b6a3a2a6b494317c20b204ee25b0f62e4fa44ad7d74833e0d16ed0fe90747ed81bc1d075427f24f8820573b74335574ceaae14fda5b diff --git a/deps/checksums/SparseArrays-248d9f94cf31d9668e5b07f237f13a239472b2ec.tar.gz/md5 b/deps/checksums/SparseArrays-248d9f94cf31d9668e5b07f237f13a239472b2ec.tar.gz/md5 new file mode 100644 index 0000000000000..f76ad7072a426 --- /dev/null +++ b/deps/checksums/SparseArrays-248d9f94cf31d9668e5b07f237f13a239472b2ec.tar.gz/md5 @@ -0,0 +1 @@ +12b074088311e98aa7b9d03da61cec9b diff --git a/deps/checksums/SparseArrays-248d9f94cf31d9668e5b07f237f13a239472b2ec.tar.gz/sha512 b/deps/checksums/SparseArrays-248d9f94cf31d9668e5b07f237f13a239472b2ec.tar.gz/sha512 new file mode 100644 index 0000000000000..ed1e307f79da6 --- /dev/null +++ b/deps/checksums/SparseArrays-248d9f94cf31d9668e5b07f237f13a239472b2ec.tar.gz/sha512 @@ -0,0 +1 @@ +285ceafd68508831fbaa84ce9bb02da6d0cd1619303640dc46a59877214f300ff891c73a8a92a0a34d0e560f7495edfa1a7656e64afc5b908c40849a21dea60e diff --git a/deps/checksums/SparseArrays-8c84b8cb6f93a772673b17bc96d410ddd8d1551e.tar.gz/md5 b/deps/checksums/SparseArrays-8c84b8cb6f93a772673b17bc96d410ddd8d1551e.tar.gz/md5 deleted file mode 100644 index 8e5bca71e155f..0000000000000 --- a/deps/checksums/SparseArrays-8c84b8cb6f93a772673b17bc96d410ddd8d1551e.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -9398bfb2db58cfefb61356f57acda462 diff --git a/deps/checksums/SparseArrays-8c84b8cb6f93a772673b17bc96d410ddd8d1551e.tar.gz/sha512 b/deps/checksums/SparseArrays-8c84b8cb6f93a772673b17bc96d410ddd8d1551e.tar.gz/sha512 deleted file mode 100644 index eb596f4b5fbb7..0000000000000 --- a/deps/checksums/SparseArrays-8c84b8cb6f93a772673b17bc96d410ddd8d1551e.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -3a22aeb67ae44b47b05c2429884f775f4d18f1ef758e122828ee6bbf49a664e6a4a0fec20a44b4e54cd155eb53c13628b345955011a661c00b1baffd6e7803c3 diff --git a/doc/src/manual/code-loading.md b/doc/src/manual/code-loading.md index 16b1b563f7f35..e41b46a41f2de 100644 --- a/doc/src/manual/code-loading.md +++ b/doc/src/manual/code-loading.md @@ -14,7 +14,7 @@ Code inclusion is quite straightforward and simple: it evaluates the given sourc A *package* is a source tree with a standard layout providing functionality that can be reused by other Julia projects. A package is loaded by `import X` or `using X` statements. These statements also make the module named `X`—which results from loading the package code—available within the module where the import statement occurs. The meaning of `X` in `import X` is context-dependent: which `X` package is loaded depends on what code the statement occurs in. Thus, handling of `import X` happens in two stages: first, it determines **what** package is defined to be `X` in this context; second, it determines **where** that particular `X` package is found. -These questions are answered by searching through the project environments listed in [`LOAD_PATH`](@ref) for project files (`Project.toml` or `JuliaProject.toml`), manifest files (`Manifest.toml` or `JuliaManifest.toml`), or folders of source files. +These questions are answered by searching through the project environments listed in [`LOAD_PATH`](@ref) for project files (`Project.toml` or `JuliaProject.toml`), manifest files (`Manifest.toml` or `JuliaManifest.toml`, or the same names suffixed by `-v{major}.{minor}.toml` for specific versions), or folders of source files. ## Federation of packages @@ -63,7 +63,7 @@ Each kind of environment defines these three maps differently, as detailed in th ### Project environments -A project environment is determined by a directory containing a project file called `Project.toml`, and optionally a manifest file called `Manifest.toml`. These files may also be called `JuliaProject.toml` and `JuliaManifest.toml`, in which case `Project.toml` and `Manifest.toml` are ignored. This allows for coexistence with other tools that might consider files called `Project.toml` and `Manifest.toml` significant. For pure Julia projects, however, the names `Project.toml` and `Manifest.toml` are preferred. +A project environment is determined by a directory containing a project file called `Project.toml`, and optionally a manifest file called `Manifest.toml`. These files may also be called `JuliaProject.toml` and `JuliaManifest.toml`, in which case `Project.toml` and `Manifest.toml` are ignored. This allows for coexistence with other tools that might consider files called `Project.toml` and `Manifest.toml` significant. For pure Julia projects, however, the names `Project.toml` and `Manifest.toml` are preferred. However, from Julia v1.10.8 onwards, `(Julia)Manifest-v{major}.{minor}.toml` is recognized as a format to make a given julia version use a specific manifest file i.e. in the same folder, a `Manifest-v1.11.toml` would be used by v1.11 and `Manifest.toml` by any other julia version. The roots, graph and paths maps of a project environment are defined as follows: diff --git a/doc/src/manual/complex-and-rational-numbers.md b/doc/src/manual/complex-and-rational-numbers.md index 9cab2ed1e4f24..d1d6ffeca245f 100644 --- a/doc/src/manual/complex-and-rational-numbers.md +++ b/doc/src/manual/complex-and-rational-numbers.md @@ -254,13 +254,30 @@ julia> float(3//4) ``` Conversion from rational to floating-point respects the following identity for any integral values -of `a` and `b`, with the exception of the two cases `b == 0` and `a == 0 && b < 0`: +of `a` and `b`, except when `a==0 && b <= 0`: ```jldoctest julia> a = 1; b = 2; julia> isequal(float(a//b), a/b) true + +julia> a, b = 0, 0 +(0, 0) + +julia> float(a//b) +ERROR: ArgumentError: invalid rational: zero(Int64)//zero(Int64) +Stacktrace: +[...] + +julia> a/b +NaN + +julia> a, b = 0, -1 +(0, -1) + +julia> float(a//b), a/b +(0.0, -0.0) ``` Constructing infinite rational values is acceptable: diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index d55090e161523..319641aa85995 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -493,7 +493,15 @@ jl_code_instance_t *jl_generate_fptr_impl(jl_method_instance_t *mi JL_PROPAGATES } else { // identify whether this is an invalidated method that is being recompiled - is_recompile = jl_atomic_load_relaxed(&mi->cache) != NULL; + // Is a recompile if there is cached code, and it was compiled (not only inferred) before + jl_code_instance_t *codeinst_old = jl_atomic_load_relaxed(&mi->cache); + while (codeinst_old != NULL) { + if (jl_atomic_load_relaxed(&codeinst_old->invoke) != NULL) { + is_recompile = 1; + break; + } + codeinst_old = jl_atomic_load_relaxed(&codeinst_old->next); + } } if (src == NULL && jl_is_method(mi->def.method) && jl_symbol_name(mi->def.method->name)[0] != '@') { diff --git a/src/staticdata.c b/src/staticdata.c index a55342604f21d..a780add783d46 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -433,6 +433,7 @@ void *native_functions; // opaque jl_native_code_desc_t blob used for fetching // table of struct field addresses to rewrite during saving static htable_t field_replace; +static htable_t relocatable_ext_cis; // array of definitions for the predefined function pointers // (reverse of fptr_to_id) @@ -656,7 +657,8 @@ static int needs_uniquing(jl_value_t *v) JL_NOTSAFEPOINT static void record_field_change(jl_value_t **addr, jl_value_t *newval) JL_NOTSAFEPOINT { - ptrhash_put(&field_replace, (void*)addr, newval); + if (*addr != newval) + ptrhash_put(&field_replace, (void*)addr, newval); } static jl_value_t *get_replaceable_field(jl_value_t **addr, int mutabl) JL_GC_DISABLED @@ -797,6 +799,8 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_ // TODO: if (ci in ci->defs->cache) record_field_change((jl_value_t**)&ci->next, NULL); } + if (jl_atomic_load_relaxed(&ci->inferred) && !is_relocatable_ci(&relocatable_ext_cis, ci)) + record_field_change((jl_value_t**)&ci->inferred, jl_nothing); } if (immediate) // must be things that can be recursively handled, and valid as type parameters @@ -1505,6 +1509,7 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED // will check on deserialize if this cache entry is still valid } } + newm->relocatability = 0; } newm->invoke = NULL; @@ -2384,7 +2389,7 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new *edges = jl_alloc_vec_any(0); *method_roots_list = jl_alloc_vec_any(0); // Collect the new method roots - jl_collect_new_roots(*method_roots_list, *new_specializations, worklist_key); + jl_collect_new_roots(&relocatable_ext_cis, *method_roots_list, *new_specializations, worklist_key); jl_collect_edges(*edges, *ext_targets, *new_specializations, world); } assert(edges_map == NULL); // jl_collect_edges clears this when done @@ -2770,6 +2775,7 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli assert((ct->reentrant_timing & 0b1110) == 0); ct->reentrant_timing |= 0b1000; if (worklist) { + htable_new(&relocatable_ext_cis, 0); jl_prepare_serialization_data(mod_array, newly_inferred, jl_worklist_key(worklist), &extext_methods, &new_specializations, &method_roots_list, &ext_targets, &edges); if (!emit_split) { @@ -2786,6 +2792,8 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli jl_save_system_image_to_stream(ff, mod_array, worklist, extext_methods, new_specializations, method_roots_list, ext_targets, edges); if (_native_data != NULL) native_functions = NULL; + if (worklist) + htable_free(&relocatable_ext_cis); // make sure we don't run any Julia code concurrently before this point // Re-enable running julia code for postoutput hooks, atexit, etc. jl_gc_enable_finalizers(ct, 1); diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index b488934606671..e327f0f84ea75 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -208,6 +208,17 @@ static int has_backedge_to_worklist(jl_method_instance_t *mi, htable_t *visited, return found; } +static int is_relocatable_ci(htable_t *relocatable_ext_cis, jl_code_instance_t *ci) +{ + if (!ci->relocatability) + return 0; + jl_method_instance_t *mi = ci->def; + jl_method_t *m = mi->def.method; + if (!ptrhash_has(relocatable_ext_cis, ci) && jl_object_in_image((jl_value_t*)m) && (!jl_is_method(m) || jl_object_in_image((jl_value_t*)m->module))) + return 0; + return 1; +} + // Given the list of CodeInstances that were inferred during the build, select // those that are (1) external, (2) still valid, (3) are inferred to be called // from the worklist or explicitly added by a `precompile` statement, and @@ -261,7 +272,7 @@ static jl_array_t *queue_external_cis(jl_array_t *list) } // New roots for external methods -static void jl_collect_new_roots(jl_array_t *roots, jl_array_t *new_specializations, uint64_t key) +static void jl_collect_new_roots(htable_t *relocatable_ext_cis, jl_array_t *roots, jl_array_t *new_specializations, uint64_t key) { htable_t mset; htable_new(&mset, 0); @@ -272,6 +283,7 @@ static void jl_collect_new_roots(jl_array_t *roots, jl_array_t *new_specializati jl_method_t *m = ci->def->def.method; assert(jl_is_method(m)); ptrhash_put(&mset, (void*)m, (void*)m); + ptrhash_put(relocatable_ext_cis, (void*)ci, (void*)ci); } int nwithkey; void *const *table = mset.table; diff --git a/src/subtype.c b/src/subtype.c index 2f8f41d50c239..f183cc9da21a9 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -1572,6 +1572,42 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t return sub; } +static int equal_var(jl_tvar_t *v, jl_value_t *x, jl_stenv_t *e) +{ + assert(e->Loffset == 0); + // Theoretically bounds change would be merged for union inputs. + // But intersection is not happy as splitting helps to avoid circular env. + assert(!e->intersection || !jl_is_uniontype(x)); + jl_varbinding_t *vb = lookup(e, v); + if (e->intersection && vb != NULL && vb->lb == vb->ub && jl_is_typevar(vb->lb)) + return equal_var((jl_tvar_t *)vb->lb, x, e); + record_var_occurrence(vb, e, 2); + if (vb == NULL) + return e->ignore_free || ( + local_forall_exists_subtype(x, v->lb, e, 2, !jl_has_free_typevars(x)) && + local_forall_exists_subtype(v->ub, x, e, 0, 0)); + if (!vb->right) + return local_forall_exists_subtype(x, vb->lb, e, 2, !jl_has_free_typevars(x)) && + local_forall_exists_subtype(vb->ub, x, e, 0, 0); + if (vb->lb == x) + return var_lt(v, x, e, 0); + if (!subtype_ccheck(x, vb->ub, e)) + return 0; + jl_value_t *lb = simple_join(vb->lb, x); + JL_GC_PUSH1(&lb); + if (!e->intersection || !jl_is_typevar(lb) || !reachable_var(lb, v, e)) + vb->lb = lb; + JL_GC_POP(); + if (vb->ub == x) + return 1; + if (!subtype_ccheck(vb->lb, x, e)) + return 0; + // skip `simple_meet` here as we have proven `x <: vb->ub` + if (!e->intersection || !reachable_var(x, v, e)) + vb->ub = x; + return 1; +} + static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) { if (obviously_egal(x, y)) return 1; @@ -1602,6 +1638,12 @@ static int forall_exists_equal(jl_value_t *x, jl_value_t *y, jl_stenv_t *e) } } + if (e->Loffset == 0 && jl_is_typevar(y) && jl_is_type(x) && (!e->intersection || !jl_is_uniontype(x))) { + // Fastpath for Type == TypeVar. + // Avoid duplicated `<:` check between adjacent `var_gt` and `var_lt` + return equal_var((jl_tvar_t *)y, x, e); + } + jl_saved_unionstate_t oldLunions; push_unionstate(&oldLunions, &e->Lunions); int sub = local_forall_exists_subtype(x, y, e, 2, -1); diff --git a/stdlib/Artifacts/src/Artifacts.jl b/stdlib/Artifacts/src/Artifacts.jl index 6b406201f11d6..6618c9bf062be 100644 --- a/stdlib/Artifacts/src/Artifacts.jl +++ b/stdlib/Artifacts/src/Artifacts.jl @@ -24,7 +24,7 @@ function parse_toml(path::String) Base.parsed_toml(path) end -# keep in sync with Base.project_names and Base.manifest_names +# keep in sync with Base.project_names const artifact_names = ("JuliaArtifacts.toml", "Artifacts.toml") const ARTIFACTS_DIR_OVERRIDE = Ref{Union{String,Nothing}}(nothing) diff --git a/stdlib/Artifacts/test/runtests.jl b/stdlib/Artifacts/test/runtests.jl index 67117217be549..2f4fe3a2a6a2a 100644 --- a/stdlib/Artifacts/test/runtests.jl +++ b/stdlib/Artifacts/test/runtests.jl @@ -161,6 +161,6 @@ end @testset "`Artifacts.artifact_names` and friends" begin n = length(Artifacts.artifact_names) @test length(Base.project_names) == n - @test length(Base.manifest_names) == n + @test length(Base.manifest_names) == 2n # there are two manifest names per project name @test length(Base.preferences_names) == n end diff --git a/stdlib/LinearAlgebra/test/triangular.jl b/stdlib/LinearAlgebra/test/triangular.jl index 236d9f08793b0..b337f3c1cf8d9 100644 --- a/stdlib/LinearAlgebra/test/triangular.jl +++ b/stdlib/LinearAlgebra/test/triangular.jl @@ -895,4 +895,14 @@ end @test exp(log(M)) ≈ M end +@testset "log_quasitriu with internal scaling s=0 (issue #54833)" begin + M = [0.9949357359852791 -0.015567763143324862 -0.09091193493947397 -0.03994428739762443 0.07338356301650806; + 0.011813655598647289 0.9968988574699793 -0.06204555000202496 0.04694097614450692 0.09028834462782365; + 0.092737943594701 0.059546719185135925 0.9935850721633324 0.025348893985651405 -0.018530261590167685; + 0.0369187299165628 -0.04903571106913449 -0.025962938675946543 0.9977767446862031 0.12901494726320517; + 0.0 0.0 0.0 0.0 1.0] + + @test exp(log(M)) ≈ M +end + end # module TestTriangular diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index 3cc55f2ac2ac3..fd91f6e800f38 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = release-1.10 -PKG_SHA1 = 06f7a7e5bb0fedc20455060d6778f5a66851c026 +PKG_SHA1 = 6390ea92bf585e182c96cb5db7529c067874e5f5 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/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index d770a41fdc358..8b9a552071ea8 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -949,7 +949,7 @@ function complete_keyword_argument(partial, last_idx, context_module) kwargs_flag == 2 && return fail # one of the previous kwargs is invalid methods = Completion[] - complete_methods!(methods, funct, Any[Vararg{Any}], kwargs_ex, -1, kwargs_flag == 1) + complete_methods!(methods, funct, Any[Vararg{Any}], kwargs_ex, MAX_METHOD_COMPLETIONS, kwargs_flag == 1) # TODO: use args_ex instead of Any[Vararg{Any}] and only provide kwarg completion for # method calls compatible with the current arguments. diff --git a/stdlib/SparseArrays.version b/stdlib/SparseArrays.version index 652ddf8720c41..2b737bc6aa2db 100644 --- a/stdlib/SparseArrays.version +++ b/stdlib/SparseArrays.version @@ -1,4 +1,4 @@ SPARSEARRAYS_BRANCH = release-1.10 -SPARSEARRAYS_SHA1 = 8c84b8cb6f93a772673b17bc96d410ddd8d1551e +SPARSEARRAYS_SHA1 = 248d9f94cf31d9668e5b07f237f13a239472b2ec SPARSEARRAYS_GIT_URL := https://github.com/JuliaSparse/SparseArrays.jl.git SPARSEARRAYS_TAR_URL = https://api.github.com/repos/JuliaSparse/SparseArrays.jl/tarball/$1 diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 12e0c1fe2d502..c47cbf105056a 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -652,7 +652,9 @@ let exename = `$(Base.julia_cmd()) --startup-file=no --color=no` code = code[3] @test occursin("llvm.module.flags", code) @test occursin("llvm.dbg.cu", code) - @test occursin("int.jl", code) + # TODO: consider moving test to llvmpasses as this fails on some platforms + # without clear reason + @test_skip occursin("int.jl", code) @test !occursin("\"Int64\"", code) end let code = readchomperrors(`$exename -g2 -E "@eval Int64(1)+Int64(1)"`) @@ -660,7 +662,9 @@ let exename = `$(Base.julia_cmd()) --startup-file=no --color=no` code = code[3] @test occursin("llvm.module.flags", code) @test occursin("llvm.dbg.cu", code) - @test occursin("int.jl", code) + # TODO: consider moving test to llvmpasses as this fails on some platforms + # without clear reason + @test_skip occursin("int.jl", code) @test occursin("\"Int64\"", code) end end diff --git a/test/compiler/irpasses.jl b/test/compiler/irpasses.jl index a1738b52161bf..9ef122b9483c7 100644 --- a/test/compiler/irpasses.jl +++ b/test/compiler/irpasses.jl @@ -1355,3 +1355,24 @@ let src = code_typed1(mut50285, Tuple{Bool, Int, Float64}) @test count(isnew, src.code) == 0 @test count(iscall((src, typeassert)), src.code) == 0 end + +# https://github.com/JuliaLang/julia/issues/54596 +# finalized object's uses have no postdominator +let f = (x)->nothing, mi = only(Base.method_instances(f, (Base.RefValue{Nothing},), Base.get_world_counter())), code = Any[ + # Basic Block 1 + Expr(:new, Base.RefValue{Nothing}, nothing) + Expr(:call, Core.finalizer, f, SSAValue(1), true, mi) + GotoIfNot(false, 6) + # Basic Block 2 + Expr(:call, Base.getfield, SSAValue(1), :x) + ReturnNode(SSAValue(4)) + # Basic Block 3 + Expr(:call, Base.getfield, SSAValue(1), :x) + ReturnNode(SSAValue(6)) +] + ir = make_ircode(code; ssavaluetypes=Any[Base.RefValue{Nothing}, Nothing, Any, Nothing, Any, Nothing, Any]) + inlining = Core.Compiler.InliningState(Core.Compiler.NativeInterpreter()) + Core.Compiler.verify_ir(ir) + ir = Core.Compiler.sroa_pass!(ir, inlining) + Core.Compiler.verify_ir(ir) +end diff --git a/test/compiler/irutils.jl b/test/compiler/irutils.jl index c2f6fd3314c1b..c8c66aeef6371 100644 --- a/test/compiler/irutils.jl +++ b/test/compiler/irutils.jl @@ -1,4 +1,4 @@ -using Core: CodeInfo, ReturnNode, MethodInstance +using Core.IR using Core.Compiler: IRCode, IncrementalCompact, singleton_type, VarState using Base.Meta: isexpr using InteractiveUtils: gen_call_with_extracted_types_and_kwargs @@ -16,7 +16,8 @@ end # check if `x` is a statement with a given `head` isnew(@nospecialize x) = isexpr(x, :new) issplatnew(@nospecialize x) = isexpr(x, :splatnew) -isreturn(@nospecialize x) = isa(x, ReturnNode) +isreturn(@nospecialize x) = isa(x, ReturnNode) && isdefined(x, :val) +isisdefined(@nospecialize x) = isexpr(x, :isdefined) # check if `x` is a dynamic call of a given function iscall(y) = @nospecialize(x) -> iscall(y, x) @@ -42,19 +43,49 @@ fully_eliminated(@nospecialize args...; retval=(@__FILE__), kwargs...) = fully_eliminated(src::CodeInfo; retval=(@__FILE__)) = fully_eliminated(src.code; retval) fully_eliminated(ir::IRCode; retval=(@__FILE__)) = fully_eliminated(ir.stmts.inst; retval) function fully_eliminated(code::Vector{Any}; retval=(@__FILE__), kwargs...) - if retval !== (@__FILE__) - length(code) == 1 || return false - code1 = code[1] - isreturn(code1) || return false - val = code1.val - if val isa QuoteNode - val = val.value - end - return val == retval - else - return length(code) == 1 && isreturn(code[1]) + length(code) == 1 || return false + retstmt = only(code) + isreturn(retstmt) || return false + retval === (@__FILE__) && return true + retval′ = retstmt.val + if retval′ isa QuoteNode + retval′ = retval′.value end + return retval′ == retval end macro fully_eliminated(ex0...) return gen_call_with_extracted_types_and_kwargs(__module__, :fully_eliminated, ex0) end + +let m = Meta.@lower 1 + 1 + @assert Meta.isexpr(m, :thunk) + orig_src = m.args[1]::CodeInfo + global function make_codeinfo(code::Vector{Any}; + ssavaluetypes::Union{Nothing,Vector{Any}}=nothing, + slottypes::Union{Nothing,Vector{Any}}=nothing) + src = copy(orig_src) + src.code = code + nstmts = length(src.code) + if ssavaluetypes === nothing + src.ssavaluetypes = nstmts + else + src.ssavaluetypes = ssavaluetypes + end + src.codelocs = fill(one(Int32), nstmts) + src.ssaflags = fill(zero(UInt32), nstmts) + if slottypes !== nothing + src.slottypes = slottypes + src.slotflags = fill(zero(UInt8), length(slottypes)) + end + return src + end + global function make_ircode(code::Vector{Any}; + ssavaluetypes::Union{Nothing,Vector{Any}}=nothing, + slottypes::Union{Nothing,Vector{Any}}=nothing, + verify::Bool=true) + src = make_codeinfo(code; ssavaluetypes, slottypes) + ir = Core.Compiler.inflate_ir(src) + verify && Core.Compiler.verify_ir(ir) + return ir + end +end diff --git a/test/dict.jl b/test/dict.jl index c935ae1be5dac..7dc12fcabe416 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -763,6 +763,13 @@ end [v for (k, v) in d] == [d[x[1]] for (i, x) in enumerate(d)] end +@testset "consistency of dict iteration order (issue #56841)" begin + dict = Dict(randn() => randn() for _ = 1:100) + @test all(zip(dict, keys(dict), values(dict), pairs(dict))) do (d, k, v, p) + d == p && first(d) == first(p) == k && last(d) == last(p) == v + end +end + @testset "generators, similar" begin d = Dict(:a=>"a") # TODO: restore when 0.7 deprecation is removed diff --git a/test/loading.jl b/test/loading.jl index 7aee1d9d1d152..3e2e88566f6a8 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -795,8 +795,10 @@ end @testset "`Base.project_names` and friends" begin # Some functions in Pkg assumes that these tuples have the same length n = length(Base.project_names) - @test length(Base.manifest_names) == n @test length(Base.preferences_names) == n + + # there are two manifest names per project name + @test length(Base.manifest_names) == 2n end @testset "Manifest formats" begin @@ -825,6 +827,33 @@ end end end +@testset "Manifest name preferential loading" begin + mktempdir() do tmp + proj = joinpath(tmp, "Project.toml") + touch(proj) + for man_name in ( + "Manifest.toml", + "JuliaManifest.toml", + "Manifest-v$(VERSION.major).$(VERSION.minor).toml", + "JuliaManifest-v$(VERSION.major).$(VERSION.minor).toml" + ) + touch(joinpath(tmp, man_name)) + man = basename(Base.project_file_manifest_path(proj)) + @test man == man_name + end + end + mktempdir() do tmp + # check that another version isn't preferred + proj = joinpath(tmp, "Project.toml") + touch(proj) + touch(joinpath(tmp, "Manifest-v1.5.toml")) + @test Base.project_file_manifest_path(proj) == nothing + touch(joinpath(tmp, "Manifest.toml")) + man = basename(Base.project_file_manifest_path(proj)) + @test man == "Manifest.toml" + end +end + @testset "error message loading pkg bad module name" begin mktempdir() do tmp old_loadpath = copy(LOAD_PATH) @@ -1101,6 +1130,41 @@ end cmd_proj_ext = addenv(cmd_proj_ext, "JULIA_LOAD_PATH" => join([joinpath(proj, "HasExtensions.jl"), joinpath(proj, "EnvWithDeps")], sep)) run(cmd_proj_ext) end + + # Extensions for "parent" dependencies + # (i.e. an `ExtAB` where A depends on / loads B, but B provides the extension) + + mktempdir() do depot # Parallel pre-compilation + code = """ + Base.disable_parallel_precompile = false + using Parent + Base.get_extension(getfield(Parent, :DepWithParentExt), :ParentExt) isa Module || error("expected extension to load") + Parent.greet() + """ + proj = joinpath(@__DIR__, "project", "Extensions", "Parent.jl") + cmd = `$(Base.julia_cmd()) --startup-file=no -e $code` + cmd = addenv(cmd, + "JULIA_LOAD_PATH" => proj, + "JULIA_DEPOT_PATH" => depot * Base.Filesystem.pathsep(), + ) + @test occursin("Hello parent!", String(read(cmd))) + end + mktempdir() do depot # Serial pre-compilation + code = """ + Base.disable_parallel_precompile = true + using Parent + Base.get_extension(getfield(Parent, :DepWithParentExt), :ParentExt) isa Module || error("expected extension to load") + Parent.greet() + """ + proj = joinpath(@__DIR__, "project", "Extensions", "Parent.jl") + cmd = `$(Base.julia_cmd()) --startup-file=no -e $code` + cmd = addenv(cmd, + "JULIA_LOAD_PATH" => proj, + "JULIA_DEPOT_PATH" => depot * Base.Filesystem.pathsep(), + ) + @test occursin("Hello parent!", String(read(cmd))) + end + finally try rm(depot_path, force=true, recursive=true) diff --git a/test/math.jl b/test/math.jl index 6a41fa55c4f47..8bc981993f5c8 100644 --- a/test/math.jl +++ b/test/math.jl @@ -366,6 +366,10 @@ end end end +@testset "https://github.com/JuliaLang/julia/issues/56782" begin + @test isnan(exp(reinterpret(Float64, 0x7ffbb14880000000))) +end + @testset "test abstractarray trig functions" begin TAA = rand(2,2) TAA = (TAA + TAA')/2. diff --git a/test/meta.jl b/test/meta.jl index 36a8acbfe08dd..43dcd72b26299 100644 --- a/test/meta.jl +++ b/test/meta.jl @@ -283,4 +283,9 @@ ci = code_lowered(g, Tuple{Val{true}})[1] @test Meta.partially_inline!(copy(ci.code), Any[isdefined_globalref, 1], Tuple{typeof(isdefined_globalref), Int}, [], 0, 0, :propagate)[1] == Expr(:isdefined, GlobalRef(Base, :foo)) + withunreachable(s::String) = sin(s) + ci = code_lowered(withunreachable, Tuple{String})[1] + ci.code[end] = Core.ReturnNode() + @test Meta.partially_inline!(copy(ci.code), Any[withunreachable, "foo"], Tuple{typeof(withunreachable), String}, + [], 0, 0, :propagate)[end] == Core.ReturnNode() end diff --git a/test/precompile.jl b/test/precompile.jl index 0b9cc9eab3417..fd3ec802430f2 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -714,7 +714,7 @@ precompile_test_harness("code caching") do dir mi = minternal.specializations::Core.MethodInstance @test mi.specTypes == Tuple{typeof(M.getelsize),Vector{Int32}} ci = mi.cache - @test ci.relocatability == 1 + @test ci.relocatability == 0 @test ci.inferred !== nothing # ...and that we can add "untracked" roots & non-relocatable CodeInstances to them too Base.invokelatest() do diff --git a/test/project/Extensions/DepWithParentExt.jl/Project.toml b/test/project/Extensions/DepWithParentExt.jl/Project.toml new file mode 100644 index 0000000000000..bc487252ced4e --- /dev/null +++ b/test/project/Extensions/DepWithParentExt.jl/Project.toml @@ -0,0 +1,9 @@ +name = "DepWithParentExt" +uuid = "8a35c396-5ffc-40d2-b7ec-e8ed2248da32" +version = "0.1.0" + +[weakdeps] +Parent = "58cecb9c-f68a-426e-b92a-89d456ae7acc" + +[extensions] +ParentExt = "Parent" diff --git a/test/project/Extensions/DepWithParentExt.jl/ext/ParentExt.jl b/test/project/Extensions/DepWithParentExt.jl/ext/ParentExt.jl new file mode 100644 index 0000000000000..56176d2f5921d --- /dev/null +++ b/test/project/Extensions/DepWithParentExt.jl/ext/ParentExt.jl @@ -0,0 +1,6 @@ +module ParentExt + +using Parent +using DepWithParentExt + +end diff --git a/test/project/Extensions/DepWithParentExt.jl/src/DepWithParentExt.jl b/test/project/Extensions/DepWithParentExt.jl/src/DepWithParentExt.jl new file mode 100644 index 0000000000000..3d4ebc4ebf8a0 --- /dev/null +++ b/test/project/Extensions/DepWithParentExt.jl/src/DepWithParentExt.jl @@ -0,0 +1,5 @@ +module DepWithParentExt + +greet() = print("Hello dep w/ ext for parent dep!") + +end # module DepWithParentExt diff --git a/test/project/Extensions/Parent.jl/Manifest.toml b/test/project/Extensions/Parent.jl/Manifest.toml new file mode 100644 index 0000000000000..e357d214bca4c --- /dev/null +++ b/test/project/Extensions/Parent.jl/Manifest.toml @@ -0,0 +1,16 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.10.6" +manifest_format = "2.0" +project_hash = "5d72c155f50f076d28b74de819d417878ffb0965" + +[[deps.DepWithParentExt]] +path = "../DepWithParentExt.jl" +uuid = "8a35c396-5ffc-40d2-b7ec-e8ed2248da32" +version = "0.1.0" + + [deps.DepWithParentExt.extensions] + ParentExt = "Parent" + + [deps.DepWithParentExt.weakdeps] + Parent = "58cecb9c-f68a-426e-b92a-89d456ae7acc" diff --git a/test/project/Extensions/Parent.jl/Project.toml b/test/project/Extensions/Parent.jl/Project.toml new file mode 100644 index 0000000000000..a79ec8859bd33 --- /dev/null +++ b/test/project/Extensions/Parent.jl/Project.toml @@ -0,0 +1,6 @@ +name = "Parent" +uuid = "58cecb9c-f68a-426e-b92a-89d456ae7acc" +version = "0.1.0" + +[deps] +DepWithParentExt = "8a35c396-5ffc-40d2-b7ec-e8ed2248da32" diff --git a/test/project/Extensions/Parent.jl/src/Parent.jl b/test/project/Extensions/Parent.jl/src/Parent.jl new file mode 100644 index 0000000000000..471f4b13ecca3 --- /dev/null +++ b/test/project/Extensions/Parent.jl/src/Parent.jl @@ -0,0 +1,7 @@ +module Parent + +using DepWithParentExt + +greet() = print("Hello parent!") + +end # module Parent diff --git a/test/subtype.jl b/test/subtype.jl index 9ee158e710c80..9d1ce866c7a6b 100644 --- a/test/subtype.jl +++ b/test/subtype.jl @@ -2679,3 +2679,19 @@ let S = Dict{V,V} where {V}, @test A <: typeintersect(S, T) @test A <: typeintersect(T, S) end + +#issue 56606 +let + A = Tuple{Val{1}} + B = Tuple{Val} + for _ in 1:30 + A = Tuple{Val{A}} + B = Tuple{Val{<:B}} + end + @test A <: B +end +@testintersect( + Val{Tuple{Int,S,T}} where {S<:Any,T<:Vector{Vector{Int}}}, + Val{Tuple{T,R,S}} where {T,R<:Vector{T},S<:Vector{R}}, + Val{Tuple{Int, Vector{Int}, T}} where T<:Vector{Vector{Int}}, +)