Opened 11 months ago

Last modified 7 months ago

#15865 new bug

Typed template haskell and implicit parameters lead to incorrect results

Reported by: mpickering Owned by:
Priority: normal Milestone:
Component: Template Haskell Version: 8.6.1
Keywords: TypedTemplateHaskell Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


In a similar vein to #15863 but this time with implicit parameters.

{-# LANGUAGE ImplicitParams #-}
{-# LANGUAGE TemplateHaskell #-}
module A where

import Language.Haskell.TH
import Data.List (sortBy)

sort   :: (?cmp :: a -> a -> Ordering) => [a] -> [a]
sort    = sortBy ?cmp

me :: Q (TExp ([Int] -> [Int]))
me = let ?cmp = compare in [|| sort ||]

In module A we quote a value which has an implicit argument but in its context we bind the implicit so the type of the quote is the monomorphic type.

{-# LANGUAGE ImplicitParams #-}
{-# LANGUAGE TemplateHaskell #-}
module B where

import A

foo :: [Int] -> [Int]
foo =
  --let ?cmp = compare in

When we splice in me, we get an error about an unbound implicit parameter which is totally bogus as we already bound it in A. There is also dynamic binding if another implicit parameter with the same name is in scope but the type of me mentions nothing about implicit parameters so this shouldn't be allowed.

B.hs:8:10: error:
    • Unbound implicit parameter (?cmp::Int -> Int -> Ordering)
        arising from a use of ‘sort’
    • In the expression: sort
      In the result of the splice:
      To see what the splice expanded to, use -ddump-splices
      In the Template Haskell splice $$(me)
8 | foo = $$(me)
  |          ^^
Failed, one module loaded.

Change History (3)

comment:1 Changed 8 months ago by mpickering

Keywords: TypedTemplateHaskell added

comment:2 Changed 8 months ago by goldfire

Component: CompilerTemplate Haskell

comment:3 Changed 7 months ago by Marge Bot <ben+marge-bot@…>

In a48753b/ghc:

Capture and simplify constraints arising from running typed splices

This fixes a regression caused by #15471 where splicing in a trivial
program such as `[|| return () ||]` would fail as the dictionary for
`return` would never get bound in the module containing the splice.

Arguably this is symptomatic of a major problem affecting TTH where we
serialise renamed asts and then retype check them. The reference to the
dictionary should be fully determined at the quote site so that splicing
doesn't have to solve any implicits at all. It's a coincidence this
works due to coherence but see #15863 and #15865 for examples where
things do go very wrong.

Fixes #16195
Note: See TracTickets for help on using tickets.