diff --git a/Project.toml b/Project.toml index 8b570e807..2c323a0f2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "JET" uuid = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" authors = ["Shuhei Kadowaki "] -version = "0.6.13" +version = "0.6.14" [deps] InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" diff --git a/README.md b/README.md index 2c6c53a3d..e2f54898c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ JET.jl employs Julia's type inference system to detect potential bugs. !!! note - The latest version of JET requires Julia versions **1.7 and higher**; + The latest version of JET requires Julia versions **1.8** and higher; JET is tested against [the current stable release](https://julialang.org/downloads/#current_stable_release) as well as [nightly version](https://julialang.org/downloads/nightlies/). \ Also note that JET deeply relies on the type inference routine implemented in [the Julia compiler](https://github.com/JuliaLang/julia/tree/master/base/compiler), and so the analysis result can vary depending on your Julia version. diff --git a/src/JET.jl b/src/JET.jl index 239593177..43e444b69 100644 --- a/src/JET.jl +++ b/src/JET.jl @@ -81,8 +81,8 @@ import .CC: switchtupleunion, tmerge, widenconst, ⊑ import Base: - @invoke, @invokelatest, IdSet, destructure_callex, parse_input_line, rewrap_unionall, - uniontypes, unwrap_unionall + @invoke, @invokelatest, @constprop, IdSet, default_tt, destructure_callex, + parse_input_line, rewrap_unionall, uniontypes, unwrap_unionall import Base.Meta: _parse_string, isexpr, lower @@ -131,23 +131,7 @@ __init__() = foreach(@nospecialize(f)->f(), INIT_HOOKS) # compat # ------ -# branch on https://github.com/JuliaLang/julia/pull/42082 -const IS_AFTER_42082 = hasmethod(InferenceState, (InferenceResult, Symbol, AbstractInterpreter)) - -const IS_AFTER_42529 = isdefined(CC, :ArgInfo) -@static IS_AFTER_42529 && import .CC: ArgInfo - -const IS_V18 = VERSION ≥ v"1.8-" -@static IS_V18 && import .CC: concrete_eval_eligible, concrete_eval_call - -# branch on https://github.com/JuliaLang/julia/pull/42125 -@static if isdefined(Base, Symbol("@constprop")) - import Base: @constprop -else - macro constprop(_, ex); esc(ex); end -end - -@static @isdefined(LazyString) || include("strings/lazy.jl") +import .CC: ArgInfo, concrete_eval_eligible, concrete_eval_call, hasintersect function anypush!(a::Vector{Any}, @nospecialize x...) na = length(a) @@ -159,13 +143,7 @@ function anypush!(a::Vector{Any}, @nospecialize x...) return a end -@static if isdefined(Core.Compiler, :hasintersect) - import .CC: hasintersect -else - hasintersect(@nospecialize(a), @nospecialize(b)) = typeintersect(a, b) !== Bottom -end - -@static if !isdefined(@__MODULE__, :getglobal) +@static if !@isdefined(getglobal) const getglobal = getfield end @@ -747,11 +725,7 @@ function analyze_method_instance!(analyzer::AbstractAnalyzer, mi::MethodInstance ) result = InferenceResult(mi) - @static if IS_AFTER_42082 - frame = InferenceState(result, #=cache=# :global, analyzer) - else - frame = InferenceState(result, #=cached=# true, analyzer) - end + frame = InferenceState(result, #=cache=# :global, analyzer) isnothing(frame) && return analyzer, result @@ -759,11 +733,9 @@ function analyze_method_instance!(analyzer::AbstractAnalyzer, mi::MethodInstance return analyze_frame!(analyzer, frame) end -const CACHE_ARG_TYPE = IS_AFTER_42082 ? Symbol : Bool - -function InferenceState(result::InferenceResult, cache::CACHE_ARG_TYPE, analyzer::AbstractAnalyzer) +function InferenceState(result::InferenceResult, cache::Symbol, analyzer::AbstractAnalyzer) init_result!(analyzer, result) # set `JETResult` for succeeding JET analysis - return @invoke InferenceState(result::InferenceResult, cache::CACHE_ARG_TYPE, analyzer::AbstractInterpreter) + return @invoke InferenceState(result::InferenceResult, cache::Symbol, analyzer::AbstractInterpreter) end function analyze_frame!(analyzer::AbstractAnalyzer, frame::InferenceState) @@ -1163,9 +1135,7 @@ function analyze_toplevel!(analyzer::AbstractAnalyzer, src::CodeInfo; # toplevel frames don't really need to be cached, but still better to be optimized # in order to get reasonable `LocalUndefVarErrorReport` and `UncaughtExceptionReport` # NOTE and also, otherwise `typeinf_edge` won't add "toplevel-to-callee" edges - frame = (@static IS_AFTER_42082 ? - InferenceState(result, src, #=cache=# :global, analyzer) : - InferenceState(result, src, #=cached=# true, analyzer))::InferenceState + frame = InferenceState(result, src, #=cache=# :global, analyzer)::InferenceState set_entry && set_entry!(analyzer, mi) return analyze_frame!(analyzer, frame) @@ -1220,34 +1190,14 @@ end # resolve toplevel symbols (and other expressions like `:foreigncall`) # so that the returned `CodeInfo` is eligible for abstractintepret and optimization # TODO `jl_resolve_globals_in_ir` can throw, and we want to bypass it to `ToplevelErrorReport` -@static if VERSION ≥ v"1.8.0-DEV.421" - function resolve_toplevel_symbols!(mod::Module, src::CodeInfo) - newsrc = copy(src) - @ccall jl_resolve_globals_in_ir( - #=jl_array_t *stmts=# newsrc.code::Any, - #=jl_module_t *m=# mod::Any, - #=jl_svec_t *sparam_vals=# svec()::Any, - #=int binding_effects=# 0::Int)::Cvoid - return newsrc - end -else - # HACK before https://github.com/JuliaLang/julia/pull/42013, we need to go through - # the method definition pipeline to get the effect of `jl_resolve_globals_in_ir` - function resolve_toplevel_symbols!(mod::Module, src::CodeInfo) - sig = svec( - #=atypes=# svec(typeof(__toplevelf__)), - #=tvars=# svec(), - #=functionloc=# LineNumberNode(@__LINE__, @__FILE__)) - # branching on https://github.com/JuliaLang/julia/pull/41137 - method = (@static if isdefined(Core.Compiler, :OverlayMethodTable) - ccall(:jl_method_def, Any, (Any, Ptr{Cvoid}, Any, Any), sig, C_NULL, src, mod) - else - ccall(:jl_method_def, Cvoid, (Any, Any, Any), sig, src, mod) - only(methods(__toplevelf__)) - end)::Method - return CC.uncompressed_ir(method) - end - function __toplevelf__ end +function resolve_toplevel_symbols!(mod::Module, src::CodeInfo) + newsrc = copy(src) + @ccall jl_resolve_globals_in_ir( + #=jl_array_t *stmts=# newsrc.code::Any, + #=jl_module_t *m=# mod::Any, + #=jl_svec_t *sparam_vals=# svec()::Any, + #=int binding_effects=# 0::Int)::Cvoid + return newsrc end # interactive @@ -1293,22 +1243,6 @@ function report_call(@nospecialize(f), @nospecialize(types = default_tt(f)); jet return report_call(tt; jetconfigs...) end -@static if isdefined(Base, :default_tt) -import Base: default_tt -else -# returns argument tuple type which is supposed to be used for `code_typed` and its family; -# if there is a single method this functions returns the method argument signature, -# otherwise returns `Tuple` that doesn't match with any signature -function default_tt(@nospecialize(f)) - ms = methods(f) - if length(ms) == 1 - return Base.tuple_type_tail(only(ms).sig) - else - return Tuple - end -end -end - function report_call(@nospecialize(tt::Type{<:Tuple}); analyzer::Type{Analyzer} = JETAnalyzer, source::Union{Nothing,AbstractString} = nothing, @@ -1318,7 +1252,7 @@ function report_call(@nospecialize(tt::Type{<:Tuple}); analyzer, result = analyze_gf_by_type!(analyzer, tt) if isnothing(source) - source = string(nameof(var"@report_call"), " ", sprint(show_tuple_as_call, Symbol(""), tt)) + source = string(nameof(var"@report_call"), " ", sprint(Base.show_tuple_as_call, Symbol(""), tt)) end return JETCallResult(result, analyzer, source; jetconfigs...) @@ -1453,15 +1387,6 @@ macro test_call(ex0...) end end -get_exceptions() = @static if isdefined(Base, :current_exceptions) - Base.current_exceptions() -else - Base.catch_stack() -end -@static if !hasfield(Pass, :source) - Pass(test_type::Symbol, orig_expr, data, thrown, source) = Pass(test_type, orig_expr, data, thrown) -end - function test_exs(ex0, m, source) analysis = InteractiveUtils.gen_call_with_extracted_types_and_kwargs(m, :report_call, ex0) orig_expr = QuoteNode( @@ -1476,7 +1401,7 @@ function test_exs(ex0, m, source) end catch err isa(err, $InterruptException) && rethrow() - $Error(:test_error, $orig_expr, err, $get_exceptions(), $source) + $Error(:test_error, $orig_expr, err, $(Base.current_exceptions()), $source) end) |> Base.remove_linenums! return testres, orig_expr end diff --git a/src/abstractinterpret/abstractanalyzer.jl b/src/abstractinterpret/abstractanalyzer.jl index 604f5996d..36bc18d0a 100644 --- a/src/abstractinterpret/abstractanalyzer.jl +++ b/src/abstractinterpret/abstractanalyzer.jl @@ -271,7 +271,7 @@ let tuple_splat::Int = 32, assume_fatal_throw::Bool = false, ) - elseif isdefined(CC, :mark_throw_blocks!) + else kwargs = :(inlining::Bool = inlining_enabled(), inline_cost_threshold::Int = 100, inline_nonleaf_penalty::Int = 1000, @@ -281,17 +281,6 @@ let tuple_splat::Int = 32, union_splitting::Int = 4, ) - else - kwargs = :(inlining::Bool = inlining_enabled(), - inline_cost_threshold::Int = 100, - inline_nonleaf_penalty::Int = 1000, - inline_tupleret_bonus::Int = 250, - inline_error_path_cost::Int = 20, - max_methods::Int = 3, - tuple_splat::Int = 32, - union_splitting::Int = 4, - unoptimize_throw_blocks::Bool = true, - ) end kwargs_exs = Expr[] names = Symbol[] @@ -525,7 +514,6 @@ CC.may_compress(analyzer::AbstractAnalyzer) = false CC.may_discard_trees(analyzer::AbstractAnalyzer) = false CC.verbose_stmt_info(analyzer::AbstractAnalyzer) = false -@static if IS_AFTER_42082 let # overload `inlining_policy` @static if isdefined(CC, :CallInfo) sigs_ex = :(analyzer::AbstractAnalyzer, @@ -555,24 +543,6 @@ let # overload `inlining_policy` end end end -else # @static if IS_AFTER_42082 -@doc """ - inlining_policy(::AbstractAnalyzer) = jet_inlining_policy - jet_inlining_policy(@nospecialize(src)) -> source::Any - -`jet_inlining_policy` implements `Core.Compiler.inlining_policy` for `AbstractAnalyzer`. -Since `AbstractAnalyzer` works on `InferenceResult` whose `src` field keeps -[`JETResult`](@ref) or [`JETCachedResult`](@ref), `jet_inlining_policy` forwards -their wrapped source to `Core.Compiler.default_inlining_policy`. -""" -CC.inlining_policy(::AbstractAnalyzer) = jet_inlining_policy -@inline function jet_inlining_policy(@nospecialize(src)) - if isa(src, JETCachedResult) - src = src.src - end - return CC.default_inlining_policy(src) -end -end # @static if IS_AFTER_42082 # AbstractAnalyzer # ================ diff --git a/src/abstractinterpret/typeinfer.jl b/src/abstractinterpret/typeinfer.jl index 251aa7f63..e5b15f9e6 100644 --- a/src/abstractinterpret/typeinfer.jl +++ b/src/abstractinterpret/typeinfer.jl @@ -107,7 +107,7 @@ function CC.builtin_tfunction(analyzer::AbstractAnalyzer, if istoplevel_getproperty(sv) ret = narrow_toplevel_getglobal(argtypes, ret) end - elseif (@static isdefined(Core, :get_binding_type) && (f === Core.get_binding_type)) + elseif f === Core.get_binding_type if istoplevel(sv) ret = narrow_toplevel_binding_type(argtypes, ret) end @@ -224,27 +224,13 @@ let # overload `abstract_call_method_with_const_args` args_ex = :(analyzer::AbstractInterpreter, result::MethodCallResult, f::Any, arginfo::ArgInfo, match::MethodMatch, sv::InferenceState, invoketypes::Any) - elseif IS_V18 + else sigs_ex = :(analyzer::AbstractAnalyzer, result::MethodCallResult, @nospecialize(f), arginfo::ArgInfo, match::MethodMatch, sv::InferenceState) args_ex = :(analyzer::AbstractInterpreter, result::MethodCallResult, f::Any, arginfo::ArgInfo, match::MethodMatch, sv::InferenceState) - elseif IS_AFTER_42529 - sigs_ex = :(analyzer::AbstractAnalyzer, - result::MethodCallResult, @nospecialize(f), arginfo::ArgInfo, match::MethodMatch, - sv::InferenceState, va_override::Bool) - args_ex = :(analyzer::AbstractInterpreter, - result::MethodCallResult, f::Any, arginfo::ArgInfo, match::MethodMatch, - sv::InferenceState, va_override::Bool) - else - sigs_ex = :(analyzer::AbstractAnalyzer, - result::MethodCallResult, @nospecialize(f), argtypes::Argtypes, match::MethodMatch, - sv::InferenceState, va_override::Bool) - args_ex = :(analyzer::AbstractInterpreter, - result::MethodCallResult, f::Any, argtypes::Argtypes, match::MethodMatch, - sv::InferenceState, va_override::Bool) end @eval function CC.abstract_call_method_with_const_args($(sigs_ex.args...)) set_cacher!(analyzer, :abstract_call_method_with_const_args => sv.result) @@ -286,13 +272,11 @@ let # overload `concrete_eval_call` args_ex = :(analyzer::AbstractInterpreter, f::Any, result::MethodCallResult, arginfo::ArgInfo, sv::InferenceState, invokecall::Union{Nothing,CC.InvokeCall}) - elseif IS_V18 + else sigs_ex = :(analyzer::AbstractAnalyzer, @nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, sv::InferenceState) args_ex = :(analyzer::AbstractInterpreter, f::Any, result::MethodCallResult, arginfo::ArgInfo, sv::InferenceState) - else - return # `concrete_eval_call` isn't defined for this case end @eval function CC.concrete_eval_call($(sigs_ex.args...)) ret = @invoke CC.concrete_eval_call($(args_ex.args...)) @@ -314,18 +298,12 @@ let # overload `abstract_call` args_ex = :(analyzer::AbstractInterpreter, arginfo::ArgInfo, si::StmtInfo, sv::InferenceState, max_methods::Int) argtypes_ex = :(arginfo.argtypes) - elseif IS_AFTER_42529 + else sigs_ex = :(analyzer::AbstractAnalyzer, arginfo::ArgInfo, sv::InferenceState, $(Expr(:kw, :(max_methods::Int), :(InferenceParams(analyzer).MAX_METHODS)))) args_ex = :(analyzer::AbstractInterpreter, arginfo::ArgInfo, sv::InferenceState, max_methods::Int) argtypes_ex = :(arginfo.argtypes) - else - sigs_ex = :(analyzer::AbstractAnalyzer, fargs::Union{Nothing,Vector{Any}}, argtypes::Argtypes, sv::InferenceState, - $(Expr(:kw, :(max_methods::Int), :(InferenceParams(analyzer).MAX_METHODS)))) - args_ex = :(analyzer::AbstractInterpreter, fargs::Union{Nothing,Vector{Any}}, argtypes::Argtypes, sv::InferenceState, - max_methods::Int) - argtypes_ex = :argtypes end @eval function CC.abstract_call($(sigs_ex.args...)) ret = @invoke CC.abstract_call($(args_ex.args...)) @@ -548,13 +526,9 @@ function CC.transform_result_for_cache(analyzer::AbstractAnalyzer, AbstractInterpreter, MethodInstance, WorldRange, InferenceResult)) inferred_result = @invoke transform_result_for_cache(analyzer::AbstractInterpreter, linfo::MethodInstance, valid_worlds::WorldRange, result::InferenceResult) - elseif isdefined(CC, :Effects) && hasmethod(CC.transform_result_for_cache, ( - AbstractInterpreter, MethodInstance, WorldRange, Any, CC.Effects)) - inferred_result = @invoke transform_result_for_cache(analyzer::AbstractInterpreter, - linfo::MethodInstance, valid_worlds::WorldRange, result.src::Any, result.ipo_effects::CC.Effects) else inferred_result = @invoke transform_result_for_cache(analyzer::AbstractInterpreter, - linfo::MethodInstance, valid_worlds::WorldRange, result.src::Any) + linfo::MethodInstance, valid_worlds::WorldRange, result.src::Any, result.ipo_effects::CC.Effects) end return JETCachedResult(inferred_result, cache) end @@ -780,13 +754,7 @@ function CC._typeinf(analyzer::AbstractAnalyzer, frame::InferenceState) if (@static VERSION ≥ v"1.9.0-DEV.1636" ? (opt isa OptimizationState{typeof(analyzer)}) : (opt isa OptimizationState)) - @static if VERSION ≥ v"1.8.0-DEV.1425" - CC.optimize(analyzer, opt, OptimizationParams(analyzer), caller) - else - result_type = caller.result - @assert !(result_type isa LimitedAccuracy) - CC.optimize(analyzer, opt, OptimizationParams(analyzer), result_type) - end + CC.optimize(analyzer, opt, OptimizationParams(analyzer), caller) # # COMBAK we may want to enable inlining ? # if opt.const_api # # XXX: The work in ir_to_codeinf! is essentially wasted. The only reason diff --git a/src/analyzers/jetanalyzer.jl b/src/analyzers/jetanalyzer.jl index 4519c9cac..4dda99cd0 100644 --- a/src/analyzers/jetanalyzer.jl +++ b/src/analyzers/jetanalyzer.jl @@ -155,8 +155,8 @@ CC.method_table(analyzer::JETAnalyzer) = analyzer.method_table # overloads # ========= -function CC.InferenceState(result::InferenceResult, cache::CACHE_ARG_TYPE, analyzer::JETAnalyzer) - frame = @invoke CC.InferenceState(result::InferenceResult, cache::CACHE_ARG_TYPE, analyzer::AbstractAnalyzer) +function CC.InferenceState(result::InferenceResult, cache::Symbol, analyzer::JETAnalyzer) + frame = @invoke CC.InferenceState(result::InferenceResult, cache::Symbol, analyzer::AbstractAnalyzer) if isnothing(frame) # indicates something bad happened within `retrieve_code_info` ReportPass(analyzer)(GeneratorErrorReport, analyzer, result) end @@ -185,21 +185,13 @@ let # overload `abstract_call_gf_by_type` args_ex = :(analyzer::AbstractAnalyzer, f::Any, arginfo::ArgInfo, si::StmtInfo, atype::Any, sv::InferenceState, max_methods::Int) argtypes_ex = :(arginfo.argtypes) - elseif IS_AFTER_42529 + else sigs_ex = :(analyzer::JETAnalyzer, @nospecialize(f), arginfo::ArgInfo, @nospecialize(atype), sv::InferenceState, $(Expr(:kw, :(max_methods::Int), :(InferenceParams(analyzer).MAX_METHODS)))) args_ex = :(analyzer::AbstractAnalyzer, f::Any, arginfo::ArgInfo, atype::Any, sv::InferenceState, max_methods::Int) argtypes_ex = :(arginfo.argtypes) - else - sigs_ex = :(analyzer::JETAnalyzer, - @nospecialize(f), fargs::Union{Nothing,Vector{Any}}, argtypes::Argtypes, @nospecialize(atype), sv::InferenceState, - $(Expr(:kw, :(max_methods::Int), :(InferenceParams(analyzer).MAX_METHODS)))) - args_ex = :(analyzer::AbstractAnalyzer, - f::Any, fargs::Union{Nothing,Vector{Any}}, argtypes::Argtypes, atype::Any, - sv::InferenceState, max_methods::Int) - argtypes_ex = :argtypes end @eval function CC.abstract_call_gf_by_type($(sigs_ex.args...)) ret = @invoke CC.abstract_call_gf_by_type($(args_ex.args...)) @@ -237,8 +229,7 @@ function CC.add_call_backedges!(analyzer::JETAnalyzer, matches::Union{MethodMatches,UnionSplitMethodMatches}, atype::Any, sv::InferenceState) end -# overload after https://github.com/JuliaLang/julia/pull/45017/ -@static if isdefined(CC, :Effects) + function CC.add_call_backedges!(analyzer::JETAnalyzer, @nospecialize(rettype), effects::CC.Effects, edges::Vector{MethodInstance}, matches::Union{MethodMatches,UnionSplitMethodMatches}, @nospecialize(atype), @@ -249,31 +240,8 @@ function CC.add_call_backedges!(analyzer::JETAnalyzer, edges::Vector{MethodInstance}, matches::Union{MethodMatches,UnionSplitMethodMatches}, atype::Any, sv::InferenceState) end -end struct __DummyAny__ end -@static if VERSION < v"1.8.0-DEV.510" -# manually take in https://github.com/JuliaLang/julia/pull/42195 -const ISEQUAL_ANY_ANY = let - ms = methods(isequal) - i = findfirst(m->m.sig===Tuple{typeof(isequal),Any,Any}, ms)::Int - ms[i] -end - -function CC.abstract_call_method(analyzer::JETAnalyzer, - method::Method, @nospecialize(sig), sparams::SimpleVector, hardlimit::Bool, sv::InferenceState) - ret = @invoke CC.abstract_call_method(analyzer::AbstractAnalyzer, - method::Method, sig::Any, sparams::SimpleVector, hardlimit::Bool, sv::InferenceState) - - # manually take in https://github.com/JuliaLang/julia/pull/42195 - if method === ISEQUAL_ANY_ANY && ret.rt === Union{Bool,Missing} - ret = MethodCallResult(Bool, ret.edgecycle, ret.edgelimited, ret.edge) - end - - return ret -end -end # @static if VERSION < v"1.8.0-DEV.510" - let # overload `const_prop_entry_heuristic` @static if @isdefined(StmtInfo) sigs_ex = :(::JETAnalyzer, result::MethodCallResult, si::StmtInfo, sv::InferenceState) @@ -303,11 +271,9 @@ let # overload `concrete_eval_eligible` # https://github.com/JuliaLang/julia/pull/46966 sigs_ex = :(analyzer::JETAnalyzer, @nospecialize(f), result::MethodCallResult, arginfo::ArgInfo) - elseif IS_V18 + else sigs_ex = :(analyzer::JETAnalyzer, @nospecialize(f), result::MethodCallResult, arginfo::ArgInfo, sv::InferenceState) - else - return end # TODO correctly reasons about error found by [semi-]concrete evaluation # for now just always fallback to the constant-prop' @@ -340,14 +306,10 @@ let # overload `abstract_invoke` sigs_ex = :(analyzer::JETAnalyzer, arginfo::ArgInfo, si::StmtInfo, sv::InferenceState) args_ex = :(analyzer::AbstractAnalyzer, arginfo::ArgInfo, si::StmtInfo, sv::InferenceState) argtypes_ex = :(arginfo.argtypes) - elseif IS_AFTER_42529 + else sigs_ex = :(analyzer::JETAnalyzer, arginfo::ArgInfo, sv::InferenceState) args_ex = :(analyzer::AbstractAnalyzer, arginfo::ArgInfo, sv::InferenceState) argtypes_ex = :(arginfo.argtypes) - else - sigs_ex = :(analyzer::JETAnalyzer, argtypes::Argtypes, sv::InferenceState) - args_ex = :(analyzer::AbstractAnalyzer, argtypes::Argtypes, sv::InferenceState) - argtypes_ex = :argtypes end @eval function CC.abstract_invoke($(sigs_ex.args...)) ret = @invoke CC.abstract_invoke($(args_ex.args...)) @@ -387,7 +349,6 @@ end # N.B. this report pass won't be necessary as the frontend will generate code # that `typeassert`s the value type as the binding type beforehand -@static VERSION ≥ v"1.8" && begin @static if isdefined(CC, :abstract_eval_basic_statement) @inline function CC.abstract_eval_basic_statement(analyzer::JETAnalyzer, @nospecialize(stmt), pc_vartable::VarTable, frame::InferenceState) @@ -412,7 +373,6 @@ function CC.abstract_eval_statement(analyzer::JETAnalyzer, return ret end end # @static if isdefined(CC, :abstract_eval_basic_statement) -end # @static VERSION ≥ v"1.8" begin function CC.abstract_eval_value(analyzer::JETAnalyzer, @nospecialize(e), vtypes::VarTable, sv::InferenceState) ret = @invoke CC.abstract_eval_value(analyzer::AbstractAnalyzer, e::Any, vtypes::VarTable, sv::InferenceState) diff --git a/src/analyzers/optanalyzer.jl b/src/analyzers/optanalyzer.jl index 22e6d5e66..f41fbe7f4 100644 --- a/src/analyzers/optanalyzer.jl +++ b/src/analyzers/optanalyzer.jl @@ -289,7 +289,7 @@ function CC.finish!(analyzer::OptAnalyzer, frame::InferenceState) (src isa OptimizationState)) # the compiler optimized it, analyze it ReportPass(analyzer)(RuntimeDispatchReport, analyzer, caller, src) elseif (@static JET_DEV_MODE ? true : false) - if (@static isdefined(CC, :ConstAPI) ? isa(src, CC.ConstAPI) : isa(src, Const)) + if isa(src, CC.ConstAPI) # the optimization was very successful (i.e. fully constant folded), # nothing to report elseif src === nothing # the optimization didn't happen @@ -323,13 +323,6 @@ end function (::OptAnalysisPass)(::Type{RuntimeDispatchReport}, analyzer::OptAnalyzer, caller::InferenceResult, opt::OptimizationState) (; src, sptypes, slottypes) = opt - # branch on https://github.com/JuliaLang/julia/pull/42149 - @static if !isdefined(CC, :mark_throw_blocks!) - throw_blocks = - analyzer.skip_unoptimized_throw_blocks && opt.inlining.params.unoptimize_throw_blocks ? - CC.find_throw_blocks(src.code) : nothing - end - # TODO better to work on `opt.ir::IRCode` (with some updates on `handle_sig!`) local reported = false for (pc, x) in enumerate(src.code) @@ -340,16 +333,8 @@ function (::OptAnalysisPass)(::Type{RuntimeDispatchReport}, analyzer::OptAnalyze # that callee should already have been reported continue end - # branch on https://github.com/JuliaLang/julia/pull/42149 - @static if isdefined(CC, :mark_throw_blocks!) - if analyzer.skip_unoptimized_throw_blocks - CC.is_stmt_throw_block(src.ssaflags[pc]) && continue - end - else - if !isnothing(throw_blocks) - # optimization is intentionally turned off for this block, let's ignore anything here - CC.in(pc, throw_blocks) && continue - end + if analyzer.skip_unoptimized_throw_blocks + CC.is_stmt_throw_block(src.ssaflags[pc]) && continue end if isexpr(x, :call) ft = widenconst(argextype(first(x.args), src, sptypes, slottypes)) diff --git a/src/strings/lazy.jl b/src/strings/lazy.jl deleted file mode 100644 index afc8c00dc..000000000 --- a/src/strings/lazy.jl +++ /dev/null @@ -1,106 +0,0 @@ -# adapted from https://github.com/JuliaLang/julia/blob/1600cb97d2e829f87b80295c0b01e6b1cf516906/base/strings/lazy.jl -# only loaded for Julia versions where Base doesn't define LazyString - -import Base: String, hash, lastindex, iterate, isequal, ==, ncodeunits, codeunit, isvalid - -""" - LazyString <: AbstractString - -A lazy representation of string interpolation. This is useful when a string -needs to be constructed in a context where performing the actual interpolation -and string construction is unnecessary or undesirable (e.g. in error paths -of functions). - -This type is designed to be cheap to construct at runtime, trying to offload -as much work as possible to either the macro or later printing operations. - -# Examples - -```jldoctest -julia> n = 5; str = LazyString("n is ", n) -"n is 5" -``` - -See also [`@lazy_str`](@ref). - -!!! compat "Julia 1.8" - `LazyString` requires Julia 1.8 or later. - -# Extended help -## Safety properties for concurrent programs - -A lazy string itself does not introduce any concurrency problems even if it is printed in -multiple Julia tasks. However, if `print` methods on a captured value can have a -concurrency issue when invoked without synchronizations, printing the lazy string may cause -an issue. Furthermore, the `print` methods on the captured values may be invoked multiple -times, though only exactly one result will be returned. - -!!! compat "Julia 1.9" - `LazyString` is safe in the above sense in Julia 1.9 and later. -""" -mutable struct LazyString <: AbstractString - #=const=# parts::Tuple - # Created on first access - @atomic str::Union{String,Nothing} - global _LazyString(parts, str) = new(parts, str) - LazyString(args...) = new(args, nothing) -end - -""" - lazy"str" - -Create a [`LazyString`](@ref) using regular string interpolation syntax. -Note that interpolations are *evaluated* at LazyString construction time, -but *printing* is delayed until the first access to the string. - -See [`LazyString`](@ref) documentation for the safety properties for concurrent programs. - -# Examples - -``` -julia> n = 5; str = lazy"n is \$n" -"n is 5" - -julia> typeof(str) -LazyString -``` - -!!! compat "Julia 1.8" - `lazy"str"` requires Julia 1.8 or later. -""" -macro lazy_str(text) - parts = Any[] - lastidx = idx = 1 - while (idx = findnext('$', text, idx)) !== nothing - lastidx < idx && push!(parts, text[lastidx:idx-1]) - idx += 1 - expr, idx = Meta.parseatom(text, idx; filename=string(__source__.file)) - push!(parts, esc(expr)) - lastidx = idx - end - lastidx <= lastindex(text) && push!(parts, text[lastidx:end]) - :(LazyString($(parts...))) -end - -function String(l::LazyString) - old = @atomic :acquire l.str - old === nothing || return old - str = sprint() do io - for p in l.parts - print(io, p) - end - end - old, ok = @atomicreplace :acquire_release :acquire l.str nothing => str - return ok ? str : (old::String) -end - -hash(s::LazyString, h::UInt64) = hash(String(s), h) -lastindex(s::LazyString) = lastindex(String(s)) -iterate(s::LazyString) = iterate(String(s)) -iterate(s::LazyString, i::Integer) = iterate(String(s), i) -isequal(a::LazyString, b::LazyString) = isequal(String(a), String(b)) -==(a::LazyString, b::LazyString) = (String(a) == String(b)) -ncodeunits(s::LazyString) = ncodeunits(String(s)) -codeunit(s::LazyString) = codeunit(String(s)) -codeunit(s::LazyString, i::Integer) = codeunit(String(s), i) -isvalid(s::LazyString, i::Integer) = isvalid(String(s), i) diff --git a/src/ui/print.jl b/src/ui/print.jl index 2f264e74d..fd6522b39 100644 --- a/src/ui/print.jl +++ b/src/ui/print.jl @@ -379,7 +379,7 @@ function show_mi(io::IO, l::MethodInstance) show(io, def) else # print(io, "MethodInstance for ") - show_tuple_as_call(io, def.name, l.specTypes) + Base.show_tuple_as_call(io, def.name, l.specTypes; qualified=true) end else # print(io, "Toplevel MethodInstance thunk") @@ -395,11 +395,3 @@ function show_mi(io::IO, l::MethodInstance) print(io, "toplevel") end end - -@inline function show_tuple_as_call(io::IO, name::Symbol, @nospecialize(sig::Type)) - @static if hasmethod(Base.show_tuple_as_call, (IO, Symbol, Type), (:demangle, :kwargs, :argnames, :qualified)) - Base.show_tuple_as_call(io, name, sig; qualified = true) - else - Base.show_tuple_as_call(io, name, sig, false, nothing, nothing, true) - end -end diff --git a/test/abstractinterpret/test_typeinfer.jl b/test/abstractinterpret/test_typeinfer.jl index e42116bf0..3176e5bb1 100644 --- a/test/abstractinterpret/test_typeinfer.jl +++ b/test/abstractinterpret/test_typeinfer.jl @@ -685,7 +685,6 @@ end end # filter_lineages! for concrete_eval_call -@static if isdefined(Base, Symbol("@assume_effects")) Base.@assume_effects :foldable function filter_unopt_call(call::Bool, f, args...) if call f(args...) @@ -698,4 +697,3 @@ let res = report_opt() do end @test isempty(get_reports_with_test(res)) end -end # @static if isdefined(Base, var"@assume_effects") diff --git a/test/runtests.jl b/test/runtests.jl index 77742e72f..7e416546c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -100,8 +100,7 @@ include("setup.jl") ft === typeof(zero) || ft === typeof(JET.copy_report) || ft === typeof(JET.handle_sig!) || - (@static VERSION < v"1.8.0-DEV.1053" && ft === typeof(isprimitivetype)) || # requires https://github.com/JuliaLang/julia/pull/43113 - (@static VERSION < v"1.9.0-DEV.283" && ft === typeof(JET.rewrap_unionall)) || # require https://github.com/JuliaLang/julia/pull/44512 + (@static VERSION < v"1.9.0-DEV.283" && ft === typeof(JET.rewrap_unionall)) || # requires https://github.com/JuliaLang/julia/pull/44512 false return false end diff --git a/test/test_JETInterface.jl b/test/test_JETInterface.jl index 31a47d918..03394e2ed 100644 --- a/test/test_JETInterface.jl +++ b/test/test_JETInterface.jl @@ -44,7 +44,7 @@ function compute_sins(i) return out end -const ERROR_MSG = @static VERSION ≥ v"1.8" ? "missing `$AbstractAnalyzer` API" : ErrorException +const ERROR_MSG = "missing `$AbstractAnalyzer` API" @test_throws ERROR_MSG @report_call analyzer=APIValidator compute_sins(10)