haskell / haskell/haskell-language-server

`-fno-max-refinement-hole-fits` is ignored

Open
#5,001 2 comments 1 reaction 0 assignees View on GitHub
status: in discussion type: bug
Dominant language
Haskell
Stars
3k
Forks
455
Avg merge
3d 21h
Merged PRs (30d)
13

Description

### Your environment

Which OS do you use? ArchLinux

Which version of GHC do you use and how did you install it? 9.14.1 GHCup

How is your project built (alternative: link to the project)? See below

Which LSP client (editor/plugin) do you use? Terminal Vim + YCM

Which version of HLS do you use and how did you install it? 2.14.0.0 via GHCup

Have you configured HLS in any way (especially: a `hie.yaml` file)? No

### Steps to reproduce

```app.cabal
cabal-version: 3.4
name: app
version: 0.1.0.0
executable app
main-is: Main.hs
build-depends: base
hs-source-dirs: .
default-language: GHC2024
```
```cabal
packages: .
package *
ghc-options: -fno-defer-typed-holes
with-compiler: ghc-9.14.1
```
```haskell
-- This is just because to bring the number of valid holes to 7 (i.e. above the
-- default of 6)
fun :: Int -> [Int] -> [Int]
fun = _

main :: IO ()
main = do
let x :: [Int] = _ (_ :: Int) (_ :: [Int])
print x
```
Ask for diagnostics on the first `_` on line 9. You'll get:
```none
• Found hole: _ :: Int -> [Int] -> [Int]
• In the expression: _ (_ :: Int) (_ :: [Int])
In a pattern binding: x :: [Int] = _ (_ :: Int) (_ :: [Int])
In a stmt of a 'do' block:
let x :: [Int] = _ (_ :: Int) (_ :: [Int])
• Relevant bindings include
main :: IO () (bound at /home/enrico/deleteme/app/Main.hs:8:1)
Valid hole fits include
fun
(:)
drop
take
(<$)
mempty
(Some hole fits suppressed; use -fmax-valid-hole-fits=N or -fno-max-valid-hole-fits)
Valid refinement hole fits include
($!) _
const _
flip _
curry _
(!!) _
id _
(Some refinement hole fits suppressed; use -fmax-refinement-hole-fits=N or -fno-max-refinement-hole-fits) [GHC-88464]
```
revealing that the default of 6 for both `-fmax-valid-hole-fits` and `-fmax-refinement-hole-fits` causes some hole fits to be suppressed.

Now add this line
```cabal
ghc-options: -fmax-valid-hole-fits=20 -fmax-refinement-hole-fits=20
```
to the `executable app` stanza, reload HLS, and see the diagnostics again:
```none
• Found hole: _ :: Int -> [Int] -> [Int]
• In the expression: _ (_ :: Int) (_ :: [Int])
In a pattern binding: x :: [Int] = _ (_ :: Int) (_ :: [Int])
In a stmt of a 'do' block:
let x :: [Int] = _ (_ :: Int) (_ :: [Int])
• Relevant bindings include
main :: IO () (bound at /home/enrico/deleteme/app/Main.hs:8:1)
Valid hole fits include
fun
(:)
drop
take
(<$)
mempty
seq
Valid refinement hole fits include
($!) _
const _
flip _
curry _
(!!) _
scanl _
scanr _
($) _
return _
pure _
id _
head _
last _
mconcat _ [GHC-88464]
```
revealing that all holes HLS is aware of are shown now.

One last time, change the added line to this:
```cabal
ghc-options: -fno-max-valid-hole-fits -fno-max-refinement-hole-fits
```

### Expected behaviour

I would expect the same diagnostics as before.

### Actual behaviour

The diagnostic you'll get, instead, is this:
```none
• Found hole: _ :: Int -> [Int] -> [Int]
• In the expression: _ (_ :: Int) (_ :: [Int])
In a pattern binding: x :: [Int] = _ (_ :: Int) (_ :: [Int])
In a stmt of a 'do' block:
let x :: [Int] = _ (_ :: Int) (_ :: [Int])
• Relevant bindings include
main :: IO () (bound at /home/enrico/deleteme/app/Main.hs:8:1)
Valid hole fits include
fun
(:)
drop
take
(<$)
mempty
seq
Valid refinement hole fits include
($!) _
const _
flip _
curry _
(!!) _
scanl _
scanr _
id _
head _
last _
(Some refinement hole fits suppressed; use -fmax-refinement-hole-fits=N or -fno-max-refinement-hole-fits) [GHC-88464]
```
which reveals that the refinement `mconcat _` is suppressed, meaning that `-fno-max-refinement-hole-fits` is in fact ignored.

### Debug information

Not sure what else I can provide. Let me know.

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the diagnostics using app.cabal and Main.hs with GHC 9.14.1, first comparing the two GHC option configurations shown in the report. Trace how HLS consumes these options for hole-fit diagnostics; done means -fno-max-refinement-hole-fits shows all refinement fits, matching the expected output.

Written by the indexing model from the issue text.

Assessment

Tech stack
haskell
Domain
devtools
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.