GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2022-07-08T10:17:42Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/21825Unable to `reifyInstances` a type class with multiple parameters2022-07-08T10:17:42ZparsonsmattUnable to `reifyInstances` a type class with multiple parameters## Summary
I'd like to be able to find matching instances of a multiparameter type class, like `class SqlSelect a b | a -> b, b -> a`. But the naive `reifyInstances ''SqlSelect [VarT (mkName "a")]` is not working, and returns the empty ...## Summary
I'd like to be able to find matching instances of a multiparameter type class, like `class SqlSelect a b | a -> b, b -> a`. But the naive `reifyInstances ''SqlSelect [VarT (mkName "a")]` is not working, and returns the empty list.
## Steps to reproduce
```haskell
{-# language MultiParamTypeClasses, TemplateHaskell #-}
import Language.Haskell.TH
class C a b
class D a
instance C Int Char
instance D Int
do
instances <- reifyInstances ''C [VarT (mkName "a")]
case instances of
[] ->
fail "should have at least one instance?"
xs -> do
runIO $ traverse print instances
pure []
```
If you `reifyInstances ''D` instead, then it returns the sole instance.
## Expected behavior
Well, that's a good question.
Obviously, `AppT (ConT ''SqlSelect) (VarT (mkName "a"))` doesn't make sense, which is the most 'obvious' way to consume the name and type given. What I really want to do is ask GHC whether there's an `instance SqlSelect wanted Foo`, and if so, use the concrete type of `wanted` in code generation.
## Environment
* GHC version used: 9.2.2
Optional:
* Operating System:
* System Architecture:https://gitlab.haskell.org/ghc/ghc/-/issues/21612ghc-stage1 failed to compile Win32 due to "File does not match module name" i...2022-05-26T15:03:53ZCarrieMYghc-stage1 failed to compile Win32 due to "File does not match module name" in `Pen.hs`## Summary
I encountered this problem when building latest ghc master branch by `make`. (I am sorry for not adopting `hadrian` yet because there I also got troubles which I will seek help else where.) If additional information is needed,...## Summary
I encountered this problem when building latest ghc master branch by `make`. (I am sorry for not adopting `hadrian` yet because there I also got troubles which I will seek help else where.) If additional information is needed, please let me know. Thanks!
## Steps to reproduce
./boot && ./configure --enable-autodownload-tarballs && make
```
... messages omitted ...
"rm" -f libraries/Win32/dist-install/build/.depend-v.haskell.tmp
"inplace/bin/ghc-stage1.exe" -M -static -O0 -H64m -Wall -this-unit-id Win32-2.12.0.0 -hide-all-packages -package-env - -i -ilibraries/Win32/. -ilibraries/Win32/dist-install/build -Ilibraries/Win32/dist-install/build -ilibraries/Win32/dist-install/build/./autogen -Ilibraries/Win32/dist-install/build/./autogen -Ilibraries/Win32/include -Ilibraries/Win32/dist-install/build/include -optP-include -optPlibraries/Win32/dist-install/build/./autogen/cabal_macros.h -package-id base-4.16.0.0 -package-id filepath-1.4.2.1 -Wall -fno-warn-name-shadowing -Wall -XHaskell2010 -XForeignFunctionInterface -XCPP -XNondecreasingIndentation -O -no-user-package-db -rtsopts -Wno-trustworthy-safe -Wno-deprecated-flags -Wnoncanonical-monad-instances -outputdir libraries/Win32/dist-install/build -dep-makefile libraries/Win32/dist-install/build/.depend-v.haskell.tmp -dep-suffix "" -include-pkg-deps libraries/Win32/./Graphics/Win32/GDI.hs libraries/Win32/dist-install/build/Graphics/Win32/GDI/Bitmap.hs libraries/Win32/dist-install/build/Graphics/Win32/GDI/Brush.hs libraries/Win32/dist-install/build/Graphics/Win32/GDI/Clip.hs libraries/Win32/dist-install/build/Graphics/Win32/GDI/Font.hs libraries/Win32/./Graphics/Win32/GDI/Graphics2D.hs libraries/Win32/./Graphics/Win32/GDI/HDC.hs libraries/Win32/dist-install/build/Graphics/Win32/GDI/Palette.hs libraries/Win32/./Graphics/Win32/GDI/Path.hs libraries/Win32/dist-install/build/Graphics/Win32/GDI/Pen.hs libraries/Win32/./Graphics/Win32/GDI/Region.hs libraries/Win32/dist-install/build/Graphics/Win32/GDI/Types.hs libraries/Win32/./Graphics/Win32.hs libraries/Win32/dist-install/build/Graphics/Win32/Control.hs libraries/Win32/dist-install/build/Graphics/Win32/Dialogue.hs libraries/Win32/./Graphics/Win32/Icon.hs libraries/Win32/dist-install/build/Graphics/Win32/Key.hs libraries/Win32/dist-install/build/Graphics/Win32/Menu.hs libraries/Win32/dist-install/build/Graphics/Win32/Message.hs libraries/Win32/dist-install/build/Graphics/Win32/Misc.hs libraries/Win32/dist-install/build/Graphics/Win32/Resource.hs libraries/Win32/dist-install/build/Graphics/Win32/Window.hs libraries/Win32/dist-install/build/Graphics/Win32/LayeredWindow.hs libraries/Win32/dist-install/build/Graphics/Win32/GDI/AlphaBlend.hs libraries/Win32/dist-install/build/Graphics/Win32/Window/AnimateWindow.hs libraries/Win32/dist-install/build/Graphics/Win32/Window/HotKey.hs libraries/Win32/dist-install/build/Graphics/Win32/Window/IMM.hs libraries/Win32/./Graphics/Win32/Window/ForegroundWindow.hs libraries/Win32/dist-install/build/Graphics/Win32/Window/PostMessage.hs libraries/Win32/./Media/Win32.hs libraries/Win32/./System/Win32.hs libraries/Win32/dist-install/build/System/Win32/DebugApi.hs libraries/Win32/dist-install/build/System/Win32/DLL.hs libraries/Win32/dist-install/build/System/Win32/Event.hs libraries/Win32/dist-install/build/System/Win32/File.hs libraries/Win32/dist-install/build/System/Win32/FileMapping.hs libraries/Win32/dist-install/build/System/Win32/Info.hs libraries/Win32/dist-install/build/System/Win32/Path.hs libraries/Win32/dist-install/build/System/Win32/Mem.hs libraries/Win32/dist-install/build/System/Win32/MinTTY.hs libraries/Win32/dist-install/build/System/Win32/NLS.hs libraries/Win32/dist-install/build/System/Win32/Process.hs libraries/Win32/dist-install/build/System/Win32/Registry.hs libraries/Win32/dist-install/build/System/Win32/SimpleMAPI.hs libraries/Win32/dist-install/build/System/Win32/Time.hs libraries/Win32/dist-install/build/System/Win32/Console.hs libraries/Win32/dist-install/build/System/Win32/Security.hs libraries/Win32/dist-install/build/System/Win32/Types.hs libraries/Win32/dist-install/build/System/Win32/Shell.hs libraries/Win32/./System/Win32/Automation.hs libraries/Win32/dist-install/build/System/Win32/Automation/Input.hs libraries/Win32/dist-install/build/System/Win32/Automation/Input/Key.hs libraries/Win32/dist-install/build/System/Win32/Automation/Input/Mouse.hs libraries/Win32/./System/Win32/Console/CtrlHandler.hs libraries/Win32/./System/Win32/Console/HWND.hs libraries/Win32/dist-install/build/System/Win32/Console/Title.hs libraries/Win32/./System/Win32/Encoding.hs libraries/Win32/./System/Win32/Exception/Unsupported.hs libraries/Win32/./System/Win32/HardLink.hs libraries/Win32/dist-install/build/System/Win32/Info/Computer.hs libraries/Win32/dist-install/build/System/Win32/Info/Version.hs libraries/Win32/./System/Win32/String.hs libraries/Win32/dist-install/build/System/Win32/SymbolicLink.hs libraries/Win32/./System/Win32/Thread.hs libraries/Win32/./System/Win32/Utils.hs libraries/Win32/./System/Win32/Word.hs
libraries\Win32\dist-install\build\Graphics\Win32\GDI\Pen.hs:1:1: error:
File name does not match module name:
Saw : ‘Main’
Expected: ‘Graphics.Win32.GDI.Pen’
libraries/Win32/ghc.mk:4: libraries/Win32/dist-install/build/.depend-v.haskell: No such file or directory
make[1]: *** [libraries/Win32/ghc.mk:5: libraries/Win32/dist-install/build/.depend-v.haskell] Error 1
make: *** [Makefile:128: all] Error 2
```
## Environment
* GHC version used: master (commit 36b8a57cb)
Optional:
* Operating System: Windows (Msys2)
* System Architecture: x86_64https://gitlab.haskell.org/ghc/ghc/-/issues/21421Represent dictionaries as unlifted data types2022-04-28T07:36:46ZSebastian GrafRepresent dictionaries as unlifted data types#20897 wonders about representing all dictionaries as data types.
Motivated by thoughts about `-fdicts-strict`, I want to go a step further and wonder: Can we represent all dictionaries as *unlifted* data types? That is, are there usefu...#20897 wonders about representing all dictionaries as data types.
Motivated by thoughts about `-fdicts-strict`, I want to go a step further and wonder: Can we represent all dictionaries as *unlifted* data types? That is, are there useful Haskell programs in which construction of a class dictionary may diverge? I suppose there is `-XUndecidableInstances`, but due to the global nature of dictionaries I think that if a dictionary diverges at definition site (where it would be forced if unlifted) it also has to diverge at use sites (where it needs to be forced even in the lifted scenario).
Note that I'm not advocating for representing the *methods* of dictionaries in some unlifted way, because that indeed would change runtime semantics.
Of course, it's not as simple. Here's a list of challenges:
1. Today, we have `type Constraint = Type`. For this ticket, we'd need `type Constraint = UnliftedType`. But then equality constraints would be unlifted, too and suddenly with GADTs we live in a very different language. I think this is already a nail in the coffin of this idea... Still, an interesting thought experiment.
Alternatively, for a more complicated design without the GADT weakness, we could make equality constraints and dictionaries live in different kinds and provide levity polymorphic constraint tuple constructors. No idea if that is even feasible.
The issue of levity in `Constraint` is a bit frustrating, because embedding an unlifted dictionary into a lifted field of a constraint tuple is a no-op as far dynamic semantics is concerned. We could even freely coerce from unlifted to lifted rep, so technically a lifted `Constraint` can simply embed an unlifted dictionary.
2. We'd need top-level unlifted bindings, #17521.https://gitlab.haskell.org/ghc/ghc/-/issues/21217ghc.compiler.GHC.Cmm.Switch.restrictMap could be more efficient2022-03-15T16:33:32Zjwaldmannghc.compiler.GHC.Cmm.Switch.restrictMap could be more efficientThe first split
```
restrictMap :: (Integer,Integer) -> M.Map Integer b -> M.Map Integer b
restrictMap (lo,hi) m = mid where
(_, mid_hi) = M.split (lo-1) m
(mid, _) = M.split (hi+1) mid_hi
```
might do useless work when the...The first split
```
restrictMap :: (Integer,Integer) -> M.Map Integer b -> M.Map Integer b
restrictMap (lo,hi) m = mid where
(_, mid_hi) = M.split (lo-1) m
(mid, _) = M.split (hi+1) mid_hi
```
might do useless work when the result map is small. See discussion at
https://github.com/haskell/containers/pull/803#issuecomment-1062968905
But .. if it did not show up in profiles before, then perhaps it does not need to be fixed. Anyway I thought I'd mention it here.https://gitlab.haskell.org/ghc/ghc/-/issues/21026Data.Complex.magnitude is very slow sometimes2022-02-03T00:32:02ZJaro ReindersData.Complex.magnitude is very slow sometimesThe `magnitude` function tries very hard to support accurate computations for large exponents:
```haskell
magnitude (x:+y) = scaleFloat k
(sqrt (sqr (scaleFloat mk x) + sqr (scaleFloat mk y)))
w...The `magnitude` function tries very hard to support accurate computations for large exponents:
```haskell
magnitude (x:+y) = scaleFloat k
(sqrt (sqr (scaleFloat mk x) + sqr (scaleFloat mk y)))
where k = max (exponent x) (exponent y)
mk = - k
sqr z = z * z
```
However this can lead to more than 10x slower programs. Here is an example program:
```haskell
import qualified Data.ByteString.Lazy as B
import Data.Complex
import System.Environment
iter = 50
limit = 2
main = do
[arg] <- getArgs
putStr $ "P4\n" ++ arg ++ " " ++ arg ++ "\n"
B.putStr . B.pack . makePBM . map fractal $ points (read arg) (read arg)
points w h =
[ (2 * x / w - 1.5) :+ (2 * y / h - 1)
| y <- [0 .. h - 1]
, x <- [0 .. w - 1]
]
fractal c = length . takeIter $ iterate (\z -> z * z + c) c
where
takeIter = take iter . takeWhile (\z -> magnitude z < limit)
makePBM =
map
( foldl (\n x -> n * 2 + if x == iter then 1 else 0) 0
. rightPad 8 0
)
. chunksOf 8
chunksOf _ [] = []
chunksOf n xs = let (l, r) = splitAt n xs in l : chunksOf n r
rightPad n x xs = foldr (\x go n -> x : go (n - 1)) (`replicate` x) xs n
```
When compiled with `ghc -O2 -fllvm` and running with `./SimpleMandelbrot 1024 >/dev/null +RTS -s` takes 2.136s. In comparison replacing `magnitude z` with `sqrt (x * x + y * y)` where `x :+ y = z`, makes the program run in 0.184s. This difference gets even larger for larger inputs such as `16000` for which I've measured about 700 seconds without vs. about 40 seconds with this simple change.
Note that using LLVM is quite critical, I think LLVM is able to compile that `sqrt x < c` to `x < c * c`, but even if I apply that manually LLVM still outperforms the native back end.
Is this enough reason to change the default implementation of `magnitude`? Should we add a second `magnitudeFast` function?
## Environment
* GHC version used: 8.10.7https://gitlab.haskell.org/ghc/ghc/-/issues/20897All classes as data types, even single-methods ones?2023-07-03T11:04:01ZJoachim Breitnermail@joachim-breitner.deAll classes as data types, even single-methods ones?
## Motivation
Currently, single-method classes (more precisely single-method-or-superclass) are implemented as `newtypes`’s around that method; see `Note [Single-method classes]`. Roughly, where we have
```
class C a where { op :: a...
## Motivation
Currently, single-method classes (more precisely single-method-or-superclass) are implemented as `newtypes`’s around that method; see `Note [Single-method classes]`. Roughly, where we have
```
class C a where { op :: a -> a }
```
we implement the class as
```
newtype C a = MkC (a->a)
```
The benefit of the status quo is that these classes are cheaper at run time (no need to project out of a dictionary; less allocation when dictinaries aren’t static anyways).
But there are various downsides:
1. We are [strongly considering](https://gitlab.haskell.org/ghc/ghc/-/issues/11715#note_431287) making `Type` and `Constraint` always and everywhere distinct. But the newtype axiom for the class `C` would be `ax :: C a ~ a->a`; and hence `KindCo ax :: Constraint ~ Type`, which is a bit like having an axiom `Int ~ Bool` -- chaos would result. Not using newtypes for classes would unblock this road, with many desirable consequences.
1. Having newtype classes leads to special cases in GHC, newtype-backed classes and data-backed classes need to be handled differently. (This still needs to be quantified.)
1. RULES on class methods don't work well with new-type backed classes. This is tracked in [this note](https://gitlab.haskell.org/ghc/ghc/-/issues/20535#note_385694); the gist is that (currently) class ops and dfuns of newtype-packed classes inline early and aggressively, to expose their cheap definition (it’s just a cast after all), and this gets in the way of matching RULES against class ops and dfuns.
This issue can likely be fixed with reasonable amount of extra work (delaying inlining etc.), but if classes were uniform there would be no need to figure this out.
1. The `-fdicts-strict` flags currently has to exclude newtype-backed classes, because functions that are strict in the dict should not be strict in the method. #17758 proposes to make `-fdicts-strict` by default, and this would make things more uniform again.
1. Currently classes cannot have unlifted methods, mainly (we think) because that wouldn't work for newtype classes. We could lift this restriction.
1. #21229 says we should not inline DFuns. But it is is jolly hard not to inline newtype DFuns (!7788). NB: #21229 is only closed because we reverted an earlier (otherwise highly desirable), and opened #21470.
## Proposal
So in [this comment](https://gitlab.haskell.org/ghc/ghc/-/issues/20535#note_385765_ Simon PJ suggests **Plan A**, that maybe it’s better to drop this special-casing and compile all classes alike. I’m opening this issue as a place to discuss this, independent of the problem in #20535 (which may have other solutions).
This ticket summarises work on this idea.
If performance is affected too much, an alternative **Plan B** could be:
* Make single-method classes look like vanilla data types, with a single, unary data constructor, right up to the code generator
* But compile `(MkC x)` as `x`, and `case c of MkC x -> blah` as `blah[c/x]`; that is discard the boxing and unboxing
* The Simplifier would have to behave as now, with special cases for single-method classes, since they would not really be lifted after all.
I prefer Plan A because it's simpler, if the perf implications are acceptable.
Draft MR: !7278
## Worries
Why *not* do this?
* Performance. Maybe there are cases where not having that extra box for a single-method class is super-important.
* The `reflection` library makes cunning use (via `unsafeCoerce`) of the (undocumented) fact that single-method classes are implemented with newtypes. Fortunately, our new `withDict` story allows `reflection` not to rely on such undocumented accidents, nor on `unsafeCoerce`. See #21568 for our plan.https://gitlab.haskell.org/ghc/ghc/-/issues/20771Be more specific when reporting import errors2022-07-21T13:40:49Zsheafsam.derbyshire@gmail.comBe more specific when reporting import errorsCurrently, with code such as:
```haskell
import Blahblah1 -- does not export foo
import Blahblah2 (foo)
bar = Blahblah1.foo
```
We simply get an error saying that `Blahblah1` does not export `foo`. But we could do suggest more fine-gr...Currently, with code such as:
```haskell
import Blahblah1 -- does not export foo
import Blahblah2 (foo)
bar = Blahblah1.foo
```
We simply get an error saying that `Blahblah1` does not export `foo`. But we could do suggest more fine-grained information:
- suggest that the user might have mis-spelled `Blahblah2` (as that module does export `foo`),
- perhaps `Blahblah1` defines foo but does not export it, so we could suggest that `foo` be added to the export list of `Blahblah1` (perhaps only if `Blahblah1` is from the current package).https://gitlab.haskell.org/ghc/ghc/-/issues/20522Backpack puts information in the EPS that depends on the HPT, causing issues ...2022-02-23T20:02:02Zsheafsam.derbyshire@gmail.comBackpack puts information in the EPS that depends on the HPT, causing issues with recompilationI've noticed a strange interaction of Backpack with `GHCi`. For readability I'm giving the test case as a `.bkp`, but note that as `--backpack` isn't supported by `GHCi`, the actual test case uses cabal.
```haskell
unit p where
sign...I've noticed a strange interaction of Backpack with `GHCi`. For readability I'm giving the test case as a `.bkp`, but note that as `--backpack` isn't supported by `GHCi`, the actual test case uses cabal.
```haskell
unit p where
signature H where
data S1
data S2
module A where
import H
data T = T S1 S2
unit q where
dependency p[H=<H2>] (A as A2)
module L where
data S1 = MkS1
signature H2(S1(MkS1), S2) where
import L
data S2
module B where
import A2
import H2
t = T :: S1 -> S2 -> T
```
When processing `q`, we instantiate `p` with `H = H2` and add it to the EPS, even though it refers to `L` and `H2` which are in the HPT. This is a problem, as the EPS is supposed to only contain stable information, whereas the HPT can be updated; any change to the HPT will not be reflected in the EPS and thus will refer to out of date information.
To demonstrate this, we can load everything in GHCi, change `H2` and reload. (Recall: using cabal, not `--backpack` mode which doesn't work with `GHCi`.)
```
[1 of 2] Compiling H[sig] ( p\H.hsig, nothing )
[2 of 2] Compiling A ( p\A.hs, nothing )
[1 of 1] Instantiating bkp10-0-inplace-p
[1 of 4] Compiling H2[sig] ( q\H2.hsig, nothing )
[2 of 4] Instantiating bkp10-0-inplace-p
[3 of 4] Compiling B ( q\B.hs, nothing )
[4 of 4] Compiling L ( q\L.hs, nothing )
Ok, three modules loaded.
now I change H2 so that S1 is defined in H2 instead of imported from L
ghci> :r
[2 of 4] Compiling H2[sig] ( q\H2.hsig, nothing ) [Source file changed]
[3 of 4] Instantiating bkp10-0-inplace-p
[4 of 4] Compiling B ( q\B.hs, nothing ) [H2 changed]
q\B.hs:4:9: error:
* Couldn't match type `{H2.S1}' with `S1'
Expected: S1 -> S2 -> T
Actual: {H2.S1} -> S2 -> T
NB: `S1' is defined at q\L.hs:3:3-16
`{H2.S1}' is defined at q\H2.hsig:3:5-11
if I quit and restart, it works:
[1 of 1] Instantiating bkp10-0-inplace-p
[3 of 4] Instantiating bkp10-0-inplace-p
[4 of 4] Compiling B ( q\B.hs, nothing ) [H2 changed]
Ok, three modules loaded.
```https://gitlab.haskell.org/ghc/ghc/-/issues/20517Backpack doesn't reject insufficiently instantiated units early enough2022-02-23T14:03:03Zsheafsam.derbyshire@gmail.comBackpack doesn't reject insufficiently instantiated units early enoughFailing to instantiate a unit which has free holes does not raise an error when it should, so we get a confusing error later on:
```haskell
unit p where
signature H where
data S
unit q where
dependency p -- we should instantiat...Failing to instantiate a unit which has free holes does not raise an error when it should, so we get a confusing error later on:
```haskell
unit p where
signature H where
data S
unit q where
dependency p -- we should instantiate, e.g. by writing p[H=<H>], but we don't
module N where
import H
```
```
error:
Could not find module `H'
It is not a module in the current program, or in any known package.
|
7 | import H
| ^^^^^^^^
```
I think we should be required to instantiate `p`, getting an error early on.
This doesn't only affect `.bkp` files, as omitting instantiation can also cause "Could not find module" errors when using `cabal`.https://gitlab.haskell.org/ghc/ghc/-/issues/20515Inconsistent constructor name causes a panic in signature files2021-10-15T10:12:17Zsheafsam.derbyshire@gmail.comInconsistent constructor name causes a panic in signature filesIf I declare a data constructor, and export it from a signature with a different name, I get a panic, as in the following `.bkp` file:
```haskell
unit p where
signature H(S(MkS)) where
data S = NotMkS
```
```
ghc: panic! (the 'im...If I declare a data constructor, and export it from a signature with a different name, I get a panic, as in the following `.bkp` file:
```haskell
unit p where
signature H(S(MkS)) where
data S = NotMkS
```
```
ghc: panic! (the 'impossible' happened)
(GHC version 9.0.1:
nameModule
internal MkS_02y
Call stack:
CallStack (from HasCallStack):
callStackDoc, called at compiler\GHC\Utils\Outputable.hs:1230:37 in ghc:GHC.Utils.Outputable
pprPanic, called at compiler\GHC\Types\Name.hs:282:3 in ghc:GHC.Types.Name
```
This happens in general Backpack usage (i.e. isn't limited to `.bkp` files).https://gitlab.haskell.org/ghc/ghc/-/issues/20462GC improvement: keep separate object metadata in a compact set of memory page...2021-11-27T13:32:34ZOrpheusGC improvement: keep separate object metadata in a compact set of memory pages to avoid full sweeping## Motivation
In the current implementation, both the blocking and non-moving GC seem (I didn't check the code) to sweep over all allocated memory pages of the heap. This causes trashing when swap space is used to complement main memory...## Motivation
In the current implementation, both the blocking and non-moving GC seem (I didn't check the code) to sweep over all allocated memory pages of the heap. This causes trashing when swap space is used to complement main memory. Even without swap space and the problem of trashing, this is a problem for two reasons: (1) in the case of blocking GC it causes long downtime especially if the heap is large and the memory bandwidth is low (e.g. Raspberry Pi); (2) in the case of non-blocking GC, it causes heavy competition for memory bandwidth, slowing down memory accesses.
## Proposal
A much better approach would be to keep a separate compact set of memory pages with metadata about what objects are present in the allocation areas, so that the garbage collector has to sweep over a small memory area only and directly release the other memory pages without touching them.https://gitlab.haskell.org/ghc/ghc/-/issues/19966Out-of-scope variables not deferred with type constructors2021-06-11T21:00:38ZKrzysztof GogolewskiOut-of-scope variables not deferred with type constructorsIn HEAD, `-fdefer-out-of-scope-variables` can no longer defer an out-of-scope identifier if it exists on the type level.
```
ghci> :set -fdefer-out-of-scope-variables
ghci> x = I
<interactive>:2:5: warning: [-Wdeferred-out-of-scope-va...In HEAD, `-fdefer-out-of-scope-variables` can no longer defer an out-of-scope identifier if it exists on the type level.
```
ghci> :set -fdefer-out-of-scope-variables
ghci> x = I
<interactive>:2:5: warning: [-Wdeferred-out-of-scope-variables]
Data constructor not in scope: I
ghci> x = IO
<interactive>:3:5: error:
• Illegal term-level use of the type constructor ‘IO’
imported from ‘Prelude’ (and originally defined in ‘GHC.Types’)
• In the expression: IO
In an equation for ‘x’: x = IO
```
In 9.0, `x = IO` behaves the same as `x = I`.
With Dependent Haskell we might ultimately allow `x = IO` to mean the type constructor, but the current situation is a bit inconsistent.
Low priority. Related: #17102.Vladislav ZavialovVladislav Zavialovhttps://gitlab.haskell.org/ghc/ghc/-/issues/19767GHC should generate workers with unlifted arguments for lifted types.2023-10-30T10:35:14ZAndreas KlebingerGHC should generate workers with unlifted arguments for lifted types.## Motivation
We already have good machinery to facilitate construction and deconstruction canceling out between caller and callee using WW.
I feel like we could reasonably expand this machinery to also facilitate to some degree avoidi...## Motivation
We already have good machinery to facilitate construction and deconstruction canceling out between caller and callee using WW.
I feel like we could reasonably expand this machinery to also facilitate to some degree avoiding re-evaluating/tag checks on values between caller and callee.
Currently if we have a silly function like this:
```haskell
{-# NOINLINE foo #-}
foo !x !y !z !n =
x || y || z || n > (1 :: Int)
```
It will evaluate x/x/z at **least** twice. Once for the seqs added by the bangs, and once for actual control flow. Tag inference will at least avoid evaluating these twice inside the body.
But what if the caller had already cased on the the arguments? Then we *still* recheck for the tag in the worker.
The worker currently looks like this:
```A.$wfoo
= \ (w_s1mU :: Bool)
(w1_s1mV :: Bool)
(w2_s1mW :: Bool)
(ww_s1n0 :: Int#) ->
case w1_s1mV of y_X1 { __DEFAULT ->
case w2_s1mW of z_X2 { __DEFAULT ->
case w_s1mU of {
False ->
case y_X1 of {
False ->
case z_X2 of {
False -> tagToEnum# @Bool (># ww_s1n0 1#);
True -> GHC.Types.True
};
True -> GHC.Types.True
};
True -> GHC.Types.True
}
}
}
```
But with [unlifted data types](https://gitlab.haskell.org/ghc/ghc/-/wikis/unlifted-data-types) we shouldn't need to do so.
It would be wonderful if we could instead generate a worker like this:
```haskell
A.$wfoo
= \ (w_s1mU :: unlifted Bool)
(y_X1 :: unlifted Bool)
(z_X2 :: unlifted Bool)
(ww_s1n0 :: Int#) ->
case lift w_s1mU of { -- lift to bring it back into the lifted domain,
-- but tag inference could still elid the tag check easily.
False ->
case lift y_X1 of {
False ->
case lift z_X2 of {
False -> tagToEnum# @Bool (># ww_s1n0 1#);
True -> GHC.Types.True
};
True -> GHC.Types.True
};
True -> GHC.Types.True
}
}
}
```
And the decision of weither or not a lifted argument could be driven by demand analysis much in the same way as we drive unboxing currently. Only it would naturally apply to sum types and avoid the risk of reboxing.
The wrapper would be a bigger problem. In the absence of changing Core (which might be reasonable) we would need something like this as a wrapper:
foo
= \ (w_s1mU :: Bool)
(w1_s1mV :: Bool)
(w2_s1mW :: Bool)
(w3_s1mX :: Int) ->
case seqCoerce# w_s1mU of u -> -- seqCoerce# would cancel out with seqs in the caller via tag inference during codegen.
case seqCoerce# w1_s1mV of v ->
case seqCoerce# w2_s1mW of w ->
case w3_s1mX of { I# ww1_s1n0 ->
A.$wfoo u v w ww1_s1n0
}
------
This is not meant as a concrete implementation proposal. But the idea of having WW passing arguments unlifted crossed my mind a lot during the work on tag inference. None of this needs to be exposed to users so I think it would be reasonable.
It's also a bit open how useful this would be. It obviously adds work for the compiler at the very least so it would need to pay it's dues. And with enough inlining there are very few boundries across which repeated seqs would cancel out to pay these.
However it would allow W/W to improve things where unboxing isn't an option. So hard to say without spending some time looking into this further. Which I don't plan to do in the near future.https://gitlab.haskell.org/ghc/ghc/-/issues/19612Split up PState2021-04-03T01:14:57ZSebastian GrafSplit up PStateThe `PState` record is huge (25 fields) and will be updated *on every token lexed*. That's about 25*8=200 bytes allocation for every byte lexed, for `PState` update alone! I see that we already store a `ParserOpts` field in `PState` that...The `PState` record is huge (25 fields) and will be updated *on every token lexed*. That's about 25*8=200 bytes allocation for every byte lexed, for `PState` update alone! I see that we already store a `ParserOpts` field in `PState` that will probably be mostly constant throughout. But there are also a lot of other fields which probably don't change that often, which we could push into a secondary state parameter. E.g. maybe we can manage to have a `HotPState` (`buffer`, `last_tk`, `*loc`, ...) that is small and changes for every `AlexToken` emitted and a `SlowPState` (`warnings`, `errors`, `tab_fist`, ...) that changes only sometimes. Maybe split up that one too into a State record for things that are modified together. We could thread them as separate parameters in the `P` monad or as a tuple/strict `PState` record.https://gitlab.haskell.org/ghc/ghc/-/issues/19477Rebindable Syntax and LinearTypes (allow a version of RebindableSyntax withou...2021-04-08T09:55:27ZEdward KmettRebindable Syntax and LinearTypes (allow a version of RebindableSyntax without ifThenElse)When working with both `LinearTypes` and unlifted data types, I find I often want to use `RebindableSyntax` to overload things.
However, right now `RebindableSyntax` is one monolithic switch which turns on things that are desirable to o...When working with both `LinearTypes` and unlifted data types, I find I often want to use `RebindableSyntax` to overload things.
However, right now `RebindableSyntax` is one monolithic switch which turns on things that are desirable to overload e.g. numeric literals, but also turns on things that I can't properly typecheck myself, such as `ifThenElse`.
Being able to split apart the scope of `RebindableSyntax` to allow the exclusion of `ifThenElse` would suffice.
## Alternatives
Morally, one can view the issue that viewed as a function `ifThenElse` doesn't really look like `ifThenElse :: Bool -> a -> a -> a`. The one supplied by GHC has superpowers that such a function lacks.
First, it works for all runtime representations, and it only forces one of its arguments. You see this if you to to define
```haskell
ifThenElse :: forall (a :: TYPE 'IntRep). Bool -> a -> a -> a
ifThenElse True t _ = t
ifThenElse False _ f = f
```
Evaluating `ifThenElse False undefined 1#` now throws an exception.
We can fix this part by defining
```haskell
type Lev (a :: TYPE r) = ()~() => a
ifThenElse :: forall (a :: TYPE r). Bool -> Lev a -> Lev a -> a
ifThenElse True t _ = t
ifThenElse False _ f = f
```
Now, `ifThenElse False undefined 1#` returns `1#` as expected. Lev also trickily let us side-step any levity polymorphism concerns with taking values of unknown `RuntimeRep` in negative position.
However, even if we can fix the levity issue we can't currently fix the linearity issue with the current type.
```haskell
ifThenElse :: forall (a :: TYPE r). Bool -> a -> a -> a
```
isn't general enough to handle `if _ then _ else _` at linear types.
We can't put
```haskell
ifThenElse :: forall (a :: TYPE r). Bool -> a %1 -> a %1 -> a
```
as we don't use each branch linearly. Morally we don't take two functions, we take the "with" or `&` of two functions in the linear logic sense. `With a b` isn't two separate arguments it a single-shot user choice to get one of the two things. It is the third linear logic connective that usually shows up in intuitionistic linear logic. In the vending machine metaphor. `(a,b)` is the ability/requirement to consume `a` and `b` both. `Either a b` is the ability/requirement to consume `a` or `b`, but you don't get to pick which, it is the suppliers choice. `With a b` is the ability/requirement to consume `a` or `b`, but the consumer gets to pick. That is exactly what `ifThenElse` is doing above when linear types are turned on.
We can model `With` in haskell as a function.
```haskell
data Choice a b x where
L :: Choice a b a
R :: Choice a b b
newtype With a b = With { runWith :: (forall x. Choice a b x %1 -> x) }
pickL :: With a b -> a
pickR :: With a b -> b
```
Then a user version of `ifThenElse` morally wants to consume the `With` of two code branches it is supplied.
However, here the rabbit hole ends, it's not really all that convenient to define such a beast, and even if we made up a `With` data type and used it to wrap both branches of the ifThenElse, this style of overloading `ifThenElse` isn't compatible with the version that arises in EDSLs and needs `GADTs`, `RankNTypes`...
As a result, I currently have to just advocate for users using `MultiWayIf` or pattern guards if they use my library, but would like to be able to leave them access to `if then else` notation.
*tl;dr* I'd like some way to split off `ifThenElse` from `RebindableSyntax` it is currently quite the blunt instrument and `ifThenElse` currently _can't_ be overloaded correctly in light of new language features.https://gitlab.haskell.org/ghc/ghc/-/issues/19391User guide sections are in a strange order2024-01-26T16:54:13ZMatthew PickeringUser guide sections are in a strange orderThe sections in the user guide are in a bit of a strange order. I would expect "Using GHC" to appear before "Using GHCi" and "Using runhaskell".
![2021-02-17-083942_262x880](/uploads/5c365f5c9afaf94eeb142fe7c902955d/2021-02-17-083942_26...The sections in the user guide are in a bit of a strange order. I would expect "Using GHC" to appear before "Using GHCi" and "Using runhaskell".
![2021-02-17-083942_262x880](/uploads/5c365f5c9afaf94eeb142fe7c902955d/2021-02-17-083942_262x880.png)https://gitlab.haskell.org/ghc/ghc/-/issues/18897Infinite floating point literal not possible2024-01-24T14:22:58ZBen GamariInfinite floating point literal not possibleOne thing that I have noticed in the past is that it is not possible to embed an efficient floating point literal in one's program. For instance, you might write:
```haskell
f :: Double -> ...
g = ... f (1/0)
```
However, GHC will end ...One thing that I have noticed in the past is that it is not possible to embed an efficient floating point literal in one's program. For instance, you might write:
```haskell
f :: Double -> ...
g = ... f (1/0)
```
However, GHC will end up floating out the free expression `1/0` to a top-level CAF. This means that you must take a tag check every time you refer to the literal. Surely we can do better than this.
Either we should avoid floating out such simple expressions or we should introduce constant-folding for this case and teach C-- about non-finite floating-point literals.
Other literals:
- `1/0` -> infinity (this one), similarly for negative infinity
- `0/0` -> NaN (one particular NaN literal should suffice), originally reported in #20379
- `-0.0` -> negative zero. Currently compiles to `negateFloat# 0.0#`, orginally reported in #20380.https://gitlab.haskell.org/ghc/ghc/-/issues/17078hpc: do away with String, to avoid making a write() syscall per character2020-01-23T19:42:30ZAlp Mestanogullarihpc: do away with String, to avoid making a write() syscall per characterFrom https://gitlab.haskell.org/ghc/ghc/merge_requests/1598#note_218752 (by @nh2):
> At some point we probably want to switch this away from `String` entirely, given that `hPutStr` floods syscalls by doing one `write()` syscall *for eac...From https://gitlab.haskell.org/ghc/ghc/merge_requests/1598#note_218752 (by @nh2):
> At some point we probably want to switch this away from `String` entirely, given that `hPutStr` floods syscalls by doing one `write()` syscall *for each character*.
This is obviously quite inefficient and should be replaced by code that makes as few `write()` syscalls as possible.https://gitlab.haskell.org/ghc/ghc/-/issues/16965Error spans of unused imports could be improved2021-02-02T02:29:06ZÖmer Sinan AğacanError spans of unused imports could be improvedExample:
```
compiler/codeGen/StgCmmExpr.hs:44:1: warning: [-Wunused-imports]
The import of ‘primRepSlot’ from module ‘RepType’ is redundant
|
44 | import RepType ( isVoidTy, countConRepArgs, primRepSlot )
| ^^^^^^^^^...Example:
```
compiler/codeGen/StgCmmExpr.hs:44:1: warning: [-Wunused-imports]
The import of ‘primRepSlot’ from module ‘RepType’ is redundant
|
44 | import RepType ( isVoidTy, countConRepArgs, primRepSlot )
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
compiler/codeGen/StgCmmExpr.hs:53:1: warning: [-Wunused-imports]
The import of ‘Data.Function’ is redundant
except perhaps to import instances from ‘Data.Function’
To import instances alone, use: import Data.Function()
|
53 | import Data.Function ( on )
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
Second error message is fine, but in the first one the span looks as if the
whole import line is the problem. I think a better error would be:
```
compiler/codeGen/StgCmmExpr.hs:44:54: warning: [-Wunused-imports]
The import of ‘primRepSlot’ from module ‘RepType’ is redundant
|
44 | import RepType ( isVoidTy, countConRepArgs, primRepSlot )
| ^^^^^^^^^^^
```
Now it's clear that only the `primRepSlot` part is the problem.
(Note that in the "improved" error message I also updated the "column" part of
the location)⊥https://gitlab.haskell.org/ghc/ghc/-/issues/16896Template Haskell quotes aren't reified in source-level Haskell2019-07-07T17:59:56ZisovectorTemplate Haskell quotes aren't reified in source-level Haskell# Summary
The expression, `d`, `t`, and `p` templatehaskell-quotes are syntactically magic, and don't exist anywhere as `QuasiQuoter`s. This breaks any chance of composition.
# Steps to reproduce
I'm unable to write the following:
``...# Summary
The expression, `d`, `t`, and `p` templatehaskell-quotes are syntactically magic, and don't exist anywhere as `QuasiQuoter`s. This breaks any chance of composition.
# Steps to reproduce
I'm unable to write the following:
```haskell
transformType :: Type -> Type
tt = QuasiQuoter
tt = QuasiQuoter
{ quoteType = fmap TransformType . quoteType t
}
foo :: [tt| Some Type |]
foo = blah
```
Instead I need to explicitly inline this composition anywhere I might need it:
```haskell
foo = $(transformType [t| Some Type |])
foo = blah
```
# Expected behavior
The TH-quotes behave just like any other `QuasiQuoter`.⊥