Subject: bug#77725: 31.0.50; Add support for types accepted by `cl-typep' to cl-generic?

From: David Ponce <[email-masked]>
Date: Fri, 11 Apr 2025 17:04:10 +0200

On 2025-04-11 15:41, Stefan Monnier wrote:
> Hi David,
> 
>>> As part of some other works, I created the attached "gtype" library,
>>> which complements `cl-deftype' so that such defined types are also
>>> recognized as argument types for dispatching generic function methods.
>>> Here is a quick example of use:
>>>
>>> (defgtype face nil ()
>>>     "A face type."
>>>     '(satisfies facep))
>>>
>>> (gtype-of 'default)
>>> => face
>>> (cl-type-of 'default)
>>> => symbol
>>>
>>> (cl-defmethod my-add-face ((text string) (face face))
>>>     (propertize text 'face face))
>>> => my-add-face
> 
> Nice.
> 
>>> I've been using this library successfully in some of my code, and was
>>> wondering if it could help add this functionality to Emacs.  My goal
>>> is not to include this library, but to use it as a starting point for
>>> further reflection on this subject.
> 
> The problem with adding new generalizers is to make sure they interact
> correctly with others.  If you allow `satisfies` kind of definitions,
> then it's easy to end up with situations where one of your new types is
> neither a subtype (aka sub-specializer) nor a supertype
> (super-specializer) of an existing type (specializer).
> 
> Let's take `function` defined as `(satisfies functionp)` is an example.
> 
>      (functionp '(lambda () 1))
>      => t
>      (type-of '(lambda a))
>      => cons
> 
> this suggests (satisfies functionp) should be a subtype of `cons`, but
> that is clearly wrong because
> 
>      (functionp (lambda () 1))
>      => t
>      (consp (lambda () 1))
>      => nil
> 
> The type-dispatch code wants *one* value (generalizer) to lookup the
> hash-table where it will find the corresponding effective method.
> That one value should be "the most specific" generalizer among the
> generalizers currently used for that generic function.
> 
> Now a `gtype-of` called `g-function` built from `(satisfies functionp)`
> will be sometimes more specific and sometimes less specific than
> `type-of`, so there is no correct PRIORITY to indicate to
> `cl-generic-define-generalizer`: we'll end up with dispatch errors if
> a generic function has a method for both `g-function` and for `cons`.
> 
> 
>          Stefan
> 

Hi Stefan,

Thank you very much for your feedback!

Your remarks make sense, for sure.

Does this mean that for a `cl-deftype'-like generalizer to work
correctly, it must be part of the "typof" generalizer?

In other words, that a function like `gtype-of' should fall back to
`cl-type-of' when there is no corresponding gtype for an object?

Or am I missing something? --- Sorry, I only started studying
cl-generic relatively recently, and I probably don't understand
all its intricacies ;-)