rust-lang / rust-mode

Emacs configuration for Rust
Apache License 2.0
1.11k stars 179 forks source link

Not able to use treesitter derived mode with straight #541

Open xofyarg opened 5 months ago

xofyarg commented 5 months ago

Given the following config, straight will byte compile the package, and generate an autoload file. The autoload file pulls in rust-prog-mode unconditionally. I'm not sure how to workaround this, maybe wrap the file content with a runtime check?

(setq straight-use-package-by-default t)
(use-package rust-mode
  :init
  (setq rust-mode-treesitter-derive t))
$ cat rust-mode-autoloads.el
...
;;; Generated autoloads from rust-prog-mode.el

(register-definition-prefixes "rust-prog-mode" '("rust-"))
...
psibi commented 4 months ago

I'm not sure how straight works to comment on this. But I would be happy to accept a documentation PR if you have found a workaround for this ?

divyaranjan1905 commented 3 months ago

@xofyarg You can disable autoloads and byte-compiling for rust-mode by doing:

(use-package rust-mode
    :straight (:build (:not compile autoloads)))

But in my experience this still doesn't work because whenever I use the above with :init (setq rust-mode-treesitter-derive t) my whole emacs session just crashes.

seagle0128 commented 3 months ago

Same issue with use-package. rust-mode was unable to load, while built-in rust-ts-mode was loaded.

psibi commented 3 months ago

Same issue with use-package. rust-mode was unable to load, while built-in rust-ts-mode was loaded.

Do you mean without straight ? If that's the case, something else is wrong - since I'm using rust-mode fine with use-package.

seagle0128 commented 3 months ago

@psibi Right! I am using use-package without straight. The config is below. Every time I open a rust file, The built-in rust-ts-mode is enabled. I have to enable rust-mode manually.

(use-package rust-mode
  :init (setq rust-format-on-save t
              rust-mode-treesitter-derive t))
seagle0128 commented 3 months ago

@psibi I found the root cause in my env. I enabled global-treesit-auto-mode, which conflicts with the treesitter derived mode in rust-mode. So maybe it's a noise.

psibi commented 3 months ago

Yeah, agree. I use rust-mode with use-package (without straight) and didn't come across this issue. This issue seems to be happening when straight is involved.

eshrh commented 1 month ago

I can't reproduce these errors. Rust-mode works fine with treesitter on my machine

xofyarg commented 3 weeks ago

Sorry for the late reply. Let me try to explain the issue in more details:

Firstly, rust-mode is defined by either rust-prog-mode or rust-mode-treesitter, depends on which one is evaluated last. There's a trap for rust-mode-treesitter-derive though. When evaluating rust-prog-mode, it requires rust-mode, which in turn requires rust-mode-treesitter to define the rust-mode. The definition will then be overridden by rust-prog-mode later. This means if rust-prog-mode is loaded, the rust-mode will be derived from prog-mode.

Secondly, straight generates the autoloads file by default with loaddefs-generate, which scans the variable/functions definitions and put register-definition-prefixes into the generated autoloads file. This leads to an entry (register-definition-prefixes "rust-prog-mode" '("rust-")).

Now let's see how it (doesn't) work: the autoloads has the code below. When a .rs file is opened, rust-mode.el will be loaded because of the auto-mode-alist and the autoload entry for rust-mode. If rust-mode-treesitter-derive is set, it will require rust-mode-treesitter, so far so good. Then if something tries to complete definitions that starts with rust-, M-x describe-function rust-mode for example, rust-prog-mode will be loaded because of the registered prefix.

(autoload 'rust-mode "rust-mode" "\
Major mode for Rust code." t)
(add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode))
(register-definition-prefixes "rust-prog-mode" '("rust-"))

The following straight snippet works but not elegant, as it manually set autoloads for rust-mode:

(use-package rust-mode
  :straight (:build (:not autoloads))
  :init
  (setq rust-mode-treesitter-derive t)
  (autoload 'rust-mode "rust-mode" nil t)
  (add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode)))

I'm not sure if there are any better options, there are something in my mind: