Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
GHC
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Gesh
GHC
Commits
5c750a88
Commit
5c750a88
authored
27 years ago
by
sof
Browse files
Options
Downloads
Patches
Plain Diff
[project @ 1997-11-25 14:00:53 by sof]
Check for duplicates in exports lists when -fwarn-duplicate-exports is on
parent
333d772d
Loading
Loading
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
ghc/compiler/rename/RnNames.lhs
+98
-31
98 additions, 31 deletions
ghc/compiler/rename/RnNames.lhs
with
98 additions
and
31 deletions
ghc/compiler/rename/RnNames.lhs
+
98
−
31
View file @
5c750a88
...
...
@@ -12,7 +12,9 @@ module RnNames (
IMP_Ubiq()
import CmdLineOpts ( opt_SourceUnchanged, opt_NoImplicitPrelude )
import CmdLineOpts ( opt_SourceUnchanged, opt_NoImplicitPrelude,
opt_WarnDuplicateExports
)
import HsSyn ( HsModule(..), HsDecl(..), FixityDecl(..), Fixity, Fake, InPat, IE(..), HsTyVar,
TyDecl, ClassDecl, InstDecl, DefaultDecl, ImportDecl(..), HsBinds, IfaceSig,
collectTopBinders
...
...
@@ -27,6 +29,7 @@ import RnIfaces ( getInterfaceExports, getDeclBinders, checkUpToDate, recordSlur
import BasicTypes ( IfaceFlavour(..) )
import RnEnv
import RnMonad
import FiniteMap
import PrelMods
import UniqFM ( UniqFM, emptyUFM, addListToUFM_C, lookupUFM )
...
...
@@ -35,7 +38,7 @@ import Maybes ( maybeToBool, expectJust )
import Name
import Pretty
import Outputable ( Outputable(..), PprStyle(..) )
import Util ( panic, pprTrace, assertPanic )
import Util ( panic, pprTrace, assertPanic
, removeDups, cmpPString
)
\end{code}
...
...
@@ -222,7 +225,7 @@ filterImports :: Module
[AvailInfo]) -- What was imported explicitly
-- Complains if import spec mentions things that the module doesn't export
-- Warns/informs if import spec contains duplicates.
filterImports mod Nothing imports
= returnRn (imports, [], [])
...
...
@@ -362,27 +365,45 @@ exported thing, and we also need to check for name clashes -- that
is: two exported things must have different @OccNames@.
\begin{code}
type AvailEnv = FiniteMap OccName (RdrNameIE, AvailInfo)
type AvailEnv = FiniteMap OccName (RdrNameIE, AvailInfo
, Int{-no. of clashes-}
)
-- The FM maps each OccName to the RdrNameIE that gave rise to it,
-- for error reporting, as well as to its AvailInfo
emptyAvailEnv = emptyFM
unitAvailEnv :: RdrNameIE -> AvailInfo -> AvailEnv
unitAvailEnv ie NotAvailable = emptyFM
unitAvailEnv ie (AvailTC _ []) = emptyFM
unitAvailEnv ie avail = unitFM (nameOccName (availName avail)) (ie,avail)
{-
Add new entry to environment. Checks for name clashes, i.e.,
plain duplicates or exported entity pairs that have different OccNames.
(c.f. 5.1.1 of Haskell 1.4 report.)
-}
addAvailEnv ie env NotAvailable = returnRn env
addAvailEnv ie env (AvailTC _ []) = returnRn env
addAvailEnv ie env avail
= mapMaybeRn (addErrRn . availClashErr) () conflict `thenRn_`
returnRn (addToFM_C add_avail env key elt)
where
key = nameOccName (availName avail)
elt = (ie,avail,reports_on)
reports_on
| maybeToBool dup = 1
| otherwise = 0
conflict = conflictFM bad_avail env key elt
dup
| opt_WarnDuplicateExports = conflictFM dup_avail env key elt
| otherwise = Nothing
plusAvailEnv a1 a2
= mapRn (addErrRn.availClashErr) (conflictsFM bad_avail a1 a2) `thenRn_`
returnRn (plusFM_C plus_avail a1 a2)
addListToAvailEnv :: AvailEnv -> RdrNameIE -> [AvailInfo] -> RnM s d AvailEnv
addListToAvailEnv env ie items = foldlRn (addAvailEnv ie) env items
listToAvailEnv :: RdrNameIE -> [AvailInfo] -> RnM s d AvailEnv
listToAvailEnv ie items
= foldlRn plusAvailEnv emptyAvailEnv (map (unitAvailEnv ie) items)
bad_avail (ie1,avail1,r1) (ie2,avail2,r2)
= availName avail1 /= availName avail2 -- Same OccName, different Name
dup_avail (ie1,avail1,r1) (ie2,avail2,r2)
= availName avail1 == availName avail2 -- Same OccName & avail.
add_avail (ie1,a1,r1) (ie2,a2,r2) = (ie1, a1 `plusAvail` a2, r1 + r2)
bad_avail (ie1,avail1) (ie2,avail2) = availName avail1 /= availName avail2 -- Same OccName, different Name
plus_avail (ie1,a1) (ie2,a2) = (ie1, a1 `plusAvail` a2)
\end{code}
Processing the export list.
...
...
@@ -401,6 +422,7 @@ exportsFromAvail :: Module
-> RnEnv
-> RnMG (Name -> ExportFlag, ExportEnv)
-- Complains if two distinct exports have same OccName
-- Warns about identical exports.
-- Complains about exports items not in scope
exportsFromAvail this_mod Nothing export_avails rn_env
= exportsFromAvail this_mod (Just [IEModuleContents this_mod]) export_avails rn_env
...
...
@@ -408,39 +430,43 @@ exportsFromAvail this_mod Nothing export_avails rn_env
exportsFromAvail this_mod (Just export_items)
(mod_avail_env, entity_avail_env)
(RnEnv name_env fixity_env)
= mapRn exports_from_item export_items `thenRn` \ avail_envs ->
foldlRn plusAvailEnv emptyAvailEnv avail_envs `thenRn` \ export_avail_env ->
= checkForModuleExportDups export_items `thenRn` \ export_items' ->
foldlRn exports_from_item emptyAvailEnv export_items' `thenRn` \ export_avail_env ->
let
dup_entries = fmToList (filterFM (\ _ (_,_,clashes) -> clashes > 0) export_avail_env)
in
mapRn (addWarnRn . dupExportWarn) dup_entries `thenRn_`
let
export_avails = map
snd
(eltsFM export_avail_env)
export_avails = map
(\ (_,a,_) -> a)
(eltsFM export_avail_env)
export_fixities = mk_exported_fixities (availsToNameSet export_avails)
export_fn = mk_export_fn export_avails
in
returnRn (export_fn, ExportEnv export_avails export_fixities)
where
exports_from_item :: RdrNameIE -> RnMG AvailEnv
exports_from_item ie@(IEModuleContents mod)
exports_from_item ::
AvailEnv ->
RdrNameIE -> RnMG AvailEnv
exports_from_item
export_avail_env
ie@(IEModuleContents mod)
= case lookupFM mod_avail_env mod of
Nothing -> failWithRn e
mptyA
vail
E
nv (modExportErr mod)
Just avails ->
l
istToAvailEnv ie avails
Nothing -> failWithRn e
xport_a
vail
_e
nv (modExportErr mod)
Just avails ->
addL
istToAvailEnv
export_avail_env
ie avails
exports_from_item ie
exports_from_item
export_avail_env
ie
| not (maybeToBool maybe_in_scope)
= failWithRn e
mptyA
vail
E
nv (unknownNameErr (ieName ie))
= failWithRn e
xport_a
vail
_e
nv (unknownNameErr (ieName ie))
#ifdef DEBUG
-- I can't see why this should ever happen; if the thing is in scope
-- at all it ought to have some availability
| not (maybeToBool maybe_avail)
= pprTrace "exportsFromAvail: curious Nothing:" (ppr PprDebug name)
returnRn e
mptyA
vail
E
nv
returnRn e
xport_a
vail
_e
nv
#endif
| not enough_avail
= failWithRn e
mptyA
vail
E
nv (exportItemErr ie export_avail)
= failWithRn e
xport_a
vail
_e
nv (exportItemErr ie export_avail)
| otherwise -- Phew! It's OK!
=
returnRn (unit
AvailEnv ie export_avail
)
=
add
AvailEnv ie export_avail
_env export_avail
where
maybe_in_scope = lookupNameEnv name_env (ieName ie)
Just name = maybe_in_scope
...
...
@@ -491,6 +517,31 @@ exportsFromAvail this_mod (Just export_items)
addToFM fix_env occ_name (fixity,prov)
}}
{- warn and weed out duplicate module entries from export list. -}
checkForModuleExportDups :: [RdrNameIE] -> RnMG [RdrNameIE]
checkForModuleExportDups ls
| opt_WarnDuplicateExports = check_modules ls
| otherwise = returnRn ls
where
-- NOTE: reorders the export list by moving all module-contents
-- exports to the end (removing duplicates in the process.)
check_modules ls =
(case dups of
[] -> returnRn ()
ls -> mapRn (\ ds@(IEModuleContents x:_) ->
addWarnRn (dupModuleExport x (length ds))) ls `thenRn_`
returnRn ()) `thenRn_`
returnRn (ls_no_modules ++ no_module_dups)
where
(ls_no_modules,modules) = foldr split_mods ([],[]) ls
split_mods i@(IEModuleContents _) ~(no_ms,ms) = (no_ms,i:ms)
split_mods i ~(no_ms,ms) = (i:no_ms,ms)
(no_module_dups, dups) = removeDups cmp_mods modules
cmp_mods (IEModuleContents m1) (IEModuleContents m2) = m1 `cmpPString` m2
mk_export_fn :: [AvailInfo] -> (Name -> ExportFlag)
mk_export_fn avails
= \name -> if name `elemNameSet` exported_names
...
...
@@ -499,8 +550,7 @@ mk_export_fn avails
where
exported_names :: NameSet
exported_names = availsToNameSet avails
\end{code}
\end{code}
%************************************************************************
%* *
...
...
@@ -523,8 +573,25 @@ exportItemErr export_item avail sty
4 (vcat [hsep [ptext SLIT("Wanted: "), ppr sty export_item],
hsep [ptext SLIT("Available:"), ppr sty (ieOcc export_item), pprAvail sty avail]])
availClashErr (occ_name, ((ie1,avail1), (ie2,avail2))) sty
availClashErr (occ_name, ((ie1,avail1
,_
), (ie2,avail2
,_
))) sty
= hsep [ptext SLIT("The export items"), ppr sty ie1, ptext SLIT("and"), ppr sty ie2,
ptext SLIT("create conflicting exports for"), ppr sty occ_name]
dupExportWarn (occ_name, (_,_,times)) sty
= hsep [ppr sty occ_name,
ptext SLIT("mentioned"), text (speak_times (times+1)),
ptext SLIT("in export list")]
dupModuleExport mod times sty
= hsep [ptext SLIT("Module"), pprModule sty mod,
ptext SLIT("mentioned"), text (speak_times times),
ptext SLIT("in export list")]
speak_times :: Int{- >=1 -} -> String
speak_times t | t == 1 = "once"
| t == 2 = "twice"
| otherwise = show t ++ " times"
\end{code}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment