Skip to content
New issue

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

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

Already on GitHub? # to your account

Syntax Highlighting related panic: IncludedRangesError(1) #3816

Closed
sevenautumns opened this issue Sep 12, 2022 · 9 comments · Fixed by #7621
Closed

Syntax Highlighting related panic: IncludedRangesError(1) #3816

sevenautumns opened this issue Sep 12, 2022 · 9 comments · Fixed by #7621
Labels
A-core Area: Helix core improvements A-tree-sitter Area: Tree-sitter C-bug Category: This is a bug

Comments

@sevenautumns
Copy link

Summary

When adding a '-symbol to a specific line of a specific nix-file, the predefined language-server for nix files (rnix-lsp) seems to provide information which results in an error in the tree_sitter parser which is unwrapped and hence panics.

parser.set_included_ranges(&self.ranges).unwrap();

Reproduction Steps

I tried this:

  1. hx flake.nix
  2. go to line 32
  3. add ' after the =-symbol of that line
  4. crash
flake.nix
{
  inputs = {
    utils.url = "github:numtide/flake-utils";
    devshell.url = "github:numtide/devshell";
    fenix.url = "github:nix-community/fenix";
    fenix.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { self, nixpkgs, utils, devshell, fenix, ... }@inputs:
    utils.lib.eachSystem [ "aarch64-linux" "i686-linux" "x86_64-linux" ]
    (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          overlays = [ devshell.overlay ];
        };
        rust-toolchain = with fenix.packages.${system};
          combine [ stable.rustc stable.cargo stable.clippy stable.rustfmt ];
      in rec {
        devShells.default = (pkgs.devshell.mkShell {
          imports = [
            # "${devshell}/extra/language/rust.nix"
            "${devshell}/extra/git/hooks.nix"
          ];
          name = "apex-rs-vanilla-dev-shell";
          packages = with pkgs; [
            rust-toolchain
            rust-analyzer
            cargo-outdated
            cargo-udeps
          ];
          devshell.startup.bindgen-hook.text = "source ${pkgs.rustPlatform.bindgenHook}/nix-support/setup-hook && populateBindgenEnv";
          git.hooks = {
            enable = true;
            pre-commit.text = "nix flake check";
          };
          commands = [
            {
              package = "git-cliff";
              help = "Changelog generator";
            }
            {
              package = "treefmt";
              help = "Format project tree with recommended formatter";
              category = "formatter";
            }
            {
              name = "udeps";
              command = "cargo-udeps udeps";
              category = "formatter";
              help = "Find unused dependencies in Cargo.toml";
            }
            {
              name = "outdated";
              command = "cargo-outdated outdated";
              category = "formatter";
              help = "Find out-of-date dependencies";
            }
            {
              name = "build";
              command = "cd $PRJ_ROOT && cargo build";
              help = "Build project";
              category = "build";
            }
            {
              name = "build release";
              command = "cd $PRJ_ROOT && cargo build --release";
              help = "Build project in release mode";
              category = "build";
            }
            {
              name = "clippy";
              command = "cd $PRJ_ROOT && cargo clippy";
              help = "Build project";
              category = "build";
            }
            {
              name = "clippy release";
              command = "cd $PRJ_ROOT && cargo clippy --release";
              help = "Build project in release mode";
              category = "build";
            }
            {
              name = "watch";
              command = "cd $PRJ_ROOT && cargo watch -x clippy";
              help = "Watch project and continuesly clippy";
              category = "build";
            }
            {
              name = "watch release";
              command = "cd $PRJ_ROOT && cargo watch -x clippy --release";
              help = "Watch project and continuesly clippy in release mode";
              category = "build";
            }
          ];
        });
        checks = {
          nixpkgs-fmt = pkgs.runCommand "nixpkgs-fmt" {
            nativeBuildInputs = [ pkgs.nixpkgs-fmt ];
          } "nixpkgs-fmt --check ${./.}; touch $out";
          cargo-fmt = pkgs.runCommand "cargo-fmt" {
            nativeBuildInputs = [ rust-toolchain ];
          } "cd ${./.}; cargo fmt --check; touch $out";
        };
      });
}

I expected this to happen:

No crash

Instead, this happened:

Crash

Helix log

~/.cache/helix/helix.log
2022-09-12T15:24:49.391 helix_lsp::transport [ERROR] err: <- StreamClosed
2022-09-12T15:24:49.391 helix_lsp::transport [ERROR] err: <- StreamClosed
console output
❯ RUST_BACKTRACE=full hx flake.nix
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: IncludedRangesError(1)', helix-core/src/syntax.rs:988:50
stack backtrace:
   0:     0x55e7021044d4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h9c2a9d2774d81873
   1:     0x55e701927cac - core::fmt::write::hba4337c43d992f49
   2:     0x55e7020fdeb5 - std::io::Write::write_fmt::heb73de6e02cfabed
   3:     0x55e70210637e - std::panicking::default_hook::{{closure}}::hc9a76eed0b18f82b
   4:     0x55e7021060ad - std::panicking::default_hook::h2e88d02087fae196
   5:     0x55e702106a0b - std::panicking::rust_panic_with_hook::habfdcc2e90f9fd4c
   6:     0x55e702106834 - std::panicking::begin_panic_handler::{{closure}}::he054b2a83a51d2cd
   7:     0x55e702104a04 - std::sys_common::backtrace::__rust_end_short_backtrace::ha48b94ab49b30915
   8:     0x55e70210659d - rust_begin_unwind
   9:     0x55e70189ed93 - core::panicking::panic_fmt::h366d3a309ae17c94
  10:     0x55e70189ee83 - core::result::unwrap_failed::hddd78f4658ac7d0f
  11:     0x55e7019efecf - helix_core::syntax::LanguageLayer::parse::h48fdfccc00f93624
  12:     0x55e7019c9375 - std::thread::local::LocalKey<T>::with::h3872ba0248f25375
  13:     0x55e7019efb32 - helix_core::syntax::Syntax::update::hfabc70c9a1af51f1
  14:     0x55e701ee80ca - helix_view::document::Document::apply_impl::h5831f29c9957f896
  15:     0x55e701ee91b7 - helix_view::document::Document::apply::h597bd3f2f8ff332e
  16:     0x55e701ce541e - helix_term::commands::insert::insert_char::h7a8fb8b8401f39f5
  17:     0x55e701c4e3e0 - helix_term::ui::editor::EditorView::insert_mode::hb6771a242a86bcbf
  18:     0x55e701c501b0 - <helix_term::ui::editor::EditorView as helix_term::compositor::Component>::handle_event::h0fee62f981b2f994
  19:     0x55e701cc9566 - helix_term::compositor::Compositor::handle_event::h6f24a639f104cd8a
  20:     0x55e701c45706 - helix_term::application::Application::handle_terminal_events::hd4a6e6651951166f
  21:     0x55e701f8517f - helix_term::application::Application::event_loop_until_idle::{{closure}}::h44cf1aa2267c2b1c
  22:     0x55e701fa31b5 - <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h2bcdc355d267fb0f
  23:     0x55e701f80342 - std::thread::local::LocalKey<T>::with::he3043768d7283740
  24:     0x55e701f6e868 - tokio::park::thread::CachedParkThread::block_on::h8a087f435dd2194f
  25:     0x55e701fc9568 - tokio::runtime::scheduler::multi_thread::MultiThread::block_on::he8e9a60150382027
  26:     0x55e701f9f87e - tokio::runtime::Runtime::block_on::hd015e4e225788d29
  27:     0x55e701f64445 - hx::main::hb7285d874580d790
  28:     0x55e701f67733 - std::sys_common::backtrace::__rust_begin_short_backtrace::h9aa95b3790b5aa07
  29:     0x55e701f7fced - std::rt::lang_start::{{closure}}::h5d2638673ea5bf71
  30:     0x55e7020f874b - std::rt::lang_start_internal::h9c06694362b5b80c
  31:     0x55e701f64552 - main
  32:     0x7f1b832e724e - __libc_start_call_main
  33:     0x7f1b832e7309 - __libc_start_main@@GLIBC_2.34
  34:     0x55e7018d67b5 - _start
  35:                0x0 - <unknown>

