haskell / haskell-language-server

Official haskell ide support via language server (LSP). Successor of ghcide & haskell-ide-engine.
Apache License 2.0
2.65k stars 355 forks source link

Ambiguous target if a module belongs to multiple executables. #3507

Open amano-kenji opened 1 year ago

amano-kenji commented 1 year ago

Your environment

Which OS do you use? Gentoo Linux Which version of GHC do you use and how did you install it? 9.0.2 from gentoo linux How is your project built? https://codeberg.org/amano.kenji/brick-tabular-list

Which LSP client (editor/plugin) do you use? nvim-lspconfig Which version of HLS do you use and how did you install it? 1.9.0.0 from gentoo linux Have you configured HLS in any way?

hie.yaml

cradle:
  cabal:

Steps to reproduce

Just open demos/Internal/GridTabularList.hs directly in an editor.

Expected behaviour

No error

Actual behaviour

Diagnostics:
1. Failed to run ["cabal","v2-repl","/path/to/brick-tabular-list/demos/Internal/GridTabularList.hs"] in directory "/path/to/brick-tabular-list". Consult the logs for full command and error.
   Failed command: cabal --builddir=$HOME/.cache/hie-bios/dist-brick-tabular-list-c78991b3683aa69b32ede05d7a2eb5f1 v2-repl --with-compiler $HOME/.cache/hie-bios/wrapper-b54f81dea4c0e6d1626911c526bc4e36 --with-hc-pkg $HOME/.cache/hie-bios/ghc-pkg-4f7979c36ba0ad4f82ac0b5533000db1 /path/to/brick-tabular-list/demos/Internal/GridTabularList.hs

   cabal: Ambiguous target
   '/path/to/brick-tabular-list/demos/Internal/GridTabularList.hs'. It could be:
   grid-tabular-list:demos/Internal/GridTabularList (file)
   grid-tabular-list-vi:demos/Internal/GridTabularList (file)

   Process Environment:
   HIE_BIOS_GHC: /usr/lib64/ghc-9.0.2/bin/ghc
   HIE_BIOS_GHC_ARGS: -B/usr/lib64/ghc-9.0.2
fendor commented 1 year ago

Thank you for the bug report! Fixing this properly in the tooling is currently not possible (i.e. requires significant effort).

As a work-around, you may extract common modules into an internal library and depend on the internal library. Cabal documentation for internal libraries: https://cabal.readthedocs.io/en/3.8/cabal-package.html?highlight=Internal Libraries#library

That, or maintain a hie.yaml which maps these shared module to one of the two executables. Example:

cradle:
  multi:
    - path: ./app/Exp.hs
      config:
        cradle:
          cabal: 
            component: "exe:exe1"
    - path: ./
      config:
        cradle:
          cabal:

See hie-bios's documentation for multi cradles for the syntax https://github.com/haskell/hie-bios#multi-cradle

amano-kenji commented 1 year ago

I created an internal library. However, if I visit the exposed library first from an executable, then there is an error because the internal library is not loaded, yet. If I visit the internal library, then the error goes away.

If I visit the internal library first from an executable module, then there is no error.

fendor commented 1 year ago

What is an error in this context? Some features not working or is HLS outright crashing?

amano-kenji commented 1 year ago

After I visit handleGridListEvent from brick-tabular-list library from an executable and get back, I get this error.

