diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2022-02-15 21:17:02 +0000 |
---|---|---|
committer | John Ericson <John.Ericson@Obsidian.Systems> | 2022-02-21 17:46:02 +0000 |
commit | 173bc4a8f42353551c65dcb387224014ff2b53b2 (patch) | |
tree | 26c919fae2cce13bdec2bbf57f76c57b6d322772 | |
parent | 6b468f7f6185e68ccdea547beb090092b77cf87e (diff) | |
download | haskell-wip/split-var-mod.tar.gz |
Create GHC.Types.Var.{Binder,ArgFlag}wip/split-var-mod
This "liberates" some definitions from an hs-boot cycle.
Some instances were moved out the the new modules (next to class def not
data def) in the process, so we had fewer instances in hs-boots too.
-rw-r--r-- | compiler/GHC/Core/TyCo/Rep.hs-boot | 3 | ||||
-rw-r--r-- | compiler/GHC/Types/Name.hs | 4 | ||||
-rw-r--r-- | compiler/GHC/Types/Var.hs | 258 | ||||
-rw-r--r-- | compiler/GHC/Types/Var.hs-boot | 8 | ||||
-rw-r--r-- | compiler/GHC/Types/Var/ArgFlag.hs | 145 | ||||
-rw-r--r-- | compiler/GHC/Types/Var/Binder.hs | 120 | ||||
-rw-r--r-- | compiler/GHC/Utils/Binary.hs | 39 | ||||
-rw-r--r-- | compiler/ghc.cabal.in | 2 |
8 files changed, 323 insertions, 256 deletions
diff --git a/compiler/GHC/Core/TyCo/Rep.hs-boot b/compiler/GHC/Core/TyCo/Rep.hs-boot index f2e59d534f..8379e70c71 100644 --- a/compiler/GHC/Core/TyCo/Rep.hs-boot +++ b/compiler/GHC/Core/TyCo/Rep.hs-boot @@ -3,8 +3,9 @@ module GHC.Core.TyCo.Rep where import GHC.Utils.Outputable ( Outputable ) import Data.Data ( Data ) -import {-# SOURCE #-} GHC.Types.Var( Var, ArgFlag, AnonArgFlag ) +import {-# SOURCE #-} GHC.Types.Var ( Var ) import {-# SOURCE #-} GHC.Core.TyCon ( TyCon ) +import GHC.Types.Var.ArgFlag ( ArgFlag, AnonArgFlag ) data Type data Coercion diff --git a/compiler/GHC/Types/Name.hs b/compiler/GHC/Types/Name.hs index d919919e81..bfce4d11d8 100644 --- a/compiler/GHC/Types/Name.hs +++ b/compiler/GHC/Types/Name.hs @@ -90,6 +90,7 @@ import GHC.Unit.Module import GHC.Unit.Home import GHC.Types.SrcLoc import GHC.Types.Unique +import GHC.Types.Var.Binder import GHC.Utils.Misc import GHC.Data.Maybe import GHC.Utils.Binary @@ -803,3 +804,6 @@ pprPrefixName :: NamedThing a => a -> SDoc pprPrefixName thing = pprPrefixVar (isSymOcc (nameOccName name)) (ppr name) where name = getName thing + +instance NamedThing tv => NamedThing (VarBndr tv flag) where + getName (Bndr tv _) = getName tv diff --git a/compiler/GHC/Types/Var.hs b/compiler/GHC/Types/Var.hs index 0a6dc6079a..ee9fe939f2 100644 --- a/compiler/GHC/Types/Var.hs +++ b/compiler/GHC/Types/Var.hs @@ -5,8 +5,13 @@ \section{@Vars@: Variables} -} -{-# LANGUAGE FlexibleContexts, MultiWayIf, FlexibleInstances, DeriveDataTypeable, - PatternSynonyms, BangPatterns #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE MultiWayIf #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE PatternSynonyms #-} +{-# LANGUAGE BangPatterns #-} + {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} {-# OPTIONS_GHC -Wno-incomplete-record-updates #-} @@ -105,8 +110,9 @@ import {-# SOURCE #-} GHC.Builtin.Types ( manyDataConTy ) import {-# SOURCE #-} GHC.Types.Name import GHC.Types.Unique ( Uniquable, Unique, getKey, getUnique , mkUniqueGrimily, nonDetCmpUnique ) +import GHC.Types.Var.ArgFlag +import GHC.Types.Var.Binder import GHC.Utils.Misc -import GHC.Utils.Binary import GHC.Utils.Outputable import GHC.Utils.Panic import GHC.Utils.Panic.Plain @@ -429,208 +435,10 @@ updateVarTypeM upd var {- ********************************************************************* * * -* ArgFlag -* * -********************************************************************* -} - --- | Argument Flag --- --- Is something required to appear in source Haskell ('Required'), --- permitted by request ('Specified') (visible type application), or --- prohibited entirely from appearing in source Haskell ('Inferred')? --- See Note [VarBndrs, TyCoVarBinders, TyConBinders, and visibility] in "GHC.Core.TyCo.Rep" -data ArgFlag = Invisible Specificity - | Required - deriving (Eq, Ord, Data) - -- (<) on ArgFlag means "is less visible than" - --- | Whether an 'Invisible' argument may appear in source Haskell. -data Specificity = InferredSpec - -- ^ the argument may not appear in source Haskell, it is - -- only inferred. - | SpecifiedSpec - -- ^ the argument may appear in source Haskell, but isn't - -- required. - deriving (Eq, Ord, Data) - -pattern Inferred, Specified :: ArgFlag -pattern Inferred = Invisible InferredSpec -pattern Specified = Invisible SpecifiedSpec - -{-# COMPLETE Required, Specified, Inferred #-} - --- | Does this 'ArgFlag' classify an argument that is written in Haskell? -isVisibleArgFlag :: ArgFlag -> Bool -isVisibleArgFlag af = not (isInvisibleArgFlag af) - --- | Does this 'ArgFlag' classify an argument that is not written in Haskell? -isInvisibleArgFlag :: ArgFlag -> Bool -isInvisibleArgFlag (Invisible {}) = True -isInvisibleArgFlag Required = False - -isInferredArgFlag :: ArgFlag -> Bool --- More restrictive than isInvisibleArgFlag -isInferredArgFlag (Invisible InferredSpec) = True -isInferredArgFlag _ = False - --- | Do these denote the same level of visibility? 'Required' --- arguments are visible, others are not. So this function --- equates 'Specified' and 'Inferred'. Used for printing. -sameVis :: ArgFlag -> ArgFlag -> Bool -sameVis Required Required = True -sameVis (Invisible _) (Invisible _) = True -sameVis _ _ = False - -instance Outputable ArgFlag where - ppr Required = text "[req]" - ppr Specified = text "[spec]" - ppr Inferred = text "[infrd]" - -instance Binary Specificity where - put_ bh SpecifiedSpec = putByte bh 0 - put_ bh InferredSpec = putByte bh 1 - - get bh = do - h <- getByte bh - case h of - 0 -> return SpecifiedSpec - _ -> return InferredSpec - -instance Binary ArgFlag where - put_ bh Required = putByte bh 0 - put_ bh Specified = putByte bh 1 - put_ bh Inferred = putByte bh 2 - - get bh = do - h <- getByte bh - case h of - 0 -> return Required - 1 -> return Specified - _ -> return Inferred - --- | The non-dependent version of 'ArgFlag'. --- See Note [AnonArgFlag] --- Appears here partly so that it's together with its friends ArgFlag --- and ForallVisFlag, but also because it is used in IfaceType, rather --- early in the compilation chain -data AnonArgFlag - = VisArg -- ^ Used for @(->)@: an ordinary non-dependent arrow. - -- The argument is visible in source code. - | InvisArg -- ^ Used for @(=>)@: a non-dependent predicate arrow. - -- The argument is invisible in source code. - deriving (Eq, Ord, Data) - -instance Outputable AnonArgFlag where - ppr VisArg = text "[vis]" - ppr InvisArg = text "[invis]" - -instance Binary AnonArgFlag where - put_ bh VisArg = putByte bh 0 - put_ bh InvisArg = putByte bh 1 - - get bh = do - h <- getByte bh - case h of - 0 -> return VisArg - _ -> return InvisArg - -{- Note [AnonArgFlag] -~~~~~~~~~~~~~~~~~~~~~ -AnonArgFlag is used principally in the FunTy constructor of Type. - FunTy VisArg t1 t2 means t1 -> t2 - FunTy InvisArg t1 t2 means t1 => t2 - -However, the AnonArgFlag in a FunTy is just redundant, cached -information. In (FunTy { ft_af = af, ft_arg = t1, ft_res = t2 }) - * if (isPredTy t1 = True) then af = InvisArg - * if (isPredTy t1 = False) then af = VisArg -where isPredTy is defined in GHC.Core.Type, and sees if t1's -kind is Constraint. See GHC.Core.TyCo.Rep -Note [Types for coercions, predicates, and evidence] - -GHC.Core.Utils.mkFunctionType :: Mult -> Type -> Type -> Type -uses isPredTy to decide the AnonArgFlag for the FunTy. - -The term (Lam b e), and coercion (FunCo co1 co2) don't carry -AnonArgFlags; instead they use mkFunctionType when we want to -get their types; see mkLamType and coercionLKind/RKind resp. -This is just an engineering choice; we could cache here too -if we wanted. - -Why bother with all this? After all, we are in Core, where (=>) and -(->) behave the same. We maintain this distinction throughout Core so -that we can cheaply and conveniently determine -* How to print a type -* How to split up a type: tcSplitSigmaTy -* How to specialise it (over type classes; GHC.Core.Opt.Specialise) - -For the specialisation point, consider -(\ (d :: Ord a). blah). We want to give it type - (Ord a => blah_ty) -with a fat arrow; that is, using mkInvisFunTy, not mkVisFunTy. -Why? Because the /specialiser/ treats dictionary arguments specially. -Suppose we do w/w on 'foo', thus (#11272, #6056) - foo :: Ord a => Int -> blah - foo a d x = case x of I# x' -> $wfoo @a d x' - - $wfoo :: Ord a => Int# -> blah - -Now, at a call we see (foo @Int dOrdInt). The specialiser will -specialise this to $sfoo, where - $sfoo :: Int -> blah - $sfoo x = case x of I# x' -> $wfoo @Int dOrdInt x' - -Now we /must/ also specialise $wfoo! But it wasn't user-written, -and has a type built with mkLamTypes. - -Conclusion: the easiest thing is to make mkLamType build - (c => ty) -when the argument is a predicate type. See GHC.Core.TyCo.Rep -Note [Types for coercions, predicates, and evidence] --} - -{- ********************************************************************* -* * * VarBndr, TyCoVarBinder * * ********************************************************************* -} -{- Note [The VarBndr type and its uses] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -VarBndr is polymorphic in both var and visibility fields. -Currently there are nine different uses of 'VarBndr': - -* Var.TyCoVarBinder = VarBndr TyCoVar ArgFlag - Binder of a forall-type; see ForAllTy in GHC.Core.TyCo.Rep - -* Var.TyVarBinder = VarBndr TyVar ArgFlag - Subset of TyCoVarBinder when we are sure the binder is a TyVar - -* Var.InvisTVBinder = VarBndr TyVar Specificity - Specialised form of TyVarBinder, when ArgFlag = Invisible s - See GHC.Core.Type.splitForAllInvisTVBinders - -* Var.ReqTVBinder = VarBndr TyVar () - Specialised form of TyVarBinder, when ArgFlag = Required - See GHC.Core.Type.splitForAllReqTVBinders - This one is barely used - -* TyCon.TyConBinder = VarBndr TyVar TyConBndrVis - Binders of a TyCon; see TyCon in GHC.Core.TyCon - -* TyCon.TyConTyCoBinder = VarBndr TyCoVar TyConBndrVis - Binders of a PromotedDataCon - See Note [Promoted GADT data constructors] in GHC.Core.TyCon - -* IfaceType.IfaceForAllBndr = VarBndr IfaceBndr ArgFlag -* IfaceType.IfaceForAllSpecBndr = VarBndr IfaceBndr Specificity -* IfaceType.IfaceTyConBinder = VarBndr IfaceBndr TyConBndrVis --} - -data VarBndr var argf = Bndr var argf - -- See Note [The VarBndr type and its uses] - deriving( Data ) - -- | Variable Binder -- -- A 'TyCoVarBinder' is the binder of a ForAllTy @@ -643,27 +451,6 @@ type TyVarBinder = VarBndr TyVar ArgFlag type InvisTVBinder = VarBndr TyVar Specificity type ReqTVBinder = VarBndr TyVar () -tyVarSpecToBinders :: [VarBndr a Specificity] -> [VarBndr a ArgFlag] -tyVarSpecToBinders = map tyVarSpecToBinder - -tyVarSpecToBinder :: VarBndr a Specificity -> VarBndr a ArgFlag -tyVarSpecToBinder (Bndr tv vis) = Bndr tv (Invisible vis) - -tyVarReqToBinders :: [VarBndr a ()] -> [VarBndr a ArgFlag] -tyVarReqToBinders = map tyVarReqToBinder - -tyVarReqToBinder :: VarBndr a () -> VarBndr a ArgFlag -tyVarReqToBinder (Bndr tv _) = Bndr tv Required - -binderVar :: VarBndr tv argf -> tv -binderVar (Bndr v _) = v - -binderVars :: [VarBndr tv argf] -> [tv] -binderVars tvbs = map binderVar tvbs - -binderArgFlag :: VarBndr tv argf -> argf -binderArgFlag (Bndr _ argf) = argf - binderType :: VarBndr TyCoVar argf -> Type binderType (Bndr tv _) = varType tv @@ -690,33 +477,6 @@ mkTyVarBinders vis = map (mkTyVarBinder vis) isTyVarBinder :: TyCoVarBinder -> Bool isTyVarBinder (Bndr v _) = isTyVar v -mapVarBndr :: (var -> var') -> (VarBndr var flag) -> (VarBndr var' flag) -mapVarBndr f (Bndr v fl) = Bndr (f v) fl - -mapVarBndrs :: (var -> var') -> [VarBndr var flag] -> [VarBndr var' flag] -mapVarBndrs f = map (mapVarBndr f) - -lookupVarBndr :: Eq var => var -> [VarBndr var flag] -> Maybe flag -lookupVarBndr var bndrs = lookup var zipped_bndrs - where - zipped_bndrs = map (\(Bndr v f) -> (v,f)) bndrs - -instance Outputable tv => Outputable (VarBndr tv ArgFlag) where - ppr (Bndr v Required) = ppr v - ppr (Bndr v Specified) = char '@' <> ppr v - ppr (Bndr v Inferred) = braces (ppr v) - -instance Outputable tv => Outputable (VarBndr tv Specificity) where - ppr = ppr . tyVarSpecToBinder - -instance (Binary tv, Binary vis) => Binary (VarBndr tv vis) where - put_ bh (Bndr tv vis) = do { put_ bh tv; put_ bh vis } - - get bh = do { tv <- get bh; vis <- get bh; return (Bndr tv vis) } - -instance NamedThing tv => NamedThing (VarBndr tv flag) where - getName (Bndr tv _) = getName tv - {- ************************************************************************ * * diff --git a/compiler/GHC/Types/Var.hs-boot b/compiler/GHC/Types/Var.hs-boot index 1882a86d33..b8de12e217 100644 --- a/compiler/GHC/Types/Var.hs-boot +++ b/compiler/GHC/Types/Var.hs-boot @@ -2,19 +2,15 @@ module GHC.Types.Var where import GHC.Prelude () -import {-# SOURCE #-} GHC.Types.Name -- We compile this GHC with -XNoImplicitPrelude, so if there are no imports -- it does not seem to depend on anything. But it does! We must, for -- example, compile GHC.Types in the ghc-prim library first. So this -- otherwise-unnecessary import tells the build system that this module -- depends on GhcPrelude, which ensures that GHC.Type is built first. +import GHC.Types.Var.ArgFlag +import GHC.Types.Var.Binder -data ArgFlag -data AnonArgFlag data Var -instance NamedThing Var -data VarBndr var argf -data Specificity type TyVar = Var type Id = Var type TyCoVar = Id diff --git a/compiler/GHC/Types/Var/ArgFlag.hs b/compiler/GHC/Types/Var/ArgFlag.hs new file mode 100644 index 0000000000..eaecb3fbd1 --- /dev/null +++ b/compiler/GHC/Types/Var/ArgFlag.hs @@ -0,0 +1,145 @@ +{-# LANGUAGE DeriveTraversable #-} +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE PatternSynonyms #-} +module GHC.Types.Var.ArgFlag + ( ArgFlag(Invisible,Required,Specified,Inferred) + , Specificity(..) + , isVisibleArgFlag + , isInvisibleArgFlag + , isInferredArgFlag + , sameVis + , AnonArgFlag(..) + ) where + +import GHC.Prelude + +import GHC.Utils.Outputable + +import Data.Data + +-- | Argument Flag +-- +-- Is something required to appear in source Haskell ('Required'), +-- permitted by request ('Specified') (visible type application), or +-- prohibited entirely from appearing in source Haskell ('Inferred')? +-- See Note [VarBndrs, TyCoVarBinders, TyConBinders, and visibility] in "GHC.Core.TyCo.Rep + +data ArgFlag = Invisible Specificity + | Required + deriving (Eq, Ord, Data) + -- (<) on ArgFlag means "is less visible than" + +-- | Whether an 'Invisible' argument may appear in source Haskell. +data Specificity = InferredSpec + -- ^ the argument may not appear in source Haskell, it is + -- only inferred. + | SpecifiedSpec + -- ^ the argument may appear in source Haskell, but isn't + -- required. + deriving (Eq, Ord, Data) + +pattern Inferred, Specified :: ArgFlag +pattern Inferred = Invisible InferredSpec +pattern Specified = Invisible SpecifiedSpec + +{-# COMPLETE Required, Specified, Inferred #-} + +-- | Does this 'ArgFlag' classify an argument that is written in Haskell? +isVisibleArgFlag :: ArgFlag -> Bool +isVisibleArgFlag af = not (isInvisibleArgFlag af) + +-- | Does this 'ArgFlag' classify an argument that is not written in Haskell? +isInvisibleArgFlag :: ArgFlag -> Bool +isInvisibleArgFlag (Invisible {}) = True +isInvisibleArgFlag Required = False + +isInferredArgFlag :: ArgFlag -> Bool +-- More restrictive than isInvisibleArgFlag +isInferredArgFlag (Invisible InferredSpec) = True +isInferredArgFlag _ = False + +-- | Do these denote the same level of visibility? 'Required' +-- arguments are visible, others are not. So this function +-- equates 'Specified' and 'Inferred'. Used for printing. +sameVis :: ArgFlag -> ArgFlag -> Bool +sameVis Required Required = True +sameVis (Invisible _) (Invisible _) = True +sameVis _ _ = False + +instance Outputable ArgFlag where + ppr Required = text "[req]" + ppr Specified = text "[spec]" + ppr Inferred = text "[infrd]" + +-- | The non-dependent version of 'ArgFlag'. +-- See Note [AnonArgFlag] +-- Appears here partly so that it's together with its friends ArgFlag +-- and ForallVisFlag, but also because it is used in IfaceType, rather +-- early in the compilation chain +data AnonArgFlag + = VisArg -- ^ Used for @(->)@: an ordinary non-dependent arrow. + -- The argument is visible in source code. + | InvisArg -- ^ Used for @(=>)@: a non-dependent predicate arrow. + -- The argument is invisible in source code. + deriving (Eq, Ord, Data) + +instance Outputable AnonArgFlag where + ppr VisArg = text "[vis]" + ppr InvisArg = text "[invis]" + +{- Note [AnonArgFlag] +~~~~~~~~~~~~~~~~~~~~~ +AnonArgFlag is used principally in the FunTy constructor of Type. + FunTy VisArg t1 t2 means t1 -> t2 + FunTy InvisArg t1 t2 means t1 => t2 + +However, the AnonArgFlag in a FunTy is just redundant, cached +information. In (FunTy { ft_af = af, ft_arg = t1, ft_res = t2 }) + * if (isPredTy t1 = True) then af = InvisArg + * if (isPredTy t1 = False) then af = VisArg +where isPredTy is defined in GHC.Core.Type, and sees if t1's +kind is Constraint. See GHC.Core.TyCo.Rep +Note [Types for coercions, predicates, and evidence] + +GHC.Core.Utils.mkFunctionType :: Mult -> Type -> Type -> Type +uses isPredTy to decide the AnonArgFlag for the FunTy. + +The term (Lam b e), and coercion (FunCo co1 co2) don't carry +AnonArgFlags; instead they use mkFunctionType when we want to +get their types; see mkLamType and coercionLKind/RKind resp. +This is just an engineering choice; we could cache here too +if we wanted. + +Why bother with all this? After all, we are in Core, where (=>) and +(->) behave the same. We maintain this distinction throughout Core so +that we can cheaply and conveniently determine +* How to print a type +* How to split up a type: tcSplitSigmaTy +* How to specialise it (over type classes; GHC.Core.Opt.Specialise) + +For the specialisation point, consider +(\ (d :: Ord a). blah). We want to give it type + (Ord a => blah_ty) +with a fat arrow; that is, using mkInvisFunTy, not mkVisFunTy. +Why? Because the /specialiser/ treats dictionary arguments specially. +Suppose we do w/w on 'foo', thus (#11272, #6056) + foo :: Ord a => Int -> blah + foo a d x = case x of I# x' -> $wfoo @a d x' + + $wfoo :: Ord a => Int# -> blah + +Now, at a call we see (foo @Int dOrdInt). The specialiser will +specialise this to $sfoo, where + $sfoo :: Int -> blah + $sfoo x = case x of I# x' -> $wfoo @Int dOrdInt x' + +Now we /must/ also specialise $wfoo! But it wasn't user-written, +and has a type built with mkLamTypes. + +Conclusion: the easiest thing is to make mkLamType build + (c => ty) +when the argument is a predicate type. See GHC.Core.TyCo.Rep +Note [Types for coercions, predicates, and evidence] +-} diff --git a/compiler/GHC/Types/Var/Binder.hs b/compiler/GHC/Types/Var/Binder.hs new file mode 100644 index 0000000000..62460b2734 --- /dev/null +++ b/compiler/GHC/Types/Var/Binder.hs @@ -0,0 +1,120 @@ +{-# LANGUAGE DeriveTraversable #-} +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE PatternSynonyms #-} +module GHC.Types.Var.Binder + ( VarBndr (..) + , binderVar + , binderVars + , binderArgFlag + , tyVarSpecToBinder + , tyVarSpecToBinders + , tyVarReqToBinder + , tyVarReqToBinders + , mapVarBndr + , mapVarBndrs + , lookupVarBndr + ) where + +import GHC.Prelude + +import GHC.Types.Var.ArgFlag +import GHC.Utils.Outputable + +import Data.Bifunctor +import Data.Bifoldable +import Data.Bitraversable +import Data.Data +import qualified Data.Semigroup as S + +{- Note [The VarBndr type and its uses] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See Haddocks below +-} + +{- | Variable Binder + +VarBndr is polymorphic in both var and visibility fields. +Currently there are nine different uses of 'VarBndr': + +* Var.TyCoVarBinder = VarBndr TyCoVar ArgFlag + Binder of a forall-type; see ForAllTy in GHC.Core.TyCo.Rep + +* Var.TyVarBinder = VarBndr TyVar ArgFlag + Subset of TyCoVarBinder when we are sure the binder is a TyVar + +* Var.InvisTVBinder = VarBndr TyVar Specificity + Specialised form of TyVarBinder, when ArgFlag = Invisible s + See GHC.Core.Type.splitForAllInvisTVBinders + +* Var.ReqTVBinder = VarBndr TyVar () + Specialised form of TyVarBinder, when ArgFlag = Required + See GHC.Core.Type.splitForAllReqTVBinders + This one is barely used + +* TyCon.TyConBinder = VarBndr TyVar TyConBndrVis + Binders of a TyCon; see TyCon in GHC.Core.TyCon + +* TyCon.TyConTyCoBinder = VarBndr TyCoVar TyConBndrVis + Binders of a PromotedDataCon + See Note [Promoted GADT data constructors] in GHC.Core.TyCon + +* IfaceType.IfaceForAllBndr = VarBndr IfaceBndr ArgFlag +* IfaceType.IfaceForAllSpecBndr = VarBndr IfaceBndr Specificity +* IfaceType.IfaceTyConBinder = VarBndr IfaceBndr TyConBndrVis +-} +data VarBndr var argf = Bndr var argf + deriving ( Eq, Data + , Functor, Foldable, Traversable + ) + +binderVar :: VarBndr tv argf -> tv +binderVar (Bndr v _) = v + +binderVars :: [VarBndr tv argf] -> [tv] +binderVars tvbs = map binderVar tvbs + +binderArgFlag :: VarBndr tv argf -> argf +binderArgFlag (Bndr _ argf) = argf + +tyVarSpecToBinders :: [VarBndr a Specificity] -> [VarBndr a ArgFlag] +tyVarSpecToBinders = map tyVarSpecToBinder + +tyVarSpecToBinder :: VarBndr a Specificity -> VarBndr a ArgFlag +tyVarSpecToBinder (Bndr tv vis) = Bndr tv (Invisible vis) + +tyVarReqToBinders :: [VarBndr a ()] -> [VarBndr a ArgFlag] +tyVarReqToBinders = map tyVarReqToBinder + +tyVarReqToBinder :: VarBndr a () -> VarBndr a ArgFlag +tyVarReqToBinder (Bndr tv _) = Bndr tv Required + +instance Bifunctor VarBndr where + bimap f g (Bndr v a) = Bndr (f v) (g a) + +instance Bifoldable VarBndr where + bifoldMap f g (Bndr v a) = f v S.<> g a + +instance Bitraversable VarBndr where + bitraverse f g (Bndr v a) = Bndr <$> f v <*> g a + +mapVarBndr :: (var -> var') -> (VarBndr var flag) -> (VarBndr var' flag) +mapVarBndr f (Bndr v fl) = Bndr (f v) fl + +mapVarBndrs :: (var -> var') -> [VarBndr var flag] -> [VarBndr var' flag] +mapVarBndrs f = map (mapVarBndr f) + +lookupVarBndr :: Eq var => var -> [VarBndr var flag] -> Maybe flag +lookupVarBndr var bndrs = lookup var zipped_bndrs + where + zipped_bndrs = map (\(Bndr v f) -> (v,f)) bndrs + +instance Outputable tv => Outputable (VarBndr tv ArgFlag) where + ppr (Bndr v Required) = ppr v + ppr (Bndr v Specified) = char '@' <> ppr v + ppr (Bndr v Inferred) = braces (ppr v) + +instance Outputable tv => Outputable (VarBndr tv Specificity) where + ppr = ppr . tyVarSpecToBinder diff --git a/compiler/GHC/Utils/Binary.hs b/compiler/GHC/Utils/Binary.hs index 36931b7b1f..039091b301 100644 --- a/compiler/GHC/Utils/Binary.hs +++ b/compiler/GHC/Utils/Binary.hs @@ -82,6 +82,8 @@ import GHC.Types.Unique.FM import GHC.Data.FastMutInt import GHC.Utils.Fingerprint import GHC.Types.SrcLoc +import GHC.Types.Var.ArgFlag +import GHC.Types.Var.Binder import qualified GHC.Data.Strict as Strict import Control.DeepSeq @@ -1323,3 +1325,40 @@ instance Binary SrcSpan where return (RealSrcSpan ss sb) _ -> do s <- get bh return (UnhelpfulSpan s) + +instance Binary Specificity where + put_ bh SpecifiedSpec = putByte bh 0 + put_ bh InferredSpec = putByte bh 1 + + get bh = do + h <- getByte bh + case h of + 0 -> return SpecifiedSpec + _ -> return InferredSpec + +instance Binary ArgFlag where + put_ bh Required = putByte bh 0 + put_ bh Specified = putByte bh 1 + put_ bh Inferred = putByte bh 2 + + get bh = do + h <- getByte bh + case h of + 0 -> return Required + 1 -> return Specified + _ -> return Inferred + +instance Binary AnonArgFlag where + put_ bh VisArg = putByte bh 0 + put_ bh InvisArg = putByte bh 1 + + get bh = do + h <- getByte bh + case h of + 0 -> return VisArg + _ -> return InvisArg + +instance (Binary tv, Binary vis) => Binary (VarBndr tv vis) where + put_ bh (Bndr tv vis) = do { put_ bh tv; put_ bh vis } + + get bh = do { tv <- get bh; vis <- get bh; return (Bndr tv vis) } diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in index 6bc23a69a8..dfcbc52429 100644 --- a/compiler/ghc.cabal.in +++ b/compiler/ghc.cabal.in @@ -702,6 +702,8 @@ Library GHC.Types.Unique.Set GHC.Types.Unique.Supply GHC.Types.Var + GHC.Types.Var.ArgFlag + GHC.Types.Var.Binder GHC.Types.Var.Env GHC.Types.Var.Set GHC.Unit |