prl-julia / julia-type-stability

10 stars 0 forks source link

Generic types in method instances are not supported #2

Closed ulysses4ever closed 1 year ago

ulysses4ever commented 3 years ago

When running analysis on the JSON package I got an exception for the method instance of the following type:

Tuple{
  typeof(JSON.Parser.int_from_bytes),
  JSON.Parser.ParserContext{DictType,IntType,AllowNanInf,NullValue} 
    where NullValue 
    where AllowNanInf 
    where DictType,
  JSON.Parser.StreamingParserState{IOStream},
  Array{UInt8,1},
  Int64,
  Int64} where IntType<:Real

(So, this is a compiled method of the int_from_bytes function.) The problem is the outer where (it binds the type parameter of a ParserContext instance). My pipeline currently does not know what to do with it.


BTW, does it work for f(@nospecialize(x)) = 1? see below https://github.com/prl-julia/julia-type-stability/issues/2#issuecomment-753510448

ulysses4ever commented 3 years ago

Update on the @nospecialize example: it simply gets substituted with Any, it seems, e.g.:

julia> f(@nospecialize(x)) = 1
f (generic function with 1 method)

julia> f(1)
1

julia> methodinstances(f)
1-element Array{Core.MethodInstance,1}:
 MethodInstance for f(::Any)
ulysses4ever commented 3 years ago

The problematic method instance from JSON uses a parametric struct with no fields. Maybe that's the reason it has not been specialized. But it's hard to see how one could repro this problem. E.g.:

julia> struct S{T} end

julia> s=S{Int64}()
S{Int64}()

julia> h(s::S{T}) where T = 3
h (generic function with 1 method)

julia> h(s)
3

julia> methodinstances(h)
1-element Array{Core.MethodInstance,1}:
 MethodInstance for h(::S{Int64})

To summarize, creating an instance of such a structure (s of type S in the example) requires to provide a type argument. And you see the same argument in the method instance after you call a function with the instance.

ulysses4ever commented 3 years ago

Temporary workaround: count the number of generic methods but not try to analyze them.

ulysses4ever commented 3 years ago

A more radical but still somewhat unsatisfying fix -- implemented after @v0.1 -- is to use Base.unwrap_unionall. I don't quite understand what a question about type stability means for a type with free type variables...

ulysses4ever commented 1 year ago

I can't reproduce it anymore. On the reference 10 packages (+ JSON and Multisets) there doesn't seem to be a case of it.

Note that reconstruct_func_call tries hard to notice if this resurfaces and will print a warning and produce an extra file (generic-instances.txt) if it's the case.

Optimistically closing.