haskell / haskell/haskell-language-server

`type variable is ambiguous`-error overshadows `variable not in scope`-error

Open
#3,825 5 comments 2 reactions 0 assignees View on GitHub
type: enhancement
Dominant language
Haskell
Stars
3k
Forks
455
Avg merge
3d 21h
Merged PRs (30d)
13

Description

## Is your enhancement request related to a problem? Please describe.

Given the following code snippet

```haskell
module Bug where

import qualified Test.Hspec as HSpec

bug =
HSpec.hspec $
HSpec.describe "Unit tests" $ do
HSpec.it "some unit test case" $ do
shouldSatisfy [(1 :: Int)] (== [1])
```

Hovering over `shouldSatisfy` in VS Code the popup displays the following:

![image](https://github.com/haskell/haskell-language-server/assets/1069247/b53ca43c-4d8b-4b8e-bfc4-e46119371a14)

The error says `Couldn't match type ‘HSpec.Arg a1’ with ‘()’. The type variable ‘a1’ is ambiguous`.

Scrolling down further in the popup, however, reveals another error:

![image](https://github.com/haskell/haskell-language-server/assets/1069247/e8ded384-9a80-4867-9f05-ea126ac8c671)

Which says `Variable not in scope: shouldSatisfy`.
In other words, a not-in-scope error is causing a type-variable-is-ambiguous error, but the type-variable-is-ambiguous error appears before the not-in-scope error, making the type-variable-is-ambiguous error seem more prominent.

## Describe the solution you'd like

The not-in-scope error should be shown before the type-variable-is-ambiguous error, since fixing the former also fixes the latter.

## Describe alternatives you've considered

Alternatively, do not show the type-variable-is-ambiguous error at all, since it's caused by another error.

## Additional context

Full popup text:

```
• Couldn't match type ‘HSpec.Arg a1’ with ‘()’
Expected type: HSpec.SpecWith ()
Actual type: HSpec.SpecWith (HSpec.Arg a1)
The type variable ‘a1’ is ambiguous
• In a stmt of a 'do' block:
HSpec.it "some unit test case"
$ do shouldSatisfy [(1 :: Int)] (== [1])
In the second argument of ‘($)’, namely
‘do HSpec.it "some unit test case"
$ do shouldSatisfy [...] (== [...])’
In the second argument of ‘($)’, namely
‘HSpec.describe "Unit tests"
$ do HSpec.it "some unit test case"
$ do shouldSatisfy [...] (== [...])’typecheck(-Wdeferred-type-errors)
• Couldn't match type ‘HSpec.Arg a1’ with ‘()’
Expected type: HSpec.SpecWith ()
Actual type: HSpec.SpecWith (HSpec.Arg a1)
The type variable ‘a1’ is ambiguous
• In a stmt of a 'do' block:
HSpec.it "some unit test case"
$ do shouldSatisfy [(1 :: Int)] (== [1])
In the second argument of ‘($)’, namely
‘do HSpec.it "some unit test case"
$ do shouldSatisfy [...] (== [...])’
In the second argument of ‘($)’, namely
‘HSpec.describe "Unit tests"
$ do HSpec.it "some unit test case"
$ do shouldSatisfy [...] (== [...])’typecheck(-Wdeferred-type-errors)
• Variable not in scope:
shouldSatisfy :: [Int] -> ([a0] -> Bool) -> a1
• Perhaps you meant one of these:
‘HSpec.shouldSatisfy’ (imported from Test.Hspec),
‘HSpec.shouldNotSatisfy’ (imported from Test.Hspec)typecheck(-Wdeferred-out-of-scope-variables)
• Variable not in scope:
shouldSatisfy :: [Int] -> ([a0] -> Bool) -> a1
• Perhaps you meant one of these:
‘HSpec.shouldSatisfy’ (imported from Test.Hspec),
‘HSpec.shouldNotSatisfy’ (imported from Test.Hspec)typecheck(-Wdeferred-out-of-scope-variables)
shouldSatisfy :: [Int] -> ([Any] -> Bool) -> Any
shouldSatisfy :: [Int] -> ([Any] -> Bool) -> Any
```

HLS terminal output

```
[Info - 10:07:25 AM] Stopping the server
2023-10-03T08:07:25.442119Z | Info | Reactor thread stopped
[Info - 10:07:25 AM] Starting the server
2023-10-03T08:07:25.461945Z | Error | Got EOF
No 'hie.yaml' found. Try to discover the project type!
Run entered for haskell-language-server-wrapper(haskell-language-server-wrapper) Version 1.9.1.0 x86_64 ghc-8.10.7
Current directory: /home/runeks/code/haskell-graph/function-graph
Operating system: linux
Arguments: ["--lsp"]
Cradle directory: /home/runeks/code/haskell-graph/function-graph
Cradle type: Cabal

Tool versions found on the $PATH
cabal: 3.4.0.0
stack: 2.9.1
ghc: 8.10.7

Consulting the cradle to get project GHC version...
Project GHC version: 8.10.7
haskell-language-server exe candidates: ["haskell-language-server-8.10.7","haskell-language-server"]
Launching haskell-language-server exe at:/home/runeks/.local/bin/haskell-language-server-8.10.7
2023-10-03T08:07:27.622543Z | Info | No log file specified; using stderr.
2023-10-03T08:07:27.622922Z | Info | haskell-language-server version: 1.9.1.0 (GHC: 8.10.7) (PATH: /home/runeks/.local/bin/haskell-language-server-8.10.7-exe)
2023-10-03T08:07:27.623759Z | Info | Directory: /home/runeks/code/haskell-graph/function-graph
2023-10-03T08:07:27.623982Z | Info | Starting (haskell-language-server) LSP server...
GhcideArguments {argsCommand = LSP, argsCwd = Nothing, argsShakeProfiling = Nothing, argsTesting = False, argsExamplePlugin = False, argsDebugOn = False, argsLogFile = Nothing, argsThreads = 0, argsProjectGhcVersion = False}
PluginIds: [ pragmas
, ghcide-extend-import-action
, hlint
, qualifyImportedNames
, brittany
, explicit-fields
, changeTypeSignature
, cabal
, moduleName
, alternateNumberFormat
, splice
, ghcide-code-actions-type-signatures
, ghcide-code-actions-bindings
, tactics
, eval
, ghcide-code-actions-fill-holes
, ghcide-type-lenses
, gadt
, ghcide-completions
, ghcide-hover-and-symbols
, importLens
, LSPRecorderCallback
, cabalfmt
, codeRange
, refineImports
, retrie
, fourmolu
, callHierarchy
, ghcide-code-actions-imports-exports
, rename
, stan
, floskell
, haddockComments
, ormolu
, class
, stylish-haskell
, ghcide-core
, explicit-fixity ]
2023-10-03T08:07:27.627676Z | Info | Logging heap statistics every 60.00s
2023-10-03T08:07:27.636578Z | Info | Starting LSP server...
If you are seeing this in a terminal, you probably should have run WITHOUT the --lsp option!
PluginIds: [ pragmas
, ghcide-extend-import-action
, hlint
, qualifyImportedNames
, brittany
, explicit-fields
, changeTypeSignature
, cabal
, moduleName
, alternateNumberFormat
, splice
, ghcide-code-actions-type-signatures
, ghcide-code-actions-bindings
, tactics
, eval
, ghcide-code-actions-fill-holes
, ghcide-type-lenses
, gadt
, ghcide-completions
, ghcide-hover-and-symbols
, importLens
, LSPRecorderCallback
, cabalfmt
, codeRange
, refineImports
, retrie
, fourmolu
, callHierarchy
, ghcide-code-actions-imports-exports
, rename
, stan
, floskell
, haddockComments
, ormolu
, class
, stylish-haskell
, ghcide-core
, explicit-fixity ]
2023-10-03T08:07:27.636920Z | Info | Starting server
2023-10-03T08:07:27.638153Z | Info | Started LSP server in 0.00s
2023-10-03T08:07:28.067461Z | Info | Registering IDE configuration: IdeConfiguration {workspaceFolders = fromList [NormalizedUri 569265803354389565 "file:///home/runeks/code/haskell-graph/function-graph"], clientSettings = hashed Nothing}
[Info - 10:07:28 AM] haskell-language-server version: 1.9.1.0 (GHC: 8.10.7) (PATH: /home/runeks/.local/bin/haskell-language-server-8.10.7-exe)
[Info - 10:07:28 AM] Directory: /home/runeks/code/haskell-graph/function-graph
[Info - 10:07:28 AM] Starting (haskell-language-server) LSP server...
GhcideArguments {argsCommand = LSP, argsCwd = Nothing, argsShakeProfiling = Nothing, argsTesting = False, argsExamplePlugin = False, argsDebugOn = False, argsLogFile = Nothing, argsThreads = 0, argsProjectGhcVersion = False}
PluginIds: [ pragmas
, ghcide-extend-import-action
, hlint
, qualifyImportedNames
, brittany
, explicit-fields
, changeTypeSignature
, cabal
, moduleName
, alternateNumberFormat
, splice
, ghcide-code-actions-type-signatures
, ghcide-code-actions-bindings
, tactics
, eval
, ghcide-code-actions-fill-holes
, ghcide-type-lenses
, gadt
, ghcide-completions
, ghcide-hover-and-symbols
, importLens
, LSPRecorderCallback
, cabalfmt
, codeRange
, refineImports
, retrie
, fourmolu
, callHierarchy
, ghcide-code-actions-imports-exports
, rename
, stan
, floskell
, haddockComments
, ormolu
, class
, stylish-haskell
, ghcide-core
, explicit-fixity ]
[Info - 10:07:28 AM] Logging heap statistics every 60.00s
[Info - 10:07:28 AM] Starting LSP server...
If you are seeing this in a terminal, you probably should have run WITHOUT the --lsp option!
PluginIds: [ pragmas
, ghcide-extend-import-action
, hlint
, qualifyImportedNames
, brittany
, explicit-fields
, changeTypeSignature
, cabal
, moduleName
, alternateNumberFormat
, splice
, ghcide-code-actions-type-signatures
, ghcide-code-actions-bindings
, tactics
, eval
, ghcide-code-actions-fill-holes
, ghcide-type-lenses
, gadt
, ghcide-completions
, ghcide-hover-and-symbols
, importLens
, LSPRecorderCallback
, cabalfmt
, codeRange
, refineImports
, retrie
, fourmolu
, callHierarchy
, ghcide-code-actions-imports-exports
, rename
, stan
, floskell
, haddockComments
, ormolu
, class
, stylish-haskell
, ghcide-core
, explicit-fixity ]
[Info - 10:07:28 AM] Starting server
[Info - 10:07:28 AM] Started LSP server in 0.00s
[Info - 10:07:28 AM] Registering IDE configuration: IdeConfiguration {workspaceFolders = fromList [NormalizedUri 569265803354389565 "file:///home/runeks/code/haskell-graph/function-graph"], clientSettings = hashed Nothing}
2023-10-03T08:07:28.078684Z | Info | Cradle path: test/Bug.hs
2023-10-03T08:07:28.078810Z | Warning | No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for test/Bug.hs.
Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).
You should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error.
[Info - 10:07:28 AM] Cradle path: test/Bug.hs
[Warn - 10:07:28 AM] No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for test/Bug.hs.
Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).
You should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error.
2023-10-03T08:07:28.525295Z | Info | Cradle path: test/Spec.hs
2023-10-03T08:07:28.525455Z | Warning | No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for test/Spec.hs.
Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).
You should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error.
[Info - 10:07:28 AM] Cradle path: test/Spec.hs
[Warn - 10:07:28 AM] No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for test/Spec.hs.
Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).
You should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error.
2023-10-03T08:07:28.526515Z | Warning | eval: InternalError: Exception in plugin PluginId "eval" while processing STextDocumentCodeLens: BadDependency "GetEvalComments"
2023-10-03T08:07:28.526666Z | Warning | codeRange: bad dependency: GetCodeRange
[Warn - 10:07:28 AM] eval: InternalError: Exception in plugin PluginId "eval" while processing STextDocumentCodeLens: BadDependency "GetEvalComments"
[Error - 10:07:28 AM] Request textDocument/codeLens failed.
Message: Exception in plugin PluginId "eval" while processing STextDocumentCodeLens: BadDependency "GetEvalComments"
Code: -32603
[Warn - 10:07:28 AM] codeRange: bad dependency: GetCodeRange
2023-10-03T08:07:29.526267Z | Info | Interface files cache directory: /home/runeks/.cache/ghcide/main-e41b465447c492208a95ecd75ec685ead34347ea
2023-10-03T08:07:29.526485Z | Info | Making new HscEnv. In-place unit ids: [main]
[Info - 10:07:29 AM] Interface files cache directory: /home/runeks/.cache/ghcide/main-e41b465447c492208a95ecd75ec685ead34347ea
[Info - 10:07:29 AM] Making new HscEnv. In-place unit ids: [main]
2023-10-03T08:07:29.548625Z | Info | Cradle path: test/Bug.hs
2023-10-03T08:07:29.548784Z | Warning | No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for test/Bug.hs.
Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).
You should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error.
[Info - 10:07:29 AM] Cradle path: test/Bug.hs
[Warn - 10:07:29 AM] No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for test/Bug.hs.
Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).
You should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error.
2023-10-03T08:07:30.526490Z | Info | Interface files cache directory: /home/runeks/.cache/ghcide/main-e41b465447c492208a95ecd75ec685ead34347ea
2023-10-03T08:07:30.526783Z | Info | Interface files cache directory: /home/runeks/.cache/ghcide/main-e41b465447c492208a95ecd75ec685ead34347ea
2023-10-03T08:07:30.526891Z | Info | Making new HscEnv. In-place unit ids: [main, main]
[Info - 10:07:30 AM] Interface files cache directory: /home/runeks/.cache/ghcide/main-e41b465447c492208a95ecd75ec685ead34347ea
[Info - 10:07:30 AM] Interface files cache directory: /home/runeks/.cache/ghcide/main-e41b465447c492208a95ecd75ec685ead34347ea
[Info - 10:07:30 AM] Making new HscEnv. In-place unit ids: [main, main]
2023-10-03T08:07:30.547732Z | Info | Cradle path: src/MyLib.hs
2023-10-03T08:07:30.547874Z | Warning | No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for src/MyLib.hs.
Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).
You should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error.
[Info - 10:07:30 AM] Cradle path: src/MyLib.hs
[Warn - 10:07:30 AM] No [cradle](https://github.com/mpickering/hie-bios#hie-bios) found for src/MyLib.hs.
Proceeding with [implicit cradle](https://hackage.haskell.org/package/implicit-hie).
You should ignore this message, unless you see a 'Multi Cradle: No prefixes matched' error.
2023-10-03T08:07:31.512373Z | Info | Interface files cache directory: /home/runeks/.cache/ghcide/function-graph-0.1.0.0-inplace-5a246bfaa6aa2d265206eeedc96e42d022b744a0
2023-10-03T08:07:31.512579Z | Info | Interface files cache directory: /home/runeks/.cache/ghcide/main-e7e1daf1d99c2c60556c80e0985d67de34695189
2023-10-03T08:07:31.512662Z | Info | Interface files cache directory: /home/runeks/.cache/ghcide/main-e7e1daf1d99c2c60556c80e0985d67de34695189
2023-10-03T08:07:31.512763Z | Info | Making new HscEnv. In-place unit ids: [ function-graph-0.1.0.0-inplace
, main
, main ]
[Info - 10:07:31 AM] Interface files cache directory: /home/runeks/.cache/ghcide/function-graph-0.1.0.0-inplace-5a246bfaa6aa2d265206eeedc96e42d022b744a0
[Info - 10:07:31 AM] Interface files cache directory: /home/runeks/.cache/ghcide/main-e7e1daf1d99c2c60556c80e0985d67de34695189
[Info - 10:07:31 AM] Interface files cache directory: /home/runeks/.cache/ghcide/main-e7e1daf1d99c2c60556c80e0985d67de34695189
[Info - 10:07:31 AM] Making new HscEnv. In-place unit ids: [ function-graph-0.1.0.0-inplace
, main
, main ]
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Reproduce the diagnostics using the Haskell snippet in test/Bug.hs and the HLS setup described in the terminal output. Start by tracing how the language server orders the reported type errors and out-of-scope errors; done means the out-of-scope diagnostic appears first or the dependent ambiguity diagnostic is suppressed.

Written by the indexing model from the issue text.

Assessment

Tech stack
haskell
Domain
devtools
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.