Renamed Type Variables Leak into Error Messages and Collide
Summary
When reporting a type error, GHC may mysteriously rename certain tyvars.
Steps to reproduce
I have minimised a reproducer out of my code base:
module BadErr where
data T f a = T (f a)
class C f where
method :: f a -> r
-- badErr :: C c1 => T c1 b -> r
-- badErr = method
worseErr :: (C c1, C c2) => T c1 b -> T c2 b -> r
worseErr = method
foo :: T c a -> r
foo = undefined
bar1, bar2 :: C f => f a -> r
bar1 = foo
bar2 = foo
Expected behavior
GHC should report a type error such as:
BadErr.hs:13:12: error: [GHC-39999]
• Could not deduce ‘C (T c1)’ arising from a use of ‘method’
from the context: (C c1, C c2)
bound by the type signature for:
worseErr :: forall {k2} (c1 :: k2 -> *) (c2 :: k2 -> *) (b :: k2)
r.
(C c1, C c2) =>
T c1 b -> T c2 b -> r
at BadErr.hs:12:1-49
• In the expression: method
In an equation for ‘worseErr’: worseErr = method
|
13 | worseErr = method
| ^^^^^^
Rather confusingly, it instead produces:
BadErr.hs:13:12: error: [GHC-39999]
• Could not deduce ‘C (T c2)’ arising from a use of ‘method’
from the context: (C c2, C c3)
bound by the type signature for:
worseErr :: forall {k2} (c2 :: k2 -> *) (c3 :: k2 -> *) (b :: k2)
r.
(C c2, C c3) =>
T c2 b -> T c3 b -> r
at BadErr.hs:12:1-49
• In the expression: method
In an equation for ‘worseErr’: worseErr = method
|
13 | worseErr = method
| ^^^^^^
Note that badErr
is sufficient to produce a similar renamed error message, but worseErr
produces a new name that collides with an old name, so it's much more misleading.
Removing either bar
causes the issue to vanish, as does changing the name of the tyvar c
in the signature of foo
.
Environment
- GHC version used: 8.4.4; 9.8.2; 9.10.1