Reorganisation of the source tree
[ghc-hetmet.git] / ghc / compiler / typecheck / TcTyDecls.lhs
diff --git a/ghc/compiler/typecheck/TcTyDecls.lhs b/ghc/compiler/typecheck/TcTyDecls.lhs
deleted file mode 100644 (file)
index 4ce5fed..0000000
+++ /dev/null
@@ -1,473 +0,0 @@
-%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1999
-%
-
-Analysis functions over data types.  Specficially
-       a) detecting recursive types
-       b) computing argument variances
-
-This stuff is only used for source-code decls; it's recorded in interface
-files for imported data types.
-
-
-\begin{code}
-module TcTyDecls(
-        calcTyConArgVrcs,
-       calcRecFlags, 
-       calcClassCycles, calcSynCycles
-    ) where
-
-#include "HsVersions.h"
-
-import TypeRep          ( Type(..), TyNote(..), PredType(..) )  -- friend
-import HsSyn           ( TyClDecl(..), HsPred(..), LTyClDecl, isClassDecl )
-import RnHsSyn         ( extractHsTyNames )
-import Type            ( predTypeRep, tcView )
-import HscTypes                ( TyThing(..), ModDetails(..) )
-import TyCon            ( TyCon, ArgVrcs, tyConArity, tyConDataCons, tyConTyVars,
-                          synTyConDefn, isSynTyCon, isAlgTyCon, 
-                         tyConName, isNewTyCon, isProductTyCon, tyConArgVrcs, newTyConRhs )
-import Class           ( classTyCon )
-import DataCon          ( dataConOrigArgTys )
-import Var              ( TyVar )
-import VarSet
-import Name            ( Name, isTyVarName )
-import NameEnv
-import NameSet
-import Digraph                 ( SCC(..), stronglyConnComp, stronglyConnCompR )
-import BasicTypes      ( RecFlag(..) )
-import SrcLoc          ( Located(..), unLoc )
-import Outputable
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-       Cycles in class and type synonym declarations
-%*                                                                     *
-%************************************************************************
-
-Checking for class-decl loops is easy, because we don't allow class decls
-in interface files.
-
-We allow type synonyms in hi-boot files, but we *trust* hi-boot files, 
-so we don't check for loops that involve them.  So we only look for synonym
-loops in the module being compiled.
-
-We check for type synonym and class cycles on the *source* code.
-Main reasons: 
-
-  a) Otherwise we'd need a special function to extract type-synonym tycons
-       from a type, whereas we have extractHsTyNames already
-
-  b) If we checked for type synonym loops after building the TyCon, we
-       can't do a hoistForAllTys on the type synonym rhs, (else we fall into
-       a black hole) which seems unclean.  Apart from anything else, it'd mean 
-       that a type-synonym rhs could have for-alls to the right of an arrow, 
-       which means adding new cases to the validity checker
-
-       Indeed, in general, checking for cycles beforehand means we need to
-       be less careful about black holes through synonym cycles.
-
-The main disadvantage is that a cycle that goes via a type synonym in an 
-.hi-boot file can lead the compiler into a loop, because it assumes that cycles
-only occur entirely within the source code of the module being compiled.  
-But hi-boot files are trusted anyway, so this isn't much worse than (say) 
-a kind error.
-
-[  NOTE ----------------------------------------------
-If we reverse this decision, this comment came from tcTyDecl1, and should
- go back there
-       -- dsHsType, not tcHsKindedType, to avoid a loop.  tcHsKindedType does hoisting,
-       -- which requires looking through synonyms... and therefore goes into a loop
-       -- on (erroneously) recursive synonyms.
-       -- Solution: do not hoist synonyms, because they'll be hoisted soon enough
-       --           when they are substituted
-
-We'd also need to add back in this definition
-
-synTyConsOfType :: Type -> [TyCon]
--- Does not look through type synonyms at all
--- Return a list of synonym tycons
-synTyConsOfType ty
-  = nameEnvElts (go ty)
-  where
-     go :: Type -> NameEnv TyCon  -- The NameEnv does duplicate elim
-     go (TyVarTy v)              = emptyNameEnv
-     go (TyConApp tc tys)        = go_tc tc tys
-     go (AppTy a b)              = go a `plusNameEnv` go b
-     go (FunTy a b)              = go a `plusNameEnv` go b
-     go (PredTy (IParam _ ty))    = go ty      
-     go (PredTy (ClassP cls tys)) = go_s tys   -- Ignore class
-     go (NoteTy _ ty)            = go ty       
-     go (ForAllTy _ ty)                  = go ty
-
-     go_tc tc tys | isSynTyCon tc = extendNameEnv (go_s tys) (tyConName tc) tc
-                 | otherwise     = go_s tys
-     go_s tys = foldr (plusNameEnv . go) emptyNameEnv tys
----------------------------------------- END NOTE ]
-
-\begin{code}
-calcSynCycles :: [LTyClDecl Name] -> [SCC (LTyClDecl Name)]
-calcSynCycles decls
-  = stronglyConnComp syn_edges
-  where
-    syn_edges = [ (ldecl, unLoc (tcdLName decl), 
-                         mk_syn_edges (tcdSynRhs decl))
-               | ldecl@(L _ decl) <- decls ]
-
-    mk_syn_edges rhs = [ tc | tc <- nameSetToList (extractHsTyNames rhs), 
-                             not (isTyVarName tc) ]
-
-
-calcClassCycles :: [LTyClDecl Name] -> [[LTyClDecl Name]]
-calcClassCycles decls
-  = [decls | CyclicSCC decls <- stronglyConnComp cls_edges]
-  where
-    cls_edges = [ (ldecl, unLoc (tcdLName decl),       
-                         mk_cls_edges (unLoc (tcdCtxt decl)))
-               | ldecl@(L _ decl) <- decls, isClassDecl decl ]
-
-    mk_cls_edges ctxt = [ cls | L _ (HsClassP cls _) <- ctxt ]
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-       Deciding which type constructors are recursive
-%*                                                                     *
-%************************************************************************
-
-For newtypes, we label some as "recursive" such that
-
-    INVARIANT: there is no cycle of non-recursive newtypes
-
-In any loop, only one newtype need be marked as recursive; it is
-a "loop breaker".  Labelling more than necessary as recursive is OK,
-provided the invariant is maintained.
-
-A newtype M.T is defined to be "recursive" iff
-       (a) it is declared in an hi-boot file (see RdrHsSyn.hsIfaceDecl)
-       (b) it is declared in a source file, but that source file has a
-           companion hi-boot file which declares the type
-   or  (c) one can get from T's rhs to T via type 
-           synonyms, or non-recursive newtypes *in M*
-            e.g.  newtype T = MkT (T -> Int)
-
-(a) is conservative; declarations in hi-boot files are always 
-       made loop breakers. That's why in (b) we can restrict attention
-       to tycons in M, because any loops through newtypes outside M
-       will be broken by those newtypes
-(b) ensures that a newtype is not treated as a loop breaker in one place
-and later as a non-loop-breaker.  This matters in GHCi particularly, when
-a newtype T might be embedded in many types in the environment, and then
-T's source module is compiled.  We don't want T's recursiveness to change.
-
-The "recursive" flag for algebraic data types is irrelevant (never consulted)
-for types with more than one constructor.
-
-An algebraic data type M.T is "recursive" iff
-       it has just one constructor, and 
-       (a) it is declared in an hi-boot file (see RdrHsSyn.hsIfaceDecl)
-       (b) it is declared in a source file, but that source file has a
-           companion hi-boot file which declares the type
- or    (c) one can get from its arg types to T via type synonyms, 
-           or by non-recursive newtypes or non-recursive product types in M
-            e.g.  data T = MkT (T -> Int) Bool
-Just like newtype in fact
-
-A type synonym is recursive if one can get from its
-right hand side back to it via type synonyms.  (This is
-reported as an error.)
-
-A class is recursive if one can get from its superclasses
-back to it.  (This is an error too.)
-
-Hi-boot types
-~~~~~~~~~~~~~
-A data type read from an hi-boot file will have an AbstractTyCon as its AlgTyConRhs
-and will respond True to isHiBootTyCon. The idea is that we treat these as if one
-could get from these types to anywhere.  So when we see
-
-       module Baz where
-       import {-# SOURCE #-} Foo( T )
-       newtype S = MkS T
-
-then we mark S as recursive, just in case. What that means is that if we see
-
-       import Baz( S )
-       newtype R = MkR S
-
-then we don't need to look inside S to compute R's recursiveness.  Since S is imported
-(not from an hi-boot file), one cannot get from R back to S except via an hi-boot file,
-and that means that some data type will be marked recursive along the way.  So R is
-unconditionly non-recursive (i.e. there'll be a loop breaker elsewhere if necessary)
-
-This in turn means that we grovel through fewer interface files when computing 
-recursiveness, because we need only look at the type decls in the module being
-compiled, plus the outer structure of directly-mentioned types.
-
-\begin{code}
-calcRecFlags :: ModDetails -> [TyThing] -> (Name -> RecFlag)
--- The 'boot_names' are the things declared in M.hi-boot, if M is the current module.
--- Any type constructors in boot_names are automatically considered loop breakers
-calcRecFlags boot_details tyclss
-  = is_rec
-  where
-    is_rec n | n `elemNameSet` rec_names = Recursive
-            | otherwise                 = NonRecursive
-
-    boot_name_set = md_exports boot_details
-    rec_names = boot_name_set    `unionNameSets` 
-               nt_loop_breakers  `unionNameSets`
-               prod_loop_breakers
-
-    all_tycons = [ tc | tycls <- tyclss,
-                          -- Recursion of newtypes/data types can happen via 
-                          -- the class TyCon, so tyclss includes the class tycons
-                       let tc = getTyCon tycls,
-                       not (tyConName tc `elemNameSet` boot_name_set) ]
-                          -- Remove the boot_name_set because they are going 
-                          -- to be loop breakers regardless.
-
-       -------------------------------------------------
-       --                      NOTE
-       -- These edge-construction loops rely on
-       -- every loop going via tyclss, the types and classes
-       -- in the module being compiled.  Stuff in interface 
-       -- files should be correctly marked.  If not (e.g. a
-       -- type synonym in a hi-boot file) we can get an infinite
-       -- loop.  We could program round this, but it'd make the code
-       -- rather less nice, so I'm not going to do that yet.
-
-       --------------- Newtypes ----------------------
-    new_tycons = filter isNewTyCon all_tycons
-    nt_loop_breakers = mkNameSet (findLoopBreakers nt_edges)
-    is_rec_nt tc = tyConName tc  `elemNameSet` nt_loop_breakers
-       -- is_rec_nt is a locally-used helper function
-
-    nt_edges = [(t, mk_nt_edges t) | t <- new_tycons]
-
-    mk_nt_edges nt     -- Invariant: nt is a newtype
-       = concatMap (mk_nt_edges1 nt) (tcTyConsOfType (new_tc_rhs nt))
-                       -- tyConsOfType looks through synonyms
-
-    mk_nt_edges1 nt tc 
-       | tc `elem` new_tycons = [tc]           -- Loop
-               -- At this point we know that either it's a local *data* type,
-               -- or it's imported.  Either way, it can't form part of a newtype cycle
-       | otherwise = []
-
-       --------------- Product types ----------------------
-       -- The "prod_tycons" are the non-newtype products
-    prod_tycons = [tc | tc <- all_tycons, 
-                       not (isNewTyCon tc), isProductTyCon tc]
-    prod_loop_breakers = mkNameSet (findLoopBreakers prod_edges)
-
-    prod_edges = [(tc, mk_prod_edges tc) | tc <- prod_tycons]
-       
-    mk_prod_edges tc   -- Invariant: tc is a product tycon
-       = concatMap (mk_prod_edges1 tc) (dataConOrigArgTys (head (tyConDataCons tc)))
-
-    mk_prod_edges1 ptc ty = concatMap (mk_prod_edges2 ptc) (tcTyConsOfType ty)
-
-    mk_prod_edges2 ptc tc 
-       | tc `elem` prod_tycons   = [tc]                -- Local product
-       | tc `elem` new_tycons    = if is_rec_nt tc     -- Local newtype
-                                   then []
-                                   else mk_prod_edges1 ptc (new_tc_rhs tc)
-               -- At this point we know that either it's a local non-product data type,
-               -- or it's imported.  Either way, it can't form part of a cycle
-       | otherwise = []
-                       
-new_tc_rhs tc = snd (newTyConRhs tc)   -- Ignore the type variables
-
-getTyCon (ATyCon tc) = tc
-getTyCon (AClass cl) = classTyCon cl
-
-findLoopBreakers :: [(TyCon, [TyCon])] -> [Name]
--- Finds a set of tycons that cut all loops
-findLoopBreakers deps
-  = go [(tc,tc,ds) | (tc,ds) <- deps]
-  where
-    go edges = [ name
-              | CyclicSCC ((tc,_,_) : edges') <- stronglyConnCompR edges,
-                name <- tyConName tc : go edges']
-\end{code}
-
-These two functions know about type representations, so they could be
-in Type or TcType -- but they are very specialised to this module, so 
-I've chosen to put them here.
-
-\begin{code}
-tcTyConsOfType :: Type -> [TyCon]
--- tcTyConsOfType looks through all synonyms, but not through any newtypes.  
--- When it finds a Class, it returns the class TyCon.  The reaons it's here
--- (not in Type.lhs) is because it is newtype-aware.
-tcTyConsOfType ty 
-  = nameEnvElts (go ty)
-  where
-     go :: Type -> NameEnv TyCon  -- The NameEnv does duplicate elim
-     go ty | Just ty' <- tcView ty = go ty'
-     go (TyVarTy v)               = emptyNameEnv
-     go (TyConApp tc tys)         = go_tc tc tys
-     go (AppTy a b)               = go a `plusNameEnv` go b
-     go (FunTy a b)               = go a `plusNameEnv` go b
-     go (PredTy (IParam _ ty))     = go ty
-     go (PredTy (ClassP cls tys))  = go_tc (classTyCon cls) tys
-     go (ForAllTy _ ty)                   = go ty
-
-     go_tc tc tys = extendNameEnv (go_s tys) (tyConName tc) tc
-     go_s tys = foldr (plusNameEnv . go) emptyNameEnv tys
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-       Compuing TyCon argument variances
-%*                                                                     *
-%************************************************************************
-
-Computing the tyConArgVrcs info
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-@tyConArgVrcs@ gives a list of (occPos,occNeg) flags, one for each
-tyvar.  For @AlgTyCon@s and @SynTyCon@s, this info must be precomputed
-separately.  Note that this is information about occurrences of type
-variables, not usages of term variables.
-
-The function @calcTyConArgVrcs@ must be passed a list of *algebraic or
-syntycons only* such that all tycons referred to (by mutual recursion)
-appear in the list.  The fixpointing will be done on this set of
-tycons as a whole.  It returns a list of @tyconVrcInfo@ data, ready to
-be (knot-tyingly?) stuck back into the appropriate fields.
-
-\begin{code}
-calcTyConArgVrcs :: [TyThing] -> Name -> ArgVrcs
--- Gives arg variances for TyCons, 
--- including the class TyCon of a class
-calcTyConArgVrcs tyclss
-  = get_vrc
-  where
-    tycons = map getTyCon tyclss
-
-       -- We should only look up things that are in the map
-    get_vrc n = case lookupNameEnv final_oi n of
-                 Just (_, pms) -> pms
-                 Nothing -> pprPanic "calcVrcs" (ppr n)
-
-       -- We are going to fold over this map,
-       -- so we need the TyCon in the range
-    final_oi :: NameEnv (TyCon, ArgVrcs)
-    final_oi = tcaoFix initial_oi
-
-    initial_oi :: NameEnv (TyCon, ArgVrcs)
-    initial_oi = mkNameEnv [(tyConName tc, (tc, initial tc))
-                          | tc <- tycons]
-    initial tc = replicate (tyConArity tc) (False,False)
-
-    tcaoFix :: NameEnv (TyCon, ArgVrcs)   -- initial ArgVrcs per tycon
-           -> NameEnv (TyCon, ArgVrcs)   -- fixpointed ArgVrcs per tycon
-    tcaoFix oi 
-       | changed   = tcaoFix oi'
-       | otherwise = oi'
-       where
-        (changed,oi') = foldNameEnv iterate (False,oi) oi
-
-    iterate (tc, pms) (changed,oi')
-      =        (changed || (pms /= pms'),
-        extendNameEnv oi' (tyConName tc) (tc, pms'))
-      where
-       pms' = tcaoIter oi' tc  -- seq not simult
-
-    tcaoIter :: NameEnv (TyCon, ArgVrcs)  -- reference ArgVrcs (initial)
-            -> TyCon                     -- tycon to update
-            -> ArgVrcs                   -- new ArgVrcs for tycon
-
-    tcaoIter oi tc | isAlgTyCon tc
-      = map (\v -> anyVrc (vrcInTy (lookup oi) v) argtys) vs
-      where
-               data_cons = tyConDataCons tc
-               vs        = tyConTyVars tc
-               argtys    = concatMap dataConOrigArgTys data_cons       -- Rep? or Orig?
-
-    tcaoIter oi tc | isSynTyCon tc
-      = let (tyvs,ty) = synTyConDefn tc
-                        -- we use the already-computed result for tycons not in this SCC
-        in  map (\v -> vrcInTy (lookup oi) v ty) tyvs
-
-    lookup oi tc = case lookupNameEnv oi (tyConName tc) of
-                       Just (_, pms) -> pms
-                       Nothing       -> tyConArgVrcs tc
-        -- We use the already-computed result for tycons not in this SCC
-\end{code}
-
-
-Variance of tyvars in a type
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A general variance-check function.  We pass a function for determining
-the @ArgVrc@s of a tycon; when fixpointing this refers to the current
-value; otherwise this should be looked up from the tycon's own
-tyConArgVrcs.  Again, it knows the representation of Types.
-
-\begin{code}
-vrcInTy :: (TyCon -> ArgVrcs)  -- function to get argVrcs of a tycon (break out of recursion)
-        -> TyVar               -- tyvar to check Vrcs of
-        -> Type                -- type to check for occ in
-        -> (Bool,Bool)         -- (occurs positively, occurs negatively)
-
-vrcInTy fao v (NoteTy (FTVNote ftv) ty) = if elemVarSet v ftv
-                                         then vrcInTy fao v ty
-                                         else (False,False)
-                       -- note that ftv cannot be calculated as occPos||occNeg,
-                       -- since if a tyvar occurs only as unused tyconarg,
-                       -- occPos==occNeg==False, but ftv=True
-
-vrcInTy fao v (TyVarTy v')              = if v==v'
-                                         then (True,False)
-                                         else (False,False)
-
-vrcInTy fao v (AppTy ty1 ty2)           = if vrcInTy fao v ty2 /= (False,False)
-                                          then (True,True)
-                                          else vrcInTy fao v ty1
-                        -- ty1 is probably unknown (or it would have been beta-reduced);
-                        -- hence if v occurs in ty2 at all then it could occur with
-                        -- either variance.  Otherwise it occurs as it does in ty1.
-
-vrcInTy fao v (FunTy ty1 ty2)           = negVrc (vrcInTy fao v ty1)
-                                          `orVrc`
-                                          vrcInTy fao v ty2
-                                        
-vrcInTy fao v (ForAllTy v' ty)          = if v==v'
-                                         then (False,False)
-                                         else vrcInTy fao v ty
-
-vrcInTy fao v (TyConApp tc tys)         = let pms1 = map (vrcInTy fao v) tys
-                                             pms2 = fao tc
-                                         in  orVrcs (zipWith timesVrc pms1 pms2)
-
-vrcInTy fao v (PredTy st) = vrcInTy fao v (predTypeRep st)
-\end{code}
-
-Variance algebra
-~~~~~~~~~~~~~~~~
-
-\begin{code}
-orVrc :: (Bool,Bool) -> (Bool,Bool) -> (Bool,Bool)
-orVrc (p1,m1) (p2,m2) = (p1||p2,m1||m2)
-
-orVrcs :: [(Bool,Bool)] -> (Bool,Bool)
-orVrcs = foldl orVrc (False,False)
-
-negVrc :: (Bool,Bool) -> (Bool,Bool)
-negVrc (p1,m1) = (m1,p1)
-
-anyVrc :: (a -> (Bool,Bool)) -> [a] -> (Bool,Bool)
-anyVrc p as = foldl (\ pm a -> pm `orVrc` p a)
-                    (False,False) as
-
-timesVrc :: (Bool,Bool) -> (Bool,Bool) -> (Bool,Bool)
-timesVrc (p1,m1) (p2,m2) = (p1 && p2 || m1 && m2,
-                           p1 && m2 || m1 && p2)
-\end{code}