GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2022-02-24T10:30:12Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/15464Template Haskell creates System names when it shouldn't2022-02-24T10:30:12ZRichard Eisenbergrae@richarde.devTemplate Haskell creates System names when it shouldn'tIf we desugar
```
[d| foo :: a -> a
foo x = x
|]
```
we discover that `a` has a "system" name. This is explained in this Note (is DsMeta):
```
Note [Scoped type variables in bindings]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Con...If we desugar
```
[d| foo :: a -> a
foo x = x
|]
```
we discover that `a` has a "system" name. This is explained in this Note (is DsMeta):
```
Note [Scoped type variables in bindings]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
f :: forall a. a -> a
f x = x::a
Here the 'forall a' brings 'a' into scope over the binding group.
To achieve this we
a) Gensym a binding for 'a' at the same time as we do one for 'f'
collecting the relevant binders with hsSigTvBinders
b) When processing the 'forall', don't gensym
The relevant places are signposted with references to this Note
```
The problem is that the gensym approach creates system names, as explained further in `Note [Binders in Template Haskell]` in Convert. Essentially, it explains why to use system names as the result of `qNewName`, which !DsMeta uses for its gensyms.
There is a good logic to this approach, but system names are just wrong in the quote above. This can be user-visible when we print out the results, as we see in test case `th/T10267`, which includes silliness like `j :: forall a0. a0 -> a0`. (Recall that GHC appends a `0` to system names when printing.)
I worry that the answer here is a new `NameFlavour`, but perhaps cooler heads will prevail.
(This problem became user-visible with the fix to #15380, but I fault TH here, not #15380.)
<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 creates System names when it shouldn't","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 we desugar\r\n\r\n{{{\r\n[d| foo :: a -> a\r\n foo x = x\r\n |]\r\n}}}\r\n\r\nwe discover that `a` has a \"system\" name. This is explained in this Note (is DsMeta):\r\n\r\n{{{\r\nNote [Scoped type variables in bindings]\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\nConsider\r\n f :: forall a. a -> a\r\n f x = x::a\r\nHere the 'forall a' brings 'a' into scope over the binding group.\r\nTo achieve this we\r\n\r\n a) Gensym a binding for 'a' at the same time as we do one for 'f'\r\n collecting the relevant binders with hsSigTvBinders\r\n\r\n b) When processing the 'forall', don't gensym\r\n\r\nThe relevant places are signposted with references to this Note\r\n}}}\r\n\r\nThe problem is that the gensym approach creates system names, as explained further in `Note [Binders in Template Haskell]` in Convert. Essentially, it explains why to use system names as the result of `qNewName`, which !DsMeta uses for its gensyms.\r\n\r\nThere is a good logic to this approach, but system names are just wrong in the quote above. This can be user-visible when we print out the results, as we see in test case `th/T10267`, which includes silliness like `j :: forall a0. a0 -> a0`. (Recall that GHC appends a `0` to system names when printing.)\r\n\r\nI worry that the answer here is a new `NameFlavour`, but perhaps cooler heads will prevail.\r\n\r\n(This problem became user-visible with the fix to #15380, but I fault TH here, not #15380.)\r\n\r\n","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/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/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/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/14838missing "incomplete-patterns" warning for TH-generated functions2021-04-20T07:14:10Zgelisammissing "incomplete-patterns" warning for TH-generated functions"incomplete-patterns" warnings are generated for TH-generated case expressions, but not for TH-generated functions, so the behaviour is inconsistent.
For example:
```hs
{-# LANGUAGE TemplateHaskell #-}
module Lib where
import Language...."incomplete-patterns" warnings are generated for TH-generated case expressions, but not for TH-generated functions, so the behaviour is inconsistent.
For example:
```hs
{-# LANGUAGE TemplateHaskell #-}
module Lib where
import Language.Haskell.TH
qIncompleteCase :: Q [Dec]
qIncompleteCase = [d|
incompleteCase :: Bool -> ()
incompleteCase b = case b of
True -> () |]
qIncompleteFunction :: Q [Dec]
qIncompleteFunction =[d|
incompleteFunction :: Bool -> ()
incompleteFunction True = () |]
```
```hs
{-# LANGUAGE TemplateHaskell #-}
module Bug where
import Lib
$qIncompleteCase
$qIncompleteFunction
incompleteCase' :: Bool -> ()
incompleteCase' b = case b of
True -> ()
incompleteFunction' :: Bool -> ()
incompleteFunction' True = ()
```
When compiling the above two files with `-Wall`, GHC 8.2.2 produces an "incomplete-patterns" warning for `qIncompleteCase`, `incompleteCase'`, and `incompleteFunction'`, but not for `qIncompleteFunction`. I would prefer to get a warning for `qIncompleteFunction` as well.
My use case is the [surjective](https://hackage.haskell.org/package/surjective) package, in which I intentionally generate code which produces warnings in order to warn the user about corresponding issues in their code. I could generate [better error messages](https://github.com/gelisam/surjective/blob/master/src/Surjective.hs#L158-L162) if GHC generated warnings for TH-generated functions as well.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.2.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":"missing \"incomplete-patterns\" warning for TH-generated functions","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"\"incomplete-patterns\" warnings are generated for TH-generated case expressions, but not for TH-generated functions, so the behaviour is inconsistent.\r\n\r\nFor example:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\nmodule Lib where\r\nimport Language.Haskell.TH\r\n\r\nqIncompleteCase :: Q [Dec]\r\nqIncompleteCase = [d|\r\n incompleteCase :: Bool -> ()\r\n incompleteCase b = case b of\r\n True -> () |]\r\n\r\nqIncompleteFunction :: Q [Dec]\r\nqIncompleteFunction =[d|\r\n incompleteFunction :: Bool -> ()\r\n incompleteFunction True = () |]\r\n}}}\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\nmodule Bug where\r\nimport Lib\r\n\r\n$qIncompleteCase\r\n\r\n$qIncompleteFunction\r\n\r\nincompleteCase' :: Bool -> ()\r\nincompleteCase' b = case b of\r\n True -> ()\r\n\r\nincompleteFunction' :: Bool -> ()\r\nincompleteFunction' True = ()\r\n}}}\r\n\r\nWhen compiling the above two files with `-Wall`, GHC 8.2.2 produces an \"incomplete-patterns\" warning for `qIncompleteCase`, `incompleteCase'`, and `incompleteFunction'`, but not for `qIncompleteFunction`. I would prefer to get a warning for `qIncompleteFunction` as well.\r\n\r\nMy use case is the [https://hackage.haskell.org/package/surjective surjective] package, in which I intentionally generate code which produces warnings in order to warn the user about corresponding issues in their code. I could generate [https://github.com/gelisam/surjective/blob/master/src/Surjective.hs#L158-L162 better error messages] if GHC generated warnings for TH-generated functions as well.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14623Allow qAddDependentFile on directories2019-07-07T18:16:15ZryantrinkleAllow qAddDependentFile on directoriesCurrently, qAddDependentFile can only be applied to files; when applied to a directory, the following exception occurs:
```
*** Exception: path/to/dir: openBinaryFile: inappropriate type (is a directory)
```
However, it can be useful t...Currently, qAddDependentFile can only be applied to files; when applied to a directory, the following exception occurs:
```
*** Exception: path/to/dir: openBinaryFile: inappropriate type (is a directory)
```
However, it can be useful to walk directory trees at compile time with TemplateHaskell, and it would be nice to ensure that rebuilds reflect changes to directory structure, even when files are not changed.
<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":"Allow qAddDependentFile on directories","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"Currently, qAddDependentFile can only be applied to files; when applied to a directory, the following exception occurs:\r\n\r\n\r\n{{{\r\n*** Exception: path/to/dir: openBinaryFile: inappropriate type (is a directory)\r\n}}}\r\n\r\nHowever, it can be useful to walk directory trees at compile time with TemplateHaskell, and it would be nice to ensure that rebuilds reflect changes to directory structure, even when files are not changed.","type_of_failure":"OtherFailure","blocking":[]} -->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/14318TH shadowing bind statement triggers -Wunused-matches2019-07-07T18:17:29ZlyxiaTH shadowing bind statement triggers -Wunused-matches```
{-# LANGUAGE TemplateHaskell #-}
module Test where
import Language.Haskell.TH
m :: (a -> [b]) -> a -> [b]
m =
$(newName "x" >>= \x ->
newName "f" >>= \f ->
lamE [varP f, varP x]
(doE [ bindS (varP x) (listE [varE f ...```
{-# LANGUAGE TemplateHaskell #-}
module Test where
import Language.Haskell.TH
m :: (a -> [b]) -> a -> [b]
m =
$(newName "x" >>= \x ->
newName "f" >>= \f ->
lamE [varP f, varP x]
(doE [ bindS (varP x) (listE [varE f `appE` varE x])
, noBindS (varE x)])
)
```
The splice generates the following expression:
```
\f x -> do
x <- [f x]
x
```
and `-Wunused-matches` complains that `x` is not used, while both bound occurrences are in fact used (the two uses have different types so that's quite certain).Michael SloanMichael Sloanhttps://gitlab.haskell.org/ghc/ghc/-/issues/14212Give better error message with non-supported Backpack/TH use2022-02-23T14:30:13ZEdward Z. YangGive better error message with non-supported Backpack/TH useThis is something of a follow up to #13268.
Suppose you have an indefinite package. If you use TemplateHaskell with a splice that was defined in the indefinite package itself, there is no reasonable way to expect this to work, since in ...This is something of a follow up to #13268.
Suppose you have an indefinite package. If you use TemplateHaskell with a splice that was defined in the indefinite package itself, there is no reasonable way to expect this to work, since in general you can't have compiled the the imported module before you need to run the splice (and the splice needs to be run before you know how the holes are instantiated.)
But say you try and do it anyway. GHC will give an error like this:
```
ghc: ^^ Could not load 'qzm0zi1zminplacezmENEL5G3hx7IK2t0f6HloyH_A_f_closure', dependency unresolved. See top entry above.
ByteCodeLink.lookupCE
During interactive linking, GHCi couldn't find the following symbol:
qzm0zi1zminplacezmENEL5G3hx7IK2t0f6HloyH_A_f_closure
This may be due to you not asking GHCi to load extra object files,
archives or DLLs needed by your current session. Restart GHCi, specifying
the missing library using the -L/path/to/object/dir and -lmissinglibname
flags, or simply by naming the relevant files on the GHCi command line.
Alternatively, this link failure might indicate a bug in GHCi.
If you suspect the latter, please send a bug report to:
glasgow-haskell-bugs@haskell.org
```
This is not a good error message. A good error message would be to say that you can't use in a splice a function defined in an indefinite package (as per the current library.)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.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":"Give better error message with non-supported Backpack/TH use","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"This is something of a follow up to #13268.\r\n\r\nSuppose you have an indefinite package. If you use TemplateHaskell with a splice that was defined in the indefinite package itself, there is no reasonable way to expect this to work, since in general you can't have compiled the the imported module before you need to run the splice (and the splice needs to be run before you know how the holes are instantiated.)\r\n\r\nBut say you try and do it anyway. GHC will give an error like this:\r\n\r\n{{{\r\nghc: ^^ Could not load 'qzm0zi1zminplacezmENEL5G3hx7IK2t0f6HloyH_A_f_closure', dependency unresolved. See top entry above.\r\n\r\n\r\nByteCodeLink.lookupCE\r\nDuring interactive linking, GHCi couldn't find the following symbol:\r\n qzm0zi1zminplacezmENEL5G3hx7IK2t0f6HloyH_A_f_closure\r\nThis may be due to you not asking GHCi to load extra object files,\r\narchives or DLLs needed by your current session. Restart GHCi, specifying\r\nthe missing library using the -L/path/to/object/dir and -lmissinglibname\r\nflags, or simply by naming the relevant files on the GHCi command line.\r\nAlternatively, this link failure might indicate a bug in GHCi.\r\nIf you suspect the latter, please send a bug report to:\r\n glasgow-haskell-bugs@haskell.org\r\n}}}\r\n\r\nThis is not a good error message. A good error message would be to say that you can't use in a splice a function defined in an indefinite package (as per the current library.)","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14032Can't splice TH quote with infix declaration for name in two different namesp...2024-02-21T10:01:03ZRyan ScottCan't splice TH quote with infix declaration for name in two different namespacesSpun off from #13799 (and #13054\##14032). This code compiles:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
infix 5 :*:
data a :*: b = a :*: b
```
But this code does not:
```hs
{-# LANGUAGE TemplateHaskell #-...Spun off from #13799 (and #13054\##14032). This code compiles:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
infix 5 :*:
data a :*: b = a :*: b
```
But this code does not:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
$([d| infix 5 :*:
data a :*: b = a :*: b
|])
```
```
$ /opt/ghc/8.2.1/bin/ghc -ddump-splices Bug.hs
[1 of 1] Compiling Main ( Bug.hs, Bug.o )
Bug.hs:(4,3)-(6,6): Splicing declarations
[d| infix 5 :*:_anM, :*:_anL
data a_anN :*:_anL b_anO = a_anN :*:_anM b_anO |]
======>
infix 5 :*:_a3IL
infix 5 :*:_a3IK
data (:*:_a3IK) a_a3IM b_a3IN = a_a3IM :*:_a3IL b_a3IN
Bug.hs:4:3: error:
Multiple fixity declarations for ‘:*:_a3IL’
also at Bug.hs:(4,3)-(6,6)
|
4 | $([d| infix 5 :*:
| ^^^^^^^^^^^^^^^...
```
Inspecting the `-ddump-splices` output reveals why: when `infix 5 :*:` is renamed, because `:*:` refers to two different names in both the value and type namespaces, it actually gets renamed to `infix 5 :*:_anM, :*:_anL`, where `:*:_anM` and `:*:_anL` are the same name with different uniques.
Normally, this isn't a problem, since feeding `infix 5 :*:_anM, :*:_anL` to the typechecker works fine. However, when it's spliced in via Template Haskell, it gets fed back into the renamer, where it believes that `:*:_anM` and `:*:_anL` are duplicate names, causing the error.
Really, this is just a symptom of the fact that infix declarations are insufficiently powerful to encode information for identical names in different namespaces. But until GHC gains this ability, we need to find some workaround for this problem. My hunch is that we'll need to give GHC the power to recognize these sorts of duplicate fixity declarations in `Convert` and only emit one actual fixity declaration per set of duplicates. (Disclaimer: I haven't worked out all the fiddly details yet.)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.0.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":"Can't splice TH quote with infix declaration for name in two different namespaces","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Spun off from #13799 (and https://ghc.haskell.org/trac/ghc/ticket/13054#comment:2). This code compiles:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE TypeOperators #-}\r\n\r\ninfix 5 :*:\r\ndata a :*: b = a :*: b\r\n}}}\r\n\r\nBut this code does not:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE TypeOperators #-}\r\n\r\n$([d| infix 5 :*:\r\n data a :*: b = a :*: b\r\n |])\r\n}}}\r\n{{{\r\n$ /opt/ghc/8.2.1/bin/ghc -ddump-splices Bug.hs\r\n[1 of 1] Compiling Main ( Bug.hs, Bug.o )\r\nBug.hs:(4,3)-(6,6): Splicing declarations\r\n [d| infix 5 :*:_anM, :*:_anL\r\n \r\n data a_anN :*:_anL b_anO = a_anN :*:_anM b_anO |]\r\n ======>\r\n infix 5 :*:_a3IL\r\n infix 5 :*:_a3IK\r\n data (:*:_a3IK) a_a3IM b_a3IN = a_a3IM :*:_a3IL b_a3IN\r\n\r\nBug.hs:4:3: error:\r\n Multiple fixity declarations for ‘:*:_a3IL’\r\n also at Bug.hs:(4,3)-(6,6)\r\n |\r\n4 | $([d| infix 5 :*:\r\n | ^^^^^^^^^^^^^^^...\r\n}}}\r\n\r\nInspecting the `-ddump-splices` output reveals why: when `infix 5 :*:` is renamed, because `:*:` refers to two different names in both the value and type namespaces, it actually gets renamed to `infix 5 :*:_anM, :*:_anL`, where `:*:_anM` and `:*:_anL` are the same name with different uniques.\r\n\r\nNormally, this isn't a problem, since feeding `infix 5 :*:_anM, :*:_anL` to the typechecker works fine. However, when it's spliced in via Template Haskell, it gets fed back into the renamer, where it believes that `:*:_anM` and `:*:_anL` are duplicate names, causing the error.\r\n\r\nReally, this is just a symptom of the fact that infix declarations are insufficiently powerful to encode information for identical names in different namespaces. But until GHC gains this ability, we need to find some workaround for this problem. My hunch is that we'll need to give GHC the power to recognize these sorts of duplicate fixity declarations in `Convert` and only emit one actual fixity declaration per set of duplicates. (Disclaimer: I haven't worked out all the fiddly details yet.)","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14030Implement the "Derive Lift instances for data types in template-haskell" prop...2024-03-18T14:36:50ZRyan ScottImplement the "Derive Lift instances for data types in template-haskell" proposalBack in September 2015, I [proposed](https://mail.haskell.org/pipermail/libraries/2015-September/026117.html) using the `DeriveLift` extension to, well, derive `Lift` instance for data types in the `template-haskell` library. The proposa...Back in September 2015, I [proposed](https://mail.haskell.org/pipermail/libraries/2015-September/026117.html) using the `DeriveLift` extension to, well, derive `Lift` instance for data types in the `template-haskell` library. The proposal was well received, but I was unable to implement it at the time due to `DeriveLift`'s newness (having only been introduced in GHC 8.0). Now that GHC 8.0 is the oldest version of GHC that we support bootstrapping with, this is no longer an obstacle.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.3 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Implement the \"Derive Lift instances for data types in template-haskell\" proposal","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"8.4.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"Back in September 2015, I [https://mail.haskell.org/pipermail/libraries/2015-September/026117.html proposed] using the `DeriveLift` extension to, well, derive `Lift` instance for data types in the `template-haskell` library. The proposal was well received, but I was unable to implement it at the time due to `DeriveLift`'s newness (having only been introduced in GHC 8.0). Now that GHC 8.0 is the oldest version of GHC that we support bootstrapping with, this is no longer an obstacle.","type_of_failure":"OtherFailure","blocking":[]} -->https://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/13551Support DEPRECATED and WARNING pragmas on Template Haskell2019-07-07T18:21:22ZutdemirSupport DEPRECATED and WARNING pragmas on Template HaskellI'm writing TH function from some JSON spec to Haskell data structures. Some fields are marked as deprecated in the spec, therefore I want to mark the accessors to those fields with DEPRECATED pragma, but as far as I can see, TH does not...I'm writing TH function from some JSON spec to Haskell data structures. Some fields are marked as deprecated in the spec, therefore I want to mark the accessors to those fields with DEPRECATED pragma, but as far as I can see, TH does not support this.
I'm aware that module level DEPRECATED pragma is impossible in TH, but I still want to be able to tag top-level attributes as DEPRECATED.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.0.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | low |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Support DEPRECATED and WARNING pragmas on Template Haskell","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"I'm writing TH function from some JSON spec to Haskell data structures. Some fields are marked as deprecated in the spec, therefore I want to mark the accessors to those fields with DEPRECATED pragma, but as far as I can see, TH does not support this.\r\n\r\nI'm aware that module level DEPRECATED pragma is impossible in TH, but I still want to be able to tag top-level attributes as DEPRECATED.\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13269Changes in foreign code used in TH do not trigger recompilation2019-07-07T18:22:40ZFacundo DomínguezChanges in foreign code used in TH do not trigger recompilationFailing example:
```
// f.c
#include <stdio.h>
int f(int x) {
printf("calling f(%d)\n",x);
return x + 1;
}
```
```
-- A.hs
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE TemplateHaskell #-}
module A where
import Lan...Failing example:
```
// f.c
#include <stdio.h>
int f(int x) {
printf("calling f(%d)\n",x);
return x + 1;
}
```
```
-- A.hs
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE TemplateHaskell #-}
module A where
import Language.Haskell.TH.Syntax
foreign import ccall f :: Int -> IO Int
do addCStub "#include \"f.c\""
addDependentFile "f.c"
return []
```
```
-- B.hs
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE TemplateHaskell #-}
module Main where
import Language.Haskell.TH.Syntax
import A
do i <- runIO $ f 0
[d| fh = i |]
main :: IO ()
main = print fh
```
```
$ ghc --make B.hs
[1 of 2] Compiling A ( A.hs, A.o )
[2 of 2] Compiling Main ( B.hs, B.o )
calling f(0)
Linking B ...
$ ./B
1
```
Edit `f.c`:
```
// f.c
#include <stdio.h>
int f(int x) {
printf("calling f(%d)\n",x);
- return x + 1;
+ return x + 2;
}
```
Recompiling we can see that `B.hs` is not rebuilt and executing the program still shows the old result.
```
$ ghc --make B.hs
[1 of 2] Compiling A ( A.hs, A.o ) [f.c changed]
Linking B ...
$ ./B
1
```https://gitlab.haskell.org/ghc/ghc/-/issues/13054Generating unique names with template haskell2019-07-07T18:23:55Ztim-m89Generating unique names with template haskellI need to use template haskell to generate a few instances where those instances each use a foreign function obtained from a particular `FunPtr`.
As far as I'm aware, the only clean way to do this requires top level declarations of the ...I need to use template haskell to generate a few instances where those instances each use a foreign function obtained from a particular `FunPtr`.
As far as I'm aware, the only clean way to do this requires top level declarations of the form:
`foreign import ccall "dynamic" makeFun1 :: FunPtr Foo -> Foo`
If there was either:
- Another way to do this without requiring top level named declarations.
- The possibility to use these within a where clause (template haskell would suggest so given that it lets you use `Dec` within a `where`).
Then I'd be fine probably be fine without names.
I've tried using `newName` as it apparently generates fresh names but I cannot get it work for me.
I've put a copy of the test case [here](https://gitlab.com/tim-m89/hs-th-name-issue). I compile with `stack build --ghc-options="-ddump-splices -ddump-to-file"` and the error is:
```
th-name-issue/app/Main.hs:7:12: error:
Multiple declarations of ‘makeFun’
Declared at: app/Main.hs:7:12
app/Main.hs:7:12
```
Then I run `gvim .stack-work/dist/x86_64-linux/Cabal-1.24.0.0/build/th-name-issue-exe/th-name-issue-exe-tmp/app/Main.dump-splices`
And can see:
```
app/Main.hs:7:12-25: Splicing declarations
template-haskell-2.11.0.0:Language.Haskell.TH.Quote.quoteDec
importGen " stuff here "
======>
foreign import ccall safe "dynamic" makeFun_a3pc
:: GHC.Ptr.FunPtr (Foreign.C.String.CString -> IO ())
-> Foreign.C.String.CString -> IO ()
foreign import ccall safe "dynamic" makeFun_a3pd
:: GHC.Ptr.FunPtr (Foreign.C.String.CString -> IO ())
-> Foreign.C.String.CString -> IO ()
```
Which suggests that I did manage to get unique names after all, so I don't know why it didn't compile??
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.0.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":"Generating unique names with template haskell","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"I need to use template haskell to generate a few instances where those instances each use a foreign function obtained from a particular {{{FunPtr}}}.\r\n\r\nAs far as I'm aware, the only clean way to do this requires top level declarations of the form:\r\n{{{foreign import ccall \"dynamic\" makeFun1 :: FunPtr Foo -> Foo}}}\r\n\r\nIf there was either:\r\n\r\n* Another way to do this without requiring top level named declarations.\r\n* The possibility to use these within a where clause (template haskell would suggest so given that it lets you use {{{Dec}}} within a {{{where}}}).\r\n\r\nThen I'd be fine probably be fine without names.\r\n\r\nI've tried using {{{newName}}} as it apparently generates fresh names but I cannot get it work for me.\r\n\r\nI've put a copy of the test case [https://gitlab.com/tim-m89/hs-th-name-issue here]. I compile with {{{stack build --ghc-options=\"-ddump-splices -ddump-to-file\"}}} and the error is:\r\n\r\n{{{\r\nth-name-issue/app/Main.hs:7:12: error:\r\n Multiple declarations of ‘makeFun’\r\n Declared at: app/Main.hs:7:12\r\n app/Main.hs:7:12\r\n}}}\r\n\r\nThen I run {{{gvim .stack-work/dist/x86_64-linux/Cabal-1.24.0.0/build/th-name-issue-exe/th-name-issue-exe-tmp/app/Main.dump-splices}}}\r\n\r\nAnd can see:\r\n\r\n{{{\r\napp/Main.hs:7:12-25: Splicing declarations\r\n template-haskell-2.11.0.0:Language.Haskell.TH.Quote.quoteDec\r\n importGen \" stuff here \"\r\n ======>\r\n foreign import ccall safe \"dynamic\" makeFun_a3pc\r\n :: GHC.Ptr.FunPtr (Foreign.C.String.CString -> IO ())\r\n -> Foreign.C.String.CString -> IO ()\r\n foreign import ccall safe \"dynamic\" makeFun_a3pd\r\n :: GHC.Ptr.FunPtr (Foreign.C.String.CString -> IO ())\r\n -> Foreign.C.String.CString -> IO ()\r\n}}}\r\n\r\nWhich suggests that I did manage to get unique names after all, so I don't know why it didn't compile??","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/12818Allow reify to find top-level bindings in later declaration groups2019-07-07T18:25:01ZFacundo DomínguezAllow reify to find top-level bindings in later declaration groupsSome time ago, at Tweag we were considering inspecting the types of declarations added with `addTopDecls` like this:
```
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH.Syntax
main :: IO ()
main =
$(do
ds <- [d| f...Some time ago, at Tweag we were considering inspecting the types of declarations added with `addTopDecls` like this:
```
{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH.Syntax
main :: IO ()
main =
$(do
ds <- [d| f = True |]
addTopDecls ds
addModFinalizer $ do
VarI _ t _ <- reify (mkName "f")
runIO $ hPutStrLn stderr ("f :: " ++ show t)
[| return () |]
)
```
`f` is not in scope when the finalizer is added. But its type would be known when the finalizer runs.
This worked before the patch https://phabricator.haskell.org/D2286.
There is a patch that we submitted to address this https://phabricator.haskell.org/D2519, but it turned out later that we didn't need it and the patch was considered less than ideal.
We are opening this ticket to keep track of the nuance in case someone finds the patch useful later.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | mboes, simonpj |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Allow reify to find top-level bindings in later declaration groups","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["mboes","simonpj"],"type":"Bug","description":"Some time ago, at Tweag we were considering inspecting the types of declarations added with `addTopDecls` like this:\r\n\r\n{{{\r\n{-# LANGUAGE TemplateHaskell #-}\r\nimport Language.Haskell.TH.Syntax\r\n\r\nmain :: IO ()\r\nmain =\r\n $(do\r\n ds <- [d| f = True |]\r\n addTopDecls ds\r\n addModFinalizer $ do\r\n VarI _ t _ <- reify (mkName \"f\")\r\n runIO $ hPutStrLn stderr (\"f :: \" ++ show t)\r\n [| return () |]\r\n )\r\n}}}\r\n`f` is not in scope when the finalizer is added. But its type would be known when the finalizer runs.\r\n\r\nThis worked before the patch https://phabricator.haskell.org/D2286.\r\nThere is a patch that we submitted to address this https://phabricator.haskell.org/D2519, but it turned out later that we didn't need it and the patch was considered less than ideal.\r\n\r\nWe are opening this ticket to keep track of the nuance in case someone finds the patch useful later.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/12561Scope extrusion in Template Haskell2020-07-16T18:01:13ZSimon Peyton JonesScope extrusion in Template HaskellWith typed quotes `[|| e ||]` and splices `$$(e)`, Template Haskell is supposed guarantee to generate type-correct code. But a conversation with Oleg following my talk at the Cambridge Metaprogramming Summer School (Aug 16) made me reali...With typed quotes `[|| e ||]` and splices `$$(e)`, Template Haskell is supposed guarantee to generate type-correct code. But a conversation with Oleg following my talk at the Cambridge Metaprogramming Summer School (Aug 16) made me realise that it isn't.
The problem is that
```
[|| e ||] :: Q (TExp ty)
```
So a typed quote is still monadic. That is useful because it means that a function returning code can fail gracefully:
```
f :: Int -> Q (TExp Bool)
f n | n < 0 = fail "Argument less than zero"
| otherwise = ....
```
yielding a civilised error in the type checker's monad.
But giving ALL the power of Q is too much. Below is a program cooked up by Oleg that demonstrates the problem concretely.
```
{-# Language TemplateHaskell #-}
module T where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Ppr
import Data.IORef
show_code cde = (runQ . unTypeQ $ cde) >>= putStrLn . pprint
t1 = do
c1 <- [|| (1::Int) + 2 ||]
c2 <- [|| 3 + $$(return c1) ||]
return c2
t2 :: Q (TExp Int)
t2 = do
r <- runIO $ newIORef undefined
c1 <- [|| \x -> (1::Int) +
$$(do
xv <- [||x||]
runIO $ writeIORef r xv
return xv) ||]
runIO $ readIORef r
t1s = show_code t1
ts2 = show_code t2
```
-----------------------
Possible solutions.
- Give typed quotes access to only an emasculated Q monad, thus
```
[[| e ||] :: QQ (TExp ty)
```
> where `QQ` has more limited effects. This would work, and has the merit of simplicity. We can read stuff (reification), report errors, and even catch those exceptions -- provided that we don't include `TExp` values in exceptions (not sure how we prevent that!).
- Do what Meta OCaml does. Oleg writes "But you can go all the way and allow any effects. Q becomes no special (and possibly redundant). The stress is not on precluding scope extrusion statically but catch it immediately when it occurs (and report it with detailed error information: which variable has escaped, on which line of the source code was its intended binder, etc). This is what MetaOCaml does. I should stress it reports the scope extrusion even for open code, if one (of many) free variables in that code cannot eventually be bound. So the problem is not a scope extrusion per se: it is waiting until the whole code is generated to report it, at which time lots of information is already lost and it becomes very difficult to find the error. But reporting the error requires quite a bit of internal changes, to track free variables in any TH code fragment. Anyway, if you want to write the Wiki page, you can refer to my BER MetaOCaml paper, which describes the process."
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------------ |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | goldfire, oleg@okmij.org |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Scope extrusion in Template Haskell","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":["TemplateHaskell"],"differentials":[],"test_case":"","architecture":"","cc":["goldfire","oleg@okmij.org"],"type":"Bug","description":"With typed quotes `[|| e ||]` and splices `$$(e)`, Template Haskell is supposed guarantee to generate type-correct code. But a conversation with Oleg following my talk at the Cambridge Metaprogramming Summer School (Aug 16) made me realise that it isn't.\r\n\r\nThe problem is that\r\n{{{\r\n[|| e ||] :: Q (TExp ty)\r\n}}}\r\nSo a typed quote is still monadic. That is useful because it means that a function returning code can fail gracefully:\r\n{{{\r\nf :: Int -> Q (TExp Bool)\r\nf n | n < 0 = fail \"Argument less than zero\"\r\n | otherwise = ....\r\n}}}\r\nyielding a civilised error in the type checker's monad.\r\n\r\nBut giving ALL the power of Q is too much. Below is a program cooked up by Oleg that demonstrates the problem concretely.\r\n{{{\r\n{-# Language TemplateHaskell #-}\r\n\r\nmodule T where\r\n\r\nimport Language.Haskell.TH\r\nimport Language.Haskell.TH.Syntax\r\nimport Language.Haskell.TH.Ppr\r\n\r\nimport Data.IORef\r\n\r\nshow_code cde = (runQ . unTypeQ $ cde) >>= putStrLn . pprint\r\n\r\nt1 = do\r\n c1 <- [|| (1::Int) + 2 ||]\r\n c2 <- [|| 3 + $$(return c1) ||]\r\n return c2\r\n\r\nt2 :: Q (TExp Int)\r\nt2 = do\r\n r <- runIO $ newIORef undefined\r\n c1 <- [|| \\x -> (1::Int) +\r\n $$(do\r\n xv <- [||x||]\r\n runIO $ writeIORef r xv\r\n return xv) ||]\r\n runIO $ readIORef r\r\n\r\nt1s = show_code t1\r\n\r\nts2 = show_code t2\r\n}}}\r\n\r\n-----------------------\r\nPossible solutions.\r\n\r\n* Give typed quotes access to only an emasculated Q monad, thus\r\n{{{\r\n[[| e ||] :: QQ (TExp ty)\r\n}}}\r\n where `QQ` has more limited effects. This would work, and has the merit of simplicity. We can read stuff (reification), report errors, and even catch those exceptions -- provided that we don't include `TExp` values in exceptions (not sure how we prevent that!).\r\n\r\n* Do what Meta OCaml does. Oleg writes \"But you can go all the way and allow any effects. Q becomes no special (and possibly redundant). The stress is not on precluding scope extrusion statically but catch it immediately when it occurs (and report it with detailed error information: which variable has escaped, on which line of the source code was its intended binder, etc). This is what MetaOCaml does. I should stress it reports the scope extrusion even for open code, if one (of many) free variables in that code cannot eventually be bound. So the problem is not a scope extrusion per se: it is waiting until the whole code is generated to report it, at which time lots of information is already lost and it becomes very difficult to find the error. But reporting the error requires quite a bit of internal changes, to track free variables in any TH code fragment. Anyway, if you want to write the Wiki page, you can refer to my BER MetaOCaml paper, which describes the process.\"","type_of_failure":"OtherFailure","blocking":[]} -->Matthew PickeringMatthew Pickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/12452TemplateHaskell - variables in top level splices and loading modules.2019-07-07T18:26:34ZmkloczkoTemplateHaskell - variables in top level splices and loading modules.The following code fails when loading Main module:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ScopedTypeVariables #-}
module TH where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Data.Typeable
usingTy...The following code fails when loading Main module:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ScopedTypeVariables #-}
module TH where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Data.Typeable
usingType :: a -> Q [Dec]
usingType _ = do
let name = "The name!"
-- theF = "The name!"
return [FunD (mkName "theF") [Clause [] (NormalB $ LitE $ StringL name ) []]]
```
```hs
{-# LANGUAGE TemplateHaskell #-}
module Main where
import TH
data A = A Int
-- Runs with `usingType (undefined :: A)` instead
$(usingType (A 3) )
main = putStrLn $ theF
```
The error:
```
$ ghc --make Main.hs
[1 of 2] Compiling TH ( TH.hs, TH.o )
[2 of 2] Compiling Main ( Main.hs, Main.o )
attempting to use module ‘Main’ (Main.hs) which is not loaded
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.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":"TemplateHaskell - variables in top level splices and loading modules.","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":["TemplateHaskell"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The following code fails when loading Main module:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE ScopedTypeVariables #-}\r\n\r\nmodule TH where\r\n\r\nimport Language.Haskell.TH\r\nimport Language.Haskell.TH.Syntax\r\nimport Data.Typeable\r\n\r\n\r\nusingType :: a -> Q [Dec]\r\nusingType _ = do\r\n let name = \"The name!\"\r\n -- theF = \"The name!\"\r\n return [FunD (mkName \"theF\") [Clause [] (NormalB $ LitE $ StringL name ) []]]\r\n}}}\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n\r\nmodule Main where\r\nimport TH \r\n\r\ndata A = A Int\r\n\r\n-- Runs with `usingType (undefined :: A)` instead\r\n$(usingType (A 3) )\r\n\r\n\r\nmain = putStrLn $ theF\r\n}}}\r\n\r\nThe error:\r\n\r\n{{{\r\n$ ghc --make Main.hs\r\n[1 of 2] Compiling TH ( TH.hs, TH.o )\r\n[2 of 2] Compiling Main ( Main.hs, Main.o )\r\nattempting to use module ‘Main’ (Main.hs) which is not loaded\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/12451TemplateHaskell and Data.Typeable - tcIfaceGlobal (local): not found2019-07-07T18:26:34ZmkloczkoTemplateHaskell and Data.Typeable - tcIfaceGlobal (local): not foundThe following code produces an ghc panic error:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ScopedTypeVariables #-}
module TH where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Data.Typeable
usingType ...The following code produces an ghc panic error:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ScopedTypeVariables #-}
module TH where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
import Data.Typeable
usingType :: forall a. Typeable a => a -> Q [Dec]
usingType _ = do
-- Try to get anything using typeRep.
let name = (tyConName $ typeRepTyCon $ typeRep (Proxy :: Proxy a)) `seq` "The name!"
-- theF = "The name!"
return [FunD (mkName "theF") [Clause [] (NormalB $ LitE $ StringL name ) []]]
```
```hs
{-# LANGUAGE TemplateHaskell #-}
module Main where
import TH
data A = A Int
-- Changing the argument to (A 3) does not help.
$(usingType (undefined :: A))
main = putStrLn $ theF
```
The error:
```
ghc: panic! (the 'impossible' happened)
(GHC version 8.0.1 for x86_64-unknown-linux):
tcIfaceGlobal (local): not found:
$tcA
[r5m0 :-> Type constructor ‘A’, r5m3 :-> Data constructor ‘A’,
r5m9 :-> Identifier ‘A’]
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.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":"TemplateHaskell and Data.Typeable - tcIfaceGlobal (local): not found","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":["TemplateHaskell,","Typeable"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The following code produces an ghc panic error:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE ScopedTypeVariables #-}\r\n\r\nmodule TH where\r\n\r\nimport Language.Haskell.TH\r\nimport Language.Haskell.TH.Syntax\r\nimport Data.Typeable\r\n\r\n\r\nusingType :: forall a. Typeable a => a -> Q [Dec]\r\nusingType _ = do\r\n -- Try to get anything using typeRep.\r\n let name = (tyConName $ typeRepTyCon $ typeRep (Proxy :: Proxy a)) `seq` \"The name!\"\r\n -- theF = \"The name!\"\r\n return [FunD (mkName \"theF\") [Clause [] (NormalB $ LitE $ StringL name ) []]]\r\n}}}\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n\r\nmodule Main where\r\nimport TH \r\n\r\ndata A = A Int\r\n\r\n-- Changing the argument to (A 3) does not help.\r\n$(usingType (undefined :: A))\r\n\r\nmain = putStrLn $ theF\r\n}}}\r\n\r\nThe error:\r\n\r\n{{{\r\nghc: panic! (the 'impossible' happened)\r\n (GHC version 8.0.1 for x86_64-unknown-linux):\r\n\ttcIfaceGlobal (local): not found:\r\n $tcA\r\n [r5m0 :-> Type constructor ‘A’, r5m3 :-> Data constructor ‘A’,\r\n r5m9 :-> Identifier ‘A’]\r\n}}}\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->