Skip to content

Commit

Permalink
Fix getfield_tfunc for constant TypeName
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
yuyichao committed Sep 7, 2020
1 parent eb2a801 commit fc15e71
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
8 changes: 7 additions & 1 deletion base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,13 @@ function getfield_tfunc(@nospecialize(s00), @nospecialize(name))
t === nothing || return t
end
elseif isa(sv, Core.TypeName)
fld = isa(nv, Symbol) ? fieldindex(Core.TypeName, nv, false) : nv
fld = if isa(nv, Symbol)
fieldindex(Core.TypeName, nv, false)
elseif isa(nv, Int)
nv
else
return Bottom
end
if (fld == TYPENAME_NAME_FIELDINDEX ||
fld == TYPENAME_MODULE_FIELDINDEX ||
fld == TYPENAME_WRAPPER_FIELDINDEX)
Expand Down
20 changes: 20 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2751,3 +2751,23 @@ f_generator_splat(t::Tuple) = tuple((identity(l) for l in t)...)
@test !Core.Compiler.sizeof_nothrow(UnionAll)

@test Base.return_types(Expr) == Any[Expr]

# Use a global constant to rely less on unrelated constant propagation
const const_int32_typename = Int32.name
getfield_const_typename_good1() = getfield(const_int32_typename, 1)
getfield_const_typename_good2() = getfield(const_int32_typename, :name)
getfield_const_typename_bad1() = getfield(const_int32_typename, 0x1)
@eval getfield_const_typename_bad2() = getfield(const_int32_typename, $(()))
for goodf in [getfield_const_typename_good1, getfield_const_typename_good2]
local goodf
local code = code_typed(goodf, Tuple{})[1].first.code
@test code[1] === Core.ReturnNode(QuoteNode(:Int32))
@test goodf() === :Int32
end
for badf in [getfield_const_typename_bad1, getfield_const_typename_bad2]
local badf
local code = code_typed(badf, Tuple{})[1].first.code
@test Meta.isexpr(code[1], :call)
@test code[end] === Core.ReturnNode()
@test_throws TypeError badf()
end

0 comments on commit fc15e71

Please sign in to comment.