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

Fix various JET errors #3519

Merged
merged 2 commits into from
Sep 21, 2023
Merged

Fix various JET errors #3519

merged 2 commits into from
Sep 21, 2023

Conversation

odow
Copy link
Member

@odow odow commented Sep 20, 2023

There are bunch of issues stemming from MOI: jump-dev/MathOptInterface.jl#2268.

In most cases, these change nothing at runtime, but they do make things friendlier for the compiler.

A common case is:

_init_NLP(model)
MOI.Nonlinear.register_operator(model.nlp_model, op, dimension, f)

where model.nlp_model::Union{Nothing,MOI.Nonlinear.Model}.

We know that after the call to _init_NLP it will never be Nothing, but the compiler cannot (currently) prove that, and so anything trying to do static compilation will look for the method MOI.Nonlinear.register_operator(::Nothing, ...) which doesn't exist.

We could technically ignore them, but fixing even the minor issues in JET lets us more explicitly find and track actual bugs like #3518, which would otherwise get lost in the noise of 10's or 100's of errors.

@codecov
Copy link

codecov bot commented Sep 20, 2023

Codecov Report

Patch coverage: 100.00% and no project coverage change.

Comparison is base (1cd82da) 98.25% compared to head (8692dd0) 98.25%.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #3519   +/-   ##
=======================================
  Coverage   98.25%   98.25%           
=======================================
  Files          37       37           
  Lines        5550     5560   +10     
=======================================
+ Hits         5453     5463   +10     
  Misses         97       97           
Files Changed Coverage Δ
src/copy.jl 96.22% <100.00%> (+0.03%) ⬆️
src/nlp.jl 100.00% <100.00%> (ø)
src/nlp_expr.jl 99.52% <100.00%> (ø)
src/objective.jl 96.72% <100.00%> (+0.05%) ⬆️
src/optimizer_interface.jl 97.02% <100.00%> (+0.01%) ⬆️
src/print.jl 99.76% <100.00%> (+<0.01%) ⬆️

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -178,7 +178,7 @@ function _nlp_objective_function(model::GenericModel)
if model.nlp_model === nothing
return nothing
end
return model.nlp_model.objective
return something(model.nlp_model).objective
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's surprising the compiler isn't able to figure this one out

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of this is because model.nlp_model calls getproperty, which may do arbitrary things.

This is another cause where the specific concrete call of a particular GenericModel{T} might be able to, but we can't figure it out statically based on (::GenericModel).

Copy link
Member

@blegat blegat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's nice to have a tool like JET that is able to highlight all the cases that are confusing static analysis

@odow
Copy link
Member Author

odow commented Sep 20, 2023

