[project @ 1998-05-04 20:56:54 by sof]
[ghc-hetmet.git] / ghc / compiler / typecheck / TcEnv.lhs
index c2b831d..06f17d3 100644 (file)
 \begin{code}
-#include "HsVersions.h"
-
 module TcEnv(
-       TcEnv, 
+       TcIdOcc(..), TcIdBndr, tcIdType, tcIdTyVars, tcInstId,
+
+       TcEnv, GlobalValueEnv,
 
        initEnv, getEnv_LocalIds, getEnv_TyCons, getEnv_Classes,
        
-       tcExtendKindEnv, tcExtendTyVarEnv, tcExtendTyConEnv, tcExtendClassEnv,
-       tcLookupTyVar, tcLookupTyCon, tcLookupClass, tcLookupClassByKey,
+       tcExtendTyVarEnv, tcLookupTyVar, 
 
-       tcExtendGlobalValEnv, tcExtendLocalValEnv,
-       tcLookupLocalValue, tcLookupLocalValueOK,
-       tcLookupGlobalValue, tcLookupGlobalValueByKey,
+       tcExtendTyConEnv, tcLookupTyCon, tcLookupTyConByKey, 
+       tcExtendClassEnv, tcLookupClass, tcLookupClassByKey,
+       tcGetTyConsAndClasses,
 
-       tcTyVarScope, newMonoIds, newLocalIds,
-       tcGetGlobalTyVars
-  ) where
+       tcExtendGlobalValEnv, tcExtendLocalValEnv, tcGetGlobalValEnv, tcSetGlobalValEnv,
+       tcLookupLocalValue, tcLookupLocalValueOK, tcLookupLocalValueByKey, 
+       tcLookupGlobalValue, tcLookupGlobalValueByKey, tcLookupGlobalValueMaybe,
+       tcAddImportedIdInfo, tcExplicitLookupGlobal,
+       tcLookupGlobalValueByKeyMaybe, 
 
+       newMonoIds, newLocalIds, newLocalId, newSpecPragmaId,
+       tcGetGlobalTyVars, tcExtendGlobalTyVars
+  ) where
 
-import Ubiq
-import TcMLoop  -- for paranoia checking
+#include "HsVersions.h"
 
-import Id      ( Id(..), GenId, idType, mkUserLocal )
-import TcHsSyn ( TcIdBndr(..) )
-import TcKind  ( TcKind, newKindVars, tcKindToKind, kindToTcKind )
-import TcType  ( TcType(..), TcMaybe, TcTyVar(..), TcTyVarSet(..), newTyVarTys, zonkTcTyVars )
-import TyVar   ( mkTyVar, getTyVarKind, unionTyVarSets, emptyTyVarSet )
-import Type    ( tyVarsOfTypes )
-import TyCon   ( TyCon, getTyConKind )
-import Class   ( Class(..), GenClass, getClassSig )
+import MkId    ( mkUserLocal, mkUserId, mkSpecPragmaId )
+import Id      ( Id, GenId, idType, replaceIdInfo, idInfo )
+import TcKind  ( TcKind, kindToTcKind, Kind )
+import TcType  ( TcType, TcMaybe, TcTyVar, TcTyVarSet, TcThetaType,
+                 newTyVarTys, tcInstTyVars, zonkTcTyVars, tcInstType
+               )
+import TyVar   ( mkTyVarSet, unionTyVarSets, emptyTyVarSet, TyVar )
+import Type    ( tyVarsOfType, tyVarsOfTypes, splitForAllTys, splitRhoTy )
+import TyCon   ( TyCon, tyConKind, tyConArity, isSynTyCon, Arity )
+import Class   ( Class )
 
 import TcMonad
 