Diagnostics:
1. • Couldn't match type: GridRenderers
                            Internal.GridTabularList.Name row0 cell0 rowH0 colH0
                    with: brick-tabular-list-0.2.0.1:Brick.Widgets.TabularList.Grid.GridRenderers
                            Internal.GridTabularList.Name
                            Internal.GridTabularList.Song
                            Internal.GridTabularList.SongCell
                            Int
                            String
     Expected: Internal.GridTabularList.LibraryEventHandler
       Actual: GridRenderers
                 Internal.GridTabularList.Name row0 cell0 rowH0 colH0
               -> vty-5.38:Graphics.Vty.Input.Events.Event
               -> brick-1.6:Brick.Types.EventM.EventM
                    Internal.GridTabularList.Name
                    (GridTabularList
                       Internal.GridTabularList.Name row0 cell0 rowH0 colH0)
                    ()
     NB: ‘brick-tabular-list-0.2.0.1:Brick.Widgets.TabularList.Grid.GridRenderers’
           is defined in ‘Brick.Widgets.TabularList.Grid’
               in package ‘brick-tabular-list-0.2.0.1’
         ‘GridRenderers’ is defined at
           /path/to/brick-tabular-list/src/Brick/Widgets/TabularList/Grid.hs:(86,1)-(91,18)
   • In the second argument of ‘runMain’, namely ‘handleGridListEvent’
     In a stmt of a 'do' block: runMain msgs handleGridListEvent
     In the expression:
       do let msgs = ...
          runMain msgs handleGridListEvent

Visiting runMain from the internal library and getting back to the executable module fixes the error.

The executable depends on the internal library and the exposed library. The internal library depends on the exposed library.

Thus, if I visit the exposed library from the executable and get back to the executable, there is an error because the internal library is not yet loaded. If I visit the internal library and get back, the error goes away.

This error would not occur if haskell-language-server just loads everything from the beginning.

fendor commented 1 year ago

While this should not be happening, this issue very much different and related to multiple home units. It should be improved with #3480 I think.

amano-kenji commented 1 year ago

I'm still stuck with GHC 9.0.2 because gentoo linux can't keep up with GHC 9.2.x.

I doubt that I will ever have access to GHC 9.6 anytime soon.

fendor commented 1 year ago

Support for GHC versions that have no native support for multiple home units will always likely be buggy.

If this is just a matter of getting your hands on a recent GHC version, use ghcup, it works reliably.

amano-kenji commented 1 year ago

Does ghcup change GHC version for haskell-language-server on neovim?

fendor commented 1 year ago

That depends on the neovim plugin, not ghcup. So, I dont know.

Also, I just learned that it also works with GHC 9.4, so no need to wait on that patch.

georgefst commented 1 year ago

I created an internal library. However, if I visit the exposed library first from an executable, then there is an error because the internal library is not loaded, yet. If I visit the internal library, then the error goes away.

This is covered by https://github.com/haskell/haskell-language-server/issues/1370 (and hopefully fixed on recent GHC versions!).

amano-kenji commented 1 year ago

How is it a duplicate of 1370? It looks very different.

georgefst commented 1 year ago

Your comment https://github.com/haskell/haskell-language-server/issues/3507#issuecomment-1446009639 suggests that the error now is that HLS fails to notice that two types are the same, due to an intermediate component not being loaded. That's what #1370 is also about, and I'm pretty sure it has the same underlying cause.

Besides, as @fendor said, this is a completely different error to the one that this thread started with.

amano-kenji commented 1 year ago

fendor mentioned

Fixing this properly in the tooling is currently not possible (i.e. requires significant effort). As a work-around, you may extract common modules into an internal library and depend on the internal library.

The new error occurs with an internal library which is a workaround. The original error occurs without a workaround.

I would very much like the original issue to be documented somewhere. The fix for the workaround is captured by 1370.

georgefst commented 1 year ago

I suppose you're right.

Sorry. I got carried away and was too keen to close the issue (this project has often suffered from a lot of duplicate/fixed issues, with no one being aggressive enough about closing them...).

Although, given what I know about Cabal, I think it's quite likely this will never be fixed. Having a module belong to multiple components is one of those things that's kind-of supported, but in practice doesn't really work. Documentation would be good though, although arguably it belongs in Cabal (maybe even a run-time warning?), not HLS.

michaelpj commented 4 months ago

Do we know if the new multiple home units support fixes this, or if the multiple references to the same module remains a problem?

fendor commented 4 months ago

I think that remains a problem. The proper solution to depend on private sub-libraries, iiuc.