diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2021-03-04 18:05:14 +0000 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-03-09 18:52:32 -0500 |
commit | 8fe274e27b9bd42c68e931da875d3f8e9c20e53f (patch) | |
tree | 4776c24d11989f8563346820cddd9014f7d3c1e3 /compiler/GHC/Tc/Gen/Export.hs | |
parent | aaa5fc21af8dda26bf6c497d1036833225c94fa1 (diff) | |
download | haskell-8fe274e27b9bd42c68e931da875d3f8e9c20e53f.tar.gz |
Fixes to dealing with the export of main
It's surprisingly tricky to deal with 'main' (#19397). This
patch does quite bit of refactoring do to it right. Well,
more-right anyway!
The moving parts are documented in GHC.Tc.Module
Note [Dealing with main]
Some other oddments:
* Rename tcRnExports to rnExports; no typechecking here!
* rnExports now uses checkNoErrs rather than failIfErrsM;
the former fails only if rnExports itself finds errors
* Small improvements to tcTyThingCategory, which ultimately
weren't important to the patch, but I've retained as
a minor improvement.
Diffstat (limited to 'compiler/GHC/Tc/Gen/Export.hs')
-rw-r--r-- | compiler/GHC/Tc/Gen/Export.hs | 75 |
1 files changed, 38 insertions, 37 deletions
diff --git a/compiler/GHC/Tc/Gen/Export.hs b/compiler/GHC/Tc/Gen/Export.hs index fe6dcfd88d..ec0efc48d5 100644 --- a/compiler/GHC/Tc/Gen/Export.hs +++ b/compiler/GHC/Tc/Gen/Export.hs @@ -3,7 +3,7 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-} -module GHC.Tc.Gen.Export (tcRnExports, exports_from_avail) where +module GHC.Tc.Gen.Export (rnExports, exports_from_avail) where import GHC.Prelude @@ -29,6 +29,7 @@ import GHC.Utils.Misc (capitalise) import GHC.Data.FastString (fsLit) import GHC.Driver.Env +import GHC.Types.TyThing( tyThingCategory ) import GHC.Types.Unique.Set import GHC.Types.SrcLoc as SrcLoc import GHC.Types.Name @@ -38,7 +39,6 @@ import GHC.Types.Avail import GHC.Types.SourceFile import GHC.Types.Id import GHC.Types.Id.Info -import GHC.Types.TyThing import GHC.Types.Name.Reader import Control.Monad @@ -153,46 +153,48 @@ type ExportOccMap = OccEnv (GreName, IE GhcPs) -- it came from. It's illegal to export two distinct things -- that have the same occurrence name -tcRnExports :: Bool -- False => no 'module M(..) where' header at all +rnExports :: Bool -- False => no 'module M(..) where' header at all -> Maybe (Located [LIE GhcPs]) -- Nothing => no explicit export list - -> TcGblEnv -> RnM TcGblEnv -- Complains if two distinct exports have same OccName -- Warns about identical exports. -- Complains about exports items not in scope -tcRnExports explicit_mod exports - tcg_env@TcGblEnv { tcg_mod = this_mod, - tcg_rdr_env = rdr_env, - tcg_imports = imports, - tcg_src = hsc_src } - = unsetWOptM Opt_WarnWarningsDeprecations $ +rnExports explicit_mod exports + = checkNoErrs $ -- Fail if anything in rnExports finds + -- an error fails, to avoid error cascade + unsetWOptM Opt_WarnWarningsDeprecations $ -- 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 { - ; dflags <- getDynFlags - ; hsc_env <- getTopEnv - ; let is_main_mod = mainModIs hsc_env == this_mod - ; let default_main = case mainFunIs dflags of - Just main_fun - | is_main_mod -> mkUnqual varName (fsLit main_fun) - _ -> main_RDR_Unqual + do { hsc_env <- getTopEnv + ; tcg_env <- getGblEnv + ; let dflags = hsc_dflags hsc_env + TcGblEnv { tcg_mod = this_mod + , tcg_rdr_env = rdr_env + , tcg_imports = imports + , tcg_src = hsc_src } = tcg_env + default_main | mainModIs hsc_env == this_mod + , Just main_fun <- mainFunIs dflags + = mkUnqual varName (fsLit main_fun) + | otherwise + = main_RDR_Unqual ; has_main <- (not . null) <$> lookupInfoOccRn 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 | explicit_mod = exports - | has_main - = Just (noLoc [noLoc (IEVar noExtField + | has_main = Just (noLoc [noLoc (IEVar noExtField (noLoc (IEName $ noLoc default_main)))]) - -- ToDo: the 'noLoc' here is unhelpful if 'main' - -- turns out to be out of scope + -- ToDo: the 'noLoc' here is unhelpful if 'main' + -- turns out to be out of scope | otherwise = Nothing + -- Rename the export list ; let do_it = exports_from_avail real_exports rdr_env imports this_mod ; (rn_exports, final_avails) <- if hsc_src == HsigFile @@ -201,19 +203,18 @@ tcRnExports explicit_mod exports Just r -> return r Nothing -> addMessages msgs >> failM else checkNoErrs do_it - ; let final_ns = availsToNameSetWithSelectors final_avails + + -- Final processing + ; let final_ns = availsToNameSetWithSelectors final_avails ; traceRn "rnExports: Exports:" (ppr final_avails) - ; let new_tcg_env = - tcg_env { tcg_exports = final_avails, - tcg_rn_exports = case tcg_rn_exports tcg_env of + ; return (tcg_env { tcg_exports = final_avails + , tcg_rn_exports = case tcg_rn_exports tcg_env of Nothing -> Nothing - Just _ -> rn_exports, - tcg_dus = tcg_dus tcg_env `plusDU` - usesOnly final_ns } - ; failIfErrsM - ; return new_tcg_env } + Just _ -> rn_exports + , tcg_dus = tcg_dus tcg_env `plusDU` + usesOnly final_ns }) } exports_from_avail :: Maybe (Located [LIE GhcPs]) -- ^ 'Nothing' means no explicit export list @@ -596,7 +597,7 @@ checkPatSynParent parent NoParent gname = return () | otherwise - = do { parent_ty_con <- tcLookupTyCon parent + = do { parent_ty_con <- tcLookupTyCon parent ; mpat_syn_thing <- tcLookupGlobal (greNameMangledName gname) -- 1. Check that the Id was actually from a thing associated with patsyns @@ -793,7 +794,7 @@ dcErrMsg ty_con what_is thing parents = <+> text "is not the parent of the" <+> text what_is <+> quotes thing <> char '.' $$ text (capitalise what_is) - <> text "s can only be exported with their parent type constructor." + <> text "s can only be exported with their parent type constructor." $$ (case parents of [] -> empty [_] -> text "Parent:" @@ -802,13 +803,13 @@ dcErrMsg ty_con what_is thing parents = failWithDcErr :: Name -> GreName -> [Name] -> TcM a failWithDcErr parent child parents = do ty_thing <- tcLookupGlobal (greNameMangledName child) - failWithTc $ dcErrMsg parent (tyThingCategory' ty_thing) + failWithTc $ dcErrMsg parent (pp_category ty_thing) (ppr child) (map ppr parents) where - tyThingCategory' :: TyThing -> String - tyThingCategory' (AnId i) + pp_category :: TyThing -> String + pp_category (AnId i) | isRecordSelector i = "record selector" - tyThingCategory' i = tyThingCategory i + pp_category i = tyThingCategory i exportClashErr :: GlobalRdrEnv |