From 775b5c1d5db1add584a637c301b973babb3ca05f Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 7 Sep 2020 02:06:55 -0400 Subject: [PATCH] Fix `getfield_tfunc` for constant `TypeName` 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. --- base/compiler/tfuncs.jl | 8 +++++++- test/compiler/inference.jl | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 9ab8f56d31392..6528de5bade23 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -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) diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 6ed0a4011b0b3..7f0c5fe2c90a2 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -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, $(())) +let goodf, badf + for goodf in [getfield_const_typename_good1, getfield_const_typename_good2] + 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 code = code_typed(badf, Tuple{})[1].first.code + @test Meta.isexpr(code[1], :call) + @test code[end] === Core.ReturnNode() + @test_throws TypeError badf() + end +end