summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/coreSyn/CoreFVs.hs2
-rw-r--r--compiler/coreSyn/CoreLint.hs1
-rw-r--r--compiler/coreSyn/CoreSyn.hs116
-rw-r--r--compiler/deSugar/Desugar.hs3
-rw-r--r--compiler/deSugar/DsBinds.hs3
-rw-r--r--compiler/iface/LoadIface.hs27
-rw-r--r--compiler/iface/MkIface.hs24
-rw-r--r--compiler/iface/TcIface.hs5
-rw-r--r--compiler/simplCore/CoreMonad.hs9
-rw-r--r--compiler/simplCore/SimplCore.hs23
-rw-r--r--compiler/simplCore/SimplMonad.hs8
-rw-r--r--compiler/specialise/Rules.hs38
-rw-r--r--compiler/specialise/SpecConstr.hs14
-rw-r--r--compiler/specialise/Specialise.hs24
-rw-r--r--compiler/types/InstEnv.hs78
-rw-r--r--testsuite/.gitignore4
-rw-r--r--testsuite/tests/plugins/Makefile19
-rw-r--r--testsuite/tests/plugins/T10294.hs7
-rw-r--r--testsuite/tests/plugins/T10294.stderr1
-rw-r--r--testsuite/tests/plugins/T10294a.hs7
-rw-r--r--testsuite/tests/plugins/T10420.hs10
-rw-r--r--testsuite/tests/plugins/T10420.stdout1
-rw-r--r--testsuite/tests/plugins/T10420a.hs (renamed from testsuite/tests/plugins/Plugins07a.hs)2
-rw-r--r--testsuite/tests/plugins/all.T21
-rw-r--r--testsuite/tests/plugins/annotation-plugin/LICENSE0
-rw-r--r--testsuite/tests/plugins/annotation-plugin/Makefile18
-rw-r--r--testsuite/tests/plugins/annotation-plugin/SayAnnNames.hs34
-rw-r--r--testsuite/tests/plugins/annotation-plugin/Setup.hs2
-rw-r--r--testsuite/tests/plugins/annotation-plugin/annotation-plugin.cabal11
-rw-r--r--testsuite/tests/plugins/plugins07.hs4
-rw-r--r--testsuite/tests/plugins/plugins07.stdout2
-rw-r--r--testsuite/tests/simplCore/should_compile/T8848.stderr10
32 files changed, 351 insertions, 177 deletions
diff --git a/compiler/coreSyn/CoreFVs.hs b/compiler/coreSyn/CoreFVs.hs
index 2a44ccc9a3..688728ae48 100644
--- a/compiler/coreSyn/CoreFVs.hs
+++ b/compiler/coreSyn/CoreFVs.hs
@@ -24,7 +24,7 @@ module CoreFVs (
idUnfoldingVars, idFreeVars, idRuleAndUnfoldingVars,
idRuleVars, idRuleRhsVars, stableUnfoldingVars,
ruleRhsFreeVars, ruleFreeVars, rulesFreeVars,
- ruleLhsOrphNames, ruleLhsFreeIds,
+ ruleLhsOrphNames, ruleLhsFreeIds, exprsOrphNames,
vectsFreeVars,
-- * Core syntax tree annotation with free variables
diff --git a/compiler/coreSyn/CoreLint.hs b/compiler/coreSyn/CoreLint.hs
index 989cb7f7bf..f681ea53ac 100644
--- a/compiler/coreSyn/CoreLint.hs
+++ b/compiler/coreSyn/CoreLint.hs
@@ -1871,6 +1871,7 @@ withoutAnnots pass guts = do
withoutFlag corem =
liftIO =<< runCoreM <$> fmap removeFlag getHscEnv <*> getRuleBase <*>
getUniqueSupplyM <*> getModule <*>
+ getVisibleOrphanMods <*>
getPrintUnqualified <*> pure corem
-- Nuke existing ticks in module.
-- TODO: Ticks in unfoldings. Maybe change unfolding so it removes
diff --git a/compiler/coreSyn/CoreSyn.hs b/compiler/coreSyn/CoreSyn.hs
index 98400c42a3..c641d88f65 100644
--- a/compiler/coreSyn/CoreSyn.hs
+++ b/compiler/coreSyn/CoreSyn.hs
@@ -67,9 +67,13 @@ module CoreSyn (
-- ** Operations on annotations
deAnnotate, deAnnotate', deAnnAlt, collectAnnBndrs,
+ -- * Orphanhood
+ IsOrphan(..), isOrphan, notOrphan,
+
-- * Core rule data types
CoreRule(..), RuleBase,
RuleName, RuleFun, IdUnfoldingFun, InScopeEnv,
+ RuleEnv(..), mkRuleEnv, emptyRuleEnv,
-- ** Operations on 'CoreRule's
ruleArity, ruleName, ruleIdName, ruleActivation,
@@ -88,7 +92,7 @@ import Var
import Type
import Coercion
import Name
-import NameEnv( NameEnv )
+import NameEnv( NameEnv, emptyNameEnv )
import Literal
import DataCon
import Module
@@ -99,6 +103,7 @@ import FastString
import Outputable
import Util
import SrcLoc ( RealSrcSpan, containsSpan )
+import Binary
import Data.Data hiding (TyCon)
import Data.Int
@@ -693,6 +698,84 @@ tickishContains t1 t2
{-
************************************************************************
* *
+ Orphans
+* *
+************************************************************************
+-}
+
+-- | Is this instance an orphan? If it is not an orphan, contains an 'OccName'
+-- witnessing the instance's non-orphanhood.
+-- See Note [Orphans]
+data IsOrphan
+ = IsOrphan
+ | NotOrphan OccName -- The OccName 'n' witnesses the instance's non-orphanhood
+ -- In that case, the instance is fingerprinted as part
+ -- of the definition of 'n's definition
+ deriving (Data, Typeable)
+
+-- | Returns true if 'IsOrphan' is orphan.
+isOrphan :: IsOrphan -> Bool
+isOrphan IsOrphan = True
+isOrphan _ = False
+
+-- | Returns true if 'IsOrphan' is not an orphan.
+notOrphan :: IsOrphan -> Bool
+notOrphan NotOrphan{} = True
+notOrphan _ = False
+
+instance Binary IsOrphan where
+ put_ bh IsOrphan = putByte bh 0
+ put_ bh (NotOrphan n) = do
+ putByte bh 1
+ put_ bh n
+ get bh = do
+ h <- getByte bh
+ case h of
+ 0 -> return IsOrphan
+ _ -> do
+ n <- get bh
+ return $ NotOrphan n
+
+{-
+Note [Orphans]
+~~~~~~~~~~~~~~
+Class instances, rules, and family instances are divided into orphans
+and non-orphans. Roughly speaking, an instance/rule is an orphan if
+its left hand side mentions nothing defined in this module. Orphan-hood
+has two major consequences
+
+ * A module that contains orphans is called an "orphan module". If
+ the module being compiled depends (transitively) on an oprhan
+ module M, then M.hi is read in regardless of whether M is oherwise
+ needed. This is to ensure that we don't miss any instance decls in
+ M. But it's painful, because it means we need to keep track of all
+ the orphan modules below us.
+
+ * A non-orphan is not finger-printed separately. Instead, for
+ fingerprinting purposes it is treated as part of the entity it
+ mentions on the LHS. For example
+ data T = T1 | T2
+ instance Eq T where ....
+ The instance (Eq T) is incorprated as part of T's fingerprint.
+
+ In constrast, orphans are all fingerprinted together in the
+ mi_orph_hash field of the ModIface.
+
+ See MkIface.addFingerprints.
+
+Orphan-hood is computed
+ * For class instances:
+ when we make a ClsInst
+ (because it is needed during instance lookup)
+
+ * For rules and family instances:
+ when we generate an IfaceRule (MkIface.coreRuleToIfaceRule)
+ or IfaceFamInst (MkIface.instanceToIfaceInst)
+-}
+
+{-
+************************************************************************
+* *
\subsection{Transformation rules}
* *
************************************************************************
@@ -706,6 +789,20 @@ type RuleBase = NameEnv [CoreRule]
-- The rules are unordered;
-- we sort out any overlaps on lookup
+-- | A full rule environment which we can apply rules from. Like a 'RuleBase',
+-- but it also includes the set of visible orphans we use to filter out orphan
+-- rules which are not visible (even though we can see them...)
+data RuleEnv
+ = RuleEnv { re_base :: RuleBase
+ , re_visible_orphs :: ModuleSet
+ }
+
+mkRuleEnv :: RuleBase -> [Module] -> RuleEnv
+mkRuleEnv rules vis_orphs = RuleEnv rules (mkModuleSet vis_orphs)
+
+emptyRuleEnv :: RuleEnv
+emptyRuleEnv = RuleEnv emptyNameEnv emptyModuleSet
+
-- | A 'CoreRule' is:
--
-- * \"Local\" if the function it is a rule for is defined in the
@@ -738,17 +835,26 @@ data CoreRule
-- @False@ <=> generated at the users behest
-- Main effect: reporting of orphan-hood
+ ru_origin :: !Module, -- ^ 'Module' the rule was defined in, used
+ -- to test if we should see an orphan rule.
+
+ ru_orphan :: !IsOrphan,
+ -- ^ Whether or not the rule is an orphan.
+
ru_local :: Bool -- ^ @True@ iff the fn at the head of the rule is
-- defined in the same module as the rule
-- and is not an implicit 'Id' (like a record selector,
- -- class operation, or data constructor)
-
- -- NB: ru_local is *not* used to decide orphan-hood
- -- c.g. MkIface.coreRuleToIfaceRule
+ -- class operation, or data constructor). This
+ -- is different from 'ru_orphan', where a rule
+ -- can avoid being an orphan if *any* Name in
+ -- LHS of the rule was defined in the same
+ -- module as the rule.
}
-- | Built-in rules are used for constant folding
-- and suchlike. They have no free variables.
+ -- A built-in rule is always visible (there is no such thing as
+ -- an orphan built-in rule.)
| BuiltinRule {
ru_name :: RuleName, -- ^ As above
ru_fn :: Name, -- ^ As above
diff --git a/compiler/deSugar/Desugar.hs b/compiler/deSugar/Desugar.hs
index 2e84560f9e..e3a31b9caa 100644
--- a/compiler/deSugar/Desugar.hs
+++ b/compiler/deSugar/Desugar.hs
@@ -356,6 +356,7 @@ dsRule (L loc (HsRule name act vars lhs _tv_lhs rhs _fv_rhs))
; rhs' <- dsLExpr rhs
; dflags <- getDynFlags
+ ; this_mod <- getModule
; (bndrs'', lhs'', rhs'') <- unfold_coerce bndrs' lhs' rhs'
@@ -371,7 +372,7 @@ dsRule (L loc (HsRule name act vars lhs _tv_lhs rhs _fv_rhs))
-- because they don't show up in the bindings until just before code gen
fn_name = idName fn_id
final_rhs = simpleOptExpr rhs'' -- De-crap it
- rule = mkRule False {- Not auto -} is_local
+ rule = mkRule this_mod False {- Not auto -} is_local
(snd $ unLoc name) act fn_name final_bndrs args
final_rhs
diff --git a/compiler/deSugar/DsBinds.hs b/compiler/deSugar/DsBinds.hs
index fac5eb7d0a..ab3dfb90e1 100644
--- a/compiler/deSugar/DsBinds.hs
+++ b/compiler/deSugar/DsBinds.hs
@@ -444,6 +444,7 @@ dsSpec mb_poly_rhs (L loc (SpecPrag poly_id spec_co spec_inl))
Right (rule_bndrs, _fn, args) -> do
{ dflags <- getDynFlags
+ ; this_mod <- getModule
; let fn_unf = realIdUnfolding poly_id
unf_fvs = stableUnfoldingVars fn_unf `orElse` emptyVarSet
in_scope = mkInScopeSet (unf_fvs `unionVarSet` exprsFreeVars args)
@@ -451,7 +452,7 @@ dsSpec mb_poly_rhs (L loc (SpecPrag poly_id spec_co spec_inl))
spec_id = mkLocalId spec_name spec_ty
`setInlinePragma` inl_prag
`setIdUnfolding` spec_unf
- rule = mkRule False {- Not auto -} is_local_id
+ rule = mkRule this_mod False {- Not auto -} is_local_id
(mkFastString ("SPEC " ++ showPpr dflags poly_name))
rule_act poly_name
rule_bndrs args
diff --git a/compiler/iface/LoadIface.hs b/compiler/iface/LoadIface.hs
index 60feb04a4f..2a8943ca11 100644
--- a/compiler/iface/LoadIface.hs
+++ b/compiler/iface/LoadIface.hs
@@ -458,11 +458,7 @@ loadInterface doc_str mod from
; updateEps_ $ \ eps ->
if elemModuleEnv mod (eps_PIT eps) then eps else
- case from of -- See Note [Care with plugin imports]
- ImportByPlugin -> eps {
- eps_PIT = extendModuleEnv (eps_PIT eps) mod final_iface,
- eps_PTE = addDeclsToPTE (eps_PTE eps) new_eps_decls}
- _ -> eps {
+ eps {
eps_PIT = extendModuleEnv (eps_PIT eps) mod final_iface,
eps_PTE = addDeclsToPTE (eps_PTE eps) new_eps_decls,
eps_rule_base = extendRuleBaseList (eps_rule_base eps)
@@ -526,27 +522,6 @@ badSourceImport mod
2 (ptext (sLit "but") <+> quotes (ppr mod) <+> ptext (sLit "is from package")
<+> quotes (ppr (modulePackageKey mod)))
-{-
-Note [Care with plugin imports]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When dynamically loading a plugin (via loadPluginInterface) we
-populate the same External Package State (EPS), even though plugin
-modules are to link with the compiler itself, and not with the
-compiled program. That's fine: mostly the EPS is just a cache for
-the interace files on disk.
-
-But it's NOT ok for the RULES or instance environment. We do not want
-to fire a RULE from the plugin on the code we are compiling, otherwise
-the code we are compiling will have a reference to a RHS of the rule
-that exists only in the compiler! This actually happened to Daniel,
-via a RULE arising from a specialisation of (^) in the plugin.
-
-Solution: when loading plugins, do not extend the rule and instance
-environments. We are only interested in the type environment, so that
-we can check that the plugin exports a function with the type that the
-compiler expects.
--}
-
-----------------------------------------------------
-- Loading type/class/value decls
-- We pass the full Module name here, replete with
diff --git a/compiler/iface/MkIface.hs b/compiler/iface/MkIface.hs
index c1a9d2523f..970031327c 100644
--- a/compiler/iface/MkIface.hs
+++ b/compiler/iface/MkIface.hs
@@ -69,7 +69,6 @@ import Demand
import Coercion( tidyCo )
import Annotations
import CoreSyn
-import CoreFVs
import Class
import Kind
import TyCon
@@ -271,7 +270,7 @@ mkIface_ hsc_env maybe_old_fingerprint
fixities = [(occ,fix) | FixItem occ fix <- nameEnvElts fix_env]
warns = src_warns
- iface_rules = map (coreRuleToIfaceRule this_mod) rules
+ iface_rules = map coreRuleToIfaceRule rules
iface_insts = map instanceToIfaceInst $ fixSafeInstances safe_mode insts
iface_fam_insts = map famInstToIfaceFamInst fam_insts
iface_vect_info = flattenVectInfo vect_info
@@ -1929,15 +1928,15 @@ toIfUnfolding _ _
= Nothing
--------------------------
-coreRuleToIfaceRule :: Module -> CoreRule -> IfaceRule
-coreRuleToIfaceRule _ (BuiltinRule { ru_fn = fn})
+coreRuleToIfaceRule :: CoreRule -> IfaceRule
+coreRuleToIfaceRule (BuiltinRule { ru_fn = fn})
= pprTrace "toHsRule: builtin" (ppr fn) $
bogusIfaceRule fn
-coreRuleToIfaceRule mod rule@(Rule { ru_name = name, ru_fn = fn,
- ru_act = act, ru_bndrs = bndrs,
- ru_args = args, ru_rhs = rhs,
- ru_auto = auto })
+coreRuleToIfaceRule (Rule { ru_name = name, ru_fn = fn,
+ ru_act = act, ru_bndrs = bndrs,
+ ru_args = args, ru_rhs = rhs,
+ ru_orphan = orph, ru_auto = auto })
= IfaceRule { ifRuleName = name, ifActivation = act,
ifRuleBndrs = map toIfaceBndr bndrs,
ifRuleHead = fn,
@@ -1954,15 +1953,6 @@ coreRuleToIfaceRule mod rule@(Rule { ru_name = name, ru_fn = fn,
do_arg (Coercion co) = IfaceCo (toIfaceCoercion co)
do_arg arg = toIfaceExpr arg
- -- Compute orphanhood. See Note [Orphans] in InstEnv
- -- A rule is an orphan only if none of the variables
- -- mentioned on its left-hand side are locally defined
- lhs_names = nameSetElems (ruleLhsOrphNames rule)
-
- orph = case filter (nameIsLocalOrFrom mod) lhs_names of
- (n : _) -> NotOrphan (nameOccName n)
- [] -> IsOrphan
-
bogusIfaceRule :: Name -> IfaceRule
bogusIfaceRule id_name
= IfaceRule { ifRuleName = fsLit "bogus", ifActivation = NeverActive,
diff --git a/compiler/iface/TcIface.hs b/compiler/iface/TcIface.hs
index 7d6d1a6aa7..4f80fc9c4e 100644
--- a/compiler/iface/TcIface.hs
+++ b/compiler/iface/TcIface.hs
@@ -625,7 +625,7 @@ tcIfaceRules ignore_prags if_rules
tcIfaceRule :: IfaceRule -> IfL CoreRule
tcIfaceRule (IfaceRule {ifRuleName = name, ifActivation = act, ifRuleBndrs = bndrs,
ifRuleHead = fn, ifRuleArgs = args, ifRuleRhs = rhs,
- ifRuleAuto = auto })
+ ifRuleAuto = auto, ifRuleOrph = orph })
= do { ~(bndrs', args', rhs') <-
-- Typecheck the payload lazily, in the hope it'll never be looked at
forkM (ptext (sLit "Rule") <+> ftext name) $
@@ -634,10 +634,13 @@ tcIfaceRule (IfaceRule {ifRuleName = name, ifActivation = act, ifRuleBndrs = bnd
; rhs' <- tcIfaceExpr rhs
; return (bndrs', args', rhs') }
; let mb_tcs = map ifTopFreeName args
+ ; this_mod <- getIfModule
; return (Rule { ru_name = name, ru_fn = fn, ru_act = act,
ru_bndrs = bndrs', ru_args = args',
ru_rhs = occurAnalyseExpr rhs',
ru_rough = mb_tcs,
+ ru_origin = this_mod,
+ ru_orphan = orph,
ru_auto = auto,
ru_local = False }) } -- An imported RULE is never for a local Id
-- or, even if it is (module loop, perhaps)
diff --git a/compiler/simplCore/CoreMonad.hs b/compiler/simplCore/CoreMonad.hs
index dec41bb4f7..fc69fdc681 100644
--- a/compiler/simplCore/CoreMonad.hs
+++ b/compiler/simplCore/CoreMonad.hs
@@ -27,6 +27,7 @@ module CoreMonad (
-- ** Reading from the monad
getHscEnv, getRuleBase, getModule,
getDynFlags, getOrigNameCache, getPackageFamInstEnv,
+ getVisibleOrphanMods,
getPrintUnqualified,
-- ** Writing to the monad
@@ -518,6 +519,7 @@ data CoreReader = CoreReader {
cr_hsc_env :: HscEnv,
cr_rule_base :: RuleBase,
cr_module :: Module,
+ cr_visible_orphan_mods :: !ModuleSet,
cr_print_unqual :: PrintUnqualified,
#ifdef GHCI
cr_globals :: (MVar PersistentLinkerState, Bool)
@@ -595,10 +597,11 @@ runCoreM :: HscEnv
-> RuleBase
-> UniqSupply
-> Module
+ -> ModuleSet
-> PrintUnqualified
-> CoreM a
-> IO (a, SimplCount)
-runCoreM hsc_env rule_base us mod print_unqual m = do
+runCoreM hsc_env rule_base us mod orph_imps print_unqual m = do
glbls <- saveLinkerGlobals
liftM extract $ runIOEnv (reader glbls) $ unCoreM m state
where
@@ -606,6 +609,7 @@ runCoreM hsc_env rule_base us mod print_unqual m = do
cr_hsc_env = hsc_env,
cr_rule_base = rule_base,
cr_module = mod,
+ cr_visible_orphan_mods = orph_imps,
cr_globals = glbls,
cr_print_unqual = print_unqual
}
@@ -668,6 +672,9 @@ getHscEnv = read cr_hsc_env
getRuleBase :: CoreM RuleBase
getRuleBase = read cr_rule_base
+getVisibleOrphanMods :: CoreM ModuleSet
+getVisibleOrphanMods = read cr_visible_orphan_mods
+
getPrintUnqualified :: CoreM PrintUnqualified
getPrintUnqualified = read cr_print_unqual
diff --git a/compiler/simplCore/SimplCore.hs b/compiler/simplCore/SimplCore.hs
index d83ab89bd6..88ca00f6a0 100644
--- a/compiler/simplCore/SimplCore.hs
+++ b/compiler/simplCore/SimplCore.hs
@@ -14,7 +14,7 @@ import DynFlags
import CoreSyn
import HscTypes
import CSE ( cseProgram )
-import Rules ( emptyRuleBase, mkRuleBase, unionRuleBase,
+import Rules ( mkRuleBase, unionRuleBase,
extendRuleBaseList, ruleCheckProgram, addSpecInfo, )
import PprCore ( pprCoreBindings, pprCoreExpr )
import OccurAnal ( occurAnalysePgm, occurAnalyseExpr )
@@ -47,6 +47,7 @@ import Vectorise ( vectorise )
import FastString
import SrcLoc
import Util
+import Module
import Maybes
import UniqSupply ( UniqSupply, mkSplitUniqSupply, splitUniqSupply )
@@ -72,8 +73,10 @@ core2core hsc_env guts
-- make sure all plugins are loaded
; let builtin_passes = getCoreToDo dflags
+ orph_mods = mkModuleSet (mg_module guts : dep_orphs (mg_deps guts))
;
- ; (guts2, stats) <- runCoreM hsc_env hpt_rule_base us mod print_unqual $
+ ; (guts2, stats) <- runCoreM hsc_env hpt_rule_base us mod
+ orph_mods print_unqual $
do { all_passes <- addPluginPasses builtin_passes
; runCorePasses all_passes guts }
@@ -411,9 +414,11 @@ ruleCheckPass :: CompilerPhase -> String -> ModGuts -> CoreM ModGuts
ruleCheckPass current_phase pat guts = do
rb <- getRuleBase
dflags <- getDynFlags
+ vis_orphs <- getVisibleOrphanMods
liftIO $ Err.showPass dflags "RuleCheck"
liftIO $ log_action dflags dflags Err.SevDump noSrcSpan defaultDumpStyle
- (ruleCheckProgram current_phase pat rb (mg_binds guts))
+ (ruleCheckProgram current_phase pat
+ (RuleEnv rb vis_orphs) (mg_binds guts))
return guts
@@ -490,8 +495,9 @@ simplifyExpr dflags expr
; let sz = exprSize expr
- ; (expr', counts) <- initSmpl dflags emptyRuleBase emptyFamInstEnvs us sz $
- simplExprGently (simplEnvForGHCi dflags) expr
+ ; (expr', counts) <- initSmpl dflags emptyRuleEnv
+ emptyFamInstEnvs us sz
+ (simplExprGently (simplEnvForGHCi dflags) expr)
; Err.dumpIfSet dflags (dopt Opt_D_dump_simpl_stats dflags)
"Simplifier statistics" (pprSimplCount counts)
@@ -551,6 +557,7 @@ simplifyPgmIO pass@(CoreDoSimplify max_iterations mode)
hsc_env us hpt_rule_base
guts@(ModGuts { mg_module = this_mod
, mg_rdr_env = rdr_env
+ , mg_deps = deps
, mg_binds = binds, mg_rules = rules
, mg_fam_inst_env = fam_inst_env })
= do { (termination_msg, it_count, counts_out, guts')
@@ -639,10 +646,12 @@ simplifyPgmIO pass@(CoreDoSimplify max_iterations mode)
eps <- hscEPS hsc_env ;
let { rule_base1 = unionRuleBase hpt_rule_base (eps_rule_base eps)
; rule_base2 = extendRuleBaseList rule_base1 rules
- ; fam_envs = (eps_fam_inst_env eps, fam_inst_env) } ;
+ ; fam_envs = (eps_fam_inst_env eps, fam_inst_env)
+ ; vis_orphs = this_mod : dep_orphs deps } ;
-- Simplify the program
- ((binds1, rules1), counts1) <- initSmpl dflags rule_base2 fam_envs us1 sz $
+ ((binds1, rules1), counts1) <-
+ initSmpl dflags (mkRuleEnv rule_base2 vis_orphs) fam_envs us1 sz $
do { env1 <- {-# SCC "SimplTopBinds" #-}
simplTopBinds simpl_env tagged_binds
diff --git a/compiler/simplCore/SimplMonad.hs b/compiler/simplCore/SimplMonad.hs
index bd60a7942c..c8503a7f3f 100644
--- a/compiler/simplCore/SimplMonad.hs
+++ b/compiler/simplCore/SimplMonad.hs
@@ -22,7 +22,7 @@ module SimplMonad (
import Id ( Id, mkSysLocal )
import Type ( Type )
import FamInstEnv ( FamInstEnv )
-import CoreSyn ( RuleBase )
+import CoreSyn ( RuleEnv(..) )
import UniqSupply
import DynFlags
import CoreMonad
@@ -55,10 +55,10 @@ newtype SimplM result
data SimplTopEnv
= STE { st_flags :: DynFlags
, st_max_ticks :: IntWithInf -- Max #ticks in this simplifier run
- , st_rules :: RuleBase
+ , st_rules :: RuleEnv
, st_fams :: (FamInstEnv, FamInstEnv) }
-initSmpl :: DynFlags -> RuleBase -> (FamInstEnv, FamInstEnv)
+initSmpl :: DynFlags -> RuleEnv -> (FamInstEnv, FamInstEnv)
-> UniqSupply -- No init count; set to 0
-> Int -- Size of the bindings, used to limit
-- the number of ticks we allow
@@ -168,7 +168,7 @@ instance MonadIO SimplM where
x <- m
return (x, us, sc)
-getSimplRules :: SimplM RuleBase
+getSimplRules :: SimplM RuleEnv
getSimplRules = SM (\st_env us sc -> return (st_rules st_env, us, sc))
getFamEnvs :: SimplM (FamInstEnv, FamInstEnv)
diff --git a/compiler/specialise/Rules.hs b/compiler/specialise/Rules.hs
index 3601253e41..cb71e3a3f3 100644
--- a/compiler/specialise/Rules.hs
+++ b/compiler/specialise/Rules.hs
@@ -29,9 +29,11 @@ module Rules (
#include "HsVersions.h"
import CoreSyn -- All of it
+import Module ( Module, ModuleSet, elemModuleSet )
import CoreSubst
import OccurAnal ( occurAnalyseExpr )
-import CoreFVs ( exprFreeVars, exprsFreeVars, bindFreeVars, rulesFreeVars )
+import CoreFVs ( exprFreeVars, exprsFreeVars, bindFreeVars
+ , rulesFreeVars, exprsOrphNames )
import CoreUtils ( exprType, eqExpr, mkTick, mkTicks,
stripTicksTopT, stripTicksTopE )
import PprCore ( pprRules )
@@ -43,7 +45,8 @@ import Id
import IdInfo ( SpecInfo( SpecInfo ) )
import VarEnv
import VarSet
-import Name ( Name, NamedThing(..) )
+import Name ( Name, NamedThing(..), nameIsLocalOrFrom, nameOccName )
+import NameSet
import NameEnv
import Unify ( ruleMatchTyX, MatchEnv(..) )
import BasicTypes ( Activation, CompilerPhase, isActive )
@@ -158,16 +161,28 @@ might have a specialisation
where pi' :: Lift Int# is the specialised version of pi.
-}
-mkRule :: Bool -> Bool -> RuleName -> Activation
+mkRule :: Module -> Bool -> Bool -> RuleName -> Activation
-> Name -> [CoreBndr] -> [CoreExpr] -> CoreExpr -> CoreRule
-- ^ Used to make 'CoreRule' for an 'Id' defined in the module being
-- compiled. See also 'CoreSyn.CoreRule'
-mkRule is_auto is_local name act fn bndrs args rhs
+mkRule this_mod is_auto is_local name act fn bndrs args rhs
= Rule { ru_name = name, ru_fn = fn, ru_act = act,
ru_bndrs = bndrs, ru_args = args,
ru_rhs = occurAnalyseExpr rhs,
ru_rough = roughTopNames args,
+ ru_origin = this_mod,
+ ru_orphan = orph,
ru_auto = is_auto, ru_local = is_local }
+ where
+ -- Compute orphanhood. See Note [Orphans] in InstEnv
+ -- A rule is an orphan only if none of the variables
+ -- mentioned on its left-hand side are locally defined
+ lhs_names = nameSetElems (extendNameSet (exprsOrphNames args) fn)
+ -- TODO: copied from ruleLhsOrphNames
+
+ orph = case filter (nameIsLocalOrFrom this_mod) lhs_names of
+ (n : _) -> NotOrphan (nameOccName n)
+ [] -> IsOrphan
--------------
roughTopNames :: [CoreExpr] -> [Maybe Name]
@@ -277,13 +292,18 @@ addIdSpecialisations id rules
rulesOfBinds :: [CoreBind] -> [CoreRule]
rulesOfBinds binds = concatMap (concatMap idCoreRules . bindersOf) binds
-getRules :: RuleBase -> Id -> [CoreRule]
+getRules :: RuleEnv -> Id -> [CoreRule]
-- See Note [Where rules are found]
-getRules rule_base fn
- = idCoreRules fn ++ imp_rules
+getRules (RuleEnv { re_base = rule_base, re_visible_orphs = orphs }) fn
+ = idCoreRules fn ++ filter (ruleIsVisible orphs) imp_rules
where
imp_rules = lookupNameEnv rule_base (idName fn) `orElse` []
+ruleIsVisible :: ModuleSet -> CoreRule -> Bool
+ruleIsVisible _ BuiltinRule{} = True
+ruleIsVisible vis_orphs Rule { ru_orphan = orph, ru_origin = origin }
+ = notOrphan orph || origin `elemModuleSet` vis_orphs
+
{-
Note [Where rules are found]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1041,7 +1061,7 @@ is so important.
-- string for the purposes of error reporting
ruleCheckProgram :: CompilerPhase -- ^ Rule activation test
-> String -- ^ Rule pattern
- -> RuleBase -- ^ Database of rules
+ -> RuleEnv -- ^ Database of rules
-> CoreProgram -- ^ Bindings to check in
-> SDoc -- ^ Resulting check message
ruleCheckProgram phase rule_pat rule_base binds
@@ -1065,7 +1085,7 @@ data RuleCheckEnv = RuleCheckEnv {
rc_is_active :: Activation -> Bool,
rc_id_unf :: IdUnfoldingFun,
rc_pattern :: String,
- rc_rule_base :: RuleBase
+ rc_rule_base :: RuleEnv
}
ruleCheckBind :: RuleCheckEnv -> CoreBind -> Bag SDoc
diff --git a/compiler/specialise/SpecConstr.hs b/compiler/specialise/SpecConstr.hs
index 7a4b4028c4..a8c6f060ab 100644
--- a/compiler/specialise/SpecConstr.hs
+++ b/compiler/specialise/SpecConstr.hs
@@ -58,6 +58,7 @@ import MonadUtils
import Control.Monad ( zipWithM )
import Data.List
import PrelNames ( specTyConName )
+import Module
-- See Note [Forcing specialisation]
#ifndef GHCI
@@ -686,9 +687,11 @@ specConstrProgram guts
dflags <- getDynFlags
us <- getUniqueSupplyM
annos <- getFirstAnnotations deserializeWithData guts
+ this_mod <- getModule
let binds' = reverse $ fst $ initUs us $ do
-- Note [Top-level recursive groups]
- (env, binds) <- goEnv (initScEnv dflags annos) (mg_binds guts)
+ (env, binds) <- goEnv (initScEnv dflags this_mod annos)
+ (mg_binds guts)
-- binds is identical to (mg_binds guts), except that the
-- binders on the LHS have been replaced by extendBndr
-- (SPJ this seems like overkill; I don't think the binders
@@ -760,6 +763,7 @@ leave it for now.
-}
data ScEnv = SCE { sc_dflags :: DynFlags,
+ sc_module :: !Module,
sc_size :: Maybe Int, -- Size threshold
sc_count :: Maybe Int, -- Max # of specialisations for any one fn
-- See Note [Avoiding exponential blowup]
@@ -811,9 +815,10 @@ instance Outputable Value where
ppr LambdaVal = ptext (sLit "<Lambda>")
---------------------
-initScEnv :: DynFlags -> UniqFM SpecConstrAnnotation -> ScEnv
-initScEnv dflags anns
+initScEnv :: DynFlags -> Module -> UniqFM SpecConstrAnnotation -> ScEnv
+initScEnv dflags this_mod anns
= SCE { sc_dflags = dflags,
+ sc_module = this_mod,
sc_size = specConstrThreshold dflags,
sc_count = specConstrCount dflags,
sc_recursive = specConstrRecursive dflags,
@@ -1650,7 +1655,8 @@ spec_one env fn arg_bndrs body (call_pat@(qvars, pats), rule_number)
body_ty = exprType spec_body
rule_rhs = mkVarApps (Var spec_id) spec_call_args
inline_act = idInlineActivation fn
- rule = mkRule True {- Auto -} True {- Local -}
+ this_mod = sc_module spec_env
+ rule = mkRule this_mod True {- Auto -} True {- Local -}
rule_name inline_act fn_name qvars pats rule_rhs
-- See Note [Transfer activation]
; return (spec_usg, OS call_pat rule spec_id spec_rhs) }
diff --git a/compiler/specialise/Specialise.hs b/compiler/specialise/Specialise.hs
index 61633f9834..5c29c28449 100644
--- a/compiler/specialise/Specialise.hs
+++ b/compiler/specialise/Specialise.hs
@@ -13,7 +13,7 @@ import Id
import TcType hiding( substTy, extendTvSubstList )
import Type hiding( substTy, extendTvSubstList )
import Coercion( Coercion )
-import Module( Module )
+import Module( Module, HasModule(..) )
import CoreMonad
import qualified CoreSubst
import CoreUnfold
@@ -578,7 +578,7 @@ specProgram guts@(ModGuts { mg_module = this_mod
= do { dflags <- getDynFlags
-- Specialise the bindings of this module
- ; (binds', uds) <- runSpecM dflags (go binds)
+ ; (binds', uds) <- runSpecM dflags this_mod (go binds)
-- Specialise imported functions
; hpt_rules <- getRuleBase
@@ -652,10 +652,11 @@ specImport dflags this_mod done rb fn calls_for_fn
-- more rules as we go along
; hsc_env <- getHscEnv
; eps <- liftIO $ hscEPS hsc_env
+ ; vis_orphs <- getVisibleOrphanMods
; let full_rb = unionRuleBase rb (eps_rule_base eps)
- rules_for_fn = getRules full_rb fn
+ rules_for_fn = getRules (RuleEnv full_rb vis_orphs) fn
- ; (rules1, spec_pairs, uds) <- runSpecM dflags $
+ ; (rules1, spec_pairs, uds) <- runSpecM dflags this_mod $
specCalls (Just this_mod) emptySpecEnv rules_for_fn calls_for_fn fn rhs
; let spec_binds1 = [NonRec b r | (b,r) <- spec_pairs]
-- After the rules kick in we may get recursion, but
@@ -1187,6 +1188,7 @@ specCalls mb_mod env rules_for_me calls_for_me fn rhs
; spec_f <- newSpecIdSM fn spec_id_ty
; (spec_rhs, rhs_uds) <- specExpr rhs_env2 (mkLams lam_args body)
+ ; this_mod <- getModule
; let
-- The rule to put in the function's specialisation is:
-- forall b, d1',d2'. f t1 b t3 d1' d2' = f1 b
@@ -1202,7 +1204,10 @@ specCalls mb_mod env rules_for_me calls_for_me fn rhs
-- otherwise uniques end up there, making builds
-- less deterministic (See #4012 comment:61 ff)
- spec_env_rule = mkRule True {- Auto generated -} is_local
+ spec_env_rule = mkRule
+ this_mod
+ True {- Auto generated -}
+ is_local
rule_name
inl_act -- Note [Auto-specialisation and RULES]
(idName fn)
@@ -1955,6 +1960,7 @@ newtype SpecM a = SpecM (State SpecState a)
data SpecState = SpecState {
spec_uniq_supply :: UniqSupply,
+ spec_module :: Module,
spec_dflags :: DynFlags
}
@@ -1989,11 +1995,15 @@ instance MonadUnique SpecM where
instance HasDynFlags SpecM where
getDynFlags = SpecM $ liftM spec_dflags get
-runSpecM :: DynFlags -> SpecM a -> CoreM a
-runSpecM dflags (SpecM spec)
+instance HasModule SpecM where
+ getModule = SpecM $ liftM spec_module get
+
+runSpecM :: DynFlags -> Module -> SpecM a -> CoreM a
+runSpecM dflags this_mod (SpecM spec)
= do us <- getUniqueSupplyM
let initialState = SpecState {
spec_uniq_supply = us,
+ spec_module = this_mod,
spec_dflags = dflags
}
return $ evalState spec initialState
diff --git a/compiler/types/InstEnv.hs b/compiler/types/InstEnv.hs
index 6151f20599..f810850d4b 100644
--- a/compiler/types/InstEnv.hs
+++ b/compiler/types/InstEnv.hs
@@ -29,6 +29,7 @@ module InstEnv (
#include "HsVersions.h"
+import CoreSyn (IsOrphan(..), isOrphan, notOrphan)
import Module
import Class
import Var
@@ -44,7 +45,6 @@ import BasicTypes
import UniqFM
import Util
import Id
-import Binary
import FastString
import Data.Data ( Data, Typeable )
import Data.Maybe ( isJust, isNothing )
@@ -274,82 +274,6 @@ instanceCantMatch (Just t : ts) (Just a : as) = t/=a || instanceCantMatch ts as
instanceCantMatch _ _ = False -- Safe
{-
-************************************************************************
-* *
- Orphans
-* *
-************************************************************************
--}
-
--- | Is this instance an orphan? If it is not an orphan, contains an 'OccName'
--- witnessing the instance's non-orphanhood.
--- See Note [Orphans]
-data IsOrphan
- = IsOrphan
- | NotOrphan OccName -- The OccName 'n' witnesses the instance's non-orphanhood
- -- In that case, the instance is fingerprinted as part
- -- of the definition of 'n's definition
- deriving (Data, Typeable)
-
--- | Returns true if 'IsOrphan' is orphan.
-isOrphan :: IsOrphan -> Bool
-isOrphan IsOrphan = True
-isOrphan _ = False
-
--- | Returns true if 'IsOrphan' is not an orphan.
-notOrphan :: IsOrphan -> Bool
-notOrphan NotOrphan{} = True
-notOrphan _ = False
-
-instance Binary IsOrphan where
- put_ bh IsOrphan = putByte bh 0
- put_ bh (NotOrphan n) = do
- putByte bh 1
- put_ bh n
- get bh = do
- h <- getByte bh
- case h of
- 0 -> return IsOrphan
- _ -> do
- n <- get bh
- return $ NotOrphan n
-
-{-
-Note [Orphans]
-~~~~~~~~~~~~~~
-Class instances, rules, and family instances are divided into orphans
-and non-orphans. Roughly speaking, an instance/rule is an orphan if
-its left hand side mentions nothing defined in this module. Orphan-hood
-has two major consequences
-
- * A module that contains orphans is called an "orphan module". If
- the module being compiled depends (transitively) on an oprhan
- module M, then M.hi is read in regardless of whether M is oherwise
- needed. This is to ensure that we don't miss any instance decls in
- M. But it's painful, because it means we need to keep track of all
- the orphan modules below us.
-
- * A non-orphan is not finger-printed separately. Instead, for
- fingerprinting purposes it is treated as part of the entity it
- mentions on the LHS. For example
- data T = T1 | T2
- instance Eq T where ....
- The instance (Eq T) is incorprated as part of T's fingerprint.
-
- In constrast, orphans are all fingerprinted together in the
- mi_orph_hash field of the ModIface.
-
- See MkIface.addFingerprints.
-
-Orphan-hood is computed
- * For class instances:
- when we make a ClsInst
- (because it is needed during instance lookup)
-
- * For rules and family instances:
- when we generate an IfaceRule (MkIface.coreRuleToIfaceRule)
- or IfaceFamInst (MkIface.instanceToIfaceInst)
-
Note [When exactly is an instance decl an orphan?]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(see MkIface.instanceToIfaceInst, which implements this)
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
index 21c5709c45..10b1bfe699 100644
--- a/testsuite/.gitignore
+++ b/testsuite/.gitignore
@@ -1202,7 +1202,11 @@ mk/ghcconfig*_inplace_bin_ghc-stage2.exe.mk
/tests/plugins/simple-plugin/pkg.plugins02/
/tests/plugins/simple-plugin/pkg.plugins03/
/tests/plugins/simple-plugin/setup
+/tests/plugins/rule-defining-plugin/pkg.T10420/
/tests/plugins/rule-defining-plugin/pkg.plugins07/
+/tests/plugins/annotation-plugin/pkg.T10294/
+/tests/plugins/annotation-plugin/pkg.T10294a/
+/tests/plugins/T10420
/tests/polykinds/Freeman
/tests/polykinds/MonoidsFD
/tests/polykinds/MonoidsTF
diff --git a/testsuite/tests/plugins/Makefile b/testsuite/tests/plugins/Makefile
index aac3b1257d..42a4d1af0a 100644
--- a/testsuite/tests/plugins/Makefile
+++ b/testsuite/tests/plugins/Makefile
@@ -2,12 +2,25 @@ TOP=../..
include $(TOP)/mk/boilerplate.mk
include $(TOP)/mk/test.mk
-.PHONY: plugins01 plugins07
-
+.PHONY: plugins01
plugins01:
"$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) --make -v0 plugins01.hs -package-db simple-plugin/pkg.plugins01/local.package.conf -fplugin Simple.Plugin -fplugin-opt Simple.Plugin:Irrelevant_Option -package simple-plugin
./plugins01
+.PHONY: plugins07
plugins07:
- "$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) --make -v0 -O plugins07.hs -package-db rule-defining-plugin/pkg.plugins07/local.package.conf -package rule-defining-plugin
+ "$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) --make -v0 -O plugins07.hs -package-db rule-defining-plugin/pkg.plugins07/local.package.conf -package rule-defining-plugin -fplugin=RuleDefiningPlugin
./plugins07
+
+.PHONY: T10420
+T10420:
+ "$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) --make -v0 -O T10420.hs -package-db rule-defining-plugin/pkg.T10420/local.package.conf -package rule-defining-plugin
+ ./T10420
+
+.PHONY: T10294
+T10294:
+ "$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) -c -v0 T10294.hs -package-db annotation-plugin/pkg.T10294/local.package.conf -package annotation-plugin -fplugin=SayAnnNames
+
+.PHONY: T10294a
+T10294a:
+ "$(TEST_HC)" $(TEST_HC_OPTS) $(ghcPluginWayFlags) -c -v0 T10294a.hs -package-db annotation-plugin/pkg.T10294a/local.package.conf -package annotation-plugin -fplugin=SayAnnNames
diff --git a/testsuite/tests/plugins/T10294.hs b/testsuite/tests/plugins/T10294.hs
new file mode 100644
index 0000000000..ff1dd57400
--- /dev/null
+++ b/testsuite/tests/plugins/T10294.hs
@@ -0,0 +1,7 @@
+module T10294 where
+
+import SayAnnNames
+
+{-# ANN foo SomeAnn #-}
+foo :: ()
+foo = ()
diff --git a/testsuite/tests/plugins/T10294.stderr b/testsuite/tests/plugins/T10294.stderr
new file mode 100644
index 0000000000..4b3737a028
--- /dev/null
+++ b/testsuite/tests/plugins/T10294.stderr
@@ -0,0 +1 @@
+Annotated binding found: foo
diff --git a/testsuite/tests/plugins/T10294a.hs b/testsuite/tests/plugins/T10294a.hs
new file mode 100644
index 0000000000..ba5942be72
--- /dev/null
+++ b/testsuite/tests/plugins/T10294a.hs
@@ -0,0 +1,7 @@
+module T10294a where
+
+import SayAnnNames
+import Data.Data
+
+baz :: Constr
+baz = toConstr SomeAnn
diff --git a/testsuite/tests/plugins/T10420.hs b/testsuite/tests/plugins/T10420.hs
new file mode 100644
index 0000000000..7b863445ec
--- /dev/null
+++ b/testsuite/tests/plugins/T10420.hs
@@ -0,0 +1,10 @@
+module Main where
+
+import T10420a
+
+import RuleDefiningPlugin
+
+{-# NOINLINE x #-}
+x = "foo"
+
+main = putStrLn (show x)
diff --git a/testsuite/tests/plugins/T10420.stdout b/testsuite/tests/plugins/T10420.stdout
new file mode 100644
index 0000000000..d27268d74f
--- /dev/null
+++ b/testsuite/tests/plugins/T10420.stdout
@@ -0,0 +1 @@
+SHOWED
diff --git a/testsuite/tests/plugins/Plugins07a.hs b/testsuite/tests/plugins/T10420a.hs
index 7453a31dea..da4d3b51a0 100644
--- a/testsuite/tests/plugins/Plugins07a.hs
+++ b/testsuite/tests/plugins/T10420a.hs
@@ -1,2 +1,2 @@
{-# OPTIONS_GHC -fplugin RuleDefiningPlugin #-}
-module Plugins07a where
+module T10420a where
diff --git a/testsuite/tests/plugins/all.T b/testsuite/tests/plugins/all.T
index e39c049dfa..62e69239b4 100644
--- a/testsuite/tests/plugins/all.T
+++ b/testsuite/tests/plugins/all.T
@@ -40,7 +40,24 @@ test('plugins06',
test('plugins07',
[pre_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin package.plugins07'),
- clean_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin clean.plugins07'),
- expect_broken(10420)],
+ clean_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin clean.plugins07')],
run_command,
['$MAKE -s --no-print-directory plugins07'])
+
+test('T10420',
+ [pre_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin package.T10420'),
+ clean_cmd('$MAKE -s --no-print-directory -C rule-defining-plugin clean.T10420')],
+ run_command,
+ ['$MAKE -s --no-print-directory T10420'])
+
+test('T10294',
+ [pre_cmd('$MAKE -s --no-print-directory -C annotation-plugin package.T10294'),
+ clean_cmd('$MAKE -s --no-print-directory -C annotation-plugin clean.T10294')],
+ run_command,
+ ['$MAKE -s --no-print-directory T10294'])
+
+test('T10294a',
+ [pre_cmd('$MAKE -s --no-print-directory -C annotation-plugin package.T10294a'),
+ clean_cmd('$MAKE -s --no-print-directory -C annotation-plugin clean.T10294a')],
+ run_command,
+ ['$MAKE -s --no-print-directory T10294a'])
diff --git a/testsuite/tests/plugins/annotation-plugin/LICENSE b/testsuite/tests/plugins/annotation-plugin/LICENSE
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testsuite/tests/plugins/annotation-plugin/LICENSE
diff --git a/testsuite/tests/plugins/annotation-plugin/Makefile b/testsuite/tests/plugins/annotation-plugin/Makefile
new file mode 100644
index 0000000000..7d957d0e95
--- /dev/null
+++ b/testsuite/tests/plugins/annotation-plugin/Makefile
@@ -0,0 +1,18 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+clean.%:
+ rm -rf pkg.$*
+
+HERE := $(abspath .)
+$(eval $(call canonicalise,HERE))
+
+package.%:
+ $(MAKE) clean.$*
+ mkdir pkg.$*
+ "$(TEST_HC)" -outputdir pkg.$* --make -v0 -o pkg.$*/setup Setup.hs
+ "$(GHC_PKG)" init pkg.$*/local.package.conf
+ pkg.$*/setup configure --distdir pkg.$*/dist -v0 $(CABAL_PLUGIN_BUILD) --prefix="$(HERE)/pkg.$*/install" --with-compiler="$(TEST_HC)" --with-hc-pkg="$(GHC_PKG)" --package-db=pkg.$*/local.package.conf
+ pkg.$*/setup build --distdir pkg.$*/dist -v0
+ pkg.$*/setup install --distdir pkg.$*/dist -v0
diff --git a/testsuite/tests/plugins/annotation-plugin/SayAnnNames.hs b/testsuite/tests/plugins/annotation-plugin/SayAnnNames.hs
new file mode 100644
index 0000000000..883ba3ada6
--- /dev/null
+++ b/testsuite/tests/plugins/annotation-plugin/SayAnnNames.hs
@@ -0,0 +1,34 @@
+{-# LANGUAGE DeriveDataTypeable #-}
+module SayAnnNames (plugin, SomeAnn(..)) where
+import GhcPlugins
+import Control.Monad (unless)
+import Data.Data
+
+data SomeAnn = SomeAnn deriving (Data, Typeable)
+
+plugin :: Plugin
+plugin = defaultPlugin {
+ installCoreToDos = install
+ }
+
+install :: [CommandLineOption] -> [CoreToDo] -> CoreM [CoreToDo]
+install _ todo = do
+ reinitializeGlobals
+ return (CoreDoPluginPass "Say name" pass : todo)
+
+pass :: ModGuts -> CoreM ModGuts
+pass g = do
+ dflags <- getDynFlags
+ mapM_ (printAnn dflags g) (mg_binds g) >> return g
+ where printAnn :: DynFlags -> ModGuts -> CoreBind -> CoreM CoreBind
+ printAnn dflags guts bndr@(NonRec b _) = do
+ anns <- annotationsOn guts b :: CoreM [SomeAnn]
+ unless (null anns) $ putMsgS $
+ "Annotated binding found: " ++ showSDoc dflags (ppr b)
+ return bndr
+ printAnn _ _ bndr = return bndr
+
+annotationsOn :: Data a => ModGuts -> CoreBndr -> CoreM [a]
+annotationsOn guts bndr = do
+ anns <- getAnnotations deserializeWithData guts
+ return $ lookupWithDefaultUFM anns [] (varUnique bndr)
diff --git a/testsuite/tests/plugins/annotation-plugin/Setup.hs b/testsuite/tests/plugins/annotation-plugin/Setup.hs
new file mode 100644
index 0000000000..9a994af677
--- /dev/null
+++ b/testsuite/tests/plugins/annotation-plugin/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/testsuite/tests/plugins/annotation-plugin/annotation-plugin.cabal b/testsuite/tests/plugins/annotation-plugin/annotation-plugin.cabal
new file mode 100644
index 0000000000..e83c0aa617
--- /dev/null
+++ b/testsuite/tests/plugins/annotation-plugin/annotation-plugin.cabal
@@ -0,0 +1,11 @@
+name: annotation-plugin
+version: 0.1.0.0
+license-file: LICENSE
+build-type: Simple
+cabal-version: >=1.10
+
+library
+ exposed-modules: SayAnnNames
+ other-extensions: DeriveDataTypeable
+ build-depends: base >=4.8 && <4.9, ghc
+ default-language: Haskell2010
diff --git a/testsuite/tests/plugins/plugins07.hs b/testsuite/tests/plugins/plugins07.hs
index 78762a3fd1..ddc2c53322 100644
--- a/testsuite/tests/plugins/plugins07.hs
+++ b/testsuite/tests/plugins/plugins07.hs
@@ -1,9 +1,5 @@
module Main where
-import Plugins07a
-
-import RuleDefiningPlugin
-
{-# NOINLINE x #-}
x = "foo"
diff --git a/testsuite/tests/plugins/plugins07.stdout b/testsuite/tests/plugins/plugins07.stdout
index d27268d74f..810c96eeeb 100644
--- a/testsuite/tests/plugins/plugins07.stdout
+++ b/testsuite/tests/plugins/plugins07.stdout
@@ -1 +1 @@
-SHOWED
+"foo"
diff --git a/testsuite/tests/simplCore/should_compile/T8848.stderr b/testsuite/tests/simplCore/should_compile/T8848.stderr
index 4cb138537b..5bdd0076ce 100644
--- a/testsuite/tests/simplCore/should_compile/T8848.stderr
+++ b/testsuite/tests/simplCore/should_compile/T8848.stderr
@@ -59,18 +59,18 @@ Rule fired: SPEC $c*> @ 'Z
Rule fired: SPEC $fApplicativeShape @ 'Z
Rule fired: SPEC $fApplicativeShape @ 'Z
Rule fired: Class op $p1Applicative
-Rule fired: Class op fmap
+Rule fired: Class op <$
Rule fired: Class op <*>
-Rule fired: SPEC/T8848 liftA2 _ _ _ @ (Shape ('S 'Z))
Rule fired: Class op $p1Applicative
-Rule fired: Class op fmap
+Rule fired: Class op <$
Rule fired: Class op <*>
Rule fired: SPEC $fApplicativeShape @ 'Z
Rule fired: Class op $p1Applicative
-Rule fired: Class op <$
+Rule fired: Class op fmap
Rule fired: Class op <*>
+Rule fired: SPEC/T8848 liftA2 _ _ _ @ (Shape ('S 'Z))
Rule fired: Class op $p1Applicative
-Rule fired: Class op <$
+Rule fired: Class op fmap
Rule fired: Class op <*>
Rule fired: SPEC $fFunctorShape @ 'Z
Rule fired: Class op fmap