Skip to content

hlint misses -XNoForeignFunctionInterface in the cradle #3095

Open
@lf-

Description

@lf-

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions