Skip to content

Fix stale completions after changing an import alias#5011

Open
BurningLutz wants to merge 1 commit into
haskell:masterfrom
BurningLutz:fix/import-alias-stale-completion
Open

Fix stale completions after changing an import alias#5011
BurningLutz wants to merge 1 commit into
haskell:masterfrom
BurningLutz:fix/import-alias-stale-completion

Conversation

@BurningLutz

Copy link
Copy Markdown
Contributor

Description

Refresh qualified completions when an import alias is changed without restarting HLS.

Previously, changing:

import A as CM

to:

import A as C

could leave non-local completions associated with the old CM qualifier. As a result, completions for C did not prioritize the members imported from A.

Root cause

GetModSummaryWithoutTimestamps used msrFingerprint as its early-cutoff fingerprint. That fingerprint represents dependency-relevant module information, such as imported
module and package names, but does not include full import declarations.

Changing only an import alias therefore left the fingerprint unchanged, preventing downstream NonLocalCompletions from being recomputed.

Changes

  • Add computeImportsFingerprint for full parsed import declarations, including aliases and import lists.
  • Combine the imports fingerprint with msrFingerprint in the GetModSummaryWithoutTimestamps early cutoff.
  • Add a regression test that changes an alias from CM to C in an open document, and verify that the new alias receives the imported module completions and the previous alias is no longer treated as active.

Testing

Ran the completion and completion-resolve test selection:

cabal test ghcide-tests \
  --test-option=-p \
  --test-option='/completion/' \
  --test-option=--hide-progress

All 49 selected tests passed.

@BurningLutz BurningLutz requested a review from wz1000 as a code owner July 13, 2026 09:23
ms_hspp_buf = error "use GetModSummary instead of GetModSummaryWithoutTimestamps"
}
fp = fingerprintToBS msrFingerprint
fp = fingerprintToBS $ Util.fingerprintFingerprints [msrFingerprint, computeImportsFingerprint msrImports]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why are we only using the computeImportsFingerprint here and not in the GetModSummary rule?

@BurningLutz BurningLutz Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Why are we only using the computeImportsFingerprint here and not in the GetModSummary rule?

@fendor I've considered that, but the imports fingerprint is a derived value from msrImports and only used here, in order not to break anything I chose to compute here. :)

Is it expected to compute in the GetModSummary rule?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It feels non-trivial to see why this works, initially I thought GetModSummary might produce the same fingerprint and thus short-circuit the calculation, rendering this fingerprint unsued. However, now I can tell, this is not the case, GetModSummary will be recomputed in this situation.

I just don't see why the fingerprinting logic should be different here, I think computeImportsFingerprint msrImports should be part of msrFingerprint from the start.
If an import changes, more than only completions need to be recomputed, like we need to typecheck the whole module again!

Actually, looking at the implementation of msrFingerprint, it looks like the imports are already part of the fingerprint. Perhaps there is a bug, or missing value in there?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Perhaps there is a bug, or missing value in there?

AFAIK, import aliases are missing in the fingerPrintImports of msrFingerprint so changing aliases won't result in a different fingerprint value.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Right, as we are fingerprinting imports, it makes some sense to me to additionally fingerprint the import aliases

@BurningLutz BurningLutz Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it makes some sense to me to additionally fingerprint the import aliases

I agree, with a little concern about the usage of msrFingerprint.
At line 684, msrFingerprint is used to compute shallowFingers which is used to compute a DependencyInformation.

So I do think It is a good reason to exclude import aliases from msrFingerprint: changing aliases won't result in a different depenceny info.

This is why I wasn't touching msrFingerprint in the first place.

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.

2 participants