Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

invoke with broadened type paramaters #15801

Closed
timholy opened this issue Apr 8, 2016 · 2 comments
Closed

invoke with broadened type paramaters #15801

timholy opened this issue Apr 8, 2016 · 2 comments

Comments

@timholy
Copy link
Member

timholy commented Apr 8, 2016

ColorTypes defines parametric colors, e.g., RGB{UFixed8} and Gray{Float32}. Often when working with colors, one might want to say convert(Gray, c) without worrying about the element type. ColorTypes contains a traits-function, ccolor ("concrete color"), which performs inferrable "concretization" of the type, so that convert(Gray, ::RGB{UFixed8}) -> Gray{UFixed8} and convert(Gray, ::RGB{Float64}) -> Gray{Float64}. Naturally, if the user asks for type that's already concrete, convert(Gray{Float32}, ::RGB{UFixed8}), that's what s/he gets.

Now let's say I want to override this method to make sure that, when T is a Colorant, it's a concrete Colorant. Here's what I tried:

julia> using Colors

julia> import Base: convert

julia> S = TypeVar(:S)
S

julia> @eval function convert{T<:Colorant,n}(::Type{Array{T,n}}, x::BitArray{n})
           # Specify the type concretely, then invoke the general algorithm on
           # the concrete type
           invoke(convert, (Type{Array{$S,n}}, BitArray{n}), Array{ccolor(T,Gray{Bool}),n}, x)
       end
convert (generic function with 602 methods)

julia> b = bitrand(3,4)
3x4 BitArray{2}:
 false   true  false   true
  true   true   true  false
 false  false   true  false

julia> convert(Array{Gray}, b)
ERROR: invoke: argument type error
 in convert(::Type{Array{ColorTypes.Gray{T<:Union{AbstractFloat,Bool,FixedPointNumbers.FixedPoint{T<:Integer,f}}},N}}, ::BitArray{2}) at ./bitarray.jl:294
 in eval(::Module, ::Any) at ./boot.jl:237

It clearly invokes the correct method, but then I get a mismatch in the type.

Is there any reasonable solution?

@JeffBezanson
Copy link
Member

This will require #8974. In the meantime you could try some of the workarounds for avoiding invoke discussed in #13123.

@timholy
Copy link
Member Author

timholy commented Apr 8, 2016

Thanks Jeff. I went with a non-exported _convert method as a workaround (see #15810). It is indeed much easier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants