    {-
    (c) The University of Glasgow 2006
    (c) The GRASP/AQUA Project, Glasgow University, 1998

    \section[PatSyn]{@PatSyn@: Pattern synonyms}
    -}

    module GHC.Core.PatSyn (
            -- * Main data types
            PatSyn, PatSynMatcher, PatSynBuilder, mkPatSyn,

            -- ** Type deconstruction
            patSynName, patSynArity, patSynIsInfix, patSynResultType,
            isVanillaPatSyn,
            patSynArgs,
            patSynMatcher, patSynBuilder,
            patSynUnivTyVarBinders, patSynExTyVars, patSynExTyVarBinders,
            patSynSig, patSynSigBndr,
            patSynInstArgTys, patSynInstResTy, patSynFieldLabels,
            patSynFieldType,

            pprPatSynType
        ) where

    import GHC.Prelude

    import GHC.Core.Type
    import GHC.Core.TyCo.Ppr
    import GHC.Types.Name
    import GHC.Types.Unique
    import GHC.Types.Basic
    import GHC.Types.Var
    import GHC.Types.FieldLabel

    import GHC.Utils.Misc
    import GHC.Utils.Outputable
    import GHC.Utils.Panic

    import Language.Haskell.Syntax.Basic (FieldLabelString(..))

    import qualified Data.Data as Data
    import Data.Function
    import Data.List (find)

    {-
    ************************************************************************
    *                                                                      *
    \subsection{Pattern synonyms}
    *                                                                      *
    ************************************************************************
    -}

    -- | Pattern Synonym
    --
    -- See Note [Pattern synonym representation]
    -- See Note [Pattern synonym signature contexts]
    data PatSyn
      = MkPatSyn {
            PatSyn -> Name
    psName        :: Name,
            PatSyn -> Unique
    psUnique      :: Unique,       -- Cached from Name

            PatSyn -> [Type]
    psArgs        :: [FRRType],    -- ^ Argument types
            PatSyn -> Arity
    psArity       :: Arity,        -- == length psArgs
            PatSyn -> Bool
    psInfix       :: Bool,         -- True <=> declared infix
            PatSyn -> [FieldLabel]
    psFieldLabels :: [FieldLabel], -- List of fields for a
                                           -- record pattern synonym
                                           -- INVARIANT: either empty if no
                                           -- record pat syn or same length as
                                           -- psArgs

            -- Universally-quantified type variables
            PatSyn -> [InvisTVBinder]
    psUnivTyVars  :: [InvisTVBinder],

            -- Required dictionaries (may mention psUnivTyVars)
            PatSyn -> [Type]
    psReqTheta    :: ThetaType,

            -- Existentially-quantified type vars
            PatSyn -> [InvisTVBinder]
    psExTyVars    :: [InvisTVBinder],

            -- Provided dictionaries (may mention psUnivTyVars or psExTyVars)
            PatSyn -> [Type]
    psProvTheta   :: ThetaType,

            -- Result type
            PatSyn -> Type
    psResultTy   :: Type,  -- Mentions only psUnivTyVars
                                   -- See Note [Pattern synonym result type]

            -- See Note [Matchers and builders for pattern synonyms]
            -- See Note [Keep Ids out of PatSyn]
            PatSyn -> PatSynMatcher
    psMatcher     :: PatSynMatcher,
            PatSyn -> PatSynBuilder
    psBuilder     :: PatSynBuilder
      }

    type PatSynMatcher = (Name, Type, Bool)
         -- Matcher function.
         -- If Bool is True then prov_theta and arg_tys are empty
         -- and type is
         --   forall (p :: RuntimeRep) (r :: TYPE p) univ_tvs.
         --                          req_theta
         --                       => res_ty
         --                       -> (forall ex_tvs. Void# -> r)
         --                       -> (Void# -> r)
         --                       -> r
         --
         -- Otherwise type is
         --   forall (p :: RuntimeRep) (r :: TYPE r) univ_tvs.
         --                          req_theta
         --                       => res_ty
         --                       -> (forall ex_tvs. prov_theta => arg_tys -> r)
         --                       -> (Void# -> r)
         --                       -> r

    type PatSynBuilder = Maybe (Name, Type, Bool)
         -- Nothing  => uni-directional pattern synonym
         -- Just (builder, is_unlifted) => bi-directional
         -- Builder function, of type
         --  forall univ_tvs, ex_tvs. (req_theta, prov_theta)
         --                       =>  arg_tys -> res_ty
         -- See Note [Builder for pattern synonyms with unboxed type]

    {- Note [Pattern synonym signature contexts]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    In a pattern synonym signature we write
       pattern P :: req => prov => t1 -> ... tn -> res_ty

    Note that the "required" context comes first, then the "provided"
    context.  Moreover, the "required" context must not mention
    existentially-bound type variables; that is, ones not mentioned in
    res_ty.  See lots of discussion in #10928.

    If there is no "provided" context, you can omit it; but you
    can't omit the "required" part (unless you omit both).

    Example 1:
          pattern P1 :: (Num a, Eq a) => b -> Maybe (a,b)
          pattern P1 x = Just (3,x)

      We require (Num a, Eq a) to match the 3; there is no provided
      context.

    Example 2:
          data T2 where
            MkT2 :: (Num a, Eq a) => a -> a -> T2

          pattern P2 :: () => (Num a, Eq a) => a -> T2
          pattern P2 x = MkT2 3 x

      When we match against P2 we get a Num dictionary provided.
      We can use that to check the match against 3.

    Example 3:
          pattern P3 :: Eq a => a -> b -> T3 b

       This signature is illegal because the (Eq a) is a required
       constraint, but it mentions the existentially-bound variable 'a'.
       You can see it's existential because it doesn't appear in the
       result type (T3 b).

    Note [Pattern synonym result type]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Consider
       data T a b = MkT b a

       pattern P :: a -> T [a] Bool
       pattern P x = MkT True [x]

    P's psResultTy is (T a Bool), and it really only matches values of
    type (T [a] Bool).  For example, this is ill-typed

       f :: T p q -> String
       f (P x) = "urk"

    This is different to the situation with GADTs:

       data S a where
         MkS :: Int -> S Bool

    Now MkS (and pattern synonyms coming from MkS) can match a
    value of type (S a), not just (S Bool); we get type refinement.

    That in turn means that if you have a pattern

       P x :: T [ty] Bool

    it's not entirely straightforward to work out the instantiation of
    P's universal tyvars. You have to /match/
      the type of the pattern, (T [ty] Bool)
    against
      the psResultTy for the pattern synonym, T [a] Bool
    to get the instantiation a := ty.

    This is very unlike DataCons, where univ tyvars match 1-1 the
    arguments of the TyCon.

    Side note: I (SG) get the impression that instantiated return types should
    generate a *required* constraint for pattern synonyms, rather than a *provided*
    constraint like it's the case for GADTs. For example, I'd expect these
    declarations to have identical semantics:

        pattern Just42 :: Maybe Int
        pattern Just42 = Just 42

        pattern Just'42 :: (a ~ Int) => Maybe a
        pattern Just'42 = Just 42

    The latter generates the proper required constraint, the former does not.
    Also rather different to GADTs is the fact that Just42 doesn't have any
    universally quantified type variables, whereas Just'42 or MkS above has.

    Note [Keep Ids out of PatSyn]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    We carefully arrange that PatSyn does not contain the Ids for the matcher
    and builder.  We want PatSyn, like TyCon and DataCon, to be completely
    immutable. But, the matcher and builder are relatively sophisticated
    functions, and we want to get their final IdInfo in the same way as
    any other Id, so we'd have to update the Ids in the PatSyn too.

    Rather than try to tidy PatSyns (which is easy to forget and is a bit
    tricky, see #19074), it seems cleaner to make them entirely immutable,
    like TyCons and Classes.  To that end PatSynBuilder and PatSynMatcher
    contain Names not Ids. Which, it turns out, is absolutely fine.

    c.f. DefMethInfo in Class, which contains the Name, but not the Id,
    of the default method.

    Note [Pattern synonym representation]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Consider the following pattern synonym declaration

            pattern P x = MkT [x] (Just 42)

    where
            data T a where
                  MkT :: (Show a, Ord b) => [b] -> a -> T a

    so pattern P has type

            b -> T (Maybe t)

    with the following typeclass constraints:

            requires: (Eq t, Num t)
            provides: (Show (Maybe t), Ord b)

    In this case, the fields of MkPatSyn will be set as follows:

      psArgs       = [b]
      psArity      = 1
      psInfix      = False

      psUnivTyVars = [t]
      psExTyVars   = [b]
      psProvTheta  = (Show (Maybe t), Ord b)
      psReqTheta   = (Eq t, Num t)
      psResultTy  = T (Maybe t)

    Note [Matchers and builders for pattern synonyms]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    For each pattern synonym P, we generate

      * a "matcher" function, used to desugar uses of P in patterns,
        which implements pattern matching

      * A "builder" function (for bidirectional pattern synonyms only),
        used to desugar uses of P in expressions, which constructs P-values.

    For the above example, the matcher function has type:

            $mP :: forall (r :: ?) t. (Eq t, Num t)
                => T (Maybe t)
                -> (forall b. (Show (Maybe t), Ord b) => b -> r)
                -> (Void# -> r)
                -> r

    with the following implementation:

            $mP @r @t $dEq $dNum scrut cont fail
              = case scrut of
                  MkT @b $dShow $dOrd [x] (Just 42) -> cont @b $dShow $dOrd x
                  _                                 -> fail Void#

    Notice that the return type 'r' has an open kind, so that it can
    be instantiated by an unboxed type; for example where we see
         f (P x) = 3#

    The extra Void# argument for the failure continuation is needed so that
    it is lazy even when the result type is unboxed.

    For the same reason, if the pattern has no arguments, an extra Void#
    argument is added to the success continuation as well.

    For *bidirectional* pattern synonyms, we also generate a "builder"
    function which implements the pattern synonym in an expression
    context. For our running example, it will be:

            $bP :: forall t b. (Eq t, Num t, Show (Maybe t), Ord b)
                => b -> T (Maybe t)
            $bP x = MkT [x] (Just 42)

    NB: the existential/universal and required/provided split does not
    apply to the builder since you are only putting stuff in, not getting
    stuff out.

    Injectivity of bidirectional pattern synonyms is checked in
    tcPatToExpr which walks the pattern and returns its corresponding
    expression when available.

    Note [Builder for pattern synonyms with unboxed type]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    For bidirectional pattern synonyms that have no arguments and have an
    unboxed type, we add an extra Void# argument to the builder, else it
    would be a top-level declaration with an unboxed type.

            pattern P = 0#

            $bP :: Void# -> Int#
            $bP _ = 0#

    This means that when typechecking an occurrence of P in an expression,
    we must remember that the builder has this void argument. This is
    done by GHC.Tc.TyCl.PatSyn.patSynBuilderOcc.

    Note [Pattern synonyms and the data type Type]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The type of a pattern synonym is of the form (See Note
    [Pattern synonym signatures] in GHC.Tc.Gen.Sig):

        forall univ_tvs. req => forall ex_tvs. prov => ...

    We cannot in general represent this by a value of type Type:

     - if ex_tvs is empty, then req and prov cannot be distinguished from
       each other
     - if req is empty, then univ_tvs and ex_tvs cannot be distinguished
       from each other, and moreover, prov is seen as the "required" context
       (as it is the only context)

    ************************************************************************
    *                                                                      *
    \subsection{Instances}
    *                                                                      *
    ************************************************************************
    -}

    instance Eq PatSyn where
        == :: PatSyn -> PatSyn -> Bool
    (==) = Unique -> Unique -> Bool
    forall a. Eq a => a -> a -> Bool
    (==) (Unique -> Unique -> Bool)
    -> (PatSyn -> Unique) -> PatSyn -> PatSyn -> Bool
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` PatSyn -> Unique
    forall a. Uniquable a => a -> Unique
    getUnique
        /= :: PatSyn -> PatSyn -> Bool
    (/=) = Unique -> Unique -> Bool
    forall a. Eq a => a -> a -> Bool
    (/=) (Unique -> Unique -> Bool)
    -> (PatSyn -> Unique) -> PatSyn -> PatSyn -> Bool
    forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
    `on` PatSyn -> Unique
    forall a. Uniquable a => a -> Unique
    getUnique

    instance Uniquable PatSyn where
        getUnique :: PatSyn -> Unique
    getUnique = PatSyn -> Unique
    psUnique

    instance NamedThing PatSyn where
        getName :: PatSyn -> Name
    getName = PatSyn -> Name
    patSynName

    instance Outputable PatSyn where
        ppr :: PatSyn -> SDoc
    ppr = Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr (Name -> SDoc) -> (PatSyn -> Name) -> PatSyn -> SDoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PatSyn -> Name
    forall a. NamedThing a => a -> Name
    getName

    instance OutputableBndr PatSyn where
        pprInfixOcc :: PatSyn -> SDoc
    pprInfixOcc = Name -> SDoc
    forall a. (Outputable a, NamedThing a) => a -> SDoc
    pprInfixName (Name -> SDoc) -> (PatSyn -> Name) -> PatSyn -> SDoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PatSyn -> Name
    forall a. NamedThing a => a -> Name
    getName
        pprPrefixOcc :: PatSyn -> SDoc
    pprPrefixOcc = Name -> SDoc
    forall a. NamedThing a => a -> SDoc
    pprPrefixName (Name -> SDoc) -> (PatSyn -> Name) -> PatSyn -> SDoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . PatSyn -> Name
    forall a. NamedThing a => a -> Name
    getName

    instance Data.Data PatSyn where
        -- don't traverse?
        toConstr :: PatSyn -> Constr
    toConstr PatSyn
    _   = String -> Constr
    abstractConstr String
    "PatSyn"
        gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PatSyn
    gunfold forall b r. Data b => c (b -> r) -> c r
    _ forall r. r -> c r
    _  = String -> Constr -> c PatSyn
    forall a. HasCallStack => String -> a
    error String
    "gunfold"
        dataTypeOf :: PatSyn -> DataType
    dataTypeOf PatSyn
    _ = String -> DataType
    mkNoRepType String
    "PatSyn"

    {-
    ************************************************************************
    *                                                                      *
    \subsection{Construction}
    *                                                                      *
    ************************************************************************
    -}

    -- | Build a new pattern synonym
    mkPatSyn :: Name
             -> Bool                 -- ^ Is the pattern synonym declared infix?
             -> ([InvisTVBinder], ThetaType) -- ^ Universally-quantified type
                                             -- variables and required dicts
             -> ([InvisTVBinder], ThetaType) -- ^ Existentially-quantified type
                                             -- variables and provided dicts
             -> [FRRType]            -- ^ Original arguments
             -> Type                 -- ^ Original result type
             -> PatSynMatcher        -- ^ Matcher
             -> PatSynBuilder        -- ^ Builder
             -> [FieldLabel]         -- ^ Names of fields for
                                     --   a record pattern synonym
             -> PatSyn
     -- NB: The univ and ex vars are both in PiTyVarBinder form and TyVar form for
     -- convenience. All the TyBinders should be Named!
    mkPatSyn :: Name
    -> Bool
    -> ([InvisTVBinder], [Type])
    -> ([InvisTVBinder], [Type])
    -> [Type]
    -> Type
    -> PatSynMatcher
    -> PatSynBuilder
    -> [FieldLabel]
    -> PatSyn
    mkPatSyn Name
    name Bool
    declared_infix
             ([InvisTVBinder]
    univ_tvs, [Type]
    req_theta)
             ([InvisTVBinder]
    ex_tvs, [Type]
    prov_theta)
             [Type]
    orig_args
             Type
    orig_res_ty
             PatSynMatcher
    matcher PatSynBuilder
    builder [FieldLabel]
    field_labels
        = MkPatSyn {psName :: Name
    psName = Name
    name, psUnique :: Unique
    psUnique = Name -> Unique
    forall a. Uniquable a => a -> Unique
    getUnique Name
    name,
                    psUnivTyVars :: [InvisTVBinder]
    psUnivTyVars = [InvisTVBinder]
    univ_tvs,
                    psExTyVars :: [InvisTVBinder]
    psExTyVars = [InvisTVBinder]
    ex_tvs,
                    psProvTheta :: [Type]
    psProvTheta = [Type]
    prov_theta, psReqTheta :: [Type]
    psReqTheta = [Type]
    req_theta,
                    psInfix :: Bool
    psInfix = Bool
    declared_infix,
                    psArgs :: [Type]
    psArgs = [Type]
    orig_args,
                    psArity :: Arity
    psArity = [Type] -> Arity
    forall a. [a] -> Arity
    forall (t :: * -> *) a. Foldable t => t a -> Arity
    length [Type]
    orig_args,
                    psResultTy :: Type
    psResultTy = Type
    orig_res_ty,
                    psMatcher :: PatSynMatcher
    psMatcher = PatSynMatcher
    matcher,
                    psBuilder :: PatSynBuilder
    psBuilder = PatSynBuilder
    builder,
                    psFieldLabels :: [FieldLabel]
    psFieldLabels = [FieldLabel]
    field_labels
                    }

    -- | The 'Name' of the 'PatSyn', giving it a unique, rooted identification
    patSynName :: PatSyn -> Name
    patSynName :: PatSyn -> Name
    patSynName = PatSyn -> Name
    psName

    -- | Should the 'PatSyn' be presented infix?
    patSynIsInfix :: PatSyn -> Bool
    patSynIsInfix :: PatSyn -> Bool
    patSynIsInfix = PatSyn -> Bool
    psInfix

    -- | Arity of the pattern synonym
    patSynArity :: PatSyn -> Arity
    patSynArity :: PatSyn -> Arity
    patSynArity = PatSyn -> Arity
    psArity

    -- | Is this a \'vanilla\' pattern synonym (no existentials, no provided constraints)?
    isVanillaPatSyn :: PatSyn -> Bool
    isVanillaPatSyn :: PatSyn -> Bool
    isVanillaPatSyn PatSyn
    ps = [InvisTVBinder] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null (PatSyn -> [InvisTVBinder]
    psExTyVars PatSyn
    ps) Bool -> Bool -> Bool
    && [Type] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null (PatSyn -> [Type]
    psProvTheta PatSyn
    ps)

    patSynArgs :: PatSyn -> [Type]
    patSynArgs :: PatSyn -> [Type]
    patSynArgs = PatSyn -> [Type]
    psArgs

    patSynFieldLabels :: PatSyn -> [FieldLabel]
    patSynFieldLabels :: PatSyn -> [FieldLabel]
    patSynFieldLabels = PatSyn -> [FieldLabel]
    psFieldLabels

    -- | Extract the type for any given labelled field of the 'DataCon'
    patSynFieldType :: PatSyn -> FieldLabelString -> Type
    patSynFieldType :: PatSyn -> FieldLabelString -> Type
    patSynFieldType PatSyn
    ps FieldLabelString
    label
      = case ((FieldLabel, Type) -> Bool)
    -> [(FieldLabel, Type)] -> Maybe (FieldLabel, Type)
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    find ((FieldLabelString -> FieldLabelString -> Bool
    forall a. Eq a => a -> a -> Bool
    == FieldLabelString
    label) (FieldLabelString -> Bool)
    -> ((FieldLabel, Type) -> FieldLabelString)
    -> (FieldLabel, Type)
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FieldLabel -> FieldLabelString
    flLabel (FieldLabel -> FieldLabelString)
    -> ((FieldLabel, Type) -> FieldLabel)
    -> (FieldLabel, Type)
    -> FieldLabelString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FieldLabel, Type) -> FieldLabel
    forall a b. (a, b) -> a
    fst) (PatSyn -> [FieldLabel]
    psFieldLabels PatSyn
    ps [FieldLabel] -> [Type] -> [(FieldLabel, Type)]
    forall a b. [a] -> [b] -> [(a, b)]
    `zip` PatSyn -> [Type]
    psArgs PatSyn
    ps) of
          Just (FieldLabel
    _, Type
    ty) -> Type
    ty
          Maybe (FieldLabel, Type)
    Nothing -> String -> SDoc -> Type
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "dataConFieldType" (PatSyn -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr PatSyn
    ps SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> FieldLabelString -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr FieldLabelString
    label)

    patSynUnivTyVarBinders :: PatSyn -> [InvisTVBinder]
    patSynUnivTyVarBinders :: PatSyn -> [InvisTVBinder]
    patSynUnivTyVarBinders = PatSyn -> [InvisTVBinder]
    psUnivTyVars

    patSynExTyVars :: PatSyn -> [TyVar]
    patSynExTyVars :: PatSyn -> [TyVar]
    patSynExTyVars PatSyn
    ps = [InvisTVBinder] -> [TyVar]
    forall tv argf. [VarBndr tv argf] -> [tv]
    binderVars (PatSyn -> [InvisTVBinder]
    psExTyVars PatSyn
    ps)

    patSynExTyVarBinders :: PatSyn -> [InvisTVBinder]
    patSynExTyVarBinders :: PatSyn -> [InvisTVBinder]
    patSynExTyVarBinders = PatSyn -> [InvisTVBinder]
    psExTyVars

    patSynSigBndr :: PatSyn -> ([InvisTVBinder], ThetaType, [InvisTVBinder], ThetaType, [Scaled Type], Type)
    patSynSigBndr :: PatSyn
    -> ([InvisTVBinder], [Type], [InvisTVBinder], [Type],
        [Scaled Type], Type)
    patSynSigBndr (MkPatSyn { psUnivTyVars :: PatSyn -> [InvisTVBinder]
    psUnivTyVars = [InvisTVBinder]
    univ_tvs, psExTyVars :: PatSyn -> [InvisTVBinder]
    psExTyVars = [InvisTVBinder]
    ex_tvs
                            , psProvTheta :: PatSyn -> [Type]
    psProvTheta = [Type]
    prov, psReqTheta :: PatSyn -> [Type]
    psReqTheta = [Type]
    req
                            , psArgs :: PatSyn -> [Type]
    psArgs = [Type]
    arg_tys, psResultTy :: PatSyn -> Type
    psResultTy = Type
    res_ty })
      = ([InvisTVBinder]
    univ_tvs, [Type]
    req, [InvisTVBinder]
    ex_tvs, [Type]
    prov, (Type -> Scaled Type) -> [Type] -> [Scaled Type]
    forall a b. (a -> b) -> [a] -> [b]
    map Type -> Scaled Type
    forall a. a -> Scaled a
    unrestricted [Type]
    arg_tys, Type
    res_ty)

    patSynSig :: PatSyn -> ([TyVar], ThetaType, [TyVar], ThetaType, [Scaled Type], Type)
    patSynSig :: PatSyn -> ([TyVar], [Type], [TyVar], [Type], [Scaled Type], Type)
    patSynSig PatSyn
    ps = let ([InvisTVBinder]
    u_tvs, [Type]
    req, [InvisTVBinder]
    e_tvs, [Type]
    prov, [Scaled Type]
    arg_tys, Type
    res_ty) = PatSyn
    -> ([InvisTVBinder], [Type], [InvisTVBinder], [Type],
        [Scaled Type], Type)
    patSynSigBndr PatSyn
    ps
                   in ([InvisTVBinder] -> [TyVar]
    forall tv argf. [VarBndr tv argf] -> [tv]
    binderVars [InvisTVBinder]
    u_tvs, [Type]
    req, [InvisTVBinder] -> [TyVar]
    forall tv argf. [VarBndr tv argf] -> [tv]
    binderVars [InvisTVBinder]
    e_tvs, [Type]
    prov, [Scaled Type]
    arg_tys, Type
    res_ty)

    patSynMatcher :: PatSyn -> PatSynMatcher
    patSynMatcher :: PatSyn -> PatSynMatcher
    patSynMatcher = PatSyn -> PatSynMatcher
    psMatcher

    patSynBuilder :: PatSyn -> PatSynBuilder
    patSynBuilder :: PatSyn -> PatSynBuilder
    patSynBuilder = PatSyn -> PatSynBuilder
    psBuilder

    patSynResultType :: PatSyn -> Type
    patSynResultType :: PatSyn -> Type
    patSynResultType = PatSyn -> Type
    psResultTy

    patSynInstArgTys :: PatSyn -> [Type] -> [Type]
    -- Return the types of the argument patterns
    -- e.g.  data D a = forall b. MkD a b (b->a)
    --       pattern P f x y = MkD (x,True) y f
    --          D :: forall a. forall b. a -> b -> (b->a) -> D a
    --          P :: forall c. forall b. (b->(c,Bool)) -> c -> b -> P c
    --   patSynInstArgTys P [Int,bb] = [bb->(Int,Bool), Int, bb]
    -- NB: the inst_tys should be both universal and existential
    patSynInstArgTys :: PatSyn -> [Type] -> [Type]
    patSynInstArgTys (MkPatSyn { psName :: PatSyn -> Name
    psName = Name
    name, psUnivTyVars :: PatSyn -> [InvisTVBinder]
    psUnivTyVars = [InvisTVBinder]
    univ_tvs
                               , psExTyVars :: PatSyn -> [InvisTVBinder]
    psExTyVars = [InvisTVBinder]
    ex_tvs, psArgs :: PatSyn -> [Type]
    psArgs = [Type]
    arg_tys })
                     [Type]
    inst_tys
      = Bool -> SDoc -> [Type] -> [Type]
    forall a. HasCallStack => Bool -> SDoc -> a -> a
    assertPpr ([TyVar]
    tyvars [TyVar] -> [Type] -> Bool
    forall a b. [a] -> [b] -> Bool
    `equalLength` [Type]
    inst_tys)
                  (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "patSynInstArgTys" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    name SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ [TyVar] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [TyVar]
    tyvars SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ [Type] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Type]
    inst_tys) ([Type] -> [Type]) -> [Type] -> [Type]
    forall a b. (a -> b) -> a -> b
    $
        (Type -> Type) -> [Type] -> [Type]
    forall a b. (a -> b) -> [a] -> [b]
    map ([TyVar] -> [Type] -> Type -> Type
    HasDebugCallStack => [TyVar] -> [Type] -> Type -> Type
    substTyWith [TyVar]
    tyvars [Type]
    inst_tys) [Type]
    arg_tys
      where
        tyvars :: [TyVar]
    tyvars = [InvisTVBinder] -> [TyVar]
    forall tv argf. [VarBndr tv argf] -> [tv]
    binderVars ([InvisTVBinder]
    univ_tvs [InvisTVBinder] -> [InvisTVBinder] -> [InvisTVBinder]
    forall a. [a] -> [a] -> [a]
    ++ [InvisTVBinder]
    ex_tvs)

    patSynInstResTy :: PatSyn -> [Type] -> Type
    -- Return the type of whole pattern
    -- E.g.  pattern P x y = Just (x,x,y)
    --         P :: a -> b -> Just (a,a,b)
    --         (patSynInstResTy P [Int,Bool] = Maybe (Int,Int,Bool)
    -- NB: unlike patSynInstArgTys, the inst_tys should be just the *universal* tyvars
    patSynInstResTy :: PatSyn -> [Type] -> Type
    patSynInstResTy (MkPatSyn { psName :: PatSyn -> Name
    psName = Name
    name, psUnivTyVars :: PatSyn -> [InvisTVBinder]
    psUnivTyVars = [InvisTVBinder]
    univ_tvs
                              , psResultTy :: PatSyn -> Type
    psResultTy = Type
    res_ty })
                    [Type]
    inst_tys
      = Bool -> SDoc -> Type -> Type
    forall a. HasCallStack => Bool -> SDoc -> a -> a
    assertPpr ([InvisTVBinder]
    univ_tvs [InvisTVBinder] -> [Type] -> Bool
    forall a b. [a] -> [b] -> Bool
    `equalLength` [Type]
    inst_tys)
                  (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "patSynInstResTy" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Name -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Name
    name SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ [InvisTVBinder] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [InvisTVBinder]
    univ_tvs SDoc -> SDoc -> SDoc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ [Type] -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr [Type]
    inst_tys) (Type -> Type) -> Type -> Type
    forall a b. (a -> b) -> a -> b
    $
        [TyVar] -> [Type] -> Type -> Type
    HasDebugCallStack => [TyVar] -> [Type] -> Type -> Type
    substTyWith ([InvisTVBinder] -> [TyVar]
    forall tv argf. [VarBndr tv argf] -> [tv]
    binderVars [InvisTVBinder]
    univ_tvs) [Type]
    inst_tys Type
    res_ty

    -- | Print the type of a pattern synonym. The foralls are printed explicitly
    pprPatSynType :: PatSyn -> SDoc
    pprPatSynType :: PatSyn -> SDoc
    pprPatSynType (MkPatSyn { psUnivTyVars :: PatSyn -> [InvisTVBinder]
    psUnivTyVars = [InvisTVBinder]
    univ_tvs,  psReqTheta :: PatSyn -> [Type]
    psReqTheta  = [Type]
    req_theta
                            , psExTyVars :: PatSyn -> [InvisTVBinder]
    psExTyVars   = [InvisTVBinder]
    ex_tvs,    psProvTheta :: PatSyn -> [Type]
    psProvTheta = [Type]
    prov_theta
                            , psArgs :: PatSyn -> [Type]
    psArgs       = [Type]
    orig_args, psResultTy :: PatSyn -> Type
    psResultTy = Type
    orig_res_ty })
      = [SDoc] -> SDoc
    forall doc. IsLine doc => [doc] -> doc
    sep [ [ForAllTyBinder] -> SDoc
    pprForAll ([ForAllTyBinder] -> SDoc) -> [ForAllTyBinder] -> SDoc
    forall a b. (a -> b) -> a -> b
    $ [InvisTVBinder] -> [ForAllTyBinder]
    forall a. [VarBndr a Specificity] -> [VarBndr a ForAllTyFlag]
    tyVarSpecToBinders [InvisTVBinder]
    univ_tvs
            , [Type] -> SDoc
    pprThetaArrowTy [Type]
    req_theta
            , Bool -> SDoc -> SDoc
    forall doc. IsOutput doc => Bool -> doc -> doc
    ppWhen Bool
    insert_empty_ctxt (SDoc -> SDoc) -> SDoc -> SDoc
    forall a b. (a -> b) -> a -> b
    $ SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc
    parens SDoc
    forall doc. IsOutput doc => doc
    empty SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc
    darrow
            , Type -> SDoc
    pprType Type
    sigma_ty ]
      where
        sigma_ty :: Type
    sigma_ty = [InvisTVBinder] -> Type -> Type
    mkInvisForAllTys [InvisTVBinder]
    ex_tvs (Type -> Type) -> Type -> Type
    forall a b. (a -> b) -> a -> b
    $
                   [Type] -> Type -> Type
    HasDebugCallStack => [Type] -> Type -> Type
    mkInvisFunTys [Type]
    prov_theta (Type -> Type) -> Type -> Type
    forall a b. (a -> b) -> a -> b
    $
                   [Type] -> Type -> Type
    mkVisFunTysMany [Type]
    orig_args Type
    orig_res_ty
        insert_empty_ctxt :: Bool
    insert_empty_ctxt = [Type] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Type]
    req_theta Bool -> Bool -> Bool
    && Bool -> Bool
    not ([Type] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Type]
    prov_theta Bool -> Bool -> Bool
    && [InvisTVBinder] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [InvisTVBinder]
    ex_tvs)