From 489d076452130c718c7d77b157b0d503bfc31602 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Thu, 23 Mar 2023 10:23:34 +0900 Subject: [PATCH] fix incorrect static parameter definedness check (#49097) We use the specialized signature of a method for accurate analysis of whether a static parameter is constrained or not. However, it turns out that we can only use it when it doesn't contain any free type variables (which it sometimes does, e.g., when the inference entry is given a signature with a free type variable). In such cases, we should use the method signature, which, by design, never contains any free type variables. --- base/compiler/inferencestate.jl | 12 +++++++++++- test/compiler/inference.jl | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 74db247e472b6..aea657404b249 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -487,7 +487,17 @@ function sptypes_from_meth_instance(linfo::MethodInstance) ty = UnionAll(tv, Type{tv}) end @label ty_computed - undef = !constrains_param(v, linfo.specTypes, #=covariant=#true) + undef = !(let sig=sig + # if the specialized signature `linfo.specTypes` doesn't contain any free + # type variables, we can use it for a more accurate analysis of whether `v` + # is constrained or not, otherwise we should use `def.sig` which always + # doesn't contain any free type variables + if !has_free_typevars(linfo.specTypes) + sig = linfo.specTypes + end + @assert !has_free_typevars(sig) + constrains_param(v, sig, #=covariant=#true) + end) elseif isvarargtype(v) ty = Int undef = false diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 85509ebf57199..e3d66c7531021 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -4684,6 +4684,26 @@ unknown_sparam_nothrow2(x::Ref{Ref{T}}) where T = @isdefined(T) ? T::Type : noth @test only(Base.return_types(unknown_sparam_nothrow1, (Ref,))) === Type @test only(Base.return_types(unknown_sparam_nothrow2, (Ref{Ref{T}} where T,))) === Type +struct Issue49027{Ty<:Number} + x::Ty +end +function issue49027(::Type{<:Issue49027{Ty}}) where Ty + if @isdefined Ty # should be false when `Ty` is given as a free type var. + return Ty::DataType + end + return nothing +end +@test only(Base.return_types(issue49027, (Type{Issue49027{TypeVar(:Ty)}},))) >: Nothing +@test isnothing(issue49027(Issue49027{TypeVar(:Ty)})) +function issue49027_integer(::Type{<:Issue49027{Ty}}) where Ty<:Integer + if @isdefined Ty # should be false when `Ty` is given as a free type var. + return Ty::DataType + end + nothing +end +@test only(Base.return_types(issue49027_integer, (Type{Issue49027{TypeVar(:Ty,Int)}},))) >: Nothing +@test isnothing(issue49027_integer(Issue49027{TypeVar(:Ty,Int)})) + function fapplicable end gapplicable() = Val(applicable(fapplicable)) gapplicable(x) = Val(applicable(fapplicable; x))