Skip to content

Commit de4f032

Browse files
authored
Merge branch 'master' into update-llvmlibunwind
2 parents cead411 + 43c6f75 commit de4f032

37 files changed

+855
-497
lines changed

base/cmd.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ function cmd_gen(parsed)
462462
(ignorestatus, flags, env, dir) = (cmd.ignorestatus, cmd.flags, cmd.env, cmd.dir)
463463
append!(args, cmd.exec)
464464
for arg in tail(parsed)
465-
append!(args, arg_gen(arg...)::Vector{String})
465+
append!(args, Base.invokelatest(arg_gen, arg...)::Vector{String})
466466
end
467467
return Cmd(Cmd(args), ignorestatus, flags, env, dir)
468468
else

base/compiler/abstractinterpretation.jl

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2034,7 +2034,7 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
20342034
fargs = nothing
20352035
end
20362036
argtypes = Any[typeof(<:), argtypes[3], argtypes[2]]
2037-
return CallMeta(abstract_call_known(interp, <:, ArgInfo(fargs, argtypes), si, sv, max_methods).rt, EFFECTS_TOTAL, NoCallInfo())
2037+
return abstract_call_known(interp, <:, ArgInfo(fargs, argtypes), si, sv, max_methods)
20382038
elseif la == 2 &&
20392039
(a2 = argtypes[2]; isa(a2, Const)) && (svecval = a2.val; isa(svecval, SimpleVector)) &&
20402040
istopfunction(f, :length)
@@ -2189,9 +2189,17 @@ function abstract_eval_value_expr(interp::AbstractInterpreter, e::Expr, vtypes::
21892189
head = e.head
21902190
if head === :static_parameter
21912191
n = e.args[1]::Int
2192+
nothrow = false
21922193
if 1 <= n <= length(sv.sptypes)
21932194
rt = sv.sptypes[n]
2195+
if is_maybeundefsp(rt)
2196+
rt = unwrap_maybeundefsp(rt)
2197+
else
2198+
nothrow = true
2199+
end
21942200
end
2201+
merge_effects!(interp, sv, Effects(EFFECTS_TOTAL; nothrow))
2202+
return rt
21952203
elseif head === :boundscheck
21962204
if isa(sv, InferenceState)
21972205
# If there is no particular `@inbounds` for this function, then we only taint `:noinbounds`,
@@ -2452,8 +2460,7 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, vtyp
24522460
elseif isexpr(sym, :static_parameter)
24532461
n = sym.args[1]::Int
24542462
if 1 <= n <= length(sv.sptypes)
2455-
spty = sv.sptypes[n]
2456-
if isa(spty, Const)
2463+
if !is_maybeundefsp(sv.sptypes, n)
24572464
t = Const(true)
24582465
end
24592466
end
@@ -2893,6 +2900,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
28932900
empty!(frame.pclimitations)
28942901
@goto find_next_bb
28952902
end
2903+
orig_condt = condt
28962904
if !(isa(condt, Const) || isa(condt, Conditional)) && isa(condx, SlotNumber)
28972905
# if this non-`Conditional` object is a slot, we form and propagate
28982906
# the conditional constraint on it
@@ -2924,6 +2932,14 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
29242932
handle_control_backedge!(interp, frame, currpc, stmt.dest)
29252933
@goto branch
29262934
else
2935+
if !(𝕃ᵢ, orig_condt, Bool)
2936+
merge_effects!(interp, frame, EFFECTS_THROWS)
2937+
if !hasintersect(widenconst(orig_condt), Bool)
2938+
ssavaluetypes[currpc] = Bottom
2939+
@goto find_next_bb
2940+
end
2941+
end
2942+
29272943
# We continue with the true branch, but process the false
29282944
# branch here.
29292945
if isa(condt, Conditional)

base/compiler/inferencestate.jl

Lines changed: 95 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -348,23 +348,109 @@ function InferenceState(result::InferenceResult, cache::Symbol, interp::Abstract
348348
return InferenceState(result, src, cache, interp)
349349
end
350350

351+
"""
352+
constrains_param(var::TypeVar, sig, covariant::Bool, type_constrains::Bool)
353+
354+
Check if `var` will be constrained to have a definite value
355+
in any concrete leaftype subtype of `sig`.
356+
357+
It is used as a helper to determine whether type intersection is guaranteed to be able to
358+
find a value for a particular type parameter.
359+
A necessary condition for type intersection to not assign a parameter is that it only
360+
appears in a `Union[All]` and during subtyping some other union component (that does not
361+
constrain the type parameter) is selected.
362+
363+
The `type_constrains` flag determines whether Type{T} is considered to be constraining
364+
`T`. This is not true in general, because of the existence of types with free type
365+
parameters, however, some callers would like to ignore this corner case.
366+
"""
367+
function constrains_param(var::TypeVar, @nospecialize(typ), covariant::Bool, type_constrains::Bool=false)
368+
typ === var && return true
369+
while typ isa UnionAll
370+
covariant && constrains_param(var, typ.var.ub, covariant, type_constrains) && return true
371+
# typ.var.lb doesn't constrain var
372+
typ = typ.body
373+
end
374+
if typ isa Union
375+
# for unions, verify that both options would constrain var
376+
ba = constrains_param(var, typ.a, covariant, type_constrains)
377+
bb = constrains_param(var, typ.b, covariant, type_constrains)
378+
(ba && bb) && return true
379+
elseif typ isa DataType
380+
# return true if any param constrains var
381+
fc = length(typ.parameters)
382+
if fc > 0
383+
if typ.name === Tuple.name
384+
# vararg tuple needs special handling
385+
for i in 1:(fc - 1)
386+
p = typ.parameters[i]
387+
constrains_param(var, p, covariant, type_constrains) && return true
388+
end
389+
lastp = typ.parameters[fc]
390+
vararg = unwrap_unionall(lastp)
391+
if vararg isa Core.TypeofVararg && isdefined(vararg, :N)
392+
constrains_param(var, vararg.N, covariant, type_constrains) && return true
393+
# T = vararg.parameters[1] doesn't constrain var
394+
else
395+
constrains_param(var, lastp, covariant, type_constrains) && return true
396+
end
397+
else
398+
if typ.name === typename(Type) && typ.parameters[1] === var && var.ub === Any
399+
# Types with free type parameters are <: Type cause the typevar
400+
# to be unconstrained because Type{T} with free typevars is illegal
401+
return type_constrains
402+
end
403+
for i in 1:fc
404+
p = typ.parameters[i]
405+
constrains_param(var, p, false, type_constrains) && return true
406+
end
407+
end
408+
end
409+
end
410+
return false
411+
end
412+
413+
"""
414+
MaybeUndefSP(typ)
415+
is_maybeundefsp(typ) -> Bool
416+
unwrap_maybeundefsp(typ) -> Any
417+
418+
A special wrapper that represents a static parameter that could be undefined at runtime.
419+
This does not participate in the native type system nor the inference lattice,
420+
and it thus should be always unwrapped when performing any type or lattice operations on it.
421+
"""
422+
struct MaybeUndefSP
423+
typ
424+
MaybeUndefSP(@nospecialize typ) = new(typ)
425+
end
426+
is_maybeundefsp(@nospecialize typ) = isa(typ, MaybeUndefSP)
427+
unwrap_maybeundefsp(@nospecialize typ) = isa(typ, MaybeUndefSP) ? typ.typ : typ
428+
is_maybeundefsp(sptypes::Vector{Any}, idx::Int) = is_maybeundefsp(sptypes[idx])
429+
unwrap_maybeundefsp(sptypes::Vector{Any}, idx::Int) = unwrap_maybeundefsp(sptypes[idx])
430+
431+
const EMPTY_SPTYPES = Any[]
432+
351433
function sptypes_from_meth_instance(linfo::MethodInstance)
352-
toplevel = !isa(linfo.def, Method)
353-
if !toplevel && isempty(linfo.sparam_vals) && isa(linfo.def.sig, UnionAll)
434+
def = linfo.def
435+
isa(def, Method) || return EMPTY_SPTYPES # toplevel
436+
sig = def.sig
437+
if isempty(linfo.sparam_vals)
438+
isa(sig, UnionAll) || return EMPTY_SPTYPES
354439
# linfo is unspecialized
355440
sp = Any[]
356-
sig = linfo.def.sig
357-
while isa(sig, UnionAll)
358-
push!(sp, sig.var)
359-
sig = sig.body
441+
sig = sig
442+
while isa(sig, UnionAll)
443+
push!(sp, sig.var)
444+
sig = sig.body
360445
end
361446
else
362447
sp = collect(Any, linfo.sparam_vals)
363448
end
364449
for i = 1:length(sp)
365450
v = sp[i]
366451
if v isa TypeVar
367-
temp = linfo.def.sig
452+
maybe_undef = !constrains_param(v, linfo.specTypes, #=covariant=#true)
453+
temp = sig
368454
for j = 1:i-1
369455
temp = temp.body
370456
end
@@ -402,12 +488,13 @@ function sptypes_from_meth_instance(linfo::MethodInstance)
402488
tv = TypeVar(v.name, lb, ub)
403489
ty = UnionAll(tv, Type{tv})
404490
end
491+
@label ty_computed
492+
maybe_undef && (ty = MaybeUndefSP(ty))
405493
elseif isvarargtype(v)
406494
ty = Int
407495
else
408496
ty = Const(v)
409497
end
410-
@label ty_computed
411498
sp[i] = ty
412499
end
413500
return sp

base/compiler/optimize.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,9 @@ function stmt_effect_flags(𝕃ₒ::AbstractLattice, @nospecialize(stmt), @nospe
267267
if isa(stmt, Expr)
268268
(; head, args) = stmt
269269
if head === :static_parameter
270-
etyp = (isa(src, IRCode) ? src.sptypes : src.ir.sptypes)[args[1]::Int]
271270
# if we aren't certain enough about the type, it might be an UndefVarError at runtime
272-
nothrow = isa(etyp, Const)
271+
sptypes = isa(src, IRCode) ? src.sptypes : src.ir.sptypes
272+
nothrow = !is_maybeundefsp(sptypes, args[1]::Int)
273273
return (true, nothrow, nothrow)
274274
end
275275
if head === :call
@@ -377,7 +377,7 @@ function argextype(
377377
sptypes::Vector{Any}, slottypes::Vector{Any})
378378
if isa(x, Expr)
379379
if x.head === :static_parameter
380-
return sptypes[x.args[1]::Int]
380+
return unwrap_maybeundefsp(sptypes, x.args[1]::Int)
381381
elseif x.head === :boundscheck
382382
return Bool
383383
elseif x.head === :copyast

base/compiler/ssair/slot2ssa.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ end
216216
function typ_for_val(@nospecialize(x), ci::CodeInfo, sptypes::Vector{Any}, idx::Int, slottypes::Vector{Any})
217217
if isa(x, Expr)
218218
if x.head === :static_parameter
219-
return sptypes[x.args[1]::Int]
219+
return unwrap_maybeundefsp(sptypes, x.args[1]::Int)
220220
elseif x.head === :boundscheck
221221
return Bool
222222
elseif x.head === :copyast

base/compiler/ssair/verify.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ function verify_ir(ir::IRCode, print::Bool=true,
268268
elseif stmt.head === :foreigncall
269269
isforeigncall = true
270270
elseif stmt.head === :isdefined && length(stmt.args) == 1 &&
271-
(stmt.args[1] isa GlobalRef || (stmt.args[1] isa Expr && stmt.args[1].head === :static_parameter))
271+
(stmt.args[1] isa GlobalRef || isexpr(stmt.args[1], :static_parameter))
272272
# a GlobalRef or static_parameter isdefined check does not evaluate its argument
273273
continue
274274
elseif stmt.head === :call

base/exports.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ export
352352
tan,
353353
tand,
354354
tanh,
355+
tanpi,
355356
trailing_ones,
356357
trailing_zeros,
357358
trunc,

0 commit comments

Comments
 (0)