-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Improve inference for ismutable with missing sparam #46693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ function find_tfunc(@nospecialize f) | |
end | ||
|
||
const DATATYPE_TYPES_FIELDINDEX = fieldindex(DataType, :types) | ||
const DATATYPE_NAME_FIELDINDEX = fieldindex(DataType, :name) | ||
|
||
########## | ||
# tfuncs # | ||
|
@@ -823,7 +824,11 @@ function getfield_nothrow(@nospecialize(s00), @nospecialize(name), boundscheck:: | |
if isa(s, Union) | ||
return getfield_nothrow(rewrap_unionall(s.a, s00), name, boundscheck) && | ||
getfield_nothrow(rewrap_unionall(s.b, s00), name, boundscheck) | ||
elseif isa(s, DataType) | ||
elseif isType(s) | ||
sv = s.parameters[1] | ||
s = s0 = typeof(sv) | ||
end | ||
if isa(s, DataType) | ||
# Can't say anything about abstract types | ||
isabstracttype(s) && return false | ||
s.name.atomicfields == C_NULL || return false # TODO: currently we're only testing for ordering === :not_atomic | ||
|
@@ -863,15 +868,40 @@ function getfield_tfunc(s00, name, order, boundscheck) | |
return getfield_tfunc(s00, name) | ||
end | ||
getfield_tfunc(@nospecialize(s00), @nospecialize(name)) = _getfield_tfunc(s00, name, false) | ||
|
||
function _getfield_fieldindex(@nospecialize(s), name::Const) | ||
nv = name.val | ||
if isa(nv, Symbol) | ||
nv = fieldindex(s, nv, false) | ||
end | ||
if isa(nv, Int) | ||
return nv | ||
end | ||
return nothing | ||
end | ||
|
||
function _getfield_tfunc_const(@nospecialize(sv), name::Const, setfield::Bool) | ||
if isa(name, Const) | ||
nv = _getfield_fieldindex(typeof(sv), name) | ||
nv === nothing && return Bottom | ||
if isa(sv, DataType) && nv == DATATYPE_TYPES_FIELDINDEX && isdefined(sv, nv) | ||
return Const(getfield(sv, nv)) | ||
end | ||
if isconst(typeof(sv), nv) | ||
if isdefined(sv, nv) | ||
return Const(getfield(sv, nv)) | ||
end | ||
return Union{} | ||
end | ||
end | ||
return nothing | ||
end | ||
|
||
function _getfield_tfunc(@nospecialize(s00), @nospecialize(name), setfield::Bool) | ||
if isa(s00, Conditional) | ||
return Bottom # Bool has no fields | ||
elseif isa(s00, Const) || isconstType(s00) | ||
if !isa(s00, Const) | ||
sv = s00.parameters[1] | ||
else | ||
sv = s00.val | ||
end | ||
elseif isa(s00, Const) | ||
sv = s00.val | ||
if isa(name, Const) | ||
nv = name.val | ||
if isa(sv, Module) | ||
|
@@ -881,31 +911,15 @@ function _getfield_tfunc(@nospecialize(s00), @nospecialize(name), setfield::Bool | |
end | ||
return Bottom | ||
end | ||
if isa(nv, Symbol) | ||
nv = fieldindex(typeof(sv), nv, false) | ||
end | ||
if !isa(nv, Int) | ||
return Bottom | ||
end | ||
if isa(sv, DataType) && nv == DATATYPE_TYPES_FIELDINDEX && isdefined(sv, nv) | ||
return Const(getfield(sv, nv)) | ||
end | ||
if isconst(typeof(sv), nv) | ||
if isdefined(sv, nv) | ||
return Const(getfield(sv, nv)) | ||
end | ||
return Union{} | ||
end | ||
r = _getfield_tfunc_const(sv, name, setfield) | ||
r !== nothing && return r | ||
end | ||
s = typeof(sv) | ||
elseif isa(s00, PartialStruct) | ||
s = widenconst(s00) | ||
sty = unwrap_unionall(s)::DataType | ||
if isa(name, Const) | ||
nv = name.val | ||
if isa(nv, Symbol) | ||
nv = fieldindex(sty, nv, false) | ||
end | ||
nv = _getfield_fieldindex(sty, name) | ||
if isa(nv, Int) && 1 <= nv <= length(s00.fields) | ||
return unwrapva(s00.fields[nv]) | ||
end | ||
|
@@ -917,6 +931,26 @@ function _getfield_tfunc(@nospecialize(s00), @nospecialize(name), setfield::Bool | |
return tmerge(_getfield_tfunc(rewrap_unionall(s.a, s00), name, setfield), | ||
_getfield_tfunc(rewrap_unionall(s.b, s00), name, setfield)) | ||
end | ||
if isType(s) | ||
if isconstType(s) | ||
sv = s00.parameters[1] | ||
if isa(name, Const) | ||
r = _getfield_tfunc_const(sv, name, setfield) | ||
r !== nothing && return r | ||
end | ||
s = typeof(sv) | ||
else | ||
sv = s.parameters[1] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, this is intended to catch the cases where we are guaranteed to find a DataType at runtime. @JeffBezanson and I thought the below was sufficient to catch that, but looking at it with fresh eyes, we probably also need to exclude There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, I think that is right, since this should be a concrete DataType at runtime. Or one of the uncommon over-wrapped types at runtime (such as found in the |
||
if isa(sv, DataType) && isa(name, Const) && (!isType(sv) && sv !== Core.TypeofBottom) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you already tested above with |
||
nv = _getfield_fieldindex(DataType, name) | ||
if nv == DATATYPE_NAME_FIELDINDEX | ||
# N.B. This doesn't work in general, because | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. because? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, whoops not sure how that line got dropped. Should have said because the other fields are not guaranteed to not depend on type parameters. |
||
return Const(sv.name) | ||
end | ||
s = DataType | ||
end | ||
end | ||
end | ||
isa(s, DataType) || return Any | ||
isabstracttype(s) && return Any | ||
if s <: Tuple && !hasintersect(widenconst(name), Int) | ||
|
@@ -972,13 +1006,8 @@ function _getfield_tfunc(@nospecialize(s00), @nospecialize(name), setfield::Bool | |
end | ||
return t | ||
end | ||
fld = name.val | ||
if isa(fld, Symbol) | ||
fld = fieldindex(s, fld, false) | ||
end | ||
if !isa(fld, Int) | ||
return Bottom | ||
end | ||
fld = _getfield_fieldindex(s, name) | ||
fld === nothing && return Bottom | ||
if s <: Tuple && fld >= nf && isvarargtype(ftypes[nf]) | ||
return rewrap_unionall(unwrapva(ftypes[nf]), s00) | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isconstType
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(otherwise, it might be say
s = UnionAll
(isa DataType) here, but at runtime turn intos = Union
ors = DataType
)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, since we put in the extra checks below, that probably needs to be reflected here.