isIfaceSigDecl, isClassDecl, isSynDecl, isClassOpSig
)
import RnHsSyn ( RenamedTyClDecl, tyClDeclFVs )
-import BasicTypes ( RecFlag(..), NewOrData(..), isRec )
+import BasicTypes ( RecFlag(..), NewOrData(..) )
import HscTypes ( implicitTyThingIds )
+import Module ( Module )
import TcMonad
import TcEnv ( TcEnv, RecTcEnv, TcTyThing(..), TyThing(..), TyThingDetails(..),
- tcExtendKindEnv, tcLookup, tcExtendGlobalEnv, tcExtendGlobalValEnv )
-import TcTyDecls ( tcTyDecl1, kcConDetails )
-import TcClassDcl ( tcClassDecl1 )
+ tcExtendKindEnv, tcLookup, tcExtendGlobalEnv, tcExtendGlobalValEnv,
+ isLocalThing )
+import TcTyDecls ( tcTyDecl, kcConDetails, checkValidTyCon )
+import TcClassDcl ( tcClassDecl1, checkValidClass )
import TcInstDcls ( tcAddDeclCtxt )
import TcMonoType ( kcHsTyVars, kcHsType, kcHsLiftedSigType, kcHsContext, mkTyClTyVars )
-import TcMType ( unifyKind, newKindVar, zonkKindEnv )
-import TcType ( Type, Kind, mkArrowKind, liftedTypeKind, zipFunTys )
+import TcMType ( newKindVar, zonkKindEnv )
+import TcUnify ( unifyKind )
+import TcType ( Type, Kind, TcKind, mkArrowKind, liftedTypeKind, zipFunTys )
+import Type ( splitTyConApp_maybe )
import Variance ( calcTyConArgVrcs )
import Class ( Class, mkClass, classTyCon )
import TyCon ( TyCon, ArgVrcs, AlgTyConFlavour(..),
- tyConKind, tyConDataCons,
+ tyConKind, tyConTyVars, tyConDataCons, isNewTyCon,
mkSynTyCon, mkAlgTyCon, mkClassTyCon, mkForeignTyCon,
- isRecursiveTyCon )
+ )
+import TysWiredIn ( unitTy )
+import Subst ( substTyWith )
import DataCon ( dataConOrigArgTys )
import Var ( varName )
import FiniteMap
~~~~~~~~~~~~~~~~~
\begin{code}
tcTyAndClassDecls :: RecTcEnv -- Knot tying stuff
+ -> Module -- Current module
-> [RenamedTyClDecl]
-> TcM TcEnv
-tcTyAndClassDecls unf_env decls
+tcTyAndClassDecls unf_env this_mod decls
= sortByDependency decls `thenTc` \ groups ->
- tcGroups unf_env groups
+ tcGroups unf_env this_mod groups
-tcGroups unf_env []
+tcGroups unf_env this_mod []
= tcGetEnv `thenNF_Tc` \ env ->
returnTc env
-tcGroups unf_env (group:groups)
- = tcGroup unf_env group `thenTc` \ env ->
- tcSetEnv env $
- tcGroups unf_env groups
+tcGroups unf_env this_mod (group:groups)
+ = tcGroup unf_env this_mod group `thenTc` \ env ->
+ tcSetEnv env $
+ tcGroups unf_env this_mod groups
\end{code}
Dealing with a group
to tcTyClDecl1.
-Step 6: tcTyClDecl1 again
- For a recursive group only, check all the decls again, just
- but this time with the wimp flag off. Now we can check things
- like whether a function argument is an unlifted tuple, looking
- through type synonyms properly. We can't do that in Step 5.
-
-Step 7: Extend environment
+Step 6: Extend environment
We extend the type environment with bindings not only for the TyCons and Classes,
but also for their "implicit Ids" like data constructors and class selectors
+Step 7: checkValidTyCl
+ For a recursive group only, check all the decls again, just
+ to check all the side conditions on validity. We could not
+ do this before because we were in a mutually recursive knot.
+
+
The knot-tying parameters: @rec_details_list@ is an alist mapping @Name@s to
@TyThing@s. @rec_vrcs@ is a finite map from @Name@s to @ArgVrcs@s.
\begin{code}
-tcGroup :: RecTcEnv -> SCC RenamedTyClDecl -> TcM TcEnv
-tcGroup unf_env scc
- = getDOptsTc `thenTc` \ dflags ->
+tcGroup :: RecTcEnv -> Module -> SCC RenamedTyClDecl -> TcM TcEnv
+tcGroup unf_env this_mod scc
+ = getDOptsTc `thenNF_Tc` \ dflags ->
-- Step 1
mapNF_Tc getInitialKind decls `thenNF_Tc` \ initial_kinds ->
rec_vrcs = calcTyConArgVrcs [tc | ATyCon tc <- all_tyclss]
in
-- Step 5
- tcExtendGlobalEnv all_tyclss $
- mapTc (tcTyClDecl1 is_rec unf_env) decls `thenTc` \ tycls_details ->
+ -- Extend the environment with the final
+ -- TyCons/Classes and check the decls
+ tcExtendGlobalEnv all_tyclss $
+ mapTc (tcTyClDecl1 unf_env) decls `thenTc` \ tycls_details ->
- -- Return results
- tcGetEnv `thenNF_Tc` \ env ->
- returnTc (tycls_details, all_tyclss, env)
- ) `thenTc` \ (_, all_tyclss, env) ->
+ -- Step 6
+ -- Extend the environment with implicit Ids
+ tcExtendGlobalValEnv (implicitTyThingIds all_tyclss) $
- tcSetEnv env $
+ -- Return results
+ tcGetEnv `thenNF_Tc` \ env ->
+ returnTc (tycls_details, tyclss, env)
+ ) `thenTc` \ (_, tyclss, env) ->
- traceTc (text "ready for pass 2" <+> ppr (isRec is_rec)) `thenTc_`
- -- Step 6
- -- For a recursive group, check all the types again,
- -- this time with the wimp flag off
- (if isRec is_rec then
- mapTc_ (tcTyClDecl1 NonRecursive unf_env) decls
- else
- returnTc ()
+ -- Step 7: Check validity
+ traceTc (text "ready for validity check") `thenTc_`
+ tcSetEnv env (
+ mapTc_ (checkValidTyCl this_mod) decls
) `thenTc_`
-
traceTc (text "done") `thenTc_`
-
- -- Step 7
- -- Extend the environment with the final TyCons/Classes
- -- and their implicit Ids
- tcExtendGlobalValEnv (implicitTyThingIds all_tyclss) tcGetEnv
+
+ returnTc env
where
is_rec = case scc of
AcyclicSCC decl -> [decl]
CyclicSCC decls -> decls
-tcTyClDecl1 is_rec unf_env decl
- | isClassDecl decl = tcAddDeclCtxt decl (tcClassDecl1 is_rec unf_env decl)
- | otherwise = tcAddDeclCtxt decl (tcTyDecl1 is_rec unf_env decl)
+tcTyClDecl1 unf_env decl
+ | isClassDecl decl = tcAddDeclCtxt decl (tcClassDecl1 unf_env decl)
+ | otherwise = tcAddDeclCtxt decl (tcTyDecl unf_env decl)
+
+checkValidTyCl this_mod decl
+ = tcLookup (tcdName decl) `thenNF_Tc` \ (AGlobal thing) ->
+ if not (isLocalThing this_mod thing) then
+ -- Don't bother to check validity for non-local things
+ returnTc ()
+ else
+ tcAddDeclCtxt decl $
+ case thing of
+ ATyCon tc -> checkValidTyCon tc
+ AClass cl -> checkValidClass cl
\end{code}
\end{code}
+
%************************************************************************
%* *
\subsection{Step 4: Building the tycon/class}
\begin{code}
mkNewTyConRep :: TyCon -- The original type constructor
-> Type -- Chosen representation type
+ -- (guaranteed not to be another newtype)
+
-- Find the representation type for this newtype TyCon
--- See notes on newypes in types/TypeRep about newtypes.
-mkNewTyConRep tc = head (dataConOrigArgTys (head (tyConDataCons tc)))
+--
+-- The non-recursive newtypes are easy, because they look transparent
+-- to splitTyConApp_maybe, but recursive ones really are represented as
+-- TyConApps (see TypeRep).
+--
+-- The trick is to to deal correctly with recursive newtypes
+-- such as newtype T = MkT T
+
+mkNewTyConRep tc
+ = go [] tc
+ where
+ -- Invariant: tc is a NewTyCon
+ -- tcs have been seen before
+ go tcs tc
+ | tc `elem` tcs = unitTy
+ | otherwise
+ = let
+ rep_ty = head (dataConOrigArgTys (head (tyConDataCons tc)))
+ in
+ case splitTyConApp_maybe rep_ty of
+ Nothing -> rep_ty
+ Just (tc', tys) | not (isNewTyCon tc') -> rep_ty
+ | otherwise -> go1 (tc:tcs) tc' tys
+
+ go1 tcs tc tys = substTyWith (tyConTyVars tc) tys (go tcs tc)
\end{code}
-
%************************************************************************
%* *
\subsection{Dependency analysis}