GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2022-11-01T08:49:22Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/22384Visible type application in record patterns2022-11-01T08:49:22ZTarmeanVisible type application in record patterns## Motivation
I've been using type applications in patterns quite a bit recently and struggled when adding or removing an argument from the constructors because all pattern matches must add/remove wildcards.
```haskell
lookupQMap :: fo...## Motivation
I've been using type applications in patterns quite a bit recently and struggled when adding or removing an argument from the constructors because all pattern matches must add/remove wildcards.
```haskell
lookupQMap :: forall a. Typeable a => QKey a -> QMap -> Maybe a
lookupQMap qid qmap =
-- This could use a Data.Typeable.cast, but it's simplified from some more complex code
case lookupQ qid qmap of
ResultEntry @r' dat _
| Just Refl <- eqT @r @r' -> ...
```
The nice way to avoid the problem would be to use record patterns. But mixing type applications with record patterns results in a parse error!
```haskell
case lookupQ qid qmap of
ResultEntry @r {resultData=dat}
-- [parser] [E] parser error on input '{'
```
I'm not sure if this is intentional, an oversight, or whether I'm missing the right syntax. It'd be really useful, though!
## Proposal
If the missing syntax is an oversight it hopefully could be added without making the grammar overly ambiguous. I do not know whether this would require a separate proposal.
If the feature already exists or is intentionally missing it maybe could be documented somewhere, though I'm not sure what the right place would be. I couldn't find a mention in the proposal or paper at least.https://gitlab.haskell.org/ghc/ghc/-/issues/22382Improve Error message when field is missing on actual Haskell record2023-06-23T12:28:19ZMagnus ViernickelImprove Error message when field is missing on actual Haskell record<!--
READ THIS FIRST: If the feature you are proposing changes the language that GHC accepts
or adds any warnings to `-Wall`, it should be written as a [GHC Proposal](https://github.com/ghc-proposals/ghc-proposals/).
Other features, appr...<!--
READ THIS FIRST: If the feature you are proposing changes the language that GHC accepts
or adds any warnings to `-Wall`, it should be written as a [GHC Proposal](https://github.com/ghc-proposals/ghc-proposals/).
Other features, appropriate for a GitLab feature request, include GHC API/plugin
innovations, new low-impact compiler flags, or other similar additions to GHC.
-->
## Motivation
When having `-XOverloadedRecordDots` on and writing the following code
```haskell
data R = MkR
{ ri :: Int
, rs :: String
}
x :: R -> Bool
x r = r.rb
```
I get the following error message
```
• No instance for (GHC.Records.HasField "rb" R Bool)
arising from selecting the field ‘rb’
• In the expression: r.rb
In an equation for ‘x’: x r = r.rb
|
97 | x r = r.rb
| ^^^^
```
which is arguably too confusing if you just want to use this extension for allowing the record dot syntax.
## Proposal
As this is a Haskell record the error message could just have been "The Haskell record `R` does not have the field `rb`" which is in my opinion easier to decipher for users who don't want to use the actual overloading of the record dot. As it's possible to also declare `HasField` instances for some specific field name (`HasField "rb" R Bool`) it would probably be good to nevertheless include a NB that this error results from a missing `HasField` instance.
I would like to implement this my own, if this was accepted, but I'm new so guidance would be appreciated :smile:
Thanks in advance!https://gitlab.haskell.org/ghc/ghc/-/issues/22250stimesDefault, stimesIdempotent etc throw exception on Integral types without...2023-03-15T20:15:31ZOleg GrenrusstimesDefault, stimesIdempotent etc throw exception on Integral types without a zero.For example
```haskell
data BinP -- also called Pos
= BE
| B0 BinP
| B1 BinP
```
like in [`bin`](https://hackage.haskell.org/package/bin) package or just
```haskell
newtype Natural1 = N1 Natural
instance Integral N1 where...For example
```haskell
data BinP -- also called Pos
= BE
| B0 BinP
| B1 BinP
```
like in [`bin`](https://hackage.haskell.org/package/bin) package or just
```haskell
newtype Natural1 = N1 Natural
instance Integral N1 where
toInteger (N1 n) = 1 + toInteger n
```
With these
```
*Data.Bin Data.Semigroup> stimes (1 :: Integer) "foo"
"foo"
*Data.Bin Data.Semigroup> stimes (2 :: Integer) "foo"
"foofoo"
*Data.Bin Data.Semigroup> stimes (3 :: Integer) "foo"
"foofoofoo"
*Data.Bin Data.Semigroup> stimes (1 :: BinP) "foo"
"*** Exception: arithmetic underflow
*Data.Bin Data.Semigroup> stimes (2 :: BinP) "foo"
"*** Exception: arithmetic underflow
*Data.Bin Data.Semigroup> stimes (3 :: BinP) "foo"
"*** Exception: arithmetic underflow
```
The `stimesDefault` is defined as
```haskell
stimesDefault :: (Integral b, Semigroup a) => b -> a -> a
stimesDefault y0 x0
| y0 <= 0 = errorWithoutStackTrace "stimes: positive multiplier expected"
| otherwise = f x0 y0 where f ...
```
but I think it can be as well defined as
```haskell
stimesDefault :: (Integral b, Semigroup a) => b -> a -> a
stimesDefault y0 x0
| y0 >= 1 = f x0 y0 where ...
| otherwise = errorWithoutStackTrace "stimes: positive multiplier expected"
```
and similarly for `stimesIdempotent`
Fixing `mtimesDefault` would be trickier as it is defined as
```haskell
stimesIdempotentMonoid :: (Integral b, Monoid a) => b -> a -> a
stimesIdempotentMonoid n x = case compare n 0 of
LT -> errorWithoutStackTrace "stimesIdempotentMonoid: negative multiplier"
EQ -> mempty
GT -> x
```
and using `compare` is probably very welcome, although for types people care about, like `Int` or `Integer`, or even `BinP` or `Natural/1`, having `n >= 1` first case is probably a win.https://gitlab.haskell.org/ghc/ghc/-/issues/22249Empty array primitives2023-03-10T15:58:53ZkonsumlammEmpty array primitives## Motivation
Currently, there is no way to create an empty array without a value of the element type, since the only primitive to create a new array is `newArray#`, which requires an element. For lifted element types, this is no proble...## Motivation
Currently, there is no way to create an empty array without a value of the element type, since the only primitive to create a new array is `newArray#`, which requires an element. For lifted element types, this is no problem, since you can use a bottom as a dummy element, but that doesn't work for unlifted types.
## Proposal
I propose adding two new primitives:
```hs
emptyArray# :: forall {l :: Levity} (a :: TYPE (BoxedRep l)). Array# a
emptSmallyArray# :: forall {l :: Levity} (a :: TYPE (BoxedRep l)). SmallArray# a
```
This should be enough, since you can also use them to create empty mutable arrays (by using `thawArray#`/`thawSmallArray#`). One could also go the other way round, adding primitives to create mutable empty arrays instead, but I'd argue that empty immutable arrays are more common (e.g. `primitive` has [`emptyArray`](https://hackage.haskell.org/package/primitive-0.7.4.0/docs/src/Data.Primitive.Array.html#emptyArray), but no `emptyMutableArray`). It might still be beneficial to additionally add primitives for empty mutable arrays though.Andreas KlebingerAndreas Klebingerhttps://gitlab.haskell.org/ghc/ghc/-/issues/22205Can't build GHC: missing or private dependencies2022-10-01T11:45:25ZRichard Eisenbergrae@richarde.devCan't build GHC: missing or private dependenciesStill can't build GHC:
```
rae:23:08:59 ~/ghc/ghc-spj> hadrun
--build-root=_build --flavour=default -j9 --flavour=devel2 --docs=none
Up to date
| Configure package 'unix'
| Configure package 'integer-gmp'
| Configure package 'text'
| Co...Still can't build GHC:
```
rae:23:08:59 ~/ghc/ghc-spj> hadrun
--build-root=_build --flavour=default -j9 --flavour=devel2 --docs=none
Up to date
| Configure package 'unix'
| Configure package 'integer-gmp'
| Configure package 'text'
| Configure package 'ghc-heap'
| Configure package 'ghc-compact'
| Configure package 'pretty'
| Configure package 'ghc-boot'
| Configure package 'directory'
| Configure package 'process'
| Configure package 'hpc'
| Configure package 'Cabal'
| Configure package 'base'
| Configure package 'binary'
| Configure package 'Cabal-syntax'
| Configure package 'ghci'
| Configure package 'array'
| Configure package 'unix'
| Configure package 'transformers'
| Configure package 'template-haskell'
| Configure package 'bytestring'
| Configure package 'Cabal-syntax'
| Configure package 'time'
| Configure package 'hpc'
| Configure package 'directory'
| Configure package 'ghc-prim'
| Configure package 'exceptions'
| Configure package 'haskeline'
| Configure package 'deepseq'
| Configure package 'terminfo'
| Configure package 'xhtml'
| Configure package 'rts'
| Configure package 'parsec'
| Configure package 'ghc-boot-th'
| Configure package 'ghc-boot'
| Configure package 'containers'
| Configure package 'stm'
| Configure package 'Cabal'
| Configure package 'libiserv'
| Configure package 'mtl'
| Configure package 'ghc-bignum'
| Configure package 'parsec'
| Configure package 'text'
| Configure package 'filepath'
| Configure package 'process'
| Configure package 'ghci'
| Configure package 'ghc'
| Configure package 'ghc'
| Copy package 'linters-common'
# cabal-copy (for _build/stageBoot/lib/package.conf.d/linters-common-0.1.0.0.conf)
# cabal-configure (for _build/stage0/libraries/unix/setup-config)
# cabal-configure (for _build/stage0/libraries/text/setup-config)
| Run Ghc FindHsDependencies (Stage0 InTreeLibs): libraries/binary/src/Data/Binary.hs (and 8 more) => _build/stage0/libraries/binary/.dependencies.mk
| Run GhcPkg Recache (Stage0 GlobalLibs): none => none
hadrian: Encountered missing or private dependencies:
base (>=4.9 && <5) && <0
ExitFailure 1
Build failed.
hadrian-util: Received ExitFailure 1 when running
Raw command: /Users/rae/ghc/ghc-spj/hadrian/build-cabal --build-root=_build --flavour=default -j9 --flavour=devel2 --docs=none
Run from: /Users/rae/ghc/ghc-spj
```
The `hadrun` at the top is an alias for Ben's hadrian-util script:
```
rae:23:09:02 ~/ghc/ghc-spj> alias hadrun
alias hadrun='hadrian-util run -j$THREADS --flavour=$GHC_FLAVOUR --docs=none'
```
where `$THREADS` is 9 and `$GHC_FLAVOUR` is `devel2`.
I'm on macOS 12.3.1 on an M1 Mac. My bootstrap GHC is 9.2.1, which is generally working for other projects.https://gitlab.haskell.org/ghc/ghc/-/issues/22145Allow promotion of one-to-one pattern synonyms2022-09-06T13:36:09ZOleg GrenrusAllow promotion of one-to-one pattern synonyms```haskell
{-# LANGUAGE PatternSynonyms, DataKinds #-}
import Data.Proxy
import Data.Kind
pattern JustJust :: a -> Maybe (Maybe a)
pattern JustJust x = Just (Just x)
p :: Proxy (JustJust Type)
p = Proxy
```
is rejected because of
``...```haskell
{-# LANGUAGE PatternSynonyms, DataKinds #-}
import Data.Proxy
import Data.Kind
pattern JustJust :: a -> Maybe (Maybe a)
pattern JustJust x = Just (Just x)
p :: Proxy (JustJust Type)
p = Proxy
```
is rejected because of
```
• Pattern synonym ‘JustJust’ cannot be used here
(pattern synonyms cannot be promoted)
```
but I don't see why not.
This issue allows to distinguish between pattern synonym and real constructor, e.g. a pattern synonym like
```haskell
pattern Some :: a -> Maybe a
pattern Some x = Just x
```
cannot be used to provide backwards compatibility when renaming constructors! (e.g. upcoming `Solo` to `MkSolo` is a real example).https://gitlab.haskell.org/ghc/ghc/-/issues/22104Error message UX around CUSKs and GHC20212023-08-09T18:16:25ZparsonsmattError message UX around CUSKs and GHC2021`GHC2021` does not enable `CUSKs`, like `Haskell2010` did, and so a common pattern of use will have a mysterious error message.
Consider the following module:
```haskell
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
module ...`GHC2021` does not enable `CUSKs`, like `Haskell2010` did, and so a common pattern of use will have a mysterious error message.
Consider the following module:
```haskell
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
module Main where
type family T (a :: k) :: k where
T Char = Int
T a = a
main = pure ()
```
With GHC 9.0, this compiles fine:
```
λ ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.0.1
λ ghc --make Main.hs
[1 of 1] Compiling Main ( Main.hs, Main.o )
Linking Main ...
```
If you upgrade to GHC 9.2, then this fails:
```
λ ghcup set ghc 9.2.4
[ Info ] GHC 9.2.4 successfully set as default version
λ ghc --make Main.hs
[1 of 1] Compiling Main ( Main.hs, Main.o )
Main.hs:8:5: error:
• Expected kind ‘k’, but ‘Char’ has kind ‘*’
• In the first argument of ‘T’, namely ‘Char’
In the type family declaration for ‘T’
|
8 | T Char = Int
| ^^^^
λ ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.2.4
```
The `cabal` file specifies `default-language: Haskell2010`, and so `cabal build` works, while `ghc --make` does not.
However, suppose a project switches from `Haskell2010` to `GHC2021`. They'll receive those confusing error messages. I was able to diagnose this by diffing the `cabal build --verbose` to get the `ghc` invocation from `cabal`, and noticed the `-XHaskell2010` flag passed in. I checked to see what that implied, and fortunately `CUSKs` was the first extension, which is the culprit.
I've never heard of `CUSKs`, since it's an implied feature in the language for the entire time that I've been using it. So I had no idea that I needed an extension at all to get this behavior.
Since `CUSKs` are on the Path to Deprecation and Removal, it'd be *great* if we could get an informative error message about the situation.
```
λ ghc --make Main.hs
[1 of 2] Compiling Main ( Main.hs, Main.o )
Main.hs:8:5: error:
• Expected kind ‘k’, but ‘Char’ has kind ‘*’
• In the first argument of ‘T’, namely ‘Char’
In the type family declaration for ‘T’
• The language extension `CUSKs` may fix this behavior,
but it will soon been deprecated in favor of `StandaloneKingSignatures`.
|
8 | T Char = Int
| ^^^^
```sheafsam.derbyshire@gmail.comsheafsam.derbyshire@gmail.comhttps://gitlab.haskell.org/ghc/ghc/-/issues/22061Lessons to be learned from the paper: Investigating Magic Numbers: Improving ...2023-09-07T11:04:14ZAndreas KlebingerLessons to be learned from the paper: Investigating Magic Numbers: Improving the Inlining Heuristic in the Glasgow Haskell CompilerThe paper [Investigating Magic Numbers: Improving the Inlining Heuristic in the Glasgow Haskell Compiler](https://michel.steuwer.info/#publications) by Hollenbeck, O'Boyle, and Steuwer (Haskell Symposium 2022) applied search to the param...The paper [Investigating Magic Numbers: Improving the Inlining Heuristic in the Glasgow Haskell Compiler](https://michel.steuwer.info/#publications) by Hollenbeck, O'Boyle, and Steuwer (Haskell Symposium 2022) applied search to the parameter space of the inliner and seems to have found quite impressive improvements.
In particular the paper found a set of inlining magic numbers which achieves a 12% speedup over the defaults of ghc-8.10.3 for the testsuites of 10 particular packages.
To me the obvious questions not answered in the paper are:
* **Compile Times.** There is no mention of compile times at all in the paper. It's generally accepted among ghc devs that being more lenient with inlining would improve runtime performance at the cost of increased compile time. If we want to change the set of magic inlining numbers we need to characterize not just the runtime but also compile time differences and make a informed decision based on the full picture.
* **nofib vs package tests.** The paper heavily criticizes nofib on a number of points (some warranted, some not) and comes up with quite a clever alternative to benchmarking. I'm not sure if it's feasible to maintain a benchmark suite based on the principles in the paper for ghc.
It would be quite informative to compare the results between their benchmarking approach and nofib. At the very least this should give us a good idea how stable these results are between different ways of evaluation.
If nofib and these packages give use very different results the next question would be if this set of packages is more (or less) representative of typical haskell code. But that's a whole other question which isn't easy to answer at all.
* **Reproduction**. In general it would be good to try to reproduce their results at least on nofib with one or multiple recent versions of ghc. But reproducing their methodology with newer versions of GHC would also be nice. Things often change between versions and it would be interesting to see how stable these results are between ghc and maybe even package versions and if they are still as beneficial for 9.4/master.9.12.1Andreas KlebingerAndreas Klebingerhttps://gitlab.haskell.org/ghc/ghc/-/issues/21738template-haskell-2.19.0.0 depends on filepath2023-05-30T05:51:53ZOleg Grenrustemplate-haskell-2.19.0.0 depends on filepathWhich makes `filepath` non-upgradable package (as virtually everything depends on `template-haskell`).
This is a regression. Given that `template-haskell` needs only `</>` (though hard to tell, as an unqualified open import is used), I'...Which makes `filepath` non-upgradable package (as virtually everything depends on `template-haskell`).
This is a regression. Given that `template-haskell` needs only `</>` (though hard to tell, as an unqualified open import is used), I'd suggest to vendor it in `template-haskell` until the story about reinstalling `template-haskell` is proven to work.Matthew PickeringMatthew Pickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/21718README.md suggests building with make rather than Hadrian2022-07-01T16:32:07ZDavid Thrane ChristiansenREADME.md suggests building with make rather than Hadrian## Summary
Location of documentation issue: (e.g. the Haddocks of `base`, the GHC user's guide)
In README.md, the "quickstart" section
Write a brief description of the issue.
The list of quick start commands is `./boot`, `./configure...## Summary
Location of documentation issue: (e.g. the Haddocks of `base`, the GHC user's guide)
In README.md, the "quickstart" section
Write a brief description of the issue.
The list of quick start commands is `./boot`, `./configure`, and then `make` and `make install`.
## Proposed improvements or changes
I propose that it should be updated to suggest Hadrian instead.
## Environment
* GHC version used (if appropriate): The latest development versionhttps://gitlab.haskell.org/ghc/ghc/-/issues/21700On-demand linking when evaluating Template Haskell splices in packages with m...2023-05-26T12:52:42ZAlexis KingOn-demand linking when evaluating Template Haskell splices in packages with many dependencies is painfully slowWhen GHC expands Template Haskell splices, it necessarily must load the code those splices depend on. It has a few different strategies for doing this, depending on what is being loaded and how GHC is built, but the default strategy used...When GHC expands Template Haskell splices, it necessarily must load the code those splices depend on. It has a few different strategies for doing this, depending on what is being loaded and how GHC is built, but the default strategy used since #3658 (which landed all the way back in GHC 7.8) can sometimes be painfully slow. In particular, on the codebase I’ve recently been looking at, more than a third of the compilation time for some modules is spent running the system linker, individual invocations of which can take *multiple seconds* to return. (And this is using `gold`; plain `ld` is even worse.)
Why does this happen? The poor performance arises from the way GHC loads code for other modules in the same package when evaluating a splice. Loading code from other packages is easy: GHC just uses `dlopen` to load the appropriate dynamic library (i.e. the `.so` file on Linux). But when a splice depends on modules from the current package, this isn’t possible, since all we have are `.dyn_o` files. It isn’t possible to `dlopen` those directly, so GHC invokes the system linker to create a `.so` on demand that contains the set of `.dyn_o` files it needs.
Unfortunately, this strategy significantly degrades as the set of external package dependencies grows. When GHC invokes the system linker, it instructs it to link the resulting library against every package the module depends on, e.g. roughly
```
ld -shared -o /tmp/ghc_01.so \
Foo.dyn_o Bar.dyn_o \
-lHSbase-4.16.0.0 -lHStext-2.0 -lHScontainers-0.6.5.1 ...
```
and this can become glacially slow if the set of dependencies becomes sufficiently large. The particular codebase I’ve been looking at depends on a little over 400 Haskell packages, which is what leads to such miserable linking times.
---
This strategy of building a `.so` file on demand is appealing in its simplicity, as it allows GHC to dispense with most of its own machinery for linking and loading and just defer to system tools. Unfortunately, on a project with thousands of modules, many of which use Template Haskell, it results in unpalatably slow compilation times. Some modules even perform this process multiple times (since later splices in the same module require further modules to be loaded), which only compounds the problem. Reducing the number of times the linker needs to be invoked would be a good first step, but it’s hard to see how to make this process significantly faster without coming up with a more efficient strategy for loading the necessary code in the first place.
I am by no means an expert on linking, so I am not sure if there is some way GHC continue to use the system linker without triggering such poor performance. However, using the system linker necessarily means that many of the variables are outside of GHC’s control, so it might be worth pursuing a means to avoid using the linker in such scenarios altogether. To that end, it seems like #21067 could be related, though I haven’t investigated the status of that work in detail.
Regardless, the status quo is painful, so we ought to find something better.Matthew PickeringMatthew Pickeringhttps://gitlab.haskell.org/ghc/ghc/-/issues/21698Missing documentation for HieAST etc structures2023-07-06T12:52:53ZOleg GrenrusMissing documentation for HieAST etc structuresIs there some documentation of why `HieAST` structure looks like what it does. There is probably some logic (`Data` based?) on how its generated, but it doesn't make much sense by just reading haddocks.
- Why annotations is a Set, (whic...Is there some documentation of why `HieAST` structure looks like what it does. There is probably some logic (`Data` based?) on how its generated, but it doesn't make much sense by just reading haddocks.
- Why annotations is a Set, (which is mostly singleton, but sometimes empty, or actually containing multiple annotations)
- Why `HieFile` has a `Map HiePath (HieAST a)`, what are these paths? Can this map be empty?
- What is `NodeOrigin` for? Can node has both, either or **none** of `NodeInfo`. What is the difference?9.2.4ZubinZubinhttps://gitlab.haskell.org/ghc/ghc/-/issues/21630Draw breaking changes into separate section of release notes2022-08-04T20:55:53ZBen GamariDraw breaking changes into separate section of release notesTo make it easier for users to assess how a release affects them we should place breaking changes in their own section of the release notes.To make it easier for users to assess how a release affects them we should place breaking changes in their own section of the release notes.Ben GamariBen Gamarihttps://gitlab.haskell.org/ghc/ghc/-/issues/21590Record ABI hash/info for official bindists2023-02-13T17:13:49ZJulian OspaldRecord ABI hash/info for official bindistsGiven that there has been issues with the updated bindists for 9.0.2 (because of missing profiling libs) wrt ABI, I suggest to add a separate file that has explicit information about ABI for every bindist.
The format (as in: what consti...Given that there has been issues with the updated bindists for 9.0.2 (because of missing profiling libs) wrt ABI, I suggest to add a separate file that has explicit information about ABI for every bindist.
The format (as in: what constitutes the ABI hash) probably could be debated, an example is in the [HLS wrapper script](https://github.com/haskell/haskell-language-server/blob/eeb1d2057d595ab8a478c0b19904987a990365f1/bindist/wrapper.in#L76).
Even if there is no re-upload of bindists, this would allow to quickly check compatibility with other bindists without unpacking.https://gitlab.haskell.org/ghc/ghc/-/issues/21495Creating function pointers from closures results in setExecutable runtime err...2022-08-15T15:50:20ZKasper Dissing BargsteenCreating function pointers from closures results in setExecutable runtime error on macOS 12+## Summary
Running a *signed* binary on macOS 12+ that creates a `FunPtr` from a closure results in a runtime error that mentions `setExecutable`.
According to https://www.securemac.com/news/arm-macs-faq, this will also be a problem in...## Summary
Running a *signed* binary on macOS 12+ that creates a `FunPtr` from a closure results in a runtime error that mentions `setExecutable`.
According to https://www.securemac.com/news/arm-macs-faq, this will also be a problem in *unsigned* binaries when running on Apple Silicon(ARM).
## Steps to reproduce
1. Create two files, `Main.hs` and `bar.c`:
```haskell
-- Main.hs
module Main where
import Foreign.Ptr (FunPtr)
foreign import ccall "bar" bar :: Callback -> Int
main :: IO ()
main = do
cb <- createFooCallback (foo 2)
let res = bar cb
print res
type CallbackType = Int -> Int
type Callback = FunPtr CallbackType
foo :: Int -> Int -> Int
foo = (+)
foreign import ccall "wrapper" createFooCallback :: CallbackType -> IO Callback
```
```c
// bar.c
extern int (*fun_ptr)(int);
int bar(int (*f)(int)) {
return (*f)(3);
}
```
2. Compile them: `ghc --make -main-is Main Main.hs bar.c`
3. Sign the binary: `sudo codesign -f --options runtime -s DEVELOPER_ID Main`
- The program runs as expected if this step is omitted.
- This step requires a developer signing certificate.
4. Run the signed binary: `./Main`
## Expected behavior
Expected:
```
$ ./Main
5
```
Actual:
```
$ ./Main
Main: internal error: setExecutable: failed to protect 0x0x42001fc000
(GHC version 8.10.4 for x86_64_apple_darwin)
Please report this as a GHC bug: https://www.haskell.org/ghc/reportabug
fish: Job 1, './Main' terminated by signal SIGABRT (Abort)
```
## Extra notes
I believe https://gitlab.haskell.org/ghc/ghc/-/issues/18376 is the root cause, and I created this new issue to draw attention to a use-case that triggers the bug. Hoping that it might be fixed :-)
We managed to work around the issue by allowing unsigned executable memory when
signing:
https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-unsigned-executable-memory
However, that is not an ideal solution.
## Environment
* GHC version used: 8.10.4 and 8.10.7
Optional:
* Operating System: macOS 12.1
* System Architecture: Intel9.4.3Ben GamariBen Gamarihttps://gitlab.haskell.org/ghc/ghc/-/issues/21281Inlining forgets strictness properties with GHC 9.0.22022-04-10T14:36:43ZTeo CamarasuInlining forgets strictness properties with GHC 9.0.2## Summary
When updating a codebase to GHC 9.0.2, I noticed that some strictness tests were newly failing. I managed to reduce it to the following reproducer.
The Core produced by this program looks suspect. Inlining seems to lead to s...## Summary
When updating a codebase to GHC 9.0.2, I noticed that some strictness tests were newly failing. I managed to reduce it to the following reproducer.
The Core produced by this program looks suspect. Inlining seems to lead to strictness properties being ignored, which doesn't happen with GHC 8.10.7.
## Steps to reproduce
Take a look at the differences between the Core generated by GHC 8.10.7 and 9.0.2.
Unfortunately this reproducer depends on mtl and unordered-containers, but my feeling is that this can be reproduced without them.
I used: mtl-2.2.2 and unordered-containers-0.2.17.0 for GHC 9.0.2
```haskell
{-# LANGUAGE BangPatterns #-}
module Repro where
import Control.Monad.RWS.Strict
import qualified Data.HashMap.Strict as HM
data Box = Box !Int
addToList :: Box -> [Box] -> [Box]
addToList !b !bs = b : bs
trigger :: Int -> RWS Int () (HM.HashMap Int [Box]) ()
trigger !indx = do
v <- ask
let b = Box v
modify' $ HM.adjust (addToList b) indx
```
<p>
<details>
<summary>GHC-8.10.7(good)</summary>
<pre><code>
Repro.trigger1
= \ (w_s2R5 :: Int)
(w1_s2R6 :: Int)
(w2_s2R7 :: HM.HashMap Int [Box]) ->
case w_s2R5 of { GHC.Types.I# ww1_s2Ra ->
case Repro.$w$sadjust
@ [Box]
(\ (bs_a14k :: [Box]) ->
case w1_s2R6 of { GHC.Types.I# dt1_a18g ->
case bs_a14k of bs1_X14s { __DEFAULT ->
GHC.Types.: @ Box (Repro.Box dt1_a18g) bs1_X14s
}
})
ww1_s2Ra
w2_s2R7
of vx_a2rj
{ __DEFAULT ->
(GHC.Tuple.(), vx_a2rj, GHC.Tuple.())
`cast` (Sym (Data.Functor.Identity.N:Identity[0]
<((), HM.HashMap Int [Box], ())>_R)
:: ((), HM.HashMap Int [Box], ())
~R# Identity ((), HM.HashMap Int [Box], ()))
}
}
</code></pre>
</details>
</p>
<p>
<details>
<summary>GHC-9.0.2(bad)</summary>
<pre><code>
trigger1
= \ w_s2P9 w1_s2Pa w2_s2Pb ->
case w_s2P9 of { I# ww1_s2Pe ->
case $w$sadjust
(let {
b_s2py = case w1_s2Pa of { I# dt1_a18B -> Box dt1_a18B } } in -- LAZY!
\ bs_a14H ->
case w1_s2Pa of { I# dt1_a18B ->
case bs_a14H of bs1_X4 { __DEFAULT -> : b_s2py bs1_X4 }
})
ww1_s2Pe
w2_s2Pb
of vx_a2pR
{ __DEFAULT ->
((), vx_a2pR, ()) `cast` <Co:9>
}
}
</code></pre>
</details>
</p>
<p>
<details>
<summary>GHC-9.2.1(bad)</summary>
<pre><code>
Repro.trigger1
= \ (w_s1Wf :: Int)
(w1_s1Wg [OS=OneShot] :: Int)
(w2_s1Wh [OS=OneShot] :: HM.HashMap Int [Box]) ->
case w_s1Wf of { GHC.Types.I# ww1_s1Wk ->
let {
b_s1Po :: Box
[LclId]
b_s1Po
= case w1_s1Wg of { GHC.Types.I# dt1_a19i ->
Repro.Box dt1_a19i
} } in -- LAZY!
case Repro.$w$s$wadjust
@[Box]
(\ (bs_a15f :: [Box]) ->
case w1_s1Wg of { GHC.Types.I# dt1_a19i ->
case bs_a15f of bs1_X4 { __DEFAULT ->
GHC.Types.: @Box b_s1Po bs1_X4
}
})
ww1_s1Wk
w2_s1Wh
of vx_a1Uc
{ __DEFAULT ->
(GHC.Tuple.(), vx_a1Uc, GHC.Tuple.())
`cast` (Sym (Data.Functor.Identity.N:Identity[0]
<((), HM.HashMap Int [Box], ())>_R)
:: ((), HM.HashMap Int [Box], ())
~R# Identity ((), HM.HashMap Int [Box], ()))
}
}
</code></pre>
</details>
</p>
## Expected behaviour
The Core generated by the trigger function should respect the strictness properties of `addToList` and ensure that the list's elements are whnf and is spine-strict.
## Environment
* GHC version used: 9.0.2, 9.2.1https://gitlab.haskell.org/ghc/ghc/-/issues/2127440% to 100% slowdown from -threaded2023-01-02T11:25:05ZMikolaj Konarski40% to 100% slowdown from -threadedUnfortunately, I can't reproduce with GHC HEAD ghc-9.3.20220316 and head.hackage, because I'm getting a segfault (after applying a PR to sdl2-ttf that makes it compile). So the tests use GHC 9.2.2. To reproduce:
```
git clone git@github...Unfortunately, I can't reproduce with GHC HEAD ghc-9.3.20220316 and head.hackage, because I'm getting a segfault (after applying a PR to sdl2-ttf that makes it compile). So the tests use GHC 9.2.2. To reproduce:
```
git clone git@github.com:LambdaHack/LambdaHack.git
git checkout v0.11.0.0
cabal build
make bench
```
then change LambdaHack.cabal by adding -threaded, as in
```
common exe-options
ghc-options: -rtsopts -threaded
```
and do again
```
cabal build
make bench
```
Depending on your version of C libsdl2 libraries this may or may not compile and/or run. Try master branch instead of v0.11.0.0 tag to overcome this.
My results without -threaded
```
~/r/LambdaHack$ make bench
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 3 --noAnim --maxFps 100000 --frontendNull --benchmark --benchMessages --stopAfterFrames 1500 --automateAll --keepAutomated --gameMode battle --setDungeonRng "SMGen 127 123" --setMainRng "SMGen 127 125"
Session time: 0.927905003s; frames: 1500. Average clips per second: 6509.287028814522. Average FPS: 1616.5447919241362.
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 3 --maxFps 100000 --frontendLazy --benchmark --benchMessages --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode battle --setDungeonRng "SMGen 127 123" --setMainRng "SMGen 127 125"
Session time: 1.424040237s; frames: 7009. Average clips per second: 4766.719242638928. Average FPS: 4921.911486690667.
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 3 --noAnim --maxFps 100000 --benchmark --benchMessages --stopAfterFrames 2000 --automateAll --keepAutomated --gameMode battle --setDungeonRng "SMGen 127 123" --setMainRng "SMGen 127 125"
Session time: 3.882431124s; frames: 2012. Average clips per second: 1706.147459784273. Average FPS: 518.2319880866481.
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 1 --noAnim --maxFps 100000 --frontendNull --benchmark --benchMessages --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng "SMGen 123 123" --setMainRng "SMGen 123 125"
Session time: 3.159201467s; frames: 7010. Average clips per second: 7755.440815006434. Average FPS: 2218.915150940578.
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 1 --noAnim --maxFps 100000 --benchmark --benchMessages --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng "SMGen 123 123" --setMainRng "SMGen 123 125"
Session time: 12.973855358s; frames: 7010. Average clips per second: 1888.4903002168958. Average FPS: 540.3174158001893.
```
and then with -threaded:
```
~/r/LambdaHack$ make bench
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 3 --noAnim --maxFps 100000 --frontendNull --benchmark --benchMessages --stopAfterFrames 1500 --automateAll --keepAutomated --gameMode battle --setDungeonRng "SMGen 127 123" --setMainRng "SMGen 127 125"
Session time: 1.338236622s; frames: 1500. Average clips per second: 4513.402114921348. Average FPS: 1120.87800867252.
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 3 --maxFps 100000 --frontendLazy --benchmark --benchMessages --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode battle --setDungeonRng "SMGen 127 123" --setMainRng "SMGen 127 125"
Session time: 3.543814058s; frames: 7009. Average clips per second: 1915.4503845020865. Average FPS: 1977.8125729191404.
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 3 --noAnim --maxFps 100000 --benchmark --benchMessages --stopAfterFrames 2000 --automateAll --keepAutomated --gameMode battle --setDungeonRng "SMGen 127 123" --setMainRng "SMGen 127 125"
Session time: 4.990851022s; frames: 2012. Average clips per second: 1327.2285569737448. Average FPS: 403.1376595155759.
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 1 --noAnim --maxFps 100000 --frontendNull --benchmark --benchMessages --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng "SMGen 123 123" --setMainRng "SMGen 123 125"
Session time: 4.56074518s; frames: 7010. Average clips per second: 5372.1484172022965. Average FPS: 1537.0295255127585.
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 1 --noAnim --maxFps 100000 --benchmark --benchMessages --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng "SMGen 123 123" --setMainRng "SMGen 123 125"
Session time: 17.029107743s; frames: 7010. Average clips per second: 1438.7718000123289. Average FPS: 411.6481089786713.
```
Here is some additional info from an investigation by @duog with a month or two older version of the codebase:
1. marking all imports in sdl2 and sdl2-ttf as `unsafe` does not improve the discrepancy
2. results of perf stat on binaries WITH unsafe foreign calls in sdl2 and sdl2-ttf
with-threaded:
```
perf stat -dd make benchFrontendCrawl
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 1 --noAnim --maxFps 100000 --benchmark --benchMessages --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode crawl --frontendNull --setDungeonRng "SMGen 123 123" --setMainRng "SMGen 123 125"
Session time: 7.796642283s; frames: 7005. Average clips per second: 2809.28625489948. Average FPS: 898.463690616393.
Performance counter stats for 'make benchFrontendCrawl':
8,162.78 msec task-clock:u # 0.907 CPUs utilized
0 context-switches:u # 0.000 /sec
0 cpu-migrations:u # 0.000 /sec
53,284 page-faults:u # 6.528 K/sec
23,013,213,417 cycles:u # 2.819 GHz (42.90%)
136,921,195 stalled-cycles-frontend:u # 0.59% frontend cycles idle (43.29%)
448,778,570 stalled-cycles-backend:u # 1.95% backend cycles idle (43.21%)
18,944,979,353 instructions:u # 0.82 insn per cycle
# 0.02 stalled cycles per insn (43.19%)
3,802,875,276 branches:u # 465.880 M/sec (43.12%)
202,717,840 branch-misses:u # 5.33% of all branches (43.10%)
7,928,213,661 L1-dcache-loads:u # 971.264 M/sec (42.98%)
285,102,363 L1-dcache-load-misses:u # 3.60% of all L1-dcache accesses (42.85%)
<not supported> LLC-loads:u
<not supported> LLC-load-misses:u
1,961,103,523 L1-icache-loads:u # 240.249 M/sec (43.03%)
19,840,051 L1-icache-load-misses:u # 1.01% of all L1-icache accesses (42.83%)
55,739,515 dTLB-loads:u # 6.828 M/sec (42.96%)
5,303,284 dTLB-load-misses:u # 9.51% of all dTLB cache accesses (42.99%)
46,210,060 iTLB-loads:u # 5.661 M/sec (42.98%)
4,717,836 iTLB-load-misses:u # 10.21% of all iTLB cache accesses (43.07%)
9.001519486 seconds time elapsed
7.657531000 seconds user
0.748577000 seconds sys
```
without -threaded
```
perf stat -dd make benchFrontendCrawl
$(cabal list-bin exe:LambdaHack) --dbgMsgSer --logPriority 4 --newGame 1 --noAnim --maxFps 100000 --benchmark --benchMessages --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode crawl --frontendNull --setDungeonRng "SMGen 123 123" --setMainRng "SMGen 123 125"
Session time: 5.799896649s; frames: 7005. Average clips per second: 3776.4466033677422. Average FPS: 1207.7801422906011.
Performance counter stats for 'make benchFrontendCrawl':
6,236.18 msec task-clock:u # 0.896 CPUs utilized
0 context-switches:u # 0.000 /sec
0 cpu-migrations:u # 0.000 /sec
53,332 page-faults:u # 8.552 K/sec
18,172,577,519 cycles:u # 2.914 GHz (42.88%)
173,871,640 stalled-cycles-frontend:u # 0.96% frontend cycles idle (42.89%)
384,575,183 stalled-cycles-backend:u # 2.12% backend cycles idle (42.90%)
18,797,086,192 instructions:u # 1.03 insn per cycle
# 0.02 stalled cycles per insn (42.83%)
3,777,918,464 branches:u # 605.807 M/sec (42.79%)
192,408,440 branch-misses:u # 5.09% of all branches (42.79%)
7,620,726,761 L1-dcache-loads:u # 1.222 G/sec (42.95%)
273,000,424 L1-dcache-load-misses:u # 3.58% of all L1-dcache accesses (43.04%)
<not supported> LLC-loads:u
<not supported> LLC-load-misses:u
1,880,798,031 L1-icache-loads:u # 301.595 M/sec (43.08%)
17,176,000 L1-icache-load-misses:u # 0.91% of all L1-icache accesses (43.09%)
54,063,881 dTLB-loads:u # 8.669 M/sec (43.15%)
5,052,959 dTLB-load-misses:u # 9.35% of all dTLB cache accesses (43.13%)
32,697,768 iTLB-loads:u # 5.243 M/sec (43.05%)
2,887,900 iTLB-load-misses:u # 8.83% of all iTLB cache accesses (42.95%)
```
3. going vanilla to -threaded costs 20% instructions per cycle. I think that's quite bad. Unfortunately my AMD CPU doesn't support LLC-loads (i.e. level3 cache) counters.https://gitlab.haskell.org/ghc/ghc/-/issues/21105Hadrian slow to start tests2023-01-30T17:19:50ZRichard Eisenbergrae@richarde.devHadrian slow to start testsWhen I say
```
rae@build01|21:35:54 ~/ghc/ghc-homo> ./hadrian/build test --freeze1 --freeze2 --docs=none --flavour=devel2+werror --only=T16135
```
Hadrian says
```
Up to date
| Run Testsuite GetExtraDeps: none
```
It then waits 5 sec...When I say
```
rae@build01|21:35:54 ~/ghc/ghc-homo> ./hadrian/build test --freeze1 --freeze2 --docs=none --flavour=devel2+werror --only=T16135
```
Hadrian says
```
Up to date
| Run Testsuite GetExtraDeps: none
```
It then waits 5 seconds or so. These 5 seconds or so are annoying when I'm going through test case failures. Is this avoidable?https://gitlab.haskell.org/ghc/ghc/-/issues/21012Suggest replacing -> with =>2022-02-03T11:41:58ZJoseph C. SibleSuggest replacing -> with =><!--
READ THIS FIRST: If the feature you are proposing changes the language that GHC accepts
or adds any warnings to `-Wall`, it should be written as a [GHC Proposal](https://github.com/ghc-proposals/ghc-proposals/).
Other features, appr...<!--
READ THIS FIRST: If the feature you are proposing changes the language that GHC accepts
or adds any warnings to `-Wall`, it should be written as a [GHC Proposal](https://github.com/ghc-proposals/ghc-proposals/).
Other features, appropriate for a GitLab feature request, include GHC API/plugin
innovations, new low-impact compiler flags, or other similar additions to GHC.
-->
## Motivation
A lot of Haskell newbies make the mistake of using `->` where they mean `=>`, and the error we give them is rather cryptic.
## Proposal
```
ghci> :{
ghci| doTwice :: Applicative t -> t () -> t ()
ghci| doTwice x = x *> x
ghci| :}
<interactive>:6:12: error:
• Expected a type, but ‘Applicative t’ has kind ‘Constraint’
• In the type signature: doTwice :: Applicative t -> t () -> t ()
ghci>
```
Make the above error suggest changing the `->` after `Applicative t` to `=>`.https://gitlab.haskell.org/ghc/ghc/-/issues/20890Multiple home units and Backpack together2024-02-12T13:02:19ZMatthew PickeringMultiple home units and Backpack togetherMultiple Home Units opens up some more natural implementation strategies for backpack but currently
Opportunities
* Unit instantiations can be expressed more naturally in terms of unit dependencies rather than shoe-horned into the mod...Multiple Home Units opens up some more natural implementation strategies for backpack but currently
Opportunities
* Unit instantiations can be expressed more naturally in terms of unit dependencies rather than shoe-horned into the module graph.
Known Problems
* Hole units assume a singular home unit (see the special case for `loadInterface` for `isHoleModule`).
* No tests at all combining MHU/Backpack
All we need is a backpack lover to try and wrangle things so that things work nicely!