Jet는 Julia의 유형 추론 시스템을 사용하여 잠재적 인 버그와 유형의 불안정성을 감지합니다.
경고
Jet의 Julia 컴파일러와의 긴밀한 통합으로 인해 Jet에서 제시 한 결과는 사용중인 Julia 버전에 따라 크게 다를 수 있습니다. 또한 Julia와 번들로 제공되는 Base 모듈 및 표준 라이브러리 구현도 결과에 영향을 줄 수 있습니다.
또한 Julia Compiler의 플러그인 시스템은 여전히 불안정하고 인터페이스가 자주 변경되므로 각 버전의 Jet는 Julia의 제한된 버전 만 호환됩니다. Julia 패키지 관리자는 Julia 버전과 호환되는 최신 버전의 JET를 자동으로 선택하고 설치합니다. 그러나 야간 버전의 Julia를 사용하는 경우 호환 가능한 제트 버전의 JET가 아직 출시되지 않았을 수 있으며 JULIA 패키지 관리자를 통해 설치 한 JET는 제대로 작동하지 않을 수 있습니다.
문서에서 더 많은 명령, 옵션 및 설명을 참조하십시오.
제트는 표준 줄리아 패키지입니다. 따라서 Julia의 내장 패키지 관리자를 통해 설치하여 다른 패키지와 마찬가지로 사용할 수 있습니다.
julia> using Pkg; Pkg . add ( " JET " )
[ some output elided ]
julia> using JET@report_opt 로 유형 불안정성을 감지하십시오 @report_opt 매크로를 사용하여 기능 호출에서 유형 불안정성을 감지 할 수 있습니다. @code_warntype 매크로와 유사하게 작동합니다. Jet는 Julia의 유형 추론에 의존하기 때문에 동적 디스패치로 인해 추론 체인이 파손되면 모든 다운 스트림 기능 호출이 컴파일러에 알려지지 않으므로 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는 귀하가 호출하는 기능뿐만 아니라 유래 한 칼리를 탐색합니다. 그러나 통화에 대한 인수 유형을 추론 할 수없는 경우 Jet는 Callee를 분석하지 않습니다. 결과적으로, No errors detected 보고서는 전체 코드베이스에 오류가 없음을 의미하지는 않습니다. Jet의 결과에 대한 신뢰를 높이려면 @report_opt 사용하여 코드가 불안한 지 확인하십시오.
Jet는 SnoopCompile과 통합되며 때로는 SnoopCompile을 사용하여 데이터를 수집하여보다 포괄적 인 분석을 수행 할 수 있습니다. SnoopCompile의 제한은 이전에 추론되지 않은 통화에 대한 데이터 만 수집하므로 새로운 세션에서 이러한 유형의 분석을 수행해야합니다.
자세한 내용은 SnoopCompile의 제트 통합 문서를 참조하십시오.
이 프로젝트는 Kyoto University의 저 학년 논문 프로젝트로 시작하여 사쿠라가와 타카시 교수가 감독했습니다. 우리는 Ruby의 실험 유형 이해/점검 도구 인 Ruby/TypeProf에서 영감을 받았습니다. 이 프로젝트에 대한 대학원 논문은 https://github.com/aviatesk/grad-thesis에 게시되지만 현재 일본어로만 사용할 수 있습니다.