diff --git a/.github/workflows/haskell.yml b/.github/workflows/haskell.yml index e255f32..be81a74 100644 --- a/.github/workflows/haskell.yml +++ b/.github/workflows/haskell.yml @@ -1,29 +1,24 @@ name: github-action -on: [push, pull_request] +on: [push, pull_request] jobs: build: strategy: matrix: - ghc: ['8.0.2', '8.2.2', '8.4.4', '8.6.5', '8.8.4', '8.10.2', '9.0.1'] + ghc: ['8.4.4', '8.6.5', '8.8.4', '8.10.7', '9.0.2', '9.2.5'] os: ['ubuntu-latest', 'macos-latest'] - exclude: - # There are some linker warnings in 802 on darwin that - # cause compilation to fail - # See https://github.com/NixOS/nixpkgs/issues/25139 - - ghc: '8.0.2' - os: 'macos-latest' runs-on: ${{ matrix.os }} name: GHC ${{ matrix.ghc }} on ${{ matrix.os }} steps: - - uses: actions/checkout@v2 - - uses: actions/setup-haskell@v1 + - uses: actions/checkout@v3 + - uses: haskell/actions/setup@v2 with: ghc-version: ${{ matrix.ghc }} + cabal-version: '3.10.1.0' - name: Cache - uses: actions/cache@v1 + uses: actions/cache@v3 env: cache-name: cache-cabal with: @@ -36,10 +31,12 @@ jobs: ${{ runner.os }} - name: Install dependencies - run: | - cabal update - cabal build --only-dependencies --enable-tests --enable-benchmarks + run: cabal build --only-dependencies --enable-tests --enable-benchmarks - name: Build run: cabal build --enable-tests --enable-benchmarks all - name: Run tests - run: cabal test all + run: cabal test --enable-tests all + - if: matrix.ghc != '8.4.4' + # docs aren't built on ghc 8.4.4 because some dependency docs don't build on older GHCs + name: Build Docs + run: cabal haddock diff --git a/ChangeLog.md b/ChangeLog.md index 5621c70..f79743d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,10 @@ # Revision history for aeson-gadt-th +## 0.2.5.2 - 2024-05-28 + +* Loosen version bounds +* Support GHC 9.8 + ## 0.2.5.1 - 2022-01-04 * Remove dependency on `th-extras`. We were just using a reexport (under a diff --git a/aeson-gadt-th.cabal b/aeson-gadt-th.cabal index 2a1cb1d..cf5eeca 100644 --- a/aeson-gadt-th.cabal +++ b/aeson-gadt-th.cabal @@ -1,6 +1,6 @@ cabal-version: 1.24 name: aeson-gadt-th -version: 0.2.5.1 +version: 0.2.5.2 synopsis: Derivation of Aeson instances for GADTs category: JSON description: Template Haskell for generating ToJSON and FromJSON instances for GADTs. See for examples. @@ -20,13 +20,13 @@ flag build-readme library exposed-modules: Data.Aeson.GADT.TH - build-depends: base >= 4.8 && < 4.16 - , aeson >= 1.3 && < 1.6 + build-depends: base >= 4.8 && < 4.20 + , aeson >= 1.3 && < 2.3 , containers >= 0.5 && < 0.7 , dependent-sum >= 0.4 && < 0.8 - , transformers >= 0.5 && < 0.6 - , template-haskell >= 2.11.0 && < 2.18 - , th-abstraction >= 0.4 && < 0.5 + , transformers >= 0.5 && < 0.7 + , template-haskell >= 2.11.0 && < 2.22 + , th-abstraction >= 0.4 && < 0.8 if impl(ghc < 8.2) build-depends: dependent-sum < 0.6.2.2 hs-source-dirs: src @@ -39,7 +39,7 @@ executable readme build-depends: base , aeson , dependent-sum - , dependent-sum-template >= 0.1 && < 0.2 + , dependent-sum-template >= 0.2 && < 0.3 , dependent-map >= 0.3 && < 0.5 , aeson-gadt-th default-language: Haskell2010 diff --git a/nixpkgs/23.11/default.nix b/nixpkgs/23.11/default.nix new file mode 100644 index 0000000..2b4d4ab --- /dev/null +++ b/nixpkgs/23.11/default.nix @@ -0,0 +1,2 @@ +# DO NOT HAND-EDIT THIS FILE +import (import ./thunk.nix) \ No newline at end of file diff --git a/nixpkgs/23.11/github.json b/nixpkgs/23.11/github.json new file mode 100644 index 0000000..bf7d8e3 --- /dev/null +++ b/nixpkgs/23.11/github.json @@ -0,0 +1,8 @@ +{ + "owner": "nixos", + "repo": "nixpkgs", + "branch": "nixos-23.11", + "private": false, + "rev": "9d29cd266cebf80234c98dd0b87256b6be0af44e", + "sha256": "0bkrjx4x6sy4g9kmcddhlwrl4cpm4yvj7cljd7b8crf7kxpvaaf6" +} diff --git a/nixpkgs/23.11/thunk.nix b/nixpkgs/23.11/thunk.nix new file mode 100644 index 0000000..20f2d28 --- /dev/null +++ b/nixpkgs/23.11/thunk.nix @@ -0,0 +1,12 @@ +# DO NOT HAND-EDIT THIS FILE +let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }: + if !fetchSubmodules && !private then builtins.fetchTarball { + url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256; + } else (import (builtins.fetchTarball { + url = "https://github.com/NixOS/nixpkgs/archive/3aad50c30c826430b0270fcf8264c8c41b005403.tar.gz"; + sha256 = "0xwqsf08sywd23x0xvw4c4ghq0l28w2ki22h0bdn766i16z9q2gr"; +}) {}).fetchFromGitHub { + inherit owner repo rev sha256 fetchSubmodules private; + }; + json = builtins.fromJSON (builtins.readFile ./github.json); +in fetch json \ No newline at end of file diff --git a/nixpkgs/reflex-platform/default.nix b/nixpkgs/reflex-platform/default.nix new file mode 100644 index 0000000..2b4d4ab --- /dev/null +++ b/nixpkgs/reflex-platform/default.nix @@ -0,0 +1,2 @@ +# DO NOT HAND-EDIT THIS FILE +import (import ./thunk.nix) \ No newline at end of file diff --git a/nixpkgs/reflex-platform/github.json b/nixpkgs/reflex-platform/github.json new file mode 100644 index 0000000..dbb1477 --- /dev/null +++ b/nixpkgs/reflex-platform/github.json @@ -0,0 +1,7 @@ +{ + "owner": "reflex-frp", + "repo": "reflex-platform", + "private": false, + "rev": "6fbaf9b5dafd3e1afc538049654fb8ab8ce64965", + "sha256": "1a24s2agmmb3xnm97hhki6v0vi1h3280dihldqxghha07a9dsd3i" +} diff --git a/nixpkgs/reflex-platform/thunk.nix b/nixpkgs/reflex-platform/thunk.nix new file mode 100644 index 0000000..20f2d28 --- /dev/null +++ b/nixpkgs/reflex-platform/thunk.nix @@ -0,0 +1,12 @@ +# DO NOT HAND-EDIT THIS FILE +let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }: + if !fetchSubmodules && !private then builtins.fetchTarball { + url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256; + } else (import (builtins.fetchTarball { + url = "https://github.com/NixOS/nixpkgs/archive/3aad50c30c826430b0270fcf8264c8c41b005403.tar.gz"; + sha256 = "0xwqsf08sywd23x0xvw4c4ghq0l28w2ki22h0bdn766i16z9q2gr"; +}) {}).fetchFromGitHub { + inherit owner repo rev sha256 fetchSubmodules private; + }; + json = builtins.fromJSON (builtins.readFile ./github.json); +in fetch json \ No newline at end of file diff --git a/nixpkgs/unstable/default.nix b/nixpkgs/unstable/default.nix new file mode 100644 index 0000000..2b4d4ab --- /dev/null +++ b/nixpkgs/unstable/default.nix @@ -0,0 +1,2 @@ +# DO NOT HAND-EDIT THIS FILE +import (import ./thunk.nix) \ No newline at end of file diff --git a/nixpkgs/unstable/github.json b/nixpkgs/unstable/github.json new file mode 100644 index 0000000..6a17c43 --- /dev/null +++ b/nixpkgs/unstable/github.json @@ -0,0 +1,8 @@ +{ + "owner": "nixos", + "repo": "nixpkgs", + "branch": "nixpkgs-unstable", + "private": false, + "rev": "e2dd4e18cc1c7314e24154331bae07df76eb582f", + "sha256": "19zbxf7rb787jvyrfhl4z9sn3aisd6xvx6ikybbi75ym9sy39jds" +} diff --git a/nixpkgs/unstable/thunk.nix b/nixpkgs/unstable/thunk.nix new file mode 100644 index 0000000..20f2d28 --- /dev/null +++ b/nixpkgs/unstable/thunk.nix @@ -0,0 +1,12 @@ +# DO NOT HAND-EDIT THIS FILE +let fetch = { private ? false, fetchSubmodules ? false, owner, repo, rev, sha256, ... }: + if !fetchSubmodules && !private then builtins.fetchTarball { + url = "https://github.com/${owner}/${repo}/archive/${rev}.tar.gz"; inherit sha256; + } else (import (builtins.fetchTarball { + url = "https://github.com/NixOS/nixpkgs/archive/3aad50c30c826430b0270fcf8264c8c41b005403.tar.gz"; + sha256 = "0xwqsf08sywd23x0xvw4c4ghq0l28w2ki22h0bdn766i16z9q2gr"; +}) {}).fetchFromGitHub { + inherit owner repo rev sha256 fetchSubmodules private; + }; + json = builtins.fromJSON (builtins.readFile ./github.json); +in fetch json \ No newline at end of file diff --git a/release.nix b/release.nix index d3b5016..e02e330 100644 --- a/release.nix +++ b/release.nix @@ -1,103 +1,21 @@ -{ }: -let - nixpkgsSets = import ./.ci/nixpkgs.nix; - inherit (nixpkgsSets) nixos1809 nixos2003 unstable; - inherit (nixos2003) lib; - inherit (nixos2003.haskell.lib) doJailbreak dontCheck; - dep-sum-overrides = self: super: { - dependent-sum-template = self.callHackageDirect { - pkg = "dependent-sum-template"; - ver = "0.1.0.3"; - sha256 = "0m5nblmwbx2810hhnlcz1c8vwis47kd3xir1ylfk0dgxa0n1ag3f"; - } {}; - dependent-sum = self.callHackageDirect { - pkg = "dependent-sum"; - ver = "0.7.1.0"; - sha256 = "0jjdjhkhny8hiz9q17bqdgncca8gb0nqdnqz3xpwa3g2g0qisrp0"; - } {}; - some = doJailbreak super.some; - dependent-map = self.callHackageDirect { - pkg = "dependent-map"; - ver = "0.4.0.0"; - sha256 = "1jycg6hz350mjbiqnqii90k3fbz95rbwd3kw09n4x9r053bbz3jn"; - } {}; - }; - ghc810-overrides = self: super: dep-sum-overrides self super // { - th-expand-syns = self.callHackageDirect { - pkg = "th-expand-syns"; - ver = "0.4.6.0"; - sha256 = "1l2g98jfg86blp8mkkvzh90h557l5qklw1nn045zqb5am8977dgq"; - } {}; - ChasingBottoms = self.callHackageDirect { - pkg = "ChasingBottoms"; - ver = "1.3.1.8"; - sha256 = "0klxmb6pgl2xv5206gn2m3n1di2aidkfyi5rlqcfdx5qvpbnhl19"; - } {}; - haskell-src-meta = self.callHackageDirect { - pkg = "haskell-src-meta"; - ver = "0.8.5"; - sha256 = "1dhncvsyv2kc8x18gvr7if4pr7vvypl0lr450jaaj3xj7rly3lwv"; - } {}; - haskell-src-exts = self.callHackageDirect { - pkg = "haskell-src-exts"; - ver = "1.22.0"; - sha256 = "1w1fzpid798b5h090pwpz7n4yyxw4hq3l4r493ygyr879dvjlr8d"; - } {}; - constraints = self.callHackageDirect { - pkg = "constraints"; - ver = "0.11"; - sha256 = "0xi2p57hsdy31f8a4isxxp1zgv8m7a26c586jlz8p2rmk0ypw3pj"; - } {}; - constraints-extras = doJailbreak super.constraints-extras; - some = doJailbreak super.some; - }; - ghcs = rec { - ghc802 = nixos1809.haskell.packages.ghc802; - ghc844 = nixos1809.haskell.packages.ghc844; - ghc865 = nixos2003.haskell.packages.ghc865; - ghc884 = nixos2003.haskell.packages.ghc884.override { - overrides = dep-sum-overrides; - }; - ghc8101 = nixos2003.haskell.packages.ghc8101.override { - overrides = ghc810-overrides; - }; - ghc8102 = unstable.haskell.packages.ghc8102; - ghc8101_aeson15 = nixos2003.haskell.packages.ghc8101.override { - overrides = self: super: ghc810-overrides self super // - { assoc = doJailbreak super.assoc; - strict = self.callHackageDirect { - pkg = "strict"; - ver = "0.4"; - sha256 = "0sl9mfpnyras2jlpjfnji4406fzp0yg2kxfcr22s3zwpir622a97"; - } {}; - these = self.callHackageDirect { - pkg = "these"; - ver = "1.1.1.1"; - sha256 = "1i1nfh41vflvqxi8w8n2s35ymx2z9119dg5zmd2r23ya7vwvaka1"; - } {}; - aeson = doJailbreak (self.callHackageDirect { - pkg = "aeson"; - ver = "1.5.2.0"; - sha256 = "0rz7j7bcj5li2c5dmiv3pnmbs581vzkl9rbx9wq2v06f4knaklkf"; - } {}); - hashable-time = doJailbreak super.hashable-time; - Diff = self.callHackageDirect { - pkg = "Diff"; - ver = "0.4.0"; - sha256 = "1phz4cz7i53jx3d1bj0xnx8vpkk482g4ph044zv5c6ssirnzq3ng"; - } {}; - doctest = dontCheck (self.callHackageDirect { - pkg = "doctest"; - ver = "0.16.3"; - sha256 = "0rm91akq3d4b8xa127dklgd1vg2x9xv962pg98i7xhgnllp6i5r3"; - } {}); - quickcheck-instances = self.callHackageDirect { - pkg = "quickcheck-instances"; - ver = "0.3.23"; - sha256 = "1baqh2harkcx7igqmk6p040vmchy30wnh1crwwvzcxqv22iwyfrw"; +let pkgs = import ./nixpkgs/23.11 {}; + hpkgs = { + overrides = self: super: { + dependent-sum-template = self.callHackageDirect { + pkg = "dependent-sum-template"; + ver = "0.2.0.1"; + sha256 = "123chg589dcp2854rfkydb8cwkvy6abjb9wp4mxazb01w4b21v5a"; } {}; }; }; - }; + ghcs = { + "ghc8107" = pkgs.haskell.packages.ghc8107.override(hpkgs); + "ghc902" = pkgs.haskell.packages.ghc902.override(hpkgs); + "ghc928" = pkgs.haskell.packages.ghc928.override(hpkgs); + "ghc948" = pkgs.haskell.packages.ghc948.override(hpkgs); + "ghc963" = pkgs.haskell.packages.ghc963.override(hpkgs); + "ghc981" = (import ./nixpkgs/unstable {}).haskell.packages.ghc981; + "ghc865" = (import ./nixpkgs/reflex-platform {}).ghc8_6; + }; in - lib.mapAttrs (_: ghc: ghc.callCabal2nix "aeson-gadt-th" ./. {}) ghcs + pkgs.lib.mapAttrs (_: ghc: ghc.callCabal2nix "aeson-gadt-th" (builtins.fetchGit ./.) {}) ghcs diff --git a/src/Data/Aeson/GADT/TH.hs b/src/Data/Aeson/GADT/TH.hs index 2fb827a..231a8c8 100644 --- a/src/Data/Aeson/GADT/TH.hs +++ b/src/Data/Aeson/GADT/TH.hs @@ -45,7 +45,16 @@ import qualified Data.Set as Set import Data.Some (Some(..)) import Language.Haskell.TH hiding (cxt) import Language.Haskell.TH.Datatype (ConstructorInfo(..), applySubstitution, datatypeCons, reifyDatatype, unifyTypes) -import Language.Haskell.TH.Datatype.TyVarBndr (TyVarBndr_, tvName) +import Language.Haskell.TH.Datatype.TyVarBndr (tvName) + +#if !MIN_VERSION_template_haskell(2,21,0) +#if MIN_VERSION_th_abstraction(0,6,0) +import Language.Haskell.TH.Datatype.TyVarBndr (TyVarBndrVis) +#else +import Language.Haskell.TH.Datatype.TyVarBndr (TyVarBndr_) +type TyVarBndrVis = TyVarBndr_ () +#endif +#endif #if MIN_VERSION_dependent_sum(0,5,0) #else @@ -54,7 +63,7 @@ pattern Some x = This x #endif -- Do not export this type family, it must remain empty. It's used as a way to trick GHC into not unifying certain type variables. -type family Skolem :: k -> k +data family Skolem :: k -> k skolemize :: Set Name -> Type -> Type skolemize rigids t = case t of @@ -143,7 +152,7 @@ deriveFromJSONGADTWithOptions opts n = do let constraints = map head . group . sort $ constraints' -- This 'head' is safe because 'group' returns a list of non-empty lists v <- newName "v" parser <- funD 'parseJSON - [ clause [varP v] (normalB [e| + [ clause [varP v] (normalB [e| do (tag', _v') <- parseJSON $(varE v) $(caseE [|tag' :: String|] $ map pure matches ++ [wild]) |]) [] @@ -238,10 +247,17 @@ conMatches clsName topVars ixVar c = do [InstanceD _ cxt (AppT _className (AppT (ConT _some) ityp)) _] -> do sub <- lift $ unifyTypes [ityp, tn] tellCxt $ applySubstitution sub cxt - return (ConP 'Some [VarP x], VarE x) + return ( ConP + 'Some +#if MIN_VERSION_template_haskell(2,18,0) + [] +#endif + [VarP x] + , VarE x + ) _ -> error $ "The following instances of " ++ show clsName ++ " for " ++ show (ppr [AppT (ConT ''Some) tn]) ++ " exist (rigids: " ++ unwords (map show $ Set.toList rigidVars) ++ "), and I don't know which to pick:\n" ++ unlines (map (show . ppr) insts) _ -> do - demandInstanceIfNecessary + demandInstanceIfNecessary return (VarP x, VarE x) -- The singleton is special-cased because of -- https://downloads.haskell.org/ghc/8.10.1-rc1/docs/html/users_guide/8.10.1-notes.html#template-haskell @@ -266,7 +282,7 @@ kindArity = \case -- its declaration, and the arity of the kind of type being defined (i.e. how many more arguments would -- need to be supplied in addition to the bound parameters in order to obtain an ordinary type of kind *). -- If the supplied 'Name' is anything other than a data or newtype, produces an error. -tyConArity' :: Name -> Q ([TyVarBndr_ ()], Int) +tyConArity' :: Name -> Q ([TyVarBndrVis], Int) tyConArity' n = reify n >>= return . \case TyConI (DataD _ _ ts mk _ _) -> (ts, maybe 0 kindArity mk) TyConI (NewtypeD _ _ ts mk _ _) -> (ts, maybe 0 kindArity mk)