Skip to content

Backports for 1.12.0-beta4 #58369

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

Merged
merged 46 commits into from
Jun 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
a4844f4
Fix removal of globals with addrspaces in removeAddrspaces (#58322)
gbaraldi May 6, 2025
e4d859d
replace incorrect Method.deleted_world with more useful Method.dispat…
vtjnash May 6, 2025
a827082
extend Method.dispatch_status optimization to ml_matches_visitor also…
vtjnash May 7, 2025
996ce67
Base.get_extension & Dates.format made public (#58108)
GHTaarn May 8, 2025
e83cb43
Fix late gc lowering pass for vector intrinsics (#55864)
gbaraldi May 8, 2025
69fef33
codegen: remove readonly from abstract type calling convention (#58356)
vtjnash May 9, 2025
6728717
Add set to temporary roots to avoid O(N) check (#57961)
gbaraldi May 10, 2025
aa0e223
fix called-argument analysis for calls with splat (#58070)
JeffBezanson May 10, 2025
e26756d
Use a nonzero initial size with llvm::SmallSet.
maleadt May 13, 2025
dbdfa11
Bump LLVM 18 to include ORC patch. (#58398)
maleadt May 14, 2025
34e68cd
Fix signedness typo in world range update (#58390)
Keno May 13, 2025
e6371c9
Add `Compiler._verify_trim_world_age` for better printing
topolarity May 13, 2025
8feef52
fix `hasmethod` with kwargs to exclude positional arg names (#58410)
JeffBezanson May 14, 2025
c585f7e
[REPL] fix type confusion resulting in nonsensical errors (#58414)
vtjnash May 15, 2025
369ed27
[REPL] more reliable extension loading (#58415)
vtjnash May 15, 2025
b49b352
reflection: Label "dynamic invoke" in `code_typed` (#58411)
topolarity May 16, 2025
1d4065e
Add some precompiles to help loading time (#58436)
IanButterworth May 16, 2025
ab198f9
Fix layout flags for types that have oddly sized primitive type field…
gbaraldi May 19, 2025
916f4c2
avoid deadlock if crashing inside profile_wr_lock (#58452)
vtjnash May 19, 2025
e358d96
inference: prevent nested slot wrappers in abstract_call_builtin (#58…
aviatesk May 2, 2025
4dde5ec
🤖 [backports-release-1.12] Bump the LinearAlgebra stdlib from 4e7c3f4…
DilumAluthgeBot May 27, 2025
92dbdad
Fix tbaa usage when storing into heap allocated immutable structs (#5…
gbaraldi May 22, 2025
9fce636
Add some loading precompiles (#58473)
IanButterworth May 20, 2025
29c5883
Fail when precompiles fail during build on CI (and fix bad precompile…
IanButterworth May 21, 2025
3c4d207
MozillaCACerts: Update to 2025-05-20 (#58496)
eschnett May 22, 2025
f7136c9
don't strip keyword argument names with --strip-metadata (#58412)
JeffBezanson May 22, 2025
4d6fece
Don't filter `Core` methods from newly-inferred list (#58510)
topolarity May 27, 2025
4589ed0
avoid error just computing coverage of generated functions (#58488)
vtjnash May 27, 2025
a430f2e
docs: Add missing compat annotation for `isdefinedglobal` (#58542)
Keno May 28, 2025
1628ac8
fix isconst definition/accessor issues with binding partitions (#58261)
vtjnash May 14, 2025
10c7bd2
check that hashing of types does not foreigncall (`jl_type_hash` is c…
KristofferC May 14, 2025
e90c949
remove invalid precompile signature
KristofferC May 28, 2025
e05fc00
REPLCompletions: remove `builtin_tfunction(::REPLInterpreter)` overlo…
aviatesk May 31, 2025
7bea4c5
Make more types jl_static_show unambiguously (#58512)
xal-0 May 29, 2025
0f7d95e
remove workaround for controlling terminal behavior in repl_cmd (#58554)
vtjnash May 29, 2025
4fc2dea
fix Module for Base.jl for Revise.jl (#58549)
vtjnash May 29, 2025
6e8340b
make typejoin nothrow (#58578)
vtjnash May 30, 2025
505789c
Make `Ptr` values static-show w/ type-information (#58584)
topolarity May 30, 2025
9fd0ba2
Add world age hint for UndefVarError (#58572)
Keno May 31, 2025
a00e1b2
ensure Type{T} gets inserted with the right key when T is a TypeVar (…
vtjnash May 31, 2025
a6394cd
relax dispatch for the `IteratorSize` method for `Generator` (#58110)
nsajko May 31, 2025
6ab22e4
fix Markdown in the `Lockable` doc strings (#58603)
nsajko Jun 2, 2025
31151e5
Update readlines(::Cmd) test to not rely on the filesystem (#58607)
fredrikekre Jun 2, 2025
c8a4fd2
Re-enable tab completion of kwargs for large method tables (#58012)
mbauman Jun 2, 2025
9aa677c
Fix `linearize` of global with complex type (#58611)
mlechu Jun 3, 2025
59ad720
Fix completing positional arguments if a semicolon exists beyond the …
xal-0 May 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
15 changes: 8 additions & 7 deletions Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1402,8 +1402,9 @@ function matching_cache_argtypes(𝕃::AbstractLattice, mi::MethodInstance,
if slotid !== nothing
# using union-split signature, we may be able to narrow down `Conditional`
sigt = widenconst(slotid > nargs ? argtypes[slotid] : cache_argtypes[slotid])
thentype = tmeet(cnd.thentype, sigt)
elsetype = tmeet(cnd.elsetype, sigt)
⊓ = meet(𝕃)
thentype = cnd.thentype ⊓ sigt
elsetype = cnd.elsetype ⊓ sigt
if thentype === Bottom && elsetype === Bottom
# we accidentally proved this method match is impossible
# TODO bail out here immediately rather than just propagating Bottom ?
Expand Down Expand Up @@ -2119,7 +2120,7 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, (; fargs
else
thentype = form_partially_defined_struct(argtype2, argtypes[3])
if thentype !== nothing
elsetype = argtype2
elsetype = widenslotwrapper(argtype2)
if rt === Const(false)
thentype = Bottom
elseif rt === Const(true)
Expand Down Expand Up @@ -2210,7 +2211,7 @@ function abstract_call_unionall(interp::AbstractInterpreter, argtypes::Vector{An
return CallMeta(ret, Any, Effects(EFFECTS_TOTAL; nothrow), call.info)
end

function ci_abi(ci::CodeInstance)
function get_ci_abi(ci::CodeInstance)
def = ci.def
isa(def, ABIOverride) && return def.abi
(def::MethodInstance).specTypes
Expand All @@ -2233,7 +2234,7 @@ function abstract_invoke(interp::AbstractInterpreter, arginfo::ArgInfo, si::Stmt
if isa(method_or_ci, CodeInstance)
our_world = sv.world.this
argtype = argtypes_to_type(pushfirst!(argtype_tail(argtypes, 4), ft))
specsig = ci_abi(method_or_ci)
specsig = get_ci_abi(method_or_ci)
defdef = get_ci_mi(method_or_ci).def
exct = method_or_ci.exctype
if !hasintersect(argtype, specsig)
Expand Down Expand Up @@ -3229,7 +3230,7 @@ function abstract_eval_isdefined_expr(interp::AbstractInterpreter, e::Expr, ssta
elseif !vtyp.undef
rt = Const(true) # definitely assigned previously
else # form `Conditional` to refine `vtyp.undef` in the then branch
rt = Conditional(sym, vtyp.typ, vtyp.typ; isdefined=true)
rt = Conditional(sym, widenslotwrapper(vtyp.typ), widenslotwrapper(vtyp.typ); isdefined=true)
end
return RTEffects(rt, Union{}, EFFECTS_TOTAL)
end
Expand Down Expand Up @@ -3497,7 +3498,7 @@ function merge_override_effects!(interp::AbstractInterpreter, effects::Effects,
# N.B.: We'd like deleted_world here, but we can't add an appropriate edge at this point.
# However, in order to reach here in the first place, ordinary method lookup would have
# had to add an edge and appropriate invalidation trigger.
valid_worlds = WorldRange(m.primary_world, typemax(Int))
valid_worlds = WorldRange(m.primary_world, typemax(UInt))
if sv.world.this in valid_worlds
update_valid_age!(sv, valid_worlds)
else
Expand Down
2 changes: 1 addition & 1 deletion Compiler/src/cicache.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ end
function setindex!(cache::InternalCodeCache, ci::CodeInstance, mi::MethodInstance)
@assert ci.owner === cache.owner
m = mi.def
if isa(m, Method) && m.module != Core
if isa(m, Method)
ccall(:jl_push_newly_inferred, Cvoid, (Any,), ci)
end
ccall(:jl_mi_cache_insert, Cvoid, (Any, Any), mi, ci)
Expand Down
19 changes: 9 additions & 10 deletions Compiler/src/ssair/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ using .Compiler: ALWAYS_FALSE, ALWAYS_TRUE, argextype, BasicBlock, block_for_ins
CachedMethodTable, CFG, compute_basic_blocks, DebugInfoStream, Effects,
EMPTY_SPTYPES, getdebugidx, IncrementalCompact, InferenceResult, InferenceState,
InvalidIRError, IRCode, LimitedAccuracy, NativeInterpreter, scan_ssa_use!,
singleton_type, sptypes_from_meth_instance, StmtRange, Timings, VarState, widenconst
singleton_type, sptypes_from_meth_instance, StmtRange, Timings, VarState, widenconst,
get_ci_mi, get_ci_abi

@nospecialize

Expand Down Expand Up @@ -95,16 +96,14 @@ function print_stmt(io::IO, idx::Int, @nospecialize(stmt), code::Union{IRCode,Co
elseif isexpr(stmt, :invoke) && length(stmt.args) >= 2 && isa(stmt.args[1], Union{MethodInstance,CodeInstance})
stmt = stmt::Expr
# TODO: why is this here, and not in Base.show_unquoted
printstyled(io, " invoke "; color = :light_black)
mi = stmt.args[1]
if !(mi isa Core.MethodInstance)
mi = (mi::Core.CodeInstance).def
end
if isa(mi, Core.ABIOverride)
abi = mi.abi
mi = mi.def
ci = stmt.args[1]
if ci isa Core.CodeInstance
printstyled(io, " invoke "; color = :light_black)
mi = get_ci_mi(ci)
abi = get_ci_abi(ci)
else
abi = mi.specTypes
printstyled(io, "dynamic invoke "; color = :yellow)
abi = (ci::Core.MethodInstance).specTypes
end
show_unquoted(io, stmt.args[2], indent)
print(io, "(")
Expand Down
7 changes: 4 additions & 3 deletions Compiler/src/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ function adjust_effects(ipo_effects::Effects, def::Method, world::UInt)
valid_worlds = WorldRange(0, typemax(UInt))
if is_effect_overridden(override, :consistent)
# See note on `typemax(Int)` instead of `deleted_world` in adjust_effects!
override_valid_worlds = WorldRange(def.primary_world, typemax(Int))
override_valid_worlds = WorldRange(def.primary_world, typemax(UInt))
if world in override_valid_worlds
ipo_effects = Effects(ipo_effects; consistent=ALWAYS_TRUE)
valid_worlds = override_valid_worlds
Expand Down Expand Up @@ -1422,7 +1422,7 @@ function compile!(codeinfos::Vector{Any}, workqueue::CompilationQueue;
# if this method is generally visible to the current compilation world,
# and this is either the primary world, or not applicable in the primary world
# then we want to compile and emit this
if item.def.primary_world <= world <= item.def.deleted_world
if item.def.primary_world <= world
ci = typeinf_ext(interp, item, SOURCE_MODE_GET_SOURCE)
ci isa CodeInstance && push!(workqueue, ci)
end
Expand Down Expand Up @@ -1523,7 +1523,8 @@ function typeinf_ext_toplevel(methods::Vector{Any}, worlds::Vector{UInt}, trim_m
return codeinfos
end

verify_typeinf_trim(codeinfos::Vector{Any}, onlywarn::Bool) = invokelatest(verify_typeinf_trim, stdout, codeinfos, onlywarn)
const _verify_trim_world_age = RefValue{UInt}(typemax(UInt))
verify_typeinf_trim(codeinfos::Vector{Any}, onlywarn::Bool) = Core._call_in_world(_verify_trim_world_age[], verify_typeinf_trim, stdout, codeinfos, onlywarn)

function return_type(@nospecialize(f), t::DataType) # this method has a special tfunc
world = tls_world_age()
Expand Down
26 changes: 26 additions & 0 deletions Compiler/test/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1032,3 +1032,29 @@ end
const x57872 = "Hello"
f57872() = (Core.isdefinedglobal(@__MODULE__, Base.compilerbarrier(:const, :x57872)), x57872) # Extra globalref here to force world age bounds
@test f57872() == (true, "Hello")

@noinline f_mutateany(@nospecialize x) = x[] = 1
g_mutateany() = (y = Ref(0); f_mutateany(y); y[])
@test g_mutateany() === 1

# 58470 tbaa for unionselbyte of heap allocated mutables
mutable struct Wrapper58470
x::Union{Nothing,Int}
end

function findsomething58470(dict, inds)
default = Wrapper58470(nothing)
for i in inds
x = get(dict, i, default).x
if !isnothing(x)
return x
end
end
return nothing
end

let io = IOBuffer()
code_llvm(io, findsomething58470, Tuple{Dict{Int64, Wrapper58470}, Vector{Int}}, dump_module=true, raw=true, optimize=false)
str = String(take!(io))
@test !occursin("jtbaa_unionselbyte", str)
end
19 changes: 17 additions & 2 deletions Compiler/test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2262,12 +2262,18 @@ struct AliasableFields{S,T}
f1::S
f2::T
end
struct NullableAliasableFields{S,T}
f1::S
f2::T
NullableAliasableFields(f1::S, f2::T) where {S,T} = new{S,T}(f1, f2)
NullableAliasableFields(f1::S) where {S} = new{S,Union{}}(f1)
end
mutable struct AliasableConstField{S,T}
const f1::S
f2::T
end

import .Compiler:
using .Compiler:
InferenceLattice, MustAliasesLattice, InterMustAliasesLattice,
BaseInferenceLattice, SimpleInferenceLattice, IPOResultLattice, typeinf_lattice, ipo_lattice, optimizer_lattice

Expand All @@ -2280,7 +2286,7 @@ Compiler.optimizer_lattice(::MustAliasInterpreter) = SimpleInferenceLattice.inst
# lattice
# -------

import .Compiler: MustAlias, Const, PartialStruct, ⊑, tmerge
using .Compiler: MustAlias, Const, PartialStruct, ⊑, tmerge
let 𝕃ᵢ = InferenceLattice(MustAliasesLattice(BaseInferenceLattice.instance))
⊑(@nospecialize(a), @nospecialize(b)) = Compiler.:⊑(𝕃ᵢ, a, b)
tmerge(@nospecialize(a), @nospecialize(b)) = Compiler.tmerge(𝕃ᵢ, a, b)
Expand Down Expand Up @@ -2518,6 +2524,15 @@ jet509_hasitems(list) = length(list) >= 1
error("list is empty")
end |> only == Vector{Int}

# don't form nested slot wrappers
@test Base.infer_return_type((NullableAliasableFields{NullableAliasableFields},); interp=MustAliasInterpreter()) do x
y = getfield(x, :f1)
if isdefined(y, :f2) && isa(getfield(y, :f2), Int)
return getfield(y, :f2)
end
return 0
end == Int

# === constraint
# --------------

Expand Down
19 changes: 7 additions & 12 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ include(strcat(BUILDROOT, "version_git.jl")) # include($BUILDROOT/base/version_g
# a slightly more verbose fashion than usual, because we're running so early.
let os = ccall(:jl_get_UNAME, Any, ())
if os === :Darwin || os === :Apple
if Base.DARWIN_FRAMEWORK
if DARWIN_FRAMEWORK
push!(DL_LOAD_PATH, "@loader_path/Frameworks")
end
push!(DL_LOAD_PATH, "@loader_path")
Expand Down Expand Up @@ -306,8 +306,8 @@ a_method_to_overwrite_in_test() = inferencebarrier(1)
(this::IncludeInto)(mapexpr::Function, fname::AbstractString) = include(mapexpr, this.m, fname)

# Compatibility with when Compiler was in Core
@eval Core const Compiler = Main.Base.Compiler
@eval Compiler const fl_parse = Core.Main.Base.fl_parse
@eval Core const Compiler = $Base.Compiler
@eval Compiler const fl_parse = $Base.fl_parse

# External libraries vendored into Base
Core.println("JuliaSyntax/src/JuliaSyntax.jl")
Expand All @@ -323,13 +323,13 @@ if is_primary_base_module
# Profiling helper
# triggers printing the report and (optionally) saving a heap snapshot after a SIGINFO/SIGUSR1 profile request
# Needs to be in Base because Profile is no longer loaded on boot
function profile_printing_listener(cond::Base.AsyncCondition)
function profile_printing_listener(cond::AsyncCondition)
profile = nothing
try
while _trywait(cond)
profile = @something(profile, require_stdlib(PkgId(UUID("9abbd945-dff8-562f-b5e8-e1ebf5ef1b79"), "Profile")))::Module
invokelatest(profile.peek_report[])
if Base.get_bool_env("JULIA_PROFILE_PEEK_HEAP_SNAPSHOT", false) === true
if get_bool_env("JULIA_PROFILE_PEEK_HEAP_SNAPSHOT", false) === true
println(stderr, "Saving heap snapshot...")
fname = invokelatest(profile.take_heap_snapshot)
println(stderr, "Heap snapshot saved to `$(fname)`")
Expand All @@ -344,8 +344,8 @@ function profile_printing_listener(cond::Base.AsyncCondition)
end

function start_profile_listener()
cond = Base.AsyncCondition()
Base.uv_unref(cond.handle)
cond = AsyncCondition()
uv_unref(cond.handle)
t = errormonitor(Threads.@spawn(profile_printing_listener(cond)))
atexit() do
# destroy this callback when exiting
Expand Down Expand Up @@ -405,7 +405,6 @@ end
const _compiler_require_dependencies = Any[]
@Core.latestworld
for i = 1:length(_included_files)
isassigned(_included_files, i) || continue
(mod, file) = _included_files[i]
if mod === Compiler || parentmodule(mod) === Compiler || endswith(file, "/Compiler.jl")
_include_dependency!(_compiler_require_dependencies, true, mod, file, true, false)
Expand All @@ -421,7 +420,3 @@ end
@assert length(_compiler_require_dependencies) >= 15

end

# Ensure this file is also tracked
@assert !isassigned(_included_files, 1)
_included_files[1] = (parentmodule(Base), abspath(@__FILE__))
4 changes: 4 additions & 0 deletions base/Base_compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -384,5 +384,9 @@ Core._setparser!(fl_parse)

# Further definition of Base will happen in Base.jl if loaded.

# Ensure this file is also tracked
@assert !isassigned(_included_files, 1)
_included_files[1] = (@__MODULE__, ccall(:jl_prepend_cwd, Any, (Any,), "Base_compiler.jl"))

end # module Base
using .Base
15 changes: 4 additions & 11 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ stackframe_lineinfo_color() = repl_color("JULIA_STACKFRAME_LINEINFO_COLOR", :bol
stackframe_function_color() = repl_color("JULIA_STACKFRAME_FUNCTION_COLOR", :bold)

function repl_cmd(cmd, out)
shell = shell_split(get(ENV, "JULIA_SHELL", get(ENV, "SHELL", "/bin/sh")))
shell_name = Base.basename(shell[1])

# Immediately expand all arguments, so that typing e.g. ~/bin/foo works.
cmd.exec .= expanduser.(cmd.exec)

Expand Down Expand Up @@ -64,19 +61,15 @@ function repl_cmd(cmd, out)
cd(dir)
println(out, pwd())
else
@static if !Sys.iswindows()
if shell_name == "fish"
shell_escape_cmd = "begin; $(shell_escape_posixly(cmd)); and true; end"
else
shell_escape_cmd = "($(shell_escape_posixly(cmd))) && true"
end
if !Sys.iswindows()
shell = shell_split(get(ENV, "JULIA_SHELL", get(ENV, "SHELL", "/bin/sh")))
shell_escape_cmd = shell_escape_posixly(cmd)
cmd = `$shell -c $shell_escape_cmd`
end
try
run(ignorestatus(cmd))
catch
# Windows doesn't shell out right now (complex issue), so Julia tries to run the program itself
# Julia throws an exception if it can't find the program, but the stack trace isn't useful
# Julia throws an exception if it can't find the cmd (which may be the shell itself), but the stack trace isn't useful
lasterr = current_exceptions()
lasterr = ExceptionStack([(exception = e[1], backtrace = [] ) for e in lasterr])
invokelatest(display_error, lasterr)
Expand Down
3 changes: 3 additions & 0 deletions base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2796,6 +2796,9 @@ a value set.
If `allow_import` is `false`, the global variable must be defined inside `m`
and may not be imported from another module.

!!! compat "Julia 1.12"
This function requires Julia 1.12 or later.

See also [`@isdefined`](@ref).

# Examples
Expand Down
40 changes: 29 additions & 11 deletions base/errorshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -588,8 +588,6 @@ function show_method_candidates(io::IO, ex::MethodError, kwargs=[])
end
if ex.world < reinterpret(UInt, method.primary_world)
print(iob, " (method too new to be called from this world context.)")
elseif ex.world > reinterpret(UInt, method.deleted_world)
print(iob, " (method deleted before this world age.)")
end
println(iob)

Expand Down Expand Up @@ -1146,22 +1144,42 @@ function UndefVarError_hint(io::IO, ex::UndefVarError)
if isdefined(ex, :scope)
scope = ex.scope
if scope isa Module
bpart = Base.lookup_binding_partition(ex.world, GlobalRef(scope, var))
kind = Base.binding_kind(bpart)
if kind === Base.PARTITION_KIND_GLOBAL || kind === Base.PARTITION_KIND_UNDEF_CONST || kind == Base.PARTITION_KIND_DECLARED
bpart = lookup_binding_partition(ex.world, GlobalRef(scope, var))
kind = binding_kind(bpart)

# Get the current world's binding partition for comparison
curworld = tls_world_age()
cur_bpart = lookup_binding_partition(curworld, GlobalRef(scope, var))
cur_kind = binding_kind(cur_bpart)

# Track if we printed the "too new" message
printed_too_new = false

# Check if the binding exists in the current world but was undefined in the error's world
if kind === PARTITION_KIND_GUARD
if isdefinedglobal(scope, var)
print(io, "\nThe binding may be too new: running in world age $(ex.world), while current world is $(curworld).")
printed_too_new = true
else
print(io, "\nSuggestion: check for spelling errors or missing imports.")
end
elseif kind === PARTITION_KIND_GLOBAL || kind === PARTITION_KIND_UNDEF_CONST || kind == PARTITION_KIND_DECLARED
print(io, "\nSuggestion: add an appropriate import or assignment. This global was declared but not assigned.")
elseif kind === Base.PARTITION_KIND_FAILED
elseif kind === PARTITION_KIND_FAILED
print(io, "\nHint: It looks like two or more modules export different ",
"bindings with this name, resulting in ambiguity. Try explicitly ",
"importing it from a particular module, or qualifying the name ",
"with the module it should come from.")
elseif kind === Base.PARTITION_KIND_GUARD
print(io, "\nSuggestion: check for spelling errors or missing imports.")
elseif Base.is_some_explicit_imported(kind)
print(io, "\nSuggestion: this global was defined as `$(Base.partition_restriction(bpart).globalref)` but not assigned a value.")
elseif kind === Base.PARTITION_KIND_BACKDATED_CONST
elseif is_some_explicit_imported(kind)
print(io, "\nSuggestion: this global was defined as `$(partition_restriction(bpart).globalref)` but not assigned a value.")
elseif kind === PARTITION_KIND_BACKDATED_CONST
print(io, "\nSuggestion: define the const at top-level before running function that uses it (stricter Julia v1.12+ rule).")
end

# Check if binding kind changed between the error's world and current world
if !printed_too_new && kind !== cur_kind
print(io, "\nNote: the binding state changed since the error occurred (was: $(kind), now: $(cur_kind)).")
end
elseif scope === :static_parameter
print(io, "\nSuggestion: run Test.detect_unbound_args to detect method arguments that do not fully constrain a type parameter.")
elseif scope === :local
Expand Down
2 changes: 1 addition & 1 deletion base/generator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ IteratorSize(::Type{Any}) = SizeUnknown()

IteratorSize(::Type{<:Tuple}) = HasLength()
IteratorSize(::Type{<:AbstractArray{<:Any,N}}) where {N} = HasShape{N}()
IteratorSize(::Type{Generator{I,F}}) where {I,F} = IteratorSize(I)
IteratorSize(::Type{<:Generator{I}}) where {I} = (@isdefined I) ? IteratorSize(I) : SizeUnknown()

haslength(iter) = IteratorSize(iter) isa Union{HasShape, HasLength}

Expand Down
3 changes: 2 additions & 1 deletion base/hashing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ hash(x::Any) = hash(x, zero(UInt))
hash(w::WeakRef, h::UInt) = hash(w.value, h)

# Types can't be deleted, so marking as total allows the compiler to look up the hash
hash(T::Type, h::UInt) = hash_uint(3h - @assume_effects :total ccall(:jl_type_hash, UInt, (Any,), T))
@noinline _jl_type_hash(T::Type) = @assume_effects :total ccall(:jl_type_hash, UInt, (Any,), T)
hash(T::Type, h::UInt) = hash_uint(3h - _jl_type_hash(T))

## hashing general objects ##

Expand Down
Loading