summaryrefslogtreecommitdiff
path: root/compiler/GHC/Tc/TyCl.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Tc/TyCl.hs')
-rw-r--r--compiler/GHC/Tc/TyCl.hs187
1 files changed, 125 insertions, 62 deletions
diff --git a/compiler/GHC/Tc/TyCl.hs b/compiler/GHC/Tc/TyCl.hs
index 302f93e691..5f4312d093 100644
--- a/compiler/GHC/Tc/TyCl.hs
+++ b/compiler/GHC/Tc/TyCl.hs
@@ -99,6 +99,7 @@ import GHC.Utils.Constants (debugIsOn)
import GHC.Utils.Misc
import Control.Monad
+import Data.Foldable
import Data.Functor.Identity
import Data.List ( partition)
import Data.List.NonEmpty ( NonEmpty(..) )
@@ -1604,16 +1605,22 @@ kcTyClDecl (FamDecl _ (FamilyDecl { fdInfo = fd_info })) fam_tc
-------------------
--- Kind-check the types of the arguments to a data constructor.
+-- Kind-check the type of an argument to a data constructor.
-- This includes doing kind unification if the type is a newtype.
-- See Note [Implementation of UnliftedNewtypes] for why we need
--- the first two arguments.
+-- the first argument.
+kcConArgTy :: ContextKind -> HsScaled GhcRn (LHsType GhcRn) -> TcM ()
+kcConArgTy exp_kind (HsScaled mult ty) = do
+ { _ <- tcCheckLHsType (getBangType ty) exp_kind
+ ; void $ tcMult mult
+ -- See Note [Implementation of UnliftedNewtypes], STEP 2
+ }
+
+-- Kind-check the types of the arguments to a data constructor.
kcConArgTys :: NewOrData -> TcKind -> [HsScaled GhcRn (LHsType GhcRn)] -> TcM ()
kcConArgTys new_or_data res_kind arg_tys = do
{ let exp_kind = getArgExpKind new_or_data res_kind
- ; forM_ arg_tys (\(HsScaled mult ty) -> do _ <- tcCheckLHsType (getBangType ty) exp_kind
- tcMult mult)
- -- See Note [Implementation of UnliftedNewtypes], STEP 2
+ ; traverse_ (kcConArgTy exp_kind) arg_tys
}
-- Kind-check the types of arguments to a Haskell98 data constructor.
@@ -1624,12 +1631,28 @@ kcConH98Args new_or_data res_kind con_args = case con_args of
RecCon (L _ flds) -> kcConArgTys new_or_data res_kind $
map (hsLinear . cd_fld_type . unLoc) flds
--- Kind-check the types of arguments to a GADT data constructor.
-kcConGADTArgs :: NewOrData -> TcKind -> HsConDeclGADTDetails GhcRn -> TcM ()
-kcConGADTArgs new_or_data res_kind con_args = case con_args of
- PrefixConGADT tys -> kcConArgTys new_or_data res_kind tys
- RecConGADT (L _ flds) _ -> kcConArgTys new_or_data res_kind $
- map (hsLinear . cd_fld_type . unLoc) flds
+-- Kind-check the types of the arguments and result in a GADT data constructor.
+kcConGadtSigBody :: NewOrData -> Kind -> ConGadtSigBody GhcRn -> TcM ()
+kcConGadtSigBody new_or_data res_kind body = case body of
+ PrefixConGADT prefix_body ->
+ kcPrefixConGadtSigBody new_or_data res_kind prefix_body
+ RecConGADT (L _ flds) _ res_ty -> do
+ _ <- tcCheckLHsType res_ty (TheKind res_kind)
+ kcConArgTys new_or_data res_kind $ map (hsLinear . cd_fld_type . unLoc) flds
+
+-- Kind-check the types of the arguments and result in a prefix GADT data constructor.
+kcPrefixConGadtSigBody :: NewOrData -> Kind -> PrefixConGadtSigBody GhcRn -> TcM ()
+kcPrefixConGadtSigBody new_or_data res_kind = go
+ where
+ exp_kind :: ContextKind
+ exp_kind = getArgExpKind new_or_data res_kind
+
+ go :: PrefixConGadtSigBody GhcRn -> TcM ()
+ go (PCGSRes res_ty) =
+ void $ tcCheckLHsType res_ty (TheKind res_kind)
+ go (PCGSAnonArg arg_ty body) = do
+ go body
+ kcConArgTy exp_kind arg_ty
kcConDecls :: NewOrData
-> TcKind -- The result kind signature
@@ -1668,7 +1691,7 @@ kcConDecl new_or_data
_tc_res_kind -- Not used in GADT case (and doesn't make sense)
(ConDeclGADT
{ con_names = names, con_bndrs = L _ outer_bndrs, con_mb_cxt = cxt
- , con_g_args = args, con_res_ty = res_ty })
+ , con_body = body })
= -- See Note [kcConDecls: kind-checking data type decls]
addErrCtxt (dataConCtxt names) $
discardResult $
@@ -1676,10 +1699,9 @@ kcConDecl new_or_data
bindOuterSigTKBndrs_Tv outer_bndrs $
-- Why "_Tv"? See Note [Using TyVarTvs for kind-checking GADTs]
do { _ <- tcHsContext cxt
- ; traceTc "kcConDecl:GADT {" (ppr names $$ ppr res_ty)
+ ; traceTc "kcConDecl:GADT {" (ppr names)
; con_res_kind <- newOpenTypeKind
- ; _ <- tcCheckLHsType res_ty (TheKind con_res_kind)
- ; kcConGADTArgs new_or_data con_res_kind args
+ ; kcConGadtSigBody new_or_data con_res_kind body
; traceTc "kcConDecl:GADT }" (ppr names $$ ppr con_res_kind)
; return () }
@@ -2174,7 +2196,7 @@ newtype instance Foo 'Red = FooRedC Int#
Note that, in the GADT case, we might have a kind signature with arrows
(newtype XYZ a b :: Type -> Type where ...). We want only the final
-component of the kind for checking in kcConDecl, so we call etaExpanAlgTyCon
+component of the kind for checking in kcConDecl, so we call etaExpandAlgTyCon
in kcTyClDecl.
STEP 3: Type-checking (desugaring), as done by tcTyClDecl. The key function
@@ -3480,8 +3502,7 @@ tcConDecl new_or_data dd_info rep_tycon tc_bndrs _res_kind tag_map
-- we get the res_kind by typechecking the result type.
(ConDeclGADT { con_names = names
, con_bndrs = L _ outer_hs_bndrs
- , con_mb_cxt = cxt, con_g_args = hs_args
- , con_res_ty = hs_res_ty })
+ , con_mb_cxt = cxt, con_body = body })
= addErrCtxt (dataConCtxt names) $
do { traceTc "tcConDecl 1 gadt" (ppr names)
; let (L _ name : _) = names
@@ -3490,26 +3511,8 @@ tcConDecl new_or_data dd_info rep_tycon tc_bndrs _res_kind tag_map
<- pushLevelAndSolveEqualitiesX "tcConDecl:GADT" $
tcOuterTKBndrs skol_info outer_hs_bndrs $
do { ctxt <- tcHsContext cxt
- ; (res_ty, res_kind) <- tcInferLHsTypeKind hs_res_ty
- -- See Note [GADT return kinds]
-
- -- For data instances (only), ensure that the return type,
- -- res_ty, is a substitution instance of the header.
- -- See Note [GADT return types]
- ; case dd_info of
- DDataType -> return ()
- DDataInstance hdr_ty ->
- do { (subst, _meta_tvs) <- newMetaTyVars (binderVars tc_bndrs)
- ; let head_shape = substTy subst hdr_ty
- ; discardResult $
- popErrCtxt $ -- Drop dataConCtxt
- addErrCtxt (dataConResCtxt names) $
- unifyType Nothing res_ty head_shape }
-
- -- See Note [Datatype return kinds]
- ; let exp_kind = getArgExpKind new_or_data res_kind
- ; btys <- tcConGADTArgs exp_kind hs_args
-
+ ; (btys, res_ty) <-
+ tcConGadtSigBody names new_or_data dd_info tc_bndrs body
; let (arg_tys, stricts) = unzip btys
; field_lbls <- lookupConstructorFields name
; return (ctxt, arg_tys, res_ty, field_lbls, stricts)
@@ -3550,7 +3553,7 @@ tcConDecl new_or_data dd_info rep_tycon tc_bndrs _res_kind tag_map
; dflags <- getDynFlags
; let
buildOneDataCon (L _ name) = do
- { is_infix <- tcConIsInfixGADT name hs_args
+ { is_infix <- tcConIsInfixGADT name body
; rep_nm <- newTyConRepName name
; let bang_opts = SrcBangOpts (initBangOpts dflags)
@@ -3663,14 +3666,14 @@ tcConIsInfixH98 _ details
PrefixCon{} -> return False
tcConIsInfixGADT :: Name
- -> HsConDeclGADTDetails GhcRn
- -> TcM Bool
-tcConIsInfixGADT con details
- = case details of
+ -> ConGadtSigBody GhcRn
+ -> TcM Bool
+tcConIsInfixGADT con body
+ = case body of
RecConGADT{} -> return False
- PrefixConGADT arg_tys -- See Note [Infix GADT constructors]
+ PrefixConGADT prefix_body -- See Note [Infix GADT constructors]
| isSymOcc (getOccName con)
- , [_ty1,_ty2] <- map hsScaledThing arg_tys
+ , [_ty1,_ty2] <- map hsScaledThing $ anonPrefixConGadtSigArgs prefix_body
-> do { fix_env <- getFixityEnv
; return (con `elemNameEnv` fix_env) }
| otherwise -> return False
@@ -3689,15 +3692,68 @@ tcConH98Args exp_kind (InfixCon bty1 bty2)
tcConH98Args exp_kind (RecCon fields)
= tcRecConDeclFields exp_kind fields
-tcConGADTArgs :: ContextKind -- expected kind of arguments
- -- always OpenKind for datatypes, but unlifted newtypes
- -- might have a specific kind
- -> HsConDeclGADTDetails GhcRn
- -> TcM [(Scaled TcType, HsSrcBang)]
-tcConGADTArgs exp_kind (PrefixConGADT btys)
- = mapM (tcConArg exp_kind) btys
-tcConGADTArgs exp_kind (RecConGADT fields _)
- = tcRecConDeclFields exp_kind fields
+tcConGadtSigBody :: [LocatedN Name]
+ -> NewOrData
+ -> DataDeclInfo
+ -> [TcTyConBinder]
+ -> ConGadtSigBody GhcRn
+ -> TcM ([(Scaled TcType, HsSrcBang)], TcType)
+tcConGadtSigBody names new_or_data dd_info tc_bndrs body =
+ case body of
+ PrefixConGADT btys ->
+ tcPrefixConGadtSigBody names new_or_data dd_info tc_bndrs btys
+ RecConGADT fields _ res_ty -> do
+ -- See Note [GADT return kinds]
+ (tc_res_ty, tc_res_kind) <- tcConGadtResTy names dd_info tc_bndrs res_ty
+ -- See Note [Datatype return kinds]
+ let exp_kind = getArgExpKind new_or_data tc_res_kind
+ tc_arg_tys <- tcRecConDeclFields exp_kind fields
+ pure (tc_arg_tys, tc_res_ty)
+
+tcPrefixConGadtSigBody :: [LocatedN Name]
+ -> NewOrData
+ -> DataDeclInfo
+ -> [TcTyConBinder]
+ -> PrefixConGadtSigBody GhcRn
+ -> TcM ([(Scaled TcType, HsSrcBang)], TcType)
+tcPrefixConGadtSigBody names new_or_data dd_info tc_bndrs prefix_body = do
+ (tc_arg_tys, tc_res_ty, _) <- go prefix_body
+ pure (tc_arg_tys, tc_res_ty)
+ where
+ go :: PrefixConGadtSigBody GhcRn
+ -> TcM ([(Scaled TcType, HsSrcBang)], TcType, TcKind)
+ go (PCGSRes res_ty) = do
+ (tc_res_ty, tc_res_kind) <- tcConGadtResTy names dd_info tc_bndrs res_ty
+ pure ([], tc_res_ty, tc_res_kind)
+ go (PCGSAnonArg arg_ty body) = do
+ (tc_arg_tys, tc_res_ty, tc_res_kind) <- go body
+ -- See Note [Datatype return kinds]
+ let exp_kind = getArgExpKind new_or_data tc_res_kind
+ tc_arg_ty <- tcConArg exp_kind arg_ty
+ pure (tc_arg_ty:tc_arg_tys, tc_res_ty, tc_res_kind)
+
+tcConGadtResTy :: [LocatedN Name]
+ -> DataDeclInfo
+ -> [TcTyConBinder]
+ -> LHsType GhcRn -> TcM (TcType, TcKind)
+tcConGadtResTy names dd_info tc_bndrs res_ty = do
+ -- See Note [GADT return kinds]
+ res@(tc_res_ty, _tc_res_kind) <- tcInferLHsTypeKind res_ty
+
+ -- For data instances (only), ensure that the return type,
+ -- res_ty, is a substitution instance of the header.
+ -- See Note [GADT return types]
+ case dd_info of
+ DDataType -> return ()
+ DDataInstance hdr_ty ->
+ do { (subst, _meta_tvs) <- newMetaTyVars (binderVars tc_bndrs)
+ ; let head_shape = substTy subst hdr_ty
+ ; discardResult $
+ popErrCtxt $ -- Drop dataConCtxt
+ addErrCtxt (dataConResCtxt names) $
+ unifyType Nothing tc_res_ty head_shape }
+
+ pure res
tcConArg :: ContextKind -- expected kind for args; always OpenKind for datatypes,
-- but might be an unlifted type with UnliftedNewtypes
@@ -3712,15 +3768,22 @@ tcConArg exp_kind (HsScaled w bty)
tcRecConDeclFields :: ContextKind
-> LocatedL [LConDeclField GhcRn]
-> TcM [(Scaled TcType, HsSrcBang)]
-tcRecConDeclFields exp_kind fields
- = mapM (tcConArg exp_kind) btys
+tcRecConDeclFields exp_kind (L _ fields)
+ = concatMapM tc_field fields
where
- -- We need a one-to-one mapping from field_names to btys
- combined = map (\(L _ f) -> (cd_fld_names f,hsLinear (cd_fld_type f)))
- (unLoc fields)
- explode (ns,ty) = zip ns (repeat ty)
- exploded = concatMap explode combined
- (_,btys) = unzip exploded
+ -- We need to ensure that each distinct field name gets its own type.
+ -- For example, if we have:
+ --
+ -- data T = MkT { a,b,c :: Int }
+ --
+ -- Then we should return /three/ Int types, not just one! At the same
+ -- time, we don't want to kind-check Int three separate times, as that
+ -- would be redundant. Therefore, we kind-check Int once and 'replicate'
+ -- it so that we return three occurrences of it.
+ tc_field :: LConDeclField GhcRn -> TcM [(Scaled TcType, HsSrcBang)]
+ tc_field (L _ f) = do
+ bty' <- tcConArg exp_kind $ hsLinear $ cd_fld_type f
+ pure $ replicate (length (cd_fld_names f)) bty'
tcDataConMult :: HsArrow GhcRn -> TcM Mult
tcDataConMult arr@(HsUnrestrictedArrow _) = do