diff options
author | Edward Z. Yang <ezyang@cs.stanford.edu> | 2015-06-03 14:33:05 -0700 |
---|---|---|
committer | Edward Z. Yang <ezyang@cs.stanford.edu> | 2015-06-20 15:13:42 -0700 |
commit | 0cb1f5cf26fae946ca745abc5e302e62a8f66feb (patch) | |
tree | 07744de6d51cea9bde926d3ea88c1fda2b138974 | |
parent | 85d539754ac07286ef5fed714ad42451bd5a1d28 (diff) | |
download | haskell-0cb1f5cf26fae946ca745abc5e302e62a8f66feb.tar.gz |
Filter orphan rules based on imports, fixes #10294 and #10420.
Summary:
If we have an orphan rule in our database, don't apply it
unless the defining module is transitively imported by the
module we are processing. We do this by defining a new RuleEnv
data type which includes both the RuleBase as well as the set
of visible orphan modules, and threading this through the
relevant environments (CoreReader, RuleCheckEnv and ScEnv).
This is analogous to the instances fix we applied in #2182
4c834fdddf4d44d12039da4d6a2c63a660975b95, but done for RULES.
An important knock-on effect is that we can remove some buggy
code in LoadInterface which tried to avoid loading interfaces
that were loaded by plugins (which sometimes caused instances
and rules to NEVER become visible).
One note about tests: I renamed the old plugins07 test to T10420
and replaced plugins07 with a test to ensure that a plugin
import did not cause new rules to be loaded in.
Signed-off-by: Edward Z. Yang <ezyang@cs.stanford.edu>
Test Plan: validate
Reviewers: simonpj, austin, goldfire
Subscribers: bgamari, thomie
Differential Revision: https://phabricator.haskell.org/D950
GHC Trac Issues: #10420
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 |