GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2019-07-07T18:23:13Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/13200Old links to snapshot releases in GHC user's guide2019-07-07T18:23:13ZTakenobu TaniOld links to snapshot releases in GHC user's guideFollowing links are out-of-date in GHC user's guide; secsion '2.4. GHC version numbering policy' \[1\]:
- We may make snapshot releases of the current stable branch __available for download__ ,
- We may make snapshot releases of the HEA...Following links are out-of-date in GHC user's guide; secsion '2.4. GHC version numbering policy' \[1\]:
- We may make snapshot releases of the current stable branch __available for download__ ,
- We may make snapshot releases of the HEAD __available for download__,
Currently there are no snapshot releases?
\[1\]: https://downloads.haskell.org/\~ghc/latest/docs/html/users_guide/intro.html\#ghc-version-numbering-policy
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------- |
| Version | 8.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Documentation |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Old links to snapshot releases in GHC user's guide","status":"New","operating_system":"","component":"Documentation","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Following links are out-of-date in GHC user's guide; secsion '2.4. GHC version numbering policy' [1]:\r\n\r\n * We may make snapshot releases of the current stable branch __available for download__ ,\r\n * We may make snapshot releases of the HEAD __available for download__, \r\n\r\nCurrently there are no snapshot releases?\r\n\r\n\r\n[1]: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/intro.html#ghc-version-numbering-policy\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13195Ticks panic2019-07-07T18:23:14ZmojojojoTicks panic```
Preprocessing test suite 'tests' for url-decoders-1...
[1 of 1] Compiling Main ( tests/Main.hs, dist/build/tests/tests-tmp/Main.o )
<no location info>: error:
ghc: panic! (the 'impossible' happened)
(GHC version 8....```
Preprocessing test suite 'tests' for url-decoders-1...
[1 of 1] Compiling Main ( tests/Main.hs, dist/build/tests/tests-tmp/Main.o )
<no location info>: error:
ghc: panic! (the 'impossible' happened)
(GHC version 8.0.1 for x86_64-apple-darwin):
Simplifier ticks exhausted
When trying UnfoldingDone withForeignPtr1
To increase the limit, use -fsimpl-tick-factor=N (default 100)
If you need to do this, let GHC HQ know, and what factor you needed
To see detailed counts use -ddump-simpl-stats
Total ticks: 144969
```
To reproduce the but, clone a repo under the specified commit from the following URL: https://github.com/nikita-volkov/url-decoders/tree/22410402a41b7524a1af03d78e381e9ea6354944
Then run the following command on the project:
```
cabal configure --enable-tests && cabal build --ghc-options=-O2
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Ticks panic","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"{{{\r\nPreprocessing test suite 'tests' for url-decoders-1...\r\n[1 of 1] Compiling Main ( tests/Main.hs, dist/build/tests/tests-tmp/Main.o )\r\n\r\n<no location info>: error:\r\n ghc: panic! (the 'impossible' happened)\r\n (GHC version 8.0.1 for x86_64-apple-darwin):\r\n\tSimplifier ticks exhausted\r\n When trying UnfoldingDone withForeignPtr1\r\n To increase the limit, use -fsimpl-tick-factor=N (default 100)\r\n If you need to do this, let GHC HQ know, and what factor you needed\r\n To see detailed counts use -ddump-simpl-stats\r\n Total ticks: 144969\r\n}}}\r\n\r\nTo reproduce the but, clone a repo under the specified commit from the following URL: https://github.com/nikita-volkov/url-decoders/tree/22410402a41b7524a1af03d78e381e9ea6354944\r\n\r\nThen run the following command on the project:\r\n\r\n{{{\r\ncabal configure --enable-tests && cabal build --ghc-options=-O2\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13194Concurrent modifications of package.cache are not safe2020-05-31T16:40:53ZGhost UserConcurrent modifications of package.cache are not safeThere are a couple of different issues here.
1. On Linux, issuing `ghc-pkg register` for multiple packages in parallel might result in lost updates to package database because of how `registerPackage` function works - it reads existing ...There are a couple of different issues here.
1. On Linux, issuing `ghc-pkg register` for multiple packages in parallel might result in lost updates to package database because of how `registerPackage` function works - it reads existing package databases, picks the one to modify, then checks that package info for the package to register is fine and replaces package database with what was read in the beginning + new package info.
Therefore, if updates interleave, it might happen that process1 reads the database, then process2 updates it while process1 still has the old version and uses it for its update later, so update made by process2 is lost.
1. On Windows, update to package database might fail - the issue is that GHC attempts to update it using rename trick, which fails whenever any other process has file to be replaced open for reading. Combine that with the fact that GHC reads package database when compiling packages and you get problems in both Stack (https://github.com/commercialhaskell/stack/issues/2617) and Cabal (https://github.com/haskell/cabal/issues/4005).
BTW, rename trick (used for atomic database updates) not only doesn't work on Windows, it's also not atomic e.g. on NFS (https://stackoverflow.com/questions/41362016/rename-atomicity-and-nfs).
The solution to both problems is to use OS specific features to lock database file (in shared mode when reading and in exclusive mode when writing). This can be done on Windows using LockFileEx. Unfortunately for POSIX things are a bit more complicated.
There are two ways to lock a file on Linux:
1. Using fcntl(F_SET_LK) (POSIX API)
1. Using flock (BSD API)
However, fcntl locks have a serious limitation:
The record locks described above are associated with the process
(unlike the open file description locks described below). This has
> some unfortunate consequences:
- If a process closes any file descriptor referring to a file, then
all of the process's locks on that file are released, regardless
of the file descriptor(s) on which the locks were obtained. This
is bad: it means that a process can lose its locks on a file such
as /etc/passwd or /etc/mtab when for some reason a library
function decides to open, read, and close the same file.
- The threads in a process share locks. In other words, a
multithreaded program can't use record locking to ensure that
threads don't simultaneously access the same region of a file.
Whereas flock is not guaranteed to work with NFS, according to https://en.wikipedia.org/wiki/File_locking\#Problems:
> Whether and how flock locks work on network filesystems, such as NFS, is implementation dependent. On BSD systems, flock calls on a file descriptor open to a file on an NFS-mounted partition are successful no-ops. On Linux prior to 2.6.12, flock calls on NFS files would act only locally. Kernel 2.6.12 and above implement flock calls on NFS files using POSIX byte-range locks. These locks will be visible to other NFS clients that implement fcntl-style POSIX locks, but invisible to those that do not.\[4\]
Assuming that the solution would be to go with locking the database, we would need to:
1. In `registerPackage`, lock all read databases in shared mode except for the database that will later be modified, which has to be locked in exclusive mode. The handle also would need to be kept open and passed to `changeDB` later and used for rewriting the database with updated version in `GHC.PackageDb.writePackageDb` instead of `writeFileAtomic` (which is not actually unconditionally atomic, as demonstrated above).
1. `GHC.PackageDb.decodeFromFile` would lock a file in appropriate mode and return the handle to open file if appropriate.
1. Add support for locking a file. This should be fairly easy to do in GHC.IO.Handle.FD by extending function `openFile'` with appropriate parameters and then adding wrapper function `openLockedFile` or something. We can add both blocking and non-blocking locking to make ghc-pkg show information about waiting for locked package database if appropriate.
Alternatively we could add a function similar to the following: `hLock :: Handle -> LockMode -> Bool{-block-} -> IO Bool`, but that requires extracting file descriptor from Handle, which as far as I see is problematic.
Is going with locking an acceptable solution here?
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | ghc-pkg |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Concurrent modification of package.cache is not safe","status":"New","operating_system":"","component":"ghc-pkg","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"There are a couple of different issues here.\r\n\r\n1. On Linux, issuing `ghc-pkg register` for multiple packages in parallel might result in lost updates to package database because of how `registerPackage` function works - it reads existing package databases, picks the one to modify, then checks that package info for the package to register is fine and replaces package database with what was read in the beginning + new package info.\r\n\r\nTherefore, if updates interleave, it might happen that process1 reads the database, then process2 updates it while process1 still has the old version and uses it for its update later, so update made by process2 is lost.\r\n\r\n2. On Windows, update to package database might fail - the issue is that GHC attempts to update it using rename trick, which fails whenever any other process has file to be replaced open for reading. Combine that with the fact that GHC reads package database when compiling packages and you get problems in both Stack (https://github.com/commercialhaskell/stack/issues/2617) and Cabal (https://github.com/haskell/cabal/issues/4005).\r\n\r\nBTW, rename trick (used for atomic database updates) not only doesn't work on Windows, it's also not atomic e.g. on NFS (https://stackoverflow.com/questions/41362016/rename-atomicity-and-nfs).\r\n\r\nThe solution to both problems is to use OS specific features to lock database file (in shared mode when reading and in exclusive mode when writing). This can be done on Windows using LockFileEx. Unfortunately for POSIX things are a bit more complicated.\r\n\r\nThere are two ways to lock a file on Linux:\r\n1. Using fcntl(F_SET_LK) (POSIX API)\r\n\r\n2. Using flock (BSD API)\r\n\r\nHowever, fcntl locks have a serious limitation:\r\n\r\n The record locks described above are associated with the process\r\n (unlike the open file description locks described below). This has\r\n some unfortunate consequences:\r\n\r\n * If a process closes any file descriptor referring to a file, then\r\n all of the process's locks on that file are released, regardless\r\n of the file descriptor(s) on which the locks were obtained. This\r\n is bad: it means that a process can lose its locks on a file such\r\n as /etc/passwd or /etc/mtab when for some reason a library\r\n function decides to open, read, and close the same file.\r\n\r\n * The threads in a process share locks. In other words, a\r\n multithreaded program can't use record locking to ensure that\r\n threads don't simultaneously access the same region of a file.\r\n\r\nWhereas flock is not guaranteed to work with NFS, according to https://en.wikipedia.org/wiki/File_locking#Problems:\r\n\r\n Whether and how flock locks work on network filesystems, such as NFS, is implementation dependent. On BSD systems, flock calls on a file descriptor open to a file on an NFS-mounted partition are successful no-ops. On Linux prior to 2.6.12, flock calls on NFS files would act only locally. Kernel 2.6.12 and above implement flock calls on NFS files using POSIX byte-range locks. These locks will be visible to other NFS clients that implement fcntl-style POSIX locks, but invisible to those that do not.[4]\r\n\r\nAssuming that the solution would be to go with locking the database, we would need to:\r\n\r\n1. In `registerPackage`, lock all read databases in shared mode except for the database that will later be modified, which has to be locked in exclusive mode. The handle also would need to be kept open and passed to `changeDB` later and used for rewriting the database with updated version in `GHC.PackageDb.writePackageDb` instead of `writeFileAtomic` (which is not actually unconditionally atomic, as demonstrated above).\r\n\r\n2. `GHC.PackageDb.decodeFromFile` would lock a file in appropriate mode and return the handle to open file if appropriate.\r\n\r\n3. Add support for locking a file. This should be fairly easy to do in GHC.IO.Handle.FD by extending function `openFile'` with appropriate parameters and then adding wrapper function `openLockedFile` or something. We can add both blocking and non-blocking locking to make ghc-pkg show information about waiting for locked package database if appropriate.\r\n\r\nAlternatively we could add a function similar to the following: `hLock :: Handle -> LockMode -> Bool{-block-} -> IO Bool`, but that requires extracting file descriptor from Handle, which as far as I see is problematic.\r\n\r\nIs going with locking an acceptable solution here?","type_of_failure":"OtherFailure","blocking":[]} -->8.2.1https://gitlab.haskell.org/ghc/ghc/-/issues/13193Integer (gmp) performance regression?2021-04-04T15:38:20Zwaldmann@imn.htwk-leipzig.deInteger (gmp) performance regression?For a simple program that uses Integer, but actual data would fit in an Int, ghc-8.0.2 seems to have more runtime overhead than ghc-6.12.3 had: http://www.imn.htwk-leipzig.de/\~waldmann/etc/mob/
I am not really sure what to make of it -...For a simple program that uses Integer, but actual data would fit in an Int, ghc-8.0.2 seems to have more runtime overhead than ghc-6.12.3 had: http://www.imn.htwk-leipzig.de/\~waldmann/etc/mob/
I am not really sure what to make of it - an answer could be:
"if you know that your Integer fits in an Int, then just use Int".
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Integer (gmp) performance regression?","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"For a simple program that uses Integer, but actual data would fit in an Int, ghc-8.0.2 seems to have more runtime overhead than ghc-6.12.3 had: http://www.imn.htwk-leipzig.de/~waldmann/etc/mob/\r\n\r\nI am not really sure what to make of it - an answer could be:\r\n\"if you know that your Integer fits in an Int, then just use Int\".\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13192Ambiguity Caused By PolyKind and Not Helpful Error Messages2019-07-07T18:23:15ZShayan-NajdAmbiguity Caused By PolyKind and Not Helpful Error MessagesThe following code results in a confusing/wrong error message, blaming a type variable (`a`) being a fixed Skolem variable:
```hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PolyKinds #-}
data I a
type family F...The following code results in a confusing/wrong error message, blaming a type variable (`a`) being a fixed Skolem variable:
```hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE PolyKinds #-}
data I a
type family F x
type instance F (I a) = a
identity :: F (I a) -> F (I a)
identity x = x
```
with the error message
```
• Couldn't match type ‘F (I a0)’ with ‘F (I a)’
Expected type: F (I a) -> F (I a)
Actual type: F (I a0) -> F (I a0)
NB: ‘F’ is a type function, and may not be injective
The type variable ‘a0’ is ambiguous
• In the ambiguity check for ‘identity’
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the type signature: identity :: F (I a) -> F (I a)
|
9 | identity :: F (I a) -> F (I a)
| ^^^^^^^^^^^^^^^^^^
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonpj |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Ambiguity Caused By PolyKind and Not Helpful Error Messages","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["simonpj"],"type":"Bug","description":"The following code results in a confusing/wrong error message, blaming a type variable (`a`) being a fixed Skolem variable:\r\n \r\n{{{#!hs\r\n{-# LANGUAGE TypeFamilies #-}\r\n{-# LANGUAGE PolyKinds #-}\r\n\r\ndata I a\r\n\r\ntype family F x\r\ntype instance F (I a) = a\r\n\r\nidentity :: F (I a) -> F (I a)\r\nidentity x = x\r\n}}}\r\n\r\nwith the error message\r\n\r\n\r\n{{{\r\n • Couldn't match type ‘F (I a0)’ with ‘F (I a)’\r\n Expected type: F (I a) -> F (I a)\r\n Actual type: F (I a0) -> F (I a0)\r\n NB: ‘F’ is a type function, and may not be injective\r\n The type variable ‘a0’ is ambiguous\r\n • In the ambiguity check for ‘identity’\r\n To defer the ambiguity check to use sites, enable AllowAmbiguousTypes\r\n In the type signature: identity :: F (I a) -> F (I a)\r\n |\r\n9 | identity :: F (I a) -> F (I a)\r\n | ^^^^^^^^^^^^^^^^^^\r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13189Implement same specification as GHC spec file for mingw322021-06-18T00:40:17ZTamar ChristinaImplement same specification as GHC spec file for mingw32When the `GCC` driver envokes the pipeline a `SPEC` is used to determine how
to configure the compiler and which libraries to pass along.
For Windows/mingw, this specfile is
https://github.com/gcc-mirror/gcc/blob/master/gcc/config/i386/...When the `GCC` driver envokes the pipeline a `SPEC` is used to determine how
to configure the compiler and which libraries to pass along.
For Windows/mingw, this specfile is
https://github.com/gcc-mirror/gcc/blob/master/gcc/config/i386/mingw32.h
This has a lot of interesting things that we need to emulate in order to
be able to link as many things out of the box as GCC. In particular this
is why you never need to specify `-lgcc_s` when compiling, but you do when
using `GHCi`.
Or specifying what `-mwindows` links in, that when `-lstdc++` is used what else to link in. Which base DLLs GCC will always link with when building an exe.
And how to link `libgcc`, either static or dynamically.
Currently we only support static linking of `libgcc` (which maybe we should change? or at least make user changeable).
The current partial implementation works by adding hooks into the RTS. A better implementation is adding it all outside the RTS in the `DriverPipeline` tied directly to the commandline options.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.0.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":"Implement same specification as GHC spec file for mingw32","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.4.1","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"Phyx-"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"When the `GCC` driver envokes the pipeline a `SPEC` is used to determine how\r\nto configure the compiler and which libraries to pass along.\r\n\r\nFor Windows/mingw, this specfile is\r\nhttps://github.com/gcc-mirror/gcc/blob/master/gcc/config/i386/mingw32.h\r\n\r\nThis has a lot of interesting things that we need to emulate in order to\r\nbe able to link as many things out of the box as GCC. In particular this\r\nis why you never need to specify `-lgcc_s` when compiling, but you do when\r\nusing `GHCi`.\r\n\r\nOr specifying what `-mwindows` links in, that when `-lstdc++` is used what else to link in. Which base DLLs GCC will always link with when building an exe.\r\n\r\nAnd how to link `libgcc`, either static or dynamically.\r\n\r\nCurrently we only support static linking of `libgcc` (which maybe we should change? or at least make user changeable).\r\n\r\nThe current partial implementation works by adding hooks into the RTS. A better implementation is adding it all outside the RTS in the `DriverPipeline` tied directly to the commandline options.","type_of_failure":"OtherFailure","blocking":[]} -->Tamar ChristinaTamar Christinahttps://gitlab.haskell.org/ghc/ghc/-/issues/13186Change EvNum to EvNum :: Natural -> EvLit2019-07-07T18:23:17ZOleg GrenrusChange EvNum to EvNum :: Natural -> EvLitCurrently we carry `Nat` kind as an Integer internally.
Just changing the type of EvNum (and related isomorphic types like `HsTyLit` etc) does pretty far. The core problem is that we should be able to output Natural literals into Core.
...Currently we carry `Nat` kind as an Integer internally.
Just changing the type of EvNum (and related isomorphic types like `HsTyLit` etc) does pretty far. The core problem is that we should be able to output Natural literals into Core.
Also this would need change to parser, to accept only Naturals in types. Currently negative literals are caught in the renamer (due the fact that template-haskell might inject negative integers as well).
This will propagate to template-haskell, changing TyLit there as well.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.0.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | bgamari |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Change EvNum to EvNum :: Natural -> EvLit","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["bgamari"],"type":"FeatureRequest","description":"Currently we carry `Nat` kind as an Integer internally.\r\n\r\nJust changing the type of EvNum (and related isomorphic types like `HsTyLit` etc) does pretty far. The core problem is that we should be able to output Natural literals into Core.\r\n\r\nAlso this would need change to parser, to accept only Naturals in types. Currently negative literals are caught in the renamer (due the fact that template-haskell might inject negative integers as well).\r\n\r\nThis will propagate to template-haskell, changing TyLit there as well.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13182Rethinking dataToTag#2019-07-07T18:23:18ZDavid FeuerRethinking dataToTag#We currently use a primop `dataToTag#` that requires some careful handling because it can only be applied to something that has already been evaluated. We (now) mark it `can_fail` to prevent it from floating out, and then add a fix-up pa...We currently use a primop `dataToTag#` that requires some careful handling because it can only be applied to something that has already been evaluated. We (now) mark it `can_fail` to prevent it from floating out, and then add a fix-up pass in CorePrep just in case things went wrong. Could we do something simpler? Suppose we had
```hs
-- The real primop, preferably not exported from *anywhere*, but at least documented as never to be used outside GHC.
secretDataToTag# :: a -> Int#
-- A wired-in safe version
dataToTag# :: a -> Int#
dataToTag# !a = secretDataToTag# a
{-# NOINLINE dataToTag# #-}
```
Then `dataToTag#` could be inlined in CorePrep, just like `runRW#`.
### Questions
How would this interact with float out? It should be perfectly safe to float out when its argument is known to be forced, but it seems likely we'll run into let/app invariant failures.
What RULES do we (or should we) have for `dataToTag#`? How will this change affect them? My vague recollection is that we don't have any, but it would be pretty nice to apply something equivalent to case-of-known-constructor. Whenever `dataToTag#` is applied to a known constructor, we should be able to evaluate it. The earlier we do this the better it will inform simplification.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.1 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Rethinking dataToTag#","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.2.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"We currently use a primop `dataToTag#` that requires some careful handling because it can only be applied to something that has already been evaluated. We (now) mark it `can_fail` to prevent it from floating out, and then add a fix-up pass in CorePrep just in case things went wrong. Could we do something simpler? Suppose we had\r\n\r\n{{{#!hs\r\n-- The real primop, preferably not exported from *anywhere*, but at least documented as never to be used outside GHC.\r\nsecretDataToTag# :: a -> Int#\r\n\r\n-- A wired-in safe version\r\ndataToTag# :: a -> Int#\r\ndataToTag# !a = secretDataToTag# a\r\n{-# NOINLINE dataToTag# #-}\r\n}}}\r\n\r\nThen `dataToTag#` could be inlined in CorePrep, just like `runRW#`.\r\n\r\n=== Questions ===\r\n\r\nHow would this interact with float out? It should be perfectly safe to float out when its argument is known to be forced, but it seems likely we'll run into let/app invariant failures.\r\n\r\nWhat RULES do we (or should we) have for `dataToTag#`? How will this change affect them? My vague recollection is that we don't have any, but it would be pretty nice to apply something equivalent to case-of-known-constructor. Whenever `dataToTag#` is applied to a known constructor, we should be able to evaluate it. The earlier we do this the better it will inform simplification.","type_of_failure":"OtherFailure","blocking":[]} -->8.4.1https://gitlab.haskell.org/ghc/ghc/-/issues/13180Confusing error when hs-boot abstract data implemented using synonym2019-07-07T18:23:18ZEdward Z. YangConfusing error when hs-boot abstract data implemented using synonymThis example is a little goofy (that's why I've marked it low priority), but here goes:
```
-- A.hs-boot
module A where
data T
f :: T -> T
-- B.hs
module B(f) where
import {-# SOURCE #-} A
-- A.hs
module A(T, f) where
import quali...This example is a little goofy (that's why I've marked it low priority), but here goes:
```
-- A.hs-boot
module A where
data T
f :: T -> T
-- B.hs
module B(f) where
import {-# SOURCE #-} A
-- A.hs
module A(T, f) where
import qualified B
type T = Int
f :: T -> T
f x = B.f x
```
When compiled, we get a very interesting error:
```
ezyang@sabre:~$ ghc-head --make A.hs -fforce-recomp
[1 of 3] Compiling A[boot] ( A.hs-boot, A.o-boot )
[2 of 3] Compiling B ( B.hs, B.o )
[3 of 3] Compiling A ( A.hs, A.o )
A.hs-boot:2:1: error:
Type constructor ‘T’ has conflicting definitions in the module
and its hs-boot file
Main module: type T = Int
Boot file: abstract T
|
2 | data T
| ^^^^^^
A.hs-boot:3:1: error:
Identifier ‘f’ has conflicting definitions in the module
and its hs-boot file
Main module: f :: T -> T
Boot file: f :: T -> T
The two types are different
|
3 | f :: T -> T
| ^^^^^^^^^^^
```
The first error is legitimate, but the second is puzzling. I believe the problem has to do with the fact that when we load the hs-boot file for checking, we knot-tie it against itself. Thus, the T referenced in "Boot file" is the one WITHOUT the type synonym unfolding, while the main module \*does\* have the type synonym unfolding.
Pretty-printing is horribly confusing in these situations, so it would be nice if we could give some better guidance here.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 8.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | low |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Confusing error when hs-boot abstract data implemented using synonym","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.1","keywords":["hs-boot"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"This example is a little goofy (that's why I've marked it low priority), but here goes:\r\n\r\n{{{\r\n-- A.hs-boot\r\nmodule A where\r\ndata T\r\nf :: T -> T\r\n\r\n-- B.hs\r\nmodule B(f) where\r\nimport {-# SOURCE #-} A\r\n\r\n-- A.hs\r\nmodule A(T, f) where\r\n import qualified B\r\n type T = Int\r\n f :: T -> T\r\n f x = B.f x\r\n}}}\r\n\r\nWhen compiled, we get a very interesting error:\r\n\r\n{{{\r\nezyang@sabre:~$ ghc-head --make A.hs -fforce-recomp\r\n[1 of 3] Compiling A[boot] ( A.hs-boot, A.o-boot )\r\n[2 of 3] Compiling B ( B.hs, B.o )\r\n[3 of 3] Compiling A ( A.hs, A.o )\r\n\r\nA.hs-boot:2:1: error:\r\n Type constructor ‘T’ has conflicting definitions in the module\r\n and its hs-boot file\r\n Main module: type T = Int\r\n Boot file: abstract T\r\n |\r\n2 | data T\r\n | ^^^^^^\r\n\r\nA.hs-boot:3:1: error:\r\n Identifier ‘f’ has conflicting definitions in the module\r\n and its hs-boot file\r\n Main module: f :: T -> T\r\n Boot file: f :: T -> T\r\n The two types are different\r\n |\r\n3 | f :: T -> T\r\n | ^^^^^^^^^^^\r\n}}}\r\n\r\nThe first error is legitimate, but the second is puzzling. I believe the problem has to do with the fact that when we load the hs-boot file for checking, we knot-tie it against itself. Thus, the T referenced in \"Boot file\" is the one WITHOUT the type synonym unfolding, while the main module *does* have the type synonym unfolding.\r\n\r\nPretty-printing is horribly confusing in these situations, so it would be nice if we could give some better guidance here.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13179Levity-polymorphic data types2022-08-16T23:24:01ZIcelandjackLevity-polymorphic data typesI don't know if this belongs as a part of [levity-polymorphic type classes](https://github.com/ghc-proposals/ghc-proposals/pull/30) (#12708) but many data types can be made levity-polymorphic, some have just been added to base:
```hs
--...I don't know if this belongs as a part of [levity-polymorphic type classes](https://github.com/ghc-proposals/ghc-proposals/pull/30) (#12708) but many data types can be made levity-polymorphic, some have just been added to base:
```hs
-- Product Array# Array# :: Type -> Type
data Product :: forall rep. (k -> TYPE rep) -> (k -> TYPE rep) -> (k -> Type) where
Pair :: f a -> g a -> (Product f g) a
-- Sum Array# Array# :: Type -> Type
data Sum :: forall rep. (k -> TYPE rep) -> (k -> TYPE rep) -> (k -> Type) where
InL :: f a -> (Sum f g) a
InR :: g a -> (Sum f g) a
-- Compose Array# [] :: Type -> Type
data Compose :: forall rep. (b -> TYPE rep) -> (a -> b) -> (a -> Type) where
Compose :: f (g a) -> (Compose f g) a
```
Can you think of other examples?https://gitlab.haskell.org/ghc/ghc/-/issues/13177Give Data.Functor.* its lifted void and unit2019-07-07T18:23:19ZIcelandjackGive Data.Functor.* its lifted void and unit`GHC.Generics` has
```hs
data V1 a
data U1 a = U1
```
They are simple but why are they not present in the `Data.Functor` hierarchy along with functions like (from [one-liner](https://hackage.haskell.org/package/one-liner-0.7/docs/src/G...`GHC.Generics` has
```hs
data V1 a
data U1 a = U1
```
They are simple but why are they not present in the `Data.Functor` hierarchy along with functions like (from [one-liner](https://hackage.haskell.org/package/one-liner-0.7/docs/src/Generics-OneLiner-Internal.html))
```hs
absurd :: V1 a -> b
absurd = \case
```
The package [linear](https://hackage.haskell.org/package/linear) provides the lifted unit functor
```hs
data V0 a = V0
```
if they or those from `GHC.Generics` should be preferred it could be added to the documentationhttps://gitlab.haskell.org/ghc/ghc/-/issues/13176Deprecate the realWorld#2020-01-23T19:32:33ZDavid FeuerDeprecate the realWorld#There's some messy code about that's intended to prevent problems with the real world. What if we deprecate `realWorld#`? People will still be able to shoot themselves in the foot by *defining* `realWorld#` in terms of `runRW#`, but a wa...There's some messy code about that's intended to prevent problems with the real world. What if we deprecate `realWorld#`? People will still be able to shoot themselves in the foot by *defining* `realWorld#` in terms of `runRW#`, but a warning in the documentation should hopefully be sufficient to prevent that.
Another, considerably more invasive, option might be to use something like
```hs
runST# :: (forall s . State# s -> o) -> o
data RealWorld :: * -> *
runIO# :: (forall i . State# (RealWorld i) -> o) -> o
```
This would (I believe) provide a much stronger guarantee that the real world can't escape. But it would probably break considerably more code, so I doubt it would be worth the trouble.https://gitlab.haskell.org/ghc/ghc/-/issues/13169Documentation for CoreMonad.getAnnotations2022-02-22T15:13:24ZabakstDocumentation for CoreMonad.getAnnotationsThe documentation for `getAnnotations` in `CoreMonad` is a bit unclear. In particular, the documentation could be improved by indicating that the returned `UniqFM` is keyed off of the `Unique` corresponding to an `AnnTarget`: That is, to...The documentation for `getAnnotations` in `CoreMonad` is a bit unclear. In particular, the documentation could be improved by indicating that the returned `UniqFM` is keyed off of the `Unique` corresponding to an `AnnTarget`: That is, to look up the annotations on `x`, it seems one should call `getAnnotations` on either `ModuleTarget x` or `NamedTarget x` (if my understanding of how this all works is correct, that is).
I stumbled across this by trying to look up the annotations on module `m` using the key `getUnique m`. This was incorrect as the annotation is stored on a unique \*derived\* from `getUnique m` (which wasn't indicated in the documentation).
Thanks!
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------- |
| Version | 7.10.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Documentation |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Documentation for CoreMonad.getAnnotations","status":"New","operating_system":"","component":"Documentation","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The documentation for `getAnnotations` in `CoreMonad` is a bit unclear. In particular, the documentation could be improved by indicating that the returned `UniqFM` is keyed off of the `Unique` corresponding to an `AnnTarget`: That is, to look up the annotations on `x`, it seems one should call `getAnnotations` on either `ModuleTarget x` or `NamedTarget x` (if my understanding of how this all works is correct, that is). \r\n\r\nI stumbled across this by trying to look up the annotations on module `m` using the key `getUnique m`. This was incorrect as the annotation is stored on a unique *derived* from `getUnique m` (which wasn't indicated in the documentation).\r\n\r\nThanks!","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13165Speed up the RTS hash table2020-12-21T04:09:30ZdobenourSpeed up the RTS hash tableThe RTS hash table is rather slow. Every lookup involves at least one indirect call (to get a hash code). It also uses separate chaining, which is itself slow.
Until recently, this didn't really matter, since the RTS hash table wasn't u...The RTS hash table is rather slow. Every lookup involves at least one indirect call (to get a hash code). It also uses separate chaining, which is itself slow.
Until recently, this didn't really matter, since the RTS hash table wasn't used for anything particularly performance critical other than `StableName` operations. However, it has since become the bottleneck when compacting with sharing, to the point that compacting without sharing is around 10x faster and is thus the default.
Fortunately, there are easy ways to make the hash table faster. These include:
- Use linear probing instead of separate chaining.
- Specialize for the case of pointer keys
- Don't use indirect calls for hashing
- Use a fast, universal hash function for pointers.
- Use SSE instructions where available to do fast searches.
- Minimize the number of indirections in the use of the table.
In both the case of the StablePtr table and that of compact regions, the keys of the table are not GC pointers, but the values are, so there needs to be a way to ensure that the GC handles the table correctly8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/13164idle time full GCs (idle cpu usage)2019-11-28T09:39:08Zlspitzneridle time full GCs (idle cpu usage)In an interactive program I noticed idle CPU usage of \~12% due to the full GCs done by the RTS on default settings. For this specific usecase this is a lot of wasted CPU cycles for no gain. Passing `-I0` to the RTS "fixes" this; nonethe...In an interactive program I noticed idle CPU usage of \~12% due to the full GCs done by the RTS on default settings. For this specific usecase this is a lot of wasted CPU cycles for no gain. Passing `-I0` to the RTS "fixes" this; nonetheless I think that the default behaviour could/should be improved, even when considering other usecases where full GCs are a good choice.
The program in question keeps \~50MB allocated on the heap but does close to no short-lived allocations in between the idle GCs. Some relevant data from the summary:
```
930,569,008 bytes allocated in the heap
4,847,446,928 bytes copied during GC
46,255,056 bytes maximum residency (111 sample(s))
378,200 bytes maximum slop
94 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 1784 colls, 0 par 0.123s 0.100s 0.0001s 0.0006s
Gen 1 111 colls, 0 par 9.377s 9.418s 0.0848s 0.1099s
INIT time 0.000s ( 0.003s elapsed)
MUT time 2.250s ( 95.029s elapsed)
GC time 9.500s ( 9.518s elapsed)
RP time 0.000s ( 0.000s elapsed)
PROF time 0.000s ( 0.000s elapsed)
EXIT time 0.007s ( 0.008s elapsed)
Total time 11.760s (104.557s elapsed)
```
The detailed GC statistics of the idle GCs look like
```
Alloc Copied Live GC GC TOT TOT Page Flts
bytes bytes bytes user elap user elap
13304 45958728 46210536 0.070 0.068 0.920 1.550 0 0 (Gen: 1)
11568 45958720 46210536 0.100 0.102 1.043 2.584 0 0 (Gen: 1)
15432 45958720 46210536 0.103 0.105 1.167 3.588 0 0 (Gen: 1)
11568 45958720 46210536 0.100 0.102 1.287 4.586 0 0 (Gen: 1)
11568 45958720 46210536 0.107 0.107 1.413 5.592 0 0 (Gen: 1)
11568 45958720 46210536 0.073 0.080 1.503 6.566 0 0 (Gen: 1)
11568 45958720 46210536 0.073 0.073 1.593 7.560 0 0 (Gen: 1)
11568 45958720 46210536 0.067 0.068 1.677 8.557 0 0 (Gen: 1)
```
I don't really know what exactly "alloc bytes" means, but my guess is that those numbers are indeed fairly low and those GCs are mostly useless.
To clarify the intention of this request: **Tweak the idle GC (default) configuration in some way so that interactive programs with moderate heap use reasonable amount of CPU time while idle.**
And "reasonable" is intentionally vague as I don't know how to weight other usecases.
Minimal example:
```
import Control.Concurrent
main :: IO ()
main = do
let large = [1..1000000]
print $ length large
[1..20] `forM_` \_ -> do
threadDelay 400000
print $ sum large
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.0.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonmar |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"idle time full GCs (idle cpu usage)","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":["GC","idle"],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"FeatureRequest","description":"In an interactive program I noticed idle CPU usage of ~12% due to the full GCs done by the RTS on default settings. For this specific usecase this is a lot of wasted CPU cycles for no gain. Passing {{{-I0}}} to the RTS \"fixes\" this; nonetheless I think that the default behaviour could/should be improved, even when considering other usecases where full GCs are a good choice.\r\n\r\nThe program in question keeps ~50MB allocated on the heap but does close to no short-lived allocations in between the idle GCs. Some relevant data from the summary:\r\n{{{\r\n 930,569,008 bytes allocated in the heap\r\n 4,847,446,928 bytes copied during GC\r\n 46,255,056 bytes maximum residency (111 sample(s))\r\n 378,200 bytes maximum slop\r\n 94 MB total memory in use (0 MB lost due to fragmentation)\r\n\r\n Tot time (elapsed) Avg pause Max pause\r\n Gen 0 1784 colls, 0 par 0.123s 0.100s 0.0001s 0.0006s\r\n Gen 1 111 colls, 0 par 9.377s 9.418s 0.0848s 0.1099s\r\n\r\n INIT time 0.000s ( 0.003s elapsed)\r\n MUT time 2.250s ( 95.029s elapsed)\r\n GC time 9.500s ( 9.518s elapsed)\r\n RP time 0.000s ( 0.000s elapsed)\r\n PROF time 0.000s ( 0.000s elapsed)\r\n EXIT time 0.007s ( 0.008s elapsed)\r\n Total time 11.760s (104.557s elapsed)\r\n}}}\r\n\r\nThe detailed GC statistics of the idle GCs look like\r\n{{{\r\n Alloc Copied Live GC GC TOT TOT Page Flts\r\n bytes bytes bytes user elap user elap\r\n 13304 45958728 46210536 0.070 0.068 0.920 1.550 0 0 (Gen: 1)\r\n 11568 45958720 46210536 0.100 0.102 1.043 2.584 0 0 (Gen: 1)\r\n 15432 45958720 46210536 0.103 0.105 1.167 3.588 0 0 (Gen: 1)\r\n 11568 45958720 46210536 0.100 0.102 1.287 4.586 0 0 (Gen: 1)\r\n 11568 45958720 46210536 0.107 0.107 1.413 5.592 0 0 (Gen: 1)\r\n 11568 45958720 46210536 0.073 0.080 1.503 6.566 0 0 (Gen: 1)\r\n 11568 45958720 46210536 0.073 0.073 1.593 7.560 0 0 (Gen: 1)\r\n 11568 45958720 46210536 0.067 0.068 1.677 8.557 0 0 (Gen: 1)\r\n}}}\r\n\r\nI don't really know what exactly \"alloc bytes\" means, but my guess is that those numbers are indeed fairly low and those GCs are mostly useless.\r\n\r\n\r\nTo clarify the intention of this request: '''Tweak the idle GC (default) configuration in some way so that interactive programs with moderate heap use reasonable amount of CPU time while idle.'''\r\n\r\nAnd \"reasonable\" is intentionally vague as I don't know how to weight other usecases.\r\n\r\nMinimal example:\r\n{{{\r\nimport Control.Concurrent\r\n\r\nmain :: IO ()\r\nmain = do\r\n let large = [1..1000000]\r\n print $ length large\r\n [1..20] `forM_` \\_ -> do\r\n threadDelay 400000\r\n print $ sum large\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13153Several Traversable instances have an extra fmap2020-10-21T22:32:54ZDavid FeuerSeveral Traversable instances have an extra fmapFor example, we define
```hs
instance Traversable ZipList where
traverse f (ZipList xs) = ZipList <$> traverse f xs
```
If the list is very short, the extra `fmap` could be bad. We can fix this by inlining the inner `traverse`. Howev...For example, we define
```hs
instance Traversable ZipList where
traverse f (ZipList xs) = ZipList <$> traverse f xs
```
If the list is very short, the extra `fmap` could be bad. We can fix this by inlining the inner `traverse`. However, I suspect a better approach would be to add a method to `Traversable`:
```hs
mapTraverse :: Applicative f
=> (t b -> r) -> (a -> f b) -> t a -> f r
mapTraverse p f xs = p <$> traverse f xs
```
but I need to work through whether this is enough power to solve enough problems.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Core Libraries |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | ekmett |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Several Traversable instances have an extra fmap","status":"New","operating_system":"","component":"Core Libraries","related":[],"milestone":"8.4.1","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"dfeuer"},"version":"8.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["ekmett"],"type":"Bug","description":"For example, we define\r\n\r\n{{{#!hs\r\ninstance Traversable ZipList where\r\n traverse f (ZipList xs) = ZipList <$> traverse f xs\r\n}}}\r\n\r\nIf the list is very short, the extra `fmap` could be bad. We can fix this by inlining the inner `traverse`. However, I suspect a better approach would be to add a method to `Traversable`:\r\n\r\n{{{#!hs\r\nmapTraverse :: Applicative f\r\n => (t b -> r) -> (a -> f b) -> t a -> f r\r\nmapTraverse p f xs = p <$> traverse f xs\r\n}}}\r\n\r\nbut I need to work through whether this is enough power to solve enough problems.","type_of_failure":"OtherFailure","blocking":[]} -->David FeuerDavid Feuerhttps://gitlab.haskell.org/ghc/ghc/-/issues/13152Provide a mechanism to notify build system when .hi file is ready2021-02-25T21:48:47ZrwbartonProvide a mechanism to notify build system when .hi file is readyIn one-shot mode GHC typically finishes writing the interface file around halfway through compilation. A dependent module (if it doesn't use Template Haskell) only needs the interface file to start building. If we could start building a ...In one-shot mode GHC typically finishes writing the interface file around halfway through compilation. A dependent module (if it doesn't use Template Haskell) only needs the interface file to start building. If we could start building a module as soon as all its dependencies' interface files are ready, we would cut the critical path by about a factor of 2; and parallelism in the GHC build tree is currently low enough that this should give significantly lower build times even on only modestly parallel systems.
The first obstruction to doing this is that there isn't a good way to know when the interface file becomes ready. I propose the following simple and flexible mechanism:
- Add a GHC command-line argument `-finterface-file-finished=N,F,str`. When GHC has finished writing the interface file it uses the `send` system call to send the string `str` to file descriptor `N` using flags `F`.
The build system might then invoke GHC with file descriptor `N` open to a UNIX datagram socket, for example, and generate a unique `str` for each interface file dependency.
Alternative suggestions are more than welcome.
I tentatively milestoned this for 8.2 since it would be nice to have this available in the bootstrapping compiler when we switch to Hadrian, and the GHC-side implementation should be simple.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------------- |
| Version | 8.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Driver |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | niteria, simonmar, thomie |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Provide a mechanism to notify build system when .hi file is ready","status":"New","operating_system":"","component":"Driver","related":[],"milestone":"8.2.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["niteria","simonmar","thomie"],"type":"FeatureRequest","description":"In one-shot mode GHC typically finishes writing the interface file around halfway through compilation. A dependent module (if it doesn't use Template Haskell) only needs the interface file to start building. If we could start building a module as soon as all its dependencies' interface files are ready, we would cut the critical path by about a factor of 2; and parallelism in the GHC build tree is currently low enough that this should give significantly lower build times even on only modestly parallel systems.\r\n\r\nThe first obstruction to doing this is that there isn't a good way to know when the interface file becomes ready. I propose the following simple and flexible mechanism:\r\n\r\n* Add a GHC command-line argument `-finterface-file-finished=N,F,str`. When GHC has finished writing the interface file it uses the `send` system call to send the string `str` to file descriptor `N` using flags `F`.\r\n\r\nThe build system might then invoke GHC with file descriptor `N` open to a UNIX datagram socket, for example, and generate a unique `str` for each interface file dependency.\r\n\r\nAlternative suggestions are more than welcome.\r\n\r\nI tentatively milestoned this for 8.2 since it would be nice to have this available in the bootstrapping compiler when we switch to Hadrian, and the GHC-side implementation should be simple.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13151Make all never-exported IfaceDecls implicit2019-09-25T15:46:18ZEdward Z. YangMake all never-exported IfaceDecls implicitConsider the representation of an instance in an interface file. It is always associated with a DFun, but the DFun is stored as a separate IfaceDecl.
You might wonder if it's possible for an IfaceClsInst to refer to an externally define...Consider the representation of an instance in an interface file. It is always associated with a DFun, but the DFun is stored as a separate IfaceDecl.
You might wonder if it's possible for an IfaceClsInst to refer to an externally defined DFun, or if it's possible to have a DFun but no IfaceClsInst associated with it. The current ClsInst representation won't tell you, but in fact, it's impossible. For example, DFuns are manually added to the type environment by TidyPgm, which literally goes through the list of ClsInsts to pull out the set of DFunIds which need to be added to the TypeEnv.
This all seems horribly indirect. Why not just \*embed\* the IfaceDecl describing the DFun inside IfaceClsInst, and treat the DFun as an "implicit TyThing"? This makes it clear that the instance declaration canonically defines the DFun.
To do this, we have to expand our idea of implicit TyThings; at the moment, only a TyThing can be associated with implicit TyThings. With this change, instances and family instances can also be associated with implicit TyThings. But this doesn't seem like too much.
Why does this matter? I was cleaning up some code in Backpack, and I noticed that I had written some very complicated things to handle DFuns and coercion axioms, because they were indirected through a Name, even though morally they should have been "implicit"-like things. The proposed refactor here would solve this correctness problem.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 8.1 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonpj |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Make all never-exported IfaceDecls implicit","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"ezyang"},"version":"8.1","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":["simonpj"],"type":"Task","description":"Consider the representation of an instance in an interface file. It is always associated with a DFun, but the DFun is stored as a separate IfaceDecl.\r\n\r\nYou might wonder if it's possible for an IfaceClsInst to refer to an externally defined DFun, or if it's possible to have a DFun but no IfaceClsInst associated with it. The current ClsInst representation won't tell you, but in fact, it's impossible. For example, DFuns are manually added to the type environment by TidyPgm, which literally goes through the list of ClsInsts to pull out the set of DFunIds which need to be added to the TypeEnv.\r\n\r\nThis all seems horribly indirect. Why not just *embed* the IfaceDecl describing the DFun inside IfaceClsInst, and treat the DFun as an \"implicit TyThing\"? This makes it clear that the instance declaration canonically defines the DFun.\r\n\r\nTo do this, we have to expand our idea of implicit TyThings; at the moment, only a TyThing can be associated with implicit TyThings. With this change, instances and family instances can also be associated with implicit TyThings. But this doesn't seem like too much.\r\n\r\nWhy does this matter? I was cleaning up some code in Backpack, and I noticed that I had written some very complicated things to handle DFuns and coercion axioms, because they were indirected through a Name, even though morally they should have been \"implicit\"-like things. The proposed refactor here would solve this correctness problem.","type_of_failure":"OtherFailure","blocking":[]} -->Edward Z. YangEdward Z. Yanghttps://gitlab.haskell.org/ghc/ghc/-/issues/13149Giving Backpack a Promotion2019-11-27T16:57:26ZEdward Z. YangGiving Backpack a PromotionThis ticket is tracking assumptions the current implementation of Backpack makes about terms and types, which may be violated when more and more term-level things start being lifted into the type level. I don't expect any work to be done...This ticket is tracking assumptions the current implementation of Backpack makes about terms and types, which may be violated when more and more term-level things start being lifted into the type level. I don't expect any work to be done on this in the near future, but I'd like to keep track of these breadcrumbs.
- We currently assume that it is impossible for a typechecked-only module (that is, one with no Core unfoldings) to refer to a DFun or a coercion axiom. In the absence of promotion, I'm pretty sure this is the case, since there is no way to refer to a term from a type (DFun), and coercions do not ordinarily occur at the type level.
With promotion, this is not true:
```
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TypeInType #-}
unit p where
signature A where
import GHC.Types
type family F a where
F Bool = Type
module B where
import A
foo :: forall (a :: F Bool). a -> a
foo x = x
unit q where
dependency p[A=<A>]
module C where
import B
```
> This will fail in a puzzling way:
```
<no location info>: error:
The identifier D:R:F does not exist in the signature for <A>
(Try adding it to the export list in that hsig file.)
```
- (Put more problems here)Research neededhttps://gitlab.haskell.org/ghc/ghc/-/issues/13148Adding weak pointers to non-mutable unboxed values segfaults2019-07-07T18:23:27ZMathieu BoespflugAdding weak pointers to non-mutable unboxed values segfaultsConsider the following program:
```hs
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
module Main where
import Foreign
import GHC.Base
import GHC.IORef
import GHC.Ptr
import GHC.STRef
import System.Mem
main = do
p@(Ptr ...Consider the following program:
```hs
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
module Main where
import Foreign
import GHC.Base
import GHC.IORef
import GHC.Ptr
import GHC.STRef
import System.Mem
main = do
p@(Ptr p#) <- mallocBytes 10
r@(IORef (STRef r#)) <- newIORef True
IO $ \s -> case mkWeakNoFinalizer# r# () s of (# s1, w #) -> (# s1, () #)
performGC
```
This program works fine. But if I `mkWeakNoFinalizer#` to `#p` instead of `#r` then it **segfaults**. That is, I can attach a weak pointer to a `MutVar#`, as well as to a `MVar#`, but not any other unboxed type, including pointer addresses.
The documentation says "Finalizers *can* be used reliably for types that are created explicitly and have identity, such as IORef and MVar". But a) I don't know that "types that have identity" is defined anywhere, b) this doesn't say that weak pointers *cannot* be used for anything else.
Should I be able to create weak pointers to any unboxed value? If not, I guess this is mostly a documentation bug.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | facundominguez |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Adding weak pointers to non-mutable unboxed values segfaults","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["facundominguez"],"type":"Bug","description":"Consider the following program:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE MagicHash #-}\r\n{-# LANGUAGE UnboxedTuples #-}\r\n\r\nmodule Main where\r\n\r\nimport Foreign\r\nimport GHC.Base\r\nimport GHC.IORef\r\nimport GHC.Ptr\r\nimport GHC.STRef\r\nimport System.Mem\r\n\r\nmain = do\r\n p@(Ptr p#) <- mallocBytes 10\r\n r@(IORef (STRef r#)) <- newIORef True\r\n IO $ \\s -> case mkWeakNoFinalizer# r# () s of (# s1, w #) -> (# s1, () #)\r\n performGC\r\n}}}\r\n\r\nThis program works fine. But if I `mkWeakNoFinalizer#` to `#p` instead of `#r` then it '''segfaults'''. That is, I can attach a weak pointer to a `MutVar#`, as well as to a `MVar#`, but not any other unboxed type, including pointer addresses.\r\n\r\nThe documentation says \"Finalizers ''can'' be used reliably for types that are created explicitly and have identity, such as IORef and MVar\". But a) I don't know that \"types that have identity\" is defined anywhere, b) this doesn't say that weak pointers ''cannot'' be used for anything else.\r\n\r\nShould I be able to create weak pointers to any unboxed value? If not, I guess this is mostly a documentation bug.","type_of_failure":"OtherFailure","blocking":[]} -->