{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes        #-}
{-# LANGUAGE TypeFamilies      #-}

module GHC.Tc.Gen.Export (rnExports, exports_from_avail) where

import GHC.Prelude

import GHC.Hs
import GHC.Types.FieldLabel
import GHC.Builtin.Names
import GHC.Tc.Errors.Types
import GHC.Tc.Utils.Monad
import GHC.Tc.Utils.Env
import GHC.Tc.Utils.TcType
import GHC.Rename.Names
import GHC.Rename.Env
import GHC.Rename.Unbound ( reportUnboundName )
import GHC.Utils.Error
import GHC.Unit.Module
import GHC.Unit.Module.Imported
import GHC.Core.TyCon
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Core.ConLike
import GHC.Core.PatSyn
import GHC.Data.Maybe
import GHC.Data.FastString (fsLit)
import GHC.Driver.Env

import GHC.Types.Unique.Set
import GHC.Types.SrcLoc as SrcLoc
import GHC.Types.Name
import GHC.Types.Name.Env
import GHC.Types.Name.Set
import GHC.Types.Avail
import GHC.Types.SourceFile
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Name.Reader

import Control.Monad
import GHC.Driver.Session
import GHC.Parser.PostProcess ( setRdrNameSpace )
import Data.Either            ( partitionEithers )
import GHC.Rename.Doc

{-
************************************************************************
*                                                                      *
\subsection{Export list processing}
*                                                                      *
************************************************************************

Processing the export list.

You might think that we should record things that appear in the export
list as ``occurrences'' (using @addOccurrenceName@), but you'd be
wrong.  We do check (here) that they are in scope, but there is no
need to slurp in their actual declaration (which is what
@addOccurrenceName@ forces).

Indeed, doing so would big trouble when compiling @PrelBase@, because
it re-exports @GHC@, which includes @takeMVar#@, whose type includes
@ConcBase.StateAndSynchVar#@, and so on...

Note [Exports of data families]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suppose you see (#5306)
        module M where
          import X( F )
          data instance F Int = FInt
What does M export?  AvailTC F [FInt]
                  or AvailTC F [F,FInt]?
The former is strictly right because F isn't defined in this module.
But then you can never do an explicit import of M, thus
    import M( F( FInt ) )
because F isn't exported by M.  Nor can you import FInt alone from here
    import M( FInt )
because we don't have syntax to support that.  (It looks like an import of
the type FInt.)

At one point I implemented a compromise:
  * When constructing exports with no export list, or with module M(
    module M ), we add the parent to the exports as well.
  * But not when you see module M( f ), even if f is a
    class method with a parent.
  * Nor when you see module M( module N ), with N /= M.

But the compromise seemed too much of a hack, so we backed it out.
You just have to use an explicit export list:
    module M( F(..) ) where ...

Note [Avails of associated data families]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Suppose you have (#16077)

    {-# LANGUAGE TypeFamilies #-}
    module A (module A) where

    class    C a  where { data T a }
    instance C () where { data T () = D }

Because @A@ is exported explicitly, GHC tries to produce an export list
from the @GlobalRdrEnv@. In this case, it pulls out the following:

    [ C defined at A.hs:4:1
    , T parent:C defined at A.hs:4:23
    , D parent:T defined at A.hs:5:35 ]

If map these directly into avails, (via 'availFromGRE'), we get
@[C{C;}, C{T;}, T{D;}]@, which eventually gets merged into @[C{C, T;}, T{D;}]@.
That's not right, because @T{D;}@ violates the AvailTC invariant: @T@ is
exported, but it isn't the first entry in the avail!

We work around this issue by expanding GREs where the parent and child
are both type constructors into two GRES.

    T parent:C defined at A.hs:4:23

      =>

    [ T parent:C defined at A.hs:4:23
    , T defined at A.hs:4:23 ]

Then, we get  @[C{C;}, C{T;}, T{T;}, T{D;}]@, which eventually gets merged
into @[C{C, T;}, T{T, D;}]@ (which satisfies the AvailTC invariant).
-}

data ExportAccum        -- The type of the accumulating parameter of
                        -- the main worker function in rnExports
     = ExportAccum
        ExportOccMap           --  Tracks exported occurrence names
        (UniqSet ModuleName)   --  Tracks (re-)exported module names

emptyExportAccum :: ExportAccum
emptyExportAccum :: ExportAccum
emptyExportAccum = ExportOccMap -> UniqSet ModuleName -> ExportAccum
ExportAccum forall a. OccEnv a
emptyOccEnv forall a. UniqSet a
emptyUniqSet

accumExports :: (ExportAccum -> x -> TcRn (Maybe (ExportAccum, y)))
             -> [x]
             -> TcRn [y]
accumExports :: forall x y.
(ExportAccum -> x -> TcRn (Maybe (ExportAccum, y)))
-> [x] -> TcRn [y]
accumExports ExportAccum -> x -> TcRn (Maybe (ExportAccum, y))
f = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. [Maybe a] -> [a]
catMaybes forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) (t :: * -> *) acc x y.
(Monad m, Traversable t) =>
(acc -> x -> m (acc, y)) -> acc -> t x -> m (acc, t y)
mapAccumLM ExportAccum
-> x -> IOEnv (Env TcGblEnv TcLclEnv) (ExportAccum, Maybe y)
f' ExportAccum
emptyExportAccum
  where f' :: ExportAccum
-> x -> IOEnv (Env TcGblEnv TcLclEnv) (ExportAccum, Maybe y)
f' ExportAccum
acc x
x = do
          Maybe (Maybe (ExportAccum, y))
m <- forall r. TcRn r -> TcRn (Maybe r)
attemptM (ExportAccum -> x -> TcRn (Maybe (ExportAccum, y))
f ExportAccum
acc x
x)
          forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ case Maybe (Maybe (ExportAccum, y))
m of
            Just (Just (ExportAccum
acc', y
y)) -> (ExportAccum
acc', forall a. a -> Maybe a
Just y
y)
            Maybe (Maybe (ExportAccum, y))
_                     -> (ExportAccum
acc, forall a. Maybe a
Nothing)

type ExportOccMap = OccEnv (GreName, IE GhcPs)
        -- Tracks what a particular exported OccName
        --   in an export list refers to, and which item
        --   it came from.  It's illegal to export two distinct things
        --   that have the same occurrence name

rnExports :: Bool       -- False => no 'module M(..) where' header at all
          -> Maybe (LocatedL [LIE GhcPs]) -- Nothing => no explicit export list
          -> RnM TcGblEnv

        -- Complains if two distinct exports have same OccName
        -- Warns about identical exports.
        -- Complains about exports items not in scope

rnExports :: Bool -> Maybe (LocatedL [LIE GhcPs]) -> RnM TcGblEnv
rnExports Bool
explicit_mod Maybe (LocatedL [LIE GhcPs])
exports
 = forall r. TcM r -> TcM r
checkNoErrs forall a b. (a -> b) -> a -> b
$   -- Fail if anything in rnExports finds
                   -- an error fails, to avoid error cascade
   forall gbl lcl a.
WarningFlag -> TcRnIf gbl lcl a -> TcRnIf gbl lcl a
unsetWOptM WarningFlag
Opt_WarnWarningsDeprecations forall a b. (a -> b) -> a -> b
$
       -- Do not report deprecations arising from the export
       -- list, to avoid bleating about re-exporting a deprecated
       -- thing (especially via 'module Foo' export item)
   do   { HscEnv
hsc_env <- forall gbl lcl. TcRnIf gbl lcl HscEnv
getTopEnv
        ; TcGblEnv
tcg_env <- forall gbl lcl. TcRnIf gbl lcl gbl
getGblEnv
        ; let dflags :: DynFlags
dflags = HscEnv -> DynFlags
hsc_dflags HscEnv
hsc_env
              TcGblEnv { tcg_mod :: TcGblEnv -> Module
tcg_mod     = Module
this_mod
                       , tcg_rdr_env :: TcGblEnv -> GlobalRdrEnv
tcg_rdr_env = GlobalRdrEnv
rdr_env
                       , tcg_imports :: TcGblEnv -> ImportAvails
tcg_imports = ImportAvails
imports
                       , tcg_src :: TcGblEnv -> HscSource
tcg_src     = HscSource
hsc_src } = TcGblEnv
tcg_env
              default_main :: RdrName
default_main | HomeUnitEnv -> Module
mainModIs (HscEnv -> HomeUnitEnv
hsc_HUE HscEnv
hsc_env) forall a. Eq a => a -> a -> Bool
== Module
this_mod
                           , Just String
main_fun <- DynFlags -> Maybe String
mainFunIs DynFlags
dflags
                           = NameSpace -> FastString -> RdrName
mkUnqual NameSpace
varName (String -> FastString
fsLit String
main_fun)
                           | Bool
otherwise
                           = RdrName
main_RDR_Unqual
        ; Bool
has_main <- (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. Foldable t => t a -> Bool
null) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RdrName -> RnM [Name]
lookupInfoOccRn RdrName
default_main -- #17832

        -- If a module has no explicit header, and it has one or more main
        -- functions in scope, then add a header like
        -- "module Main(main) where ..."                               #13839
        -- See Note [Modules without a module header]
        ; let real_exports :: Maybe (LocatedL [LIE GhcPs])
real_exports
                 | Bool
explicit_mod = Maybe (LocatedL [LIE GhcPs])
exports
                 | Bool
has_main
                          = forall a. a -> Maybe a
Just (forall a an. a -> LocatedAn an a
noLocA [forall a an. a -> LocatedAn an a
noLocA (forall pass. XIEVar pass -> LIEWrappedName pass -> IE pass
IEVar NoExtField
noExtField
                                     (forall a an. a -> LocatedAn an a
noLocA (forall p. XIEName p -> LIdP p -> IEWrappedName p
IEName NoExtField
noExtField forall a b. (a -> b) -> a -> b
$ forall a an. a -> LocatedAn an a
noLocA RdrName
default_main)))])
                        -- ToDo: the 'noLoc' here is unhelpful if 'main'
                        --       turns out to be out of scope
                 | Bool
otherwise = forall a. Maybe a
Nothing

        -- Rename the export list
        ; let do_it :: RnM (Maybe [(LIE GhcRn, [AvailInfo])], [AvailInfo])
do_it = Maybe (LocatedL [LIE GhcPs])
-> GlobalRdrEnv
-> ImportAvails
-> Module
-> RnM (Maybe [(LIE GhcRn, [AvailInfo])], [AvailInfo])
exports_from_avail Maybe (LocatedL [LIE GhcPs])
real_exports GlobalRdrEnv
rdr_env ImportAvails
imports Module
this_mod
        ; (Maybe [(GenLocated SrcSpanAnnA (IE GhcRn), [AvailInfo])]
rn_exports, [AvailInfo]
final_avails)
            <- if HscSource
hsc_src forall a. Eq a => a -> a -> Bool
== HscSource
HsigFile
                then do (Maybe
  (Maybe [(GenLocated SrcSpanAnnA (IE GhcRn), [AvailInfo])],
   [AvailInfo])
mb_r, Messages TcRnMessage
msgs) <- forall a. TcRn a -> TcRn (Maybe a, Messages TcRnMessage)
tryTc RnM (Maybe [(LIE GhcRn, [AvailInfo])], [AvailInfo])
do_it
                        case Maybe
  (Maybe [(GenLocated SrcSpanAnnA (IE GhcRn), [AvailInfo])],
   [AvailInfo])
mb_r of
                            Just (Maybe [(GenLocated SrcSpanAnnA (IE GhcRn), [AvailInfo])],
 [AvailInfo])
r  -> forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe [(GenLocated SrcSpanAnnA (IE GhcRn), [AvailInfo])],
 [AvailInfo])
r
                            Maybe
  (Maybe [(GenLocated SrcSpanAnnA (IE GhcRn), [AvailInfo])],
   [AvailInfo])
Nothing -> Messages TcRnMessage -> TcRn ()
addMessages Messages TcRnMessage
msgs forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall env a. IOEnv env a
failM
                else forall r. TcM r -> TcM r
checkNoErrs RnM (Maybe [(LIE GhcRn, [AvailInfo])], [AvailInfo])
do_it

        -- Final processing
        ; let final_ns :: NameSet
final_ns = [AvailInfo] -> NameSet
availsToNameSetWithSelectors [AvailInfo]
final_avails

        ; String -> SDoc -> TcRn ()
traceRn String
"rnExports: Exports:" (forall a. Outputable a => a -> SDoc
ppr [AvailInfo]
final_avails)

        ; forall (m :: * -> *) a. Monad m => a -> m a
return (TcGblEnv
tcg_env { tcg_exports :: [AvailInfo]
tcg_exports    = [AvailInfo]
final_avails
                          , tcg_rn_exports :: Maybe [(LIE GhcRn, [AvailInfo])]
tcg_rn_exports = case TcGblEnv -> Maybe [(LIE GhcRn, [AvailInfo])]
tcg_rn_exports TcGblEnv
tcg_env of
                                                Maybe [(LIE GhcRn, [AvailInfo])]
Nothing -> forall a. Maybe a
Nothing
                                                Just [(LIE GhcRn, [AvailInfo])]
_  -> Maybe [(GenLocated SrcSpanAnnA (IE GhcRn), [AvailInfo])]
rn_exports
                          , tcg_dus :: DefUses
tcg_dus = TcGblEnv -> DefUses
tcg_dus TcGblEnv
tcg_env DefUses -> DefUses -> DefUses
`plusDU`
                                      NameSet -> DefUses
usesOnly NameSet
final_ns }) }

exports_from_avail :: Maybe (LocatedL [LIE GhcPs])
                         -- ^ 'Nothing' means no explicit export list
                   -> GlobalRdrEnv
                   -> ImportAvails
                         -- ^ Imported modules; this is used to test if a
                         -- @module Foo@ export is valid (it's not valid
                         -- if we didn't import @Foo@!)
                   -> Module
                   -> RnM (Maybe [(LIE GhcRn, Avails)], Avails)
                         -- (Nothing, _) <=> no explicit export list
                         -- if explicit export list is present it contains
                         -- each renamed export item together with its exported
                         -- names.

exports_from_avail :: Maybe (LocatedL [LIE GhcPs])
-> GlobalRdrEnv
-> ImportAvails
-> Module
-> RnM (Maybe [(LIE GhcRn, [AvailInfo])], [AvailInfo])
exports_from_avail Maybe (LocatedL [LIE GhcPs])
Nothing GlobalRdrEnv
rdr_env ImportAvails
_imports Module
_this_mod
   -- The same as (module M) where M is the current module name,
   -- so that's how we handle it, except we also export the data family
   -- when a data instance is exported.
  = do {
    ; TcRnMessage -> TcRn ()
addDiagnostic
        (ModuleName -> TcRnMessage
TcRnMissingExportList forall a b. (a -> b) -> a -> b
$ forall unit. GenModule unit -> ModuleName
moduleName Module
_this_mod)
    ; let avails :: [AvailInfo]
avails =
            forall a b. (a -> b) -> [a] -> [b]
map AvailInfo -> AvailInfo
fix_faminst forall b c a. (b -> c) -> (a -> b) -> a -> c
. [GlobalRdrElt] -> [AvailInfo]
gresToAvailInfo
              forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [a]
filter GlobalRdrElt -> Bool
isLocalGRE forall b c a. (b -> c) -> (a -> b) -> a -> c
. GlobalRdrEnv -> [GlobalRdrElt]
globalRdrEnvElts forall a b. (a -> b) -> a -> b
$ GlobalRdrEnv
rdr_env
    ; forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. Maybe a
Nothing, [AvailInfo]
avails) }
  where
    -- #11164: when we define a data instance
    -- but not data family, re-export the family
    -- Even though we don't check whether this is actually a data family
    -- only data families can locally define subordinate things (`ns` here)
    -- without locally defining (and instead importing) the parent (`n`)
    fix_faminst :: AvailInfo -> AvailInfo
fix_faminst avail :: AvailInfo
avail@(AvailTC Name
n [GreName]
ns)
      | AvailInfo -> Bool
availExportsDecl AvailInfo
avail = AvailInfo
avail
      | Bool
otherwise = Name -> [GreName] -> AvailInfo
AvailTC Name
n (Name -> GreName
NormalGreName Name
nforall a. a -> [a] -> [a]
:[GreName]
ns)
    fix_faminst AvailInfo
avail = AvailInfo
avail


exports_from_avail (Just (L SrcSpanAnnL
_ [LIE GhcPs]
rdr_items)) GlobalRdrEnv
rdr_env ImportAvails
imports Module
this_mod
  = do [(GenLocated SrcSpanAnnA (IE GhcRn), [AvailInfo])]
ie_avails <- forall x y.
(ExportAccum -> x -> TcRn (Maybe (ExportAccum, y)))
-> [x] -> TcRn [y]
accumExports ExportAccum
-> LIE GhcPs -> RnM (Maybe (ExportAccum, (LIE GhcRn, [AvailInfo])))
do_litem [LIE GhcPs]
rdr_items
       let final_exports :: [AvailInfo]
final_exports = [AvailInfo] -> [AvailInfo]
nubAvails (forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall a b. (a, b) -> b
snd [(GenLocated SrcSpanAnnA (IE GhcRn), [AvailInfo])]
ie_avails) -- Combine families
       forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just [(GenLocated SrcSpanAnnA (IE GhcRn), [AvailInfo])]
ie_avails, [AvailInfo]
final_exports)
  where
    do_litem :: ExportAccum -> LIE GhcPs
             -> RnM (Maybe (ExportAccum, (LIE GhcRn, Avails)))
    do_litem :: ExportAccum
-> LIE GhcPs -> RnM (Maybe (ExportAccum, (LIE GhcRn, [AvailInfo])))
do_litem ExportAccum
acc LIE GhcPs
lie = forall a. SrcSpan -> TcRn a -> TcRn a
setSrcSpan (forall a e. GenLocated (SrcSpanAnn' a) e -> SrcSpan
getLocA LIE GhcPs
lie) (ExportAccum
-> LIE GhcPs -> RnM (Maybe (ExportAccum, (LIE GhcRn, [AvailInfo])))
exports_from_item ExportAccum
acc LIE GhcPs
lie)

    -- Maps a parent to its in-scope children
    kids_env :: NameEnv [GlobalRdrElt]
    kids_env :: NameEnv [GlobalRdrElt]
kids_env = [GlobalRdrElt] -> NameEnv [GlobalRdrElt]
mkChildEnv (GlobalRdrEnv -> [GlobalRdrElt]
globalRdrEnvElts GlobalRdrEnv
rdr_env)

    -- See Note [Avails of associated data families]
    expand_tyty_gre :: GlobalRdrElt -> [GlobalRdrElt]
    expand_tyty_gre :: GlobalRdrElt -> [GlobalRdrElt]
expand_tyty_gre (gre :: GlobalRdrElt
gre@GRE { gre_par :: GlobalRdrElt -> Parent
gre_par = ParentIs Name
p })
      | Name -> Bool
isTyConName Name
p, Name -> Bool
isTyConName (GlobalRdrElt -> Name
greMangledName GlobalRdrElt
gre) = [GlobalRdrElt
gre, GlobalRdrElt
gre{ gre_par :: Parent
gre_par = Parent
NoParent }]
    expand_tyty_gre GlobalRdrElt
gre = [GlobalRdrElt
gre]

    imported_modules :: [ModuleName]
imported_modules = [ ImportedModsVal -> ModuleName
imv_name ImportedModsVal
imv
                       | [ImportedBy]
xs <- forall a. ModuleEnv a -> [a]
moduleEnvElts forall a b. (a -> b) -> a -> b
$ ImportAvails -> ImportedMods
imp_mods ImportAvails
imports
                       , ImportedModsVal
imv <- [ImportedBy] -> [ImportedModsVal]
importedByUser [ImportedBy]
xs ]

    exports_from_item :: ExportAccum -> LIE GhcPs
                      -> RnM (Maybe (ExportAccum, (LIE GhcRn, Avails)))
    exports_from_item :: ExportAccum
-> LIE GhcPs -> RnM (Maybe (ExportAccum, (LIE GhcRn, [AvailInfo])))
exports_from_item (ExportAccum ExportOccMap
occs UniqSet ModuleName
earlier_mods)
                      (L SrcSpanAnnA
loc ie :: IE GhcPs
ie@(IEModuleContents XIEModuleContents GhcPs
_ lmod :: XRec GhcPs ModuleName
lmod@(L SrcSpanAnnA
_ ModuleName
mod)))
        | ModuleName
mod forall a. Uniquable a => a -> UniqSet a -> Bool
`elementOfUniqSet` UniqSet ModuleName
earlier_mods    -- Duplicate export of M
        = do { TcRnMessage -> TcRn ()
addDiagnostic (ModuleName -> TcRnMessage
TcRnDupeModuleExport ModuleName
mod) ;
               forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing }

        | Bool
otherwise
        = do { let { exportValid :: Bool
exportValid = (ModuleName
mod forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ModuleName]
imported_modules)
                                Bool -> Bool -> Bool
|| (forall unit. GenModule unit -> ModuleName
moduleName Module
this_mod forall a. Eq a => a -> a -> Bool
== ModuleName
mod)
                   ; gre_prs :: [(GlobalRdrElt, GlobalRdrElt)]
gre_prs     = ModuleName -> [GlobalRdrElt] -> [(GlobalRdrElt, GlobalRdrElt)]
pickGREsModExp ModuleName
mod (GlobalRdrEnv -> [GlobalRdrElt]
globalRdrEnvElts GlobalRdrEnv
rdr_env)
                   ; new_exports :: [AvailInfo]
new_exports = [ GlobalRdrElt -> AvailInfo
availFromGRE GlobalRdrElt
gre'
                                   | (GlobalRdrElt
gre, GlobalRdrElt
_) <- [(GlobalRdrElt, GlobalRdrElt)]
gre_prs
                                   , GlobalRdrElt
gre' <- GlobalRdrElt -> [GlobalRdrElt]
expand_tyty_gre GlobalRdrElt
gre ]
                   ; all_gres :: [GlobalRdrElt]
all_gres    = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (\(GlobalRdrElt
gre1,GlobalRdrElt
gre2) [GlobalRdrElt]
gres -> GlobalRdrElt
gre1 forall a. a -> [a] -> [a]
: GlobalRdrElt
gre2 forall a. a -> [a] -> [a]
: [GlobalRdrElt]
gres) [] [(GlobalRdrElt, GlobalRdrElt)]
gre_prs
                   ; mods :: UniqSet ModuleName
mods        = forall a. Uniquable a => UniqSet a -> a -> UniqSet a
addOneToUniqSet UniqSet ModuleName
earlier_mods ModuleName
mod
                   }

             ; Bool -> TcRnMessage -> TcRn ()
checkErr Bool
exportValid (ModuleName -> TcRnMessage
TcRnExportedModNotImported ModuleName
mod)
             ; Bool -> TcRnMessage -> TcRn ()
warnIf (Bool
exportValid Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(GlobalRdrElt, GlobalRdrElt)]
gre_prs) (ModuleName -> TcRnMessage
TcRnNullExportedModule ModuleName
mod)

             ; String -> SDoc -> TcRn ()
traceRn String
"efa" (forall a. Outputable a => a -> SDoc
ppr ModuleName
mod forall doc. IsDoc doc => doc -> doc -> doc
$$ forall a. Outputable a => a -> SDoc
ppr [GlobalRdrElt]
all_gres)
             ; [GlobalRdrElt] -> TcRn ()
addUsedGREs [GlobalRdrElt]
all_gres

             ; ExportOccMap
occs' <- IE GhcPs -> ExportOccMap -> [AvailInfo] -> RnM ExportOccMap
check_occs IE GhcPs
ie ExportOccMap
occs [AvailInfo]
new_exports
                      -- This check_occs not only finds conflicts
                      -- between this item and others, but also
                      -- internally within this item.  That is, if
                      -- 'M.x' is in scope in several ways, we'll have
                      -- several members of mod_avails with the same
                      -- OccName.
             ; String -> SDoc -> TcRn ()
traceRn String
"export_mod"
                       (forall doc. IsDoc doc => [doc] -> doc
vcat [ forall a. Outputable a => a -> SDoc
ppr ModuleName
mod
                             , forall a. Outputable a => a -> SDoc
ppr [AvailInfo]
new_exports ])

             ; forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just ( ExportOccMap -> UniqSet ModuleName -> ExportAccum
ExportAccum ExportOccMap
occs' UniqSet ModuleName
mods
                            , ( forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
loc (forall pass.
XIEModuleContents pass -> XRec pass ModuleName -> IE pass
IEModuleContents NoExtField
noExtField XRec GhcPs ModuleName
lmod)
                              , [AvailInfo]
new_exports))) }

    exports_from_item acc :: ExportAccum
