-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
fatal error in type inference (type bound) #43064
Comments
When union splitting, we currently emit a fallback block that prints `fatal error in type inference (type bound)`. This has always been an oddity, because there are plenty of other places in the compiler that we rely on the correctness of inference, but it has caught a number of issues over the years and we do still have a few issues (e.g. #43064) that show this error. Nevertheless, the occurrence of issues like this has become less frequent, so it might be time to turn it off soon. At the same time, we have downstream users of the compiler infrastructure that get confused by having extra `throw` calls inserted into functions that (post-#43852) were inferred as `:nothrow`. Here we add an optimization param (defaulted to on) to determine whether or not to insert the unionsplit fallback block. Because of the conservative default, we can decide later what the correct default is (maybe turn it on in `debug` mode?), while letting downstream consumers play with the setting for now to see if any issues crop up.
When union splitting, we currently emit a fallback block that prints `fatal error in type inference (type bound)`. This has always been an oddity, because there are plenty of other places in the compiler that we rely on the correctness of inference, but it has caught a number of issues over the years and we do still have a few issues (e.g. #43064) that show this error. Nevertheless, the occurrence of issues like this has become less frequent, so it might be time to turn it off soon. At the same time, we have downstream users of the compiler infrastructure that get confused by having extra `throw` calls inserted into functions that (post-#43852) were inferred as `:nothrow`. Here we add an optimization param (defaulted to on) to determine whether or not to insert the unionsplit fallback block. Because of the conservative default, we can decide later what the correct default is (maybe turn it on in `debug` mode?), while letting downstream consumers play with the setting for now to see if any issues crop up.
When union splitting, we currently emit a fallback block that prints `fatal error in type inference (type bound)`. This has always been an oddity, because there are plenty of other places in the compiler that we rely on the correctness of inference, but it has caught a number of issues over the years and we do still have a few issues (e.g. #43064) that show this error. Nevertheless, the occurrence of issues like this has become less frequent, so it might be time to turn it off soon. At the same time, we have downstream users of the compiler infrastructure that get confused by having extra `throw` calls inserted into functions that (post-#43852) were inferred as `:nothrow`. Here we add an optimization param (defaulted to on) to determine whether or not to insert the unionsplit fallback block. Because of the conservative default, we can decide later what the correct default is (maybe turn it on in `debug` mode?), while letting downstream consumers play with the setting for now to see if any issues crop up.
When union splitting, we currently emit a fallback block that prints `fatal error in type inference (type bound)`. This has always been an oddity, because there are plenty of other places in the compiler that we rely on the correctness of inference, but it has caught a number of issues over the years and we do still have a few issues (e.g. JuliaLang#43064) that show this error. Nevertheless, the occurrence of issues like this has become less frequent, so it might be time to turn it off soon. At the same time, we have downstream users of the compiler infrastructure that get confused by having extra `throw` calls inserted into functions that (post-JuliaLang#43852) were inferred as `:nothrow`. Here we add an optimization param (defaulted to on) to determine whether or not to insert the unionsplit fallback block. Because of the conservative default, we can decide later what the correct default is (maybe turn it on in `debug` mode?), while letting downstream consumers play with the setting for now to see if any issues crop up.
When union splitting, we currently emit a fallback block that prints `fatal error in type inference (type bound)`. This has always been an oddity, because there are plenty of other places in the compiler that we rely on the correctness of inference, but it has caught a number of issues over the years and we do still have a few issues (e.g. JuliaLang#43064) that show this error. Nevertheless, the occurrence of issues like this has become less frequent, so it might be time to turn it off soon. At the same time, we have downstream users of the compiler infrastructure that get confused by having extra `throw` calls inserted into functions that (post-JuliaLang#43852) were inferred as `:nothrow`. Here we add an optimization param (defaulted to on) to determine whether or not to insert the unionsplit fallback block. Because of the conservative default, we can decide later what the correct default is (maybe turn it on in `debug` mode?), while letting downstream consumers play with the setting for now to see if any issues crop up.
When union splitting, we currently emit a fallback block that prints `fatal error in type inference (type bound)`. This has always been an oddity, because there are plenty of other places in the compiler that we rely on the correctness of inference, but it has caught a number of issues over the years and we do still have a few issues (e.g. JuliaLang#43064) that show this error. Nevertheless, the occurrence of issues like this has become less frequent, so it might be time to turn it off soon. At the same time, we have downstream users of the compiler infrastructure that get confused by having extra `throw` calls inserted into functions that (post-JuliaLang#43852) were inferred as `:nothrow`. Here we add an optimization param (defaulted to on) to determine whether or not to insert the unionsplit fallback block. Because of the conservative default, we can decide later what the correct default is (maybe turn it on in `debug` mode?), while letting downstream consumers play with the setting for now to see if any issues crop up.
Reproducers (first two from @mcabbott): julia> mapslices(tuple, [1 2; 3 4], dims=1)
1×2 Matrix{Tuple{Vector{Int64}}}:
([1, 3],) ([2, 4],)
julia> mapslices(x -> tuple(x), [1 2; 3 4], dims=1)
ERROR: fatal error in type inference (type bound)
Stacktrace:
[1] mapslices(f::var"#5#6", A::Matrix{Int64}; dims::Int64)
@ Base ./abstractarray.jl:2896
[2] top-level scope
@ REPL[13]:1
julia> mapslices(argmax, rand(10,10); dims=2)
ERROR: fatal error in type inference (type bound)
Stacktrace:
[1] mapslices(f::typeof(argmax), A::Matrix{Float64}; dims::Int64)
@ Base ./abstractarray.jl:2896
[2] top-level scope
@ REPL[14]:1 |
One more example, in which julia> mapslices(findmin, rand(3); dims=1) # works in 1D, and infers
1-element Vector{Tuple{Float64, Int64}}:
(0.10724568875730223, 3)
julia> @code_warntype mapslices(findmin, rand(3); dims=1)
...
Body::Vector{Tuple{Float64, Int64}}
julia> mapslices(findmin, rand(3,3); dims=1) # errors in 2D
ERROR: fatal error in type inference (type bound)
julia> mapslices(findmin, rand(3,3,3); dims=1) |> summary # works in 3D, but does not infer
"1×3×3 Array{Tuple{Float64, Int64}, 3}"
julia> @code_warntype mapslices(findmin, rand(3,3,3); dims=1)
...
Body::Any |
Reduction based on the julia> function f(dims)
idx1 = ntuple(d -> d in dims ? (:) : 1, 2)
Aslice = [1 2; 3 4][idx1...]
r1 = (x -> tuple(x))(Aslice)
_res1 = similar(Aslice, typeof(r1), Base.reduced_indices(Aslice, 1:ndims(Aslice)))
_res1[begin] = r1
end
f (generic function with 1 method)
julia> f(1)
ERROR: fatal error in type inference (type bound) With Indeed, I find the following: julia> T1 = Type{Tuple{Int64}};
julia> T2 = Type{Tuple{Vector{Int64}}};
julia> only(code_typed(similar, (Vector{Int64}, T1, Tuple{Base.OneTo{Int64}})))[2] # ok
Vector{Tuple{Int64}} (alias for Array{Tuple{Int64}, 1})
julia> only(code_typed(similar, (Vector{Int64}, T2, Tuple{Base.OneTo{Int64}})))[2] # ok
Vector{Tuple{Vector{Int64}}} (alias for Array{Tuple{Array{Int64, 1}}, 1})
julia> only(code_typed(similar, (Vector{Int64}, Union{T1, T2}, Tuple{Base.OneTo{Int64}})))[2] # should be the union of the above?
Vector{Tuple{Int64}} (alias for Array{Tuple{Int64}, 1}) And: julia> code_warntype(similar, (Vector{Int64}, Union{T1, T2}, Tuple{Base.OneTo{Int64}}))
MethodInstance for similar(::Vector{Int64}, ::Union{Type{Tuple{Vector{Int64}}}, Type{Tuple{Int64}}}, ::Tuple{Base.OneTo{Int64}})
from similar(a::AbstractArray, ::Type{T}, dims::Tuple{Union{Integer, Base.OneTo}, Vararg{Union{Integer, Base.OneTo}}}) where T
@ Base abstractarray.jl:815
Static Parameters
T = Tuple{Int64}
Arguments
#self#::Core.Const(similar)
a::Vector{Int64}
_::Union{Type{Tuple{Vector{Int64}}}, Type{Tuple{Int64}}}
dims::Tuple{Base.OneTo{Int64}}
Body::Vector{Tuple{Int64}}
1 ─ %1 = $(Expr(:static_parameter, 1))::Core.Const(Tuple{Int64})
│ %2 = Base.to_shape(dims)::Tuple{Int64}
│ %3 = Base.similar(a, %1, %2)::Vector{Tuple{Int64}}
└── return %3 Note the discrepancy between julia> code_warntype(similar, (Vector{Int64}, Union{T1, T2}, Int64))
MethodInstance for similar(::Vector{Int64}, ::Union{Type{Tuple{Vector{Int64}}}, Type{Tuple{Int64}}}, ::Int64)
from similar(a::AbstractArray, ::Type{T}, dims::Union{Integer, AbstractUnitRange}...) where T
@ Base abstractarray.jl:809
Static Parameters
T <: Any
Arguments
#self#::Core.Const(similar)
a::Vector{Int64}
_::Union{Type{Tuple{Vector{Int64}}}, Type{Tuple{Int64}}}
dims::Tuple{Int64}
Body::Union{Vector{Tuple{Vector{Int64}}}, Vector{Tuple{Int64}}}
1 ─ %1 = $(Expr(:static_parameter, 1))::Union{Type{Tuple{Vector{Int64}}}, Type{Tuple{Int64}}}
│ %2 = Base.to_shape(dims)::Tuple{Int64}
│ %3 = Base.similar(a, %1, %2)::Union{Vector{Tuple{Vector{Int64}}}, Vector{Tuple{Int64}}}
└── return %3 Here |
Looks like a bug in f(::Type{T}, ::Union{Nothing,Int,Missing}) where {T} = T
tt = Tuple{typeof(f),Union{Type{Int},Type{Float16}},Nothing}
match = Base._methods_by_ftype(tt, -1, typemax(UInt))[1]
match.sparams # svec(Int64) wrong
g(::Type{T}, ::Any) where {T} = T
tt = Tuple{typeof(g),Union{Type{Int},Type{Float16}},Nothing}
match = Base._methods_by_ftype(tt, -1, Base.get_world_counter())[1]
match.sparams #svec(T) # correct |
Duplicate of #41096 (comment) |
This commit fixes examples reported in JuliaLang#43064. We should not erase the current `envout` value, as `subtype_unionall` needs it to check whether we are trying to assign a different one.
This commit fixes examples reported in JuliaLang#43064. We should not erase the current `envout` value, as `subtype_unionall` needs it to check whether we are trying to assign a different one.
This commit fixes examples reported in JuliaLang#43064. We should not erase the current `envout` value, as `subtype_unionall` needs it to check whether we are trying to assign a different one.
This commit fixes examples reported in JuliaLang#43064. We should not erase the current `envout` value, as `subtype_unionall` needs it to check whether we are trying to assign a different one.
This commit fixes examples reported in JuliaLang#43064. We should not erase the current `envout` value, as `subtype_unionall` needs it to check whether we are trying to assign a different one.
I got the above error locally with #40996, which I have never seen before.
CI sees it too, here: https://build.julialang.org/#/builders/7/builds/5932/steps/5/logs/stdio (17f851b)
The text was updated successfully, but these errors were encountered: