diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 1bdba2a5d8924..49149fde59691 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -243,6 +243,7 @@ function find_matching_methods(𝕃::AbstractLattice, for i in 1:length(split_argtypes) arg_n = split_argtypes[i]::Vector{Any} sig_n = argtypes_to_type(arg_n) + sig_n === Bottom && continue mt = ccall(:jl_method_table_for, Any, (Any,), sig_n) mt === nothing && return FailedMethodMatch("Could not identify method table for call") mt = mt::MethodTable @@ -506,7 +507,10 @@ function abstract_call_method(interp::AbstractInterpreter, return MethodCallResult(Any, false, false, nothing, Effects()) end sigtuple = unwrap_unionall(sig) - sigtuple isa DataType || return MethodCallResult(Any, false, false, nothing, Effects()) + sigtuple isa DataType || + return MethodCallResult(Any, false, false, nothing, Effects()) + all(@nospecialize(x) -> isvarargtype(x) || valid_as_lattice(x, true), sigtuple.parameters) || + return MethodCallResult(Union{}, false, false, nothing, EFFECTS_THROWS) # catch bad type intersections early if is_nospecializeinfer(method) sig = get_nospecializeinfer_sig(method, sig, sparams) @@ -1385,25 +1389,35 @@ function precise_container_type(interp::AbstractInterpreter, @nospecialize(itft) end if isa(tti, Union) utis = uniontypes(tti) - if any(@nospecialize(t) -> !isa(t, DataType) || !(t <: Tuple) || !isknownlength(t), utis) - return AbstractIterationResult(Any[Vararg{Any}], nothing, Effects()) - end - ltp = length((utis[1]::DataType).parameters) - for t in utis - if length((t::DataType).parameters) != ltp - return AbstractIterationResult(Any[Vararg{Any}], nothing) + # refine the Union to remove elements that are not valid tags for objects + filter!(@nospecialize(x) -> valid_as_lattice(x, true), utis) + if length(utis) == 0 + return AbstractIterationResult(Any[], nothing) # oops, this statement was actually unreachable + elseif length(utis) == 1 + tti = utis[1] + tti0 = rewrap_unionall(tti, tti0) + else + if any(@nospecialize(t) -> !isa(t, DataType) || !(t <: Tuple) || !isknownlength(t), utis) + return AbstractIterationResult(Any[Vararg{Any}], nothing, Effects()) end - end - result = Any[ Union{} for _ in 1:ltp ] - for t in utis - tps = (t::DataType).parameters - _all(valid_as_lattice, tps) || continue - for j in 1:ltp - result[j] = tmerge(result[j], rewrap_unionall(tps[j], tti0)) + ltp = length((utis[1]::DataType).parameters) + for t in utis + if length((t::DataType).parameters) != ltp + return AbstractIterationResult(Any[Vararg{Any}], nothing) + end + end + result = Any[ Union{} for _ in 1:ltp ] + for t in utis + tps = (t::DataType).parameters + for j in 1:ltp + @assert valid_as_lattice(tps[j], true) + result[j] = tmerge(result[j], rewrap_unionall(tps[j], tti0)) + end end + return AbstractIterationResult(result, nothing) end - return AbstractIterationResult(result, nothing) - elseif tti0 <: Tuple + end + if tti0 <: Tuple if isa(tti0, DataType) return AbstractIterationResult(Any[ p for p in tti0.parameters ], nothing) elseif !isa(tti, DataType) @@ -1667,7 +1681,7 @@ end return isa_condition(xt, ty, max_union_splitting) end @inline function isa_condition(@nospecialize(xt), @nospecialize(ty), max_union_splitting::Int) - tty_ub, isexact_tty = instanceof_tfunc(ty) + tty_ub, isexact_tty = instanceof_tfunc(ty, true) tty = widenconst(xt) if isexact_tty && !isa(tty_ub, TypeVar) tty_lb = tty_ub # TODO: this would be wrong if !isexact_tty, but instanceof_tfunc doesn't preserve this info @@ -1677,7 +1691,7 @@ end # `typeintersect` may be unable narrow down `Type`-type thentype = tty_ub end - valid_as_lattice(thentype) || (thentype = Bottom) + valid_as_lattice(thentype, true) || (thentype = Bottom) elsetype = typesubtract(tty, tty_lb, max_union_splitting) return ConditionalTypes(thentype, elsetype) end @@ -1923,7 +1937,7 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn ftβ€² = argtype_by_index(argtypes, 2) ft = widenconst(ftβ€²) ft === Bottom && return CallMeta(Bottom, EFFECTS_THROWS, NoCallInfo()) - (types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, 3)) + (types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, 3), false) isexact || return CallMeta(Any, Effects(), NoCallInfo()) unwrapped = unwrap_unionall(types) if types === Bottom || !(unwrapped isa DataType) || unwrapped.name !== Tuple.name @@ -2153,6 +2167,7 @@ function abstract_call_unknown(interp::AbstractInterpreter, @nospecialize(ft), end # non-constant function, but the number of arguments is known and the `f` is not a builtin or intrinsic atype = argtypes_to_type(arginfo.argtypes) + atype === Bottom && return CallMeta(Union{}, Union{}, EFFECTS_THROWS, NoCallInfo()) # accidentally unreachable return abstract_call_gf_by_type(interp, nothing, arginfo, si, atype, sv, max_methods) end @@ -2380,7 +2395,7 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp (; rt, effects) = abstract_eval_call(interp, e, vtypes, sv) t = rt elseif ehead === :new - t, isexact = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv)) + t, isexact = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv), true) ut = unwrap_unionall(t) consistent = ALWAYS_FALSE nothrow = false @@ -2444,7 +2459,7 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp end effects = Effects(EFFECTS_TOTAL; consistent, nothrow) elseif ehead === :splatnew - t, isexact = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv)) + t, isexact = instanceof_tfunc(abstract_eval_value(interp, e.args[1], vtypes, sv), true) nothrow = false # TODO: More precision if length(e.args) == 2 && isconcretedispatch(t) && !ismutabletype(t) at = abstract_eval_value(interp, e.args[2], vtypes, sv) diff --git a/base/compiler/abstractlattice.jl b/base/compiler/abstractlattice.jl index 3c6c874a9a09c..42c7579698b21 100644 --- a/base/compiler/abstractlattice.jl +++ b/base/compiler/abstractlattice.jl @@ -98,8 +98,10 @@ is_valid_lattice_norec(::InferenceLattice, @nospecialize(elem)) = isa(elem, Limi """ tmeet(𝕃::AbstractLattice, a, b::Type) -Compute the lattice meet of lattice elements `a` and `b` over the lattice `𝕃`. -If `𝕃` is `JLTypeLattice`, this is equivalent to type intersection. +Compute the lattice meet of lattice elements `a` and `b` over the lattice `𝕃`, +dropping any results that will not be inhabited at runtime. +If `𝕃` is `JLTypeLattice`, this is equivalent to type intersection plus the +elimination of results that have no concrete subtypes. Note that currently `b` is restricted to being a type (interpreted as a lattice element in the `JLTypeLattice` sub-lattice of `𝕃`). """ @@ -107,7 +109,7 @@ function tmeet end function tmeet(::JLTypeLattice, @nospecialize(a::Type), @nospecialize(b::Type)) ti = typeintersect(a, b) - valid_as_lattice(ti) || return Bottom + valid_as_lattice(ti, true) || return Bottom return ti end diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 3a8de06811cc2..28c10b75c158a 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -305,7 +305,7 @@ function stmt_effect_flags(𝕃ₒ::AbstractLattice, @nospecialize(stmt), @nospe elseif head === :new_opaque_closure length(args) < 4 && return (false, false, false) typ = argextype(args[1], src) - typ, isexact = instanceof_tfunc(typ) + typ, isexact = instanceof_tfunc(typ, true) isexact || return (false, false, false) βŠ‘(𝕃ₒ, typ, Tuple) || return (false, false, false) rt_lb = argextype(args[2], src) diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index 75e63f5c6b2e4..1302d81e23427 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -1202,7 +1202,7 @@ function handle_invoke_call!(todo::Vector{Pair{Int,Any}}, end function invoke_signature(argtypes::Vector{Any}) - ft, argtyps = widenconst(argtypes[2]), instanceof_tfunc(widenconst(argtypes[3]))[1] + ft, argtyps = widenconst(argtypes[2]), instanceof_tfunc(widenconst(argtypes[3]), false)[1] return rewrap_unionall(Tuple{ft, unwrap_unionall(argtyps).parameters...}, argtyps) end @@ -1450,8 +1450,9 @@ function handle_call!(todo::Vector{Pair{Int,Any}}, cases = compute_inlining_cases(info, flag, sig, state) cases === nothing && return nothing cases, all_covered, joint_effects = cases - handle_cases!(todo, ir, idx, stmt, argtypes_to_type(sig.argtypes), cases, - all_covered, joint_effects) + atype = argtypes_to_type(sig.argtypes) + atype === Union{} && return nothing # accidentally actually unreachable + handle_cases!(todo, ir, idx, stmt, atype, cases, all_covered, joint_effects) end function handle_match!(cases::Vector{InliningCase}, diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index afdc0fd0b9ab2..46a93009429b3 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -1705,7 +1705,7 @@ function adce_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing) else if is_known_call(stmt, typeassert, compact) && length(stmt.args) == 3 # nullify safe `typeassert` calls - ty, isexact = instanceof_tfunc(argextype(stmt.args[3], compact)) + ty, isexact = instanceof_tfunc(argextype(stmt.args[3], compact), true) if isexact && βŠ‘(𝕃ₒ, argextype(stmt.args[2], compact), ty) compact[idx] = nothing continue diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index e2773752c68e6..da3b40c709079 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -95,9 +95,9 @@ add_tfunc(throw, 1, 1, @nospecs((𝕃::AbstractLattice, x)->Bottom), 0) # if isexact is false, the actual runtime type may (will) be a subtype of t # if isconcrete is true, the actual runtime type is definitely concrete (unreachable if not valid as a typeof) # if istype is true, the actual runtime value will definitely be a type (e.g. this is false for Union{Type{Int}, Int}) -function instanceof_tfunc(@nospecialize(t), @nospecialize(troot) = t) +function instanceof_tfunc(@nospecialize(t), astag::Bool=false, @nospecialize(troot) = t) if isa(t, Const) - if isa(t.val, Type) && valid_as_lattice(t.val) + if isa(t.val, Type) && valid_as_lattice(t.val, astag) return t.val, true, isconcretetype(t.val), true end return Bottom, true, false, false # runtime throws on non-Type @@ -110,7 +110,7 @@ function instanceof_tfunc(@nospecialize(t), @nospecialize(troot) = t) return Bottom, true, false, false # literal Bottom or non-Type elseif isType(t) tp = t.parameters[1] - valid_as_lattice(tp) || return Bottom, true, false, false # runtime unreachable / throws on non-Type + valid_as_lattice(tp, astag) || return Bottom, true, false, false # runtime unreachable / throws on non-Type if troot isa UnionAll # Free `TypeVar`s inside `Type` has violated the "diagonal" rule. # Widen them before `UnionAll` rewraping to relax concrete constraint. @@ -119,7 +119,7 @@ function instanceof_tfunc(@nospecialize(t), @nospecialize(troot) = t) return tp, !has_free_typevars(tp), isconcretetype(tp), true elseif isa(t, UnionAll) tβ€² = unwrap_unionall(t) - tβ€²β€², isexact, isconcrete, istype = instanceof_tfunc(tβ€², rewrap_unionall(t, troot)) + tβ€²β€², isexact, isconcrete, istype = instanceof_tfunc(tβ€², astag, rewrap_unionall(t, troot)) tr = rewrap_unionall(tβ€²β€², t) if tβ€²β€² isa DataType && tβ€²β€².name !== Tuple.name && !has_free_typevars(tr) # a real instance must be within the declared bounds of the type, @@ -134,8 +134,8 @@ function instanceof_tfunc(@nospecialize(t), @nospecialize(troot) = t) end return tr, isexact, isconcrete, istype elseif isa(t, Union) - ta, isexact_a, isconcrete_a, istype_a = instanceof_tfunc(unwraptv(t.a), troot) - tb, isexact_b, isconcrete_b, istype_b = instanceof_tfunc(unwraptv(t.b), troot) + ta, isexact_a, isconcrete_a, istype_a = instanceof_tfunc(unwraptv(t.a), astag, troot) + tb, isexact_b, isconcrete_b, istype_b = instanceof_tfunc(unwraptv(t.b), astag, troot) isconcrete = isconcrete_a && isconcrete_b istype = istype_a && istype_b # most users already handle the Union case, so here we assume that @@ -155,9 +155,9 @@ end # ---------- @nospecs bitcast_tfunc(𝕃::AbstractLattice, t, x) = bitcast_tfunc(widenlattice(𝕃), t, x) -@nospecs bitcast_tfunc(::JLTypeLattice, t, x) = instanceof_tfunc(t)[1] +@nospecs bitcast_tfunc(::JLTypeLattice, t, x) = instanceof_tfunc(t, true)[1] @nospecs conversion_tfunc(𝕃::AbstractLattice, t, x) = conversion_tfunc(widenlattice(𝕃), t, x) -@nospecs conversion_tfunc(::JLTypeLattice, t, x) = instanceof_tfunc(t)[1] +@nospecs conversion_tfunc(::JLTypeLattice, t, x) = instanceof_tfunc(t, true)[1] add_tfunc(bitcast, 2, 2, bitcast_tfunc, 1) add_tfunc(sext_int, 2, 2, conversion_tfunc, 1) @@ -275,7 +275,7 @@ add_tfunc(checked_umul_int, 2, 2, chk_tfunc, 10) # ----------- @nospecs function llvmcall_tfunc(𝕃::AbstractLattice, fptr, rt, at, a...) - return instanceof_tfunc(rt)[1] + return instanceof_tfunc(rt, true)[1] end add_tfunc(Core.Intrinsics.llvmcall, 3, INT_INF, llvmcall_tfunc, 10) @@ -445,7 +445,7 @@ function sizeof_nothrow(@nospecialize(x)) return sizeof_nothrow(rewrap_unionall(xu.a, x)) && sizeof_nothrow(rewrap_unionall(xu.b, x)) end - t, exact, isconcrete = instanceof_tfunc(x) + t, exact, isconcrete = instanceof_tfunc(x, false) if t === Bottom # x must be an instance (not a Type) or is the Bottom type object x = widenconst(x) @@ -497,7 +497,7 @@ end end # Core.sizeof operates on either a type or a value. First check which # case we're in. - t, exact = instanceof_tfunc(x) + t, exact = instanceof_tfunc(x, false) if t !== Bottom # The value corresponding to `x` at runtime could be a type. # Normalize the query to ask about that type. @@ -657,7 +657,7 @@ function pointer_eltype(@nospecialize(ptr)) unw = unwrap_unionall(a) if isa(unw, DataType) && unw.name === Ptr.body.name T = unw.parameters[1] - valid_as_lattice(T) || return Bottom + valid_as_lattice(T, true) || return Bottom return rewrap_unionall(T, a) end end @@ -689,7 +689,7 @@ end if isa(unw, DataType) && unw.name === Ptr.body.name T = unw.parameters[1] # note: we could sometimes refine this to a PartialStruct if we analyzed `op(T, T)::T` - valid_as_lattice(T) || return Bottom + valid_as_lattice(T, true) || return Bottom return rewrap_unionall(Pair{T, T}, a) end end @@ -701,7 +701,7 @@ end unw = unwrap_unionall(a) if isa(unw, DataType) && unw.name === Ptr.body.name T = unw.parameters[1] - valid_as_lattice(T) || return Bottom + valid_as_lattice(T, true) || return Bottom return rewrap_unionall(ccall(:jl_apply_cmpswap_type, Any, (Any,), T), a) end end @@ -805,7 +805,7 @@ end add_tfunc(typeof, 1, 1, typeof_tfunc, 1) @nospecs function typeassert_tfunc(𝕃::AbstractLattice, v, t) - t = instanceof_tfunc(t)[1] + t = instanceof_tfunc(t, true)[1] t === Any && return v return tmeet(𝕃, v, t) end @@ -813,7 +813,7 @@ add_tfunc(typeassert, 2, 2, typeassert_tfunc, 4) @nospecs function typeassert_nothrow(𝕃::AbstractLattice, v, t) βŠ‘ = Core.Compiler.:βŠ‘(𝕃) - # ty, exact = instanceof_tfunc(t) + # ty, exact = instanceof_tfunc(t, true) # return exact && v βŠ‘ ty if (isType(t) && !has_free_typevars(t) && v βŠ‘ t.parameters[1]) || (isa(t, Const) && isa(t.val, Type) && v βŠ‘ t.val) @@ -823,7 +823,7 @@ add_tfunc(typeassert, 2, 2, typeassert_tfunc, 4) end @nospecs function isa_tfunc(𝕃::AbstractLattice, v, tt) - t, isexact = instanceof_tfunc(tt) + t, isexact = instanceof_tfunc(tt, true) if t === Bottom # check if t could be equivalent to typeof(Bottom), since that's valid in `isa`, but the set of `v` is empty # if `t` cannot have instances, it's also invalid on the RHS of isa @@ -863,8 +863,8 @@ add_tfunc(isa, 2, 2, isa_tfunc, 1) end @nospecs function subtype_tfunc(𝕃::AbstractLattice, a, b) - a, isexact_a = instanceof_tfunc(a) - b, isexact_b = instanceof_tfunc(b) + a, isexact_a = instanceof_tfunc(a, false) + b, isexact_b = instanceof_tfunc(b, false) if !has_free_typevars(a) && !has_free_typevars(b) if a <: b if isexact_b || a === Bottom @@ -1216,31 +1216,36 @@ end return Bottom end if nf == 1 - return rewrap_unionall(unwrapva(ftypes[1]), s00) - end - # union together types of all fields - t = Bottom - for i in 1:nf - _ft = ftypes[i] - setfield && isconst(s, i) && continue - t = tmerge(t, rewrap_unionall(unwrapva(_ft), s00)) - t === Any && break + fld = 1 + else + # union together types of all fields + t = Bottom + for i in 1:nf + _ft = unwrapva(ftypes[i]) + valid_as_lattice(_ft, true) || continue + setfield && isconst(s, i) && continue + t = tmerge(t, rewrap_unionall(_ft, s00)) + t === Any && break + end + return t end - return t + else + fld = _getfield_fieldindex(s, name) + fld === nothing && return Bottom end - fld = _getfield_fieldindex(s, name) - fld === nothing && return Bottom if s <: Tuple && fld >= nf && isvarargtype(ftypes[nf]) - return rewrap_unionall(unwrapva(ftypes[nf]), s00) - end - if fld < 1 || fld > nf - return Bottom - elseif setfield && isconst(s, fld) - return Bottom - end - R = ftypes[fld] - if isempty(s.parameters) - return R + R = unwrapva(ftypes[nf]) + else + if fld < 1 || fld > nf + return Bottom + elseif setfield && isconst(s, fld) + return Bottom + end + R = ftypes[fld] + valid_as_lattice(R, true) || return Bottom + if isempty(s.parameters) + return R + end end return rewrap_unionall(R, s00) end @@ -1375,7 +1380,7 @@ end T = _fieldtype_tfunc(𝕃, o, f, isconcretetype(o)) T === Bottom && return Bottom PT = Const(Pair) - return instanceof_tfunc(apply_type_tfunc(𝕃, PT, T, T))[1] + return instanceof_tfunc(apply_type_tfunc(𝕃, PT, T, T), true)[1] end function abstract_modifyfield!(interp::AbstractInterpreter, argtypes::Vector{Any}, si::StmtInfo, sv::AbsIntState) nargs = length(argtypes) @@ -1417,7 +1422,7 @@ end T = _fieldtype_tfunc(𝕃, o, f, isconcretetype(o)) T === Bottom && return Bottom PT = Const(ccall(:jl_apply_cmpswap_type, Any, (Any,), T) where T) - return instanceof_tfunc(apply_type_tfunc(𝕃, PT, T))[1] + return instanceof_tfunc(apply_type_tfunc(𝕃, PT, T), true)[1] end # we could use tuple_tfunc instead of widenconst, but `o` is mutable, so that is unlikely to be beneficial @@ -1449,7 +1454,7 @@ add_tfunc(replacefield!, 4, 6, replacefield!_tfunc, 3) fieldtype_nothrow(𝕃, rewrap_unionall(su.b, s0), name) end - s, exact = instanceof_tfunc(s0) + s, exact = instanceof_tfunc(s0, false) s === Bottom && return false # always return _fieldtype_nothrow(s, exact, name) end @@ -1514,7 +1519,7 @@ end fieldtype_tfunc(𝕃, rewrap_unionall(su.b, s0), name)) end - s, exact = instanceof_tfunc(s0) + s, exact = instanceof_tfunc(s0, false) s === Bottom && return Bottom return _fieldtype_tfunc(𝕃, s, name, exact) end @@ -1527,8 +1532,8 @@ end tb0 = _fieldtype_tfunc(𝕃, rewrap_unionall(u.b, s), name, exact) ta0 βŠ‘ tb0 && return tb0 tb0 βŠ‘ ta0 && return ta0 - ta, exacta, _, istypea = instanceof_tfunc(ta0) - tb, exactb, _, istypeb = instanceof_tfunc(tb0) + ta, exacta, _, istypea = instanceof_tfunc(ta0, false) + tb, exactb, _, istypeb = instanceof_tfunc(tb0, false) if exact && exacta && exactb return Const(Union{ta, tb}) end @@ -1662,7 +1667,7 @@ function apply_type_nothrow(𝕃::AbstractLattice, argtypes::Vector{Any}, @nospe return false end else - T, exact, _, istype = instanceof_tfunc(ai) + T, exact, _, istype = instanceof_tfunc(ai, false) if T === Bottom if !(u.var.lb === Union{} && u.var.ub === Any) return false @@ -1726,9 +1731,7 @@ const _tvarnames = Symbol[:_A, :_B, :_C, :_D, :_E, :_F, :_G, :_H, :_I, :_J, :_K, end end if largs == 1 # Union{T} --> T - u1 = typeintersect(widenconst(args[1]), Union{Type,TypeVar}) - valid_as_lattice(u1) || return Bottom - return u1 + return tmeet(widenconst(args[1]), Union{Type,TypeVar}) end hasnonType && return Type ty = Union{} @@ -1813,7 +1816,7 @@ const _tvarnames = Symbol[:_A, :_B, :_C, :_D, :_E, :_F, :_G, :_H, :_I, :_J, :_K, elseif !isT # if we didn't have isType to compute ub directly, try to use instanceof_tfunc to refine this guess ai_w = widenconst(ai) - ub = ai_w isa Type && ai_w <: Type ? instanceof_tfunc(ai)[1] : Any + ub = ai_w isa Type && ai_w <: Type ? instanceof_tfunc(ai, false)[1] : Any end if istuple # in the last parameter of a Tuple type, if the upper bound is Any @@ -2012,7 +2015,7 @@ function array_elmtype(@nospecialize ary) end if isa(a, DataType) T = a.parameters[1] - valid_as_lattice(T) || return Bottom + valid_as_lattice(T, true) || return Bottom return rewrap_unionall(T, a0) end end @@ -2542,7 +2545,7 @@ function intrinsic_nothrow(f::IntrinsicFunction, argtypes::Vector{Any}) return argtypes[1] βŠ‘ Array end if f === Intrinsics.bitcast - ty, isexact, isconcrete = instanceof_tfunc(argtypes[1]) + ty, isexact, isconcrete = instanceof_tfunc(argtypes[1], true) xty = widenconst(argtypes[2]) return isconcrete && isprimitivetype(ty) && isprimitivetype(xty) && Core.sizeof(ty) === Core.sizeof(xty) end @@ -2551,12 +2554,12 @@ function intrinsic_nothrow(f::IntrinsicFunction, argtypes::Vector{Any}) Intrinsics.sitofp, Intrinsics.fptrunc, Intrinsics.fpext) # If !isconcrete, `ty` may be Union{} at runtime even if we have # isprimitivetype(ty). - ty, isexact, isconcrete = instanceof_tfunc(argtypes[1]) + ty, isexact, isconcrete = instanceof_tfunc(argtypes[1], true) xty = widenconst(argtypes[2]) return isconcrete && isprimitivetype(ty) && isprimitivetype(xty) end if f === Intrinsics.have_fma - ty, isexact, isconcrete = instanceof_tfunc(argtypes[1]) + ty, isexact, isconcrete = instanceof_tfunc(argtypes[1], true) return isconcrete && isprimitivetype(ty) end # The remaining intrinsics are math/bits/comparison intrinsics. They work on all @@ -2694,6 +2697,10 @@ function abstract_applicable(interp::AbstractInterpreter, argtypes::Vector{Any}, isvarargtype(argtypes[2]) && return CallMeta(Bool, EFFECTS_UNKNOWN, NoCallInfo()) argtypes = argtypes[2:end] atype = argtypes_to_type(argtypes) + if atype === Union{} + rt = Union{} # accidentally unreachable code + return CallMeta(rt, EFFECTS_TOTAL, NoCallInfo()) + end matches = find_matching_methods(typeinf_lattice(interp), argtypes, atype, method_table(interp), InferenceParams(interp).max_union_splitting, max_methods) if isa(matches, FailedMethodMatch) @@ -2746,7 +2753,7 @@ function _hasmethod_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, sv else return CallMeta(Any, Effects(), NoCallInfo()) end - (types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, typeidx)) + (types, isexact, isconcrete, istype) = instanceof_tfunc(argtype_by_index(argtypes, typeidx), false) isexact || return CallMeta(Bool, Effects(), NoCallInfo()) unwrapped = unwrap_unionall(types) if types === Bottom || !(unwrapped isa DataType) || unwrapped.name !== Tuple.name diff --git a/base/compiler/typelattice.jl b/base/compiler/typelattice.jl index 324f2b600cc44..df6022609d612 100644 --- a/base/compiler/typelattice.jl +++ b/base/compiler/typelattice.jl @@ -607,7 +607,7 @@ end if ti === widev return v end - valid_as_lattice(ti) || return Bottom + valid_as_lattice(ti, true) || return Bottom if widev <: Tuple new_fields = Vector{Any}(undef, length(v.fields)) for i = 1:length(new_fields) @@ -631,7 +631,7 @@ end return v end ti = typeintersect(widev, t) - valid_as_lattice(ti) || return Bottom + valid_as_lattice(ti, true) || return Bottom return PartialOpaque(ti, v.env, v.parent, v.source) end return tmeet(widenlattice(lattice), v, t) diff --git a/base/compiler/typeutils.jl b/base/compiler/typeutils.jl index 2ecc077228264..4d2a2c1a5015a 100644 --- a/base/compiler/typeutils.jl +++ b/base/compiler/typeutils.jl @@ -54,7 +54,12 @@ has_extended_info(@nospecialize x) = (!isa(x, Type) && !isvarargtype(x)) || isTy # certain combinations of `a` and `b` where one/both isa/are `Union`/`UnionAll` type(s)s. isnotbrokensubtype(@nospecialize(a), @nospecialize(b)) = (!iskindtype(b) || !isType(a) || hasuniquerep(a.parameters[1]) || b <: a) -argtypes_to_type(argtypes::Array{Any,1}) = Tuple{anymap(@nospecialize(a) -> isvarargtype(a) ? a : widenconst(a), argtypes)...} +function argtypes_to_type(argtypes::Array{Any,1}) + argtypes = anymap(@nospecialize(a) -> isvarargtype(a) ? a : widenconst(a), argtypes) + filter!(@nospecialize(x) -> !isvarargtype(x) || valid_as_lattice(unwrapva(x), true), argtypes) + all(@nospecialize(x) -> isvarargtype(x) || valid_as_lattice(x, true), argtypes) || return Bottom + return Tuple{argtypes...} +end function isknownlength(t::DataType) isvatuple(t) || return true @@ -95,12 +100,13 @@ end has_concrete_subtype(d::DataType) = d.flags & 0x0020 == 0x0020 # n.b. often computed only after setting the type and layout fields -# determine whether x is a valid lattice element tag +# determine whether x is a valid lattice element # For example, Type{v} is not valid if v is a value -# Accepts TypeVars also, since it assumes the user will rewrap it correctly -function valid_as_lattice(@nospecialize(x)) +# Accepts TypeVars and has_free_typevar also, since it assumes the user will rewrap it correctly +# If astag is true, then also requires that it be a possible type tag for a valid object +function valid_as_lattice(@nospecialize(x), astag::Bool=false) x === Bottom && false - x isa TypeVar && return valid_as_lattice(x.ub) + x isa TypeVar && return valid_as_lattice(x.ub, astag) x isa UnionAll && (x = unwrap_unionall(x)) if x isa Union # the Union constructor ensures this (and we'll recheck after @@ -111,6 +117,9 @@ function valid_as_lattice(@nospecialize(x)) if isType(x) p = x.parameters[1] p isa Type || p isa TypeVar || return false + elseif astag && isstructtype(x) + datatype_fieldtypes(x) # force computation of has_concrete_subtype to be updated now + return has_concrete_subtype(x) end return true end @@ -149,6 +158,7 @@ function compatible_vatuple(a::DataType, b::DataType) end # return an upper-bound on type `a` with type `b` removed +# and also any contents that are not valid type tags on any objects # such that `return <: a` && `Union{return, b} == Union{a, b}` function typesubtract(@nospecialize(a), @nospecialize(b), max_union_splitting::Int) if a <: b && isnotbrokensubtype(a, b) @@ -158,8 +168,8 @@ function typesubtract(@nospecialize(a), @nospecialize(b), max_union_splitting::I if isa(ua, Union) uua = typesubtract(rewrap_unionall(ua.a, a), b, max_union_splitting) uub = typesubtract(rewrap_unionall(ua.b, a), b, max_union_splitting) - return Union{valid_as_lattice(uua) ? uua : Union{}, - valid_as_lattice(uub) ? uub : Union{}} + return Union{valid_as_lattice(uua, true) ? uua : Union{}, + valid_as_lattice(uub, true) ? uub : Union{}} elseif a isa DataType ub = unwrap_unionall(b) if ub isa DataType diff --git a/base/docs/basedocs.jl b/base/docs/basedocs.jl index b45560287edd0..c6c59f496ea88 100644 --- a/base/docs/basedocs.jl +++ b/base/docs/basedocs.jl @@ -3299,6 +3299,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/expr.jl b/base/expr.jl index 75e54a2249508..284beed95c9a4 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -388,13 +388,14 @@ macro constprop(setting) end function constprop_setting(@nospecialize setting) + s = setting isa(setting, QuoteNode) && (setting = setting.value) if setting === :aggressive return :aggressive_constprop elseif setting === :none return :no_constprop end - throw(ArgumentError(LazyString("@constprop "), setting, "not supported")) + throw(ArgumentError(LazyString("`Base.@constprop ", s, "` not supported"))) end """ diff --git a/base/io.jl b/base/io.jl index bf58493ad27ff..5159b2e5f5208 100644 --- a/base/io.jl +++ b/base/io.jl @@ -747,11 +747,10 @@ end function write(io::IO, c::Char) u = bswap(reinterpret(UInt32, c)) - n = 1 + n = 0 while true - write(io, u % UInt8) + n += write(io, u % UInt8) (u >>= 8) == 0 && return n - n += 1 end end # write(io, ::AbstractChar) is not defined: implementations diff --git a/base/meta.jl b/base/meta.jl index 171ae574ab5ec..99683aac38a99 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -364,6 +364,19 @@ function _partially_inline!(@nospecialize(x), slot_replacements::Vector{Any}, x.edges .+= slot_offset return x end + if isa(x, Core.UpsilonNode) + if !isdefined(x, :val) + return x + end + return Core.UpsilonNode( + _partially_inline!(x.val, slot_replacements, type_signature, static_param_values, + slot_offset, statement_offset, boundscheck), + ) + end + if isa(x, Core.PhiCNode) + _partially_inline!(x.values, slot_replacements, type_signature, static_param_values, + slot_offset, statement_offset, boundscheck) + end if isa(x, Core.ReturnNode) # Unreachable doesn't have val defined if !isdefined(x, :val) diff --git a/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/md5 b/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/md5 new file mode 100644 index 0000000000000..4a0ebe571c2f4 --- /dev/null +++ b/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/md5 @@ -0,0 +1 @@ +7269046040e860f243cf379ad1b4291d diff --git a/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/sha512 b/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/sha512 new file mode 100644 index 0000000000000..46348fa21d5a3 --- /dev/null +++ b/deps/checksums/Pkg-0b3af4592d7158d4cba1132a9cc9df15e8e51706.tar.gz/sha512 @@ -0,0 +1 @@ +31853a2d083a576ddacf2e0318fc5f3ca982b8b7ce2da88ce0fb20617ff2e4adcb3973bcf0d793d131f61104418da0471dd23f7912c65e406881d76f2e0b6914 diff --git a/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 b/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 deleted file mode 100644 index 8132509853c1a..0000000000000 --- a/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/md5 +++ /dev/null @@ -1 +0,0 @@ -220272702d818b059c86d96e5d7b6483 diff --git a/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 b/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 deleted file mode 100644 index 38f3fc48e8ffb..0000000000000 --- a/deps/checksums/Pkg-6390ea92bf585e182c96cb5db7529c067874e5f5.tar.gz/sha512 +++ /dev/null @@ -1 +0,0 @@ -f87ae5aee2c875028cca1b6a3a2a6b494317c20b204ee25b0f62e4fa44ad7d74833e0d16ed0fe90747ed81bc1d075427f24f8820573b74335574ceaae14fda5b diff --git a/deps/checksums/openlibm b/deps/checksums/openlibm index 452abb133c671..22d35d23ea7aa 100644 --- a/deps/checksums/openlibm +++ b/deps/checksums/openlibm @@ -1,34 +1,34 @@ -OpenLibm.v0.8.1+2.aarch64-apple-darwin.tar.gz/md5/9ce53048e8944f6edff44f75b731229c -OpenLibm.v0.8.1+2.aarch64-apple-darwin.tar.gz/sha512/3a14e28db0656b47a473e19ca0afae1f8b72dd01e108d6b6cb52dc24fc03e4a43db867616b375369e82177bb274fbcfeb8f24b488ee68871e8da8463e9090adf -OpenLibm.v0.8.1+2.aarch64-linux-gnu.tar.gz/md5/8b284fe2905c3e5315291f5e5f27ca8b -OpenLibm.v0.8.1+2.aarch64-linux-gnu.tar.gz/sha512/d326181349ee7f74b73611cd71f933e93c38c11d6db9a1cd4fee49d1ac06c7f244f4cfc6ab373dd52909064117405b3d4fa39e5c626464c066ab53f1cd26dc4a -OpenLibm.v0.8.1+2.aarch64-linux-musl.tar.gz/md5/dc40ad1f2e53a3b914dcca364b6ead77 -OpenLibm.v0.8.1+2.aarch64-linux-musl.tar.gz/sha512/3779d8cd23c5987a15666e2160e40f5a6fc5e7d350c9e3c86d8af8c99515a8cb1f3b5e8438dae0f3cf0b5e1cb2c0cb74c5dd5a06c65e0c2a2382d86dacfaf9fb -OpenLibm.v0.8.1+2.armv6l-linux-gnueabihf.tar.gz/md5/7c9e56f6124b85e7dee74601f8c16abd -OpenLibm.v0.8.1+2.armv6l-linux-gnueabihf.tar.gz/sha512/a78e15177992025462d334a9d5b10b9c7f6710d77ac36056fe7a1cc3bc3fada87f16696366578cfa5f325d5f746639c41c5d80b4885814014d29556d63bd4c7c -OpenLibm.v0.8.1+2.armv6l-linux-musleabihf.tar.gz/md5/78d9e3178fdf93a35f7d2b0b00753dc6 -OpenLibm.v0.8.1+2.armv6l-linux-musleabihf.tar.gz/sha512/ff7b78786f7035eaa08770ddf7d4eb2984595a318c3ac4dfbe4091ca398e00638df2e77bc2ab5fd159defd0927d4fe46b7e824cf055fbae4860bfa12347e8c5b -OpenLibm.v0.8.1+2.armv7l-linux-gnueabihf.tar.gz/md5/7c9e56f6124b85e7dee74601f8c16abd -OpenLibm.v0.8.1+2.armv7l-linux-gnueabihf.tar.gz/sha512/a78e15177992025462d334a9d5b10b9c7f6710d77ac36056fe7a1cc3bc3fada87f16696366578cfa5f325d5f746639c41c5d80b4885814014d29556d63bd4c7c -OpenLibm.v0.8.1+2.armv7l-linux-musleabihf.tar.gz/md5/78d9e3178fdf93a35f7d2b0b00753dc6 -OpenLibm.v0.8.1+2.armv7l-linux-musleabihf.tar.gz/sha512/ff7b78786f7035eaa08770ddf7d4eb2984595a318c3ac4dfbe4091ca398e00638df2e77bc2ab5fd159defd0927d4fe46b7e824cf055fbae4860bfa12347e8c5b -OpenLibm.v0.8.1+2.i686-linux-gnu.tar.gz/md5/e9942dca99f024ae27876ea5ab1592a9 -OpenLibm.v0.8.1+2.i686-linux-gnu.tar.gz/sha512/406e39894a643bf99c493585fa631800bbbcd6c36aaa9e677de772f7ceaed93b462fdf797235174e22baf2f34c26527f400e282061954b34f05b389acaba1e29 -OpenLibm.v0.8.1+2.i686-linux-musl.tar.gz/md5/0037f2e2113282d49967eba72f215c4b -OpenLibm.v0.8.1+2.i686-linux-musl.tar.gz/sha512/96666332a814232084340791384505acf964064dba4f7b62db51a7ae4416237decb40318dc07b9a041547fd4ff77f204f42bc5c7f029e590af1ee1dd6196d843 -OpenLibm.v0.8.1+2.i686-w64-mingw32.tar.gz/md5/73193f2e5149d07008902adfbf1b74b2 -OpenLibm.v0.8.1+2.i686-w64-mingw32.tar.gz/sha512/e8202b59b8f922bcc908b8b8e6687a674faa701689f5c6175d83fea0bcc5d73f74bed37660e60406f37873dab1d8489e0fd1506294791adfa61a069555eababf -OpenLibm.v0.8.1+2.powerpc64le-linux-gnu.tar.gz/md5/01997fb48464f94f59f4708bd26eabc3 -OpenLibm.v0.8.1+2.powerpc64le-linux-gnu.tar.gz/sha512/1e1d8901fd3aab0948be5c387b8d5bd0db12766fe00bf800ee3100aa0d5973c7aa03ef9c9b4e34942e5e2b46b64035d7f8d7b070113db031d4611f2a7dd02ca3 -OpenLibm.v0.8.1+2.x86_64-apple-darwin.tar.gz/md5/6cb5a472d6c1446acfca11bb8f7283d6 -OpenLibm.v0.8.1+2.x86_64-apple-darwin.tar.gz/sha512/e52f399002544d94536c3bda742d3cc5b0995929d656eeb0e808954fb800fd8e5cfc0ab57279fbccab44fc33a1207ab345d78e685d519ff7f02cca8f554b9c06 -OpenLibm.v0.8.1+2.x86_64-linux-gnu.tar.gz/md5/e1c7dc61e98d5b8aa68de3462a2620a4 -OpenLibm.v0.8.1+2.x86_64-linux-gnu.tar.gz/sha512/fe6d74a2522d75374b87ac9746d444d75a768e069f24f3fbfc6a140aa9d073fa54e8899861f839e647b9261e660c5f2b5555f52fab39ef84a74685b632e89df9 -OpenLibm.v0.8.1+2.x86_64-linux-musl.tar.gz/md5/5fe8eb59d21732a80f432720419324b3 -OpenLibm.v0.8.1+2.x86_64-linux-musl.tar.gz/sha512/0d1b22ca01eda89caa1832b63b1d7ddafe0fedf5906680e817100e2176cbbae95f576409706a9ea1834bc692b72009f4fd244586df30228d18e626bf25fc040a -OpenLibm.v0.8.1+2.x86_64-unknown-freebsd.tar.gz/md5/2bcdf32fdef91433763e32be029814d9 -OpenLibm.v0.8.1+2.x86_64-unknown-freebsd.tar.gz/sha512/97854736fc8c797abd5a5c331e5795dfa9124ac108a76fc2bcac518f5750a08884717d611bb98222b13387bcd27e1c3f4ec841547859e87fafbbe8c7dcd7381a -OpenLibm.v0.8.1+2.x86_64-w64-mingw32.tar.gz/md5/e22079c6e610c9543cca0fb88495d989 -OpenLibm.v0.8.1+2.x86_64-w64-mingw32.tar.gz/sha512/67081bcf360a62eee3928bd1b9d5302ed29b4a176245721723692d5ef938a828379617847308f26a2c7bc0cb2d0dce129d4b8c65c0446c611126894c0aaa5ea8 +OpenLibm.v0.8.1+4.aarch64-apple-darwin.tar.gz/md5/f7f8947d276e50b58db7530e050062fd +OpenLibm.v0.8.1+4.aarch64-apple-darwin.tar.gz/sha512/9e28c02d1aa98fdff8e637c9d1a577325d76c098bc89837b5bd3a50ec05647ab8379893a7945d570907b82ef9446804a0065403b6ddec8ede4cb9b0acf5b27ea +OpenLibm.v0.8.1+4.aarch64-linux-gnu.tar.gz/md5/bf9e4bc08aa8488319724b9a3011be8b +OpenLibm.v0.8.1+4.aarch64-linux-gnu.tar.gz/sha512/773263ff709fbdbd07cde5049372175f7cf8fefa26a5fae0fdc48990886911e8c9bcfdb8b05158f38621c79a17e445ad73d41cc4186f6d9df84a3e8232a8a17d +OpenLibm.v0.8.1+4.aarch64-linux-musl.tar.gz/md5/eab078c285039562f65f8fc1d8d62fd9 +OpenLibm.v0.8.1+4.aarch64-linux-musl.tar.gz/sha512/c0b818d728f85ef1ed4231dc2a3bc78e95de9186829d12012b168505b6d6505e4732a379c67a5a3c37e40e048bbaadabc00d153383347e9f606fc9731ebb26d5 +OpenLibm.v0.8.1+4.armv6l-linux-gnueabihf.tar.gz/md5/c76f4ca7bbcd276e5769bd73bee00966 +OpenLibm.v0.8.1+4.armv6l-linux-gnueabihf.tar.gz/sha512/0a711684d1289c747ecadeee0fa1c8ca6067727a5ab5d531f7c30f998c8ee04803c6712067426c939f50698c15104724214eaa3953e522a6dc210c39954f2727 +OpenLibm.v0.8.1+4.armv6l-linux-musleabihf.tar.gz/md5/e072d09a671f98bede25cb0bd00a2fd4 +OpenLibm.v0.8.1+4.armv6l-linux-musleabihf.tar.gz/sha512/37a741e5f66ca4dc8c9358376afb562c7d2a1bb1fcbde2c9b555001a4e6faffc0446b5faff33aead192d4b2fc8cd45c8261b06cc40abec73e39dc63da932b8ab +OpenLibm.v0.8.1+4.armv7l-linux-gnueabihf.tar.gz/md5/c76f4ca7bbcd276e5769bd73bee00966 +OpenLibm.v0.8.1+4.armv7l-linux-gnueabihf.tar.gz/sha512/0a711684d1289c747ecadeee0fa1c8ca6067727a5ab5d531f7c30f998c8ee04803c6712067426c939f50698c15104724214eaa3953e522a6dc210c39954f2727 +OpenLibm.v0.8.1+4.armv7l-linux-musleabihf.tar.gz/md5/e072d09a671f98bede25cb0bd00a2fd4 +OpenLibm.v0.8.1+4.armv7l-linux-musleabihf.tar.gz/sha512/37a741e5f66ca4dc8c9358376afb562c7d2a1bb1fcbde2c9b555001a4e6faffc0446b5faff33aead192d4b2fc8cd45c8261b06cc40abec73e39dc63da932b8ab +OpenLibm.v0.8.1+4.i686-linux-gnu.tar.gz/md5/d8602652f0f347a16e39a869eb2ccb83 +OpenLibm.v0.8.1+4.i686-linux-gnu.tar.gz/sha512/b140032c96497c7e6626751b799598bd54f687af3976bc43ac7ddb6f490527dca64fd44a125da2f54d8ca3679ad53d2700d412ec4c2ddcfe7bfbfe719c0cfc05 +OpenLibm.v0.8.1+4.i686-linux-musl.tar.gz/md5/5d20637487e85b529e3901d129b586a7 +OpenLibm.v0.8.1+4.i686-linux-musl.tar.gz/sha512/b83742801cdfee62bf14bf66f4d20e42219899d431ab335c23f2943c00363c82ee2ab1b853ec421eb825dbe65899fc8f3a3c91c3d86c5e4891c60ddc981d0831 +OpenLibm.v0.8.1+4.i686-w64-mingw32.tar.gz/md5/6ba08a1d5b3aa21fa58618f9ea2a9b8d +OpenLibm.v0.8.1+4.i686-w64-mingw32.tar.gz/sha512/63bed0bc519fa87abae157b53f439f8b452720090780f306b62ff802b8f8ddc4b546899aad5b3e91dacdc3439b7a10a36080d34f09f072719f766c3cdb0baa82 +OpenLibm.v0.8.1+4.powerpc64le-linux-gnu.tar.gz/md5/c9c690ff59b202763ee901f22a798d69 +OpenLibm.v0.8.1+4.powerpc64le-linux-gnu.tar.gz/sha512/83a1e37a62dcff357836385f55f9410cf49b10445c8320b62381359557306c97f11773c508e816fb0bbd4de372b6666833e960921959b6dbb4c7c954e230004a +OpenLibm.v0.8.1+4.x86_64-apple-darwin.tar.gz/md5/bbe8f7a039ad3f07baca340112ea2e65 +OpenLibm.v0.8.1+4.x86_64-apple-darwin.tar.gz/sha512/89e578b7e8e56e7152c9f5881fbf51b33833f8e2143126212e60db262de5641573f33dea5b810575a39e21ec4fbaaa307a049d42e06970c7d4e052b97622938a +OpenLibm.v0.8.1+4.x86_64-linux-gnu.tar.gz/md5/94f42c769349c92987ed3bd9f35d96e0 +OpenLibm.v0.8.1+4.x86_64-linux-gnu.tar.gz/sha512/5e901618da26aa6f0f7d05ed1e5c538aea88cadb59b0efc7213203f1714e85aa0b6f0d463f2a4d367d2a8af36e37e7c353fdefbb98599fdc5bc182a6b93e4348 +OpenLibm.v0.8.1+4.x86_64-linux-musl.tar.gz/md5/462b9dfebd341f0c8bb33ba72f99f769 +OpenLibm.v0.8.1+4.x86_64-linux-musl.tar.gz/sha512/df84815a282a065e8fa33aa35ee29166a1119cd776f8812073e55521ca8c94f4bca679206b8a67ef69edbbb6ba6fca520d81626f687ca353a63146c4858ced80 +OpenLibm.v0.8.1+4.x86_64-unknown-freebsd.tar.gz/md5/f3642b29670e6216056a13f5da9e87b8 +OpenLibm.v0.8.1+4.x86_64-unknown-freebsd.tar.gz/sha512/613242d2f24b1dcc4b2bfd6f22ad66e9889f618ee685b50d9fdf33b9f3798fe503fc9e278f291118db70bacd54bd475f12554a4a56c60c369222fd23b3c5ba22 +OpenLibm.v0.8.1+4.x86_64-w64-mingw32.tar.gz/md5/59381a874c86a5ad5f3fb3b206587f64 +OpenLibm.v0.8.1+4.x86_64-w64-mingw32.tar.gz/sha512/3a8dd3ef46f15f78a34bdc37c5e26dcbf8522625457aa7c52dca21cbb967c5e39257216e5fc203ff57c9171b6c0f2e2ee9d6216c43b0254008f0e91318bb5f0e openlibm-ae2d91698508701c83cab83714d42a1146dccf85.tar.gz/md5/19408d70bf042a109e1c267a53740089 openlibm-ae2d91698508701c83cab83714d42a1146dccf85.tar.gz/sha512/9597fdcbc4af8369e6eecc3f8e86f251661cc64d236578f3ee8a6b39e77a47951446e1a0fe1151513da153e7ed17bf39aa5a36c32153d0d0400232bed2839e22 diff --git a/deps/openlibm.mk b/deps/openlibm.mk index f99cdade47b91..0656ede2a9c8b 100644 --- a/deps/openlibm.mk +++ b/deps/openlibm.mk @@ -6,7 +6,14 @@ $(eval $(call git-external,openlibm,OPENLIBM,,,$(BUILDDIR))) OPENLIBM_FLAGS := ARCH="$(ARCH)" REAL_ARCH="$(MARCH)" CC="$(CC)" FC="$(FC)" AR="$(AR)" OS="$(OS)" USECLANG=$(USECLANG) USEGCC=$(USEGCC) -$(BUILDDIR)/$(OPENLIBM_SRC_DIR)/build-compiled: $(BUILDDIR)/$(OPENLIBM_SRC_DIR)/source-extracted + +$(BUILDDIR)/$(OPENLIBM_SRC_DIR)/source-extracted/openlibm-stack-markings.patch-applied: $(BUILDDIR)/$(OPENLIBM_SRC_DIR)/source-extracted + mkdir -p $(dir $@) + cd $(SRCCACHE)/openlibm-$(OPENLIBM_VER) && \ + patch -p1 -f < $(SRCDIR)/patches/openlibm-stack-markings.patch + echo 1 > $@ + +$(BUILDDIR)/$(OPENLIBM_SRC_DIR)/build-compiled: $(BUILDDIR)/$(OPENLIBM_SRC_DIR)/source-extracted/openlibm-stack-markings.patch-applied $(MAKE) -C $(dir $<) $(OPENLIBM_FLAGS) $(MAKE_COMMON) echo 1 > $@ diff --git a/deps/patches/openlibm-stack-markings.patch b/deps/patches/openlibm-stack-markings.patch new file mode 100644 index 0000000000000..57bc7f4f28b7b --- /dev/null +++ b/deps/patches/openlibm-stack-markings.patch @@ -0,0 +1,69 @@ +From e2482c959e584d52c032af63d1073d2a4e57c345 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jakov=20Smoli=C4=87?= +Date: Mon, 5 Aug 2024 00:12:41 +0200 +Subject: [PATCH] Add stack markings for GNU to fmod assembly files (#307) + +This adds stack markings to the missing fmod .S files, otherwise the +final libopenlibm object file gets marked with an executable stack. + +Output when compiling from source on Gentoo Linux: + +``` + * QA Notice: The following files contain writable and executable sections + * Files with such sections will not work properly (or at all!) on some + * architectures/operating systems. A bug should be filed at + * https://bugs.gentoo.org/ to make sure the issue is fixed. + * For more information, see: + * + * https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart + * + * Please include the following list of files in your report: + * Note: Bugs should be filed for the respective maintainers + * of the package in question and not hardened@gentoo.org. + * RWX --- --- usr/lib64/libopenlibm.so.4.0 +``` +--- + amd64/e_fmod.S | 5 +++++ + amd64/e_fmodf.S | 5 +++++ + amd64/e_fmodl.S | 5 +++++ + 3 files changed, 15 insertions(+) + +diff --git a/amd64/e_fmod.S b/amd64/e_fmod.S +index 37cae391..d2c8ecd9 100644 +--- a/amd64/e_fmod.S ++++ b/amd64/e_fmod.S +@@ -49,3 +49,8 @@ ENTRY(fmod) + fstp %st + ret + END(fmod) ++ ++/* Enable stack protection */ ++#if defined(__ELF__) ++.section .note.GNU-stack,"",%progbits ++#endif +diff --git a/amd64/e_fmodf.S b/amd64/e_fmodf.S +index 197892e8..b045e735 100644 +--- a/amd64/e_fmodf.S ++++ b/amd64/e_fmodf.S +@@ -19,3 +19,8 @@ ENTRY(fmodf) + fstp %st + ret + END(fmodf) ++ ++/* Enable stack protection */ ++#if defined(__ELF__) ++.section .note.GNU-stack,"",%progbits ++#endif +diff --git a/amd64/e_fmodl.S b/amd64/e_fmodl.S +index 64be92f1..cab539d5 100644 +--- a/amd64/e_fmodl.S ++++ b/amd64/e_fmodl.S +@@ -45,3 +45,8 @@ ENTRY(fmodl) + fstp %st(1) + ret + END(fmodl) ++ ++/* Enable stack protection */ ++#if defined(__ELF__) ++.section .note.GNU-stack,"",%progbits ++#endif diff --git a/src/builtins.c b/src/builtins.c index 2fd57059f8ac2..a8285aab99953 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -1707,6 +1707,12 @@ static int references_name(jl_value_t *p, jl_typename_t *name, int affects_layou if (jl_is_uniontype(p)) return references_name(((jl_uniontype_t*)p)->a, name, affects_layout) || references_name(((jl_uniontype_t*)p)->b, name, affects_layout); + if (jl_is_vararg(p)) { + jl_value_t *T = ((jl_vararg_t*)p)->T; + jl_value_t *N = ((jl_vararg_t*)p)->N; + return (T && references_name(T, name, affects_layout)) || + (N && references_name(N, name, affects_layout)); + } if (jl_is_unionall(p)) return references_name((jl_value_t*)((jl_unionall_t*)p)->var->lb, name, 0) || references_name((jl_value_t*)((jl_unionall_t*)p)->var->ub, name, 0) || diff --git a/src/jltypes.c b/src/jltypes.c index dd26d1df06625..ee1684d0d4b05 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -1936,7 +1936,7 @@ static jl_value_t *inst_datatype_inner(jl_datatype_t *dt, jl_svec_t *p, jl_value // normalize types equal to wrappers (prepare for Typeofwrapper) jl_value_t *tw = extract_wrapper(pi); if (tw && tw != pi && (tn != jl_type_typename || jl_typeof(pi) == jl_typeof(tw)) && - jl_types_equal(pi, tw)) { + !jl_has_free_typevars(pi) && jl_types_equal(pi, tw)) { iparams[i] = tw; if (p) jl_gc_wb(p, tw); } @@ -2569,7 +2569,7 @@ jl_vararg_t *jl_wrap_vararg(jl_value_t *t, jl_value_t *n, int check, int nothrow if (valid) { t = normalize_unionalls(t); jl_value_t *tw = extract_wrapper(t); - if (tw && t != tw && jl_types_equal(t, tw)) + if (tw && t != tw && !jl_has_free_typevars(t) && jl_types_equal(t, tw)) t = tw; } } diff --git a/src/subtype.c b/src/subtype.c index f183cc9da21a9..5b326237e0dd2 100644 --- a/src/subtype.c +++ b/src/subtype.c @@ -39,20 +39,24 @@ extern "C" { // Union type decision points are discovered while the algorithm works. // If a new Union decision is encountered, the `more` flag is set to tell // the forall/exists loop to grow the stack. -// TODO: the stack probably needs to be artificially large because of some -// deeper problem (see #21191) and could be shrunk once that is fixed + +typedef struct jl_bits_stack_t { + uint32_t data[16]; + struct jl_bits_stack_t *next; +} jl_bits_stack_t; + typedef struct { int16_t depth; int16_t more; int16_t used; - uint32_t stack[100]; // stack of bits represented as a bit vector + jl_bits_stack_t stack; } jl_unionstate_t; typedef struct { int16_t depth; int16_t more; int16_t used; - void *stack; + uint8_t *stack; } jl_saved_unionstate_t; // Linked list storing the type variable environment. A new jl_varbinding_t @@ -120,37 +124,111 @@ static jl_varbinding_t *lookup(jl_stenv_t *e, jl_tvar_t *v) JL_GLOBALLY_ROOTED J } #endif +// union-stack tools + static int statestack_get(jl_unionstate_t *st, int i) JL_NOTSAFEPOINT { - assert(i >= 0 && i < sizeof(st->stack) * 8); + assert(i >= 0 && i <= 32767); // limited by the depth bit. // get the `i`th bit in an array of 32-bit words - return (st->stack[i>>5] & (1u<<(i&31))) != 0; + jl_bits_stack_t *stack = &st->stack; + while (i >= sizeof(stack->data) * 8) { + // We should have set this bit. + assert(stack->next); + stack = stack->next; + i -= sizeof(stack->data) * 8; + } + return (stack->data[i>>5] & (1u<<(i&31))) != 0; } static void statestack_set(jl_unionstate_t *st, int i, int val) JL_NOTSAFEPOINT { - assert(i >= 0 && i < sizeof(st->stack) * 8); + assert(i >= 0 && i <= 32767); // limited by the depth bit. + jl_bits_stack_t *stack = &st->stack; + while (i >= sizeof(stack->data) * 8) { + if (__unlikely(stack->next == NULL)) { + stack->next = (jl_bits_stack_t *)malloc(sizeof(jl_bits_stack_t)); + stack->next->next = NULL; + } + stack = stack->next; + i -= sizeof(stack->data) * 8; + } if (val) - st->stack[i>>5] |= (1u<<(i&31)); + stack->data[i>>5] |= (1u<<(i&31)); else - st->stack[i>>5] &= ~(1u<<(i&31)); + stack->data[i>>5] &= ~(1u<<(i&31)); +} + +#define has_next_union_state(e, R) ((((R) ? &(e)->Runions : &(e)->Lunions)->more) != 0) + +static int next_union_state(jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT +{ + jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; + if (state->more == 0) + return 0; + // reset `used` and let `pick_union_decision` clean the stack. + state->used = state->more; + statestack_set(state, state->used - 1, 1); + return 1; +} + +static int pick_union_decision(jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT +{ + jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; + if (state->depth >= state->used) { + statestack_set(state, state->used, 0); + state->used++; + } + int ui = statestack_get(state, state->depth); + state->depth++; + if (ui == 0) + state->more = state->depth; // memorize that this was the deepest available choice + return ui; } -#define push_unionstate(saved, src) \ - do { \ - (saved)->depth = (src)->depth; \ - (saved)->more = (src)->more; \ - (saved)->used = (src)->used; \ - (saved)->stack = alloca(((src)->used+7)/8); \ - memcpy((saved)->stack, &(src)->stack, ((src)->used+7)/8); \ +static jl_value_t *pick_union_element(jl_value_t *u JL_PROPAGATES_ROOT, jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT +{ + do { + if (pick_union_decision(e, R)) + u = ((jl_uniontype_t*)u)->b; + else + u = ((jl_uniontype_t*)u)->a; + } while (jl_is_uniontype(u)); + return u; +} + +#define push_unionstate(saved, src) \ + do { \ + (saved)->depth = (src)->depth; \ + (saved)->more = (src)->more; \ + (saved)->used = (src)->used; \ + jl_bits_stack_t *srcstack = &(src)->stack; \ + int pushbits = ((saved)->used+7)/8; \ + (saved)->stack = (uint8_t *)alloca(pushbits); \ + for (int n = 0; n < pushbits; n += sizeof(srcstack->data)) { \ + assert(srcstack != NULL); \ + int rest = pushbits - n; \ + if (rest > sizeof(srcstack->data)) \ + rest = sizeof(srcstack->data); \ + memcpy(&(saved)->stack[n], &srcstack->data, rest); \ + srcstack = srcstack->next; \ + } \ } while (0); -#define pop_unionstate(dst, saved) \ - do { \ - (dst)->depth = (saved)->depth; \ - (dst)->more = (saved)->more; \ - (dst)->used = (saved)->used; \ - memcpy(&(dst)->stack, (saved)->stack, ((saved)->used+7)/8); \ +#define pop_unionstate(dst, saved) \ + do { \ + (dst)->depth = (saved)->depth; \ + (dst)->more = (saved)->more; \ + (dst)->used = (saved)->used; \ + jl_bits_stack_t *dststack = &(dst)->stack; \ + int popbits = ((saved)->used+7)/8; \ + for (int n = 0; n < popbits; n += sizeof(dststack->data)) { \ + assert(dststack != NULL); \ + int rest = popbits - n; \ + if (rest > sizeof(dststack->data)) \ + rest = sizeof(dststack->data); \ + memcpy(&dststack->data, &(saved)->stack[n], rest); \ + dststack = dststack->next; \ + } \ } while (0); static int current_env_length(jl_stenv_t *e) @@ -252,6 +330,18 @@ static void free_env(jl_savedenv_t *se) JL_NOTSAFEPOINT se->buf = NULL; } +static void free_stenv(jl_stenv_t *e) JL_NOTSAFEPOINT +{ + for (int R = 0; R < 2; R++) { + jl_bits_stack_t *temp = R ? e->Runions.stack.next : e->Lunions.stack.next; + while (temp != NULL) { + jl_bits_stack_t *next = temp->next; + free(temp); + temp = next; + } + } +} + static void restore_env(jl_stenv_t *e, jl_savedenv_t *se, int root) JL_NOTSAFEPOINT { jl_value_t **roots = NULL; @@ -574,44 +664,6 @@ static jl_value_t *simple_meet(jl_value_t *a, jl_value_t *b, int overesi) static int subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param); -#define has_next_union_state(e, R) ((((R) ? &(e)->Runions : &(e)->Lunions)->more) != 0) - -static int next_union_state(jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT -{ - jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; - if (state->more == 0) - return 0; - // reset `used` and let `pick_union_decision` clean the stack. - state->used = state->more; - statestack_set(state, state->used - 1, 1); - return 1; -} - -static int pick_union_decision(jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT -{ - jl_unionstate_t *state = R ? &e->Runions : &e->Lunions; - if (state->depth >= state->used) { - statestack_set(state, state->used, 0); - state->used++; - } - int ui = statestack_get(state, state->depth); - state->depth++; - if (ui == 0) - state->more = state->depth; // memorize that this was the deepest available choice - return ui; -} - -static jl_value_t *pick_union_element(jl_value_t *u JL_PROPAGATES_ROOT, jl_stenv_t *e, int8_t R) JL_NOTSAFEPOINT -{ - do { - if (pick_union_decision(e, R)) - u = ((jl_uniontype_t*)u)->b; - else - u = ((jl_uniontype_t*)u)->a; - } while (jl_is_uniontype(u)); - return u; -} - static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param, int limit_slow); // subtype for variable bounds consistency check. needs its own forall/exists environment. @@ -1474,37 +1526,12 @@ static int is_definite_length_tuple_type(jl_value_t *x) return k == JL_VARARG_NONE || k == JL_VARARG_INT; } -static int _forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param, int *count, int *noRmore); - -static int may_contain_union_decision(jl_value_t *x, jl_stenv_t *e, jl_typeenv_t *log) JL_NOTSAFEPOINT +static int is_exists_typevar(jl_value_t *x, jl_stenv_t *e) { - if (x == NULL || x == (jl_value_t*)jl_any_type || x == jl_bottom_type) - return 0; - if (jl_is_unionall(x)) - return may_contain_union_decision(((jl_unionall_t *)x)->body, e, log); - if (jl_is_datatype(x)) { - jl_datatype_t *xd = (jl_datatype_t *)x; - for (int i = 0; i < jl_nparams(xd); i++) { - jl_value_t *param = jl_tparam(xd, i); - if (jl_is_vararg(param)) - param = jl_unwrap_vararg(param); - if (may_contain_union_decision(param, e, log)) - return 1; - } - return 0; - } if (!jl_is_typevar(x)) - return jl_is_type(x); - jl_typeenv_t *t = log; - while (t != NULL) { - if (x == (jl_value_t *)t->var) - return 1; - t = t->prev; - } - jl_typeenv_t newlog = { (jl_tvar_t*)x, NULL, log }; - jl_varbinding_t *xb = lookup(e, (jl_tvar_t *)x); - return may_contain_union_decision(xb ? xb->lb : ((jl_tvar_t *)x)->lb, e, &newlog) || - may_contain_union_decision(xb ? xb->ub : ((jl_tvar_t *)x)->ub, e, &newlog); + return 0; + jl_varbinding_t *vb = lookup(e, (jl_tvar_t *)x); + return vb && vb->right; } static int has_exists_typevar(jl_value_t *x, jl_stenv_t *e) JL_NOTSAFEPOINT @@ -1535,31 +1562,9 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t int kindy = !jl_has_free_typevars(y); if (kindx && kindy) return jl_subtype(x, y); - if (may_contain_union_decision(y, e, NULL) && pick_union_decision(e, 1) == 0) { - jl_saved_unionstate_t oldRunions; push_unionstate(&oldRunions, &e->Runions); - e->Lunions.used = e->Runions.used = 0; - e->Lunions.depth = e->Runions.depth = 0; - e->Lunions.more = e->Runions.more = 0; - int count = 0, noRmore = 0; - sub = _forall_exists_subtype(x, y, e, param, &count, &noRmore); - pop_unionstate(&e->Runions, &oldRunions); - // We could skip the slow path safely if - // 1) `_βˆ€_βˆƒ_subtype` has tested all cases - // 2) `_βˆ€_βˆƒ_subtype` returns 1 && `x` and `y` contain no βˆƒ typevar - // Once `limit_slow == 1`, also skip it if - // 1) `_βˆ€_βˆƒ_subtype` returns 0 - // 2) the left `Union` looks big - // TODO: `limit_slow` ignores complexity from inner `local_βˆ€_exists_subtype`. - if (limit_slow == -1) - limit_slow = kindx || kindy; - int skip = noRmore || (limit_slow && (count > 3 || !sub)) || - (sub && (kindx || !has_exists_typevar(x, e)) && - (kindy || !has_exists_typevar(y, e))); - if (skip) - e->Runions.more = oldRmore; - } - else { - // slow path + int has_exists = (!kindx && has_exists_typevar(x, e)) || + (!kindy && has_exists_typevar(y, e)); + if (has_exists && (is_exists_typevar(x, e) != is_exists_typevar(y, e))) { e->Lunions.used = 0; while (1) { e->Lunions.more = 0; @@ -1568,7 +1573,51 @@ static int local_forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t if (!sub || !next_union_state(e, 0)) break; } + return sub; } + if (limit_slow == -1) + limit_slow = kindx || kindy; + jl_savedenv_t se; + save_env(e, &se, has_exists); + int count, limited = 0, ini_count = 0; + jl_saved_unionstate_t latestLunions = {0, 0, 0, NULL}; + while (1) { + count = ini_count; + if (ini_count == 0) + e->Lunions.used = 0; + else + pop_unionstate(&e->Lunions, &latestLunions); + while (1) { + e->Lunions.more = 0; + e->Lunions.depth = 0; + if (count < 4) count++; + sub = subtype(x, y, e, param); + if (limit_slow && count == 4) + limited = 1; + if (!sub || !next_union_state(e, 0)) + break; + if (limited || !has_exists || e->Runions.more == oldRmore) { + // re-save env and freeze the βˆƒdecision for previous βˆ€Union + // Note: We could ignore the rest `βˆƒUnion` decisions if `x` and `y` + // contain no βˆƒ typevar, as they have no effect on env. + ini_count = count; + push_unionstate(&latestLunions, &e->Lunions); + re_save_env(e, &se, has_exists); + e->Runions.more = oldRmore; + } + } + if (sub || e->Runions.more == oldRmore) + break; + assert(e->Runions.more > oldRmore); + next_union_state(e, 1); + restore_env(e, &se, has_exists); // also restore Rdepth here + e->Runions.more = oldRmore; + } + if (!sub) + assert(e->Runions.more == oldRmore); + else if (limited || !has_exists) + e->Runions.more = oldRmore; + free_env(&se); return sub; } @@ -1680,7 +1729,7 @@ static int exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, jl_savede } } -static int _forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param, int *count, int *noRmore) +static int forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) { // The depth recursion has the following shape, after simplification: // βˆ€β‚ @@ -1692,12 +1741,8 @@ static int _forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, i e->Lunions.used = 0; int sub; - if (count) *count = 0; - if (noRmore) *noRmore = 1; while (1) { sub = exists_subtype(x, y, e, &se, param); - if (count) *count = (*count < 4) ? *count + 1 : 4; - if (noRmore) *noRmore = *noRmore && e->Runions.more == 0; if (!sub || !next_union_state(e, 0)) break; re_save_env(e, &se, 1); @@ -1707,11 +1752,6 @@ static int _forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, i return sub; } -static int forall_exists_subtype(jl_value_t *x, jl_value_t *y, jl_stenv_t *e, int param) -{ - return _forall_exists_subtype(x, y, e, param, NULL, NULL); -} - static void init_stenv(jl_stenv_t *e, jl_value_t **env, int envsz) { e->vars = NULL; @@ -1731,6 +1771,8 @@ static void init_stenv(jl_stenv_t *e, jl_value_t **env, int envsz) e->Lunions.depth = 0; e->Runions.depth = 0; e->Lunions.more = 0; e->Runions.more = 0; e->Lunions.used = 0; e->Runions.used = 0; + e->Lunions.stack.next = NULL; + e->Runions.stack.next = NULL; } // subtyping entry points @@ -2160,6 +2202,7 @@ JL_DLLEXPORT int jl_subtype_env(jl_value_t *x, jl_value_t *y, jl_value_t **env, } init_stenv(&e, env, envsz); int subtype = forall_exists_subtype(x, y, &e, 0); + free_stenv(&e); assert(obvious_subtype == 3 || obvious_subtype == subtype || jl_has_free_typevars(x) || jl_has_free_typevars(y)); #ifndef NDEBUG if (obvious_subtype == 0 || (obvious_subtype == 1 && envsz == 0)) @@ -2252,6 +2295,7 @@ JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) { init_stenv(&e, NULL, 0); int subtype = forall_exists_subtype(a, b, &e, 0); + free_stenv(&e); assert(subtype_ab == 3 || subtype_ab == subtype || jl_has_free_typevars(a) || jl_has_free_typevars(b)); #ifndef NDEBUG if (subtype_ab != 0 && subtype_ab != 1) // ensures that running in a debugger doesn't change the result @@ -2268,6 +2312,7 @@ JL_DLLEXPORT int jl_types_equal(jl_value_t *a, jl_value_t *b) { init_stenv(&e, NULL, 0); int subtype = forall_exists_subtype(b, a, &e, 0); + free_stenv(&e); assert(subtype_ba == 3 || subtype_ba == subtype || jl_has_free_typevars(a) || jl_has_free_typevars(b)); #ifndef NDEBUG if (subtype_ba != 0 && subtype_ba != 1) // ensures that running in a debugger doesn't change the result @@ -4061,7 +4106,9 @@ static jl_value_t *intersect_types(jl_value_t *x, jl_value_t *y, int emptiness_o init_stenv(&e, NULL, 0); e.intersection = e.ignore_free = 1; e.emptiness_only = emptiness_only; - return intersect_all(x, y, &e); + jl_value_t *ans = intersect_all(x, y, &e); + free_stenv(&e); + return ans; } JL_DLLEXPORT jl_value_t *jl_intersect_types(jl_value_t *x, jl_value_t *y) @@ -4238,6 +4285,7 @@ jl_value_t *jl_type_intersection_env_s(jl_value_t *a, jl_value_t *b, jl_svec_t * memset(env, 0, szb*sizeof(void*)); e.envsz = szb; *ans = intersect_all(a, b, &e); + free_stenv(&e); if (*ans == jl_bottom_type) goto bot; // TODO: code dealing with method signatures is not able to handle unions, so if // `a` and `b` are both tuples, we need to be careful and may not return a union, diff --git a/src/threading.c b/src/threading.c index 67617da0951dd..622825c76f364 100644 --- a/src/threading.c +++ b/src/threading.c @@ -345,7 +345,17 @@ jl_ptls_t jl_init_threadtls(int16_t tid) #endif if (jl_get_pgcstack() != NULL) abort(); - jl_ptls_t ptls = (jl_ptls_t)calloc(1, sizeof(jl_tls_states_t)); + jl_ptls_t ptls; +#if defined(_OS_WINDOWS_) + ptls = _aligned_malloc(sizeof(jl_tls_states_t), alignof(jl_tls_states_t)); + if (ptls == NULL) + abort(); +#else + if (posix_memalign((void**)&ptls, alignof(jl_tls_states_t), sizeof(jl_tls_states_t))) + abort(); +#endif + memset(ptls, 0, sizeof(jl_tls_states_t)); + #ifndef _OS_WINDOWS_ pthread_setspecific(jl_task_exit_key, (void*)ptls); #endif diff --git a/stdlib/LinearAlgebra/test/triangular.jl b/stdlib/LinearAlgebra/test/triangular.jl index b337f3c1cf8d9..c0d86caa0f6b8 100644 --- a/stdlib/LinearAlgebra/test/triangular.jl +++ b/stdlib/LinearAlgebra/test/triangular.jl @@ -905,4 +905,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/OpenLibm_jll/Project.toml b/stdlib/OpenLibm_jll/Project.toml index f6162f402bfcf..c5ba7fe77b651 100644 --- a/stdlib/OpenLibm_jll/Project.toml +++ b/stdlib/OpenLibm_jll/Project.toml @@ -1,6 +1,6 @@ name = "OpenLibm_jll" uuid = "05823500-19ac-5b8b-9628-191a04bc5112" -version = "0.8.1+2" +version = "0.8.1+4" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/Pkg.version b/stdlib/Pkg.version index fd91f6e800f38..1fa2db36f0cb9 100644 --- a/stdlib/Pkg.version +++ b/stdlib/Pkg.version @@ -1,4 +1,4 @@ PKG_BRANCH = release-1.10 -PKG_SHA1 = 6390ea92bf585e182c96cb5db7529c067874e5f5 +PKG_SHA1 = 0b3af4592d7158d4cba1132a9cc9df15e8e51706 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 8b9a552071ea8..8de1cefa06e4a 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -961,6 +961,9 @@ function complete_keyword_argument(partial, last_idx, context_module) last_word = partial[wordrange] # the word to complete kwargs = Set{String}() for m in methods + # if MAX_METHOD_COMPLETIONS is hit a single TextCompletion is return by complete_methods! with an explanation + # which can be ignored here + m isa TextCompletion && continue m::MethodCompletion possible_kwargs = Base.kwarg_decl(m.method) current_kwarg_candidates = String[] diff --git a/stdlib/Test/src/Test.jl b/stdlib/Test/src/Test.jl index 622c696b383a0..3493cfc5e2bd9 100644 --- a/stdlib/Test/src/Test.jl +++ b/stdlib/Test/src/Test.jl @@ -1135,7 +1135,7 @@ function print_test_results(ts::DefaultTestSet, depth_pad=0) duration_width = max(length("Time"), length(duration)) # Calculate the alignment of the test result counts by # recursively walking the tree of test sets - align = max(get_alignment(ts, 0), length("Test Summary:")) + align = max(get_alignment(ts, depth_pad), textwidth("Test Summary:")) # Print the outer test set header once pad = total == 0 ? "" : " " printstyled(rpad("Test Summary:", align, " "), " |", pad; bold=true) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index c61a756a0b6a7..916756eb6bfb7 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5172,3 +5172,30 @@ end) === Union{} @test only(Base.Base.return_types() do TypeVar(:Issue56248, Any, 1) end) === Union{} + +# issue 51228 +global whatever_unknown_value51228 +f51228() = f51228(whatever_unknown_value51228) +f51228(x) = 1 +f51228(::Vararg{T,T}) where {T} = "2" +@test only(Base.return_types(f51228, ())) == Int + +struct A51317 + b::Tuple{1} + A1() = new() +end +struct An51317 + a::Int + b::Tuple{1} + An51317() = new() +end +@test only(Base.return_types((x,f) -> getfield(x, f), (A51317, Symbol))) === Union{} +@test only(Base.return_types((x,f) -> getfield(x, f), (An51317, Symbol))) === Int +@test only(Base.return_types(x -> getfield(x, :b), (A51317,))) === Union{} +@test only(Base.return_types(x -> getfield(x, :b), (An51317,))) === Union{} + +# issue #56628 +@test Core.Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}} ]) === Tuple{Int, UnitRange{Int}} +@test Core.Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}}, Float64 ]) === Tuple{Int, UnitRange{Int}, Float64} +@test Core.Compiler.argtypes_to_type(Any[ Int, UnitRange{Int}, Vararg{Pair{Any, Union{}}}, Float64, Tuple{2} ]) === Union{} +@test Base.return_types(Tuple{Tuple{Int, Vararg{Pair{Any, Union{}}}}},) do x; Returns(true)(x...); end |> only === Bool diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 780a5424a29c2..7ab3589c725f9 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -1642,33 +1642,6 @@ function oc_capture_oc(z) end @test fully_eliminated(oc_capture_oc, (Int,)) -@eval struct OldVal{T} - x::T - (OV::Type{OldVal{T}})() where T = $(Expr(:new, :OV)) -end -with_unmatched_typeparam1(x::OldVal{i}) where {i} = i -with_unmatched_typeparam2() = [ Base.donotdelete(OldVal{i}()) for i in 1:10000 ] -function with_unmatched_typeparam3() - f(x::OldVal{i}) where {i} = i - r = 0 - for i = 1:10000 - r += f(OldVal{i}()) - end - return r -end - -@testset "Inlining with unmatched type parameters" begin - let src = code_typed1(with_unmatched_typeparam1, (Any,)) - @test !any(@nospecialize(x) -> isexpr(x, :call) && length(x.args) == 1, src.code) - end - let src = code_typed1(with_unmatched_typeparam2) - @test !any(@nospecialize(x) -> isexpr(x, :call) && length(x.args) == 1, src.code) - end - let src = code_typed1(with_unmatched_typeparam3) - @test !any(@nospecialize(x) -> isexpr(x, :call) && length(x.args) == 1, src.code) - end -end - function twice_sitofp(x::Int, y::Int) x = Base.sitofp(Float64, x) y = Base.sitofp(Float64, y) diff --git a/test/core.jl b/test/core.jl index 1321fb825e814..1938e0801a100 100644 --- a/test/core.jl +++ b/test/core.jl @@ -7467,6 +7467,13 @@ struct A43411{S, T} end @test isbitstype(A43411{(:a,), Tuple{Int}}) +# issue #55189 +struct A55189{N} + children::NTuple{N,A55189{N}} +end +@test fieldtype(A55189{2}, 1) === Tuple{A55189{2}, A55189{2}} +@assert !isbitstype(A55189{2}) + # issue #44614 struct T44614_1{T} m::T diff --git a/test/iobuffer.jl b/test/iobuffer.jl index ec77903b4a5b8..9726007b87f7e 100644 --- a/test/iobuffer.jl +++ b/test/iobuffer.jl @@ -357,3 +357,9 @@ end seek(io,0) @test Base.read_sub(io,v,1,1) == [1,0] end + +@testset "Writing Char to full buffer" begin + io = IOBuffer(;maxsize=1) + write(io, 'a') + @test write(io, 'a') == 0 +end diff --git a/test/misc.jl b/test/misc.jl index 79b684badf1e0..c4a12c4db8e7d 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -1402,3 +1402,15 @@ end GC.gc(true); yield() @test in_fin[] end + +@testset "`@constprop`, `@assume_effects` handling of an unknown setting" begin + for x ∈ ("constprop", "assume_effects") + try + eval(Meta.parse("Base.@$x :unknown f() = 3")) + error("unexpectedly reached") + catch e + e::LoadError + @test e.error isa ArgumentError + end + end +end