[project @ 2001-10-23 22:25:46 by sof]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcMonad.lhs
index 4d38539..41f0890 100644 (file)
@@ -1,9 +1,7 @@
 \begin{code}
 module TcMonad(
-       TcType, 
-       TcTauType, TcPredType, TcThetaType, TcRhoType,
-       TcTyVar, TcTyVarSet,
-       TcKind,
+       TcType, TcTauType, TcPredType, TcThetaType, TcRhoType,
+       TcTyVar, TcTyVarSet, TcKind,
 
        TcM, NF_TcM, TcDown, TcEnv, 
 
@@ -27,12 +25,12 @@ module TcMonad(
 
        tcGetEnv, tcSetEnv,
        tcGetDefaultTys, tcSetDefaultTys,
-       tcGetUnique, tcGetUniques, tcGetDFunUniq,
+       tcGetUnique, tcGetUniques, 
        doptsTc, getDOptsTc,
 
        tcAddSrcLoc, tcGetSrcLoc, tcGetInstLoc,
        tcAddErrCtxtM, tcSetErrCtxtM,
-       tcAddErrCtxt, tcSetErrCtxt,
+       tcAddErrCtxt, tcSetErrCtxt, tcPopErrCtxt,
 
        tcNewMutVar, tcNewSigTyVar, tcReadMutVar, tcWriteMutVar, TcRef,
        tcNewMutTyVar, tcReadMutTyVar, tcWriteMutTyVar,
@@ -47,9 +45,9 @@ module TcMonad(
 
 import {-# SOURCE #-} TcEnv  ( TcEnv )
 
-import RnHsSyn         ( RenamedPat, RenamedArithSeqInfo, RenamedHsExpr, RenamedHsOverLit )
-import Type            ( Type, Kind, PredType, ThetaType, RhoType, TauType,
-                       )
+import HsLit           ( HsOverLit )
+import RnHsSyn         ( RenamedPat, RenamedArithSeqInfo, RenamedHsExpr )
+import TcType          ( Type, Kind, PredType, ThetaType, TauType, RhoType )
 import ErrUtils                ( addShortErrLocLine, addShortWarnLocLine, ErrMsg, Message, WarnMsg )
 
 import Bag             ( Bag, emptyBag, isEmptyBag,
@@ -63,7 +61,6 @@ import UniqSupply     ( UniqSupply, uniqFromSupply, uniqsFromSupply,
                          splitUniqSupply, mkSplitUniqSupply,
                          UniqSM, initUs_ )
 import SrcLoc          ( SrcLoc, noSrcLoc )
-import FiniteMap       ( FiniteMap, lookupFM, addToFM, emptyFM )
 import UniqFM          ( emptyUFM )
 import Unique          ( Unique )
 import CmdLineOpts
@@ -94,11 +91,11 @@ type TcType = Type          -- A TcType can have mutable type variables
        -- a cannot occur inside a MutTyVar in T; that is,
        -- T is "flattened" before quantifying over a
 
-type TcPredType  = PredType
-type TcThetaType = ThetaType
-type TcRhoType   = RhoType
-type TcTauType   = TauType
-type TcKind      = TcType
+type TcPredType     = PredType
+type TcThetaType    = ThetaType
+type TcRhoType      = RhoType
+type TcTauType      = TauType
+type TcKind         = TcType
 \end{code}
 
 
@@ -131,14 +128,13 @@ initTc dflags tc_env do_this
   = do {
       us       <- mkSplitUniqSupply 'a' ;
       us_var   <- newIORef us ;
-      dfun_var <- newIORef emptyFM ;
       errs_var <- newIORef (emptyBag,emptyBag) ;
       tvs_var  <- newIORef emptyUFM ;
 
       let
-          init_down = TcDown dflags [] us_var dfun_var
-                            noSrcLoc
-                            [] errs_var
+          init_down = TcDown { tc_dflags = dflags, tc_def = [],
+                              tc_us = us_var, tc_loc = noSrcLoc,
+                              tc_ctxt = [], tc_errs = errs_var }
       ;
 
       maybe_res <- catch (do {  res <- do_this init_down tc_env ;
@@ -218,6 +214,12 @@ mapBagTc f bag
 fixTc    :: (a -> TcM a)    -> TcM a
 fixNF_Tc :: (a -> NF_TcM a) -> NF_TcM a
 fixTc m env down = fixIO (\ loop -> m loop env down)
+{-# NOINLINE fixTc #-}
+-- aargh!  Not inlining fixTc alleviates a space leak problem.
+-- Normally fixTc is used with a lazy tuple match: if the optimiser is
+-- shown the definition of fixTc, it occasionally transforms the code
+-- in such a way that the code generator doesn't spot the selector
+-- thunks.  Sigh.
 
 recoverTc    :: TcM r -> TcM r -> TcM r
 recoverNF_Tc :: NF_TcM r -> TcM r -> NF_TcM r
@@ -245,13 +247,13 @@ which is a Royal Pain.  By the time this fork stuff is used they'll
 have been unified down so there won't be any kind variables, but we
 can't express that in the current typechecker framework.
 
-So we compromise and use unsafeInterleaveSST.
+So we compromise and use unsafeInterleaveIO.
 
 We throw away any error messages!
 
 \begin{code}
 forkNF_Tc :: NF_TcM r -> NF_TcM r
-forkNF_Tc m (TcDown dflags deflts u_var df_var src_loc err_cxt err_var) env
+forkNF_Tc m down@(TcDown { tc_us = u_var }) env
   = do
        -- Get a fresh unique supply
        us <- readIORef u_var
@@ -261,8 +263,7 @@ forkNF_Tc m (TcDown dflags deflts u_var df_var src_loc err_cxt err_var) env
        unsafeInterleaveIO (do {
                us_var'  <- newIORef us2 ;
                err_var' <- newIORef (emptyBag,emptyBag) ;
-               tv_var'  <- newIORef emptyUFM ;
-               let { down' = TcDown dflags deflts us_var' df_var src_loc err_cxt err_var' } ;
+               let { down' = down { tc_us = us_var', tc_errs = err_var' } };
                m down' env
                        -- ToDo: optionally dump any error messages
                })
@@ -270,7 +271,9 @@ forkNF_Tc m (TcDown dflags deflts u_var df_var src_loc err_cxt err_var) env
 
 \begin{code}
 traceTc :: SDoc -> NF_TcM ()
-traceTc doc down env = printErrs doc
+traceTc doc (TcDown { tc_dflags=dflags }) env 
+  | dopt Opt_D_dump_tc_trace dflags = printDump doc
+  | otherwise                      = return ()
 
 ioToTc :: IO a -> NF_TcM a
 ioToTc io down env = io
@@ -292,7 +295,7 @@ failTc :: TcM a
 failTc down env = give_up
 
 give_up :: IO a
-give_up = IOERROR (userError "Typecheck failed")
+give_up = ioError (userError "Typecheck failed")
 
 failWithTc :: Message -> TcM a                 -- Add an error message and fail
 failWithTc err_msg = failWithTcM (emptyTidyEnv, err_msg)
@@ -388,6 +391,8 @@ tryTc recover main down env
        m_errs_var <- newIORef (emptyBag,emptyBag)
        catch (my_main m_errs_var) (\ _ -> my_recover m_errs_var)
   where
+    errs_var = getTcErrs down
+
     my_recover m_errs_var
       = do warns_and_errs <- readIORef m_errs_var
           recover warns_and_errs down env
@@ -400,7 +405,13 @@ tryTc recover main down env
                -- errors along the way.
            (m_warns, m_errs) <- readIORef m_errs_var
            if isEmptyBag m_errs then
-               return result
+               -- No errors, so return normally, but don't lose the warnings
+               if isEmptyBag m_warns then
+                  return result
+               else
+                  do (warns, errs) <- readIORef errs_var
+                     writeIORef errs_var (warns `unionBags` m_warns, errs)
+                     return result
              else
                give_up         -- This triggers the catch
 
@@ -518,6 +529,9 @@ tcSetErrCtxt, tcAddErrCtxt :: Message -> Either_TcM r -> Either_TcM r
 -- Usual thing
 tcSetErrCtxt msg m down env = m (setErrCtxt down (\env -> returnNF_Tc (env, msg))) env
 tcAddErrCtxt msg m down env = m (addErrCtxt down (\env -> returnNF_Tc (env, msg))) env
+
+tcPopErrCtxt :: Either_TcM r -> Either_TcM  r
+tcPopErrCtxt m down env = m (popErrCtxt down) env
 \end{code}
 
 
@@ -538,11 +552,11 @@ tcGetUnique down env
   where
     u_var = getUniqSupplyVar down
 
-tcGetUniques :: Int -> NF_TcM [Unique]
-tcGetUniques n down env
+tcGetUniques :: NF_TcM [Unique]
+tcGetUniques down env
   = do uniq_supply <- readIORef u_var
        let (new_uniq_supply, uniq_s) = splitUniqSupply uniq_supply
-           uniqs                     = uniqsFromSupply n uniq_s
+           uniqs                     = uniqsFromSupply uniq_s
        writeIORef u_var new_uniq_supply
        return uniqs
   where
@@ -559,20 +573,6 @@ uniqSMToTcM m down env
 \end{code}
 
 
-\begin{code}
-tcGetDFunUniq :: String -> NF_TcM Int
-tcGetDFunUniq key down env
-  = do dfun_supply <- readIORef d_var
-       let uniq = case lookupFM dfun_supply key of
-                     Just x  -> x+1
-                     Nothing -> 0
-       let dfun_supply' = addToFM dfun_supply key uniq
-       writeIORef d_var dfun_supply'
-       return uniq
-  where
-    d_var = getDFunSupplyVar down
-\end{code}
-
 
 %************************************************************************
 %*                                                                     *
@@ -585,11 +585,7 @@ data TcDown
    = TcDown {
         tc_dflags :: DynFlags,
        tc_def    :: [Type],                    -- Types used for defaulting
-
        tc_us     :: (TcRef UniqSupply),        -- Unique supply
-       tc_ds     :: (TcRef DFunNameSupply),    -- Name supply for 
-                                               -- dictionary function names
-
        tc_loc    :: SrcLoc,                    -- Source location
        tc_ctxt   :: ErrCtxt,                   -- Error context
        tc_errs   :: (TcRef (Bag WarnMsg, Bag ErrMsg))
@@ -599,19 +595,6 @@ type ErrCtxt = [TidyEnv -> NF_TcM (TidyEnv, Message)]
                        -- Innermost first.  Monadic so that we have a chance
                        -- to deal with bound type variables just before error
                        -- message construction
-
-type DFunNameSupply = FiniteMap String Int
-       -- This is used as a name supply for dictionary functions
-       -- From the inst decl we derive a string, usually by glomming together
-       -- the class and tycon name -- but it doesn't matter exactly how;
-       -- this map then gives a unique int for each inst decl with that
-       -- string.  (In Haskell 98 there can only be one,
-       -- but not so in more extended versions; also class CC type T
-       -- and class C type TT might both give the string CCT
-       --      
-       -- We could just use one Int for all the instance decls, but this
-       -- way the uniques change less when you add an instance decl,   
-       -- hence less recompilation
 \end{code}
 
 -- These selectors are *local* to TcMonad.lhs
@@ -627,12 +610,15 @@ getLoc (TcDown{tc_loc=loc}) = loc
 setLoc down loc = down{tc_loc=loc}
 
 getUniqSupplyVar (TcDown{tc_us=us}) = us
-getDFunSupplyVar (TcDown{tc_ds=ds}) = ds
 
 getErrCtxt (TcDown{tc_ctxt=ctxt}) = ctxt
 setErrCtxt down msg = down{tc_ctxt=[msg]}
 addErrCtxt down msg = down{tc_ctxt = msg : tc_ctxt down}
 
+popErrCtxt down = case tc_ctxt down of
+                       []     -> down
+                       m : ms -> down{tc_ctxt = ms}
+
 doptsTc :: DynFlag -> TcM Bool
 doptsTc dflag (TcDown{tc_dflags=dflags}) env_down
    = return (dopt dflag dflags)
@@ -693,13 +679,16 @@ type InstLoc = (InstOrigin, SrcLoc, ErrCtxt)
 data InstOrigin
   = OccurrenceOf Id            -- Occurrence of an overloaded identifier
 
+  | IPOcc Name                 -- Occurrence of an implicit parameter
+  | IPBind Name                        -- Binding site of an implicit parameter
+
   | RecordUpdOrigin
 
   | DataDeclOrigin             -- Typechecking a data declaration
 
   | InstanceDeclOrigin         -- Typechecking an instance decl
 
-  | LiteralOrigin RenamedHsOverLit     -- Occurrence of a literal
+  | LiteralOrigin HsOverLit    -- Occurrence of a literal
 
   | PatOrigin RenamedPat
 
@@ -744,12 +733,16 @@ pprInstLoc (orig, locn, ctxt)
   where
     pp_orig (OccurrenceOf id)
        = hsep [ptext SLIT("use of"), quotes (ppr id)]
+    pp_orig (IPOcc name)
+       = hsep [ptext SLIT("use of implicit parameter"), quotes (char '?' <> ppr name)]
+    pp_orig (IPBind name)
+       = hsep [ptext SLIT("binding for implicit parameter"), quotes (char '?' <> ppr name)]
     pp_orig (LiteralOrigin lit)
        = hsep [ptext SLIT("the literal"), quotes (ppr lit)]
     pp_orig (PatOrigin pat)
        = hsep [ptext SLIT("the pattern"), quotes (ppr pat)]
     pp_orig (InstanceDeclOrigin)
-       =  ptext SLIT("an instance declaration")
+       =  ptext SLIT("the instance declaration")
     pp_orig (ArithSeqOrigin seq)
        = hsep [ptext SLIT("the arithmetic sequence"), quotes (ppr seq)]
     pp_orig (SignatureOrigin)