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

From: Stefan Monnier <[email-masked]>
Date: Tue, 06 May 2025 11:55:09 -0400

>  Debugger entered--Lisp error: (void-function kmacro-register-p)
>   kmacro-register-p(2)
>   cl-typep(2 (satisfies kmacro-register-p))
>   cl-typep(2 kmacro-register)
>   cl-types-of(2)
>   (seq-intersection (cl-types-of 2) types)
>   [...]

That's an incorrect `cl-deftype` call.  AFAIK this was in `register.el`
but I actually removed it from there with:

    commit b1407b41a16c4a3ec15c88be91ba0ae1e65c212e
    Author: Stefan Monnier <[email-masked]>
    Date:   Tue Apr 29 16:04:54 2025 -0400
    
        register.el: Remove bogus deftypes and fix associated methods
        
        * lisp/register.el (frame-register, kmacro-register): Remove bogus deftypes.
        (register--type) <oclosure>: Fix kmacro method and generalize it to
        any OClosure.
        (register--type) <frameset-register>: Fix method and move it to ...
        * lisp/frameset.el (register--type) <frameset-register>: ... here,
        where `frameset-register` is defined.

I guess I need to rebase the `cl-types` branch.  🙂

>>> (cl-types-of 'button) => button match `icon' type, so the `cl--type-flag'
>>> of `icon' is set to `symbol' (cl-type-of or root-type of `button')
>>>
>>> (cl-types-of 12) => `root-type' of 12 is `fixnum', so cl-types-of doesn't
>>> waste time checking if 12 if of type `icon', because we are sure it cannot
>>> match (their root-types are different).  An so on with other types whose
>>> root-type is known.
>> That makes a lot of sense, indeed.
>> But ... does it work for:
>>     (cl-deftype my-pair ()
>>       `(and number (satisfies ,(lambda (x) (zerop (logand x 1))))))
>> (cl-types-of (expt 2 128)) => (expt 2 128) matches `my-pair` type, so
>> the `cl--type-flag` of `my-pair` is set to `bignum`.  Now when I try
>> (cl-types-of 4) won't it skip `my-pair` because (cl-type-of 4) is not
>> `bignum`?  What am I missing?
>
> Good point! The problem is that the type returned by `cl-type-of' is too
> specific. If I instead use `type-of' to map a set of cl-types to a
> built-in type, your example above works as expected, as do other
> categories I've tested, like symbol, cons, string, etc.
> Using `type-of' to determine a set of cl-types seems like a good
> compromise to me. WDYT?

That just solves some occurrences, but not all:

     (cl-deftype my-pair-length ()
       `(and sequence (satisfies ,(lambda (x) (zerop (logand (length x) 1))))))

and now (cl-types-of [1 2]) will set `cl--type-flag` to
`vector` so (cl-types-of "ab") will miss `my-pair-length`!

If you want more cases, think of

    (cl-deftype my-foo ()
      '(or TYPE1 TYPE2))

- Stefan