Skip to content

Commit 1378bb6

Browse files
authored
Fix getfield_tfunc for constant TypeName (#37443)
The field should be either `Symbol` or `Int`. Ref #37423 Unlike #37423, in additional to worse type info in inference, the missing type check here can actually cause type inference error due to errors in user code.
1 parent 1e6d771 commit 1378bb6

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

base/compiler/tfuncs.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,9 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
745745
end
746746
if isa(name, Const)
747747
nv = name.val
748+
if !(isa(nv,Symbol) || isa(nv,Int))
749+
return Bottom
750+
end
748751
if isa(sv, UnionAll)
749752
if nv === :var || nv === 1
750753
return Const(sv.var)
@@ -771,9 +774,6 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
771774
if isa(sv, Module) && isa(nv, Symbol)
772775
return abstract_eval_global(sv, nv)
773776
end
774-
if !(isa(nv,Symbol) || isa(nv,Int))
775-
return Bottom
776-
end
777777
if (isa(sv, SimpleVector) || !ismutable(sv)) && isdefined(sv, nv)
778778
return Const(getfield(sv, nv))
779779
end

test/compiler/inference.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2751,3 +2751,25 @@ f_generator_splat(t::Tuple) = tuple((identity(l) for l in t)...)
27512751
@test !Core.Compiler.sizeof_nothrow(UnionAll)
27522752

27532753
@test Base.return_types(Expr) == Any[Expr]
2754+
2755+
# Use a global constant to rely less on unrelated constant propagation
2756+
const const_int32_typename = Int32.name
2757+
# Check constant propagation for field of constant `TypeName`
2758+
# works for both valid and invalid field names. (Ref #37443)
2759+
getfield_const_typename_good1() = getfield(const_int32_typename, 1)
2760+
getfield_const_typename_good2() = getfield(const_int32_typename, :name)
2761+
getfield_const_typename_bad1() = getfield(const_int32_typename, 0x1)
2762+
@eval getfield_const_typename_bad2() = getfield(const_int32_typename, $(()))
2763+
for goodf in [getfield_const_typename_good1, getfield_const_typename_good2]
2764+
local goodf
2765+
local code = code_typed(goodf, Tuple{})[1].first.code
2766+
@test code[1] === Core.ReturnNode(QuoteNode(:Int32))
2767+
@test goodf() === :Int32
2768+
end
2769+
for badf in [getfield_const_typename_bad1, getfield_const_typename_bad2]
2770+
local badf
2771+
local code = code_typed(badf, Tuple{})[1].first.code
2772+
@test Meta.isexpr(code[1], :call)
2773+
@test code[end] === Core.ReturnNode()
2774+
@test_throws TypeError badf()
2775+
end

0 commit comments

Comments
 (0)