Repository: rust-lang/rust-mode (language: rust)

Issue:
File mode specification error: (void-function rust-mode)
The following error is returned when opening a `.rs` file:

```
File mode specification error: (void-function rust-mode)
```

It seems to be caused by:

https://github.com/rust-lang/rust-mode/blob/d8a09f218e24407acbc9f36c641be4f913f1a63c/rust-mode.el#L78-L79

Because after the last changes to support treesitter, no `rust-mode` is autoloaded.

https://github.com/rust-lang/rust-mode/blob/d8a09f218e24407acbc9f36c641be4f913f1a63c/rust-mode.el#L74-L76

https://github.com/rust-lang/rust-mode/blob/d8a09f218e24407acbc9f36c641be4f913f1a63c/rust-prog-mode.el#L1448

https://github.com/rust-lang/rust-mode/blob/d8a09f218e24407acbc9f36c641be4f913f1a63c/rust-mode-treesitter.el#L15

My current workaround it is to `require 'rust-mode` in my `init.el`. However, this was not necessary before and it woud be great to continue supporting lazy-loading.


Discussion / hints:
How are you installing rust-mode ?
With this configuration I'm not able to reproduce the issue:
```
(use-package rust-mode
  :defer t
  :init
  (setq rust-mode-treesitter-derive t))
 ```
@psibi plain `package.el`. These are the relevant pieces of [my configuration](https://github.com/jroimartin/dotfiles/blob/ee91c2d3beef2d3c7ed5bbf1c14518afa593c8ce/.emacs.d/init.el):

```
(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(package-selected-packages
   '(denote forge dockerfile-mode rust-mode yaml-mode magit go-mode markdown-mode)))
```

```
;; Install selected packages if any is missing.
(unless (seq-every-p #'package-installed-p package-selected-packages)
  (package-install-selected-packages))
```

```
;; Rust.
;; Requires: rustup [+toolchain] component add rust-analyzer
;; Indentation: 4 spaces
(customize-set-variable 'rust-indent-offset 4)
(add-hook 'rust-mode-hook
          #'(lambda ()
              (setq indent-tabs-mode nil)))
(add-hook 'rust-mode-hook
          #'(lambda ()
              (eglot-ensure)
              (add-hook 'before-save-hook #'eglot-format-buffer nil t)))
```
Thanks!

Does reverting this PR fix it: https://github.com/rust-lang/rust-mode/pull/526/files ?
@psibi probably, but that would break the treesitter derived mode, right?

If I'm not wrong, you choose the right `rust-mode` based on this:

https://github.com/rust-lang/rust-mode/blob/d8a09f218e24407acbc9f36c641be4f913f1a63c/rust-mode.el#L74-L76

What about doing something like this? (not tested)

```
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode-choose))

;;;###autoload
(defun rust-mode-choose ()
  "Choose the appropriate rust-mode."
  (if (and (version<= "29.1" emacs-version) rust-mode-treesitter-derive)
      (require 'rust-mode-treesitter)
    (require 'rust-prog-mode))
  (rust-mode))
```
That sounds fair, can you send out a PR for it ? CC: @condy0919 What do you think about the above proposed patch ?
> (add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode-choose))

Thinking further, I'm not so sure about this: Since `rust-mode-chose` is not a mode.
I have just created #530. You can see in the default `auto-mode-alist` value, that this pattern is commonly used. For instance,

```
     ("[/.]c\\(?:on\\)?f\\(?:i?g\\)?\\(?:\\.[a-zA-Z0-9._-]+\\)?\\'" . conf-mode-maybe)
```

```
(defun conf-mode-maybe ()
  "Select Conf mode or XML mode according to start of file."
  (if (save-excursion
	(save-restriction
	  (widen)
	  (goto-char (point-min))
	  (looking-at "<\\?xml \\|<!-- \\|<!DOCTYPE ")))
      (xml-mode)
    (conf-mode)))
```
Cool, thanks!
That being said, I'm far from being an experienced elisp programmer. So, take everything I said with a grain of salt.
Good job！

Fix patch:
diff --git a/rust-mode.el b/rust-mode.el
index 70c2a2c..ec1ecba 100644
--- a/rust-mode.el
+++ b/rust-mode.el
@@ -75,6 +75,9 @@ instead of `prog-mode'. This option requires emacs29+."
     (require 'rust-mode-treesitter)
   (require 'rust-prog-mode))
 
+;;;###autoload
+(autoload 'rust-mode "rust-mode" "Major mode for Rust code.")
+
 ;;;###autoload
 (add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode))
 


Test patch: