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

From: Stefan Monnier <[email-masked]>
Date: Fri, 11 Apr 2025 12:26:05 -0400

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

No, but it needs to be either always more precise or always less precise
than `type-of`.

IOW, either:

    (eql (gtypeof-generalizer A) (gtypeof-generalizer B))
    IMPLIES ((eql (gtypeof-generalizer A) nil)
             OR (eql (cl-type-of A) (cl-type-of B)))

or the reverse.  That's a current limitation in the cl-generic system.

One way to solve this is to use a generalizer that returns either nil or
a pair containing both the `gtype-of` and the `cl-type-of`, so it's
trivially always more precise than `cl-type-of`.  But beware: these
things are compared with `eql` so you need to "uniquify" them with
a sort of hashconsing scheme.

BTW if you do

    (defgtype cons-car-foo nil ()
      "A cons with a `foo' car."
      `(satisfies ,(lambda (x) (eq (car-safe x) 'foo))))

    (defgtype cons-cdr-foo nil ()
      "A cons with a `foo' cdr."
      `(satisfies ,(lambda (x) (eq (cdr-safe x) 'foo))))

what's the `(gtype-of '(foo . foo))` ?

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

Yeah, it's unsatisfactorily intricate, indeed.  It's designed first and
foremost to keep the dispatch "simple and reasonable fast", at the cost
of making `cl-generic-define-generalizer` a very sharp tool.  🙂

I have recently been thinking about how to make it more reliable (which
would also make it more flexible/powerful, allowing the definition of
both `and` and `or` specializers).  I have some vague idea, but there's
no code at all yet, and it might come with some non-trivial tradeoffs
(e.g. preloading the byte-compiler).

        Stefan