═════ 12 possible errors found ═════
┌ getindex(x::JuMP.Containers._AxisLookup{Dict{K, Int64}}, keys::AbstractVector) where K @ JuMP.Containers /Users/oscar/.julia/dev/JuMP/src/Containers/DenseAxisArray.jl:59
│┌ collect(itr::Base.Generator) @ Base ./array.jl:792
││┌ collect_to_with_first!(dest::Union{var"##JETVirtualModule#292".JuMP.Containers.DenseAxisArray, var"##JETVirtualModule#292".JuMP.Containers.SparseAxisArray}, first_value::Any, iterator::Base.Generator, state::Any) @ var"##JETVirtualModule#292".JuMP.Containers /Users/oscar/.julia/dev/JuMP/src/Containers/Containers.jl:48
│││┌ indexed_iterate(I::Nothing, i::Int64) @ Base ./tuple.jl:91
││││ no matching method found `iterate(::Nothing)`: x = iterate(I::Nothing)
│││└────────────────────
│││┌ indexed_iterate(I::Nothing, i::Int64, state::Int64) @ Base ./tuple.jl:96
││││ no matching method found `iterate(::Nothing, ::Int64)`: x = iterate(I::Nothing, state::Int64)
│││└────────────────────
┌ _fixed_indices(view_axes::Tuple, axes::Tuple) @ JuMP.Containers /Users/oscar/.julia/dev/JuMP/src/Containers/DenseAxisArray.jl:750
│┌ filter(f::JuMP.Containers.var"#35#37", t::Tuple{Vararg{Int64}}) @ Base ./tuple.jl:440
││┌ collect(itr::Tuple{Vararg{Int64}}) @ Base ./array.jl:707
│││┌ _collect(cont::UnitRange{Int64}, itr::Tuple{Vararg{Int64}}, ::Base.HasEltype, isz::Base.HasLength) @ Base ./array.jl:713
││││┌ copyto!(dest::Vector{Union{}}, src::Tuple{Vararg{Int64}}) @ Base ./abstractarray.jl:951
│││││┌ setindex!(A::Vector{Union{}}, x::Int64, i1::Int64) @ Base ./array.jl:969
││││││ no matching method found `convert(::Type{Union{}}, ::Int64)`: convert(T::Type{Union{}}, x::Int64)
│││││└────────────────────
││┌ filter(f::JuMP.Containers.var"#35#37", a::Vector{Union{}}) @ Base ./array.jl:2608
│││┌ iterate(A::Vector{Union{}}) @ Base ./array.jl:893
││││┌ iterate(A::Vector{Union{}}, i::Int64) @ Base ./array.jl:893
│││││┌ getindex(A::Vector{Union{}}, i1::Int64) @ Base ./essentials.jl:13
││││││ invalid builtin function call: Base.arrayref($(Expr(:boundscheck)), A::Vector{Union{}}, i1::Int64)
│││││└────────────────────
┌ normalized_coefficient(con_ref::JuMP.ConstraintRef{<:JuMP.AbstractModel, MathOptInterface.ConstraintIndex{F, S}}, variable::Any) where {S, T, F<:Union{MathOptInterface.ScalarAffineFunction{T}, MathOptInterface.ScalarQuadraticFunction{T}}} @ JuMP /Users/oscar/.julia/dev/JuMP/src/constraints.jl:828
│┌ constraint_object(con_ref::JuMP.ConstraintRef{<:JuMP.AbstractModel, MathOptInterface.ConstraintIndex{Union{}, SetType}}) where SetType<:MathOptInterface.AbstractVectorSet @ JuMP /Users/oscar/.julia/dev/JuMP/src/constraints.jl:663
││ invalid builtin function call: f = typeassert(MathOptInterface.get(model, MathOptInterface.ConstraintFunction()::MathOptInterface.ConstraintFunction, con_ref::JuMP.ConstraintRef{<:JuMP.AbstractModel, MathOptInterface.ConstraintIndex{Union{}, SetType}} where SetType<:MathOptInterface.AbstractVectorSet)::Any, FuncType::Type{Union{}})
│└────────────────────
┌ normalized_coefficient(con_ref::JuMP.ConstraintRef{<:JuMP.AbstractModel, MathOptInterface.ConstraintIndex{F, S}}, variable::Any) where {S, T, F<:Union{MathOptInterface.ScalarAffineFunction{T}, MathOptInterface.ScalarQuadraticFunction{T}}} @ JuMP /Users/oscar/.julia/dev/JuMP/src/constraints.jl:829
│ no matching method found `_affine_coefficient(::Number, ::Any)` (1/2 union split): JuMP._affine_coefficient(con.func::Union{Number, JuMP.AbstractJuMPScalar}, variable::Any)
└────────────────────
┌ constraint_object(c::JuMP.NonlinearConstraintRef) @ JuMP /Users/oscar/.julia/dev/JuMP/src/nlp_expr.jl:582
│┌ jump_function(model::JuMP.Model, expr::MathOptInterface.Nonlinear.Expression) @ JuMP /Users/oscar/.julia/dev/JuMP/src/nlp_expr.jl:599
││┌ getproperty(x::Nothing, f::Symbol) @ Base ./Base.jl:37
│││ type Nothing has no field operators: Base.getfield(x::Nothing, f::Symbol)
││└────────────────────
┌ _functionize(v::LinearAlgebra.Symmetric{V, S} where S<:(AbstractMatrix{<:V})) where V<:JuMP.AbstractVariableRef @ JuMP /Users/oscar/.julia/dev/JuMP/src/macros.jl:380
│┌ LinearAlgebra.Symmetric(A::LinearAlgebra.Hermitian) @ LinearAlgebra /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-grannysmith-C07ZQ07RJYVY.0/build/default-grannysmith-C07ZQ07RJYVY-0/julialang/julia-release-1-dot-9/usr/share/julia/stdlib/v1.9/LinearAlgebra/src/symmetric.jl:179
││┌ LinearAlgebra.Symmetric(A::LinearAlgebra.Hermitian, uplo::Symbol) @ LinearAlgebra /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-grannysmith-C07ZQ07RJYVY.0/build/default-grannysmith-C07ZQ07RJYVY-0/julialang/julia-release-1-dot-9/usr/share/julia/stdlib/v1.9/LinearAlgebra/src/symmetric.jl:182
│││┌ diagind(A::AbstractMatrix) @ LinearAlgebra /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-grannysmith-C07ZQ07RJYVY.0/build/default-grannysmith-C07ZQ07RJYVY-0/julialang/julia-release-1-dot-9/usr/share/julia/stdlib/v1.9/LinearAlgebra/src/dense.jl:224
││││┌ diagind(A::AbstractMatrix, k::Int64) @ LinearAlgebra /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-grannysmith-C07ZQ07RJYVY.0/build/default-grannysmith-C07ZQ07RJYVY-0/julialang/julia-release-1-dot-9/usr/share/julia/stdlib/v1.9/LinearAlgebra/src/dense.jl:225
│││││┌ diagind(m::Integer, n::Integer, k::Int64) @ LinearAlgebra /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-grannysmith-C07ZQ07RJYVY.0/build/default-grannysmith-C07ZQ07RJYVY-0/julialang/julia-release-1-dot-9/usr/share/julia/stdlib/v1.9/LinearAlgebra/src/dense.jl:201
││││││┌ kwcall(::NamedTuple{(:step, :length), _A} where _A<:Tuple{Any, Any}, ::typeof(range), start::Int64) @ Base ./range.jl:142
│││││││┌ range(start::Int64; stop::Nothing, length::Union{Nothing, Integer}, step::Any) @ Base ./range.jl:142
││││││││┌ _range(start::Int64, step::Any, stop::Nothing, len::Integer) @ Base ./range.jl:163
│││││││││┌ range_start_step_length(a::Int64, st::Union{Float16, Float32, Float64}, len::Integer) @ Base ./twiceprecision.jl:440
││││││││││┌ range_start_step_length(a::Float16, st::Float16, len::Integer) @ Base ./twiceprecision.jl:461
│││││││││││┌ floatrange(::Type{Float16}, start_n::Int64, step_n::Int64, len::Integer, den::Int64) @ Base ./twiceprecision.jl:388
││││││││││││┌ round(::DataType, x::Float64) @ Base ./missing.jl:144
│││││││││││││┌ round(::DataType, x::Float64, r::RoundingMode{:Nearest}) @ Base ./missing.jl:144
││││││││││││││┌ round(::Core.TypeofBottom, x::Float64, r::RoundingMode{:Nearest}) @ Base ./floatfuncs.jl:124
│││││││││││││││ no matching method found `trunc(::Type{Union{}}, ::Float64)`: trunc(T::Type{Union{}}, x::Float64)
││││││││││││││└────────────────────
┌ build_constraint(_error::Function, func::Any, set::Any, args::Vararg{Any}) @ JuMP /Users/oscar/.julia/dev/JuMP/src/macros.jl:935
│┌ build_constraint(_error::Function, func::Any, set::Any, args::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}) @ JuMP /Users/oscar/.julia/dev/JuMP/src/macros.jl:938
││┌ join(iterator::Tuple{Vararg{Union{}}}, delim::String) @ Base ./strings/io.jl:353
│││┌ sprint(::typeof(join), ::Tuple{Vararg{Union{}}}, ::String) @ Base ./strings/io.jl:107
││││┌ sprint(::typeof(join), ::Tuple{Vararg{Union{}}}, ::String; context::Nothing, sizehint::Int64) @ Base ./strings/io.jl:114
│││││┌ join(io::IOBuffer, iterator::Tuple{Vararg{Union{}}}, delim::String) @ Base ./strings/io.jl:346
││││││┌ iterate(t::Tuple{Vararg{Union{}}}) @ Base ./tuple.jl:68
│││││││┌ iterate(t::Tuple{Vararg{Union{}}}, i::Int64) @ Base ./tuple.jl:68
││││││││┌ getindex(t::Tuple{Vararg{Union{}}}, i::Int64) @ Base ./tuple.jl:29
│││││││││ invalid builtin function call: Base.getfield(t::Tuple{Vararg{Union{}}}, i::Int64, $(Expr(:boundscheck)))
││││││││└────────────────────
┌ primal_feasibility_report(model::JuMP.GenericModel{T}, point::AbstractDict{JuMP.GenericVariableRef{T}, T}; atol::Any, skip_missing::Bool) where T @ JuMP /Users/oscar/.julia/dev/JuMP/src/feasibility_checker.jl:58
│┌ kwcall(::NamedTuple{(:atol, :skip_missing), _A} where _A<:Tuple{Any, Bool}, ::typeof(JuMP.primal_feasibility_report), point::JuMP.var"#146#147"{Bool}, model::JuMP.GenericModel{T} where T) @ JuMP /Users/oscar/.julia/dev/JuMP/src/feasibility_checker.jl:99
││┌ primal_feasibility_report(point::JuMP.var"#146#147"{Bool}, model::JuMP.GenericModel{T}; atol::Any, skip_missing::Bool) where T @ JuMP /Users/oscar/.julia/dev/JuMP/src/feasibility_checker.jl:123
│││┌ _add_infeasible_nonlinear_constraints(model::JuMP.GenericModel{T}, violated_constraints::Dict{Any, T}, point_f::JuMP.var"#146#147"{Bool}, atol::T) where T @ JuMP /Users/oscar/.julia/dev/JuMP/src/feasibility_checker.jl:158
││││┌ initialize(evaluator::MathOptInterface.Nonlinear.Evaluator{MathOptInterface.Nonlinear.ReverseAD.NLPEvaluator}, features::Vector{Symbol}) @ MathOptInterface.Nonlinear /Users/oscar/.julia/dev/MathOptInterface/src/Nonlinear/evaluator.jl:79
│││││┌ initialize(d::MathOptInterface.Nonlinear.ReverseAD.NLPEvaluator, requested_features::Vector{Symbol}) @ MathOptInterface.Nonlinear.ReverseAD /Users/oscar/.julia/dev/MathOptInterface/src/Nonlinear/ReverseAD/mathoptinterface_api.jl:163
││││││┌ append!(a::Vector{Tuple{Int64, Int64}}, iter::Base.Iterators.Zip{Tuple{Vector{Int64}, Vector{Int64}}}) @ Base ./array.jl:1126
│││││││┌ _append!(a::Vector{Tuple{Int64, Int64}}, ::Base.HasShape{1}, iter::Base.Iterators.Zip{Tuple{Vector{Int64}, Vector{Int64}}}) @ Base ./array.jl:1135
││││││││┌ iterate(z::Base.Iterators.Zip{Tuple{UnitRange{Int64}, Base.Iterators.Zip{Tuple{Vector{Int64}, Vector{Int64}}}}}) @ Base.Iterators ./iterators.jl:406
│││││││││┌ _zip_iterate_all(is::Tuple{UnitRange{Int64}, Base.Iterators.Zip{Tuple{Vector{Int64}, Vector{Int64}}}}, ss::Tuple{Tuple{}, Tuple{}}) @ Base.Iterators ./iterators.jl:416
││││││││││┌ _zip_iterate_some(is::Tuple{UnitRange{Int64}, Base.Iterators.Zip{Tuple{Vector{Int64}, Vector{Int64}}}}, ss::Tuple{Tuple{}, Tuple{}}, ds::Tuple{Missing, Missing}, f::Missing) @ Base.Iterators ./iterators.jl:426
│││││││││││┌ _zip_iterate_some(is::Tuple{Base.Iterators.Zip{Tuple{Vector{Int64}, Vector{Int64}}}}, ss::Tuple{Tuple{}}, ds::Tuple{Missing}, f::Missing) @ Base.Iterators ./iterators.jl:424
││││││││││││┌ iterate(z::Base.Iterators.Zip{Tuple{Vector{Int64}, Vector{Int64}}}) @ Base.Iterators ./iterators.jl:406
│││││││││││││┌ _zip_iterate_all(is::Tuple{Vector{Int64}, Vector{Int64}}, ss::Any) @ Base.Iterators ./iterators.jl:414
││││││││││││││┌ _zip_isdone(is::Tuple{Vector{Int64}, Vector{Int64}}, ss::Any) @ Base.Iterators ./iterators.jl:446
│││││││││││││││┌ _zip_isdone(is::Tuple{Vector{Int64}}, ss::Any) @ Base.Iterators ./iterators.jl:446
││││││││││││││││┌ _zip_isdone(is::Tuple{}, ss::Any) @ Base.Iterators ./iterators.jl:445
│││││││││││││││││┌ getindex(t::Tuple{}, i::Int64) @ Base ./tuple.jl:29
││││││││││││││││││ BoundsError: attempt to access Tuple{} at index [1]: Base.getfield(t::Tuple{}, i::Int64, $(Expr(:boundscheck)))
│││││││││││││││││└────────────────────
┌ write_to_file(model::JuMP.GenericModel, filename::String; format::MathOptInterface.FileFormats.FileFormat, kwargs::Base.Pairs{Symbol, V, Tuple{Vararg{Symbol, N}}, NamedTuple{names, T}} where {V, N, names, T<:Tuple{Vararg{Any, N}}}) @ JuMP /Users/oscar/.julia/dev/JuMP/src/file_formats.jl:52
│┌ _copy_to_bridged_model(f::JuMP.var"#150#151"{MathOptInterface.FileFormats.FileFormat, _A, String} where _A, model::JuMP.GenericModel) @ JuMP /Users/oscar/.julia/dev/JuMP/src/file_formats.jl:20
││┌ copy_to(dest::MathOptInterface.Bridges.LazyBridgeOptimizer, src::JuMP.GenericModel) @ JuMP /Users/oscar/.julia/dev/JuMP/src/copy.jl:337
│││┌ copy_to(dest::MathOptInterface.Bridges.LazyBridgeOptimizer, src::MathOptInterface.AbstractOptimizer) @ MathOptInterface.Bridges /Users/oscar/.julia/dev/MathOptInterface/src/Bridges/bridge_optimizer.jl:453
││││┌ default_copy_to(dest::MathOptInterface.Bridges.LazyBridgeOptimizer, src::MathOptInterface.AbstractOptimizer) @ MathOptInterface.Utilities /Users/oscar/.julia/dev/MathOptInterface/src/Utilities/copy.jl:490
│││││┌ collect(::Type{Any}, itr::Base.Generator) @ Base ./array.jl:642
││││││┌ _collect(::Type{Any}, itr::Base.Generator, isz::Union{Base.HasLength, Base.HasShape}) @ Base ./array.jl:644
│││││││┌ _array_for(::Type{Any}, itr::Base.HasLength, isz::Any) @ Base ./array.jl:674
││││││││┌ _similar_shape(itr::Base.HasLength, ::Base.HasShape) @ Base ./array.jl:659
│││││││││┌ axes(A::Base.HasLength) @ Base ./abstractarray.jl:98
││││││││││ no matching method found `size(::Base.HasLength)`: size(A::Base.HasLength)
│││││││││└────────────────────
││││││││┌ _similar_shape(itr::Base.HasLength, ::Base.HasLength) @ Base ./array.jl:658
│││││││││ no matching method found `length(::Base.HasLength)`: length(itr::Base.HasLength)
││││││││└────────────────────

@odow odow merged commit ef4c115 into master Sep 21, 2023
11 checks passed
@odow odow deleted the od/jet branch September 21, 2023 01:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants