GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2019-07-07T18:49:46Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/7430GHC API reports CPP errors in confusing ways2019-07-07T18:49:46ZMikolaj KonarskiGHC API reports CPP errors in confusing waysWhen there is a CPP error, the GHC API provides a normal error message (such as in case of type errors), e.g.,
```
error: missing binary operator before token "("
```
but it does not say it's a CPP error. In addition (and unlike for ty...When there is a CPP error, the GHC API provides a normal error message (such as in case of type errors), e.g.,
```
error: missing binary operator before token "("
```
but it does not say it's a CPP error. In addition (and unlike for type errors), GHC API throws an exception, e.g.,
```
phase `C pre-processor' failed (exitcode = 1)
```
which states the error comes from CPP, but is otherwise uninformative and not tied in any way to the normal error message.
Ideally, all the information would be in the error message and the exception that disrupts the normal control flow would not be thrown.
Here's how to reproduce this: in the following repo (uh, just realised it's a rather large repo)
```
https://github.com/Mikolaj/ghc/tree/CPPrunGhc
```
run
```
ghc --make GhcRun.hs -package ghc-7.6.1
```
and then
```
./GhcRun
```
You should get
```
Normal error message:
Severity: SevError SrcSpan: RealSrcSpan (SrcSpanPoint {srcSpanFile = "Ticks.hs", srcSpanLine = 1, srcSpanCol = 0}) MsgDoc: error: missing binary operator before token "("
Exception:
GhcRun: phase `C pre-processor' failed (exitcode = 1)
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.6.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | GHC API |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"GHC API reports CPP errors in confusing ways","status":"New","operating_system":"","component":"GHC API","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"When there is a CPP error, the GHC API provides a normal error message (such as in case of type errors), e.g., \r\n{{{\r\nerror: missing binary operator before token \"(\"\r\n}}}\r\nbut it does not say it's a CPP error. In addition (and unlike for type errors), GHC API throws an exception, e.g., \r\n{{{\r\nphase `C pre-processor' failed (exitcode = 1)\r\n}}}\r\nwhich states the error comes from CPP, but is otherwise uninformative and not tied in any way to the normal error message. \r\n\r\nIdeally, all the information would be in the error message and the exception that disrupts the normal control flow would not be thrown.\r\n\r\nHere's how to reproduce this: in the following repo (uh, just realised it's a rather large repo)\r\n{{{\r\nhttps://github.com/Mikolaj/ghc/tree/CPPrunGhc\r\n}}}\r\nrun\r\n{{{\r\nghc --make GhcRun.hs -package ghc-7.6.1\r\n}}}\r\nand then\r\n{{{\r\n./GhcRun\r\n}}}\r\nYou should get\r\n{{{\r\nNormal error message:\r\nSeverity: SevError SrcSpan: RealSrcSpan (SrcSpanPoint {srcSpanFile = \"Ticks.hs\", srcSpanLine = 1, srcSpanCol = 0}) MsgDoc: error: missing binary operator before token \"(\"\r\n\r\nException:\r\nGhcRun: phase `C pre-processor' failed (exitcode = 1)\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7428GHC compile times are seriously non-linear in program size2021-11-12T09:11:46ZnuddedGHC compile times are seriously non-linear in program sizeWhen compiling the attached code with -O2 GHC runs out of memory. Experimenting with different monad stacks shows exponential memory usage.
<details><summary>Trac metadata</summary>
| Trac field | Value |
|...When compiling the attached code with -O2 GHC runs out of memory. Experimenting with different monad stacks shows exponential memory usage.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------------- |
| Version | 7.4.2 |
| Type | Bug |
| TypeOfFailure | CompileTimePerformance |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | MacOS X |
| Architecture | x86_64 (amd64) |
</details>
<!-- {"blocked_by":[],"summary":"Occurrence analyzer out of memory","status":"New","operating_system":"MacOS X","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.2","keywords":[],"differentials":[],"test_case":"","architecture":"x86_64 (amd64)","cc":[""],"type":"Bug","description":"When compiling the attached code with -O2 GHC runs out of memory. Experimenting with different monad stacks shows exponential memory usage.","type_of_failure":"CompileTimePerformance","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7413runghc (runhaskell) should be able to reload code on editing2019-10-07T08:04:51Zva1en0krunghc (runhaskell) should be able to reload code on editingHot code reloading on file edit is an incredibly useful feature for server development.
Right now several Haskell web frameworks are able to reload code on file edits, however there does not seem to be a simple way to use code reloader ...Hot code reloading on file edit is an incredibly useful feature for server development.
Right now several Haskell web frameworks are able to reload code on file edits, however there does not seem to be a simple way to use code reloader from one of them without finding yourself up to the neck in the framework.
It seems to me that the best thing what can be done is a flag to runghc / runhaskell:
```
runghc --reload MyServer.hs
```
It should watch for changes in the main file and all imported modules (or at least imported modules in the current folder).
A nice addition would be an ability to specify more files to watch
```
runghc --reload-watch *.some.weird.haskell.js --reload MyServer.hs
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.6.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"runghc (runhaskell) should be able to reload code on editing","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"Hot code reloading on file edit is an incredibly useful feature for server development.\r\n\r\nRight now several Haskell web frameworks are able to reload code on file edits, however there does not seem to be a simple way to use code reloader from one of them without finding yourself up to the neck in the framework.\r\n\r\nIt seems to me that the best thing what can be done is a flag to runghc / runhaskell:\r\n\r\n{{{\r\nrunghc --reload MyServer.hs\r\n}}}\r\n\r\nIt should watch for changes in the main file and all imported modules (or at least imported modules in the current folder).\r\n\r\nA nice addition would be an ability to specify more files to watch\r\n\r\n{{{\r\nrunghc --reload-watch *.some.weird.haskell.js --reload MyServer.hs \r\n}}}\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7395DefaultSignatures conflict with default implementations2019-07-12T12:56:54ZcgaebelDefaultSignatures conflict with default implementationsDefault signatures cannot be used with default implementations.
This is quite annoying for the hashable package, as we'd like to provide both options to the user.
See the attached test case.
<details><summary>Trac metadata</summary>
...Default signatures cannot be used with default implementations.
This is quite annoying for the hashable package, as we'd like to provide both options to the user.
See the attached test case.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 7.6.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | http://hpaste.org/77290 |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"DefaultSignatures conflict with default implementations","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":["DefaultSignatures"],"differentials":[],"test_case":"http://hpaste.org/77290","architecture":"","cc":[""],"type":"Bug","description":"Default signatures cannot be used with default implementations.\r\n\r\nThis is quite annoying for the hashable package, as we'd like to provide both options to the user.\r\n\r\nSee the attached test case.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7380Panic: mkNoTick: Breakpoint loading modules with -O2 via API2019-07-07T18:50:01ZJeanPhilippeMoresmauPanic: mkNoTick: Breakpoint loading modules with -O2 via APII load a trivial module via the API. I get a panic:
GHCBugs.exe: GHCBugs.exe: panic! (the 'impossible' happened)
> (GHC version 7.4.1 for i386-unknown-mingw32):
mkNoTick: Breakpoint
If I pass -O2 in the options. Without -O2 the modul...I load a trivial module via the API. I get a panic:
GHCBugs.exe: GHCBugs.exe: panic! (the 'impossible' happened)
> (GHC version 7.4.1 for i386-unknown-mingw32):
mkNoTick: Breakpoint
If I pass -O2 in the options. Without -O2 the module loads.
I attach the source code using the API to the ticket. The module I try to load just says:
module Main where
main::IO()
main = print "Hello Fay"
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.4.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | GHC API |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | Windows |
| Architecture | ia64 |
</details>
<!-- {"blocked_by":[],"summary":"Panic: mkNoTick: Breakpoint loading modules with -O2 via API","status":"New","operating_system":"Windows","component":"GHC API","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"ia64","cc":[""],"type":"Bug","description":"I load a trivial module via the API. I get a panic:\r\nGHCBugs.exe: GHCBugs.exe: panic! (the 'impossible' happened)\r\n (GHC version 7.4.1 for i386-unknown-mingw32):\r\n\tmkNoTick: Breakpoint\r\n\r\nIf I pass -O2 in the options. Without -O2 the module loads.\r\n\r\nI attach the source code using the API to the ticket. The module I try to load just says:\r\nmodule Main where\r\n\r\nmain::IO()\r\nmain = print \"Hello Fay\"","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7374rule not firing2019-07-07T18:50:02ZIan Lynagh <igloo@earth.li>rule not firingIn the code below, the rule appears not to fire.
Based on the bytestring rules, reported as broken here:
http://www.haskell.org/pipermail/glasgow-haskell-users/2012-August/022775.html
```
ghc -O --make h.hs -ddump-simpl -fforce-recomp ...In the code below, the rule appears not to fire.
Based on the bytestring rules, reported as broken here:
http://www.haskell.org/pipermail/glasgow-haskell-users/2012-August/022775.html
```
ghc -O --make h.hs -ddump-simpl -fforce-recomp -Wall
```
```
module Q (f) where
{-# NOINLINE f #-}
f :: Bool -> String
f c = g ((==) c)
{-# NOINLINE g #-}
g :: (Bool -> Bool) -> String
g _ = "g"
h :: Bool -> String
h _ = "h"
{-# RULES "MyRule" forall x . g ((==) x) = h x #-}
```
```
==================== Tidy Core ====================
Result size of Tidy Core = {terms: 25, types: 21, coercions: 0}
lvl_rkK :: GHC.Types.Char
[GblId, Caf=NoCafRefs, Str=DmdType m]
lvl_rkK = GHC.Types.C# 'h'
lvl1_rkL :: [GHC.Types.Char]
[GblId, Caf=NoCafRefs, Str=DmdType]
lvl1_rkL =
GHC.Types.:
@ GHC.Types.Char lvl_rkK (GHC.Types.[] @ GHC.Types.Char)
h_reA :: GHC.Types.Bool -> GHC.Base.String
[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType A]
h_reA = \ _ -> lvl1_rkL
lvl2_rkM :: GHC.Types.Char
[GblId, Caf=NoCafRefs, Str=DmdType m]
lvl2_rkM = GHC.Types.C# 'g'
lvl3_rkN :: [GHC.Types.Char]
[GblId, Caf=NoCafRefs, Str=DmdType]
lvl3_rkN =
GHC.Types.:
@ GHC.Types.Char lvl2_rkM (GHC.Types.[] @ GHC.Types.Char)
g_rez :: (GHC.Types.Bool -> GHC.Types.Bool) -> GHC.Base.String
[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType A]
g_rez = \ _ -> lvl3_rkN
Q.f [InlPrag=NOINLINE] :: GHC.Types.Bool -> GHC.Base.String
[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType A]
Q.f =
\ (c_aeC :: GHC.Types.Bool) ->
g_rez (GHC.Classes.$fEqBool_$c== c_aeC)
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.6.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"rule not firing","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"7.8.3","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"In the code below, the rule appears not to fire.\r\n\r\nBased on the bytestring rules, reported as broken here:\r\nhttp://www.haskell.org/pipermail/glasgow-haskell-users/2012-August/022775.html\r\n\r\n{{{\r\nghc -O --make h.hs -ddump-simpl -fforce-recomp -Wall\r\n}}}\r\n{{{\r\nmodule Q (f) where\r\n\r\n{-# NOINLINE f #-}\r\nf :: Bool -> String\r\nf c = g ((==) c)\r\n\r\n{-# NOINLINE g #-}\r\ng :: (Bool -> Bool) -> String\r\ng _ = \"g\"\r\n\r\nh :: Bool -> String\r\nh _ = \"h\"\r\n\r\n{-# RULES \"MyRule\" forall x . g ((==) x) = h x #-}\r\n}}}\r\n{{{\r\n==================== Tidy Core ====================\r\nResult size of Tidy Core = {terms: 25, types: 21, coercions: 0}\r\n\r\nlvl_rkK :: GHC.Types.Char\r\n[GblId, Caf=NoCafRefs, Str=DmdType m]\r\nlvl_rkK = GHC.Types.C# 'h'\r\n\r\nlvl1_rkL :: [GHC.Types.Char]\r\n[GblId, Caf=NoCafRefs, Str=DmdType]\r\nlvl1_rkL =\r\n GHC.Types.:\r\n @ GHC.Types.Char lvl_rkK (GHC.Types.[] @ GHC.Types.Char)\r\n\r\nh_reA :: GHC.Types.Bool -> GHC.Base.String\r\n[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType A]\r\nh_reA = \\ _ -> lvl1_rkL\r\n\r\nlvl2_rkM :: GHC.Types.Char\r\n[GblId, Caf=NoCafRefs, Str=DmdType m]\r\nlvl2_rkM = GHC.Types.C# 'g'\r\n\r\nlvl3_rkN :: [GHC.Types.Char]\r\n[GblId, Caf=NoCafRefs, Str=DmdType]\r\nlvl3_rkN =\r\n GHC.Types.:\r\n @ GHC.Types.Char lvl2_rkM (GHC.Types.[] @ GHC.Types.Char)\r\n\r\ng_rez :: (GHC.Types.Bool -> GHC.Types.Bool) -> GHC.Base.String\r\n[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType A]\r\ng_rez = \\ _ -> lvl3_rkN\r\n\r\nQ.f [InlPrag=NOINLINE] :: GHC.Types.Bool -> GHC.Base.String\r\n[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType A]\r\nQ.f =\r\n \\ (c_aeC :: GHC.Types.Bool) ->\r\n g_rez (GHC.Classes.$fEqBool_$c== c_aeC)\r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7337GHC does not generate great code for bit-level rotation2019-07-07T18:50:12ZbosGHC does not generate great code for bit-level rotationI'm working on some hashing functions at the moment, and I notice that GHC generates an `or` and a pair of shifts for a rotate. The LLVM back end is smart enough to recover the code's intent via strength reduction and emit a single `rot`...I'm working on some hashing functions at the moment, and I notice that GHC generates an `or` and a pair of shifts for a rotate. The LLVM back end is smart enough to recover the code's intent via strength reduction and emit a single `rot` instruction, but the regular code generator emits three instructions.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.6.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"GHC does not generate great code for bit-level rotation","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"I'm working on some hashing functions at the moment, and I notice that GHC generates an {{{or}}} and a pair of shifts for a rotate. The LLVM back end is smart enough to recover the code's intent via strength reduction and emit a single {{{rot}}} instruction, but the regular code generator emits three instructions.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7335Need for extra warning pragma for accidental pattern matching in do blocks2019-07-07T18:50:12ZduncanNeed for extra warning pragma for accidental pattern matching in do blocksThere are a few functions (actually monadic actions) where it's almost always an error to pattern match on the result, e.g.:
```
(x,y) <- rpar $ ... -- this is wrong!
(x,y) <- unsafeInterleaveIO $ ... -- this is also wrong!
```
...There are a few functions (actually monadic actions) where it's almost always an error to pattern match on the result, e.g.:
```
(x,y) <- rpar $ ... -- this is wrong!
(x,y) <- unsafeInterleaveIO $ ... -- this is also wrong!
```
We can help users by warning when they do this. To do this sensibly we would need a new warning pragma.
Here's a suggestion:
```
{-# WARN_DO_PATTERNMATCH unsafeInterleaveIO
"You don't want to use pattern matching directly on the
result of unsafeInterleaveIO because that will immediately
force the IO to be done, defeating the intention of lazily
deferring it." #-}
unsafeInterleaveIO :: IO a -> IO a
unsafeInterleaveIO = ...
{-# WARN_DO_PATTERNMATCH rpar "You don't want to use pattern
matching directly on the result of rpar because that will
immediately wait for the result to be evaluated, defeating
the intention of doing it in parallel." #-}
par :: Strategy a
par = ...
```
The warning message should probably suggest using a \~ lazy irrefutable match. Perhaps that bit of the message should be generated rather than taken from the string in the pragma, since it can provide the actual pattern the user used, with the extra \~.
As far as I can tell, this is only needed in a 'do' context, not a pure 'case' context.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.6.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Need for extra warning pragma for accidental pattern matching in do blocks","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"There are a few functions (actually monadic actions) where it's almost always an error to pattern match on the result, e.g.:\r\n{{{\r\n (x,y) <- rpar $ ... -- this is wrong!\r\n\r\n (x,y) <- unsafeInterleaveIO $ ... -- this is also wrong!\r\n}}}\r\nWe can help users by warning when they do this. To do this sensibly we would need a new warning pragma.\r\n\r\nHere's a suggestion:\r\n{{{\r\n {-# WARN_DO_PATTERNMATCH unsafeInterleaveIO\r\n \"You don't want to use pattern matching directly on the\r\n result of unsafeInterleaveIO because that will immediately\r\n force the IO to be done, defeating the intention of lazily\r\n deferring it.\" #-}\r\n unsafeInterleaveIO :: IO a -> IO a\r\n unsafeInterleaveIO = ...\r\n\r\n {-# WARN_DO_PATTERNMATCH rpar \"You don't want to use pattern\r\n matching directly on the result of rpar because that will\r\n immediately wait for the result to be evaluated, defeating\r\n the intention of doing it in parallel.\" #-}\r\n par :: Strategy a\r\n par = ...\r\n}}}\r\nThe warning message should probably suggest using a ~ lazy irrefutable match. Perhaps that bit of the message should be generated rather than taken from the string in the pragma, since it can provide the actual pattern the user used, with the extra ~.\r\n\r\nAs far as I can tell, this is only needed in a 'do' context, not a pure 'case' context.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7331Allow the evaluation of declaration splices in GHCi2019-07-07T18:50:13ZparcsAllow the evaluation of declaration splices in GHCiAs it stands GHCi cannot evaluate declaration splices because all splices are assumed to be expression splices:
```
> $( [d| a = True |] )
<interactive>:1:4:
Couldn't match expected type `Language.Haskell.TH.Syntax.Exp'
...As it stands GHCi cannot evaluate declaration splices because all splices are assumed to be expression splices:
```
> $( [d| a = True |] )
<interactive>:1:4:
Couldn't match expected type `Language.Haskell.TH.Syntax.Exp'
with actual type `[Language.Haskell.TH.Syntax.Dec]'
...
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.6.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | GHCi |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Allow the evaluation of declaration splices in GHCi","status":"New","operating_system":"","component":"GHCi","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"As it stands GHCi cannot evaluate declaration splices because all splices are assumed to be expression splices:\r\n\r\n{{{\r\n> $( [d| a = True |] )\r\n<interactive>:1:4:\r\n Couldn't match expected type `Language.Haskell.TH.Syntax.Exp'\r\n with actual type `[Language.Haskell.TH.Syntax.Dec]'\r\n...\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7307Share top-level code for strings2019-07-07T18:50:26ZSimon Peyton JonesShare top-level code for stringsA string constant in GHC turns into
```hs
foo :: String
foo = unpackCString# "the-string'
```
This is a top-level thunk, and it expands into rather a lot of code like this
```
.text
.align 4,0x90
.long 0
.long 22
.globl _Foo_zdfTyp...A string constant in GHC turns into
```hs
foo :: String
foo = unpackCString# "the-string'
```
This is a top-level thunk, and it expands into rather a lot of code like this
```
.text
.align 4,0x90
.long 0
.long 22
.globl _Foo_zdfTypeableTzuds1_info
_Foo_zdfTypeableTzuds1_info:
.LcvI:
movl %esi,%eax
leal -12(%ebp),%ecx
cmpl 84(%ebx),%ecx
jb .LcvQ
addl $8,%edi
cmpl 92(%ebx),%edi
ja .LcvS
movl $_stg_CAF_BLACKHOLE_info,-4(%edi)
movl 100(%ebx),%ecx
movl %ecx,0(%edi)
leal -4(%edi),%ecx
pushl %ecx
pushl %eax
pushl %ebx
movl %eax,76(%esp)
call _newCAF
addl $12,%esp
testl %eax,%eax
je .LcvL
movl $_stg_bh_upd_frame_info,-8(%ebp)
leal -4(%edi),%eax
movl %eax,-4(%ebp)
movl $_cvJ_str,-12(%ebp)
addl $-12,%ebp
jmp _ghczmprim_GHCziCString_unpackCStringzh_info
.LcvL:
movl 64(%esp),%eax
jmp *(%eax)
.LcvS:
movl $8,116(%ebx)
.LcvQ:
movl %eax,%esi
jmp *-12(%ebx)
```
That's rather a lot of goop for one thunk! Of course we can share this, by making a 2-word thunk like this:
```
------------------------------
| TopUnpack_info | -------|-----> "the-string"#
------------------------------
```
where `TopUnpack_info` is a shared RTS info-table and code that embodies the code fragment above.
This would save useless code bloat for every constant string. (This came up when looking at the code generated by `deriving(Typeable)`.)8.0.1parcsparcshttps://gitlab.haskell.org/ghc/ghc/-/issues/7300Allow CAFs kept reachable by FFI to be forcibly made unreachable for GC2019-07-07T18:50:28ZabsenceAllow CAFs kept reachable by FFI to be forcibly made unreachable for GCCAFs used by a foreign exported function are kept reachable the entire session because GHC can't know when the function will be called from C. If such a CAF is an evolving expression, like an FRP network, a space leak occurs because (I'm...CAFs used by a foreign exported function are kept reachable the entire session because GHC can't know when the function will be called from C. If such a CAF is an evolving expression, like an FRP network, a space leak occurs because (I'm guessing) the thunks that build up during iteration go all the way back to the initial CAF, and the GC can't start collecting because it considers the CAF reachable. According to JaffaCake on the \#haskell IRC channel, the runtime is capable of sovling this problem, it just needs a function that tells it to consider the specific CAF unreachable. It is then the responsibility of the user to not call the foreign exported function after the CAF is forced unreachable.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (FFI) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Allow CAFs kept reachable by FFI to be forcibly made unreachable for GC","status":"New","operating_system":"","component":"Compiler (FFI)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":["caf","gc","unsafe"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"CAFs used by a foreign exported function are kept reachable the entire session because GHC can't know when the function will be called from C. If such a CAF is an evolving expression, like an FRP network, a space leak occurs because (I'm guessing) the thunks that build up during iteration go all the way back to the initial CAF, and the GC can't start collecting because it considers the CAF reachable. According to JaffaCake on the #haskell IRC channel, the runtime is capable of sovling this problem, it just needs a function that tells it to consider the specific CAF unreachable. It is then the responsibility of the user to not call the foreign exported function after the CAF is forced unreachable.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7297LLVM incorrectly hoisting loads2019-07-07T18:50:28ZdtereiLLVM incorrectly hoisting loadstest 367_letnoescape fails under LLVM as a load of the !HpLim register is hoisted out of the loop. So yielding is never done.
What I am not sure about right now is the best way to fix. Loads in LLVM can be annotated in a few different w...test 367_letnoescape fails under LLVM as a load of the !HpLim register is hoisted out of the loop. So yielding is never done.
What I am not sure about right now is the best way to fix. Loads in LLVM can be annotated in a few different ways to fix this and not sure which one is the most 'correct'.
All the following work:
- mark the load as volatile. (seems to give nicest code as well)
- mark the load as atomic with either monotonic or seq_cst ordering.
- mark the load as both volatile and atomic.
This bug while only affecting a single test case seems very serious and potentially indicative of a large problem. How well are we communicating the load/store threaded semantics to LLVM?
And what semantics do we need to communicate? I think we are fine other than the STG registers...
So making a bug for now as I don't know yet the best way to proceed without dedicating some time to reading LLVM docs and probably talking to the LLVM devs as the docs on the memory model are fairly confusing.
e.g., Code in question:
Bad version (LBB0_1 loops forever as load hoisted out):
```
r1Uf_info: # @r1Uf_info
# BB#0: # %c1Vy
movq 144(%r13), %rax
decq %r14
.align 16, 0x90
.LBB0_1: # %tailrecurse
# =>This Inner Loop Header: Depth=1
incq %r14
testq %rax, %rax
jne .LBB0_1
# BB#2: # %c1VD
movq -8(%r13), %rax
movl $r1Uf_closure, %ebx
jmpq *%rax # TAILCALL
```
Code when marked with atomic (either monatonic or seq_cst) or both atomic and volatile:
```
r1Uf_info: # @r1Uf_info
# BB#0: # %c1Vy
decq %r14
.align 16, 0x90
.LBB0_1: # %tailrecurse
# =>This Inner Loop Header: Depth=1
incq %r14
movq 144(%r13), %rax
testq %rax, %rax
jne .LBB0_1
# BB#2: # %c1VD
movq -8(%r13), %rax
movl $r1Uf_closure, %ebx
jmpq *%rax # TAILCALL
```
Code when marked volatile:
```
r1Uf_info: # @r1Uf_info
# BB#0: # %c1Vy
decq %r14
.align 16, 0x90
.LBB0_1: # %tailrecurse
# =>This Inner Loop Header: Depth=1
incq %r14
cmpq $0, 144(%r13)
jne .LBB0_1
# BB#2: # %c1VD
movq -8(%r13), %rax
movl $r1Uf_closure, %ebx
jmpq *%rax # TAILCALL
```8.0.1dtereidtereihttps://gitlab.haskell.org/ghc/ghc/-/issues/7296ghc-7 assumes incoherent instances without requiring language `IncoherentInst...2023-02-03T20:59:39ZChristian Maederghc-7 assumes incoherent instances without requiring language `IncoherentInstances`the attached examples works with ghc-7 and returns
```
*Main> a
[Spec1 Spec2]
*Main> b
[]
```
(One may wish that b also returned \[Spec1 Spec2\])
ghc-6 complains with
```
Splittable.hs:16:36:
Overlapping instances...the attached examples works with ghc-7 and returns
```
*Main> a
[Spec1 Spec2]
*Main> b
[]
```
(One may wish that b also returned \[Spec1 Spec2\])
ghc-6 complains with
```
Splittable.hs:16:36:
Overlapping instances for Test a Spec2
arising from a use of `test' at Splittable.hs:16:36-43
Matching instances:
instance [overlap ok] Test a Spec2
-- Defined at Splittable.hs:20:13-24
instance [overlap ok] Test Bool Spec2
-- Defined at Splittable.hs:25:13-27
(The choice depends on the instantiation of `a'
To pick the first instance above, use -XIncoherentInstances
when compiling the other instance declarations)
In the second argument of `($)', namely `test a b'
In the expression: map Spec1 $ test a b
In the definition of `test':
test a (Spec1 b) = map Spec1 $ test a b
Failed, modules loaded: none.
```
After adding `IncoherentInstances` the file also goes through ghc-6 with the same results.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | --------------------- |
| Version | 7.6.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | sternkinder@gmail.com |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"ghc-7 assumes incoherent instances without requiring language `IncoherentInstances`","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["sternkinder@gmail.com"],"type":"Bug","description":"the attached examples works with ghc-7 and returns\r\n\r\n{{{\r\n *Main> a\r\n [Spec1 Spec2]\r\n *Main> b\r\n []\r\n}}}\r\n\r\n(One may wish that b also returned [Spec1 Spec2])\r\n\r\nghc-6 complains with\r\n\r\n{{{\r\nSplittable.hs:16:36:\r\n Overlapping instances for Test a Spec2\r\n arising from a use of `test' at Splittable.hs:16:36-43\r\n Matching instances:\r\n instance [overlap ok] Test a Spec2\r\n -- Defined at Splittable.hs:20:13-24\r\n instance [overlap ok] Test Bool Spec2\r\n -- Defined at Splittable.hs:25:13-27\r\n (The choice depends on the instantiation of `a'\r\n To pick the first instance above, use -XIncoherentInstances\r\n when compiling the other instance declarations)\r\n In the second argument of `($)', namely `test a b'\r\n In the expression: map Spec1 $ test a b\r\n In the definition of `test':\r\n test a (Spec1 b) = map Spec1 $ test a b\r\nFailed, modules loaded: none.\r\n}}}\r\n\r\nAfter adding `IncoherentInstances` the file also goes through ghc-6 with the same results.\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Simon Peyton JonesSimon Peyton Joneshttps://gitlab.haskell.org/ghc/ghc/-/issues/7285mkWeakMVar is non-compositional2019-07-07T18:50:31Zedsko@edsko.netmkWeakMVar is non-compositionalIn base 4.6 `addMVarFinalizer` is deprecated in favour of `mkWeakMVar` of type
```
mkWeakMVar :: MVar a -> IO () -> IO (Weak (MVar a))
```
This type makes it inherently non-compositional. For instance, if we have a larger datatype ...In base 4.6 `addMVarFinalizer` is deprecated in favour of `mkWeakMVar` of type
```
mkWeakMVar :: MVar a -> IO () -> IO (Weak (MVar a))
```
This type makes it inherently non-compositional. For instance, if we have a larger datatype T that contains an MVar somewhere inside then there in no way to define mkWeakT in terms of mkWeakMVar; instead, mkWeakT would have to be defined along the lines of
```
mkWeakT :: T a -> IO () -> IO (Weak (T a))
mkWeakT m@(MkT (MVar m#) _) f = IO $ \s ->
case mkWeak# m# m f s of (# s1, w #) -> (# s1, Weak w #)
```
It would be better if the type of mkWeakMVar would change to
```
mkWeakMVar :: MVar a -> v -> Maybe (IO ()) -> IO (Weak v)
```
(i.e., following `mkWeak` rather than `mkWeakPtr`).
(The same comment goes for related functions such as mkWeakIORef.)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.6.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"mkWeakMVar is non-compositional","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"In base 4.6 `addMVarFinalizer` is deprecated in favour of `mkWeakMVar` of type\r\n\r\n{{{\r\n mkWeakMVar :: MVar a -> IO () -> IO (Weak (MVar a))\r\n}}}\r\n\r\nThis type makes it inherently non-compositional. For instance, if we have a larger datatype T that contains an MVar somewhere inside then there in no way to define mkWeakT in terms of mkWeakMVar; instead, mkWeakT would have to be defined along the lines of\r\n\r\n{{{\r\n mkWeakT :: T a -> IO () -> IO (Weak (T a))\r\n mkWeakT m@(MkT (MVar m#) _) f = IO $ \\s ->\r\n case mkWeak# m# m f s of (# s1, w #) -> (# s1, Weak w #)\r\n}}}\r\n\r\nIt would be better if the type of mkWeakMVar would change to\r\n\r\n{{{\r\n mkWeakMVar :: MVar a -> v -> Maybe (IO ()) -> IO (Weak v)\r\n}}}\r\n\r\n(i.e., following `mkWeak` rather than `mkWeakPtr`). \r\n\r\n(The same comment goes for related functions such as mkWeakIORef.)","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Edward KmettEdward Kmetthttps://gitlab.haskell.org/ghc/ghc/-/issues/7283Specialise INLINE functions2019-07-07T18:50:32Zrl@cse.unsw.edu.auSpecialise INLINE functionsQuick summary: At the moment, INLINE means inline a function if it is fully applied and '''don't use its unfolding** otherwise. I think we might want to change this to INLINE a function if it is fully applied and **treat it as to INLINAB...Quick summary: At the moment, INLINE means inline a function if it is fully applied and '''don't use its unfolding** otherwise. I think we might want to change this to INLINE a function if it is fully applied and **treat it as to INLINABLE''' otherwise.
Here is a small example:
```
module T where
f :: Num a => a -> a
{-# INLINE [1] f #-}
f = \x -> x+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1
g :: Num a => a -> a
{-# INLINE [1] g #-}
g x = x+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2
h :: Num a => a -> a
{-# INLINABLE [1] h #-}
h x = x+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3
apply :: (a -> b) -> a -> b
{-# NOINLINE apply #-}
apply f x = f x
```
```
module U where
import T
ff :: Int -> Int -> Int
ff x y = apply f x + apply f y
gg :: Int -> Int -> Int
gg x y = apply g x + apply g y
hh :: Int -> Int -> Int
hh x y = apply h x + apply h y
```
With -O2 -fno-cse (CSE does optimise this example but doesn't solve the problem of intermediate code bloat), GHC produces the following:
- The RHS of `f` is duplicated since it is inlined twice - **bad**.
- `g` is neither inlined nor specialised since it isn't fully applied - **bad**.
- `h` is specialised but its RHS isn't duplicated - **good**.
But of course, `h` isn't guaranteed to be inlined even if it is fully applied which, in the real-world examples I have in mind, is **bad**.
I think `INLINE [n] f` should mean that:
1. `f` will always be inlined if it is fully applied,
1. `f` will be specialised when possible,
1. specialisations of `f` will also be `INLINE [n]`.
I don't think it's possible to achieve this effect at the moment. If we treated `INLINE [n]` as `INLINABLE [n]` until the function is fully applied, we would get exactly this, though, except for 3 which probably isn't too hard to implement.
Now, if I understand correctly, INLINABLE also means that GHC is free to inline the function if it wants but the function isn't treated as cheap. I think it would be fine if we did this for unsaturated `INLINE` functions rather than not inlining them under any circumstances. The original motivation for only inlining when fully applied was code bloat in DPH. But IIRC that only happened because INLINE functions were always cheap and so GHC was very keen to inline them even when they weren't saturated which wouldn't be the case with my proposal. We would have to check how this affects DPH and related libraries, though.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.7 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Specialise INLINE functions","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.7","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"Quick summary: At the moment, INLINE means inline a function if it is fully applied and '''don't use its unfolding''' otherwise. I think we might want to change this to INLINE a function if it is fully applied and '''treat it as to INLINABLE''' otherwise.\r\n\r\nHere is a small example:\r\n\r\n{{{\r\nmodule T where\r\n\r\nf :: Num a => a -> a\r\n{-# INLINE [1] f #-}\r\nf = \\x -> x+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1\r\n\r\ng :: Num a => a -> a\r\n{-# INLINE [1] g #-}\r\ng x = x+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2+2\r\n\r\nh :: Num a => a -> a\r\n{-# INLINABLE [1] h #-}\r\nh x = x+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3+3\r\n\r\napply :: (a -> b) -> a -> b\r\n{-# NOINLINE apply #-}\r\napply f x = f x\r\n}}}\r\n\r\n{{{\r\nmodule U where\r\n\r\nimport T\r\n\r\nff :: Int -> Int -> Int\r\nff x y = apply f x + apply f y\r\n\r\ngg :: Int -> Int -> Int\r\ngg x y = apply g x + apply g y\r\n\r\nhh :: Int -> Int -> Int\r\nhh x y = apply h x + apply h y\r\n}}}\r\n\r\nWith -O2 -fno-cse (CSE does optimise this example but doesn't solve the problem of intermediate code bloat), GHC produces the following:\r\n\r\n * The RHS of `f` is duplicated since it is inlined twice - '''bad'''.\r\n * `g` is neither inlined nor specialised since it isn't fully applied - '''bad'''.\r\n * `h` is specialised but its RHS isn't duplicated - '''good'''.\r\n\r\nBut of course, `h` isn't guaranteed to be inlined even if it is fully applied which, in the real-world examples I have in mind, is '''bad'''.\r\n\r\nI think `INLINE [n] f` should mean that:\r\n\r\n 1. `f` will always be inlined if it is fully applied,\r\n 2. `f` will be specialised when possible,\r\n 3. specialisations of `f` will also be `INLINE [n]`.\r\n\r\nI don't think it's possible to achieve this effect at the moment. If we treated `INLINE [n]` as `INLINABLE [n]` until the function is fully applied, we would get exactly this, though, except for 3 which probably isn't too hard to implement.\r\n\r\nNow, if I understand correctly, INLINABLE also means that GHC is free to inline the function if it wants but the function isn't treated as cheap. I think it would be fine if we did this for unsaturated `INLINE` functions rather than not inlining them under any circumstances. The original motivation for only inlining when fully applied was code bloat in DPH. But IIRC that only happened because INLINE functions were always cheap and so GHC was very keen to inline them even when they weren't saturated which wouldn't be the case with my proposal. We would have to check how this affects DPH and related libraries, though.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7258Compiling DynFlags is jolly slow2020-03-30T15:15:34ZSimon Peyton JonesCompiling DynFlags is jolly slowCompiling `DynFlags` really takes a long time these days.
Ian thinks that it's due to the `Read` and `Show` instances he has added (see attached `W2.hs`.
Simon M suggests: instead of using `Read/Show`, you could generate some code in `...Compiling `DynFlags` really takes a long time these days.
Ian thinks that it's due to the `Read` and `Show` instances he has added (see attached `W2.hs`.
Simon M suggests: instead of using `Read/Show`, you could generate some code in `mkDerivedConstants` to use `ReadP` and `Outputable`, which should be much smaller and faster.
This ticket is
- To see if we can speed up compilation of `DynFlags`
- To check WHY it is so slow. Are there any lessons we can learn or ways to make it compile faster? Is it tickling some asymptotically-bad corner of the compiler?
Simon
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.6.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Compiling DynFlags is jolly slow","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Compiling `DynFlags` really takes a long time these days. \r\n\r\nIan thinks that it's due to the `Read` and `Show` instances he has added (see attached `W2.hs`.\r\n\r\nSimon M suggests: instead of using `Read/Show`, you could generate some code in `mkDerivedConstants` to use `ReadP` and `Outputable`, which should be much smaller and faster.\r\n\r\nThis ticket is\r\n * To see if we can speed up compilation of `DynFlags` \r\n * To check WHY it is so slow. Are there any lessons we can learn or ways to make it compile faster? Is it tickling some asymptotically-bad corner of the compiler?\r\n\r\nSimon","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1Simon Peyton JonesSimon Peyton Joneshttps://gitlab.haskell.org/ghc/ghc/-/issues/7246Callstack depends on way (prof, profasm, profthreaded2019-07-07T18:50:42ZJoachim Breitnermail@joachim-breitner.deCallstack depends on way (prof, profasm, profthreadedConsider the attached test case. The expected output is the that of the ```prof``` way, while for ```profasm``` and ```profthreaded```, I get this result:
```
=====> callstack003(profthreaded) 19 of 21 [0, 1, 0]
cd . && '/home/jojo/doku...Consider the attached test case. The expected output is the that of the ```prof``` way, while for ```profasm``` and ```profthreaded```, I get this result:
```
=====> callstack003(profthreaded) 19 of 21 [0, 1, 0]
cd . && '/home/jojo/dokumente/Uni/info/ghc/inplace/bin/ghc-stage2' -fforce-recomp -dcore-lint -dcmm-lint -dno-debug-output -no-user-package-db -rtsopts -fno-ghci-history -o callstack003 callstack003.hs -O -prof -auto-all -threaded -fprof-auto-calls -fno-full-laziness -fno-state-hack >callstack003.comp.stderr 2>&1
cd . && ./callstack003 +RTS -p -RTS </dev/null >callstack003.run.stdout 2>callstack003.run.stderr
Actual stdout output differs from expected:
--- ./callstack003.stdout 2012-09-17 11:27:02.607458948 +0200
+++ ./callstack003.run.stdout 2012-09-17 12:20:33.988109494 +0200
@@ -1,8 +1,8 @@
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:15-17)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:22-24)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:15-17)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:22-24)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:15-17)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:22-24)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:15-17)","Main.f (callstack003.hs:7:11-36)"]
-["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.doTwice (callstack003.hs:10:22-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
+["Main.CAF (<entire-module>)","Main.main (callstack003.hs:9:8-21)","Main.doTwice (callstack003.hs:10:15-24)","Main.f (callstack003.hs:7:11-36)"]
*** unexpected failure for callstack003(profthreaded)
```
Not sure if this really hurts anyone, and the behavior of the call stack WRT recursive calls is anyways not quite perfect yet (see #7240), this makes adding good test cases a bit difficult.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.6.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Profiling |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Callstack depends on way (prof, profasm, profthreaded","status":"New","operating_system":"","component":"Profiling","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Consider the attached test case. The expected output is the that of the ```prof``` way, while for ```profasm``` and ```profthreaded```, I get this result:\r\n\r\n{{{\r\n=====> callstack003(profthreaded) 19 of 21 [0, 1, 0]\r\ncd . && '/home/jojo/dokumente/Uni/info/ghc/inplace/bin/ghc-stage2' -fforce-recomp -dcore-lint -dcmm-lint -dno-debug-output -no-user-package-db -rtsopts -fno-ghci-history -o callstack003 callstack003.hs -O -prof -auto-all -threaded -fprof-auto-calls -fno-full-laziness -fno-state-hack >callstack003.comp.stderr 2>&1\r\ncd . && ./callstack003 +RTS -p -RTS </dev/null >callstack003.run.stdout 2>callstack003.run.stderr\r\nActual stdout output differs from expected:\r\n--- ./callstack003.stdout\t2012-09-17 11:27:02.607458948 +0200\r\n+++ ./callstack003.run.stdout\t2012-09-17 12:20:33.988109494 +0200\r\n@@ -1,8 +1,8 @@\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:15-17)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:22-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:15-17)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:22-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:15-17)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:22-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:15-17)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n-[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.doTwice (callstack003.hs:10:22-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n+[\"Main.CAF (<entire-module>)\",\"Main.main (callstack003.hs:9:8-21)\",\"Main.doTwice (callstack003.hs:10:15-24)\",\"Main.f (callstack003.hs:7:11-36)\"]\r\n*** unexpected failure for callstack003(profthreaded)\r\n}}}\r\n\r\nNot sure if this really hurts anyone, and the behavior of the call stack WRT recursive calls is anyways not quite perfect yet (see #7240), this makes adding good test cases a bit difficult.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7245INLINEing top-level patterns causes ghc to emit 'arity missing' traces2022-11-20T00:52:38ZjwlatoINLINEing top-level patterns causes ghc to emit 'arity missing' tracesWhen an INLINE pragma is specified on a pattern, ghc-7.6.1 shows some internal trace messages.
```
module Foo where
{-# INLINE widths #-}
widths :: [Int]
widthMonth, widthYear :: Int
widths@[widthMonth, widthYear] = [1,2]
```
```
~/...When an INLINE pragma is specified on a pattern, ghc-7.6.1 shows some internal trace messages.
```
module Foo where
{-# INLINE widths #-}
widths :: [Int]
widthMonth, widthYear :: Int
widths@[widthMonth, widthYear] = [1,2]
```
```
~/Downloads$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.6.1
~/Downloads$ ghc Foo.hs -O
[1 of 1] Compiling Foo ( Foo.hs, Foo.o )
makeCorePair: arity missing widths{v aeJ} [lid]
```
I'm not certain that specifying an INLINE pragma in this context even makes sense, in which case perhaps a more useful warning could be produced.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 7.6.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | jwlato@gmail.com |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"INLINEing top-level patterns causes ghc to emit 'arity missing' traces","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.6.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["jwlato@gmail.com"],"type":"Bug","description":"When an INLINE pragma is specified on a pattern, ghc-7.6.1 shows some internal trace messages.\r\n\r\n{{{\r\nmodule Foo where\r\n\r\n{-# INLINE widths #-}\r\n\r\nwidths :: [Int]\r\nwidthMonth, widthYear :: Int\r\n\r\nwidths@[widthMonth, widthYear] = [1,2]\r\n}}}\r\n\r\n{{{\r\n~/Downloads$ ghc --version\r\nThe Glorious Glasgow Haskell Compilation System, version 7.6.1\r\n~/Downloads$ ghc Foo.hs -O\r\n[1 of 1] Compiling Foo ( Foo.hs, Foo.o )\r\nmakeCorePair: arity missing widths{v aeJ} [lid]\r\n}}}\r\n\r\nI'm not certain that specifying an INLINE pragma in this context even makes sense, in which case perhaps a more useful warning could be produced.","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7240Stack trace truncated too much with indirect recursion2019-07-07T18:50:44ZJoachim Breitnermail@joachim-breitner.deStack trace truncated too much with indirect recursionThis is to write down the improvements suggestions for the stack trace that I had after the HIW talk. Consider:
```
$ cat truncstack.hs
import System.Environment
import Debug.Trace
runThisTwice x y = x y >> x y
main = getArgs >>= runT...This is to write down the improvements suggestions for the stack trace that I had after the HIW talk. Consider:
```
$ cat truncstack.hs
import System.Environment
import Debug.Trace
runThisTwice x y = x y >> x y
main = getArgs >>= runThisTwice go1 . head
go1 l = runThisTwice go2 l
go2 l = runThisTwice go l
go x = traceStack x (error "done")
$ ghc --make -prof -fprof-auto truncstack.hs && ./truncstack x
[1 of 1] Compiling Main ( truncstack.hs, truncstack.o )
Linking truncstack ...
x
Stack trace:
Main.go (truncstack.hs:8:1-34)
Main.runThisTwice (truncstack.hs:4:1-29)
Main.main (truncstack.hs:5:1-42)
Main.CAF (<entire-module>)
truncstack: done
```
Clearly. the programer would want go1 and go2 to be mentioned as well.
I think it would not be too hard to keep the stacktrace more complete and only truncate “real” recursion (i.e. repeating sublists in the stack), or even annotate them with the number of loops. Simon Marlow told me that one need to ensure that a change in the stack does not have unwanted effects on the profiling attributions.
I plan to look into this issue (unless someone shouts “no no don’t do that”).
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.4.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Profiling |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Stack trace truncated too much with indirect recursion","status":"New","operating_system":"","component":"Profiling","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"nomeata"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"This is to write down the improvements suggestions for the stack trace that I had after the HIW talk. Consider:\r\n\r\n{{{\r\n$ cat truncstack.hs \r\nimport System.Environment\r\nimport Debug.Trace\r\n\r\nrunThisTwice x y = x y >> x y\r\nmain = getArgs >>= runThisTwice go1 . head\r\ngo1 l = runThisTwice go2 l\r\ngo2 l = runThisTwice go l\r\ngo x = traceStack x (error \"done\")\r\n$ ghc --make -prof -fprof-auto truncstack.hs && ./truncstack x\r\n[1 of 1] Compiling Main ( truncstack.hs, truncstack.o )\r\nLinking truncstack ...\r\nx\r\nStack trace:\r\n Main.go (truncstack.hs:8:1-34)\r\n Main.runThisTwice (truncstack.hs:4:1-29)\r\n Main.main (truncstack.hs:5:1-42)\r\n Main.CAF (<entire-module>)\r\ntruncstack: done\r\n}}}\r\n\r\nClearly. the programer would want go1 and go2 to be mentioned as well.\r\n\r\nI think it would not be too hard to keep the stacktrace more complete and only truncate “real” recursion (i.e. repeating sublists in the stack), or even annotate them with the number of loops. Simon Marlow told me that one need to ensure that a change in the stack does not have unwanted effects on the profiling attributions.\r\n\r\nI plan to look into this issue (unless someone shouts “no no don’t do that”).","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1https://gitlab.haskell.org/ghc/ghc/-/issues/7204Use a class to control FFI marshalling2019-07-07T18:50:52ZSimon Peyton JonesUse a class to control FFI marshallingThere has been a string of tickets concerning argument/result types for `foreign` declarations: #3008, #5529, #5610, #5664. This ticket suggest a new idea that Simon and I came up with this morning.
The current story is that a `newtype`...There has been a string of tickets concerning argument/result types for `foreign` declarations: #3008, #5529, #5610, #5664. This ticket suggest a new idea that Simon and I came up with this morning.
The current story is that a `newtype` can only be used in an FFI decl if the newtype's data constructor is in scope. This is enshrined in the FFI spec, but it's inconvenient and somewhat controversial. But suppose instead the ability to be passed to a `foreign` call was controlled by a class? Thus
```
class Marshal a where
type RepType a
marshal :: a -> RepType a
unMarshal :: RepType a -> a
instance Marshal Int where
type RepType Int = Int
marshal = id
unMarshal = id
newtype Age a = MkAge a
instance Marshal a => Marshal (Age a) where
type RepType (Age a) = RepType a
marshal (Age x) = marshal x
unMarshal x = Age x
```
An author can control whether a newtype is marshalable by making it an instance of `Marshal` (or not). Moreover `newtype deriving` will work just fine on class `Marshal` so you can write
```
newtype Age a = MkAge a deriving( Marshal )
```
The FFI stub generation machinery would do the following. Given a declaration
```
foreign import foo :: T -> IO S
```
it will generate a Haskell `foo` thus:
```
foo :: T -> S
foo t = case (marshal t) of
I# x# -> case "ccall foo x#" of
r# -> unMarshal (F# r#)
```
(I'm being a bit sloppy about the IO part, becuase it's not part of the main point here.)
In this example I've assumed that (after some type-level reductions)
```
RepType T = Int
RepType S = Float
```
but it should be OK provided the `RepType T` reduces to one of a fixed set of primitive types that GHC knows how to marshal.
So the rules become that an argument type `T` must satisfy two conditions:
- `T` must be an instance of `Marshal`
- `(RepType T)` must reduce to one of a fixed family of primitive types, `Int`, `Float` and so on.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 7.4.2 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Use a class to control FFI marshalling","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"There has been a string of tickets concerning argument/result types for `foreign` declarations: #3008, #5529, #5610, #5664. This ticket suggest a new idea that Simon and I came up with this morning.\r\n\r\nThe current story is that a `newtype` can only be used in an FFI decl if the newtype's data constructor is in scope. This is enshrined in the FFI spec, but it's inconvenient and somewhat controversial. But suppose instead the ability to be passed to a `foreign` call was controlled by a class? Thus\r\n{{{\r\nclass Marshal a where\r\n type RepType a\r\n marshal :: a -> RepType a\r\n unMarshal :: RepType a -> a\r\n\r\ninstance Marshal Int where\r\n type RepType Int = Int\r\n marshal = id\r\n unMarshal = id\r\n\r\nnewtype Age a = MkAge a\r\ninstance Marshal a => Marshal (Age a) where\r\n type RepType (Age a) = RepType a\r\n marshal (Age x) = marshal x\r\n unMarshal x = Age x\r\n}}}\r\nAn author can control whether a newtype is marshalable by making it an instance of `Marshal` (or not). Moreover `newtype deriving` will work just fine on class `Marshal` so you can write\r\n{{{\r\nnewtype Age a = MkAge a deriving( Marshal )\r\n}}}\r\n\r\nThe FFI stub generation machinery would do the following. Given a declaration\r\n{{{\r\nforeign import foo :: T -> IO S\r\n}}}\r\nit will generate a Haskell `foo` thus:\r\n{{{\r\nfoo :: T -> S\r\nfoo t = case (marshal t) of\r\n I# x# -> case \"ccall foo x#\" of\r\n r# -> unMarshal (F# r#)\r\n}}}\r\n(I'm being a bit sloppy about the IO part, becuase it's not part of the main point here.) \r\n\r\nIn this example I've assumed that (after some type-level reductions)\r\n{{{\r\n RepType T = Int\r\n RepType S = Float\r\n}}}\r\nbut it should be OK provided the `RepType T` reduces to one of a fixed set of primitive types that GHC knows how to marshal.\r\n\r\nSo the rules become that an argument type `T` must satisfy two conditions:\r\n * `T` must be an instance of `Marshal`\r\n * `(RepType T)` must reduce to one of a fixed family of primitive types, `Int`, `Float` and so on.\r\n\r\n\r\n ","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1