It may seem weird that code and details would travel along two paths
now instead of one but it makes sense after considering that sometimes
the code and details are application data from the remote application
and sometimes they are transport data from the transport between the
local and remote applications.
(1) In _ingestion, it's the "details" attribute of a
NoSuchMethodException that we want. The "message" is inherited from the
base Exception class.
(2) In _transmission, use a proper sum type for representing operation
abortion. Trying to overload the existing _completion value for
status-and-details-when-aborting was trying to be too clever.
(3) In _calls... oof. Just look. Oof. Test coverage for this code path
is added.
(4) In _service, the application-provided
face.MultiMethodImplementation isn't directly callable, but rather
exposes a method named "service".
(5) In crust.implementations, the wrapping that we've put around the
application-provided face.MultiMethodImplementation *is* directly
callable, and *does not* expose a method named "service".
(6) Also in crust.implementations, base.NoSuchMethodError's constructor
takes a code value and a details value.
(7) Again in crust.implementations, the application-provided
face.MultiMethodImplementation may be None, and if it is None, we
shouldn't wrap it with an adaptation function that would only raise a
TypeError at a later time.