Platform

Linux (NixOS)

Terminal Emulator

alacritty

Helix Version

helix 22.08.1 (0361217)

@sevenautumns sevenautumns added the C-bug Category: This is a bug label Sep 12, 2022
@AlexanderBrevig
Copy link
Contributor

Unable to reproduce.

Linux 5.15.60-1-MANJARO @ 21.3.7
Kitty 0.25.2
helix 22.08.1 (23027a4)
rnix-lsp 0.2.5-1

Which rnix-lsp are you on?

@archseer
Copy link
Member

Seems to trigger if the start of the range is past the end of the range or if ranges overlap:

            for (i, range) in ranges.iter().enumerate() {
                if range.start_byte < prev_end_byte || range.end_byte < range.start_byte {
                    return Err(IncludedRangesError(i));
                }
                prev_end_byte = range.end_byte;
            }

I also can't replicate: which = sign on this line?

renameOutputs = {"helix-term" = "helix";};
Do you have auto-pairs disabled?

I don't think it has anything to do with the LSP, this is a tree-sitter parsing issue.

@sudormrfbin
Copy link
Member

There's a flake.nix linked in the initial post, it's collapsible so easy to miss. I could reproduce the crash with it (on mobile right now so can't get the hx --version).

@AlexanderBrevig
Copy link
Contributor

I tested that file with 32ggf=a' and I simply just get the normal diagnostic error message. Do you have another set of keys you use to trigger the error?

@sevenautumns
Copy link
Author

@AlexanderBrevig
I am on rnix-lsp 0.2.5.

Do you have another set of keys you use to trigger the error?

At least for me there are no keys required at all. I tested adding the ' with another language selected. It works, but when I reopened the file afterwards helix would just straight up crash.

@archseer

Do you have auto-pairs disabled?

I do not have auto-pairs disabled. I'll provide my config here:

~/.config/helix/config.toml
theme = "autumn"

[editor]
idle-timeout = 0

[editor.cursor-shape]
insert = "bar"
normal = "block"
select = "block"

[keys]
[keys.insert]
down = "move_line_down"
left = "move_char_left"
right = "move_char_right"
up = "move_line_up"

[keys.normal.space]
n = ":new"
u = ":format"
~/.config/helix/languages.toml
[[language]]
name = "latex"

[language.language-server]
command = "ltex-ls"

[[language]]
name = "nix"

[language.formatter]
command = "/nix/store/8i4cph1j35jx722snpd2dbj9s8w60amr-nixfmt-0.5.0/bin/nixfmt"

[[language]]
comment-token = "#"
file-types = ["COMMIT_EDITMSG"]
name = "git-commit"
roots = []
scope = "git.commitmsg"

[language.indent]
tab-width = 2
unit = "  "

[language.language-server]
command = "ltex-ls"

[[language]]
file-types = ["md"]
name = "markdown"
roots = []
scope = "source.markdown"

[language.language-server]
command = "ltex-ls"

Other than these settings, default from 0361217 are used

@sevenautumns
Copy link
Author

@AlexanderBrevig

Here is a flake.nix which just straight up crashes helix.

flake.nix <----- Collapsible
{
  inputs = {
    utils.url = "github:numtide/flake-utils";
    devshell.url = "github:numtide/devshell";
    fenix.url = "github:nix-community/fenix";
    fenix.inputs.nixpkgs.follows = "nixpkgs";
  };

  outputs = { self, nixpkgs, utils, devshell, fenix, ... }@inputs:
    utils.lib.eachSystem [ "aarch64-linux" "i686-linux" "x86_64-linux" ]
    (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          overlays = [ devshell.overlay ];
        };
        rust-toolchain = with fenix.packages.${system};
          combine [ stable.rustc stable.cargo stable.clippy stable.rustfmt ];
      in rec {
        devShells.default = (pkgs.devshell.mkShell {
          imports = [
            # "${devshell}/extra/language/rust.nix"
            "${devshell}/extra/git/hooks.nix"
          ];
          name = "apex-rs-vanilla-dev-shell";
          packages = with pkgs; [
            rust-toolchain
            rust-analyzer
            cargo-outdated
            cargo-udeps
          ];
          devshell.startup.bindgen-hook.text = ''
            source ${pkgs.rustPlatform.bindgenHook}/nix-support/setup-hook
            populateBindgenEnv
          '';
          git.hooks = {
            enable = true;
            pre-commit.text = "nix flake check";
          };
          commands = [
            {
              package = "git-cliff";
              help = "Changelog generator";
            }
            {
              package = "treefmt";
              help = "Format project tree with recommended formatter";
              category = "formatter";
            }
            {
              name = "udeps";
              command = "cargo-udeps udeps";
              category = "formatter";
              help = "Find unused dependencies in Cargo.toml";
            }
            {
              name = "outdated";
              command = "cargo-outdated outdated";
              category = "formatter";
              help = "Find out-of-date dependencies";
            }
            {
              name = "build";
              command = "cd $PRJ_ROOT && cargo build";
              help = "Build project";
              category = "build";
            }
            {
              name = "build release";
              command = "cd $PRJ_ROOT && cargo build --release";
              help = "Build project in release mode";
              category = "build";
            }
            {
              name = "clippy";
              command = "cd $PRJ_ROOT && cargo clippy";
              help = "Build project";
              category = "build";
            }
            {
              name = "clippy release";
              command = "cd $PRJ_ROOT && cargo clippy --release";
              help = "Build project in release mode";
              category = "build";
            }
            {
              name = "watch";
              command = "cd $PRJ_ROOT && cargo watch -x clippy";
              help = "Watch project and continuesly clippy";
              category = "build";
            }
            {
              name = "watch release";
              command = "cd $PRJ_ROOT && cargo watch -x clippy --release";
              help = "Watch project and continuesly clippy in release mode";
              category = "build";
            }
          ];
        });
        checks = {
          nixpkgs-fmt = pkgs.runCommand "nixpkgs-fmt" {
            nativeBuildInputs = [ pkgs.nixpkgs-fmt ];
          } "nixpkgs-fmt --check ${./.}; touch $out";
          cargo-fmt = pkgs.runCommand "cargo-fmt" {
            nativeBuildInputs = [ rust-toolchain ];
          } "cd ${./.}; cargo fmt --check; touch $out";
        };
      });
}

