Skip to content

Superfluous boot import crashes HLS where GHC is fine #4911

@martijnbastiaan

Description

@martijnbastiaan

Your environment

Which OS do you use?
Ubuntu 22.04

Which version of GHC do you use and how did you install it?

$ cabal --version
cabal-install version 3.16.0.0 
compiled using version 3.16.0.0 of the Cabal library (in-tree)

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.10.3

I'm using the Nix development environment.

How is your project built (alternative: link to the project)?
Cabal, please see:

martijnbastiaan@10635cc

Which LSP client (editor/plugin) do you use?
VSCode + Haskell plugin

Which version of HLS do you use and how did you install it?

$ haskell-language-server-wrapper --version
haskell-language-server version: 2.12.0.0 (GHC: 9.10.3) (PATH: /nix/store/7qzs1f2whcaqi1k281hi1jmzk12li8bi-haskell-language-server-2.12.0.0/bin/haskell-language-server-wrapper)

I'm using the Nix development environment.

Have you configured HLS in any way (especially: a hie.yaml file)?
No

Steps to reproduce

git clone https://github.com/martijnbastiaan/haskell-language-server.git
cd haskell-language-server
git checkout mixed-normal-source-imports
cabal run ghcide-tests -- -p SOURCE

Expected behaviour

HLS should behave the same as GHC:

martijn@deskei:~/code/haskell-language-server/ghcide-test/data/boot-qualified$ ghc -fno-code *.hs *.hs-boot
[1 of 4] Compiling A[boot]          ( A.hs-boot, nothing )
[2 of 4] Compiling B[boot]          ( B.hs-boot, nothing )
[3 of 4] Compiling A                ( A.hs, nothing )
[4 of 4] Compiling B                ( B.hs, nothing )

Actual behaviour

ghcide
  boot
    qualified import alongside SOURCE import resolves to full module: FAIL (5.06s)
      ghcide-test/exe/BootTests.hs:58:
      Got unexpected diagnostics for Uri {getUri = "file:///tmp/nix-shell.uWGfIe/hls-test-root/extra-dir-99938760403216/B.hs"} got [Diagnostic {_range = Range {_start = Position {_line = 14, _character = 17}, _end = Position {_line = 14, _character = 27}}, _severity = Just DiagnosticSeverity_Error, _code = Just (InR "GHC-88464"), _codeDescription = Just (CodeDescription {_href = Uri {getUri = "https://errors.haskell.org/messages/GHC-88464"}}), _source = Just "typecheck", _message = "Variable not in scope: QA.extraFn :: T -> T\nNB: the module \8216A\8217 does not export \8216extraFn\8217.", _tags = Just [], _relatedInformation = Just [DiagnosticRelatedInformation {_location = Location {_uri = Uri {getUri = "file:///tmp/nix-shell.uWGfIe/hls-test-root/extra-dir-99938760403216/B.hs"}, _range = Range {_start = Position {_line = 14, _character = 17}, _end = Position {_line = 14, _character = 27}}}, _message = "TypeCheck"}], _data_ = Just (Object (fromList [("attachedReason",Array [String "-Wdeferred-out-of-scope-variables"])]))}]

Potential fix

LLMs pointed me here, but I doubt it's the correct fix, please take it with a heap of salt:

diff --git a/ghcide/src/Development/IDE/Core/Rules.hs b/ghcide/src/Development/IDE/Core/Rules.hs
index 723e1784e6..df2c7a3013 100644
--- a/ghcide/src/Development/IDE/Core/Rules.hs
+++ b/ghcide/src/Development/IDE/Core/Rules.hs
@@ -798,7 +798,13 @@ ghcSessionDepsDefinition fullModSummary GhcSessionDepsConfig{..} hscEnvEq file =
                 env = msrHscEnv msr
             depSessions <- map hscEnv <$> uses_ (GhcSessionDeps_ fullModSummary) deps
             ifaces <- uses_ GetModIface deps
-            let inLoadOrder = map (\HiFileResult{..} -> HomeModInfo hirModIface hirModDetails emptyHomeModInfoLinkable) ifaces
+            -- Load .hs-boot before .hs: the HPT is keyed by module name, and
+            -- addHomeModInfoToHpt overwrites, so the non-boot must be last.
+            let inLoadOrder = sortOn (not . isBootHmi)
+                  $ map (\HiFileResult{..} -> HomeModInfo hirModIface hirModDetails emptyHomeModInfoLinkable) ifaces
+                isBootHmi hmi = case mi_hsc_src (hm_iface hmi) of
+                  HsBootFile -> True
+                  _          -> False
             de <- useWithSeparateFingerprintRule_ GetModuleGraphTransDepsFingerprints GetModuleGraph file
             mg <- do
               if fullModuleGraph

Debug information

N/A

Metadata

Metadata

Assignees

Labels

component: ghcidetype: bugSomething isn't right: doesn't work as intended, documentation is missing/outdated, etc..

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions