GNU bug report logs - #69739
30.0.50; `type-of` is not precise enough

Previous Next

Package: emacs;

Reported by: Stefan Monnier <monnier <at> iro.umontreal.ca>

Date: Mon, 11 Mar 2024 23:22:01 UTC

Severity: normal

Found in version 30.0.50

Done: Stefan Monnier <monnier <at> iro.umontreal.ca>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: help-debbugs <at> gnu.org (GNU bug Tracking System)
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: bug#69739: closed (Re: bug#69739: 30.0.50; `type-of` is not
 precise enough)
Date: Mon, 18 Mar 2024 13:35:02 +0000
[Message part 1 (text/plain, inline)]
Your bug report

#69739: 30.0.50; `type-of` is not precise enough

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to 69739 <at> debbugs.gnu.org.

-- 
69739: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=69739
GNU Bug Tracking System
Contact help-debbugs <at> gnu.org with problems
[Message part 2 (message/rfc822, inline)]
From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: acorallo <at> gnu.org, basil <at> contovou.net, 69739-done <at> debbugs.gnu.org
Subject: Re: bug#69739: 30.0.50; `type-of` is not precise enough
Date: Mon, 18 Mar 2024 09:33:58 -0400
>> +@example
>> +(object-type 1)
>> +     @result{} fixnum
>> +@group
>> +(object-type 'nil)
>> +     @result{} null
>> +(object-type (record 'foo))
>> +     @result{} foo
>
> "object-type"?

Oops!  thanks.

>>  DEFUN ("type-of", Ftype_of, Stype_of, 1, 1, 0,
>>         doc: /* Return a symbol representing the type of OBJECT.
>>  The symbol returned names the object's basic type;
>> -for example, (type-of 1) returns `integer'.  */)
>> +for example, (type-of 1) returns `integer'.
>> +Contrary to `cl-type-of' the returned type is not always the most
>                           ^^
> I think we want a comma there.
>> +DEFUN ("cl-type-of", Fcl_type_of, Scl_type_of, 1, 1, 0,
>> +       doc: /* Return a symbol representing the type of OBJECT.
>> +The symbol returned names the most specific possible type of the object.
>    ^^^^^^^^^^^^^^^^^^^
> I think "The returned symbol" is better here, as it prevents a
> possible confusion (whether "returned" alludes to "symbol" or to
> "names").

Agreed.

>> +for example, (object-type nil) returns `null'.
>                  ^^^^^^^^^^^
> "object-type"?

As you can see I had used `object-type` instead of `cl-type-of` in some
prior version of the code :-)

>>  (defsubst subr-primitive-p (object)
>> -  "Return t if OBJECT is a built-in primitive function."
>> +  "Return t if OBJECT is a built-in primitive written in C."
>>    (declare (side-effect-free error-free))
>>    (and (subrp object)
>>         (not (subr-native-elisp-p object))))
>>  
>> +(defsubst primitive-function-p (object)
>> +  "Return t if OBJECT is a built-in primitive function."
>> +  (declare (side-effect-free error-free))
>> +  (and (subrp object)
>> +       (not (or (subr-native-elisp-p object)
>> +                (eq (cdr (subr-arity object)) 'unevalled)))))
>
> Should these doc strings mention the special case of special form,
> which each one of them treats differently?

OK.

Pushed, thanks,


        Stefan


[Message part 3 (message/rfc822, inline)]
From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: bug-gnu-emacs <at> gnu.org
Subject: 30.0.50; `type-of` is not precise enough
Date: Mon, 11 Mar 2024 19:19:40 -0400
Package: Emacs
Version: 30.0.50


`type-of` is supposed to return "the" type of its argument.  Given that
ELisp has a notion of subtyping, "the" type is expected to mean "the
most precise type".  This is used in `cl-generic` to decide which method
to apply, so it's important that it returns precise information.

Currently, there `type-of` fails to return precise enough information in
a few cases:

- When the argument is nil, it returns `symbol`.  The problem here is
  that `symbol` is not a subtype of `list`, whereas nil is a list.

- When the argument is a special form, a C primitive, or
  a native-compiled function it returns `subr`.  Currently our
  type hierarchy says that `subr` is a subtype of `compiled-function`
  (and hence of `function`), but a special form is *not* a function
  (it fails the `functionp` test and can't be `funcall`ed).

Currently `cl-generic` works around the first point above by using
(if FOO (type-of FOO) 'null) instead of calling `type-of` directly.

Suggestion:

    I suggest we change `type-of` to return `null` for `nil`,
    `special-form` for subrs that are special forms, `subr-primitive`
    for C primitives, and `subr-native-elisp` for native-compiled subrs.

There are a few other cases where we could improve the precision, tho
they are less important because they don't cause problems w.r.t
subtyping like the above does.

Further improvements could include:

- Return `boolean` for `t`.  This would be nice otherwise (with the
  above suggestion) `cl-generic` can dispatch on "nil is a boolean"
  but not on "t is a boolean".
- Return `keyword` for symbols that are keywords.
- Return `fixnum` or `bignum` rather than just `integer`.
  Probably not worth the trouble.
- We could go crazy and return `keyword-with-pos` for `symbols-with-pos`
  that are keywords.

Of these further improvements, only the first (return `boolean` for `t`)
seems worth the trouble.

Still, any change as suggested here would be an incompatible change, so
there's risk it'll break some code out there (`type-of` is not used very
often, but it *is* used).  Another option is to introduce a new function
which does the same as `type-of` but with changes like the ones above.
(we could even decide to give it a `cl-generic-` prefix to discourage
its use elsewhere so we can be more free to change its return value in
the future).


        Stefan




This bug report was last modified 1 year and 121 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.