acc@(ExportAccum ExportOccMap
occs UniqSet ModuleName
mods) (L SrcSpanAnnA
loc IE GhcPs
ie) = do
        Maybe (IE GhcRn)
m_new_ie <- IE GhcPs -> RnM (Maybe (IE GhcRn))
lookup_doc_ie IE GhcPs
ie
        case Maybe (IE GhcRn)
m_new_ie of
          Just IE GhcRn
new_ie -> forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just (ExportAccum
acc, (forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
loc IE GhcRn
new_ie, [])))
          Maybe (IE GhcRn)
Nothing -> do
             (IE GhcRn
new_ie, AvailInfo
avail) <- IE GhcPs -> RnM (IE GhcRn, AvailInfo)
lookup_ie IE GhcPs
ie
             if Name -> Bool
isUnboundName (forall (p :: Pass). IE (GhcPass p) -> IdP (GhcPass p)
ieName IE GhcRn
new_ie)
                  then forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing    -- Avoid error cascade
                  else do

                    ExportOccMap
occs' <- IE GhcPs -> ExportOccMap -> [AvailInfo] -> RnM ExportOccMap
check_occs IE GhcPs
ie ExportOccMap
occs [AvailInfo
avail]

                    forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just ( ExportOccMap -> UniqSet ModuleName -> ExportAccum
ExportAccum ExportOccMap
occs' UniqSet ModuleName
mods
                                 , (forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
loc IE GhcRn
new_ie, [AvailInfo
avail])))

    -------------
    lookup_ie :: IE GhcPs -> RnM (IE GhcRn, AvailInfo)
    lookup_ie :: IE GhcPs -> RnM (IE GhcRn, AvailInfo)
