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

Fix LSP regression #1583

Merged
merged 7 commits into from
Sep 11, 2023
Merged

Fix LSP regression #1583

merged 7 commits into from
Sep 11, 2023

Conversation

yannham
Copy link
Member

@yannham yannham commented Sep 7, 2023

Closes #1574.

Cause

After the bidirectional refactoring (better separating the rules between infer and check), the LSP was experiencing regressions, not showing hover information in some cases, in particular within statically typed blocks.

The separation between infer and check makes less clear which function is responsible for adding the term to the linearizer: sometimes it's check, sometimes it's infer, and it really depends on the call graph and where each function is called from.

It turns out the implementation was adding many terms in double, and this caused the initial regression observed.

Content

Fixing the double visit is made harder by the fact that infer doesn't have a type to provide right now to the linearizer: it first need to, well, infer it. But the linearizer currently relies on AST nodes being visited in order, so we can't either call to it whenever we want.

The situation seemed intricate enough that it was easier to split "visiting the term" and "amending the type of the term" in two operations. This PR thus adds a retype method to the Linearizer trait, plus some id-related signature changes. Now, the typechecking code can add a term to the linearizer as soon as it visits it, and update the type later. More discipline has been introduced so that check and infer don't repeat the same term visits anymore, fixing the original issue.

Doing so, this PR also cleans a bit the LSP implementation, as changing it was very hard to get right.IdGen in particular is gone, as it amounted to maintain a parallel insertion index by hand instead of just relying on the current linearization's size, which was very error-prone and caused strange errors if any off-by-one error happened.

The truth is, a refactor to make the code actually maintainable should be much more involved, but this commit is just a fix for the 1.2.0 release to get out. I did the minimum changes to be able to make the patch without losing mental sanity. The linearizer is a legacy component that will be scraped as soon as the AST-based LSP reaches feature parity with the linearizer, hence it's probably not worth a heavy rework.

@github-actions github-actions bot temporarily deployed to pull request September 7, 2023 19:02 Inactive
@github-actions github-actions bot temporarily deployed to pull request September 8, 2023 11:44 Inactive
@github-actions github-actions bot temporarily deployed to pull request September 8, 2023 12:36 Inactive
@github-actions github-actions bot temporarily deployed to pull request September 8, 2023 13:15 Inactive
After the bidirectional refactoring (better separating the rules between
`infer` and `check`), the LSP was experiencing regressions, not showing
hover information in some cases, in particular within statically typed
blocks.

It turns out the separation between `infer` and `check` makes less clear
which function is responsible for adding the term to the linearizer:
sometimes it's `check`, sometimes it's `infer`, and it really depends on
the call graph and where each function is called from.

It turns out the previous implementation was adding many terms in
double, and this caused the initial regression observed.

Morever, fixing is made hard by the fact that `infer` now doesn't have a
type to provide right now for the linearizer: it first need to, well,
infer it. But the linearizer currently relies on AST nodes being visited
in order, so we can't either call to it whenever we want.

The situation seemed intricate enough that it was easier to separate
"visiting the term" from "amending the type of the term". This commit
thus adds a `retype` method to the `Linearizer` trait, plus some
id-related signature changes. Now, the typechecking code can add a term
to the linearizer as soon as it visits it, and set the type later. More
discipline has been introduced so that `check` and `infer` don't repeat
the same term visits anymore.

Doing so, this commit also cleans a bit the LSP implementation which was
very hard to change getting it right: `IdGen` in particular is gone
(which was maintaining a counter by hand in parallel to the
linearization's size, which was very error-prone, and if any mismatch
occurred, anything could happen). The truth is, the refactor should be
much more involved to make the code maintainable, but this commit is
just a fix for the 1.2.0 release to get out, and the linearizer is a
legacy component that will be scraped soon when the AST-based LSP will
reach feature parity with the linearizer.
@github-actions github-actions bot temporarily deployed to pull request September 8, 2023 13:39 Inactive
@yannham yannham marked this pull request as ready for review September 8, 2023 13:49
@yannham yannham requested review from vkleen and jneem September 8, 2023 13:49
core/src/typecheck/mod.rs Outdated Show resolved Hide resolved
@github-actions github-actions bot temporarily deployed to pull request September 8, 2023 13:52 Inactive
core/src/typecheck/linearization.rs Outdated Show resolved Hide resolved
core/src/typecheck/mod.rs Outdated Show resolved Hide resolved
core/src/typecheck/mod.rs Outdated Show resolved Hide resolved
lsp/nls/src/linearization/building.rs Outdated Show resolved Hide resolved
@github-actions github-actions bot temporarily deployed to pull request September 8, 2023 14:38 Inactive
@github-actions github-actions bot temporarily deployed to pull request September 8, 2023 14:48 Inactive
@github-actions github-actions bot temporarily deployed to pull request September 8, 2023 16:40 Inactive

/// Variant of [infer] taking an additional `item_id` to indicate that inference is done on a term
/// that has already been visited by the linearizer, for example when coming directly from [check].
/// When `item_id` is defined, the linearizer isn't called. [infer] is just `infer_visited` called
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// When `item_id` is defined, the linearizer isn't called. [infer] is just `infer_visited` called
/// When `item_id` is defined, the term `rt` will not be added to the linearizer. [infer] is just `infer_visited` called

core/src/typecheck/mod.rs Show resolved Hide resolved
@yannham yannham added this pull request to the merge queue Sep 11, 2023
Merged via the queue into master with commit c79bc9e Sep 11, 2023
5 checks passed
@yannham yannham deleted the refactor/linearizer branch September 11, 2023 16:09
suimong pushed a commit to suimong/nickel that referenced this pull request Sep 17, 2023
* Fix LSP not showing hover information

After the bidirectional refactoring (better separating the rules between
`infer` and `check`), the LSP was experiencing regressions, not showing
hover information in some cases, in particular within statically typed
blocks.

It turns out the separation between `infer` and `check` makes less clear
which function is responsible for adding the term to the linearizer:
sometimes it's `check`, sometimes it's `infer`, and it really depends on
the call graph and where each function is called from.

It turns out the previous implementation was adding many terms in
double, and this caused the initial regression observed.

Morever, fixing is made hard by the fact that `infer` now doesn't have a
type to provide right now for the linearizer: it first need to, well,
infer it. But the linearizer currently relies on AST nodes being visited
in order, so we can't either call to it whenever we want.

The situation seemed intricate enough that it was easier to separate
"visiting the term" from "amending the type of the term". This commit
thus adds a `retype` method to the `Linearizer` trait, plus some
id-related signature changes. Now, the typechecking code can add a term
to the linearizer as soon as it visits it, and set the type later. More
discipline has been introduced so that `check` and `infer` don't repeat
the same term visits anymore.

Doing so, this commit also cleans a bit the LSP implementation which was
very hard to change getting it right: `IdGen` in particular is gone
(which was maintaining a counter by hand in parallel to the
linearization's size, which was very error-prone, and if any mismatch
occurred, anything could happen). The truth is, the refactor should be
much more involved to make the code maintainable, but this commit is
just a fix for the 1.2.0 release to get out, and the linearizer is a
legacy component that will be scraped soon when the AST-based LSP will
reach feature parity with the linearizer.

* Add Hover capability to tests

* Add regression test for hover after bidir pull request

* Formatting and code clean-up

* Apply suggestions from code review

Co-authored-by: Viktor Kleen <[email protected]>

* Make retype calls less verbose

* Fix documentation dangling link

---------

Co-authored-by: Viktor Kleen <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

LSP regression when hovering on the function field in std.xxx.function
3 participants