Defining `show` method for all `MIME` types at once threw an error for `display`

MWE (tested on Julia 1.11.5):

julia> struct MyT{T}
           a::T
       end

julia> import Base: show

julia> Base.show(io::IO, ::MIME, obj::MyT) = print(io, typeof(obj), "(...)")

julia> MyT(1)
Error showing value of type MyT{Int64}:

SYSTEM (REPL): showing an error caused an error
ERROR: MethodError: no method matching display(::MyT{Int64})

Based on the documentation, this worked:

julia> struct MyT{T} # In a new Julia REPL process
           a::T
       end

julia> import Base: show

julia> Base.show(io::IO, ::MIME"text/plain", obj::MyT) = print(io, typeof(obj), "(...)")

julia> MyT(1)
MyT{Int64}(...)

Does this mean one should always specify the MIME type they want to customize “show” for?

Thanks!!

Yes. It makes no sense to have a MIME-independent show method.

For example, why would you use the same method for text/plain and img/png?

Note, however, that error here is misleading and should probably be fixed. The real reason display is throwing an error is that the method dispatch is ambiguous. We can see the true error if we call a lower-level method:

julia> display(Base.Multimedia.displays[1], MyT(1))
ERROR: MethodError: show(::Base.TTY, ::MIME{Symbol("text/plain")}, ::MyT{Int64}) is ambiguous.

Candidates:
  show(io::IO, ::MIME{Symbol("text/plain")}, x)
    @ Base.Multimedia multimedia.jl:47
  show(io::IO, ::MIME, obj::MyT)
    @ Main REPL[3]:1

Possible fix, define
  show(::IO, ::MIME{Symbol("text/plain")}, ::MyT)

Stacktrace:
 [1] display(d::TextDisplay, M::MIME{Symbol("text/plain")}, x::Any)
   @ Base.Multimedia ./multimedia.jl:254
 [2] display(d::TextDisplay, x::Any)
   @ Base.Multimedia ./multimedia.jl:255
 [3] top-level scope
   @ REPL[15]:1

The Base.show method is ambiguous because there is a MIME"text/plain" fallback method for any type of x, as well as your show method for any MIME but a specific type of x.

4 Likes

Thanks for the explanation!