Skip to content

Commit 4f5b22e

Browse files
committed
inference: fix widenconst call for ReturnNode of PartialStruct
Previously, we might accidentally leave behind content in the fields that should not be there. For example: ``` julia> code_typed(() -> (TypeVar(:x),), (), optimize=false) 1-element Vector{Any}: CodeInfo( @ REPL[1]:1 within `#3' 1 ─ %1 = Main.TypeVar(:x)::Core.Compiler.PartialTypeVar(x, true, true) │ %2 = Core.tuple(%1)::Core.PartialStruct(Tuple{TypeVar}, Any[Core.Compiler.PartialTypeVar(x, true, true)]) └── return %2 ) => Tuple{TypeVar} julia> ans[1][1].rettype Core.PartialStruct(Tuple{TypeVar}, Any[Core.Compiler.PartialTypeVar(x, true, true)]) ```
1 parent 2465db2 commit 4f5b22e

File tree

3 files changed

+26
-7
lines changed

3 files changed

+26
-7
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,28 @@ function abstract_eval_ssavalue(s::SSAValue, src::CodeInfo)
13251325
return typ
13261326
end
13271327

1328+
function widenreturn(@nospecialize rt)
1329+
# only propagate information we know we can store
1330+
# and is valid and good inter-procedurally
1331+
rt = widenconditional(rt)
1332+
isa(rt, Const) && return rt
1333+
isa(rt, Type) && return rt
1334+
if isa(rt, PartialStruct)
1335+
fields = copy(rt.fields)
1336+
haveconst = false
1337+
for i in 1:length(fields)
1338+
a = widenreturn(fields[i])
1339+
if !haveconst && has_const_info(a)
1340+
# TODO: consider adding && const_prop_profitable(a) here?
1341+
haveconst = true
1342+
end
1343+
fields[i] = a
1344+
end
1345+
haveconst && return PartialStruct(rt.typ, fields)
1346+
end
1347+
return widenconst(rt)
1348+
end
1349+
13281350
# make as much progress on `frame` as possible (without handling cycles)
13291351
function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
13301352
@assert !frame.inferred
@@ -1404,12 +1426,7 @@ function typeinf_local(interp::AbstractInterpreter, frame::InferenceState)
14041426
end
14051427
elseif isa(stmt, ReturnNode)
14061428
pc´ = n + 1
1407-
rt = widenconditional(abstract_eval_value(interp, stmt.val, s[pc], frame))
1408-
if !isa(rt, Const) && !isa(rt, Type) && !isa(rt, PartialStruct)
1409-
# only propagate information we know we can store
1410-
# and is valid inter-procedurally
1411-
rt = widenconst(rt)
1412-
end
1429+
rt = widenreturn(abstract_eval_value(interp, stmt.val, s[pc], frame))
14131430
# copy limitations to return value
14141431
if !isempty(frame.pclimitations)
14151432
union!(frame.limitations, frame.pclimitations)

base/compiler/tfuncs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1318,7 +1318,7 @@ function tuple_tfunc(atypes::Vector{Any})
13181318
x = atypes[i]
13191319
# TODO ignore singleton Const (don't forget to update cache logic if you implement this)
13201320
if !anyinfo
1321-
anyinfo = (!isa(x, Type) && !isvarargtype(x)) || isType(x)
1321+
anyinfo = has_const_info(x)
13221322
end
13231323
if isa(x, Const)
13241324
params[i] = typeof(x.val)

base/compiler/typeutils.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ function has_nontrivial_const_info(@nospecialize t)
3939
return !isdefined(typeof(val), :instance) && !(isa(val, Type) && hasuniquerep(val))
4040
end
4141

42+
has_const_info(@nospecialize x) = (!isa(x, Type) && !isvarargtype(x)) || isType(x)
43+
4244
# Subtyping currently intentionally answers certain queries incorrectly for kind types. For
4345
# some of these queries, this check can be used to somewhat protect against making incorrect
4446
# decisions based on incorrect subtyping. Note that this check, itself, is broken for

0 commit comments

Comments
 (0)