Subject: Re: bug#79363: 31.0.50; Font locking issue in go-ts-mode when tree-sitter grammar is automatically installed

From: Yuan Fu <[email-masked]>
Date: Tue, 9 Sep 2025 00:38:41 -0700

> On Sep 1, 2025, at 2:31 PM, Roi Martin <[email-masked]> wrote:
> 
> Steps to reproduce:
> 
> 1. Run
>     emacs -Q --init-directory=/tmp/go-ts-mode-bug
> 2. Eval
>     (setopt treesit-enabled-modes '(go-ts-mode))
> 3. Open .go file
> 4. Answer y to the question
>     Tree-sitter grammar for `go' is missing; install it?  (y or n)
> 5. go-ts-mode emits the following warning and definitions are not
>   highlighted correctly.
> 
>     ⛔ Warning (treesit-font-lock-rules-mismatch): Emacs cannot compile
>     every font-lock rules because a mismatch between the grammar and the
>     rules.  This is most likely due to a mismatch between the font-lock
>     rules defined by the major mode and the tree-sitter grammar.
> 
>     This error can be fixed by either downgrading the grammar
>     (tree-sitter-go) on your system, or upgrading the major mode package.
>     The following are the temporarily disabled features:
> 
>     - `definition' for go.
> 
> In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
> 3.24.49, cairo version 1.18.2)
> Repository revision: 3c94ae5a37eac0191fe5d8bd85164b190ac10244
> Repository branch: master
> 
> I took a quick look and I think this is caused by the following issue:
> 
> 1. `go-ts-mode--font-lock-settings' depends on the following functions:
> 
>     (defun go-ts-mode--iota-query-supported-p ()
>       "Return t if the iota query is supported by the tree-sitter-go grammar."
>       (ignore-errors
>         (or (treesit-query-string "" '((iota) @font-lock-constant-face) 'go) t)))
> 
>     (defun go-ts-mode--method-elem-supported-p ()
>       "Return t if Go grammar uses `method_elem' instead of `method_spec'."
>       (ignore-errors
>         (or (treesit-query-string "" '((method_elem) @cap) 'go) t)))
> 
> 2. In this sceneario we don't have the Go grammar installed yet.  So,
>   `treesit-query-string' returns a `not-found' error.
> 3. Because of the previous error, `go-ts-mode--method-elem-supported-p'
>   returns `nil'.  Thus, the "definition" rule uses "method_spec" which
>   is not supported by the default grammar (commit
>   "12fe553fdaaa7449f764bc876fd777704d4fb752").
> 
>     (defvar go-ts-mode--font-lock-settings
>       (treesit-font-lock-rules
>        ...
>        :language 'go
>        :feature 'definition
>        `(...
>          (,(if (go-ts-mode--method-elem-supported-p)
>                'method_elem
>              'method_spec)
>           name: (field_identifier) @font-lock-function-name-face)
> 
> Please, take this analysis with a pinch of salt.  I'm not familiar with
> the code base.  But I hope it makes sense.
> 
>        Roi

Thanks for the analysis! Does that mean once the grammar is installed, and you restart Emacs, go-ts-mode would work as normal?

We do need to fix how we’re defining font-lock rules, the test should be done when major mode is enabled, not when the package is loaded. I thought about this problem and wanted to come up with some generic solution, such as letting treesit-font-lock-rules support a predicate function/query for font-lock-rules, or define rules in a fallback list. I didn’t come up with a very satisfying solution and the progress kind of stalled. Anyway, now it seems I need to put some thought into this and come up with something soon.

Yuan