addIdSpecialisations,
-- * Misc. CoreRule helpers
- rulesOfBinds, getRules, pprRulesForUser,
+ rulesOfBinds, getRules, pprRulesForUser, expandId,
- lookupRule, mkLocalRule, roughTopNames
+ lookupRule, mkRule, mkLocalRule, roughTopNames
) where
#include "HsVersions.h"
-> Name -> [CoreBndr] -> [CoreExpr] -> CoreExpr -> CoreRule
-- ^ Used to make 'CoreRule' for an 'Id' defined in the module being
-- compiled. See also 'CoreSyn.CoreRule'
-mkLocalRule name act fn bndrs args rhs
+mkLocalRule = mkRule True
+
+mkRule :: 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_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 = rhs, ru_rough = roughTopNames args,
- ru_local = True }
+ ru_rhs = occurAnalyseExpr rhs,
+ ru_rough = roughTopNames args,
+ ru_local = is_local }
--------------
roughTopNames :: [CoreExpr] -> [Maybe Name]
rulesOfBinds binds = concatMap (concatMap idCoreRules . bindersOf) binds
getRules :: RuleBase -> Id -> [CoreRule]
- -- The rules for an Id come from two places:
- -- (a) the ones it is born with (idCoreRules fn)
- -- (b) rules added in subsequent modules (extra_rules)
- -- PrimOps, for example, are born with a bunch of rules under (a)
+-- See Note [Where rules are found]
getRules rule_base fn
- | isLocalId fn = idCoreRules fn
- | otherwise = WARN( not (isPrimOpId fn) && notNull (idCoreRules fn),
- ppr fn <+> ppr (idCoreRules fn) )
- idCoreRules fn ++ (lookupNameEnv rule_base (idName fn) `orElse` [])
- -- Only PrimOpIds have rules inside themselves, and perhaps more besides
+ = idCoreRules fn ++ imp_rules
+ where
+ imp_rules = lookupNameEnv rule_base (idName fn) `orElse` []
\end{code}
+Note [Where rules are found]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The rules for an Id come from two places:
+ (a) the ones it is born with, stored inside the Id iself (idCoreRules fn),
+ (b) rules added in other modules, stored in the global RuleBase (imp_rules)
+
+It's tempting to think that
+ - LocalIds have only (a)
+ - non-LocalIds have only (b)
+
+but that isn't quite right:
+
+ - PrimOps and ClassOps are born with a bunch of rules inside the Id,
+ even when they are imported
+
+ - The rules in PrelRules.builtinRules should be active even
+ in the module defining the Id (when it's a LocalId), but
+ the rules are kept in the global RuleBase
+
%************************************************************************
%* *
matchRule _is_active _in_scope args _rough_args
(BuiltinRule { ru_try = match_fn })
+-- Built-in rules can't be switched off, it seems
= case match_fn args of
Just expr -> Just expr
Nothing -> Nothing
| Just subst <- match_var menv subst v1 e2
= Just subst
-match menv subst e1 (Note _ e2)
- = match menv subst e1 e2
- -- See Note [Notes in RULE matching]
+match menv subst (Note _ e1) e2 = match menv subst e1 e2
+match menv subst e1 (Note _ e2) = match menv subst e1 e2
+ -- Ignore notes in both template and thing to be matched
+ -- See Note [Notes in RULE matching]
match menv subst e1 (Var v2) -- Note [Expanding variables]
| not (locallyBoundR rn_env v2) -- Note [Do not expand locally-bound variables]
; match menv subst1 e1 e2 }
-- Everything else fails
-match _ _ _e1 _e2 = -- pprTrace "Failing at" ((text "e1:" <+> ppr e1) $$ (text "e2:" <+> ppr e2)) $
+match _ _ _e1 _e2 = -- pprTrace "Failing at" ((text "e1:" <+> ppr _e1) $$ (text "e2:" <+> ppr _e2)) $
Nothing
------------------------------------------
Note [Notes in RULE matching]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Look through Notes. In particular, we don't want to
-be confused by InlineMe notes. Maybe we should be more
-careful about profiling notes, but for now I'm just
-riding roughshod over them.
-See Note [Notes in call patterns] in SpecConstr
+Look through Notes in both template and expression being matched. In
+particular, we don't want to be confused by InlineMe notes. Maybe we
+should be more careful about profiling notes, but for now I'm just
+riding roughshod over them. cf Note [Notes in call patterns] in
+SpecConstr
Note [Matching lets]
~~~~~~~~~~~~~~~~~~~~