Skip to content

Commit

Permalink
fix incorrect static paramter definedness check
Browse files Browse the repository at this point in the history
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.

fix #49027
  • Loading branch information
aviatesk committed Mar 22, 2023
1 parent 7a13258 commit 1306d82
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
13 changes: 12 additions & 1 deletion base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ function sptypes_from_meth_instance(linfo::MethodInstance)
def = linfo.def
isa(def, Method) || return EMPTY_SPTYPES # toplevel
sig = def.sig
@assert !has_free_typevars(sig)
if isempty(linfo.sparam_vals)
isa(sig, UnionAll) || return EMPTY_SPTYPES
# linfo is unspecialized
Expand Down Expand Up @@ -487,7 +488,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
Expand Down
20 changes: 20 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down

0 comments on commit 1306d82

Please sign in to comment.