Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
166c99b
allow specifying projects in a workspace more than one level under it…
KristofferC Oct 17, 2025
4b01fcb
update llvmcall docs, opaque pointers are now supported (#59873)
simeonschaub Oct 17, 2025
53eb2dc
fix accidental save (and restore) of sigmask when interpreting try (#…
vtjnash Oct 19, 2025
d526618
Type-assert `isfinite(::AbstractFloat)` (#59888)
JamesWrigley Oct 20, 2025
9ff6c46
Type-assert `DataType.layout` in some Base functions (#59886)
JamesWrigley Oct 20, 2025
8e5da22
absint: allow ad-hoc cancellation of concrete evaluation (#59908)
aviatesk Oct 20, 2025
d9aa8e5
reflection: enable `Base._which` with non-base `Compiler.MethodTableV…
aviatesk Oct 21, 2025
19ae89d
🤖 [backports-release-1.12] Bump LinearAlgebra stdlib 24f5e21 → 556750…
DilumAluthgeBot Oct 22, 2025
570139a
Set types of boxed variables in `abstract_eval_nonlinearized_foreignc…
JamesWrigley Oct 24, 2025
ec3201f
Update left-over reference to Core.GlobalMethods (#59976)
fingolfin Oct 29, 2025
e611d7f
[backports-release-1.12] OpenSSL: Update to version 3.5.4 (#59710) (#…
bluesmoon Oct 29, 2025
d0161e4
[backports-release-1.12] Bump LibCURL_jll to 8.15.0 (#59983)
bluesmoon Nov 1, 2025
f9733bd
Fix: waitall can throw when all tasks are done (#59905)
jakobnissen Oct 20, 2025
edf9fa7
Names docstring: compat & implicit using (#59937)
LilithHafner Oct 24, 2025
eda6a12
fix: TOML parsing of fractional seconds (#59999)
haakon-e Oct 31, 2025
8218435
inference: revisit all methods in cycle (#59974)
vtjnash Nov 1, 2025
2fc0ebd
REPL: make interactive precompiles test more robust (#60006)
IanButterworth Nov 1, 2025
6286cfd
fix `pointerarith_tfunc` for Const ptr (#60011)
oscardssmith Nov 1, 2025
f8f009d
Don't trigger full rebuild if git is dirty (#60023)
IanButterworth Nov 5, 2025
c53224f
fix waitall deadlock if any errors occur (#60030)
vtjnash Nov 5, 2025
fc0e312
Type-assert the return type of `collect(...)` in TOML (#59932)
JamesWrigley Nov 4, 2025
2e88e34
Markdown: don't allow space between parts of a link (#59977)
fingolfin Nov 7, 2025
4a79cf9
bump Pkg to latest 1.12
KristofferC Nov 8, 2025
c4448e2
Backport p7zip_jll infrastructure changes from f03e9c3
KristofferC Nov 8, 2025
84f859e
p7zip 17.7.0 (#60025)
nhz2 Nov 7, 2025
d9323c0
fix string completion with cursor in the middle of text
KristofferC Nov 5, 2025
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
13 changes: 7 additions & 6 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -872,11 +872,12 @@ function abstract_call_method_with_const_args(interp::AbstractInterpreter,
concrete_eval_result = nothing
if eligibility === :concrete_eval
concrete_eval_result = concrete_eval_call(interp, f, result, arginfo, sv, invokecall)
# if we don't inline the result of this concrete evaluation,
# give const-prop' a chance to inline a better method body
if !may_optimize(interp) || (
may_inline_concrete_result(concrete_eval_result.const_result::ConcreteResult) ||
concrete_eval_result.rt === Bottom) # unless this call deterministically throws and thus is non-inlineable
if (concrete_eval_result !== nothing && # allow external abstract interpreters to disable concrete evaluation ad-hoc
# if we don't inline the result of this concrete evaluation,
# give const-prop' a chance to inline a better method body
(!may_optimize(interp) ||
may_inline_concrete_result(concrete_eval_result.const_result::ConcreteResult) ||
concrete_eval_result.rt === Bottom)) # unless this call deterministically throws and thus is non-inlineable
return concrete_eval_result
end
# TODO allow semi-concrete interp for this call?
Expand Down Expand Up @@ -3457,7 +3458,7 @@ function abstract_eval_nonlinearized_foreigncall_name(
callresult = Future{CallMeta}()
i::Int = 1
nextstate::UInt8 = 0x0
local ai, res
local ai::Future, res::Future
function evalargs(interp, sv)
if nextstate === 0x1
@goto state1
Expand Down
2 changes: 1 addition & 1 deletion Compiler/src/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ function pointer_eltype(@nospecialize(ptr))
end

@nospecs function pointerarith_tfunc(𝕃::AbstractLattice, ptr, offset)
return ptr
return widenconst(ptr)
end
@nospecs function pointerref_tfunc(𝕃::AbstractLattice, a, i, align)
return pointer_eltype(a)
Expand Down
17 changes: 5 additions & 12 deletions Compiler/src/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -761,17 +761,10 @@ function type_annotate!(interp::AbstractInterpreter, sv::InferenceState)
end

function merge_call_chain!(::AbstractInterpreter, parent::InferenceState, child::InferenceState)
# add backedge of parent <- child
# then add all backedges of parent <- parent.parent
# update all cycleid to be in the same group
frames = parent.callstack::Vector{AbsIntState}
@assert child.callstack === frames
ancestorid = child.cycleid
while true
add_cycle_backedge!(parent, child)
parent.cycleid === ancestorid && break
child = parent
parent = cycle_parent(child)::InferenceState
end
# ensure that walking the callstack has the same cycleid (DAG)
for frameid = reverse(ancestorid:length(frames))
frame = frames[frameid]::InferenceState
Expand All @@ -782,7 +775,6 @@ function merge_call_chain!(::AbstractInterpreter, parent::InferenceState, child:
end

function add_cycle_backedge!(caller::InferenceState, frame::InferenceState)
update_valid_age!(caller, frame.world.valid_worlds)
backedge = (caller, caller.currpc)
contains_is(frame.cycle_backedges, backedge) || push!(frame.cycle_backedges, backedge)
return frame
Expand All @@ -801,9 +793,8 @@ end
# frame matching `mi` is encountered, then there is a cycle in the call graph
# (i.e. `mi` is a descendant callee of itself). Upon encountering this cycle,
# we "resolve" it by merging the call chain, which entails updating each intermediary
# frame's `cycleid` field and adding the appropriate backedges. Finally,
# we return `mi`'s pre-existing frame. If no cycles are found, `nothing` is
# returned instead.
# frame's `cycleid` field. Finally, we return `mi`'s pre-existing frame.
# If no cycles are found, `nothing` is returned instead.
function resolve_call_cycle!(interp::AbstractInterpreter, mi::MethodInstance, parent::AbsIntState)
# TODO (#48913) implement a proper recursion handling for irinterp:
# This works most of the time currently just because the irinterp code doesn't get used much with
Expand Down Expand Up @@ -992,6 +983,7 @@ function typeinf_edge(interp::AbstractInterpreter, method::Method, @nospecialize
result.ci_as_edge = edge_ci # set the edge for the inliner usage
VolatileInferenceResult(result)
end
isinferred || add_cycle_backedge!(caller, frame)
mresult[] = MethodCallResult(interp, caller, method, bestguess, exc_bestguess, effects,
edge, edgecycle, edgelimited, volatile_inf_result)
return true
Expand All @@ -1010,6 +1002,7 @@ function typeinf_edge(interp::AbstractInterpreter, method::Method, @nospecialize
update_valid_age!(caller, valid_worlds)
bestguess = frame.bestguess
exc_bestguess = refine_exception_type(frame.exc_bestguess, effects)
add_cycle_backedge!(caller, frame)
return Future(MethodCallResult(interp, caller, method, bestguess, exc_bestguess, effects, nothing, edgecycle, edgelimited))
end

Expand Down
7 changes: 7 additions & 0 deletions Compiler/test/effects.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1478,3 +1478,10 @@ let effects = Base.infer_effects((Core.SimpleVector,Int); optimize=false) do sve
end

@test Compiler.is_nothrow(Base.infer_effects(length, (Core.SimpleVector,)))


# https://github.com/JuliaLang/julia/issues/60009
function null_offset(offset)
Ptr{UInt8}(C_NULL) + offset
end
@test null_offset(Int(100)) == Ptr{UInt8}(UInt(100))
20 changes: 9 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,9 @@ endif

# private libraries, that are installed in $(prefix)/lib/julia
JL_PRIVATE_LIBS-0 := libccalltest libccalllazyfoo libccalllazybar libllvmcalltest
JL_PRIVATE_LIBS-1 := # libraries from USE_SYSTEM=1
JL_PRIVATE_EXES := 7z
JL_PRIVATE_TOOLS := lld$(EXE) dsymutil$(EXE)
ifeq ($(JULIA_BUILD_MODE),release)
JL_PRIVATE_LIBS-0 += libjulia-internal libjulia-codegen
else ifeq ($(JULIA_BUILD_MODE),debug)
Expand Down Expand Up @@ -325,9 +328,6 @@ endif
-$(INSTALL_M) $(wildcard $(build_private_libdir)/*.a) $(DESTDIR)$(private_libdir)/
-rm -f $(DESTDIR)$(private_libdir)/sys-o.a

# We have a single exception; we want 7z.dll to live in private_libexecdir,
# not bindir, so that 7z.exe can find it.
-mv $(DESTDIR)$(bindir)/7z.dll $(DESTDIR)$(private_libexecdir)/
-$(INSTALL_M) $(build_bindir)/libopenlibm.dll.a $(DESTDIR)$(libdir)/
-$(INSTALL_M) $(build_libdir)/libssp.dll.a $(DESTDIR)$(libdir)/
else
Expand Down Expand Up @@ -384,14 +384,12 @@ endif
done \
done
endif
# Install `7z` into private_libexecdir
$(INSTALL_M) $(build_bindir)/7z$(EXE) $(DESTDIR)$(private_libexecdir)/

# Install `lld` into private_libexecdir
$(INSTALL_M) $(build_depsbindir)/lld$(EXE) $(DESTDIR)$(private_libexecdir)/

# Install `dsymutil` into private_libexecdir/
$(INSTALL_M) $(build_depsbindir)/dsymutil$(EXE) $(DESTDIR)$(private_libexecdir)/
for exe in $(JL_PRIVATE_EXES) ; do \
$(INSTALL_M) $(build_private_libexecdir)/$$exe $(DESTDIR)$(private_libexecdir) || exit 1; \
done
for exe in $(JL_PRIVATE_TOOLS) ; do \
$(INSTALL_M) $(build_depsbindir)/$$exe $(DESTDIR)$(private_libexecdir) || exit 1; \
done

# Copy public headers
cp -R -L $(build_includedir)/julia/* $(DESTDIR)$(includedir)/julia
Expand Down
1 change: 1 addition & 0 deletions base/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
/uv_constants.jl
/version_git.jl
/version_git.jl.phony
/version_git_dirty
/userimg.jl
/JuliaSyntax
1 change: 1 addition & 0 deletions base/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -306,4 +306,5 @@ clean:
-rm -f $(BUILDDIR)/file_constants.jl
-rm -f $(BUILDDIR)/version_git.jl
-rm -f $(BUILDDIR)/version_git.jl.phony
-rm -f $(BUILDDIR)/version_git_dirty
-rm -f $(build_private_libdir)/lib*.$(SHLIB_EXT)*
2 changes: 0 additions & 2 deletions base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1396,8 +1396,6 @@ a tuple of types. All types, as well as the LLVM code, should be specified as li
not as variables or expressions (it may be necessary to use `@eval` to generate these
literals).
[Opaque pointers](https://llvm.org/docs/OpaquePointers.html) (written as `ptr`) are not allowed in the LLVM code.
See
[`test/llvmcall.jl`](https://github.com/JuliaLang/julia/blob/v$VERSION/test/llvmcall.jl)
for usage examples.
Expand Down
2 changes: 1 addition & 1 deletion base/float.jl
Original file line number Diff line number Diff line change
Expand Up @@ -709,7 +709,7 @@ See also: [`iszero`](@ref), [`isone`](@ref), [`isinf`](@ref), [`ismissing`](@ref
isnan(x::AbstractFloat) = (x != x)::Bool
isnan(x::Number) = false

isfinite(x::AbstractFloat) = !isnan(x - x)
isfinite(x::AbstractFloat) = !(isnan(x - x)::Bool)
isfinite(x::Real) = decompose(x)[3] != 0
isfinite(x::Integer) = true

Expand Down
51 changes: 38 additions & 13 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -667,20 +667,45 @@ function env_project_file(env::String)::Union{Bool,String}
end

function base_project(project_file)
base_dir = abspath(joinpath(dirname(project_file), ".."))
base_project_file = env_project_file(base_dir)
base_project_file isa String || return nothing
d = parsed_toml(base_project_file)
workspace = get(d, "workspace", nothing)::Union{Dict{String, Any}, Nothing}
if workspace === nothing
return nothing
end
projects = get(workspace, "projects", nothing)::Union{Vector{String}, Nothing, String}
projects === nothing && return nothing
if projects isa Vector && basename(dirname(project_file)) in projects
return base_project_file
home_dir = abspath(homedir())
project_dir = abspath(dirname(project_file))
current_dir = project_dir
# Only stop at home boundary if we started under home
started_in_home = startswith(project_dir, home_dir)

while true
parent_dir = dirname(current_dir)
# Stop if we've reached root
if parent_dir == current_dir
return nothing
end
# Stop if we started in home and have now left it
if started_in_home && !startswith(parent_dir, home_dir)
return nothing
end

base_project_file = env_project_file(parent_dir)
if base_project_file isa String
d = parsed_toml(base_project_file)
workspace = get(d, "workspace", nothing)::Union{Dict{String, Any}, Nothing}
if workspace !== nothing
projects = get(workspace, "projects", nothing)::Union{Vector{String}, Nothing, String}
if projects isa Vector
# Check if any project in the workspace matches the original project
workspace_root = dirname(base_project_file)
for project in projects
project_path = joinpath(workspace_root, project)
if isdir(project_path)
if samefile(project_path, project_dir)
return base_project_file
end
end
end
end
end
end
current_dir = parent_dir
end
return nothing
end

function project_deps_get(env::String, name::String)::Union{Nothing,PkgId}
Expand Down
19 changes: 17 additions & 2 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -261,14 +261,29 @@ function invoke_interp_compiler(interp, fname::Symbol, args...)
T = typeof(interp)
while true
Tname = typename(T).name
Tname === :Any && error("Expected Interpreter")
Tname === :Any && error("Expected AbstractInterpreter")
Tname === :AbstractInterpreter && break
T = supertype(T)
end
return getglobal(typename(T).module, fname)(args...)
end
end

function invoke_mt_compiler(mt, fname::Symbol, args...)
if mt === nothing
return invoke_default_compiler(fname, args...)
else
T = typeof(mt)
while true
Tname = typename(T).name
Tname === :Any && error("Expected MethodTableView")
Tname === :MethodTableView && break
T = supertype(T)
end
return getglobal(typename(T).module, fname)(args...)
end
end

"""
code_typed_by_type(types::Type{<:Tuple}; ...)
Expand Down Expand Up @@ -870,7 +885,7 @@ function _which(@nospecialize(tt::Type);
world::UInt=get_world_counter(),
raise::Bool=true)
world == typemax(UInt) && error("code reflection cannot be used from generated functions")
match, = invoke_default_compiler(:findsup_mt, tt, world, method_table)
match, = invoke_mt_compiler(method_table, :findsup_mt, tt, world, method_table)
if match === nothing
raise && error("no unique matching method found for the specified argument types")
return nothing
Expand Down
15 changes: 10 additions & 5 deletions base/runtime_internals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ If `all` is true, then the list also includes non-public names defined in the mo
deprecated names, and compiler-generated names.
If `imported` is true, then names explicitly imported from other modules
are also included.
If `usings` is true, then names explicitly imported via `using` are also included.
If `usings` is true, then names explicitly or implicitly imported via `using` are also included.
Names are returned in sorted order.
As a special case, all names defined in `Main` are considered \"public\",
Expand All @@ -110,6 +110,9 @@ since it is not idiomatic to explicitly mark names from `Main` as public.
`names` may return duplicate names. The duplication happens, e.g. if an `import`ed name
conflicts with an already existing identifier.
!!! compat "Julia 1.12"
The `usings` argument requires Julia 1.12 or later.
See also: [`Base.isexported`](@ref), [`Base.ispublic`](@ref), [`Base.@locals`](@ref), [`@__MODULE__`](@ref).
"""
names(m::Module; kwargs...) = sort!(unsorted_names(m; kwargs...))
Expand Down Expand Up @@ -543,8 +546,9 @@ alignment of the elements, not the whole object.
"""
function datatype_alignment(dt::DataType)
@_foldable_meta
dt.layout == C_NULL && throw(UndefRefError())
alignment = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).alignment
layout = dt.layout::Ptr{Cvoid}
layout == C_NULL && throw(UndefRefError())
alignment = unsafe_load(convert(Ptr{DataTypeLayout}, layout)).alignment
return Int(alignment)
end

Expand Down Expand Up @@ -627,8 +631,9 @@ Return the number of pointers in the layout of a datatype.
"""
function datatype_npointers(dt::DataType)
@_foldable_meta
dt.layout == C_NULL && throw(UndefRefError())
return unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).npointers
layout = dt.layout::Ptr{Cvoid}
layout == C_NULL && throw(UndefRefError())
return unsafe_load(convert(Ptr{DataTypeLayout}, layout)).npointers
end

"""
Expand Down
Loading