Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backports for Julia 1.10.7 #56381

Open
wants to merge 23 commits into
base: release-1.10
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
bb62a53
Subtype: bug fix for bounds with deeper covariant var (#50832)
N5N3 Aug 10, 2023
56f51da
Fix remove-addrspaces pass in the presence of globals with addrspaces…
gbaraldi Oct 20, 2023
6c9897c
irrationals: restrict assume effects annotations to known types (#55886)
nsajko Oct 10, 2024
4c69200
update `hash` doc string: `widen` not required any more (#55867)
nsajko Oct 10, 2024
40f67ef
fix infinite recursion in `promote_type` for `Irrational` (#55870)
nsajko Oct 18, 2024
53adba9
REPL: don't complete str and cmd macros when the input matches the in…
IanButterworth Oct 23, 2024
7442535
Fix trampoline warning on x86 as well (#56280)
gbaraldi Oct 23, 2024
85aecff
recommend explicit `using Foo: Foo, ...` in package code (was: "using…
KristofferC Oct 26, 2024
0cf1432
Add compat entry for `Base.donotdelete` (#55773)
LilithHafner Sep 14, 2024
d48243f
inference: fix inference error from constructing invalid `TypeVar` (#…
aviatesk Oct 21, 2024
aa58f67
typeintersect: more fastpath to skip intersect under circular env (#5…
N5N3 Oct 23, 2024
f34528d
InteractiveUtils.jl: fixes issue where subtypes resolves bindings and…
dgleich Oct 24, 2024
2454b24
move time_imports and trace_* macros to Base but remain owned by Inte…
IanButterworth Oct 22, 2024
fe891d1
REPL: fix brace detection when ' is used for transpose (#56252)
IanButterworth Oct 21, 2024
b2be809
Make loading work when stdlib deps are missing in the manifest (#56148)
IanButterworth Oct 15, 2024
d830b45
Fix `pkgdir` for extensions (#55720)
IanButterworth Sep 10, 2024
27a0143
bump Pkg to latest 1.10
Oct 30, 2024
a03c5cd
Fix handling of virtual exit node in `PostDomTree` (#53739)
topolarity Mar 19, 2024
bb86259
update inference reflection usage for 1.10
KristofferC Oct 30, 2024
396b557
[backports-release-1.10] allow extensions to trigger from packages in…
topolarity Oct 31, 2024
3b088df
typeintersect: fix bounds merging during inner `intersect_all`.
N5N3 Jul 26, 2024
e23fb4b
[backport-1.10] Fix dispatch for rdiv! with LU (#56415)
dkarrasch Nov 3, 2024
5549ee2
🤖 [backports-release-1.10] Bump the SparseArrays stdlib from 279b363 …
DilumAluthgeBot Nov 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions base/compiler/ssair/domtree.jl
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,7 @@ function SNCA!(domtree::GenericDomTree{IsPostDom}, blocks::Vector{BasicBlock}, m
ancestors = copy(D.to_parent_pre)
relevant_blocks = IsPostDom ? (1:max_pre) : (2:max_pre)
for w::PreNumber in reverse(relevant_blocks)
# LLVM initializes this to the parent, the paper initializes this to
# `w`, but it doesn't really matter (the parent is a predecessor, so at
# worst we'll discover it below). Save a memory reference here.
semi_w = typemax(PreNumber)
semi_w = ancestors[w]
last_linked = PreNumber(w + 1)
for v ∈ dom_edges(domtree, blocks, D.from_pre[w])
# For the purpose of the domtree, ignore virtual predecessors into
Expand Down
12 changes: 10 additions & 2 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -574,8 +574,16 @@ add_tfunc(svec, 0, INT_INF, @nospecs((𝕃::AbstractLattice, args...)->SimpleVec
return TypeVar
end
end
tv = TypeVar(nval, lb, ub)
return PartialTypeVar(tv, lb_certain, ub_certain)
lb_valid = lb isa Type || lb isa TypeVar
ub_valid = ub isa Type || ub isa TypeVar
if lb_valid && ub_valid
tv = TypeVar(nval, lb, ub)
return PartialTypeVar(tv, lb_certain, ub_certain)
elseif !lb_valid && lb_certain
return Union{}
elseif !ub_valid && ub_certain
return Union{}
end
end
return TypeVar
end
Expand Down
11 changes: 11 additions & 0 deletions base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ kw"help", kw"Julia", kw"julia", kw""
available for direct use. Names can also be used via dot syntax (e.g. `Foo.foo` to access
the name `foo`), whether they are `export`ed or not.
See the [manual section about modules](@ref modules) for details.

!!! note
When two or more packages/modules export a name and that name does not refer to the
same thing in each of the packages, and the packages are loaded via `using` without
an explicit list of names, it is an error to reference that name without qualification.
It is thus recommended that code intended to be forward-compatible with future versions
of its dependencies and of Julia, e.g., code in released packages, list the names it
uses from each loaded package, e.g., `using Foo: Foo, f` rather than `using Foo`.
"""
kw"using"

Expand Down Expand Up @@ -3285,6 +3293,9 @@ unused and delete the entire benchmark code).
`donotdelete(1+1)`, no add instruction needs to be executed at runtime and
the code is semantically equivalent to `donotdelete(2).`

!!! compat "Julia 1.8"
This method was added in Julia 1.8.

# Examples

```julia
Expand Down
4 changes: 1 addition & 3 deletions base/hashing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ optional second argument `h` is another hash code to be mixed with the result.
New types should implement the 2-argument form, typically by calling the 2-argument `hash`
method recursively in order to mix hashes of the contents with each other (and with `h`).
Typically, any type that implements `hash` should also implement its own [`==`](@ref) (hence
[`isequal`](@ref)) to guarantee the property mentioned above. Types supporting subtraction
(operator `-`) should also implement [`widen`](@ref), which is required to hash
values inside heterogeneous arrays.
[`isequal`](@ref)) to guarantee the property mentioned above.

The hash value may change when a new Julia process is started.

Expand Down
33 changes: 24 additions & 9 deletions base/irrationals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,22 @@ promote_rule(::Type{<:AbstractIrrational}, ::Type{Float16}) = Float16
promote_rule(::Type{<:AbstractIrrational}, ::Type{Float32}) = Float32
promote_rule(::Type{<:AbstractIrrational}, ::Type{<:AbstractIrrational}) = Float64
promote_rule(::Type{<:AbstractIrrational}, ::Type{T}) where {T<:Real} = promote_type(Float64, T)
promote_rule(::Type{S}, ::Type{T}) where {S<:AbstractIrrational,T<:Number} = promote_type(promote_type(S, real(T)), T)

function promote_rule(::Type{S}, ::Type{T}) where {S<:AbstractIrrational,T<:Number}
U = promote_type(S, real(T))
if S <: U
# prevent infinite recursion
promote_type(Float64, T)
else
promote_type(U, T)
end
end

AbstractFloat(x::AbstractIrrational) = Float64(x)::Float64
Float16(x::AbstractIrrational) = Float16(Float32(x)::Float32)
Complex{T}(x::AbstractIrrational) where {T<:Real} = Complex{T}(T(x))

# XXX this may change `DEFAULT_PRECISION`, thus not effect free
@assume_effects :total function Rational{T}(x::AbstractIrrational) where T<:Integer
function _irrational_to_rational(::Type{T}, x::AbstractIrrational) where T<:Integer
o = precision(BigFloat)
p = 256
while true
Expand All @@ -63,13 +71,16 @@ Complex{T}(x::AbstractIrrational) where {T<:Real} = Complex{T}(T(x))
p += 32
end
end
Rational{BigInt}(x::AbstractIrrational) = throw(ArgumentError("Cannot convert an AbstractIrrational to a Rational{BigInt}: use rationalize(BigInt, x) instead"))
Rational{T}(x::AbstractIrrational) where {T<:Integer} = _irrational_to_rational(T, x)
_throw_argument_error_irrational_to_rational_bigint() = throw(ArgumentError("Cannot convert an AbstractIrrational to a Rational{BigInt}: use rationalize(BigInt, x) instead"))
Rational{BigInt}(::AbstractIrrational) = _throw_argument_error_irrational_to_rational_bigint()

@assume_effects :total function (t::Type{T})(x::AbstractIrrational, r::RoundingMode) where T<:Union{Float32,Float64}
function _irrational_to_float(::Type{T}, x::AbstractIrrational, r::RoundingMode) where T<:Union{Float32,Float64}
setprecision(BigFloat, 256) do
T(BigFloat(x)::BigFloat, r)
end
end
(::Type{T})(x::AbstractIrrational, r::RoundingMode) where {T<:Union{Float32,Float64}} = _irrational_to_float(T, x, r)

float(::Type{<:AbstractIrrational}) = Float64

Expand Down Expand Up @@ -107,14 +118,18 @@ end
<=(x::AbstractFloat, y::AbstractIrrational) = x < y

# Irrational vs Rational
@assume_effects :total function rationalize(::Type{T}, x::AbstractIrrational; tol::Real=0) where T
function _rationalize_irrational(::Type{T}, x::AbstractIrrational, tol::Real) where {T<:Integer}
return rationalize(T, big(x), tol=tol)
end
@assume_effects :total function lessrational(rx::Rational{<:Integer}, x::AbstractIrrational)
# an @assume_effects :total version of `<` for determining if the rationalization of
# an irrational number required rounding up or down
function rationalize(::Type{T}, x::AbstractIrrational; tol::Real=0) where {T<:Integer}
return _rationalize_irrational(T, x, tol)
end
function _lessrational(rx::Rational, x::AbstractIrrational)
return rx < big(x)
end
function lessrational(rx::Rational, x::AbstractIrrational)
return _lessrational(rx, x)
end
function <(x::AbstractIrrational, y::Rational{T}) where T
T <: Unsigned && x < 0.0 && return true
rx = rationalize(T, x)
Expand Down
141 changes: 102 additions & 39 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,21 @@ function find_package(arg)
return locate_package(pkg, env)
end

# is there a better/faster ground truth?
function is_stdlib(pkgid::PkgId)
pkgid.name in readdir(Sys.STDLIB) || return false
stdlib_root = joinpath(Sys.STDLIB, pkgid.name)
project_file = locate_project_file(stdlib_root)
if project_file isa String
d = parsed_toml(project_file)
uuid = get(d, "uuid", nothing)
if uuid !== nothing
return UUID(uuid) == pkgid.uuid
end
end
return false
end

"""
Base.identify_package_env(name::String)::Union{Tuple{PkgId, String}, Nothing}
Base.identify_package_env(where::Union{Module,PkgId}, name::String)::Union{Tuple{PkgId, String} Nothing}
Expand Down Expand Up @@ -333,6 +348,12 @@ function identify_package_env(where::PkgId, name::String)
end
break # found in implicit environment--return "not found"
end
if pkg_env === nothing && is_stdlib(where)
# if not found it could be that manifests are from a different julia version/commit
# where stdlib dependencies have changed, so look up deps based on the stdlib Project.toml
# as a fallback
pkg_env = identify_stdlib_project_dep(where, name)
end
end
if cache !== nothing
cache.identified_where[(where, name)] = pkg_env
Expand All @@ -359,6 +380,22 @@ function identify_package_env(name::String)
return pkg_env
end

function identify_stdlib_project_dep(stdlib::PkgId, depname::String)
@debug """
Stdlib $(repr("text/plain", stdlib)) is trying to load `$depname`
which is not listed as a dep in the load path manifests, so resorting to search
in the stdlib Project.tomls for true deps"""
stdlib_projfile = locate_project_file(joinpath(Sys.STDLIB, stdlib.name))
stdlib_projfile === nothing && return nothing
found = explicit_project_deps_get(stdlib_projfile, depname)
if found !== nothing
@debug "$(repr("text/plain", stdlib)) indeed depends on $depname in project $stdlib_projfile"
pkgid = PkgId(found, depname)
return pkgid, stdlib_projfile
end
return nothing
end

_nothing_or_first(x) = x === nothing ? nothing : first(x)

"""
Expand Down Expand Up @@ -499,6 +536,8 @@ package root.
To get the root directory of the package that implements the current module
the form `pkgdir(@__MODULE__)` can be used.

If an extension module is given, the root of the parent package is returned.

```julia-repl
julia> pkgdir(Foo)
"/path/to/Foo.jl"
Expand All @@ -514,7 +553,19 @@ function pkgdir(m::Module, paths::String...)
rootmodule = moduleroot(m)
path = pathof(rootmodule)
path === nothing && return nothing
return joinpath(dirname(dirname(path)), paths...)
original = path
path, base = splitdir(dirname(path))
if base == "src"
# package source in `../src/Foo.jl`
elseif base == "ext"
# extension source in `../ext/FooExt.jl`
elseif basename(path) == "ext"
# extension source in `../ext/FooExt/FooExt.jl`
path = dirname(path)
else
error("Unexpected path structure for module source: $original")
end
return joinpath(path, paths...)
end

function get_pkgversion_from_path(path)
Expand Down Expand Up @@ -827,14 +878,14 @@ function explicit_manifest_deps_get(project_file::String, where::PkgId, name::St
entry = entry::Dict{String, Any}
uuid = get(entry, "uuid", nothing)::Union{String, Nothing}
uuid === nothing && continue
# deps is either a list of names (deps = ["DepA", "DepB"]) or
# a table of entries (deps = {"DepA" = "6ea...", "DepB" = "55d..."}
deps = get(entry, "deps", nothing)::Union{Vector{String}, Dict{String, Any}, Nothing}
if UUID(uuid) === where.uuid
found_where = true
# deps is either a list of names (deps = ["DepA", "DepB"]) or
# a table of entries (deps = {"DepA" = "6ea...", "DepB" = "55d..."}
deps = get(entry, "deps", nothing)::Union{Vector{String}, Dict{String, Any}, Nothing}
if deps isa Vector{String}
found_name = name in deps
break
found_name && @goto done
elseif deps isa Dict{String, Any}
deps = deps::Dict{String, Any}
for (dep, uuid) in deps
Expand All @@ -853,30 +904,33 @@ function explicit_manifest_deps_get(project_file::String, where::PkgId, name::St
return PkgId(UUID(uuid), name)
end
exts = extensions[where.name]::Union{String, Vector{String}}
weakdeps = get(entry, "weakdeps", nothing)::Union{Vector{String}, Dict{String, Any}, Nothing}
if (exts isa String && name == exts) || (exts isa Vector{String} && name in exts)
weakdeps = get(entry, "weakdeps", nothing)::Union{Vector{String}, Dict{String, Any}, Nothing}
if weakdeps !== nothing
if weakdeps isa Vector{String}
found_name = name in weakdeps
break
elseif weakdeps isa Dict{String, Any}
weakdeps = weakdeps::Dict{String, Any}
for (dep, uuid) in weakdeps
uuid::String
if dep === name
return PkgId(UUID(uuid), name)
for deps′ in [weakdeps, deps]
if deps′ !== nothing
if deps′ isa Vector{String}
found_name = name in deps′
found_name && @goto done
elseif deps′ isa Dict{String, Any}
deps′ = deps′::Dict{String, Any}
for (dep, uuid) in deps′
uuid::String
if dep === name
return PkgId(UUID(uuid), name)
end
end
end
end
end
end
end
# `name` is not an ext, do standard lookup as if this was the parent
return identify_package(PkgId(UUID(uuid), dep_name), name)
end
end
end
end
end
@label done
found_where || return nothing
found_name || return PkgId(name)
# Only reach here if deps was not a dict which mean we have a unique name for the dep
Expand Down Expand Up @@ -1211,12 +1265,13 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi
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)
weakdeps = get(Dict{String, Any}, d_proj, "weakdeps")::Union{Vector{String}, Dict{String,Any}}
deps = get(Dict{String, Any}, d_proj, "deps")::Union{Vector{String}, Dict{String,Any}}
if weakdeps isa Dict{String,Any} && deps isa Dict{String,Any}
total_deps = merge(weakdeps, deps)
return _insert_extension_triggers(pkg, extensions, total_deps)
end
end

Expand All @@ -1231,35 +1286,43 @@ function insert_extension_triggers(env::String, pkg::PkgId)::Union{Nothing,Missi
uuid = get(entry, "uuid", nothing)::Union{String, Nothing}
uuid === nothing && continue
if UUID(uuid) == pkg.uuid
weakdeps = get(entry, "weakdeps", nothing)::Union{Nothing, Vector{String}, Dict{String,Any}}
extensions = get(entry, "extensions", nothing)::Union{Nothing, Dict{String, Any}}
extensions === nothing && return
weakdeps === nothing && return
if weakdeps isa Dict{String, Any}
return _insert_extension_triggers(pkg, extensions, weakdeps)
weakdeps = get(Dict{String, Any}, entry, "weakdeps")::Union{Vector{String}, Dict{String,Any}}
deps = get(Dict{String, Any}, entry, "deps")::Union{Vector{String}, Dict{String,Any}}

function expand_deps_list(deps′::Vector{String})
deps′_expanded = Dict{String, Any}()
for (dep_name, entries) in d
dep_name in deps′ || continue
entries::Vector{Any}
if length(entries) != 1
error("expected a single entry for $(repr(dep_name)) in $(repr(project_file))")
end
entry = first(entries)::Dict{String, Any}
uuid = entry["uuid"]::String
deps′_expanded[dep_name] = uuid
end
return deps′_expanded
end

d_weakdeps = Dict{String, Any}()
for (dep_name, entries) in d
dep_name in weakdeps || continue
entries::Vector{Any}
if length(entries) != 1
error("expected a single entry for $(repr(dep_name)) in $(repr(project_file))")
end
entry = first(entries)::Dict{String, Any}
uuid = entry["uuid"]::String
d_weakdeps[dep_name] = uuid
if weakdeps isa Vector{String}
weakdeps = expand_deps_list(weakdeps)
end
@assert length(d_weakdeps) == length(weakdeps)
return _insert_extension_triggers(pkg, extensions, d_weakdeps)
if deps isa Vector{String}
deps = expand_deps_list(deps)
end

total_deps = merge(weakdeps, deps)
return _insert_extension_triggers(pkg, extensions, total_deps)
end
end
end
end
return nothing
end

function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}, weakdeps::Dict{String, Any})
function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}, totaldeps::Dict{String, Any})
for (ext, triggers) in extensions
triggers = triggers::Union{String, Vector{String}}
triggers isa String && (triggers = [triggers])
Expand All @@ -1273,7 +1336,7 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, Any}
push!(trigger1, gid)
for trigger in triggers
# TODO: Better error message if this lookup fails?
uuid_trigger = UUID(weakdeps[trigger]::String)
uuid_trigger = UUID(totaldeps[trigger]::String)
trigger_id = PkgId(uuid_trigger, trigger)
if !haskey(Base.loaded_modules, trigger_id) || haskey(package_locks, trigger_id)
trigger1 = get!(Vector{ExtensionId}, EXT_DORMITORY, trigger_id)
Expand Down
Loading