Skip to content

Odd (and inconsistent) behavior when importing associated type families with (..)

Consider this program:

module Foo where

import GHC.Generics (Rep(..))

f :: Generic a => a -> Rep a ()
f = from

There are two erroneous things about this program:

  1. Rep, an associated type family of the Generic class, is imported with (..). This suggests that there are other items associated with Rep, but that doesn't really make sense for associated type families.
  2. Neither the Generic class nor its from method are in scope, despite being used in f.

Despite these errors, GHC will typecheck this program without any errors or warnings! (Not even with -Wall -Wdodgy-imports.)

To make things even stranger, if you restructure this program so that GHC.Generics is re-exported by another module:

module Bar (module GHC.Generics) where

import GHC.Generics
module Foo where

import Bar (Rep(..))

f :: Generic a => a -> Rep a ()
f = from

Then GHC will reject Foo:

$ ghc-9.6.2 Foo.hs
[1 of 2] Compiling Bar              ( Bar.hs, Bar.o )
[2 of 2] Compiling Foo              ( Foo.hs, Foo.o )

Foo.hs:5:6: error: [GHC-76037]
    Not in scope: type constructor or class ‘Generic’
    Suggested fix:
      Perhaps you want to add ‘Generic’ to the import list
      in the import of ‘Bar’ (Foo.hs:3:1-20).
  |
5 | f :: Generic a => a -> Rep a ()
  |      ^^^^^^^

This is inconsistent: I would expect the same behavior regardless of whether I'm importing GHC.Generics directly or via a module that re-exports it.

What should be the intended behavior? I'm not sure, but I would propose that GHC either accept both examples or reject both examples. The current status quo is confusing, and I ran into this issue in practice when debugging #23496.

Edited by Ryan Scott
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information