mkDataCon :: Name
          -> Bool               -- ^ Is the constructor declared infix?
          -> [HsBang]           -- ^ Strictness annotations written in the source file
          -> [FieldLabel]       -- ^ Field labels for the constructor, if it is a record,
                                --   otherwise empty
          -> [TyVar]            -- ^ Universally quantified type variables
          -> [TyVar]            -- ^ Existentially quantified type variables
          -> [(TyVar,Type)]     -- ^ GADT equalities
          -> ThetaType          -- ^ Theta-type occuring before the arguments proper
          -> [Type]             -- ^ Original argument types
          -> Type               -- ^ Original result type
          -> TyCon              -- ^ Representation type constructor
          -> ThetaType          -- ^ The "stupid theta", context of the data declaration
                                --   e.g. @data Eq a => T a ...@
          -> Id                 -- ^ Worker Id
          -> DataConRep         -- ^ Representation
          -> DataCon
  -- Can get the tag from the TyCon

mkDataCon name declared_infix
          arg_stricts   -- Must match orig_arg_tys 1-1
          fields
          univ_tvs ex_tvs
          eq_spec theta
          orig_arg_tys orig_res_ty rep_tycon
          stupid_theta work_id rep
-- Warning: mkDataCon is not a good place to check invariants.
-- If the programmer writes the wrong result type in the decl, thus:
--      data T a where { MkT :: S }
-- then it's possible that the univ_tvs may hit an assertion failure
-- if you pull on univ_tvs.  This case is checked by checkValidDataCon,
-- so the error is detected properly... it's just that asaertions here
-- are a little dodgy.

  = con
  where
    is_vanilla = null ex_tvs && null eq_spec && null theta
    con = MkData {dcName = name, dcUnique = nameUnique name,
                  dcVanilla = is_vanilla, dcInfix = declared_infix,
                  dcUnivTyVars = univ_tvs, dcExTyVars = ex_tvs,
                  dcEqSpec = eq_spec,
                  dcOtherTheta = theta,
                  dcStupidTheta = stupid_theta,
                  dcOrigArgTys = orig_arg_tys, dcOrigResTy = orig_res_ty,
                  dcRepTyCon = rep_tycon,
                  dcArgBangs = arg_stricts,
                  dcFields = fields, dcTag = tag, dcRepType = rep_ty,
                  dcWorkId = work_id,
                  dcRep = rep,
                  dcSourceArity = length orig_arg_tys,
                  dcRepArity = length rep_arg_tys,
                  dcPromoted = mb_promoted }

        -- The 'arg_stricts' passed to mkDataCon are simply those for the
        -- source-language arguments.  We add extra ones for the
        -- dictionary arguments right here.

    tag = assoc "mkDataCon" (tyConDataCons rep_tycon `zip` [fIRST_TAG..]) con
    rep_arg_tys = dataConRepArgTys con
    rep_ty = mkForAllTys univ_tvs $ mkForAllTys ex_tvs $
             mkFunTys rep_arg_tys $
             mkTyConApp rep_tycon (mkTyVarTys univ_tvs)

    mb_promoted   -- See Note [Promoted data constructors] in TyCon
      | isJust (promotableTyCon_maybe rep_tycon)
          -- The TyCon is promotable only if all its datacons
          -- are, so the promoteType for prom_kind should succeed
      = Just (mkPromotedDataCon con name (getUnique name) prom_kind roles)
      | otherwise
      = Nothing
    prom_kind = promoteType (dataConUserType con)
    roles = map (const Nominal)          (univ_tvs ++ ex_tvs) ++
            map (const Representational) orig_arg_tys
mkDataCon :: Name
          -> Bool               -- ^ Is the constructor declared infix?
          -> [HsBang]           -- ^ Strictness annotations written in the source file
          -> [FieldLabel]       -- ^ Field labels for the constructor, if it is a record,
                                --   otherwise empty
          -> [TyVar]            -- ^ Universally quantified type variables
          -> [TyVar]            -- ^ Existentially quantified type variables
          -> [(TyVar,Type)]     -- ^ GADT equalities
          -> ThetaType          -- ^ Theta-type occuring before the arguments proper
          -> [Type]             -- ^ Original argument types
          -> Type               -- ^ Original result type
          -> TyCon              -- ^ Representation type constructor
          -> ThetaType          -- ^ The "stupid theta", context of the data declaration
                                --   e.g. @data Eq a => T a ...@
          -> Id                 -- ^ Worker Id
          -> DataConRep         -- ^ Representation
          -> DataCon
mkDataCon name declared_infix
          arg_stricts   -- Must match orig_arg_tys 1-1
          fields
          univ_tvs ex_tvs
          eq_spec theta
          orig_arg_tys orig_res_ty rep_tycon
          stupid_theta work_id rep
-- Warning: mkDataCon is not a good place to check invariants.
-- If the programmer writes the wrong result type in the decl, thus:
--      data T a where { MkT :: S }
-- then it's possible that the univ_tvs may hit an assertion failure
-- if you pull on univ_tvs.  This case is checked by checkValidDataCon,
-- so the error is detected properly... it's just that asaertions here
-- are a little dodgy.

  = con
  where
    is_vanilla = null ex_tvs && null eq_spec && null theta
    con = MkData {dcName = name, dcUnique = nameUnique name,
                  dcVanilla = is_vanilla, dcInfix = declared_infix,
                  dcUnivTyVars = univ_tvs, dcExTyVars = ex_tvs,
                  dcEqSpec = eq_spec,
                  dcOtherTheta = theta,
                  dcStupidTheta = stupid_theta,
                  dcOrigArgTys = orig_arg_tys, dcOrigResTy = orig_res_ty,
                  dcRepTyCon = rep_tycon,
                  dcArgBangs = arg_stricts,
                  dcFields = fields, dcTag = tag, dcRepType = rep_ty,
                  dcWorkId = work_id,
                  dcRep = rep,
                  dcSourceArity = length orig_arg_tys,
                  dcRepArity = length rep_arg_tys,
                  dcPromoted = mb_promoted }

        -- The 'arg_stricts' passed to mkDataCon are simply those for the
        -- source-language arguments.  We add extra ones for the
        -- dictionary arguments right here.

    tag = assoc "mkDataCon" (tyConDataCons rep_tycon `zip` [fIRST_TAG..]) con
    rep_arg_tys = dataConRepArgTys con
    rep_ty = mkForAllTys univ_tvs $ mkForAllTys ex_tvs $
             mkFunTys rep_arg_tys $
             mkTyConApp rep_tycon (mkTyVarTys univ_tvs)

    mb_promoted   -- See Note [Promoted data constructors] in TyCon
      | isJust (promotableTyCon_maybe rep_tycon)
          -- The TyCon is promotable only if all its datacons
          -- are, so the promoteType for prom_kind should succeed
      = Just (mkPromotedDataCon con name (getUnique name) prom_kind roles)
      | otherwise
      = Nothing
    prom_kind = promoteType (dataConUserType con)
    roles = map (const Nominal)          (univ_tvs ++ ex_tvs) ++
            map (const Representational) orig_arg_tys
mkDataCon name declared_infix
          arg_stricts   -- Must match orig_arg_tys 1-1
          fields
          univ_tvs ex_tvs
          eq_spec theta
          orig_arg_tys orig_res_ty rep_tycon
          stupid_theta work_id rep
-- Warning: mkDataCon is not a good place to check invariants.
-- If the programmer writes the wrong result type in the decl, thus:
--      data T a where { MkT :: S }
-- then it's possible that the univ_tvs may hit an assertion failure
-- if you pull on univ_tvs.  This case is checked by checkValidDataCon,
-- so the error is detected properly... it's just that asaertions here
-- are a little dodgy.

  = con
  where
    is_vanilla = null ex_tvs && null eq_spec && null theta
    con = MkData {dcName = name, dcUnique = nameUnique name,
                  dcVanilla = is_vanilla, dcInfix = declared_infix,
                  dcUnivTyVars = univ_tvs, dcExTyVars = ex_tvs,
                  dcEqSpec = eq_spec,
                  dcOtherTheta = theta,
                  dcStupidTheta = stupid_theta,
                  dcOrigArgTys = orig_arg_tys, dcOrigResTy = orig_res_ty,
                  dcRepTyCon = rep_tycon,
                  dcArgBangs = arg_stricts,
                  dcFields = fields, dcTag = tag, dcRepType = rep_ty,
                  dcWorkId = work_id,
                  dcRep = rep,
                  dcSourceArity = length orig_arg_tys,
                  dcRepArity = length rep_arg_tys,
                  dcPromoted = mb_promoted }

        -- The 'arg_stricts' passed to mkDataCon are simply those for the
        -- source-language arguments.  We add extra ones for the
        -- dictionary arguments right here.

    tag = assoc "mkDataCon" (tyConDataCons rep_tycon `zip` [fIRST_TAG..]) con
    rep_arg_tys = dataConRepArgTys con
    rep_ty = mkForAllTys univ_tvs $ mkForAllTys ex_tvs $
             mkFunTys rep_arg_tys $
             mkTyConApp rep_tycon (mkTyVarTys univ_tvs)

    mb_promoted   -- See Note [Promoted data constructors] in TyCon
      | isJust (promotableTyCon_maybe rep_tycon)
          -- The TyCon is promotable only if all its datacons
          -- are, so the promoteType for prom_kind should succeed
      = Just (mkPromotedDataCon con name (getUnique name) prom_kind roles)
      | otherwise
      = Nothing
    prom_kind = promoteType (dataConUserType con)
    roles = map (const Nominal)          (univ_tvs ++ ex_tvs) ++
            map (const Representational) orig_arg_tys