GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2020-05-09T15:41:44Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/18153reifyInstances doesn't work with closed type families2020-05-09T15:41:44ZEllie HermaszewskareifyInstances doesn't work with closed type families## Summary
`reifyInstances` throws an error when applied to the name of a closed type family
```
Bug.hs:(13,1)-(15,9): error:
• reifyInstances: ‘ClosedFam’
is not a class constraint or type family application
• In the a...## Summary
`reifyInstances` throws an error when applied to the name of a closed type family
```
Bug.hs:(13,1)-(15,9): error:
• reifyInstances: ‘ClosedFam’
is not a class constraint or type family application
• In the argument of reifyInstances: Bug.ClosedFam
```
## Steps to reproduce
- Compile the following module
- Observe that an error is thrown by `reifyInstances`
```haskell
{-# LANGUAGE TemplateHaskell #-}
module Bug
where
import Language.Haskell.TH
-- Select between these two lines
--
-- While the open type family works, the closed one doesn't
type family ClosedFam where
-- type family ClosedFam
do
reifyInstances ''ClosedFam []
pure []
```
## Expected behavior
`reifyInstances` to return the list of matching equations in `ClosedFam`. Or at the very least for the error message not to confuse me by saying that `ClosedFam` isn't a type family.
## Environment
* GHC version used: 8.8.2https://gitlab.haskell.org/ghc/ghc/-/issues/17222.hie files don't contain template Haskell splices2020-04-03T14:45:16ZOllie Charles.hie files don't contain template Haskell splices## Motivation
I want to use the new `.hie` files to do full-project reachability analysis. Given some roots (e.g., `main` in module `Main`), the program will report any declarations that aren't reachable from those roots, thus identifyi...## Motivation
I want to use the new `.hie` files to do full-project reachability analysis. Given some roots (e.g., `main` in module `Main`), the program will report any declarations that aren't reachable from those roots, thus identifying them as dead code. I do this by traversing `HieAST`s and building a graph of which symbols refer to which. However, Template Haskell splices aren't expanded, so if something is referred to from a splice, it won't cause that node to be correctly represented in the reachability graph.
One example of this is Yesod - we have the splice `mkYesodDispatch "App" resourcesApp`, which creates a `YesodDispatch` instance for `App`:
```
src/AppMain.hs:80:1-34: Splicing declarations
mkYesodDispatch "App" resourcesApp
======>
instance YesodDispatch App where
yesodDispatch env6176_a1vQg req6176_a1vQh
= helper6176_a1vQi (pathInfo req6176_a1vQh)
where
helper6176_a1vQi ((:) "robots.txt" [])
= case requestMethod req6176_a1vQh of
"GET"
-> (((yesodRunner getRobotTxtR) env6176_a1vQg) (Just RobotTxtR))
req6176_a1vQh
_ -> (((yesodRunner (void badMethod)) env6176_a1vQg)
(Just RobotTxtR))
req6176_a1vQh
```
However, the `.hie` file doesn't contain all of this information, it only contains the instance head. `ppHie` reports:
```
Node src/AppMain.hs:80:1-34 [(AbsBinds, HsBindLR),
(ClsInstD, InstDecl), (FunBind, HsBindLR), (HsApp, HsExpr),
(HsAppTy, HsType), (HsConLikeOut, HsExpr), (HsTyVar, HsType),
(HsVar, HsExpr), (HsWrap, HsExpr), (VarBind, HsBindLR)] [53, 58,
55,
66] [(Right C:YesodDispatch,
IdentifierDetails Nothing {Use}),
(Right yesodDispatch,
IdentifierDetails Nothing {ValBind InstanceBind ModuleScope (Just SrcSpanOneLine "src/AppMain.hs" 80 1 35)}),
(Right yesodDispatch,
IdentifierDetails Just 55 {ValBind RegularBind ModuleScope (Just SrcSpanOneLine "src/AppMain.hs" 80 1 35)}),
(Right $cyesodDispatch,
IdentifierDetails Just 55 {Use}),
(Right $cp1YesodDispatch,
IdentifierDetails Just 53 {Use})]
```
and that's it. Thus the symbols referred to in the definition of `yesodDispatch` aren't visible to me.
## Proposal
The full instance declaration is visible.https://gitlab.haskell.org/ghc/ghc/-/issues/17888Load Haskell libraries more lazily in TemplateHaskell/ghci/etc2020-03-15T16:34:17ZJudah JacobsonLoad Haskell libraries more lazily in TemplateHaskell/ghci/etc## Motivation
Currently GHC loads shared libraries from `-package` or `-package-id` directives *eagerly*. That is, for modes like `-XTemplateHaskell` or `--interactive`, GHC looks for all packages specified via `-package{-id}` and load...## Motivation
Currently GHC loads shared libraries from `-package` or `-package-id` directives *eagerly*. That is, for modes like `-XTemplateHaskell` or `--interactive`, GHC looks for all packages specified via `-package{-id}` and loads their shared libraries at startup, whether or not they're actually needed.
We have found a few downsides of this approach:
- If a file uses TemplateHaskell then GHC loads *every* transitive dependency, even when only a small subset of the imported modules are needed. For example, pandoc has many transitive dependencies but only uses TH to generate a few JSON instances.
- When you use ghci, the shared libraries aren't needed if all you want to do is typecheck or `:browse` code. However, ghci loads those shared libraries unconditionally.
- We found it harder to get shared libraries for some of our C/C++ dependencies. In reality, nothing from our TH splices used those libraries. Unfortunately, GHC's eager nature made it try to load them regardless of whether they were needed.
As it turns out, GHC *is* capable of loading shared libraries more lazily. In fact, if you only pass `-package-db` and *not* `-package`, the package will be loaded lazily; it can even be directly imported, as long as it was registered with `exposed: True`. However, most build systems nowadays use `-hide-all-packages` which has better behavior; for example, it allows multiple transitive deps of the same package name but different versions.
Internally, our team uses the following simple (2-line) patch:
https://gitlab.haskell.org/ghc/ghc/commit/e4ffc94b58d1c6518f76677ea110125b34a06c3d
The downside of that patch is that it breaks the following use-case:
```
ghci -package foo -lbar
```
When running code in ghci, GHC allows the C library `bar` to use symbols defined in the Haskell library `foo`. This note documents it in more detail:
https://gitlab.haskell.org/ghc/ghc/blob/master/compiler/GHC/Runtime/Linker.hs#L390
With the proposed change, `foo` would instead of use symbols from `bar`.
## Proposal
I propose adding a new flag to GHC to make it load shared libraries from `-package`/`-package-id` lazily (as in the above patch). We'd probably want to turn that flag on by default in tools such as Cabal and Stack. As far as I can tell they don't rely on the edge case I called out above.
Actually, to be honest, I'm not really aware of any code that relies on that behavior anymore. If so, maybe we should just enable the flag by default? (Note that a couple of GHC tests do correctly fail under the above patch).
If this is better-suited as a GHC proposal, let me know and I can file it there. I wanted to double-check first since this could end up as a fairly minor change.https://gitlab.haskell.org/ghc/ghc/-/issues/10599Template Haskell doesn't allow `newName "type"`2020-01-23T19:37:51ZmetefichaTemplate Haskell doesn't allow `newName "type"`Using `type` as a name is, of course, forbidden. OTOH, `type_1` is allowed as a name.
However, using GHC 7.10.1 and `ghc --make T.hs` on files:
```hs
-- T.hs
{-# LANGUAGE TemplateHaskell #-}
module T where
import Q
test
-- Q.hs
module...Using `type` as a name is, of course, forbidden. OTOH, `type_1` is allowed as a name.
However, using GHC 7.10.1 and `ghc --make T.hs` on files:
```hs
-- T.hs
{-# LANGUAGE TemplateHaskell #-}
module T where
import Q
test
-- Q.hs
module Q where
import Language.Haskell.TH
test :: Q [Dec]
test = do
t <- newName "type"
return
[FunD t
[Clause
[]
(NormalB $ LitE $ CharL 't')
[]]]
```
Leads to the following error:
```
$ ghc --make -ddump-splices T.hs
[2 of 2] Compiling T ( T.hs, T.o )
T.hs:6:1:
Illegal variable name: ‘type’
When splicing a TH declaration: ident_0 type_1 = type_1
```
The above example works fine for GHC 7.8.4, so it's a regression.
Reference: https://github.com/yesodweb/persistent/issues/412
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 7.10.1 |
| 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":"Template Haskell doesn't allow `newName \"type\"`","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Using `type` as a name is, of course, forbidden. OTOH, `type_1` is allowed as a name.\r\n\r\nHowever, using GHC 7.10.1 and `ghc --make T.hs` on files:\r\n\r\n{{{#!hs\r\n-- T.hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\nmodule T where\r\nimport Q\r\ntest\r\n\r\n-- Q.hs\r\nmodule Q where\r\n\r\nimport Language.Haskell.TH\r\n\r\ntest :: Q [Dec]\r\ntest = do\r\n t <- newName \"type\"\r\n return\r\n [FunD t\r\n [Clause\r\n []\r\n (NormalB $ LitE $ CharL 't')\r\n []]]\r\n}}}\r\n\r\nLeads to the following error:\r\n\r\n{{{\r\n$ ghc --make -ddump-splices T.hs\r\n[2 of 2] Compiling T ( T.hs, T.o )\r\n\r\nT.hs:6:1:\r\n Illegal variable name: ‘type’\r\n When splicing a TH declaration: ident_0 type_1 = type_1\r\n}}}\r\n\r\nThe above example works fine for GHC 7.8.4, so it's a regression.\r\n\r\nReference: https://github.com/yesodweb/persistent/issues/412","type_of_failure":"OtherFailure","blocking":[]} -->Richard Eisenbergrae@richarde.devRichard Eisenbergrae@richarde.devhttps://gitlab.haskell.org/ghc/ghc/-/issues/15167DerivClause list is not populated for (TyConI (DataD ...))2020-01-23T19:20:40Z0xd34df00dDerivClause list is not populated for (TyConI (DataD ...))```haskell
% cat Test.hs
{-# LANGUAGE LambdaCase #-}
module Test where
import Language.Haskell.TH
test :: Name -> Q [Dec]
test name = reify name >>= \case
TyConI dec -> do
runIO $ print dec
pure []
_ -> pure []...```haskell
% cat Test.hs
{-# LANGUAGE LambdaCase #-}
module Test where
import Language.Haskell.TH
test :: Name -> Q [Dec]
test name = reify name >>= \case
TyConI dec -> do
runIO $ print dec
pure []
_ -> pure []
% cat Run.hs
{-# LANGUAGE TemplateHaskell #-}
import Test
data Foo = Foo deriving (Eq, Ord, Show)
test ''Foo
% ghc Run.hs
[2 of 2] Compiling Main ( Run.hs, Run.o )
DataD [] Main.Foo [] Nothing [NormalC Main.Foo []] []
```
One might expect the `DataD` to mention `Eq, Ord, Show` in the `DerivClause` list, but it doesn't.
This behavior manifests with every ghc version I tried: 8.0.2, 8.2.2, 8.4.2. I also asked a question whether it's intended behaviour on \#haskell, and I've been advised to open a bug report, so here it is.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.4.2 |
| 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":"DerivClause list is not populated for (TyConI (DataD ...))","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"{{{#!haskell\r\n% cat Test.hs\r\n{-# LANGUAGE LambdaCase #-}\r\n\r\nmodule Test where\r\n\r\nimport Language.Haskell.TH\r\n\r\ntest :: Name -> Q [Dec]\r\ntest name = reify name >>= \\case\r\n TyConI dec -> do\r\n runIO $ print dec\r\n pure []\r\n _ -> pure []\r\n\r\n% cat Run.hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n\r\nimport Test\r\n\r\ndata Foo = Foo deriving (Eq, Ord, Show)\r\n\r\ntest ''Foo\r\n\r\n% ghc Run.hs\r\n[2 of 2] Compiling Main ( Run.hs, Run.o )\r\nDataD [] Main.Foo [] Nothing [NormalC Main.Foo []] []\r\n}}}\r\n\r\nOne might expect the `DataD` to mention `Eq, Ord, Show` in the `DerivClause` list, but it doesn't.\r\n\r\nThis behavior manifests with every ghc version I tried: 8.0.2, 8.2.2, 8.4.2. I also asked a question whether it's intended behaviour on #haskell, and I've been advised to open a bug report, so here it is.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/15270TH doesn't verify name types during conversion2020-01-23T19:20:24ZBen GamariTH doesn't verify name types during conversionAngerman reported that a use of the [\`deriveEq\`](http://hackage.haskell.org/package/deriving-compat-0.4.2/docs/src/Data.Eq.Deriving.Internal.html#deriveEq1) splice is causing GHC to abort with an assertion failure:
```hs
zonkExpr env ...Angerman reported that a use of the [\`deriveEq\`](http://hackage.haskell.org/package/deriving-compat-0.4.2/docs/src/Data.Eq.Deriving.Internal.html#deriveEq1) splice is causing GHC to abort with an assertion failure:
```hs
zonkExpr env (HsVar x (L l id))
= ASSERT2( isNothing (isDataConId_maybe id), ppr id )
return (HsVar x (L l (zonkIdOcc env id)))
```
I suspect the `deriveEq1` is calling `varE` with a DataCon name. We should catch this case and throw a better error message.https://gitlab.haskell.org/ghc/ghc/-/issues/15356Template Haskell should turn off RebindableSyntax in quotes2020-01-23T19:18:03ZRichard Eisenbergrae@richarde.devTemplate Haskell should turn off RebindableSyntax in quotesIf I say
```hs
{-# LANGUAGE RebindableSyntax, TemplateHaskellQuotes #-}
module Bug ( quote ) where
quote = [| if 5>3 then 'x' else 'y' |]
```
GHC complains that `ifThenElse` and `fromInteger` are not in scope. If I then bring these i...If I say
```hs
{-# LANGUAGE RebindableSyntax, TemplateHaskellQuotes #-}
module Bug ( quote ) where
quote = [| if 5>3 then 'x' else 'y' |]
```
GHC complains that `ifThenElse` and `fromInteger` are not in scope. If I then bring these into scope somehow, then the resulting quote does not use them.
I think it's correct that the resulting quote doesn't use the rebindable syntax -- a quote should just stand for a convenient way or writing the TH AST. But then we shouldn't complain about missing rebindable syntax bits inside of a quote.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.4.3 |
| 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":"Template Haskell should turn off RebindableSyntax in quotes","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"If I say\r\n\r\n{{{#!hs\r\n{-# LANGUAGE RebindableSyntax, TemplateHaskellQuotes #-}\r\n\r\nmodule Bug ( quote ) where\r\n\r\nquote = [| if 5>3 then 'x' else 'y' |]\r\n}}}\r\n\r\nGHC complains that `ifThenElse` and `fromInteger` are not in scope. If I then bring these into scope somehow, then the resulting quote does not use them.\r\n\r\nI think it's correct that the resulting quote doesn't use the rebindable syntax -- a quote should just stand for a convenient way or writing the TH AST. But then we shouldn't complain about missing rebindable syntax bits inside of a quote.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/17689Template Haskell fails when quoting an out-of-scope SPECIALISE2020-01-15T18:37:54ZRichard Eisenbergrae@richarde.devTemplate Haskell fails when quoting an out-of-scope SPECIALISEIf I say
```hs
$( do ty <- [d| {-# SPECIALISE x :: Int #-} |]
TH.runIO $ print ty
return [] )
```
then I see
```
• Not in scope: ‘x’
• In the Template Haskell quotation
[d| {-# SPECIALISE x :: Int #-} |]
``...If I say
```hs
$( do ty <- [d| {-# SPECIALISE x :: Int #-} |]
TH.runIO $ print ty
return [] )
```
then I see
```
• Not in scope: ‘x’
• In the Template Haskell quotation
[d| {-# SPECIALISE x :: Int #-} |]
```
This surprises me, as `x` does not need to be in scope to be able to desugar this quotation. Like we do elsewhere, we should just make `x` a capturable identifier.
To be clear, this is not ruining my day. I just came across it in other work and was surprised. Happy for this to be low priority.https://gitlab.haskell.org/ghc/ghc/-/issues/17650Inconsistent definition for `kindedTV` and `plainTV` in template-haskell2020-01-15T18:32:15ZIavor S. DiatchkiInconsistent definition for `kindedTV` and `plainTV` in template-haskellThe `template-haskell` package has two versions of `kindedTV` and `plainTV`: one is in `*.TH.Lib` and the other is in `*.TH.Lib.Internal`.
The difference between the two is that the "internal" one takes parameters that are in `Q` monad...The `template-haskell` package has two versions of `kindedTV` and `plainTV`: one is in `*.TH.Lib` and the other is in `*.TH.Lib.Internal`.
The difference between the two is that the "internal" one takes parameters that are in `Q` monad, while the other one does not.
The style used by the "internal" one matches how the rest of the library works, and is compatible with using quotations (e.g., it allows one to write `kindedTV nm [t| MyKind |]`). On the other hand, the version in `*.TH.Lib` is simply a synonym for the constructor of the datatype and as such seems to serve no useful purpose.
This looks like an accidental divergence: we should have just one version which has the type of the definitions that are currently in `*.TH.Lib.Internal` but it resides in `*.TH.Lib`.https://gitlab.haskell.org/ghc/ghc/-/issues/17205Error message mentions pending splices2019-12-27T21:51:59ZRichard Eisenbergrae@richarde.devError message mentions pending splicesWhen I say
```hs
{-# LANGUAGE TemplateHaskellQuotes #-}
module Bug where
import Language.Haskell.TH
f :: Q Exp -> Q Exp
f x = [| Just $x |]
```
I get
```
Bug.hs:8:7: error:
• No instance for (Language.Haskell.TH.Syntax.Lift (Q ...When I say
```hs
{-# LANGUAGE TemplateHaskellQuotes #-}
module Bug where
import Language.Haskell.TH
f :: Q Exp -> Q Exp
f x = [| Just $x |]
```
I get
```
Bug.hs:8:7: error:
• No instance for (Language.Haskell.TH.Syntax.Lift (Q Exp))
arising from a use of ‘Language.Haskell.TH.Syntax.lift’
• In the expression: Language.Haskell.TH.Syntax.lift x
In the expression:
[| Just $ x |]
pending(rn) [<x, Language.Haskell.TH.Syntax.lift x>]
In an equation for ‘f’:
f x
= [| Just $ x |]
pending(rn) [<x, Language.Haskell.TH.Syntax.lift x>]
|
8 | f x = [| Just $x |]
| ^^^^^^^^^^^^^
```
This is unfortunate in at least two ways:
1. The error message mentions pending splices.
2. I clearly wanted to splice `x`. But because I have `TemplateHaskellQuotes` (not `TemplateHaskell`), I have actually applied the `$` operator.
I suppose this ticket is really about (1), but I wanted to whinge about (2) while I had your attention. Perhaps `TemplateHaskellQuotes` should change the parsing of `$`, even if splices aren't actually allowed.https://gitlab.haskell.org/ghc/ghc/-/issues/17523Reification of primitive equality2019-12-04T16:55:22ZRichard Eisenbergrae@richarde.devReification of primitive equalityWhen I reify `(~~)`, I get something that looks like
```hs
class a ~ b => GHC.Types.~~ (a :: k0) (b :: k1)
```
This is wrong in at least two ways:
1. `~` is homogeneous, so this is ill-kinded
2. The superclass of `~~` is `~#`, not `~`...When I reify `(~~)`, I get something that looks like
```hs
class a ~ b => GHC.Types.~~ (a :: k0) (b :: k1)
```
This is wrong in at least two ways:
1. `~` is homogeneous, so this is ill-kinded
2. The superclass of `~~` is `~#`, not `~`.
I think we should just fail if we try to reify `~#` or `R#`. But we don't. Instead, look at this:
```hs
reify_tc_app :: TyCon -> [Type.Type] -> TcM TH.Type
reify_tc_app tc tys
= do { tys' <- reifyTypes (filterOutInvisibleTypes tc tys)
; maybe_sig_t (mkThAppTs r_tc tys') }
where
arity = tyConArity tc
r_tc | isUnboxedSumTyCon tc = TH.UnboxedSumT (arity `div` 2)
| isUnboxedTupleTyCon tc = TH.UnboxedTupleT (arity `div` 2)
| isPromotedTupleTyCon tc = TH.PromotedTupleT (arity `div` 2)
-- See Note [Unboxed tuple RuntimeRep vars] in TyCon
| isTupleTyCon tc = if isPromotedDataCon tc
then TH.PromotedTupleT arity
else TH.TupleT arity
| tc `hasKey` constraintKindTyConKey
= TH.ConstraintT
| tc `hasKey` funTyConKey = TH.ArrowT
| tc `hasKey` listTyConKey = TH.ListT
| tc `hasKey` nilDataConKey = TH.PromotedNilT
| tc `hasKey` consDataConKey = TH.PromotedConsT
| tc `hasKey` heqTyConKey = TH.EqualityT
| tc `hasKey` eqPrimTyConKey = TH.EqualityT
| tc `hasKey` eqReprPrimTyConKey = TH.ConT (reifyName coercibleTyCon)
| isPromotedDataCon tc = TH.PromotedT (reifyName tc)
| otherwise = TH.ConT (reifyName tc)
```
This erroneously maps the heterogeneous `heqTyCon` (that is, `~~`) to `EqualityT` (presumably homogeneous -- indeed, it maps to `~` in ThToHs), along with strangely mapping primitive equality to lifted versions. And it doesn't detect `~` at all! Indeed, reifying `~` gives us `GHC.Types.~`.
This is all terrible. Can we fix? I propose erroring (with a nice, user-facing error message) on primitive equality, and not treating `~~` specially at all.https://gitlab.haskell.org/ghc/ghc/-/issues/14474reify RHS of "value" variable2019-11-05T21:08:02Zdailecticreify RHS of "value" variableAccording to the [documentation](https://hackage.haskell.org/package/template-haskell-2.12.0.0/docs/Language-Haskell-TH-Syntax.html#t:Info), when reifying value variables "returning the RHS has not yet been implemented because of lack of...According to the [documentation](https://hackage.haskell.org/package/template-haskell-2.12.0.0/docs/Language-Haskell-TH-Syntax.html#t:Info), when reifying value variables "returning the RHS has not yet been implemented because of lack of interest". I'd like to formally request interest since I don't see a ticket here (may have missed it).
My motivating example is to make source available for documentation and better error messages. Something like:
```hs
printSource :: Name -> Q Exp
printSource n = do
VarI _ _ (Just dec) <- reify n
lift $ pprint dec
foo x = x * 2
fooSource = $(printSource 'foo) -- === "\x_0 -> x_0 GHC.Num.* 2"
```
How significant of a change is this? I could take a pass at it if pointed to the relevant bits, having not contributed to GHC before.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.2.1 |
| 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":"reify RHS of \"value\" variable","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"According to the [https://hackage.haskell.org/package/template-haskell-2.12.0.0/docs/Language-Haskell-TH-Syntax.html#t:Info documentation], when reifying value variables \"returning the RHS has not yet been implemented because of lack of interest\". I'd like to formally request interest since I don't see a ticket here (may have missed it).\r\n\r\nMy motivating example is to make source available for documentation and better error messages. Something like:\r\n\r\n{{{#!hs\r\nprintSource :: Name -> Q Exp\r\nprintSource n = do\r\n VarI _ _ (Just dec) <- reify n\r\n lift $ pprint dec\r\n\r\nfoo x = x * 2\r\nfooSource = $(printSource 'foo) -- === \"\\x_0 -> x_0 GHC.Num.* 2\"\r\n}}}\r\n\r\nHow significant of a change is this? I could take a pass at it if pointed to the relevant bits, having not contributed to GHC before.","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/1444Template Haskell: add proper support for qualified names in non-splicing appl...2019-07-07T19:13:31ZSamuel BronsonTemplate Haskell: add proper support for qualified names in non-splicing applicationsFor the uninitiated, Derive is an application of Template Haskell that can generate external Haskell code (depending on how you use it) instead of having it spliced into a module. Template Haskell was not designed for this, and it shows ...For the uninitiated, Derive is an application of Template Haskell that can generate external Haskell code (depending on how you use it) instead of having it spliced into a module. Template Haskell was not designed for this, and it shows in the handling of qualified names. For example:
```
Prelude> '[]
GHC.Base.[]
Prelude> 'True
GHC.Base.True
Prelude> '(*)
GHC.Num.*
Prelude Data.Array.Unboxed> ''UArray
Data.Array.Base.UArray
```
It would be nice if Template Haskell could instead use public names, where available, so that Derive and similar tools would be able to use qualified names (and the quoting syntax without fear of their ending up pointing into the middle of no-mans-land, or even GHC-only land.
This would also mean that users of Derive via TH splicing wouldn't need to import so many modules that the derivings depend on.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 6.6.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | Unknown |
| Architecture | Unknown |
</details>
<!-- {"blocked_by":[],"summary":"Template Haskell: add proper support for qualified names in non-splicing applications","status":"New","operating_system":"Unknown","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"Unknown","cc":[""],"type":"FeatureRequest","description":"For the uninitiated, Derive is an application of Template Haskell that can generate external Haskell code (depending on how you use it) instead of having it spliced into a module. Template Haskell was not designed for this, and it shows in the handling of qualified names. For example:\r\n\r\n{{{\r\nPrelude> '[]\r\nGHC.Base.[]\r\nPrelude> 'True\r\nGHC.Base.True\r\nPrelude> '(*)\r\nGHC.Num.*\r\nPrelude Data.Array.Unboxed> ''UArray\r\nData.Array.Base.UArray\r\n}}}\r\n\r\nIt would be nice if Template Haskell could instead use public names, where available, so that Derive and similar tools would be able to use qualified names (and the quoting syntax without fear of their ending up pointing into the middle of no-mans-land, or even GHC-only land.\r\n\r\nThis would also mean that users of Derive via TH splicing wouldn't need to import so many modules that the derivings depend on.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/2041Allow splicing in concrete syntax2019-07-07T19:10:29ZIan Lynagh <igloo@earth.li>Allow splicing in concrete syntaxTemplate Haskell tends to lag behind GHC extensions, so it might be nice to allow concrete syntax to be returned, e.g. something like
```
f = $( return (RawE "5 + 6") )
```
There wouldn't be any need to restrict it to the top level, e....Template Haskell tends to lag behind GHC extensions, so it might be nice to allow concrete syntax to be returned, e.g. something like
```
f = $( return (RawE "5 + 6") )
```
There wouldn't be any need to restrict it to the top level, e.g. this would also be allowed:
```
f = $( return (InfixE (IntE 5) '(+) (RawE "6")) )
```
One possible disadvantage is that it might result in TH languishing even further behind, as there is less incentive to fill in the gaps.
Also, if a module splices in a raw expression from a TH library, what extensions should be enabled when parsing the string? Should we use the extensions enabled for the module, or should the `RawE` constructor specify the extensions to be used? We actually have this problem already, as (for example) when instances are spliced in we might need !OverlappingInstances enabled, so just using the extensions enabled for the module would be consistent.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 6.8.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | Unknown |
| Architecture | Unknown |
</details>
<!-- {"blocked_by":[],"summary":"Allow splicing in concrete syntax","status":"New","operating_system":"Unknown","component":"Template Haskell","related":[],"milestone":"6.10 branch","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.8.2","keywords":[],"differentials":[],"test_case":"","architecture":"Unknown","cc":[""],"type":"Bug","description":"\r\nTemplate Haskell tends to lag behind GHC extensions, so it might be nice to allow concrete syntax to be returned, e.g. something like\r\n{{{\r\nf = $( return (RawE \"5 + 6\") )\r\n}}}\r\nThere wouldn't be any need to restrict it to the top level, e.g. this would also be allowed:\r\n{{{\r\nf = $( return (InfixE (IntE 5) '(+) (RawE \"6\")) )\r\n}}}\r\n\r\nOne possible disadvantage is that it might result in TH languishing even further behind, as there is less incentive to fill in the gaps.\r\n\r\nAlso, if a module splices in a raw expression from a TH library, what extensions should be enabled when parsing the string? Should we use the extensions enabled for the module, or should the `RawE` constructor specify the extensions to be used? We actually have this problem already, as (for example) when instances are spliced in we might need !OverlappingInstances enabled, so just using the extensions enabled for the module would be consistent.\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/3355Refactor Template Haskell syntax conversions2019-07-07T19:04:16ZSimon MarlowRefactor Template Haskell syntax conversionsOn [TemplateHaskell/Conversions](template-haskell/conversions) there is a proposed refactoring of the Tempate Haskell-related syntax conversions. This task is to do that refactoring.
Edit: link.On [TemplateHaskell/Conversions](template-haskell/conversions) there is a proposed refactoring of the Tempate Haskell-related syntax conversions. This task is to do that refactoring.
Edit: link.8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/4372Accept expressions in left-hand side of quasiquotations2019-07-07T18:59:18ZSimon Peyton JonesAccept expressions in left-hand side of quasiquotationsGershom Bazerman (gershomb\@gmail.com) writes: Attached is an experimental patch (not read for prime-time) that extends quasiquotation syntax. At the moment, quasiquoters can only be single identifiers of type `QuasiQuoter` (and of cours...Gershom Bazerman (gershomb\@gmail.com) writes: Attached is an experimental patch (not read for prime-time) that extends quasiquotation syntax. At the moment, quasiquoters can only be single identifiers of type `QuasiQuoter` (and of course declared outside the current module). This patch allows an entire expression of type `QuasiQuoter` in the quoter position. The staging restriction is extended to all free variables in the quasiquoter expression.
So if `qq1 :: Int -> QuasiQuoter`, one can now write `[$qq1 12 | ... |]`
This syntax would be quite useful for my own project (jmacro), and from discussions at ICFP, to others who also are beginning to take serious advantage of quasiquotation.
Here's one use case. Suppose jmt is a `QuasiQuoter` which returns both a parsed Javascript expression and its "module signature" (or "typing environment" if you prefer). Then, one can pass that typing environment directly into another quasiquoter in a different module, so that further code can be typechecked at compile-time with functions defined in the first quasiquote available to the Javascript typechecker. This style of programming is currently possible, but it requires defining additional new modules which contain `QuasiQuoters` parameterized with each successive typing environment.
There are a number of tricky choices made in this patch, not all of which are perhaps correct.
First, currently, the quoter and quotation are lexed and parsed as a single token. To avoid reinvoking the lexer and/or parser, now '\[$' is lexed as one token, and a flag is set in the lexer state which lexes the `|...|]` (i.e. the quotation) as a single quotation on encountering the first vbar. This means that guards can't be used inside a quasiquoter expression -- i.e. `[$let x | True = 1 in qq1 x|..|]` would fail to parse. This also means that while now in ghc 7, one can write `[qq|..]`, to parse a full expression rather than identifier, we need the dollar sign as well.
The former problem (stealing guards within quasiquoter expressions) can be fixed by a syntax change which moves from a single vbar to a new symbol (perhaps `$|` or `||` ?) to signal the transition between the quoter expression and the quote itself. I tend to feel that the loss of guards within quasiquoter expressions is not too painful, however. Adding a new symbol between quoter and quotee also would simplify the necessary changes to the lexer, removing the need to set a special flag in the lexer state.
The second problem (need to reintroduce a dollar) is somewhat irritating, but not terribly so. One could either introduce the dollar in all cases, which allows simplifying the lexer and parser, or keep the dollarless syntax as well for single identifiers, which adds both complexity and duplicate syntax, but keeps the default case especially lightweight.
The patch as it stands introduces "extended quasiquotations" as an orthogonal change that doesn't affect the existing quasiquotation machinery, and, at the moment, only allows for quasiquotations of expressions (i.e., not patterns, etc.).
If there is sentiment that this is useful and could be accepted, modulo whatever requested tweaks, I'd be happy to do whatever work is necessary -- implementing changes, adding documentation, pushing the changes through to quasiquoters in other positions, etc.8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/4899Non-standard compile plus Template Haskell produces spurious "unknown symbol"...2019-07-07T18:58:00ZjepstNon-standard compile plus Template Haskell produces spurious "unknown symbol" linker errorPrograms that use Template Haskell fail to link when doing a "non-standard" compile. Specifically, compilations with -prof and -dynamic produce this bug, although other flags may as well; it seems that compilations that require the two-s...Programs that use Template Haskell fail to link when doing a "non-standard" compile. Specifically, compilations with -prof and -dynamic produce this bug, although other flags may as well; it seems that compilations that require the two-stage -osuf flag produce this bug. The error message is always "unknown symbol" but the specific symbol that is allegedly missing varies. Removing the TH block from the code makes the problem go away.
I've provided a minimal example of a program that can reproduce this bug, in the enclosed files Bug1.hs and Main.hs. A typescript demonstrating the error message is also included.
Tested on GHC 7.0.1 and 6.12.1, running under Ubuntu 10.04, both 64-bit and 32-bit. Also tested with 6.12.3 under 32-bit Windows 7.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.0.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":"Non-standard compile plus Template Haskell produces spurious \"unknown symbol\" linker error","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.0.1","keywords":["dynamic","link","prof","template"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Programs that use Template Haskell fail to link when doing a \"non-standard\" compile. Specifically, compilations with -prof and -dynamic produce this bug, although other flags may as well; it seems that compilations that require the two-stage -osuf flag produce this bug. The error message is always \"unknown symbol\" but the specific symbol that is allegedly missing varies. Removing the TH block from the code makes the problem go away.\r\n\r\nI've provided a minimal example of a program that can reproduce this bug, in the enclosed files Bug1.hs and Main.hs. A typescript demonstrating the error message is also included.\r\n\r\nTested on GHC 7.0.1 and 6.12.1, running under Ubuntu 10.04, both 64-bit and 32-bit. Also tested with 6.12.3 under 32-bit Windows 7.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Simon MarlowSimon Marlowhttps://gitlab.haskell.org/ghc/ghc/-/issues/5463SPECIALISE pragmas generated from Template Haskell are ignored2019-07-07T18:55:09ZGhost UserSPECIALISE pragmas generated from Template Haskell are ignoredHi,
I have the following program which contains a SPECIALISE pragma:
```
module Test(threeList) where
{-# NOINLINE three #-}
three :: Monad m => m Int
three = return 3
{-# SPECIALISE three :: [Int] #-}
threeList :: [Int]
threeList = ...Hi,
I have the following program which contains a SPECIALISE pragma:
```
module Test(threeList) where
{-# NOINLINE three #-}
three :: Monad m => m Int
three = return 3
{-# SPECIALISE three :: [Int] #-}
threeList :: [Int]
threeList = three
```
The specialisation works and -ddump-simpl gives me the following:
```
a :: Int
[GblId, Caf=NoCafRefs, Str=DmdType m]
a = I# 3
threeList [InlPrag=NOINLINE] :: [Int]
[GblId, Caf=NoCafRefs, Str=DmdType]
threeList = : @ Int a ([] @ Int)
```
Suppose now I alter my program so that it uses Template Haskell to generate the SPECIALISE pragma:
```
{-# LANGUAGE TemplateHaskell #-}
module TestTH(threeList) where
import TH
{-# NOINLINE three #-}
three :: Monad m => m Int
three = return 3
$(specialise 'three)
threeList :: [Int]
threeList = three
{-# LANGUAGE TemplateHaskell #-}
module TH where
import Language.Haskell.TH
specialise :: Name -> DecsQ
specialise x = do
listInt <- [t| [Int] |]
return [ PragmaD (SpecialiseP x listInt Nothing) ]
```
The specialisation should work just as before. However, if I compile with -ddump-splices -ddump-simpl, I see that the correct pragma was spliced in but no specialisation happened and GHC generated icky code:
```
TestTH.hs:1:1: Splicing declarations
specialise 'three
======>
TestTH.hs:9:3-19
{-# SPECIALIZE three :: [Int] #-}
==================== Tidy Core ====================
lvl :: Int
[GblId, Caf=NoCafRefs, Str=DmdType m]
lvl = I# 3
three [InlPrag=NOINLINE] :: forall (m :: * -> *). Monad m => m Int
[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType U(AASA)]
three =
\ (@ m::* -> *) ($dMonad :: Monad m) ->
return @ m $dMonad @ Int lvl
threeList :: [Int]
[GblId,
Str=DmdType,
Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=0, Value=False,
ConLike=False, Cheap=False, Expandable=True,
Guidance=IF_ARGS [] 2 0}]
threeList = three @ [] $fMonad[]
```
This happens on at least GHC 7.0.4 and 7.2.1.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 7.2.1 |
| 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":"SPECIALISE pragmas generated from Template Haskell are ignored","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Hi,\r\n\r\nI have the following program which contains a SPECIALISE pragma:\r\n{{{\r\nmodule Test(threeList) where\r\n\r\n{-# NOINLINE three #-}\r\nthree :: Monad m => m Int\r\nthree = return 3\r\n{-# SPECIALISE three :: [Int] #-}\r\n\r\nthreeList :: [Int]\r\nthreeList = three\r\n}}}\r\n\r\nThe specialisation works and -ddump-simpl gives me the following:\r\n{{{\r\na :: Int\r\n[GblId, Caf=NoCafRefs, Str=DmdType m]\r\na = I# 3\r\n\r\nthreeList [InlPrag=NOINLINE] :: [Int]\r\n[GblId, Caf=NoCafRefs, Str=DmdType]\r\nthreeList = : @ Int a ([] @ Int)\r\n}}}\r\n\r\nSuppose now I alter my program so that it uses Template Haskell to generate the SPECIALISE pragma:\r\n{{{\r\n{-# LANGUAGE TemplateHaskell #-}\r\nmodule TestTH(threeList) where\r\n\r\nimport TH\r\n\r\n{-# NOINLINE three #-}\r\nthree :: Monad m => m Int\r\nthree = return 3\r\n$(specialise 'three)\r\n\r\nthreeList :: [Int]\r\nthreeList = three\r\n\r\n{-# LANGUAGE TemplateHaskell #-}\r\nmodule TH where\r\n\r\nimport Language.Haskell.TH\r\n\r\nspecialise :: Name -> DecsQ\r\nspecialise x = do\r\n listInt <- [t| [Int] |]\r\n return [ PragmaD (SpecialiseP x listInt Nothing) ]\r\n}}}\r\n\r\nThe specialisation should work just as before. However, if I compile with -ddump-splices -ddump-simpl, I see that the correct pragma was spliced in but no specialisation happened and GHC generated icky code:\r\n{{{\r\nTestTH.hs:1:1: Splicing declarations\r\n specialise 'three\r\n ======>\r\n TestTH.hs:9:3-19\r\n {-# SPECIALIZE three :: [Int] #-}\r\n\r\n==================== Tidy Core ====================\r\nlvl :: Int\r\n[GblId, Caf=NoCafRefs, Str=DmdType m]\r\nlvl = I# 3\r\n\r\nthree [InlPrag=NOINLINE] :: forall (m :: * -> *). Monad m => m Int\r\n[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType U(AASA)]\r\nthree =\r\n \\ (@ m::* -> *) ($dMonad :: Monad m) ->\r\n return @ m $dMonad @ Int lvl\r\n\r\nthreeList :: [Int]\r\n[GblId,\r\n Str=DmdType,\r\n Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=0, Value=False,\r\n ConLike=False, Cheap=False, Expandable=True,\r\n Guidance=IF_ARGS [] 2 0}]\r\nthreeList = three @ [] $fMonad[]\r\n}}}\r\n\r\nThis happens on at least GHC 7.0.4 and 7.2.1.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/6089Allow declaration splices inside declaration brackets2019-07-07T18:52:15ZIan Lynagh <igloo@earth.li>Allow declaration splices inside declaration bracketsI would like to be able to write code like:
```
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
decs :: Q [Dec]
decs = [d| data MyType = MyCon | MyOtherCon
val1 :: MyType
val1 = MyCon
val...I would like to be able to write code like:
```
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
decs :: Q [Dec]
decs = [d| data MyType = MyCon | MyOtherCon
val1 :: MyType
val1 = MyCon
val2 :: MyType
val2 = MyOtherCon
$( do let mkFun v i = [| if $v == i then val1 else val2 |]
[d| fun3 x = $(mkFun [| x |] 3)
fun4 x = $(mkFun [| x |] 4) |] ) |]
```
but GHC says:
```
$ ghci decSplices.hs
GHCi, version 7.5.20120420: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main ( decSplices.hs, interpreted )
decSplices.hs:15:15:
Declaration splices are not permitted inside declaration brackets
Failed, modules loaded: none.
```
As far as I can see there is no technical reason why this couldn't work, with a splice within a declaration bracket splitting the declarations into 3. The declarations before the splice would be renamed, typechecked etc first, then those in the splice, and finally those after the splice.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 7.4.1 |
| 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":"Allow declaration splices inside declaration brackets","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"I would like to be able to write code like:\r\n{{{\r\n{-# LANGUAGE TemplateHaskell #-}\r\n\r\nimport Language.Haskell.TH\r\n\r\ndecs :: Q [Dec]\r\ndecs = [d| data MyType = MyCon | MyOtherCon\r\n\r\n val1 :: MyType\r\n val1 = MyCon\r\n\r\n val2 :: MyType\r\n val2 = MyOtherCon\r\n\r\n $( do let mkFun v i = [| if $v == i then val1 else val2 |]\r\n [d| fun3 x = $(mkFun [| x |] 3)\r\n fun4 x = $(mkFun [| x |] 4) |] ) |]\r\n}}}\r\nbut GHC says:\r\n{{{\r\n$ ghci decSplices.hs\r\nGHCi, version 7.5.20120420: http://www.haskell.org/ghc/ :? for help\r\nLoading package ghc-prim ... linking ... done.\r\nLoading package integer-gmp ... linking ... done.\r\nLoading package base ... linking ... done.\r\n[1 of 1] Compiling Main ( decSplices.hs, interpreted )\r\n\r\ndecSplices.hs:15:15:\r\n Declaration splices are not permitted inside declaration brackets\r\nFailed, modules loaded: none.\r\n}}}\r\n\r\nAs far as I can see there is no technical reason why this couldn't work, with a splice within a declaration bracket splitting the declarations into 3. The declarations before the splice would be renamed, typechecked etc first, then those in the splice, and finally those after the splice.\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Simon Peyton JonesSimon Peyton Jones