haskell-language-server
haskell-language-server copied to clipboard
HLS confuses multiple paths to the same library, in presence of nested cabal project
Tested with HLS 2.0.0.0 (has been bugging me for many versions)
I have created a reproducible repository for this issue.
- Clone the repo, either stay in the
main
branch or switch to theerror-when-opening-deep-dep
branch - Open VSCode in the root directory.
- Open
MyLib.hs
and fiddle with it to make sure it does type check (it should). - Put your cursor on
SomeTypeCtor
, and jump-to-definition (F12 for me, orGo to Definition
in the command palette)
What I see:
-
DeepDep.hs
opens, but - Now there is a type (kind) error in
MyLib.hs
, or the form:
• Expected kind ‘deep-dep-0.1.0.0:DeepDep.SomeType’,
but ‘'SomeTypeCtor 'True’ has kind ‘SomeType’
NB: ‘deep-dep-0.1.0.0:DeepDep.SomeType’
is defined in ‘DeepDep’ in package ‘deep-dep-0.1.0.0’
‘SomeType’ is defined at
/home/val/personal/demonstrate-hls-issue/toplevel/deps/submodule/deep-dep/src/DeepDep.hs:5:1-36
• In the first argument of ‘SomeParameterizedType’, namely
‘('SomeTypeCtor 'True)’
In the type ‘SomeParameterizedType ('SomeTypeCtor 'True)’
In the type declaration for ‘Test’
What seems to happen is that HLS tries to type check deep-dep
, but in the process creates an independent copy of it, separate from the one that MyLib
depends upon. Then it gets confused between two instances of the very same kind that it now considers distinct.
There is a fix, demonstrated in the fixed-it
branch of the reproduction repository. If you add a hie.yaml
in the submodule
directory, that lists all local paths and libraries, then when you open DeepDep.hs
, everything keeps type-checking.
Unfortunately, in my real world use case, there are dozens of submodules, there are submodules that contain other submodules in a nested fashion, and none of those have any hie.yaml
.
Adding a toplevel hie.yaml
that lists everything does not seem to suffice: see error-with-toplevel-hie
branch.
It'd be great if the default behavior was not to get confused in such a way. Clearly it's doable, as demonstrated in the fixed-it
branch, but a solution that could rely on solely the top-level hie.yaml
would be ideal.
In case it helps, this is the directory structure in the error-when-opening-deep-dep
branch:
.
├── cabal.project
├── deps
│ └── submodule
│ ├── cabal.project
│ ├── deep-dep
│ │ ├── deep-dep.cabal
│ │ └── src
│ │ └── DeepDep.hs
│ └── less-deep-dep
│ ├── less-deep-dep.cabal
│ └── src
│ └── LessDeepDep.hs
├── src
│ └── MyLib.hs
└── toplevel.cabal
I can reproduce, and I think this is an issue with multiple home units https://well-typed.com/blog/2023/03/cabal-multi-unit/ and https://gist.github.com/fendor/5b26d36538787c8c2ed8c6eb6e68541f#interactive-ghc-session and what not. In short, many open issues.
Bad news, for old GHC versions, I don't think there is much we can do. The good news is, as you might tell from the blog posts, cabal and GHC support for multiple home units has been added. Once we also give hie-bios the necessary facelifting, we should be able to kill all these issues for good.
I think this should be fixed by the proper multi-home-unit support.