Skip to content

Commit

Permalink
Merge pull request #213 from timholy/teh/get_def
Browse files Browse the repository at this point in the history
Use type intersection to match signatures to those of methods
  • Loading branch information
timholy committed Dec 2, 2018
2 parents 13c482c + 674643a commit f0bca76
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/Revise.jl
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ function eval_revised!(fmmrep::FMMaps, mod::Module,
lineoffset = (isa(lnref, Integer) && isa(lnnew, Integer)) ? lnnew-lnref : 0
fmmrep.defmap[defref] = (sigtref, lineoffset)
for sigt in sigtref
# sigt = sigt2methsig(sigt)
fmmrep.sigtmap[sigt] = defref
end
oldoffset != lineoffset && @debug "LineOffset" _group="Action" time=time() deltainfo=(sigtref, lnnew, oldoffset=>lineoffset)
Expand Down Expand Up @@ -296,11 +297,14 @@ function eval_and_insert!(fmm::FMMaps, mod::Module, pr::Pair)
if val isa RelocatableExpr
instantiate_sigs!(fmm, def, val, mod)
else
fmm.defmap[def] = val
if val !== nothing
for sigt in val[1]
sigts = Any[sigt2methsig(sigt) for sigt in val[1]]
fmm.defmap[def] = (sigts, val[2])
for sigt in sigts
fmm.sigtmap[sigt] = def
end
else
fmm.defmap[def] = val
end
end
catch err
Expand Down Expand Up @@ -439,6 +443,7 @@ end

function instantiate_sigs!(fmm::FMMaps, def::RelocatableExpr, sig::RelocatableExpr, mod::Module)
sigts = sigex2sigts(mod, sig, def)
sigts = Any[sigt2methsig(sigt) for sigt in sigts]
# Insert into the maps
fmm.defmap[def] = (sigts, 0)
for sigt in sigts
Expand Down
12 changes: 12 additions & 0 deletions src/exprutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,18 @@ function sigex2sigts(mod::Module, sig::ExLike, def=nothing)
return sigts
end

"""
methsig = sigt2methsig(sig)
For a signature `sig`, try to return the signature `methsig` of a currently-defined method.
"""
function sigt2methsig(sig)
ret = Base._methods_by_ftype(sig, -1, typemax(UInt))
isempty(ret) && return sig
methsig = ret[end][3].sig # the last method returned is the least-specific that matches, and thus most likely to be type-equal
@assert sig <: methsig && methsig <: sig
return methsig
end

"""
callex = get_callexpr(sigex::ExLike)
Expand Down
28 changes: 28 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,34 @@ end
Base.delete_method(first(methods(Base.revisefoo)))
end

@testset "get_def" begin
testdir = randtmp()
mkdir(testdir)
push!(to_remove, testdir)
push!(LOAD_PATH, testdir)
dn = joinpath(testdir, "GetDef", "src")
mkpath(dn)
open(joinpath(dn, "GetDef.jl"), "w") do io
println(io, """
module GetDef
f(x) = 1
f(v::AbstractVector) = 2
f(v::AbstractVector{<:Integer}) = 3
end
""")
end
@eval using GetDef
@test GetDef.f(1.0) == 1
@test GetDef.f([1.0]) == 2
@test GetDef.f([1]) == 3
m = @which GetDef.f([1])
ex = Revise.get_def(m)
@test ex isa Revise.RelocatableExpr
@test isequal(ex, Revise.relocatable!(:(f(v::AbstractVector{<:Integer}) = 3)))
end

@testset "Pkg exclusion" begin
push!(Revise.dont_watch_pkgs, :Example)
push!(Revise.silence_pkgs, :Example)
Expand Down

0 comments on commit f0bca76

Please sign in to comment.