lookup_ie (IEVar XIEVar GhcPs
_ (L SrcSpanAnnA
l IEWrappedName GhcPs
rdr))
        = do (Name
name, AvailInfo
avail) <- RdrName -> RnM (Name, AvailInfo)
lookupGreAvailRn forall a b. (a -> b) -> a -> b
$ forall (p :: Pass). IEWrappedName (GhcPass p) -> IdP (GhcPass p)
ieWrappedName IEWrappedName GhcPs
rdr
             forall (m :: * -> *) a. Monad m => a -> m a
return (forall pass. XIEVar pass -> LIEWrappedName pass -> IE pass
IEVar NoExtField
noExtField (forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
l (IEWrappedName GhcPs -> IdP GhcRn -> IEWrappedName GhcRn
replaceWrappedName IEWrappedName GhcPs
rdr Name
name)), AvailInfo
avail)

    lookup_ie (IEThingAbs XIEThingAbs GhcPs
_ (L SrcSpanAnnA
l IEWrappedName GhcPs
rdr))
        = do (Name
name, AvailInfo
avail) <- RdrName -> RnM (Name, AvailInfo)
lookupGreAvailRn forall a b. (a -> b) -> a -> b
$ forall (p :: Pass). IEWrappedName (GhcPass p) -> IdP (GhcPass p)
ieWrappedName IEWrappedName GhcPs
rdr
             forall (m :: * -> *) a. Monad m => a -> m a
