Further comments: - For a declaration like (cl-deftype list-of (elem-type) `(and list (satisfies ,(lambda (list) (cl-every (lambda (elem) (cl-typep elem elem-type)) list))))) we add the type to `cl--type-list` even though it's unusable there (the `cl-typep` call in `cl-types-of` will always signal an error because the type can't be used without argument). - Regarding incorporation into CL-Lib: apparently we don't need to `cl-deftype` in preloaded files, so `cl--type-deftype` does not have to be in `cl-preloaded`. But if `cl-deftype` expands to a call to it, then it needs to be (auto)loaded even when CL-Lib is not loaded, which suggests putting it into `cl-lib.el`. Another option would be to make `cl-deftype` expand to code which does not immediately call `cl--type-deftype`. One way to do that would be to wrap the call into a `(with-eval-after-load 'cl-lib ...)` or something similar. - One way to solve the problem with `list-of` (and even open up the possibility to dispatch on complex types like `(list-of FOO)`) is to populate `cl--type-dispatch-list` (i.e. the list of types that need to be checked during dispatch) from `cl-generic-generalizers` so it includes only those types for which there's a method, rather than all defined types. - The dispatch of types defined by `cl-deftype` is inherently unreliable because the priority to use is not always the same. For a type defined as `(or integer symbol)` the priority should be *lower* than the priority of the "typeof" generalizer, whereas for a type defined as `(list-of (eql 'a))` the priority should be higher than that of the "head" generalizer. I don't think we can solve this problem, but it should be clearly documented somewhere as a limitation. See below my current local changes (not really related to the comments above) as a diff w.r.t. the `scratch/cl-types` branch. Stefan