Open michaelpj opened 1 year ago
The "never use the user's compiler" approach is a new one to me. Have we considered it before? It seems potentially good. But I don't know what we'd need to do to beef up HLS's ghc
library into something that could actually stand in for a full GHC installation.
I'm liking the never use the user's ghc compiler option -- no more cpp!. I guess the problem is when there's a breaking change between ghc versions and a package doesn't build with the latest ghc, then hls is also unable to build it, which would not be great.
Right, so we're assuming that there are no serious behaviour changes between minor versions, which I think is fairly safe. If it's a breaking change it should be in a major version!
Right, so we're assuming that there are no serious behaviour changes between minor versions, which I think is fairly safe.
I personally don't trust this assessment.
Right, so we're assuming that there are no serious behaviour changes between minor versions, which I think is fairly safe. If it's a breaking change it should be in a major version!
Right, and even though we can't rule out the occasional minor breaking change, the benefit (not having to ship separate minor versions) probably outweighs the negatives
This issue is an attempt to write down as much of the picture around how HLS uses GHC, and especially how HLS interacts with the user's GHC.
Preliminaries
Constraints
We have some big constraints on what we can do:
Big picture
The basic picture of a HLS session is:
hie-bios
) asks the build tool (cabal) to tell us what flags are needed to build files in the project (e.g.A.hs
)A.hs
), and then processes the resulting AST in some way (e.g. to produce code actions). (HLS does much more than this, but let's focus on this for now). This requires a component (call ithls-ghc
) that must:Various approaches
This section lists various possible approaches. These clearly have some similarities but I'm just going to list them for now.
Use the
ghc
APIDecide on the
ghc
API at build timeThis is what we do today. Constraint 3 means that we therefore need one HLS binary per built compiler, which is quite painful for distribution.
Even if we could lift constraint 3, we would need one binary per minor version because of constraint 2. If we lifted constraint 2 as well, we might be able to have one binary per major version, which would be a significant improvement.
Also, since
ghc
cannot be reinstalled, this locks us into our choices of build compiler also. This is not a necessary state of affairs, contrast withghc-lib-parser
, where you can buildghc-lib-parser-9.6
with GHC 9.2. There is no necessary reason why a HLS supporting GHC X needs to be built with GHC X.Use multiple copies of the
ghc
APIA wild idea would be to move the duplication from multiple binaries into a single binary. If
ghc
was reinstallable and cabal allowed multiple instances of the same library in a build plan, then we could have multiple librarieshls-9.0
(depending onghc-9.0
),hls-9.2
(depending onghc-9.2
) etc. Each of thehls-*
libraries could have the same source files with different CPP options set. We could then bundle all of the libraries together in a single binary, with the choice of library being determined at runtime depending on the version of the user's compiler.This would essentially merge all of our current binaries (including the wrapper) into one, which would be simpler.
This would probably also only work if we manage to lift constraint 3, and it would be best if we could lift constraint 2 as well (otherwise we'd need
hls-9.0.0
,hls-9.0.1
... etc.).Use the user's compiler
We have all these problems about compatibility with the user's compiler, why not actually use it ourselves?
Over a protocol
We could imagine moving all the functionality that HLS needs into GHC, and talking to it over some protocol. This has a few problems:
However, this would solve many of the compatibility issues. We could build HLS with whatever compiler we wanted, so long as we had client libraries for all the versions of the protocol we wanted to support.
By linking the
ghc
library from the user's compilerI'm pretty sure this can't work: we'd have ABI compatibility issues between the local library and the HLS binary. It's the same problem that we already had with taking locally build libraries and loading them into HLS.
Never use the user's compiler
The other way of avoiding incompatibility with the user's compiler is not to use it. HLS has (or could have?) a working
ghc
, so we could tell the build tool to use our GHC instead of the user's one. Problems:What about constraint 1? Well, we can probably get away with processing the user's code using a different minor version of the same compiler that they are using. So if we shipped one HLS for each major version, always built with the latest minor version of that major version, then the user-visible behaviour should be pretty much identical.
So this would let us ship only one HLS per major version and not have to worry so much about ABI compatibility.
Related issues