return (forall pass. XIEThingAbs pass -> LIEWrappedName pass -> IE pass
IEThingAbs forall a. EpAnn a
noAnn (forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
l (IEWrappedName GhcPs -> IdP GhcRn -> IEWrappedName GhcRn
replaceWrappedName IEWrappedName GhcPs
rdr Name
name))
                    , AvailInfo
avail)

    lookup_ie ie :: IE GhcPs
ie@(IEThingAll XIEThingAll GhcPs
_ LIEWrappedName GhcPs
n')
        = do
            (Located Name
n, [Name]
avail, [FieldLabel]
flds) <- IE GhcPs
-> LIEWrappedName GhcPs -> RnM (Located Name, [Name], [FieldLabel])
lookup_ie_all IE GhcPs
ie LIEWrappedName GhcPs
n'
            let name :: Name
name = forall l e. GenLocated l e -> e
unLoc Located Name
n
            forall (m :: * -> *) a. Monad m => a -> m a
return (forall pass. XIEThingAll pass -> LIEWrappedName pass -> IE pass
IEThingAll forall a. EpAnn a
noAnn (LIEWrappedName GhcPs -> IdP GhcRn -> LIEWrappedName GhcRn
replaceLWrappedName LIEWrappedName GhcPs
n' (forall l e. GenLocated l e -> e
unLoc Located Name
n))
                   , Name -> [Name] -> [FieldLabel] -> AvailInfo
availTC Name
name (Name
nameforall a. a -> [a] -> [a]
:[Name]
avail) [FieldLabel]
flds)


    lookup_ie ie :: IE GhcPs
ie@(IEThingWith XIEThingWith GhcPs
_ LIEWrappedName GhcPs
l IEWildcard
wc [LIEWrappedName GhcPs]
sub_rdrs)
        = do
            (Located Name
lname, [GenLocated SrcSpanAnnA (IEWrappedName GhcRn)]
subs, [Name]
avails, [Located FieldLabel]
flds)
              <- forall (p :: Pass) a.
OutputableBndrId p =>
IE (GhcPass p) -> TcM a -> TcM a
addExportErrCtxt IE GhcPs
ie forall a b. (a -> b) -> a -> b
$ LIEWrappedName GhcPs
-> [LIEWrappedName GhcPs]
-> TcM
     (Located Name, [LIEWrappedName GhcRn], [Name],
      [Located FieldLabel])
lookup_ie_with LIEWrappedName GhcPs
l [LIEWrappedName GhcPs]
sub_rdrs
            (Located Name
_, [Name]
all_avail, [FieldLabel]
all_flds) <-
              case IEWildcard
wc of
                IEWildcard
NoIEWildcard -> forall (m :: * -> *) a. Monad m => a -> m a
return (Located Name
lname, [], [])
                IEWildcard Int
_ -> IE GhcPs
-> LIEWrappedName GhcPs -> RnM (Located Name, [Name], [FieldLabel])
lookup_ie_all IE GhcPs
ie LIEWrappedName GhcPs
l
            let name :: Name
name = forall l e. GenLocated l e -> e
unLoc Located Name
lname
            let flds' :: [Located FieldLabel]
flds' = [Located FieldLabel]
flds forall a. [a] -> [a] -> [a]
++ (forall a b. (a -> b) -> [a] -> [b]
map forall e. e -> Located e
noLoc [FieldLabel]
all_flds)
            forall (m :: * -> *) a. Monad m => a -> m a
return (forall pass.
XIEThingWith pass
-> LIEWrappedName pass
-> IEWildcard
-> [LIEWrappedName pass]
-> IE pass
IEThingWith [Located FieldLabel]
flds' (LIEWrappedName GhcPs -> IdP GhcRn -> LIEWrappedName GhcRn
replaceLWrappedName LIEWrappedName GhcPs
l Name
name) IEWildcard
wc [GenLocated SrcSpanAnnA (IEWrappedName GhcRn)]
subs,
                    Name -> [Name] -> [FieldLabel] -> AvailInfo
