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