diff --git a/changelog/2025-11-06T13_17_27+01_00_reduce_type_family_applications b/changelog/2025-11-06T13_17_27+01_00_reduce_type_family_applications new file mode 100644 index 0000000000..d6139fde3f --- /dev/null +++ b/changelog/2025-11-06T13_17_27+01_00_reduce_type_family_applications @@ -0,0 +1 @@ +FIXED: Type families that appear in GHC core types are now normalized before being translated into their Clash core equivalent. See [#3063](https://github.com/clash-lang/clash-compiler/issues/3063). diff --git a/clash-ghc/src-ghc/Clash/GHC/GHC2Core.hs b/clash-ghc/src-ghc/Clash/GHC/GHC2Core.hs index d47253d286..25bd86a31b 100644 --- a/clash-ghc/src-ghc/Clash/GHC/GHC2Core.hs +++ b/clash-ghc/src-ghc/Clash/GHC/GHC2Core.hs @@ -2,7 +2,7 @@ Copyright : (C) 2013-2016, University of Twente, 2016-2017, Myrtle Software Ltd, 2017-2022, Google Inc. - 2021-2024, QBayLogic B.V., + 2021-2025, QBayLogic B.V., License : BSD2 (see the file LICENSE) Maintainer : QBayLogic B.V. -} @@ -65,7 +65,7 @@ import Language.Haskell.Syntax.Basic (FieldLabelString (..)) -- GHC API #if MIN_VERSION_ghc(9,4,0) -import GHC.Core.Reduction (Reduction(Reduction)) +import GHC.Core.Reduction (Reduction(Reduction), HetReduction(..)) #endif #if MIN_VERSION_ghc(9,0,0) import GHC.Builtin.Types (falseDataCon) @@ -89,7 +89,9 @@ import GHC.Core.DataCon dataConTyCon, dataConUnivTyVars, dataConWorkId, dataConFieldLabels, flLabel, HsImplBang(..), dataConImplBangs) import GHC.Core.FamInstEnv - (FamInst (..), FamInstEnvs, familyInstances, normaliseType, emptyFamInstEnvs) + ( FamInst (..), FamInstEnvs + , familyInstances, normaliseType, emptyFamInstEnvs, topReduceTyFamApp_maybe + ) import GHC.Data.FastString (unpackFS, bytesFS) import GHC.Types.Id (isDataConId_maybe) import GHC.Types.Id.Info (IdDetails (..), unfoldingInfo) @@ -121,8 +123,8 @@ import GHC.Types.Var import GHC.Types.Var.Set (isEmptyVarSet) #else import CoAxiom (CoAxiom (co_ax_branches), CoAxBranch (cab_lhs,cab_rhs), - fromBranches, Role (Nominal)) -import Coercion (coercionType,coercionKind) + fromBranches, Role (Nominal, Representational)) +import Coercion (coercionType, coercionKind, mkTransCo) import CoreFVs (exprSomeFreeVars) import CoreSyn (AltCon (..), Bind (..), CoreExpr, Expr (..), Unfolding (..), Tickish (..), @@ -139,7 +141,8 @@ import DataCon (DataCon, HsImplBang(..), dataConUnivTyVars, dataConWorkId, dataConFieldLabels, flLabel, dataConImplBangs) import FamInstEnv (FamInst (..), FamInstEnvs, - familyInstances, normaliseType, emptyFamInstEnvs) + familyInstances, normaliseType, emptyFamInstEnvs, + normaliseTcArgs, reduceTyFamApp_maybe) #if MIN_VERSION_ghc(8,10,0) import FastString (unpackFS, bytesFS) @@ -1025,10 +1028,30 @@ coreToType -> C2C C.Type coreToType ty = ty'' >>= annotateType ty where - ty'' = - case coreView ty of - Just ty' -> coreToType ty' - Nothing -> coreToType' ty + ty'' | Just ty' <- coreView ty = coreToType ty' + | TyConApp tc xs <- ty = do + envs <- view famInstEnvs + case topReduceTyFamApp_maybe envs tc xs of + Nothing -> coreToType' ty +#if MIN_VERSION_ghc(9,4,0) + Just (HetReduction (Reduction _ ty') _) -> coreToType ty' +#else + Just (_, ty', _) -> coreToType ty' +#endif + | otherwise = coreToType' ty + +#if !MIN_VERSION_ghc(9,0,0) + -- taken and adapted from GHC.Core.FamInstEnv (GHC 9.0.2) + topReduceTyFamApp_maybe envs fam_tc arg_tys + | isFamilyTyCon fam_tc + , Just (co, rhs) <- reduceTyFamApp_maybe envs role fam_tc ntys + = Just (args_co `mkTransCo` co, rhs, res_co) + | otherwise + = Nothing + where + role = Representational + (args_co, ntys, res_co) = normaliseTcArgs envs role fam_tc arg_tys +#endif coreToType' :: Type