availTC Name
name (Name
name forall a. a -> [a] -> [a]
: [Name]
avails forall a. [a] -> [a] -> [a]
++ [Name]
all_avail)
                                 (forall a b. (a -> b) -> [a] -> [b]
map forall l e. GenLocated l e -> e
unLoc [Located FieldLabel]
flds forall a. [a] -> [a] -> [a]
++ [FieldLabel]
all_flds))


    lookup_ie IE GhcPs
_ = forall a. HasCallStack => String -> a
panic String
"lookup_ie"    -- Other cases covered earlier


    lookup_ie_with :: LIEWrappedName GhcPs -> [LIEWrappedName GhcPs]
                   -> RnM (Located Name, [LIEWrappedName GhcRn], [Name],
                           [Located FieldLabel])
    lookup_ie_with :: LIEWrappedName GhcPs
-> [LIEWrappedName GhcPs]
-> TcM
     (Located Name, [LIEWrappedName GhcRn], [Name],
      [Located FieldLabel])
lookup_ie_with (L SrcSpanAnnA
l IEWrappedName GhcPs
rdr) [LIEWrappedName GhcPs]
sub_rdrs
        = do Name
name <- RdrName -> RnM Name
lookupGlobalOccRn forall a b. (a -> b) -> a -> b
$ forall (p :: Pass). IEWrappedName (GhcPass p) -> IdP (GhcPass p)
ieWrappedName IEWrappedName GhcPs
rdr
             ([GenLocated SrcSpanAnnA (IEWrappedName GhcRn)]
non_flds, [Located FieldLabel]
flds) <- Name
-> [LIEWrappedName GhcPs]
-> RnM ([LIEWrappedName GhcRn], [Located FieldLabel])
lookupChildrenExport Name
name [LIEWrappedName GhcPs]
sub_rdrs
             if Name -> Bool
isUnboundName Name
name
                then forall (m :: * -> *) a. Monad m => a -> m a
return (forall l e. l -> e -> GenLocated l e
L (forall a. SrcSpanAnn' a -> SrcSpan
locA SrcSpanAnnA
l) Name
name, [], [Name
name], [])
                else forall (m :: * -> *) a. Monad m => a -> m a
return (forall l e. l -> e -> GenLocated l e
L (forall a. SrcSpanAnn' a -> SrcSpan
locA SrcSpanAnnA
l) Name
name, [GenLocated SrcSpanAnnA (IEWrappedName GhcRn)]
non_flds
                            , forall a b. (a -> b) -> [a] -> [b]
map (forall (p :: Pass). IEWrappedName (GhcPass p) -> IdP (GhcPass p)
ieWrappedName forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l e. GenLocated l e -> e
unLoc) [GenLocated SrcSpanAnnA (IEWrappedName GhcRn)]
non_flds
                            , [Located FieldLabel]
flds)

    lookup_ie_all :: IE GhcPs -> LIEWrappedName GhcPs
                  -> RnM (Located Name, [Name], [FieldLabel])
    lookup_ie_all :: IE GhcPs
-> LIEWrappedName GhcPs -> RnM (Located Name, [Name], [FieldLabel])
lookup_ie_all IE GhcPs
ie (L SrcSpanAnnA
l IEWrappedName GhcPs
rdr) =
          do Name
name <- RdrName -> RnM Name
lookupGlobalOccRn forall a b. (a -> b) -> a -> b
$ forall (p :: Pass). IEWrappedName (GhcPass p) -> IdP (GhcPass p)
ieWrappedName IEWrappedName GhcPs
rdr
             let gres :: [GlobalRdrElt]
gres = forall a. NameEnv [a] -> Name -> [a]
findChildren NameEnv [GlobalRdrElt]
kids_env Name
name
                 ([Name]
non_flds, [FieldLabel]
flds) = [GlobalRdrElt] -> ([Name], [FieldLabel])
classifyGREs [GlobalRdrElt]
gres
             RdrName -> [GlobalRdrElt] -> TcRn ()
addUsedKids (forall (p :: Pass). IEWrappedName (GhcPass p) -> IdP (GhcPass p)
ieWrappedName IEWrappedName GhcPs
rdr) [GlobalRdrElt]
gres
             forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [GlobalRdrElt]
gres) forall a b. (a -> b) -> a -> b
$
                  if Name -> Bool
isTyConName Name
name
                  then TcRnMessage -> TcRn ()
addTcRnDiagnostic (Name -> TcRnMessage
TcRnDodgyExports Name
name)
                  else -- This occurs when you export T(..), but
                       -- only import T abstractly, or T is a synonym.
                       TcRnMessage -> TcRn ()
addErr (IE GhcPs -> TcRnMessage
TcRnExportHiddenComponents IE GhcPs
ie)
             forall (m :: * -> *) a. Monad m => a -> m a
return (forall l e. l -> e -> GenLocated l e
L (forall a. SrcSpanAnn' a -> SrcSpan
locA SrcSpanAnnA
l) Name
name, [Name]
non_flds, [FieldLabel]
flds)

    -------------
    lookup_doc_ie :: IE GhcPs -> RnM (Maybe (IE GhcRn))
    lookup_doc_ie :: IE GhcPs -> RnM (Maybe (IE GhcRn))
lookup_doc_ie (IEGroup XIEGroup GhcPs
_ Int
lev LHsDoc GhcPs
doc) = do
      LHsDoc GhcRn
