Skip to content

[FR] NotImplementedError, to communicate user-extendable but not-yet-implemented API #50196

@Seelengrab

Description

@Seelengrab

Currently, defining some form of API like so:

abstract type Foo end

"""
    bar(::Foo)

Implements `bar` for subtypes of `Foo`. Needs to be implemented to fulfill the interface expected of `Foo`.
"""
function bar end

always throws a MethodError. From a user-perspective, it's hard to find out whether bar was supposed to be implemented by a package they're using or not - it could very well just be a bug, since all MethodError communicates is "There is no method matching this". Since this can bubble up from deep in some library, it'd be better for users to be able to say "I got this NotImplementedError", which also makes it clear to package maintainers that they forgot to implement some method that is required of the interface they claim to implement.

This feature request/proposal is aimed at solving this issue, by giving package authors & Base an option to communicate to users "There is no fallback definition, since your type should implement this". This is done with a new error type, NotImplementedError, which is defined like so:

struct NotImplementedError <: Exception
    interface::String
    func::String
end

function Base.showerror(io::IO, nie::NotImplementedError)
    printstyled(io, "NotImplementedError: "; color=:red)
    print(io, "The called method is part of a fallback definition for the `", nie.interface, "` Interface.\n",
              "Please implement `", nie.func, "` for your type T.")
end

and used like so:

julia> abstract type Foo end

julia> bar(::Foo, ::Int) = throw(NotImplementedError("Foo", "bar(::T, ::Int)"))

julia> struct Baz <: Foo end

julia> bar(Baz(), 1)
ERROR: NotImplementedError: The called method is part of a fallback definition for the `Foo` Interface.
Please implement `bar(::T, ::Int)` for your type T.
Stacktrace:
 [1] bar(::Baz, ::Int64)
   @ Main ./REPL[4]:1
 [2] top-level scope
   @ REPL[6]:1

image

This allows the distinction between intended-to-be-extended API (bar(::Foo, ::Int)) and this-is-supposed-to-error (any other signature on bar, which throws a MethodError).

To be discussed

The details of what exactly NotImplementedError should contain, since this version with just two strings is IMO too bare-bones, as it requires discipline/good grasp of the intended API to be able to create the string directly.

Why is this needed?

This error and variations on it are widespread throughout the ecosystem and I think Base could benefit from having some fallback definitions like the one above as well, to give much more informative error messages when subtyping e.g. <: AbstractArray or other abstract types in Base.

Metadata

Metadata

Assignees

No one assigned

    Labels

    error messagesBetter, more actionable error messagesfeatureIndicates new feature / enhancement requests

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions