Skip to content

Commit ff706aa

Browse files
authored
Merge pull request #23470 from JuliaLang/jn/var-infer
better constant variable inference
2 parents 5b12051 + de7b893 commit ff706aa

File tree

2 files changed

+77
-40
lines changed

2 files changed

+77
-40
lines changed

base/inference.jl

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3153,6 +3153,10 @@ function typeinf_work(frame::InferenceState)
31533153
# directly forward changes to an SSAValue to the applicable line
31543154
record_ssa_assign(changes_var.id + 1, changes.vtype.typ, frame)
31553155
end
3156+
elseif isa(stmt, NewvarNode)
3157+
sn = slot_id(stmt.slot)
3158+
changes = changes::VarTable
3159+
changes[sn] = VarState(Bottom, true)
31563160
elseif isa(stmt, GotoNode)
31573161
pc´ = (stmt::GotoNode).label
31583162
elseif isa(stmt, Expr)
@@ -3563,7 +3567,7 @@ function annotate_slot_load!(e::Expr, vtypes::VarTable, sv::InferenceState, unde
35633567
elseif isa(subex, Slot)
35643568
id = slot_id(subex)
35653569
s = vtypes[id]
3566-
vt = widenconst(s.typ)
3570+
vt = s.typ
35673571
if s.undef
35683572
# find used-undef variables
35693573
undefs[id] = true
@@ -3680,28 +3684,39 @@ function type_annotate!(sv::InferenceState)
36803684
end
36813685

36823686
# widen all Const elements in type annotations
3683-
function _widen_all_consts!(e::Expr, untypedload::Vector{Bool})
3687+
function _widen_all_consts!(e::Expr, untypedload::Vector{Bool}, slottypes::Vector{Any})
36843688
e.typ = widenconst(e.typ)
36853689
for i = 1:length(e.args)
36863690
x = e.args[i]
36873691
if isa(x, Expr)
3688-
_widen_all_consts!(x, untypedload)
3689-
elseif isa(x, Slot) && (i != 1 || e.head !== :(=))
3690-
untypedload[slot_id(x)] = true
3692+
_widen_all_consts!(x, untypedload, slottypes)
3693+
elseif isa(x, TypedSlot)
3694+
vt = widenconst(x.typ)
3695+
if !(vt === x.typ)
3696+
if slottypes[x.id] <: vt
3697+
x = SlotNumber(x.id)
3698+
untypedload[x.id] = true
3699+
else
3700+
x = TypedSlot(x.id, vt)
3701+
end
3702+
e.args[i] = x
3703+
end
3704+
elseif isa(x, SlotNumber) && (i != 1 || e.head !== :(=))
3705+
untypedload[x.id] = true
36913706
end
36923707
end
36933708
nothing
36943709
end
3710+
36953711
function widen_all_consts!(src::CodeInfo)
36963712
for i = 1:length(src.ssavaluetypes)
36973713
src.ssavaluetypes[i] = widenconst(src.ssavaluetypes[i])
36983714
end
36993715
nslots = length(src.slottypes)
37003716
untypedload = fill(false, nslots)
3701-
for i = 1:length(src.code)
3702-
x = src.code[i]
3703-
isa(x, Expr) && _widen_all_consts!(x, untypedload)
3704-
end
3717+
e = Expr(:body)
3718+
e.args = src.code
3719+
_widen_all_consts!(e, untypedload, src.slottypes)
37053720
for i = 1:nslots
37063721
src.slottypes[i] = widen_slot_type(src.slottypes[i], untypedload[i])
37073722
end

test/inference.jl

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -254,35 +254,6 @@ function foo9222()
254254
end
255255
@test 0.0 == foo9222()
256256

257-
# make sure none of the slottypes are left as Core.Inference.Const objects
258-
function f18679()
259-
for i = 1:2
260-
if i == 1
261-
a = ((),)
262-
else
263-
return a[1]
264-
end
265-
end
266-
end
267-
g18679(x::Tuple) = ()
268-
g18679() = g18679(any_undef_global::Union{Int,Tuple{}})
269-
for code in Any[
270-
@code_typed(f18679())[1]
271-
@code_typed(g18679())[1]]
272-
@test all(x->isa(x, Type), code.slottypes)
273-
local notconst(@nospecialize(other)) = true
274-
notconst(slot::TypedSlot) = @test isa(slot.typ, Type)
275-
function notconst(expr::Expr)
276-
@test isa(expr.typ, Type)
277-
for a in expr.args
278-
notconst(a)
279-
end
280-
end
281-
for e in code.code
282-
notconst(e)
283-
end
284-
end
285-
286257
# branching based on inferrable conditions
287258
let f(x) = isa(x,Int) ? 1 : ""
288259
@test Base.return_types(f, Tuple{Int}) == [Int]
@@ -470,11 +441,62 @@ function test_inferred_static(arrow::Pair)
470441
end
471442
end
472443

444+
function f18679()
445+
local a
446+
for i = 1:2
447+
if i == 1
448+
a = ((),)
449+
else
450+
return a[1]
451+
end
452+
end
453+
end
454+
g18679(x::Tuple) = ()
455+
g18679() = g18679(any_undef_global::Union{Int, Tuple{}})
456+
function h18679()
457+
for i = 1:2
458+
local a
459+
if i == 1
460+
a = ((),)
461+
else
462+
@isdefined(a) && return "BAD"
463+
end
464+
end
465+
end
466+
473467
function g19348(x)
474468
a, b = x
475-
return a + b
469+
g = 1
470+
g = 2
471+
c = Base.indexed_next(x, g, g)
472+
return a + b + c[1]
473+
end
474+
475+
for codetype in Any[
476+
@code_typed(f18679()),
477+
@code_typed(g18679()),
478+
@code_typed(h18679()),
479+
@code_typed(g19348((1, 2.0)))]
480+
# make sure none of the slottypes are left as Core.Inference.Const objects
481+
code = codetype[1]
482+
@test all(x->isa(x, Type), code.slottypes)
483+
local notconst(@nospecialize(other)) = true
484+
notconst(slot::TypedSlot) = @test isa(slot.typ, Type)
485+
function notconst(expr::Expr)
486+
@test isa(expr.typ, Type)
487+
for a in expr.args
488+
notconst(a)
489+
end
490+
end
491+
for e in code.code
492+
notconst(e)
493+
end
494+
test_inferred_static(code)
476495
end
477-
test_inferred_static(@code_typed g19348((1, 2.0)))
496+
@test f18679() === ()
497+
@test_throws UndefVarError(:any_undef_global) g18679()
498+
@test h18679() === nothing
499+
478500

479501
# issue #5575
480502
f5575() = zeros(Type[Float64][1], 1)

0 commit comments

Comments
 (0)