haskell / error-messages

71 stars 18 forks source link

GHC will recommend a module that is hidden #524

Open silky opened 2 years ago

silky commented 2 years ago

Consider:

import Data.HashMap.Strict (HashMap, insert)

f :: (Eq k) => k -> v -> HashMap k v -> HashMap k v
f = insert

Error is:

    • Could not deduce (hashable-1.3.5.0:Data.Hashable.Class.Hashable
                          k)
        arising from a use of ‘insert’

The problem is Data.Hashable.Class is hidden, so if I add:

import Data.Hashable.Class (Hashable)

I get:

/home/noon/tmp/hbl/src/Main.hs:4:1: error:
    Could not load module ‘Data.Hashable.Class’
    it is a hidden module in the package ‘hashable-1.3.5.0’
    Use -v (or `:set -v` in ghci) to see a list of the files searched for.

The actual fix here is to import Data.Hashable (Hashable).

Maybe we could do some kind of best-effort to find a publicly-exposed version of the constraint?

goldfirere commented 2 years ago

As you admit (by "best-effort"), this is hard in general. Indeed, it's possible that a library exposes a type with a class constraint such that the class cannot be imported at all. (This is likely poor design, but still possible.)

As I think about the best way to do this, I think it's best done actually by an IDE, which would have a higher-level perspective than GHC. For example, an IDE can know what modules are imported elsewhere, what packages are in a cabal file, etc. Of course, the current infrastructure makes it very difficult for the IDE to edit the error message appropriately. We need structured error messages here, but it's hard to see how to do this well otherwise..

silky commented 2 years ago

I guess I mean, GHC has two pieces of information up there that it could tie together.

It could not that it can't deduce the class; then it could pre-empt the second error message by checking if the class it wants is actually public (surely that's doable?) and if not, it could give a hint in the first error:

    • Could not deduce (hashable-1.3.5.0:Data.Hashable.Class.Hashable
                          k)
        arising from a use of ‘insert’

        Note: Data.Hashable.Class.Hashable is a hidden module in the package `hashable-1.3.5.0`, 
        but perhaps it is re-exposed by another module in that package?

?

goldfirere commented 2 years ago

The Note @silky proposes is definitely doable, yes. Does it improve the status quo?

silky commented 2 years ago

for me i would argue it probably would; i was stuck in a loop of those two errors; had i seen both pieces of information at once, i might've solved it.

( note, in my actual case, i was a bit confounded by a third issue, namely that i had two versions of hashable around, and i thought that what had happened is one version exposed it, and the other didn't; this ended up being a red herring. )