Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add compatibility shims for TypeAbstractions in GHC 9.8 #104

Merged
merged 2 commits into from
Jul 31, 2023

Conversation

RyanGlScott
Copy link
Collaborator

GHC 9.8 implements GHC proposal #425, which adds support for invisible binders for type-level declarations. This impacts Template Haskell, as various TyVarBndrs are now parameterized by a new BndrVis type instead of ().

As such, th-abstraction must be updated accordingly. This patch does so by:

  • Backporting BndrVis to Language.Haskell.TH.Datatype.TyVarBndr, as well as related types and utility functions. With these changes, one can write BndrVis-related code that will compile on all GHC versions without CPP.

  • Changing dataDCompat and newtypeDCompat in Language.Haskell.TH.Datatype to use TyVarBndrVis instead of TyVarBndrUnit to make it compile on GHC 9.8, matching similar changes in DataD and NewtypeD in template-haskell. Because BndrVis is a synonym for () on pre-9.8 versions of GHC, this change is unlikely to break any existing code, but do be aware of this change if you write code that needs to support GHC 9.8 or later.

See the th-abstraction changelog for the full details.

Fixes #103.

@ncfavier
Copy link

Does not build with GHC 9.9.20230703, is this expected?

src/Language/Haskell/TH/Datatype/TyVarBndr.hs:219:10: error: [GHC-87543]
    Ambiguous occurrence ‘DefaultBndrFlag’.
    It could refer to
       either ‘Language.Haskell.TH.Lib.DefaultBndrFlag’,
              imported from ‘Language.Haskell.TH.Lib’ at src/Language/Haskell/TH/Datatype/TyVarBndr.hs:106:1-30,
           or ‘Language.Haskell.TH.Datatype.TyVarBndr.DefaultBndrFlag’,
              defined at src/Language/Haskell/TH/Datatype/TyVarBndr.hs:216:1.
    |
219 | instance DefaultBndrFlag () where
    |          ^^^^^^^^^^^^^^^

src/Language/Haskell/TH/Datatype/TyVarBndr.hs:222:10: error: [GHC-87543]
    Ambiguous occurrence ‘DefaultBndrFlag’.
    It could refer to
       either ‘Language.Haskell.TH.Lib.DefaultBndrFlag’,
              imported from ‘Language.Haskell.TH.Lib’ at src/Language/Haskell/TH/Datatype/TyVarBndr.hs:106:1-30,
           or ‘Language.Haskell.TH.Datatype.TyVarBndr.DefaultBndrFlag’,
              defined at src/Language/Haskell/TH/Datatype/TyVarBndr.hs:216:1.
    |
222 | instance DefaultBndrFlag Specificity where
    |          ^^^^^^^^^^^^^^^

@RyanGlScott
Copy link
Collaborator Author

This is expected—at least for the time being. GHC's ghc-9.8 branch has bumped its Template Haskell version to 2.21.0.0, but GHC's master branch hasn't done this yet. As a result, the #if MIN_VERSION_template_haskell(2,21,0) CPP guards used in th-abstraction won't work as intended.

This should be addressed once https://gitlab.haskell.org/ghc/ghc/-/merge_requests/10936 lands in GHC's master branch.