doc' <- LHsDoc GhcPs -> RnM (LHsDoc GhcRn)
rnLHsDoc LHsDoc GhcPs
doc
      forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just (forall pass. XIEGroup pass -> Int -> LHsDoc pass -> IE pass
IEGroup NoExtField
noExtField Int
lev LHsDoc GhcRn
doc')
    lookup_doc_ie (IEDoc XIEDoc GhcPs
_ LHsDoc GhcPs
doc)       = do
      LHsDoc GhcRn
doc' <- LHsDoc GhcPs -> RnM (LHsDoc GhcRn)
rnLHsDoc LHsDoc GhcPs
doc
      forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just (forall pass. XIEDoc pass -> LHsDoc pass -> IE pass
IEDoc NoExtField
noExtField LHsDoc GhcRn
doc')
    lookup_doc_ie (IEDocNamed XIEDocNamed GhcPs
_ String
str)  = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just (forall pass. XIEDocNamed pass -> String -> IE pass
IEDocNamed NoExtField
noExtField String
str)
    lookup_doc_ie IE GhcPs
_ = forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing

    -- In an export item M.T(A,B,C), we want to treat the uses of
    -- A,B,C as if they were M.A, M.B, M.C
    -- Happily pickGREs does just the right thing
    addUsedKids :: RdrName -> [GlobalRdrElt] -> RnM ()
    addUsedKids :: RdrName -> [GlobalRdrElt] -> TcRn ()
addUsedKids RdrName
parent_rdr [GlobalRdrElt]
kid_gres = [GlobalRdrElt] -> TcRn ()
addUsedGREs (RdrName -> [GlobalRdrElt] -> [GlobalRdrElt]
pickGREs RdrName
parent_rdr [GlobalRdrElt]
kid_gres)

classifyGREs :: [GlobalRdrElt] -> ([Name], [FieldLabel])
classifyGREs :: [GlobalRdrElt] -> ([Name], [FieldLabel])
classifyGREs = [GreName] -> ([Name], [FieldLabel])
partitionGreNames forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map GlobalRdrElt -> GreName
gre_name

-- Renaming and typechecking of exports happens after everything else has
-- been typechecked.

{-
Note [Modules without a module header]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Haskell 2010 report says in section 5.1:

>> An abbreviated form of module, consisting only of the module body, is
>> permitted. If this is used, the header is assumed to be
>> ‘module Main(main) where’.

For modules without a module header, this is implemented the
following way:

If the module has a main function in scope:
   Then create a module header and export the main function,
   as if a module header like ‘module Main(main) where...’ would exist.
   This has the effect to mark the main function and all top level
   functions called directly or indirectly via main as 'used',
   and later on, unused top-level functions can be reported correctly.
   There is no distinction between GHC and GHCi.
If the module has several main functions in scope:
   Then generate a header as above. The ambiguity is reported later in
   module  `GHC.Tc.Module` function `check_main`.
If the module has NO main function:
   Then export all top-level functions. This marks all top level
   functions as 'used'.
   In GHCi this has the effect, that we don't get any 'non-used' warnings.
   In GHC, however, the 'has-main-module' check in GHC.Tc.Module.checkMain
   fires, and we get the error:
      The IO action ‘main’ is not defined in module ‘Main’
-}


-- Renaming exports lists is a minefield. Five different things can appear in
-- children export lists ( T(A, B, C) ).
-- 1. Record selectors
-- 2. Type constructors
-- 3. Data constructors
-- 4. Pattern Synonyms
-- 5. Pattern Synonym Selectors
--
-- However, things get put into weird name spaces.
-- 1. Some type constructors are parsed as variables (-.->) for example.
-- 2. All data constructors are parsed as type constructors
-- 3. When there is ambiguity, we default type constructors to data
-- constructors and require the explicit `type` keyword for type
-- constructors.
--
-- This function first establishes the possible namespaces that an
-- identifier might be in (`choosePossibleNameSpaces`).
--
-- Then for each namespace in turn, tries to find the correct identifier
-- there returning the first positive result or the first terminating
-- error.
--



lookupChildrenExport :: Name -> [LIEWrappedName GhcPs]
                     -> RnM ([LIEWrappedName GhcRn], [Located FieldLabel])
lookupChildrenExport :: Name
-> [LIEWrappedName GhcPs]
-> RnM ([LIEWrappedName GhcRn], [Located FieldLabel])
lookupChildrenExport Name
spec_parent [LIEWrappedName GhcPs]
rdr_items =
  do
    [Either
   (GenLocated SrcSpanAnnA (IEWrappedName GhcRn))
   (Located FieldLabel)]
xs <- forall a b. (a -> TcRn b) -> [a] -> TcRn [b]
mapAndReportM LIEWrappedName GhcPs
-> RnM (Either (LIEWrappedName GhcRn) (Located FieldLabel))
doOne [LIEWrappedName GhcPs]
rdr_items
    forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall a b. [Either a b] -> ([a], [b])
partitionEithers [Either
   (GenLocated SrcSpanAnnA (IEWrappedName GhcRn))
   (Located FieldLabel)]
xs
    where
        -- Pick out the possible namespaces in order of priority
        -- This is a consequence of how the parser parses all
        -- data constructors as type constructors.
        choosePossibleNamespaces :: NameSpace -> [NameSpace]
        choosePossibleNamespaces :: NameSpace -> [NameSpace]
choosePossibleNamespaces NameSpace
ns
          | NameSpace
ns forall a. Eq a => a -> a -> Bool
== NameSpace
varName = [NameSpace
varName, NameSpace
tcName]
          | NameSpace
ns forall a. Eq a => a -> a -> Bool
== NameSpace
tcName  = [NameSpace
dataName, NameSpace
tcName]
          | Bool
otherwise = [NameSpace
ns]
        -- Process an individual child
        doOne :: LIEWrappedName GhcPs
              -> RnM (Either (LIEWrappedName GhcRn) (Located FieldLabel))
        doOne :: LIEWrappedName GhcPs
-> RnM (Either (LIEWrappedName GhcRn) (Located FieldLabel))
doOne LIEWrappedName GhcPs
n = do

          let bareName :: RdrName
bareName = (forall (p :: Pass). IEWrappedName (GhcPass p) -> IdP (GhcPass p)
ieWrappedName forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l e. GenLocated l e -> e
unLoc) LIEWrappedName GhcPs
n
              lkup :: NameSpace -> RnM ChildLookupResult
lkup NameSpace
v = Bool -> Bool -> Name -> RdrName -> RnM ChildLookupResult
lookupSubBndrOcc_helper Bool
False Bool
True
                        Name
spec_parent (RdrName -> NameSpace -> RdrName
setRdrNameSpace RdrName
bareName NameSpace
v)

          ChildLookupResult
name <-  [RnM ChildLookupResult] -> RnM ChildLookupResult
combineChildLookupResult forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map NameSpace -> RnM ChildLookupResult
lkup forall a b. (a -> b) -> a -> b
$
                   NameSpace -> [NameSpace]
choosePossibleNamespaces (RdrName -> NameSpace
rdrNameSpace RdrName
bareName)
          String -> SDoc -> TcRn ()
traceRn String
"lookupChildrenExport" (forall a. Outputable a => a -> SDoc
ppr ChildLookupResult
name)
          -- Default to data constructors for slightly better error
          -- messages
          let unboundName :: RdrName
              unboundName :: RdrName
unboundName = if RdrName -> NameSpace
rdrNameSpace RdrName
bareName forall a. Eq a => a -> a -> Bool
== NameSpace
varName
                                then RdrName
bareName
                                else RdrName -> NameSpace -> RdrName
setRdrNameSpace RdrName
bareName NameSpace
dataName

          case ChildLookupResult
name of
            ChildLookupResult
NameNotFound -> do { Name
ub <- RdrName -> RnM Name
reportUnboundName RdrName
unboundName
                               ; let l :: SrcSpanAnnA
l = forall l e. GenLocated l e -> l
getLoc LIEWrappedName GhcPs
n
                               ; forall (m :: * -> *) a. Monad m => a -> m a
return (forall a b. a -> Either a b
Left (forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
l (forall p. XIEName p -> LIdP p -> IEWrappedName p
IEName NoExtField
noExtField (forall l e. l -> e -> GenLocated l e
L (forall a. SrcSpanAnn' a -> SrcSpanAnnN
la2na SrcSpanAnnA
l) Name
ub))))}
            FoundChild Parent
par GreName
child -> do { Name -> Parent -> GreName -> TcRn ()
checkPatSynParent Name
spec_parent Parent
par GreName
child
                                       ; forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case GreName
child of
                                           FieldGreName FieldLabel
fl   -> forall a b. b -> Either a b
Right (forall l e. l -> e -> GenLocated l e
L (forall a e. GenLocated (SrcSpanAnn' a) e -> SrcSpan
getLocA LIEWrappedName GhcPs
n) FieldLabel
fl)
                                           NormalGreName  Name
name -> forall a b. a -> Either a b
Left (LIEWrappedName GhcPs -> IdP GhcRn -> LIEWrappedName GhcRn
replaceLWrappedName LIEWrappedName GhcPs
n Name
name)
                                       }
            IncorrectParent Name
p GreName
c [Name]
gs -> forall a. Name -> GreName -> [Name] -> TcM a
failWithDcErr Name
p GreName
c [Name]
gs


-- Note [Typing Pattern Synonym Exports]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- It proved quite a challenge to precisely specify which pattern synonyms
-- should be allowed to be bundled with which type constructors.
-- In the end it was decided to be quite liberal in what we allow. Below is
-- how Simon described the implementation.
--
-- "Personally I think we should Keep It Simple.  All this talk of
--  satisfiability makes me shiver.  I suggest this: allow T( P ) in all
--   situations except where `P`'s type is ''visibly incompatible'' with
--   `T`.
--
--    What does "visibly incompatible" mean?  `P` is visibly incompatible
--    with
--     `T` if
--       * `P`'s type is of form `... -> S t1 t2`
--       * `S` is a data/newtype constructor distinct from `T`
--
--  Nothing harmful happens if we allow `P` to be exported with
--  a type it can't possibly be useful for, but specifying a tighter
--  relationship is very awkward as you have discovered."
--
-- Note that this allows *any* pattern synonym to be bundled with any
-- datatype type constructor. For example, the following pattern `P` can be
-- bundled with any type.
--
-- ```
-- pattern P :: (A ~ f) => f
-- ```
--
-- So we provide basic type checking in order to help the user out, most
-- pattern synonyms are defined with definite type constructors, but don't
-- actually prevent a library author completely confusing their users if
-- they want to.
--
-- So, we check for exactly four things
-- 1. The name arises from a pattern synonym definition. (Either a pattern
--    synonym constructor or a pattern synonym selector)
-- 2. The pattern synonym is only bundled with a datatype or newtype.
-- 3. Check that the head of the result type constructor is an actual type
--    constructor and not a type variable. (See above example)
-- 4. Is so, check that this type constructor is the same as the parent
--    type constructor.
--
--
-- Note [Types of TyCon]
-- ~~~~~~~~~~~~~~~~~~~~~
-- This check appears to be overly complicated, Richard asked why it
-- is not simply just `isAlgTyCon`. The answer for this is that
-- a classTyCon is also an `AlgTyCon` which we explicitly want to disallow.
-- (It is either a newtype or data depending on the number of methods)
--

-- | Given a resolved name in the children export list and a parent. Decide
-- whether we are allowed to export the child with the parent.
-- Invariant: gre_par == NoParent
-- See Note [Typing Pattern Synonym Exports]
checkPatSynParent :: Name    -- ^ Alleged parent type constructor
                             -- User wrote T( P, Q )
                  -> Parent  -- The parent of P we discovered
                  -> GreName   -- ^ Either a
                             --   a) Pattern Synonym Constructor
                             --   b) A pattern synonym selector
                  -> TcM ()  -- Fails if wrong parent
checkPatSynParent :: Name -> Parent -> GreName -> TcRn ()
checkPatSynParent Name
_ (ParentIs {}) GreName
_
  = forall (m :: * -> *) a. Monad m => a -> m a
return ()

checkPatSynParent Name
parent Parent
NoParent GreName
gname
  | Name -> Bool
isUnboundName Name
parent -- Avoid an error cascade
  = forall (m :: * -> *) a. Monad m => a -> m a
return ()

  | Bool
otherwise
  = do { TyCon
parent_ty_con  <- Name -> TcM TyCon
tcLookupTyCon Name
parent
       ; TyThing
mpat_syn_thing <- Name -> TcM TyThing
tcLookupGlobal (GreName -> Name
greNameMangledName GreName
gname)

        -- 1. Check that the Id was actually from a thing associated with patsyns
       ; case TyThing
mpat_syn_thing of
            AnId Id
i | Id -> Bool
isId Id
i
                   , RecSelId { sel_tycon :: IdDetails -> RecSelParent
sel_tycon = RecSelPatSyn PatSyn
p } <- Id -> IdDetails
idDetails Id
i
                   -> SDoc -> TyCon -> PatSyn -> TcRn ()
handle_pat_syn (GreName -> SDoc
selErr GreName
gname) TyCon
parent_ty_con PatSyn
p

            AConLike (PatSynCon PatSyn
p) -> SDoc -> TyCon -> PatSyn -> TcRn ()
handle_pat_syn (PatSyn -> SDoc
psErr PatSyn
p) TyCon
parent_ty_con PatSyn
p

            TyThing
_ -> forall a. Name -> GreName -> [Name] -> TcM a
failWithDcErr Name
parent GreName
gname [] }
  where
    psErr :: PatSyn -> SDoc
psErr  = forall o. Outputable o => String -> o -> SDoc
exportErrCtxt String
"pattern synonym"
    selErr :: GreName -> SDoc
selErr = forall o. Outputable o => String -> o -> SDoc
exportErrCtxt String
"pattern synonym record selector"

    handle_pat_syn :: SDoc
                   -> TyCon      -- Parent TyCon
                   -> PatSyn     -- Corresponding bundled PatSyn
                                 -- and pretty printed origin
                   -> TcM ()
    handle_pat_syn :: SDoc -> TyCon -> PatSyn -> TcRn ()
handle_pat_syn SDoc
doc TyCon
ty_con PatSyn
pat_syn

      -- 2. See Note [Types of TyCon]
      | Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ TyCon -> Bool
isTyConWithSrcDataCons TyCon
ty_con
      = forall a. SDoc -> TcM a -> TcM a
addErrCtxt SDoc
doc forall a b. (a -> b) -> a -> b
$ forall a. TcRnMessage -> TcM a
failWithTc TcRnMessage
TcRnPatSynBundledWithNonDataCon

      -- 3. Is the head a type variable?
      | Maybe TyCon
Nothing <- Maybe TyCon
mtycon
      = forall (m :: * -> *) a. Monad m => a -> m a
return ()
      -- 4. Ok. Check they are actually the same type constructor.

      | Just TyCon
p_ty_con <- Maybe TyCon
mtycon, TyCon
p_ty_con forall a. Eq a => a -> a -> Bool
/= TyCon
ty_con
      = forall a. SDoc -> TcM a -> TcM a
addErrCtxt SDoc
doc forall a b. (a -> b) -> a -> b
$ forall a. TcRnMessage -> TcM a
failWithTc
          (Type -> Type -> TcRnMessage
TcRnPatSynBundledWithWrongType Type
expected_res_ty Type
res_ty)

      -- 5. We passed!
      | Bool
otherwise
      = forall (m :: * -> *) a. Monad m => a -> m a
return ()

      where
        expected_res_ty :: Type
expected_res_ty = TyCon -> [Type] -> Type
mkTyConApp TyCon
ty_con ([Id] -> [Type]
mkTyVarTys (TyCon -> [Id]
tyConTyVars TyCon
ty_con))
        ([Id]
_, [Type]
_, [Id]
_, [Type]
_, [Scaled Type]
_, Type
res_ty) = PatSyn -> ([Id], [Type], [Id], [Type], [Scaled Type], Type)
patSynSig PatSyn
pat_syn
        mtycon :: Maybe TyCon
mtycon = forall a b. (a, b) -> a
fst forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HasCallStack => Type -> Maybe (TyCon, [Type])
tcSplitTyConApp_maybe Type
res_ty


{-===========================================================================-}
check_occs :: IE GhcPs -> ExportOccMap -> [AvailInfo]
           -> RnM ExportOccMap
check_occs :: IE GhcPs -> ExportOccMap -> [AvailInfo] -> RnM ExportOccMap
check_occs IE GhcPs
ie ExportOccMap
occs [AvailInfo]
avails
  -- 'avails' are the entities specified by 'ie'
  = forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldlM ExportOccMap -> GreName -> RnM ExportOccMap
check ExportOccMap
occs [GreName]
children
  where
    children :: [GreName]
children = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap AvailInfo -> [GreName]
availGreNames [AvailInfo]
avails

    -- Check for distinct children exported with the same OccName (an error) or
    -- for duplicate exports of the same child (a warning).
    check :: ExportOccMap -> GreName -> RnM ExportOccMap
    check :: ExportOccMap -> GreName -> RnM ExportOccMap
check ExportOccMap
occs GreName
child
      = case ExportOccMap -> GreName -> Either (GreName, IE GhcPs) ExportOccMap
try_insert ExportOccMap
occs GreName
child of
          Right ExportOccMap
occs' -> forall (m :: * -> *) a. Monad m => a -> m a
return ExportOccMap
occs'

          Left (GreName
child', IE GhcPs
ie')
            | GreName -> Name
greNameMangledName GreName
child forall a. Eq a => a -> a -> Bool
== GreName -> Name
greNameMangledName GreName
child'   -- Duplicate export
            -- But we don't want to warn if the same thing is exported
            -- by two different module exports. See ticket #4478.
            -> do { Bool -> TcRnMessage -> TcRn ()
warnIf (Bool -> Bool
not (GreName -> IE GhcPs -> IE GhcPs -> Bool
dupExport_ok GreName
child IE GhcPs
ie IE GhcPs
ie')) (GreName -> IE GhcPs -> IE GhcPs -> TcRnMessage
TcRnDuplicateExport GreName
child IE GhcPs
ie IE GhcPs
ie')
                  ; forall (m :: * -> *) a. Monad m => a -> m a
return ExportOccMap
occs }

            | Bool
otherwise    -- Same occ name but different names: an error
            ->  do { GlobalRdrEnv
global_env <- TcRn GlobalRdrEnv
getGlobalRdrEnv ;
                     TcRnMessage -> TcRn ()
addErr (GlobalRdrEnv
-> GreName -> GreName -> IE GhcPs -> IE GhcPs -> TcRnMessage
exportClashErr GlobalRdrEnv
global_env GreName
child' GreName
child IE GhcPs
ie' IE GhcPs
ie) ;
                     forall (m :: * -> *) a. Monad m => a -> m a
return ExportOccMap
occs }

    -- Try to insert a child into the map, returning Left if there is something
    -- already exported with the same OccName
    try_insert :: ExportOccMap -> GreName -> Either (GreName, IE GhcPs) ExportOccMap
    try_insert :: ExportOccMap -> GreName -> Either (GreName, IE GhcPs) ExportOccMap
try_insert ExportOccMap
occs GreName
child
      = case forall a. OccEnv a -> OccName -> Maybe a
lookupOccEnv ExportOccMap
occs OccName
name_occ of
          Maybe (GreName, IE GhcPs)
Nothing -> forall a b. b -> Either a b
Right (forall a. OccEnv a -> OccName -> a -> OccEnv a
extendOccEnv ExportOccMap
occs OccName
name_occ (GreName
child, IE GhcPs
ie))
          Just (GreName, IE GhcPs)
x  -> forall a b. a -> Either a b
Left (GreName, IE GhcPs)
x
      where
        -- For fields, we check for export clashes using the (OccName of the)
        -- selector Name
        name_occ :: OccName
name_occ = Name -> OccName
nameOccName (GreName -> Name
greNameMangledName GreName
child)


dupExport_ok :: GreName -> IE GhcPs -> IE GhcPs -> Bool
-- The GreName is exported by both IEs. Is that ok?
-- "No"  iff the name is mentioned explicitly in both IEs
--        or one of the IEs mentions the name *alone*
-- "Yes" otherwise
--
-- Examples of "no":  module M( f, f )
--                    module M( fmap, Functor(..) )
--                    module M( module Data.List, head )
--
-- Example of "yes"
--    module M( module A, module B ) where
--        import A( f )
--        import B( f )
--
-- Example of "yes" (#2436)
--    module M( C(..), T(..) ) where
--         class C a where { data T a }
--         instance C Int where { data T Int = TInt }
--
-- Example of "yes" (#2436)
--    module Foo ( T ) where
--      data family T a
--    module Bar ( T(..), module Foo ) where
--        import Foo
--        data instance T Int = TInt

dupExport_ok :: GreName -> IE GhcPs -> IE GhcPs -> Bool
dupExport_ok GreName
child IE GhcPs
ie1 IE GhcPs
ie2
  = Bool -> Bool
not (  forall {pass}. IE pass -> Bool
single IE GhcPs
ie1 Bool -> Bool -> Bool
|| forall {pass}. IE pass -> Bool
single IE GhcPs
ie2
        Bool -> Bool -> Bool
|| (IE GhcPs -> Bool
explicit_in IE GhcPs
ie1 Bool -> Bool -> Bool
&& IE GhcPs -> Bool
explicit_in IE GhcPs
ie2) )
  where
    explicit_in :: IE GhcPs -> Bool
explicit_in (IEModuleContents {}) = Bool
False                   -- module M
    explicit_in (IEThingAll XIEThingAll GhcPs
_ LIEWrappedName GhcPs
r)
      = forall name. HasOccName name => name -> OccName
occName GreName
child forall a. Eq a => a -> a -> Bool
== RdrName -> OccName
rdrNameOcc (forall (p :: Pass). IEWrappedName (GhcPass p) -> IdP (GhcPass p)
ieWrappedName forall a b. (a -> b) -> a -> b
$ forall l e. GenLocated l e -> e
unLoc LIEWrappedName GhcPs
r)  -- T(..)
    explicit_in IE GhcPs
_              = Bool
True

    single :: IE pass -> Bool
single IEVar {}      = Bool
True
    single IEThingAbs {} = Bool
True
    single IE pass
_               = Bool
False


exportErrCtxt :: Outputable o => String -> o -> SDoc
exportErrCtxt :: forall o. Outputable o => String -> o -> SDoc
exportErrCtxt String
herald o
exp =
  forall doc. IsLine doc => String -> doc
text String
"In the" forall doc. IsLine doc => doc -> doc -> doc
<+> forall doc. IsLine doc => String -> doc
text (String
herald forall a. [a] -> [a] -> [a]
++ String
":") forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr o
exp


addExportErrCtxt :: (OutputableBndrId p)
                 => IE (GhcPass p) -> TcM a -> TcM a
addExportErrCtxt :: forall (p :: Pass) a.
OutputableBndrId p =>
IE (GhcPass p) -> TcM a -> TcM a
addExportErrCtxt IE (GhcPass p)
ie = forall a. SDoc -> TcM a -> TcM a
addErrCtxt SDoc
exportCtxt
  where
    exportCtxt :: SDoc
exportCtxt = forall doc. IsLine doc => String -> doc
text String
"In the export:" forall doc. IsLine doc => doc -> doc -> doc
<+> forall a. Outputable a => a -> SDoc
ppr IE (GhcPass p)
ie


failWithDcErr :: Name -> GreName -> [Name] -> TcM a
failWithDcErr :: forall a. Name -> GreName -> [Name] -> TcM a
failWithDcErr Name
parent GreName
child [Name]
parents = do
  TyThing
ty_thing <- Name -> TcM TyThing
tcLookupGlobal (GreName -> Name
greNameMangledName GreName
child)
  forall a. TcRnMessage -> TcM a
failWithTc forall a b. (a -> b) -> a -> b
$ Name -> TyThing -> GreName -> [Name] -> TcRnMessage
TcRnExportedParentChildMismatch Name
parent TyThing
ty_thing GreName
child [Name]
parents


exportClashErr :: GlobalRdrEnv
               -> GreName -> GreName
               -> IE GhcPs -> IE GhcPs
               -> TcRnMessage
exportClashErr :: GlobalRdrEnv
-> GreName -> GreName -> IE GhcPs -> IE GhcPs -> TcRnMessage
exportClashErr GlobalRdrEnv
global_env GreName
child1 GreName
child2 IE GhcPs
ie1 IE GhcPs
ie2
  = OccName
-> GreName
-> GlobalRdrElt
-> IE GhcPs
-> GreName
-> GlobalRdrElt
-> IE GhcPs
-> TcRnMessage
TcRnConflictingExports OccName
occ GreName
child1' GlobalRdrElt
gre1' IE GhcPs
ie1' GreName
child2' GlobalRdrElt
gre2' IE GhcPs
ie2'
  where
    occ :: OccName
occ = forall name. HasOccName name => name -> OccName
occName GreName
child1
    -- get_gre finds a GRE for the Name, so that we can show its provenance
    gre1 :: GlobalRdrElt
gre1 = GreName -> GlobalRdrElt
get_gre GreName
child1
    gre2 :: GlobalRdrElt
gre2 = GreName -> GlobalRdrElt
get_gre GreName
child2
    get_gre :: GreName -> GlobalRdrElt
get_gre GreName
child
        = forall a. a -> Maybe a -> a
fromMaybe (forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"exportClashErr" (forall a. Outputable a => a -> SDoc
ppr GreName
child))
                    (GlobalRdrEnv -> GreName -> Maybe GlobalRdrElt
lookupGRE_GreName GlobalRdrEnv
global_env GreName
child)
    (GreName
child1', GlobalRdrElt
gre1', IE GhcPs
ie1', GreName
child2', GlobalRdrElt
gre2', IE GhcPs
ie2') =
      case SrcSpan -> SrcSpan -> Ordering
SrcLoc.leftmost_smallest (GlobalRdrElt -> SrcSpan
greSrcSpan GlobalRdrElt
gre1) (GlobalRdrElt -> SrcSpan
greSrcSpan GlobalRdrElt
gre2) of
        Ordering
LT -> (GreName
child1, GlobalRdrElt
gre1, IE GhcPs
ie1, GreName
child2, GlobalRdrElt
gre2, IE GhcPs
ie2)
        Ordering
GT -> (GreName
child2, GlobalRdrElt
gre2, IE GhcPs
ie2, GreName
child1, GlobalRdrElt
gre1, IE GhcPs
ie1)
        Ordering
EQ -> forall a. HasCallStack => String -> a
panic String
"exportClashErr: clashing exports have identical location"