-import Name    ( Name(..), getNameShortName )
-import PprStyle
-import Pretty
-import Unique  ( Unique )
-import UniqFM
-import Util    ( zipWithEqual, zipWith3Equal, zipLazy, panic )
+import IdInfo          ( noIdInfo )
+import Name            ( Name, OccName(..), nameOccName,
+                         maybeWiredInTyConName, maybeWiredInIdName, isLocallyDefined,
+                         NamedThing(..)
+                       )
+import Unique          ( pprUnique10{-, pprUnique ToDo:rm-}, Unique, Uniquable(..) )
+import UniqFM       
+import Util            ( zipEqual, zipWithEqual, zipWith3Equal )
+import Maybes          ( maybeToBool )
+import Outputable
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection{TcId, TcIdOcc}
+%*                                                                     *
+%************************************************************************
+
+
+\begin{code}
+type TcIdBndr s = GenId  (TcType s)    -- Binders are all TcTypes
+data TcIdOcc  s = TcId   (TcIdBndr s)  -- Bindees may be either
+               | RealId Id
+
+instance Eq (TcIdOcc s) where
+  (TcId id1)   == (TcId id2)   = id1 == id2
+  (RealId id1) == (RealId id2) = id1 == id2
+  _           == _            = False
+
+instance Ord (TcIdOcc s) where
+  (TcId id1)   `compare` (TcId id2)   = id1 `compare` id2
+  (RealId id1) `compare` (RealId id2) = id1 `compare` id2
+  (TcId _)     `compare` (RealId _)   = LT
+  (RealId _)   `compare` (TcId _)     = GT
+
+instance Outputable (TcIdOcc s) where
+  ppr (TcId id)   = ppr id
+  ppr (RealId id) = ppr id
+
+instance NamedThing (TcIdOcc s) where
+  getName (TcId id)   = getName id
+  getName (RealId id) = getName id
+
+
+tcIdType :: TcIdOcc s -> TcType s
+tcIdType (TcId   id) = idType id
+tcIdType (RealId id) = pprPanic "tcIdType:" (ppr id)
+
+tcIdTyVars (TcId id)  = tyVarsOfType (idType id)
+tcIdTyVars (RealId _) = emptyTyVarSet          -- Top level Ids have no free type variables
+
+
+-- A useful function that takes an occurrence of a global thing
+-- and instantiates its type with fresh type variables
+tcInstId :: Id
+        -> NF_TcM s ([TcTyVar s],      -- It's instantiated type
+                     TcThetaType s,    --
+                     TcType s)         --
+
+tcInstId id
+  = let
+      (tyvars, rho) = splitForAllTys (idType id)
+    in
+    tcInstTyVars tyvars                `thenNF_Tc` \ (tyvars', arg_tys, tenv) ->
+    tcInstType tenv rho                `thenNF_Tc` \ rho' ->
+    let
+       (theta', tau') = splitRhoTy rho'
+    in
+    returnNF_Tc (tyvars', theta', tau')
 \end{code}
 
+
+%************************************************************************
+%*                                                                     *
+\subsection{TcEnv}
+%*                                                                     *
+%************************************************************************
+
 Data type declarations
 ~~~~~~~~~~~~~~~~~~~~~
 
 \begin{code}
 data TcEnv s = TcEnv
                  (TyVarEnv s)
-                 (ValueEnv Id)                 -- Globals
+                 (TyConEnv s)
+                 (ClassEnv s)
+                 GlobalValueEnv
                  (ValueEnv (TcIdBndr s))       -- Locals
-                 (MutableVar s (TcTyVarSet s)) -- Free type variables of locals
+                 (TcRef s (TcTyVarSet s))      -- Free type variables of locals
                                                -- ...why mutable? see notes with tcGetGlobalTyVars
-                 (KindEnv s)                   -- Gives TcKinds of TyCons and Classes
-                 TyConEnv
-                 ClassEnv
 
 type TyVarEnv s  = UniqFM (TcKind s, TyVar)
-type TyConEnv    = UniqFM TyCon
-type KindEnv s   = UniqFM (TcKind s)
-type ClassEnv    = UniqFM Class
+type TyConEnv s  = UniqFM (TcKind s, Maybe Arity, TyCon)       -- Arity present for Synonyms only
+type ClassEnv s  = UniqFM ([TcKind s], Class)          -- The kinds are the kinds of the args
+                                                       -- to the class
 type ValueEnv id = UniqFM id
+type GlobalValueEnv = ValueEnv Id                      -- Globals
 
-initEnv :: MutableVar s (TcTyVarSet s) -> TcEnv s
-initEnv mut = TcEnv emptyUFM emptyUFM emptyUFM mut emptyUFM emptyUFM emptyUFM 
+initEnv :: TcRef s (TcTyVarSet s) -> TcEnv s
+initEnv mut = TcEnv emptyUFM emptyUFM emptyUFM emptyUFM emptyUFM mut 
 
-getEnv_LocalIds (TcEnv _ _ ls _ _ _ _) = ls
-getEnv_TyCons   (TcEnv _ _ _ _ _ ts _) = ts
-getEnv_Classes  (TcEnv _ _ _ _ _ _ cs) = cs
+getEnv_LocalIds (TcEnv _ _ _ _ ls _) = eltsUFM ls
+getEnv_TyCons   (TcEnv _ ts _ _ _ _) = [tycon | (_, _, tycon) <- eltsUFM ts]
+getEnv_Classes  (TcEnv _ _ cs _ _ _) = [clas  | (_, clas)     <- eltsUFM cs]
 \end{code}
 
-Making new TcTyVars, with knot tying!
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Type variable env
+~~~~~~~~~~~~~~~~~
 \begin{code}
-tcTyVarScope :: [Name]                 -- Names of some type variables
-            -> ([TyVar] -> TcM s a)    -- Thing to type check in their scope
-            -> TcM s a                 -- Result
-
-tcTyVarScope tyvar_names thing_inside
-  = newKindVars (length tyvar_names)   `thenNF_Tc` \ tyvar_kinds ->
-
-    fixTc (\ ~(tyvars, _) ->
-               -- Ok to look at kinds, but not tyvars!
-      tcExtendTyVarEnv tyvar_names (tyvar_kinds `zipLazy` tyvars) (
-
-               -- Do the thing inside
-       thing_inside tyvars                     `thenTc` \ result ->
-               -- Get the tyvar's Kinds from their TcKinds
-       mapNF_Tc tcKindToKind tyvar_kinds       `thenNF_Tc` \ tyvar_kinds' ->
-
-               -- Construct the real TyVars
-       let
-         tyvars             = zipWithEqual mk_tyvar tyvar_names tyvar_kinds'
-         mk_tyvar name kind = mkTyVar (getNameShortName name) (getItsUnique name) kind
-       in
-       returnTc (tyvars, result)
-    ))                                 `thenTc` \ (_,result) ->
-    returnTc result
+tcExtendTyVarEnv :: [Name] -> [(TcKind s, TyVar)] -> TcM s r -> TcM s r
+tcExtendTyVarEnv names kinds_w_types scope
+  = tcGetEnv                                   `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+    let
+       tve' = addListToUFM tve (zipEqual "tcTyVarScope" names kinds_w_types)
+    in
+    tcSetEnv (TcEnv tve' tce ce gve lve gtvs) scope
 \end{code}
 
-
 The Kind, TyVar, Class and TyCon envs
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Extending the environments
+Extending the environments. 
 
 \begin{code}
-tcExtendKindEnv :: [Name] -> [TcKind s] -> TcM s r -> TcM s r
-tcExtendKindEnv names kinds scope
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
-    let
-       ke' = addListToUFM ke (names `zip` kinds)
-    in
-    tcSetEnv (TcEnv tve gve lve gtvs ke' tce ce) scope
+tcExtendTyConEnv :: [(Name, (TcKind s, Maybe Arity, TyCon))] -> TcM s r -> TcM s r
 
-tcExtendTyVarEnv :: [Name] -> [(TcKind s, TyVar)] -> TcM s r -> TcM s r
-tcExtendTyVarEnv tyvar_names kinds_w_tyvars scope
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
+tcExtendTyConEnv bindings scope
+  = tcGetEnv                                   `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
     let
-       tve' = addListToUFM tve (tyvar_names `zip` kinds_w_tyvars)
+       tce' = addListToUFM tce bindings
     in
-    tcSetEnv (TcEnv tve' gve lve gtvs ke tce ce) scope
+    tcSetEnv (TcEnv tve tce' ce gve lve gtvs) scope
 
-tcExtendTyConEnv tycons scope
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
-    let
-       tce' = addListToUFM_Directly tce [(getItsUnique tycon, tycon) | tycon <- tycons]
-    in
-    tcSetEnv (TcEnv tve gve lve gtvs ke tce' ce) scope
 
-tcExtendClassEnv classes scope
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
+tcExtendClassEnv :: [(Name, ([TcKind s], Class))] -> TcM s r -> TcM s r
+tcExtendClassEnv bindings scope
+  = tcGetEnv                           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
     let
-       ce' = addListToUFM_Directly ce [(getItsUnique clas, clas) | clas <- classes]
+       ce' = addListToUFM ce bindings
     in
-    tcSetEnv (TcEnv tve gve lve gtvs ke tce ce') scope
+    tcSetEnv (TcEnv tve tce ce' gve lve gtvs) scope
 \end{code}
 
 
-Looking up in the environments
+Looking up in the environments.
 
 \begin{code}
 tcLookupTyVar name
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
-    returnNF_Tc (lookupWithDefaultUFM tve (panic "tcLookupTyVar") name)
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+    returnNF_Tc (lookupWithDefaultUFM tve (pprPanic "tcLookupTyVar:" (ppr name)) name)
 
 
-tcLookupTyCon (WiredInTyCon tc)                -- wired in tycons
-  = returnNF_Tc (kindToTcKind (getTyConKind tc), tc)
-
 tcLookupTyCon name
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
-    let
-       tycon = lookupWithDefaultUFM tce (panic "tcLookupTyCon")             name
-       kind  = lookupWithDefaultUFM ke  (kindToTcKind (getTyConKind tycon)) name
-               -- The KE will bind tycon in the current mutually-recursive set.
-               -- If the KE doesn't, then the tycon is already defined, and we
-               -- can safely grab the kind from the TyCon itself
+  =    -- Try for a wired-in tycon
+    case maybeWiredInTyConName name of {
+       Just tc | isSynTyCon tc -> returnTc (kind, Just (tyConArity tc), tc)
+               | otherwise     -> returnTc (kind, Nothing,              tc)
+               where {
+                 kind = kindToTcKind (tyConKind tc) 
+               };
+
+       Nothing -> 
+
+           -- Try in the environment
+         tcGetEnv      `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+          case lookupUFM tce name of {
+             Just stuff -> returnTc stuff;
+
+             Nothing    ->
+
+               -- Could be that he's using a class name as a type constructor
+              case lookupUFM ce name of
+                Just _  -> failWithTc (classAsTyConErr name)
+                Nothing -> pprPanic "tcLookupTyCon:" (ppr name)
+           } } 
+
+tcLookupTyConByKey uniq
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+    let 
+       (kind, arity, tycon) =  lookupWithDefaultUFM_Directly tce 
+                                       (pprPanic "tcLookupTyConByKey:" (pprUnique10 uniq)) 
+                                       uniq
     in
-    returnNF_Tc (kind,tycon)
-
+    returnNF_Tc tycon
 
 tcLookupClass name
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
-    let
-       clas = lookupWithDefaultUFM ce (panic "tcLookupClass")             name
-       (tyvar, _, _) = getClassSig clas
-       kind = lookupWithDefaultUFM ke (kindToTcKind (getTyVarKind tyvar)) name
-    in
-    returnNF_Tc (kind,clas)
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+    case lookupUFM ce name of
+       Just stuff         -- Common case: it's ok
+         -> returnTc stuff
+
+       Nothing            -- Could be that he's using a type constructor as a class
+         |  maybeToBool (maybeWiredInTyConName name)
+         || maybeToBool (lookupUFM tce name)
+         -> failWithTc (tyConAsClassErr name)
+
+         | otherwise      -- Wierd!  Renamer shouldn't let this happen
+         -> pprPanic "tcLookupClass" (ppr name)
 
 tcLookupClassByKey uniq
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
     let
-       clas = lookupWithDefaultUFM_Directly ce (panic "tcLookupClas") uniq
+       (kind, clas) = lookupWithDefaultUFM_Directly ce 
+                               (pprPanic "tcLookupClassByKey:" (pprUnique10 uniq))
+                               uniq
     in
-    returnNF_Tc (clas)
+    returnNF_Tc clas
+
+tcGetTyConsAndClasses :: NF_TcM s ([TyCon], [Class])
+tcGetTyConsAndClasses
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+    returnNF_Tc ([tc | (_, _, tc) <- eltsUFM tce],
+                [c  | (_, c)     <- eltsUFM ce])
 \end{code}
 
 
@@ -183,23 +258,23 @@ Extending and consulting the value environment
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 \begin{code}
 tcExtendGlobalValEnv ids scope
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
     let
-       gve' = addListToUFM_Directly gve [(getItsUnique id, id) | id <- ids]
+       gve' = addListToUFM_Directly gve [(uniqueOf id, id) | id <- ids]
     in
-    tcSetEnv (TcEnv tve gve' lve gtvs ke tce ce) scope
+    tcSetEnv (TcEnv tve tce ce gve' lve gtvs) scope
 
 tcExtendLocalValEnv names ids scope
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
     tcReadMutVar gtvs  `thenNF_Tc` \ global_tvs ->
     let
-       lve' = addListToUFM lve (names `zip` ids)
+       lve' = addListToUFM lve (zipEqual "tcExtendLocalValEnv" names ids)
        extra_global_tyvars = tyVarsOfTypes (map idType ids)
        new_global_tyvars   = global_tvs `unionTyVarSets` extra_global_tyvars
     in
     tcNewMutVar new_global_tyvars      `thenNF_Tc` \ gtvs' ->
 
-    tcSetEnv (TcEnv tve gve lve' gtvs' ke tce ce) scope
+    tcSetEnv (TcEnv tve tce ce gve lve' gtvs') scope
 \end{code}
 
 @tcGetGlobalTyVars@ returns a fully-zonked set of tyvars free in the environment.
@@ -209,52 +284,105 @@ the environment.
 \begin{code}
 tcGetGlobalTyVars :: NF_TcM s (TcTyVarSet s)
 tcGetGlobalTyVars
-  = tcGetEnv                           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
+  = tcGetEnv                           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
     tcReadMutVar gtvs                  `thenNF_Tc` \ global_tvs ->
     zonkTcTyVars global_tvs            `thenNF_Tc` \ global_tvs' ->
-    tcWriteMutVar gtvs global_tvs'     `thenNF_Tc_`
+    tcWriteMutVar gtvs global_tvs'     `thenNF_Tc_` 
     returnNF_Tc global_tvs'
+
+tcExtendGlobalTyVars extra_global_tvs scope
+  = tcGetEnv                           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+    tcReadMutVar gtvs                  `thenNF_Tc` \ global_tvs ->
+    let
+       new_global_tyvars = global_tvs `unionTyVarSets` mkTyVarSet extra_global_tvs
+    in
+    tcNewMutVar new_global_tyvars      `thenNF_Tc` \ gtvs' ->
+    tcSetEnv (TcEnv tve tce ce gve lve gtvs') scope
 \end{code}
 
 \begin{code}
 tcLookupLocalValue :: Name -> NF_TcM s (Maybe (TcIdBndr s))
 tcLookupLocalValue name
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
     returnNF_Tc (lookupUFM lve name)
 
+tcLookupLocalValueByKey :: Unique -> NF_TcM s (Maybe (TcIdBndr s))
+tcLookupLocalValueByKey uniq
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+    returnNF_Tc (lookupUFM_Directly lve uniq)
+
 tcLookupLocalValueOK :: String -> Name -> NF_TcM s (TcIdBndr s)
 tcLookupLocalValueOK err name
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
     returnNF_Tc (lookupWithDefaultUFM lve (panic err) name)
 
 
 tcLookupGlobalValue :: Name -> NF_TcM s Id
-
-tcLookupGlobalValue (WiredInVal id)    -- wired in ids
-  = returnNF_Tc id
-
 tcLookupGlobalValue name
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
-    returnNF_Tc (lookupWithDefaultUFM gve def name)
+  = case maybeWiredInIdName name of
+       Just id -> returnNF_Tc id
+       Nothing -> tcGetEnv             `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+                  returnNF_Tc (lookupWithDefaultUFM gve def name)
   where
-#ifdef DEBUG
-    def = panic ("tcLookupGlobalValue:" ++ ppShow 1000 (ppr PprDebug name))
-#else
-    def = panic "tcLookupGlobalValue"
-#endif
+    def = pprPanic "tcLookupGlobalValue:" (ppr name)
+
+tcLookupGlobalValueMaybe :: Name -> NF_TcM s (Maybe Id)
+tcLookupGlobalValueMaybe name
+  = case maybeWiredInIdName name of
+       Just id -> returnNF_Tc (Just id)
+       Nothing -> tcGetEnv             `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+                  returnNF_Tc (lookupUFM gve name)
 
 
 tcLookupGlobalValueByKey :: Unique -> NF_TcM s Id
 tcLookupGlobalValueByKey uniq
-  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve gve lve gtvs ke tce ce) ->
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
     returnNF_Tc (lookupWithDefaultUFM_Directly gve def uniq)
   where
 #ifdef DEBUG
-    def = panic ("tcLookupGlobalValueByKey:" ++ ppShow 1000 (ppr PprDebug uniq))
+    def = pprPanic "tcLookupGlobalValueByKey:" (pprUnique10 uniq)
 #else
     def = panic "tcLookupGlobalValueByKey"
 #endif
 
+tcLookupGlobalValueByKeyMaybe :: Unique -> NF_TcM s (Maybe Id)
+tcLookupGlobalValueByKeyMaybe uniq
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+    returnNF_Tc (lookupUFM_Directly gve uniq)
+
+tcGetGlobalValEnv :: NF_TcM s GlobalValueEnv
+tcGetGlobalValEnv
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce gve lve gtvs) ->
+    returnNF_Tc gve
+
+tcSetGlobalValEnv :: GlobalValueEnv -> TcM s a -> TcM s a
+tcSetGlobalValEnv gve scope
+  = tcGetEnv           `thenNF_Tc` \ (TcEnv tve tce ce _ lve gtvs) ->
+    tcSetEnv (TcEnv tve tce ce gve lve gtvs) scope
+
+
+-- Non-monadic version, environment given explicitly
+tcExplicitLookupGlobal :: GlobalValueEnv -> Name -> Maybe Id
+tcExplicitLookupGlobal gve name
+  = case maybeWiredInIdName name of
+       Just id -> Just id
+       Nothing -> lookupUFM gve name
+
+       -- Extract the IdInfo from an IfaceSig imported from an interface file
+tcAddImportedIdInfo :: GlobalValueEnv -> Id -> Id
+tcAddImportedIdInfo unf_env id
+  | isLocallyDefined id                -- Don't look up locally defined Ids, because they
+                               -- have explicit local definitions, so we get a black hole!
+  = id
+  | otherwise
+  = id `replaceIdInfo` new_info
+       -- The Id must be returned without a data dependency on maybe_id
+  where
+    new_info = -- pprTrace "tcAdd" (ppr id) $
+              case tcExplicitLookupGlobal unf_env (getName id) of
+                    Nothing          -> noIdInfo
+                    Just imported_id -> idInfo imported_id
+               -- ToDo: could check that types are the same
 \end{code}
 
 
@@ -262,28 +390,47 @@ Constructing new Ids
 ~~~~~~~~~~~~~~~~~~~~
 
 \begin{code}
+-- Uses the Name as the Name of the Id
 newMonoIds :: [Name] -> Kind -> ([TcIdBndr s] -> TcM s a) -> TcM s a
+
 newMonoIds names kind m
   = newTyVarTys no_of_names kind       `thenNF_Tc` \ tys ->
-    tcGetUniques no_of_names           `thenNF_Tc` \ uniqs ->
     let
-       new_ids            = zipWith3Equal mk_id names uniqs tys
-       mk_id name uniq ty = mkUserLocal (getOccurrenceName name) uniq ty
-                                        (getSrcLoc name)
+       new_ids       = zipWithEqual "newMonoIds" mk_id names tys
+       mk_id name ty = mkUserId name ty
     in
     tcExtendLocalValEnv names new_ids (m new_ids)
   where
     no_of_names = length names
 
-newLocalIds :: [FAST_STRING] -> [TcType s] -> NF_TcM s [TcIdBndr s]
+newLocalId :: OccName -> TcType s -> NF_TcM s (TcIdBndr s)
+newLocalId name ty
+  = tcGetSrcLoc                `thenNF_Tc` \ loc ->
+    tcGetUnique                `thenNF_Tc` \ uniq ->
+    returnNF_Tc (mkUserLocal name uniq ty loc)
+
+newLocalIds :: [OccName] -> [TcType s] -> NF_TcM s [TcIdBndr s]
 newLocalIds names tys
   = tcGetSrcLoc                        `thenNF_Tc` \ loc ->
     tcGetUniques (length names) `thenNF_Tc` \ uniqs ->
     let
-       new_ids            = zipWith3Equal mk_id names uniqs tys
+       new_ids            = zipWith3Equal "newLocalIds" mk_id names uniqs tys
        mk_id name uniq ty = mkUserLocal name uniq ty loc
     in
     returnNF_Tc new_ids
+
+newSpecPragmaId :: Name -> TcType s -> NF_TcM s (TcIdBndr s)
+newSpecPragmaId name ty 
+  = tcGetSrcLoc                `thenNF_Tc` \ loc ->
+    tcGetUnique                `thenNF_Tc` \ uniq ->
+    returnNF_Tc (mkSpecPragmaId (nameOccName name) uniq ty loc)
 \end{code}
 
 
+\begin{code}
+classAsTyConErr name
+  = ptext SLIT("Class used as a type constructor:") <+> ppr name
+
+tyConAsClassErr name
+  = ptext SLIT("Type constructor used as a class:") <+> ppr name
+\end{code}