aboutsummaryrefslogtreecommitdiff
path: root/haddock-api/src/Haddock/Interface
diff options
context:
space:
mode:
authoralexbiehl-gc <72160047+alexbiehl-gc@users.noreply.github.com>2021-02-07 18:39:59 +0100
committerGitHub <noreply@github.com>2021-02-07 18:39:59 +0100
commit786d3e69799398c3aac26fbd5017a127bc69cacc (patch)
tree883ee3f8c0e195299925b790cba6f88a537200f6 /haddock-api/src/Haddock/Interface
parente90e79815960823a749287968fb1c6d09559a67f (diff)
parent0f7ff041fb824653a7930e1292b81f34df1e967d (diff)
Merge branch 'ghc-head' into ghc-9.0
Diffstat (limited to 'haddock-api/src/Haddock/Interface')
-rw-r--r--haddock-api/src/Haddock/Interface/Create.hs684
-rw-r--r--haddock-api/src/Haddock/Interface/Json.hs2
-rw-r--r--haddock-api/src/Haddock/Interface/LexParseRn.hs23
-rw-r--r--haddock-api/src/Haddock/Interface/Rename.hs100
-rw-r--r--haddock-api/src/Haddock/Interface/Specialize.hs97
5 files changed, 528 insertions, 378 deletions
diff --git a/haddock-api/src/Haddock/Interface/Create.hs b/haddock-api/src/Haddock/Interface/Create.hs
index c4988480..9a773b6c 100644
--- a/haddock-api/src/Haddock/Interface/Create.hs
+++ b/haddock-api/src/Haddock/Interface/Create.hs
@@ -1,6 +1,8 @@
-{-# LANGUAGE CPP, TupleSections, BangPatterns, LambdaCase #-}
+{-# LANGUAGE StandaloneDeriving, FlexibleInstances, MultiParamTypeClasses, CPP, TupleSections, BangPatterns, LambdaCase, NamedFieldPuns, ScopedTypeVariables, RecordWildCards #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
+{-# LANGUAGE DerivingStrategies #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# OPTIONS_GHC -Wwarn #-}
-----------------------------------------------------------------------------
-- |
@@ -18,234 +20,321 @@
-- which creates a Haddock 'Interface' from the typechecking
-- results 'TypecheckedModule' from GHC.
-----------------------------------------------------------------------------
-module Haddock.Interface.Create (createInterface) where
+module Haddock.Interface.Create (IfM, runIfM, createInterface1) where
import Documentation.Haddock.Doc (metaDocAppend)
-import Haddock.Types
+import Haddock.Types hiding (liftErrMsg)
import Haddock.Options
import Haddock.GhcUtils
import Haddock.Utils
import Haddock.Convert
import Haddock.Interface.LexParseRn
-import Data.Bifunctor
+import Control.Monad.Reader
+import Control.Monad.Writer.Strict hiding (tell)
import Data.Bitraversable
import qualified Data.Map as M
-import qualified Data.Set as S
import Data.Map (Map)
-import Data.List (find, foldl')
+import Data.List
import Data.Maybe
-import Control.Monad
import Data.Traversable
-import GHC.Stack (HasCallStack)
+import GHC.Stack
+import GHC.Tc.Utils.Monad (finalSafeMode)
import GHC.Types.Avail hiding (avail)
import qualified GHC.Types.Avail as Avail
import qualified GHC.Unit.Module as Module
+import GHC.Unit.Module.ModSummary
import qualified GHC.Types.SrcLoc as SrcLoc
+import GHC.Types.SourceFile
+import GHC.Core.Class
import GHC.Core.ConLike (ConLike(..))
-import GHC
-import GHC.Driver.Types
+import GHC hiding (lookupName)
+import GHC.Driver.Ppr
import GHC.Types.Name
import GHC.Types.Name.Set
import GHC.Types.Name.Env
import GHC.Unit.State
import GHC.Types.Name.Reader
-import GHC.Tc.Types
+import GHC.Tc.Types hiding (IfM)
import GHC.Data.FastString ( unpackFS, bytesFS )
-import GHC.Types.Basic ( StringLiteral(..), SourceText(..), PromotionFlag(..) )
+import GHC.Types.Basic ( PromotionFlag(..) )
+import GHC.Types.SourceText
import qualified GHC.Utils.Outputable as O
+import GHC.Utils.Panic
import GHC.HsToCore.Docs hiding (mkMaps)
import GHC.Parser.Annotation (IsUnicodeSyntax(..))
+import GHC.Unit.Module.Warnings
-mkExceptionContext :: TypecheckedModule -> String
-mkExceptionContext =
- ("creating Haddock interface for " ++) . moduleNameString . ms_mod_name . pm_mod_summary . tm_parsed_module
-
--- | Use a 'TypecheckedModule' to produce an 'Interface'.
--- To do this, we need access to already processed modules in the topological
--- sort. That's what's in the 'IfaceMap'.
-createInterface :: HasCallStack
- => TypecheckedModule
- -> [Flag] -- Boolean flags
- -> IfaceMap -- Locally processed modules
- -> InstIfaceMap -- External, already installed interfaces
- -> ErrMsgGhc Interface
-createInterface tm flags modMap instIfaceMap =
- withExceptionContext (mkExceptionContext tm) $ do
-
- let ms = pm_mod_summary . tm_parsed_module $ tm
- mi = moduleInfo tm
- L _ hsm = parsedSource tm
- !safety = modInfoSafe mi
- mdl = ms_mod ms
- sem_mdl = tcg_semantic_mod (fst (tm_internals_ tm))
- is_sig = ms_hsc_src ms == HsigFile
- dflags = ms_hspp_opts ms
- !instances = modInfoInstances mi
- !fam_instances = md_fam_insts md
- !exportedNames = modInfoExportsWithSelectors mi
- (pkgNameFS, _) = modulePackageInfo dflags flags (Just mdl)
- pkgName = fmap (unpackFS . (\(PackageName n) -> n)) pkgNameFS
-
- (TcGblEnv { tcg_rdr_env = gre
- , tcg_warns = warnings
- , tcg_exports = all_exports0
- }, md) = tm_internals_ tm
- all_local_avails = gresToAvailInfo . filter isLocalGRE . globalRdrEnvElts $ gre
-
- -- The 'pkgName' is necessary to decide what package to mention in "@since"
- -- annotations. Not having it is not fatal though.
- --
- -- Cabal can be trusted to pass the right flags, so this warning should be
- -- mostly encountered when running Haddock outside of Cabal.
- when (isNothing pkgName) $
- liftErrMsg $ tell [ "Warning: Package name is not available." ]
-
- -- The renamed source should always be available to us, but it's best
- -- to be on the safe side.
- (group_, imports, mayExports, mayDocHeader) <-
- case renamedSource tm of
- Nothing -> do
- liftErrMsg $ tell [ "Warning: Renamed source is not available." ]
- return (emptyRnGroup, [], Nothing, Nothing)
- Just x -> return x
-
- opts <- liftErrMsg $ mkDocOpts (haddockOptions dflags) flags mdl
+newtype IfEnv m = IfEnv
+ {
+ -- | Lookup names in the enviroment.
+ ife_lookup_name :: Name -> m (Maybe TyThing)
+ }
+
+
+-- | A monad in which we create Haddock interfaces. Not to be confused with
+-- `GHC.Tc.Types.IfM` which is used to write GHC interfaces.
+--
+-- In the past `createInterface` was running in the `Ghc` monad but proved hard
+-- to sustain as soon as we moved over for Haddock to be a plugin. Also abstracting
+-- over the Ghc specific clarifies where side effects happen.
+newtype IfM m a = IfM { unIfM :: ReaderT (IfEnv m) (WriterT [ErrMsg] m) a }
+
+
+deriving newtype instance Functor m => Functor (IfM m)
+deriving newtype instance Applicative m => Applicative (IfM m)
+deriving newtype instance Monad m => Monad (IfM m)
+deriving newtype instance MonadIO m => MonadIO (IfM m)
+deriving newtype instance Monad m => MonadReader (IfEnv m) (IfM m)
+deriving newtype instance Monad m => MonadWriter [ErrMsg] (IfM m)
+
+
+-- | Run an `IfM` action.
+runIfM
+ -- | Lookup a global name in the current session. Used in cases
+ -- where declarations don't
+ :: (Name -> m (Maybe TyThing))
+ -- | The action to run.
+ -> IfM m a
+ -- | Result and accumulated error/warning messages.
+ -> m (a, [ErrMsg])
+runIfM lookup_name action = do
+ let
+ if_env = IfEnv
+ {
+ ife_lookup_name = lookup_name
+ }
+ runWriterT (runReaderT (unIfM action) if_env)
+
+
+liftErrMsg :: Monad m => ErrMsgM a -> IfM m a
+liftErrMsg action = do
+ writer (runWriter action)
+
+
+lookupName :: Monad m => Name -> IfM m (Maybe TyThing)
+lookupName name = IfM $ do
+ lookup_name <- asks ife_lookup_name
+ lift $ lift (lookup_name name)
+
+
+createInterface1
+ :: MonadIO m
+ => [Flag]
+ -> UnitState
+ -> ModSummary
+ -> TcGblEnv
+ -> IfaceMap
+ -> InstIfaceMap
+ -> IfM m Interface
+createInterface1 flags unit_state mod_sum tc_gbl_env ifaces inst_ifaces = do
+
+ let
+ ModSummary
+ {
+ -- Cached flags from OPTIONS, INCLUDE and LANGUAGE
+ -- pragmas in the modules source code. Used to infer
+ -- safety of module.
+ ms_hspp_opts
+ , ms_location = ModLocation
+ {
+ ml_hie_file
+ }
+ } = mod_sum
+
+ TcGblEnv
+ {
+ tcg_mod
+ , tcg_src
+ , tcg_semantic_mod
+ , tcg_rdr_env
+ , tcg_exports
+ , tcg_insts
+ , tcg_fam_insts
+ , tcg_warns
+
+ -- Renamed source
+ , tcg_rn_imports
+ , tcg_rn_exports
+ , tcg_rn_decls
+
+ , tcg_doc_hdr
+ } = tc_gbl_env
+
+ dflags = ms_hspp_opts
+
+ is_sig = tcg_src == HsigFile
+
+ (pkg_name_fs, _) =
+ modulePackageInfo unit_state flags (Just tcg_mod)
+
+ pkg_name :: Maybe Package
+ pkg_name =
+ let
+ unpack (PackageName name) = unpackFS name
+ in
+ fmap unpack pkg_name_fs
+
+ fixities :: FixMap
+ fixities = case tcg_rn_decls of
+ Nothing -> mempty
+ Just dx -> mkFixMap dx
+
+ -- Locations of all the TH splices
+ loc_splices :: [SrcSpan]
+ loc_splices = case tcg_rn_decls of
+ Nothing -> []
+ Just HsGroup { hs_splcds } -> [ loc | L loc _ <- hs_splcds ]
+
+ decls <- case tcg_rn_decls of
+ Nothing -> do
+ tell [ "Warning: Renamed source is not available" ]
+ pure []
+ Just dx ->
+ pure (topDecls dx)
+
+ -- Derive final options to use for haddocking this module
+ doc_opts <- liftErrMsg $ mkDocOpts (haddockOptions ms_hspp_opts) flags tcg_mod
+
+ let
+ -- All elements of an explicit export list, if present
+ export_list :: Maybe [(IE GhcRn, Avails)]
+ export_list
+ | OptIgnoreExports `elem` doc_opts =
+ Nothing
+ | Just rn_exports <- tcg_rn_exports =
+ Just [ (ie, avail) | (L _ ie, avail) <- rn_exports ]
+ | otherwise =
+ Nothing
+
+ -- All the exported Names of this module.
+ exported_names :: [Name]
+ exported_names =
+ concatMap availNamesWithSelectors tcg_exports
+
+ -- Module imports of the form `import X`. Note that there is
+ -- a) no qualification and
+ -- b) no import list
+ imported_modules :: Map ModuleName [ModuleName]
+ imported_modules
+ | Just{} <- export_list =
+ unrestrictedModuleImports (map unLoc tcg_rn_imports)
+ | otherwise =
+ M.empty
+
+ -- TyThings that have instances defined in this module
+ local_instances :: [Name]
+ local_instances =
+ [ name
+ | name <- map getName tcg_insts ++ map getName tcg_fam_insts
+ , nameIsLocalOrFrom tcg_semantic_mod name
+ ]
+
+ -- Infer module safety
+ safety <- liftIO (finalSafeMode ms_hspp_opts tc_gbl_env)
-- Process the top-level module header documentation.
- (!info, mbDoc) <- liftErrMsg $ processModuleHeader dflags pkgName gre safety mayDocHeader
-
- let declsWithDocs = topDecls group_
-
- exports0 = fmap (map (first unLoc)) mayExports
- (all_exports, exports)
- | OptIgnoreExports `elem` opts = (all_local_avails, Nothing)
- | otherwise = (all_exports0, exports0)
-
- unrestrictedImportedMods
- -- module re-exports are only possible with
- -- explicit export list
- | Just{} <- exports
- = unrestrictedModuleImports (map unLoc imports)
- | otherwise = M.empty
-
- fixMap = mkFixMap group_
- (decls, _) = unzip declsWithDocs
- localInsts = filter (nameIsLocalOrFrom sem_mdl)
- $ map getName fam_instances
- ++ map getName instances
- -- Locations of all TH splices
- splices = [ l | L l (SpliceD _ _) <- hsmodDecls hsm ]
-
- warningMap <- liftErrMsg (mkWarningMap dflags warnings gre exportedNames)
-
- maps@(!docMap, !argMap, !declMap, _) <-
- liftErrMsg (mkMaps dflags pkgName gre localInsts declsWithDocs)
-
- let allWarnings = M.unions (warningMap : map ifaceWarningMap (M.elems modMap))
-
- -- The MAIN functionality: compute the export items which will
- -- each be the actual documentation of this module.
- exportItems <- mkExportItems is_sig modMap pkgName mdl sem_mdl allWarnings gre
- exportedNames decls maps fixMap unrestrictedImportedMods
- splices exports all_exports instIfaceMap dflags
-
- let !visibleNames = mkVisibleNames maps exportItems opts
-
- -- Measure haddock documentation coverage.
- let prunedExportItems0 = pruneExportItems exportItems
- !haddockable = 1 + length exportItems -- module + exports
- !haddocked = (if isJust mbDoc then 1 else 0) + length prunedExportItems0
- !coverage = (haddockable, haddocked)
-
- -- Prune the export list to just those declarations that have
- -- documentation, if the 'prune' option is on.
- let prunedExportItems'
- | OptPrune `elem` opts = prunedExportItems0
- | otherwise = exportItems
- !prunedExportItems = seqList prunedExportItems' `seq` prunedExportItems'
-
- let !aliases =
- mkAliasMap (unitState dflags) $ tm_renamed_source tm
-
- modWarn <- liftErrMsg (moduleWarning dflags gre warnings)
-
- -- Prune the docstring 'Map's to keep only docstrings that are not private.
- --
- -- Besides all the names that GHC has told us this module exports, we also
- -- keep the docs for locally defined class instances. This is more names than
- -- we need, but figuring out which instances are fully private is tricky.
- --
- -- We do this pruning to avoid having to rename, emit warnings, and save
- -- docstrings which will anyways never be rendered.
- let !localVisibleNames = S.fromList (localInsts ++ exportedNames)
- !prunedDocMap = M.restrictKeys docMap localVisibleNames
- !prunedArgMap = M.restrictKeys argMap localVisibleNames
-
- return $! Interface {
- ifaceMod = mdl
- , ifaceIsSig = is_sig
- , ifaceOrigFilename = msHsFilePath ms
- , ifaceInfo = info
- , ifaceDoc = Documentation mbDoc modWarn
- , ifaceRnDoc = Documentation Nothing Nothing
- , ifaceOptions = opts
- , ifaceDocMap = prunedDocMap
- , ifaceArgMap = prunedArgMap
- , ifaceRnDocMap = M.empty -- Filled in `renameInterface`
- , ifaceRnArgMap = M.empty -- Filled in `renameInterface`
- , ifaceExportItems = prunedExportItems
- , ifaceRnExportItems = [] -- Filled in `renameInterface`
- , ifaceExports = exportedNames
- , ifaceVisibleExports = visibleNames
- , ifaceDeclMap = declMap
- , ifaceFixMap = fixMap
- , ifaceModuleAliases = aliases
- , ifaceInstances = instances
- , ifaceFamInstances = fam_instances
- , ifaceOrphanInstances = [] -- Filled in `attachInstances`
- , ifaceRnOrphanInstances = [] -- Filled in `renameInterface`
- , ifaceHaddockCoverage = coverage
- , ifaceWarningMap = warningMap
- , ifaceHieFile = Just $ ml_hie_file $ ms_location ms
- , ifaceDynFlags = dflags
- }
+ (!info, header_doc) <- liftErrMsg $ processModuleHeader dflags pkg_name
+ tcg_rdr_env safety tcg_doc_hdr
+
+ -- Warnings on declarations in this module
+ decl_warnings <- liftErrMsg (mkWarningMap dflags tcg_warns tcg_rdr_env exported_names)
+
+ -- Warning on the module header
+ mod_warning <- liftErrMsg (moduleWarning dflags tcg_rdr_env tcg_warns)
+
+ let
+ -- Warnings in this module and transitive warnings from dependend modules
+ warnings :: Map Name (Doc Name)
+ warnings = M.unions (decl_warnings : map ifaceWarningMap (M.elems ifaces))
+
+ maps@(!docs, !arg_docs, !decl_map, _) <-
+ liftErrMsg (mkMaps dflags pkg_name tcg_rdr_env local_instances decls)
+
+ export_items <- mkExportItems is_sig ifaces pkg_name tcg_mod tcg_semantic_mod
+ warnings tcg_rdr_env exported_names (map fst decls) maps fixities
+ imported_modules loc_splices export_list tcg_exports inst_ifaces dflags
+
+ let
+ visible_names :: [Name]
+ visible_names = mkVisibleNames maps export_items doc_opts
+
+ -- Measure haddock documentation coverage.
+ pruned_export_items :: [ExportItem GhcRn]
+ pruned_export_items = pruneExportItems export_items
+
+ !haddockable = 1 + length export_items -- module + exports
+ !haddocked = (if isJust tcg_doc_hdr then 1 else 0) + length pruned_export_items
+
+ coverage :: (Int, Int)
+ !coverage = (haddockable, haddocked)
+
+ aliases :: Map Module ModuleName
+ aliases = mkAliasMap unit_state tcg_rn_imports
+
+ return $! Interface
+ {
+ ifaceMod = tcg_mod
+ , ifaceIsSig = is_sig
+ , ifaceOrigFilename = msHsFilePath mod_sum
+ , ifaceHieFile = Just ml_hie_file
+ , ifaceInfo = info
+ , ifaceDoc = Documentation header_doc mod_warning
+ , ifaceRnDoc = Documentation Nothing Nothing
+ , ifaceOptions = doc_opts
+ , ifaceDocMap = docs
+ , ifaceArgMap = arg_docs
+ , ifaceRnDocMap = M.empty
+ , ifaceRnArgMap = M.empty
+ , ifaceExportItems = if OptPrune `elem` doc_opts then
+ pruned_export_items else export_items
+ , ifaceRnExportItems = []
+ , ifaceExports = exported_names
+ , ifaceVisibleExports = visible_names
+ , ifaceDeclMap = decl_map
+ , ifaceFixMap = fixities
+ , ifaceModuleAliases = aliases
+ , ifaceInstances = tcg_insts
+ , ifaceFamInstances = tcg_fam_insts
+ , ifaceOrphanInstances = [] -- Filled in attachInstances
+ , ifaceRnOrphanInstances = [] -- Filled in attachInstances
+ , ifaceHaddockCoverage = coverage
+ , ifaceWarningMap = warnings
+ , ifaceDynFlags = dflags
+ }
-- | Given all of the @import M as N@ declarations in a package,
-- create a mapping from the module identity of M, to an alias N
-- (if there are multiple aliases, we pick the last one.) This
-- will go in 'ifaceModuleAliases'.
-mkAliasMap :: UnitState -> Maybe RenamedSource -> M.Map Module ModuleName
-mkAliasMap state mRenamedSource =
- case mRenamedSource of
- Nothing -> M.empty
- Just (_,impDecls,_,_) ->
- M.fromList $
- mapMaybe (\(SrcLoc.L _ impDecl) -> do
- SrcLoc.L _ alias <- ideclAs impDecl
- return $
- (lookupModuleDyn state
- -- TODO: This is supremely dodgy, because in general the
- -- UnitId isn't going to look anything like the package
- -- qualifier (even with old versions of GHC, the
- -- IPID would be p-0.1, but a package qualifier never
- -- has a version number it. (Is it possible that in
- -- Haddock-land, the UnitIds never have version numbers?
- -- I, ezyang, have not quite understand Haddock's package
- -- identifier model.)
- --
- -- Additionally, this is simulating some logic GHC already
- -- has for deciding how to qualify names when it outputs
- -- them to the user. We should reuse that information;
- -- or at least reuse the renamed imports, which know what
- -- they import!
- (fmap Module.fsToUnit $
- fmap sl_fs $ ideclPkgQual impDecl)
- (case ideclName impDecl of SrcLoc.L _ name -> name),
- alias))
- impDecls
+mkAliasMap :: UnitState -> [LImportDecl GhcRn] -> M.Map Module ModuleName
+mkAliasMap state impDecls =
+ M.fromList $
+ mapMaybe (\(SrcLoc.L _ impDecl) -> do
+ SrcLoc.L _ alias <- ideclAs impDecl
+ return $
+ (lookupModuleDyn state
+ -- TODO: This is supremely dodgy, because in general the
+ -- UnitId isn't going to look anything like the package
+ -- qualifier (even with old versions of GHC, the
+ -- IPID would be p-0.1, but a package qualifier never
+ -- has a version number it. (Is it possible that in
+ -- Haddock-land, the UnitIds never have version numbers?
+ -- I, ezyang, have not quite understand Haddock's package
+ -- identifier model.)
+ --
+ -- Additionally, this is simulating some logic GHC already
+ -- has for deciding how to qualify names when it outputs
+ -- them to the user. We should reuse that information;
+ -- or at least reuse the renamed imports, which know what
+ -- they import!
+ (fmap Module.fsToUnit $
+ fmap sl_fs $ ideclPkgQual impDecl)
+ (case ideclName impDecl of SrcLoc.L _ name -> name),
+ alias))
+ impDecls
-- We want to know which modules are imported without any qualification. This
-- way we can display module reexports more compactly. This mapping also looks
@@ -257,7 +346,7 @@ mkAliasMap state mRenamedSource =
--
-- With our mapping we know that we can display exported modules M1 and M2.
--
-unrestrictedModuleImports :: [ImportDecl name] -> M.Map ModuleName [ModuleName]
+unrestrictedModuleImports :: [ImportDecl GhcRn] -> M.Map ModuleName [ModuleName]
unrestrictedModuleImports idecls =
M.map (map (unLoc . ideclName))
$ M.filter (all isInteresting) impModMap
@@ -306,7 +395,7 @@ mkWarningMap dflags warnings gre exps = case warnings of
let ws' = [ (n, w)
| (occ, w) <- ws
, elt <- lookupGlobalRdrEnv gre occ
- , let n = gre_name elt, n `elem` exps ]
+ , let n = greMangledName elt, n `elem` exps ]
in M.fromList <$> traverse (bitraverse pure (parseWarning dflags gre)) ws'
moduleWarning :: DynFlags -> GlobalRdrEnv -> Warnings -> ErrMsgM (Maybe (Doc Name))
@@ -436,7 +525,7 @@ mkMaps dflags pkgName gre instances decls = do
-- The CoAx's loc is the whole line, but only for TFs. The
-- workaround is to dig into the family instance declaration and
-- get the identifier with the right location.
- TyFamInstD _ (TyFamInstDecl d') -> getLoc (feqn_tycon (hsib_body d'))
+ TyFamInstD _ (TyFamInstDecl d') -> getLoc (feqn_tycon d')
_ -> getInstLoc d
names l (DerivD {}) = maybeToList (M.lookup l instanceMap) -- See note [2].
names _ decl = getMainDeclBinder decl
@@ -470,7 +559,7 @@ mkFixMap group_ =
-- We create the export items even if the module is hidden, since they
-- might be useful when creating the export items for other modules.
mkExportItems
- :: HasCallStack
+ :: Monad m
=> Bool -- is it a signature
-> IfaceMap
-> Maybe Package -- this package
@@ -488,7 +577,7 @@ mkExportItems
-> Avails -- exported stuff from this module
-> InstIfaceMap
-> DynFlags
- -> ErrMsgGhc [ExportItem GhcRn]
+ -> IfM m [ExportItem GhcRn]
mkExportItems
is_sig modMap pkgName thisMod semMod warnings gre exportedNames decls
maps fixMap unrestricted_imp_mods splices exportList allExports
@@ -509,7 +598,7 @@ mkExportItems
return [ExportDoc doc]
lookupExport (IEDocNamed _ str, _) = liftErrMsg $
- findNamedDoc str [ unLoc d | d <- decls ] >>= \case
+ findNamedDoc str [ unL d | d <- decls ] >>= \case
Nothing -> return []
Just docStr -> do
doc <- processDocStringParas dflags pkgName gre docStr
@@ -530,25 +619,39 @@ mkExportItems
availExportItem is_sig modMap thisMod semMod warnings exportedNames
maps fixMap splices instIfaceMap dflags avail
-availExportItem :: HasCallStack
- => Bool -- is it a signature
- -> IfaceMap
- -> Module -- this module
- -> Module -- semantic module
- -> WarningMap
- -> [Name] -- exported names (orig)
- -> Maps
- -> FixMap
- -> [SrcSpan] -- splice locations
- -> InstIfaceMap
- -> DynFlags
- -> AvailInfo
- -> ErrMsgGhc [ExportItem GhcRn]
+
+-- Extract the minimal complete definition of a Name, if one exists
+minimalDef :: Monad m => Name -> IfM m (Maybe ClassMinimalDef)
+minimalDef n = do
+ mty <- lookupName n
+ case mty of
+ Just (ATyCon (tyConClass_maybe -> Just c)) ->
+ return . Just $ classMinimalDef c
+ _ ->
+ return Nothing
+
+
+availExportItem
+ :: forall m
+ . Monad m
+ => Bool -- is it a signature
+ -> IfaceMap
+ -> Module -- this module
+ -> Module -- semantic module
+ -> WarningMap
+ -> [Name] -- exported names (orig)
+ -> Maps
+ -> FixMap
+ -> [SrcSpan] -- splice locations
+ -> InstIfaceMap
+ -> DynFlags
+ -> AvailInfo
+ -> IfM m [ExportItem GhcRn]
availExportItem is_sig modMap thisMod semMod warnings exportedNames
(docMap, argMap, declMap, _) fixMap splices instIfaceMap
dflags availInfo = declWith availInfo
where
- declWith :: AvailInfo -> ErrMsgGhc [ ExportItem GhcRn ]
+ declWith :: AvailInfo -> IfM m [ ExportItem GhcRn ]
declWith avail = do
let t = availName avail
r <- findDecl avail
@@ -558,13 +661,13 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames
export <- hiValExportItem dflags t l doc (l `elem` splices) $ M.lookup t fixMap
return [export]
(ds, docs_) | decl : _ <- filter (not . isValD . unLoc) ds ->
- let declNames = getMainDeclBinder (unLoc decl)
+ let declNames = getMainDeclBinder (unL decl)
in case () of
_
-- We should not show a subordinate by itself if any of its
-- parents is also exported. See note [1].
| t `notElem` declNames,
- Just p <- find isExported (parents t $ unLoc decl) ->
+ Just p <- find isExported (parents t $ unL decl) ->
do liftErrMsg $ tell [
"Warning: " ++ moduleString thisMod ++ ": " ++
pretty dflags (nameOccName t) ++ " is exported separately but " ++
@@ -584,11 +687,11 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames
let newDecl = L loc . SigD noExtField . fromJust $ filterSigNames (== t) sig
in availExportDecl avail newDecl docs_
- L loc (TyClD _ cl@ClassDecl{}) -> do
- mdef <- liftGhcToErrMsgGhc $ minimalDef t
+ L loc (TyClD _ ClassDecl {..}) -> do
+ mdef <- minimalDef t
let sig = maybeToList $ fmap (noLoc . MinimalSig noExtField NoSourceText . noLoc . fmap noLoc) mdef
availExportDecl avail
- (L loc $ TyClD noExtField cl { tcdSigs = sig ++ tcdSigs cl }) docs_
+ (L loc $ TyClD noExtField ClassDecl { tcdSigs = sig ++ tcdSigs, .. }) docs_
_ -> availExportDecl avail decl docs_
@@ -614,7 +717,7 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames
_ -> return []
-- Tries 'extractDecl' first then falls back to 'hiDecl' if that fails
- availDecl :: Name -> LHsDecl GhcRn -> ErrMsgGhc (LHsDecl GhcRn)
+ availDecl :: Name -> LHsDecl GhcRn -> IfM m (LHsDecl GhcRn)
availDecl declName parentDecl =
case extractDecl declMap declName parentDecl of
Right d -> pure d
@@ -622,11 +725,11 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames
synifiedDeclOpt <- hiDecl dflags declName
case synifiedDeclOpt of
Just synifiedDecl -> pure synifiedDecl
- Nothing -> O.pprPanic "availExportItem" (O.text err)
+ Nothing -> pprPanic "availExportItem" (O.text err)
availExportDecl :: AvailInfo -> LHsDecl GhcRn
-> (DocForDecl Name, [(Name, DocForDecl Name)])
- -> ErrMsgGhc [ ExportItem GhcRn ]
+ -> IfM m [ ExportItem GhcRn ]
availExportDecl avail decl (doc, subs)
| availExportsDecl avail = do
extractedDecl <- availDecl (availName avail) decl
@@ -672,7 +775,7 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames
exportedNameSet = mkNameSet exportedNames
isExported n = elemNameSet n exportedNameSet
- findDecl :: AvailInfo -> ErrMsgGhc ([LHsDecl GhcRn], (DocForDecl Name, [(Name, DocForDecl Name)]))
+ findDecl :: AvailInfo -> IfM m ([LHsDecl GhcRn], (DocForDecl Name, [(Name, DocForDecl Name)]))
findDecl avail
| m == semMod =
case M.lookup n declMap of
@@ -701,10 +804,10 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames
n = availName avail
m = nameModule n
- findBundledPatterns :: AvailInfo -> ErrMsgGhc [(HsDecl GhcRn, DocForDecl Name)]
+ findBundledPatterns :: AvailInfo -> IfM m [(HsDecl GhcRn, DocForDecl Name)]
findBundledPatterns avail = do
patsyns <- for constructor_names $ \name -> do
- mtyThing <- liftGhcToErrMsgGhc (lookupName name)
+ mtyThing <- lookupName name
case mtyThing of
Just (AConLike PatSynCon{}) -> do
export_items <- declWith (Avail.avail name)
@@ -720,16 +823,8 @@ availExportItem is_sig modMap thisMod semMod warnings exportedNames
constructor_names =
filter isDataConName (availSubordinates avail)
--- this heavily depends on the invariants stated in Avail
-availExportsDecl :: AvailInfo -> Bool
-availExportsDecl (AvailTC ty_name names _)
- | n : _ <- names = ty_name == n
- | otherwise = False
-availExportsDecl _ = True
-
availSubordinates :: AvailInfo -> [Name]
-availSubordinates avail =
- filter (/= availName avail) (availNamesWithSelectors avail)
+availSubordinates = map greNameMangledName . availSubordinateGreNames
availNoDocs :: AvailInfo -> [(Name, DocForDecl Name)]
availNoDocs avail =
@@ -742,10 +837,9 @@ semToIdMod this_uid m
| Module.isHoleModule m = mkModule this_uid (moduleName m)
| otherwise = m
--- | Reify a declaration from the GHC internal 'TyThing' representation.
-hiDecl :: DynFlags -> Name -> ErrMsgGhc (Maybe (LHsDecl GhcRn))
+hiDecl :: Monad m => DynFlags -> Name -> IfM m (Maybe (LHsDecl GhcRn))
hiDecl dflags t = do
- mayTyThing <- liftGhcToErrMsgGhc $ lookupName t
+ mayTyThing <- lookupName t
case mayTyThing of
Nothing -> do
liftErrMsg $ tell ["Warning: Not found in environment: " ++ pretty dflags t]
@@ -758,14 +852,15 @@ hiDecl dflags t = do
warnLine x = O.text "haddock-bug:" O.<+> O.text x O.<>
O.comma O.<+> O.quotes (O.ppr t) O.<+>
O.text "-- Please report this on Haddock issue tracker!"
- bugWarn = O.showSDoc dflags . warnLine
+ bugWarn = showSDoc dflags . warnLine
-- | This function is called for top-level bindings without type signatures.
-- It gets the type signature from GHC and that means it's not going to
-- have a meaningful 'SrcSpan'. So we pass down 'SrcSpan' for the
-- declaration and use it instead - 'nLoc' here.
-hiValExportItem :: DynFlags -> Name -> SrcSpan -> DocForDecl Name -> Bool
- -> Maybe Fixity -> ErrMsgGhc (ExportItem GhcRn)
+hiValExportItem
+ :: Monad m => DynFlags -> Name -> SrcSpan -> DocForDecl Name -> Bool
+ -> Maybe Fixity -> IfM m (ExportItem GhcRn)
hiValExportItem dflags name nLoc doc splice fixity = do
mayDecl <- hiDecl dflags name
case mayDecl of
@@ -795,12 +890,14 @@ lookupDocs avail warnings docMap argMap =
-- | Export the given module as `ExportModule`. We are not concerned with the
-- single export items of the given module.
-moduleExport :: Module -- ^ Module A (identity, NOT semantic)
- -> DynFlags -- ^ The flags used when typechecking A
- -> IfaceMap -- ^ Already created interfaces
- -> InstIfaceMap -- ^ Interfaces in other packages
- -> ModuleName -- ^ The exported module
- -> ErrMsgGhc [ExportItem GhcRn] -- ^ Resulting export items
+moduleExport
+ :: Monad m
+ => Module -- ^ Module A (identity, NOT semantic)
+ -> DynFlags -- ^ The flags used when typechecking A
+ -> IfaceMap -- ^ Already created interfaces
+ -> InstIfaceMap -- ^ Interfaces in other packages
+ -> ModuleName -- ^ The exported module
+ -> IfM m [ExportItem GhcRn] -- ^ Resulting export items
moduleExport thisMod dflags ifaceMap instIfaceMap expMod =
-- NB: we constructed the identity module when looking up in
-- the IfaceMap.
@@ -814,9 +911,8 @@ moduleExport thisMod dflags ifaceMap instIfaceMap expMod =
case M.lookup expMod (M.mapKeys moduleName instIfaceMap) of
Just iface -> return [ ExportModule (instMod iface) ]
Nothing -> do
- liftErrMsg $
- tell ["Warning: " ++ pretty dflags thisMod ++ ": Could not find " ++
- "documentation for exported module: " ++ pretty dflags expMod]
+ liftErrMsg $ tell ["Warning: " ++ pretty dflags thisMod ++ ": Could not find " ++
+ "documentation for exported module: " ++ pretty dflags expMod]
return []
where
m = mkModule (moduleUnit thisMod) expMod -- Identity module!
@@ -842,22 +938,24 @@ moduleExport thisMod dflags ifaceMap instIfaceMap expMod =
-- every locally defined declaration is exported; thus, we just
-- zip through the renamed declarations.
-fullModuleContents :: Bool -- is it a signature
- -> IfaceMap
- -> Maybe Package -- this package
- -> Module -- this module
- -> Module -- semantic module
- -> WarningMap
- -> GlobalRdrEnv -- ^ The renaming environment
- -> [Name] -- exported names (orig)
- -> [LHsDecl GhcRn] -- renamed source declarations
- -> Maps
- -> FixMap
- -> [SrcSpan] -- splice locations
- -> InstIfaceMap
- -> DynFlags
- -> Avails
- -> ErrMsgGhc [ExportItem GhcRn]
+fullModuleContents
+ :: Monad m
+ => Bool -- is it a signature
+ -> IfaceMap
+ -> Maybe Package -- this package
+ -> Module -- this module
+ -> Module -- semantic module
+ -> WarningMap
+ -> GlobalRdrEnv -- ^ The renaming environment
+ -> [Name] -- exported names (orig)
+ -> [LHsDecl GhcRn] -- renamed source declarations
+ -> Maps
+ -> FixMap
+ -> [SrcSpan] -- splice locations
+ -> InstIfaceMap
+ -> DynFlags
+ -> Avails
+ -> IfM m [ExportItem GhcRn]
fullModuleContents is_sig modMap pkgName thisMod semMod warnings gre exportedNames
decls maps@(_, _, declMap, _) fixMap splices instIfaceMap dflags avails = do
let availEnv = availsToNameEnv (nubAvails avails)
@@ -870,7 +968,7 @@ fullModuleContents is_sig modMap pkgName thisMod semMod warnings gre exportedNam
doc <- liftErrMsg (processDocStringParas dflags pkgName gre docStr)
return [[ExportDoc doc]]
(L _ (ValD _ valDecl))
- | name:_ <- collectHsBindBinders valDecl
+ | name:_ <- collectHsBindBinders CollNoDictBinders valDecl
, Just (L _ SigD{}:_) <- filter isSigD <$> M.lookup name declMap
-> return []
_ ->
@@ -885,7 +983,6 @@ fullModuleContents is_sig modMap pkgName thisMod semMod warnings gre exportedNam
isSigD (L _ SigD{}) = True
isSigD _ = False
-
-- | Sometimes the declaration we want to export is not the "main" declaration:
-- it might be an individual record selector or a class method. In these
-- cases we have to extract the required declaration (and somehow cobble
@@ -936,7 +1033,7 @@ extractDecl declMap name decl
TyClD _ d@DataDecl { tcdLName = L _ dataNm
, tcdDataDefn = HsDataDefn { dd_cons = dataCons } } -> do
- let ty_args = map HsValArg (lHsQTyVarsToTypes (tyClDeclTyVars d))
+ let ty_args = lHsQTyVarsToTypes (tyClDeclTyVars d)
lsig <- if isDataConName name
then extractPatternSyn name dataNm ty_args dataCons
else extractRecSel name dataNm ty_args dataCons
@@ -946,30 +1043,26 @@ extractDecl declMap name decl
| isValName name
, Just (famInst:_) <- M.lookup name declMap
-> extractDecl declMap name famInst
- InstD _ (DataFamInstD _ (DataFamInstDecl (HsIB { hsib_body =
- FamEqn { feqn_tycon = L _ famName
- , feqn_pats = ty_args
- , feqn_rhs = HsDataDefn { dd_cons = dataCons } }}))) -> do
- lsig <- if isDataConName name
- then extractPatternSyn name famName ty_args dataCons
- else extractRecSel name famName ty_args dataCons
- pure (SigD noExtField <$> lsig)
+ InstD _ (DataFamInstD _ (DataFamInstDecl
+ (FamEqn { feqn_tycon = L _ n
+ , feqn_pats = tys
+ , feqn_rhs = defn }))) ->
+ if isDataConName name
+ then fmap (SigD noExtField) <$> extractPatternSyn name n tys (dd_cons defn)
+ else fmap (SigD noExtField) <$> extractRecSel name n tys (dd_cons defn)
InstD _ (ClsInstD _ ClsInstDecl { cid_datafam_insts = insts })
| isDataConName name ->
- let matches = [ d' | L _ d'@(DataFamInstDecl (HsIB { hsib_body =
- FamEqn { feqn_rhs = HsDataDefn { dd_cons = dataCons }
- }
- })) <- insts
- , name `elem` map unLoc (concatMap (getConNames . unLoc) dataCons)
+ let matches = [ d' | L _ d'@(DataFamInstDecl (FamEqn { feqn_rhs = dd })) <- insts
+ , name `elem` map unLoc (concatMap (getConNames . unLoc) (dd_cons dd))
]
in case matches of
[d0] -> extractDecl declMap name (noLoc (InstD noExtField (DataFamInstD noExtField d0)))
_ -> Left "internal: extractDecl (ClsInstD)"
| otherwise ->
- let matches = [ d' | L _ d'@(DataFamInstDecl (HsIB { hsib_body = d }))
+ let matches = [ d' | L _ d'@(DataFamInstDecl d )
<- insts
-- , L _ ConDecl { con_details = RecCon rec } <- dd_cons (feqn_rhs d)
- , RecCon rec <- map (getConArgs . unLoc) (dd_cons (feqn_rhs d))
+ , Just rec <- map (getRecConArgs_maybe . unLoc) (dd_cons (feqn_rhs d))
, ConDeclField { cd_fld_names = ns } <- map unLoc (unLoc rec)
, L _ n <- ns
, extFieldOcc n == name
@@ -979,10 +1072,13 @@ extractDecl declMap name decl
_ -> Left "internal: extractDecl (ClsInstD)"
_ -> Left ("extractDecl: Unhandled decl for " ++ getOccString name)
-extractPatternSyn :: Name -> Name -> [LHsTypeArg GhcRn] -> [LConDecl GhcRn] -> Either ErrMsg (LSig GhcRn)
+extractPatternSyn :: HasCallStack
+ => Name -> Name
+ -> [LHsTypeArg GhcRn] -> [LConDecl GhcRn]
+ -> Either ErrMsg (LSig GhcRn)
extractPatternSyn nm t tvs cons =
case filter matches cons of
- [] -> Left . O.showSDocUnsafe $
+ [] -> Left . O.showSDocOneLine O.defaultSDocContext $
O.text "constructor pattern " O.<+> O.ppr nm O.<+> O.text "not found in type" O.<+> O.ppr t
con:_ -> pure (extract <$> con)
where
@@ -991,17 +1087,21 @@ extractPatternSyn nm t tvs cons =
extract :: ConDecl GhcRn -> Sig GhcRn
extract con =
let args =
- case getConArgs con of
- PrefixCon args' -> (map hsScaledThing args')
- RecCon (L _ fields) -> cd_fld_type . unLoc <$> fields
- InfixCon arg1 arg2 -> map hsScaledThing [arg1, arg2]
+ case con of
+ ConDeclH98 { con_args = con_args' } -> case con_args' of
+ PrefixCon _ args' -> map hsScaledThing args'
+ RecCon (L _ fields) -> cd_fld_type . unLoc <$> fields
+ InfixCon arg1 arg2 -> map hsScaledThing [arg1, arg2]
+ ConDeclGADT { con_g_args = con_args' } -> case con_args' of
+ PrefixConGADT args' -> map hsScaledThing args'
+ RecConGADT (L _ fields) -> cd_fld_type . unLoc <$> fields
typ = longArrow args (data_ty con)
typ' =
case con of
ConDeclH98 { con_mb_cxt = Just cxt } -> noLoc (HsQualTy noExtField cxt typ)
_ -> typ
typ'' = noLoc (HsQualTy noExtField (noLoc []) typ')
- in PatSynSig noExtField [noLoc nm] (mkEmptyImplicitBndrs typ'')
+ in PatSynSig noExtField [noLoc nm] (mkEmptySigType typ'')
longArrow :: [LHsType GhcRn] -> LHsType GhcRn -> LHsType GhcRn
longArrow inputs output = foldr (\x y -> noLoc (HsFunTy noExtField (HsUnrestrictedArrow NormalSyntax) x y)) output inputs
@@ -1019,9 +1119,9 @@ extractRecSel :: Name -> Name -> [LHsTypeArg GhcRn] -> [LConDecl GhcRn]
extractRecSel _ _ _ [] = Left "extractRecSel: selector not found"
extractRecSel nm t tvs (L _ con : rest) =
- case getConArgs con of
- RecCon (L _ fields) | ((l,L _ (ConDeclField _ _nn ty _)) : _) <- matching_fields fields ->
- pure (L l (TypeSig noExtField [noLoc nm] (mkEmptySigWcType (noLoc (HsFunTy noExtField (HsUnrestrictedArrow NormalSyntax) data_ty (getBangType ty))))))
+ case getRecConArgs_maybe con of
+ Just (L _ fields) | ((l,L _ (ConDeclField _ _nn ty _)) : _) <- matching_fields fields ->
+ pure (L l (TypeSig noExtField [noLoc nm] (mkEmptyWildCardBndrs $ mkEmptySigType (noLoc (HsFunTy noExtField (HsUnrestrictedArrow NormalSyntax) data_ty (getBangType ty))))))
_ -> extractRecSel nm t tvs rest
where
matching_fields :: [LConDeclField GhcRn] -> [(SrcSpan, LConDeclField GhcRn)]
diff --git a/haddock-api/src/Haddock/Interface/Json.hs b/haddock-api/src/Haddock/Interface/Json.hs
index 95889a63..92fb2e75 100644
--- a/haddock-api/src/Haddock/Interface/Json.hs
+++ b/haddock-api/src/Haddock/Interface/Json.hs
@@ -5,7 +5,7 @@ module Haddock.Interface.Json (
, renderJson
) where
-import GHC.Types.Basic
+import GHC.Types.Fixity
import GHC.Utils.Json
import GHC.Unit.Module
import GHC.Types.Name
diff --git a/haddock-api/src/Haddock/Interface/LexParseRn.hs b/haddock-api/src/Haddock/Interface/LexParseRn.hs
index 87210273..6da89e7c 100644
--- a/haddock-api/src/Haddock/Interface/LexParseRn.hs
+++ b/haddock-api/src/Haddock/Interface/LexParseRn.hs
@@ -1,5 +1,6 @@
{-# OPTIONS_GHC -Wwarn #-}
{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ViewPatterns #-}
-----------------------------------------------------------------------------
-- |
@@ -21,8 +22,8 @@ module Haddock.Interface.LexParseRn
import Control.Arrow
import Control.Monad
-import Data.Functor (($>))
-import Data.List (maximumBy, (\\))
+import Data.Functor
+import Data.List ((\\), maximumBy)
import Data.Ord
import Documentation.Haddock.Doc (metaDocConcat)
import GHC.Driver.Session (languageExtensions)
@@ -32,8 +33,9 @@ import Haddock.Interface.ParseModuleHeader
import Haddock.Parser
import Haddock.Types
import GHC.Types.Name
+import GHC.Types.Avail ( availName )
import GHC.Parser.PostProcess
-import GHC.Utils.Outputable ( showPpr, showSDoc )
+import GHC.Driver.Ppr ( showPpr, showSDoc )
import GHC.Types.Name.Reader
import GHC.Data.EnumSet as EnumSet
@@ -134,7 +136,7 @@ rename dflags gre = rn
-- There is only one name in the environment that matches so
-- use it.
- [a] -> pure (DocIdentifier (i $> gre_name a))
+ [a] -> pure $ DocIdentifier (i $> greMangledName a)
-- There are multiple names available.
gres -> ambiguous dflags i gres
@@ -199,9 +201,10 @@ ambiguous :: DynFlags
-> [GlobalRdrElt] -- ^ More than one @gre@s sharing the same `RdrName` above.
-> ErrMsgM (Doc Name)
ambiguous dflags x gres = do
- let dflt = maximumBy (comparing (gre_lcl &&& isTyConName . gre_name)) gres
+ let noChildren = map availName (gresToAvailInfo gres)
+ dflt = maximumBy (comparing (isLocalName &&& isTyConName)) noChildren
msg = "Warning: " ++ showNsRdrName dflags x ++ " is ambiguous. It is defined\n" ++
- concatMap (\n -> " * " ++ defnLoc n ++ "\n") gres ++
+ concatMap (\n -> " * " ++ defnLoc n ++ "\n") (map greMangledName gres) ++
" You may be able to disambiguate the identifier by qualifying it or\n" ++
" by specifying the type/value namespace explicitly.\n" ++
" Defaulting to the one defined " ++ defnLoc dflt
@@ -210,10 +213,12 @@ ambiguous dflags x gres = do
-- of the same name, but not the only constructor.
-- For example, for @data D = C | D@, someone may want to reference the @D@
-- constructor.
- when (length (gresToAvailInfo gres) > 1) $ tell [msg]
- pure (DocIdentifier (x $> gre_name dflt))
+ when (length noChildren > 1) $ tell [msg]
+ pure (DocIdentifier (x $> dflt))
where
- defnLoc = showSDoc dflags . pprNameDefnLoc . gre_name
+ isLocalName (nameSrcLoc -> RealSrcLoc {}) = True
+ isLocalName _ = False
+ defnLoc = showSDoc dflags . pprNameDefnLoc
-- | Handle value-namespaced names that cannot be for values.
--
diff --git a/haddock-api/src/Haddock/Interface/Rename.hs b/haddock-api/src/Haddock/Interface/Rename.hs
index bb9cd02d..b212adce 100644
--- a/haddock-api/src/Haddock/Interface/Rename.hs
+++ b/haddock-api/src/Haddock/Interface/Rename.hs
@@ -213,10 +213,10 @@ renameLTypeArg (HsTypeArg l ki) = do { ki' <- renameLKind ki
renameLTypeArg (HsArgPar sp) = return $ HsArgPar sp
renameLSigType :: LHsSigType GhcRn -> RnM (LHsSigType DocNameI)
-renameLSigType = renameImplicit renameLType
+renameLSigType = mapM renameSigType
renameLSigWcType :: LHsSigWcType GhcRn -> RnM (LHsSigWcType DocNameI)
-renameLSigWcType = renameWc (renameImplicit renameLType)
+renameLSigWcType = renameWc renameLSigType
renameLKind :: LHsKind GhcRn -> RnM (LHsKind DocNameI)
renameLKind = renameLType
@@ -310,12 +310,18 @@ renameType t = case t of
HsTyLit _ x -> return (HsTyLit noExtField x)
HsRecTy _ a -> HsRecTy noExtField <$> mapM renameConDeclFieldField a
- (XHsType (NHsCoreTy a)) -> pure (XHsType (NHsCoreTy a))
+ XHsType a -> pure (XHsType a)
HsExplicitListTy i a b -> HsExplicitListTy i a <$> mapM renameLType b
HsExplicitTupleTy a b -> HsExplicitTupleTy a <$> mapM renameLType b
HsSpliceTy _ s -> renameHsSpliceTy s
HsWildCardTy a -> pure (HsWildCardTy a)
+renameSigType :: HsSigType GhcRn -> RnM (HsSigType DocNameI)
+renameSigType (HsSig { sig_bndrs = bndrs, sig_body = body }) = do
+ bndrs' <- renameOuterTyVarBndrs bndrs
+ body' <- renameLType body
+ pure $ HsSig { sig_ext = noExtField, sig_bndrs = bndrs', sig_body = body' }
+
-- | Rename splices, but _only_ those that turn out to be for types.
-- I think this is actually safe for our possible inputs:
--
@@ -496,46 +502,55 @@ renameDataDefn (HsDataDefn { dd_ND = nd, dd_ctxt = lcontext, dd_cType = cType
renameCon :: ConDecl GhcRn -> RnM (ConDecl DocNameI)
renameCon decl@(ConDeclH98 { con_name = lname, con_ex_tvs = ltyvars
, con_mb_cxt = lcontext, con_args = details
- , con_doc = mbldoc }) = do
+ , con_doc = mbldoc
+ , con_forall = forall }) = do
lname' <- renameL lname
ltyvars' <- mapM renameLTyVarBndr ltyvars
lcontext' <- traverse renameLContext lcontext
- details' <- renameDetails details
+ details' <- renameH98Details details
mbldoc' <- mapM renameLDocHsSyn mbldoc
return (decl { con_ext = noExtField, con_name = lname', con_ex_tvs = ltyvars'
, con_mb_cxt = lcontext'
+ , con_forall = forall -- Remove when #18311 is fixed
, con_args = details', con_doc = mbldoc' })
-renameCon decl@(ConDeclGADT { con_names = lnames, con_qvars = ltyvars
- , con_mb_cxt = lcontext, con_args = details
+renameCon ConDeclGADT { con_names = lnames, con_bndrs = bndrs
+ , con_mb_cxt = lcontext, con_g_args = details
, con_res_ty = res_ty
- , con_doc = mbldoc }) = do
+ , con_doc = mbldoc } = do
lnames' <- mapM renameL lnames
- ltyvars' <- mapM renameLTyVarBndr ltyvars
+ bndrs' <- mapM renameOuterTyVarBndrs bndrs
lcontext' <- traverse renameLContext lcontext
- details' <- renameDetails details
+ details' <- renameGADTDetails details
res_ty' <- renameLType res_ty
mbldoc' <- mapM renameLDocHsSyn mbldoc
- return (decl { con_g_ext = noExtField, con_names = lnames', con_qvars = ltyvars'
- , con_mb_cxt = lcontext', con_args = details'
+ return (ConDeclGADT
+ { con_g_ext = noExtField, con_names = lnames', con_bndrs = bndrs'
+ , con_mb_cxt = lcontext', con_g_args = details'
, con_res_ty = res_ty', con_doc = mbldoc' })
renameHsScaled :: HsScaled GhcRn (LHsType GhcRn)
-> RnM (HsScaled DocNameI (LHsType DocNameI))
renameHsScaled (HsScaled w ty) = HsScaled <$> renameArrow w <*> renameLType ty
-renameDetails :: HsConDeclDetails GhcRn -> RnM (HsConDeclDetails DocNameI)
-renameDetails (RecCon (L l fields)) = do
+renameH98Details :: HsConDeclH98Details GhcRn
+ -> RnM (HsConDeclH98Details DocNameI)
+renameH98Details (RecCon (L l fields)) = do
fields' <- mapM renameConDeclFieldField fields
return (RecCon (L l fields'))
- -- This causes an assertion failure
---renameDetails (PrefixCon ps) = -- return . PrefixCon =<< mapM (_renameLType) ps
-renameDetails (PrefixCon ps) = PrefixCon <$> mapM renameHsScaled ps
-renameDetails (InfixCon a b) = do
+renameH98Details (PrefixCon ts ps) = PrefixCon ts <$> mapM renameHsScaled ps
+renameH98Details (InfixCon a b) = do
a' <- renameHsScaled a
b' <- renameHsScaled b
return (InfixCon a' b')
+renameGADTDetails :: HsConDeclGADTDetails GhcRn
+ -> RnM (HsConDeclGADTDetails DocNameI)
+renameGADTDetails (RecConGADT (L l fields)) = do
+ fields' <- mapM renameConDeclFieldField fields
+ return (RecConGADT (L l fields'))
+renameGADTDetails (PrefixConGADT ps) = PrefixConGADT <$> mapM renameHsScaled ps
+
renameConDeclFieldField :: LConDeclField GhcRn -> RnM (LConDeclField DocNameI)
renameConDeclFieldField (L l (ConDeclField _ names t doc)) = do
names' <- mapM renameLFieldOcc names
@@ -630,32 +645,26 @@ renameTyFamInstD (TyFamInstDecl { tfid_eqn = eqn })
; return (TyFamInstDecl { tfid_eqn = eqn' }) }
renameTyFamInstEqn :: TyFamInstEqn GhcRn -> RnM (TyFamInstEqn DocNameI)
-renameTyFamInstEqn eqn
- = renameImplicit rename_ty_fam_eqn eqn
- where
- rename_ty_fam_eqn
- :: FamEqn GhcRn (LHsType GhcRn)
- -> RnM (FamEqn DocNameI (LHsType DocNameI))
- rename_ty_fam_eqn (FamEqn { feqn_tycon = tc, feqn_bndrs = bndrs
- , feqn_pats = pats, feqn_fixity = fixity
- , feqn_rhs = rhs })
- = do { tc' <- renameL tc
- ; bndrs' <- traverse (mapM renameLTyVarBndr) bndrs
- ; pats' <- mapM renameLTypeArg pats
- ; rhs' <- renameLType rhs
- ; return (FamEqn { feqn_ext = noExtField
- , feqn_tycon = tc'
- , feqn_bndrs = bndrs'
- , feqn_pats = pats'
- , feqn_fixity = fixity
- , feqn_rhs = rhs' }) }
+renameTyFamInstEqn (FamEqn { feqn_tycon = tc, feqn_bndrs = bndrs
+ , feqn_pats = pats, feqn_fixity = fixity
+ , feqn_rhs = rhs })
+ = do { tc' <- renameL tc
+ ; bndrs' <- renameOuterTyVarBndrs bndrs
+ ; pats' <- mapM renameLTypeArg pats
+ ; rhs' <- renameLType rhs
+ ; return (FamEqn { feqn_ext = noExtField
+ , feqn_tycon = tc'
+ , feqn_bndrs = bndrs'
+ , feqn_pats = pats'
+ , feqn_fixity = fixity
+ , feqn_rhs = rhs' }) }
renameTyFamDefltD :: TyFamDefltDecl GhcRn -> RnM (TyFamDefltDecl DocNameI)
renameTyFamDefltD = renameTyFamInstD
renameDataFamInstD :: DataFamInstDecl GhcRn -> RnM (DataFamInstDecl DocNameI)
renameDataFamInstD (DataFamInstDecl { dfid_eqn = eqn })
- = do { eqn' <- renameImplicit rename_data_fam_eqn eqn
+ = do { eqn' <- rename_data_fam_eqn eqn
; return (DataFamInstDecl { dfid_eqn = eqn' }) }
where
rename_data_fam_eqn
@@ -665,7 +674,7 @@ renameDataFamInstD (DataFamInstDecl { dfid_eqn = eqn })
, feqn_pats = pats, feqn_fixity = fixity
, feqn_rhs = defn })
= do { tc' <- renameL tc
- ; bndrs' <- traverse (mapM renameLTyVarBndr) bndrs
+ ; bndrs' <- renameOuterTyVarBndrs bndrs
; pats' <- mapM renameLTypeArg pats
; defn' <- renameDataDefn defn
; return (FamEqn { feqn_ext = noExtField
@@ -675,13 +684,12 @@ renameDataFamInstD (DataFamInstDecl { dfid_eqn = eqn })
, feqn_fixity = fixity
, feqn_rhs = defn' }) }
-renameImplicit :: (in_thing -> RnM out_thing)
- -> HsImplicitBndrs GhcRn in_thing
- -> RnM (HsImplicitBndrs DocNameI out_thing)
-renameImplicit rn_thing (HsIB { hsib_body = thing })
- = do { thing' <- rn_thing thing
- ; return (HsIB { hsib_body = thing'
- , hsib_ext = noExtField }) }
+renameOuterTyVarBndrs :: HsOuterTyVarBndrs flag GhcRn
+ -> RnM (HsOuterTyVarBndrs flag DocNameI)
+renameOuterTyVarBndrs (HsOuterImplicit{}) =
+ pure $ HsOuterImplicit{hso_ximplicit = noExtField}
+renameOuterTyVarBndrs (HsOuterExplicit{hso_bndrs = exp_bndrs}) =
+ HsOuterExplicit noExtField <$> mapM renameLTyVarBndr exp_bndrs
renameWc :: (in_thing -> RnM out_thing)
-> HsWildCardBndrs GhcRn in_thing
diff --git a/haddock-api/src/Haddock/Interface/Specialize.hs b/haddock-api/src/Haddock/Interface/Specialize.hs
index ad2f61c2..f37e1da9 100644
--- a/haddock-api/src/Haddock/Interface/Specialize.hs
+++ b/haddock-api/src/Haddock/Interface/Specialize.hs
@@ -3,6 +3,7 @@
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE GADTs #-}
{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
module Haddock.Interface.Specialize
@@ -38,7 +39,7 @@ specialize specs = go spec_map0
go :: forall x. Data x => Map Name (HsType GhcRn) -> x -> x
go spec_map = everywhereButType @Name $ mkT $ sugar . strip_kind_sig . specialize_ty_var spec_map
- strip_kind_sig :: HsType name -> HsType name
+ strip_kind_sig :: HsType GhcRn -> HsType GhcRn
strip_kind_sig (HsKindSig _ (L _ t) _) = t
strip_kind_sig typ = typ
@@ -57,7 +58,7 @@ specialize specs = go spec_map0
--
-- Again, it is just a convenience function around 'specialize'. Note that
-- length of type list should be the same as the number of binders.
-specializeTyVarBndrs :: LHsQTyVars GhcRn -> [HsType GhcRn] -> HsType GhcRn -> HsType GhcRn
+specializeTyVarBndrs :: Data a => LHsQTyVars GhcRn -> [HsType GhcRn] -> a -> a
specializeTyVarBndrs bndrs typs = specialize $ zip bndrs' typs
where
bndrs' = map (hsTyVarBndrName . unLoc) . hsq_explicit $ bndrs
@@ -74,13 +75,13 @@ specializeSig :: LHsQTyVars GhcRn -> [HsType GhcRn]
-> Sig GhcRn
-> Sig GhcRn
specializeSig bndrs typs (TypeSig _ lnames typ) =
- TypeSig noExtField lnames (typ {hswc_body = (hswc_body typ) {hsib_body = noLoc typ'}})
+ TypeSig noExtField lnames (typ {hswc_body = noLoc typ'})
where
- true_type :: HsType GhcRn
- true_type = unLoc (hsSigWcType typ)
- typ' :: HsType GhcRn
+ true_type :: HsSigType GhcRn
+ true_type = unLoc (dropWildCards typ)
+ typ' :: HsSigType GhcRn
typ' = rename fv $ specializeTyVarBndrs bndrs typs true_type
- fv = foldr Set.union Set.empty . map freeVariables $ typs
+ fv = foldr Set.union Set.empty . map freeVariablesType $ typs
specializeSig _ _ sig = sig
@@ -121,7 +122,7 @@ sugarTuples typ =
aux apps (HsAppTy _ (L _ ftyp) atyp) = aux (atyp:apps) ftyp
aux apps (HsParTy _ (L _ typ')) = aux apps typ'
aux apps (HsTyVar _ _ (L _ name))
- | isBuiltInSyntax name' && suitable = HsTupleTy noExtField HsBoxedTuple apps
+ | isBuiltInSyntax name' && suitable = HsTupleTy noExtField HsBoxedOrConstraintTuple apps
where
name' = getName name
strName = getOccString name
@@ -176,19 +177,25 @@ parseTupleArity _ = Nothing
-- not converted to 'String' or alike to avoid new allocations. Additionally,
-- since it is stored mostly in 'Set', fast comparison of 'FastString' is also
-- quite nice.
-type NameRep = FastString
+newtype NameRep
+ = NameRep FastString
+ deriving (Eq)
+
+instance Ord NameRep where
+ compare (NameRep fs1) (NameRep fs2) = uniqCompareFS fs1 fs2
+
getNameRep :: NamedThing name => name -> NameRep
-getNameRep = getOccFS
+getNameRep = NameRep . getOccFS
nameRepString :: NameRep -> String
-nameRepString = unpackFS
+nameRepString (NameRep fs) = unpackFS fs
stringNameRep :: String -> NameRep
-stringNameRep = mkFastString
+stringNameRep = NameRep . mkFastString
setInternalNameRep :: SetName name => NameRep -> name -> name
-setInternalNameRep = setInternalOccName . mkVarOccFS
+setInternalNameRep (NameRep fs) = setInternalOccName (mkVarOccFS fs)
setInternalOccName :: SetName name => OccName -> name -> name
setInternalOccName occ name =
@@ -198,23 +205,37 @@ setInternalOccName occ name =
nname' = mkInternalName (nameUnique nname) occ (nameSrcSpan nname)
--- | Compute set of free variables of given type.
-freeVariables :: HsType GhcRn -> Set Name
-freeVariables =
- everythingWithState Set.empty Set.union query
+-- | Compute set of free variables of a given 'HsType'.
+freeVariablesType :: HsType GhcRn -> Set Name
+freeVariablesType =
+ everythingWithState Set.empty Set.union
+ (mkQ (\ctx -> (Set.empty, ctx)) queryType)
+
+-- | Compute set of free variables of a given 'HsType'.
+freeVariablesSigType :: HsSigType GhcRn -> Set Name
+freeVariablesSigType =
+ everythingWithState Set.empty Set.union
+ (mkQ (\ctx -> (Set.empty, ctx)) queryType `extQ` querySigType)
+
+queryType :: HsType GhcRn -> Set Name -> (Set Name, Set Name)
+queryType term ctx = case term of
+ HsForAllTy _ tele _ ->
+ (Set.empty, Set.union ctx (teleNames tele))
+ HsTyVar _ _ (L _ name)
+ | getName name `Set.member` ctx -> (Set.empty, ctx)
+ | otherwise -> (Set.singleton $ getName name, ctx)
+ _ -> (Set.empty, ctx)
where
- query term ctx = case cast term :: Maybe (HsType GhcRn) of
- Just (HsForAllTy _ tele _) ->
- (Set.empty, Set.union ctx (teleNames tele))
- Just (HsTyVar _ _ (L _ name))
- | getName name `Set.member` ctx -> (Set.empty, ctx)
- | otherwise -> (Set.singleton $ getName name, ctx)
- _ -> (Set.empty, ctx)
-
+ teleNames :: HsForAllTelescope GhcRn -> Set Name
teleNames (HsForAllVis _ bndrs) = bndrsNames bndrs
teleNames (HsForAllInvis _ bndrs) = bndrsNames bndrs
- bndrsNames = Set.fromList . map (getName . hsTyVarBndrName . unLoc)
+querySigType :: HsSigType GhcRn -> Set Name -> (Set Name, Set Name)
+querySigType (HsSig { sig_bndrs = outer_bndrs }) ctx =
+ (Set.empty, Set.union ctx (bndrsNames (hsOuterExplicitBndrs outer_bndrs)))
+
+bndrsNames :: [LHsTyVarBndr flag GhcRn] -> Set Name
+bndrsNames = Set.fromList . map (getName . tyVarName . unLoc)
-- | Make given type visually unambiguous.
@@ -225,12 +246,12 @@ freeVariables =
-- different type variable than latter one. Applying 'rename' function
-- will fix that type to be visually unambiguous again (making it something
-- like @(a -> b0) -> b@).
-rename :: Set Name -> HsType GhcRn -> HsType GhcRn
-rename fv typ = evalState (renameType typ) env
+rename :: Set Name -> HsSigType GhcRn -> HsSigType GhcRn
+rename fv typ = evalState (renameSigType typ) env
where
env = RenameEnv
{ rneHeadFVs = Map.fromList . map mkPair . Set.toList $ fv
- , rneSigFVs = Set.map getNameRep $ freeVariables typ
+ , rneSigFVs = Set.map getNameRep $ freeVariablesSigType typ
, rneCtx = Map.empty
}
mkPair name = (getNameRep name, name)
@@ -245,6 +266,17 @@ data RenameEnv name = RenameEnv
}
+renameSigType :: HsSigType GhcRn -> Rename (IdP GhcRn) (HsSigType GhcRn)
+renameSigType (HsSig x bndrs body) =
+ HsSig x <$> renameOuterTyVarBndrs bndrs <*> renameLType body
+
+renameOuterTyVarBndrs :: HsOuterTyVarBndrs flag GhcRn
+ -> Rename (IdP GhcRn) (HsOuterTyVarBndrs flag GhcRn)
+renameOuterTyVarBndrs (HsOuterImplicit imp_tvs) =
+ HsOuterImplicit <$> mapM renameName imp_tvs
+renameOuterTyVarBndrs (HsOuterExplicit x exp_bndrs) =
+ HsOuterExplicit x <$> mapM renameLBinder exp_bndrs
+
renameType :: HsType GhcRn -> Rename (IdP GhcRn) (HsType GhcRn)
renameType (HsForAllTy x tele lt) =
HsForAllTy x
@@ -271,7 +303,7 @@ renameType t@(HsSpliceTy _ _) = pure t
renameType (HsDocTy x lt doc) = HsDocTy x <$> renameLType lt <*> pure doc
renameType (HsBangTy x bang lt) = HsBangTy x bang <$> renameLType lt
renameType t@(HsRecTy _ _) = pure t
-renameType t@(XHsType (NHsCoreTy _)) = pure t
+renameType t@(XHsType _) = pure t
renameType (HsExplicitListTy x ip ltys) =
HsExplicitListTy x ip <$> renameLTypes ltys
renameType (HsExplicitTupleTy x ltys) =
@@ -362,3 +394,8 @@ alternativeNames name =
located :: Functor f => (a -> f b) -> Located a -> f (Located b)
located f (L loc e) = L loc <$> f e
+
+
+tyVarName :: HsTyVarBndr flag GhcRn -> IdP GhcRn
+tyVarName (UserTyVar _ _ name) = unLoc name
+tyVarName (KindedTyVar _ _ (L _ name) _) = name