Jet использует систему вывода типа Джулии, чтобы обнаружить потенциальные ошибки и нестабильности типа.
Предупреждение
Обратите внимание, что из -за жесткой интеграции Jet с компилятором Julia результаты, представленные Jet, могут значительно варьироваться в зависимости от версии Julia, которую вы используете. Кроме того, реализация Base модуля и стандартных библиотек, связанных с Юлией, также может повлиять на результаты.
Более того, система плагинов компилятора Julia все еще нестабильна, и его интерфейс часто изменяется, поэтому каждая версия Jet совместима только с ограниченными версиями Julia. Диспетчер пакетов Julia автоматически выберет и установит последнюю версию Jet, совместимая с вашей версией Julia. Однако, если вы используете ночную версию Джулии, обратите внимание, что совместимая версия Jet, возможно, еще не была выпущена, и Jet, установленная через диспетчер пакетов Julia, может не функционировать должным образом.
Смотрите больше команд, параметров и объяснений в документации.
Jet - стандартный пакет Julia. Таким образом, вы можете просто установить его через встроенный менеджер пакетов Julia и использовать его, как и любой другой пакет:
julia> using Pkg; Pkg . add ( " JET " )
[ some output elided ]
julia> using JET@report_opt Несчастность типа может быть обнаружена в вызовах функций с помощью макроса @report_opt , который работает аналогично макросу @code_warntype . Обратите внимание, что, поскольку Jet полагается на вывод типа Джулии, если цепочка вывода сломана из -за динамической диспетчеры, то все вызовы функций вниз по течению будут неизвестны компилятору, и поэтому Jet не может их проанализировать.
julia> @report_opt foldl ( + , Any[]; init = 0 )
═════ 2 possible errors found ═════
┌ kwcall(::@NamedTuple{init::Int64}, ::typeof(foldl), op::typeof(+), itr::Vector{Any}) @ Base ./reduce.jl:198
│┌ foldl(op::typeof(+), itr::Vector{Any}; kw::@Kwargs{init::Int64}) @ Base ./reduce.jl:198
││┌ kwcall(::@NamedTuple{init::Int64}, ::typeof(mapfoldl), f::typeof(identity), op::typeof(+), itr::Vector{Any}) @ Base ./reduce.jl:175
│││┌ mapfoldl(f::typeof(identity), op::typeof(+), itr::Vector{Any}; init::Int64) @ Base ./reduce.jl:175
││││┌ mapfoldl_impl(f::typeof(identity), op::typeof(+), nt::Int64, itr::Vector{Any}) @ Base ./reduce.jl:44
│││││┌ foldl_impl(op::Base.BottomRF{typeof(+)}, nt::Int64, itr::Vector{Any}) @ Base ./reduce.jl:48
││││││┌ _foldl_impl(op::Base.BottomRF{typeof(+)}, init::Int64, itr::Vector{Any}) @ Base ./reduce.jl:58
│││││││┌ (::Base.BottomRF{typeof(+)})(acc::Int64, x::Any) @ Base ./reduce.jl:86
││││││││ runtime dispatch detected: +(acc::Int64, x::Any)::Any
│││││││└────────────────────
││││││┌ _foldl_impl(op::Base.BottomRF{typeof(+)}, init::Int64, itr::Vector{Any}) @ Base ./reduce.jl:62
│││││││┌ (::Base.BottomRF{typeof(+)})(acc::Any, x::Any) @ Base ./reduce.jl:86
││││││││ runtime dispatch detected: +(acc::Any, x::Any)::Any
│││││││└────────────────────@report_call Это лучше всего работает на стабильном коде типа, поэтому используйте @report_opt Liberally, прежде чем использовать @report_call .
julia> @report_call foldl ( + , Char[])
═════ 2 possible errors found ═════
┌ foldl(op::typeof(+), itr::Vector{Char}) @ Base ./reduce.jl:198
│┌ foldl(op::typeof(+), itr::Vector{Char}; kw::@Kwargs{}) @ Base ./reduce.jl:198
││┌ mapfoldl(f::typeof(identity), op::typeof(+), itr::Vector{Char}) @ Base ./reduce.jl:175
│││┌ mapfoldl(f::typeof(identity), op::typeof(+), itr::Vector{Char}; init::Base._InitialValue) @ Base ./reduce.jl:175
││││┌ mapfoldl_impl(f::typeof(identity), op::typeof(+), nt::Base._InitialValue, itr::Vector{Char}) @ Base ./reduce.jl:44
│││││┌ foldl_impl(op::Base.BottomRF{typeof(+)}, nt::Base._InitialValue, itr::Vector{Char}) @ Base ./reduce.jl:48
││││││┌ _foldl_impl(op::Base.BottomRF{typeof(+)}, init::Base._InitialValue, itr::Vector{Char}) @ Base ./reduce.jl:62
│││││││┌ (::Base.BottomRF{typeof(+)})(acc::Char, x::Char) @ Base ./reduce.jl:86
││││││││ no matching method found `+(::Char, ::Char)`: (op::Base.BottomRF{typeof(+)}).rf::typeof(+)(acc::Char, x::Char)
│││││││└────────────────────
│││││┌ foldl_impl(op::Base.BottomRF{typeof(+)}, nt::Base._InitialValue, itr::Vector{Char}) @ Base ./reduce.jl:49
││││││┌ reduce_empty_iter(op::Base.BottomRF{typeof(+)}, itr::Vector{Char}) @ Base ./reduce.jl:383
│││││││┌ reduce_empty_iter(op::Base.BottomRF{typeof(+)}, itr::Vector{Char}, ::Base.HasEltype) @ Base ./reduce.jl:384
││││││││┌ reduce_empty(op::Base.BottomRF{typeof(+)}, ::Type{Char}) @ Base ./reduce.jl:360
│││││││││┌ reduce_empty(::typeof(+), ::Type{Char}) @ Base ./reduce.jl:343
││││││││││ no matching method found `zero(::Type{Char})`: zero(T::Type{Char})
│││││││││└────────────────────report_package Это ищет все определения методов и анализ вызовов функций на основе их подписей. Обратите внимание, что это менее точное, чем @report_call , потому что фактические типы вводов не могут быть известны общими методами.
julia> using Pkg; Pkg . activate (; temp = true , io = devnull ); Pkg . add ( " AbstractTrees " ; io = devnull );
julia> Pkg . status ()
Status `/private/var/folders/xh/6zzly9vx71v05_y67nm_s9_c0000gn/T/jl_h07K2m/Project.toml`
[1520ce14] AbstractTrees v0.4.4
julia> report_package ( " AbstractTrees " )
[ some output elided ]
═════ 7 possible errors found ═════
┌ isroot(root::Any, x::Any) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/base.jl:102
│ no matching method found `parent(::Any, ::Any)`: AbstractTrees.parent(root::Any, x::Any)
└────────────────────
┌ AbstractTrees.IndexNode(tree::Any) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/indexing.jl:117
│ no matching method found `rootindex(::Any)`: rootindex(tree::Any)
└────────────────────
┌ parent(idx::AbstractTrees.IndexNode) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/indexing.jl:127
│ no matching method found `parentindex(::Any, ::Any)`: pidx = parentindex((idx::AbstractTrees.IndexNode).tree::Any, (idx::AbstractTrees.IndexNode).index::Any)
└────────────────────
┌ nextsibling(idx::AbstractTrees.IndexNode) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/indexing.jl:132
│ no matching method found `nextsiblingindex(::Any, ::Any)`: sidx = nextsiblingindex((idx::AbstractTrees.IndexNode).tree::Any, (idx::AbstractTrees.IndexNode).index::Any)
└────────────────────
┌ prevsibling(idx::AbstractTrees.IndexNode) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/indexing.jl:137
│ no matching method found `prevsiblingindex(::Any, ::Any)`: sidx = prevsiblingindex((idx::AbstractTrees.IndexNode).tree::Any, (idx::AbstractTrees.IndexNode).index::Any)
└────────────────────
┌ prevsibling(csr::AbstractTrees.IndexedCursor) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/cursors.jl:234
│ no matching method found `getindex(::Nothing, ::Int64)` (1/2 union split): (AbstractTrees.parent(csr::AbstractTrees.IndexedCursor)::Union{Nothing, AbstractTrees.IndexedCursor})[idx::Int64]
└────────────────────
┌ (::AbstractTrees.var"#17#18")(n::Any) @ AbstractTrees ~/.julia/packages/AbstractTrees/EUx8s/src/iteration.jl:323
│ no matching method found `parent(::Any, ::Any)`: AbstractTrees.parent(getfield(#self#::AbstractTrees.var"#17#18", :tree)::Any, n::Any)
└──────────────────── Jet исследует функции, которые вы называете напрямую, а также их выводящие Callees. Однако, если типы аргументов для вызова не могут быть выведены, Jet не анализирует Callee. Следовательно, отчет о No errors detected не подразумевает, что вся ваша кодовая база не имеет ошибок. Чтобы повысить уверенность в результатах JET, используйте @report_opt , чтобы убедиться, что ваш код является определенным.
Jet интегрируется с SnoopCompile, и вы иногда можете использовать SnoopCompile для сбора данных для проведения более полных анализов. Ограничением Snoopcompile является то, что он собирает только данные только для вызовов, которые ранее не были выведены, поэтому вы должны выполнить этот тип анализа на свежем сессии.
См. Документацию Snoopcompile по интеграции Jet для получения дополнительной информации.
Этот проект начался как мой проект по бакалавриату в Киотском университете под руководством профессора Такаши Сакурагава. Мы были сильно вдохновлены Ruby/TypeProf, экспериментальным типом, инструментом понимания/проверки для Ruby. Выпускная диссертация об этом проекте публикуется по адресу https://github.com/aviatesk/grad-theesis, но в настоящее время он доступен только на японском языке.