Jetは、潜在的なバグとタイプの不安定性を検出するために、ジュリアのタイプ推論システムを採用しています。
警告
JetがJuliaコンパイラとの緊密な統合により、Jetが提示する結果は、使用しているジュリアのバージョンによって大きく異なる場合があることに注意してください。さらに、ジュリアにバンドルされたBaseモジュールと標準ライブラリの実装も結果に影響を与える可能性があります。
さらに、ジュリアコンパイラのプラグインシステムはまだ不安定であり、そのインターフェイスが頻繁に変更されるため、ジェットの各バージョンはジュリアの限られたバージョンのみと互換性があります。 Julia Package Managerは、Juliaバージョンと互換性のあるJetの最新バージョンを自動的に選択およびインストールします。ただし、ジュリアの毎晩のバージョンを使用している場合は、互換性のあるバージョンのジェットがまだリリースされていない可能性があり、Juliaパッケージマネージャーを介してJETがインストールされている可能性があることに注意してください。
ドキュメントのコマンド、オプション、説明をもっと参照してください。
ジェットは標準的なジュリアパッケージです。そのため、ジュリアの内蔵パッケージマネージャーを介してインストールして、他のパッケージと同じように使用できます。
julia> using Pkg; Pkg . add ( " JET " )
[ some output elided ]
julia> using JET@report_optでタイプの不安定性を検出しますタイプの不安定性は、 @code_warntypeマクロと同様に機能する@report_optマクロを使用して、関数呼び出しで検出できます。 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_callを使用する前に@report_opt自由に使用してください。
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はCalleeを分析しません。その結果、 No errors detectedのレポートは、コードベース全体にエラーがないことを意味しません。 Jetの結果に対する信頼性を高めるには、 @report_optを使用して、コードが非常に異なることを確認します。
JetはSnoopcompileと統合され、Snoopcompileを使用してデータを収集して、より包括的な分析を実行することがあります。 SnoopCompileの制限は、以前に推測されていないコールのデータのみを収集するため、このタイプの分析を新しいセッションで実行する必要があることです。
詳細については、SnoopcompileのJet-Integrationドキュメントを参照してください。
このプロジェクトは、京都大学の私の学部論文プロジェクトとして始まりました。私たちは、Rubyの実験的なタイプの理解/チェックツールであるRuby/Typeprofに重く触発されました。このプロジェクトに関するグレードの論文は、https://github.com/aviatesk/grad-thesisで公開されていますが、現在は日本語でのみ利用可能です。