[project @ 1998-08-14 11:47:29 by sof]
[ghc-hetmet.git] / ghc / compiler / rename / RnNames.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
3 %
4 \section[RnNames]{Extracting imported and top-level names in scope}
5
6 \begin{code}
7 module RnNames (
8         getGlobalNames
9     ) where
10
11 #include "HsVersions.h"
12
13 import CmdLineOpts    ( opt_NoImplicitPrelude, opt_WarnDuplicateExports, 
14                         opt_SourceUnchanged
15                       )
16
17 import HsSyn    ( HsModule(..), ImportDecl(..), HsDecl(..), 
18                   IE(..), ieName, 
19                   ForeignDecl(..), ExtName(..),
20                   FixityDecl(..),
21                   collectTopBinders
22                 )
23 import RdrHsSyn ( RdrNameHsDecl, RdrName(..), RdrNameIE, RdrNameImportDecl,
24                   RdrNameHsModule, RdrNameFixityDecl,
25                   rdrNameOcc, ieOcc
26                 )
27 import RnIfaces ( getInterfaceExports, getDeclBinders, recordSlurp, checkUpToDate )
28 import BasicTypes ( IfaceFlavour(..) )
29 import RnEnv
30 import RnMonad
31
32 import FiniteMap
33 import PrelMods
34 import UniqFM   ( UniqFM, addListToUFM_C, lookupUFM )
35 import Bag      ( Bag, bagToList )
36 import Maybes   ( maybeToBool )
37 import Name
38 import Outputable
39 import Util     ( removeDups )
40 \end{code}
41
42
43
44 %************************************************************************
45 %*                                                                      *
46 \subsection{Get global names}
47 %*                                                                      *
48 %************************************************************************
49
50 \begin{code}
51 getGlobalNames :: RdrNameHsModule
52                -> RnMG (Maybe (ExportEnv, 
53                                RnEnv, 
54                                FiniteMap Name HowInScope,       -- Locally defined or explicitly imported 
55                                Name -> PrintUnqualified))
56                         -- Nothing => no need to recompile
57
58 getGlobalNames m@(HsModule this_mod _ exports imports _ _ mod_loc)
59   = fixRn (\ ~(rec_exp_fn, _) ->
60
61         -- PROCESS LOCAL DECLS
62         -- Do these *first* so that the correct provenance gets
63         -- into the global name cache.
64       importsFromLocalDecls rec_exp_fn m        `thenRn` \ (local_rn_env, local_mod_avails, local_info) ->
65
66         -- PROCESS IMPORT DECLS
67       mapAndUnzip3Rn importsFromImportDecl all_imports
68                                                 `thenRn` \ (imp_rn_envs, imp_avails_s, explicit_imports_s) ->
69
70         -- COMBINE RESULTS
71         -- We put the local env second, so that a local provenance
72         -- "wins", even if a module imports itself.
73       foldlRn plusRnEnv emptyRnEnv imp_rn_envs          `thenRn` \ imp_rn_env ->
74       plusRnEnv imp_rn_env local_rn_env                 `thenRn` \ rn_env ->
75
76         -- TRY FOR EARLY EXIT
77         -- We can't go for an early exit before this because we have to check
78         -- for name clashes.  Consider:
79         --
80         --      module A where          module B where
81         --         import B                h = True
82         --         f = h
83         --
84         -- Suppose I've compiled everything up, and then I add a
85         -- new definition to module B, that defines "f".
86         --
87         -- Then I must detect the name clash in A before going for an early
88         -- exit.  The early-exit code checks what's actually needed from B
89         -- to compile A, and of course that doesn't include B.f.  That's
90         -- why we wait till after the plusRnEnv stuff to do the early-exit.
91       checkEarlyExit this_mod                           `thenRn` \ up_to_date ->
92       if up_to_date then
93         returnRn (error "early exit", Nothing)
94       else
95  
96
97         -- PROCESS EXPORT LISTS
98       let
99          export_avails :: ExportAvails
100          export_avails = foldr plusExportAvails local_mod_avails imp_avails_s
101
102          explicit_info :: FiniteMap Name HowInScope  -- Locally defined or explicitly imported
103          explicit_info = foldr plusFM local_info explicit_imports_s
104       in
105       exportsFromAvail this_mod exports export_avails rn_env    
106                                                         `thenRn` \ (export_fn, export_env) ->
107
108         -- BUILD THE "IMPORT FN".  It just tells whether a name is in
109         -- scope in an unqualified form.
110       let 
111           print_unqual = mkImportFn imp_rn_env
112       in   
113
114       returnRn (export_fn, Just (export_env, rn_env, explicit_info, print_unqual))
115     )                                                   `thenRn` \ (_, result) ->
116     returnRn result
117   where
118     junk_exp_fn = error "RnNames:export_fn"
119
120     all_imports = prel_imports ++ imports
121
122         -- NB: opt_NoImplicitPrelude is slightly different to import Prelude ();
123         -- because the former doesn't even look at Prelude.hi for instance declarations,
124         -- whereas the latter does.
125     prel_imports | this_mod == pRELUDE ||
126                    explicit_prelude_import ||
127                    opt_NoImplicitPrelude
128                  = []
129
130                  | otherwise               = [ImportDecl pRELUDE 
131                                                          False          {- Not qualified -}
132                                                          HiFile         {- Not source imported -}
133                                                          Nothing        {- No "as" -}
134                                                          Nothing        {- No import list -}
135                                                          mod_loc]
136     
137     explicit_prelude_import
138       = not (null [ () | (ImportDecl mod qual _ _ _ _) <- imports, mod == pRELUDE ])
139 \end{code}
140         
141 \begin{code}
142 checkEarlyExit mod
143   = checkErrsRn                         `thenRn` \ no_errs_so_far ->
144     if not no_errs_so_far then
145         -- Found errors already, so exit now
146         returnRn True
147     else
148
149     traceRn (text "Considering whether compilation is required...")     `thenRn_`
150     if not opt_SourceUnchanged then
151         -- Source code changed and no errors yet... carry on 
152         traceRn (nest 4 (text "source file changed or recompilation check turned off")) `thenRn_` 
153         returnRn False
154     else
155
156         -- Unchanged source, and no errors yet; see if usage info
157         -- up to date, and exit if so
158     checkUpToDate mod                                           `thenRn` \ up_to_date ->
159     putDocRn (text "Compilation" <+> 
160               text (if up_to_date then "IS NOT" else "IS") <+>
161               text "required")                                  `thenRn_`
162     returnRn up_to_date
163 \end{code}
164         
165 \begin{code}
166 importsFromImportDecl :: RdrNameImportDecl
167                       -> RnMG (RnEnv, 
168                                ExportAvails, 
169                                FiniteMap Name HowInScope)  -- Records the explicitly-imported things
170
171 importsFromImportDecl (ImportDecl mod qual_only as_source as_mod import_spec loc)
172   = pushSrcLocRn loc $
173     getInterfaceExports mod as_source           `thenRn` \ (avails, fixities) ->
174     filterImports mod import_spec avails        `thenRn` \ (filtered_avails, hides, explicits) ->
175     let
176         how_in_scope = FromImportDecl mod loc
177         explicit_info = listToFM [(name, how_in_scope) 
178                                  | avail <- explicits,
179                                    name  <- availNames avail
180                                  ]
181     in
182     qualifyImports mod 
183                    True                 -- Want qualified names
184                    (not qual_only)      -- Maybe want unqualified names
185                    as_mod
186                    hides
187                    filtered_avails (\n -> how_in_scope)
188                    [ (occ,(fixity,how_in_scope)) | (occ,fixity) <- fixities ]
189                                                         `thenRn` \ (rn_env, mod_avails) ->
190     returnRn (rn_env, mod_avails, explicit_info)
191 \end{code}
192
193
194 \begin{code}
195 importsFromLocalDecls rec_exp_fn (HsModule mod _ _ _ fix_decls decls _)
196   = foldlRn getLocalDeclBinders [] decls                `thenRn` \ avails ->
197
198         -- Record that locally-defined things are available
199     mapRn (recordSlurp Nothing Compulsory) avails       `thenRn_`
200
201         -- Fixities
202     mapRn fixityFromFixDecl fix_decls                   `thenRn` \ fixities ->
203
204         -- Record where the available stuff came from
205     let
206         explicit_info = listToFM [(name, FromLocalDefn (getSrcLoc name))
207                                  | avail <- avails,
208                                    name  <- availNames avail
209                                  ]
210     in
211     qualifyImports mod 
212                    False        -- Don't want qualified names
213                    True         -- Want unqualified names
214                    Nothing      -- No "as M" part
215                    []           -- Hide nothing
216                    avails (\n -> FromLocalDefn (getSrcLoc n))
217                    fixities
218                                                         `thenRn` \ (rn_env, mod_avails) ->
219     returnRn (rn_env, mod_avails, explicit_info)
220   where
221     newLocalName rdr_name loc
222       = newLocallyDefinedGlobalName mod (rdrNameOcc rdr_name) rec_exp_fn loc
223
224     getLocalDeclBinders avails (ValD binds)
225       = mapRn do_one (bagToList (collectTopBinders binds))      `thenRn` \ val_avails ->
226         returnRn (val_avails ++ avails)
227
228     -- foreign import declaration
229     getLocalDeclBinders avails (ForD (ForeignDecl nm (Just _) _ _ _ loc))
230       = do_one (nm,loc)                     `thenRn` \ for_avail ->
231         returnRn (for_avail : avails)
232
233     -- foreign export dynamic declaration
234     getLocalDeclBinders avails (ForD (ForeignDecl nm Nothing _ Dynamic _ loc))
235       = do_one (nm,loc)                     `thenRn` \ for_avail ->
236         returnRn (for_avail : avails)
237
238     getLocalDeclBinders avails decl
239       = getDeclBinders newLocalName decl        `thenRn` \ avail ->
240         case avail of
241            NotAvailable -> returnRn avails              -- Instance decls and suchlike
242            other        -> returnRn (avail : avails)
243
244     do_one (rdr_name, loc)
245       = newLocalName rdr_name loc       `thenRn` \ name ->
246         returnRn (Avail name)
247 \end{code}
248
249 %************************************************************************
250 %*                                                                      *
251 \subsection{Filtering imports}
252 %*                                                                      *
253 %************************************************************************
254
255 @filterImports@ takes the @ExportEnv@ telling what the imported module makes
256 available, and filters it through the import spec (if any).
257
258 \begin{code}
259 filterImports :: Module
260               -> Maybe (Bool, [RdrNameIE])              -- Import spec; True => hidin
261               -> [AvailInfo]                            -- What's available
262               -> RnMG ([AvailInfo],                     -- What's actually imported
263                        [AvailInfo],                     -- What's to be hidden (the unqualified version, that is)
264                        [AvailInfo])                     -- What was imported explicitly
265
266         -- Complains if import spec mentions things that the module doesn't export
267         -- Warns/informs if import spec contains duplicates.
268 filterImports mod Nothing imports
269   = returnRn (imports, [], [])
270
271 filterImports mod (Just (want_hiding, import_items)) avails
272   = mapRn check_item import_items               `thenRn` \ item_avails ->
273     if want_hiding 
274     then        
275         returnRn (avails, item_avails, [])      -- All imported; item_avails to be hidden
276     else
277         returnRn (item_avails, [], item_avails) -- Just item_avails imported; nothing to be hidden
278
279   where
280     import_fm :: FiniteMap OccName AvailInfo
281     import_fm = listToFM [ (nameOccName name, avail) 
282                          | avail <- avails,
283                            name  <- availEntityNames avail]
284
285     check_item item@(IEModuleContents _)
286       = addErrRn (badImportItemErr mod item)    `thenRn_`
287         returnRn NotAvailable
288
289     check_item item
290       | not (maybeToBool maybe_in_import_avails) ||
291         (case filtered_avail of { NotAvailable -> True; other -> False })
292       = addErrRn (badImportItemErr mod item)    `thenRn_`
293         returnRn NotAvailable
294
295       | dodgy_import = addWarnRn (dodgyImportWarn mod item)     `thenRn_`
296                        returnRn filtered_avail
297
298       | otherwise    = returnRn filtered_avail
299                 
300       where
301         maybe_in_import_avails = lookupFM import_fm (ieOcc item)
302         Just avail             = maybe_in_import_avails
303         filtered_avail         = filterAvail item avail
304         dodgy_import           = case (item, avail) of
305                                    (IEThingAll _, AvailTC _ [n]) -> True
306                                         -- This occurs when you import T(..), but
307                                         -- only export T abstractly.  The single [n]
308                                         -- in the AvailTC is the type or class itself
309                                         
310                                    other -> False
311                                         
312 \end{code}
313
314
315
316 %************************************************************************
317 %*                                                                      *
318 \subsection{Qualifiying imports}
319 %*                                                                      *
320 %************************************************************************
321
322 @qualifyImports@ takes the @ExportEnv@ after filtering through the import spec
323 of an import decl, and deals with producing an @RnEnv@ with the 
324 right qualified names.  It also turns the @Names@ in the @ExportEnv@ into
325 fully fledged @Names@.
326
327 \begin{code}
328 qualifyImports :: Module                                -- Imported module
329                -> Bool                                  -- True <=> want qualified import
330                -> Bool                                  -- True <=> want unqualified import
331                -> Maybe Module                          -- Optional "as M" part 
332                -> [AvailInfo]                           -- What's to be hidden
333                -> Avails -> (Name -> HowInScope)        -- Whats imported and how
334                -> [(OccName, (Fixity, HowInScope))]     -- Ditto for fixities
335                -> RnMG (RnEnv, ExportAvails)
336
337 qualifyImports this_mod qual_imp unqual_imp as_mod hides
338                avails name_to_his fixities
339   = 
340         -- Make the name environment.  Even though we're talking about a 
341         -- single import module there might still be name clashes, 
342         -- because it might be the module being compiled.
343     foldlRn add_avail emptyGlobalNameEnv avails `thenRn` \ name_env1 ->
344     let
345         -- Delete things that are hidden
346         name_env2 = foldl del_avail name_env1 hides
347
348         -- Create the fixity env
349         fixity_env = foldl (add_fixity name_env2) emptyFixityEnv fixities
350
351         -- Create the export-availability info
352         export_avails = mkExportAvails qual_mod unqual_imp name_env2 avails
353     in
354     returnRn (RnEnv name_env2 fixity_env, export_avails)
355   where
356     qual_mod = case as_mod of
357                   Nothing           -> this_mod
358                   Just another_name -> another_name
359
360     add_avail :: GlobalNameEnv -> AvailInfo -> RnMG GlobalNameEnv
361     add_avail env avail = foldlRn add_name env (availNames avail)
362
363     add_name env name   = add qual_imp   env  (Qual qual_mod occ err_hif) `thenRn` \ env1 ->
364                           add unqual_imp env1 (Unqual occ)
365                         where
366                           add False env rdr_name = returnRn env
367                           add True  env rdr_name = addOneToGlobalNameEnv env rdr_name (name, name_to_his name)
368                           occ  = nameOccName name
369
370     del_avail env avail = foldl delOneFromGlobalNameEnv env rdr_names
371                         where
372                           rdr_names = map (Unqual . nameOccName) (availNames avail)
373                         
374     add_fixity name_env fix_env (occ_name, fixity)
375         = add qual $ add unqual $ fix_env
376         where
377           qual   = Qual qual_mod occ_name err_hif
378           unqual = Unqual occ_name
379
380           add rdr_name fix_env | maybeToBool (lookupFM name_env rdr_name)
381                                = addOneToFixityEnv fix_env rdr_name fixity
382                                | otherwise
383                                = fix_env
384
385 err_hif = error "qualifyImports: hif"   -- Not needed in key to mapping
386 \end{code}
387
388 unQualify adds an Unqual binding for every existing Qual binding.
389
390 \begin{code}
391 unQualify :: FiniteMap RdrName elt -> FiniteMap RdrName elt
392 unQualify fm = addListToFM fm [(Unqual occ, elt) | (Qual _ occ _, elt) <- fmToList fm]
393 \end{code}
394
395 %************************************************************************
396 %*                                                                      *
397 \subsection{Local declarations}
398 %*                                                                      *
399 %************************************************************************
400
401
402 \begin{code}
403 fixityFromFixDecl :: RdrNameFixityDecl -> RnMG (OccName, (Fixity, HowInScope))
404
405 fixityFromFixDecl (FixityDecl rdr_name fixity loc)
406   = returnRn (rdrNameOcc rdr_name, (fixity, FromLocalDefn loc))
407 \end{code}
408
409
410 %************************************************************************
411 %*                                                                      *
412 \subsection{Export list processing
413 %*                                                                      *
414 %************************************************************************
415
416 The @AvailEnv@ type is just used internally in @exportsFromAvail@.
417 When exporting we need to combine the availabilities for a particular
418 exported thing, and we also need to check for name clashes -- that
419 is: two exported things must have different @OccNames@.
420
421 \begin{code}
422 type AvailEnv = FiniteMap OccName (RdrNameIE, AvailInfo, Int{-no. of clashes-})
423         -- The FM maps each OccName to the RdrNameIE that gave rise to it,
424         -- for error reporting, as well as to its AvailInfo
425
426 emptyAvailEnv = emptyFM
427
428 {-
429  Add new entry to environment. Checks for name clashes, i.e.,
430  plain duplicates or exported entity pairs that have different OccNames.
431  (c.f. 5.1.1 of Haskell 1.4 report.)
432 -}
433 addAvailEnv :: Bool -> RdrNameIE -> AvailEnv -> AvailInfo -> RnM s d AvailEnv
434 addAvailEnv warn_dups ie env NotAvailable   = returnRn env
435 addAvailEnv warn_dups ie env (AvailTC _ []) = returnRn env
436 addAvailEnv warn_dups ie env avail
437   | warn_dups = mapMaybeRn (addErrRn . availClashErr) () conflict `thenRn_`
438                 returnRn (addToFM_C addAvail env key elt)
439   | otherwise = returnRn (addToFM_C addAvail env key elt)
440   where
441    occ_avail = nameOccName (availName avail)
442    occ_ie    = ieOcc ie
443    key
444     | not warn_dups || occ_ie == occ_avail = occ_avail
445     | otherwise                            = occ_ie 
446         -- export item is a class method, use export occ name instead.
447         -- (this is only needed to get more precise warnings about
448         --  duplicates.)
449    elt  = (ie,avail,reports_on)
450
451    reports_on
452     | maybeToBool dup = 1
453     | otherwise       = 0
454
455    conflict = conflictFM bad_avail env key elt
456    dup 
457     | warn_dups = conflictFM dup_avail env key elt
458     | otherwise = Nothing
459
460 addListToAvailEnv :: AvailEnv -> RdrNameIE -> [AvailInfo] -> RnM s d AvailEnv
461 addListToAvailEnv env ie items 
462   = foldlRn (addAvailEnv False{-don't warn about dups-} ie) env items
463
464 bad_avail  (ie1,avail1,r1) (ie2,avail2,r2) 
465    = availName avail1 /= availName avail2  -- Same OccName, different Name
466 dup_avail  (ie1,avail1,r1) (ie2,avail2,r2) 
467    = availName avail1 == availName avail2 -- Same OccName & avail.
468
469 addAvail (ie1,a1,r1) (ie2,a2,r2) = (ie1, a1 `plusAvail` a2, r1 + r2)
470 \end{code}
471
472 Processing the export list.
473
474 You might think that we should record things that appear in the export list as
475 ``occurrences'' (using addOccurrenceName), but you'd be wrong.  We do check (here)
476 that they are in scope, but there is no need to slurp in their actual declaration
477 (which is what addOccurrenceName forces).  Indeed, doing so would big trouble when
478 compiling PrelBase, because it re-exports GHC, which includes takeMVar#, whose type
479 includes ConcBase.StateAndSynchVar#, and so on...
480
481 \begin{code}
482 exportsFromAvail :: Module
483                  -> Maybe [RdrNameIE]   -- Export spec
484                  -> ExportAvails
485                  -> RnEnv
486                  -> RnMG (Name -> ExportFlag, ExportEnv)
487         -- Complains if two distinct exports have same OccName
488         -- Warns about identical exports.
489         -- Complains about exports items not in scope
490 exportsFromAvail this_mod Nothing export_avails rn_env
491   = exportsFromAvail this_mod (Just [IEModuleContents this_mod]) export_avails rn_env
492
493 exportsFromAvail this_mod (Just export_items) 
494                  (mod_avail_env, entity_avail_env)
495                  (RnEnv global_name_env fixity_env)
496   = checkForModuleExportDups export_items                 `thenRn` \ export_items' ->
497     foldlRn exports_from_item emptyAvailEnv export_items' `thenRn` \ export_avail_env ->
498     let
499      dup_entries = fmToList (filterFM (\ _ (_,_,clashes) -> clashes > 0) export_avail_env)
500     in
501     mapRn (addWarnRn . dupExportWarn) dup_entries         `thenRn_`
502     let
503         export_avails   = map (\ (_,a,_) -> a) (eltsFM export_avail_env)
504         export_fixities = mk_exported_fixities (availsToNameSet export_avails)
505         export_fn       = mk_export_fn export_avails
506     in
507     returnRn (export_fn, ExportEnv export_avails export_fixities)
508
509   where
510     exports_from_item :: AvailEnv -> RdrNameIE -> RnMG AvailEnv
511     exports_from_item export_avail_env ie@(IEModuleContents mod)
512         = case lookupFM mod_avail_env mod of
513                 Nothing     -> failWithRn export_avail_env (modExportErr mod)
514                 Just avails -> addListToAvailEnv export_avail_env ie avails
515
516     exports_from_item export_avail_env ie
517         | not (maybeToBool maybe_in_scope) 
518         = failWithRn export_avail_env (unknownNameErr (ieName ie))
519
520 #ifdef DEBUG
521         -- I can't see why this should ever happen; if the thing is in scope
522         -- at all it ought to have some availability
523         | not (maybeToBool maybe_avail)
524         = pprTrace "exportsFromAvail: curious Nothing:" (ppr name)
525           returnRn export_avail_env
526 #endif
527
528         | not enough_avail
529         = failWithRn export_avail_env (exportItemErr ie export_avail)
530
531         | otherwise     -- Phew!  It's OK!
532         = addAvailEnv opt_WarnDuplicateExports ie export_avail_env export_avail
533        where
534           maybe_in_scope  = lookupFM global_name_env (ieName ie)
535           Just (name,_)   = maybe_in_scope
536           maybe_avail     = lookupUFM entity_avail_env name
537           Just avail      = maybe_avail
538           export_avail    = filterAvail ie avail
539           enough_avail    = case export_avail of {NotAvailable -> False; other -> True}
540
541         -- We export a fixity iff we export a thing with the same (qualified) RdrName
542     mk_exported_fixities :: NameSet -> [(OccName, Fixity)]
543     mk_exported_fixities exports
544         = fmToList (foldr (perhaps_add_fixity exports) 
545                           emptyFM
546                           (fmToList fixity_env))
547
548     perhaps_add_fixity :: NameSet -> (RdrName, (Fixity, HowInScope))
549                        -> FiniteMap OccName Fixity
550                        -> FiniteMap OccName Fixity
551     perhaps_add_fixity exports (rdr_name, (fixity, how_in_scope)) fix_env
552       =  let
553             do_nothing = fix_env                -- The default is to pass on the env unchanged
554          in
555                 -- Step 1: check whether the rdr_name is in scope; if so find its Name
556          case lookupFM global_name_env rdr_name of {
557            Nothing              -> do_nothing;
558            Just (fixity_name,_) -> 
559
560                 -- Step 2: check whether the fixity thing is exported
561          if not (fixity_name `elemNameSet` exports) then
562                 do_nothing
563          else
564         
565                 -- Step 3: check whether we already have a fixity for the
566                 -- Name's OccName in the fix_env we are building up.  This can easily
567                 -- happen.  the original fixity_env might contain bindings for
568                 --      M.a and N.a, if a was imported via M and N.
569                 -- If this does happen, we expect the fixity to be the same either way.
570         let
571             occ_name = rdrNameOcc rdr_name
572         in
573         case lookupFM fix_env occ_name of {
574           Just fixity1 ->       -- Got it already
575                            ASSERT( fixity == fixity1 )
576                            do_nothing;
577           Nothing -> 
578
579                 -- Step 3: add it to the outgoing fix_env
580         addToFM fix_env occ_name fixity
581         }}
582
583 {- warn and weed out duplicate module entries from export list. -}
584 checkForModuleExportDups :: [RdrNameIE] -> RnMG [RdrNameIE]
585 checkForModuleExportDups ls 
586   | opt_WarnDuplicateExports = check_modules ls
587   | otherwise                = returnRn ls
588   where
589    -- NOTE: reorders the export list by moving all module-contents
590    -- exports to the end (removing duplicates in the process.)
591    check_modules ls = 
592      (case dups of
593         [] -> returnRn ()
594         ls -> mapRn (\ ds@(IEModuleContents x:_) -> 
595                        addWarnRn (dupModuleExport x (length ds))) ls `thenRn_`
596               returnRn ()) `thenRn_`
597      returnRn (ls_no_modules ++ no_module_dups)
598      where
599       (ls_no_modules,modules) = foldr split_mods ([],[]) ls
600
601       split_mods i@(IEModuleContents _) (no_ms,ms) = (no_ms,i:ms)
602       split_mods i (no_ms,ms) = (i:no_ms,ms)
603
604       (no_module_dups, dups) = removeDups cmp_mods modules
605
606       cmp_mods (IEModuleContents m1) (IEModuleContents m2) = m1 `compare` m2
607   
608 mk_export_fn :: [AvailInfo] -> (Name -> ExportFlag)
609 mk_export_fn avails
610   = \name -> if name `elemNameSet` exported_names
611              then Exported
612              else NotExported
613   where
614     exported_names :: NameSet
615     exported_names = availsToNameSet avails
616 \end{code}
617
618 %************************************************************************
619 %*                                                                      *
620 \subsection{Errors}
621 %*                                                                      *
622 %************************************************************************
623
624 \begin{code}
625 badImportItemErr mod ie
626   = sep [ptext SLIT("Module"), quotes (pprModule mod), 
627          ptext SLIT("does not export"), quotes (ppr ie)]
628
629 dodgyImportWarn mod (IEThingAll tc)
630   = sep [ptext SLIT("Module") <+> quotes (pprModule mod) <+> ptext SLIT("exports") <+> quotes (ppr tc), 
631          ptext SLIT("with no constructors/class operations;"),
632          ptext SLIT("yet it is imported with a (..)")]
633
634 modExportErr mod
635   = hsep [ ptext SLIT("Unknown module in export list: module"), quotes (pprModule mod)]
636
637 exportItemErr export_item NotAvailable
638   = sep [ ptext SLIT("Export item not in scope:"), quotes (ppr export_item)]
639
640 exportItemErr export_item avail
641   = hang (ptext SLIT("Export item not fully in scope:"))
642            4 (vcat [hsep [ptext SLIT("Wanted:   "), ppr export_item],
643                     hsep [ptext SLIT("Available:"), ppr (ieOcc export_item), pprAvail avail]])
644
645 availClashErr (occ_name, ((ie1,avail1,_), (ie2,avail2,_)))
646   = hsep [ptext SLIT("The export items"), quotes (ppr ie1), ptext SLIT("and"), quotes (ppr ie2),
647           ptext SLIT("create conflicting exports for"), quotes (ppr occ_name)]
648
649 dupExportWarn (occ_name, (_,_,times))
650   = hsep [quotes (ppr occ_name), 
651           ptext SLIT("mentioned"), speakNTimes (times+1),
652           ptext SLIT("in export list")]
653
654 dupModuleExport mod times
655   = hsep [ptext SLIT("Module"), quotes (pprModule mod), 
656           ptext SLIT("mentioned"), speakNTimes times,
657           ptext SLIT("in export list")]
658 \end{code}
659