GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2024-03-27T16:39:35Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/22317Boring join points should not inline2024-03-27T16:39:35ZSebastian GrafBoring join points should not inlineIn https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9104#note_457018 I investigated how a different optimisation path in the Simplifier caused unnecessary code bloat. Here is a standalone reproducer:
```hs
{-# LANGUAGE BangPatterns #...In https://gitlab.haskell.org/ghc/ghc/-/merge_requests/9104#note_457018 I investigated how a different optimisation path in the Simplifier caused unnecessary code bloat. Here is a standalone reproducer:
```hs
{-# LANGUAGE BangPatterns #-}
module Lib where
data T = T (Maybe Bool) (Maybe Bool) (Maybe Bool) (Maybe Bool)
m :: Maybe a -> Maybe a -> Maybe a
m (Just v1) Nothing = Just v1
m _ mb = mb
{-# INLINE m #-}
f :: T -> T -> T
f (T a1 b1 c1 d1) (T a2 b2 c2 d2)
= let j1 !a = let j2 !b = let j3 !c = let j4 !d = T a b c d
in j4 (m d1 d2)
in j3 (m c1 c2)
in j2 (m b1 b2)
in j1 (m a1 a2)
{-# OPAQUE f #-}
```
(The use of `OPAQUE` is jsut so that we don't unbox.)
After inlining `m`, this is pretty much the optimal code; specifically, it doesn't make sense to inline the join points, for the following reasons:
- No simplification to be had with the return site, because otherwise we'd have pushed the context into the join point
- No simplifiation to be had with concrete arguments, because they just end up in `T`'s fields. The `seq` will be done at the call site thanks to tag inference.
- `jump j4 ...` is much smaller than `T a b c d` and an unconditional direct jump, so that is also not a good reason.
Yet in HEAD, I see
```
f = \ ds ds1 ->
case ds of { T a1 b1 c1 d1 ->
case ds1 of { T a2 b2 c2 d2 ->
join {
$j a
= case a of a4 { __DEFAULT ->
join {
$j1 b
= case b of b4 { __DEFAULT ->
case c1 of wild2 {
Nothing ->
case c2 of c { __DEFAULT ->
case d1 of wild3 {
Nothing -> case d2 of d { __DEFAULT -> T a4 b4 c d };
Just v1 ->
case d2 of wild4 {
Nothing -> T a4 b4 c wild3;
Just ipv -> T a4 b4 c wild4
}
}
};
Just v1 ->
case c2 of wild3 {
Nothing ->
case d1 of wild4 {
Nothing -> case d2 of d { __DEFAULT -> T a4 b4 wild2 d };
Just v2 ->
case d2 of wild5 {
Nothing -> T a4 b4 wild2 wild4;
Just ipv -> T a4 b4 wild2 wild5
}
};
Just ipv ->
case d1 of wild4 {
Nothing -> case d2 of d { __DEFAULT -> T a4 b4 wild3 d };
Just v2 ->
case d2 of wild5 {
Nothing -> T a4 b4 wild3 wild4;
Just ipv1 -> T a4 b4 wild3 wild5
}
}
}
}
} } in
case b1 of wild2 {
Nothing -> jump $j1 b2;
Just v1 ->
case b2 of wild3 {
Nothing -> jump $j1 wild2;
Just ipv -> jump $j1 wild3
}
}
} } in
case a1 of wild2 {
Nothing -> jump $j a2;
Just v1 ->
case a2 of wild3 {
Nothing -> jump $j wild2;
Just ipv -> jump $j wild3
}
}
}
}
```
Note that we inlined `j3` and `j4`.
My investigation so far pointed to `Note [Inline small things to avoid creating a thunk]` which causes us to postinline small join points in the final phase. But inlining join points doesn't avoid creating a thunk! So at the very least that Note should not apply to join points.
But even then, this is the output of `-dinline-check \$j`:
```
Considering inlining: $j_szM
arg infos [ValueArg]
interesting continuation BoringCtxt
some_benefit True
is exp: True
is work-free: True
guidance ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=True)
ANSWER = YES
Considering inlining: $j_szM
arg infos [ValueArg]
interesting continuation BoringCtxt
some_benefit True
is exp: True
is work-free: True
guidance ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=True)
ANSWER = YES
Considering inlining: $j_szM
arg infos [ValueArg]
interesting continuation BoringCtxt
some_benefit True
is exp: True
is work-free: True
guidance ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=True)
ANSWER = YES
Considering inlining: $j_szN
arg infos [ValueArg]
interesting continuation BoringCtxt
some_benefit True
is exp: True
is work-free: True
guidance IF_ARGS [20] 120 30
case depth = 1
depth based penalty = 0
discounted size = 80
ANSWER = YES
Considering inlining: $j_szN
arg infos [ValueArg]
interesting continuation BoringCtxt
some_benefit True
is exp: True
is work-free: True
guidance IF_ARGS [20] 120 30
case depth = 2
depth based penalty = 0
discounted size = 80
ANSWER = YES
Considering inlining: $j_szN
arg infos [ValueArg]
interesting continuation BoringCtxt
some_benefit True
is exp: True
is work-free: True
guidance IF_ARGS [20] 120 30
case depth = 2
depth based penalty = 0
discounted size = 80
ANSWER = YES
...
```
So `calcUnfoldingGuidance` seems to give some of these an `ALWAYS_IF` guidance and boring contexts and unsaturated calls (!!) are OK, too. `Note [INLINE for small functions]` seems relevant there.
It's all a bit fishy; clearly `j4` is *not* just a function call that is as small as the call to `j4` itself. There is no call to `j4` to begin with, just a jump, because it's a join point. The only time when inlining a join point may decrease code size is when itself is just a jump to another join point. Currently, `condInline` does not check for join points at all.
Anyway,
Still, it's wasteful to inline *any* of the join points.https://gitlab.haskell.org/ghc/ghc/-/issues/11836Hello World Bug - silent stdout errors2024-03-21T17:37:36ZbitHello World Bug - silent stdout errors## Background
This entertaining talk explains the issue: https://www.irill.org/events/ghm-gnu-hackers-meeting/videos/jim-meyering-goodbye-world-the-perils-of-relying-on-output-streams-in-c
## hello.hs
```hs
main = putStrLn "Hello worl...## Background
This entertaining talk explains the issue: https://www.irill.org/events/ghm-gnu-hackers-meeting/videos/jim-meyering-goodbye-world-the-perils-of-relying-on-output-streams-in-c
## hello.hs
```hs
main = putStrLn "Hello world"
```
## Run it
```
$ runhaskell hello.hs > /dev/full ; echo $?
hello.hs: <stdout>: hPutChar: resource exhausted (No space left on device)
1
```
That looks good! We tried to save the output to a file but the disk was full, so we got an error message, and a process exit code indicating failure.
## Run it compiled
```
$ ghc hello.hs
$ ./hello > /dev/full ; echo $?
0
```
Not good! The error was silently ignored, and additionally the process lied when it reported a successful exit status.
Why did it behave differently when compiled? When `runhaskell` is used, the buffering of stdout is `NoBuffering` therefore the putStrLn call fails. But when compiled, stdout is in `LineBuffering` mode and therefore the putStrLn call succeeds.
The fix:
## hello2.hs
```hs
import System.IO
main = do
putStrLn "Hello world"
hClose stdout
```
## Run it compiled
```
$ ghc hello2.hs
$ ./hello2 > /dev/full ; echo $?
hello: <stdout>: hClose: resource exhausted (No space left on device)
1
```
Looks good! But there's a catch:
```
$ runhaskell hello2.hs ; echo $?
Hello world
ghc: <stdout>: hFlush: illegal operation (handle is closed)
1
```
Now our program fails to run correctly with `runhaskell` :(
It seems that `runhaskell` is running some hidden code after main finished. It is not clear to me how to write a correct "Hello World" that works both compiled and with `runhaskell`.
## Summary
One of the greatest things about Haskell is that short, clear and concise programs can also be correct.
It is my opinion that the original "hello.hs" should Just Work™. Haskell programmers shouldn't have to know that they need to always close stdout before exiting. Especially since it's not even clear how to do it properly...
Thank you!
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 7.10.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Hello World Bug - silent stdout errors","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"7.10.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"== Background\r\n\r\nThis entertaining talk explains the issue: https://www.irill.org/events/ghm-gnu-hackers-meeting/videos/jim-meyering-goodbye-world-the-perils-of-relying-on-output-streams-in-c\r\n\r\n== hello.hs\r\n{{{#!hs\r\nmain = putStrLn \"Hello world\"\r\n}}}\r\n\r\n== Run it\r\n\r\n{{{\r\n$ runhaskell hello.hs > /dev/full ; echo $?\r\nhello.hs: <stdout>: hPutChar: resource exhausted (No space left on device)\r\n1\r\n}}}\r\n\r\nThat looks good! We tried to save the output to a file but the disk was full, so we got an error message, and a process exit code indicating failure.\r\n\r\n== Run it compiled\r\n\r\n{{{\r\n$ ghc hello.hs\r\n$ ./hello > /dev/full ; echo $?\r\n0\r\n}}}\r\n\r\nNot good! The error was silently ignored, and additionally the process lied when it reported a successful exit status.\r\n\r\nWhy did it behave differently when compiled? When `runhaskell` is used, the buffering of stdout is `NoBuffering` therefore the putStrLn call fails. But when compiled, stdout is in `LineBuffering` mode and therefore the putStrLn call succeeds.\r\n\r\nThe fix:\r\n\r\n== hello2.hs\r\n{{{#!hs\r\nimport System.IO\r\n\r\nmain = do\r\n putStrLn \"Hello world\"\r\n hClose stdout\r\n}}}\r\n\r\n== Run it compiled\r\n\r\n{{{\r\n$ ghc hello2.hs\r\n$ ./hello2 > /dev/full ; echo $?\r\nhello: <stdout>: hClose: resource exhausted (No space left on device)\r\n1\r\n}}}\r\n\r\nLooks good! But there's a catch:\r\n\r\n{{{\r\n$ runhaskell hello2.hs ; echo $?\r\nHello world\r\nghc: <stdout>: hFlush: illegal operation (handle is closed)\r\n1\r\n}}}\r\n\r\nNow our program fails to run correctly with `runhaskell` :(\r\n\r\nIt seems that `runhaskell` is running some hidden code after main finished. It is not clear to me how to write a correct \"Hello World\" that works both compiled and with `runhaskell`.\r\n\r\n== Summary\r\n\r\nOne of the greatest things about Haskell is that short, clear and concise programs can also be correct.\r\n\r\nIt is my opinion that the original \"hello.hs\" should Just Work™. Haskell programmers shouldn't have to know that they need to always close stdout before exiting. Especially since it's not even clear how to do it properly...\r\n\r\nThank you!","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/24031Deprecate `PrimTyConI`2024-03-18T13:15:51ZTeo CamarasuDeprecate `PrimTyConI`See also
* #20914
## Motivation
One of the possible response forms from reifying a datatype using `template-haskell` is the [`PrimTyConI`](https://hackage.haskell.org/package/template-haskell-2.20.0.0/docs/Language-Haskell-TH-Syntax.ht...See also
* #20914
## Motivation
One of the possible response forms from reifying a datatype using `template-haskell` is the [`PrimTyConI`](https://hackage.haskell.org/package/template-haskell-2.20.0.0/docs/Language-Haskell-TH-Syntax.html#v:PrimTyConI) constructor.
This is defined as:
```hs
data Info =
...
-- | A \"primitive\" type constructor, which can't be expressed with a 'Dec'.
-- Examples: @(->)@, @Int#@.
| PrimTyConI
Name
Arity
Unlifted
...
```
The strange thing about this constructor is that it could be completely subsumed into the `TyConI` case, which is the more general one for type constructors.
The only thing that sets it apart is that it labels the type as "primitive" (which I take to be wired-in unlifted/unboxed types). Yet, not all primitive types are represented by this constructor. Reifying unboxed tuples and sums gives you a `TyConI` constructor. So, it doesn't even give users an accurate portrait of which types are "primitive".
I think this used to be necessary before GHC had proper support for unboxed/unlifted kinds, but I'm not sure if it's still needed.
It just appears to be a vestigial edge case.
## Proposal
Stop emitting instances of this constructor and consistently use `TyConI` instead.
I don't think there's any immediate need to get rid of the constructor for now, since code might rely on its existence.https://gitlab.haskell.org/ghc/ghc/-/issues/24488TypeAbstractions example produces a parse error2024-03-09T17:48:33ZJkensikTypeAbstractions example produces a parse error## Summary
The example from the documentation
`
f5 :: [forall a. a -> a -> a]
f5 = [ \ @a x _ -> x :: a,
\ @a _ y -> y :: a ]
`
gives the error
error: [GHC-58481] parse error on input ‘@’
|
26 | f5 = [ \ @a x _ -> x :: a,
...## Summary
The example from the documentation
`
f5 :: [forall a. a -> a -> a]
f5 = [ \ @a x _ -> x :: a,
\ @a _ y -> y :: a ]
`
gives the error
error: [GHC-58481] parse error on input ‘@’
|
26 | f5 = [ \ @a x _ -> x :: a,
## Environment
GHC9.8.2Vladislav ZavialovVladislav Zavialovhttps://gitlab.haskell.org/ghc/ghc/-/issues/21997Add info table information to StopThread event where appropriate2024-03-07T20:12:24ZTeo CamarasuAdd info table information to StopThread event where appropriate### Motivation
The eventlog has a helpful StopThread event that tells us why a Haskell thread has stopped executing.
Some of these options relate to a Haskell heap object, eg, a blackhole or an mvar.
In these cases it's helpful to vagu...### Motivation
The eventlog has a helpful StopThread event that tells us why a Haskell thread has stopped executing.
Some of these options relate to a Haskell heap object, eg, a blackhole or an mvar.
In these cases it's helpful to vaguely know which heap object this is.
### Proposal
Where possible add the value of the info-table pointer to the StopThread event.
Then we can use IPE information to figure out information about the Haskell heap object that has caused the thread to be paused.
This is in a similar vein to #21877.https://gitlab.haskell.org/ghc/ghc/-/issues/24491Add a --test-ways flag to hadrian2024-03-05T14:36:55ZTeo CamarasuAdd a --test-ways flag to hadrianThis is a small idea to improve hadrian. Have a `--test-ways=<way>(,<way>)*` flag that allows specifying multiple ways at the same time rather than having to use several `--test-way=way1 --test-way=way2` options.This is a small idea to improve hadrian. Have a `--test-ways=<way>(,<way>)*` flag that allows specifying multiple ways at the same time rather than having to use several `--test-way=way1 --test-way=way2` options.https://gitlab.haskell.org/ghc/ghc/-/issues/23946When printing type signatures of types, GHC always prints ASCII double semico...2024-02-28T13:28:34ZkindaroWhen printing type signatures of types, GHC always prints ASCII double semicolon and never prints Unicode proportion symbol.## Summary
I have the setting `-fprint-unicode-syntax` switched on. However, GHC still prints type signatures of types with the ASCII double semicolon. It would print Unicode stars `★` and Unicode arrows `→` on the same very line, so th...## Summary
I have the setting `-fprint-unicode-syntax` switched on. However, GHC still prints type signatures of types with the ASCII double semicolon. It would print Unicode stars `★` and Unicode arrows `→` on the same very line, so this is specific to the double semicolon.
## Steps to reproduce
Start `ghci` and type `:set -fprint-unicode-syntax` then `:info IO`. You shall see:
```
λ :info IO
type IO :: ★ → ★
…
```
_(ellipsis mine)_
This is wrong!
## Expected behavior
```
λ :info IO
type IO ∷ ★ → ★
…
```
_(ellipsis mine)_
## Environment
* GHC version used: 9.2.8, 9.6.2.
Optional:
* Operating System: Linux
* System Architecture: `x86_64`https://gitlab.haskell.org/ghc/ghc/-/issues/21744interestingArg should not consider OtherCon[] interesting.2024-02-27T13:58:43ZAndreas KlebingerinterestingArg should not consider OtherCon[] interesting.See also https://gitlab.haskell.org/ghc/ghc/-/merge_requests/8148#note_437483
The issue is that if we have:
```
foo x y = case x of x' -> case y of y' ->
bar x y
```
Inlining `bar` is not really a win, so we shouldn't do it....See also https://gitlab.haskell.org/ghc/ghc/-/merge_requests/8148#note_437483
The issue is that if we have:
```
foo x y = case x of x' -> case y of y' ->
bar x y
```
Inlining `bar` is not really a win, so we shouldn't do it. However currently x' and y' are considered ValueArgs so we will apply a discount and likely inline `bar`.
The best fix is probably to check for OtherCon[] explicitly.
Note that inlining something with an OtherCon[SomeCon] unfolding *is* beneficial. As we potentially can remove a branch inside `bar`.https://gitlab.haskell.org/ghc/ghc/-/issues/21777Missed opt.: Fold arithmetic into LEA2024-02-27T13:58:43ZBenjamin MaurerMissed opt.: Fold arithmetic into LEAI noticed a few cases, where NCG could do better on x86, folding arithmetic into a single LEA instruction:
([Compiler Explorer](https://gcc.godbolt.org/z/h55heb6jn))
-- Unboxed makes it easier to see:
foo :: Int# -> Int#
fo...I noticed a few cases, where NCG could do better on x86, folding arithmetic into a single LEA instruction:
([Compiler Explorer](https://gcc.godbolt.org/z/h55heb6jn))
-- Unboxed makes it easier to see:
foo :: Int# -> Int#
foo x = 42# +# 2# *# x
-- Cmm: R1 = (R2 << 1) + 42;
-- ASM: shlq $1,%r14
leaq 42(%r14),%rbx
--
-- Could be: leaq 42(%r14,%r14), %rbx
-- Same but additional load from memory
foo2 :: Int -> Int
foo2 x = 42 + 2*x
-- Cmm: _sAY::I64 = (I64[R1 + 7] << 1) + 42;
-- ASM: movq 7(%rbx),%rax
-- shlq $1,%rax
-- addq $42,%rax
--
-- Could be: movq 7(%rbx),%rcx
leaq 42(%rcx,%rcx), %rax
-- LEA can do "base + scale * index + displacement":
foo3 :: Int# -> Int# -> Int#
foo3 x y = x +# y *# 4# -# 4#
-- Cmm: R1 = R2 + (R3 << 2) - 4;
-- ASM: shlq $2,%rsi
-- addq %rsi,%r14
-- leaq -4(%r14),%rbx
--
-- Could be: leaq -4(%r14,%rsi,4), %rbx
I tried it out bc. I saw a demonstration of [GCC doing this](https://gcc.godbolt.org/z/5KjvoT8hj).
For the first use, LEA is already used, so a simple rule for merging SHIFTL and ADD should work.
Just leaving this issue here as a reminder, when I or someone else has too much time on their hand :)https://gitlab.haskell.org/ghc/ghc/-/issues/23158Precomputed static closures for nullary GADT workers and wrappers2024-02-23T00:39:10ZBen GamariPrecomputed static closures for nullary GADT workers and wrappersConsider the program
```haskell
module B where
import GHC.Exts
type NP :: [Type] -> Type
data NP xs where
UNil :: NP '[]
```
This will give rise to the following Cmm:
```c
[UNil_entry() { // []
{ info_tbls: [(cE4,
...Consider the program
```haskell
module B where
import GHC.Exts
type NP :: [Type] -> Type
data NP xs where
UNil :: NP '[]
```
This will give rise to the following Cmm:
```c
[UNil_entry() { // []
{ info_tbls: [(cE4,
label: UNil_info
rep: HeapRep static { Fun {arity: 1 fun_type: ArgSpec 3} }
srt: Nothing)]
stack_info: arg_space: 8
}
{offset
cE4:
unwind Sp = Just Sp;
unwind Sp = Just Sp;
Hp = Hp + 16;
if (Hp > HpLim) (likely: False) goto cE8; else goto cE7;
cE8:
unwind Sp = Just Sp;
HpAlloc = 16;
unwind Sp = Just Sp;
R1 = UNil_closure;
call (stg_gc_fun)(R1) args: 8, res: 0, upd: 8;
cE7:
unwind Sp = Just Sp;
I64[Hp - 8] = UNil_con_info;
R1 = Hp - 7;
call (P64[Sp])(R1) args: 8, res: 0, upd: 8;
}
},
section ""data" . UNil_closure" {
UNil_closure:
const UNil_info;
}]
```
Note that `UNil_entry` may allocate unnecessarily: If the heap check fails then we correctly return `UNil_closure`. However, If the heap check succeeds then we will allocate a new `UNil` constructor on the dynamic heap. There is no reason to do this.Rodrigo MesquitaRodrigo Mesquitahttps://gitlab.haskell.org/ghc/ghc/-/issues/21252-Wunused-local-binds doesn't work for expressions in GHCi2024-02-22T16:05:17ZRyan Scott-Wunused-local-binds doesn't work for expressions in GHCiIf you compile this file with `-Wunused-local-binds`:
```hs
main = let x = () in return ()
```
It will produce a warning, as expected:
```
$ ghc-9.2.2 Foo.hs -fforce-recomp -Wunused-local-binds
[1 of 1] Compiling Main ( Fo...If you compile this file with `-Wunused-local-binds`:
```hs
main = let x = () in return ()
```
It will produce a warning, as expected:
```
$ ghc-9.2.2 Foo.hs -fforce-recomp -Wunused-local-binds
[1 of 1] Compiling Main ( Foo.hs, Foo.o )
Foo.hs:1:12: warning: [-Wunused-local-binds]
Defined but not used: ‘x’
|
1 | main = let x = () in return ()
| ^
Linking Foo ...
```
If you type the same expression into GHCi, however, it produces no warnings!
```
$ ghci-9.2.2
GHCi, version 9.2.2: https://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/rscott/.ghci
λ> :set -Wunused-local-binds
λ> let x = () in return ()
λ>
```
This seems like a discrepancy. Further investigation reveals that GHCi in fact [deliberately disables `-Wunused-local-binds`](https://gitlab.haskell.org/ghc/ghc/-/blob/1a0dd0088247f9d4e403a460f0f6120184af3e15/compiler/GHC/Runtime/Eval.hs#L216-220):
```hs
-- Turn off -fwarn-unused-local-binds when running a statement, to hide
-- warnings about the implicit bindings we introduce.
let ic = hsc_IC hsc_env -- use the interactive dflags
idflags' = ic_dflags ic `wopt_unset` Opt_WarnUnusedLocalBinds
hsc_env' = mkInteractiveHscEnv (hsc_env{ hsc_IC = ic{ ic_dflags = idflags' }})
```
This code was introduced 14 years ago in 86bec4298d582ef1d8f0a201d6a81145e1be9498. I don't find the stated reason to be convincing, however. Rather than disabling `-Wunused-local-binds` entirely, which suppresses useful warnings, we should instead find a way to make the implicit bindings that GHCi introduces not trigger `-Wunused-local-binds` warnings.https://gitlab.haskell.org/ghc/ghc/-/issues/2988Improve float-in2024-02-22T14:11:01ZSimon Peyton JonesImprove float-inAt the moment we can get a cascade of simplifier iterations like this:
```hs
let x1 = blah
x2 = x1 : []
x3 = 1 : x2
x4 = 2 : x3
in case blah of
True -> f x4
False -> g x4
```
Then `x4` satisfies the conditions for `post...At the moment we can get a cascade of simplifier iterations like this:
```hs
let x1 = blah
x2 = x1 : []
x3 = 1 : x2
x4 = 2 : x3
in case blah of
True -> f x4
False -> g x4
```
Then `x4` satisfies the conditions for `postInlineUnconditionally` (not top-level, used once in each case branch, not inside lambda). So it's inlined. In the next iteration of the simplifier, `x3` satisfies the conditions, and so on.
It might be better for `postUnconditionally` to require an interesting context. But then this case doesn't work so well:
```hs
let x = blah in case foo of { A -> ..x..; B -> ..x..; C -> ..no x.. }
```
If C is the hot branch, it's a good idea to push `x` into the A,B branches.
But perhaps this question is one that `FloatIn` should deal with, not `postInlineUnconditionally`. Indeed `FloatIn` has the following comment:
```hs
-- For case expressions we duplicate the binding if it is
-- reasonably small, and if it is not used in all the RHSs
-- This is good for situations like
-- let x = I# y in
-- case e of
-- C -> error x
-- D -> error x
-- E -> ...not mentioning x...
```
So this ticket is just to record the idea:
- Make `postInlineUnconditionally` check for interesting context
1. ..and check on performance changes, and whether `FloatIn` is doing the Right Thing.
Simon8.4.1https://gitlab.haskell.org/ghc/ghc/-/issues/11630More precise LANGUAGE pragma when forall is used2024-02-21T20:41:56ZEdward Z. YangMore precise LANGUAGE pragma when forall is usedIn all cases when a user attempts to use the `forall` keyword, GHC suggests enabling `RankNTypes`. This seems suboptimal, since a more direct way to enable just the syntax is `ExplicitForAll`. So maybe we should just suggest that instead...In all cases when a user attempts to use the `forall` keyword, GHC suggests enabling `RankNTypes`. This seems suboptimal, since a more direct way to enable just the syntax is `ExplicitForAll`. So maybe we should just suggest that instead.
In some cases, the user will immediately thereafter have to add `RankNTypes`, or `Rank2Types`, or `ExistentialQuantification`, etc. So it would be more user friendly to suggest the appropriate extension directly. I don't know how much harder this would be to do.
<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":"More precise LANGUAGE pragma when forall is used","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"In all cases when a user attempts to use the `forall` keyword, GHC suggests enabling `RankNTypes`. This seems suboptimal, since a more direct way to enable just the syntax is `ExplicitForAll`. So maybe we should just suggest that instead.\r\n\r\nIn some cases, the user will immediately thereafter have to add `RankNTypes`, or `Rank2Types`, or `ExistentialQuantification`, etc. So it would be more user friendly to suggest the appropriate extension directly. I don't know how much harder this would be to do.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/15660source file modify race leads to inconsistent error message2024-02-21T13:50:16Zjoeyhesssource file modify race leads to inconsistent error messageI got this odd error message from ghc:
```
Command/AddUrl.hs:120:32: error:
lexical error in string/character literal at character '-'
|
120 | BatchNull -> '\0'
| ^
```
Part o...I got this odd error message from ghc:
```
Command/AddUrl.hs:120:32: error:
lexical error in string/character literal at character '-'
|
120 | BatchNull -> '\0'
| ^
```
Part of the error message says that '-' is the problem character,
but the quoted line of code does not contain that.
What happened is I started the build, noticed I had typoed '\\-' and quickly corrected it in my editor and saved. It seems ghc must have read the source file twice, so I raced it and so experienced this inconsistency.
I wonder if it could display the wrong line entirely if a larger change was made to the file?
Thanks for your time with such a minor thing as this bug.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | low |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"source file modify race leads to inconsistent error message","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"I got this odd error message from ghc:\r\n\r\n\r\n{{{\r\n\r\nCommand/AddUrl.hs:120:32: error:\r\n lexical error in string/character literal at character '-'\r\n |\r\n120 | BatchNull -> '\\0'\r\n | ^\r\n\r\n}}}\r\n\r\nPart of the error message says that '-' is the problem character,\r\nbut the quoted line of code does not contain that.\r\n\r\nWhat happened is I started the build, noticed I had typoed '\\-' and quickly corrected it in my editor and saved. It seems ghc must have read the source file twice, so I raced it and so experienced this inconsistency.\r\n\r\nI wonder if it could display the wrong line entirely if a larger change was made to the file?\r\n\r\nThanks for your time with such a minor thing as this bug.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/24439Parser: use left-recursion in apats and argpats2024-02-20T14:38:06ZVladislav ZavialovParser: use left-recursion in apats and argpatsThe following discussion from !11109 should be addressed:
- [ ] https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11109#note_521826
> Happy works better with left-recursive grammars, so I expected to see
>
> ```
> ar...The following discussion from !11109 should be addressed:
- [ ] https://gitlab.haskell.org/ghc/ghc/-/merge_requests/11109#note_521826
> Happy works better with left-recursive grammars, so I expected to see
>
> ```
> argpats :: { [LArgPat GhcPs] } -- reversed
> : argpats argpat { $2 : $1 }
> | { [] }
> ```
>
> But then I noticed that `apats` has the same problem, and you probably simply used it as a reference.
>
> We should fix this at some point, but maybe not in this patch.https://gitlab.haskell.org/ghc/ghc/-/issues/24437STM: Potentially invalid assertion in STM.c2024-02-13T14:45:17ZAndreas KlebingerSTM: Potentially invalid assertion in STM.c## Summary
In the code for committing a transaction we have this sequence:
```C
...
{
ACQ_ASSERT(tvar_is_locked(s, trec));
IF_STM_FG_LOCKS({
// We have locked the TVar therefore nonatomic addi...## Summary
In the code for committing a transaction we have this sequence:
```C
...
{
ACQ_ASSERT(tvar_is_locked(s, trec));
IF_STM_FG_LOCKS({
// We have locked the TVar therefore nonatomic addition is sufficient
NONATOMIC_ADD(&s->num_updates, 1);
});
unlock_tvar(cap, trec, s, e -> new_value, true);
}
ACQ_ASSERT(!tvar_is_locked(s, trec));
```
To me this seems like an potential bug. We assert a TVar is unlocked after we unlock it. But it's not obvious why the TVar couldn't have been locked by another thread in between the unlock operation and the assert.
I will leave the assert in for now as it might check some non-obvious undocumented invariant. But I will leave this here in case anyone else actually hits this assertion while nothing is wrong.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!https://gitlab.haskell.org/ghc/ghc/-/issues/23940JavaScriptFFI extension is undocumented2024-02-09T17:32:36ZAdam GundryJavaScriptFFI extension is undocumentedThe new `JavaScriptFFI` extension is not properly documented in the user's guide. It is mentioned implicitly in https://ghc.gitlab.haskell.org/ghc/doc/users_guide/javascript.html but there's no extension block.The new `JavaScriptFFI` extension is not properly documented in the user's guide. It is mentioned implicitly in https://ghc.gitlab.haskell.org/ghc/doc/users_guide/javascript.html but there's no extension block.sheafsam.derbyshire@gmail.comsheafsam.derbyshire@gmail.comhttps://gitlab.haskell.org/ghc/ghc/-/issues/19998-XJavaScriptFFI does nothing2024-02-09T17:32:35ZKrzysztof Gogolewski-XJavaScriptFFI does nothingThe extension JavaScriptFFI has not been doing anything since it was added in b372e8eadc.
It should either control `foreign import javascript` or be deprecated. (For example, the proposed `winapi` calling convention https://github.com/g...The extension JavaScriptFFI has not been doing anything since it was added in b372e8eadc.
It should either control `foreign import javascript` or be deprecated. (For example, the proposed `winapi` calling convention https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0277-winapi-callconv.rst#proposed-change does not have a flag.)https://gitlab.haskell.org/ghc/ghc/-/issues/3372Allow for multiple linker instances2024-02-02T17:24:01ZDaniel GorínAllow for multiple linker instancesRight now there is only one RTS linker with a single symbol table.This means, for example, that one cannot have multiple instances of the GHC interpreter in the same process running simultaneously.
<details><summary>Trac metadata</summa...Right now there is only one RTS linker with a single symbol table.This means, for example, that one cannot have multiple instances of the GHC interpreter in the same process running simultaneously.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | |
| 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":"Allow for multiple linker instances","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"Right now there is only one RTS linker with a single symbol table.This means, for example, that one cannot have multiple instances of the GHC interpreter in the same process running simultaneously.\r\n\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.0.1