GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2019-07-07T18:03:34Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/15657Support promotion of pattern synonyms to kinds2019-07-07T18:03:34Zinfinity0Support promotion of pattern synonyms to kindsSuppose we define a heterogeneous binary tree:
```hs
{-# LANGUAGE
DataKinds
, GADTs
, PatternSynonyms
#-}
data Tree a = TLeaf | TNode a (Tree a) (Tree a)
data HTree xs where
HLeaf :: HTree 'TLeaf
HNode :: x -> HTree ls -...Suppose we define a heterogeneous binary tree:
```hs
{-# LANGUAGE
DataKinds
, GADTs
, PatternSynonyms
#-}
data Tree a = TLeaf | TNode a (Tree a) (Tree a)
data HTree xs where
HLeaf :: HTree 'TLeaf
HNode :: x -> HTree ls -> HTree rs -> HTree ('TNode x ls rs)
```
A tree representation is chosen because it's pretty general, and easy to combine - just `HNode` a bunch of them together. With a `HList` for example, it's harder to do this in nested fashion, and we want to be able to do that for the `$BigRealWorld` things we're writing.
However in the majority of cases, the `$BigRealWorld` things defined by actual clients of the API don't need the full power of the HTree, and so pattern synonyms potentially allow them to easily define a tree of one item, or a small unnested list of items.
```hs
-- as above, then:
pattern TPure :: a -> Tree a
pattern TPure a = TNode a TLeaf TLeaf
pattern TCons :: a -> Tree a -> Tree a
pattern TCons x y = TNode x TLeaf y
pattern HTPure :: x -> HTree ('TPure x) -- error, has to be ('TNode x 'TLeaf 'TLeaf)
pattern HTPure a = HNode a HLeaf HLeaf
clientThing :: HTree ('TPure Int) -- error, has to be ('TNode Int 'TLeaf 'TLeaf)
clientThing = HTPure 3
```
Oh no! GHC fails with:
```
• Pattern synonym ‘TPure’ cannot be used here
(Pattern synonyms cannot be promoted)
• In the first argument of ‘HTree’, namely ‘( 'TPure x)’
In the type ‘x -> HTree ( 'TPure x)’
|
20 | pattern HTPure :: x -> HTree ('TPure x)
```
Actually the first one is not a big deal, we only write that once so it doesn't matter if we need to expand it fully. But things like `clientThing` might be defined several times and then it's annoying to have to write the synonym out in full every time.
I appreciate `ViewPatterns` make it hard to do this and would be totally happy with a solution that only works to promote non-ViewPattern pattern synonyms.8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15655Simpliify tcTyConScopedTyVars2020-05-23T05:58:52ZSimon Peyton JonesSimpliify tcTyConScopedTyVarsCurrently we have
```
tcTyConScopedTyVars :: [(Name,TyVar)],
```
But actually every call of `mkTcTyCon` passes something like `(mkTyVarNamePairs tvs)` to it. So we could noticeably simplify this to
```
tcTyConScopedTyV...Currently we have
```
tcTyConScopedTyVars :: [(Name,TyVar)],
```
But actually every call of `mkTcTyCon` passes something like `(mkTyVarNamePairs tvs)` to it. So we could noticeably simplify this to
```
tcTyConScopedTyVars :: [TyVar],
```
Less fiddling around.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.4.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":"Simpliify tcTyConScopedTyVars","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Currently we have\r\n{{{\r\n tcTyConScopedTyVars :: [(Name,TyVar)],\r\n}}}\r\nBut actually every call of `mkTcTyCon` passes something like `(mkTyVarNamePairs tvs)` to it. So we could noticeably simplify this to \r\n{{{\r\n tcTyConScopedTyVars :: [TyVar],\r\n}}}\r\nLess fiddling around.","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15652SerializedCompact has a [(Ptr a, Word)] instead of a custom datatype2021-01-24T06:20:32ZchessaiSerializedCompact has a [(Ptr a, Word)] instead of a custom datatype```hs
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}
```
I'm not sure why the first member of `SerializedCompact` isn't something like
```hs
data Co...```hs
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [(Ptr a, Word)]
, serializedCompactRoot :: Ptr a
}
```
I'm not sure why the first member of `SerializedCompact` isn't something like
```hs
data CompactBlock a = CompactBlock {-# UNPACK #-} (Ptr a) {-# UNPACK #-} Word
```
so the `Ptr` can unpack into the constructor, which isn't possible with `(,)`. `SerializedCompact` would then look like
```hs
data SerializedCompact a = SerializedCompact
{ serializedCompactBlockList :: [CompactBlock a]
, serializedCompactRoot :: Ptr a
}
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------ |
| Version | 8.4.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries/compact |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | andrewthad, ezyang |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"SerializedCompact has a [(Ptr a, Word)] instead of a custom datatype","status":"New","operating_system":"","component":"libraries/compact","related":[],"milestone":"8.8.1","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"ezyang"},"version":"8.4.3","keywords":["compact","ghc-compact,","regions"],"differentials":[],"test_case":"","architecture":"","cc":["andrewthad","ezyang"],"type":"Bug","description":"{{{#!hs\r\ndata SerializedCompact a = SerializedCompact\r\n { serializedCompactBlockList :: [(Ptr a, Word)]\r\n , serializedCompactRoot :: Ptr a\r\n }\r\n}}}\r\n\r\nI'm not sure why the first member of {{{SerializedCompact}}} isn't something like\r\n\r\n{{{#!hs\r\ndata CompactBlock a = CompactBlock {-# UNPACK #-} (Ptr a) {-# UNPACK #-} Word\r\n}}}\r\n\r\nso the {{{Ptr}}} can unpack into the constructor, which isn't possible with {{{(,)}}}. {{{SerializedCompact}}} would then look like\r\n\r\n{{{#!hs\r\ndata SerializedCompact a = SerializedCompact\r\n { serializedCompactBlockList :: [CompactBlock a]\r\n , serializedCompactRoot :: Ptr a\r\n }\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->Edward Z. YangEdward Z. Yanghttps://gitlab.haskell.org/ghc/ghc/-/issues/15651Check if some auto apply code is dead and remove if appropriate.2021-09-07T15:56:33ZAndreas KlebingerCheck if some auto apply code is dead and remove if appropriate.There is a whole family of stg_ap_stk_\* and stg_stk_save_\* functions generated in AutoApply.cmm which as far as I can tell is not used anywhere in the compiler and can likely be removed.
In particular this would involve:
- Stop the c...There is a whole family of stg_ap_stk_\* and stg_stk_save_\* functions generated in AutoApply.cmm which as far as I can tell is not used anywhere in the compiler and can likely be removed.
In particular this would involve:
- Stop the code in question from being generated. (utils/genapply)
- Make sure that doesn't break things. (Validate/Run the testsuite).
- Grep for stk in the compiler to make sure we don't build calls to these in rare circumstances with string concatenation for extra safety.
- Document the change in patch notes just in case.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.4.3 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Check if some auto apply code is dead and remove if appropriate.","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":["Newcomer"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"There is a whole family of stg_ap_stk_* and stg_stk_save_* functions generated in AutoApply.cmm which as far as I can tell is not used anywhere in the compiler and can likely be removed.\r\n\r\nIn particular this would involve:\r\n* Stop the code in question from being generated. (utils/genapply)\r\n* Make sure that doesn't break things. (Validate/Run the testsuite).\r\n* Grep for stk in the compiler to make sure we don't build calls to these in rare circumstances with string concatenation for extra safety.\r\n* Document the change in patch notes just in case.","type_of_failure":"OtherFailure","blocking":[]} -->⊥https://gitlab.haskell.org/ghc/ghc/-/issues/15650Add (or document if already exist) ability to derive custom typeclasses via s...2023-06-09T09:15:40ZDmitrii KovanikovAdd (or document if already exist) ability to derive custom typeclasses via source plugins## Problem
Suppose, I have some custom typeclass `Foo` defined in some library `foo`:
```hs
class Foo a where
... some methods ...
```
I would like to be able to derive instances of this typeclass for any possible data type using ...## Problem
Suppose, I have some custom typeclass `Foo` defined in some library `foo`:
```hs
class Foo a where
... some methods ...
```
I would like to be able to derive instances of this typeclass for any possible data type using `deriving` clause just like GHC already does for typeclasses `Eq`, `Ord`, `Show`, `Read`, `Enum`, etc.:
```hs
data Bar = Bar | Baz
deriving (Eq, Ord, Foo)
```
There're already two possible ways to derive instances of custom typeclasses:
1. `anyclass` deriving strategy (usually involves `Generic`)
1. `-XTemplateHaskell` solution.
But I would like to have source-plugin-based solution for this problem so I can just add `-fplugin=Foo.Plugin` and enjoy deriving capabilities.
## Advantage over existing approaches
Solution with `-XTemplateHaskell` is not that pleasant to write and easy to maintain (you need to use libraries like http://hackage.haskell.org/package/th-abstraction to support multiple GHC versions),involves scoping restriction and is syntactically uglier. Compare:
```hs
{-# LANGUAGE TemplateHaskell #-}
data Bar = Bar | Baz
deriving (Eq, Ord)
deriveFoo ''Bar
```
Solution with something like `Generic` introduces performance overhead (required for to/from generic representation conversion). This might not be significant for something like *parsing CLI arguments* but it's more important if you want to have efficient binary serialisation.
Also, it's known that deriving typeclasses is a relatively slow compilation process (https://github.com/tfausak/tfausak.github.io/issues/127) so there's slight chance that deriving typeclass manually can be slightly faster than deriving `Generic + MyClass`. Especially when maintainers of plugins can experiment with some caching strategies for deriving typeclasses.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.6.1-beta1 |
| 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":"Add (or document if already exist) ability to derive custom typeclasses via source plugins","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.1-beta1","keywords":["plugins,deriving,typeclass","source"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"== Problem\r\n\r\nSuppose, I have some custom typeclass `Foo` defined in some library `foo`:\r\n\r\n{{{#!hs\r\nclass Foo a where\r\n ... some methods ...\r\n}}}\r\n\r\nI would like to be able to derive instances of this typeclass for any possible data type using `deriving` clause just like GHC already does for typeclasses `Eq`, `Ord`, `Show`, `Read`, `Enum`, etc.:\r\n\r\n{{{#!hs\r\ndata Bar = Bar | Baz\r\n deriving (Eq, Ord, Foo)\r\n}}}\r\n\r\nThere're already two possible ways to derive instances of custom typeclasses:\r\n\r\n1. `anyclass` deriving strategy (usually involves `Generic`)\r\n2. `-XTemplateHaskell` solution.\r\n\r\nBut I would like to have source-plugin-based solution for this problem so I can just add `-fplugin=Foo.Plugin` and enjoy deriving capabilities.\r\n\r\n== Advantage over existing approaches\r\n\r\nSolution with `-XTemplateHaskell` is not that pleasant to write and easy to maintain (you need to use libraries like http://hackage.haskell.org/package/th-abstraction to support multiple GHC versions),involves scoping restriction and is syntactically uglier. Compare:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n\r\ndata Bar = Bar | Baz\r\n deriving (Eq, Ord)\r\n\r\nderiveFoo ''Bar\r\n}}}\r\n\r\nSolution with something like `Generic` introduces performance overhead (required for to/from generic representation conversion). This might not be significant for something like ''parsing CLI arguments'' but it's more important if you want to have efficient binary serialisation. \r\n\r\nAlso, it's known that deriving typeclasses is a relatively slow compilation process (https://github.com/tfausak/tfausak.github.io/issues/127) so there's slight chance that deriving typeclass manually can be slightly faster than deriving `Generic + MyClass`. Especially when maintainers of plugins can experiment with some caching strategies for deriving typeclasses.","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15642Improve the worst case performance of weak pointers2021-09-07T15:55:31ZDavid FeuerImprove the worst case performance of weak pointersGarbage collecting weak pointers involves repeatedly traversing the weak pointer list, checking which keys are still alive, and in response marking the relevant values and finalizers live. This works well in most cases, but if there are ...Garbage collecting weak pointers involves repeatedly traversing the weak pointer list, checking which keys are still alive, and in response marking the relevant values and finalizers live. This works well in most cases, but if there are long chains of weak pointers, it's terrible. I wonder if we can do something about that without significantly hurting performance elsewhere. Here's the (probably naive) idea:
1. Maintain a hash table mapping weak pointer keys to lists of weak pointers. This replaces the current weak pointer list.
1. Use a bit in the info table pointer of every heap object to indicate whether that object is referenced from any `Weak#`. This is the weakest link: if we don't have a spare bit there, or don't want to use one, then I think this whole idea is sunk.
When creating a weak pointer, set the appropriate bit in the key and insert the key and pointer into the hash table. When performing early finalization, clear the bit in the key if no other `Weak#` points to it.
When performing garbage collection: check the bit in each object as it is marked. If the bit is set, move the key and its attached `Weak#`s from the hash table into a new hash table (or an association list that gets turned into a hash table after evacuation or whatever), and mark all the linked weak pointer targets and finalizers live. In the end, the old hash table contains only unreachable objects. Now mark those objects live (for finalization and in case of resurrection), and queue up the finalizers.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.6.1-beta1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Runtime System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonmar |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Improve the worst case performance of weak pointers","status":"New","operating_system":"","component":"Runtime System","related":[],"milestone":"8.8.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.1-beta1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"FeatureRequest","description":"Garbage collecting weak pointers involves repeatedly traversing the weak pointer list, checking which keys are still alive, and in response marking the relevant values and finalizers live. This works well in most cases, but if there are long chains of weak pointers, it's terrible. I wonder if we can do something about that without significantly hurting performance elsewhere. Here's the (probably naive) idea:\r\n\r\n1. Maintain a hash table mapping weak pointer keys to lists of weak pointers. This replaces the current weak pointer list.\r\n\r\n2. Use a bit in the info table pointer of every heap object to indicate whether that object is referenced from any `Weak#`. This is the weakest link: if we don't have a spare bit there, or don't want to use one, then I think this whole idea is sunk.\r\n\r\nWhen creating a weak pointer, set the appropriate bit in the key and insert the key and pointer into the hash table. When performing early finalization, clear the bit in the key if no other `Weak#` points to it.\r\n\r\nWhen performing garbage collection: check the bit in each object as it is marked. If the bit is set, move the key and its attached `Weak#`s from the hash table into a new hash table (or an association list that gets turned into a hash table after evacuation or whatever), and mark all the linked weak pointer targets and finalizers live. In the end, the old hash table contains only unreachable objects. Now mark those objects live (for finalization and in case of resurrection), and queue up the finalizers.","type_of_failure":"OtherFailure","blocking":[]} -->⊥https://gitlab.haskell.org/ghc/ghc/-/issues/15640Add "difficulty" field to tickets2019-07-07T18:03:38ZPhilippeAdd "difficulty" field to ticketsI propose to add a new field to tickets to indicate the difficulty of fixing a bug. This for three purposes:
- The priority of the bug can be affected by the difficulty, thus making the difficulty visible as a field can be handy to set/...I propose to add a new field to tickets to indicate the difficulty of fixing a bug. This for three purposes:
- The priority of the bug can be affected by the difficulty, thus making the difficulty visible as a field can be handy to set/affect the priority accordingly, example: #15579\##15640
- Can be welcoming to newcomers who want to contribute to GHC to start with tickets with low priority. The new field should be searchable so they can get a list of all tickets with low difficulty
- Can make work on GHC more efficient by doing more high-priority / low-difficulty bugs. This plays into pareto principle - 80/20 rule
As for the actual levels, "easy" or "hard" is subjective. So i think it's a good idea to have levels according to some experience level somebody should have. I can imagine some bugs can only be squashed by a few or even one person, while others can be jumped on by people who have decent haskell experience (given they want to read the background of setting up GHC dev and such).
One could then argue that this field should then be named "skill level needed", but i like difficulty more :) And this also allows for situations where the bug can be fixed only by a few people who are really knowledgeable about the matter but still find a need for different gradients of difficulty level.
Maybe something like:
- Very easy - new to haskell
- Easy - need haskell experience
- Medium - need a lot of haskell experience
- Hard - need experience with GHC dev
- Very Hard - as before + profiling/debugging tools + system knowledge
- Very Hard - as before + specific compiling techniques
- Very Hard - as before + need C skills (for RTS)
- ..
I'm not sure how and who can change the Trac settings, but the procedure for this is described on this page: https://trac.edgewall.org/wiki/TracTicketsCustomFields
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Trac & Git |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Add \"difficulty\" field to tickets","status":"New","operating_system":"","component":"Trac & Git","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"OwnedBy","contents":"hvr"},"version":"","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"I propose to add a new field to tickets to indicate the difficulty of fixing a bug. This for three purposes:\r\n\r\n* The priority of the bug can be affected by the difficulty, thus making the difficulty visible as a field can be handy to set/affect the priority accordingly, example: https://ghc.haskell.org/trac/ghc/ticket/15579#comment:1\r\n\r\n* Can be welcoming to newcomers who want to contribute to GHC to start with tickets with low priority. The new field should be searchable so they can get a list of all tickets with low difficulty\r\n\r\n* Can make work on GHC more efficient by doing more high-priority / low-difficulty bugs. This plays into pareto principle - 80/20 rule\r\n\r\nAs for the actual levels, \"easy\" or \"hard\" is subjective. So i think it's a good idea to have levels according to some experience level somebody should have. I can imagine some bugs can only be squashed by a few or even one person, while others can be jumped on by people who have decent haskell experience (given they want to read the background of setting up GHC dev and such).\r\n\r\nOne could then argue that this field should then be named \"skill level needed\", but i like difficulty more :) And this also allows for situations where the bug can be fixed only by a few people who are really knowledgeable about the matter but still find a need for different gradients of difficulty level.\r\n\r\nMaybe something like:\r\n* Very easy - new to haskell\r\n* Easy - need haskell experience\r\n* Medium - need a lot of haskell experience\r\n* Hard - need experience with GHC dev\r\n* Very Hard - as before + profiling/debugging tools + system knowledge\r\n* Very Hard - as before + specific compiling techniques\r\n* Very Hard - as before + need C skills (for RTS)\r\n* ..\r\n\r\nI'm not sure how and who can change the Trac settings, but the procedure for this is described on this page: https://trac.edgewall.org/wiki/TracTicketsCustomFields","type_of_failure":"OtherFailure","blocking":[]} -->Herbert Valerio Riedelhvr@gnu.orgHerbert Valerio Riedelhvr@gnu.orghttps://gitlab.haskell.org/ghc/ghc/-/issues/15639Surprising failure combining QuantifiedConstraints with Coercible2019-07-07T18:03:38ZDavid FeuerSurprising failure combining QuantifiedConstraints with CoercibleI don't understand what's going wrong here.
```hs
-- Fishy.hs
{-# language RankNTypes, QuantifiedConstraints, RoleAnnotations #-}
module Fishy (Yeah, yeahCoercible) where
import Data.Coerce
data Yeah_ a = Yeah_ Int
newtype Yeah a = Yea...I don't understand what's going wrong here.
```hs
-- Fishy.hs
{-# language RankNTypes, QuantifiedConstraints, RoleAnnotations #-}
module Fishy (Yeah, yeahCoercible) where
import Data.Coerce
data Yeah_ a = Yeah_ Int
newtype Yeah a = Yeah (Yeah_ a)
type role Yeah representational
yeahCoercible :: ((forall a b. Coercible (Yeah a) (Yeah b)) => r) -> r
yeahCoercible r = r
-- Fishy2.hs
module Fishy2 where
import Fishy
import Data.Type.Coercion
import Data.Coerce
yeah :: Coercion [Yeah a] [Yeah b]
yeah = yeahCoercible Coercion
```
I get
```
Fishy2.hs:8:22: error:
• Couldn't match representation of type ‘a’ with that of ‘b’
arising from a use of ‘Coercion’
‘a’ is a rigid type variable bound by
the type signature for:
yeah :: forall a b. Coercion [Yeah a] [Yeah b]
at Fishy2.hs:7:1-34
‘b’ is a rigid type variable bound by
the type signature for:
yeah :: forall a b. Coercion [Yeah a] [Yeah b]
at Fishy2.hs:7:1-34
• In the first argument of ‘yeahCoercible’, namely ‘Coercion’
In the expression: yeahCoercible Coercion
In an equation for ‘yeah’: yeah = yeahCoercible Coercion
• Relevant bindings include
yeah :: Coercion [Yeah a] [Yeah b] (bound at Fishy2.hs:8:1)
|
8 | yeah = yeahCoercible Coercion
|
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 8.5 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Surprising failure combining QuantifiedConstraints with Coercible","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.5","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"I don't understand what's going wrong here.\r\n\r\n{{{#!hs\r\n-- Fishy.hs\r\n{-# language RankNTypes, QuantifiedConstraints, RoleAnnotations #-}\r\nmodule Fishy (Yeah, yeahCoercible) where\r\nimport Data.Coerce\r\n\r\ndata Yeah_ a = Yeah_ Int\r\nnewtype Yeah a = Yeah (Yeah_ a)\r\ntype role Yeah representational\r\n\r\nyeahCoercible :: ((forall a b. Coercible (Yeah a) (Yeah b)) => r) -> r\r\nyeahCoercible r = r\r\n\r\n\r\n-- Fishy2.hs\r\n\r\nmodule Fishy2 where\r\n\r\nimport Fishy\r\nimport Data.Type.Coercion\r\nimport Data.Coerce\r\n\r\nyeah :: Coercion [Yeah a] [Yeah b]\r\nyeah = yeahCoercible Coercion\r\n}}}\r\n\r\nI get\r\n\r\n{{{\r\nFishy2.hs:8:22: error:\r\n • Couldn't match representation of type ‘a’ with that of ‘b’\r\n arising from a use of ‘Coercion’\r\n ‘a’ is a rigid type variable bound by\r\n the type signature for:\r\n yeah :: forall a b. Coercion [Yeah a] [Yeah b]\r\n at Fishy2.hs:7:1-34\r\n ‘b’ is a rigid type variable bound by\r\n the type signature for:\r\n yeah :: forall a b. Coercion [Yeah a] [Yeah b]\r\n at Fishy2.hs:7:1-34\r\n • In the first argument of ‘yeahCoercible’, namely ‘Coercion’\r\n In the expression: yeahCoercible Coercion\r\n In an equation for ‘yeah’: yeah = yeahCoercible Coercion\r\n • Relevant bindings include\r\n yeah :: Coercion [Yeah a] [Yeah b] (bound at Fishy2.hs:8:1)\r\n |\r\n8 | yeah = yeahCoercible Coercion\r\n |\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15634GHCi: Segmentation fault Data.List.sum large number2019-07-07T18:03:39ZksallbergGHCi: Segmentation fault Data.List.sum large numberHello, first bug report here, so please let me know what I should provide. I tried to search for this but didn't find it.
```
kristian@snabbadatorn:~$ ghci
GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help
Prelude> [1..100]
...Hello, first bug report here, so please let me know what I should provide. I tried to search for this but didn't find it.
```
kristian@snabbadatorn:~$ ghci
GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help
Prelude> [1..100]
[1,2,3,4,5,6,7,8,9,10,11,12... and so on
Prelude> sum [1..10000000]
50000005000000
Prelude> sum [1..100000000]
Segmentation fault
```
Machine: Google compute engine, n1-highcpu-8 (8 vCPUs, 7.2 GB memory),
uname -r: 4.9.0-8-amd64
```
kristian@snabbadatorn:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 9.5 (stretch)
Release: 9.5
Codename: stretch
```
```
kristian@snabbadatorn:~$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 8.0.1
```
-----------------------
Similar problem in older GHC version, although GHCi at least does not exit:
Amazon ec2, r4.8xlarge, 32 cores:
```
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
Prelude> sum [1..100000000]
*** Exception: stack overflow
Prelude>
```
```
ubuntu@ip-172-31-21-176:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.5 LTS
Release: 16.04
Codename: xenial
```
```
ubuntu@ip-172-31-21-176:~$ uname -r
4.4.0-1065-aws
```Research neededhttps://gitlab.haskell.org/ghc/ghc/-/issues/15632Undependable Dependencies2020-10-30T21:05:15ZAntCUndependable DependenciesConsider
```hs
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies,
GADTs, FlexibleInstances, FlexibleContexts,
UndecidableInstances #-}
data Hither = Hither deriving (Eq, Show, Read) -- just th...Consider
```hs
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies,
GADTs, FlexibleInstances, FlexibleContexts,
UndecidableInstances #-}
data Hither = Hither deriving (Eq, Show, Read) -- just three
data Thither = Thither deriving (Eq, Show, Read) -- distinct
data Yon = Yon deriving (Eq, Show, Read) -- types
class Whither a b | a -> b where
whither :: a -> b -> b
-- instance Whither Int Hither where -- rejected: FunDep conflict
-- whither _ y = y -- with Thither instance, so
instance {-# OVERLAPPING #-} (b ~ Hither) => Whither Int b where
whither _ y = y
instance {-# OVERLAPS #-} Whither a Thither where
whither _ y = y
instance {-# OVERLAPPABLE #-} (b ~ Yon) => Whither a b where
whither _ y = y
f :: Whither Int b => Int -> b -> b
f = whither
g :: Whither Bool b => Bool -> b -> b
g = whither
```
Should those three instances be accepted together? In particular, the published work on FDs (including the FDs through CHRs paper) says the `Thither` instance should behave as if:
```hs
instance (beta ~ Thither) => Whither a beta where ...
```
(in which `beta` is a unification variable and the `~` constraint is type improvement under the FD.) But now the instance head is the same as the `Yon` instance, modulo alpha renaming; with the constraints being contrary.
That's demonstrated by the inferred/improved type for `g`:
```hs
*Whither> :t g
===> g :: Bool -> Thither -> Thither -- and yet
*Whither> g True Yon
===> Yon
```
What do I expect here?
- At least the `Thither` and `Yon` instances to be rejected as inconsistent under the FunDep.
- (The `Hither` instance is also inconsistent, going by the strict interpretation in published work. But GHC's rule here is bogus, as documented in Trac #10675.)
Exploiting Overlapping instances is essential to making this go wrong. The published work shies away from considering `FunDeps + Overlap`; and yet specifying the semantics as if the instances used bare unification variables is almost inevitably going give overlaps -- especially if there are multiple FDs.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.6.1-beta1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | #10675 |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Undependable Dependencies","status":"New","operating_system":"","component":"Compiler","related":[10675],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.1-beta1","keywords":["FunctionalDependencies,","OverlappingInstances"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Consider\r\n\r\n{{{#!hs\r\n{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies,\r\n GADTs, FlexibleInstances, FlexibleContexts,\r\n UndecidableInstances #-}\r\n\r\n\r\ndata Hither = Hither deriving (Eq, Show, Read)\t\t-- just three\r\ndata Thither = Thither deriving (Eq, Show, Read)\t-- distinct\r\ndata Yon = Yon deriving (Eq, Show, Read)\t\t-- types\r\n\r\nclass Whither a b | a -> b where\r\n whither :: a -> b -> b\r\n\r\n-- instance Whither Int Hither where\t-- rejected: FunDep conflict\r\n-- whither _ y = y\t\t\t-- with Thither instance, so\r\n\r\ninstance {-# OVERLAPPING #-} (b ~ Hither) => Whither Int b where\r\n whither _ y = y\r\n\r\ninstance {-# OVERLAPS #-} Whither a Thither where\r\n whither _ y = y\r\ninstance {-# OVERLAPPABLE #-} (b ~ Yon) => Whither a b where\r\n whither _ y = y\r\n\r\nf :: Whither Int b => Int -> b -> b\r\nf = whither\r\n\r\ng :: Whither Bool b => Bool -> b -> b\r\ng = whither\r\n}}}\r\n\r\nShould those three instances be accepted together? In particular, the published work on FDs (including the FDs through CHRs paper) says the `Thither` instance should behave as if:\r\n\r\n{{{#!hs\r\ninstance (beta ~ Thither) => Whither a beta where ...\r\n}}}\r\n(in which `beta` is a unification variable and the `~` constraint is type improvement under the FD.) But now the instance head is the same as the `Yon` instance, modulo alpha renaming; with the constraints being contrary.\r\n\r\nThat's demonstrated by the inferred/improved type for `g`:\r\n\r\n{{{#!hs\r\n*Whither> :t g\r\n===> g :: Bool -> Thither -> Thither -- and yet\r\n\r\n*Whither> g True Yon\r\n===> Yon\r\n}}}\r\n\r\nWhat do I expect here?\r\n* At least the `Thither` and `Yon` instances to be rejected as inconsistent under the FunDep.\r\n* (The `Hither` instance is also inconsistent, going by the strict interpretation in published work. But GHC's rule here is bogus, as documented in Trac #10675.)\r\n\r\nExploiting Overlapping instances is essential to making this go wrong. The published work shies away from considering `FunDeps + Overlap`; and yet specifying the semantics as if the instances used bare unification variables is almost inevitably going give overlaps -- especially if there are multiple FDs.","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15626Optimise wakeups for STM2019-07-07T18:03:41ZÖmer Sinan AğacanOptimise wakeups for STMAs discovered while debugging #15544, the previous attempt at optimising STM wakeups (Phab:D4961, merged as 502640c90c3d0fbb6c46257be14fdc7e3c694c6c) broke other things (see comment 17) and reverted in [D5144](https://phabricator.haskell...As discovered while debugging #15544, the previous attempt at optimising STM wakeups (Phab:D4961, merged as 502640c90c3d0fbb6c46257be14fdc7e3c694c6c) broke other things (see comment 17) and reverted in [D5144](https://phabricator.haskell.org/D5144). This is the tracking ticket for this issue.
To summarize the problem: when a thread from capability 2 is in wait list of a TVar and we update the TVar in capability 1 we send a wakeup message to capability 2. If before capability 2 actually wake ups the thread capability 1 updates the TVar again we send a message again, causing redundant wakeup message sending. Ideally we should somehow mark the TSO as "awoken" and not send wakeup messages more than once. [D4961](https://phabricator.haskell.org/D4961) did exactly this, but in a wrong way (updated a field of TSO that shouldn't have been updated).8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15621Error message involving type families points to wrong location2021-09-07T15:55:20ZRyan ScottError message involving type families points to wrong locationConsider the following program:
```hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Bug where
import Data.Type.Equality
type family F a
f :: ()
f =
let a :: F Int :~: F Int
a = Refl
b :: F Int :~:...Consider the following program:
```hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Bug where
import Data.Type.Equality
type family F a
f :: ()
f =
let a :: F Int :~: F Int
a = Refl
b :: F Int :~: F Bool
b = Refl
in ()
```
This doesn't typecheck, which isn't surprising, since `F Int` doesn't equal `F Bool` in the definition of `b`. What //is// surprising is where the error message points to:
```
$ /opt/ghc/8.4.3/bin/ghc Bug.hs
[1 of 1] Compiling Bug ( Bug.hs, Bug.o )
Bug.hs:12:11: error:
• Couldn't match type ‘F Int’ with ‘F Bool’
Expected type: F Int :~: F Int
Actual type: F Bool :~: F Bool
NB: ‘F’ is a non-injective type family
• In the expression: Refl
In an equation for ‘a’: a = Refl
In the expression:
let
a :: F Int :~: F Int
a = Refl
b :: F Int :~: F Bool
....
in ()
|
12 | a = Refl
| ^^^^
```
This claims that the error message arises from the definition of `a`, which is completely wrong! As evidence, if you comment out `b`, then the program typechecks again.
Another interesting facet of this bug is that if you comment out `a`:
```hs
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Bug where
import Data.Type.Equality
type family F a
f :: ()
f =
let {- a :: F Int :~: F Int
a = Refl -}
b :: F Int :~: F Bool
b = Refl
in ()
```
Then the error message will actually point to `b` this time:
```
$ /opt/ghc/8.4.3/bin/ghc Bug.hs
[1 of 1] Compiling Bug ( Bug.hs, Bug.o )
Bug.hs:15:11: error:
• Couldn't match type ‘F Int’ with ‘F Bool’
Expected type: F Int :~: F Bool
Actual type: F Bool :~: F Bool
NB: ‘F’ is a non-injective type family
• In the expression: Refl
In an equation for ‘b’: b = Refl
In the expression:
let
b :: F Int :~: F Bool
b = Refl
in ()
|
15 | b = Refl
| ^^^^
```
The use of type families appears to be important to triggering this bug, since I can't observe this behavior without the use of `F`.
This is a regression that was introduced at some point between GHC 8.0.2 and 8.2.2, since 8.2.2 gives the incorrect error message shown above, while 8.0.2 points to the right location:
```
$ /opt/ghc/8.0.2/bin/ghc Bug.hs
[1 of 1] Compiling Bug ( Bug.hs, Bug.o )
Bug.hs:15:11: error:
• Couldn't match type ‘F Int’ with ‘F Bool’
Expected type: F Int :~: F Bool
Actual type: F Int :~: F Int
NB: ‘F’ is a type function, and may not be injective
• In the expression: Refl
In an equation for ‘b’: b = Refl
In the expression:
let
a :: F Int :~: F Int
a = Refl
b :: F Int :~: F Bool
....
in ()
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 8.4.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Type checker) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Error message involving type families points to wrong location","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":["TypeFamilies"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Consider the following program:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TypeFamilies #-}\r\n{-# LANGUAGE TypeOperators #-}\r\nmodule Bug where\r\n\r\nimport Data.Type.Equality\r\n\r\ntype family F a\r\n\r\nf :: ()\r\nf =\r\n let a :: F Int :~: F Int\r\n a = Refl\r\n\r\n b :: F Int :~: F Bool\r\n b = Refl\r\n in ()\r\n}}}\r\n\r\nThis doesn't typecheck, which isn't surprising, since `F Int` doesn't equal `F Bool` in the definition of `b`. What //is// surprising is where the error message points to:\r\n\r\n{{{\r\n$ /opt/ghc/8.4.3/bin/ghc Bug.hs\r\n[1 of 1] Compiling Bug ( Bug.hs, Bug.o )\r\n\r\nBug.hs:12:11: error:\r\n • Couldn't match type ‘F Int’ with ‘F Bool’\r\n Expected type: F Int :~: F Int\r\n Actual type: F Bool :~: F Bool\r\n NB: ‘F’ is a non-injective type family\r\n • In the expression: Refl\r\n In an equation for ‘a’: a = Refl\r\n In the expression:\r\n let\r\n a :: F Int :~: F Int\r\n a = Refl\r\n b :: F Int :~: F Bool\r\n ....\r\n in ()\r\n |\r\n12 | a = Refl\r\n | ^^^^\r\n}}}\r\n\r\nThis claims that the error message arises from the definition of `a`, which is completely wrong! As evidence, if you comment out `b`, then the program typechecks again.\r\n\r\nAnother interesting facet of this bug is that if you comment out `a`:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TypeFamilies #-}\r\n{-# LANGUAGE TypeOperators #-}\r\nmodule Bug where\r\n\r\nimport Data.Type.Equality\r\n\r\ntype family F a\r\n\r\nf :: ()\r\nf =\r\n let {- a :: F Int :~: F Int\r\n a = Refl -}\r\n\r\n b :: F Int :~: F Bool\r\n b = Refl\r\n in ()\r\n}}}\r\n\r\nThen the error message will actually point to `b` this time:\r\n\r\n{{{\r\n$ /opt/ghc/8.4.3/bin/ghc Bug.hs\r\n[1 of 1] Compiling Bug ( Bug.hs, Bug.o )\r\n\r\nBug.hs:15:11: error:\r\n • Couldn't match type ‘F Int’ with ‘F Bool’\r\n Expected type: F Int :~: F Bool\r\n Actual type: F Bool :~: F Bool\r\n NB: ‘F’ is a non-injective type family\r\n • In the expression: Refl\r\n In an equation for ‘b’: b = Refl\r\n In the expression:\r\n let\r\n b :: F Int :~: F Bool\r\n b = Refl\r\n in ()\r\n |\r\n15 | b = Refl\r\n | ^^^^\r\n}}}\r\n\r\nThe use of type families appears to be important to triggering this bug, since I can't observe this behavior without the use of `F`.\r\n\r\nThis is a regression that was introduced at some point between GHC 8.0.2 and 8.2.2, since 8.2.2 gives the incorrect error message shown above, while 8.0.2 points to the right location:\r\n\r\n{{{\r\n$ /opt/ghc/8.0.2/bin/ghc Bug.hs\r\n[1 of 1] Compiling Bug ( Bug.hs, Bug.o )\r\n\r\nBug.hs:15:11: error:\r\n • Couldn't match type ‘F Int’ with ‘F Bool’\r\n Expected type: F Int :~: F Bool\r\n Actual type: F Int :~: F Int\r\n NB: ‘F’ is a type function, and may not be injective\r\n • In the expression: Refl\r\n In an equation for ‘b’: b = Refl\r\n In the expression:\r\n let\r\n a :: F Int :~: F Int\r\n a = Refl\r\n b :: F Int :~: F Bool\r\n ....\r\n in ()\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->⊥https://gitlab.haskell.org/ghc/ghc/-/issues/15620Speed up Data.Unique2020-09-07T20:23:20ZDavid FeuerSpeed up Data.UniqueThe current `Data.Unique` code seems heavier than necessary:
1. It uses `Integer` when it can surely get away with less than two words on 64-bit systems.
1. It effectively guarantees that uniques will be consecutive, which isn't very us...The current `Data.Unique` code seems heavier than necessary:
1. It uses `Integer` when it can surely get away with less than two words on 64-bit systems.
1. It effectively guarantees that uniques will be consecutive, which isn't very useful.
I don't know how to fix this, but I'm confident there's a better way out there.
One silly idea: use one 100 or so-bit counter per capability. Use the rest of the bits to distinguish among the capabilities. To reduce hash collisions, make each capability increment its counter by a different prime number (or something like that).
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.4.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Core Libraries |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Speed up Data.Unique","status":"New","operating_system":"","component":"Core Libraries","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The current `Data.Unique` code seems heavier than necessary:\r\n\r\n1. It uses `Integer` when it can surely get away with less than two words on 64-bit systems.\r\n\r\n2. It effectively guarantees that uniques will be consecutive, which isn't very useful.\r\n\r\nI don't know how to fix this, but I'm confident there's a better way out there.\r\n\r\nOne silly idea: use one 100 or so-bit counter per capability. Use the rest of the bits to distinguish among the capabilities. To reduce hash collisions, make each capability increment its counter by a different prime number (or something like that).","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15619List comprehension seems to prevent some rewrite rules to fire2019-07-07T18:03:43ZnobrakalList comprehension seems to prevent some rewrite rules to fireHi,
Consider
```hs
module Test (problem, noProblem) where
data Relation = Relation Int
vertex :: Int -> Relation
vertex = Relation
{-# NOINLINE vertex #-}
star :: Int -> [Int] -> Relation
star x [] = vertex x
star x xs = vertex x
{-...Hi,
Consider
```hs
module Test (problem, noProblem) where
data Relation = Relation Int
vertex :: Int -> Relation
vertex = Relation
{-# NOINLINE vertex #-}
star :: Int -> [Int] -> Relation
star x [] = vertex x
star x xs = vertex x
{-# INLINE star #-}
transpose :: Relation -> Relation
transpose (Relation e) = Relation (-e)
{-# NOINLINE transpose #-}
{-# RULES
"transpose/vertex" forall x. transpose (vertex x) = vertex x
#-}
-- The "transpose/vertex" rule does not fire here
problem :: Relation
problem = transpose $ star 0 [1..2]
-- The "transpose/vertex" rule does fire here
noProblem :: Relation
noProblem = transpose $ star 0 [1,2]
```
`problem` and `noProblem` seems equivalents, but in the first the rewrite rule does not fire.
- Commenting `noProblem` and compiling with "-ddump-rule-firings" gives:
```
[1 of 1] Compiling Test ( Test.hs, Test.o )
Rule fired: Class op negate (BUILTIN)
Rule fired: Class op enumFromTo (BUILTIN)
Rule fired: eftIntList (GHC.Enum)
```
- Commenting `problem` and compiling with "-ddump-rule-firings" gives:
```
[1 of 1] Compiling Test ( Test.hs, Test.o )
Rule fired: Class op negate (BUILTIN)
Rule fired: transpose/vertex (Test)
```
It is a very "borderline" example (refined from a more complex one):
- changing the `data` to a `newtype` solves the problem
- removing the dumb pattern-match on the list in `star` also solves the problem
I suspect the list comprehension to be the problem, but I am not sure at all (I am not sure if the whole thing is a real bug indeed).
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.4.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":"List comprehension seems to prevent some rewrite rules to fire","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Hi,\r\n\r\nConsider\r\n\r\n{{{#!hs\r\nmodule Test (problem, noProblem) where\r\n\r\ndata Relation = Relation Int\r\n\r\nvertex :: Int -> Relation\r\nvertex = Relation\r\n{-# NOINLINE vertex #-}\r\n\r\nstar :: Int -> [Int] -> Relation\r\nstar x [] = vertex x\r\nstar x xs = vertex x\r\n{-# INLINE star #-}\r\n\r\ntranspose :: Relation -> Relation\r\ntranspose (Relation e) = Relation (-e)\r\n{-# NOINLINE transpose #-}\r\n\r\n{-# RULES\r\n\"transpose/vertex\" forall x. transpose (vertex x) = vertex x\r\n #-}\r\n\r\n-- The \"transpose/vertex\" rule does not fire here\r\nproblem :: Relation\r\nproblem = transpose $ star 0 [1..2]\r\n\r\n-- The \"transpose/vertex\" rule does fire here\r\nnoProblem :: Relation\r\nnoProblem = transpose $ star 0 [1,2]\r\n}}}\r\n\r\n`problem` and `noProblem` seems equivalents, but in the first the rewrite rule does not fire.\r\n\r\n* Commenting `noProblem` and compiling with \"-ddump-rule-firings\" gives:\r\n\r\n{{{\r\n[1 of 1] Compiling Test ( Test.hs, Test.o )\r\nRule fired: Class op negate (BUILTIN)\r\nRule fired: Class op enumFromTo (BUILTIN)\r\nRule fired: eftIntList (GHC.Enum)\r\n}}}\r\n\r\n* Commenting `problem` and compiling with \"-ddump-rule-firings\" gives:\r\n\r\n{{{\r\n[1 of 1] Compiling Test ( Test.hs, Test.o )\r\nRule fired: Class op negate (BUILTIN)\r\nRule fired: transpose/vertex (Test)\r\n}}}\r\n\r\nIt is a very \"borderline\" example (refined from a more complex one): \r\n\r\n* changing the `data` to a `newtype` solves the problem\r\n* removing the dumb pattern-match on the list in `star` also solves the problem\r\n\r\nI suspect the list comprehension to be the problem, but I am not sure at all (I am not sure if the whole thing is a real bug indeed).","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15614Test suite should show reason for skipping a test2019-07-07T18:03:44ZÖmer Sinan AğacanTest suite should show reason for skipping a testI want to add a GHCi test, but it's a bit tricky to run the test so I use a
make rule and use `run_command`, like this:
```
test('UnsafeReenterGhci',
[only_ways(['ghci']), exit_code(1), extra_files(['UnsafeReenter.hs', 'UnsafeReent...I want to add a GHCi test, but it's a bit tricky to run the test so I use a
make rule and use `run_command`, like this:
```
test('UnsafeReenterGhci',
[only_ways(['ghci']), exit_code(1), extra_files(['UnsafeReenter.hs', 'UnsafeReenterC.c'])],
run_command,
['$MAKE -s --no-print-directory UnsafeReenterGhci'])
```
The important part is `run_command` and `only_ways(['ghci'])`. The problem is
that it's impossible to run this test, because by default a `run_command` test
can only be run in normal way (see test_common_work() in testlib.py), but
there's no way to know this without reading the source code.
Having better documentation might help, but I think the test driver should
print why a test is skipped (maybe only in verbose mode -- if such a mode
exists). In our case it should print something like "Test is only run in
'normal' way" (because `run_command` tests only run in 'normal' way).
Correct version of this test is:
```
test('UnsafeReenterGhci',
[extra_ways(['ghci']), only_ways(['ghci']), exit_code(1), extra_files(['UnsafeReenter.hs', 'UnsafeReenterC.c'])],
run_command,
['$MAKE -s --no-print-directory UnsafeReenterGhci'])
```
The `extra_ways` makes the test driver consider running the test in `ghci` way,
`only_ways` is to avoid running it in `normal` way (the default and only way
for `run_command`).
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.5 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Test Suite |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Test suite should show reason for skipping a test","status":"New","operating_system":"","component":"Test Suite","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.5","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"I want to add a GHCi test, but it's a bit tricky to run the test so I use a\r\nmake rule and use `run_command`, like this:\r\n\r\n{{{\r\ntest('UnsafeReenterGhci',\r\n [only_ways(['ghci']), exit_code(1), extra_files(['UnsafeReenter.hs', 'UnsafeReenterC.c'])],\r\n run_command,\r\n ['$MAKE -s --no-print-directory UnsafeReenterGhci'])\r\n}}}\r\n\r\nThe important part is `run_command` and `only_ways(['ghci'])`. The problem is\r\nthat it's impossible to run this test, because by default a `run_command` test\r\ncan only be run in normal way (see test_common_work() in testlib.py), but\r\nthere's no way to know this without reading the source code.\r\n\r\nHaving better documentation might help, but I think the test driver should\r\nprint why a test is skipped (maybe only in verbose mode -- if such a mode\r\nexists). In our case it should print something like \"Test is only run in\r\n'normal' way\" (because `run_command` tests only run in 'normal' way).\r\n\r\nCorrect version of this test is:\r\n\r\n{{{\r\ntest('UnsafeReenterGhci',\r\n [extra_ways(['ghci']), only_ways(['ghci']), exit_code(1), extra_files(['UnsafeReenter.hs', 'UnsafeReenterC.c'])],\r\n run_command,\r\n ['$MAKE -s --no-print-directory UnsafeReenterGhci'])\r\n}}}\r\n\r\nThe `extra_ways` makes the test driver consider running the test in `ghci` way,\r\n`only_ways` is to avoid running it in `normal` way (the default and only way\r\nfor `run_command`).","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/15606Don't float out lets in between lambdsa2019-07-07T18:03:46ZSimon Peyton JonesDon't float out lets in between lambdsaConsider
```
f = \x. let y = <blah>
in \z. let v = h x y in <stuff>
```
The full laziness pass will float out that v-binding thus
```
f = \x. let y = <blah>
v = h x y
in \z. <stuff>
```
And now (if `h` is,...Consider
```
f = \x. let y = <blah>
in \z. let v = h x y in <stuff>
```
The full laziness pass will float out that v-binding thus
```
f = \x. let y = <blah>
v = h x y
in \z. <stuff>
```
And now (if `h` is, say, imported) it'll stay like that.
But suppose `<blah>` simlifies to `Just x`. Then we allow ourselves to eta-expand thus
```
f = \x z. let y = <blah>
v = h x y
in <stuff>
```
Now (an early design choice in the let-floater) we never float the v-binding in between the `\x` and `\z`.
This is very non-confluent: a smal change in exactly how rapidly `<blah>` simplifies can
have a big, irreversible effect on the code for `f`.
IDEA: extend the let-floater's design choice to not float out between two lambdas, even if
they are separated by lets/cases etc. One way to say this is to ask when a lambda gets
a new level number compared to its immediately enclosing lambda.
Examples where `y` gets the same level number as `x`
- `\x.\y. blah`
- `\x. let binds in \y`
- `\x. case scrut of pi -> \y.blah`
Examples where `y` gets the a level number one bigger than `x`
- `\x. let v = \y.rhs in blah`
- `\x. f (\y.rhs)`
This probably won't make a lot of difference, but it'd be worth trying
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.4.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":"Don't float out lets in between lambdsa","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Consider\r\n{{{\r\nf = \\x. let y = <blah>\r\n in \\z. let v = h x y in <stuff>\r\n}}}\r\nThe full laziness pass will float out that v-binding thus\r\n{{{\r\nf = \\x. let y = <blah>\r\n v = h x y\r\n in \\z. <stuff>\r\n}}}\r\nAnd now (if `h` is, say, imported) it'll stay like that.\r\n\r\nBut suppose `<blah>` simlifies to `Just x`. Then we allow ourselves to eta-expand thus\r\n{{{\r\nf = \\x z. let y = <blah>\r\n v = h x y\r\n in <stuff>\r\n}}}\r\nNow (an early design choice in the let-floater) we never float the v-binding in between the `\\x` and `\\z`.\r\n\r\nThis is very non-confluent: a smal change in exactly how rapidly `<blah>` simplifies can\r\nhave a big, irreversible effect on the code for `f`.\r\n\r\nIDEA: extend the let-floater's design choice to not float out between two lambdas, even if\r\nthey are separated by lets/cases etc. One way to say this is to ask when a lambda gets\r\na new level number compared to its immediately enclosing lambda.\r\n\r\nExamples where `y` gets the same level number as `x`\r\n* `\\x.\\y. blah`\r\n* `\\x. let binds in \\y`\r\n* `\\x. case scrut of pi -> \\y.blah`\r\n\r\nExamples where `y` gets the a level number one bigger than `x`\r\n* `\\x. let v = \\y.rhs in blah`\r\n* `\\x. f (\\y.rhs)`\r\n\r\nThis probably won't make a lot of difference, but it'd be worth trying\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15605Documentation of atomicModifyMutVar# does not show properly2019-07-07T18:03:46ZharendraDocumentation of atomicModifyMutVar# does not show properlyThe actual documentation in the source is:
```
-- | Modify the contents of a @MutVar\#@. Note that this isn\'t strictly
-- speaking the correct type for this function, it should really be
-- @MutVar# s a -> (a -> (a,b)) -> Sta...The actual documentation in the source is:
```
-- | Modify the contents of a @MutVar\#@. Note that this isn\'t strictly
-- speaking the correct type for this function, it should really be
-- @MutVar# s a -> (a -> (a,b)) -> State# s -> (# State# s, b #)@, however
-- we don\'t know about pairs here.
```
It actually shows as this in the docs, note the incomplete signature:
```
Modify the contents of a MutVar#. Note that this isn't strictly speaking the correct
type for this function, it should really be MutVar s -> ( s, b #), however we
don't know about pairs here.
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------- |
| Version | 8.4.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | libraries (other) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Documentation of atomicModifyMutVar# does not show properly","status":"New","operating_system":"","component":"libraries (other)","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":["ghc-prim"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"The actual documentation in the source is:\r\n\r\n{{{\r\n-- | Modify the contents of a @MutVar\\#@. Note that this isn\\'t strictly\r\n-- speaking the correct type for this function, it should really be\r\n-- @MutVar# s a -> (a -> (a,b)) -> State# s -> (# State# s, b #)@, however\r\n-- we don\\'t know about pairs here. \r\n}}}\r\n\r\nIt actually shows as this in the docs, note the incomplete signature:\r\n\r\n{{{\r\nModify the contents of a MutVar#. Note that this isn't strictly speaking the correct\r\ntype for this function, it should really be MutVar s -> ( s, b #), however we \r\ndon't know about pairs here.\r\n}}}\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15602PAP invariant of pointer tagging does not hold in profiling builds2019-07-07T18:03:46ZÖmer Sinan AğacanPAP invariant of pointer tagging does not hold in profiling buildsThe PAP invariant of pointer tagging says
> the PAP entry code jumps to the function's entry code, so it must have a tagged pointer to the function closure in R1. We therefore assume that a PAP always contains a tagged pointer to the fu...The PAP invariant of pointer tagging says
> the PAP entry code jumps to the function's entry code, so it must have a tagged pointer to the function closure in R1. We therefore assume that a PAP always contains a tagged pointer to the function closure.
(from https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/HaskellExecution/PointerTagging)
As discovered while debugging #15508, this currently does not hold. I tried to fix this in one PAP allocation site in [D5051](https://phabricator.haskell.org/D5051) but it somehow broke another test. We should review all PAP allocation sites and make sure the invariant holds, and then fix any bugs that this fix reveals.
Relevant commits:
- 6015a94f9108a502150565577b66c23650796639: Implements pointer tagging
- f9c6d53fe997f1c560cda6f346f4b201711df37c: Fixes a PAP allocation site (#13767)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.5 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | simonmar |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"PAP invariant of pointer tagging does not hold","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.5","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["simonmar"],"type":"Bug","description":"The PAP invariant of pointer tagging says\r\n\r\n> the PAP entry code jumps to the function's entry code, so it must have a tagged pointer to the function closure in R1. We therefore assume that a PAP always contains a tagged pointer to the function closure.\r\n\r\n(from https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/HaskellExecution/PointerTagging)\r\n\r\nAs discovered while debugging #15508, this currently does not hold. I tried to fix this in one PAP allocation site in Phab:D5051 but it somehow broke another test. We should review all PAP allocation sites and make sure the invariant holds, and then fix any bugs that this fix reveals.\r\n\r\nRelevant commits:\r\n\r\n- 6015a94f9108a502150565577b66c23650796639: Implements pointer tagging\r\n- f9c6d53fe997f1c560cda6f346f4b201711df37c: Fixes a PAP allocation site (#13767)","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15599typeclass inference depends on whether a module is exposed.2019-07-07T18:03:49Zgleachkrtypeclass inference depends on whether a module is exposed.My first bug report for GHC: I've found some strange behavior in GHC 8.2.2 relating to typeclass inference.
Essentially, for two identical modules, GHC infers for one of them that one typeclass instance applies, and for another that a d...My first bug report for GHC: I've found some strange behavior in GHC 8.2.2 relating to typeclass inference.
Essentially, for two identical modules, GHC infers for one of them that one typeclass instance applies, and for another that a different instance applies. The only language extensions involved are FlexibleInstances, MultiParamTypeClasses, GADTs, and ScopedTypeVariables. There are no INCOHERENT pragmas involved. The only difference between the two modules is that one of them (the one displaying correct typeclass inference) is an exposed module, while the other is not mentioned in the cabal file. The phenomenon affects other packages that import the original package---they display the incorrect behavior, rather than the correct behavior that the exposed module displays.
The original discussion is here: [https://github.com/gleachkr/Carnap/issues/4](https://github.com/gleachkr/Carnap/issues/4)
My best attempt at a minimal example can be found at [https://github.com/gleachkr/GHC-Repro](https://github.com/gleachkr/GHC-Repro). You can run the "test.sh" script included there to see the phenomenon in action.
I don't see this behavior in other GHC versions, but I'm told that bug reports for older GHC versions are welcome, so here I am.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.2 |
| 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":"typeclass inference depends on whether a module is exposed.","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.2.3","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"My first bug report for GHC: I've found some strange behavior in GHC 8.2.2 relating to typeclass inference. \r\n\r\nEssentially, for two identical modules, GHC infers for one of them that one typeclass instance applies, and for another that a different instance applies. The only language extensions involved are FlexibleInstances, MultiParamTypeClasses, GADTs, and ScopedTypeVariables. There are no INCOHERENT pragmas involved. The only difference between the two modules is that one of them (the one displaying correct typeclass inference) is an exposed module, while the other is not mentioned in the cabal file. The phenomenon affects other packages that import the original package---they display the incorrect behavior, rather than the correct behavior that the exposed module displays.\r\n\r\nThe original discussion is here: [https://github.com/gleachkr/Carnap/issues/4]\r\n\r\nMy best attempt at a minimal example can be found at [https://github.com/gleachkr/GHC-Repro]. You can run the \"test.sh\" script included there to see the phenomenon in action.\r\n\r\nI don't see this behavior in other GHC versions, but I'm told that bug reports for older GHC versions are welcome, so here I am.","type_of_failure":"OtherFailure","blocking":[]} -->8.2.3https://gitlab.haskell.org/ghc/ghc/-/issues/15596When a type application cannot be applied to an identifier due to the absence...2021-09-07T15:54:40ZkindaroWhen a type application cannot be applied to an identifier due to the absence of an explicit type signature, let the error just say so!Consider this code:
```hs
{-# language TypeApplications #-}
module TypeApplicationsErrorMessage where
f = (+)
g = f @Integer
```
This is what happens when I try to compile it:
```hs
% ghc TypeApplicationsErrorMessage.hs
[1 of 1] Com...Consider this code:
```hs
{-# language TypeApplications #-}
module TypeApplicationsErrorMessage where
f = (+)
g = f @Integer
```
This is what happens when I try to compile it:
```hs
% ghc TypeApplicationsErrorMessage.hs
[1 of 1] Compiling TypeApplicationsErrorMessage ( TypeApplicationsErrorMessage.hs, TypeApplicationsErrorMessage.o )
TypeApplicationsErrorMessage.hs:6:5: error:
• Cannot apply expression of type ‘a0 -> a0 -> a0’
to a visible type argument ‘Integer’
• In the expression: f @Integer
In an equation for ‘g’: g = f @Integer
|
6 | g = f @Integer
| ^^^^^^^^^^
```
This error is easily fixed by supplying an explicit type signature to `f`. So, perhaps the error message could just say so?
I am observing this with `The Glorious Glasgow Haskell Compilation System, version 8.6.0.20180810`.
<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":"When a type application cannot be applied to an identifier due to the absence of an explicit type signature, let the error just say so!","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"Consider this code:\r\n\r\n{{{#!hs\r\n{-# language TypeApplications #-}\r\n\r\nmodule TypeApplicationsErrorMessage where\r\n\r\nf = (+)\r\ng = f @Integer\r\n}}}\r\n\r\nThis is what happens when I try to compile it:\r\n\r\n{{{#!hs\r\n% ghc TypeApplicationsErrorMessage.hs\r\n[1 of 1] Compiling TypeApplicationsErrorMessage ( TypeApplicationsErrorMessage.hs, TypeApplicationsErrorMessage.o )\r\n\r\nTypeApplicationsErrorMessage.hs:6:5: error:\r\n • Cannot apply expression of type ‘a0 -> a0 -> a0’\r\n to a visible type argument ‘Integer’\r\n • In the expression: f @Integer\r\n In an equation for ‘g’: g = f @Integer\r\n |\r\n6 | g = f @Integer\r\n | ^^^^^^^^^^\r\n}}}\r\n\r\nThis error is easily fixed by supplying an explicit type signature to `f`. So, perhaps the error message could just say so?\r\n\r\nI am observing this with `The Glorious Glasgow Haskell Compilation System, version 8.6.0.20180810`.","type_of_failure":"OtherFailure","blocking":[]} -->⊥