summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2021-03-23 13:26:44 +0000
committerMatthew Pickering <matthewtpickering@gmail.com>2021-03-23 13:26:44 +0000
commit1998c66e674fba382ffa1c7d8e52b282589ec1ec (patch)
treeabea412b17c239f1ea9b42fe5ae1a9cd7bef3f41
parenta9129f9fdfbd358e76aa197ba00bfe75012d6b4f (diff)
downloadhaskell-wip/splice-import.tar.gz
WIP: Splice importswip/splice-import
-rw-r--r--compiler/GHC.hs1
-rw-r--r--compiler/GHC/Driver/Session.hs1
-rw-r--r--compiler/GHC/Hs/ImpExp.hs4
-rw-r--r--compiler/GHC/Hs/Stats.hs30
-rw-r--r--compiler/GHC/Parser.y27
-rw-r--r--compiler/GHC/Parser/Header.hs7
-rw-r--r--compiler/GHC/Parser/Lexer.x4
-rw-r--r--compiler/GHC/Rename/Env.hs2
-rw-r--r--compiler/GHC/Rename/Expr.hs17
-rw-r--r--compiler/GHC/Rename/Names.hs19
-rw-r--r--compiler/GHC/Rename/Splice.hs27
-rw-r--r--compiler/GHC/Rename/Unbound.hs15
-rw-r--r--compiler/GHC/Runtime/Loader.hs3
-rw-r--r--compiler/GHC/Tc/Gen/Head.hs2
-rw-r--r--compiler/GHC/Tc/Utils/Backpack.hs5
-rw-r--r--compiler/GHC/Types/Name/Reader.hs15
-rw-r--r--compiler/GHC/Unit/Types.hs12
-rw-r--r--hadrian/src/Rules/Test.hs4
-rw-r--r--libraries/ghc-boot-th/GHC/LanguageExtensions/Type.hs1
-rw-r--r--utils/check-exact/ExactPrint.hs4
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