GHC 9.8 implements
[GHC proposal #425](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0425-decl-invis-binders.rst),
which adds support for invisible binders for type-level declarations. This
impacts Template Haskell, as various `TyVarBndr`s are now parameterized by a
new `BndrVis` type instead of `()`.

As such, `th-abstraction` must be updated accordingly. This patch does so by:

* Backporting `BndrVis` to `Language.Haskell.TH.Datatype.TyVarBndr`, as well as
  related types and utility functions. With these changes, one can write
  `BndrVis`-related code that will compile on all GHC versions without CPP.

* Changing `dataDCompat` and `newtypeDCompat` in `Language.Haskell.TH.Datatype`
  to use `TyVarBndrVis` instead of `TyVarBndrUnit` to make it compile on GHC
  9.8, matching similar changes in `DataD` and `NewtypeD` in
  `template-haskell`. Because `BndrVis` is a synonym for `()` on pre-9.8
  versions of GHC, this change is unlikely to break any existing code, but do
  be aware of this change if you write code that needs to support GHC 9.8 or
  later.

See the `th-abstraction` changelog for the full details.

Fixes #103.
@RyanGlScott RyanGlScott merged commit dee5fb9 into master Jul 31, 2023
32 checks passed
@RyanGlScott RyanGlScott deleted the type-abstractions branch July 31, 2023 11:19
@michaelpj
Copy link

Just looking at this - is there any intention to change the type of DatatypeInfo.datatypeVars and so on? Those still return TyVarBndrUnit.

@RyanGlScott
Copy link
Collaborator Author

is there any intention to change the type of DatatypeInfo.datatypeVars and so on? Those still return TyVarBndrUnit.

No, I intentionally did not change datatypeVars' type. The reason is because of data family instances. If you have this:

data family D a
data instance D (Either a b) = MkD

Then when you call reifyDatatype 'MkD, you'll have something like datatypeVars = [PlainTV a (), PlainTV b ()]. If datatypeVars were a list of TyVarBndrVis values, however, then we'd have to determine whether a and b should be given BndrReq or BndrInvis. It's not at all obvious to me what the right answer to that question is, since a/b don't really have the same visibility properties that you'd see in an ordinary data type declaration. After all, you can't write something write D @Bool @Int to get D (Either Bool Int).

For this reason, I opted not to change that part of the API.

@erikd
Copy link

erikd commented Sep 27, 2023

@RyanGlScott I have some code:

  di@(TH.DatatypeInfo{TH.datatypeVariant=dVariant, TH.datatypeCons=cons, TH.datatypeName=name, TH.datatypeVars=tTypeVars}) <- TH.normalizeDec dec

  -- a fresh name for the new datatype, but same lexically as the old one
  cname <- TH.newName (show name)
  -- The newtype declaration
  let ntD =
        let con = TH.NormalC cname [(TH.Bang TH.NoSourceUnpackedness TH.NoSourceStrictness, TH.ConT ''BuiltinData)]
        in TH.NewtypeD [] name tTypeVars Nothing con derivs

that compiled with ghc-9.6 but fails with ghc9.8 with:

    • Couldn't match type ‘()’ with ‘TH.BndrVis’
      Expected: [TH.TyVarBndr TH.BndrVis]
        Actual: [TH.TyVarBndrUnit]
    • In the third argument of ‘TH.NewtypeD’, namely ‘tTypeVars’
      In the expression: TH.NewtypeD [] name tTypeVars Nothing con derivs
      In the expression:
        let con = TH.NormalC cname [...]
        in TH.NewtypeD [] name tTypeVars Nothing con derivs
   |
88 |         in TH.NewtypeD [] name tTypeVars Nothing con derivs
   |                                ^^^^^^^^^

So it seems that normalizeDec returns a value that is the wrong type to fit in a NewtypeD constructor. Is there a way of converting a TyVarBndrUnit to a TyVarBndr BndrVis ?

@RyanGlScott
Copy link
Collaborator Author

You can convert the flags in a list of TyVarBndrs by using the changeTVFlags function. I don't quite understand what your code is doing, but something like changeTVFlags BndrReq tTypeVars might suffice.

@erikd
Copy link

erikd commented Sep 27, 2023

So close:

src/PlutusTx/AsData.hs:90:46: error: [GHC-31891]
    • Illegal term-level use of the type constructor or class ‘TH.BndrVis’
    • imported qualified from ‘Language.Haskell.TH.Datatype.TyVarBndr’ at src/PlutusTx/AsData.hs:18:1-61
      (and originally defined in ‘Language.Haskell.TH.Syntax’)
    • In the first argument of ‘TH.changeTVFlags’, namely ‘TH.BndrVis’
      In the second argument of ‘($)’, namely
        ‘TH.changeTVFlags TH.BndrVis [tTypeVars]’
      In the third argument of ‘TH.NewtypeD’, namely
        ‘(Prelude.head $ TH.changeTVFlags TH.BndrVis [tTypeVars])’
   |
90 |             (Prelude.head $ TH.changeTVFlags TH.BndrVis [tTypeVars])
   |     

@RyanGlScott
Copy link
Collaborator Author

BndrReq, not BndrVis.

@erikd
Copy link

erikd commented Sep 27, 2023

Awesome. Thanks @RyanGlScott !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Adapt to TypeAbstractions in GHC 9.8
4 participants