From f644520723f00510f249e57123b0b042a9b79628 Mon Sep 17 00:00:00 2001 From: Artem Pelenitsyn Date: Fri, 8 Sep 2023 14:01:12 -0400 Subject: [PATCH] first stroke at the new report template comparing noDB to DB the report looks reasonable for Multisets also couple bugs fixed, based on Flux experience --- scripts/aggregate.sh | 2 +- src/StabilityCheck.jl | 8 ++++---- src/enumeration.jl | 11 ++++++++--- src/report.jl | 38 ++++++++++++++++++++++++++++++++------ src/utils.jl | 1 + 5 files changed, 46 insertions(+), 14 deletions(-) diff --git a/scripts/aggregate.sh b/scripts/aggregate.sh index 5d1c88b08..2011e1733 100755 --- a/scripts/aggregate.sh +++ b/scripts/aggregate.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -ADD_HEAD='1i Module,Methods,Stable,Unstable,Partial,Any,Vararg,Generic,TcFail,NoFuel' +ADD_HEAD='1i Module,MethodsGood,Stable,Unstable,NoFuel,DBStableDiff,DBUnstableDiff,DBNoFuelDiff' find . -maxdepth 2 -name "*-agg.txt" -exec cat {} + | sort | sed "$ADD_HEAD" > aggregate.csv diff --git a/src/StabilityCheck.jl b/src/StabilityCheck.jl index 571657d95..047a5d7e7 100644 --- a/src/StabilityCheck.jl +++ b/src/StabilityCheck.jl @@ -96,8 +96,8 @@ is_stable_module_aux(mod::Module, root::Module, seen::Set{Module}, scfg::SearchC our_methods_of_function(evsym, mod))) catch e if e isa UndefVarError - @warn "Module $mod exports symbol $sym but it's undefined" - # showerror(stdout, e) + @warn "Module $mod contains symbol $sym but we can't evaluate it" + showerror(stdout, e) # not our problem, so proceed as usual elseif e isa CantSplitMethod @warn "Can't process method with no canonical instance:\n$m" @@ -156,7 +156,7 @@ is_stable_method(m::Method, scfg :: SearchCfg = default_scfg) :: StCheck = begin @debug "is_stable_method: any, vararg checks" Any ∈ sig_types && ! scfg.typesDBcfg.use_types_db && return AnyParam() - any(t -> is_vararg(t), sig_types) && + any(t -> has_vararg(t), sig_types) && return VarargParam() # TODO: @@ -201,7 +201,7 @@ is_stable_method(m::Method, scfg :: SearchCfg = default_scfg) :: StCheck = begin result isa OutOfFuel && return result return if isempty(unst) - if isempty(skipexists) + if isempty(skipexists) # TODO: kill skipexist, we don't use it Stb(stepCount) else UConstrExist(stepCount, skipexists) diff --git a/src/enumeration.jl b/src/enumeration.jl index c7ca9d032..67f15af5e 100644 --- a/src/enumeration.jl +++ b/src/enumeration.jl @@ -87,10 +87,13 @@ has_unboundeded_exist(tv :: JlSignature) = begin end # Shortcut: well-known underconstrained types that we want to avoid -# for which we will return NoFuel eventually +# for which we will return NoFuel eventually. +# Varargs, Tuple, Function, etc. blocklist = [Function] -is_vararg(t) = isa(t, Core.TypeofVararg) -to_avoid(t) = is_vararg(t) || any(b -> t <: b, blocklist) +has_vararg(t) = occursin("Vararg", "$t") || # crude but works + t == Tuple # ~ Tuple{Vararg{Any}} +to_avoid(t) = has_vararg(t) || + any(b -> t <: b, blocklist) # # direct_subtypes: JlSignature, SearchCfg -> [Union{JlSignature, SkippedUnionAlls}] @@ -155,6 +158,8 @@ direct_subtypes1(t::Any, scfg :: SearchCfg) = begin subtype_union(t) elseif is_concrete_type(t) [t] + elseif t <: Tuple + direct_subtypes(Vector{Any}([t.parameters...]), scfg) else @assert false "direct_subtypes1: can't subtype $t (should not happen)" end diff --git a/src/report.jl b/src/report.jl index a36be3b05..3a1d276a8 100644 --- a/src/report.jl +++ b/src/report.jl @@ -83,8 +83,12 @@ prepCsv(mcs::StCheckResults) :: StCheckResultsCsv = map(prepCsvCheck, mcs) # +# # Record of aggregated results. One Julia module turns into one instance of it. -# Note: If you change it, you probably need to update scripts/aggregate.sh +# +# NOTE: If you change it, you probably need to update scripts/aggregate.sh and +# the two functions right below. +# struct AgStats methCnt :: Int64 stbCnt :: Int64 @@ -92,14 +96,34 @@ struct AgStats parCnt :: Int64 anyCnt :: Int64 vaCnt :: Int64 - gen :: Int64 + genCnt :: Int64 tcfCnt :: Int64 nofCnt :: Int64 end -showAgStats(pkg::String, ags::AgStats) :: String = - "$pkg,$(ags.methCnt),$(ags.stbCnt),$(ags.unsCnt),$(ags.parCnt),$(ags.anyCnt)," * - "$(ags.vaCnt),$(ags.gen),$(ags.tcfCnt),$(ags.nofCnt)\n" +showAgStatsDB(pkg::String, agsNoDb::AgStats, agsDb::AgStats) :: String = begin + @assert agsNoDb.parCnt == 0 + @assert agsDb.parCnt == 0 + + # @info agsDb + methGood = agsNoDb.methCnt - agsNoDb.tcfCnt - agsNoDb.genCnt + noFuel = agsNoDb.vaCnt + agsNoDb.nofCnt + agsNoDb.anyCnt + noFuelDb = agsDb.vaCnt + agsDb.nofCnt + agsDb.anyCnt + + # $(agsNoDb.methCnt), # should this be in? makes the table noisier... + "$pkg,$(methGood)," * + "$(agsNoDb.stbCnt),$(agsNoDb.unsCnt),$(noFuel)," * + "$(agsDb.stbCnt - agsNoDb.stbCnt),$(agsDb.unsCnt - agsNoDb.unsCnt),$(noFuelDb - noFuel)" * + "\n" +end + +showAgStats(pkg::String, ags::AgStats) :: String = begin + @assert ags.parCnt == 0 + methGood = ags.methCnt - ags.tcfCnt - ags.genCnt + noFuel = ags.vaCnt + ags.nofCnt + ags.anyCnt + "$pkg,$(ags.methCnt), $(methGood)," * + "$(ags.stbCnt),$(ags.unsCnt),$(noFuel)\n" +end aggregateStats(mcs::StCheckResults) :: AgStats = AgStats( # TODO: this is a lot of passes over mcs; should rewrite into one loop @@ -128,6 +152,7 @@ aggregateStats(mcs::StCheckResults) :: AgStats = AgStats( checkModule(m::Module, out::String="."; pkg::String="$m")= begin scfg = build_typesdb_scfg(sample_count=10) checkRes = is_stable_module(m, scfg) + checkResNoDb = is_stable_module(m) # raw, to allow load it back up for debugging purposes # CSV.write(joinpath(out, "$m-raw.csv"), checkRes) @@ -140,7 +165,8 @@ checkModule(m::Module, out::String="."; pkg::String="$m")= begin # aggregate aggrepname = joinpath(out, "$pkg-agg.txt") @info "Generating and writing out aggregated report to $aggrepname" - write(aggrepname, showAgStats(pkg, aggregateStats(checkRes))) + write(aggrepname, + showAgStatsDB(pkg, aggregateStats(checkResNoDb), aggregateStats(checkRes))) return () end diff --git a/src/utils.jl b/src/utils.jl index b30940949..4817b9608 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -51,6 +51,7 @@ end # Note: Follows definition used in @code_warntype (cf. `warntype_type_printer` in: # julia/stdlib/InteractiveUtils/src/codeview.jl) is_concrete_type(@nospecialize(ty)) = begin + ty == DataType && return true if ty isa Type && (!Base.isdispatchelem(ty) || ty == Core.Box) if ty isa Union && is_expected_union(ty) true # this is a "mild" problem, so we round up to "stable"