GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2021-01-13T02:20:23Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/17188Fix backpack typechecking with -j2021-01-13T02:20:23ZEdward KmettFix backpack typechecking with -j## Motivation
Currently, backpack typechecking is not supported with `-j` as seen [here](https://github.com/ghc/ghc/blob/a31b24a591aecc734449d3af479e3a3d1834b0ed/compiler/main/GhcMake.hs#L947).
This rather drastically increases compile...## Motivation
Currently, backpack typechecking is not supported with `-j` as seen [here](https://github.com/ghc/ghc/blob/a31b24a591aecc734449d3af479e3a3d1834b0ed/compiler/main/GhcMake.hs#L947).
This rather drastically increases compile times for large projects using backpack. It has not been revisited since the original backpack merge.
## Proposal
Enable backpack typechecking with `-j`, addressing whatever attendant issues caused this initial restriction. @ezyang expressed willingness to help out at least at a mentor level.John EricsonJohn Ericsonhttps://gitlab.haskell.org/ghc/ghc/-/issues/16412Type family signatures in indefinite modules2019-07-07T18:00:12ZAndrew MartinType family signatures in indefinite modulesBackpack does not allow type family signatures in indefinite modules. As an example, although GHC does accept:
```
-- indefinite module
data Foo :: Bool
-- implementing module
type Foo = 'True
```
It does not accept:
```
-- indefinite...Backpack does not allow type family signatures in indefinite modules. As an example, although GHC does accept:
```
-- indefinite module
data Foo :: Bool
-- implementing module
type Foo = 'True
```
It does not accept:
```
-- indefinite module
type family Foo (b :: Bool) :: Bool
-- implementing module
type family Foo (b :: Bool) :: Bool where
Foo 'True = 'False
Foo 'False = 'True
```
I'm not sure if there is a fundamental reason for this (e.g. a requirement that everything is matchable). It would be helpful for the thing I'm experimenting with if this restriction could be lifted.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.6.4 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | ezyang |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Type family signatures in indefinite modules","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.6.4","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":["ezyang"],"type":"FeatureRequest","description":"Backpack does not allow type family signatures in indefinite modules. As an example, although GHC does accept:\r\n\r\n{{{\r\n-- indefinite module\r\ndata Foo :: Bool\r\n-- implementing module\r\ntype Foo = 'True\r\n}}}\r\n\r\nIt does not accept:\r\n\r\n{{{\r\n-- indefinite module\r\ntype family Foo (b :: Bool) :: Bool\r\n-- implementing module\r\ntype family Foo (b :: Bool) :: Bool where\r\n Foo 'True = 'False\r\n Foo 'False = 'True\r\n}}}\r\n\r\nI'm not sure if there is a fundamental reason for this (e.g. a requirement that everything is matchable). It would be helpful for the thing I'm experimenting with if this restriction could be lifted.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/16219Backpack - TH+indefinite module interface file error2021-10-19T07:30:21ZIsaac ElliottBackpack - TH+indefinite module interface file errorRepro: https://github.com/LightAndLight/backpack-test
I've been stuck on this for a while now. There's a weird interaction between the Template Haskell pragma and indefinite modules. When Template Haskell is enabled in this particular f...Repro: https://github.com/LightAndLight/backpack-test
I've been stuck on this for a while now. There's a weird interaction between the Template Haskell pragma and indefinite modules. When Template Haskell is enabled in this particular file (but TH features aren't used) I get an interface error. When I remove the pragma, the project successfully compiles.
I hope I haven't made some trivial .cabal blunder.
Anyway, I'm interested in potentially trying to fix this, but I've been digging around in GHC for a couple of days and figured it was time to ask for help.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.7 |
| 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":"Backpack - TH+indefinite module interface file error","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.7","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Repro: https://github.com/LightAndLight/backpack-test\r\n\r\nI've been stuck on this for a while now. There's a weird interaction between the Template Haskell pragma and indefinite modules. When Template Haskell is enabled in this particular file (but TH features aren't used) I get an interface error. When I remove the pragma, the project successfully compiles.\r\n\r\nI hope I haven't made some trivial .cabal blunder.\r\n\r\nAnyway, I'm interested in potentially trying to fix this, but I've been digging around in GHC for a couple of days and figured it was time to ask for help.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/15984Backpack accepts ill-kinded instantiations. Can cause GHC panic2019-07-07T18:02:09ZaaronvargoBackpack accepts ill-kinded instantiations. Can cause GHC panicGiven the following:
```hs
{-# language KindSignatures #-}
signature A where
data A :: *
```
```hs
module Foo where
import A
foo :: A -> A
foo = id
```
```hs
module IllKindedA where
type A = Maybe
```
GHC allows the signature `A`...Given the following:
```hs
{-# language KindSignatures #-}
signature A where
data A :: *
```
```hs
module Foo where
import A
foo :: A -> A
foo = id
```
```hs
module IllKindedA where
type A = Maybe
```
GHC allows the signature `A` to be instantiated with `IllKindedA`:
```
mixins: foo (Foo as Bug) requires (A as IllKindedA)
```
Using the resulting module can cause odd errors or a panic. E.g. the following causes a panic:
```hs
module Bar where
import Bug
bar = foo
```
```
ghc: panic! (the 'impossible' happened)
(GHC version 8.6.2 for x86_64-unknown-linux):
getRuntimeRep
A :: * -> *
Call stack:
CallStack (from HasCallStack):
callStackDoc, called at compiler/utils/Outputable.hs:1160:37 in ghc:Outputable
pprPanic, called at compiler/types/Type.hs:2049:18 in ghc:Type
```8.6.3https://gitlab.haskell.org/ghc/ghc/-/issues/15594--abi-hash with Backpack incorrectly loads modules from dependent packages2020-09-28T07:11:37ZEdward Z. Yang--abi-hash with Backpack incorrectly loads modules from dependent packagesRepro at: https://github.com/alexbiehl/cabal-backpack-register-repro
If you use Backpack with data families, you might fail during `--abi-hash` with:
```
cabal:
'/nix/store/m338klajhqlw7v4jd61fiqd82wx305fj-ghc-8.4.3-with-packages/bin/g...Repro at: https://github.com/alexbiehl/cabal-backpack-register-repro
If you use Backpack with data families, you might fail during `--abi-hash` with:
```
cabal:
'/nix/store/m338klajhqlw7v4jd61fiqd82wx305fj-ghc-8.4.3-with-packages/bin/ghc'
exited with an error:
Failed to load interface for ‘Stuff’
no unit id matching ‘backpack-trans-0.1.0.0-L6CFTQZAAWWFpCQD2NXR4W-indef’ was
found
```8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/15391Maybe ghc-pkg register should unregister packages with "incompatible" signatures2021-09-07T14:56:49ZEdward Z. YangMaybe ghc-pkg register should unregister packages with "incompatible" signaturesConsider the following situation:
1. I register package 'p-0.1-inplace' instantiated with 'P = base:Data.Map'
1. I register package 'p-0.1-inplace' instantiated with 'P = base:Control.Monad'
Even though the IPID of these two packages i...Consider the following situation:
1. I register package 'p-0.1-inplace' instantiated with 'P = base:Data.Map'
1. I register package 'p-0.1-inplace' instantiated with 'P = base:Control.Monad'
Even though the IPID of these two packages is the same, we clearly want to keep both of them in the database. This thus motivates the following lines in ghc-pkg
```
removes = [ RemovePackage p
| not multi_instance,
p <- packages db_to_operate_on,
mungedId p == mungedId pkg,
-- Only remove things that were instantiated the same way!
instantiatedWith p == instantiatedWith pkg ]
```
OK... now consider the following situation
1. I register package 'p-0.1-inplace' instantiated with 'P = base:Data.Map'
1. I register package 'p-0.1-inplace', instantiated with nothing (I have edited 'p' such that it has no more signatures)
So... ghc-pkg is going to keep both of these packages (per the logic above). But is that really what we want? Now the package database is in a half-consistent state, where the instances of 'p-0.1-inplace' are not consistent with the number of holes they are supposed to have. So let us suggest an invariant:
INVARIANT: All packages which have the same IPID in a package database are self-consistent with each other.
OK, so given this invariant, what do we have to do in step 2? It would seem that when we get a prospective package to register, we must \*find all packages which are incompatible with it\*, and remove them from the package database. So, given a package with a set of holes H, we must remove all packages with holes H' such that H = H'
I'm not completely convinced this is a good idea. Usually ghc-pkg only removes a single package in response to a new registration, and this behavior could result in lots of packages getting unregistered, more than you might expect. On the other hand, if you think of the package database in a more hierarchical manner, it makes sense that changing the root registration would invalidate all the children.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.4.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | ghc-pkg |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | int-index |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Maybe ghc-pkg register should unregister packages with \"incompatible\" signatures","status":"New","operating_system":"","component":"ghc-pkg","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":["int-index"],"type":"Bug","description":"Consider the following situation:\r\n\r\n1. I register package 'p-0.1-inplace' instantiated with 'P = base:Data.Map'\r\n2. I register package 'p-0.1-inplace' instantiated with 'P = base:Control.Monad'\r\n\r\nEven though the IPID of these two packages is the same, we clearly want to keep both of them in the database. This thus motivates the following lines in ghc-pkg\r\n\r\n{{{\r\n removes = [ RemovePackage p\r\n | not multi_instance,\r\n p <- packages db_to_operate_on,\r\n mungedId p == mungedId pkg,\r\n -- Only remove things that were instantiated the same way!\r\n instantiatedWith p == instantiatedWith pkg ]\r\n}}}\r\n\r\nOK... now consider the following situation\r\n\r\n1. I register package 'p-0.1-inplace' instantiated with 'P = base:Data.Map'\r\n2. I register package 'p-0.1-inplace', instantiated with nothing (I have edited 'p' such that it has no more signatures)\r\n\r\nSo... ghc-pkg is going to keep both of these packages (per the logic above). But is that really what we want? Now the package database is in a half-consistent state, where the instances of 'p-0.1-inplace' are not consistent with the number of holes they are supposed to have. So let us suggest an invariant:\r\n\r\nINVARIANT: All packages which have the same IPID in a package database are self-consistent with each other.\r\n\r\nOK, so given this invariant, what do we have to do in step 2? It would seem that when we get a prospective package to register, we must *find all packages which are incompatible with it*, and remove them from the package database. So, given a package with a set of holes H, we must remove all packages with holes H' such that H = H'\r\n\r\nI'm not completely convinced this is a good idea. Usually ghc-pkg only removes a single package in response to a new registration, and this behavior could result in lots of packages getting unregistered, more than you might expect. On the other hand, if you think of the package database in a more hierarchical manner, it makes sense that changing the root registration would invalidate all the children.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/15379Don't reject user-written instances of KnownNat and friends in hsig files2019-07-07T18:12:54ZEdward Z. YangDon't reject user-written instances of KnownNat and friends in hsig filesPiyush has graciously volunteered to fix this.
Relevant commit c5609577fab8a214c50561bea861c70d4bfd47c7
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Ve...Piyush has graciously volunteered to fix this.
Relevant commit c5609577fab8a214c50561bea861c70d4bfd47c7
<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 | ppk |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Don't reject user-written instances of KnownNat and friends in hsig files","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":["ppk"],"type":"Bug","description":"Piyush has graciously volunteered to fix this.\r\n\r\nRelevant commit c5609577fab8a214c50561bea861c70d4bfd47c7","type_of_failure":"OtherFailure","blocking":[]} -->8.8.1https://gitlab.haskell.org/ghc/ghc/-/issues/15138Unable to instantiate data members of kind Nat in backpack signatures.2019-07-07T18:14:06ZPiyush P KururUnable to instantiate data members of kind Nat in backpack signatures.This is in context with backpack signatures and their instantiation with concrete implementation. Consider the signature `Abstract` which contains a
data `NatType` of kind `Nat`.
```hs
{- skipped relevant language extensions -}
signatu...This is in context with backpack signatures and their instantiation with concrete implementation. Consider the signature `Abstract` which contains a
data `NatType` of kind `Nat`.
```hs
{- skipped relevant language extensions -}
signature Abstract where
import GHC.TypeLits
data NatType :: Nat -- comment this out
```
Concrete implementations are unable to instantiate this abstract class during
linking
```hs
module Concrete where
type NatType = 42
```
This is neither working with explicit .bkp files nor actual cabal package.
I have isolated a minimum example into a repository [a cabal packages](https://github.com/piyush-kurur/backpack-nat) as well as a [single bkp file](https://github.com/piyush-kurur/backpack-nat/blob/master/as-bkpfiles/backpack-nat.bkp). The urls above also have the associated
ghc log messages.
The version of ghc I have tested with is 8.4.1
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.4.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Unable to instantiate data members of kind Nat in backpack signatures.","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"This is in context with backpack signatures and their instantiation with concrete implementation. Consider the signature `Abstract` which contains a\r\ndata `NatType` of kind `Nat`. \r\n\r\n{{{#!hs\r\n\r\n{- skipped relevant language extensions -}\r\n\r\nsignature Abstract where\r\n import GHC.TypeLits\r\n data NatType :: Nat -- comment this out\r\n \r\n\r\n}}}\r\n\r\nConcrete implementations are unable to instantiate this abstract class during\r\nlinking\r\n\r\n{{{#!hs\r\n\r\n module Concrete where\r\n type NatType = 42\r\n}}}\r\n\r\nThis is neither working with explicit .bkp files nor actual cabal package.\r\nI have isolated a minimum example into a repository [[https://github.com/piyush-kurur/backpack-nat| a cabal packages]] as well as a [[https://github.com/piyush-kurur/backpack-nat/blob/master/as-bkpfiles/backpack-nat.bkp|single bkp file]]. The urls above also have the associated \r\nghc log messages.\r\n\r\nThe version of ghc I have tested with is 8.4.1\r\n","type_of_failure":"OtherFailure","blocking":[]} -->8.8.1https://gitlab.haskell.org/ghc/ghc/-/issues/15041rnIfaceBndr implementation in RnModIface looks incorrect2019-07-07T18:14:35ZMatthew PickeringrnIfaceBndr implementation in RnModIface looks incorrect```
rnIfaceBndr :: Rename IfaceBndr
rnIfaceBndr (IfaceIdBndr (fs, ty)) = IfaceIdBndr <$> ((,) fs <$> rnIfaceType ty)
rnIfaceBndr (IfaceTvBndr tv_bndr) = IfaceIdBndr <$> rnIfaceTvBndr tv_bndr
```
This is the implementation currently. Not...```
rnIfaceBndr :: Rename IfaceBndr
rnIfaceBndr (IfaceIdBndr (fs, ty)) = IfaceIdBndr <$> ((,) fs <$> rnIfaceType ty)
rnIfaceBndr (IfaceTvBndr tv_bndr) = IfaceIdBndr <$> rnIfaceTvBndr tv_bndr
```
This is the implementation currently. Notice in the second branch that an `IfaceTvBndr` is converted to an `IfaceIdBndr`. Should it instead be `IfaceTvBndr`?
<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 | ezyang |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"rnIfaceBndr implementation in RnModIface looks incorrect","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"8.6.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.2","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":["ezyang"],"type":"Bug","description":"{{{\r\nrnIfaceBndr :: Rename IfaceBndr\r\nrnIfaceBndr (IfaceIdBndr (fs, ty)) = IfaceIdBndr <$> ((,) fs <$> rnIfaceType ty)\r\nrnIfaceBndr (IfaceTvBndr tv_bndr) = IfaceIdBndr <$> rnIfaceTvBndr tv_bndr\r\n}}}\r\n\r\nThis is the implementation currently. Notice in the second branch that an `IfaceTvBndr` is converted to an `IfaceIdBndr`. Should it instead be `IfaceTvBndr`?","type_of_failure":"OtherFailure","blocking":[]} -->8.6.1https://gitlab.haskell.org/ghc/ghc/-/issues/14674Deferring more levity polymorphism checks in indefinite backpack modules2019-07-07T18:16:04ZAndrew MartinDeferring more levity polymorphism checks in indefinite backpack modulesThis is kind of a follow up issue to issue #13955. I'm able to get along a little further with the thing I'm trying to do. Here's a minimal example. The `number-example-a` and `number-example-b` sections are not really needed to trigger ...This is kind of a follow up issue to issue #13955. I'm able to get along a little further with the thing I'm trying to do. Here's a minimal example. The `number-example-a` and `number-example-b` sections are not really needed to trigger the problem. They are included as examples of how the signature might be instantiated.
```
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
unit the-fam where
module TheFamily where
import Data.Kind
import GHC.Types
import GHC.Prim
data Liftedness = Lifted | Unlifted
data SingLiftedness (x :: Liftedness) where
SingLifted :: SingLiftedness 'Lifted
SingUnlifted :: SingLiftedness 'Unlifted
type family LiftednessIntRep (x :: Liftedness) :: RuntimeRep where
LiftednessIntRep 'Lifted = LiftedRep
LiftednessIntRep 'Unlifted = IntRep
type family LiftednessInt (x :: Liftedness) :: TYPE (LiftednessIntRep x) where
LiftednessInt 'Lifted = Int
LiftednessInt 'Unlifted = Int#
unit number-indefinite where
dependency the-fam
signature NumberUnknown where
import GHC.Types
import TheFamily
data MyLiftedness :: Liftedness
module NumberStuff where
import NumberUnknown
import TheFamily
identityInt :: LiftednessInt MyLiftedness -> LiftednessInt MyLiftedness
identityInt i = i
unit number-example-a where
dependency the-fam
module NumberUnknown where
import GHC.Types
import TheFamily
type MyLiftedness = Lifted
identityInt :: Int -> Int
identityInt x = x
unit number-example-b where
dependency the-fam
module NumberUnknown where
import GHC.Types
import GHC.Prim
import TheFamily
type MyLiftedness = Unlifted
identityInt :: Int# -> Int#
identityInt i = i
unit main where
dependency number-indefinite[NumberUnknown=number-example-a:NumberUnknown]
module Main where
import NumberStuff
import GHC.Types
main = print (identityInt 5)
```
Attempting to compile with the ghc 8.4 release candidate gives:
```
> /usr/local/bin/ghc-8.4.0.20171214 --backpack small_levity_backpack.bkp
small_levity_backpack.bkp:35:17: error:
A levity-polymorphic type is not allowed here:
Type: LiftednessInt MyLiftedness
Kind: TYPE (LiftednessIntRep MyLiftedness)
In the type of binder ‘i’
|
35 | identityInt i = i
| ^
```
I disagree with this error. The type of `i` is not actually levity polymorphic in either of the example instantiations of the signature. If this check were omitted from the type-checking of the indefinite module, I suspect that this code should be able to compile and run fine.
I'm not sure if there's a good general rule for when to suppress these checks in indefinite modules and when to not suppress them. Clearly, there are some cases were a function will with a levity-polymorphic binder no matter how the signature is fulfilled, and those ideally should continue to be rejected. And there are other cases like the one I raise here where it's guaranteed to be safe. There are other cases where the whether or not there's a levity-polymorphic binder depends on the instantiation:
```
data X = X1 | X2
type family Rep (a :: X) (r :: RuntimeRep) :: RuntimeRep
Rep X1 r = r
Rep X2 r = UnliftedRep
```
And then finally, there are situations where it's always going to lead to a levity-polymorphic binder, but it isn't feasible for the compiler to figure that out. A sufficiently tricky type family would cause this.
Sorry this was a bit of a ramble. I think there actually is a good rule for this. Defer the levity-polymorphic binder check in indefinite modules any time the type-checker encounters a type variable whose RuntimeRep is a type family that cannot be reduced. The check will happen later any way, and more correct code will be accepted.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.4.1-alpha1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | ezyang, goldfire |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Deferring more levity polymorphism checks in indefinite backpack modules","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.1-alpha1","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":["ezyang","goldfire"],"type":"FeatureRequest","description":"This is kind of a follow up issue to issue #13955. I'm able to get along a little further with the thing I'm trying to do. Here's a minimal example. The `number-example-a` and `number-example-b` sections are not really needed to trigger the problem. They are included as examples of how the signature might be instantiated.\r\n\r\n{{{\r\n{-# LANGUAGE MagicHash #-}\r\n{-# LANGUAGE TypeInType #-}\r\n{-# LANGUAGE PolyKinds #-}\r\n{-# LANGUAGE DataKinds #-}\r\n{-# LANGUAGE RankNTypes #-}\r\n{-# LANGUAGE GADTs #-}\r\n{-# LANGUAGE TypeFamilies #-}\r\n\r\nunit the-fam where\r\n module TheFamily where\r\n import Data.Kind\r\n import GHC.Types\r\n import GHC.Prim\r\n data Liftedness = Lifted | Unlifted\r\n data SingLiftedness (x :: Liftedness) where\r\n SingLifted :: SingLiftedness 'Lifted\r\n SingUnlifted :: SingLiftedness 'Unlifted\r\n type family LiftednessIntRep (x :: Liftedness) :: RuntimeRep where\r\n LiftednessIntRep 'Lifted = LiftedRep\r\n LiftednessIntRep 'Unlifted = IntRep\r\n type family LiftednessInt (x :: Liftedness) :: TYPE (LiftednessIntRep x) where\r\n LiftednessInt 'Lifted = Int\r\n LiftednessInt 'Unlifted = Int#\r\n\r\nunit number-indefinite where\r\n dependency the-fam\r\n signature NumberUnknown where\r\n import GHC.Types\r\n import TheFamily\r\n data MyLiftedness :: Liftedness\r\n module NumberStuff where\r\n import NumberUnknown\r\n import TheFamily\r\n identityInt :: LiftednessInt MyLiftedness -> LiftednessInt MyLiftedness\r\n identityInt i = i\r\n\r\nunit number-example-a where\r\n dependency the-fam\r\n module NumberUnknown where\r\n import GHC.Types\r\n import TheFamily\r\n type MyLiftedness = Lifted\r\n identityInt :: Int -> Int\r\n identityInt x = x\r\n\r\nunit number-example-b where\r\n dependency the-fam\r\n module NumberUnknown where\r\n import GHC.Types\r\n import GHC.Prim\r\n import TheFamily\r\n type MyLiftedness = Unlifted\r\n identityInt :: Int# -> Int#\r\n identityInt i = i\r\n\r\nunit main where\r\n dependency number-indefinite[NumberUnknown=number-example-a:NumberUnknown]\r\n module Main where\r\n import NumberStuff\r\n import GHC.Types\r\n main = print (identityInt 5)\r\n}}}\r\n\r\nAttempting to compile with the ghc 8.4 release candidate gives:\r\n\r\n{{{\r\n> /usr/local/bin/ghc-8.4.0.20171214 --backpack small_levity_backpack.bkp\r\nsmall_levity_backpack.bkp:35:17: error:\r\n A levity-polymorphic type is not allowed here:\r\n Type: LiftednessInt MyLiftedness\r\n Kind: TYPE (LiftednessIntRep MyLiftedness)\r\n In the type of binder ‘i’\r\n |\r\n35 | identityInt i = i\r\n | ^\r\n}}}\r\n\r\nI disagree with this error. The type of `i` is not actually levity polymorphic in either of the example instantiations of the signature. If this check were omitted from the type-checking of the indefinite module, I suspect that this code should be able to compile and run fine.\r\n\r\nI'm not sure if there's a good general rule for when to suppress these checks in indefinite modules and when to not suppress them. Clearly, there are some cases were a function will with a levity-polymorphic binder no matter how the signature is fulfilled, and those ideally should continue to be rejected. And there are other cases like the one I raise here where it's guaranteed to be safe. There are other cases where the whether or not there's a levity-polymorphic binder depends on the instantiation:\r\n\r\n{{{\r\ndata X = X1 | X2\r\ntype family Rep (a :: X) (r :: RuntimeRep) :: RuntimeRep\r\n Rep X1 r = r\r\n Rep X2 r = UnliftedRep\r\n}}}\r\n\r\nAnd then finally, there are situations where it's always going to lead to a levity-polymorphic binder, but it isn't feasible for the compiler to figure that out. A sufficiently tricky type family would cause this.\r\n\r\nSorry this was a bit of a ramble. I think there actually is a good rule for this. Defer the levity-polymorphic binder check in indefinite modules any time the type-checker encounters a type variable whose RuntimeRep is a type family that cannot be reduced. The check will happen later any way, and more correct code will be accepted.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14525Backpack doesn't work with CPP2019-07-07T18:16:40ZEdward Z. YangBackpack doesn't work with CPPSteps to repro:
1. Create a package with a signature and a module which imports it
1. Add `{-# LANGUAGE CPP #-}` to the module
Expected result: it works
Actual result:
```
<command line>: unknown package: hole
```
<details><summary>...Steps to repro:
1. Create a package with a signature and a module which imports it
1. Add `{-# LANGUAGE CPP #-}` to the module
Expected result: it works
Actual result:
```
<command line>: unknown package: hole
```
<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":"Backpack doesn't work with CPP","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.2","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Steps to repro:\r\n1. Create a package with a signature and a module which imports it\r\n2. Add `{-# LANGUAGE CPP #-}` to the module\r\n\r\nExpected result: it works\r\n\r\nActual result:\r\n\r\n{{{\r\n<command line>: unknown package: hole\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14478Abstract pattern synonyms (for hsig and hs-boot)2019-07-07T18:16:52ZEdward Z. YangAbstract pattern synonyms (for hsig and hs-boot)Most declaration forms (data types, values, type families, etc) support forward declaration in hs-boot/hsig files. However, pattern synonyms do not. This seems like a major omission!
Some problems to solve:
- The obvious syntax `patter...Most declaration forms (data types, values, type families, etc) support forward declaration in hs-boot/hsig files. However, pattern synonyms do not. This seems like a major omission!
Some problems to solve:
- The obvious syntax `pattern Foo :: pat_ty` is insufficient to specify whether or not a pattern is bidirectional or unidirectional. How should this be represented syntactically?
- What is the interaction with bundling? Should it be possible to export a bundle of abstract pattern synonyms, with the intent that this means an implementation must also have bundled them together
- See also #12717; abstract pattern synonym should be implementable with a plain old constructor
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------------- |
| Version | 8.2.1 |
| Type | FeatureRequest |
| 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":"Abstract pattern synonyms (for hsig and hs-boot)","status":"New","operating_system":"","component":"Compiler (Type checker)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"Most declaration forms (data types, values, type families, etc) support forward declaration in hs-boot/hsig files. However, pattern synonyms do not. This seems like a major omission!\r\n\r\nSome problems to solve:\r\n\r\n* The obvious syntax `pattern Foo :: pat_ty` is insufficient to specify whether or not a pattern is bidirectional or unidirectional. How should this be represented syntactically?\r\n* What is the interaction with bundling? Should it be possible to export a bundle of abstract pattern synonyms, with the intent that this means an implementation must also have bundled them together\r\n* See also #12717; abstract pattern synonym should be implementable with a plain old constructor","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14304Instantiated libraries (Backpack) don't get linked with enough deps2019-07-07T18:17:33ZEdward Z. YangInstantiated libraries (Backpack) don't get linked with enough depsOne downstream instance of this reported at https://github.com/haskell/cabal/issues/4755
Basically, if you instantiate a library q with library p, you need to make sure libHSp.so shows up in its linker dependencies. This is not the case...One downstream instance of this reported at https://github.com/haskell/cabal/issues/4755
Basically, if you instantiate a library q with library p, you need to make sure libHSp.so shows up in its linker dependencies. This is not the case right now.
Patch coming (I filed this to get a bug number :)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------ |
| Version | 8.2.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Linking) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Instantiated libraries (Backpack) don't get linked with enough deps","status":"New","operating_system":"","component":"Compiler (Linking)","related":[],"milestone":"8.2.2","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"One downstream instance of this reported at https://github.com/haskell/cabal/issues/4755\r\n\r\nBasically, if you instantiate a library q with library p, you need to make sure libHSp.so shows up in its linker dependencies. This is not the case right now.\r\n\r\nPatch coming (I filed this to get a bug number :)","type_of_failure":"OtherFailure","blocking":[]} -->8.2.2https://gitlab.haskell.org/ghc/ghc/-/issues/14212Give better error message with non-supported Backpack/TH use2022-02-23T14:30:13ZEdward Z. YangGive better error message with non-supported Backpack/TH useThis is something of a follow up to #13268.
Suppose you have an indefinite package. If you use TemplateHaskell with a splice that was defined in the indefinite package itself, there is no reasonable way to expect this to work, since in ...This is something of a follow up to #13268.
Suppose you have an indefinite package. If you use TemplateHaskell with a splice that was defined in the indefinite package itself, there is no reasonable way to expect this to work, since in general you can't have compiled the the imported module before you need to run the splice (and the splice needs to be run before you know how the holes are instantiated.)
But say you try and do it anyway. GHC will give an error like this:
```
ghc: ^^ Could not load 'qzm0zi1zminplacezmENEL5G3hx7IK2t0f6HloyH_A_f_closure', dependency unresolved. See top entry above.
ByteCodeLink.lookupCE
During interactive linking, GHCi couldn't find the following symbol:
qzm0zi1zminplacezmENEL5G3hx7IK2t0f6HloyH_A_f_closure
This may be due to you not asking GHCi to load extra object files,
archives or DLLs needed by your current session. Restart GHCi, specifying
the missing library using the -L/path/to/object/dir and -lmissinglibname
flags, or simply by naming the relevant files on the GHCi command line.
Alternatively, this link failure might indicate a bug in GHCi.
If you suspect the latter, please send a bug report to:
glasgow-haskell-bugs@haskell.org
```
This is not a good error message. A good error message would be to say that you can't use in a splice a function defined in an indefinite package (as per the current library.)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.2.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Give better error message with non-supported Backpack/TH use","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"This is something of a follow up to #13268.\r\n\r\nSuppose you have an indefinite package. If you use TemplateHaskell with a splice that was defined in the indefinite package itself, there is no reasonable way to expect this to work, since in general you can't have compiled the the imported module before you need to run the splice (and the splice needs to be run before you know how the holes are instantiated.)\r\n\r\nBut say you try and do it anyway. GHC will give an error like this:\r\n\r\n{{{\r\nghc: ^^ Could not load 'qzm0zi1zminplacezmENEL5G3hx7IK2t0f6HloyH_A_f_closure', dependency unresolved. See top entry above.\r\n\r\n\r\nByteCodeLink.lookupCE\r\nDuring interactive linking, GHCi couldn't find the following symbol:\r\n qzm0zi1zminplacezmENEL5G3hx7IK2t0f6HloyH_A_f_closure\r\nThis may be due to you not asking GHCi to load extra object files,\r\narchives or DLLs needed by your current session. Restart GHCi, specifying\r\nthe missing library using the -L/path/to/object/dir and -lmissinglibname\r\nflags, or simply by naming the relevant files on the GHCi command line.\r\nAlternatively, this link failure might indicate a bug in GHCi.\r\nIf you suspect the latter, please send a bug report to:\r\n glasgow-haskell-bugs@haskell.org\r\n}}}\r\n\r\nThis is not a good error message. A good error message would be to say that you can't use in a splice a function defined in an indefinite package (as per the current library.)","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14210bkp files cannot find TemplateHaskell symbols (even without Backpack features)2023-05-05T12:59:22ZEdward Z. Yangbkp files cannot find TemplateHaskell symbols (even without Backpack features)```
{-# LANGUAGE TemplateHaskell #-}
unit th where
module TH where
f = [d| x = True |]
unit p where
dependency th
module B where
import TH
$(f)
```
When run, this gives:
```
ghc: ^^ Could not load 't...```
{-# LANGUAGE TemplateHaskell #-}
unit th where
module TH where
f = [d| x = True |]
unit p where
dependency th
module B where
import TH
$(f)
```
When run, this gives:
```
ghc: ^^ Could not load 'th_TH_f_closure', dependency unresolved. See top entry above.
ByteCodeLink.lookupCE
During interactive linking, GHCi couldn't find the following symbol:
th_TH_f_closure
This may be due to you not asking GHCi to load extra object files,
archives or DLLs needed by your current session. Restart GHCi, specifying
the missing library using the -L/path/to/object/dir and -lmissinglibname
flags, or simply by naming the relevant files on the GHCi command line.
Alternatively, this link failure might indicate a bug in GHCi.
If you suspect the latter, please send a bug report to:
glasgow-haskell-bugs@haskell.org
```
I am not sure how easy or hard the fix is. We should bump this priority up if we get more serious about supporting Template Haskell with Backpack.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------------ |
| Version | 8.2.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | low |
| Resolution | Unresolved |
| Component | Compiler (Linking) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"bkp files cannot find TemplateHaskell symbols (even without Backpack features)","status":"New","operating_system":"","component":"Compiler (Linking)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"{{{\r\n{-# LANGUAGE TemplateHaskell #-}\r\nunit th where\r\n module TH where\r\n f = [d| x = True |]\r\nunit p where\r\n dependency th\r\n module B where\r\n import TH\r\n $(f)\r\n}}}\r\n\r\nWhen run, this gives:\r\n\r\n{{{\r\nghc: ^^ Could not load 'th_TH_f_closure', dependency unresolved. See top entry above.\r\n\r\n\r\nByteCodeLink.lookupCE\r\nDuring interactive linking, GHCi couldn't find the following symbol:\r\n th_TH_f_closure\r\nThis may be due to you not asking GHCi to load extra object files,\r\narchives or DLLs needed by your current session. Restart GHCi, specifying\r\nthe missing library using the -L/path/to/object/dir and -lmissinglibname\r\nflags, or simply by naming the relevant files on the GHCi command line.\r\nAlternatively, this link failure might indicate a bug in GHCi.\r\nIf you suspect the latter, please send a bug report to:\r\n glasgow-haskell-bugs@haskell.org\r\n}}}\r\n\r\nI am not sure how easy or hard the fix is. We should bump this priority up if we get more serious about supporting Template Haskell with Backpack.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14063Compiling with --backpack with undefined dependency results in "the 'impossib...2023-05-05T12:59:10ZrcookCompiling with --backpack with undefined dependency results in "the 'impossible' happened"Using GHC 8.2.1:
```
> ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.2.1
```
And compiling with `--backpack` as follows:
```
> ghc --backpack foo.bkp
[1 of 4] Processing foo-indef
[1 of 2] Compiling Str[si...Using GHC 8.2.1:
```
> ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.2.1
```
And compiling with `--backpack` as follows:
```
> ghc --backpack foo.bkp
[1 of 4] Processing foo-indef
[1 of 2] Compiling Str[sig] ( foo-indef\Str.hsig, nothing )
[2 of 2] Compiling Foo ( foo-indef\Foo.hs, nothing )
[2 of 4] Processing foo-string
Instantiating foo-string
[1 of 1] Compiling Str ( foo-string\Str.hs, foo-string\Str.o )
[3 of 4] Processing foo-int
Instantiating foo-int
[1 of 1] Compiling Str ( foo-int\Str.hs, foo-int\Str.o )
[4 of 4] Processing main
ghc.EXE: panic! (the 'impossible' happened)
(GHC version 8.2.1 for x86_64-unknown-mingw32):
no package name
CallStack (from HasCallStack):
error, called at compiler\backpack\DriverBkp.hs:573:32 in ghc:DriverBkp
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
make: *** [foo-indef/Foo.hi] Error 1
```
See attached `foo.bkp` file. While the Backpack file *is* invalid, in that the `main` unit mentions the `foo` dependency, which does not exist, this shouldn't lead to a GHC panic.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Compiling with --backpack with undefined dependency results in \"the 'impossible' happened\"","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["Backpack"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Using GHC 8.2.1:\r\n\r\n{{{\r\n> ghc --version\r\nThe Glorious Glasgow Haskell Compilation System, version 8.2.1\r\n}}}\r\n\r\nAnd compiling with `--backpack` as follows:\r\n\r\n{{{\r\n> ghc --backpack foo.bkp\r\n[1 of 4] Processing foo-indef\r\n [1 of 2] Compiling Str[sig] ( foo-indef\\Str.hsig, nothing )\r\n [2 of 2] Compiling Foo ( foo-indef\\Foo.hs, nothing )\r\n[2 of 4] Processing foo-string\r\n Instantiating foo-string\r\n [1 of 1] Compiling Str ( foo-string\\Str.hs, foo-string\\Str.o )\r\n[3 of 4] Processing foo-int\r\n Instantiating foo-int\r\n [1 of 1] Compiling Str ( foo-int\\Str.hs, foo-int\\Str.o )\r\n[4 of 4] Processing main\r\nghc.EXE: panic! (the 'impossible' happened)\r\n (GHC version 8.2.1 for x86_64-unknown-mingw32):\r\n no package name\r\nCallStack (from HasCallStack):\r\n error, called at compiler\\backpack\\DriverBkp.hs:573:32 in ghc:DriverBkp\r\n\r\nPlease report this as a GHC bug: http://www.haskell.org/ghc/reportabug\r\n\r\nmake: *** [foo-indef/Foo.hi] Error 1\r\n}}}\r\n\r\nSee attached `foo.bkp` file. While the Backpack file ''is'' invalid, in that the `main` unit mentions the `foo` dependency, which does not exist, this shouldn't lead to a GHC panic.\r\n","type_of_failure":"OtherFailure","blocking":[]} -->Edward Z. YangEdward Z. Yanghttps://gitlab.haskell.org/ghc/ghc/-/issues/13955Backpack does not handle unlifted types2021-07-19T22:53:12ZAndrew MartinBackpack does not handle unlifted typesIn the code snippet below, I attempt to use backpack with levity polymorphism:
```
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
unit number-unknown where
signature Numbe...In the code snippet below, I attempt to use backpack with levity polymorphism:
```
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
unit number-unknown where
signature NumberUnknown where
import GHC.Types
data Number
plus :: Number -> Number -> Number
multiply :: Number -> Number -> Number
module NumberStuff where
import NumberUnknown
funcA :: Number -> Number -> Number
funcA x y = plus x (multiply x y)
unit number-int where
module NumberUnknown where
type Number = Int
plus :: Int -> Int -> Int
plus = (+)
multiply :: Int -> Int -> Int
multiply = (*)
unit number-unboxed-int where
module NumberUnknown where
import GHC.Prim
type Number = Int#
plus :: Int# -> Int# -> Int#
plus = (+#)
multiply :: Int# -> Int# -> Int#
multiply = (*#)
unit main where
dependency number-unknown[NumberUnknown=number-unboxed-int:NumberUnknown]
module Main where
import NumberStuff
main = putStrLn "Hello world!"
```
Compiling this with `ghc --backpack packer.bkp` fails with the following error:
```
- Type constructor ‘Number’ has conflicting definitions in the module
and its hsig file
Main module: type Number = GHC.Prim.Int# :: TYPE 'GHC.Types.IntRep
Hsig file: data Number
The types have different kinds
- while checking that number-unboxed-int:NumberUnknown implements signature NumberUnknown in number-unknown[NumberUnknown=number-unboxed-int:NumberUnknown]
type Number = Int#
```
The error is pretty clear: `Number` can only be instantiated by types of kind `Type` (aka `TYPE LiftedRep`). Even while remaining levity monomorphic, there doesn't seem to be a way to pick a different kind. For example, redefining `Number` in the signature as
```
data Number :: TYPE IntRep
```
leads to the following immediate failure:
```
Kind signature on data type declaration has non-* return kind TYPE 'IntRep
```
I do not understand any of the internals of backpack, so I do not understand if there's anything fundamental that makes this impossible. Going one step further, I would like to be able to do something like this (the syntax here is not even currently valid for a backpack signature):
```
type MyRep :: RuntimeRep
data Number :: TYPE MyRep
```
This may be instantiated with something like this:
```
type MyRep = IntRep
type Number = Int#
```
And then end users would be able to monomorphize levity-polymorphic functions. This would be really neat because there is currently no way to do this in GHC.
So, I guess there are really two feature requests in here. One is the ability to use unlifted data types with backpack. The other is the ability to use backpack to monomorphize levity-polymorphic functions.
It seems unlikely to sneak this into GHC 8.2 but who knows!8.4.1https://gitlab.haskell.org/ghc/ghc/-/issues/13765GHC cannot parse valid Haskell98 whose first identifier is named signature2019-07-07T18:20:11ZEdward Z. YangGHC cannot parse valid Haskell98 whose first identifier is named signatureThis no longer parses in GHC 8.2:
```
ezyang@sabre:~$ cat A.hs
signature = 2
ezyang@sabre:~$ ghc-8.0 -c A.hs
A.hs:1:1: error:
The IO action ‘main’ is not defined in module ‘Main’
ezyang@sabre:~$ ghc-head -c A.hs
A.hs:1:11: error:
...This no longer parses in GHC 8.2:
```
ezyang@sabre:~$ cat A.hs
signature = 2
ezyang@sabre:~$ ghc-8.0 -c A.hs
A.hs:1:1: error:
The IO action ‘main’ is not defined in module ‘Main’
ezyang@sabre:~$ ghc-head -c A.hs
A.hs:1:11: error:
parse error on input ‘=’
Perhaps you need a 'let' in a 'do' block?
e.g. 'let x = 5' instead of 'x = 5'
|
1 | signature =
```
The problem is that signature is only a keyword in the module header and not in the rest of the code, which means that there is a shift/reduce conflict when you have a `signature` at the top of the module.
This is fairly benign bug as you can only trigger it when you have no imports; nevertheless, we should fix it. One possibility is to have a completely different parser entry when you are parsing an `hsig` file so that `signature` never occurs in a module header when you parse a normal Haskell file. ISTR this was modestly more irritating to implement but perhaps it is still not too bad. (Note that the shift/reduce conflict still exists, but since you'll never declare a signature without a module header it is essentially irrelevant.)
I discovered this when mpickering pointed out that adding 'signature' to the module header increased the number of shift reduce conflicts. (https://github.com/haskell-suite/haskell-src-exts/pull/355\#issuecomment-304536290). This wasn't the case in GHC's parser but only accidentally: there is already a shift reduce conflict when you have a top-level Haddock doc block!
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------- |
| Version | 8.2.1-rc2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | low |
| Resolution | Unresolved |
| Component | Compiler (Parser) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"GHC cannot parse valid Haskell98 whose first identifier is named signature","status":"New","operating_system":"","component":"Compiler (Parser)","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1-rc2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"This no longer parses in GHC 8.2:\r\n\r\n{{{\r\nezyang@sabre:~$ cat A.hs\r\nsignature = 2\r\nezyang@sabre:~$ ghc-8.0 -c A.hs\r\n\r\nA.hs:1:1: error:\r\n The IO action ‘main’ is not defined in module ‘Main’\r\nezyang@sabre:~$ ghc-head -c A.hs\r\n\r\nA.hs:1:11: error:\r\n parse error on input ‘=’\r\n Perhaps you need a 'let' in a 'do' block?\r\n e.g. 'let x = 5' instead of 'x = 5'\r\n |\r\n1 | signature = \r\n}}}\r\n\r\nThe problem is that signature is only a keyword in the module header and not in the rest of the code, which means that there is a shift/reduce conflict when you have a `signature` at the top of the module.\r\n\r\nThis is fairly benign bug as you can only trigger it when you have no imports; nevertheless, we should fix it. One possibility is to have a completely different parser entry when you are parsing an `hsig` file so that `signature` never occurs in a module header when you parse a normal Haskell file. ISTR this was modestly more irritating to implement but perhaps it is still not too bad. (Note that the shift/reduce conflict still exists, but since you'll never declare a signature without a module header it is essentially irrelevant.)\r\n\r\nI discovered this when mpickering pointed out that adding 'signature' to the module header increased the number of shift reduce conflicts. (https://github.com/haskell-suite/haskell-src-exts/pull/355#issuecomment-304536290). This wasn't the case in GHC's parser but only accidentally: there is already a shift reduce conflict when you have a top-level Haddock doc block!","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13493Recompilation avoidance and Backpack2020-08-11T13:37:30ZEdward Z. YangRecompilation avoidance and BackpackToday, recompilation avoidance is centered around two major mechanisms:
1. First, we keep track of entities we \*use\* (`tcg_dus`), which is done by reading off all external names from the renamed source code of a Haskell source file.
1...Today, recompilation avoidance is centered around two major mechanisms:
1. First, we keep track of entities we \*use\* (`tcg_dus`), which is done by reading off all external names from the renamed source code of a Haskell source file.
1. Second, we keep track of what we \*import\* (`tcg_imports`), which tracked when we rename imports.
These two pieces of information get assembled into a module-indexed series of usages in `mk_mod_usage_info`. The general idea is that when an entity is used, we must record the hash of the entity; when a module is imported, we must record its export hash.
There is an implicit assumption here, which is that a (direct) import is the only way we depend on the exports of a module, and an occurrence of a name in the renamed syntax is the only way we depend on an actual entity.
Backpack breaks these assumptions:
- When we perform signature merging, we depend on the exports and entities of each of the signatures we merge in. Furthermore, it is important to distinguish each of these by identity module (not semantic module, which collapses the distinction.)
- When we instantiate a module, we depend on the exports and entities of the implementing module.
When I initially implemented Backpack, I slowly added extra information to fix recompilation problems as I noticed them. I thus accreted the following recompilation avoidance mechanisms:
- When signature merging occurs, we specially record the module hash for each used merge requirement as a special new field `UsageMergedRequirement`, and recomp if the module hash changed at all. We also add each merged signature to ImportAvails (but not as an "import") to ensure we pick up family instances.
- When we instantiate a module, we treat it as if we had a direct import of it (not yet merged, in https://phabricator.haskell.org/D3381). Since instantiations are always referencing non-local modules, we'll always record a module hash in such cases.
This is quite a hodgepodge, and I have no confidence that it is correct. For example, if an implementing module reexports an entity from another module, and that original entity changes, I doubt we recompile at this point. We "accidentally" handle the case when it's not a reexport because we record the module hash for the entire instantiating module.
It seems that it would be better if we can recast this in terms of imports and usages. Here is a try at the design:
- In both instantiation and merging, we must record the export hash of the modules we instantiated/merged in. It is a little troublesome to think of these as imports, however, because they're not (and if you try to implement this, you find yourself making a fake ImportedModVal for an import that doesn't exist); I think the correct thing here is to introduce a new notion of dependency for things that don't correspond to source level imports (another possibility is to add another constructor to ImportedModVal but the effect of this on existing code would have to be determined.)
- The usages when we instantiate a signature are the (instantiated) usages of the original signature (in particular, this picks up the usages from instance lookup), plus a usage for each entity that we match against (because we must rematch if the type changes.)
- Usages for signature merging are a little trickier. We want a usage for every entity that we end up merging in (so, we must record usages post thinning), BUT we must make sure the usage points at the identity module of the signature that originally provided it, not the semantic module (which will invariably point to the current module under compilation.)
One more thing: when we instantiate a module on-the-fly, we need to account for how we instantiated it (to put it differently, the recompilation information we compute when we do on-the-fly should be the (morally) the same as what we would get if we actually compiled the modules in question. This is a bit troublesome since we don't have detailed information relating how a signature was instantiated and what we used (the on-the-fly instantiation process shortcuts this). The simplest thing is probably to just record the module hashes of each module that was used to instantiate an imported module (recursively); we might be able to do this even by just twiddling `mi_mod_hash` hash when we instantiate (the alternative is to switch to recording InstalledModule/InstalledUnitId only in hashes, and augmenting usage information to also carry along instantiations.)
Another problem is that we record usages for Module (instantiated things), but hashes are actually on an InstalledModule basis.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Recompilation avoidance and Backpack","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.1","keywords":["backpack","recomp"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Today, recompilation avoidance is centered around two major mechanisms:\r\n\r\n1. First, we keep track of entities we *use* (`tcg_dus`), which is done by reading off all external names from the renamed source code of a Haskell source file.\r\n\r\n2. Second, we keep track of what we *import* (`tcg_imports`), which tracked when we rename imports.\r\n\r\nThese two pieces of information get assembled into a module-indexed series of usages in `mk_mod_usage_info`. The general idea is that when an entity is used, we must record the hash of the entity; when a module is imported, we must record its export hash.\r\n\r\nThere is an implicit assumption here, which is that a (direct) import is the only way we depend on the exports of a module, and an occurrence of a name in the renamed syntax is the only way we depend on an actual entity.\r\n\r\nBackpack breaks these assumptions:\r\n\r\n* When we perform signature merging, we depend on the exports and entities of each of the signatures we merge in. Furthermore, it is important to distinguish each of these by identity module (not semantic module, which collapses the distinction.)\r\n\r\n* When we instantiate a module, we depend on the exports and entities of the implementing module.\r\n\r\nWhen I initially implemented Backpack, I slowly added extra information to fix recompilation problems as I noticed them. I thus accreted the following recompilation avoidance mechanisms:\r\n\r\n* When signature merging occurs, we specially record the module hash for each used merge requirement as a special new field `UsageMergedRequirement`, and recomp if the module hash changed at all. We also add each merged signature to ImportAvails (but not as an \"import\") to ensure we pick up family instances.\r\n\r\n* When we instantiate a module, we treat it as if we had a direct import of it (not yet merged, in https://phabricator.haskell.org/D3381). Since instantiations are always referencing non-local modules, we'll always record a module hash in such cases.\r\n\r\nThis is quite a hodgepodge, and I have no confidence that it is correct. For example, if an implementing module reexports an entity from another module, and that original entity changes, I doubt we recompile at this point. We \"accidentally\" handle the case when it's not a reexport because we record the module hash for the entire instantiating module.\r\n\r\nIt seems that it would be better if we can recast this in terms of imports and usages. Here is a try at the design:\r\n\r\n* In both instantiation and merging, we must record the export hash of the modules we instantiated/merged in. It is a little troublesome to think of these as imports, however, because they're not (and if you try to implement this, you find yourself making a fake ImportedModVal for an import that doesn't exist); I think the correct thing here is to introduce a new notion of dependency for things that don't correspond to source level imports (another possibility is to add another constructor to ImportedModVal but the effect of this on existing code would have to be determined.)\r\n\r\n* The usages when we instantiate a signature are the (instantiated) usages of the original signature (in particular, this picks up the usages from instance lookup), plus a usage for each entity that we match against (because we must rematch if the type changes.)\r\n\r\n* Usages for signature merging are a little trickier. We want a usage for every entity that we end up merging in (so, we must record usages post thinning), BUT we must make sure the usage points at the identity module of the signature that originally provided it, not the semantic module (which will invariably point to the current module under compilation.)\r\n\r\nOne more thing: when we instantiate a module on-the-fly, we need to account for how we instantiated it (to put it differently, the recompilation information we compute when we do on-the-fly should be the (morally) the same as what we would get if we actually compiled the modules in question. This is a bit troublesome since we don't have detailed information relating how a signature was instantiated and what we used (the on-the-fly instantiation process shortcuts this). The simplest thing is probably to just record the module hashes of each module that was used to instantiate an imported module (recursively); we might be able to do this even by just twiddling `mi_mod_hash` hash when we instantiate (the alternative is to switch to recording InstalledModule/InstalledUnitId only in hashes, and augmenting usage information to also carry along instantiations.)\r\n\r\nAnother problem is that we record usages for Module (instantiated things), but hashes are actually on an InstalledModule basis.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/13469-fdefer-type-errors for Backpack2019-07-07T18:21:44ZEdward Z. Yang-fdefer-type-errors for BackpackIt would be great if `-fdefer-type-errors` worked with Backpack. There are two senses in which it could work:
1. When matching signatures, if the instantiating module didn't provide a required function, we could just create one out of t...It would be great if `-fdefer-type-errors` worked with Backpack. There are two senses in which it could work:
1. When matching signatures, if the instantiating module didn't provide a required function, we could just create one out of thin air so we can continue building.
1. When matching signature, if the implementation doesn't match the signature, we instead create a deferred type error.
(2) is more difficult because it basically requires us to solve #12703.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.1 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"-fdefer-type-errors for Backpack","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.1","keywords":["backpack"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"It would be great if `-fdefer-type-errors` worked with Backpack. There are two senses in which it could work:\r\n\r\n1. When matching signatures, if the instantiating module didn't provide a required function, we could just create one out of thin air so we can continue building.\r\n\r\n2. When matching signature, if the implementation doesn't match the signature, we instead create a deferred type error.\r\n\r\n(2) is more difficult because it basically requires us to solve #12703.","type_of_failure":"OtherFailure","blocking":[]} -->