Here is an hls branch with a broken test case (only runs on ghc-9.2):
https://github.com/lf-/haskell-language-server/tree/hlint-flags-bug
and the commit, for convenience: lf-@8a90d27
The issue happens in this source:
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedRecordDot #-}
module Foo (Node(..)) where
data Node = Node
{
label :: ()
}
instance Semigroup Node where
n1 <> n2 = Node
{ label = n1.label <> n2.label
-- ^^^ this is a parse error because "label" is undocumentedly a reserved word when -XForeignFunctionInterface is enabled (which it is by default)
}
The bug is that hls' hlint plugin will trigger parse errors, even if the hlint.yaml has -XNoForeignFunctionInterface in it, and also even if the cradle provides it.
It is "fixable" in a project by "haskell.plugin.hlint.config.flags": ["-XNoForeignFunctionInterface"].
The cause of this bug is that the disabled language extensions are not correctly propagated to hlint when hlint is called: only enabled extensions are propagated:
|
setExtensions flags = do |
|
hlintExts <- getExtensions nfp |
|
logWith recorder Debug $ LogUsingExtensions nfp (fmap show hlintExts) |
|
return $ flags { enabledExtensions = hlintExts } |
Unfortunately, actually retrieving disabled extensions is significantly frustrated by OnOff (https://hackage.haskell.org/package/ghc-9.2.4/docs/src/GHC.Driver.Session.html#OnOff) being a private member of GHC.Driver.Session, so it is impossible to get the disabled extensions out of DynFlags.extensions without more or less doing something like read . dropOnOffPrefix . show.
So what I am 99% sure is happening, based on putting traces in both sides, is that ForeignFunctionInterface is absent from the enabledExtensions passed to hlint if the cradle is configured with -XNoForeignFunctionInterface, but it is then reenabled because it is a default extension.
I got fairly far in fixing this, but ran up against this brick wall, and don't really have more time to commit to fixing it. So I am filing this report with the hopes that it will at least be easier to fix. I found some time :)
Your environment
..
Steps to reproduce
Run the test suite from https://github.com/lf-/haskell-language-server/tree/hlint-flags-bug
Expected behaviour
Should pass :)
Actual behaviour
src/Test/Hls/Util.hs:317:
Got unexpected diagnostics for Uri {getUri = "file:///Users/jade/co/haskell-language-server/plugins/hls-hlint-plugin/test/testdata/lab
elkeyword/LabelKeyword.hs"} got [Diagnostic {_range = Range {_start = Position {_line = 11, _character = 17}, _end = Position {_line = 11, _
character = 22}}, _severity = Just DsInfo, _code = Just (InR "parser"), _source = Just "hlint", _message = "/Users/jade/co/haskell-language-
server/plugins/hls-hlint-plugin/test/testdata/labelkeyword/LabelKeyword.hs:12:18: error:\n parse error on input `label'\n instance Semig
roup Node where\n n1 <> n2 = Node\n> { label = n1.label <> n2.label\n }\n\n", _tags = Nothing, _relatedInformation = Nothing}]
Debug information
Here is an hls branch with a broken test case (only runs on ghc-9.2):
https://github.com/lf-/haskell-language-server/tree/hlint-flags-bug
and the commit, for convenience: lf-@8a90d27
The issue happens in this source:
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE OverloadedRecordDot #-} module Foo (Node(..)) where data Node = Node { label :: () } instance Semigroup Node where n1 <> n2 = Node { label = n1.label <> n2.label -- ^^^ this is a parse error because "label" is undocumentedly a reserved word when -XForeignFunctionInterface is enabled (which it is by default) }The bug is that hls' hlint plugin will trigger parse errors, even if the hlint.yaml has
-XNoForeignFunctionInterfacein it, and also even if the cradle provides it.It is "fixable" in a project by
"haskell.plugin.hlint.config.flags": ["-XNoForeignFunctionInterface"].The cause of this bug is that the disabled language extensions are not correctly propagated to hlint when hlint is called: only enabled extensions are propagated:
haskell-language-server/plugins/hls-hlint-plugin/src/Ide/Plugin/Hlint.hs
Lines 318 to 321 in 1bc1def
Unfortunately, actually retrieving disabled extensions is significantly frustrated by OnOff (https://hackage.haskell.org/package/ghc-9.2.4/docs/src/GHC.Driver.Session.html#OnOff) being a private member of GHC.Driver.Session, so it is impossible to get the disabled extensions out of
DynFlags.extensionswithout more or less doing something likeread . dropOnOffPrefix . show.So what I am 99% sure is happening, based on putting traces in both sides, is that
ForeignFunctionInterfaceis absent from theenabledExtensionspassed to hlint if the cradle is configured with-XNoForeignFunctionInterface, but it is then reenabled because it is a default extension.I got fairly far in fixing this, but ran up against this brick wall, and don't really have more time to commit to fixing it. So I am filing this report with the hopes that it will at least be easier to fix.I found some time :)Your environment
..
Steps to reproduce
Run the test suite from https://github.com/lf-/haskell-language-server/tree/hlint-flags-bug
Expected behaviour
Should pass :)
Actual behaviour
Debug information