From 3d6da2cffeaca8ee510b3598b31055d4b3d917b6 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 25 Apr 2024 00:04:24 -0400 Subject: [PATCH] Make sure `fieldcount` constant-folds for `Tuple{...}` (#54239) In PR #53750, we stopped constant folding `isdefined` for non-`const` fields assuming that they may revert to `undef`. Unfortunately, this broke const-prop for `fieldcount` for `Tuple`s, causing significant inference quality degradation. Adjust `fieldcount` to avoid this. --- base/reflection.jl | 7 +++++-- test/compiler/inference.jl | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/base/reflection.jl b/base/reflection.jl index f27da6d4df32e..b6cf005d1a11e 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1005,12 +1005,15 @@ function datatype_fieldcount(t::DataType) return fieldcount(types) end return nothing - elseif isabstracttype(t) || (t.name === Tuple.name && isvatuple(t)) + elseif isabstracttype(t) return nothing end - if isdefined(t, :types) + if t.name === Tuple.name + isvatuple(t) && return nothing return length(t.types) end + # Equivalent to length(t.types), but `t.types` is lazy and we do not want + # to be forced to compute it. return length(t.name.names) end diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 358b165f1d7e8..870eeaaf0687b 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5725,3 +5725,6 @@ let interp = CachedConditionalInterp(); result.linfo.def.name === :func_cached_conditional end == 1 end + +# fieldcount on `Tuple` should constant fold, even though `.fields` not const +@test fully_eliminated(Base.fieldcount, Tuple{Type{Tuple{Nothing, Int, Int}}})