JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.72k stars 5.48k forks source link

incomplete methodswith output #5722

Closed stevengj closed 10 years ago

stevengj commented 10 years ago
type Foo
end
bar{T<:Foo}(x::T) = 1
methodswith(Foo)

returns 0-element Array{Method,1}, which doesn't seem right.

jiahao commented 10 years ago

I just encountered this in Base.LinAlg.UMFPACK, thanks to a somewhat awkwardly defined method:

julia> A=randn(5,5);A=sparse(A'*A); b=lufact(A)
UMFPACK LU Factorization of a 5-by-5 sparse matrix
Ptr{Void} @0x00007fdea6f66ff0

julia> typeof(b)
UmfpackLU{Float64,Int64} (constructor with 1 method)

julia> det(b) #The determinant of the sparse LU factorization is defined and works
11.241089139377763

julia> methodswith(typeof(b)) #???
0-element Array{Method,1}

julia> @which det(b) #Strange parametric definition, since neither Float64 not Int64 have subtypes
det{Tv<:Float64,Ti<:Int64}(lu::UmfpackLU{Tv<:Float64,Ti<:Int64}) at linalg/umfpack.jl:248

julia> methodswith(Base.LinAlg.UMFPACK.UmfpackLU) #not here either
6-element Array{Method,1}:
 A_ldiv_B!{T<:Union(Complex{Float64},Float64)}(lu::UmfpackLU{T<:Union(Complex{Float64},Float64),Ti<:Union(Int64,Int32)},b::Union(Array{T<:Union(Complex{Float64},Float64),2},Array{T<:Union(Complex{Float64},Float64),1})) at linalg/umfpack.jl:302                                                                                                                                                               
 A_ldiv_B!{Tlu<:Union(Complex{Float64},Float64),Tb<:Number}(lu::UmfpackLU{Tlu<:Union(Complex{Float64},Float64),Ti<:Union(Int64,Int32)},b::Union(SubArray{Tb<:Number,1,A<:DenseArray{T,N},I<:(Union(Range1{Int64},Int64,Range{Int64})...,)},DenseArray{Tb<:Number,1},SubArray{Tb<:Number,2,A<:DenseArray{T,N},I<:(Union(Range1{Int64},Int64,Range{Int64})...,)},DenseArray{Tb<:Number,2})) at linalg/umfpack.jl:308
 A_ldiv_B!{Tlu<:Union(Complex{Float64},Float64),Tb<:Number}(lu::UmfpackLU{Tlu<:Union(Complex{Float64},Float64),Ti<:Union(Int64,Int32)},b::Union(AbstractArray{Tb<:Number,1},AbstractArray{Tb<:Number,2})) at linalg/umfpack.jl:309                                                                                                                                                                                
 show(io::IO,f::UmfpackLU{Tv<:Union(Complex{Float64},Float64),Ti<:Union(Int64,Int32)}) at linalg/umfpack.jl:134                                                                                                                                                                                                                                                                                                   
 getindex(lu::UmfpackLU{Tv<:Union(Complex{Float64},Float64),Ti<:Union(Int64,Int32)},d::Symbol) at linalg/umfpack.jl:330                                                                                                                                                                                                                                                                                           
 getindex(lu::UmfpackLU{Tv<:Union(Complex{Float64},Float64),Ti<:Union(Int64,Int32)},d::Symbol) at linalg/umfpack.jl:330                                                                                                                                                                                                                                                                                           
ViralBShah commented 10 years ago

Bump. Still broken. Is this something to fix for 0.3?

stevengj commented 10 years ago

No, I don't think it should block 0.3. It's not a regression (0.2 had the same problem).

ihnorton commented 10 years ago

@jiahao's issue appears to be fixed on master.

for the original issue, this works:

diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl
index 5349420..62495f5 100644
--- a/base/interactiveutil.jl
+++ b/base/interactiveutil.jl
@@ -257,7 +257,7 @@ function methodswith(t::Type, m::Module, showparents::Bool=false)
            mt = eval(m, nm)
            d = mt.env.defs
            while !is(d,())
-               if any(map(x -> x == t || (showparents && t <: x && x != Any && x != ANY && !isa(x, TypeVar)), d.sig))
+               if any(map(x -> x == t || (showparents && t <: x && x != Any && x != ANY && (!isa(x, TypeVar) || x.ub == t)), d.sig))
                    push!(meths, d)
                end
                d = d.next

but @stevengj not sure if that is the behavior you want (should it check any TypeVar regardless of showparents bool option?)

stevengj commented 10 years ago

Shouldn't it be (showparents ? x.lb <: t <: x.ub : t == x.ub)?

ihnorton commented 10 years ago

If we want to always match (x::TypeVar).ub then I think the order should be switched because by default showparents == false. PR submitted.

ihnorton commented 10 years ago

6658

stevengj commented 10 years ago

Still seems buggy:

type Foo
end
bar{T<:Foo}(x::T) = 1
methodswith(Foo)

gives duplicated output

2-element Array{Method,1}:
 bar{T<:Foo}(x::T<:Foo) at none:1
 bar{T<:Foo}(x::T<:Foo) at none:1

and

abstract Bar
type Baz <: Bar
end
baz{T<:Bar}(x::T) = 1
methodswith(Baz)

(correctly) gives 0-element Array{Method,1}, but methodswith(Baz, true) gives

16-element Array{Method,1}:
 range{T}(a::T,len::Integer) at range.jl:75
range{T,S}(a::T,step::S,len::Integer) at range.jl:86
givens{T}(f::T,g::T,i1::Integer,i2::Integer,size::Integer) at linalg/givens.jl:185
StepRange{T,S}(start::T,step::S,stop::T) at range.jl:57
promote{T,S}(x::T,y::S) at promotion.jl:123
oftype{T}(x::T,c) at operators.jl:138
powermod{T}(b::Integer,p::Integer,m::T) at intfuncs.jl:90
get!{T}(X::AbstractArray{T,N},A::AbstractArray{T,N},I::Union(Range{T},AbstractArray{Int64,1}),default::T) at abstractarray.jl:467
 get!{T}(X::AbstractArray{T,N},A::AbstractArray{T,N},I::Union((Union(Range{T},AbstractArray{Int64,1})...,),AbstractArray{UnitRange{Int64},1},AbstractArray{Range{Int64},1},AbstractArray{A<:AbstractArray{Int64,1},1}),default::T) at abstractarray.jl:477
 readuntil{T}(s::IO,delim::T) at io.jl:164
Enumerate{I}(itr::I)                                                                                                                                                         clamp{X,L,H}(x::X,lo::L,hi::H) at math.jl:29
Filter{I}(flt::Function,itr::I)                                                                                                                                     colon{T}(start::T,stop::T) at range.jl:73
colon{T}(start::T,step,stop::T) at
range.jl:84
baz{T<:Bar}(x::T<:Bar) at none:1                 

which seems wrong.