Splicing a type class method selects the wrong instance
Consider these 4 modules as concocted by Csongor.
The wrong instance is selected when you splice in B.me
into D
.
https://gist.github.com/mpickering/959a95525647802414ab50e8e6ed490c
module A where
class C a where
foo :: a -> String
instance C Int where
foo _ = "int"
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
module B where
import A
import Language.Haskell.TH
instance C a => C [a] where
foo _ = "list"
me :: Q (TExp ([Int] -> String))
me = [|| foo ||]
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
module C where
import A
import Language.Haskell.TH
instance {-# OVERLAPPING #-} C [Int] where
foo _ = "list2"
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
module D where
import A
import B
import C
main2 = $$(me) [1 :: Int]
>>> main2
"list2"
In B
, B.me
is created by quoting foo
. B.me :: Q (TExp ([Int] -> String))
so in order to type check this quote we need to solve the instance C [Int]
which we should do by using the instance defined in B
(and A
).
In module C
we define a different overlapping instance (note that this could be in a completely different library not under our control).
When we then splice B.me
into D
, the instance from C
is used and can be witnessed by printing main2
which shows "list2"
rather than "list"
as expected.
This is a symptom of the fact that the renamed rather than the typechecked AST is serialised I think.
Trac metadata
Trac field | Value |
---|---|
Version | 8.6.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |