GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2020-09-26T19:15:02Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/5165GHC doesn't optimize FP excess precision properly2020-09-26T19:15:02ZEdward Z. YangGHC doesn't optimize FP excess precision properlyjmcarthur helped in constructing the test case. Consider the following program:
```
module Main where
{-# NOINLINE x #-}
{-# NOINLINE y #-}
x, y :: Double
x = 3
y = 7
main = print $ x/y == (3/7 :: Double)
```
When run on 32-bit Linux...jmcarthur helped in constructing the test case. Consider the following program:
```
module Main where
{-# NOINLINE x #-}
{-# NOINLINE y #-}
x, y :: Double
x = 3
y = 7
main = print $ x/y == (3/7 :: Double)
```
When run on 32-bit Linux, we get the following results:
```
ezyang@javelin:~$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.0.3
ezyang@javelin:~$ ghc --make Bar.hs -o Bar -O0 -fforce-recomp && ./Bar
[1 of 1] Compiling Main ( Bar.hs, Bar.o )
Linking Bar ...
True
ezyang@javelin:~$ ghc --make Bar.hs -o Bar -O -fforce-recomp && ./Bar
[1 of 1] Compiling Main ( Bar.hs, Bar.o )
Linking Bar ...
False
```
The second result should be True (and only false if `-fexcess-precision` is specified). I also tested on a devel2 build of GHC HEAD and got similar results.
This appears to be a regression from 6.12.1:
```
ezyang@javelin:~$ /usr/bin/ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.12.1
ezyang@javelin:~$ /usr/bin/ghc --make Bar.hs -o Bar -O && ./Bar
True
```
I also kind of suspect `-fexcess-precision` doesn't do anything for the native codegen (based on source code surfing), but it's hard to tell with this current bug.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.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":"GHC doesn't optimize FP excess precision properly","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"jmcarthur helped in constructing the test case. Consider the following program:\r\n\r\n{{{\r\nmodule Main where\r\n\r\n{-# NOINLINE x #-}\r\n{-# NOINLINE y #-}\r\nx, y :: Double\r\nx = 3\r\ny = 7\r\n\r\nmain = print $ x/y == (3/7 :: Double)\r\n}}}\r\n\r\nWhen run on 32-bit Linux, we get the following results:\r\n\r\n{{{\r\nezyang@javelin:~$ ghc --version\r\nThe Glorious Glasgow Haskell Compilation System, version 7.0.3\r\nezyang@javelin:~$ ghc --make Bar.hs -o Bar -O0 -fforce-recomp && ./Bar\r\n[1 of 1] Compiling Main ( Bar.hs, Bar.o )\r\nLinking Bar ...\r\nTrue\r\nezyang@javelin:~$ ghc --make Bar.hs -o Bar -O -fforce-recomp && ./Bar\r\n[1 of 1] Compiling Main ( Bar.hs, Bar.o )\r\nLinking Bar ...\r\nFalse\r\n}}}\r\n\r\nThe second result should be True (and only false if `-fexcess-precision` is specified). I also tested on a devel2 build of GHC HEAD and got similar results.\r\n\r\nThis appears to be a regression from 6.12.1:\r\n\r\n{{{\r\nezyang@javelin:~$ /usr/bin/ghc --version\r\nThe Glorious Glasgow Haskell Compilation System, version 6.12.1\r\nezyang@javelin:~$ /usr/bin/ghc --make Bar.hs -o Bar -O && ./Bar\r\nTrue\r\n}}}\r\n\r\nI also kind of suspect `-fexcess-precision` doesn't do anything for the native codegen (based on source code surfing), but it's hard to tell with this current bug.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/2021let ghc find framework header files and link with frameworks located in $HOME...2019-07-07T19:10:34ZChristian Maederlet ghc find framework header files and link with frameworks located in $HOME/Library/FrameworksAs described in ticket #1395 I want ghc to be able to work with my local frameworks. Therefore I've extended the file `compiler/main/DriverPipeline.hs`.
In my latest (attached) version I've also removed a few duplications.
I've conside...As described in ticket #1395 I want ghc to be able to work with my local frameworks. Therefore I've extended the file `compiler/main/DriverPipeline.hs`.
In my latest (attached) version I've also removed a few duplications.
I've considered to check if the directory `$HOME/Library/Frameworks` exists using `doesDirectoryExist`, but that's done anyway by gcc and ld on mac. I've also considered to only pass
`"-F$HOME/Library/Frameworks"` if there are `-framework` flags on the command line at all, but this did not work for `HsReadline_cbits.c`:
```
../../compiler/stage1/ghc-inplace -Iinclude -package base-3.0.1.0 -package process-1.0.0.0 -optc-O2 -odir dist/build -c HsReadline_cbits.c -o dist/build/HsReadline_cbits.o
In file included from HsReadline_cbits.c:1:0:
include/HsReadline.h:7:43:
error: GNUreadline/readline/readline.h: No such file or directory
include/HsReadline.h:8:42:
error: GNUreadline/readline/history.h: No such file or directory
HsReadline_cbits.c: In function 'hs_rl_message':
HsReadline_cbits.c:5:0:
warning: implicit declaration of function 'rl_message'
make[2]: *** [dist/build/HsReadline_cbits.o] Error 1
make[1]: *** [make.library.readline] Error 2
make: *** [stage1] Error 2
```
This (single) case may be fixed by passing "`-F$HOME/Library/Frameworks`" manually, but what is the risk of passing "`-F$HOME/Library/Frameworks`" always? Well, someone may have spoiled frameworks there, but even that is no problem as long as they are not used, because dylibs are used instead. Of course other C-compilers may not like the -F flag (in fact that is a problem if ghc is used as C-compiler and was actually bad for hsc2hs #1395).
Maybe configure should check if gcc understands -F on macs? What do others think? Would you commit my `DriverPipeline.hs` changes?
A `"diff -u -w"` currently looks as follows:
```
+++ compiler/main/DriverPipeline.hs 2008-01-07 14:39:12.000000000 +0100
@@ -822,6 +822,9 @@
let include_paths = foldr (\ x xs -> "-I" : x : xs) []
(cmdline_include_paths ++ pkg_include_dirs)
+#ifdef darwin_TARGET_OS
+ framework_path_opts <- getFrameworkPathOpts dflags pkgs
+#endif
let (md_c_flags, md_regd_c_flags) = machdepCCOpts dflags
gcc_extra_viac_flags <- getExtraViaCOpts dflags
let pic_c_flags = picCCOpts dflags
@@ -905,6 +908,9 @@
++ cc_opts
++ split_opt
++ include_paths
+#ifdef darwin_TARGET_OS
+ ++ framework_path_opts
+#endif
++ pkg_extra_cc_opts
))
@@ -1199,17 +1205,10 @@
pkg_link_opts <- getPackageLinkOpts dflags dep_packages
#ifdef darwin_TARGET_OS
- pkg_framework_paths <- getPackageFrameworkPath dflags dep_packages
- let pkg_framework_path_opts = map ("-F"++) pkg_framework_paths
-
- let framework_paths = frameworkPaths dflags
- framework_path_opts = map ("-F"++) framework_paths
-
+ framework_path_opts <- getFrameworkPathOpts dflags dep_packages
pkg_frameworks <- getPackageFrameworks dflags dep_packages
- let pkg_framework_opts = concat [ ["-framework", fw] | fw <- pkg_frameworks ]
-
- let frameworks = cmdlineFrameworks dflags
- framework_opts = concat [ ["-framework", fw] | fw <- reverse frameworks ]
+ let framework_opts = concat [ ["-framework", fw]
+ | fw <- pkg_frameworks ++ reverse (cmdlineFrameworks dflags) ]
-- reverse because they're added in reverse order from the cmd line
#endif
@@ -1264,10 +1263,6 @@
#endif
++ pkg_lib_path_opts
++ pkg_link_opts
-#ifdef darwin_TARGET_OS
- ++ pkg_framework_path_opts
- ++ pkg_framework_opts
-#endif
++ debug_opts
++ thread_opts
))
@@ -1278,6 +1273,15 @@
if success then return ()
else throwDyn (InstallationError ("cannot move binary to PVM dir")))
+-- options to pass to gcc and ld on macs only
+getFrameworkPathOpts :: DynFlags -> [PackageId] -> IO [String]
+getFrameworkPathOpts dflags pkgs = do
+ ps <- getPackageFrameworkPath dflags pkgs
+ let fps = ps ++ frameworkPaths dflags
+ eitherDir <- IO.try getHomeDirectory
+ return $ map ("-F" ++) $ case eitherDir of
+ Left _ -> fps
+ Right hdir -> (hdir ++ "/Library/Frameworks") : fps
exeFileName :: DynFlags -> FilePath
exeFileName dflags
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 6.8.2 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | Multiple |
</details>
<!-- {"blocked_by":[],"summary":"let ghc find framework header files and link with frameworks located in $HOME/Library/Frameworks","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.8.2","keywords":[],"differentials":[],"test_case":"","architecture":"Multiple","cc":[""],"type":"FeatureRequest","description":"As described in ticket #1395 I want ghc to be able to work with my local frameworks. Therefore I've extended the file `compiler/main/DriverPipeline.hs`. \r\n\r\nIn my latest (attached) version I've also removed a few duplications.\r\n\r\nI've considered to check if the directory `$HOME/Library/Frameworks` exists using `doesDirectoryExist`, but that's done anyway by gcc and ld on mac. I've also considered to only pass \r\n`\"-F$HOME/Library/Frameworks\"` if there are `-framework` flags on the command line at all, but this did not work for `HsReadline_cbits.c`:\r\n\r\n{{{\r\n../../compiler/stage1/ghc-inplace -Iinclude -package base-3.0.1.0 -package process-1.0.0.0 -optc-O2 -odir dist/build -c HsReadline_cbits.c -o dist/build/HsReadline_cbits.o\r\n\r\nIn file included from HsReadline_cbits.c:1:0:\r\n\r\ninclude/HsReadline.h:7:43:\r\n error: GNUreadline/readline/readline.h: No such file or directory\r\n\r\ninclude/HsReadline.h:8:42:\r\n error: GNUreadline/readline/history.h: No such file or directory\r\nHsReadline_cbits.c: In function 'hs_rl_message':\r\n\r\nHsReadline_cbits.c:5:0:\r\n warning: implicit declaration of function 'rl_message'\r\nmake[2]: *** [dist/build/HsReadline_cbits.o] Error 1\r\nmake[1]: *** [make.library.readline] Error 2\r\nmake: *** [stage1] Error 2\r\n}}}\r\n\r\nThis (single) case may be fixed by passing \"`-F$HOME/Library/Frameworks`\" manually, but what is the risk of passing \"`-F$HOME/Library/Frameworks`\" always? Well, someone may have spoiled frameworks there, but even that is no problem as long as they are not used, because dylibs are used instead. Of course other C-compilers may not like the -F flag (in fact that is a problem if ghc is used as C-compiler and was actually bad for hsc2hs #1395). \r\n\r\nMaybe configure should check if gcc understands -F on macs? What do others think? Would you commit my `DriverPipeline.hs` changes?\r\n\r\nA `\"diff -u -w\"` currently looks as follows:\r\n{{{\r\n+++ compiler/main/DriverPipeline.hs 2008-01-07 14:39:12.000000000 +0100\r\n@@ -822,6 +822,9 @@\r\n let include_paths = foldr (\\ x xs -> \"-I\" : x : xs) []\r\n (cmdline_include_paths ++ pkg_include_dirs)\r\n\r\n+#ifdef darwin_TARGET_OS\r\n+ framework_path_opts <- getFrameworkPathOpts dflags pkgs\r\n+#endif\r\n let (md_c_flags, md_regd_c_flags) = machdepCCOpts dflags\r\n gcc_extra_viac_flags <- getExtraViaCOpts dflags\r\n let pic_c_flags = picCCOpts dflags\r\n@@ -905,6 +908,9 @@\r\n ++ cc_opts\r\n ++ split_opt\r\n ++ include_paths\r\n+#ifdef darwin_TARGET_OS\r\n+ ++ framework_path_opts\r\n+#endif\r\n ++ pkg_extra_cc_opts\r\n ))\r\n\r\n@@ -1199,17 +1205,10 @@\r\n pkg_link_opts <- getPackageLinkOpts dflags dep_packages\r\n\r\n #ifdef darwin_TARGET_OS\r\n- pkg_framework_paths <- getPackageFrameworkPath dflags dep_packages\r\n- let pkg_framework_path_opts = map (\"-F\"++) pkg_framework_paths\r\n-\r\n- let framework_paths = frameworkPaths dflags\r\n- framework_path_opts = map (\"-F\"++) framework_paths\r\n-\r\n+ framework_path_opts <- getFrameworkPathOpts dflags dep_packages\r\n pkg_frameworks <- getPackageFrameworks dflags dep_packages\r\n- let pkg_framework_opts = concat [ [\"-framework\", fw] | fw <- pkg_frameworks ]\r\n-\r\n- let frameworks = cmdlineFrameworks dflags\r\n- framework_opts = concat [ [\"-framework\", fw] | fw <- reverse frameworks ]\r\n+ let framework_opts = concat [ [\"-framework\", fw]\r\n+ | fw <- pkg_frameworks ++ reverse (cmdlineFrameworks dflags) ]\r\n -- reverse because they're added in reverse order from the cmd line\r\n #endif\r\n\r\n@@ -1264,10 +1263,6 @@\r\n #endif\r\n ++ pkg_lib_path_opts\r\n ++ pkg_link_opts\r\n-#ifdef darwin_TARGET_OS\r\n- ++ pkg_framework_path_opts\r\n- ++ pkg_framework_opts\r\n-#endif\r\n ++ debug_opts\r\n ++ thread_opts\r\n ))\r\n@@ -1278,6 +1273,15 @@\r\n if success then return ()\r\n else throwDyn (InstallationError (\"cannot move binary to PVM dir\")))\r\n\r\n+-- options to pass to gcc and ld on macs only\r\n+getFrameworkPathOpts :: DynFlags -> [PackageId] -> IO [String]\r\n+getFrameworkPathOpts dflags pkgs = do\r\n+ ps <- getPackageFrameworkPath dflags pkgs\r\n+ let fps = ps ++ frameworkPaths dflags\r\n+ eitherDir <- IO.try getHomeDirectory\r\n+ return $ map (\"-F\" ++) $ case eitherDir of\r\n+ Left _ -> fps\r\n+ Right hdir -> (hdir ++ \"/Library/Frameworks\") : fps\r\n\r\n exeFileName :: DynFlags -> FilePath\r\n exeFileName dflags\r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/2078INLINE and strictness2019-07-07T19:10:18ZSimon Peyton JonesINLINE and strictnessConsider this code
```
module A where
{-# INLINE [0] foo #-}
{#- RULE foo (reverse xs) = xs #-}
foo xs = reverse $ xs
module B where
import A( foo )
g b ys = foo (case b of
True -> reverse ys
...Consider this code
```
module A where
{-# INLINE [0] foo #-}
{#- RULE foo (reverse xs) = xs #-}
foo xs = reverse $ xs
module B where
import A( foo )
g b ys = foo (case b of
True -> reverse ys
False -> ys)
h xs = map foo xs
```
At the moment the body of `foo` is not optimised at all, because it's going to be inlined. But that means that
- The `foo` executed by the `map` in `h` is very inefficient, because it actually calls `$` etc.
- The strictness analyser doesn't see that `foo` is strict, because again the `$` gets in the way. So the rule for `foo` does not match in the RHS of `g`. (If `foo` were strict, we'd push the call to `foo` inside the case branches.)
For both reasons it'd be better to
- Retain the original RHS of `foo` for inlining purposes
- But otherwise optimise `foo` normally, so that if it is not inlined, we get the efficient version, and so that strictness analysis does the right thing.
Hmm. Maybe INLINE should turn into a RULE, rather than (as now) a `Note` in Core?
Anyway, this ticket is to make sure I don't forget this point.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------- |
| Version | 6.8.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | ndp@cse.unsw.edu.au |
| Operating system | Unknown |
| Architecture | Unknown |
</details>
<!-- {"blocked_by":[],"summary":"INLINE and strictness","status":"New","operating_system":"Unknown","component":"Compiler","related":[],"milestone":"6.10 branch","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"simonpj"},"version":"6.8.2","keywords":[],"differentials":[],"test_case":"","architecture":"Unknown","cc":["ndp@cse.unsw.edu.au"],"type":"Bug","description":"Consider this code \r\n{{{\r\nmodule A where\r\n {-# INLINE [0] foo #-}\r\n {#- RULE foo (reverse xs) = xs #-}\r\n foo xs = reverse $ xs\r\n\r\nmodule B where\r\n import A( foo )\r\n g b ys = foo (case b of \r\n True -> reverse ys\r\n False -> ys)\r\n\r\n h xs = map foo xs\r\n}}}\r\nAt the moment the body of `foo` is not optimised at all, because it's going to be inlined. But that means that\r\n\r\n * The `foo` executed by the `map` in `h` is very inefficient, because it actually calls `$` etc.\r\n\r\n * The strictness analyser doesn't see that `foo` is strict, because again the `$` gets in the way. So the rule for `foo` does not match in the RHS of `g`. (If `foo` were strict, we'd push the call to `foo` inside the case branches.)\r\n\r\nFor both reasons it'd be better to \r\n * Retain the original RHS of `foo` for inlining purposes\r\n * But otherwise optimise `foo` normally, so that if it is not inlined, we get the efficient version, and so that strictness analysis does the right thing.\r\n\r\nHmm. Maybe INLINE should turn into a RULE, rather than (as now) a `Note` in Core?\r\n\r\nAnyway, this ticket is to make sure I don't forget this point.\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1Simon Peyton JonesSimon Peyton Joneshttps://gitlab.haskell.org/ghc/ghc/-/issues/2534Odd probable cause given by type checker2019-07-07T19:08:10Zred5_2@hotmail.comOdd probable cause given by type checkerIn the following code, a function has been applied to zero arguments, which the type checker suggests is too many.
```
Prelude> foldr (>>=) [] []
<interactive>:1:6:
Occurs check: cannot construct the infinite type: b = a -> b
P...In the following code, a function has been applied to zero arguments, which the type checker suggests is too many.
```
Prelude> foldr (>>=) [] []
<interactive>:1:6:
Occurs check: cannot construct the infinite type: b = a -> b
Probable cause: `>>=' is applied to too many arguments
In the first argument of `foldr', namely `(>>=)'
In the expression: foldr (>>=) [] []
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 6.8.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | Unknown |
| Architecture | Unknown |
</details>
<!-- {"blocked_by":[],"summary":"Odd probable cause given by type checker","status":"New","operating_system":"Unknown","component":"Compiler (Type checker)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.8.2","keywords":[],"differentials":[],"test_case":"","architecture":"Unknown","cc":[""],"type":"Bug","description":"In the following code, a function has been applied to zero arguments, which the type checker suggests is too many.\r\n\r\n{{{\r\nPrelude> foldr (>>=) [] []\r\n\r\n<interactive>:1:6:\r\n Occurs check: cannot construct the infinite type: b = a -> b\r\n Probable cause: `>>=' is applied to too many arguments\r\n In the first argument of `foldr', namely `(>>=)'\r\n In the expression: foldr (>>=) [] []\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1Simon Peyton JonesSimon Peyton Joneshttps://gitlab.haskell.org/ghc/ghc/-/issues/2892(threadDelay (-1)) hangs2019-07-07T19:06:23Zdancor(threadDelay (-1)) hangsthreadDelay silently hangs forever given a negative delay interval. It seems like this should at least be documented, but further is probably suboptimal magical behavior that leads to harder-to-find bugs; instead this should be an error....threadDelay silently hangs forever given a negative delay interval. It seems like this should at least be documented, but further is probably suboptimal magical behavior that leads to harder-to-find bugs; instead this should be an error. Conceivably threadDelay could take Maybe Int but that seems kind of out there.
Here is some discussion from \#haskell:
```
06:39 < dancor> do other ppl agree that (threadDelay (-1)) hanging silently is
bug?
06:39 < dancor> i guess you might want infinite hang, hm
06:39 < Cale> dancor: I think I might agree with that, though now that you
mention it, it's very handy.
06:39 < Cale> dancor: A lot of things which would cause a thread to block
forever will throw an exception and kill the thread.
06:40 < Cale> (an exception which you'd often wish were silent)
06:40 < Cale> But threadDelay is the wrong place for that
06:40 < b_jonas> dancor: yeah, the thread should just be garbage-collected
06:42 * quicksilver uses "forever (threadDelay maxBound)"
```
I'm on Debian lenny:
```
~ uname -a
Linux pima 2.6.26-1-686-bigmem #1 SMP Sat Nov 8 19:46:36 UTC 2008 i686 GNU/Linux
~ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.10.1
~ cat threadHang.hs
import Control.Concurrent
main = threadDelay (-1)
```7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/2947infix precedence of backtick functions defined in ghci is not reported by :info2019-07-07T19:06:11ZEyalLoteminfix precedence of backtick functions defined in ghci is not reported by :infoexcerpt from ghci:
```
Prelude> let infixr 9 `f` ; f = (+)
let infixr 9 `f` ; f = (+)
Prelude> 5 * 3 `f` 4
35
Prelude> :info f
f :: Integer -> Integer -> Integer
-- Defined at <interactive>:1:19
Prelude> :info `f`
f :: Integer -> Int...excerpt from ghci:
```
Prelude> let infixr 9 `f` ; f = (+)
let infixr 9 `f` ; f = (+)
Prelude> 5 * 3 `f` 4
35
Prelude> :info f
f :: Integer -> Integer -> Integer
-- Defined at <interactive>:1:19
Prelude> :info `f`
f :: Integer -> Integer -> Integer
-- Defined at <interactive>:1:19
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 6.10.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | GHCi |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"infix precedence of backtick functions defined in ghci is not reported by :info","status":"New","operating_system":"","component":"GHCi","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.10.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"excerpt from ghci:\r\n{{{\r\nPrelude> let infixr 9 `f` ; f = (+)\r\nlet infixr 9 `f` ; f = (+)\r\nPrelude> 5 * 3 `f` 4\r\n35\r\nPrelude> :info f\r\nf :: Integer -> Integer -> Integer\r\n \t-- Defined at <interactive>:1:19\r\nPrelude> :info `f`\r\nf :: Integer -> Integer -> Integer\r\n \t-- Defined at <interactive>:1:19\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1pcapriottipcapriottihttps://gitlab.haskell.org/ghc/ghc/-/issues/3222GLFW 0.3 build fails w/ SSE error in 6.10.3, works in 6.10.12019-07-07T19:04:50ZGregFrascadoreGLFW 0.3 build fails w/ SSE error in 6.10.3, works in 6.10.1Using GHC 6.10.3 to build GLFW 0.3 dies with:
```
/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/xmmintrin.h:35:3:
error: #error "SSE instruction set not enabled"
```
on Mac OSX 10.5.6 (intel)
By downgrading to 6.10.1 the build wor...Using GHC 6.10.3 to build GLFW 0.3 dies with:
```
/usr/lib/gcc/i686-apple-darwin9/4.0.1/include/xmmintrin.h:35:3:
error: #error "SSE instruction set not enabled"
```
on Mac OSX 10.5.6 (intel)
By downgrading to 6.10.1 the build works.
I saw some IRC chat logs where others had this problem with 6.10.2.7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/3871Missing reference in manpage2019-07-07T19:01:45ZmarcotmarcotMissing reference in manpagefrom ghc(1):
```
-e expr
Evaluate expr; see for details.
```
I think there's a word missing after see.
Greetings.from ghc(1):
```
-e expr
Evaluate expr; see for details.
```
I think there's a word missing after see.
Greetings.7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/3940Propagate bug fix into new code generator2019-07-07T19:01:25ZSimon Peyton JonesPropagate bug fix into new code generatorWe must not forget to propagate this fix into the new code generator pipeline:
```
Thu Mar 25 04:03:28 PDT 2010 Simon Marlow <marlowsd@gmail.com>
* do_checks: do not set HpAlloc if the stack check fails
This fixes a very rare he...We must not forget to propagate this fix into the new code generator pipeline:
```
Thu Mar 25 04:03:28 PDT 2010 Simon Marlow <marlowsd@gmail.com>
* do_checks: do not set HpAlloc if the stack check fails
This fixes a very rare heap corruption bug, whereby
- a context switch is requested, which sets HpLim to zero
(contextSwitchCapability(), called by the timer signal or
another Capability).
- simultaneously a stack check fails, in a code fragment that has
both a stack and a heap check.
The RTS then assumes that a heap-check failure has occurred and
subtracts HpAlloc from Hp, although in fact it was a stack-check
failure and retreating Hp will overwrite valid heap objects. The bug
is that HpAlloc should only be set when Hp has been incremented by the
heap check. See comments in rts/HeapStackCheck.cmm for more details.
This bug is probably incredibly rare in practice, but I happened to be
working on a test that triggers it reliably:
concurrent/should_run/throwto001, compiled with -O -threaded, args 30
300 +RTS -N2, run repeatedly in a loop.
M ./compiler/codeGen/CgHeapery.lhs -6 +16
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | |
| 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":"Propagate bug fix into new code generator","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"6.14 branch","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"We must not forget to propagate this fix into the new code generator pipeline:\r\n{{{\r\nThu Mar 25 04:03:28 PDT 2010 Simon Marlow <marlowsd@gmail.com>\r\n * do_checks: do not set HpAlloc if the stack check fails\r\n \r\n This fixes a very rare heap corruption bug, whereby\r\n \r\n - a context switch is requested, which sets HpLim to zero\r\n (contextSwitchCapability(), called by the timer signal or\r\n another Capability).\r\n \r\n - simultaneously a stack check fails, in a code fragment that has\r\n both a stack and a heap check.\r\n \r\n The RTS then assumes that a heap-check failure has occurred and\r\n subtracts HpAlloc from Hp, although in fact it was a stack-check\r\n failure and retreating Hp will overwrite valid heap objects. The bug\r\n is that HpAlloc should only be set when Hp has been incremented by the\r\n heap check. See comments in rts/HeapStackCheck.cmm for more details.\r\n \r\n This bug is probably incredibly rare in practice, but I happened to be\r\n working on a test that triggers it reliably:\r\n concurrent/should_run/throwto001, compiled with -O -threaded, args 30\r\n 300 +RTS -N2, run repeatedly in a loop.\r\n\r\n M ./compiler/codeGen/CgHeapery.lhs -6 +16\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/4148improve new recursive do syntax2019-07-07T19:00:23Zguestimprove new recursive do syntaxThis is a request for an adjustment of the syntax for the new
recursive do notation. "rec { ... }" should parse/type check as an expression
such that:
```
mdo
a <- getChar
b <- f c
c <- g b
putChar c
retu...This is a request for an adjustment of the syntax for the new
recursive do notation. "rec { ... }" should parse/type check as an expression
such that:
```
mdo
a <- getChar
b <- f c
c <- g b
putChar c
return b
```
can be written as
```
do rec
a <- getChar
b <- f c
c <- g b
putChar c
return b
```
at moment the closest you can get is ...
```
t5 =
do rec
a <- getChar
b <- f c
c <- g b
putChar c
return b
```
it seems rec { ... } is a binding construct not an expression and therefore
can not be used in the final position (or sole component) of a do block
benefits
- drop in replacement for mdo, that is the construct "do rec"
> becomes semantically and syntactically equivalent to the mdo
> notation
- current layout is maintained (which is much neater)
- I would argue that it is more intuitive
dificulty
- it seems to be a minor change?.
related
- this change seems to have been introduced as
> [http://hackage.haskell.org/trac/ghc/ticket/2798](http://hackage.haskell.org/trac/ghc/ticket/2798)
> somewhat surreptitiously (well, cought me by surprise, anyway.).
## background
1. 12.1 introduced a change to the recursive do syntax
[http://old.nabble.com/Update-on-GHC-6.12.1-td26103595.html](http://old.nabble.com/Update-on-GHC-6.12.1-td26103595.html)
Instead of writing
```
mdo
a <- getChar
b <- f c
c <- g b
putChar c
return b
```
you would write
```
do
a <- getChar
rec { b <- f c
; c <- g b }
putChar c
return b
```
A couple of issues about the change:
- the new syntax spoils layout (see above)
- migrating to the new syntax with the current limitation is
> non-trivial, requires analysis of code (in some cases).
for the record ...
```
> t2 =
> do rec
> a <- getChar
> b <- f c
> c <- g b
> putChar c
> return b
> f = return . (const 'a')
> g = return
eg.lhs:23:6:
The last statement in a 'do' construct must be an expression
Failed, modules loaded: none.
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------ |
| Version | 6.12.3 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | jvlask@hotmail.com |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"improve new recursive do syntax","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.12.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["jvlask@hotmail.com"],"type":"FeatureRequest","description":"This is a request for an adjustment of the syntax for the new\r\nrecursive do notation. \"rec { ... }\" should parse/type check as an expression\r\nsuch that:\r\n\r\n{{{\r\n mdo\r\n a <- getChar\r\n b <- f c\r\n c <- g b\r\n putChar c\r\n return b\r\n}}}\r\n\r\ncan be written as\r\n\r\n{{{\r\n do rec\r\n a <- getChar\r\n b <- f c\r\n c <- g b\r\n putChar c\r\n return b\r\n}}}\r\n\r\nat moment the closest you can get is ...\r\n\r\n{{{\r\nt5 =\r\n do rec \r\n a <- getChar\r\n b <- f c\r\n c <- g b\r\n putChar c\r\n return b \r\n}}}\r\n\r\nit seems rec { ... } is a binding construct not an expression and therefore\r\ncan not be used in the final position (or sole component) of a do block\r\n\r\nbenefits\r\n - drop in replacement for mdo, that is the construct \"do rec\"\r\n becomes semantically and syntactically equivalent to the mdo\r\n notation\r\n - current layout is maintained (which is much neater)\r\n - I would argue that it is more intuitive\r\n\r\n\r\ndificulty\r\n - it seems to be a minor change?.\r\n\r\nrelated\r\n - this change seems to have been introduced as\r\n [http://hackage.haskell.org/trac/ghc/ticket/2798]\r\n somewhat surreptitiously (well, cought me by surprise, anyway.).\r\n\r\n== background ==\r\n\r\n6.12.1 introduced a change to the recursive do syntax\r\n[http://old.nabble.com/Update-on-GHC-6.12.1-td26103595.html]\r\n\r\nInstead of writing\r\n\r\n{{{\r\n mdo\r\n a <- getChar\r\n b <- f c\r\n c <- g b\r\n putChar c\r\n return b\r\n}}}\r\n\r\nyou would write\r\n\r\n{{{\r\n do\r\n a <- getChar\r\n rec { b <- f c\r\n ; c <- g b }\r\n putChar c\r\n return b\r\n}}}\r\n\r\nA couple of issues about the change:\r\n\r\n\r\n\r\n - the new syntax spoils layout (see above)\r\n - migrating to the new syntax with the current limitation is\r\n non-trivial, requires analysis of code (in some cases).\r\n\r\nfor the record ...\r\n\r\n{{{\r\n> t2 =\r\n> do rec\r\n> a <- getChar\r\n> b <- f c\r\n> c <- g b\r\n> putChar c\r\n> return b\r\n\r\n> f = return . (const 'a')\r\n> g = return\r\n\r\neg.lhs:23:6:\r\n The last statement in a 'do' construct must be an expression\r\nFailed, modules loaded: none.\r\n}}}\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/4197clarify which names can not be quoted2019-07-07T19:00:09ZChristian Maederclarify which names can not be quotedhttp://www.haskell.org/ghc/docs/6.12.2/html/users_guide/template-haskell.html\#id665813
I suppose a primed identifier like x' or T' can not be quoted, because they would be scanned as character.
Maybe all identifiers containing primes ...http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/template-haskell.html\#id665813
I suppose a primed identifier like x' or T' can not be quoted, because they would be scanned as character.
Maybe all identifiers containing primes should be disallowed being quoted by one or two leading primes.
In any case, the documentation should match the implementation.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------- |
| Version | 6.12.3 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Documentation |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"clarify which names can not be quoted","status":"New","operating_system":"","component":"Documentation","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"6.12.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"http://www.haskell.org/ghc/docs/6.12.2/html/users_guide/template-haskell.html#id665813\r\n\r\nI suppose a primed identifier like x' or T' can not be quoted, because they would be scanned as character.\r\n\r\nMaybe all identifiers containing primes should be disallowed being quoted by one or two leading primes.\r\n\r\nIn any case, the documentation should match the implementation.\r\n\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/5261-pgmF messes up hpc .mix output2019-07-07T18:56:10Zelaforge-pgmF messes up hpc .mix outputFor example:
```
% cat t.hs
f x = x * 20
main = print (f 20)
% cat pp
#!/bin/sh
cp $2 $3
% ghc -fhpc -F -pgmF./pp t.hs
[1 of 1] Compiling Main ( t.hs, t.o )
Linking t ...
% cat .hpc/Main.mix
Mix "t.hs" 1308170257 1934109072 ...For example:
```
% cat t.hs
f x = x * 20
main = print (f 20)
% cat pp
#!/bin/sh
cp $2 $3
% ghc -fhpc -F -pgmF./pp t.hs
[1 of 1] Compiling Main ( t.hs, t.o )
Linking t ...
% cat .hpc/Main.mix
Mix "t.hs" 1308170257 1934109072 1 []
```
If I omit pgmF, then I get proper Boxes in the .mix file. When I run over a large code base, some scattered expressions get Boxes, but the majority don't.
I think this started showing up with ghc 7.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------- |
| Version | 7.0.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Code Coverage |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | qdunkan@gmail.com |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"-pgmF messes up hpc .mix output","status":"New","operating_system":"","component":"Code Coverage","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"andy@galois.com"},"version":"7.0.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["qdunkan@gmail.com"],"type":"Bug","description":"For example:\r\n\r\n\r\n{{{\r\n% cat t.hs\r\nf x = x * 20\r\nmain = print (f 20)\r\n% cat pp\r\n#!/bin/sh\r\ncp $2 $3\r\n% ghc -fhpc -F -pgmF./pp t.hs\r\n[1 of 1] Compiling Main ( t.hs, t.o )\r\nLinking t ...\r\n% cat .hpc/Main.mix\r\nMix \"t.hs\" 1308170257 1934109072 1 []\r\n}}}\r\n\r\nIf I omit pgmF, then I get proper Boxes in the .mix file. When I run over a large code base, some scattered expressions get Boxes, but the majority don't.\r\n\r\nI think this started showing up with ghc 7.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1andy@galois.comandy@galois.comhttps://gitlab.haskell.org/ghc/ghc/-/issues/5321Very slow constraint solving for type families2019-07-07T18:55:54ZSimon Peyton JonesVery slow constraint solving for type familiesThis post (to the ghc-users mailing list, from Gershom Bazerman) is in literate Haskell. It describes how certain performance leaks are introduced in type level programming. These leaks do not affect program runtimes, but can cause compi...This post (to the ghc-users mailing list, from Gershom Bazerman) is in literate Haskell. It describes how certain performance leaks are introduced in type level programming. These leaks do not affect program runtimes, but can cause compile times to grow drastically. They exist both with Functional Dependencies and Type Families, but are currently worse with the former, and have grown worse with the new constraint solver in GHC 7. It is intended both as a guide to those encountering these issues, and as a motivation for the GHC development team to address such issues as the constraint solver is developed and improved.
```
> {-# OPTIONS_GHC -fcontext-stack=1000 #-} {-# LANGUAGE
> FlexibleContexts, FlexibleInstances, FunctionalDependencies,
> MultiParamTypeClasses, OverlappingInstances, TypeSynonymInstances,
> TypeOperators, UndecidableInstances, TypeFamilies #-} module
> TypePerformance where
```
Our running example, for simplicity's sake, is a type-level map of a single function. For reference, here is the code for a simple value-level map of a single function.
```
> vfoo = id
> mapfoo (x : xs) = vfoo x : mapfoo xs
> mapfoo [] = []
```
Because Haskell is a lazy language, this runs in O(n) time and constant stack.
We now lift map to the type level, to operate over HLists.
First, the basic HList types
```
> infixr 3 :*
> data x :* xs = x :* xs deriving Show
> data HNil = HNil deriving Show
```
Next, a large boring HList
```
> -- Adds ten cells
> addData x = i :* i :* d :* d :* s :*
> i :* i :* d :* d :* s :*
> x
> where i = 1 :: Int
> d = 1 :: Double
> s = ""
>
> -- Has 70 cells.
> sampleData = addData $ addData $ addData $ addData $ addData $
> addData $ addData $
> HNil
```
Next, a simple polymorphic function to map
```
> class Foo x y | x -> y
> where foo :: x -> y
> foo = undefined
> instance Foo Int Double
> instance Foo Double Int
> instance Foo String String
```
Now, our map
```
> class HMapFoo1 as bs | as -> bs where
> hMapFoo1 :: as -> bs
>
> instance (Foo a b, HMapFoo1 as bs) => HMapFoo1 (a :* as) (b :* bs) where
> hMapFoo1 (x :* xs) = foo x :* hMapFoo1 xs
>
> instance HMapFoo1 HNil HNil where
> hMapFoo1 _ = HNil
```
If we enable the following line, compilation time is \~ 9 seconds.
```
> testHMapFoo1 = hMapFoo1 sampleData
```
Furthermore, playing with the size of sampleData, we see that the time spent in compilation is superlinear -- each additional cell costs a greater amount of time. This is because while Haskell is lazy at the value level, it is strict at the type level. Therefore, just as in a strict language, HMapFoo1's cost grows O(n\*\*2) because even as we induct over the as, we build up a stack of bs. Just as in a strict language, the solution is to make hMapFoo tail recursive through introducing an accumulator. This also reverses the hlist, but never mind that.
```
> class HMapFoo2 acc as bs | acc as -> bs where
> hMapFoo2 :: acc -> as -> bs
>
> instance (Foo a b, HMapFoo2 (b :* bs) as res) => HMapFoo2 bs (a :* as) res where
> hMapFoo2 acc (x :* xs) = hMapFoo2 (foo x :* acc) xs
>
> instance HMapFoo2 acc HNil acc where
> hMapFoo2 acc _ = acc
```
If we enable the following line, compilation time is a much more satisfying \~0.5s.
```
> testHMapFoo2 = hMapFoo2 HNil sampleData
```
But wait, there's trouble on the horizon! Consider the following version:
```
> class HMapFoo3 acc as bs | acc as -> bs where
> hMapFoo3 :: acc -> as -> bs
>
> instance (HMapFoo3 (b :* bs) as res, Foo a b) => HMapFoo3 bs (a :* as) res where
> hMapFoo3 acc (x :* xs) = hMapFoo3 (foo x :* acc) xs
>
> instance HMapFoo3 acc HNil acc where
> hMapFoo3 acc _ = acc
```
The only difference between hMapFoo2 and hMapFoo3 is that the order of constraints on the inductive case has been reversed, with the recursive constraint first and the immediately checkable constraint second. Now, if we enable the following line, compilation time rockets to \~6s!
```
> testHMapFoo3 = hMapFoo3 HNil sampleData
```
Slowdowns such as those described here are not a purely hypothetical issue, but have caused real problems in production code. The example given above is fairly simple. The constraints used are minimal and easily checked. In real programs, the constraints are more difficult, increasing constant factors significantly. These constant factors, combined with unexpected algorithmic slowdowns due to the type inference engine, can lead (and have lead) to compilation times of HList-style code becoming deeply unwieldy-to-unusable, and can lead (and have lead) to this occuring only well after this code has been introduced and used on smaller cases without trouble.
The constraint solver should certainly be smart enough to reduce the compile times of HMapFoo3 to those of HMapFoo2. In fact, with type families, the there is no difference (see below). Could the compiler be smart enough to do the same for HMapFoo1? I'm not sure. Certainly, it could at least knock down its own constant factors a bit, even if it can't improve the big-O performance there.
----
== Appendix: Examples with Type Families ==
As the below code demonstrates, the same issues demonstrated with Functional Dependencies also appear with Type Families, although less horribly, as their code-path seems more optimized in the current constraint solver:
```
> class TFoo x where
> type TFooFun x
> tfoo :: x -> TFooFun x
> tfoo = undefined
>
> instance TFoo Int where
> type TFooFun Int = Double
> instance TFoo Double where
> type TFooFun Double = Int
> instance TFoo String where
> type TFooFun String = String
>
> class THMapFoo1 as where
> type THMapFoo1Res as
> thMapFoo1 :: as -> THMapFoo1Res as
>
> instance (TFoo a, THMapFoo1 as) => THMapFoo1 (a :* as) where
> type THMapFoo1Res (a :* as) = TFooFun a :* THMapFoo1Res as
> thMapFoo1 (x :* xs) = tfoo x :* thMapFoo1 xs
>
> instance THMapFoo1 HNil where
> type THMapFoo1Res HNil = HNil
> thMapFoo1 _ = HNil
```
The following, when enabled, takes \~3.5s. This demonstrates that slowdown occurs with type families as well.
```
> testTHMapFoo1 = thMapFoo1 sampleData
> class THMapFoo2 acc as where
> type THMapFoo2Res acc as
> thMapFoo2 :: acc -> as -> THMapFoo2Res acc as
>
> instance (TFoo a, THMapFoo2 (TFooFun a :* acc) as) => THMapFoo2 acc (a :* as) where
> type THMapFoo2Res acc (a :* as) = THMapFoo2Res (TFooFun a :* acc) as
> thMapFoo2 acc (x :* xs) = thMapFoo2 (tfoo x :* acc) xs
>
> instance THMapFoo2 acc HNil where
> type THMapFoo2Res acc HNil = acc
> thMapFoo2 acc _ = acc
```
The following, when enabled, takes \~0.6s. This demonstrates that the tail recursive transform fixes the slowdown with type families just as with fundeps.
```
> testTHMapFoo2 = thMapFoo2 HNil sampleData
> class THMapFoo3 acc as where
> type THMapFoo3Res acc as
> thMapFoo3 :: acc -> as -> THMapFoo3Res acc as
>
> instance (THMapFoo3 (TFooFun a :* acc) as, TFoo a) => THMapFoo3 acc (a :* as) where
> type THMapFoo3Res acc (a :* as) = THMapFoo3Res (TFooFun a :* acc) as
> thMapFoo3 acc (x :* xs) = thMapFoo3 (tfoo x :* acc) xs
>
> instance THMapFoo3 acc HNil where
> type THMapFoo3Res acc HNil = acc
> thMapFoo3 acc _ = acc
```
The following, when enabled, also takes \~0.6s. This demonstrates that, unlike the fundep case, the order of type class constraints does not, in this instance, affect the performance of type families.
```
> testTHMapFoo3 = thMapFoo3 HNil sampleData
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------------------------------ |
| Version | 7.0.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | dimitris@microsoft.com, gershomb@gmail.com |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Very slow constraint solving for type families","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.0.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["dimitris@microsoft.com","gershomb@gmail.com"],"type":"Bug","description":"This post (to the ghc-users mailing list, from Gershom Bazerman) is in literate Haskell. It describes how certain performance leaks are introduced in type level programming. These leaks do not affect program runtimes, but can cause compile times to grow drastically. They exist both with Functional Dependencies and Type Families, but are currently worse with the former, and have grown worse with the new constraint solver in GHC 7. It is intended both as a guide to those encountering these issues, and as a motivation for the GHC development team to address such issues as the constraint solver is developed and improved. \r\n\r\n{{{\r\n> {-# OPTIONS_GHC -fcontext-stack=1000 #-} {-# LANGUAGE \r\n> FlexibleContexts, FlexibleInstances, FunctionalDependencies, \r\n> MultiParamTypeClasses, OverlappingInstances, TypeSynonymInstances, \r\n> TypeOperators, UndecidableInstances, TypeFamilies #-} module \r\n> TypePerformance where\r\n}}}\r\nOur running example, for simplicity's sake, is a type-level map of a single function. For reference, here is the code for a simple value-level map of a single function. \r\n{{{\r\n> vfoo = id\r\n> mapfoo (x : xs) = vfoo x : mapfoo xs\r\n> mapfoo [] = []\r\n}}}\r\nBecause Haskell is a lazy language, this runs in O(n) time and constant stack. \r\n\r\nWe now lift map to the type level, to operate over HLists. \r\n\r\nFirst, the basic HList types \r\n{{{\r\n> infixr 3 :*\r\n> data x :* xs = x :* xs deriving Show\r\n> data HNil = HNil deriving Show\r\n}}}\r\nNext, a large boring HList \r\n{{{\r\n> -- Adds ten cells\r\n> addData x = i :* i :* d :* d :* s :* \r\n> i :* i :* d :* d :* s :* \r\n> x \r\n> where i = 1 :: Int \r\n> d = 1 :: Double \r\n> s = \"\" \r\n> \r\n> -- Has 70 cells. \r\n> sampleData = addData $ addData $ addData $ addData $ addData $ \r\n> addData $ addData $ \r\n> HNil\r\n}}}\r\nNext, a simple polymorphic function to map \r\n{{{\r\n> class Foo x y | x -> y \r\n> where foo :: x -> y \r\n> foo = undefined\r\n\r\n> instance Foo Int Double\r\n> instance Foo Double Int\r\n> instance Foo String String\r\n}}}\r\nNow, our map \r\n{{{\r\n> class HMapFoo1 as bs | as -> bs where \r\n> hMapFoo1 :: as -> bs\r\n> \r\n> instance (Foo a b, HMapFoo1 as bs) => HMapFoo1 (a :* as) (b :* bs) where \r\n> hMapFoo1 (x :* xs) = foo x :* hMapFoo1 xs\r\n> \r\n> instance HMapFoo1 HNil HNil where \r\n> hMapFoo1 _ = HNil\r\n}}}\r\nIf we enable the following line, compilation time is ~ 9 seconds. \r\n{{{\r\n > testHMapFoo1 = hMapFoo1 sampleData \r\n}}}\r\nFurthermore, playing with the size of sampleData, we see that the time spent in compilation is superlinear -- each additional cell costs a greater amount of time. This is because while Haskell is lazy at the value level, it is strict at the type level. Therefore, just as in a strict language, HMapFoo1's cost grows O(n**2) because even as we induct over the as, we build up a stack of bs. Just as in a strict language, the solution is to make hMapFoo tail recursive through introducing an accumulator. This also reverses the hlist, but never mind that. \r\n{{{\r\n> class HMapFoo2 acc as bs | acc as -> bs where \r\n> hMapFoo2 :: acc -> as -> bs\r\n> \r\n> instance (Foo a b, HMapFoo2 (b :* bs) as res) => HMapFoo2 bs (a :* as) res where \r\n> hMapFoo2 acc (x :* xs) = hMapFoo2 (foo x :* acc) xs\r\n> \r\n> instance HMapFoo2 acc HNil acc where \r\n> hMapFoo2 acc _ = acc\r\n}}}\r\nIf we enable the following line, compilation time is a much more satisfying ~0.5s. \r\n{{{\r\n > testHMapFoo2 = hMapFoo2 HNil sampleData \r\n}}}\r\nBut wait, there's trouble on the horizon! Consider the following version: \r\n{{{\r\n> class HMapFoo3 acc as bs | acc as -> bs where \r\n> hMapFoo3 :: acc -> as -> bs\r\n> \r\n> instance (HMapFoo3 (b :* bs) as res, Foo a b) => HMapFoo3 bs (a :* as) res where \r\n> hMapFoo3 acc (x :* xs) = hMapFoo3 (foo x :* acc) xs\r\n> \r\n> instance HMapFoo3 acc HNil acc where \r\n> hMapFoo3 acc _ = acc\r\n}}}\r\nThe only difference between hMapFoo2 and hMapFoo3 is that the order of constraints on the inductive case has been reversed, with the recursive constraint first and the immediately checkable constraint second. Now, if we enable the following line, compilation time rockets to ~6s! \r\n{{{\r\n > testHMapFoo3 = hMapFoo3 HNil sampleData \r\n}}}\r\nSlowdowns such as those described here are not a purely hypothetical issue, but have caused real problems in production code. The example given above is fairly simple. The constraints used are minimal and easily checked. In real programs, the constraints are more difficult, increasing constant factors significantly. These constant factors, combined with unexpected algorithmic slowdowns due to the type inference engine, can lead (and have lead) to compilation times of HList-style code becoming deeply unwieldy-to-unusable, and can lead (and have lead) to this occuring only well after this code has been introduced and used on smaller cases without trouble. \r\n\r\nThe constraint solver should certainly be smart enough to reduce the compile times of HMapFoo3 to those of HMapFoo2. In fact, with type families, the there is no difference (see below). Could the compiler be smart enough to do the same for HMapFoo1? I'm not sure. Certainly, it could at least knock down its own constant factors a bit, even if it can't improve the big-O performance there. \r\n\r\n----\r\n== Appendix: Examples with Type Families ==\r\n\r\nAs the below code demonstrates, the same issues demonstrated with Functional Dependencies also appear with Type Families, although less horribly, as their code-path seems more optimized in the current constraint solver: \r\n{{{\r\n> class TFoo x where \r\n> type TFooFun x \r\n> tfoo :: x -> TFooFun x \r\n> tfoo = undefined\r\n> \r\n> instance TFoo Int where \r\n> type TFooFun Int = Double\r\n> instance TFoo Double where \r\n> type TFooFun Double = Int\r\n> instance TFoo String where \r\n> type TFooFun String = String\r\n> \r\n> class THMapFoo1 as where \r\n> type THMapFoo1Res as \r\n> thMapFoo1 :: as -> THMapFoo1Res as\r\n> \r\n> instance (TFoo a, THMapFoo1 as) => THMapFoo1 (a :* as) where \r\n> type THMapFoo1Res (a :* as) = TFooFun a :* THMapFoo1Res as \r\n> thMapFoo1 (x :* xs) = tfoo x :* thMapFoo1 xs\r\n> \r\n> instance THMapFoo1 HNil where \r\n> type THMapFoo1Res HNil = HNil \r\n> thMapFoo1 _ = HNil\r\n}}}\r\nThe following, when enabled, takes ~3.5s. This demonstrates that slowdown occurs with type families as well. \r\n{{{\r\n > testTHMapFoo1 = thMapFoo1 sampleData \r\n\r\n> class THMapFoo2 acc as where \r\n> type THMapFoo2Res acc as \r\n> thMapFoo2 :: acc -> as -> THMapFoo2Res acc as\r\n> \r\n> instance (TFoo a, THMapFoo2 (TFooFun a :* acc) as) => THMapFoo2 acc (a :* as) where \r\n> type THMapFoo2Res acc (a :* as) = THMapFoo2Res (TFooFun a :* acc) as \r\n> thMapFoo2 acc (x :* xs) = thMapFoo2 (tfoo x :* acc) xs\r\n> \r\n> instance THMapFoo2 acc HNil where \r\n> type THMapFoo2Res acc HNil = acc \r\n> thMapFoo2 acc _ = acc\r\n}}}\r\nThe following, when enabled, takes ~0.6s. This demonstrates that the tail recursive transform fixes the slowdown with type families just as with fundeps. \r\n{{{\r\n > testTHMapFoo2 = thMapFoo2 HNil sampleData \r\n\r\n> class THMapFoo3 acc as where \r\n> type THMapFoo3Res acc as \r\n> thMapFoo3 :: acc -> as -> THMapFoo3Res acc as\r\n> \r\n> instance (THMapFoo3 (TFooFun a :* acc) as, TFoo a) => THMapFoo3 acc (a :* as) where \r\n> type THMapFoo3Res acc (a :* as) = THMapFoo3Res (TFooFun a :* acc) as \r\n> thMapFoo3 acc (x :* xs) = thMapFoo3 (tfoo x :* acc) xs\r\n> \r\n> instance THMapFoo3 acc HNil where \r\n> type THMapFoo3Res acc HNil = acc \r\n> thMapFoo3 acc _ = acc\r\n}}}\r\nThe following, when enabled, also takes ~0.6s. This demonstrates that, unlike the fundep case, the order of type class constraints does not, in this instance, affect the performance of type families. \r\n{{{\r\n > testTHMapFoo3 = thMapFoo3 HNil sampleData \r\n}}}\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/5390Hard-coded /Developer path in Mac ghc2019-07-07T18:55:38ZAhrumanHard-coded /Developer path in Mac ghcThe Haskell Platform package for Mac OS X installs a /usr/bin/ghc script which hard-codes the path to gcc as:
```
pgmgcc="/Developer/usr/bin/gcc"
```
This is incorrect, as Xcode tools can be installed at semi-arbitrary locations, and t...The Haskell Platform package for Mac OS X installs a /usr/bin/ghc script which hard-codes the path to gcc as:
```
pgmgcc="/Developer/usr/bin/gcc"
```
This is incorrect, as Xcode tools can be installed at semi-arbitrary locations, and there may be several versions installed. The correct approach is:
```
developerpath=`xcode-select --print-path` # Produces "/Developer" or alternative path
pgmgcc="$developerpath/usr/bin/gcc"
```7.6.1pumpkinpumpkinhttps://gitlab.haskell.org/ghc/ghc/-/issues/5582Panic from -C flag2019-07-07T18:54:38ZmjoPanic from -C flagjumba \~ $ cat hello_world.hs
```
main = do
print "Hello, World."
```
jumba \~ $ ghc -C hello_world.hs
```
addFlag by -C on the commandline:
Warning: The -fvia-C flag does nothing; it will be removed in a future GHC release
ghc:...jumba \~ $ cat hello_world.hs
```
main = do
print "Hello, World."
```
jumba \~ $ ghc -C hello_world.hs
```
addFlag by -C on the commandline:
Warning: The -fvia-C flag does nothing; it will be removed in a future GHC release
ghc: panic! (the 'impossible' happened)
(GHC version 7.2.1 for x86_64-unknown-linux):
pipeLoop: at phase As but I wanted to stop at phase HCc
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.2.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":"Panic from -C flag","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"jumba ~ $ cat hello_world.hs\r\n\r\n{{{\r\nmain = do\r\n print \"Hello, World.\"\r\n}}}\r\n\r\njumba ~ $ ghc -C hello_world.hs\r\n\r\n{{{\r\naddFlag by -C on the commandline:\r\n Warning: The -fvia-C flag does nothing; it will be removed in a future GHC release\r\nghc: panic! (the 'impossible' happened)\r\n (GHC version 7.2.1 for x86_64-unknown-linux):\r\n\tpipeLoop: at phase As but I wanted to stop at phase HCc\r\n\r\nPlease report this as a GHC bug: http://www.haskell.org/ghc/reportabug\r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1Ian Lynagh <igloo@earth.li>Ian Lynagh <igloo@earth.li>https://gitlab.haskell.org/ghc/ghc/-/issues/5612Better support for kinds in Template Haskell2019-07-07T18:54:22ZguestBetter support for kinds in Template HaskellType checking the attached code produces a legitimate type error, and also the following message:
```
Tip.hs:107:14:ghc: panic! (the 'impossible' happened)
(GHC version 7.0.3 for i386-unknown-linux):
Exotic form of kind ghc-prim:GHC....Type checking the attached code produces a legitimate type error, and also the following message:
```
Tip.hs:107:14:ghc: panic! (the 'impossible' happened)
(GHC version 7.0.3 for i386-unknown-linux):
Exotic form of kind ghc-prim:GHC.Prim.?{(w) tc 34g}
```7.6.1lunarislunarishttps://gitlab.haskell.org/ghc/ghc/-/issues/5978Type error in one function causes wrong type error report in another function...2019-07-07T18:52:44ZLemmingType error in one function causes wrong type error report in another function in the presence of functionally dependent typesWhen trying to reduce my problem in #5970 to a simple program I encountered an even more obvious bug. The problem is essentially as follows: I have
```
correct :: T
correct = ...
wrong :: T
wrong = f correct
```
where 'wrong' has a ty...When trying to reduce my problem in #5970 to a simple program I encountered an even more obvious bug. The problem is essentially as follows: I have
```
correct :: T
correct = ...
wrong :: T
wrong = f correct
```
where 'wrong' has a type error and 'correct' is type correct. If I outcomment 'wrong' then GHC correctly confirms type-correctness of 'correct', but if 'wrong' is enabled then GHC claims a type error in both 'wrong' and 'correct'.
To me it looks like the type-checker is trying to unify types across function boundaries. This would explain both non-linear growth of type-checking time and the observed effect of incorrect type errors.
See attached program for a working example.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 7.4.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Type error in one function causes wrong type error report in another function in the presence of functionally dependent types","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"When trying to reduce my problem in #5970 to a simple program I encountered an even more obvious bug. The problem is essentially as follows: I have\r\n{{{\r\ncorrect :: T\r\ncorrect = ...\r\n\r\nwrong :: T\r\nwrong = f correct\r\n}}}\r\nwhere 'wrong' has a type error and 'correct' is type correct. If I outcomment 'wrong' then GHC correctly confirms type-correctness of 'correct', but if 'wrong' is enabled then GHC claims a type error in both 'wrong' and 'correct'.\r\nTo me it looks like the type-checker is trying to unify types across function boundaries. This would explain both non-linear growth of type-checking time and the observed effect of incorrect type errors.\r\nSee attached program for a working example.","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/7010Type error in one function causes wrong type error report in another function...2019-07-07T18:51:48ZLemmingType error in one function causes wrong type error report in another function when using type familiesThis ticket is very similar to #5978, but this time it is about type families. If I load the attached module I get the two error messages:
```
TypeCheck7_4_1_TF_IncorrectMsg.hs:27:21:
Couldn't match type `Float' with `Serial Float'
...This ticket is very similar to #5978, but this time it is about type families. If I load the attached module I get the two error messages:
```
TypeCheck7_4_1_TF_IncorrectMsg.hs:27:21:
Couldn't match type `Float' with `Serial Float'
Expected type: (ValueTuple Vector, ValueTuple Vector)
Actual type: (Serial Float, Serial Float)
In the first argument of `processIO', namely `stereoFromMono'
In the expression: processIO stereoFromMono
TypeCheck7_4_1_TF_IncorrectMsg.hs:42:27:
Couldn't match type `IO' with `Serial'
Expected type: (Float, ValueTuple Vector)
Actual type: (Float, ValueTuple Float)
In the first argument of `withArgs', namely `plug'
In the expression: withArgs plug
```
If I uncomment 'filterFormant', that is, only the second one of the two criticized parts, then the module is accepted.
These two error messages are very confusing because in the original module 'phoneme' was a complex definition and it was not immediately clear that it is actually correct. Trying hard to fix it does not succeed because it is not broken.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.4.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":"Type error in one function causes wrong type error report in another function when using type families","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"This ticket is very similar to #5978, but this time it is about type families. If I load the attached module I get the two error messages:\r\n{{{\r\nTypeCheck7_4_1_TF_IncorrectMsg.hs:27:21:\r\n Couldn't match type `Float' with `Serial Float'\r\n Expected type: (ValueTuple Vector, ValueTuple Vector)\r\n Actual type: (Serial Float, Serial Float)\r\n In the first argument of `processIO', namely `stereoFromMono'\r\n In the expression: processIO stereoFromMono\r\n\r\nTypeCheck7_4_1_TF_IncorrectMsg.hs:42:27:\r\n Couldn't match type `IO' with `Serial'\r\n Expected type: (Float, ValueTuple Vector)\r\n Actual type: (Float, ValueTuple Float)\r\n In the first argument of `withArgs', namely `plug'\r\n In the expression: withArgs plug\r\n}}}\r\nIf I uncomment 'filterFormant', that is, only the second one of the two criticized parts, then the module is accepted.\r\n\r\nThese two error messages are very confusing because in the original module 'phoneme' was a complex definition and it was not immediately clear that it is actually correct. Trying hard to fix it does not succeed because it is not broken.\r\n","type_of_failure":"OtherFailure","blocking":[]} -->7.6.1