X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2FbasicTypes%2FRdrName.lhs;h=6b28786145bafddf41f3157dd13f1e90e92433d3;hp=2f7f7a8b50977d52d7294c78a4ca52819ca4175c;hb=66579ff945831c5fc9a17c58c722ff01f2268d76;hpb=b00b5bc04ff36a551552470060064f0b7d84ca30 diff --git a/compiler/basicTypes/RdrName.lhs b/compiler/basicTypes/RdrName.lhs index 2f7f7a8..6b28786 100644 --- a/compiler/basicTypes/RdrName.lhs +++ b/compiler/basicTypes/RdrName.lhs @@ -1,54 +1,72 @@ % +% (c) The University of Glasgow 2006 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -\section[RdrName]{@RdrName@} - \begin{code} + +-- | +-- #name_types# +-- GHC uses several kinds of name internally: +-- +-- * 'OccName.OccName': see "OccName#name_types" +-- +-- * 'RdrName.RdrName' is the type of names that come directly from the parser. They +-- have not yet had their scoping and binding resolved by the renamer and can be +-- thought of to a first approximation as an 'OccName.OccName' with an optional module +-- qualifier +-- +-- * 'Name.Name': see "Name#name_types" +-- +-- * 'Id.Id': see "Id#name_types" +-- +-- * 'Var.Var': see "Var#name_types" module RdrName ( + -- * The main type RdrName(..), -- Constructors exported only to BinIface - -- Construction + -- ** Construction mkRdrUnqual, mkRdrQual, mkUnqual, mkVarUnqual, mkQual, mkOrig, nameRdrName, getRdrName, mkDerivedRdrName, - -- Destruction - rdrNameOcc, setRdrNameSpace, + -- ** Destruction + rdrNameOcc, rdrNameSpace, setRdrNameSpace, isRdrDataCon, isRdrTyVar, isRdrTc, isQual, isQual_maybe, isUnqual, isOrig, isOrig_maybe, isExact, isExact_maybe, isSrcRdrName, - -- Printing; instance Outputable RdrName + -- ** Printing + showRdrName, - -- LocalRdrEnv + -- * Local mapping of 'RdrName' to 'Name.Name' LocalRdrEnv, emptyLocalRdrEnv, extendLocalRdrEnv, - lookupLocalRdrEnv, elemLocalRdrEnv, + lookupLocalRdrEnv, lookupLocalRdrOcc, elemLocalRdrEnv, - -- GlobalRdrEnv + -- * Global mapping of 'RdrName' to 'GlobalRdrElt's GlobalRdrEnv, emptyGlobalRdrEnv, mkGlobalRdrEnv, plusGlobalRdrEnv, lookupGlobalRdrEnv, extendGlobalRdrEnv, pprGlobalRdrEnv, globalRdrEnvElts, - lookupGRE_RdrName, lookupGRE_Name, hideSomeUnquals, + lookupGRE_RdrName, lookupGRE_Name, getGRE_NameQualifier_maybes, + hideSomeUnquals, findLocalDupsRdrEnv, - -- GlobalRdrElt, Provenance, ImportSpec - GlobalRdrElt(..), isLocalGRE, unQualOK, + -- ** Global 'RdrName' mapping elements: 'GlobalRdrElt', 'Provenance', 'ImportSpec' + GlobalRdrElt(..), isLocalGRE, unQualOK, qualSpecOK, unQualSpecOK, Provenance(..), pprNameProvenance, + Parent(..), ImportSpec(..), ImpDeclSpec(..), ImpItemSpec(..), - importSpecLoc, importSpecModule + importSpecLoc, importSpecModule, isExplicitItem ) where #include "HsVersions.h" -import OccName -import Module ( ModuleName, mkModuleNameFS, Module, moduleName ) -import Name ( Name, NamedThing(getName), nameModule, - nameOccName, isExternalName, nameSrcLoc ) -import Maybes ( mapCatMaybes ) -import SrcLoc ( isGoodSrcLoc, isGoodSrcSpan, srcLocSpan, SrcSpan ) -import FastString ( FastString ) +import Module +import Name +import Maybes +import SrcLoc +import FastString import Outputable -import Util ( thenCmp ) +import Util \end{code} %************************************************************************ @@ -58,27 +76,37 @@ import Util ( thenCmp ) %************************************************************************ \begin{code} -data RdrName +-- | Do not use the data constructors of RdrName directly: prefer the family +-- of functions that creates them, such as 'mkRdrUnqual' +data RdrName = Unqual OccName - -- Used for ordinary, unqualified occurrences + -- ^ Used for ordinary, unqualified occurrences, e.g. @x@, @y@ or @Foo@. + -- Create such a 'RdrName' with 'mkRdrUnqual' | Qual ModuleName OccName - -- A qualified name written by the user in - -- *source* code. The module isn't necessarily + -- ^ A qualified name written by the user in + -- /source/ code. The module isn't necessarily -- the module where the thing is defined; - -- just the one from which it is imported + -- just the one from which it is imported. + -- Examples are @Bar.x@, @Bar.y@ or @Bar.Foo@. + -- Create such a 'RdrName' with 'mkRdrQual' | Orig Module OccName - -- An original name; the module is the *defining* module. + -- ^ An original name; the module is the /defining/ module. -- This is used when GHC generates code that will be fed -- into the renamer (e.g. from deriving clauses), but where - -- we want to say "Use Prelude.map dammit". + -- we want to say \"Use Prelude.map dammit\". One of these + -- can be created with 'mkOrig' | Exact Name - -- We know exactly the Name. This is used - -- (a) when the parser parses built-in syntax like "[]" - -- and "(,)", but wants a RdrName from it - -- (b) by Template Haskell, when TH has generated a unique name + -- ^ We know exactly the 'Name'. This is used: + -- + -- (1) When the parser parses built-in syntax like @[]@ + -- and @(,)@, but wants a 'RdrName' from it + -- + -- (2) By Template Haskell, when TH has generated a unique name + -- + -- Such a 'RdrName' can be created by using 'getRdrName' on a 'Name' \end{code} @@ -95,19 +123,28 @@ rdrNameOcc (Unqual occ) = occ rdrNameOcc (Orig _ occ) = occ rdrNameOcc (Exact name) = nameOccName name +rdrNameSpace :: RdrName -> NameSpace +rdrNameSpace = occNameSpace . rdrNameOcc + setRdrNameSpace :: RdrName -> NameSpace -> RdrName --- This rather gruesome function is used mainly by the parser --- When parsing data T a = T | T1 Int --- we parse the data constructors as *types* because of parser ambiguities, --- so then we need to change the *type constr* to a *data constr* +-- ^ This rather gruesome function is used mainly by the parser. +-- When parsing: +-- +-- > data T a = T | T1 Int -- --- The original-name case *can* occur when parsing --- data [] a = [] | a : [a] --- For the orig-name case we return an unqualified name. +-- we parse the data constructors as /types/ because of parser ambiguities, +-- so then we need to change the /type constr/ to a /data constr/ +-- +-- The exact-name case /can/ occur when parsing: +-- +-- > data [] a = [] | a : [a] +-- +-- For the exact-name case we return an original name. setRdrNameSpace (Unqual occ) ns = Unqual (setOccNameSpace ns occ) setRdrNameSpace (Qual m occ) ns = Qual m (setOccNameSpace ns occ) setRdrNameSpace (Orig m occ) ns = Orig m (setOccNameSpace ns occ) -setRdrNameSpace (Exact n) ns = Orig (nameModule n) +setRdrNameSpace (Exact n) ns = ASSERT( isExternalName n ) + Orig (nameModule n) (setOccNameSpace ns (nameOccName n)) \end{code} @@ -123,9 +160,12 @@ mkOrig :: Module -> OccName -> RdrName mkOrig mod occ = Orig mod occ --------------- -mkDerivedRdrName :: Name -> (OccName -> OccName) -> (RdrName) +-- | Produce an original 'RdrName' whose module that of a parent 'Name' but its 'OccName' +-- is derived from that of it's parent using the supplied function +mkDerivedRdrName :: Name -> (OccName -> OccName) -> RdrName mkDerivedRdrName parent mk_occ - = mkOrig (nameModule parent) (mk_occ (nameOccName parent)) + = ASSERT2( isExternalName parent, ppr parent ) + mkOrig (nameModule parent) (mk_occ (nameOccName parent)) --------------- -- These two are used when parsing source files @@ -136,6 +176,8 @@ mkUnqual sp n = Unqual (mkOccNameFS sp n) mkVarUnqual :: FastString -> RdrName mkVarUnqual n = Unqual (mkVarOccFS n) +-- | Make a qualified 'RdrName' in the given namespace and where the 'ModuleName' and +-- the 'OccName' are taken from the first and second elements of the tuple respectively mkQual :: NameSpace -> (FastString, FastString) -> RdrName mkQual sp (m, n) = Qual (mkModuleNameFS m) (mkOccNameFS sp n) @@ -155,34 +197,46 @@ nukeExact n \end{code} \begin{code} +isRdrDataCon :: RdrName -> Bool +isRdrTyVar :: RdrName -> Bool +isRdrTc :: RdrName -> Bool + isRdrDataCon rn = isDataOcc (rdrNameOcc rn) isRdrTyVar rn = isTvOcc (rdrNameOcc rn) isRdrTc rn = isTcOcc (rdrNameOcc rn) +isSrcRdrName :: RdrName -> Bool isSrcRdrName (Unqual _) = True isSrcRdrName (Qual _ _) = True isSrcRdrName _ = False +isUnqual :: RdrName -> Bool isUnqual (Unqual _) = True -isUnqual other = False +isUnqual _ = False +isQual :: RdrName -> Bool isQual (Qual _ _) = True isQual _ = False +isQual_maybe :: RdrName -> Maybe (ModuleName, OccName) isQual_maybe (Qual m n) = Just (m,n) isQual_maybe _ = Nothing +isOrig :: RdrName -> Bool isOrig (Orig _ _) = True isOrig _ = False +isOrig_maybe :: RdrName -> Maybe (Module, OccName) isOrig_maybe (Orig m n) = Just (m,n) isOrig_maybe _ = Nothing +isExact :: RdrName -> Bool isExact (Exact _) = True -isExact other = False +isExact _ = False +isExact_maybe :: RdrName -> Maybe Name isExact_maybe (Exact n) = Just n -isExact_maybe other = Nothing +isExact_maybe _ = Nothing \end{code} @@ -204,6 +258,9 @@ instance OutputableBndr RdrName where | isTvOcc (rdrNameOcc n) = char '@' <+> ppr n | otherwise = ppr n +showRdrName :: RdrName -> String +showRdrName r = showSDoc (ppr r) + instance Eq RdrName where (Exact n1) == (Exact n2) = n1==n2 -- Convert exact to orig @@ -213,7 +270,7 @@ instance Eq RdrName where (Orig m1 o1) == (Orig m2 o2) = m1==m2 && o1==o2 (Qual m1 o1) == (Qual m2 o2) = m1==m2 && o1==o2 (Unqual o1) == (Unqual o2) = o1==o2 - r1 == r2 = False + _ == _ = False instance Ord RdrName where a <= b = case (a `compare` b) of { LT -> True; EQ -> True; GT -> False } @@ -230,7 +287,7 @@ instance Ord RdrName where -- } -- I think we can do without this conversion compare (Exact n1) (Exact n2) = n1 `compare` n2 - compare (Exact n1) n2 = LT + compare (Exact _) _ = LT compare (Unqual _) (Exact _) = GT compare (Unqual o1) (Unqual o2) = o1 `compare` o2 @@ -245,20 +302,18 @@ instance Ord RdrName where compare (Orig _ _) _ = GT \end{code} - - %************************************************************************ %* * LocalRdrEnv %* * %************************************************************************ -A LocalRdrEnv is used for local bindings (let, where, lambda, case) -It is keyed by OccName, because we never use it for qualified names. - \begin{code} +-- | This environment is used to store local bindings (@let@, @where@, lambda, @case@). +-- It is keyed by OccName, because we never use it for qualified names type LocalRdrEnv = OccEnv Name +emptyLocalRdrEnv :: LocalRdrEnv emptyLocalRdrEnv = emptyOccEnv extendLocalRdrEnv :: LocalRdrEnv -> [Name] -> LocalRdrEnv @@ -266,9 +321,12 @@ extendLocalRdrEnv env names = extendOccEnvList env [(nameOccName n, n) | n <- names] lookupLocalRdrEnv :: LocalRdrEnv -> RdrName -> Maybe Name -lookupLocalRdrEnv env (Exact name) = Just name +lookupLocalRdrEnv _ (Exact name) = Just name lookupLocalRdrEnv env (Unqual occ) = lookupOccEnv env occ -lookupLocalRdrEnv env other = Nothing +lookupLocalRdrEnv _ _ = Nothing + +lookupLocalRdrOcc :: LocalRdrEnv -> OccName -> Maybe Name +lookupLocalRdrOcc env occ = lookupOccEnv env occ elemLocalRdrEnv :: RdrName -> LocalRdrEnv -> Bool elemLocalRdrEnv rdr_name env @@ -276,7 +334,6 @@ elemLocalRdrEnv rdr_name env | otherwise = False \end{code} - %************************************************************************ %* * GlobalRdrEnv @@ -285,34 +342,59 @@ elemLocalRdrEnv rdr_name env \begin{code} type GlobalRdrEnv = OccEnv [GlobalRdrElt] - -- Keyed by OccName; when looking up a qualified name - -- we look up the OccName part, and then check the Provenance - -- to see if the appropriate qualification is valid. This - -- saves routinely doubling the size of the env by adding both - -- qualified and unqualified names to the domain. - -- - -- The list in the range is reqd because there may be name clashes - -- These only get reported on lookup, not on construction +-- ^ Keyed by 'OccName'; when looking up a qualified name +-- we look up the 'OccName' part, and then check the 'Provenance' +-- to see if the appropriate qualification is valid. This +-- saves routinely doubling the size of the env by adding both +-- qualified and unqualified names to the domain. +-- +-- The list in the codomain is required because there may be name clashes +-- These only get reported on lookup, not on construction +-- +-- INVARIANT: All the members of the list have distinct +-- 'gre_name' fields; that is, no duplicate Names - -- INVARIANT: All the members of the list have distinct - -- gre_name fields; that is, no duplicate Names +-- | An element of the 'GlobalRdrEnv' +data GlobalRdrElt + = GRE { gre_name :: Name, + gre_par :: Parent, + gre_prov :: Provenance -- ^ Why it's in scope + } +data Parent = NoParent | ParentIs Name + deriving (Eq) + +instance Outputable Parent where + ppr NoParent = empty + ppr (ParentIs n) = ptext (sLit "parent:") <> ppr n + + +plusParent :: Parent -> Parent -> Parent +plusParent p1 p2 = ASSERT2( p1 == p2, parens (ppr p1) <+> parens (ppr p2) ) + p1 + +{- Why so complicated? -=chak +plusParent :: Parent -> Parent -> Parent +plusParent NoParent rel = + ASSERT2( case rel of { NoParent -> True; other -> False }, + ptext (sLit "plusParent[NoParent]: ") <+> ppr rel ) + NoParent +plusParent (ParentIs n) rel = + ASSERT2( case rel of { ParentIs m -> n==m; other -> False }, + ptext (sLit "plusParent[ParentIs]:") <+> ppr n <> comma <+> ppr rel ) + ParentIs n + -} + +emptyGlobalRdrEnv :: GlobalRdrEnv emptyGlobalRdrEnv = emptyOccEnv globalRdrEnvElts :: GlobalRdrEnv -> [GlobalRdrElt] globalRdrEnvElts env = foldOccEnv (++) [] env -data GlobalRdrElt - = GRE { gre_name :: Name, - gre_prov :: Provenance -- Why it's in scope - } - instance Outputable GlobalRdrElt where - ppr gre = ppr name <+> parens (pprNameProvenance gre) + ppr gre = ppr name <+> parens (ppr (gre_par gre) <+> pprNameProvenance gre) where name = gre_name gre - pp_parent (Just p) = brackets (text "parent:" <+> ppr p) - pp_parent Nothing = empty pprGlobalRdrEnv :: GlobalRdrEnv -> SDoc pprGlobalRdrEnv env @@ -325,7 +407,7 @@ pprGlobalRdrEnv env \begin{code} lookupGlobalRdrEnv :: GlobalRdrEnv -> OccName -> [GlobalRdrElt] -lookupGlobalRdrEnv env rdr_name = case lookupOccEnv env rdr_name of +lookupGlobalRdrEnv env occ_name = case lookupOccEnv env occ_name of Nothing -> [] Just gres -> gres @@ -346,22 +428,31 @@ lookupGRE_Name env name = [ gre | gre <- lookupGlobalRdrEnv env (nameOccName name), gre_name gre == name ] +getGRE_NameQualifier_maybes :: GlobalRdrEnv -> Name -> [Maybe [ModuleName]] +getGRE_NameQualifier_maybes env + = map qualifier_maybe . map gre_prov . lookupGRE_Name env + where qualifier_maybe LocalDef = Nothing + qualifier_maybe (Imported iss) = Just $ map (is_as . is_decl) iss pickGREs :: RdrName -> [GlobalRdrElt] -> [GlobalRdrElt] --- Take a list of GREs which have the right OccName +-- ^ Take a list of GREs which have the right OccName -- Pick those GREs that are suitable for this RdrName -- And for those, keep only only the Provenances that are suitable -- --- Consider +-- Consider: +-- +-- @ -- module A ( f ) where -- import qualified Foo( f ) -- import Baz( f ) -- f = undefined --- Let's suppose that Foo.f and Baz.f are the same entity really. --- The export of f is ambiguous because it's in scope from the local def --- and the import. The lookup of (Unqual f) should return a GRE for --- the locally-defined f, and a GRE for the imported f, with a *single* --- provenance, namely the one for Baz(f). +-- @ +-- +-- Let's suppose that @Foo.f@ and @Baz.f@ are the same entity really. +-- The export of @f@ is ambiguous because it's in scope from the local def +-- and the import. The lookup of @Unqual f@ should return a GRE for +-- the locally-defined @f@, and a GRE for the imported @f@, with a /single/ +-- provenance, namely the one for @Baz(f)@. pickGREs rdr_name gres = mapCatMaybes pick gres where @@ -393,12 +484,12 @@ pickGREs rdr_name gres isLocalGRE :: GlobalRdrElt -> Bool isLocalGRE (GRE {gre_prov = LocalDef}) = True -isLocalGRE other = False +isLocalGRE _ = False unQualOK :: GlobalRdrElt -> Bool --- An unqualifed version of this thing is in scope +-- ^ Test if an unqualifed version of this thing would be in scope unQualOK (GRE {gre_prov = LocalDef}) = True -unQualOK (GRE {gre_prov = Imported is}) = not (all (is_qual . is_decl) is) +unQualOK (GRE {gre_prov = Imported is}) = any unQualSpecOK is plusGlobalRdrEnv :: GlobalRdrEnv -> GlobalRdrEnv -> GlobalRdrEnv plusGlobalRdrEnv env1 env2 = plusOccEnv_C (foldr insertGRE) env1 env2 @@ -411,6 +502,27 @@ mkGlobalRdrEnv gres (nameOccName (gre_name gre)) [gre] +findLocalDupsRdrEnv :: GlobalRdrEnv -> [OccName] -> (GlobalRdrEnv, [[Name]]) +-- ^ For each 'OccName', see if there are multiple local definitions +-- for it. If so, remove all but one (to suppress subsequent error messages) +-- and return a list of the duplicate bindings +findLocalDupsRdrEnv rdr_env occs + = go rdr_env [] occs + where + go rdr_env dups [] = (rdr_env, dups) + go rdr_env dups (occ:occs) + = case filter isLocalGRE gres of + [] -> WARN( True, ppr occ <+> ppr rdr_env ) + go rdr_env dups occs -- Weird! No binding for occ + [_] -> go rdr_env dups occs -- The common case + dup_gres -> go (extendOccEnv rdr_env occ (head dup_gres : nonlocal_gres)) + (map gre_name dup_gres : dups) + occs + where + gres = lookupOccEnv rdr_env occ `orElse` [] + nonlocal_gres = filterOut isLocalGRE gres + + insertGRE :: GlobalRdrElt -> [GlobalRdrElt] -> [GlobalRdrElt] insertGRE new_g [] = [new_g] insertGRE new_g (old_g : old_gs) @@ -423,15 +535,19 @@ plusGRE :: GlobalRdrElt -> GlobalRdrElt -> GlobalRdrElt -- Used when the gre_name fields match plusGRE g1 g2 = GRE { gre_name = gre_name g1, - gre_prov = gre_prov g1 `plusProv` gre_prov g2 } + gre_prov = gre_prov g1 `plusProv` gre_prov g2, + gre_par = gre_par g1 `plusParent` gre_par g2 } hideSomeUnquals :: GlobalRdrEnv -> [OccName] -> GlobalRdrEnv --- Hide any unqualified bindings for the specified OccNames +-- ^ Hide any unqualified bindings for the specified OccNames -- This is used in TH, when renaming a declaration bracket --- [d| foo = ... |] --- We want unqualified 'foo' in "..." to mean this foo, not --- the one from the enclosing module. But the *qualified* name --- from the enclosing moudule must certainly still be avaialable +-- +-- > [d| foo = ... |] +-- +-- We want unqualified @foo@ in "..." to mean this @foo@, not +-- the one from the enclosing module. But the /qualified/ name +-- from the enclosing module must certainly still be available + -- Seems like 5 times as much work as it deserves! hideSomeUnquals rdr_env occs = foldr hide rdr_env occs @@ -440,9 +556,9 @@ hideSomeUnquals rdr_env occs | Just gres <- lookupOccEnv env occ = extendOccEnv env occ (map qual_gre gres) | otherwise = env qual_gre gre@(GRE { gre_name = name, gre_prov = LocalDef }) - = GRE { gre_name = name, gre_prov = Imported [imp_spec] } + = gre { gre_prov = Imported [imp_spec] } where -- Local defs get transfomed to (fake) imported things - mod = moduleName (nameModule name) + mod = ASSERT2( isExternalName name, ppr name) moduleName (nameModule name) imp_spec = ImpSpec { is_item = ImpAll, is_decl = decl_spec } decl_spec = ImpDeclSpec { is_mod = mod, is_as = mod, is_qual = True, @@ -455,53 +571,66 @@ hideSomeUnquals rdr_env occs = spec { is_decl = decl_spec { is_qual = True } } \end{code} - %************************************************************************ %* * Provenance %* * %************************************************************************ -The "provenance" of something says how it came to be in scope. -It's quite elaborate so that we can give accurate unused-name warnings. - \begin{code} +-- | The 'Provenance' of something says how it came to be in scope. +-- It's quite elaborate so that we can give accurate unused-name warnings. data Provenance - = LocalDef -- Defined locally - | Imported -- Imported - [ImportSpec] -- INVARIANT: non-empty + = LocalDef -- ^ The thing was defined locally + | Imported + [ImportSpec] -- ^ The thing was imported. + -- + -- INVARIANT: the list of 'ImportSpec' is non-empty data ImportSpec = ImpSpec { is_decl :: ImpDeclSpec, is_item :: ImpItemSpec } deriving( Eq, Ord ) -data ImpDeclSpec -- Describes a particular import declaration - -- Shared among all the Provenaces for that decl +-- | Describes a particular import declaration and is +-- shared among all the 'Provenance's for that decl +data ImpDeclSpec = ImpDeclSpec { - is_mod :: ModuleName, -- 'import Muggle' - -- Note the Muggle may well not be - -- the defining module for this thing! - -- TODO: either should be Module, or there - -- should be a Maybe PackageId here too. - is_as :: ModuleName, -- 'as M' (or 'Muggle' if there is no 'as' clause) - is_qual :: Bool, -- True <=> qualified (only) - is_dloc :: SrcSpan -- Location of import declaration + is_mod :: ModuleName, -- ^ Module imported, e.g. @import Muggle@ + -- Note the @Muggle@ may well not be + -- the defining module for this thing! + + -- TODO: either should be Module, or there + -- should be a Maybe PackageId here too. + is_as :: ModuleName, -- ^ Import alias, e.g. from @as M@ (or @Muggle@ if there is no @as@ clause) + is_qual :: Bool, -- ^ Was this import qualified? + is_dloc :: SrcSpan -- ^ The location of the import declaration } -data ImpItemSpec -- Describes import info a particular Name - = ImpAll -- The import had no import list, - -- or had a hiding list +-- | Describes import info a particular Name +data ImpItemSpec + = ImpAll -- ^ The import had no import list, + -- or had a hiding list - | ImpSome { -- The import had an import list + | ImpSome { is_explicit :: Bool, is_iloc :: SrcSpan -- Location of the import item - } - -- The is_explicit field is True iff the thing was named - -- *explicitly* in the import specs rather - -- than being imported as part of a "..." group - -- e.g. import C( T(..) ) - -- Here the constructors of T are not named explicitly; - -- only T is named explicitly. + } -- ^ The import had an import list. + -- The 'is_explicit' field is @True@ iff the thing was named + -- /explicitly/ in the import specs rather + -- than being imported as part of a "..." group. Consider: + -- + -- > import C( T(..) ) + -- + -- Here the constructors of @T@ are not named explicitly; + -- only @T@ is named explicitly. + +unQualSpecOK :: ImportSpec -> Bool +-- ^ Is in scope unqualified? +unQualSpecOK is = not (is_qual (is_decl is)) + +qualSpecOK :: ModuleName -> ImportSpec -> Bool +-- ^ Is in scope qualified with the given module? +qualSpecOK mod is = mod == is_as (is_decl is) importSpecLoc :: ImportSpec -> SrcSpan importSpecLoc (ImpSpec decl ImpAll) = is_dloc decl @@ -510,6 +639,10 @@ importSpecLoc (ImpSpec _ item) = is_iloc item importSpecModule :: ImportSpec -> ModuleName importSpecModule is = is_mod (is_decl is) +isExplicitItem :: ImpItemSpec -> Bool +isExplicitItem ImpAll = False +isExplicitItem (ImpSome {is_explicit = exp}) = exp + -- Note [Comparing provenance] -- Comparison of provenance is just used for grouping -- error messages (in RnEnv.warnUnusedBinds) @@ -545,29 +678,30 @@ plusProv :: Provenance -> Provenance -> Provenance -- defined, and one might refer to it with a qualified name from -- the import -- but I'm going to ignore that because it makes -- the isLocalGRE predicate so much nicer this way -plusProv LocalDef LocalDef = panic "plusProv" -plusProv LocalDef p2 = LocalDef -plusProv p1 LocalDef = LocalDef +plusProv LocalDef LocalDef = panic "plusProv" +plusProv LocalDef _ = LocalDef +plusProv _ LocalDef = LocalDef plusProv (Imported is1) (Imported is2) = Imported (is1++is2) pprNameProvenance :: GlobalRdrElt -> SDoc --- Print out the place where the name was imported +-- ^ Print out the place where the name was imported pprNameProvenance (GRE {gre_name = name, gre_prov = LocalDef}) - = ptext SLIT("defined at") <+> ppr (nameSrcLoc name) + = ptext (sLit "defined at") <+> ppr (nameSrcLoc name) pprNameProvenance (GRE {gre_name = name, gre_prov = Imported whys}) = case whys of - (why:whys) -> sep [ppr why, nest 2 (ppr_defn (nameSrcLoc name))] + (why:_) -> sep [ppr why, nest 2 (ppr_defn (nameSrcLoc name))] [] -> panic "pprNameProvenance" -- If we know the exact definition point (which we may do with GHCi) -- then show that too. But not if it's just "imported from X". -ppr_defn loc | isGoodSrcLoc loc = parens (ptext SLIT("defined at") <+> ppr loc) +ppr_defn :: SrcLoc -> SDoc +ppr_defn loc | isGoodSrcLoc loc = parens (ptext (sLit "defined at") <+> ppr loc) | otherwise = empty instance Outputable ImportSpec where ppr imp_spec - = ptext SLIT("imported from") <+> ppr (importSpecModule imp_spec) - <+> if isGoodSrcSpan loc then ptext SLIT("at") <+> ppr loc + = ptext (sLit "imported from") <+> ppr (importSpecModule imp_spec) + <+> if isGoodSrcSpan loc then ptext (sLit "at") <+> ppr loc else empty where loc = importSpecLoc imp_spec