Skip to content

Commit f529e8a

Browse files
yuyichaoKristofferC
authored andcommitted
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. (cherry picked from commit 1378bb6)
1 parent 4ea0e8c commit f529e8a

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
@@ -729,6 +729,9 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
729729
end
730730
if isa(name, Const)
731731
nv = name.val
732+
if !(isa(nv,Symbol) || isa(nv,Int))
733+
return Bottom
734+
end
732735
if isa(sv, UnionAll)
733736
if nv === :var || nv === 1
734737
return Const(sv.var)
@@ -755,9 +758,6 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
755758
if isa(sv, Module) && isa(nv, Symbol)
756759
return abstract_eval_global(sv, nv)
757760
end
758-
if !(isa(nv,Symbol) || isa(nv,Int))
759-
return Bottom
760-
end
761761
if (isa(sv, SimpleVector) || !ismutable(sv)) && isdefined(sv, nv)
762762
return AbstractEvalConstant(getfield(sv, nv))
763763
end

test/compiler/inference.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2625,3 +2625,25 @@ f36531(args...) = tuple((args...)...)
26252625
@test (sizeof(Ptr),) == sizeof.((Ptr,)) == sizeof.((Ptr{Cvoid},))
26262626
@test Core.Compiler.sizeof_tfunc(UnionAll) === Int
26272627
@test !Core.Compiler.sizeof_nothrow(UnionAll)
2628+
2629+
# Use a global constant to rely less on unrelated constant propagation
2630+
const const_int32_typename = Int32.name
2631+
# Check constant propagation for field of constant `TypeName`
2632+
# works for both valid and invalid field names. (Ref #37443)
2633+
getfield_const_typename_good1() = getfield(const_int32_typename, 1)
2634+
getfield_const_typename_good2() = getfield(const_int32_typename, :name)
2635+
getfield_const_typename_bad1() = getfield(const_int32_typename, 0x1)
2636+
@eval getfield_const_typename_bad2() = getfield(const_int32_typename, $(()))
2637+
for goodf in [getfield_const_typename_good1, getfield_const_typename_good2]
2638+
local goodf
2639+
local code = code_typed(goodf, Tuple{})[1].first.code
2640+
@test code[1] === Core.ReturnNode(QuoteNode(:Int32))
2641+
@test goodf() === :Int32
2642+
end
2643+
for badf in [getfield_const_typename_bad1, getfield_const_typename_bad2]
2644+
local badf
2645+
local code = code_typed(badf, Tuple{})[1].first.code
2646+
@test Meta.isexpr(code[1], :call)
2647+
@test code[end] === Core.ReturnNode()
2648+
@test_throws TypeError badf()
2649+
end

0 commit comments

Comments
 (0)