diff options
author | Matthew Pickering <matthewtpickering@gmail.com> | 2021-03-23 13:26:44 +0000 |
---|---|---|
committer | Matthew Pickering <matthewtpickering@gmail.com> | 2021-03-23 13:26:44 +0000 |
commit | 1998c66e674fba382ffa1c7d8e52b282589ec1ec (patch) | |
tree | abea412b17c239f1ea9b42fe5ae1a9cd7bef3f41 | |
parent | a9129f9fdfbd358e76aa197ba00bfe75012d6b4f (diff) | |
download | haskell-wip/splice-import.tar.gz |
WIP: Splice importswip/splice-import
-rw-r--r-- | compiler/GHC.hs | 1 | ||||
-rw-r--r-- | compiler/GHC/Driver/Session.hs | 1 | ||||
-rw-r--r-- | compiler/GHC/Hs/ImpExp.hs | 4 | ||||
-rw-r--r-- | compiler/GHC/Hs/Stats.hs | 30 | ||||
-rw-r--r-- | compiler/GHC/Parser.y | 27 | ||||
-rw-r--r-- | compiler/GHC/Parser/Header.hs | 7 | ||||
-rw-r--r-- | compiler/GHC/Parser/Lexer.x | 4 | ||||
-rw-r--r-- | compiler/GHC/Rename/Env.hs | 2 | ||||
-rw-r--r-- | compiler/GHC/Rename/Expr.hs | 17 | ||||
-rw-r--r-- | compiler/GHC/Rename/Names.hs | 19 | ||||
-rw-r--r-- | compiler/GHC/Rename/Splice.hs | 27 | ||||
-rw-r--r-- | compiler/GHC/Rename/Unbound.hs | 15 | ||||
-rw-r--r-- | compiler/GHC/Runtime/Loader.hs | 3 | ||||
-rw-r--r-- | compiler/GHC/Tc/Gen/Head.hs | 2 | ||||
-rw-r--r-- | compiler/GHC/Tc/Utils/Backpack.hs | 5 | ||||
-rw-r--r-- | compiler/GHC/Types/Name/Reader.hs | 15 | ||||
-rw-r--r-- | compiler/GHC/Unit/Types.hs | 12 | ||||
-rw-r--r-- | hadrian/src/Rules/Test.hs | 4 | ||||
-rw-r--r-- | libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs | 1 | ||||
-rw-r--r-- | utils/check-exact/ExactPrint.hs | 4 |
20 files changed, 147 insertions, 53 deletions
diff --git a/compiler/GHC.hs b/compiler/GHC.hs index 9d2d6fb65f..8b1629857a 100644 --- a/compiler/GHC.hs +++ b/compiler/GHC.hs @@ -1380,6 +1380,7 @@ availsToGlobalRdrEnv mod_name avails imp_spec = ImpSpec { is_decl = decl, is_item = ImpAll} decl = ImpDeclSpec { is_mod = mod_name, is_as = mod_name, is_qual = False, + is_splice = False, -- TODO MP is_dloc = srcLocSpan interactiveSrcLoc } diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs index eb14bbc91f..7a5ee744f5 100644 --- a/compiler/GHC/Driver/Session.hs +++ b/compiler/GHC/Driver/Session.hs @@ -3510,6 +3510,7 @@ xFlagsDeps = [ flagSpec "ExistentialQuantification" LangExt.ExistentialQuantification, flagSpec "ExplicitForAll" LangExt.ExplicitForAll, flagSpec "ExplicitNamespaces" LangExt.ExplicitNamespaces, + flagSpec "ExplicitSpliceImports" LangExt.ExplicitSpliceImports, flagSpec "ExtendedDefaultRules" LangExt.ExtendedDefaultRules, flagSpec "FlexibleContexts" LangExt.FlexibleContexts, flagSpec "FlexibleInstances" LangExt.FlexibleInstances, diff --git a/compiler/GHC/Hs/ImpExp.hs b/compiler/GHC/Hs/ImpExp.hs index f4c40bd185..70f9da4fb3 100644 --- a/compiler/GHC/Hs/ImpExp.hs +++ b/compiler/GHC/Hs/ImpExp.hs @@ -77,6 +77,8 @@ isImportDeclQualified :: ImportDeclQualifiedStyle -> Bool isImportDeclQualified NotQualified = False isImportDeclQualified _ = True +data IsSpliceImport = SpliceImport | NormalImport deriving (Data, Show, Eq, Ord) + -- | Import Declaration -- -- A single Haskell @import@ declaration. @@ -90,6 +92,7 @@ data ImportDecl pass ideclSource :: IsBootInterface, -- ^ IsBoot <=> {-\# SOURCE \#-} import ideclSafe :: Bool, -- ^ True => safe import ideclQualified :: ImportDeclQualifiedStyle, -- ^ If/how the import is qualified. + ideclSplice :: IsSpliceImport, -- ^ Whether the import is a splice import ideclImplicit :: Bool, -- ^ True => implicit import (of Prelude) ideclAs :: Maybe (XRec pass ModuleName), -- ^ as Module ideclHiding :: Maybe (Bool, XRec pass [LIE pass]) @@ -147,6 +150,7 @@ simpleImportDecl mn = ImportDecl { ideclSafe = False, ideclImplicit = False, ideclQualified = NotQualified, + ideclSplice = NormalImport, ideclAs = Nothing, ideclHiding = Nothing } diff --git a/compiler/GHC/Hs/Stats.hs b/compiler/GHC/Hs/Stats.hs index bd3e2e6b6d..03d60d2819 100644 --- a/compiler/GHC/Hs/Stats.hs +++ b/compiler/GHC/Hs/Stats.hs @@ -36,6 +36,7 @@ ppSourceStats short (L _ (HsModule{ hsmodExports = exports, hsmodImports = impor (" ImpAll ", imp_all), (" ImpPartial ", imp_partial), (" ImpHiding ", imp_hiding), + (" ImpSplices ", imp_splices), ("FixityDecls ", fixity_sigs), ("DefaultDecls ", default_ds), ("TypeDecls ", type_ds), @@ -96,8 +97,8 @@ ppSourceStats short (L _ (HsModule{ hsmodExports = exports, hsmodImports = impor (val_bind_ds, fn_bind_ds, patsyn_ds) = sum3 (map count_bind val_decls) - (imp_no, imp_safe, imp_qual, imp_as, imp_all, imp_partial, imp_hiding) - = sum7 (map import_info imports) + (imp_no, imp_safe, imp_qual, imp_as, imp_all, imp_partial, imp_hiding, imp_splices) + = sum8 (map import_info imports) (data_constrs, data_derivs) = sum2 (map data_info tycl_decls) (class_method_ds, default_method_ds) @@ -120,10 +121,11 @@ ppSourceStats short (L _ (HsModule{ hsmodExports = exports, hsmodImports = impor sig_info (ClassOpSig {}) = (0,0,0,0,1) sig_info _ = (0,0,0,0,0) - import_info :: LImportDecl GhcPs -> (Int, Int, Int, Int, Int, Int, Int) + import_info :: LImportDecl GhcPs -> (Int, Int, Int, Int, Int, Int, Int, Int) import_info (L _ (ImportDecl { ideclSafe = safe, ideclQualified = qual - , ideclAs = as, ideclHiding = spec })) - = add7 (1, safe_info safe, qual_info qual, as_info as, 0,0,0) (spec_info spec) + , ideclAs = as, ideclHiding = spec + , ideclSplice = sp })) + = add8 (1, safe_info safe, qual_info qual, as_info as, 0,0,0, sp_info sp) (spec_info spec) safe_info False = 0 safe_info True = 1 @@ -131,9 +133,11 @@ ppSourceStats short (L _ (HsModule{ hsmodExports = exports, hsmodImports = impor qual_info _ = 1 as_info Nothing = 0 as_info (Just _) = 1 - spec_info Nothing = (0,0,0,0,1,0,0) - spec_info (Just (False, _)) = (0,0,0,0,0,1,0) - spec_info (Just (True, _)) = (0,0,0,0,0,0,1) + spec_info Nothing = (0,0,0,0,1,0,0,0) + spec_info (Just (False, _)) = (0,0,0,0,0,1,0,0) + spec_info (Just (True, _)) = (0,0,0,0,0,0,1,0) + sp_info SpliceImport = 1 + sp_info NormalImport = 0 data_info (DataDecl { tcdDataDefn = HsDataDefn { dd_cons = cs @@ -169,9 +173,9 @@ ppSourceStats short (L _ (HsModule{ hsmodExports = exports, hsmodImports = impor sum2 :: [(Int, Int)] -> (Int, Int) sum3 :: [(Int, Int, Int)] -> (Int, Int, Int) sum5 :: [(Int, Int, Int, Int, Int)] -> (Int, Int, Int, Int, Int) - sum7 :: [(Int, Int, Int, Int, Int, Int, Int)] -> (Int, Int, Int, Int, Int, Int, Int) - add7 :: (Int, Int, Int, Int, Int, Int, Int) -> (Int, Int, Int, Int, Int, Int, Int) - -> (Int, Int, Int, Int, Int, Int, Int) + sum8 :: [(Int, Int, Int, Int, Int, Int, Int, Int)] -> (Int, Int, Int, Int, Int, Int, Int, Int) + add8 :: (Int, Int, Int, Int, Int, Int, Int, Int) -> (Int, Int, Int, Int, Int, Int, Int, Int) + -> (Int, Int, Int, Int, Int, Int, Int, Int) addpr (x,y,z) = x+y+z sum2 = foldr add2 (0,0) @@ -183,6 +187,6 @@ ppSourceStats short (L _ (HsModule{ hsmodExports = exports, hsmodImports = impor sum5 = foldr add5 (0,0,0,0,0) where add5 (x1,x2,x3,x4,x5) (y1,y2,y3,y4,y5) = (x1+y1,x2+y2,x3+y3,x4+y4,x5+y5) - sum7 = foldr add7 (0,0,0,0,0,0,0) + sum8 = foldr add8 (0,0,0,0,0,0,0,0) - add7 (x1,x2,x3,x4,x5,x6,x7) (y1,y2,y3,y4,y5,y6,y7) = (x1+y1,x2+y2,x3+y3,x4+y4,x5+y5,x6+y6,x7+y7) + add8 (x1,x2,x3,x4,x5,x6,x7, x8) (y1,y2,y3,y4,y5,y6,y7,y8) = (x1+y1,x2+y2,x3+y3,x4+y4,x5+y5,x6+y6,x7+y7,x8+y8) diff --git a/compiler/GHC/Parser.y b/compiler/GHC/Parser.y index f786940591..31db2761cb 100644 --- a/compiler/GHC/Parser.y +++ b/compiler/GHC/Parser.y @@ -58,7 +58,7 @@ import GHC.Unit.Module.Warnings import GHC.Data.OrdList import GHC.Data.BooleanFormula ( BooleanFormula(..), LBooleanFormula, mkTrue ) import GHC.Data.FastString -import GHC.Data.Maybe ( orElse ) +import GHC.Data.Maybe ( orElse, isJust ) import GHC.Utils.Outputable import GHC.Utils.Misc ( looksLikePackageName, fstOf3, sndOf3, thdOf3 ) @@ -582,6 +582,7 @@ are the most common patterns, rewritten as regular expressions for clarity: 'newtype' { L _ ITnewtype } 'of' { L _ ITof } 'qualified' { L _ ITqualified } + 'splice' { L _ ITsplice } 'then' { L _ ITthen } 'type' { L _ ITtype } 'where' { L _ ITwhere } @@ -1085,10 +1086,10 @@ importdecls_semi | {- empty -} { [] } importdecl :: { LImportDecl GhcPs } - : 'import' maybe_src maybe_safe optqualified maybe_pkg modid optqualified maybeas maybeimpspec + : 'import' maybe_src maybe_safe optsplice optqualified maybe_pkg modid optqualified maybeas maybeimpspec {% do { - ; let { ; mPreQual = unLoc $4 - ; mPostQual = unLoc $7 } + ; let { ; mPreQual = unLoc $5 + ; mPostQual = unLoc $8 } ; checkImportDecl mPreQual mPostQual ; let anns = ApiAnnImportDecl @@ -1096,18 +1097,19 @@ importdecl :: { LImportDecl GhcPs } , importDeclAnnPragma = fst $ fst $2 , importDeclAnnSafe = fst $3 , importDeclAnnQualified = fst $ importDeclQualifiedStyle mPreQual mPostQual - , importDeclAnnPackage = fst $5 - , importDeclAnnAs = fst $8 + , importDeclAnnPackage = fst $6 + , importDeclAnnAs = fst $9 } - ; fmap reLocA $ acs (\cs -> L (comb5 $1 $6 $7 (snd $8) $9) $ + ; fmap reLocA $ acs (\cs -> L (comb5 $1 $7 $8 (snd $9) $10) $ ImportDecl { ideclExt = ApiAnn (glR $1) anns cs , ideclSourceSrc = snd $ fst $2 - , ideclName = $6, ideclPkgQual = snd $5 + , ideclName = $7, ideclPkgQual = snd $6 , ideclSource = snd $2, ideclSafe = snd $3 , ideclQualified = snd $ importDeclQualifiedStyle mPreQual mPostQual + , ideclSplice = if isJust (unLoc $4) then SpliceImport else NormalImport , ideclImplicit = False - , ideclAs = unLoc (snd $8) - , ideclHiding = unLoc $9 }) + , ideclAs = unLoc (snd $9) + , ideclHiding = unLoc $10 }) } } @@ -1132,6 +1134,10 @@ optqualified :: { Located (Maybe AnnAnchor) } : 'qualified' { sL1 $1 (Just (glAA $1)) } | {- empty -} { noLoc Nothing } +optsplice :: { Located (Maybe AnnAnchor) } + : 'splice' { sL1 $1 (Just (glAA $1)) } + | {- empty -} { noLoc Nothing } + maybeas :: { (Maybe AnnAnchor,Located (Maybe (Located ModuleName))) } : 'as' modid { (Just (glAA $1) ,sLL $1 $> (Just $2)) } @@ -3761,6 +3767,7 @@ special_id :: { Located FastString } special_id : 'as' { sL1 $1 (fsLit "as") } | 'qualified' { sL1 $1 (fsLit "qualified") } + | 'splice' { sL1 $1 (fsLit "splice") } | 'hiding' { sL1 $1 (fsLit "hiding") } | 'export' { sL1 $1 (fsLit "export") } | 'label' { sL1 $1 (fsLit "label") } diff --git a/compiler/GHC/Parser/Header.hs b/compiler/GHC/Parser/Header.hs index 7b561f2119..28dd2cf792 100644 --- a/compiler/GHC/Parser/Header.hs +++ b/compiler/GHC/Parser/Header.hs @@ -127,7 +127,7 @@ mkPrelImports this_mod loc implicit_prelude import_decls || explicit_prelude_import || not implicit_prelude = [] - | otherwise = [preludeImportDecl] + | otherwise = [preludeImportDecl sp_import | sp_import <- [NormalImport, SpliceImport]] where explicit_prelude_import = any is_prelude_import import_decls @@ -140,8 +140,8 @@ mkPrelImports this_mod loc implicit_prelude import_decls loc' = noAnnSrcSpan loc - preludeImportDecl :: LImportDecl GhcPs - preludeImportDecl + preludeImportDecl :: IsSpliceImport -> LImportDecl GhcPs + preludeImportDecl sp_import = L loc' $ ImportDecl { ideclExt = noAnn, ideclSourceSrc = NoSourceText, ideclName = L loc pRELUDE_NAME, @@ -150,6 +150,7 @@ mkPrelImports this_mod loc implicit_prelude import_decls ideclSafe = False, -- Not a safe import ideclQualified = NotQualified, ideclImplicit = True, -- Implicit! + ideclSplice = sp_import, ideclAs = Nothing, ideclHiding = Nothing } diff --git a/compiler/GHC/Parser/Lexer.x b/compiler/GHC/Parser/Lexer.x index bfebbfa411..30eff8ccec 100644 --- a/compiler/GHC/Parser/Lexer.x +++ b/compiler/GHC/Parser/Lexer.x @@ -712,6 +712,7 @@ data Token | ITnewtype | ITof | ITqualified + | ITsplice | ITthen | ITtype | ITwhere @@ -968,6 +969,7 @@ reservedWordsFM = listToUFM $ ( "newtype", ITnewtype, 0 ), ( "of", ITof, 0 ), ( "qualified", ITqualified, 0 ), + ( "splice", ITsplice, xbit ExplicitSpliceImportsBit ), ( "then", ITthen, 0 ), ( "type", ITtype, 0 ), ( "where", ITwhere, 0 ), @@ -2728,6 +2730,7 @@ data ExtBits | NoLexicalNegationBit -- See Note [Why not LexicalNegationBit] | OverloadedRecordDotBit | OverloadedRecordUpdateBit + | ExplicitSpliceImportsBit -- Flags that are updated once parsing starts | InRulePragBit @@ -2806,6 +2809,7 @@ mkParserOpts warningFlags extensionFlags .|. NoLexicalNegationBit `xoptNotBit` LangExt.LexicalNegation -- See Note [Why not LexicalNegationBit] .|. OverloadedRecordDotBit `xoptBit` LangExt.OverloadedRecordDot .|. OverloadedRecordUpdateBit `xoptBit` LangExt.OverloadedRecordUpdate -- Enable testing via 'getBit OverloadedRecordUpdateBit' in the parser (RecordDotSyntax parsing uses that information). + .|. ExplicitSpliceImportsBit `xoptBit` LangExt.ExplicitSpliceImports optBits = HaddockBit `setBitIf` isHaddock .|. RawTokenStreamBit `setBitIf` rawTokStream diff --git a/compiler/GHC/Rename/Env.hs b/compiler/GHC/Rename/Env.hs index 68c299a3b0..2b0af26b5c 100644 --- a/compiler/GHC/Rename/Env.hs +++ b/compiler/GHC/Rename/Env.hs @@ -1634,7 +1634,7 @@ lookupOneQualifiedNameGHCi fos rdr_name = do -- field name multiple times (see -- Note [DuplicateRecordFields and -fimplicit-import-qualified]). toGRE gname = GRE { gre_name = gname, gre_par = NoParent, gre_lcl = False, gre_imp = [is] } - is = ImpSpec { is_decl = ImpDeclSpec { is_mod = mod, is_as = mod, is_qual = True, is_dloc = noSrcSpan } + is = ImpSpec { is_decl = ImpDeclSpec { is_mod = mod, is_as = mod, is_qual = True, is_splice = False, is_dloc = noSrcSpan } , is_item = ImpAll } -- If -fimplicit-import-qualified succeeded, the name must be qualified. (mod, _) = fromMaybe (pprPanic "lookupOneQualifiedNameGHCi" (ppr rdr_name)) (isQual_maybe rdr_name) diff --git a/compiler/GHC/Rename/Expr.hs b/compiler/GHC/Rename/Expr.hs index bbf52be2f8..e36747184b 100644 --- a/compiler/GHC/Rename/Expr.hs +++ b/compiler/GHC/Rename/Expr.hs @@ -43,7 +43,7 @@ import GHC.Rename.Utils ( HsDocContext(..), bindLocalNamesFV, checkDupNames , warnUnusedLocalBinds, typeAppErr , checkUnusedRecordWildcard ) import GHC.Rename.Unbound ( reportUnboundName ) -import GHC.Rename.Splice ( rnBracket, rnSpliceExpr, checkThLocalName ) +import GHC.Rename.Splice ( rnBracket, rnSpliceExpr, checkThLocalName, checkSpliceImports ) import GHC.Rename.HsType import GHC.Rename.Pat import GHC.Driver.Session @@ -189,14 +189,17 @@ rnLExpr = wrapLocFstMA rnExpr rnExpr :: HsExpr GhcPs -> RnM (HsExpr GhcRn, FreeVars) -finishHsVar :: LocatedA Name -> RnM (HsExpr GhcRn, FreeVars) +finishHsVar :: RdrName -> LocatedA Name -> RnM (HsExpr GhcRn, FreeVars) -- Separated from rnExpr because it's also used -- when renaming infix expressions -finishHsVar (L l name) +finishHsVar orig_rdrname (L l name) = do { this_mod <- getModule - ; when (nameIsLocalOrFrom this_mod name) $ - checkThLocalName name - ; return (HsVar noExtField (L (la2na l) name), unitFV name) } + ; splice_import <- xoptM LangExt.ExplicitSpliceImports + ; name' <- if (not (nameIsLocalOrFrom this_mod name) && splice_import) + then checkSpliceImports orig_rdrname name + else return name + ; when (nameIsLocalOrFrom this_mod name') $ checkThLocalName name' + ; return (HsVar noExtField (L (la2na l) name'), unitFV name') } rnUnboundVar :: RdrName -> RnM (HsExpr GhcRn, FreeVars) rnUnboundVar v = @@ -225,7 +228,7 @@ rnExpr (HsVar _ (L l v)) -> rnExpr (ExplicitList noAnn []) | otherwise - -> finishHsVar (L (na2la l) name) ; + -> finishHsVar v (L (na2la l) name) ; Just (UnambiguousGre (FieldGreName fl)) -> let sel_name = flSelector fl in return ( HsRecFld noExtField (Unambiguous sel_name (L l v) ), unitFV sel_name) ; diff --git a/compiler/GHC/Rename/Names.hs b/compiler/GHC/Rename/Names.hs index 6c99bf7b5b..afe47525c5 100644 --- a/compiler/GHC/Rename/Names.hs +++ b/compiler/GHC/Rename/Names.hs @@ -290,7 +290,8 @@ rnImportDecl this_mod , ideclPkgQual = mb_pkg , ideclSource = want_boot, ideclSafe = mod_safe , ideclQualified = qual_style, ideclImplicit = implicit - , ideclAs = as_mod, ideclHiding = imp_details })) + , ideclAs = as_mod, ideclHiding = imp_details + , ideclSplice = sp_style })) = setSrcSpanA loc $ do when (isJust mb_pkg) $ do @@ -298,6 +299,10 @@ rnImportDecl this_mod when (not pkg_imports) $ addErr packageImportErr let qual_only = isImportDeclQualified qual_style + splice_only = case sp_style of + SpliceImport -> True + NormalImport -> False + want_compiled = if splice_only then NeededCompiled else NotNeededCompiled -- If there's an error in loadInterface, (e.g. interface -- file not found) we get lots of spurious errors from 'filterImports' @@ -361,7 +366,8 @@ rnImportDecl this_mod let qual_mod_name = fmap unLoc as_mod `orElse` imp_mod_name imp_spec = ImpDeclSpec { is_mod = imp_mod_name, is_qual = qual_only, - is_dloc = locA loc, is_as = qual_mod_name } + is_dloc = locA loc, is_as = qual_mod_name, + is_splice = splice_only } -- filter the imports according to the import declaration (new_imp_details, gres) <- filterImports iface imp_spec imp_details @@ -390,7 +396,7 @@ rnImportDecl this_mod , imv_all_exports = potential_gres , imv_qualified = qual_only } - imports = calculateAvails home_unit iface mod_safe' want_boot (ImportedByUser imv) + imports = calculateAvails home_unit iface mod_safe' want_boot want_compiled (ImportedByUser imv) -- Complain if we import a deprecated module whenWOptM Opt_WarnWarningsDeprecations ( @@ -416,9 +422,10 @@ calculateAvails :: HomeUnit -> ModIface -> IsSafeImport -> IsBootInterface + -> IsNeededCompiled -> ImportedBy -> ImportAvails -calculateAvails home_unit iface mod_safe' want_boot imported_by = +calculateAvails home_unit iface mod_safe' want_boot want_compiled imported_by = let imp_mod = mi_module iface imp_sem_mod= mi_semantic_module iface orph_iface = mi_orphan (mi_final_exts iface) @@ -481,7 +488,9 @@ calculateAvails home_unit iface mod_safe' want_boot imported_by = -- know if any of them depended on CM.hi-boot, in -- which case we should do the hi-boot consistency -- check. See GHC.Iface.Load.loadHiBootInterface - ( GWIB { gwib_mod = moduleName imp_mod, gwib_isBoot = want_boot } : dep_mods deps + ( GWIB { gwib_mod = moduleName imp_mod + , gwib_isBoot = want_boot + } : dep_mods deps , dep_pkgs deps , ptrust ) diff --git a/compiler/GHC/Rename/Splice.hs b/compiler/GHC/Rename/Splice.hs index d22cabf69e..1ebdbe81d6 100644 --- a/compiler/GHC/Rename/Splice.hs +++ b/compiler/GHC/Rename/Splice.hs @@ -7,7 +7,7 @@ module GHC.Rename.Splice ( rnTopSpliceDecls, rnSpliceType, rnSpliceExpr, rnSplicePat, rnSpliceDecl, rnBracket, - checkThLocalName + checkThLocalName, checkSpliceImports , traceSplice, SpliceInfo(..) ) where @@ -24,7 +24,7 @@ import GHC.Driver.Env.Types import GHC.Rename.Env import GHC.Rename.Utils ( HsDocContext(..), newLocalBndrRn ) -import GHC.Rename.Unbound ( isUnboundName ) +import GHC.Rename.Unbound ( isUnboundName, unboundNameX, WhereLooking (..) ) import GHC.Rename.Module ( rnSrcDecls, findSplice ) import GHC.Rename.Pat ( rnPat ) import GHC.Types.Basic ( TopLevelFlag, isTopLevel ) @@ -846,6 +846,29 @@ illegalTypedSplice = text "Typed splices may not appear in untyped brackets" illegalUntypedSplice :: SDoc illegalUntypedSplice = text "Untyped splices may not appear in typed brackets" +-- | When 'ExplicitSpliceImports' is enabled, check that a name appearing inside +-- a splice is splice imported +checkSpliceImports :: RdrName -> Name -> RnM Name +checkSpliceImports orig_rdrname name = do + rdr_env <- getGlobalRdrEnv + st <- getStage + let in_splice = is_splice_stage st + case lookupGRE_Name rdr_env name of + Just gre -> + if pick_splice in_splice gre + then return name + else unboundNameX (if in_splice then WL_SpliceImport else WL_NonSpliceImport) orig_rdrname (error_text in_splice) + Nothing -> return name + where + error_text False = text "is splice imported but used outside a splice." + error_text True = text "is used inside a splice but not splice imported." + + pick_splice :: Bool -> GlobalRdrElt -> Bool + pick_splice in_splice = any ((in_splice ==) . is_splice . is_decl) . gre_imp + + is_splice_stage (Splice {}) = True + is_splice_stage _ = False + checkThLocalName :: Name -> RnM () checkThLocalName name | isUnboundName name -- Do not report two errors for diff --git a/compiler/GHC/Rename/Unbound.hs b/compiler/GHC/Rename/Unbound.hs index 9ebd15e5f6..ce8614bdbc 100644 --- a/compiler/GHC/Rename/Unbound.hs +++ b/compiler/GHC/Rename/Unbound.hs @@ -52,6 +52,8 @@ import Data.Function ( on ) -} data WhereLooking = WL_Any -- Any binding + | WL_SpliceImport + | WL_NonSpliceImport | WL_Global -- Any top-level binding (local or imported) | WL_LocalTop -- Any top-level binding in this module | WL_LocalOnly @@ -130,7 +132,7 @@ fieldSelectorSuggestions global_env tried_rdr_name $$ text "that has been suppressed by NoFieldSelectors" where gres = filter isNoFieldSelectorGRE $ - lookupGRE_RdrName' tried_rdr_name global_env + lookupGRE_RdrName' tried_rdr_name global_env -- TODO MP parents = [ parent | ParentIs parent <- map gre_par gres ] -- parents may be empty if this is a pattern synonym field without a selector @@ -352,7 +354,14 @@ importSuggestions where_look global_env hpt currMod imports rdr_name -- wouldn't have an out-of-scope error in the first place) helpful_imports = filter helpful interesting_imports where helpful (_,imv) - = not . null $ lookupGlobalRdrEnv (imv_all_exports imv) occ_name + = not . null . splice_selector $ lookupGlobalRdrEnv (imv_all_exports imv) occ_name + + -- Need to only suggest splice imported modules for things which are out + -- of scope because + splice_selector = case where_look of + WL_SpliceImport -> filter isSpliceImportedGRE + WL_NonSpliceImport -> filter isNonSpliceImportedGRE + _ -> id -- Which of these do that because of an explicit hiding list resp. an -- explicit import list @@ -396,6 +405,8 @@ isGreOk :: WhereLooking -> GlobalRdrElt -> Bool isGreOk where_look = case where_look of WL_LocalTop -> isLocalGRE WL_LocalOnly -> const False + WL_SpliceImport -> isSpliceImportedGRE + WL_NonSpliceImport -> isNonSpliceImportedGRE _ -> const True {- Note [When to show/hide the module-not-imported line] -- #15611 diff --git a/compiler/GHC/Runtime/Loader.hs b/compiler/GHC/Runtime/Loader.hs index 73ad45c246..40c6a01c5f 100644 --- a/compiler/GHC/Runtime/Loader.hs +++ b/compiler/GHC/Runtime/Loader.hs @@ -269,7 +269,8 @@ lookupRdrNameInModuleForPlugins hsc_env mod_name rdr_name = do Just iface -> do -- Try and find the required name in the exports let decl_spec = ImpDeclSpec { is_mod = mod_name, is_as = mod_name - , is_qual = False, is_dloc = noSrcSpan } + , is_qual = False, is_splice = False + , is_dloc = noSrcSpan } imp_spec = ImpSpec decl_spec ImpAll env = mkGlobalRdrEnv (gresFromAvails (Just imp_spec) (mi_exports iface)) case lookupGRE_RdrName rdr_name env of diff --git a/compiler/GHC/Tc/Gen/Head.hs b/compiler/GHC/Tc/Gen/Head.hs index 2a442b3fd9..b5a4deee28 100644 --- a/compiler/GHC/Tc/Gen/Head.hs +++ b/compiler/GHC/Tc/Gen/Head.hs @@ -679,7 +679,7 @@ lookupParents is_selector rdr -- Filter by isRecFldGRE because otherwise a non-selector variable with -- an overlapping name can get through when NoFieldSelectors is enabled. -- See Note [NoFieldSelectors] in GHC.Rename.Env. - ; let all_gres = lookupGRE_RdrName' rdr env + ; let all_gres = lookupGRE_RdrName' rdr env --TODO MP ; let gres | is_selector = filter isFieldSelectorGRE all_gres | otherwise = filter isRecFldGRE all_gres ; mapM lookupParent gres } diff --git a/compiler/GHC/Tc/Utils/Backpack.hs b/compiler/GHC/Tc/Utils/Backpack.hs index 707d936504..b32dd165f9 100644 --- a/compiler/GHC/Tc/Utils/Backpack.hs +++ b/compiler/GHC/Tc/Utils/Backpack.hs @@ -665,6 +665,7 @@ mergeSignatures is_mod = mod_name, is_as = mod_name, is_qual = False, + is_splice = False, is_dloc = locA loc } ImpAll rdr_env = mkGlobalRdrEnv (gresFromAvails (Just ispec) as1) @@ -872,7 +873,7 @@ mergeSignatures iface' = iface { mi_final_exts = (mi_final_exts iface){ mi_orphan = False, mi_finsts = False } } home_unit = hsc_home_unit hsc_env avails = plusImportAvails (tcg_imports tcg_env) $ - calculateAvails home_unit iface' False NotBoot ImportedBySystem + calculateAvails home_unit iface' False NotBoot NotNeededCompiled ImportedBySystem return tcg_env { tcg_inst_env = inst_env, tcg_insts = insts, @@ -963,7 +964,7 @@ checkImplements impl_mod req_mod@(Module uid mod_name) = do (dep_orphs (mi_deps impl_iface)) let avails = calculateAvails home_unit - impl_iface False{- safe -} NotBoot ImportedBySystem + impl_iface False{- safe -} NotBoot NotNeededCompiled ImportedBySystem fix_env = mkNameEnv [ (greMangledName rdr_elt, FixItem occ f) | (occ, f) <- mi_fixities impl_iface , rdr_elt <- lookupGlobalRdrEnv impl_gr occ ] diff --git a/compiler/GHC/Types/Name/Reader.hs b/compiler/GHC/Types/Name/Reader.hs index a4ec4bea8d..6c64ff9404 100644 --- a/compiler/GHC/Types/Name/Reader.hs +++ b/compiler/GHC/Types/Name/Reader.hs @@ -63,6 +63,7 @@ module GHC.Types.Name.Reader ( -- ** Global 'RdrName' mapping elements: 'GlobalRdrElt', 'Provenance', 'ImportSpec' GlobalRdrElt(..), isLocalGRE, isRecFldGRE, isDuplicateRecFldGRE, isNoFieldSelectorGRE, isFieldSelectorGRE, + isSpliceImportedGRE, isNonSpliceImportedGRE, distinguishSpliceImports, unQualOK, qualSpecOK, unQualSpecOK, pprNameProvenance, GreName(..), greNameSrcSpan, @@ -843,7 +844,7 @@ lookupGRE_RdrName :: RdrName -> GlobalRdrEnv -> [GlobalRdrElt] lookupGRE_RdrName rdr_name env = filter (not . isNoFieldSelectorGRE) (lookupGRE_RdrName' rdr_name env) -lookupGRE_RdrName' :: RdrName -> GlobalRdrEnv -> [GlobalRdrElt] +lookupGRE_RdrName' :: RdrName -> GlobalRdrEnv -> [GlobalRdrElt] -- ^ Look for this 'RdrName' in the global environment. Includes record fields -- without selector functions (see Note [NoFieldSelectors] in GHC.Rename.Env). lookupGRE_RdrName' rdr_name env @@ -851,6 +852,7 @@ lookupGRE_RdrName' rdr_name env Nothing -> [] Just gres -> pickGREs rdr_name gres + lookupGRE_Name :: GlobalRdrEnv -> Name -> Maybe GlobalRdrElt -- ^ Look for precisely this 'Name' in the environment. This tests -- whether it is in scope, ignoring anything else that might be in @@ -902,6 +904,15 @@ getGRE_NameQualifier_maybes env name isLocalGRE :: GlobalRdrElt -> Bool isLocalGRE (GRE {gre_lcl = lcl }) = lcl +isSpliceImportedGRE :: GlobalRdrElt -> Bool +isSpliceImportedGRE = distinguishSpliceImports True + +isNonSpliceImportedGRE :: GlobalRdrElt -> Bool +isNonSpliceImportedGRE = distinguishSpliceImports False + +distinguishSpliceImports :: Bool -> GlobalRdrElt -> Bool +distinguishSpliceImports in_splice = any ((in_splice ==) . is_splice . is_decl) . gre_imp + isRecFldGRE :: GlobalRdrElt -> Bool isRecFldGRE = isJust . greFieldLabel @@ -1180,6 +1191,7 @@ shadowName env new_name id_spec = ImpDeclSpec { is_mod = old_mod_name , is_as = old_mod_name , is_qual = True + , is_splice = undefined -- TODO MP , is_dloc = greDefinitionSrcSpan old_gre } shadow_is :: ImportSpec -> Maybe ImportSpec @@ -1221,6 +1233,7 @@ data ImpDeclSpec -- should be a Maybe UnitId here too. is_as :: ModuleName, -- ^ Import alias, e.g. from @as M@ (or @Muggle@ if there is no @as@ clause) is_qual :: Bool, -- ^ Was this import qualified? + is_splice :: Bool, -- ^ Was this a splice import is_dloc :: SrcSpan -- ^ The location of the entire import declaration } deriving (Eq, Data) diff --git a/compiler/GHC/Unit/Types.hs b/compiler/GHC/Unit/Types.hs index 57dcddef6b..e5962d12d8 100644 --- a/compiler/GHC/Unit/Types.hs +++ b/compiler/GHC/Unit/Types.hs @@ -83,6 +83,8 @@ module GHC.Unit.Types , GenWithIsBoot (..) , ModuleNameWithIsBoot , ModuleWithIsBoot + + , IsNeededCompiled(..) ) where @@ -641,6 +643,7 @@ wiredInUnitIds = data IsBootInterface = NotBoot | IsBoot deriving (Eq, Ord, Show, Data) + instance Binary IsBootInterface where put_ bh ib = put_ bh $ case ib of @@ -652,6 +655,13 @@ instance Binary IsBootInterface where False -> NotBoot True -> IsBoot +data IsNeededCompiled = NeededCompiled | NotNeededCompiled + deriving (Eq, Ord, Show, Data, Enum) + +instance Binary IsNeededCompiled where + put_ bh ic = put_ bh (fromEnum ic) + get bh = toEnum <$> get bh + -- | This data type just pairs a value 'mod' with an IsBootInterface flag. In -- practice, 'mod' is usually a @Module@ or @ModuleName@'. data GenWithIsBoot mod = GWIB @@ -666,7 +676,7 @@ type ModuleNameWithIsBoot = GenWithIsBoot ModuleName type ModuleWithIsBoot = GenWithIsBoot Module instance Binary a => Binary (GenWithIsBoot a) where - put_ bh (GWIB { gwib_mod, gwib_isBoot }) = do + put_ bh (GWIB { gwib_mod, gwib_isBoot}) = do put_ bh gwib_mod put_ bh gwib_isBoot get bh = do diff --git a/hadrian/src/Rules/Test.hs b/hadrian/src/Rules/Test.hs index 43982b9549..704e720448 100644 --- a/hadrian/src/Rules/Test.hs +++ b/hadrian/src/Rules/Test.hs @@ -214,11 +214,11 @@ needIservBins = do rtsways <- interpretInContext (vanillaContext stg ghc) getRtsWays need =<< traverse programPath [ Context stg iserv w - | w <- [vanilla, profiling, dynamic] + | w <- [vanilla, dynamic] , w `elem` rtsways ] pkgFile :: Stage -> Package -> Action FilePath pkgFile stage pkg - | isLibrary pkg = pkgConfFile (Context stage pkg profilingDynamic) + | isLibrary pkg = pkgConfFile (Context stage pkg dynamic) | otherwise = programPath =<< programContext stage pkg diff --git a/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs b/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs index 8dc2b67a36..96417919a5 100644 --- a/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs +++ b/libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs @@ -149,6 +149,7 @@ data Extension | FieldSelectors | OverloadedRecordDot | OverloadedRecordUpdate + | ExplicitSpliceImports deriving (Eq, Enum, Show, Generic, Bounded) -- 'Ord' and 'Bounded' are provided for GHC API users (see discussions -- in https://gitlab.haskell.org/ghc/ghc/merge_requests/2707 and diff --git a/utils/check-exact/ExactPrint.hs b/utils/check-exact/ExactPrint.hs index 8f4f89e265..b2ab796346 100644 --- a/utils/check-exact/ExactPrint.hs +++ b/utils/check-exact/ExactPrint.hs @@ -713,8 +713,8 @@ instance ExactPrint (LocatedP WarningTxt) where instance ExactPrint (ImportDecl GhcPs) where getAnnotationEntry idecl = fromAnn (ideclExt idecl) - exact x@(ImportDecl ApiAnnNotUsed _ _ _ _ _ _ _ _ _) = withPpr x - exact (ImportDecl ann@(ApiAnn _ an _) msrc (L lm modname) mpkg _src safeflag qualFlag _impl mAs hiding) = do + exact x@(ImportDecl {ideclExt = ApiAnnNotUsed}) = withPpr x + exact (ImportDecl ann@(ApiAnn _ an _) msrc (L lm modname) mpkg _src safeflag qualFlag spliceFlag _impl mAs hiding) = do markAnnKw ann importDeclAnnImport AnnImport |