With #3826 of course the output of the program changes to:

Program output
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: InvalidRanges', helix-core/src/syntax.rs:618:14
stack backtrace:
   0:     0x55a65d770ed4 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::h9c2a9d2774d81873
   1:     0x55a65cf94ccc - core::fmt::write::hba4337c43d992f49
   2:     0x55a65d76a8b5 - std::io::Write::write_fmt::heb73de6e02cfabed
   3:     0x55a65d772d7e - std::panicking::default_hook::{{closure}}::hc9a76eed0b18f82b
   4:     0x55a65d772aad - std::panicking::default_hook::h2e88d02087fae196
   5:     0x55a65d773325 - std::panicking::rust_panic_with_hook::habfdcc2e90f9fd4c
   6:     0x55a65d773234 - std::panicking::begin_panic_handler::{{closure}}::he054b2a83a51d2cd
   7:     0x55a65d771404 - std::sys_common::backtrace::__rust_end_short_backtrace::ha48b94ab49b30915
   8:     0x55a65d772f9d - rust_begin_unwind
   9:     0x55a65cf0bd93 - core::panicking::panic_fmt::h366d3a309ae17c94
  10:     0x55a65cf0be83 - core::result::unwrap_failed::hddd78f4658ac7d0f
  11:     0x55a65d05c372 - helix_core::syntax::Syntax::new::h3e77386699b9bd03
  12:     0x55a65d553450 - helix_view::document::Document::set_language::h4013a5d56dd28867
  13:     0x55a65d551e8e - helix_view::document::Document::open::hc8eeb61a7d9ec6b4
  14:     0x55a65d51c8e1 - helix_view::editor::Editor::open::h60cbbb87afa07f7b
  15:     0x55a65d2af6f9 - helix_term::application::Application::new::h626015731ae4f831
  16:     0x55a65d610201 - <core::future::from_generator::GenFuture<T> as core::future::future::Future>::poll::h5f3b37062c32a82c
  17:     0x55a65d5ecb42 - std::thread::local::LocalKey<T>::with::hb5d8ea16e9cadeef
  18:     0x55a65d5db2c8 - tokio::park::thread::CachedParkThread::block_on::h59b4805dfbf7bc54
  19:     0x55a65d635ed8 - tokio::runtime::scheduler::multi_thread::MultiThread::block_on::h44c594da2be2f6c5
  20:     0x55a65d60c22e - tokio::runtime::Runtime::block_on::hdc7affd610a62c07
  21:     0x55a65d5d0f25 - hx::main::h3502fc2a3489134c
  22:     0x55a65d5d4213 - std::sys_common::backtrace::__rust_begin_short_backtrace::h4f9548a5e84dface
  23:     0x55a65d5ec6ad - std::rt::lang_start::{{closure}}::h1c682f4407c90018
  24:     0x55a65d76514b - std::rt::lang_start_internal::h9c06694362b5b80c
  25:     0x55a65d5d1032 - main
  26:     0x7f7582fd124e - __libc_start_call_main
  27:     0x7f7582fd1309 - __libc_start_main@@GLIBC_2.34
  28:     0x55a65cf437d5 - _start
  29:                0x0 - <unknown>

