GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2020-02-24T17:59:27Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/17813Mark template-haskell as explicitly Safe / Trustworthy.2020-02-24T17:59:27ZOleg GrenrusMark template-haskell as explicitly Safe / Trustworthy.The template-haskell modules seem to be trustworthy since 2.12.0.0 or so, but not explicitly marked as such. Package in increasing amount depend on `template-haskell` in simple way, e.e.g to
```
deriving instance Lift URI
```
It would...The template-haskell modules seem to be trustworthy since 2.12.0.0 or so, but not explicitly marked as such. Package in increasing amount depend on `template-haskell` in simple way, e.e.g to
```
deriving instance Lift URI
```
It would be great, if `template-haskell` were explicitly `Safe` / `Trustworthy`. E.g. docs for GHC-8.10.1 rc1 are correctly saying that `Language.Haskell.TH` is "just" `SafeHaskell-inferred`: https://downloads.haskell.org/ghc/8.10.1-rc1/docs/html/libraries/template-haskell-2.16.0.0/Language-Haskell-TH.html
And when I compile a package with `-Winferred-safe-imports` I get
```
Network/URI/Static.hs:27:1: warning: [-Winferred-safe-imports]
Importing Safe-Inferred module Language.Haskell.TH.Lib from explicitly Safe module
|
27 | import Language.Haskell.TH.Lib (ExpQ)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Network/URI/Static.hs:28:1: warning: [-Winferred-safe-imports]
Importing Safe-Inferred module Language.Haskell.TH.Quote from explicitly Safe module
|
28 | import Language.Haskell.TH.Quote (QuasiQuoter(..))
|
```
---
EDIT: The patch should be trivial, as `pretty` is explicitly `Safe`, so keeping SafeHaskell invariant shouldn't be a problem.8.10.1https://gitlab.haskell.org/ghc/ghc/-/issues/17511HEAD regression: TH code fails to compile due to Unit%2020-08-30T09:33:18ZRyan ScottHEAD regression: TH code fails to compile due to Unit%The following program compiles in GHC 8.8.1 and earlier, but not with GHC HEAD:
```hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE TemplateHaskell #-}
module Bug where
import Language.Haskell.TH
f :: ...The following program compiles in GHC 8.8.1 and earlier, but not with GHC HEAD:
```hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE TemplateHaskell #-}
module Bug where
import Language.Haskell.TH
f :: $(pure (ForallT [] [TupleT 1 `AppT` (ConT ''Show `AppT` ConT ''Int)] (ConT ''String)))
f = "abc"
```
```
$ ~/Software/ghc5/inplace/bin/ghc-stage2 Bug.hs
[1 of 1] Compiling Bug ( Bug.hs, Bug.o, Bug.dyn_o )
Bug.hs:8:8: error:
• Can't find interface-file declaration for type constructor or class GHC.Classes.Unit%
Probable cause: bug in .hi-boot file, or inconsistent .hi file
Use -ddump-if-trace to get an idea of which file caused the error
• In the type signature: f :: (Unit Show Int => String)
|
8 | f :: $(pure (ForallT [] [TupleT 1 `AppT` (ConT ''Show `AppT` ConT ''Int)] (ConT ''String)))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
I'm not sure if this program should compile or not, but it does seem like we should give a better error message here.8.10.1https://gitlab.haskell.org/ghc/ghc/-/issues/17461Type operator is parenthesized incorrectly in standalone kind signature with ...2020-02-25T01:04:31ZRyan ScottType operator is parenthesized incorrectly in standalone kind signature with -ddump-splicesIf you compile the following code on GHC HEAD:
```hs
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Bug where
import Data.Kind
$([d| ...If you compile the following code on GHC HEAD:
```hs
{-# LANGUAGE StandaloneKindSignatures #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Bug where
import Data.Kind
$([d| type (:+:) :: Type -> Type -> Type
type (:+:) = Either
|])
```
You'll get some curious output:
```
$ ~/Software/ghc5/inplace/bin/ghc-stage2 --interactive Bug.hs -dsuppress-uniques
GHCi, version 8.9.0.20191110: https://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/rgscott/.ghci
[1 of 1] Compiling Bug ( Bug.hs, interpreted )
Bug.hs:(9,3)-(11,6): Splicing declarations
[d| type :+: :: Type -> Type -> Type
type (:+:) = Either |]
======>
type :+: :: Type -> Type -> Type
type (:+:) = Either
```
Note the incorrectly parenthesized standalone kind signature `type :+: :: Type -> Type -> Type`. Curiously, this doesn't happen in the body of the type synonym `type (:+:) = Either`.8.10.1https://gitlab.haskell.org/ghc/ghc/-/issues/17394-ddump-splices fails to preserve DataKinds tick when splicing InfixT2019-10-25T11:10:10ZRyan Scott-ddump-splices fails to preserve DataKinds tick when splicing InfixTIf you compile the following code:
```hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Bug where
import GHC.Generics
import Language.Haskell.TH
type T = $(infixT (promotedT 'Noth...If you compile the following code:
```hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Bug where
import GHC.Generics
import Language.Haskell.TH
type T = $(infixT (promotedT 'Nothing) '(:*:) (promotedT 'Nothing))
```
You'll get the following `-ddump-splices` output:
```
$ /opt/ghc/8.8.1/bin/ghci Bug.hs
GHCi, version 8.8.1: https://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/rgscott/.ghci
[1 of 1] Compiling Bug ( Bug.hs, interpreted )
Bug.hs:9:12-66: Splicing type
infixT (promotedT 'Nothing) '(:*:) (promotedT 'Nothing)
======>
(:*:) 'Nothing 'Nothing
Ok, one module loaded.
```
Notice how the type that gets spliced in is `(:*:) 'Nothing 'Nothing`. This is actually incorrect, since I used `(:*:)` as a _data_ constructor name in the original code (i.e., `'(:*:)`), not `(:*:)` as a _type_ constructor name (i.e., `''(:*:)`). One consequence is that copy-pasting `(:*:) 'Nothing 'Nothing` back into a Haskell file will fail.
Patch incoming.8.10.1https://gitlab.haskell.org/ghc/ghc/-/issues/17270GHC HEAD regression: -Wincomplete-patterns incorrectly warns on TH-quoted fun...2020-05-29T11:23:52ZRyan ScottGHC HEAD regression: -Wincomplete-patterns incorrectly warns on TH-quoted functionCompile the following program with GHC HEAD:
```hs
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wall #-}
module Bug where
import Data.Type.Equality
...Compile the following program with GHC HEAD:
```hs
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -Wall #-}
module Bug where
import Data.Type.Equality
f :: a :~: Int -> b :~: Bool -> a :~: b -> void
f Refl Refl x = case x of {}
$([d| g :: a :~: Int -> b :~: Bool -> a :~: b -> void
g Refl Refl x = case x of {}
|])
```
And you'll get a warning, surprisingly enough:
```
$ ~/Software/ghc5/inplace/bin/ghc-stage2 Bug.hs
[1 of 1] Compiling Bug ( Bug.hs, Bug.o, Bug.dyn_o )
Bug.hs:13:3: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In a case alternative: Patterns not matched: Refl
|
13 | $([d| g :: a :~: Int -> b :~: Bool -> a :~: b -> void
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
```
This is unusual because `f` and `g` have the same definition and both should be deemed exhaustive, since nothing inhabits the type `Int :~: Bool`. The only difference between `f` and `g` is that the latter function is defined using Template Haskell quotes.
This is a regression from GHC 8.8.1 and earlier, which do not produce any warnings for either function.
cc @sgraf8128.10.1Sebastian GrafSebastian Grafhttps://gitlab.haskell.org/ghc/ghc/-/issues/16895Panic when splicing a malformed InfixE2019-07-07T17:59:56ZArtyom KazakPanic when splicing a malformed InfixE# Summary
GHC panics when splicing `InfixE a op b` or `UInfixE a op b` where `op` is not a variable. Related issue: https://gitlab.haskell.org/ghc/ghc/issues/4877.
# Steps to reproduce
Compiling the following file results in a panic:
...# Summary
GHC panics when splicing `InfixE a op b` or `UInfixE a op b` where `op` is not a variable. Related issue: https://gitlab.haskell.org/ghc/ghc/issues/4877.
# Steps to reproduce
Compiling the following file results in a panic:
```haskell
-- panic.hs
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
main = print $(uInfixE [|1|] [|id id|] [|2|])
```
```
$ stack ghc --compiler=ghc-8.6.5 -- -fforce-recomp panic.hs
[1 of 1] Compiling Main ( panic.hs, panic.o )
Linking panic ...
Undefined symbols for architecture x86_64:
"_Main_main_closure", referenced from:
_ZCMain_main_info in panic.o
_u4lI_srt in panic.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
`gcc' failed in phase `Linker'. (Exit code: 1)
```
The behavior is slightly different when using GHCi:
```
> :set -XTemplateHaskell
> import Language.Haskell.TH
> $(uInfixE [|1|] [|id id|] [|2|])
ghc: panic! (the 'impossible' happened)
(GHC version 8.6.5 for x86_64-apple-darwin):
nameModule
internal it_a4n5
Call stack:
CallStack (from HasCallStack):
callStackDoc, called at compiler/utils/Outputable.hs:1160:37 in ghc:Outputable
pprPanic, called at compiler/basicTypes/Name.hs:240:3 in ghc:Name
```
# Expected behavior
Not panicking.
# Environment
* GHC version used: 8.6.5
Optional:
* Operating System: macOS Mojave
* System Architecture: x648.10.1Alex DAlex Dhttps://gitlab.haskell.org/ghc/ghc/-/issues/16881Template Haskell drops unary tuples2020-08-30T11:30:50ZRichard Eisenbergrae@richarde.devTemplate Haskell drops unary tuples# Summary
Template Haskell drops unary tuples
# Steps to reproduce
```hs
foo = $( return (TupE [VarE 'undefined]) )
bar = foo `seq` "hi"
```
and evaluate `bar`. You will observe `undefined` is evaluated leading to an exception.
# E...# Summary
Template Haskell drops unary tuples
# Steps to reproduce
```hs
foo = $( return (TupE [VarE 'undefined]) )
bar = foo `seq` "hi"
```
and evaluate `bar`. You will observe `undefined` is evaluated leading to an exception.
# Expected behavior
I expect Template Haskell to throw an exception, saying that unary tuples do not exist.
# Environment
* GHC version used: 8.6
# Commentary
Convert.hs drops unary tuple constructors. Of course, we don't have unary boxed tuples, but if `foo` is accepted above, I would surely expect `bar` to be `"hi"`. Instead, we should just reject `foo` outright.8.10.1Alex DAlex Dhttps://gitlab.haskell.org/ghc/ghc/-/issues/16666-ddump-splices parenthesizes QuantifiedConstraints incorrectly in instance de...2019-06-05T08:28:21ZRyan Scott-ddump-splices parenthesizes QuantifiedConstraints incorrectly in instance declarations(Originally observed [here](https://github.com/haskell/haddock/issues/1063).)
If you compile this file with GHC 8.6 or later:
```hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses ...(Originally observed [here](https://github.com/haskell/haddock/issues/1063).)
If you compile this file with GHC 8.6 or later:
```hs
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Bug where
$([d| class (c => d) => Implies c d
instance (c => d) => Implies c d
|])
```
You'll get the following `-ddump-splices` output:
```
$ /opt/ghc/8.6.5/bin/ghci Bug.hs
GHCi, version 8.6.5: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/rgscott/.ghci
[1 of 1] Compiling Bug ( Bug.hs, interpreted )
Bug.hs:(10,3)-(12,6): Splicing declarations
[d| class (c_a1A7 => d_a1A8) => Implies_a1A6 c_a1A7 d_a1A8
instance (c_a1A9 => d_a1Aa) => Implies_a1A6 c_a1A9 d_a1Aa |]
======>
class c_a4rz => d_a4rA => Implies_a4ry c_a4rz d_a4rA
instance c_a4rB => d_a4rC => Implies_a4ry c_a4rB d_a4rC
```
This is wrong, as required parentheses are missing around `c => d` in both the class and instance declarations.8.10.1https://gitlab.haskell.org/ghc/ghc/-/issues/16300Make TH always reify data types with explicit return kinds2019-07-26T14:15:14ZRyan ScottMake TH always reify data types with explicit return kindsCurrently, whenever you reify a data type with Template Haskell, it will return a `DataD`/`NewtypeD` where the return kind information has been set to `Nothing`:
```
λ> putStrLn $(reify ''Bool >>= stringE . show)
TyConI (DataD [] GHC.Ty...Currently, whenever you reify a data type with Template Haskell, it will return a `DataD`/`NewtypeD` where the return kind information has been set to `Nothing`:
```
λ> putStrLn $(reify ''Bool >>= stringE . show)
TyConI (DataD [] GHC.Types.Bool [] Nothing [NormalC GHC.Types.False [],NormalC GHC.Types.True []] [])
```
One could argue that this isn't a problem since data types always have return kind `Type` anyway. For 99% of data types, this is true. There are a handful of exceptions, such as unboxed tuples (with return kind `TYPE (TupleRep [...])`, but those could be dismissed as unusual special cases.
With the advent of [unlifted newtypes](https://phabricator.haskell.org/D4777), however, things become murkier. `UnliftedNewtypes` let you define newtypes like this one:
```hs
newtype Foo :: TYPE IntRep where MkFoo :: Int# -> Foo
```
Notice how the return kind is //not// `Type`, but instead `TYPE IntRep`. However, TH reification doesn't clue you in to this fact:
```
λ> putStrLn $(reify ''Foo >>= stringE . show)
TyConI (NewtypeD [] Ghci8.Foo [] Nothing (GadtC [Ghci8.MkFoo] [(Bang NoSourceUnpackedness NoSourceStrictness,ConT GHC.Prim.Int#)] (ConT Ghci8.Foo)) [])
```
Still `Nothing`. There's no easy way in general to determine what the return kind of an unlifted newtype is using TH reification, which is unfortunate.
Luckily, I think there's a very simple fix that we could apply here: just have TH reification return `Just (<kind>)` instead of `Nothing`! There's no technical reason why TH couldn't do this; the only reason it currently returns `Nothing` is due to historical convention. Moreover, I doubt that this would even break any code in the wild, since `Nothing` doesn't convey any useful information in the context of TH reification anyway.
Does this sound reasonable?
<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":"Make TH always reify data types with explicit return kinds","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"Currently, whenever you reify a data type with Template Haskell, it will return a `DataD`/`NewtypeD` where the return kind information has been set to `Nothing`:\r\n\r\n{{{\r\nλ> putStrLn $(reify ''Bool >>= stringE . show)\r\nTyConI (DataD [] GHC.Types.Bool [] Nothing [NormalC GHC.Types.False [],NormalC GHC.Types.True []] [])\r\n}}}\r\n\r\nOne could argue that this isn't a problem since data types always have return kind `Type` anyway. For 99% of data types, this is true. There are a handful of exceptions, such as unboxed tuples (with return kind `TYPE (TupleRep [...])`, but those could be dismissed as unusual special cases.\r\n\r\nWith the advent of [https://phabricator.haskell.org/D4777 unlifted newtypes], however, things become murkier. `UnliftedNewtypes` let you define newtypes like this one:\r\n\r\n{{{#!hs\r\nnewtype Foo :: TYPE IntRep where MkFoo :: Int# -> Foo\r\n}}}\r\n\r\nNotice how the return kind is //not// `Type`, but instead `TYPE IntRep`. However, TH reification doesn't clue you in to this fact:\r\n\r\n{{{\r\nλ> putStrLn $(reify ''Foo >>= stringE . show)\r\nTyConI (NewtypeD [] Ghci8.Foo [] Nothing (GadtC [Ghci8.MkFoo] [(Bang NoSourceUnpackedness NoSourceStrictness,ConT GHC.Prim.Int#)] (ConT Ghci8.Foo)) [])\r\n}}}\r\n\r\nStill `Nothing`. There's no easy way in general to determine what the return kind of an unlifted newtype is using TH reification, which is unfortunate.\r\n\r\nLuckily, I think there's a very simple fix that we could apply here: just have TH reification return `Just (<kind>)` instead of `Nothing`! There's no technical reason why TH couldn't do this; the only reason it currently returns `Nothing` is due to historical convention. Moreover, I doubt that this would even break any code in the wild, since `Nothing` doesn't convey any useful information in the context of TH reification anyway.\r\n\r\nDoes this sound reasonable?","type_of_failure":"OtherFailure","blocking":[]} -->8.10.1https://gitlab.haskell.org/ghc/ghc/-/issues/15843Tuple sections can't be quoted2019-07-07T18:02:45ZMatthew PickeringTuple sections can't be quotedThere are quite a few forms that are not supported in template haskell quotes. It seems that it would be at least a good warm up patch to add support for tuple sections which you can do simply by desugaring to a lambda and the normal tup...There are quite a few forms that are not supported in template haskell quotes. It seems that it would be at least a good warm up patch to add support for tuple sections which you can do simply by desugaring to a lambda and the normal tuple constructor.
```
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
module Foo where
foo = [|| (,5) ||]
```
1. Modify `DsMeta.repE` to handle tuple sections. You can desugar `(,5) => \x -> (x, 5)`.
1. Add the above test to the test suite.8.10.1Alex DAlex Dhttps://gitlab.haskell.org/ghc/ghc/-/issues/14671Make the Template Haskell class Lift work over typed expressions2019-07-07T18:16:04ZSimon Peyton JonesMake the Template Haskell class Lift work over typed expressionsAt the moment we have the `Lift` class in TH:
```
class Lift t where
lift :: t -> Q Exp
```
But that loses type information. What we want is this:
```
Lift t where
typedLift :: t -> Q (TExp t)
lift :: Lift t => t -> Q Exp
lift = ...At the moment we have the `Lift` class in TH:
```
class Lift t where
lift :: t -> Q Exp
```
But that loses type information. What we want is this:
```
Lift t where
typedLift :: t -> Q (TExp t)
lift :: Lift t => t -> Q Exp
lift = fmap unType . typedLift
```
Otherwise, when you want the typed version, people resort to unsafe-coerce operations, which are entirely unnecessary.
See [this thread on the libraries list](https://mail.haskell.org/pipermail/libraries/2018-January/028409.html).
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.2.2 |
| 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":"Make the Template Haskell class Lift work over typed expressions","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.2","keywords":["TemplateHaskell"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"At the moment we have the `Lift` class in TH:\r\n{{{\r\nclass Lift t where\r\n lift :: t -> Q Exp\r\n}}}\r\nBut that loses type information. What we want is this:\r\n{{{\r\nLift t where\r\n typedLift :: t -> Q (TExp t)\r\n\r\nlift :: Lift t => t -> Q Exp\r\nlift = fmap unType . typedLift\r\n}}}\r\nOtherwise, when you want the typed version, people resort to unsafe-coerce operations, which are entirely unnecessary.\r\n\r\nSee [https://mail.haskell.org/pipermail/libraries/2018-January/028409.html this thread on the libraries list].\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.10.1