Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flycheck reports 'the function ... is not known to be defined' for autoloaded elisp function. Why? #2063

Open
6 tasks done
ktetzlaff opened this issue Mar 7, 2024 · 7 comments

Comments

@ktetzlaff
Copy link

ktetzlaff commented Mar 7, 2024

Checklist

  • I have searched existing issues and StackOverflow for solutions.
  • I have read the [Flycheck manual][].
  • I have read the [Troubleshooting Guide][].
  • I have checked my issue has not been reported yet.

Problem description

Flycheck reports the function ... is not known to be defined for user defined, autoloaded elisp function. How do I get rid of this error?

Steps to reproduce

  1. Create new directory with the following 3 files:

test-flycheck-fn.el:

;; test-flycheck-fn.el --- helper -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:
(defun my-autoloaded-function (dummy)
  "Autoloaded function with a DUMMY arg."
  (interactive)
  (message "arg: %s" dummy))

(provide 'test-flycheck-fn)
;;; test-flycheck-fn.el ends here

test-flycheck-autoloads.el:

(autoload 'my-autoloaded-function "test-flycheck-fn" "\
Autoloaded function with a DUMMY arg.

(fn DUMMY)" t)

test-flycheck.el:

;; test-flycheck.el --- test flycheck autoloads -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:
(require 'package)
(setq package-user-dir (directory-file-name (file-name-directory load-file-name)))
(add-to-list 'load-path package-user-dir)
(package-initialize)
(package-install 'flycheck)

(require 'flycheck)
(setq flycheck-emacs-lisp-load-path 'inherit)
(flycheck-mode 1)

(load "test-flycheck-autoloads")
(my-autoloaded-function "test")

(find-file load-file-name)
(flycheck-compile 'emacs-lisp)
(provide 'test-flycheck)
;;; test-flycheck.el ends here
  1. start emacs: emacs -Q --load "<testdir>/test-flycheck.el"
  2. observe warning in compilation buffer: test-flycheck.el:15:2: Warning: the function ‘my-autoloaded-function’ is not known to be defined.

Expected behavior

No flycheck warning in step 3.

Screenshots

Screenshot showing the flycheck warning:
image

System configuration

Syntax checkers for buffer test-flycheck.el in emacs-lisp-mode:

First checker to run:

  emacs-lisp
    - may enable:    yes
    - may run:       t
    - executable:    Found at /usr/bin/emacs
    - next checkers: emacs-lisp-checkdoc

Checkers that may run as part of the first checker's chain:

  emacs-lisp-checkdoc
    - may enable: yes
    - executable: Found at /usr/bin/emacs

Flycheck Mode is enabled.  Use C-u C-c ! x to enable disabled
checkers.

--------------------

Flycheck version: 34.1
Emacs version:    29.1
System:           x86_64-pc-linux-gnu
Window system:    nil

Emacs configuration:

  • Plain Emacs

Additional notes

complete flycheck-compile output:

-*- mode: compilation; default-directory: "~/tmp/" -*-
Compilation started at Thu Mar  7 07:22:38

/usr/bin/emacs -Q --batch --directory /home/kail/tmp/flycheck-34.1 --directory /home/kail/tmp --directory /usr/share/emacs/29.1/lisp --directory /usr/share/emacs/29.1/lisp/vc --directory /usr/share/emacs/29.1/lisp/use-package --directory /usr/share/emacs/29.1/lisp/url --directory /usr/share/emacs/29.1/lisp/textmodes --directory /usr/share/emacs/29.1/lisp/progmodes --directory /usr/share/emacs/29.1/lisp/play --directory /usr/share/emacs/29.1/lisp/org --directory /usr/share/emacs/29.1/lisp/nxml --directory /usr/share/emacs/29.1/lisp/net --directory /usr/share/emacs/29.1/lisp/mh-e --directory /usr/share/emacs/29.1/lisp/mail --directory /usr/share/emacs/29.1/lisp/leim --directory /usr/share/emacs/29.1/lisp/language --directory /usr/share/emacs/29.1/lisp/international --directory /usr/share/emacs/29.1/lisp/image --directory /usr/share/emacs/29.1/lisp/gnus --directory /usr/share/emacs/29.1/lisp/eshell --directory /usr/share/emacs/29.1/lisp/erc --directory /usr/share/emacs/29.1/lisp/emulation --directory /usr/share/emacs/29.1/lisp/emacs-lisp --directory /usr/share/emacs/29.1/lisp/cedet --directory /usr/share/emacs/29.1/lisp/calendar --directory /usr/share/emacs/29.1/lisp/calc --directory /usr/share/emacs/29.1/lisp/obsolete --eval \(setq\ package-user-dir\ \"/home/kail/tmp\"\) --eval \(progn\ \(require\ \'bytecomp\)\ \(setq\ byte-compile-root-dir\ \"/home/kail/tmp/\"\)\) --eval \(progn\ \(defvar\ jka-compr-inhibit\)\ \(unwind-protect\ \(let\ \(\(jka-compr-inhibit\ t\)\)\ \(when\ \(equal\ \(car\ command-line-args-left\)\ \"--\"\)\ \(setq\ command-line-args-left\ \(cdr\ command-line-args-left\)\)\)\ \(require\ \'bytecomp\)\ \(defvar\ flycheck-byte-compiled-files\ nil\)\ \(let\ \(\(byte-compile-dest-file-function\ \(lambda\ \(source\)\ \(let\ \(\(temp-file\ \(make-temp-file\ \(file-name-nondirectory\ source\)\)\)\)\ \(push\ temp-file\ flycheck-byte-compiled-files\)\ temp-file\)\)\)\)\ \(unwind-protect\ \(byte-compile-file\ \(car\ command-line-args-left\)\)\ \(mapc\ \(lambda\ \(f\)\ \(ignore-errors\ \(delete-file\ f\)\)\)\ flycheck-byte-compiled-files\)\)\ \(when\ \(bound-and-true-p\ flycheck-emacs-lisp-check-declare\)\ \(check-declare-file\ \(car\ command-line-args-left\)\)\)\)\)\ \(setq\ command-line-args-left\ nil\)\)\) -- /home/kail/tmp/test-flycheck.el

In end of data:
test-flycheck.el:15:2: Warning: the function ‘my-autoloaded-function’ is not known to be defined.

Compilation finished at Thu Mar  7 07:22:38
@cpitclaudel
Copy link
Member

Thanks for the detailed report 😍
The warning is computed by the Emacs bytecode compiler, not by Flycheck itself. You can use M-x flycheck-compile to see exactly how it is invoked.

@ktetzlaff
Copy link
Author

The warning is computed by the Emacs bytecode compiler, not by Flycheck itself.

Thanks for the quick reply! Any idea how to avoid the warning?

@bbatsov
Copy link
Contributor

bbatsov commented Mar 7, 2024

@ktetzlaff
Copy link
Author

ktetzlaff commented Mar 7, 2024

You can use declare-function for this. ...

@bbatsov Yes, that works. However, I would need to add declare-function to a lot of files. Is it somehow possible to declare a function globally? I.e. make a user defined function work like a built-in/preloaded function?

Or trick flycheck into ignoring the warning for a specific function?

@cpitclaudel
Copy link
Member

See flycheck-emacs-lisp-load-path maybe?

@ktetzlaff
Copy link
Author

See flycheck-emacs-lisp-load-path maybe?

@cpitclaudel I have flycheck-emacs-lisp-load-path set to inherit and the flycheck-compile output shows that the directory containing the test files gets added (--directory /home/kail/tmp). So: No - unfortunately that doesn't help.

@daedsidog
Copy link

daedsidog commented Mar 13, 2024

I have the same issue, just with the function ‘...' might not be defined at runtime. I have code such as this:

(use-package web-mode
  :mode ("\\.vue\\'" . web-mode)
  :config
  (customize-set-variable 'web-mode-markup-indent-offset 2)
  (customize-set-variable 'web-mode-css-indent-offset 2)
  (customize-set-variable 'web-mode-code-indent-offset 2))

(defun my/twee-mode-language-at-pos ()
  "Determine language at point, defaulting to web-mode if not Twee code."
  (if (save-excursion
        (beginning-of-line)
        (looking-at "^\s*<<"))
      "twee"
    (web-mode-language-at-pos)))

I get the function ‘web-mode-language-at-pos’ might not be defined at runtime. even though if I use (require 'web-mode) it works just fine.

If I expand the use-package macro, I get:

(progn
  (defvar use-package--warning43
    (function
     (lambda
       (keyword err)
       (let
           ((msg
             (format "%s/%s: %s" 'web-mode keyword
                     (error-message-string err))))
         (display-warning 'use-package msg :error)))))
  (condition-case-unless-debug err
      (progn
        (unless
            (fboundp 'web-mode)
          (autoload
            (function web-mode)
            "web-mode" nil t))
        (eval-after-load 'web-mode
          '(condition-case-unless-debug err
               (progn
                 (customize-set-variable 'web-mode-markup-indent-offset 2)
                 (customize-set-variable 'web-mode-css-indent-offset 2)
                 (customize-set-variable 'web-mode-code-indent-offset 2)
                 t)
             (error
              (funcall use-package--warning43 :config err))))
        (add-to-list 'auto-mode-alist
                     '("\\.vue\\'" . web-mode)))
    (error
     (funcall use-package--warning43 :catch err))))

Seems like the require part is under a conditional, which is why the byte compiler may have trouble recognizing this.

Anyways, this isn't really a Flycheck bug. The byte compiler also complains. I just wish there was a way to get rid of these.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants