Skip to content
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

SumOfSquares error in inference #57852

Open
vtjnash opened this issue Mar 21, 2025 · 2 comments
Open

SumOfSquares error in inference #57852

vtjnash opened this issue Mar 21, 2025 · 2 comments
Labels
regression Regression in behavior compared to a previous version types and dispatch Types, subtyping and method dispatch

Comments

@vtjnash
Copy link
Member

vtjnash commented Mar 21, 2025

Looking at the segfault in https://s3.amazonaws.com/julialang-reports/nanosoldier/pkgeval/by_date/2025-03/18/SumOfSquares.primary.log, inference is coming to the wrong answer on master

julia> using MathOptInterface, MutableArithmetics, MultivariateMoments

julia> code_typed(MutableArithmetics.promote_operation, Tuple{typeof(MultivariateMoments.:+), Type{MathOptInterface.VariableIndex}, Type{MathOptInterface.ScalarAffineFunction{Complex{Float64}}} where _A}, optimize=false)
[ Warning: + is defined in Base and is not public in MultivariateMoments
1-element Vector{Any}:
 CodeInfo(
    @ /home/vtjnash/.julia/packages/MathOptInterface/jGuEH/src/Utilities/mutable_arithmetics.jl:90 within `unknown scope`
1 ─ %1 = MathOptInterface.Utilities.promote_operation::Core.Const(MathOptInterface.Utilities.promote_operation)
│   %2 = $(Expr(:static_parameter, 1))::Core.Const(ComplexF64)
│   %3 =   dynamic (%1)(op, %2, F, G)::Core.Const(MathOptInterface.ScalarAffineFunction{ComplexF64})
└──      return %3
) => Type{MathOptInterface.ScalarAffineFunction{ComplexF64}}

julia> code_typed(MutableArithmetics.promote_operation, Tuple{typeof(MultivariateMoments.:+), Type{MathOptInterface.VariableIndex}, Type{MathOptInterface.ScalarAffineFunction{Complex{_A}}} where _A}, optimize=false)
1-element Vector{Any}:
 CodeInfo(
    @ /home/vtjnash/.julia/packages/MathOptInterface/jGuEH/src/Utilities/mutable_arithmetics.jl:90 within `unknown scope`
1 ─ %1 = MathOptInterface.Utilities.promote_operation::Core.Const(MathOptInterface.Utilities.promote_operation)
│   %2 = $(Expr(:static_parameter, 1))::Type{T} where T<:(Complex{_A} where _A)
│          dynamic (%1)(op, %2, F, G)::Union{}
└──      Core.Const(:(return %3))::Union{}
) => Union{}

on v1.12 this was

julia> code_typed(MutableArithmetics.promote_operation, Tuple{typeof(MultivariateMoments.:+), Type{MathOptInterface.VariableIndex}, Type{MathOptInterface.ScalarAffineFunction{Complex{_A}}} where _A}, optimize=false)
1-element Vector{Any}:
 CodeInfo(
    @ /home/vtjnash/.julia/packages/MathOptInterface/jGuEH/src/Utilities/mutable_arithmetics.jl:90 within `unknown scope`
1 ─ %1 = MathOptInterface.Utilities.promote_operation::Core.Const(MathOptInterface.Utilities.promote_operation)
│   %2 = $(Expr(:static_parameter, 1))::Type{T} where T<:(Complex{_A} where _A)
│   %3 =   dynamic (%1)(op, %2, F, G)::Type{MathOptInterface.ScalarAffineFunction{Complex{_A}}} where _A
└──      return %3
) => Type{MathOptInterface.ScalarAffineFunction{Complex{_A}}} where _A
@vtjnash
Copy link
Member Author

vtjnash commented Mar 21, 2025

Actually, only a slight tweak is needed to the MWE to make it fail on v1.12 and v1.11 too. Somehow inference is reporting there are no possible methods to call, and so inlining is replacing the dynamic dispatch call with Core.throw_methoderror, even though there seems no sane reason for doing that (there is in fact exactly one method matching)

julia> code_typed(MutableArithmetics.promote_operation, Tuple{typeof(MultivariateMoments.:+), Type{Complex{T}} where T, Type{MathOptInterface.VariableIndex}}, optimize=false)
1-element Vector{Any}:
 CodeInfo(
    @ /home/vtjnash/.julia/packages/MathOptInterface/jGuEH/src/Utilities/mutable_arithmetics.jl:122 within `unknown scope`
1 ─ %1 = MathOptInterface.Utilities.promote_operation::Core.Const(MathOptInterface.Utilities.promote_operation)
│          dynamic (%1)(op, F, F, G)::Union{}
└──      Core.Const(:(return %2))::Union{}
) => Union{}

julia> code_typed(MutableArithmetics.promote_operation, Tuple{typeof(MultivariateMoments.:+), Type{Complex{T}} where T, Type{MathOptInterface.VariableIndex}}, optimize=true)
1-element Vector{Any}:
 CodeInfo(
    @ /home/vtjnash/.julia/packages/MathOptInterface/jGuEH/src/Utilities/mutable_arithmetics.jl:122 within `promote_operation`
1 ─       builtin Core.throw_methoderror(MathOptInterface.Utilities.promote_operation, op, F, F, G)::Union{}
└──     unreachable
) => Union{}

@vtjnash
Copy link
Member Author

vtjnash commented Mar 21, 2025

Oh, amazing, this packages uses two different functions of the same name in different modules and has them call into each other. Here's the real method call which failed in type-intersection:

julia> methods(MathOptInterface.Utilities.promote_operation, Tuple{typeof(+), Type{Complex{Float64}}, Type{Complex{Float64}} where T, Type{MathOptInterface.VariableIndex}})
# 1 method for generic function "promote_operation" from MathOptInterface.Utilities:
 [1] promote_operation(::Union{typeof(+), typeof(-)}, ::Type{T}, ::Type{<:F}, ::Type{<:F}) where {T, F<:Union{MathOptInterface.VariableIndex, MathOptInterface.ScalarAffineFunction{T}, T}}
     @ ~/.julia/packages/MathOptInterface/jGuEH/src/Utilities/promote_operation.jl:70

julia> methods(MathOptInterface.Utilities.promote_operation, Tuple{typeof(+), Type{Complex{T}} where T, Type{Complex{T}} where T, Type{MathOptInterface.VariableIndex}})
# 0 methods for generic function "promote_operation" from MathOptInterface.Utilities

This intersection mistake was introduced in v1.7:

julia> A = Tuple{Type{T}, Type{<:F}, Type{<:F}} where {T, F<:Union{String, T}}
Tuple{Type{T}, Type{<:F}, Type{<:F}} where {T, F<:Union{String, T}}

julia> typeintersect(A, Tuple{Type{Complex{T}} where T, Type{Complex{T}} where T, Type{String}})
Union{} # wrong
# previously correct answer was Tuple{Type{Complex{T}}, Type{Complex{T}}, Type{String}} where T

julia> typeintersect(A, Tuple{Type{Complex{Float64}} where T, Type{Complex{Float64}} where T, Type{String}})
Tuple{Type{ComplexF64}, Type{ComplexF64}, Type{String}} # proof-by-counter-example

@vtjnash vtjnash added regression Regression in behavior compared to a previous version types and dispatch Types, subtyping and method dispatch labels Mar 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
regression Regression in behavior compared to a previous version types and dispatch Types, subtyping and method dispatch
Projects
None yet
Development

No branches or pull requests

1 participant