ndmitchell / hlint

Haskell source code suggestions
Other
1.45k stars 194 forks source link

HLint hangs on the unison codebase #1443

Open philderbeast opened 1 year ago

philderbeast commented 1 year ago

I tried running HLint on the unison codebase and it hung:

$ hlint --default . > .hlint.yaml
fish: Job 1, 'hlint --default . > .hlint.yaml' terminated by signal SIGKILL (Forced quit)
shayne-fletcher commented 1 year ago

i think the command you meant was hlint --default > .hlint.yaml and that terminates i observe. i don't know for sure what hlint --default . > .hlint.yaml is going to do but my guess is it's not what you intend & probably involves checking every .hs file in the repo for hints.

philderbeast commented 1 year ago

I tried hlint --default and it dumps the default .hlint.yaml configuration file as-is but supplying one or more directories or files will then include ignores (with counts) for triggered warnings. From the root of the unison codebase (as an example), hlint --default produces a configuraition with no section entitled "# Warnings currently triggered by your code" but here is the difference in triggered warnings between supplying one directory and two, between:

  # Warnings currently triggered by your code
  - ignore: {name: "Eta reduce"} # 2 hints
  - ignore: {name: "Functor law"} # 1 hint
+ - ignore: {name: "Move brackets to avoid $"} # 1 hint
+ - ignore: {name: "Redundant <$>"} # 1 hint
- - ignore: {name: "Unused LANGUAGE pragma"} # 4 hints
+ - ignore: {name: "Unused LANGUAGE pragma"} # 6 hints
  - ignore: {name: "Use second"} # 1 hint

With hlint --default . I want to find every warning triggered by every *.hs file in the unison codebase and ignore all these hints in the configuration dump. That is a good starting point if adding something like haskell/actions/hlint-setup. Afterwards these triggered warnings can be tackled one hint at a time using the # counts to gauge how much work each hint might be to heed and not ignore (by removing the ignore rule for that hint in .hlint.yaml).

I've used hlint a lot and really like it. It has always run fast and never hung for me. The unison code base doesn't seem too big to handle and I'm wondering what in there is making hlint hang.

$ tree --prune -P '*.hs'
...
204 directories, 427 files

Even weirder, letting hlint . run interactively and watching the output scroll past, I see output that looks repetitive.

philderbeast commented 1 year ago

Found something else from looking at the output, I'm seeing a path deeper than any seen in the tree command I mentioned earlier:

$ hlint .
...
codebase2/codebase-sqlite/U/Codebase/Sqlite/Branch/Full.hs:6:1-33: Warning: Unused LANGUAGE pragma
Found:
  {-# LANGUAGE TypeApplications #-}
...
codebase2/codebase-sqlite/unison/U/Codebase/Sqlite/Branch/Full.hs:6:1-33: Warning: Unused LANGUAGE pragma
Found:
  {-# LANGUAGE TypeApplications #-}
...
codebase2/codebase-sqlite/unison/unison/U/Codebase/Sqlite/Branch/Full.hs:6:1-33: Warning: Unused LANGUAGE pragma
Found:
  {-# LANGUAGE TypeApplications #-}
...
codebase2/codebase-sqlite/unison/unison/unison/U/Codebase/Sqlite/Branch/Full.hs:6:1-33: Warning: Unused LANGUAGE pragma
Found:
  {-# LANGUAGE TypeApplications #-}
...
codebase2/codebase-sqlite/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/unison/U/Codebase/Sqlite/Branch/Full.hs:6:1-33: Warning: Unused LANGUAGE pragma
Found:
  {-# LANGUAGE TypeApplications #-}
...
shayne-fletcher commented 1 year ago

I tried hlint --default and it dumps the default [.hlint.yaml] ... I've used hlint a lot and really like it. It has always run fast and never hung for me. The unison code base doesn't seem too big to handle and I'm wondering what in there is making hlint hang.

$ tree --prune -P '*.hs'
...
204 directories, 427 files

Even weirder, letting hlint . run interactively and watching the output scroll past, I see output that looks repetitive.

thanks for elaborating for me! yes, i agree this is rather a bother then 😔

shayne-fletcher commented 1 year ago

its been running now for about 20 mins cpu time. i took some samples using activity monitor. maybe there's a clue in them

sample0.txt sample1.txt sample2.txt sample3.txt sample4.txt sample5.txt

shayne-fletcher commented 1 year ago

unison/unison/unison/

this is a pretty suspicious pattern.

googleson78 commented 1 year ago

Well, there's this symlink unison in the following directory: https://github.com/unisonweb/unison/tree/trunk/codebase2/codebase-sqlite.

It links to.. the directory itself(.). And I'm assuming hlint follows that and loops indefinitely.

So I'm not sure if this is an issue with hlint at all - following symlinks might be slightly debatable(?), but it also might be reasonable for some people's usage.

We could potentially add a --no-follow-symlinks if it turns out you do need to have that sort of symlink

philderbeast commented 1 year ago

With hlint we specify [FILE/DIR] on the command line. Is this possible with - arguments: in .hlint.yaml?

Is there a way with hlint to exclude a certain path, in this case to exclude the troublesome symlink path?

$ hlint --help
HLint v3.5, (C) Neil Mitchell 2006-2022

hlint [OPTIONS] [FILE/DIR]

Common flags:
...
    --ignore-glob=ITEM                    Ignore paths matching glob pattern
                                           (e.g. foo/bar/*.hs)
...