unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Inferred function types in the *Help* buffer
@ 2023-05-23 16:44 Andrea Corallo
  2023-05-24 10:46 ` Eli Zaretskii
  0 siblings, 1 reply; 26+ messages in thread
From: Andrea Corallo @ 2023-05-23 16:44 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1354 bytes --]

Hello all,

on my Emacs I'm toying with the attached patch.  Applied on top of
master it adds the inferred type for native compiled functions into the
help buffer.

So for instance for a function like:

(defun foo (n)
  (unless (integerp n)
    (error "Panic"))
  (if (> n 100)
      'too-big
    (if (< n 100)
        'to-small
      n)))

The content of the *Help* buffer becomes:

====
foo is a native-compiled Lisp function in
‘~/.emacs.d/eln-cache/30.0.50-e29d76eb/test-a526a80f-5481bc95.eln’.

Signature: (foo N)

Inferred type: (function (t) (or (member to-small too-big) (integer
100 100)))

...
====

Indeed the native compiler is not capable of predicting precisly the
return type for every compiled function, often can't predict anything
more precise than 't'.  But in a -Q Emacs on my system it manages to
predict non trivial results for ~20% of loaded functions at startup.

I feel this would be a nice addition to the self-documenting
capabilities of Emacs, so I wanted to probe what's the general feeling
about this.

If it's considered too invasive we might indeed control it with a
customize, WDYT?

ATM I adds as well "Signature: " in front of the signature to
differentiate it from the type.  But looking at it in restrospective it
might be not even necessary.

Thanks

  Andrea


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: typef.patch --]
[-- Type: text/x-diff, Size: 761 bytes --]

diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 1966193d1a7..69f5c623f5c 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -710,7 +710,11 @@ help-fns--signature
               (high-doc (cdr high)))
           (unless (and (symbolp function)
                        (get function 'reader-construct))
-            (insert high-usage "\n"))
+            (insert "Signature: " high-usage "\n\n")
+            (when (and (featurep 'native-compile)
+                       (subr-native-elisp-p (symbol-function function))
+                       (subr-type (symbol-function function)))
+              (insert (format "Inferred type: %s\n" (subr-type (symbol-function function))))))
           (fill-region fill-begin (point))
           high-doc)))))
 

^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
@ 2023-05-23 16:47 Payas Relekar
  2023-05-23 18:51 ` Philip Kaludercic
  2023-05-24 12:20 ` Andrea Corallo
  0 siblings, 2 replies; 26+ messages in thread
From: Payas Relekar @ 2023-05-23 16:47 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: emacs-devel

Andrea Corallo <akrl@sdf.org> writes:

> ====
> foo is a native-compiled Lisp function in
> ‘~/.emacs.d/eln-cache/30.0.50-e29d76eb/test-a526a80f-5481bc95.eln’.
>
> Signature: (foo N)
>
> Inferred type: (function (t) (or (member to-small too-big) (integer
> 100 100)))
>
> ...
> ====

Pretty cool.

Tangentially, there's also Elsa: https://github.com/emacs-elsa/Elsa

How feasible would you say it would be to integrate it within
Emacs/native-compiler?

Regards,
Payas

--



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-23 16:47 Inferred function types in the *Help* buffer Payas Relekar
@ 2023-05-23 18:51 ` Philip Kaludercic
  2023-05-24 12:20 ` Andrea Corallo
  1 sibling, 0 replies; 26+ messages in thread
From: Philip Kaludercic @ 2023-05-23 18:51 UTC (permalink / raw)
  To: Payas Relekar; +Cc: Andrea Corallo, emacs-devel

Payas Relekar <relekarpayas@gmail.com> writes:

> Andrea Corallo <akrl@sdf.org> writes:
>
>> ====
>> foo is a native-compiled Lisp function in
>> ‘~/.emacs.d/eln-cache/30.0.50-e29d76eb/test-a526a80f-5481bc95.eln’.
>>
>> Signature: (foo N)
>>
>> Inferred type: (function (t) (or (member to-small too-big) (integer
>> 100 100)))
>>
>> ...
>> ====
>
> Pretty cool.
>
> Tangentially, there's also Elsa: https://github.com/emacs-elsa/Elsa
>
> How feasible would you say it would be to integrate it within
> Emacs/native-compiler?

Elsa?  In a recent discussion[0] the author (Matus Goljer) told me this:

> Elsa is complex and it currently can't run from user session Emacs and
> most likely never will. There is many ways to run Elsa mentioned in
> the Readme. Currently no other ways are supported, but I'm sure it's
> possible. Elsa is not a linter like "checkdoc", it is a full
> evaluation engine for Emacs Lisp, it's a gradual type system, it's a
> language server, it's a refactoring tool. It will be more things in
> the future. You should imagine it being a separate program that you
> run alongside Emacs, not inside Emacs.

[0] https://github.com/emacs-elsa/Elsa/issues/218#issuecomment-1470421487

> Regards,
> Payas
>
> --



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-23 16:44 Andrea Corallo
@ 2023-05-24 10:46 ` Eli Zaretskii
  2023-05-24 12:19   ` Andrea Corallo
  0 siblings, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2023-05-24 10:46 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: emacs-devel

> From: Andrea Corallo <akrl@sdf.org>
> Date: Tue, 23 May 2023 16:44:08 +0000
> 
> foo is a native-compiled Lisp function in
> ‘~/.emacs.d/eln-cache/30.0.50-e29d76eb/test-a526a80f-5481bc95.eln’.

Why does it name the .eln file, not its source .el file?  Or is this
the case when there's no .el file?

> Signature: (foo N)
> 
> Inferred type: (function (t) (or (member to-small too-big) (integer
> 100 100)))

Can you explain what is this "Inferred type" information about?

> ATM I adds as well "Signature: " in front of the signature to
> differentiate it from the type.  But looking at it in restrospective it
> might be not even necessary.

We should probably preserve the current format of just showing the
signature without any headings.



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-24 10:46 ` Eli Zaretskii
@ 2023-05-24 12:19   ` Andrea Corallo
  2023-05-30 16:46     ` Andrea Corallo
  0 siblings, 1 reply; 26+ messages in thread
From: Andrea Corallo @ 2023-05-24 12:19 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Andrea Corallo <akrl@sdf.org>
>> Date: Tue, 23 May 2023 16:44:08 +0000
>> 
>> foo is a native-compiled Lisp function in
>> ‘~/.emacs.d/eln-cache/30.0.50-e29d76eb/test-a526a80f-5481bc95.eln’.
>
> Why does it name the .eln file, not its source .el file?  Or is this
> the case when there's no .el file?

I believe we show the .eln when this is loaded directly like (load
"xxx.eln"), IOW when we have no information on the original source.

>> Signature: (foo N)
>> 
>> Inferred type: (function (t) (or (member to-small too-big) (integer
>> 100 100)))
>
> Can you explain what is this "Inferred type" information about?

Sure, the native compiler in the attempt of optimizing the code is
propagating value type informations over the code being compiled.

The inferred type is formed using the arglist of the function (ATM is
not possible to specify types for arguments so they are all of type t)
and the return type.  The return type is nothing more than the union of
all types inferred by the compiler at the various return point of the
function.

At the time I wrote something about this here
<https://akrl.sdf.org/gccemacs.html#orge596749>.

Also for more about CL type specifiers
<https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node44.html>.

>> ATM I adds as well "Signature: " in front of the signature to
>> differentiate it from the type.  But looking at it in restrospective it
>> might be not even necessary.
>
> We should probably preserve the current format of just showing the
> signature without any headings.

Agreed.

Thanks

  Andrea



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-23 16:47 Inferred function types in the *Help* buffer Payas Relekar
  2023-05-23 18:51 ` Philip Kaludercic
@ 2023-05-24 12:20 ` Andrea Corallo
  1 sibling, 0 replies; 26+ messages in thread
From: Andrea Corallo @ 2023-05-24 12:20 UTC (permalink / raw)
  To: Payas Relekar; +Cc: emacs-devel

Payas Relekar <relekarpayas@gmail.com> writes:

> Andrea Corallo <akrl@sdf.org> writes:
>
>> ====
>> foo is a native-compiled Lisp function in
>> ‘~/.emacs.d/eln-cache/30.0.50-e29d76eb/test-a526a80f-5481bc95.eln’.
>>
>> Signature: (foo N)
>>
>> Inferred type: (function (t) (or (member to-small too-big) (integer
>> 100 100)))
>>
>> ...
>> ====
>
> Pretty cool.
>
> Tangentially, there's also Elsa: https://github.com/emacs-elsa/Elsa
>
> How feasible would you say it would be to integrate it within
> Emacs/native-compiler?

I think not very much, I guess way more feasible to do the opposite.

Best Regards

  Andrea



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-24 12:19   ` Andrea Corallo
@ 2023-05-30 16:46     ` Andrea Corallo
  2023-05-30 18:14       ` Mattias Engdegård
  2023-05-31 13:46       ` Eli Zaretskii
  0 siblings, 2 replies; 26+ messages in thread
From: Andrea Corallo @ 2023-05-30 16:46 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2609 bytes --]

Andrea Corallo <akrl@sdf.org> writes:

> Eli Zaretskii <eliz@gnu.org> writes:
>
>>> From: Andrea Corallo <akrl@sdf.org>
>>> Date: Tue, 23 May 2023 16:44:08 +0000
>>> 
>>> foo is a native-compiled Lisp function in
>>> ‘~/.emacs.d/eln-cache/30.0.50-e29d76eb/test-a526a80f-5481bc95.eln’.
>>
>> Why does it name the .eln file, not its source .el file?  Or is this
>> the case when there's no .el file?
>
> I believe we show the .eln when this is loaded directly like (load
> "xxx.eln"), IOW when we have no information on the original source.
>
>>> Signature: (foo N)
>>> 
>>> Inferred type: (function (t) (or (member to-small too-big) (integer
>>> 100 100)))
>>
>> Can you explain what is this "Inferred type" information about?
>
> Sure, the native compiler in the attempt of optimizing the code is
> propagating value type informations over the code being compiled.
>
> The inferred type is formed using the arglist of the function (ATM is
> not possible to specify types for arguments so they are all of type t)
> and the return type.  The return type is nothing more than the union of
> all types inferred by the compiler at the various return point of the
> function.
>
> At the time I wrote something about this here
> <https://akrl.sdf.org/gccemacs.html#orge596749>.
>
> Also for more about CL type specifiers
> <https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node44.html>.
>
>>> ATM I adds as well "Signature: " in front of the signature to
>>> differentiate it from the type.  But looking at it in restrospective it
>>> might be not even necessary.
>>
>> We should probably preserve the current format of just showing the
>> signature without any headings.
>
> Agreed.

Okay I installed ecc1d990d9e into master to implement this, please let
me know if the entry in NEWS can be improved or feel free to just do it
(I'm terrible at writing).

Also I'd like to improve this feature to list also the function types
that are known to the compiler (Read `comp-known-type-specifiers').  ATM
they lives in comp.el but would be better to move them out.

Ideally I think we should have a declare syntax and maybe an extention
to the DEFUN macro to cover for primitives as well, in order to have
these declaration where each function is defined.  But probably for now
something like the attached patch is sufficient and considerably less
invasive?

My main questions are: is subr-x.el the right place to move them in?  If
not which one?  Should be `comp-known-type-specifiers' be renamed into
something else or it's okay?

Thanks

  Andrea


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Print-know-function-types-in-C-h-f.patch --]
[-- Type: text/x-diff, Size: 35413 bytes --]

From 977046f8979b4f18f6be358a2d3d6aaefe5ffcd6 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <akrl@sdf.org>
Date: Tue, 30 May 2023 15:30:11 +0200
Subject: [PATCH] Print know function types in C-h f

* lisp/emacs-lisp/subr-x.el (comp-known-type-specifiers): Move to
subr-x.el.
* lisp/help-fns.el (help-fns--signature): Make use of
`comp-known-type-specifiers' for printing more function types.
---
 lisp/emacs-lisp/comp.el   | 317 +-------------------------------------
 lisp/emacs-lisp/subr-x.el | 315 +++++++++++++++++++++++++++++++++++++
 lisp/help-fns.el          |  10 +-
 3 files changed, 322 insertions(+), 320 deletions(-)

diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index ec51f805c2b..6d9270ba0b7 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -275,322 +275,7 @@ comp-post-pass-hooks
 Useful to hook into pass checkers.")
 
 ;; FIXME this probably should not be here but... good for now.
-(defconst comp-known-type-specifiers
-  `(
-    ;; Functions we can trust not to be or if redefined should expose
-    ;; the same type.  Vast majority of these is either pure or
-    ;; primitive, the original list is the union of pure +
-    ;; side-effect-free-fns + side-effect-and-error-free-fns:
-    (% (function ((or number marker) (or number marker)) number))
-    (* (function (&rest (or number marker)) number))
-    (+ (function (&rest (or number marker)) number))
-    (- (function (&rest (or number marker)) number))
-    (/ (function ((or number marker) &rest (or number marker)) number))
-    (/= (function ((or number marker) (or number marker)) boolean))
-    (1+ (function ((or number marker)) number))
-    (1- (function ((or number marker)) number))
-    (< (function ((or number marker) &rest (or number marker)) boolean))
-    (<= (function ((or number marker) &rest (or number marker)) boolean))
-    (= (function ((or number marker) &rest (or number marker)) boolean))
-    (> (function ((or number marker) &rest (or number marker)) boolean))
-    (>= (function ((or number marker) &rest (or number marker)) boolean))
-    (abs (function (number) number))
-    (acos (function (number) float))
-    (append (function (&rest t) t))
-    (aref (function (t fixnum) t))
-    (arrayp (function (t) boolean))
-    (ash (function (integer integer) integer))
-    (asin (function (number) float))
-    (assq (function (t list) list))
-    (atan (function (number &optional number) float))
-    (atom (function (t) boolean))
-    (bignump (function (t) boolean))
-    (bobp (function () boolean))
-    (bolp (function () boolean))
-    (bool-vector-count-consecutive (function (bool-vector boolean integer) fixnum))
-    (bool-vector-count-population (function (bool-vector) fixnum))
-    (bool-vector-not (function (bool-vector &optional bool-vector) bool-vector))
-    (bool-vector-p (function (t) boolean))
-    (bool-vector-subsetp (function (bool-vector bool-vector) boolean))
-    (boundp (function (symbol) boolean))
-    (buffer-end (function ((or number marker)) integer))
-    (buffer-file-name (function (&optional buffer) (or string null)))
-    (buffer-list (function (&optional frame) list))
-    (buffer-local-variables (function (&optional buffer) list))
-    (buffer-modified-p (function (&optional buffer) boolean))
-    (buffer-size (function (&optional buffer) integer))
-    (buffer-string (function () string))
-    (buffer-substring (function ((or integer marker) (or integer marker)) string))
-    (bufferp (function (t) boolean))
-    (byte-code-function-p (function (t) boolean))
-    (capitalize (function (or integer string) (or integer string)))
-    (car (function (list) t))
-    (car-less-than-car (function (list list) boolean))
-    (car-safe (function (t) t))
-    (case-table-p (function (t) boolean))
-    (cdr (function (list) t))
-    (cdr-safe (function (t) t))
-    (ceiling (function (number &optional number) integer))
-    (char-after (function (&optional (or marker integer)) (or fixnum null)))
-    (char-before (function (&optional (or marker integer)) (or fixnum null)))
-    (char-equal (function (integer integer) boolean))
-    (char-or-string-p (function (t) boolean))
-    (char-to-string (function (fixnum) string))
-    (char-width (function (fixnum) fixnum))
-    (characterp (function (t &optional t) boolean))
-    (charsetp (function (t) boolean))
-    (commandp (function (t &optional t) boolean))
-    (compare-strings (function (string (or integer marker null) (or integer marker null) string (or integer marker null) (or integer marker null) &optional t) (or (member t) fixnum)))
-    (concat (function (&rest sequence) string))
-    (cons (function (t t) cons))
-    (consp (function (t) boolean))
-    (coordinates-in-window-p (function (cons window) boolean))
-    (copy-alist (function (list) list))
-    (copy-marker (function (&optional (or integer marker) boolean) marker))
-    (copy-sequence (function (sequence) sequence))
-    (copysign (function (float float) float))
-    (cos (function (number) float))
-    (count-lines (function ((or integer marker) (or integer marker) &optional t) integer))
-    (current-buffer (function () buffer))
-    (current-global-map (function () cons))
-    (current-indentation (function () integer))
-    (current-local-map (function () (or cons null)))
-    (current-minor-mode-maps (function () (or cons null)))
-    (current-time (function () cons))
-    (current-time-string (function (&optional (or number list)
-                                              (or symbol string cons integer))
-                                   string))
-    (current-time-zone (function (&optional (or number list)
-                                            (or symbol string cons integer))
-                                 cons))
-    (custom-variable-p (function (symbol) boolean))
-    (decode-char (function (cons t) (or fixnum null)))
-    (decode-time (function (&optional (or number list)
-                                      (or symbol string cons integer)
-                                      symbol)
-                           cons))
-    (default-boundp (function (symbol) boolean))
-    (default-value (function (symbol) t))
-    (degrees-to-radians (function (number) float))
-    (documentation (function ((or function symbol subr) &optional t) (or null string)))
-    (downcase (function ((or fixnum string)) (or fixnum string)))
-    (elt (function (sequence integer) t))
-    (encode-char (function (fixnum symbol) (or fixnum null)))
-    (encode-time (function (cons &rest t) cons))
-    (eobp (function () boolean))
-    (eolp (function () boolean))
-    (eq (function (t t) boolean))
-    (eql (function (t t) boolean))
-    (equal (function (t t) boolean))
-    (error-message-string (function (list) string))
-    (eventp (function (t) boolean))
-    (exp (function (number) float))
-    (expt (function (number number) float))
-    (fboundp (function (symbol) boolean))
-    (fceiling (function (float) float))
-    (featurep (function (symbol &optional symbol) boolean))
-    (ffloor (function (float) float))
-    (file-directory-p (function (string) boolean))
-    (file-exists-p (function (string) boolean))
-    (file-locked-p (function (string) boolean))
-    (file-name-absolute-p (function (string) boolean))
-    (file-newer-than-file-p (function (string string) boolean))
-    (file-readable-p (function (string) boolean))
-    (file-symlink-p (function (string) boolean))
-    (file-writable-p (function (string) boolean))
-    (fixnump (function (t) boolean))
-    (float (function (number) float))
-    (float-time (function (&optional (or number list)) float))
-    (floatp (function (t) boolean))
-    (floor (function (number &optional number) integer))
-    (following-char (function () fixnum))
-    (format (function (string &rest t) string))
-    (format-time-string (function (string &optional (or number list)
-                                          (or symbol string cons integer))
-                                  string))
-    (frame-first-window (function ((or frame window)) window))
-    (frame-root-window (function (&optional (or frame window)) window))
-    (frame-selected-window (function (&optional (or frame window)) window))
-    (frame-visible-p (function (frame) boolean))
-    (framep (function (t) boolean))
-    (fround (function (float) float))
-    (ftruncate (function (float) float))
-    (get (function (symbol symbol) t))
-    (get-buffer (function ((or buffer string)) (or buffer null)))
-    (get-buffer-window (function (&optional (or buffer string) (or symbol (integer 0 0))) (or null window)))
-    (get-file-buffer (function (string) (or null buffer)))
-    (get-largest-window (function (&optional t t t) (or window null)))
-    (get-lru-window (function (&optional t t t) (or window null)))
-    (getenv (function (string &optional frame) (or null string)))
-    (gethash (function (t hash-table &optional t) t))
-    (hash-table-count (function (hash-table) integer))
-    (hash-table-p (function (t) boolean))
-    (identity (function (t) t))
-    (ignore (function (&rest t) null))
-    (int-to-string (function (number) string))
-    (integer-or-marker-p (function (t) boolean))
-    (integerp (function (t) boolean))
-    (interactive-p (function () boolean))
-    (intern-soft (function ((or string symbol) &optional vector) symbol))
-    (invocation-directory (function () string))
-    (invocation-name (function () string))
-    (isnan (function (float) boolean))
-    (keymap-parent (function (cons) (or cons null)))
-    (keymapp (function (t) boolean))
-    (keywordp (function (t) boolean))
-    (last (function (list &optional integer) list))
-    (lax-plist-get (function (list t) t))
-    (ldexp (function (number integer) float))
-    (length (function (t) (integer 0 *)))
-    (length< (function (sequence fixnum) boolean))
-    (length= (function (sequence fixnum) boolean))
-    (length> (function (sequence fixnum) boolean))
-    (line-beginning-position (function (&optional integer) integer))
-    (line-end-position (function (&optional integer) integer))
-    (list (function (&rest t) list))
-    (listp (function (t) boolean))
-    (local-variable-if-set-p (function (symbol &optional buffer) boolean))
-    (local-variable-p (function (symbol &optional buffer) boolean))
-    (locale-info (function ((member codeset days months paper)) (or null string)))
-    (log (function (number number) float))
-    (log10 (function (number) float))
-    (logand (function (&rest (or integer marker)) integer))
-    (logb (function (number) integer))
-    (logcount (function (integer) integer))
-    (logior (function (&rest (or integer marker)) integer))
-    (lognot (function (integer) integer))
-    (logxor (function (&rest (or integer marker)) integer))
-    ;; (lsh (function ((integer ,most-negative-fixnum *) integer) integer)) ?
-    (lsh (function (integer integer) integer))
-    (make-byte-code (function ((or fixnum list) string vector integer &optional string t &rest t) vector))
-    (make-list (function (integer t) list))
-    (make-marker (function () marker))
-    (make-string (function (integer fixnum &optional t) string))
-    (make-symbol (function (string) symbol))
-    (mark (function (&optional t) (or integer null)))
-    (mark-marker (function () marker))
-    (marker-buffer (function (marker) (or buffer null)))
-    (markerp (function (t) boolean))
-    (max (function ((or number marker) &rest (or number marker)) number))
-    (max-char (function (&optional t) fixnum))
-    (member (function (t list) list))
-    (memory-limit (function () integer))
-    (memq (function (t list) list))
-    (memql (function (t list) list))
-    (min (function ((or number marker) &rest (or number marker)) number))
-    (minibuffer-selected-window (function () (or window null)))
-    (minibuffer-window (function (&optional frame) window))
-    (mod (function ((or number marker) (or number marker)) (or (integer 0 *) (float 0 *))))
-    (mouse-movement-p (function (t) boolean))
-    (multibyte-char-to-unibyte (function (fixnum) fixnum))
-    (natnump (function (t) boolean))
-    (next-window (function (&optional window t t) window))
-    (nlistp (function (t) boolean))
-    (not (function (t) boolean))
-    (nth (function (integer list) t))
-    (nthcdr (function (integer t) t))
-    (null (function (t) boolean))
-    (number-or-marker-p (function (t) boolean))
-    (number-to-string (function (number) string))
-    (numberp (function (t) boolean))
-    (one-window-p (function (&optional t t) boolean))
-    (overlayp (function (t) boolean))
-    (parse-colon-path (function (string) cons))
-    (plist-get (function (list t &optional t) t))
-    (plist-member (function (list t &optional t) list))
-    (point (function () integer))
-    (point-marker (function () marker))
-    (point-max (function () integer))
-    (point-min (function () integer))
-    (preceding-char (function () fixnum))
-    (previous-window (function (&optional window t t) window))
-    (prin1-to-string (function (t &optional t t) string))
-    (processp (function (t) boolean))
-    (proper-list-p (function (t) boolean))
-    (propertize (function (string &rest t) string))
-    (radians-to-degrees (function (number) float))
-    (rassoc (function (t list) list))
-    (rassq (function (t list) list))
-    (read-from-string (function (string &optional integer integer) cons))
-    (recent-keys (function (&optional (or cons null)) vector))
-    (recursion-depth (function () integer))
-    (regexp-opt (function (list) string))
-    (regexp-quote (function (string) string))
-    (region-beginning (function () integer))
-    (region-end (function () integer))
-    (reverse (function (sequence) sequence))
-    (round (function (number &optional number) integer))
-    (safe-length (function (t) integer))
-    (selected-frame (function () frame))
-    (selected-window (function () window))
-    (sequencep (function (t) boolean))
-    (sin (function (number) float))
-    (sqrt (function (number) float))
-    (standard-case-table (function () char-table))
-    (standard-syntax-table (function () char-table))
-    (string (function (&rest fixnum) string))
-    (string-as-multibyte (function (string) string))
-    (string-as-unibyte (function (string) string))
-    (string-equal (function ((or string symbol) (or string symbol)) boolean))
-    (string-lessp (function ((or string symbol) (or string symbol)) boolean))
-    (string-make-multibyte (function (string) string))
-    (string-make-unibyte (function (string) string))
-    (string-search (function (string string &optional integer) (or integer null)))
-    (string-to-char (function (string) fixnum))
-    (string-to-multibyte (function (string) string))
-    (string-to-number (function (string &optional integer) number))
-    (string-to-syntax (function (string) (or cons null)))
-    (string< (function ((or string symbol) (or string symbol)) boolean))
-    (string= (function ((or string symbol) (or string symbol)) boolean))
-    (stringp (function (t) boolean))
-    (subrp (function (t) boolean))
-    (substring (function ((or string vector) &optional integer integer) (or string vector)))
-    (sxhash (function (t) integer))
-    (sxhash-eq (function (t) integer))
-    (sxhash-eql (function (t) integer))
-    (sxhash-equal (function (t) integer))
-    (symbol-function (function (symbol) t))
-    (symbol-name (function (symbol) string))
-    (symbol-plist (function (symbol) list))
-    (symbol-value (function (symbol) t))
-    (symbolp (function (t) boolean))
-    (syntax-table (function () char-table))
-    (syntax-table-p (function (t) boolean))
-    (tan (function (number) float))
-    (this-command-keys (function () string))
-    (this-command-keys-vector (function () vector))
-    (this-single-command-keys (function () vector))
-    (this-single-command-raw-keys (function () vector))
-    (time-convert (function ((or number list) &optional (or symbol integer))
-                            (or cons number)))
-    (truncate (function (number &optional number) integer))
-    (type-of (function (t) symbol))
-    (unibyte-char-to-multibyte (function (fixnum) fixnum)) ;; byte is fixnum
-    (upcase (function ((or fixnum string)) (or fixnum string)))
-    (user-full-name (function (&optional integer) (or string null)))
-    (user-login-name (function (&optional integer) (or string null)))
-    (user-original-login-name (function (&optional integer) (or string null)))
-    (user-real-login-name (function () string))
-    (user-real-uid (function () integer))
-    (user-uid (function () integer))
-    (vconcat (function (&rest sequence) vector))
-    (vector (function (&rest t) vector))
-    (vectorp (function (t) boolean))
-    (visible-frame-list (function () list))
-    (wholenump (function (t) boolean))
-    (window-configuration-p (function (t) boolean))
-    (window-live-p (function (t) boolean))
-    (window-valid-p (function (t) boolean))
-    (windowp (function (t) boolean))
-    (zerop (function (number) boolean))
-    ;; Type hints
-    (comp-hint-fixnum (function (t) fixnum))
-    (comp-hint-cons (function (t) cons))
-    ;; Non returning functions
-    (throw (function (t t) nil))
-    (error (function (string &rest t) nil))
-    (signal (function (symbol t) nil)))
-  "Alist used for type propagation.")
+
 
 (defconst comp-known-func-cstr-h
   (cl-loop
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 9e906930b92..d9a32b950bb 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -37,6 +37,321 @@
 
 (eval-when-compile (require 'cl-lib))
 
+(defconst comp-known-type-specifiers
+  ;; Functions we can trust not to be redefined or if redefined should
+  ;; expose the same type.  The vast majority of these is either
+  ;; pure or primitive, the original list is the union of pure +
+  ;; side-effect-free-fns + side-effect-and-error-free-fns:
+  `((% (function ((or number marker) (or number marker)) number))
+    (* (function (&rest (or number marker)) number))
+    (+ (function (&rest (or number marker)) number))
+    (- (function (&rest (or number marker)) number))
+    (/ (function ((or number marker) &rest (or number marker)) number))
+    (/= (function ((or number marker) (or number marker)) boolean))
+    (1+ (function ((or number marker)) number))
+    (1- (function ((or number marker)) number))
+    (< (function ((or number marker) &rest (or number marker)) boolean))
+    (<= (function ((or number marker) &rest (or number marker)) boolean))
+    (= (function ((or number marker) &rest (or number marker)) boolean))
+    (> (function ((or number marker) &rest (or number marker)) boolean))
+    (>= (function ((or number marker) &rest (or number marker)) boolean))
+    (abs (function (number) number))
+    (acos (function (number) float))
+    (append (function (&rest t) t))
+    (aref (function (t fixnum) t))
+    (arrayp (function (t) boolean))
+    (ash (function (integer integer) integer))
+    (asin (function (number) float))
+    (assq (function (t list) list))
+    (atan (function (number &optional number) float))
+    (atom (function (t) boolean))
+    (bignump (function (t) boolean))
+    (bobp (function () boolean))
+    (bolp (function () boolean))
+    (bool-vector-count-consecutive (function (bool-vector boolean integer) fixnum))
+    (bool-vector-count-population (function (bool-vector) fixnum))
+    (bool-vector-not (function (bool-vector &optional bool-vector) bool-vector))
+    (bool-vector-p (function (t) boolean))
+    (bool-vector-subsetp (function (bool-vector bool-vector) boolean))
+    (boundp (function (symbol) boolean))
+    (buffer-end (function ((or number marker)) integer))
+    (buffer-file-name (function (&optional buffer) (or string null)))
+    (buffer-list (function (&optional frame) list))
+    (buffer-local-variables (function (&optional buffer) list))
+    (buffer-modified-p (function (&optional buffer) boolean))
+    (buffer-size (function (&optional buffer) integer))
+    (buffer-string (function () string))
+    (buffer-substring (function ((or integer marker) (or integer marker)) string))
+    (bufferp (function (t) boolean))
+    (byte-code-function-p (function (t) boolean))
+    (capitalize (function (or integer string) (or integer string)))
+    (car (function (list) t))
+    (car-less-than-car (function (list list) boolean))
+    (car-safe (function (t) t))
+    (case-table-p (function (t) boolean))
+    (cdr (function (list) t))
+    (cdr-safe (function (t) t))
+    (ceiling (function (number &optional number) integer))
+    (char-after (function (&optional (or marker integer)) (or fixnum null)))
+    (char-before (function (&optional (or marker integer)) (or fixnum null)))
+    (char-equal (function (integer integer) boolean))
+    (char-or-string-p (function (t) boolean))
+    (char-to-string (function (fixnum) string))
+    (char-width (function (fixnum) fixnum))
+    (characterp (function (t &optional t) boolean))
+    (charsetp (function (t) boolean))
+    (commandp (function (t &optional t) boolean))
+    (compare-strings (function (string (or integer marker null) (or integer marker null) string (or integer marker null) (or integer marker null) &optional t) (or (member t) fixnum)))
+    (concat (function (&rest sequence) string))
+    (cons (function (t t) cons))
+    (consp (function (t) boolean))
+    (coordinates-in-window-p (function (cons window) boolean))
+    (copy-alist (function (list) list))
+    (copy-marker (function (&optional (or integer marker) boolean) marker))
+    (copy-sequence (function (sequence) sequence))
+    (copysign (function (float float) float))
+    (cos (function (number) float))
+    (count-lines (function ((or integer marker) (or integer marker) &optional t) integer))
+    (current-buffer (function () buffer))
+    (current-global-map (function () cons))
+    (current-indentation (function () integer))
+    (current-local-map (function () (or cons null)))
+    (current-minor-mode-maps (function () (or cons null)))
+    (current-time (function () cons))
+    (current-time-string (function (&optional (or number list)
+                                              (or symbol string cons integer))
+                                   string))
+    (current-time-zone (function (&optional (or number list)
+                                            (or symbol string cons integer))
+                                 cons))
+    (custom-variable-p (function (symbol) boolean))
+    (decode-char (function (cons t) (or fixnum null)))
+    (decode-time (function (&optional (or number list)
+                                      (or symbol string cons integer)
+                                      symbol)
+                           cons))
+    (default-boundp (function (symbol) boolean))
+    (default-value (function (symbol) t))
+    (degrees-to-radians (function (number) float))
+    (documentation (function ((or function symbol subr) &optional t) (or null string)))
+    (downcase (function ((or fixnum string)) (or fixnum string)))
+    (elt (function (sequence integer) t))
+    (encode-char (function (fixnum symbol) (or fixnum null)))
+    (encode-time (function (cons &rest t) cons))
+    (eobp (function () boolean))
+    (eolp (function () boolean))
+    (eq (function (t t) boolean))
+    (eql (function (t t) boolean))
+    (equal (function (t t) boolean))
+    (error-message-string (function (list) string))
+    (eventp (function (t) boolean))
+    (exp (function (number) float))
+    (expt (function (number number) float))
+    (fboundp (function (symbol) boolean))
+    (fceiling (function (float) float))
+    (featurep (function (symbol &optional symbol) boolean))
+    (ffloor (function (float) float))
+    (file-directory-p (function (string) boolean))
+    (file-exists-p (function (string) boolean))
+    (file-locked-p (function (string) boolean))
+    (file-name-absolute-p (function (string) boolean))
+    (file-newer-than-file-p (function (string string) boolean))
+    (file-readable-p (function (string) boolean))
+    (file-symlink-p (function (string) boolean))
+    (file-writable-p (function (string) boolean))
+    (fixnump (function (t) boolean))
+    (float (function (number) float))
+    (float-time (function (&optional (or number list)) float))
+    (floatp (function (t) boolean))
+    (floor (function (number &optional number) integer))
+    (following-char (function () fixnum))
+    (format (function (string &rest t) string))
+    (format-time-string (function (string &optional (or number list)
+                                          (or symbol string cons integer))
+                                  string))
+    (frame-first-window (function ((or frame window)) window))
+    (frame-root-window (function (&optional (or frame window)) window))
+    (frame-selected-window (function (&optional (or frame window)) window))
+    (frame-visible-p (function (frame) boolean))
+    (framep (function (t) boolean))
+    (fround (function (float) float))
+    (ftruncate (function (float) float))
+    (get (function (symbol symbol) t))
+    (get-buffer (function ((or buffer string)) (or buffer null)))
+    (get-buffer-window (function (&optional (or buffer string) (or symbol (integer 0 0))) (or null window)))
+    (get-file-buffer (function (string) (or null buffer)))
+    (get-largest-window (function (&optional t t t) (or window null)))
+    (get-lru-window (function (&optional t t t) (or window null)))
+    (getenv (function (string &optional frame) (or null string)))
+    (gethash (function (t hash-table &optional t) t))
+    (hash-table-count (function (hash-table) integer))
+    (hash-table-p (function (t) boolean))
+    (identity (function (t) t))
+    (ignore (function (&rest t) null))
+    (int-to-string (function (number) string))
+    (integer-or-marker-p (function (t) boolean))
+    (integerp (function (t) boolean))
+    (interactive-p (function () boolean))
+    (intern-soft (function ((or string symbol) &optional vector) symbol))
+    (invocation-directory (function () string))
+    (invocation-name (function () string))
+    (isnan (function (float) boolean))
+    (keymap-parent (function (cons) (or cons null)))
+    (keymapp (function (t) boolean))
+    (keywordp (function (t) boolean))
+    (last (function (list &optional integer) list))
+    (lax-plist-get (function (list t) t))
+    (ldexp (function (number integer) float))
+    (length (function (t) (integer 0 *)))
+    (length< (function (sequence fixnum) boolean))
+    (length= (function (sequence fixnum) boolean))
+    (length> (function (sequence fixnum) boolean))
+    (line-beginning-position (function (&optional integer) integer))
+    (line-end-position (function (&optional integer) integer))
+    (list (function (&rest t) list))
+    (listp (function (t) boolean))
+    (local-variable-if-set-p (function (symbol &optional buffer) boolean))
+    (local-variable-p (function (symbol &optional buffer) boolean))
+    (locale-info (function ((member codeset days months paper)) (or null string)))
+    (log (function (number number) float))
+    (log10 (function (number) float))
+    (logand (function (&rest (or integer marker)) integer))
+    (logb (function (number) integer))
+    (logcount (function (integer) integer))
+    (logior (function (&rest (or integer marker)) integer))
+    (lognot (function (integer) integer))
+    (logxor (function (&rest (or integer marker)) integer))
+    ;; (lsh (function ((integer ,most-negative-fixnum *) integer) integer)) ?
+    (lsh (function (integer integer) integer))
+    (make-byte-code (function ((or fixnum list) string vector integer &optional string t &rest t) vector))
+    (make-list (function (integer t) list))
+    (make-marker (function () marker))
+    (make-string (function (integer fixnum &optional t) string))
+    (make-symbol (function (string) symbol))
+    (mark (function (&optional t) (or integer null)))
+    (mark-marker (function () marker))
+    (marker-buffer (function (marker) (or buffer null)))
+    (markerp (function (t) boolean))
+    (max (function ((or number marker) &rest (or number marker)) number))
+    (max-char (function (&optional t) fixnum))
+    (member (function (t list) list))
+    (memory-limit (function () integer))
+    (memq (function (t list) list))
+    (memql (function (t list) list))
+    (min (function ((or number marker) &rest (or number marker)) number))
+    (minibuffer-selected-window (function () (or window null)))
+    (minibuffer-window (function (&optional frame) window))
+    (mod (function ((or number marker) (or number marker)) (or (integer 0 *) (float 0 *))))
+    (mouse-movement-p (function (t) boolean))
+    (multibyte-char-to-unibyte (function (fixnum) fixnum))
+    (natnump (function (t) boolean))
+    (next-window (function (&optional window t t) window))
+    (nlistp (function (t) boolean))
+    (not (function (t) boolean))
+    (nth (function (integer list) t))
+    (nthcdr (function (integer t) t))
+    (null (function (t) boolean))
+    (number-or-marker-p (function (t) boolean))
+    (number-to-string (function (number) string))
+    (numberp (function (t) boolean))
+    (one-window-p (function (&optional t t) boolean))
+    (overlayp (function (t) boolean))
+    (parse-colon-path (function (string) cons))
+    (plist-get (function (list t &optional t) t))
+    (plist-member (function (list t &optional t) list))
+    (point (function () integer))
+    (point-marker (function () marker))
+    (point-max (function () integer))
+    (point-min (function () integer))
+    (preceding-char (function () fixnum))
+    (previous-window (function (&optional window t t) window))
+    (prin1-to-string (function (t &optional t t) string))
+    (processp (function (t) boolean))
+    (proper-list-p (function (t) boolean))
+    (propertize (function (string &rest t) string))
+    (radians-to-degrees (function (number) float))
+    (rassoc (function (t list) list))
+    (rassq (function (t list) list))
+    (read-from-string (function (string &optional integer integer) cons))
+    (recent-keys (function (&optional (or cons null)) vector))
+    (recursion-depth (function () integer))
+    (regexp-opt (function (list) string))
+    (regexp-quote (function (string) string))
+    (region-beginning (function () integer))
+    (region-end (function () integer))
+    (reverse (function (sequence) sequence))
+    (round (function (number &optional number) integer))
+    (safe-length (function (t) integer))
+    (selected-frame (function () frame))
+    (selected-window (function () window))
+    (sequencep (function (t) boolean))
+    (sin (function (number) float))
+    (sqrt (function (number) float))
+    (standard-case-table (function () char-table))
+    (standard-syntax-table (function () char-table))
+    (string (function (&rest fixnum) string))
+    (string-as-multibyte (function (string) string))
+    (string-as-unibyte (function (string) string))
+    (string-equal (function ((or string symbol) (or string symbol)) boolean))
+    (string-lessp (function ((or string symbol) (or string symbol)) boolean))
+    (string-make-multibyte (function (string) string))
+    (string-make-unibyte (function (string) string))
+    (string-search (function (string string &optional integer) (or integer null)))
+    (string-to-char (function (string) fixnum))
+    (string-to-multibyte (function (string) string))
+    (string-to-number (function (string &optional integer) number))
+    (string-to-syntax (function (string) (or cons null)))
+    (string< (function ((or string symbol) (or string symbol)) boolean))
+    (string= (function ((or string symbol) (or string symbol)) boolean))
+    (stringp (function (t) boolean))
+    (subrp (function (t) boolean))
+    (substring (function ((or string vector) &optional integer integer) (or string vector)))
+    (sxhash (function (t) integer))
+    (sxhash-eq (function (t) integer))
+    (sxhash-eql (function (t) integer))
+    (sxhash-equal (function (t) integer))
+    (symbol-function (function (symbol) t))
+    (symbol-name (function (symbol) string))
+    (symbol-plist (function (symbol) list))
+    (symbol-value (function (symbol) t))
+    (symbolp (function (t) boolean))
+    (syntax-table (function () char-table))
+    (syntax-table-p (function (t) boolean))
+    (tan (function (number) float))
+    (this-command-keys (function () string))
+    (this-command-keys-vector (function () vector))
+    (this-single-command-keys (function () vector))
+    (this-single-command-raw-keys (function () vector))
+    (time-convert (function ((or number list) &optional (or symbol integer))
+                            (or cons number)))
+    (truncate (function (number &optional number) integer))
+    (type-of (function (t) symbol))
+    (unibyte-char-to-multibyte (function (fixnum) fixnum)) ;; byte is fixnum
+    (upcase (function ((or fixnum string)) (or fixnum string)))
+    (user-full-name (function (&optional integer) (or string null)))
+    (user-login-name (function (&optional integer) (or string null)))
+    (user-original-login-name (function (&optional integer) (or string null)))
+    (user-real-login-name (function () string))
+    (user-real-uid (function () integer))
+    (user-uid (function () integer))
+    (vconcat (function (&rest sequence) vector))
+    (vector (function (&rest t) vector))
+    (vectorp (function (t) boolean))
+    (visible-frame-list (function () list))
+    (wholenump (function (t) boolean))
+    (window-configuration-p (function (t) boolean))
+    (window-live-p (function (t) boolean))
+    (window-valid-p (function (t) boolean))
+    (windowp (function (t) boolean))
+    (zerop (function (number) boolean))
+    ;; Type hints
+    (comp-hint-fixnum (function (t) fixnum))
+    (comp-hint-cons (function (t) cons))
+    ;; Non returning functions
+    (throw (function (t t) nil))
+    (error (function (string &rest t) nil))
+    (signal (function (symbol t) nil)))
+  "Alist used for type propagation.")
 
 (defmacro internal--thread-argument (first? &rest forms)
   "Internal implementation for `thread-first' and `thread-last'.
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index c4e09e48bea..af1c37f2d86 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -711,10 +711,12 @@ help-fns--signature
           (unless (and (symbolp function)
                        (get function 'reader-construct))
             (insert high-usage "\n")
-            (when (and (featurep 'native-compile)
-                       (subr-native-elisp-p (symbol-function function))
-                       (subr-type (symbol-function function)))
-              (insert (format "\nInferred type: %s\n" (subr-type (symbol-function function))))))
+            (if-let ((entry (assoc function comp-known-type-specifiers)))
+                (insert (format "\nType: %s\n" (car (cdr entry))))
+              (when (and (featurep 'native-compile)
+                         (subr-native-elisp-p (symbol-function function))
+                         (subr-type (symbol-function function)))
+                (insert (format "\nInferred type: %s\n" (subr-type (symbol-function function)))))))
           (fill-region fill-begin (point))
           high-doc)))))
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-30 16:46     ` Andrea Corallo
@ 2023-05-30 18:14       ` Mattias Engdegård
  2023-05-30 18:48         ` Andrea Corallo
  2023-05-31 13:46       ` Eli Zaretskii
  1 sibling, 1 reply; 26+ messages in thread
From: Mattias Engdegård @ 2023-05-30 18:14 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

30 maj 2023 kl. 18.46 skrev Andrea Corallo <acorallo@gnu.org>:

> Ideally I think we should have a declare syntax and maybe an extention
> to the DEFUN macro to cover for primitives as well, in order to have
> these declaration where each function is defined.

That would probably be a good thing in the long run, yes. There are other declarations we would like to be able to attach to DEFUN as well.

>  But probably for now
> something like the attached patch is sufficient and considerably less
> invasive?

Actually it sort of increases coupling; I'd rather it stayed in comp.el for the time being. You could write a function (in comp.el) for access. (Maybe comp.el should adopt the double-dash naming convention more as well.)

The data could be useful for the byte-compiler, too, but for that we would first need to agree on exact definitions of the types to prevent any misunderstanding. It would also need more scrutiny if code using it for other purposes depend on it.




^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-30 18:14       ` Mattias Engdegård
@ 2023-05-30 18:48         ` Andrea Corallo
  2023-05-31 12:19           ` Andrea Corallo
  0 siblings, 1 reply; 26+ messages in thread
From: Andrea Corallo @ 2023-05-30 18:48 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

Mattias Engdegård <mattias.engdegard@gmail.com> writes:

> 30 maj 2023 kl. 18.46 skrev Andrea Corallo <acorallo@gnu.org>:
>
>> Ideally I think we should have a declare syntax and maybe an extention
>> to the DEFUN macro to cover for primitives as well, in order to have
>> these declaration where each function is defined.
>
> That would probably be a good thing in the long run, yes. There are other declarations we would like to be able to attach to DEFUN as well.

Hi Mattias,

thanks for your feedback.

yep agree, I think we should convey on a syntax for everything we want
to express (type and other properties), so we have something to
implement on the long run both for the Lisp both for the C side.

>>  But probably for now
>> something like the attached patch is sufficient and considerably less
>> invasive?
>
> Actually it sort of increases coupling; I'd rather it stayed in
> comp.el for the time being. You could write a function (in comp.el)
> for access.

The main reason why I'd like to move them out is not to require the load
of comp.el for a simple C-h f.  Secondary yeah I think that if it's in
use outside the compilation functionality should just not live there.

Anyway I'm happy with any solution (as long as we find one :).

Thanks

  Andrea



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-30 18:48         ` Andrea Corallo
@ 2023-05-31 12:19           ` Andrea Corallo
  2023-05-31 14:08             ` Eli Zaretskii
  2023-06-01 11:28             ` Mattias Engdegård
  0 siblings, 2 replies; 26+ messages in thread
From: Andrea Corallo @ 2023-05-31 12:19 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

Andrea Corallo <acorallo@gnu.org> writes:

> Mattias Engdegård <mattias.engdegard@gmail.com> writes:
>
>> 30 maj 2023 kl. 18.46 skrev Andrea Corallo <acorallo@gnu.org>:
>>
>>> Ideally I think we should have a declare syntax and maybe an extention
>>> to the DEFUN macro to cover for primitives as well, in order to have
>>> these declaration where each function is defined.
>>
>> That would probably be a good thing in the long run, yes. There are other declarations we would like to be able to attach to DEFUN as well.
>
> Hi Mattias,
>
> thanks for your feedback.
>
> yep agree, I think we should convey on a syntax for everything we want
> to express (type and other properties), so we have something to
> implement on the long run both for the Lisp both for the C side.
>
>>>  But probably for now
>>> something like the attached patch is sufficient and considerably less
>>> invasive?
>>
>> Actually it sort of increases coupling; I'd rather it stayed in
>> comp.el for the time being. You could write a function (in comp.el)
>> for access.
>
> The main reason why I'd like to move them out is not to require the load
> of comp.el for a simple C-h f.  Secondary yeah I think that if it's in
> use outside the compilation functionality should just not live there.

Thinking about more I can't see why we should force people to load
comp.el for a simple C-h f.  If this data is consumed by both comp.el
and help-fns.el it should stay in a commonly available place.

Moreover this functionality would be available to non native compiled
Emacsen as well, so forcing the load of comp.el feels to me even more
odd.

  Andrea



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-30 16:46     ` Andrea Corallo
  2023-05-30 18:14       ` Mattias Engdegård
@ 2023-05-31 13:46       ` Eli Zaretskii
  2023-06-01  8:42         ` Andrea Corallo
  1 sibling, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2023-05-31 13:46 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: akrl, emacs-devel

> From: Andrea Corallo <acorallo@gnu.org>
> Cc: Eli Zaretskii <eliz@gnu.org>,  emacs-devel@gnu.org
> Date: Tue, 30 May 2023 12:46:04 -0400
> 
> Okay I installed ecc1d990d9e into master to implement this, please let
> me know if the entry in NEWS can be improved or feel free to just do it
> (I'm terrible at writing).

The NEWS entry, viz.:

  ** Help
  ** 'describe-function' shows function inferred type when available.
  For native compiled Lisp functions 'describe-function' prints (after
  the signature) the automatically inferred function type as well.

Is IMO too terse.  "Inferred type" is terminology we didn't use and
don't explain the manual, so the above doesn't really tell what kind
of information is displayed.  We should give a hint, and perhaps have
more details in the ELisp manual, probably as part of documenting
subr-type.

> Also I'd like to improve this feature to list also the function types
> that are known to the compiler (Read `comp-known-type-specifiers').  ATM
> they lives in comp.el but would be better to move them out.

I don't necessarily see the reason.  We will probably move to having
native-compilation be the default, in which case comp.el will be
loaded in the majority of sessions quite soon after startup.  So it
doesn't make a lot of sense to try to move these out of comp.el.



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-31 12:19           ` Andrea Corallo
@ 2023-05-31 14:08             ` Eli Zaretskii
  2023-06-01 11:28             ` Mattias Engdegård
  1 sibling, 0 replies; 26+ messages in thread
From: Eli Zaretskii @ 2023-05-31 14:08 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: mattias.engdegard, akrl, emacs-devel

> From: Andrea Corallo <acorallo@gnu.org>
> Cc: Andrea Corallo <akrl@sdf.org>,  Eli Zaretskii <eliz@gnu.org>,
>   emacs-devel <emacs-devel@gnu.org>
> Date: Wed, 31 May 2023 08:19:31 -0400
> 
> Thinking about more I can't see why we should force people to load
> comp.el for a simple C-h f.

It happens more often than not anyway, because Help functions
frequently load packages to access documentation and other
information, and loading a package native-compiles it.

I wouldn't worry about loading comp.el too much.

> Moreover this functionality would be available to non native compiled
> Emacsen as well, so forcing the load of comp.el feels to me even more
> odd.

When this is available to non-NATIVE_COMP builds, it would maybe make
sense to split it in two, and have each part stored in a relevant
file, no?



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-31 13:46       ` Eli Zaretskii
@ 2023-06-01  8:42         ` Andrea Corallo
  2023-06-01  8:53           ` Eli Zaretskii
  0 siblings, 1 reply; 26+ messages in thread
From: Andrea Corallo @ 2023-06-01  8:42 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: akrl, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Andrea Corallo <acorallo@gnu.org>
>> Cc: Eli Zaretskii <eliz@gnu.org>,  emacs-devel@gnu.org
>> Date: Tue, 30 May 2023 12:46:04 -0400
>> 
>> Okay I installed ecc1d990d9e into master to implement this, please let
>> me know if the entry in NEWS can be improved or feel free to just do it
>> (I'm terrible at writing).
>
> The NEWS entry, viz.:
>
>   ** Help
>   ** 'describe-function' shows function inferred type when available.
>   For native compiled Lisp functions 'describe-function' prints (after
>   the signature) the automatically inferred function type as well.
>
> Is IMO too terse.  "Inferred type" is terminology we didn't use and
> don't explain the manual, so the above doesn't really tell what kind
> of information is displayed.  We should give a hint, and perhaps have
> more details in the ELisp manual, probably as part of documenting
> subr-type.

Okay, I think I need some advise on where to get started on this so this
weekend I can try to put some effort on.  Where should we add the
documentation for subr-type in the manual?

>> Also I'd like to improve this feature to list also the function types
>> that are known to the compiler (Read `comp-known-type-specifiers').  ATM
>> they lives in comp.el but would be better to move them out.
>
> I don't necessarily see the reason.  We will probably move to having
> native-compilation be the default, in which case comp.el will be
> loaded in the majority of sessions quite soon after startup.  So it
> doesn't make a lot of sense to try to move these out of comp.el.

Right, from this POV I get it.  Breaking comp.el in two I'm not sure
it's worth, as of now the only part that would be used outside is
actually comp-known-type-specifiers.

Thanks

  Andrea



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01  8:42         ` Andrea Corallo
@ 2023-06-01  8:53           ` Eli Zaretskii
  0 siblings, 0 replies; 26+ messages in thread
From: Eli Zaretskii @ 2023-06-01  8:53 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: akrl, emacs-devel

> From: Andrea Corallo <acorallo@gnu.org>
> Cc: akrl@sdf.org,  emacs-devel@gnu.org
> Date: Thu, 01 Jun 2023 04:42:03 -0400
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> >   ** Help
> >   ** 'describe-function' shows function inferred type when available.
> >   For native compiled Lisp functions 'describe-function' prints (after
> >   the signature) the automatically inferred function type as well.
> >
> > Is IMO too terse.  "Inferred type" is terminology we didn't use and
> > don't explain the manual, so the above doesn't really tell what kind
> > of information is displayed.  We should give a hint, and perhaps have
> > more details in the ELisp manual, probably as part of documenting
> > subr-type.
> 
> Okay, I think I need some advise on where to get started on this so this
> weekend I can try to put some effort on.  Where should we add the
> documentation for subr-type in the manual?

I think in "What Is a Function", where we document subrp and
subr-arity.

If you don't feel like writing the final text, complete with markup
and all, just post the raw text, and I will do the rest.

Thanks.



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-05-31 12:19           ` Andrea Corallo
  2023-05-31 14:08             ` Eli Zaretskii
@ 2023-06-01 11:28             ` Mattias Engdegård
  2023-06-01 11:35               ` Eli Zaretskii
  2023-06-01 11:50               ` Andrea Corallo
  1 sibling, 2 replies; 26+ messages in thread
From: Mattias Engdegård @ 2023-06-01 11:28 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

31 maj 2023 kl. 14.19 skrev Andrea Corallo <acorallo@gnu.org>:

>> The main reason why I'd like to move them out is not to require the load
>> of comp.el for a simple C-h f.  Secondary yeah I think that if it's in
>> use outside the compilation functionality should just not live there.
> 
> Thinking about more I can't see why we should force people to load
> comp.el for a simple C-h f.  If this data is consumed by both comp.el
> and help-fns.el it should stay in a commonly available place.

Let's use a separate file for the data then, rather than subr-x.el. That also keeps down the size of subr-x.el which is used very widely in practice. If the information is moved into function declarations then that new file will just go away.

Another concern is whether this information is useful to display in the help in the first place. The documentation should be authoritative; if the symbolic type is in conflict, actually or seemingly, the user will be confused.




^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 11:28             ` Mattias Engdegård
@ 2023-06-01 11:35               ` Eli Zaretskii
  2023-06-01 11:36                 ` Mattias Engdegård
  2023-06-01 11:50               ` Andrea Corallo
  1 sibling, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2023-06-01 11:35 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: acorallo, akrl, emacs-devel

> From: Mattias Engdegård <mattias.engdegard@gmail.com>
> Date: Thu, 1 Jun 2023 13:28:43 +0200
> Cc: Andrea Corallo <akrl@sdf.org>,
>  Eli Zaretskii <eliz@gnu.org>,
>  emacs-devel <emacs-devel@gnu.org>
> 
> 31 maj 2023 kl. 14.19 skrev Andrea Corallo <acorallo@gnu.org>:
> 
> >> The main reason why I'd like to move them out is not to require the load
> >> of comp.el for a simple C-h f.  Secondary yeah I think that if it's in
> >> use outside the compilation functionality should just not live there.
> > 
> > Thinking about more I can't see why we should force people to load
> > comp.el for a simple C-h f.  If this data is consumed by both comp.el
> > and help-fns.el it should stay in a commonly available place.
> 
> Let's use a separate file for the data then, rather than subr-x.el. That also keeps down the size of subr-x.el which is used very widely in practice. If the information is moved into function declarations then that new file will just go away.

I thought we all agreed to leave it in comp.el.

Why not?



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 11:35               ` Eli Zaretskii
@ 2023-06-01 11:36                 ` Mattias Engdegård
  2023-06-01 11:54                   ` Andrea Corallo
  0 siblings, 1 reply; 26+ messages in thread
From: Mattias Engdegård @ 2023-06-01 11:36 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: acorallo, akrl, emacs-devel

1 juni 2023 kl. 13.35 skrev Eli Zaretskii <eliz@gnu.org>:

> I thought we all agreed to leave it in comp.el.

That's completely fine, but I got the impression that Andrea didn't want that. Perhaps we are just talking past one another.




^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 11:28             ` Mattias Engdegård
  2023-06-01 11:35               ` Eli Zaretskii
@ 2023-06-01 11:50               ` Andrea Corallo
  2023-06-01 13:06                 ` Mattias Engdegård
  1 sibling, 1 reply; 26+ messages in thread
From: Andrea Corallo @ 2023-06-01 11:50 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

Mattias Engdegård <mattias.engdegard@gmail.com> writes:

> 31 maj 2023 kl. 14.19 skrev Andrea Corallo <acorallo@gnu.org>:
>
>>> The main reason why I'd like to move them out is not to require the load
>>> of comp.el for a simple C-h f.  Secondary yeah I think that if it's in
>>> use outside the compilation functionality should just not live there.
>> 
>> Thinking about more I can't see why we should force people to load
>> comp.el for a simple C-h f.  If this data is consumed by both comp.el
>> and help-fns.el it should stay in a commonly available place.
>
> Let's use a separate file for the data then, rather than
> subr-x.el. That also keeps down the size of subr-x.el which is used
> very widely in practice. If the information is moved into function
> declarations then that new file will just go away.
>
> Another concern is whether this information is useful to display in
> the help in the first place. The documentation should be
> authoritative; if the symbolic type is in conflict, actually or
> seemingly, the user will be confused.

Hi Mattias,

I'm not sure I understand this argument, if something will prove not to
be correct we'll just fix it as we do for everything else.  I don't
think sweeping something under the carpet will help us on the long term
anyway, I rather prefer exposing things and having a feedback in case
something is not optimal.

Best Regards

  Andrea



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 11:36                 ` Mattias Engdegård
@ 2023-06-01 11:54                   ` Andrea Corallo
  0 siblings, 0 replies; 26+ messages in thread
From: Andrea Corallo @ 2023-06-01 11:54 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: Eli Zaretskii, akrl, emacs-devel

Mattias Engdegård <mattias.engdegard@gmail.com> writes:

> 1 juni 2023 kl. 13.35 skrev Eli Zaretskii <eliz@gnu.org>:
>
>> I thought we all agreed to leave it in comp.el.
>
> That's completely fine, but I got the impression that Andrea didn't want that. Perhaps we are just talking past one another.

Yeah sorry, my fault, in light of this:

> I don't necessarily see the reason.  We will probably move to having
> native-compilation be the default, in which case comp.el will be
> loaded in the majority of sessions quite soon after startup.  So it
> doesn't make a lot of sense to try to move these out of comp.el.

I changed my mind and I'm fine also requiring everyone to load comp.el.
We can always change strategy afterwards if we see this is not optimal I
guess.

BR

  Andrea



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 11:50               ` Andrea Corallo
@ 2023-06-01 13:06                 ` Mattias Engdegård
  2023-06-01 13:34                   ` Andrea Corallo
  2023-06-01 14:09                   ` Andrea Corallo
  0 siblings, 2 replies; 26+ messages in thread
From: Mattias Engdegård @ 2023-06-01 13:06 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

1 juni 2023 kl. 13.50 skrev Andrea Corallo <acorallo@gnu.org>:

> if something will prove not to
> be correct we'll just fix it as we do for everything else.

I think the general idea is fine. What I meant was that some type specifications can be more of a hindrance than help, in the same way that we in some docstrings prefer to override the automatically generated argument signature -- for better precision, or to avoid confusing the user with technicalities or obsolete arguments.

There may also be a problem of inaccuracy, and here is a little anecdote. I needed a table of boolean functions that only return nil or t for the byte-compiler, so I tried to use comp-known-type-specifiers.

Either I misunderstood what a return value of `boolean` means, or that list is riddled with errors. The following functions are specified to return boolean in comp-known-type-specifiers but actually may return other values as well:

  proper-list-p
  buffer-modified-p
  coordinates-in-window-p
  custom-variable-p
  file-locked-p
  file-symlink-p
  frame-visible-p
  framep

and, since we have no guarantees about what file handlers actually return,

  file-directory-p
  file-exists-p
  file-newer-than-file-p
  file-readable-p
  file-writable-p

This is just from a quick survey of a small subset of comp-known-type-specifiers, which means that it is difficult to trust in its current state. It can all be corrected but it is slow and tedious work.




^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 13:06                 ` Mattias Engdegård
@ 2023-06-01 13:34                   ` Andrea Corallo
  2023-06-01 14:50                     ` Mattias Engdegård
  2023-06-01 14:09                   ` Andrea Corallo
  1 sibling, 1 reply; 26+ messages in thread
From: Andrea Corallo @ 2023-06-01 13:34 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

Mattias Engdegård <mattias.engdegard@gmail.com> writes:

> 1 juni 2023 kl. 13.50 skrev Andrea Corallo <acorallo@gnu.org>:
>
>> if something will prove not to
>> be correct we'll just fix it as we do for everything else.
>
> I think the general idea is fine. What I meant was that some type
> specifications can be more of a hindrance than help, in the same way
> that we in some docstrings prefer to override the automatically
> generated argument signature -- for better precision, or to avoid
> confusing the user with technicalities or obsolete arguments.

Are you suggesting we need some kind of override method for this?

> There may also be a problem of inaccuracy, and here is a little
> anecdote. I needed a table of boolean functions that only return nil
> or t for the byte-compiler, so I tried to use
> comp-known-type-specifiers.
>
> Either I misunderstood what a return value of `boolean` means, or that
> list is riddled with errors. The following functions are specified to
> return boolean in comp-known-type-specifiers but actually may return
> other values as well:
>
>   proper-list-p
>   buffer-modified-p
>   coordinates-in-window-p
>   custom-variable-p
>   file-locked-p
>   file-symlink-p
>   frame-visible-p
>   framep
>
> and, since we have no guarantees about what file handlers actually return,
>
>   file-directory-p
>   file-exists-p
>   file-newer-than-file-p
>   file-readable-p
>   file-writable-p

Again, if you've found these to be incorrect that's a bug we already
have in the code in use.  They had to be reported/looked into since
probably the time we noticed this inchoerence for the first time.

Best Regards

  Andrea



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 13:06                 ` Mattias Engdegård
  2023-06-01 13:34                   ` Andrea Corallo
@ 2023-06-01 14:09                   ` Andrea Corallo
  1 sibling, 0 replies; 26+ messages in thread
From: Andrea Corallo @ 2023-06-01 14:09 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 955 bytes --]

Mattias Engdegård <mattias.engdegard@gmail.com> writes:

[...]

> Either I misunderstood what a return value of `boolean` means, or that
> list is riddled with errors. The following functions are specified to
> return boolean in comp-known-type-specifiers but actually may return
> other values as well:
>
>   proper-list-p
>   buffer-modified-p
>   coordinates-in-window-p
>   custom-variable-p
>   file-locked-p
>   file-symlink-p
>   frame-visible-p
>   framep

Okay the attached should address these (please have a look if/when
you've time).

> and, since we have no guarantees about what file handlers actually return,
>
>   file-directory-p
>   file-exists-p
>   file-newer-than-file-p
>   file-readable-p
>   file-writable-p

Aren't the entries we have in agreement with the docstring?  If the
docstring is not in sync with the implementation we have either to fix
one o the other I think.

Thanks!

  Andrea


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-lisp-emacs-lisp-comp.el-comp-known-type-specifiers-F.patch --]
[-- Type: text/x-diff, Size: 3957 bytes --]

From 59383af6b309cd4f6b0340d7d1c8fd90ac71d569 Mon Sep 17 00:00:00 2001
From: Andrea Corallo <akrl@sdf.org>
Date: Thu, 1 Jun 2023 15:53:39 +0200
Subject: [PATCH] * lisp/emacs-lisp/comp.el (comp-known-type-specifiers): Fix a
 bunch of

---
 lisp/emacs-lisp/comp.el | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index b2704ae1446..d361b312a60 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -317,7 +317,7 @@ comp-known-type-specifiers
     (buffer-file-name (function (&optional buffer) (or string null)))
     (buffer-list (function (&optional frame) list))
     (buffer-local-variables (function (&optional buffer) list))
-    (buffer-modified-p (function (&optional buffer) boolean))
+    (buffer-modified-p (function (&optional buffer) (or boolean (member autosaved))))
     (buffer-size (function (&optional buffer) integer))
     (buffer-string (function () string))
     (buffer-substring (function ((or integer marker) (or integer marker)) string))
@@ -344,7 +344,7 @@ comp-known-type-specifiers
     (concat (function (&rest sequence) string))
     (cons (function (t t) cons))
     (consp (function (t) boolean))
-    (coordinates-in-window-p (function (cons window) boolean))
+    (coordinates-in-window-p (function (cons window) (or cons (member bottom-divider right-divider mode-line header-line tab-lineleft-fringeright-fringevertical-line left-margin right-margin))))
     (copy-alist (function (list) list))
     (copy-marker (function (&optional (or integer marker) boolean) marker))
     (copy-sequence (function (sequence) sequence))
@@ -363,7 +363,7 @@ comp-known-type-specifiers
     (current-time-zone (function (&optional (or number list)
                                             (or symbol string cons integer))
                                  cons))
-    (custom-variable-p (function (symbol) boolean))
+    (custom-variable-p (function (symbol) t))
     (decode-char (function (cons t) (or fixnum null)))
     (decode-time (function (&optional (or number list)
                                       (or symbol string cons integer)
@@ -392,11 +392,11 @@ comp-known-type-specifiers
     (ffloor (function (float) float))
     (file-directory-p (function (string) boolean))
     (file-exists-p (function (string) boolean))
-    (file-locked-p (function (string) boolean))
+    (file-locked-p (function (string) (or boolean string)))
     (file-name-absolute-p (function (string) boolean))
     (file-newer-than-file-p (function (string string) boolean))
     (file-readable-p (function (string) boolean))
-    (file-symlink-p (function (string) boolean))
+    (file-symlink-p (function (string) (or boolean string)))
     (file-writable-p (function (string) boolean))
     (fixnump (function (t) boolean))
     (float (function (number) float))
@@ -411,8 +411,8 @@ comp-known-type-specifiers
     (frame-first-window (function ((or frame window)) window))
     (frame-root-window (function (&optional (or frame window)) window))
     (frame-selected-window (function (&optional (or frame window)) window))
-    (frame-visible-p (function (frame) boolean))
-    (framep (function (t) boolean))
+    (frame-visible-p (function (frame) (or boolean (member icon))))
+    (framep (function (t) (or boolean (member x w32 ns pc pgtk haiku))))
     (fround (function (float) float))
     (ftruncate (function (float) float))
     (get (function (symbol symbol) t))
@@ -506,7 +506,7 @@ comp-known-type-specifiers
     (previous-window (function (&optional window t t) window))
     (prin1-to-string (function (t &optional t t) string))
     (processp (function (t) boolean))
-    (proper-list-p (function (t) boolean))
+    (proper-list-p (function (t) (or fixnum null)))
     (propertize (function (string &rest t) string))
     (radians-to-degrees (function (number) float))
     (rassoc (function (t list) list))
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 13:34                   ` Andrea Corallo
@ 2023-06-01 14:50                     ` Mattias Engdegård
  2023-06-01 15:10                       ` Andrea Corallo
  0 siblings, 1 reply; 26+ messages in thread
From: Mattias Engdegård @ 2023-06-01 14:50 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

1 juni 2023 kl. 15.34 skrev Andrea Corallo <acorallo@gnu.org>:

> Are you suggesting we need some kind of override method for this?

Maybe. It depends on what the purpose of showing the type in the help test is in the first place.

> Again, if you've found these to be incorrect that's a bug we already
> have in the code in use.  They had to be reported/looked into since
> probably the time we noticed this inchoerence for the first time.

Sorry, I originally assumed that I had misunderstood what the types meant and how they were used by the native compiler. After all, I cannot take it for granted that internals of code found elsewhere should be neatly arranged for my own purposes.

> Aren't the entries we have in agreement with the docstring?  If the
> docstring is not in sync with the implementation we have either to fix
> one o the other I think.

It's a policy problem: either we trust handlers to be implemented to spec or we distrust them just to be on the safe side. Normally we assume that users follow documented rules or suffer the consequences, but in this case it may not be the same user who writes the handler and who calls the function, so it may be fairer to shield the caller by normalising the return value of all handlers in these and other cases.

> -    (coordinates-in-window-p (function (cons window) boolean))
> +    (coordinates-in-window-p (function (cons window) (or cons (member bottom-divider right-divider mode-line header-line tab-lineleft-fringeright-fringevertical-line left-margin right-margin))))

Typos here (and null is missing).

> -    (framep (function (t) boolean))
> +    (framep (function (t) (or boolean (member x w32 ns pc pgtk haiku))))

This may be too fragile. Next port won't find this place to add its name.

Of course, if we manage to put these type declarations near the function definitions then accuracy would likely be better and maintenance easier (and more likely to take place at all).





^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 14:50                     ` Mattias Engdegård
@ 2023-06-01 15:10                       ` Andrea Corallo
  2023-06-01 17:53                         ` Mattias Engdegård
  0 siblings, 1 reply; 26+ messages in thread
From: Andrea Corallo @ 2023-06-01 15:10 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

Mattias Engdegård <mattias.engdegard@gmail.com> writes:

> 1 juni 2023 kl. 15.34 skrev Andrea Corallo <acorallo@gnu.org>:
>
>> Are you suggesting we need some kind of override method for this?
>
> Maybe. It depends on what the purpose of showing the type in the help test is in the first place.

It's just a very concise and effective way to express the input/output
value/types of the function.  I, for one, find it very useful.

>> Again, if you've found these to be incorrect that's a bug we already
>> have in the code in use.  They had to be reported/looked into since
>> probably the time we noticed this inchoerence for the first time.
>
> Sorry, I originally assumed that I had misunderstood what the types
> meant and how they were used by the native compiler. After all, I
> cannot take it for granted that internals of code found elsewhere
> should be neatly arranged for my own purposes.
>
>> Aren't the entries we have in agreement with the docstring?  If the
>> docstring is not in sync with the implementation we have either to fix
>> one o the other I think.
>
> It's a policy problem: either we trust handlers to be implemented to
> spec or we distrust them just to be on the safe side. Normally we
> assume that users follow documented rules or suffer the consequences,
> but in this case it may not be the same user who writes the handler
> and who calls the function, so it may be fairer to shield the caller
> by normalising the return value of all handlers in these and other
> cases.

If we distrust the handler either we should coerce the value to boolean
before returning it or either we should change the docstring.

>> -    (coordinates-in-window-p (function (cons window) boolean))
>> +    (coordinates-in-window-p (function (cons window) (or cons (member bottom-divider right-divider mode-line header-line tab-lineleft-fringeright-fringevertical-line left-margin right-margin))))
>
> Typos here (and null is missing).

Thanks

>> -    (framep (function (t) boolean))
>> +    (framep (function (t) (or boolean (member x w32 ns pc pgtk haiku))))
>
> This may be too fragile. Next port won't find this place to add its name.
>
> Of course, if we manage to put these type declarations near the function definitions then accuracy would likely be better and maintenance easier (and more likely to take place at all).

Yeah that's the general argument for that.  As metioned I guess this
should be a temporal solution anyway.

BTW I believe that most likely the next port value will be to added to
comp-known-type-specifiers only if we expose it into the help :)

Thanks

  Andrea



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 15:10                       ` Andrea Corallo
@ 2023-06-01 17:53                         ` Mattias Engdegård
  2023-06-01 19:13                           ` Andrea Corallo
  0 siblings, 1 reply; 26+ messages in thread
From: Mattias Engdegård @ 2023-06-01 17:53 UTC (permalink / raw)
  To: Andrea Corallo; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

1 juni 2023 kl. 17.10 skrev Andrea Corallo <acorallo@gnu.org>:

> It's just a very concise and effective way to express the input/output
> value/types of the function.  I, for one, find it very useful.

If we want to be as nice as possible to the user then perhaps we should massage the output a bit.
For instance, the `function` part is useless, and using the names of the arguments would be very helpful.

In other words, instead of describing `make-string` as

 (function (integer fixnum &optional t) string)

we could say something like

 LENGTH:integer INIT:fixnum MULTIBYTE -> string

(Not sure how practical it is, I'm just making this up.)

How concise are inferred types, for that matter? I can imagine them becoming pretty voluminous.

By the way, `expt` should have the return type `number`, not `float`. This is just something I noticed in passing; I haven't done any systematic review.




^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: Inferred function types in the *Help* buffer
  2023-06-01 17:53                         ` Mattias Engdegård
@ 2023-06-01 19:13                           ` Andrea Corallo
  0 siblings, 0 replies; 26+ messages in thread
From: Andrea Corallo @ 2023-06-01 19:13 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: Andrea Corallo, Eli Zaretskii, emacs-devel

Mattias Engdegård <mattias.engdegard@gmail.com> writes:

> 1 juni 2023 kl. 17.10 skrev Andrea Corallo <acorallo@gnu.org>:
>
>> It's just a very concise and effective way to express the input/output
>> value/types of the function.  I, for one, find it very useful.
>
> If we want to be as nice as possible to the user then perhaps we should massage the output a bit.
> For instance, the `function` part is useless, and using the names of the arguments would be very helpful.
>
> In other words, instead of describing `make-string` as
>
>  (function (integer fixnum &optional t) string)
>
> we could say something like
>
>  LENGTH:integer INIT:fixnum MULTIBYTE -> string
>
> (Not sure how practical it is, I'm just making this up.)

I see your point, I'm not sure how practical this is tho.  'function' is
there to say that the type specifier in object is describing a function.

This is important because a function is just a special kind of object,
and for instance we might have a function returning a function, this way
we can express it with something like:

(function () (function () t))

Another advantage of this notation is that being it borrowed by CL is
already well formalized [1] and deployed.

My opinion is that we might want to extend this in order to be able to
express properties of the functions we want (ex the ones we now have in
byte-opt.el).

> How concise are inferred types, for that matter? I can imagine them becoming pretty voluminous.

They are quite concise, due to the dynamic nature of Lisp the native
compiler can't predict in many cases the return type accurately if at
all.  As mentioned in my emacs -Q ~22% of the loaded functions gets a
non t return type, indeed we might improve in the future.

> By the way, `expt` should have the return type `number`, not `float`. This is just something I noticed in passing; I haven't done any systematic review.

Thanks, the fix is now in the patch.

Best Regards

  Andrea

[1] <http://www.lispworks.com/documentation/lw70/CLHS/Body/04_bc.htm>



^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2023-06-01 19:13 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-23 16:47 Inferred function types in the *Help* buffer Payas Relekar
2023-05-23 18:51 ` Philip Kaludercic
2023-05-24 12:20 ` Andrea Corallo
  -- strict thread matches above, loose matches on Subject: below --
2023-05-23 16:44 Andrea Corallo
2023-05-24 10:46 ` Eli Zaretskii
2023-05-24 12:19   ` Andrea Corallo
2023-05-30 16:46     ` Andrea Corallo
2023-05-30 18:14       ` Mattias Engdegård
2023-05-30 18:48         ` Andrea Corallo
2023-05-31 12:19           ` Andrea Corallo
2023-05-31 14:08             ` Eli Zaretskii
2023-06-01 11:28             ` Mattias Engdegård
2023-06-01 11:35               ` Eli Zaretskii
2023-06-01 11:36                 ` Mattias Engdegård
2023-06-01 11:54                   ` Andrea Corallo
2023-06-01 11:50               ` Andrea Corallo
2023-06-01 13:06                 ` Mattias Engdegård
2023-06-01 13:34                   ` Andrea Corallo
2023-06-01 14:50                     ` Mattias Engdegård
2023-06-01 15:10                       ` Andrea Corallo
2023-06-01 17:53                         ` Mattias Engdegård
2023-06-01 19:13                           ` Andrea Corallo
2023-06-01 14:09                   ` Andrea Corallo
2023-05-31 13:46       ` Eli Zaretskii
2023-06-01  8:42         ` Andrea Corallo
2023-06-01  8:53           ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).