remove the *.raw files
[ghc-hetmet.git] / compiler / rename / RnNames.lhs
index 738a0c4..d61133b 100644 (file)
@@ -32,8 +32,8 @@ import NameEnv
 import NameSet
 import OccName         ( srcDataName, pprNonVarNameSpace,
                          occNameSpace,
-                         OccEnv, mkOccEnv, lookupOccEnv, emptyOccEnv,
-                         extendOccEnv )
+                         OccEnv, mkOccEnv, mkOccEnv_C, lookupOccEnv,
+                         emptyOccEnv, extendOccEnv )
 import HscTypes                ( GenAvailInfo(..), AvailInfo, availNames, availName,
                          HomePackageTable, PackageIfaceTable, 
                          mkPrintUnqualified, availsToNameSet,
@@ -43,7 +43,8 @@ import HscTypes               ( GenAvailInfo(..), AvailInfo, availNames, availName,
 import RdrName         ( RdrName, rdrNameOcc, setRdrNameSpace, Parent(..),
                          GlobalRdrEnv, mkGlobalRdrEnv, GlobalRdrElt(..), 
                          emptyGlobalRdrEnv, plusGlobalRdrEnv, globalRdrEnvElts,
-                         extendGlobalRdrEnv, lookupGlobalRdrEnv, lookupGRE_Name,
+                         extendGlobalRdrEnv, lookupGlobalRdrEnv,
+                         lookupGRE_RdrName, lookupGRE_Name, 
                          Provenance(..), ImportSpec(..), ImpDeclSpec(..), ImpItemSpec(..), 
                          importSpecLoc, importSpecModule, isLocalGRE, pprNameProvenance,
                          unQualSpecOK, qualSpecOK )
@@ -57,7 +58,7 @@ import BasicTypes     ( DeprecTxt )
 import DriverPhases    ( isHsBoot )
 import Util
 import ListSetOps
-import Data.List        ( partition, concatMap )
+import Data.List        ( partition, concatMap, (\\), delete )
 import IO              ( openFile, IOMode(..) )
 import Monad           ( when )
 \end{code}
@@ -411,15 +412,33 @@ filterImports iface decl_spec (Just (want_hiding, import_items)) all_avails
         return (Just (want_hiding, map fst items2), mkGlobalRdrEnv gres)
   where
        -- This environment is how we map names mentioned in the import
-        -- list to the actual Name they correspond to, and the family
-        -- that the Name belongs to (an AvailInfo).
+        -- list to the actual Name they correspond to, and the name family
+        -- that the Name belongs to (the AvailInfo).  The situation is
+        -- complicated by associated families, which introduce a three-level
+        -- hierachy, where class = grand parent, assoc family = parent, and
+        -- data constructors = children.  The occ_env entries for associated
+        -- families needs to capture all this information; hence, we have the
+        -- third component of the environment that gives the class name (=
+        -- grand parent) in case of associated families.
         --
        -- This env will have entries for data constructors too,
        -- they won't make any difference because naked entities like T
        -- in an import list map to TcOccs, not VarOccs.
-    occ_env :: OccEnv (Name,AvailInfo)
-    occ_env = mkOccEnv [ (nameOccName n, (n,a)) 
-                       | a <- all_avails, n <- availNames a ]
+    occ_env :: OccEnv (Name,       -- the name
+                      AvailInfo,   -- the export item providing the name
+                      Maybe Name)  -- the parent of associated types
+    occ_env = mkOccEnv_C combine [ (nameOccName n, (n, a, Nothing)) 
+                                | a <- all_avails, n <- availNames a]
+      where
+        -- we know that (1) there are at most entries for one name, (2) their
+        -- first component is identical, (3) they are for tys/cls, and (4) one
+        -- entry has the name in its parent position (the other doesn't)
+        combine (name, AvailTC p1 subs1, Nothing)
+               (_   , AvailTC p2 subs2, Nothing)
+          = let
+             (parent, subs) = if p1 == name then (p2, subs1) else (p1, subs2)
+           in
+           (name, AvailTC name subs, Just parent)
 
     lookup_lie :: Bool -> LIE RdrName -> TcRn [(LIE Name, AvailInfo)]
     lookup_lie opt_indexedtypes (L loc ieRdr)
@@ -445,7 +464,10 @@ filterImports iface decl_spec (Just (want_hiding, import_items)) all_avails
         -- Returns Nothing on error.
         -- We return a list here, because in the case of an import
         -- item like C, if we are hiding, then C refers to *both* a
-        -- type/class and a data constructor.
+        -- type/class and a data constructor.  Moreover, when we import
+       -- data constructors of an associated family, we need separate
+       -- AvailInfos for the data constructors and the family (as they have
+       -- different parents).  See the discussion at occ_env.
     lookup_ie :: Bool -> IE RdrName -> MaybeErr Message [(IE Name,AvailInfo)]
     lookup_ie opt_indexedtypes ie 
       = let bad_ie = Failed (badImportItemErr iface decl_spec ie)
@@ -457,12 +479,18 @@ filterImports iface decl_spec (Just (want_hiding, import_items)) all_avails
         in
         case ie of
          IEVar n -> do
-             (name,avail) <- lookup_name n
+             (name, avail, _) <- lookup_name n
              return [(IEVar name, trimAvail avail name)]
 
          IEThingAll tc -> do
-             (name,avail) <- lookup_name tc
-             return [(IEThingAll name, avail)]
+             (name, avail@(AvailTC name2 subs), mb_parent) <- lookup_name tc
+             case mb_parent of
+              -- non-associated ty/cls
+              Nothing     -> return [(IEThingAll name, avail)]
+              -- associated ty
+              Just parent -> return [(IEThingAll name, 
+                                      AvailTC name2 (subs \\ [name])),
+                                     (IEThingAll name, AvailTC parent [name])]
 
          IEThingAbs tc
              | want_hiding   -- hiding ( C )
@@ -473,36 +501,42 @@ filterImports iface decl_spec (Just (want_hiding, import_items)) all_avails
                 in
                 case catMaybeErr [ tc_name, dc_name ] of
                   []    -> bad_ie
-                  names -> return [ (IEThingAbs n, trimAvail av n) 
-                                 | (n,av) <- names ]
+                  names -> return [mkIEThingAbs name | name <- names]
              | otherwise
-             -> do (name,avail) <- lookup_name tc
-                   return [(IEThingAbs name, AvailTC name [name])]
-
-         IEThingWith n ns -> do
-            (name,avail) <- lookup_name n
-            case avail of
-                AvailTC nm subnames | nm == name -> do
-                     let env = mkOccEnv [ (nameOccName s, s) 
-                                        | s <- subnames ]
-                     let mb_children = map (lookupOccEnv env . rdrNameOcc) ns
-                     children <- 
-                        if any isNothing mb_children
-                          then bad_ie
-                          else return (catMaybes mb_children)
-                        -- check for proper import of indexed types
-                     when (not opt_indexedtypes && any isTyConName children) $
-                        Failed (typeItemErr (head . filter isTyConName 
-                                                $ children )
-                                    (text "in import list"))
-                     return [(IEThingWith name children, AvailTC name (name:children))]
-
-                _otherwise -> bad_ie
+             -> do nameAvail <- lookup_name tc
+                   return [mkIEThingAbs nameAvail]
+
+         IEThingWith tc ns -> do
+            (name, AvailTC name2 subnames, mb_parent) <- lookup_name tc
+           let 
+             env         = mkOccEnv [(nameOccName s, s) | s <- subnames]
+             mb_children = map (lookupOccEnv env . rdrNameOcc) ns
+           children <- if any isNothing mb_children
+                        then bad_ie
+                        else return (catMaybes mb_children)
+              -- check for proper import of indexed types
+           when (not opt_indexedtypes && any isTyConName children) $
+              Failed (typeItemErr (head . filter isTyConName $ children)
+                                 (text "in import list"))
+            case mb_parent of
+              -- non-associated ty/cls
+             Nothing     -> return [(IEThingWith name children, 
+                                     AvailTC name (name:children))]
+              -- associated ty
+             Just parent -> return [(IEThingWith name children, 
+                                     AvailTC name children),
+                                    (IEThingWith name children, 
+                                     AvailTC parent [name])]
 
          _other -> Failed illegalImportItemErr
          -- could be IEModuleContents, IEGroup, IEDoc, IEDocNamed
          -- all errors.
 
+      where
+        mkIEThingAbs (n, av, Nothing    ) = (IEThingAbs n, trimAvail av n) 
+       mkIEThingAbs (n, av, Just parent) = (IEThingAbs n, AvailTC parent [n]) 
+
+
 catMaybeErr :: [MaybeErr err a] -> [a]
 catMaybeErr ms =  [ a | Succeeded a <- ms ]
 \end{code}
@@ -618,9 +652,18 @@ mkAvailEnv :: [AvailInfo] -> AvailEnv
        -- We want to combine these; addAvail does that
 mkAvailEnv avails = foldl addAvail emptyAvailEnv avails
 
+-- After combining the avails, we need to ensure that the parent name is the
+-- first entry in the list of subnames, if it is included at all.  (Subsequent
+-- functions rely on that.)
+normaliseAvail :: AvailInfo -> AvailInfo
+normaliseAvail avail@(Avail _)     = avail
+normaliseAvail (AvailTC name subs) = AvailTC name subs'
+  where
+    subs' = if name `elem` subs then name : (delete name subs) else subs
+
 -- | combines 'AvailInfo's from the same family
 nubAvails :: [AvailInfo] -> [AvailInfo]
-nubAvails avails = nameEnvElts (mkAvailEnv avails)
+nubAvails avails = map normaliseAvail . nameEnvElts . mkAvailEnv $ avails
 \end{code}
 
 
@@ -712,6 +755,7 @@ exports_from_avail Nothing rdr_env imports this_mod
 
 exports_from_avail (Just rdr_items) rdr_env imports this_mod
   = do (ie_names, _, exports) <- foldlM do_litem emptyExportAccum rdr_items
+
        return (Just ie_names, exports)
   where
     do_litem :: ExportAccum -> LIE RdrName -> RnM ExportAccum
@@ -769,7 +813,13 @@ exports_from_avail (Just rdr_items) rdr_env imports this_mod
 
     lookup_ie (IEThingAbs rdr) 
         = do name <- lookupGlobalOccRn rdr
-             return (IEThingAbs name, AvailTC name [name])
+            case lookupGRE_RdrName rdr rdr_env of
+              []    -> panic "RnNames.lookup_ie"
+              elt:_ -> case gre_par elt of
+                         NoParent   -> return (IEThingAbs name, 
+                                               AvailTC name [name])
+                         ParentIs p -> return (IEThingAbs name, 
+                                               AvailTC p [name])
 
     lookup_ie ie@(IEThingAll rdr) 
         = do name <- lookupGlobalOccRn rdr