GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2020-08-25T09:55:38Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/10271Typed Template Haskell splice difficulty when resolving overloading2020-08-25T09:55:38ZSimon Peyton JonesTyped Template Haskell splice difficulty when resolving overloadingJ Garrett Morris describes the following surprising behaviour for typed Template Haskell
```
{-# LANGUAGE TemplateHaskell, FlexibleInstances #-}
module PrintfLib where
import Language.Haskell.TH
class Printf t where
print...J Garrett Morris describes the following surprising behaviour for typed Template Haskell
```
{-# LANGUAGE TemplateHaskell, FlexibleInstances #-}
module PrintfLib where
import Language.Haskell.TH
class Printf t where
printf :: String -> Q (TExp String) -> Q (TExp t)
instance Printf [Char] where
tf s t | '%' `notElem` s = [|| $$t ++ s ||]
| otherwise = fail ("Unexpected format %"
++ [c])
where (_, _:c:_) = break ('%' ==) s
instance Printf t => Printf (Char -> t) where
printf s t
| c /= 'c' = fail ("Unexpected format %" ++ [c] ++
" for character")
| otherwise = [|| \c -> $$(printf s''
[|| $$t ++ s' ++ [c] ||])
||]
where (s', '%':c:s'') = break ('%' ==) s
-------------------------
{-# LANGUAGE TemplateHaskell #-}
module Printf where
import PrintfLib
f :: Char -> String
f = $$(printf "foo %c" [||""||])
h :: Char -> String
h y = $$(printf "foo %c" [||""||]) y
```
Oddly, `f` typechecks but `h` does not, even though `h` is just an eta-expanded version of `f`:
```
Printf.hs:9:10:
No instance for (Printf t0) arising from a use of ‘printf’
The type variable ‘t0’ is ambiguous
Note: there are several potential instances:
instance Printf t => Printf (Char -> t) -- Defined in ‘PrintfLib’
instance Printf [Char] -- Defined in ‘PrintfLib’
In the expression: printf "foo %c" [|| "" ||]
```
What is going on? Here's the deal
- To run the splice, GHC must solve any constraints that arise form the expression `(printf "foo %c" ...)`.
- Since `printf` is overloaded, and overloaded on its result type, the type needed by the context of the splice is what determines which instance of `Printf` is needed.
- In `f` the context needs `Char -> String`, and so the call to `printf` must have type `TExpr (Char -> String)`, so we get the constraint `Printf (Char -> String)` which we can solve.
- But in `h` the rule for application tries to *infer* a type for the splice. So the context for the call just says `TExp t0` for some unification variable `t0`; and that leads to the insoluble constraint.
You may say that GHC should be cleverer, and push that type signature information into the application. And perhaps it should. But you can never win. For example:
```
hard x = [ $$(printf "gluk" [|| "" ||]), undefined :: Char -> String ]
```
Here the RHS of `hard` is a 2-element list. Since all elements of a list have the same type, the splice must have the same type as the second element of the list, namely `Char->String`. But seeing that would mean that we'd have to typecheck right-to-left. In general GHC tries very very hard NOT to depend on traversal order. There is no way in general to ensure that we have all the information now that constraint solving may ultimately produce.
I'm not sure what to do about this.
- It seldom matters, because resolving the overloading on the splice seldom depends on the result type.
- When it does matter, you can fix it by giving a type signature to the splice itself.
But it seems unsatisfactory. Ideas welcome.https://gitlab.haskell.org/ghc/ghc/-/issues/10945Typed Template Haskell splices broken in HEAD (7.11)2019-07-07T18:32:57ZJan Stolarekjan.stolarek@ed.ac.ukTyped Template Haskell splices broken in HEAD (7.11)In the latest HEAD (e2b579e8d77357e8b36f57d15daead101586ac8e) when I say:
```hs
$$(return [
SigD (mkName "m")
(ForallT [PlainTV (mkName "a")]
[]
(AppT (AppT ArrowT (VarT (mkName "a"))) (VarT ...In the latest HEAD (e2b579e8d77357e8b36f57d15daead101586ac8e) when I say:
```hs
$$(return [
SigD (mkName "m")
(ForallT [PlainTV (mkName "a")]
[]
(AppT (AppT ArrowT (VarT (mkName "a"))) (VarT (mkName "a"))))
, FunD (mkName "m")
[Clause [VarP (mkName "x")] (NormalB (VarE (mkName "x"))) []]
])
```
I get:
```
ghc-stage2: panic! (the 'impossible' happened)
(GHC version 7.11.20151007 for x86_64-unknown-linux):
runRnSplice
$$(return
[SigD
(mkName "m")
(ForallT
[PlainTV (mkName "a")]
[]
(AppT (AppT ArrowT (VarT (mkName "a"))) (VarT (mkName "a")))),
FunD
(mkName "m")
[Clause [VarP (mkName "x")] (NormalB (VarE (mkName "x"))) []]])
```
This code compiles correctly in GHC 7.10.1.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 7.11 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | high |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | goldfire |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Typed Template Haskell splices broken in HEAD (7.11)","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"8.0.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.11","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["goldfire"],"type":"Bug","description":"In the latest HEAD (e2b579e8d77357e8b36f57d15daead101586ac8e) when I say:\r\n\r\n{{{#!hs\r\n$$(return [\r\n SigD (mkName \"m\")\r\n (ForallT [PlainTV (mkName \"a\")]\r\n []\r\n (AppT (AppT ArrowT (VarT (mkName \"a\"))) (VarT (mkName \"a\"))))\r\n , FunD (mkName \"m\")\r\n [Clause [VarP (mkName \"x\")] (NormalB (VarE (mkName \"x\"))) []]\r\n ])\r\n}}}\r\nI get:\r\n{{{\r\nghc-stage2: panic! (the 'impossible' happened)\r\n (GHC version 7.11.20151007 for x86_64-unknown-linux):\r\n runRnSplice\r\n $$(return\r\n [SigD\r\n (mkName \"m\")\r\n (ForallT\r\n [PlainTV (mkName \"a\")]\r\n []\r\n (AppT (AppT ArrowT (VarT (mkName \"a\"))) (VarT (mkName \"a\")))),\r\n FunD\r\n (mkName \"m\")\r\n [Clause [VarP (mkName \"x\")] (NormalB (VarE (mkName \"x\"))) []]])\r\n}}}\r\nThis code compiles correctly in GHC 7.10.1.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Jan Stolarekjan.stolarek@ed.ac.ukJan Stolarekjan.stolarek@ed.ac.ukhttps://gitlab.haskell.org/ghc/ghc/-/issues/10946Typed hole inside typed Template Haskell bracket causes panic2022-01-29T16:06:57ZJan Stolarekjan.stolarek@ed.ac.ukTyped hole inside typed Template Haskell bracket causes panicWhen I say:
```hs
m :: a -> a
m x = $$([||_||])
```
I get:
```
T10946.hs:47:13:ghc: panic! (the 'impossible' happened)
(GHC version 7.10.1 for x86_64-unknown-linux):
No skolem info: a_apJ[sk]
```
This happens both with GHC ...When I say:
```hs
m :: a -> a
m x = $$([||_||])
```
I get:
```
T10946.hs:47:13:ghc: panic! (the 'impossible' happened)
(GHC version 7.10.1 for x86_64-unknown-linux):
No skolem info: a_apJ[sk]
```
This happens both with GHC 7.10.1 and latest HEAD (e2b579e8d77357e8b36f57d15daead101586ac8e).
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 7.10.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | high |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | goldfire |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Typed hole inside typed Template Haskell bracket causes panic","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"8.0.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["goldfire"],"type":"Bug","description":"When I say:\r\n\r\n{{{#!hs\r\nm :: a -> a\r\nm x = $$([||_||])\r\n}}}\r\nI get:\r\n{{{\r\nT10946.hs:47:13:ghc: panic! (the 'impossible' happened)\r\n (GHC version 7.10.1 for x86_64-unknown-linux):\r\n No skolem info: a_apJ[sk]\r\n}}}\r\nThis happens both with GHC 7.10.1 and latest HEAD (e2b579e8d77357e8b36f57d15daead101586ac8e).","type_of_failure":"OtherFailure","blocking":[]} -->8.10.2https://gitlab.haskell.org/ghc/ghc/-/issues/10949Document typed Template Haskell2021-06-30T10:40:36ZRichard Eisenbergrae@richarde.devDocument typed Template HaskellAs far as I can tell, typed Template Haskell is completely missing from the manual.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version ...As far as I can tell, typed Template Haskell is completely missing from the manual.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 7.10.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | high |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Document typed Template Haskell","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"8.0.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"As far as I can tell, typed Template Haskell is completely missing from the manual.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/11452Typed Template Haskell sneakily allows impredicativity2019-07-07T18:30:21ZRichard Eisenbergrae@richarde.devTyped Template Haskell sneakily allows impredicativityThe following module is accepted:
```hs
{-# LANGUAGE ExplicitForAll, TemplateHaskell #-}
module Bug where
impred :: forall a. a -> a
impred = $$( [|| \x -> x ||] )
```
But that requires an intermediate `TExp (forall a. a -> a)`.
Wil...The following module is accepted:
```hs
{-# LANGUAGE ExplicitForAll, TemplateHaskell #-}
module Bug where
impred :: forall a. a -> a
impred = $$( [|| \x -> x ||] )
```
But that requires an intermediate `TExp (forall a. a -> a)`.
Will fix in ongoing work.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Typed Template Haskell sneakily allows impredicativity","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"goldfire"},"version":"8.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The following module is accepted:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE ExplicitForAll, TemplateHaskell #-}\r\n\r\nmodule Bug where\r\n\r\nimpred :: forall a. a -> a\r\nimpred = $$( [|| \\x -> x ||] )\r\n}}}\r\n\r\nBut that requires an intermediate `TExp (forall a. a -> a)`.\r\n\r\nWill fix in ongoing work.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Richard Eisenbergrae@richarde.devRichard Eisenbergrae@richarde.devhttps://gitlab.haskell.org/ghc/ghc/-/issues/12103Typed Template Haskell missing utilities provided by untyped variant2019-07-07T18:27:38ZBen GamariTyped Template Haskell missing utilities provided by untyped variantCurrently typed TH feels a bit second-class as it lacks a number of handy utilities which are provided in the untyped case. In my brief look at this I encountered the following,
```hs
type TExpQ a = Q (TExp a)
stringT :: String -> TExp...Currently typed TH feels a bit second-class as it lacks a number of handy utilities which are provided in the untyped case. In my brief look at this I encountered the following,
```hs
type TExpQ a = Q (TExp a)
stringT :: String -> TExpQ String
trueT, falseT :: TExpQ Bool
```
Names still need bike-shedded.
Of course, another reasonable option would just be to rather push users to instead use quotes.8.2.1https://gitlab.haskell.org/ghc/ghc/-/issues/13587addTopDecls fails with typed Template Haskell2019-07-07T18:21:09ZTrevor L. McDonelladdTopDecls fails with typed Template HaskellThe following untyped Template Haskell works as expected:
```hs
--- AddTopDecls.hs ---
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
module AddTopDecls where
import Language.Haskell.TH
import Language.Haskell.TH.Sy...The following untyped Template Haskell works as expected:
```hs
--- AddTopDecls.hs ---
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
module AddTopDecls where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
importDoubleToDouble :: String -> ExpQ
importDoubleToDouble fname = do
n <- newName fname
d <- forImpD CCall unsafe fname n [t|Double -> Double|]
addTopDecls [d]
varE n
--- Main.hs ---
{-# LANGUAGE TemplateHaskell #-}
module Main where
import AddTopDecls
main :: IO ()
main = do
let sin' = $(importDoubleToDouble "sin")
cos' = $(importDoubleToDouble "cos")
--
print (sin' 0)
print (cos' pi)
```
However it fails if I convert to the equivalent typed version:
```hs
--- AddTopDecls.hs ---
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
module AddTopDecls where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
importDoubleToDouble :: String -> Q (TExp (Double -> Double))
importDoubleToDouble fname = do
n <- newName fname
d <- forImpD CCall unsafe fname n [t|Double -> Double|]
addTopDecls [d]
unsafeTExpCoerce (varE n)
--- Main.hs ---
{-# LANGUAGE TemplateHaskell #-}
module Main where
import AddTopDecls
main :: IO ()
main = do
let sin' = $$(importDoubleToDouble "sin")
cos' = $$(importDoubleToDouble "cos")
--
print (sin' 0)
print (cos' pi)
```
With the error:
```
> ghci Main.hs -ddump-splices
GHCi, version 8.2.0.20170404: http://www.haskell.org/ghc/ :? for help
[1 of 2] Compiling AddTopDecls ( AddTopDecls.hs, interpreted )
[2 of 2] Compiling Main ( Main.hs, interpreted )
Main.hs:9:19-44: Splicing expression
importDoubleToDouble "sin" ======> sin_a4s2
Main.hs:1:1: Splicing top-level declarations added with addTopDecls
======>
foreign import ccall unsafe "sin" Main.sin :: Double -> Double
Main.hs:9:19: error:
• GHC internal error: ‘sin_a4s2’ is not in scope during type checking, but it passed the renamer
tcl_env of environment: [a4dl :-> Identifier[sin'::t1, TopLevelLet [] False],
a4dm :-> Identifier[cos'::t1, TopLevelLet [] False],
r4cW :-> Identifier[main::IO (), TopLevelLet]]
• In the expression: sin_a4s2
In the result of the splice:
$importDoubleToDouble "sin"
To see what the splice expanded to, use -ddump-splices
In the Template Haskell splice $$(importDoubleToDouble "sin")
|
9 | let sin' = $$(importDoubleToDouble "sin")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
```
Tested with 7.10.3, 8.0.2, and 8.2.0-rc1.
Unfortunately I can't use untyped TH in my real use case, so if you have any suggestions for a workaround that would also be great.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.2.1-rc1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"addTopDecls fails with typed Template Haskell","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1-rc1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The following untyped Template Haskell works as expected:\r\n\r\n{{{#!hs\r\n--- AddTopDecls.hs ---\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE QuasiQuotes #-}\r\n\r\nmodule AddTopDecls where\r\n\r\nimport Language.Haskell.TH\r\nimport Language.Haskell.TH.Syntax\r\n\r\nimportDoubleToDouble :: String -> ExpQ\r\nimportDoubleToDouble fname = do\r\n n <- newName fname\r\n d <- forImpD CCall unsafe fname n [t|Double -> Double|]\r\n addTopDecls [d]\r\n varE n\r\n\r\n--- Main.hs ---\r\n{-# LANGUAGE TemplateHaskell #-}\r\n\r\nmodule Main where\r\n\r\nimport AddTopDecls\r\n\r\nmain :: IO ()\r\nmain = do\r\n let sin' = $(importDoubleToDouble \"sin\")\r\n cos' = $(importDoubleToDouble \"cos\")\r\n --\r\n print (sin' 0)\r\n print (cos' pi)\r\n}}}\r\n\r\nHowever it fails if I convert to the equivalent typed version:\r\n\r\n{{{#!hs\r\n--- AddTopDecls.hs ---\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE QuasiQuotes #-}\r\n\r\nmodule AddTopDecls where\r\n\r\nimport Language.Haskell.TH\r\nimport Language.Haskell.TH.Syntax\r\n\r\nimportDoubleToDouble :: String -> Q (TExp (Double -> Double))\r\nimportDoubleToDouble fname = do\r\n n <- newName fname\r\n d <- forImpD CCall unsafe fname n [t|Double -> Double|]\r\n addTopDecls [d]\r\n unsafeTExpCoerce (varE n)\r\n\r\n--- Main.hs ---\r\n{-# LANGUAGE TemplateHaskell #-}\r\n\r\nmodule Main where\r\n\r\nimport AddTopDecls\r\n\r\nmain :: IO ()\r\nmain = do\r\n let sin' = $$(importDoubleToDouble \"sin\")\r\n cos' = $$(importDoubleToDouble \"cos\")\r\n --\r\n print (sin' 0)\r\n print (cos' pi)\r\n}}}\r\n\r\nWith the error:\r\n\r\n{{{\r\n> ghci Main.hs -ddump-splices\r\nGHCi, version 8.2.0.20170404: http://www.haskell.org/ghc/ :? for help\r\n[1 of 2] Compiling AddTopDecls ( AddTopDecls.hs, interpreted )\r\n[2 of 2] Compiling Main ( Main.hs, interpreted )\r\nMain.hs:9:19-44: Splicing expression\r\n importDoubleToDouble \"sin\" ======> sin_a4s2\r\nMain.hs:1:1: Splicing top-level declarations added with addTopDecls\r\n ======>\r\n foreign import ccall unsafe \"sin\" Main.sin :: Double -> Double\r\n\r\nMain.hs:9:19: error:\r\n • GHC internal error: ‘sin_a4s2’ is not in scope during type checking, but it passed the renamer\r\n tcl_env of environment: [a4dl :-> Identifier[sin'::t1, TopLevelLet [] False],\r\n a4dm :-> Identifier[cos'::t1, TopLevelLet [] False],\r\n r4cW :-> Identifier[main::IO (), TopLevelLet]]\r\n • In the expression: sin_a4s2\r\n In the result of the splice:\r\n $importDoubleToDouble \"sin\"\r\n To see what the splice expanded to, use -ddump-splices\r\n In the Template Haskell splice $$(importDoubleToDouble \"sin\")\r\n |\r\n9 | let sin' = $$(importDoubleToDouble \"sin\")\r\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^\r\n}}}\r\n\r\nTested with 7.10.3, 8.0.2, and 8.2.0-rc1.\r\n\r\nUnfortunately I can't use untyped TH in my real use case, so if you have any suggestions for a workaround that would also be great.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/15437Internal error when applying a scoped type variable inside a typed expression...2023-08-11T11:04:21ZdminuosoInternal error when applying a scoped type variable inside a typed expression quotation```hs
{-# LANGUAGE TemplateHaskell #-}
import TestMod
f :: Int
f = $$(foo)
main :: IO ()
main = main
```
```hs
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
module TestMod wh...```hs
{-# LANGUAGE TemplateHaskell #-}
import TestMod
f :: Int
f = $$(foo)
main :: IO ()
main = main
```
```hs
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
module TestMod where
import Language.Haskell.TH.Syntax (Q, TExp)
get :: forall a. Int
get = 1
foo :: forall a. Q (TExp Int)
foo = [|| get @a ||]
```
```
Test.hs:6:8: error:
• The exact Name ‘a’ is not in scope
Probable cause: you used a unique Template Haskell name (NameU),
perhaps via newName, but did not bind it
If that's it, then -ddump-splices might be useful
• In the result of the splice:
$foo
To see what the splice expanded to, use -ddump-splices
In the Template Haskell splice $$(foo)
In the expression: $$(foo)
|
6 | f = $$(foo)
| ^^^
Test.hs:6:8: error:
• GHC internal error: ‘a’ is not in scope during type checking, but it passed the renamer
tcl_env of environment: [r3Kl :-> Identifier[f::Int, TopLevelLet [] True],
r3PI :-> Identifier[main::IO (), TopLevelLet [r3PI :-> main] True]]
• In the type ‘a’
In the expression: get @a
In the result of the splice:
$foo
To see what the splice expanded to, use -ddump-splices
|
6 | f = $$(foo)
|
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.4.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Internal error when applying a scoped type variable inside a typed expression quotation","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n\r\nimport TestMod\r\n\r\nf :: Int\r\nf = $$(foo)\r\n\r\nmain :: IO ()\r\nmain = main\r\n}}}\r\n\r\n{{{#!hs\r\n{-# LANGUAGE ScopedTypeVariables #-}\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE TypeApplications #-}\r\n\r\nmodule TestMod where\r\n\r\nimport Language.Haskell.TH.Syntax (Q, TExp)\r\n\r\nget :: forall a. Int\r\nget = 1\r\n\r\nfoo :: forall a. Q (TExp Int)\r\nfoo = [|| get @a ||]\r\n}}}\r\n\r\n{{{\r\nTest.hs:6:8: error:\r\n • The exact Name ‘a’ is not in scope\r\n Probable cause: you used a unique Template Haskell name (NameU),\r\n perhaps via newName, but did not bind it\r\n If that's it, then -ddump-splices might be useful\r\n • In the result of the splice:\r\n $foo\r\n To see what the splice expanded to, use -ddump-splices\r\n In the Template Haskell splice $$(foo)\r\n In the expression: $$(foo)\r\n |\r\n6 | f = $$(foo)\r\n | ^^^\r\n\r\nTest.hs:6:8: error:\r\n • GHC internal error: ‘a’ is not in scope during type checking, but it passed the renamer\r\n tcl_env of environment: [r3Kl :-> Identifier[f::Int, TopLevelLet [] True],\r\n r3PI :-> Identifier[main::IO (), TopLevelLet [r3PI :-> main] True]]\r\n • In the type ‘a’\r\n In the expression: get @a\r\n In the result of the splice:\r\n $foo\r\n To see what the splice expanded to, use -ddump-splices\r\n |\r\n6 | f = $$(foo)\r\n |\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->8.10.2https://gitlab.haskell.org/ghc/ghc/-/issues/15471Polymorphism, typed splices and type inference don't mix2019-07-07T18:04:36ZMatthew PickeringPolymorphism, typed splices and type inference don't mixTrying to quote and splice a polymorphic function doesn't work unless you have a type signature.
```
{-# LANGUAGE TemplateHaskell #-}
module A where
foo1 x = x
test_foo = [|| foo1 ||]
```
```
{-# LANGUAGE TemplateHaskell #-}
module B...Trying to quote and splice a polymorphic function doesn't work unless you have a type signature.
```
{-# LANGUAGE TemplateHaskell #-}
module A where
foo1 x = x
test_foo = [|| foo1 ||]
```
```
{-# LANGUAGE TemplateHaskell #-}
module B where
import A
qux = $$(test_foo)
```
The type of `qux` is `Any -> Any`! Which is clearly wrong.
Adding a type signature to `qux` fixes the problem.
```
qux :: a -> a
qux = $$(test_foo)
```
Either there should be a better error or this should just work.
It seems that this has always been broken. Ryan tested on GHC 7.8.4 for me.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.4.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Polymorphism, typed splices and type inference don't mix","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Trying to quote and splice a polymorphic function doesn't work unless you have a type signature.\r\n\r\n{{{\r\n{-# LANGUAGE TemplateHaskell #-}\r\nmodule A where\r\n\r\nfoo1 x = x\r\n\r\ntest_foo = [|| foo1 ||]\r\n}}}\r\n\r\n{{{\r\n{-# LANGUAGE TemplateHaskell #-}\r\nmodule B where\r\n\r\nimport A\r\n\r\nqux = $$(test_foo)\r\n}}}\r\n\r\nThe type of `qux` is `Any -> Any`! Which is clearly wrong.\r\n\r\nAdding a type signature to `qux` fixes the problem.\r\n\r\n{{{\r\nqux :: a -> a\r\nqux = $$(test_foo)\r\n}}}\r\n\r\nEither there should be a better error or this should just work.\r\n\r\nIt seems that this has always been broken. Ryan tested on GHC 7.8.4 for me.","type_of_failure":"OtherFailure","blocking":[]} -->8.8.1https://gitlab.haskell.org/ghc/ghc/-/issues/15833Typed template haskell quote fails to typecheck when spliced due to an ambigu...2019-07-07T18:02:48ZMatthew PickeringTyped template haskell quote fails to typecheck when spliced due to an ambiguous type variableIt should be the case that a code value constructed using typed template haskell should never fail to type check when spliced. Running `ghc Test.hs` with the following two modules produces an error about an ambiguous type variable.
http...It should be the case that a code value constructed using typed template haskell should never fail to type check when spliced. Running `ghc Test.hs` with the following two modules produces an error about an ambiguous type variable.
https://gist.github.com/5890c14dda73da738d2041c7f677b786
```
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wall #-}
module Compiler where
import Language.Haskell.TH
data Operator = Scan
| Join Operator Operator deriving Show
queryJoin :: Operator
queryJoin = Join Scan Scan
type QTExp a = Q (TExp a)
fix :: (a -> a) -> a
fix f = let x = f x in x
while ::
Monoid m =>
QTExp (IO m -> IO m) -> QTExp (IO m)
while b = [|| fix (\r -> whenM True ($$b r)) ||]
whenM :: Monoid m => Bool -> m -> m
whenM b act = if b then act else mempty
execOp :: Monoid m => Operator -> QTExp (IO m) -> QTExp (IO m)
execOp op yld =
case op of
Scan ->
while [|| \r -> ($$(yld) >> r)||]
Join left right ->
execOp left (execOp right yld)
runQuery :: QTExp (IO ())
runQuery = execOp (Join Scan Scan) ([|| return () ||])
```
```
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Test where
import qualified Compiler as C
main :: IO ()
main = do
$$(C.runQuery)
```
```
Test.hs:9:6: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘C.whenM’
prevents the constraint ‘(Monoid a0)’ from being solved.
Relevant bindings include r_a5GX :: IO a0 (bound at Test.hs:9:6)
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Monoid a => Monoid (IO a) -- Defined in ‘GHC.Base’
instance Monoid Ordering -- Defined in ‘GHC.Base’
instance Semigroup a => Monoid (Maybe a) -- Defined in ‘GHC.Base’
...plus 7 others
(use -fprint-potential-instances to see them all)
• In the expression:
(C.whenM True) ((\ r_a5GY -> ((return ()) >> r_a5GY)) r_a5GX)
In the first argument of ‘C.fix’, namely
‘(\ r_a5GX
-> (C.whenM True) ((\ r_a5GY -> ((return ()) >> r_a5GY)) r_a5GX))’
In the first argument of ‘(>>)’, namely
‘(C.fix
(\ r_a5GX
-> (C.whenM True) ((\ r_a5GY -> ((return ()) >> r_a5GY)) r_a5GX)))’
|
9 | $$(C.runQuery)
|
```
The generated code
```
Test.hs:9:6-15: Splicing expression
C.runQuery
======>
C.fix
(\ r_a5GV
-> (C.whenM True)
((\ r_a5GW
-> ((C.fix
(\ r_a5GX
-> (C.whenM True)
((\ r_a5GY -> ((return GHC.Tuple.()) >> r_a5GY)) r_a5GX)))
>> r_a5GW))
r_a5GV))
```
<details><summary>Trac metadata</summary>
| 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 | |
</details>
<!-- {"blocked_by":[],"summary":"Typed template haskell quote fails to typecheck when spliced due to an ambiguous type variable","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"It should be the case that a code value constructed using typed template haskell should never fail to type check when spliced. Running `ghc Test.hs` with the following two modules produces an error about an ambiguous type variable. \r\n\r\nhttps://gist.github.com/5890c14dda73da738d2041c7f677b786\r\n\r\n\r\n{{{\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# OPTIONS_GHC -Wall #-}\r\nmodule Compiler where\r\n\r\nimport Language.Haskell.TH\r\n\r\ndata Operator = Scan\r\n | Join Operator Operator deriving Show\r\n\r\nqueryJoin :: Operator\r\nqueryJoin = Join Scan Scan\r\n\r\ntype QTExp a = Q (TExp a)\r\n\r\nfix :: (a -> a) -> a\r\nfix f = let x = f x in x\r\n\r\nwhile ::\r\n Monoid m =>\r\n QTExp (IO m -> IO m) -> QTExp (IO m)\r\nwhile b = [|| fix (\\r -> whenM True ($$b r)) ||]\r\n\r\nwhenM :: Monoid m => Bool -> m -> m\r\nwhenM b act = if b then act else mempty\r\n\r\nexecOp :: Monoid m => Operator -> QTExp (IO m) -> QTExp (IO m)\r\nexecOp op yld =\r\n case op of\r\n Scan ->\r\n while [|| \\r -> ($$(yld) >> r)||]\r\n Join left right ->\r\n execOp left (execOp right yld)\r\n\r\nrunQuery :: QTExp (IO ())\r\nrunQuery = execOp (Join Scan Scan) ([|| return () ||])\r\n}}}\r\n\r\n{{{\r\n\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# OPTIONS_GHC -ddump-splices #-}\r\nmodule Test where\r\n\r\nimport qualified Compiler as C\r\n\r\nmain :: IO ()\r\nmain = do\r\n$$(C.runQuery)\r\n\r\n}}}\r\n\r\n{{{\r\nTest.hs:9:6: error:\r\n • Ambiguous type variable ‘a0’ arising from a use of ‘C.whenM’\r\n prevents the constraint ‘(Monoid a0)’ from being solved.\r\n Relevant bindings include r_a5GX :: IO a0 (bound at Test.hs:9:6)\r\n Probable fix: use a type annotation to specify what ‘a0’ should be.\r\n These potential instances exist:\r\n instance Monoid a => Monoid (IO a) -- Defined in ‘GHC.Base’\r\n instance Monoid Ordering -- Defined in ‘GHC.Base’\r\n instance Semigroup a => Monoid (Maybe a) -- Defined in ‘GHC.Base’\r\n ...plus 7 others\r\n (use -fprint-potential-instances to see them all)\r\n • In the expression:\r\n (C.whenM True) ((\\ r_a5GY -> ((return ()) >> r_a5GY)) r_a5GX)\r\n In the first argument of ‘C.fix’, namely\r\n ‘(\\ r_a5GX\r\n -> (C.whenM True) ((\\ r_a5GY -> ((return ()) >> r_a5GY)) r_a5GX))’\r\n In the first argument of ‘(>>)’, namely\r\n ‘(C.fix\r\n (\\ r_a5GX\r\n -> (C.whenM True) ((\\ r_a5GY -> ((return ()) >> r_a5GY)) r_a5GX)))’\r\n |\r\n9 | $$(C.runQuery)\r\n | \r\n}}}\r\n\r\nThe generated code\r\n\r\n{{{\r\nTest.hs:9:6-15: Splicing expression\r\n C.runQuery\r\n ======>\r\n C.fix\r\n (\\ r_a5GV\r\n -> (C.whenM True)\r\n ((\\ r_a5GW\r\n -> ((C.fix\r\n (\\ r_a5GX\r\n -> (C.whenM True)\r\n ((\\ r_a5GY -> ((return GHC.Tuple.()) >> r_a5GY)) r_a5GX)))\r\n >> r_a5GW))\r\n r_a5GV))\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/15835Internal error when splicing value constructed using typed template haskell2019-07-07T18:02:47ZMatthew PickeringInternal error when splicing value constructed using typed template haskellRelated to #15833
Compiling Test.hs leads to an internal compiler error.
https://gist.github.com/f04a613bb5e20c241c5b91c2f38b8f06
```
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Test where
import qualif...Related to #15833
Compiling Test.hs leads to an internal compiler error.
https://gist.github.com/f04a613bb5e20c241c5b91c2f38b8f06
```
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Test where
import qualified Compiler as C
main :: IO ()
main = $$(C.runQuery)
```
```
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -Wall #-}
module Compiler where
import Language.Haskell.TH
type QTExp a = Q (TExp a)
fix :: (a -> a) -> a
fix f = let x = f x in x
while ::
forall m . Monoid m =>
QTExp (IO m -> IO m) -> QTExp (IO m)
while b = [|| fix (\r -> whenM @(IO m) ($$b r)) ||]
whenM :: Monoid m => m -> m
whenM _ = mempty
execOp :: forall m . Monoid m => QTExp (IO m)
execOp = while [|| \r -> $$(while @m [|| id ||]) >> r ||]
runQuery :: QTExp (IO ())
runQuery = execOp
```
Leads to the following internal errors even though `Compiler` type checked.
```
Prelude> :r
[1 of 2] Compiling Compiler ( Compiler.hs, interpreted )
[2 of 2] Compiling Test ( Test.hs, interpreted )
Test.hs:9:6-15: Splicing expression
C.runQuery
======>
C.fix
(\ r_a7K7
-> (C.whenM @(IO m_a7Gp))
((\ r_a7K8
-> ((C.fix (\ r_a7K9 -> (C.whenM @(IO m_a7Gp)) (id r_a7K9)))
>> r_a7K8))
r_a7K7))
Test.hs:9:6: error:
• The exact Name ‘m’ is not in scope
Probable cause: you used a unique Template Haskell name (NameU),
perhaps via newName, but did not bind it
If that's it, then -ddump-splices might be useful
• In the result of the splice:
$C.runQuery
To see what the splice expanded to, use -ddump-splices
In the Template Haskell splice $$(C.runQuery)
In a stmt of a 'do' block: $$(C.runQuery)
|
9 | $$(C.runQuery)
| ^^^^^^^^^^
Test.hs:9:6: error:
• The exact Name ‘m’ is not in scope
Probable cause: you used a unique Template Haskell name (NameU),
perhaps via newName, but did not bind it
If that's it, then -ddump-splices might be useful
• In the result of the splice:
$C.runQuery
To see what the splice expanded to, use -ddump-splices
In the Template Haskell splice $$(C.runQuery)
In a stmt of a 'do' block: $$(C.runQuery)
|
9 | $$(C.runQuery)
| ^^^^^^^^^^
Test.hs:9:6: error:
• GHC internal error: ‘m’ is not in scope during type checking, but it passed the renamer
tcl_env of environment: [a7K7 :-> Identifier[r_a7K7::a0, NotLetBound],
r5Fg :-> Identifier[main::IO (), TopLevelLet [] True]]
• In the first argument of ‘IO’, namely ‘m’
In the type ‘(IO m)’
In the expression:
(C.whenM @(IO m))
((\ r_a7K8
-> ((C.fix (\ r_a7K9 -> (C.whenM @(IO m)) (id r_a7K9))) >> r_a7K8))
r_a7K7)
|
9 | $$(C.runQuery)
|
```
<details><summary>Trac metadata</summary>
| 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 | |
</details>
<!-- {"blocked_by":[],"summary":"Internal error when splicing value constructed using typed template haskell","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Related to #15833\r\n\r\nCompiling Test.hs leads to an internal compiler error. \r\n\r\nhttps://gist.github.com/f04a613bb5e20c241c5b91c2f38b8f06\r\n\r\n{{{\r\n\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# OPTIONS_GHC -ddump-splices #-}\r\nmodule Test where\r\n\r\nimport qualified Compiler as C\r\n\r\nmain :: IO ()\r\nmain = do\r\n$$(C.runQuery)\r\n}}}\r\n\r\n{{{\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE ScopedTypeVariables #-}\r\n{-# LANGUAGE TypeApplications #-}\r\n{-# OPTIONS_GHC -Wall #-}\r\nmodule Compiler where\r\n\r\nimport Language.Haskell.TH\r\n\r\ntype QTExp a = Q (TExp a)\r\n\r\nfix :: (a -> a) -> a\r\nfix f = let x = f x in x\r\n\r\nwhile ::\r\n forall m . Monoid m =>\r\n QTExp (IO m -> IO m) -> QTExp (IO m)\r\nwhile b = [|| fix (\\r -> whenM @(IO m) ($$b r)) ||]\r\n\r\nwhenM :: Monoid m => m -> m\r\nwhenM _ = mempty\r\n\r\nexecOp :: forall m . Monoid m => QTExp (IO m)\r\nexecOp = while [|| \\r -> $$(while @m [|| id ||]) >> r ||]\r\n\r\nrunQuery :: QTExp (IO ())\r\nrunQuery = execOp\r\n}}}\r\n\r\n\r\n\r\nLeads to the following internal errors even though `Compiler` type checked.\r\n\r\n{{{\r\nPrelude> :r\r\n[1 of 2] Compiling Compiler ( Compiler.hs, interpreted )\r\n[2 of 2] Compiling Test ( Test.hs, interpreted )\r\nTest.hs:9:6-15: Splicing expression\r\n C.runQuery\r\n ======>\r\n C.fix\r\n (\\ r_a7K7\r\n -> (C.whenM @(IO m_a7Gp))\r\n ((\\ r_a7K8\r\n -> ((C.fix (\\ r_a7K9 -> (C.whenM @(IO m_a7Gp)) (id r_a7K9)))\r\n >> r_a7K8))\r\n r_a7K7))\r\n\r\nTest.hs:9:6: error:\r\n • The exact Name ‘m’ is not in scope\r\n Probable cause: you used a unique Template Haskell name (NameU), \r\n perhaps via newName, but did not bind it\r\n If that's it, then -ddump-splices might be useful\r\n • In the result of the splice:\r\n $C.runQuery\r\n To see what the splice expanded to, use -ddump-splices\r\n In the Template Haskell splice $$(C.runQuery)\r\n In a stmt of a 'do' block: $$(C.runQuery)\r\n |\r\n9 | $$(C.runQuery)\r\n | ^^^^^^^^^^\r\n\r\nTest.hs:9:6: error:\r\n • The exact Name ‘m’ is not in scope\r\n Probable cause: you used a unique Template Haskell name (NameU), \r\n perhaps via newName, but did not bind it\r\n If that's it, then -ddump-splices might be useful\r\n • In the result of the splice:\r\n $C.runQuery\r\n To see what the splice expanded to, use -ddump-splices\r\n In the Template Haskell splice $$(C.runQuery)\r\n In a stmt of a 'do' block: $$(C.runQuery)\r\n |\r\n9 | $$(C.runQuery)\r\n | ^^^^^^^^^^\r\n\r\nTest.hs:9:6: error:\r\n • GHC internal error: ‘m’ is not in scope during type checking, but it passed the renamer\r\n tcl_env of environment: [a7K7 :-> Identifier[r_a7K7::a0, NotLetBound],\r\n r5Fg :-> Identifier[main::IO (), TopLevelLet [] True]]\r\n • In the first argument of ‘IO’, namely ‘m’\r\n In the type ‘(IO m)’\r\n In the expression:\r\n (C.whenM @(IO m))\r\n ((\\ r_a7K8\r\n -> ((C.fix (\\ r_a7K9 -> (C.whenM @(IO m)) (id r_a7K9))) >> r_a7K8))\r\n r_a7K7)\r\n |\r\n9 | $$(C.runQuery)\r\n | \r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->
https://gitlab.haskell.org/ghc/ghc/-/issues/15863Splicing a type class method selects the wrong instance2019-07-07T18:02:40ZMatthew PickeringSplicing a type class method selects the wrong instanceConsider 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 ->...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.
<details><summary>Trac metadata</summary>
| 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 | |
</details>
<!-- {"blocked_by":[],"summary":"Splcing a type class method selects the wrong instance","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Consider these 4 modules as concocted by Csongor. \r\n\r\nThe wrong instance is selected when you splice in `B.me` into `D`.\r\n\r\nhttps://gist.github.com/mpickering/959a95525647802414ab50e8e6ed490c\r\n\r\n{{{\r\nmodule A where\r\n\r\nclass C a where\r\n foo :: a -> String\r\n\r\ninstance C Int where\r\nfoo _ = \"int\"\r\n}}}\r\n\r\n{{{\r\n{-# LANGUAGE FlexibleInstances #-}\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE NoMonomorphismRestriction #-}\r\nmodule B where\r\n\r\nimport A\r\n\r\nimport Language.Haskell.TH\r\n\r\ninstance C a => C [a] where\r\n foo _ = \"list\"\r\n\r\nme :: Q (TExp ([Int] -> String))\r\nme = [|| foo ||]\r\n}}}\r\n\r\n{{{\r\n{-# LANGUAGE FlexibleInstances #-}\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE NoMonomorphismRestriction #-}\r\nmodule C where\r\n\r\nimport A\r\n\r\nimport Language.Haskell.TH\r\n\r\ninstance {-# OVERLAPPING #-} C [Int] where\r\nfoo _ = \"list2\"\r\n}}}\r\n\r\n{{{\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE NoMonomorphismRestriction #-}\r\nmodule D where\r\n\r\nimport A\r\nimport B\r\nimport C\r\n\r\nmain2 = $$(me) [1 :: Int]\r\n}}}\r\n\r\n{{{\r\n>>> main2\r\n\"list2\"\r\n}}}\r\n\r\n\r\nIn `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`). \r\n\r\nIn module `C` we define a different overlapping instance (note that this could be in a completely different library not under our control).\r\n\r\nWhen 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.\r\n\r\nThis is a symptom of the fact that the renamed rather than the typechecked AST is serialised I think.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/15865Typed template haskell and implicit parameters lead to incorrect results2020-10-30T19:29:43ZMatthew PickeringTyped template haskell and implicit parameters lead to incorrect resultsIn a similar vein to #15863 but this time with implicit parameters.
https://gist.github.com/b6919b13abe0954fdad844e16e0edb48
```
{-# LANGUAGE ImplicitParams #-}
{-# LANGUAGE TemplateHaskell #-}
module A where
import Language.Haskell.T...In a similar vein to #15863 but this time with implicit parameters.
https://gist.github.com/b6919b13abe0954fdad844e16e0edb48
```
{-# 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
$$(me)
```
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:
$me
To see what the splice expanded to, use -ddump-splices
In the Template Haskell splice $$(me)
|
8 | foo = $$(me)
| ^^
Failed, one module loaded.
```
<details><summary>Trac metadata</summary>
| 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 | |
</details>
<!-- {"blocked_by":[],"summary":"Typed template haskell and implicit parameters lead to incorrect results","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"In a similar vein to #15863 but this time with implicit parameters.\r\n\r\nhttps://gist.github.com/b6919b13abe0954fdad844e16e0edb48\r\n\r\n{{{\r\n{-# LANGUAGE ImplicitParams #-}\r\n{-# LANGUAGE TemplateHaskell #-}\r\nmodule A where\r\n\r\nimport Language.Haskell.TH\r\nimport Data.List (sortBy)\r\n\r\n\r\nsort :: (?cmp :: a -> a -> Ordering) => [a] -> [a]\r\nsort = sortBy ?cmp\r\n\r\nme :: Q (TExp ([Int] -> [Int]))\r\nme = let ?cmp = compare in [|| sort ||]\r\n}}}\r\n\r\nIn 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.\r\n\r\n{{{\r\n{-# LANGUAGE ImplicitParams #-}\r\n{-# LANGUAGE TemplateHaskell #-}\r\nmodule B where\r\n\r\nimport A\r\n\r\nfoo :: [Int] -> [Int]\r\nfoo =\r\n --let ?cmp = compare in\r\n $$(me)\r\n}}}\r\n\r\nWhen 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.\r\n\r\n{{{\r\nB.hs:8:10: error:\r\n • Unbound implicit parameter (?cmp::Int -> Int -> Ordering)\r\n arising from a use of ‘sort’\r\n • In the expression: sort\r\n In the result of the splice:\r\n $me\r\n To see what the splice expanded to, use -ddump-splices\r\n In the Template Haskell splice $$(me)\r\n |\r\n8 | foo = $$(me)\r\n | ^^\r\nFailed, one module loaded.\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/16169Unused variable warning affects compositionality when generating code2019-10-03T08:46:45ZMatthew PickeringUnused variable warning affects compositionality when generating codeIf I'm generating a program using template haskell, I might define
a combinator to help me generate lambdas.
```
type Code a = Q (TExp a)
_lam :: (Code a -> Code b) -> Code (a -> b)
_lam f = [|| \a -> $$(f [|| a ||]) ||]
```
However, ...If I'm generating a program using template haskell, I might define
a combinator to help me generate lambdas.
```
type Code a = Q (TExp a)
_lam :: (Code a -> Code b) -> Code (a -> b)
_lam f = [|| \a -> $$(f [|| a ||]) ||]
```
However, if I now pass a constant function into `_lam`, the generated code contains an unused variable `a` that I can do nothing about and desire not to do anything about.
```
c5 :: Code (a -> Int)
c5 = _lam (const [|| 5 ||])
```
However, GHC decides that it's wise to warn me about this when I splice it in.
```
> $$c5
F2.hs:6:5: warning: [-Wunused-matches] Defined but not used: ‘a’
|
6 | q = $$c5
| ^^^
```
As Ryan will tell you, I'm against emitting warnings from generated code as it breaks the abstraction. The code that is generated is guaranteed to be type and scope correct but any aesthetic warning is irrelevant to the consumer.
I see it in precisely the same way as warning if we use a function that contains an unused variable in a library. Once the definition is exported from the library, its definition is opaque. The same principle should be applied to code generated by template haskell.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.6.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Unused variable warning affects compositionality when generating code","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"If I'm generating a program using template haskell, I might define\r\na combinator to help me generate lambdas. \r\n\r\n{{{\r\ntype Code a = Q (TExp a)\r\n\r\n_lam :: (Code a -> Code b) -> Code (a -> b)\r\n_lam f = [|| \\a -> $$(f [|| a ||]) ||]\r\n}}}\r\n\r\nHowever, if I now pass a constant function into `_lam`, the generated code contains an unused variable `a` that I can do nothing about and desire not to do anything about.\r\n\r\n{{{\r\nc5 :: Code (a -> Int)\r\nc5 = _lam (const [|| 5 ||])\r\n}}}\r\n\r\nHowever, GHC decides that it's wise to warn me about this when I splice it in.\r\n\r\n{{{\r\n> $$c5\r\nF2.hs:6:5: warning: [-Wunused-matches] Defined but not used: ‘a’\r\n |\r\n6 | q = $$c5\r\n | ^^^\r\n}}}\r\n\r\nAs Ryan will tell you, I'm against emitting warnings from generated code as it breaks the abstraction. The code that is generated is guaranteed to be type and scope correct but any aesthetic warning is irrelevant to the consumer. \r\n\r\nI see it in precisely the same way as warning if we use a function that contains an unused variable in a library. Once the definition is exported from the library, its definition is opaque. The same principle should be applied to code generated by template haskell. \r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/16176Let-insertion for template haskell2019-07-07T18:01:07ZMatthew PickeringLet-insertion for template haskellWhen using Template Haskell to generate programs it's very easy to end up with a lot of duplication as splices are naively spliced in place.
For example
```
foo x = [|| $$x + $$x ||]
```
Will generate a program which completely duplic...When using Template Haskell to generate programs it's very easy to end up with a lot of duplication as splices are naively spliced in place.
For example
```
foo x = [|| $$x + $$x ||]
```
Will generate a program which completely duplicates its argument. In this case I can manually remove the duplicate by inserting a let.
```
foo x = [|| let x' = $$x in x' + x' ||]
```
Not too bad but a bit annoying to have to do manually.
When constructing bigger programs however this process becomes tedious or impossible to do correctly by hand.
```
foo :: (Q (TExp (Bool)) -> Q (TExp Int)) -> Q (TExp Int)
foo xf = [|| (let x = True in $$(xf [|| x ||])) + (let x = False in $$(xf [|| x ||]) ||]
```
Now if I pass a constant function to `foo`, the resulting code won't mention `x` so it could be floated out. However, there's not way I can tell that without running `xf` so I can't perform the same transformation as I did for the earlier program and manually insert a let. In the case of splicing in fully static data you really want it to float to the top-level and turn into a CAF.
The proposal of this ticket is to implement something like the mechanism for let-insertion in
metaocaml.
http://okmij.org/ftp/meta-programming/\#let-insert
We add two new primitives:
```
genlet :: Q (TExp a) -> Q (TExp a)
let_locus :: Q (TExp a) -> Q (TExp a)
```
`genlet` marks a code value that we want to float. `let_locus` marks places where we want to insert a let. When we evaluate the code fragment and encounter a `genlet` call, whatever the argument evaluates to is floated as far upwards as possible and inserted at the position of one of the loci.
For example,
```
sqr :: Code Int -> Code Int
sqr c = [|| $$c + $$c ||]
sqr_let :: Code Int -> Code Int
sqr_let c = let_locus (sqr (genlet c))
```
Splicing `sqr [|| 1 ||]` will result in `1 + 1` but `sqr_let [|| c ||]` will equal `let x = 1 in x + x ||]`.
It's important to do this earlier rather than later as a lot of duplication can take place which the simplifier does not like.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.6.3 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Let-insertion for template haskell","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.3","keywords":["TypedTemplateHaskell"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"When using Template Haskell to generate programs it's very easy to end up with a lot of duplication as splices are naively spliced in place. \r\n\r\nFor example\r\n\r\n{{{\r\nfoo x = [|| $$x + $$x ||]\r\n}}}\r\n\r\nWill generate a program which completely duplicates its argument. In this case I can manually remove the duplicate by inserting a let.\r\n\r\n{{{\r\nfoo x = [|| let x' = $$x in x' + x' ||]\r\n}}}\r\n\r\nNot too bad but a bit annoying to have to do manually. \r\n\r\nWhen constructing bigger programs however this process becomes tedious or impossible to do correctly by hand.\r\n\r\n{{{\r\nfoo :: (Q (TExp (Bool)) -> Q (TExp Int)) -> Q (TExp Int) \r\nfoo xf = [|| (let x = True in $$(xf [|| x ||])) + (let x = False in $$(xf [|| x ||]) ||]\r\n}}}\r\n\r\nNow if I pass a constant function to `foo`, the resulting code won't mention `x` so it could be floated out. However, there's not way I can tell that without running `xf` so I can't perform the same transformation as I did for the earlier program and manually insert a let. In the case of splicing in fully static data you really want it to float to the top-level and turn into a CAF.\r\n\r\nThe proposal of this ticket is to implement something like the mechanism for let-insertion in\r\nmetaocaml.\r\n\r\nhttp://okmij.org/ftp/meta-programming/#let-insert\r\n\r\nWe add two new primitives:\r\n\r\n{{{\r\ngenlet :: Q (TExp a) -> Q (TExp a)\r\nlet_locus :: Q (TExp a) -> Q (TExp a)\r\n}}}\r\n\r\n`genlet` marks a code value that we want to float. `let_locus` marks places where we want to insert a let. When we evaluate the code fragment and encounter a `genlet` call, whatever the argument evaluates to is floated as far upwards as possible and inserted at the position of one of the loci. \r\n\r\nFor example,\r\n\r\n{{{\r\nsqr :: Code Int -> Code Int\r\nsqr c = [|| $$c + $$c ||]\r\n\r\nsqr_let :: Code Int -> Code Int\r\nsqr_let c = let_locus (sqr (genlet c))\r\n}}}\r\n\r\nSplicing `sqr [|| 1 ||]` will result in `1 + 1` but `sqr_let [|| c ||]` will equal `let x = 1 in x + x ||]`. \r\n\r\nIt's important to do this earlier rather than later as a lot of duplication can take place which the simplifier does not like. ","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/16177Rename Q (TExp a) to Code a2022-06-23T20:12:33ZMatthew PickeringRename Q (TExp a) to Code aI propose that we modify the typed template haskell API so that quoting an expression of type `t` results in a value of type `Code t` rather than `Q (TExp a)` and the splice construct requires an argument of type `Code a` to produce a va...I propose that we modify the typed template haskell API so that quoting an expression of type `t` results in a value of type `Code t` rather than `Q (TExp a)` and the splice construct requires an argument of type `Code a` to produce a value of type `a`.
The definition of `Code` is as follows.
```
newtype Code a = Code (Q (TExp a))
```
There are two good reasons to do this.
1. `Q (TExp a)` is ugly and leaks implementation details to the user. Using effects from the `Q` monad is unsafe and against the principle of staged programming.
1. Writing instances for `Q (TExp a)` is quite difficult. It's much easier when the newtype is defined but at the cost of constant wrapping and unwrapping.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.6.3 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Rename Q (TExp a) to Code a","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.3","keywords":["TypedTemplateHaskell"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"I propose that we modify the typed template haskell API so that quoting an expression of type `t` results in a value of type `Code t` rather than `Q (TExp a)` and the splice construct requires an argument of type `Code a` to produce a value of type `a`. \r\n\r\nThe definition of `Code` is as follows.\r\n\r\n{{{\r\nnewtype Code a = Code (Q (TExp a))\r\n}}}\r\n\r\nThere are two good reasons to do this.\r\n\r\n1. `Q (TExp a)` is ugly and leaks implementation details to the user. Using effects from the `Q` monad is unsafe and against the principle of staged programming.\r\n2. Writing instances for `Q (TExp a)` is quite difficult. It's much easier when the newtype is defined but at the cost of constant wrapping and unwrapping.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/16178Brackets and splices should be overloaded like the static keyword2019-07-07T18:01:06ZMatthew PickeringBrackets and splices should be overloaded like the static keywordIt's quite convenient that the `static` keyword is rebindable. To recap, if `e :: T` then `static e :: (IsStatic p) => p t`.
It should also be possible rebind brackets and splices in the same manner.
So we introduce two type classes `Is...It's quite convenient that the `static` keyword is rebindable. To recap, if `e :: T` then `static e :: (IsStatic p) => p t`.
It should also be possible rebind brackets and splices in the same manner.
So we introduce two type classes `IsBracket` and `IsSplice`. Now quoting a term `e :: T` has type `e :: IsBracket p => p T` and the argument to a splice
must have type `e :: IsSplice p => p T` which results in a value of type `T`.
```
class IsBracket p where
fromBracket :: Code t -> p t
class IsSplice p where
toBracket :: p t -> Code t
foo :: IsBracket p => p Int
foo = [|| 5 ||]
qux :: (IsSplice p, IsBracket p) => Int
qux = $$(foo)
```
As an aside, arguably the `static` form should only be rebindable when `RebindableSyntax` is enabled but that boat seems to have sailed.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.6.3 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Brackets and splices should be overloaded like the static keyword","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.3","keywords":["TypedTemplateHaskell"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"It's quite convenient that the `static` keyword is rebindable. To recap, if `e :: T` then `static e :: (IsStatic p) => p t`. \r\n\r\nIt should also be possible rebind brackets and splices in the same manner. \r\nSo we introduce two type classes `IsBracket` and `IsSplice`. Now quoting a term `e :: T` has type `e :: IsBracket p => p T` and the argument to a splice\r\nmust have type `e :: IsSplice p => p T` which results in a value of type `T`. \r\n\r\n{{{\r\nclass IsBracket p where\r\n fromBracket :: Code t -> p t\r\n\r\nclass IsSplice p where\r\n toBracket :: p t -> Code t\r\n\r\nfoo :: IsBracket p => p Int\r\nfoo = [|| 5 ||]\r\n\r\nqux :: (IsSplice p, IsBracket p) => Int\r\nqux = $$(foo)\r\n}}}\r\n\r\n\r\nAs an aside, arguably the `static` form should only be rebindable when `RebindableSyntax` is enabled but that boat seems to have sailed. ","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/16195Program with trivial polymorphism leads to out of scope dictionary2019-07-07T18:01:00ZMatthew PickeringProgram with trivial polymorphism leads to out of scope dictionaryAlmost certainly due to c2455e647501c5a382861196b64df3dd05b620a2
A trivial program now causes a core lint error due to an out-of-scope dictionary.
```
module A where
foo :: Code (IO ())
foo = [|| return () ||]
```
```
module B where
...Almost certainly due to c2455e647501c5a382861196b64df3dd05b620a2
A trivial program now causes a core lint error due to an out-of-scope dictionary.
```
module A where
foo :: Code (IO ())
foo = [|| return () ||]
```
```
module B where
main :: IO ()
main = $$foo
```
```
*** Core Lint errors : in result of Desugar (before optimization) ***
<no location info>: warning:
In the expression: return @ IO $dMonad_a4od @ () ()
Out of scope: $dMonad_a4od :: Monad m_a4oc[tau:0]
[LclId]
*** Offending Program ***
Rec {
$trModule :: Module
[LclIdX]
$trModule = Module (TrNameS "main"#) (TrNameS "B"#)
main :: IO ()
[LclIdX]
main = return @ IO $dMonad_a4od @ () ()
end Rec }
*** End of Offense ***
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.7 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | high |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Program with trivial polymorphism leads to out of scope dictionary","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.8.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.7","keywords":["TypedTemplateHaskell"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Almost certainly due to c2455e647501c5a382861196b64df3dd05b620a2\r\n\r\nA trivial program now causes a core lint error due to an out-of-scope dictionary. \r\n\r\n{{{\r\nmodule A where\r\n\r\nfoo :: Code (IO ())\r\nfoo = [|| return () ||]\r\n}}}\r\n\r\n{{{\r\nmodule B where\r\n\r\nmain :: IO ()\r\nmain = $$foo\r\n}}}\r\n\r\n{{{\r\n*** Core Lint errors : in result of Desugar (before optimization) ***\r\n<no location info>: warning:\r\n In the expression: return @ IO $dMonad_a4od @ () ()\r\n Out of scope: $dMonad_a4od :: Monad m_a4oc[tau:0]\r\n [LclId]\r\n*** Offending Program ***\r\nRec {\r\n$trModule :: Module\r\n[LclIdX]\r\n$trModule = Module (TrNameS \"main\"#) (TrNameS \"B\"#)\r\n\r\nmain :: IO ()\r\n[LclIdX]\r\nmain = return @ IO $dMonad_a4od @ () ()\r\nend Rec }\r\n\r\n*** End of Offense ***\r\n}}}\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.8.1https://gitlab.haskell.org/ghc/ghc/-/issues/16472Weakened Q Proposal2020-01-13T10:50:44ZMatthew PickeringWeakened Q ProposalThis ticket tracks the idea of modifying quotation brackets to return something different to `Q` which is weaker and only supports the effects needed to create the syntax representation.
See also https://github.com/ghc-proposals/ghc-pr...This ticket tracks the idea of modifying quotation brackets to return something different to `Q` which is weaker and only supports the effects needed to create the syntax representation.
See also https://github.com/ghc-proposals/ghc-proposals/pull/195
Related to #16178
This ticket is the gitlab equivalent of
https://github.com/ghc-proposals/ghc-proposals/issues/211
For some reason the issue exists there rather than on the actual issue tracker.https://gitlab.haskell.org/ghc/ghc/-/issues/16524unused-top-binds Warning is Disabled in the Presence of TemplateHaskell2022-03-28T05:18:02Zrprijeunused-top-binds Warning is Disabled in the Presence of TemplateHaskell# Summary
If `TemplateHaskell` is enabled and a template haskell splice is used in code used by exported toplevel binds, then `unused-top-binds` fails to warn on any unused toplevel binds.
# Steps to reproduce
Given this code:
```
{-...# Summary
If `TemplateHaskell` is enabled and a template haskell splice is used in code used by exported toplevel binds, then `unused-top-binds` fails to warn on any unused toplevel binds.
# Steps to reproduce
Given this code:
```
{-# LANGUAGE TemplateHaskell #-}
module Main (main) where
import Foo
breakTopBindCheck :: IO ()
breakTopBindCheck = let _ = $$(foo 'f') in pure ()
normalOperation :: IO ()
normalOperation = pure ()
main :: IO ()
main = run
where
-- run = normalOperation
run = breakTopBindCheck
```
And any template haskell implementation of foo. For example:
```
{-# LANGUAGE TemplateHaskell #-}
module Foo (foo) where
import Language.Haskell.TH (Q)
import Language.Haskell.TH.Syntax (Exp (..), Lit (..), TExp (..))
foo :: Char -> Q (TExp Char)
foo c = pure $ TExp $ LitE $ CharL c
```
The Main module, when compiled, will fail to complain about the unused top binding for the `normalOperation` function. If the `run` definition binding to `breakTopBindCheck` is commented out, and the `run` definition binding to `normalOperation` is uncommented, then compiling successfully warns about the unused `breakTopBindCheck` binding.
# Expected behavior
I expect unused top binds to result in warnings when unused top binds warnings are enabled, regardless of whether TemplateHaskell is in use.
# Environment
* GHC version used: 8.4.4
Optional:
* Operating System: Linux, NixOS, Kernel 4.14.107
* System Architecture: x86-64https://gitlab.haskell.org/ghc/ghc/-/issues/17212Allow default methods to be implemented using template haskell2023-06-12T14:48:02ZMatthew PickeringAllow default methods to be implemented using template haskellIn conversations with @kosmikus he suggested that it would be nice to integrate default implementations with typed template haskell.
For example,
```
class Eq a where
eq :: a -> a -> Bool
default splice eq :: Generic a => Cod...In conversations with @kosmikus he suggested that it would be nice to integrate default implementations with typed template haskell.
For example,
```
class Eq a where
eq :: a -> a -> Bool
default splice eq :: Generic a => Code (a -> a -> Bool)
eq = _impl_
```
This has the massive advantage that the default implementation can be efficient than the usual `Data` or `Generics` based implementations.
There would need to be a GHC proposal related to this ticket but I write it down here in case anyone else finds it interesting.
Related to #12457Matthew PickeringMatthew Pickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/17220Interaction of constraints and top-level splices is poorly specified and hard...2020-01-08T13:13:13ZMatthew PickeringInteraction of constraints and top-level splices is poorly specified and hard to controlOn a fresh Thursday morning I set out to achieve the seemingly simple task of defining an instance for a type using typed template haskell. However, as I am sure the reader can already guess, I ran into some unexpected difficulties conce...On a fresh Thursday morning I set out to achieve the seemingly simple task of defining an instance for a type using typed template haskell. However, as I am sure the reader can already guess, I ran into some unexpected difficulties concerning type class constraints.
Code: https://github.com/mpickering/tth-define-instances
## Take 1
I want to implement an `Ord` instance using the generically defined `gcompare`. `gcompare` requires each field of the datatype to
be an instance of `Ord`, as it is recursive, including the instance we are currently defining.
```
instance Ord (BinTree Int) where
compare = $$(gcompare)
gcompare_1 :: (GenericSyntax a, All (All Ord) (Description a)) => Q (TExp (a -> a -> Ordering)))
```
However, this leads to an error because we can't use the instance for `Ord (BinTree Int)` in the top-level splice, because
it's being define in the current module, it would be possible to use it to influence the code we are currently generating.
```
Use.hs:14:16: error:
• GHC stage restriction:
instance for ‘Ord
(BinTree
Int)’ is used in a top-level splice, quasi-quote, or annotation,
and must be imported, not defined locally
• In the expression: gcompare
In the Template Haskell splice $$(gcompare)
In the expression: $$(gcompare)
|
14 | compare = $$(gcompare)
|
```
The problem is, the use of the `Ord` dictionary is in fact safe, because it's only used in generated code.
In order to reflect the static information about the dictionaries, I modified the definition of `gcompare` in order to
explicitly take the necessary evidence.
## Take 2
```
gcompare_2 :: GenericSyntax a => POP Compa (Description a) -> Syntax (a -> a -> Ordering)
data Compa a where
Compa :: Q (TExp (a -> a -> Ordering)) -> Compa a
```
`gcompare_2` takes an explicit argument which plays the role of the `All (All Ord) xs` constraint from `gcompare_1` but with the
difference that we only have access to the comparison functions in the next stage.
This means we can use `gcompare_2` as follows:
### Attempt 1
Firstly just trying to use it directly in the instance with quoted `compare` functions. I expected this to work.
```
instance Ord (BinTree Int) where
compare = $$(gcompare_2 (POP (Nil :* ((Compa [|| compare ||] :* Compa [|| compare ||] :* Compa [|| compare ||] :* Nil) :* Nil))))
```
```
Use.hs:21:48-62: error:
• GHC stage restriction:
instance for ‘Ord
(BinTree
Int)’ is used in a top-level splice, quasi-quote, or annotation,
and must be imported, not defined locally
• In the Template Haskell quotation [|| compare ||]
In the first argument of ‘Compa’, namely ‘[|| compare ||]’
In the first argument of ‘(:*)’, namely ‘Compa [|| compare ||]’
|
21 | compare = $$(gcompare_2 (POP (Nil :* ((Compa [|| compare ||] :* Compa [|| compare ||] :* Compa
[|| compare ||] :* Nil) :* Nil))))
| ^^^^^^^^^^^^^^^
```
Analysis: GHC isn't smart enough to know that `compare` is the function we are currently defining.
### Attempt 2
Try defining the function just at the top-level without the complications of the instance.
```
compareBinTree :: (Ord a) => BinTree a -> BinTree a -> Ordering
compareBinTree = $$(gcompare_2 (POP (Nil :* ((Compa [|| compareBinTree ||] :* Compa [|| compare ||] :* Compa [|| compareBinTree ||] :* Nil) :* Nil))))
```
Still doesn't work.
```
Use.hs:25:53-74: error:
• No instance for (Ord a) arising from a use of ‘compareBinTree’
• In the Template Haskell quotation [|| compareBinTree ||]
In the first argument of ‘Compa’, namely ‘[|| compareBinTree ||]’
In the first argument of ‘(:*)’, namely
‘Compa [|| compareBinTree ||]’
|
25 | compareBinTree = $$(gcompare_2 (POP (Nil :* ((Compa [|| compareBinTree ||] :* Compa [|| compare ||]
:* Compa [|| compareBinTree ||] :* Nil) :* Nil))))
| ^^^^^^^^^^^^^^^^^^^^^^
```
Analysis: This looks like a simple bug of the constraint environment not being restored inside a quotation.
### Attempt 3
Explicitly pass the comparison argument, this one works.
```
compareBinTree :: (a -> a -> Ordering) -> BinTree a -> BinTree a -> Ordering
compareBinTree c = $$(gcompare_2 (POP (Nil :* ((Compa [|| compareBinTree c ||] :* Compa [|| c ||] :* Compa [|| compareBinTree c ||] :* Nil) :* Nil))))
instance Ord (BinTree Int) where
compare = compareBinTree compare
```
----
It's not clear what to do about this ticket. It's clear that generating code which relies on constraints is currently quite inconvenient.
cc @kosmikushttps://gitlab.haskell.org/ghc/ghc/-/issues/17221Constraint scoping is wrong when using top-level splices2021-11-15T22:49:53ZMatthew PickeringConstraint scoping is wrong when using top-level splicesI claim this program should work:
```
top :: Ord a => a -> a -> Ordering
top = $$([|| compare ||])
```
because the following program works
```
top :: (a -> a -> Ordering) -> a -> a -> O...I claim this program should work:
```
top :: Ord a => a -> a -> Ordering
top = $$([|| compare ||])
```
because the following program works
```
top :: (a -> a -> Ordering) -> a -> a -> Ordering
top c = $$([|| c ||])
```
Related to #17220https://gitlab.haskell.org/ghc/ghc/-/issues/17804Ideas about testing and verifying code generated by typed template haskell2021-03-05T04:14:05ZMatthew PickeringIdeas about testing and verifying code generated by typed template haskellIn the recent practical experience of myself, Jamie and Andes we have felt the need for some more support for *verifing* that the programs that we generate using typed template haskell adhere to certain properties we had in mind.
This ...In the recent practical experience of myself, Jamie and Andes we have felt the need for some more support for *verifing* that the programs that we generate using typed template haskell adhere to certain properties we had in mind.
This ticket is a public place to write down some of these ideas so they are not lost forever.
## Size of subtrees
We want to be able to assert, at compile time, that the size of the generated code bares some known relationship to a statically known input. For example, the generated code is linear in the size of the input list.
In order to implement this we need the compiler to be able to report the size of a quotation. If the size of a quotation can be
inspected then the assertion functionality can be built into a library.
## Certain constructors are not present
We want to assert that in generated code certain constructors are not present. In particular, asserting that generic constructors never appear is an important property. In our own closed programs you can know this with reasonable confidence but in a hypothetical open world where people provide more staged interfaces, a rogue library may inefficiently implement an operation.
This would be a limited analysis at first because you can easily call already compiled functions in your generated code but can't inspect their definition.
## Thresholds for generating programs
A common mistake that people make when writing a staged program is to create an infinite compile time loop which generates an infinitely sized program rather than generating a loop which executes at runtime. This is much easier to do than when writing normal programs. It would be good if there was a limit as to how much recursion you were allowed to do at compile time so that beginners can get a good warning rather than puzzle, like we all did, about why the program is looping forever.
Other compile time evaluation features in GHC such as type class resolution and the inliner already have these warnings built in.
## Warning for CSP by lifting
In general, cross-stage persistence is bad. It makes it easy to accidentally create bloated programs if you accidentally use a variable at the wrong stage. For advanced users it should be possible to at least issue a warning if your program contains a cross-stage reference as you probably didn't mean it. If you did mean it, write it using an explicit splice and lift.
## Use overloaded quotes in order to perform analysis at runtime?
In order to perform some other verification it could be possible to instead perform runtime code generation by using overloaded quotations and inspecting the generating `Exp` value.https://gitlab.haskell.org/ghc/ghc/-/issues/17863Typed template haskell is very underdocumented2020-02-26T17:01:10ZadamTyped template haskell is very underdocumentedThere is a lack of documentation in both the [users guide][1] and the [template-haskell haddocks][2]. Every time I go looking it takes a while to find the 2 bullet points in the users guide on the syntax.
An own section and a worked exa...There is a lack of documentation in both the [users guide][1] and the [template-haskell haddocks][2]. Every time I go looking it takes a while to find the 2 bullet points in the users guide on the syntax.
An own section and a worked example would be a big improvement.
[1]: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html?highlight=typed%20expression#th-syntax
[2]: https://hackage.haskell.org/package/template-haskell-2.15.0.0/docs/Language-Haskell-TH.html#g:12https://gitlab.haskell.org/ghc/ghc/-/issues/18102TemplateHaskellQuotes and RebindableSyntax don't play nicely2021-02-05T10:11:11ZRichard Eisenbergrae@richarde.devTemplateHaskellQuotes and RebindableSyntax don't play nicelyEDIT: The original problem described here was about untyped TH, and it was fixed in !2960. But we identify a new problem with typed Template Haskell, which has yet to be solved. https://gitlab.haskell.org/ghc/ghc/-/issues/18102#note_2922...EDIT: The original problem described here was about untyped TH, and it was fixed in !2960. But we identify a new problem with typed Template Haskell, which has yet to be solved. https://gitlab.haskell.org/ghc/ghc/-/issues/18102#note_292247 shows two illustrative examples.
-------------------------------------------------------
If I say
```hs
{-# LANGUAGE TemplateHaskell, RebindableSyntax #-}
module Bug where
import Prelude ( Monad(..), Bool(..), print, ($) )
import Language.Haskell.TH.Syntax
$( do stuff <- [| if True then 10 else 15 |]
runIO $ print stuff
return [] )
```
then I get errors about `ifThenElse` and `fromInteger` not being in scope. When I bring them into scope, the code is accepted, but the quoted syntax does not mention them, instead accurately reflecting the original source Haskell I wrote.
There are several problems in this story:
1. Template Haskell quotes are meant to work even in the presence of unbound identifiers.
2. Template Haskell is all about quoting (and splicing) surface syntax. Quoting should not care about `-XRebindableSyntax`.
3. If we were to decide that quoting should respect `-XRebindableSyntax` (I disagree with this design, to be clear), then the output of the quote is incorrect.
I propose: disable `-XRebindableSyntax` within quotes. That should fix all these problems.
Other reasonable possibility: disable `-XRebindableSyntax` within quotes, but use the TH combinators that are in scope (like `conE` and `appE`, etc.). I think this would be nightmarish to implement, and no one is asking for it, but it would be a consistent way forward.https://gitlab.haskell.org/ghc/ghc/-/issues/18170More Typed Template Haskell unsoundness due to levity polymorphism2022-05-10T16:26:58ZMatthew PickeringMore Typed Template Haskell unsoundness due to levity polymorphismThe levity polymorphism check does not run on quoted expressions which means you can use quotes to define a levity polymorphic code generator.
This leads to unsoundness as a well-typed code generator leads to an ill-typed program.
```
...The levity polymorphism check does not run on quoted expressions which means you can use quotes to define a levity polymorphic code generator.
This leads to unsoundness as a well-typed code generator leads to an ill-typed program.
```
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TemplateHaskell #-}
module Bad where
import Language.Haskell.TH.Lib
import GHC.Exts
-- Example from the user guide but with the function wrapped in quotes
bad :: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep)
(a :: TYPE r1) (b :: TYPE r2).
TExpQ ((a -> b) -> a -> b)
bad = [|| \f x -> f x ||]
```
```
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TemplateHaskell #-}
module Lev where
import Language.Haskell.TH.Lib
import Bad
import GHC.Exts
-- Code generator type checked but splicing fails to produce well-typed
-- program -- unsound
unsound :: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep)
(a :: TYPE r1) (b :: TYPE r2).
((a -> b) -> a -> b)
unsound = $$(bad)
-- Generating a monomorphic program is sound, and hence a workaround for
-- normal levity polymorphic restrictions.
workaround :: Int
workaround = $$bad id 5
```
https://gist.github.com/144e42b4429673d8449f59413cc10ca4
cc @RyanGlScott who was interested in this issue.https://gitlab.haskell.org/ghc/ghc/-/issues/18211Types of Typed Spliced are not inferred (looks like only checked)2023-02-16T12:45:37ZOleg GrenrusTypes of Typed Spliced are not inferred (looks like only checked)I think this might be duplicate of #10271, but I'm not sure. This example is simpler.
Consider a small utility type-class (a variant discussed in !3290
```haskell
{-# LANGUAGE GADTs #-}
module CodeFromString where
import La...I think this might be duplicate of #10271, but I'm not sure. This example is simpler.
Consider a small utility type-class (a variant discussed in !3290
```haskell
{-# LANGUAGE GADTs #-}
module CodeFromString where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
class CodeFromString a where
codeFromString :: String -> TExpQ a
instance a ~ Char => CodeFromString [a] where
codeFromString = liftTyped
```
It seems to work
```haskell
{-# LANGUAGE TemplateHaskell #-}
module Main (main) where
import CodeFromString
main :: IO ()
main = do
putStrLn $$(codeFromString "example string")
```
Yet, if we make the setting just slightly more complicated like:
```haskell
-- doesn't work
print $ $$(codeFromString "example string") == "example string"
-- doesn't work
print $ $$(codeFromString "example string") == ("example string" :: String)
```
The type of splice `TExpQ String` should be easily inferrable, but GHC refuses to infer it. If we make GHC check the type with
```haskell
-- works.
print $ ($$(codeFromString "example string") :: String) == ("example string" :: String)
```
it works again. But the explicit type-annotation / checked positions make this kind of usage quite impractical.
cc @mpickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/18521Code is levity-polymorphic, but CodeQ and TExpQ aren't2020-08-20T23:55:51ZRyan ScottCode is levity-polymorphic, but CodeQ and TExpQ aren'tOn HEAD, the following will typecheck:
```hs
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE TemplateHaskell #-}
module Bug where
import GHC.Exts (Int#)
import Language.Haskell.TH
a :: Code Q Int#
a = [|| 42# ||]
```
But @buggymcbugfix obser...On HEAD, the following will typecheck:
```hs
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE TemplateHaskell #-}
module Bug where
import GHC.Exts (Int#)
import Language.Haskell.TH
a :: Code Q Int#
a = [|| 42# ||]
```
But @buggymcbugfix observed that neither of the following will typecheck:
```hs
b :: CodeQ Int#
b = a
c :: TExpQ Int#
c = examineCode a
```
```
[1 of 1] Compiling Bug ( Bug.hs, interpreted )
Bug.hs:11:12: error:
• Expecting a lifted type, but ‘Int#’ is unlifted
• In the first argument of ‘CodeQ’, namely ‘Int#’
In the type signature: b :: CodeQ Int#
|
11 | b :: CodeQ Int#
| ^^^^
Bug.hs:14:12: error:
• Expecting a lifted type, but ‘Int#’ is unlifted
• In the first argument of ‘TExpQ’, namely ‘Int#’
In the type signature: c :: TExpQ Int#
|
14 | c :: TExpQ Int#
| ^^^^
```
This is because `Code` is levity polymorphic in its last argument, but neither `CodeQ` nor `TExpQ` are. It feels like they should be for the sake of consistency.9.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/18600Typed Template Haskell can observe order of type checking2020-09-30T21:53:45ZRichard Eisenbergrae@richarde.devTyped Template Haskell can observe order of type checkingSuppose I say
```hs
{-# LANGUAGE ScopedTypeVariables, TemplateHaskell, TypeApplications, GADTs #-}
module Meta where
import Type.Reflection
import Language.Haskell.TH
foo :: forall a. Typeable a => Code Q a
foo | Just HRefl <- typeRe...Suppose I say
```hs
{-# LANGUAGE ScopedTypeVariables, TemplateHaskell, TypeApplications, GADTs #-}
module Meta where
import Type.Reflection
import Language.Haskell.TH
foo :: forall a. Typeable a => Code Q a
foo | Just HRefl <- typeRep @a `eqTypeRep` typeRep @String
= [|| "TyDe " ||]
| otherwise
= error "urk"
```
```hs
{-# LANGUAGE TemplateHaskell #-}
module Meta2 where
import Meta
both :: a -> a -> (a,a)
both = (,)
ex1 = both $$foo "hello"
ex2 = both "hello" $$foo
```
Then `ex1` is rejected while `ex2` is accepted. The reason is that `ex2` solves for the choice of type variable `a` *before* we encounter the TTH splice, while `ex1` doesn't have that happy circumstance. Sadly, this means that TTH succeeds or fails depending on the order of type checking, which is distasteful.
One approach is outlined in https://icfp20.sigplan.org/details/tyde-2020-papers/6/Predictable-Macros-for-Hindley-Milner-Extended-Abstract- (which will hopefully be posted publicly somewhere -- I just watched the talk) and it involves *stuck macros*. The idea would be that we delay evaluating TTH splices with `Typeable` constraints until all metavariables are solved.https://gitlab.haskell.org/ghc/ghc/-/issues/18736Linear types: type inference in Typed Template Haskell2021-02-06T15:14:03ZKrzysztof GogolewskiLinear types: type inference in Typed Template HaskellThe following module should compile, but it doesn't:
```
{-# LANGUAGE TemplateHaskell, LinearTypes #-}
module Bug where
import Language.Haskell.TH
idenq :: Quote m => Code m (a #-> a)
idenq = [|| \x -> x ||]
```
```
• Couldn't mat...The following module should compile, but it doesn't:
```
{-# LANGUAGE TemplateHaskell, LinearTypes #-}
module Bug where
import Language.Haskell.TH
idenq :: Quote m => Code m (a #-> a)
idenq = [|| \x -> x ||]
```
```
• Couldn't match type ‘'Many’ with ‘'One’
Expected: Code m (a #-> a)
Actual: Code m (a -> a)
```
The workaround is `[|| (\x -> x) :: a #-> a ||]`.
Originally reported at https://gitlab.haskell.org/ghc/ghc/-/merge_requests/852#note_280765.https://gitlab.haskell.org/ghc/ghc/-/issues/19368Typed Template Haskell suppresses -Wunused-top-binds warnings2021-02-21T15:24:30ZRyan ScottTyped Template Haskell suppresses -Wunused-top-binds warningsIn this program:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wunused-top-binds #-}
module Bug (a) where
a :: Int
a = $([| 42 |])
-- a = $$([|| 42 ||])
z :: Int
z = 42
```
GHC correctly informs me that `z` is defined but n...In this program:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -Wunused-top-binds #-}
module Bug (a) where
a :: Int
a = $([| 42 |])
-- a = $$([|| 42 ||])
z :: Int
z = 42
```
GHC correctly informs me that `z` is defined but not used:
```
$ /opt/ghc/8.10.3/bin/ghc Bug.hs
[1 of 1] Compiling Bug ( Bug.hs, Bug.o, Bug.dyn_o )
Bug.hs:10:1: warning: [-Wunused-top-binds]
Defined but not used: ‘z’
|
10 | z = 42
| ^
```
If I comment out the definition of `a` and replace it with `a = $$([|| 42 ||])`, however, then GHC doesn't report any warnings at all!
```
$ /opt/ghc/8.10.3/bin/ghc Bug.hs
[1 of 1] Compiling Bug ( Bug.hs, Bug.o, Bug.dyn_o )
```
I'm unclear why the use of typed Template Haskell would change things here, as I would expect `-Wunused-top-binds` warnings in both scenarios.https://gitlab.haskell.org/ghc/ghc/-/issues/19470GHCi does not error when typed template haskell errors in IO2022-01-22T01:03:07ZolligobberGHCi does not error when typed template haskell errors in IO## Summary
If some expression using typed template haskell would cause an exception when running compile-time code, then putting that expression into IO using pure or print suppresses the error and does not execute the IO action.
## St...## Summary
If some expression using typed template haskell would cause an exception when running compile-time code, then putting that expression into IO using pure or print suppresses the error and does not execute the IO action.
## Steps to reproduce
Enter GHCi with -XTemplateHaskell and run `print ($$undefined :: String)`.
## Expected behavior
Print an error, similar to when running `($$undefined :: String)` or `print ($undefined :: String)` in GHCi.
## Environment
* GHC version used: 8.10.4
Optional:
* Operating System: 5.11.1-arch1-1
* System Architecture: x86_64Matthew PickeringMatthew Pickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/19893Core Lint error with typed Template Haskell (The type variable ... is out of ...2023-08-11T11:04:21ZRyan ScottCore Lint error with typed Template Haskell (The type variable ... is out of scope)The `parsley-0.1.0.1` Hackage library fails to compile with `-dcore-lint`. Here is a minimized version of the failing code:
```hs
{-# LANGUAGE TemplateHaskell #-}
module Bug where
import Control.Monad.ST
import Language.Haskell.TH
f :...The `parsley-0.1.0.1` Hackage library fails to compile with `-dcore-lint`. Here is a minimized version of the failing code:
```hs
{-# LANGUAGE TemplateHaskell #-}
module Bug where
import Control.Monad.ST
import Language.Haskell.TH
f :: Code Q Char
f = [|| runST $$([|| pure 'a' ||]) ||]
```
```
$ /opt/ghc/9.0.1/bin/ghc Bug.hs -dcore-lint
[1 of 1] Compiling Bug ( Bug.hs, Bug.o, Bug.dyn_o )
*** Core Lint errors : in result of Desugar (before optimization) ***
<no location info>: warning:
The type variable @s_a20Z[sk:1] is out of scope
In the type of a binder: $dApplicative_a218
In the type ‘Applicative (ST s_a20Z[sk:1])’
Substitution: [TCvSubst
In scope: InScope {}
Type env: []
Co env: []]
*** Offending Program ***
Rec {
$dQuote_a211 :: Quote Q
[LclId]
$dQuote_a211 = $dQuote_a20R
$dQuote_a20R :: Quote Q
[LclId]
$dQuote_a20R = $fQuoteQ
$dApplicative_a218 :: Applicative (ST s_a20Z[sk:1])
[LclId]
$dApplicative_a218 = $fApplicativeST @s_a20Z[sk:1]
$trModule :: Module
[LclIdX]
$trModule = Module (TrNameS "main"#) (TrNameS "Bug"#)
f :: Code Q Char
[LclIdX]
f = unsafeCodeCoerce
@'LiftedRep
@Char
@Q
$dQuote_a20R
(appE
@Q
$dQuote_a20R
(varE
@Q
$dQuote_a20R
(mkNameG_v
(unpackCString# "base"#)
(unpackCString# "GHC.ST"#)
(unpackCString# "runST"#)))
(unTypeCode
@'LiftedRep
@(ST s_a20Z[sk:1] Char)
@Q
$dQuote_a20R
(unsafeCodeCoerce
@'LiftedRep
@(ST s_a20Z[sk:1] Char)
@Q
$dQuote_a211
(appE
@Q
$dQuote_a211
(varE
@Q
$dQuote_a211
(mkNameG_v
(unpackCString# "base"#)
(unpackCString# "GHC.Base"#)
(unpackCString# "pure"#)))
(litE @Q $dQuote_a211 (charL (C# 'a'#)))))))
end Rec }
*** End of Offense ***
<no location info>: error:
Compilation had errors
```https://gitlab.haskell.org/ghc/ghc/-/issues/20157Suggest TemplateHaskell when failing to parse a typed splice2021-07-27T16:06:41ZKirill Elaginkirelagin@gmail.comSuggest TemplateHaskell when failing to parse a typed splice## Summary
If you forget to enable `TemplateHaskell` and then write `$(foo)`, you will get:
```
parse error on input ‘$’
Perhaps you intended to use TemplateHaskell
```
However, for `$$(foo)` you will only get:
```
parse erro...## Summary
If you forget to enable `TemplateHaskell` and then write `$(foo)`, you will get:
```
parse error on input ‘$’
Perhaps you intended to use TemplateHaskell
```
However, for `$$(foo)` you will only get:
```
parse error on input ‘$$’
```
and no suggestion to enable the extension. That’s unfair!
## Steps to reproduce
* `echo 'foo = $$()' > test.hs && ghc test.hs`
## Expected behavior
Say “parse error on input ‘$$’” and suggest `TemplateHaskell`.
## Environment
* GHC version used: 8.10.4
Optional:
* Operating System:
* System Architecture:Krzysztof GogolewskiKrzysztof Gogolewskihttps://gitlab.haskell.org/ghc/ghc/-/issues/20969Panic in the Template Haskell2023-08-22T07:58:11ZDavid FeuerPanic in the Template Haskell## Summary
Write a brief description of the issue.
## Steps to reproduce
Write a module like this
```haskell
{-# language TemplateHaskellQuotes #-}
module SequenceCode where
import Data.Sequence.Internal
import qualified Language.Has...## Summary
Write a brief description of the issue.
## Steps to reproduce
Write a module like this
```haskell
{-# language TemplateHaskellQuotes #-}
module SequenceCode where
import Data.Sequence.Internal
import qualified Language.Haskell.TH.Syntax as TH
class Functor t => SequenceCode t where
traverseCode :: TH.Quote m => (a -> TH.Code m b) -> t a -> TH.Code m (t b)
traverseCode f = sequenceCode . fmap f
sequenceCode :: TH.Quote m => t (TH.Code m a) -> TH.Code m (t a)
sequenceCode = traverseCode id
instance SequenceCode Seq where
sequenceCode (Seq t) = [|| Seq $$(traverseCode sequenceCode t) ||]
instance SequenceCode Elem where
sequenceCode (Elem t) = [|| Elem $$t ||]
instance SequenceCode FingerTree where
sequenceCode (Deep s pr m sf) =
[|| Deep s $$(sequenceCode pr) $$(traverseCode sequenceCode m) $$(sequenceCode sf) ||]
sequenceCode (Single a) = [|| Single $$a ||]
sequenceCode EmptyT = [|| EmptyT ||]
instance SequenceCode Digit where
sequenceCode (One a) = [|| One $$a ||]
sequenceCode (Two a b) = [|| Two $$a $$b ||]
sequenceCode (Three a b c) = [|| Three $$a $$b $$c ||]
sequenceCode (Four a b c d) = [|| Four $$a $$b $$c $$d ||]
instance SequenceCode Node where
sequenceCode (Node2 s x y) = [|| Node2 s $$x $$y ||]
sequenceCode (Node3 s x y z) = [|| Node3 s $$x $$y $$z ||]
```
Then write another one importing it and doing thus:
```haskell
{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}
glumber :: forall a. Num a => a -> Seq a
glumber x = $$(sequenceCode (fromList [TH.liftTyped _ :: TH.Code TH.Q a, [||x||]]))
```
Result:
```haskell
tests/seq-properties.hs:974:40: error:
• No instance for (TH.Lift a) arising from a use of ‘TH.liftTyped’
• In the expression: TH.liftTyped _ :: TH.Code TH.Q a
In the first argument of ‘fromList’, namely
‘[TH.liftTyped _ :: TH.Code TH.Q a, [|| x ||]]’
In the first argument of ‘sequenceCode’, namely
‘(fromList [TH.liftTyped _ :: TH.Code TH.Q a, [|| x ||]])’
|
974 | glumber x = $$(sequenceCode (fromList [TH.liftTyped _ :: TH.Code TH.Q a, [||x||]]))
| ^^^^^^^^^^^^
tests/seq-properties.hs:974:53: error:ghc: panic! (the 'impossible' happened)
(GHC version 9.2.1:
No skolem info:
[a_aaba[sk:1]]
Call stack:
CallStack (from HasCallStack):
callStackDoc, called at compiler/GHC/Utils/Panic.hs:181:37 in ghc:GHC.Utils.Panic
pprPanic, called at compiler/GHC/Tc/Errors.hs:2888:17 in ghc:GHC.Tc.Errors
```
## Expected behavior
I expect my error messages not to be accompanied by panics.
## Environment
* GHC version used: 9.2.1
Optional:
* Operating System:
* System Architecture:Matthew PickeringMatthew Pickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/21050Assertion failure with typed Template Haskell type variable2023-05-09T22:40:48ZKrzysztof GogolewskiAssertion failure with typed Template Haskell type variableFile:
```haskell
{-# LANGUAGE TemplateHaskell, RankNTypes #-}
module M where
import Language.Haskell.TH.Syntax
data T = MkT (forall a. a)
f x = [|| MkT $$(x) ||]
```
In 9.2 and earlier, this compiles, even with `-dcore-lint` enabled. B...File:
```haskell
{-# LANGUAGE TemplateHaskell, RankNTypes #-}
module M where
import Language.Haskell.TH.Syntax
data T = MkT (forall a. a)
f x = [|| MkT $$(x) ||]
```
In 9.2 and earlier, this compiles, even with `-dcore-lint` enabled. But the inferred type, `f :: Q (TExp a) -> Q (TExp T)`, is wrong; that'd be correct if `MkT :: a -> T` while `MkT :: (forall a. a) -> T`.
In master, this gives an assertion failure about levels inside `writeMetaTyVarRef`. If assertions are disabled, it fails Lint.
```
*** Core Lint errors : in result of Desugar (before optimization) ***
M.hs:6:1: warning:
The type variable @a_a1W4[sk:2] is out of scope
In the type of a binder: f
In the type ‘forall {m :: * -> *}.
Quote m =>
Code m a_a1W4[sk:2] -> Code m T’
Substitution: [TCvSubst
In scope: InScope {m_a1Ib}
Type env: [a1Ib :-> m_a1Ib]
Co env: []]
```
This looks related to #19893, but I'm not sure if it's the same bug.https://gitlab.haskell.org/ghc/ghc/-/issues/21051Stage restriction differs between untyped and typed TH2022-02-08T12:50:31ZKrzysztof GogolewskiStage restriction differs between untyped and typed THFile:
```haskell
{-# LANGUAGE TemplateHaskell, TypeApplications #-}
module M where
data T
x = $(const @_ @T [| 'a' |] undefined)
y = $$(const @_ @T [|| 'a' ||] undefined)
```
`x` is rejected:
```
• GHC stage restriction:
...File:
```haskell
{-# LANGUAGE TemplateHaskell, TypeApplications #-}
module M where
data T
x = $(const @_ @T [| 'a' |] undefined)
y = $$(const @_ @T [|| 'a' ||] undefined)
```
`x` is rejected:
```
• GHC stage restriction:
‘T’ is used in a top-level splice, quasi-quote, or annotation,
and must be imported, not defined locally
```
But `y` is accepted. Is there any reason why untyped and typed TH behave differently?
I don't have any example where this actually goes wrong. If there's a reason, it might be added to the documentation.https://gitlab.haskell.org/ghc/ghc/-/issues/21910Scoped type variables in typed quotes lose scope2022-07-25T09:20:36ZAndrasKovacsScoped type variables in typed quotes lose scopeConsider the following code. I used GHC-9.2.3.
```haskell
{-# language TemplateHaskell, ScopedTypeVariables #-}
import Language.Haskell.TH
f :: forall a. CodeQ a -> CodeQ a
f x = [|| let y :: a; y = $$x in y ||]
```
This typechecks, bu...Consider the following code. I used GHC-9.2.3.
```haskell
{-# language TemplateHaskell, ScopedTypeVariables #-}
import Language.Haskell.TH
f :: forall a. CodeQ a -> CodeQ a
f x = [|| let y :: a; y = $$x in y ||]
```
This typechecks, but the following doesn't:
```haskell
g :: Bool -> Bool
g x = $$(f [||x||])
```
I get
```
• Couldn't match expected type ‘a’ with actual type ‘Bool’
‘a’ is a rigid type variable bound by
the type signature for:
x_a8Yw :: forall a. a
```
It looks like the scoped `a` is transformed into a generalized `a` after splicing.
Looking at `-ddump-simpl -dsuppress-all`, it seems that the connection between the scoped `forall a.` and the `a` in `x :: a` is completely lost in the code for `f`, although GHC does know about it during type checking `f`'s definition. As far as I see, the same thing happens with all scoped variables in quotes.
One solution would be to have quoting for types. In hypothetical syntax:
```haskell
f :: forall (a : CodeQ Type). CodeQ $$a -> CodeQ $$a
f @a x = [|| let y :: $$a; y = $$x in y ||]
```
This one seems a rather big change but I'm not sure about other solutions which are perhaps more realistic to integrate to TH (I don't really know how splice processing works).https://gitlab.haskell.org/ghc/ghc/-/issues/22056panic! no skolem info when using typed template haskell2022-08-16T15:49:59Zoberblastmeisterpanic! no skolem info when using typed template haskell## Summary
When using typed template haskell with equality constraints GHC panics.
## Steps to reproduce
```haskell
{-# LANGUAGE TemplateHaskell #-}
module A where
import Language.Haskell.TH
bomb :: Code Q Int
bomb = [||1||]
```
```...## Summary
When using typed template haskell with equality constraints GHC panics.
## Steps to reproduce
```haskell
{-# LANGUAGE TemplateHaskell #-}
module A where
import Language.Haskell.TH
bomb :: Code Q Int
bomb = [||1||]
```
```haskell
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE GADTs #-}
module B where
import A
boom :: (a ~ Int) => a
boom = $$(bomb)
```
## Expected behavior
GHC should not panic.
## Environment
* GHC version used: 9.2.3
Optional:
* Operating System: NixOS
* System Architecture: x86_64https://gitlab.haskell.org/ghc/ghc/-/issues/22260panic when building haddock for ghc-check2022-12-13T11:43:44Zmaralornmail@maralorn.depanic when building haddock for ghc-check## Summary
While trying to build ghc-check 0.5.0.0 within nixpkgs I encounter the following error when generating haddocks.
## Steps to reproduce
`nix build .#haskell.packages.ghc942.ghc-check` on a current `haskell-updates` branch of...## Summary
While trying to build ghc-check 0.5.0.0 within nixpkgs I encounter the following error when generating haddocks.
## Steps to reproduce
`nix build .#haskell.packages.ghc942.ghc-check` on a current `haskell-updates` branch of nixpkgs (bbd00e8632c).
build ends with:
```
ghc-check> haddockPhase
ghc-check> Preprocessing library for ghc-check-0.5.0.8..
ghc-check> Running Haddock on library for ghc-check-0.5.0.8..
ghc-check> Warning: --source-* options are ignored when --hyperlinked-source is enabled.
ghc-check> 75% ( 3 / 4) in 'GHC.Check.Executable'
ghc-check> Missing documentation for:
ghc-check> trim (src/GHC/Check/Executable.hs:25)
ghc-check>
ghc-check> <no location info>: error:
ghc-check> panic! (the 'impossible' happened)
ghc-check> GHC version 9.4.2:
ghc-check> hsExprType: Unexpected HsSpliceE
ghc-check> unTypeCode (liftSplice . pure $ TExp verLifted_agFU)
ghc-check> Call stack:
ghc-check> CallStack (from HasCallStack):
ghc-check> callStackDoc, called at compiler/GHC/Utils/Panic.hs:182:37 in ghc:GHC.Utils.Panic
ghc-check> pprPanic, called at compiler/GHC/Hs/Syn/Type.hs:134:30 in ghc:GHC.Hs.Syn.Type
ghc-check>
ghc-check> Please report this as a GHC bug: https://www.haskell.org/ghc/reportabug
ghc-check>
ghc-check> haddock: Cannot typecheck modules
error: builder for '/nix/store/s3ahary8r0bysjpdzdafx9s2sp8vf151-ghc-check-0.5.0.8.drv' failed with exit code 1;
```
I realize, this is not a very nice reproducer, because it uses nix. If desired I can try to contribute to the debugging.
Still the error told me to report this, so I did.9.4.3Matthew PickeringMatthew Pickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/23148template-haskell: rewrite TExp and Code documentation2023-05-08T16:21:39ZDanila Dankotemplate-haskell: rewrite TExp and Code documentation## Summary
https://hackage.haskell.org/package/template-haskell-2.19.0.0/docs/Language-Haskell-TH.html#t:TExp
mentions that
> typed quotes, written as [|| ... ||] where ... is an expression; if that expression has type a, then the qu...## Summary
https://hackage.haskell.org/package/template-haskell-2.19.0.0/docs/Language-Haskell-TH.html#t:TExp
mentions that
> typed quotes, written as [|| ... ||] where ... is an expression; if that expression has type a, then the quotation has type Q (TExp a)
However, [|| ... ||] produces Code Q a, as expected
https://downloads.haskell.org/ghc/latest/docs/users_guide/exts/template_haskell.html#syntax
## Proposed improvements or changes
Re-write docs for TExp and Code for newer compilers.
## Environment
GHC 925Matthew PickeringMatthew Pickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/23250Allow generation of TTH syntax with TH2023-06-14T19:21:22ZOleg GrenrusAllow generation of TTH syntax with TH<!--
READ THIS FIRST: If the feature you are proposing changes the language that GHC accepts
or adds any warnings to `-Wall`, it should be written as a [GHC Proposal](https://github.com/ghc-proposals/ghc-proposals/).
Other features, appr...<!--
READ THIS FIRST: If the feature you are proposing changes the language that GHC accepts
or adds any warnings to `-Wall`, it should be written as a [GHC Proposal](https://github.com/ghc-proposals/ghc-proposals/).
Other features, appropriate for a GitLab feature request, include GHC API/plugin
innovations, new low-impact compiler flags, or other similar additions to GHC.
-->
## Motivation
That is useful in cases where a library is build with TTH in mind, but we still want to generate some auxiliary declarations, where TTH cannot help us, but untyped TH can. One such example is `staged-sop` which works with TTH, but we would like to derive `Generic` declarations with TH.
An alternative approach is to use `unsafeCodeCoerce`, but then the derived `Generic` instances would be type-checked only at use sites, i.e. much later. Also `-ddump-splices` output is quite ugly: user-written instances would use TTH brackets, not `unsafeCodeCoerce`.
## Proposal
In other words allow generation of typed splices and brackets with Untyped Template Haskell.Oleg GrenrusOleg Grenrushttps://gitlab.haskell.org/ghc/ghc/-/issues/24190Allow untyped brackets in typed splices and vice versa.2023-12-21T21:18:04ZOleg GrenrusAllow untyped brackets in typed splices and vice versa.```haskell
Prelude> :set -XTemplateHaskell
Prelude> :m +Language.Haskell.TH
Prelude Language.Haskell.TH> $(unTypeCode [|| 'x' ||])
<interactive>:3:14: error: [GHC-45108]
• Typed brackets may not appear in untyped splices.
• In t...```haskell
Prelude> :set -XTemplateHaskell
Prelude> :m +Language.Haskell.TH
Prelude Language.Haskell.TH> $(unTypeCode [|| 'x' ||])
<interactive>:3:14: error: [GHC-45108]
• Typed brackets may not appear in untyped splices.
• In the Template Haskell typed quotation [|| 'x' ||]
In the untyped splice: $(unTypeCode [|| 'x' ||])
Prelude Language.Haskell.TH> $$(unsafeCodeCoerce [| 'x' |])
<interactive>:4:21: error: [GHC-45108]
• Untyped brackets may not appear in typed splices.
• In the Template Haskell quotation [| 'x' |]
In the typed splice: $$(unsafeCodeCoerce [| 'x' |])
```
but I don't see any reason to disallow these.
In my use case I want to use type brackets (`[t| ... |]`) and there isn't typed variant of that.