7fad74c375000383d81872dc57b8623662394a3c
[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(..), ForKind(..),
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 (FoImport _) _ _ _ loc))
230       = do_one (nm,loc)                     `thenRn` \ for_avail ->
231         returnRn (for_avail : avails)
232
233     -- foreign import declaration
234     getLocalDeclBinders avails (ForD (ForeignDecl nm FoLabel _ _ _ loc))
235       = do_one (nm,loc)                     `thenRn` \ for_avail ->
236         returnRn (for_avail : avails)
237
238     -- foreign export dynamic declaration
239     getLocalDeclBinders avails (ForD (ForeignDecl nm FoExport _ Dynamic _ loc))
240       = do_one (nm,loc)                     `thenRn` \ for_avail ->
241         returnRn (for_avail : avails)
242
243     getLocalDeclBinders avails decl
244       = getDeclBinders newLocalName decl        `thenRn` \ avail ->
245         case avail of
246            NotAvailable -> returnRn avails              -- Instance decls and suchlike
247            other        -> returnRn (avail : avails)
248
249     do_one (rdr_name, loc)
250       = newLocalName rdr_name loc       `thenRn` \ name ->
251         returnRn (Avail name)
252 \end{code}
253
254 %************************************************************************
255 %*                                                                      *
256 \subsection{Filtering imports}
257 %*                                                                      *
258 %************************************************************************
259
260 @filterImports@ takes the @ExportEnv@ telling what the imported module makes
261 available, and filters it through the import spec (if any).
262
263 \begin{code}
264 filterImports :: Module
265               -> Maybe (Bool, [RdrNameIE])              -- Import spec; True => hidin
266               -> [AvailInfo]                            -- What's available
267               -> RnMG ([AvailInfo],                     -- What's actually imported
268                        [AvailInfo],                     -- What's to be hidden (the unqualified version, that is)
269                        [AvailInfo])                     -- What was imported explicitly
270
271         -- Complains if import spec mentions things that the module doesn't export
272         -- Warns/informs if import spec contains duplicates.
273 filterImports mod Nothing imports
274   = returnRn (imports, [], [])
275
276 filterImports mod (Just (want_hiding, import_items)) avails
277   = mapRn check_item import_items               `thenRn` \ item_avails ->
278     if want_hiding 
279     then        
280         returnRn (avails, item_avails, [])      -- All imported; item_avails to be hidden
281     else
282         returnRn (item_avails, [], item_avails) -- Just item_avails imported; nothing to be hidden
283
284   where
285     import_fm :: FiniteMap OccName AvailInfo
286     import_fm = listToFM [ (nameOccName name, avail) 
287                          | avail <- avails,
288                            name  <- availEntityNames avail]
289
290     check_item item@(IEModuleContents _)
291       = addErrRn (badImportItemErr mod item)    `thenRn_`
292         returnRn NotAvailable
293
294     check_item item
295       | not (maybeToBool maybe_in_import_avails) ||
296         (case filtered_avail of { NotAvailable -> True; other -> False })
297       = addErrRn (badImportItemErr mod item)    `thenRn_`
298         returnRn NotAvailable
299
300       | dodgy_import = addWarnRn (dodgyImportWarn mod item)     `thenRn_`
301                        returnRn filtered_avail
302
303       | otherwise    = returnRn filtered_avail
304                 
305       where
306         maybe_in_import_avails = lookupFM import_fm (ieOcc item)
307         Just avail             = maybe_in_import_avails
308         filtered_avail         = filterAvail item avail
309         dodgy_import           = case (item, avail) of
310                                    (IEThingAll _, AvailTC _ [n]) -> True
311                                         -- This occurs when you import T(..), but
312                                         -- only export T abstractly.  The single [n]
313                                         -- in the AvailTC is the type or class itself
314                                         
315                                    other -> False
316                                         
317 \end{code}
318
319
320
321 %************************************************************************
322 %*                                                                      *
323 \subsection{Qualifiying imports}
324 %*                                                                      *
325 %************************************************************************
326
327 @qualifyImports@ takes the @ExportEnv@ after filtering through the import spec
328 of an import decl, and deals with producing an @RnEnv@ with the 
329 right qualified names.  It also turns the @Names@ in the @ExportEnv@ into
330 fully fledged @Names@.
331
332 \begin{code}
333 qualifyImports :: Module                                -- Imported module
334                -> Bool                                  -- True <=> want qualified import
335                -> Bool                                  -- True <=> want unqualified import
336                -> Maybe Module                          -- Optional "as M" part 
337                -> [AvailInfo]                           -- What's to be hidden
338                -> Avails -> (Name -> HowInScope)        -- Whats imported and how
339                -> [(OccName, (Fixity, HowInScope))]     -- Ditto for fixities
340                -> RnMG (RnEnv, ExportAvails)
341
342 qualifyImports this_mod qual_imp unqual_imp as_mod hides
343                avails name_to_his fixities
344   = 
345         -- Make the name environment.  Even though we're talking about a 
346         -- single import module there might still be name clashes, 
347         -- because it might be the module being compiled.
348     foldlRn add_avail emptyGlobalNameEnv avails `thenRn` \ name_env1 ->
349     let
350         -- Delete things that are hidden
351         name_env2 = foldl del_avail name_env1 hides
352
353         -- Create the fixity env
354         fixity_env = foldl (add_fixity name_env2) emptyFixityEnv fixities
355
356         -- Create the export-availability info
357         export_avails = mkExportAvails qual_mod unqual_imp name_env2 avails
358     in
359     returnRn (RnEnv name_env2 fixity_env, export_avails)
360   where
361     qual_mod = case as_mod of
362                   Nothing           -> this_mod
363                   Just another_name -> another_name
364
365     add_avail :: GlobalNameEnv -> AvailInfo -> RnMG GlobalNameEnv
366     add_avail env avail = foldlRn add_name env (availNames avail)
367
368     add_name env name   = add qual_imp   env  (Qual qual_mod occ err_hif) `thenRn` \ env1 ->
369                           add unqual_imp env1 (Unqual occ)
370                         where
371                           add False env rdr_name = returnRn env
372                           add True  env rdr_name = addOneToGlobalNameEnv env rdr_name (name, name_to_his name)
373                           occ  = nameOccName name
374
375     del_avail env avail = foldl delOneFromGlobalNameEnv env rdr_names
376                         where
377                           rdr_names = map (Unqual . nameOccName) (availNames avail)
378                         
379     add_fixity name_env fix_env (occ_name, fixity)
380         = add qual $ add unqual $ fix_env
381         where
382           qual   = Qual qual_mod occ_name err_hif
383           unqual = Unqual occ_name
384
385           add rdr_name fix_env | maybeToBool (lookupFM name_env rdr_name)
386                                = addOneToFixityEnv fix_env rdr_name fixity
387                                | otherwise
388                                = fix_env
389
390 err_hif = error "qualifyImports: hif"   -- Not needed in key to mapping
391 \end{code}
392
393 unQualify adds an Unqual binding for every existing Qual binding.
394
395 \begin{code}
396 unQualify :: FiniteMap RdrName elt -> FiniteMap RdrName elt
397 unQualify fm = addListToFM fm [(Unqual occ, elt) | (Qual _ occ _, elt) <- fmToList fm]
398 \end{code}
399
400 %************************************************************************
401 %*                                                                      *
402 \subsection{Local declarations}
403 %*                                                                      *
404 %************************************************************************
405
406
407 \begin{code}
408 fixityFromFixDecl :: RdrNameFixityDecl -> RnMG (OccName, (Fixity, HowInScope))
409
410 fixityFromFixDecl (FixityDecl rdr_name fixity loc)
411   = returnRn (rdrNameOcc rdr_name, (fixity, FromLocalDefn loc))
412 \end{code}
413
414
415 %************************************************************************
416 %*                                                                      *
417 \subsection{Export list processing
418 %*                                                                      *
419 %************************************************************************
420
421 The @AvailEnv@ type is just used internally in @exportsFromAvail@.
422 When exporting we need to combine the availabilities for a particular
423 exported thing, and we also need to check for name clashes -- that
424 is: two exported things must have different @OccNames@.
425
426 \begin{code}
427 type AvailEnv = FiniteMap OccName (RdrNameIE, AvailInfo, Int{-no. of clashes-})
428         -- The FM maps each OccName to the RdrNameIE that gave rise to it,
429         -- for error reporting, as well as to its AvailInfo
430
431 emptyAvailEnv = emptyFM
432
433 {-
434  Add new entry to environment. Checks for name clashes, i.e.,
435  plain duplicates or exported entity pairs that have different OccNames.
436  (c.f. 5.1.1 of Haskell 1.4 report.)
437 -}
438 addAvailEnv :: Bool -> RdrNameIE -> AvailEnv -> AvailInfo -> RnM s d AvailEnv
439 addAvailEnv warn_dups ie env NotAvailable   = returnRn env
440 addAvailEnv warn_dups ie env (AvailTC _ []) = returnRn env
441 addAvailEnv warn_dups ie env avail
442   | warn_dups = mapMaybeRn (addErrRn . availClashErr) () conflict `thenRn_`
443                 returnRn (addToFM_C addAvail env key elt)
444   | otherwise = returnRn (addToFM_C addAvail env key elt)
445   where
446    occ_avail = nameOccName (availName avail)
447    occ_ie    = ieOcc ie
448    key
449     | not warn_dups || occ_ie == occ_avail = occ_avail
450     | otherwise                            = occ_ie 
451         -- export item is a class method, use export occ name instead.
452         -- (this is only needed to get more precise warnings about
453         --  duplicates.)
454    elt  = (ie,avail,reports_on)
455
456    reports_on
457     | maybeToBool dup = 1
458     | otherwise       = 0
459
460    conflict = conflictFM bad_avail env key elt
461    dup 
462     | warn_dups = conflictFM dup_avail env key elt
463     | otherwise = Nothing
464
465 addListToAvailEnv :: AvailEnv -> RdrNameIE -> [AvailInfo] -> RnM s d AvailEnv
466 addListToAvailEnv env ie items 
467   = foldlRn (addAvailEnv False{-don't warn about dups-} ie) env items
468
469 bad_avail  (ie1,avail1,r1) (ie2,avail2,r2) 
470    = availName avail1 /= availName avail2  -- Same OccName, different Name
471 dup_avail  (ie1,avail1,r1) (ie2,avail2,r2) 
472    = availName avail1 == availName avail2 -- Same OccName & avail.
473
474 addAvail (ie1,a1,r1) (ie2,a2,r2) = (ie1, a1 `plusAvail` a2, r1 + r2)
475 \end{code}
476
477 Processing the export list.
478
479 You might think that we should record things that appear in the export list as
480 ``occurrences'' (using addOccurrenceName), but you'd be wrong.  We do check (here)
481 that they are in scope, but there is no need to slurp in their actual declaration
482 (which is what addOccurrenceName forces).  Indeed, doing so would big trouble when
483 compiling PrelBase, because it re-exports GHC, which includes takeMVar#, whose type
484 includes ConcBase.StateAndSynchVar#, and so on...
485
486 \begin{code}
487 exportsFromAvail :: Module
488                  -> Maybe [RdrNameIE]   -- Export spec
489                  -> ExportAvails
490                  -> RnEnv
491                  -> RnMG (Name -> ExportFlag, ExportEnv)
492         -- Complains if two distinct exports have same OccName
493         -- Warns about identical exports.
494         -- Complains about exports items not in scope
495 exportsFromAvail this_mod Nothing export_avails rn_env
496   = exportsFromAvail this_mod (Just [IEModuleContents this_mod]) export_avails rn_env
497
498 exportsFromAvail this_mod (Just export_items) 
499                  (mod_avail_env, entity_avail_env)
500                  (RnEnv global_name_env fixity_env)
501   = checkForModuleExportDups export_items                 `thenRn` \ export_items' ->
502     foldlRn exports_from_item emptyAvailEnv export_items' `thenRn` \ export_avail_env ->
503     let
504      dup_entries = fmToList (filterFM (\ _ (_,_,clashes) -> clashes > 0) export_avail_env)
505     in
506     mapRn (addWarnRn . dupExportWarn) dup_entries         `thenRn_`
507     let
508         export_avails   = map (\ (_,a,_) -> a) (eltsFM export_avail_env)
509         export_fixities = mk_exported_fixities (availsToNameSet export_avails)
510         export_fn       = mk_export_fn export_avails
511     in
512     returnRn (export_fn, ExportEnv export_avails export_fixities)
513
514   where
515     exports_from_item :: AvailEnv -> RdrNameIE -> RnMG AvailEnv
516     exports_from_item export_avail_env ie@(IEModuleContents mod)
517         = case lookupFM mod_avail_env mod of
518                 Nothing     -> failWithRn export_avail_env (modExportErr mod)
519                 Just avails -> addListToAvailEnv export_avail_env ie avails
520
521     exports_from_item export_avail_env ie
522         | not (maybeToBool maybe_in_scope) 
523         = failWithRn export_avail_env (unknownNameErr (ieName ie))
524
525 #ifdef DEBUG
526         -- I can't see why this should ever happen; if the thing is in scope
527         -- at all it ought to have some availability
528         | not (maybeToBool maybe_avail)
529         = pprTrace "exportsFromAvail: curious Nothing:" (ppr name)
530           returnRn export_avail_env
531 #endif
532
533         | not enough_avail
534         = failWithRn export_avail_env (exportItemErr ie export_avail)
535
536         | otherwise     -- Phew!  It's OK!
537         = addAvailEnv opt_WarnDuplicateExports ie export_avail_env export_avail
538        where
539           maybe_in_scope  = lookupFM global_name_env (ieName ie)
540           Just (name,_)   = maybe_in_scope
541           maybe_avail     = lookupUFM entity_avail_env name
542           Just avail      = maybe_avail
543           export_avail    = filterAvail ie avail
544           enough_avail    = case export_avail of {NotAvailable -> False; other -> True}
545
546         -- We export a fixity iff we export a thing with the same (qualified) RdrName
547     mk_exported_fixities :: NameSet -> [(OccName, Fixity)]
548     mk_exported_fixities exports
549         = fmToList (foldr (perhaps_add_fixity exports) 
550                           emptyFM
551                           (fmToList fixity_env))
552
553     perhaps_add_fixity :: NameSet -> (RdrName, (Fixity, HowInScope))
554                        -> FiniteMap OccName Fixity
555                        -> FiniteMap OccName Fixity
556     perhaps_add_fixity exports (rdr_name, (fixity, how_in_scope)) fix_env
557       =  let
558             do_nothing = fix_env                -- The default is to pass on the env unchanged
559          in
560                 -- Step 1: check whether the rdr_name is in scope; if so find its Name
561          case lookupFM global_name_env rdr_name of {
562            Nothing              -> do_nothing;
563            Just (fixity_name,_) -> 
564
565                 -- Step 2: check whether the fixity thing is exported
566          if not (fixity_name `elemNameSet` exports) then
567                 do_nothing
568          else
569         
570                 -- Step 3: check whether we already have a fixity for the
571                 -- Name's OccName in the fix_env we are building up.  This can easily
572                 -- happen.  the original fixity_env might contain bindings for
573                 --      M.a and N.a, if a was imported via M and N.
574                 -- If this does happen, we expect the fixity to be the same either way.
575         let
576             occ_name = rdrNameOcc rdr_name
577         in
578         case lookupFM fix_env occ_name of {
579           Just fixity1 ->       -- Got it already
580                            ASSERT( fixity == fixity1 )
581                            do_nothing;
582           Nothing -> 
583
584                 -- Step 3: add it to the outgoing fix_env
585         addToFM fix_env occ_name fixity
586         }}
587
588 {- warn and weed out duplicate module entries from export list. -}
589 checkForModuleExportDups :: [RdrNameIE] -> RnMG [RdrNameIE]
590 checkForModuleExportDups ls 
591   | opt_WarnDuplicateExports = check_modules ls
592   | otherwise                = returnRn ls
593   where
594    -- NOTE: reorders the export list by moving all module-contents
595    -- exports to the end (removing duplicates in the process.)
596    check_modules ls = 
597      (case dups of
598         [] -> returnRn ()
599         ls -> mapRn (\ ds@(IEModuleContents x:_) -> 
600                        addWarnRn (dupModuleExport x (length ds))) ls `thenRn_`
601               returnRn ()) `thenRn_`
602      returnRn (ls_no_modules ++ no_module_dups)
603      where
604       (ls_no_modules,modules) = foldr split_mods ([],[]) ls
605
606       split_mods i@(IEModuleContents _) (no_ms,ms) = (no_ms,i:ms)
607       split_mods i (no_ms,ms) = (i:no_ms,ms)
608
609       (no_module_dups, dups) = removeDups cmp_mods modules
610
611       cmp_mods (IEModuleContents m1) (IEModuleContents m2) = m1 `compare` m2
612   
613 mk_export_fn :: [AvailInfo] -> (Name -> ExportFlag)
614 mk_export_fn avails
615   = \name -> if name `elemNameSet` exported_names
616              then Exported
617              else NotExported
618   where
619     exported_names :: NameSet
620     exported_names = availsToNameSet avails
621 \end{code}
622
623 %************************************************************************
624 %*                                                                      *
625 \subsection{Errors}
626 %*                                                                      *
627 %************************************************************************
628
629 \begin{code}
630 badImportItemErr mod ie
631   = sep [ptext SLIT("Module"), quotes (pprModule mod), 
632          ptext SLIT("does not export"), quotes (ppr ie)]
633
634 dodgyImportWarn mod (IEThingAll tc)
635   = sep [ptext SLIT("Module") <+> quotes (pprModule mod) <+> ptext SLIT("exports") <+> quotes (ppr tc), 
636          ptext SLIT("with no constructors/class operations;"),
637          ptext SLIT("yet it is imported with a (..)")]
638
639 modExportErr mod
640   = hsep [ ptext SLIT("Unknown module in export list: module"), quotes (pprModule mod)]
641
642 exportItemErr export_item NotAvailable
643   = sep [ ptext SLIT("Export item not in scope:"), quotes (ppr export_item)]
644
645 exportItemErr export_item avail
646   = hang (ptext SLIT("Export item not fully in scope:"))
647            4 (vcat [hsep [ptext SLIT("Wanted:   "), ppr export_item],
648                     hsep [ptext SLIT("Available:"), ppr (ieOcc export_item), pprAvail avail]])
649
650 availClashErr (occ_name, ((ie1,avail1,_), (ie2,avail2,_)))
651   = hsep [ptext SLIT("The export items"), quotes (ppr ie1), ptext SLIT("and"), quotes (ppr ie2),
652           ptext SLIT("create conflicting exports for"), quotes (ppr occ_name)]
653
654 dupExportWarn (occ_name, (_,_,times))
655   = hsep [quotes (ppr occ_name), 
656           ptext SLIT("mentioned"), speakNTimes (times+1),
657           ptext SLIT("in export list")]
658
659 dupModuleExport mod times
660   = hsep [ptext SLIT("Module"), quotes (pprModule mod), 
661           ptext SLIT("mentioned"), speakNTimes times,
662           ptext SLIT("in export list")]
663 \end{code}
664