summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2022-02-15 21:17:02 +0000
committerJohn Ericson <John.Ericson@Obsidian.Systems>2022-02-21 17:46:02 +0000
commit173bc4a8f42353551c65dcb387224014ff2b53b2 (patch)
tree26c919fae2cce13bdec2bbf57f76c57b6d322772
parent6b468f7f6185e68ccdea547beb090092b77cf87e (diff)
downloadhaskell-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-boot3
-rw-r--r--compiler/GHC/Types/Name.hs4
-rw-r--r--compiler/GHC/Types/Var.hs258
-rw-r--r--compiler/GHC/Types/Var.hs-boot8
-rw-r--r--compiler/GHC/Types/Var/ArgFlag.hs145
-rw-r--r--compiler/GHC/Types/Var/Binder.hs120
-rw-r--r--compiler/GHC/Utils/Binary.hs39
-rw-r--r--compiler/ghc.cabal.in2
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