import HsSyn ( TyClDecl(..), HsConDetails(..), HsTyVarBndr(..),
ConDecl(..), Sig(..), BangType(..), HsBang(..),
- tyClDeclTyVars, getBangType, getBangStrictness,
+ tyClDeclTyVars, getBangType, getBangStrictness, isSynDecl,
LTyClDecl, tcdName, LHsTyVarBndr
)
import BasicTypes ( RecFlag(..), NewOrData(..), StrictnessMark(..) )
import TcRnMonad
import TcEnv ( TcTyThing(..), TyThing(..),
tcLookupLocated, tcLookupLocatedGlobal,
- tcExtendGlobalEnv,
+ tcExtendGlobalEnv, tcExtendKindEnv,
tcExtendRecEnv, tcLookupTyVar )
-import TcTyDecls ( calcTyConArgVrcs, calcRecFlags, calcCycleErrs )
+import TcTyDecls ( calcTyConArgVrcs, calcRecFlags, calcClassCycles, calcSynCycles )
import TcClassDcl ( tcClassSigs, tcAddDeclCtxt )
-import TcHsType ( kcHsTyVars, kcHsLiftedSigType, kcHsSigType, kcCheckHsType,
+import TcHsType ( kcHsTyVars, kcHsLiftedSigType, kcHsSigType, kcHsType,
kcHsContext, tcTyVarBndrs, tcHsKindedType, tcHsKindedContext )
import TcMType ( newKindVar, checkValidTheta, checkValidType, checkFreeness,
UserTypeCtxt(..), SourceTyCtxt(..) )
import DataCon ( DataCon, dataConWrapId, dataConName, dataConSig, dataConFieldLabels )
import Var ( TyVar, idType, idName )
import VarSet ( elemVarSet )
-import Name ( Name, getSrcLoc )
+import Name ( Name )
import Outputable
import Util ( zipLazy, isSingleton, notNull )
-import SrcLoc ( srcLocSpan, Located(..), unLoc )
+import List ( partition )
+import SrcLoc ( Located(..), unLoc, getLoc )
import ListSetOps ( equivClasses )
+import Digraph ( SCC(..) )
import CmdLineOpts ( DynFlag( Opt_GlasgowExts, Opt_Generics, Opt_UnboxStrictFields ) )
\end{code}
-- See notes with checkCycleErrs
checkCycleErrs decls
- ; let { udecls = map unLoc decls }
- ; tyclss <- fixM (\ rec_tyclss ->
- do { lcl_things <- mappM getInitialKind udecls
- -- Extend the local env with kinds, and
- -- the global env with the knot-tied results
- ; let { gbl_things = mkGlobalThings udecls rec_tyclss }
- ; tcExtendRecEnv gbl_things lcl_things $ do
-
- -- The local type environment is populated with
- -- {"T" -> ARecTyCon k, ...}
- -- and the global type envt with
- -- {"T" -> ATyCon T, ...}
- -- where k is T's (unzonked) kind
- -- T is the loop-tied TyCon itself
- -- We must populate the environment with the loop-tied T's right
- -- away, because the kind checker may "fault in" some type
- -- constructors that recursively mention T
-
- -- Kind-check the declarations, returning kind-annotated decls
- { kc_decls <- mappM kcTyClDecl decls
-
- -- Calculate variances and rec-flag
- ; let { calc_vrcs = calcTyConArgVrcs rec_tyclss
- ; calc_rec = calcRecFlags rec_tyclss }
-
- ; mappM (tcTyClDecl calc_vrcs calc_rec) kc_decls
- }})
+ ; (syn_tycons, alg_tyclss) <- fixM (\ ~(rec_syn_tycons, rec_alg_tyclss) ->
+ do { let { -- Calculate variances and rec-flag
+ ; (syn_decls, alg_decls) = partition (isSynDecl . unLoc) decls }
+
+ -- Extend the global env with the knot-tied results
+ -- for data types and classes
+ --
+ -- We must populate the environment with the loop-tied T's right
+ -- away, because the kind checker may "fault in" some type
+ -- constructors that recursively mention T
+ ; let { gbl_things = mkGlobalThings alg_decls rec_alg_tyclss }
+ ; tcExtendRecEnv gbl_things $ do
+
+ -- Kind-check the declarations
+ { (kc_syn_decls, kc_alg_decls) <- kcTyClDecls syn_decls alg_decls
+
+ ; let { calc_vrcs = calcTyConArgVrcs (rec_syn_tycons ++ rec_alg_tyclss)
+ ; calc_rec = calcRecFlags rec_alg_tyclss
+ ; tc_decl = addLocM (tcTyClDecl calc_vrcs calc_rec) }
+ -- Type-check the type synonyms, and extend the envt
+ ; syn_tycons <- tcSynDecls calc_vrcs kc_syn_decls
+ ; tcExtendGlobalEnv syn_tycons $ do
+
+ -- Type-check the data types and classes
+ { alg_tyclss <- mappM tc_decl kc_alg_decls
+ ; return (syn_tycons, alg_tyclss)
+ }}})
-- Finished with knot-tying now
-- Extend the environment with the finished things
- ; tcExtendGlobalEnv tyclss $ do
+ ; tcExtendGlobalEnv (syn_tycons ++ alg_tyclss) $ do
-- Perform the validity check
{ traceTc (text "ready for validity check")
- ; mappM_ checkValidTyCl decls
+ ; mappM_ (addLocM checkValidTyCl) decls
; traceTc (text "done")
-- Add the implicit things;
-- we want them in the environment because
-- they may be mentioned in interface files
- ; let { implicit_things = concatMap implicitTyThings tyclss }
- ; traceTc ((text "Adding" <+> ppr tyclss) $$ (text "and" <+> ppr implicit_things))
+ ; let { implicit_things = concatMap implicitTyThings alg_tyclss }
+ ; traceTc ((text "Adding" <+> ppr alg_tyclss) $$ (text "and" <+> ppr implicit_things))
; tcExtendGlobalEnv implicit_things getGblEnv
}}
-mkGlobalThings :: [TyClDecl Name] -- The decls
+mkGlobalThings :: [LTyClDecl Name] -- The decls
-> [TyThing] -- Knot-tied, in 1-1 correspondence with the decls
-> [(Name,TyThing)]
-- Driven by the Decls, and treating the TyThings lazily
mkGlobalThings decls things
= map mk_thing (decls `zipLazy` things)
where
- mk_thing (ClassDecl {tcdLName = L _ name}, ~(AClass cl))
+ mk_thing (L _ (ClassDecl {tcdLName = L _ name}), ~(AClass cl))
= (name, AClass cl)
- mk_thing (decl, ~(ATyCon tc))
+ mk_thing (L _ decl, ~(ATyCon tc))
= (tcdName decl, ATyCon tc)
\end{code}
depends on *all the uses of class D*. For example, the use of
Monad c in bop's type signature means that D must have kind Type->Type.
-\begin{code}
-------------------------------------------------------------------------
-getInitialKind :: TyClDecl Name -> TcM (Name, TcTyThing)
-
--- Note the lazy pattern match on the ATyCon etc
--- Exactly the same reason as the zipLay above
-
-getInitialKind (TyData {tcdLName = L _ name})
- = newKindVar `thenM` \ kind ->
- returnM (name, ARecTyCon kind)
-
-getInitialKind (TySynonym {tcdLName = L _ name})
- = newKindVar `thenM` \ kind ->
- returnM (name, ARecTyCon kind)
-
-getInitialKind (ClassDecl {tcdLName = L _ name})
- = newKindVar `thenM` \ kind ->
- returnM (name, ARecClass kind)
+However type synonyms work differently. They can have kinds which don't
+just involve (->) and *:
+ type R = Int# -- Kind #
+ type S a = Array# a -- Kind * -> #
+ type T a b = (# a,b #) -- Kind * -> * -> (# a,b #)
+So we must infer their kinds from their right-hand sides *first* and then
+use them, whereas for the mutually recursive data types D we bring into
+scope kind bindings D -> k, where k is a kind variable, and do inference.
+\begin{code}
+kcTyClDecls syn_decls alg_decls
+ = do { -- First extend the kind env with each data
+ -- type and class, mapping them to a type variable
+ alg_kinds <- mappM getInitialKind alg_decls
+ ; tcExtendKindEnv alg_kinds $ do
+
+ -- Now kind-check the type synonyms, in dependency order
+ -- We do these differently to data type and classes,
+ -- because a type synonym can be an unboxed type
+ -- type Foo = Int#
+ -- and a kind variable can't unify with UnboxedTypeKind
+ -- So we infer their kinds in dependency order
+ { (kc_syn_decls, syn_kinds) <- kcSynDecls (calcSynCycles syn_decls)
+ ; tcExtendKindEnv syn_kinds $ do
+
+ -- Now kind-check the data type and class declarations,
+ -- returning kind-annotated decls
+ { kc_alg_decls <- mappM (wrapLocM kcTyClDecl) alg_decls
+
+ ; return (kc_syn_decls, kc_alg_decls) }}}
------------------------------------------------------------------------
-kcTyClDecl :: LTyClDecl Name -> TcM (LTyClDecl Name)
+getInitialKind :: LTyClDecl Name -> TcM (Name, TcKind)
+
+getInitialKind decl
+ = newKindVar `thenM` \ kind ->
+ returnM (unLoc (tcdLName (unLoc decl)), kind)
+
+----------------
+kcSynDecls :: [SCC (LTyClDecl Name)]
+ -> TcM ([LTyClDecl Name], -- Kind-annotated decls
+ [(Name,TcKind)]) -- Kind bindings
+kcSynDecls []
+ = return ([], [])
+kcSynDecls (group : groups)
+ = do { (decl, nk) <- kcSynDecl group
+ ; (decls, nks) <- tcExtendKindEnv [nk] (kcSynDecls groups)
+ ; return (decl:decls, nk:nks) }
+
+----------------
+kcSynDecl :: SCC (LTyClDecl Name)
+ -> TcM (LTyClDecl Name, -- Kind-annotated decls
+ (Name,TcKind)) -- Kind bindings
+kcSynDecl (AcyclicSCC ldecl@(L loc decl))
+ = tcAddDeclCtxt decl $
+ kcHsTyVars (tcdTyVars decl) (\ k_tvs ->
+ do { traceTc (text "kcd1" <+> ppr (unLoc (tcdLName decl)) <+> brackets (ppr (tcdTyVars decl))
+ <+> brackets (ppr k_tvs))
+ ; (k_rhs, rhs_kind) <- kcHsType (tcdSynRhs decl)
+ ; traceTc (text "kcd2" <+> ppr (unLoc (tcdLName decl)))
+ ; let tc_kind = foldr (mkArrowKind . kindedTyVarKind) rhs_kind k_tvs
+ ; return (L loc (decl { tcdTyVars = k_tvs, tcdSynRhs = k_rhs }),
+ (unLoc (tcdLName decl), tc_kind)) })
+
+kcSynDecl (CyclicSCC decls)
+ = do { recSynErr decls; failM } -- Fail here to avoid error cascade
+ -- of out-of-scope tycons
-kcTyClDecl decl@(L loc d@(TySynonym {tcdSynRhs = rhs}))
- = do { res_kind <- newKindVar
- ; kcTyClDeclBody decl res_kind $ \ tvs' ->
- do { rhs' <- kcCheckHsType rhs res_kind
- ; return (L loc d{tcdTyVars = tvs', tcdSynRhs = rhs'}) } }
+------------------------------------------------------------------------
+kcTyClDecl :: TyClDecl Name -> TcM (TyClDecl Name)
+ -- Not used for type synonyms (see kcSynDecl)
-kcTyClDecl decl@(L loc d@(TyData {tcdND = new_or_data, tcdCtxt = ctxt, tcdCons = cons}))
- = kcTyClDeclBody decl liftedTypeKind $ \ tvs' ->
+kcTyClDecl decl@(TyData {tcdND = new_or_data, tcdCtxt = ctxt, tcdCons = cons})
+ = kcTyClDeclBody decl $ \ tvs' ->
do { ctxt' <- kcHsContext ctxt
; cons' <- mappM (wrapLocM kc_con_decl) cons
- ; return (L loc d{tcdTyVars = tvs', tcdCtxt = ctxt', tcdCons = cons'}) }
+ ; return (decl {tcdTyVars = tvs', tcdCtxt = ctxt', tcdCons = cons'}) }
where
kc_con_decl (ConDecl name ex_tvs ex_ctxt details)
= kcHsTyVars ex_tvs $ \ ex_tvs' ->
-- Can't allow an unlifted type for newtypes, because we're effectively
-- going to remove the constructor while coercing it to a lifted type.
-kcTyClDecl decl@(L loc d@(ClassDecl {tcdCtxt = ctxt, tcdSigs = sigs}))
- = kcTyClDeclBody decl liftedTypeKind $ \ tvs' ->
+kcTyClDecl decl@(ClassDecl {tcdCtxt = ctxt, tcdSigs = sigs})
+ = kcTyClDeclBody decl $ \ tvs' ->
do { ctxt' <- kcHsContext ctxt
; sigs' <- mappM (wrapLocM kc_sig) sigs
- ; return (L loc d{tcdTyVars = tvs', tcdCtxt = ctxt', tcdSigs = sigs'}) }
+ ; return (decl {tcdTyVars = tvs', tcdCtxt = ctxt', tcdSigs = sigs'}) }
where
kc_sig (Sig nm op_ty) = do { op_ty' <- kcHsLiftedSigType op_ty
; return (Sig nm op_ty') }
kc_sig other_sig = return other_sig
-kcTyClDecl decl@(L _ (ForeignType {}))
+kcTyClDecl decl@(ForeignType {})
= return decl
-kcTyClDeclBody :: LTyClDecl Name -> TcKind
+kcTyClDeclBody :: TyClDecl Name
-> ([LHsTyVarBndr Name] -> TcM a)
-> TcM a
-- Extend the env with bindings for the tyvars, taken from
-- the kind of the tycon/class. Give it to the thing inside, and
-- check the result kind matches
-kcTyClDeclBody decl res_kind thing_inside
+kcTyClDeclBody decl thing_inside
= tcAddDeclCtxt decl $
- kcHsTyVars (tyClDeclTyVars (unLoc decl)) $ \ kinded_tvs ->
- do { tc_ty_thing <- tcLookupLocated (tcdLName (unLoc decl))
- ; let { tc_kind = case tc_ty_thing of
- ARecClass k -> k
- ARecTyCon k -> k
- }
+ kcHsTyVars (tyClDeclTyVars decl) $ \ kinded_tvs ->
+ do { tc_ty_thing <- tcLookupLocated (tcdLName decl)
+ ; let tc_kind = case tc_ty_thing of { AThing k -> k }
; unifyKind tc_kind (foldr (mkArrowKind . kindedTyVarKind)
- res_kind kinded_tvs)
+ liftedTypeKind kinded_tvs)
; thing_inside kinded_tvs }
kindedTyVarKind (L _ (KindedTyVar _ k)) = k
%************************************************************************
\begin{code}
+tcSynDecls :: (Name -> ArgVrcs) -> [LTyClDecl Name] -> TcM [TyThing]
+tcSynDecls calc_vrcs [] = return []
+tcSynDecls calc_vrcs (decl : decls)
+ = do { syn_tc <- addLocM (tcSynDecl calc_vrcs) decl
+ ; syn_tcs <- tcExtendGlobalEnv [syn_tc] (tcSynDecls calc_vrcs decls)
+ ; return (syn_tc : syn_tcs) }
+
+tcSynDecl calc_vrcs
+ (TySynonym {tcdLName = L _ tc_name, tcdTyVars = tvs, tcdSynRhs = rhs_ty})
+ = tcTyVarBndrs tvs $ \ tvs' -> do
+ { traceTc (text "tcd1" <+> ppr tc_name)
+ ; rhs_ty' <- tcHsKindedType rhs_ty
+ ; return (ATyCon (buildSynTyCon tc_name tvs' rhs_ty' (calc_vrcs tc_name))) }
+
+--------------------
tcTyClDecl :: (Name -> ArgVrcs) -> (Name -> RecFlag)
- -> LTyClDecl Name -> TcM TyThing
+ -> TyClDecl Name -> TcM TyThing
tcTyClDecl calc_vrcs calc_isrec decl
- = tcAddDeclCtxt decl (tcTyClDecl1 calc_vrcs calc_isrec (unLoc decl))
-
-tcTyClDecl1 calc_vrcs calc_isrec
- (TySynonym {tcdLName = L _ tc_name, tcdTyVars = tvs, tcdSynRhs = rhs_ty})
- = tcTyVarBndrs tvs $ \ tvs' -> do
- { rhs_ty' <- tcHsKindedType rhs_ty
- ; return (ATyCon (buildSynTyCon tc_name tvs' rhs_ty' arg_vrcs)) }
- where
- arg_vrcs = calc_vrcs tc_name
+ = tcAddDeclCtxt decl (tcTyClDecl1 calc_vrcs calc_isrec decl)
tcTyClDecl1 calc_vrcs calc_isrec
(TyData {tcdND = new_or_data, tcdCtxt = ctxt, tcdTyVars = tvs,
\begin{code}
checkCycleErrs :: [LTyClDecl Name] -> TcM ()
checkCycleErrs tyclss
- | null syn_cycles && null cls_cycles
+ | null cls_cycles
= return ()
| otherwise
- = do { mappM_ recSynErr syn_cycles
- ; mappM_ recClsErr cls_cycles
+ = do { mappM_ recClsErr cls_cycles
; failM } -- Give up now, because later checkValidTyCl
-- will loop if the synonym is recursive
where
- (syn_cycles, cls_cycles) = calcCycleErrs tyclss
+ cls_cycles = calcClassCycles tyclss
-checkValidTyCl :: LTyClDecl Name -> TcM ()
+checkValidTyCl :: TyClDecl Name -> TcM ()
-- We do the validity check over declarations, rather than TyThings
-- only so that we can add a nice context with tcAddDeclCtxt
checkValidTyCl decl
= tcAddDeclCtxt decl $
- do { thing <- tcLookupLocatedGlobal (tcdLName (unLoc decl))
+ do { thing <- tcLookupLocatedGlobal (tcdLName decl)
; traceTc (text "Validity of" <+> ppr thing)
; case thing of
ATyCon tc -> checkValidTyCon tc
4 (vcat [ppr op <+> dcolon <+> ppr op_ty,
ptext SLIT("You can only use type variables, arrows, and tuples")])
-recSynErr tcs
- = addSrcSpan (srcLocSpan (getSrcLoc (head tcs))) $
+recSynErr syn_decls
+ = addSrcSpan (getLoc (head syn_decls)) $
addErr (sep [ptext SLIT("Cycle in type synonym declarations:"),
- nest 2 (vcat (map ppr_thing tcs))])
+ nest 2 (vcat (map ppr_decl syn_decls))])
+ where
+ ppr_decl (L loc decl) = ppr loc <> colon <+> ppr decl
-recClsErr clss
- = addSrcSpan (srcLocSpan (getSrcLoc (head clss))) $
+recClsErr cls_decls
+ = addSrcSpan (getLoc (head cls_decls)) $
addErr (sep [ptext SLIT("Cycle in class declarations (via superclasses):"),
- nest 2 (vcat (map ppr_thing clss))])
-
-ppr_thing :: Name -> SDoc
-ppr_thing n = ppr n <+> parens (ppr (getSrcLoc n))
-
+ nest 2 (vcat (map ppr_decl cls_decls))])
+ where
+ ppr_decl (L loc decl) = ppr loc <> colon <+> ppr (decl { tcdSigs = [] })
exRecConErr name
= ptext SLIT("Can't combine named fields with locally-quantified type variables")