@kirawi kirawi added A-tree-sitter Area: Tree-sitter A-core Area: Helix core improvements labels Sep 14, 2022
@the-mikedavis
Copy link
Member

It looks like this was introduced by 665e27f

@gabydd
Copy link
Member

gabydd commented Jun 21, 2023

minimal reproduction:

{
  startup.hook = ''
    sh
  ''
}

I assume it has something to do with this:

(#match? @_path "(^\\w*Phase|command|(pre|post)\\w*|(.*\\.)?\\w*([sS]cript|[hH]ook)|(.*\\.)?startup)$")
I'll dig into it a little bit later

@gabydd
Copy link
Member

gabydd commented Jun 22, 2023

looking at this the query:

((binding
attrpath: (attrpath (identifier) @_path)
expression: [
(indented_string_expression (string_fragment) @injection.content)
(binary_expression (indented_string_expression (string_fragment) @injection.content))
])
(#match? @_path "(^\\w*Phase|command|(pre|post)\\w*|(.*\\.)?\\w*([sS]cript|[hH]ook)|(.*\\.)?startup)$")
(#set! injection.language "bash")
(#set! injection.combined))

matches twice for the above nix text

QueryMatch { id: 0, pattern_index: 2, captures: [QueryCapture { node: {Node identifier (1, 2) - (1, 9)}, index: 2 }, QueryCapture { node: {Node string_fragment (1, 19) - (3, 2)}, index: 0 }] }
QueryMatch { id: 1, pattern_index: 2, captures: [QueryCapture { node: {Node identifier (1, 10) - (1, 14)}, index: 2 }, QueryCapture { node: {Node string_fragment (1, 19) - (3, 2)}, index: 0 }] }

so there is duplicated content nodes
[{Node string_fragment (1, 19) - (3, 2)}, {Node string_fragment (1, 19) - (3, 2)}]
which creates duplicated ranges:

helix/helix-core/src/syntax.rs

Lines 1192 to 1197 in eb81cf3

if let Some(config) = (injection_callback)(&lang_name) {
let ranges = intersect_ranges(
&layer.ranges,
&content_nodes,
included_children,
);

adding ranges.dedup(); after the above line did fix this issue but I am pretty sure that is not the correct fix

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-core Area: Helix core improvements A-tree-sitter Area: Tree-sitter C-bug Category: This is a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants