Skip to content

Commit 969193b

Browse files
Kenovtjnash
andauthored
Follow-up #46693 - Also exclude Type{Tuple{Union{...}, ...}} (#46723)
* Follow-up #46693 - Also exclude `Type{Tuple{Union{...}, ...}}` The check in #46693 was attempting to guarantee that the runtime value was a `DataType`, but was missing at least the case where a tuple of unions could have been re-distributed. Fix that up and refactor while we're at it. * Apply suggestions from code review Co-authored-by: Jameson Nash <vtjnash@gmail.com> Co-authored-by: Jameson Nash <vtjnash@gmail.com>
1 parent 8a59be6 commit 969193b

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

base/compiler/tfuncs.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -824,9 +824,8 @@ function getfield_nothrow(@nospecialize(s00), @nospecialize(name), boundscheck::
824824
if isa(s, Union)
825825
return getfield_nothrow(rewrap_unionall(s.a, s00), name, boundscheck) &&
826826
getfield_nothrow(rewrap_unionall(s.b, s00), name, boundscheck)
827-
elseif isType(s)
828-
sv = s.parameters[1]
829-
s = s0 = typeof(sv)
827+
elseif isType(s) && isTypeDataType(s.parameters[1])
828+
s = s0 = DataType
830829
end
831830
if isa(s, DataType)
832831
# Can't say anything about abstract types
@@ -941,10 +940,11 @@ function _getfield_tfunc(@nospecialize(s00), @nospecialize(name), setfield::Bool
941940
s = typeof(sv)
942941
else
943942
sv = s.parameters[1]
944-
if isa(sv, DataType) && isa(name, Const) && (!isType(sv) && sv !== Core.TypeofBottom)
943+
if isTypeDataType(sv) && isa(name, Const)
945944
nv = _getfield_fieldindex(DataType, name)
946945
if nv == DATATYPE_NAME_FIELDINDEX
947-
# N.B. This doesn't work in general, because
946+
# N.B. This only works for fields that do not depend on type
947+
# parameters (which we do not know here).
948948
return Const(sv.name)
949949
end
950950
s = DataType

base/compiler/typeutils.jl

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,29 @@ function hasuniquerep(@nospecialize t)
2323
return false
2424
end
2525

26+
"""
27+
isTypeDataType(@nospecialize t)
28+
29+
For a type `t` test whether ∀S s.t. `isa(S, rewrap_unionall(Type{t}, ...))`,
30+
we have `isa(S, DataType)`. In particular, if a statement is typed as `Type{t}`
31+
(potentially wrapped in some UnionAll), then we are guaranteed that this statement
32+
will be a DataType at runtime (and not e.g. a Union or UnionAll typeequal to it).
33+
"""
34+
function isTypeDataType(@nospecialize t)
35+
isa(t, DataType) || return false
36+
isType(t) && return false
37+
# Could be Union{} at runtime
38+
t === Core.TypeofBottom && return false
39+
if t.name === Tuple.name
40+
# If we have a Union parameter, could have been redistributed at runtime,
41+
# e.g. `Tuple{Union{Int, Float64}, Int}` is a DataType, but
42+
# `Union{Tuple{Int, Int}, Tuple{Float64, Int}}` is typeequal to it and
43+
# is not.
44+
return _all(isTypeDataType, t.parameters)
45+
end
46+
return true
47+
end
48+
2649
function has_nontrivial_const_info(lattice::PartialsLattice, @nospecialize t)
2750
isa(t, PartialStruct) && return true
2851
isa(t, PartialOpaque) && return true

test/compiler/inline.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,4 +1511,5 @@ end
15111511

15121512
# Test getfield modeling of Type{Ref{_A}} where _A
15131513
@test Core.Compiler.getfield_tfunc(Type, Core.Compiler.Const(:parameters)) !== Union{}
1514+
@test !isa(Core.Compiler.getfield_tfunc(Type{Tuple{Union{Int, Float64}, Int}}, Core.Compiler.Const(:name)), Core.Compiler.Const)
15141515
@test fully_eliminated(Base.ismutable, Tuple{Base.RefValue})

0 commit comments

Comments
 (0)