Simon Peyton Jones pushed to branch wip/T26989 at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • compiler/GHC/Core.hs
    ... ... @@ -1968,6 +1968,11 @@ Given this decision it's vital that we do *always* do it.
    1968 1968
       occurrence in f out of scope. This happened in #8892, where the unfolding
    
    1969 1969
       in question was a DFun unfolding.
    
    1970 1970
     
    
    1971
    +Wrinkles
    
    1972
    +
    
    1973
    +(OUR1) For a RULE, say,
    
    1974
    +              forall x y. f (x,y) = x+y
    
    1975
    +ToDO
    
    1971 1976
     
    
    1972 1977
     ************************************************************************
    
    1973 1978
     *                                                                      *
    

  • compiler/GHC/Core/Opt/OccurAnal.hs
    ... ... @@ -27,7 +27,8 @@ core expression with (hopefully) improved usage information.
    27 27
     
    
    28 28
     module GHC.Core.Opt.OccurAnal (
    
    29 29
         occurAnalysePgm,
    
    30
    -    occurAnalyseExpr, occurAnalyseExpr_Prep,
    
    30
    +    occurAnalyseExpr, occurAnalyseBndrsAndExpr,
    
    31
    +    occurAnalyseExpr_Prep,
    
    31 32
         zapLambdaBndrs
    
    32 33
       ) where
    
    33 34
     
    
    ... ... @@ -85,6 +86,14 @@ occurAnalyseExpr expr = expr'
    85 86
       where
    
    86 87
         WUD _ expr' = occAnal initOccEnv expr
    
    87 88
     
    
    89
    +occurAnalyseBndrsAndExpr :: [Var] -> CoreExpr -> ([Var], CoreExpr)
    
    90
    +-- Occur-anal (\bs.e), but taking and returning `bs` and `e` separately
    
    91
    +occurAnalyseBndrsAndExpr bndrs expr
    
    92
    +  = (bndrs', expr')
    
    93
    +  where
    
    94
    +    WUD usage expr' = occAnal initOccEnv expr
    
    95
    +    bndrs' = tagLamBinders usage bndrs
    
    96
    +
    
    88 97
     -- | A version of 'occurAnalyseExpr' suitable for CorePrep.
    
    89 98
     --
    
    90 99
     -- Different from 'occurAnalyseExpr' due to (JCT3)
    

  • compiler/GHC/Core/Opt/Simplify/Iteration.hs
    ... ... @@ -1219,9 +1219,21 @@ simplExprF1 _ (Type ty) cont
    1219 1219
     simplExprF1 env (Var v)        cont = {-#SCC "simplInId" #-} simplInId env v cont
    
    1220 1220
     simplExprF1 env (Lit lit)      cont = {-#SCC "rebuild" #-} rebuild env (Lit lit) cont
    
    1221 1221
     simplExprF1 env (Tick t expr)  cont = {-#SCC "simplTick" #-} simplTick env t expr cont
    
    1222
    -simplExprF1 env (Cast body co) cont = {-#SCC "simplCast" #-} simplCast env body co cont
    
    1223 1222
     simplExprF1 env (Coercion co)  cont = {-#SCC "simplCoercionF" #-} simplCoercionF env co cont
    
    1224 1223
     
    
    1224
    +simplExprF1 env (Cast body co) cont
    
    1225
    +  = do  { co1 <- {-#SCC "simplCast-simplCoercion" #-}
    
    1226
    +                 simplCoercion env co
    
    1227
    +
    
    1228
    +        ; cont1 <- {-#SCC "simplCast-addCoerce" #-}
    
    1229
    +                   if isReflCo co1
    
    1230
    +                   then return cont  -- See Note [Optimising reflexivity]
    
    1231
    +                   else pushCast env co1 cont
    
    1232
    +                        -- True <=> co1 is optimised
    
    1233
    +
    
    1234
    +        ; {-#SCC "simplCast-simplExprF" #-}
    
    1235
    +          simplExprF env body cont1 }
    
    1236
    +
    
    1225 1237
     simplExprF1 env (App fun arg) cont
    
    1226 1238
       = {-#SCC "simplExprF1-App" #-} case arg of
    
    1227 1239
           Type ty -> do { -- The argument type will (almost) certainly be used
    
    ... ... @@ -1567,6 +1579,10 @@ rebuild_go env expr cont
    1567 1579
           Stop {}          -> return (emptyFloats env, expr)
    
    1568 1580
           TickIt t cont    -> rebuild_go env (mkTick t expr) cont
    
    1569 1581
           CastIt { sc_co = co, sc_opt = opt, sc_cont = cont }
    
    1582
    +        | isReflexiveCo co'  -- Worth trying this because casts can
    
    1583
    +                             -- get stacked up by simplCast
    
    1584
    +        -> rebuild_go env expr cont
    
    1585
    +        | otherwise
    
    1570 1586
             -> rebuild_go env (mkCast expr co') cont
    
    1571 1587
                -- NB: mkCast implements the (Coercion co |> g) optimisation
    
    1572 1588
             where
    
    ... ... @@ -1689,9 +1705,8 @@ on each successive composition -- that's at least quadratic. So:
    1689 1705
     * In `addCoerce` (in `simplCast`) if we combine this new coercion with
    
    1690 1706
       an existing once, we build a CastIt for (co1 ; co2) with sc_opt=False.
    
    1691 1707
     
    
    1692
    -* When unpacking a CastIt, in `rebuildCall` and `rebuild`, we optimise
    
    1693
    -  the (presumably composed) coercion if sc_opt=False; this is done
    
    1694
    -  by `optOutCoercion`.
    
    1708
    +* When unpacking a CastIt, in `rebuild`, we optimise the (presumably
    
    1709
    +  composed) coercion if sc_opt=False; this is done by `optOutCoercion`.
    
    1695 1710
     
    
    1696 1711
     * When duplicating a continuation in `mkDupableContWithDmds`, before
    
    1697 1712
       duplicating a CastIt, optimise the coercion. Otherwise we'll end up
    
    ... ... @@ -1708,76 +1723,70 @@ optOutCoercion env co already_optimised
    1708 1723
         empty_subst = mkEmptySubst (seInScope env)
    
    1709 1724
         opts = seOptCoercionOpts env
    
    1710 1725
     
    
    1711
    -simplCast :: SimplEnv -> InExpr -> InCoercion -> SimplCont
    
    1712
    -          -> SimplM (SimplFloats, OutExpr)
    
    1713
    -simplCast env body co0 cont0
    
    1714
    -  = do  { co1   <- {-#SCC "simplCast-simplCoercion" #-} simplCoercion env co0
    
    1715
    -        ; cont1 <- {-#SCC "simplCast-addCoerce" #-}
    
    1716
    -                   if isReflCo co1
    
    1717
    -                   then return cont0  -- See Note [Optimising reflexivity]
    
    1718
    -                   else addCoerce co1 True cont0
    
    1719
    -                        -- True <=> co1 is optimised
    
    1720
    -        ; {-#SCC "simplCast-simplExprF" #-} simplExprF env body cont1 }
    
    1726
    +pushCast :: SimplEnv -> OutCoercion -> SimplCont -> SimplM SimplCont
    
    1727
    +pushCast env co cont
    
    1728
    +  = go co True cont
    
    1721 1729
       where
    
    1730
    +    go :: OutCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1731
    +    go co1 _ (CastIt { sc_co = co2, sc_cont = cont })  -- See Note [Optimising reflexivity]
    
    1732
    +      = go (mkTransCo co1 co2) False cont
    
    1733
    +                  -- False: (mkTransCo co1 co2) is not fully optimised
    
    1734
    +                  -- See Note [Avoid re-simplifying coercions]
    
    1735
    +
    
    1736
    +    go co co_is_opt (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = tail })
    
    1737
    +      | Just (arg_ty', m_co') <- pushCoTyArg co arg_ty
    
    1738
    +      = {-#SCC "addCoerce-pushCoTyArg" #-}
    
    1739
    +        do { tail' <- go_mco m_co' co_is_opt tail
    
    1740
    +           ; return (ApplyToTy { sc_arg_ty  = arg_ty'
    
    1741
    +                               , sc_cont    = tail'
    
    1742
    +                               , sc_hole_ty = coercionLKind co }) }
    
    1743
    +                                    -- NB!  As the cast goes past, the
    
    1744
    +                                    -- type of the hole changes (#16312)
    
    1745
    +
    
    1746
    +    -- (f |> co) e   ===>   (f (e |> co1)) |> co2
    
    1747
    +    -- where   co :: (s1->s2) ~ (t1->t2)
    
    1748
    +    --         co1 :: t1 ~ s1
    
    1749
    +    --         co2 :: s2 ~ t2
    
    1750
    +    go co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
    
    1751
    +                                     , sc_dup = dup, sc_cont = tail
    
    1752
    +                                     , sc_hole_ty = fun_ty })
    
    1753
    +      | not co_is_opt
    
    1754
    +      = -- pushCoValArg duplicates the coercion, so optimise first
    
    1755
    +        go (optOutCoercion (zapSubstEnv env) co co_is_opt) True cont
    
    1756
    +
    
    1757
    +      | Just (m_co1, m_co2) <- pushCoValArg co
    
    1758
    +      = {-#SCC "addCoerce-pushCoValArg" #-}
    
    1759
    +        do { tail' <- go_mco m_co2 co_is_opt tail
    
    1760
    +           ; case m_co1 of {
    
    1761
    +               MRefl -> return (cont { sc_cont = tail'
    
    1762
    +                                     , sc_hole_ty = coercionLKind co }) ;
    
    1763
    +                  -- See Note [Avoiding simplifying repeatedly]
    
    1764
    +
    
    1765
    +               MCo co1 ->
    
    1766
    +        do { (dup', arg_se', arg') <- simplLazyArg env dup fun_ty Nothing arg_se arg
    
    1767
    +                -- When we build the ApplyTo we can't mix the OutCoercion
    
    1768
    +                -- 'co' with the InExpr 'arg', so we simplify
    
    1769
    +                -- to make it all consistent.  It's a bit messy.
    
    1770
    +                -- But it isn't a common case.
    
    1771
    +                -- Example of use: #995
    
    1772
    +           ; return (ApplyToVal { sc_arg  = mkCast arg' co1
    
    1773
    +                                , sc_env  = arg_se'
    
    1774
    +                                , sc_dup  = dup'
    
    1775
    +                                , sc_cont = tail'
    
    1776
    +                                , sc_hole_ty = coercionLKind co }) } } }
    
    1777
    +
    
    1778
    +    go co co_is_opt cont
    
    1779
    +      | isReflCo co = return cont  -- Having this at the end makes a huge
    
    1780
    +                                   -- difference in T12227, for some reason
    
    1781
    +                                   -- See Note [Optimising reflexivity]
    
    1782
    +      | otherwise = return (CastIt { sc_co = co, sc_opt = co_is_opt, sc_cont = cont })
    
    1783
    +
    
    1722 1784
     
    
    1723 1785
             -- If the first parameter is MRefl, then simplifying revealed a
    
    1724 1786
             -- reflexive coercion. Omit.
    
    1725
    -        addCoerceM :: MOutCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1726
    -        addCoerceM MRefl    _   cont = return cont
    
    1727
    -        addCoerceM (MCo co) opt cont = addCoerce co opt cont
    
    1728
    -
    
    1729
    -        addCoerce :: OutCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1730
    -        addCoerce co1 _ (CastIt { sc_co = co2, sc_cont = cont })  -- See Note [Optimising reflexivity]
    
    1731
    -          = addCoerce (mkTransCo co1 co2) False cont
    
    1732
    -                      -- False: (mkTransCo co1 co2) is not fully optimised
    
    1733
    -                      -- See Note [Avoid re-simplifying coercions]
    
    1734
    -
    
    1735
    -        addCoerce co co_is_opt (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = tail })
    
    1736
    -          | Just (arg_ty', m_co') <- pushCoTyArg co arg_ty
    
    1737
    -          = {-#SCC "addCoerce-pushCoTyArg" #-}
    
    1738
    -            do { tail' <- addCoerceM m_co' co_is_opt tail
    
    1739
    -               ; return (ApplyToTy { sc_arg_ty  = arg_ty'
    
    1740
    -                                   , sc_cont    = tail'
    
    1741
    -                                   , sc_hole_ty = coercionLKind co }) }
    
    1742
    -                                        -- NB!  As the cast goes past, the
    
    1743
    -                                        -- type of the hole changes (#16312)
    
    1744
    -
    
    1745
    -        -- (f |> co) e   ===>   (f (e |> co1)) |> co2
    
    1746
    -        -- where   co :: (s1->s2) ~ (t1->t2)
    
    1747
    -        --         co1 :: t1 ~ s1
    
    1748
    -        --         co2 :: s2 ~ t2
    
    1749
    -        addCoerce co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
    
    1750
    -                                                , sc_dup = dup, sc_cont = tail
    
    1751
    -                                                , sc_hole_ty = fun_ty })
    
    1752
    -          | not co_is_opt  -- pushCoValArg duplicates the coercion, so optimise first
    
    1753
    -          = addCoerce (optOutCoercion (zapSubstEnv env) co co_is_opt) True cont
    
    1754
    -
    
    1755
    -          | Just (m_co1, m_co2) <- pushCoValArg co
    
    1756
    -          = {-#SCC "addCoerce-pushCoValArg" #-}
    
    1757
    -            do { tail' <- addCoerceM m_co2 co_is_opt tail
    
    1758
    -               ; case m_co1 of {
    
    1759
    -                   MRefl -> return (cont { sc_cont = tail'
    
    1760
    -                                         , sc_hole_ty = coercionLKind co }) ;
    
    1761
    -                      -- See Note [Avoiding simplifying repeatedly]
    
    1762
    -
    
    1763
    -                   MCo co1 ->
    
    1764
    -            do { (dup', arg_se', arg') <- simplLazyArg env dup fun_ty Nothing arg_se arg
    
    1765
    -                    -- When we build the ApplyTo we can't mix the OutCoercion
    
    1766
    -                    -- 'co' with the InExpr 'arg', so we simplify
    
    1767
    -                    -- to make it all consistent.  It's a bit messy.
    
    1768
    -                    -- But it isn't a common case.
    
    1769
    -                    -- Example of use: #995
    
    1770
    -               ; return (ApplyToVal { sc_arg  = mkCast arg' co1
    
    1771
    -                                    , sc_env  = arg_se'
    
    1772
    -                                    , sc_dup  = dup'
    
    1773
    -                                    , sc_cont = tail'
    
    1774
    -                                    , sc_hole_ty = coercionLKind co }) } } }
    
    1775
    -
    
    1776
    -        addCoerce co co_is_opt cont
    
    1777
    -          | isReflCo co = return cont  -- Having this at the end makes a huge
    
    1778
    -                                       -- difference in T12227, for some reason
    
    1779
    -                                       -- See Note [Optimising reflexivity]
    
    1780
    -          | otherwise = return (CastIt { sc_co = co, sc_opt = co_is_opt, sc_cont = cont })
    
    1787
    +    go_mco :: MOutCoercion -> Bool -> SimplCont -> SimplM SimplCont
    
    1788
    +    go_mco MRefl    _   cont = return cont
    
    1789
    +    go_mco (MCo co) opt cont = go co opt cont
    
    1781 1790
     
    
    1782 1791
     simplLazyArg :: SimplEnvIS              -- ^ Used only for its InScopeSet
    
    1783 1792
                  -> DupFlag
    
    ... ... @@ -2293,14 +2302,21 @@ simplInId env var cont
    2293 2302
     ---------------------------------------------------------
    
    2294 2303
     simplOutExpr :: SimplEnvIS -> OutExpr -> SimplCont -> SimplM (SimplFloats, OutExpr)
    
    2295 2304
     simplOutExpr env expr cont
    
    2296
    -  = case fun of
    
    2297
    -      Var v                    -> simplOutId env v cont'
    
    2298
    -      Lam {} | not (null args) -> simplLam env occ_fun cont'  -- We have a beta-redex
    
    2299
    -      _                        -> rebuild_go env expr cont
    
    2300
    -  where
    
    2301
    -    (fun, args) = collectArgs expr
    
    2302
    -    cont' = pushArgs env Simplified (exprType fun) args cont
    
    2303
    -    occ_fun = occurAnalyseExpr fun  -- ToDo:explain; c.f. Note [Occurrence-analyse after rule firing]
    
    2305
    +  | Lam {} <- expr
    
    2306
    +  , hasArgs cont
    
    2307
    +  = simplLam env (occurAnalyseExpr expr) cont
    
    2308
    +    -- ToDo:explain; c.f. Note [Occurrence-analyse after rule firing]
    
    2309
    +
    
    2310
    +  | Cast e co <- expr  -- The inlined expression may be (x |> co)
    
    2311
    +                       -- and the cast may cancel with `cont`
    
    2312
    +  = do { cont' <- pushCast env co cont
    
    2313
    +       ; simplOutExpr env e cont' }
    
    2314
    +
    
    2315
    +  | (Var v, args) <- collectArgs expr
    
    2316
    +  = simplOutId env v (pushArgs env (idType v) args cont)
    
    2317
    +
    
    2318
    +  | otherwise
    
    2319
    +  = rebuild_go env expr cont
    
    2304 2320
     
    
    2305 2321
     ---------------------------------------------------------
    
    2306 2322
     simplOutId :: SimplEnvIS -> OutId -> SimplCont -> SimplM (SimplFloats, OutExpr)
    
    ... ... @@ -2654,7 +2670,7 @@ fireRuleAFTER env rule_match arg_specs cont
    2654 2670
            , rm_binds = wrap, rm_bndrs = bndrs } <- rule_match
    
    2655 2671
       = do { let env' = env `addNewInScopeIds` bndrs
    
    2656 2672
            ; (floats, e') <- simplExprF env' rhs $
    
    2657
    -                         pushArgs env' Simplified (exprType rhs) rhs_args $
    
    2673
    +                         pushArgs env' (exprType rhs) rhs_args $
    
    2658 2674
                              pushArgSpecs env' (drop (ruleArity rule) arg_specs) cont
    
    2659 2675
            ; return $
    
    2660 2676
              if isEmptyBindWrapper wrap  -- Not very pretty
    

  • compiler/GHC/Core/Opt/Simplify/Utils.hs
    ... ... @@ -25,7 +25,7 @@ module GHC.Core.Opt.Simplify.Utils (
    25 25
             isSimplified, contIsStop,
    
    26 26
             contIsDupable, contResultType, contHoleType, contHoleScaling,
    
    27 27
             contIsTrivial, contArgs, contIsRhs,
    
    28
    -        countArgs, contOutArgs, dropContArgs,
    
    28
    +        hasArgs, countArgs, contOutArgs, dropContArgs,
    
    29 29
             mkBoringStop, mkRhsStop, mkLazyArgStop,
    
    30 30
             interestingCallContext,
    
    31 31
     
    
    ... ... @@ -384,17 +384,17 @@ isStrictArgInfo (ArgInfo { ai_dmds = dmds })
    384 384
       | dmd:_ <- dmds = isStrUsedDmd dmd
    
    385 385
       | otherwise     = False
    
    386 386
     
    
    387
    -pushArgs :: SimplEnvIS -> DupFlag -> Type -> [OutExpr] -> SimplCont -> SimplCont
    
    388
    -pushArgs _env _dup _fun_ty [] cont
    
    387
    +pushArgs :: SimplEnvIS -> Type -> [OutExpr] -> SimplCont -> SimplCont
    
    388
    +pushArgs _env _fun_ty [] cont
    
    389 389
       = cont
    
    390
    -pushArgs env dup fun_ty (arg:args) cont
    
    390
    +pushArgs env fun_ty (arg:args) cont
    
    391 391
       | Type ty <- arg
    
    392 392
       = ApplyToTy { sc_hole_ty = fun_ty, sc_arg_ty = ty
    
    393
    -              , sc_cont = pushArgs env dup (piResultTy fun_ty ty) args cont }
    
    393
    +              , sc_cont = pushArgs env (piResultTy fun_ty ty) args cont }
    
    394 394
       | otherwise
    
    395
    -  = ApplyToVal { sc_dup = dup, sc_hole_ty = fun_ty
    
    395
    +  = ApplyToVal { sc_dup = Simplified, sc_hole_ty = fun_ty
    
    396 396
                    , sc_arg = arg, sc_env = env
    
    397
    -               , sc_cont = pushArgs env dup (funResultTy fun_ty) args  cont}
    
    397
    +               , sc_cont = pushArgs env (funResultTy fun_ty) args  cont}
    
    398 398
     
    
    399 399
     pushArgSpecs :: SimplEnvIS  -- Barely needed, since sc_dup = Simplified
    
    400 400
                  -> [ArgSpec]   -- In normal, forward order
    
    ... ... @@ -522,6 +522,12 @@ contHoleScaling (ApplyToVal { sc_cont = k }) = contHoleScaling k
    522 522
     contHoleScaling (TickIt _ k) = contHoleScaling k
    
    523 523
     
    
    524 524
     -------------------
    
    525
    +hasArgs :: SimplCont -> Bool
    
    526
    +-- True <=> some leading arguments
    
    527
    +hasArgs (ApplyToTy {})  = True
    
    528
    +hasArgs (ApplyToVal {}) = True
    
    529
    +hasArgs _               = False
    
    530
    +
    
    525 531
     countArgs :: SimplCont -> Int
    
    526 532
     -- Count all arguments, including types, coercions,
    
    527 533
     -- and other values; skipping over casts.
    

  • compiler/GHC/Core/Rules.hs
    ... ... @@ -65,7 +65,7 @@ import GHC.Core.Tidy ( tidyRules )
    65 65
     import GHC.Core.Map.Expr ( eqCoreExpr )
    
    66 66
     import GHC.Core.Opt.Arity( etaExpandToJoinPointRule )
    
    67 67
     import GHC.Core.Make     ( mkCoreLams )
    
    68
    -import GHC.Core.Opt.OccurAnal( occurAnalyseExpr )
    
    68
    +import GHC.Core.Opt.OccurAnal( occurAnalyseBndrsAndExpr )
    
    69 69
     import GHC.Core.Rules.Config (roBuiltinRules)
    
    70 70
     
    
    71 71
     import GHC.Tc.Utils.TcType  ( tcSplitTyConApp_maybe )
    
    ... ... @@ -200,16 +200,18 @@ mkRule this_mod is_auto is_local name act fn bndrs args rhs
    200 200
       = Rule { ru_name   = name
    
    201 201
              , ru_act    = act
    
    202 202
              , ru_fn     = fn
    
    203
    -         , ru_bndrs  = bndrs
    
    203
    +         , ru_bndrs  = bndrs'
    
    204 204
              , ru_args   = args
    
    205
    -         , ru_rhs    = occurAnalyseExpr rhs
    
    206
    -                       -- See Note [OccInfo in unfoldings and rules]
    
    205
    +         , ru_rhs    = rhs'
    
    207 206
              , ru_rough  = roughTopNames args
    
    208 207
              , ru_origin = this_mod
    
    209 208
              , ru_orphan = orph
    
    210 209
              , ru_auto   = is_auto
    
    211 210
              , ru_local  = is_local }
    
    212 211
       where
    
    212
    +    (bndrs', rhs') = occurAnalyseBndrsAndExpr bndrs rhs
    
    213
    +        -- See Note [OccInfo in unfoldings and rules]
    
    214
    +
    
    213 215
             -- Compute orphanhood.  See Note [Orphans] in GHC.Core.InstEnv
    
    214 216
             -- A rule is an orphan only if none of the variables
    
    215 217
             -- mentioned on its left-hand side are locally defined
    

  • compiler/GHC/IfaceToCore.hs
    ... ... @@ -76,7 +76,7 @@ import GHC.Core.Predicate( isUnaryClass )
    76 76
     import GHC.Core.TyCon
    
    77 77
     import GHC.Core.ConLike
    
    78 78
     import GHC.Core.DataCon
    
    79
    -import GHC.Core.Opt.OccurAnal ( occurAnalyseExpr )
    
    79
    +import GHC.Core.Opt.OccurAnal ( occurAnalyseBndrsAndExpr )
    
    80 80
     import GHC.Core.Ppr
    
    81 81
     
    
    82 82
     import GHC.Hs.Extension ( GhcRn )
    
    ... ... @@ -1418,18 +1418,22 @@ tcIfaceRule (IfaceRule {ifRuleName = name, ifActivation = act, ifRuleBndrs = bnd
    1418 1418
                                                    (emptyBag, errs) }
    
    1419 1419
                        ; return (bndrs', args', rhs') }
    
    1420 1420
             ; let mb_tcs = map ifTopFreeName args
    
    1421
    +              (bndrs_occ, rhs_occ) = occurAnalyseBndrsAndExpr bndrs' rhs'
    
    1422
    +                   -- See Note [OccInfo in unfoldings and rules]
    
    1421 1423
             ; this_mod <- getIfModule
    
    1422
    -        ; return (Rule { ru_name = name, ru_fn = fn,
    
    1423
    -                          ru_act = act,
    
    1424
    -                          ru_bndrs = bndrs', ru_args = args',
    
    1425
    -                          ru_rhs = occurAnalyseExpr rhs',
    
    1426
    -                          ru_rough = mb_tcs,
    
    1427
    -                          ru_origin = this_mod,
    
    1428
    -                          ru_orphan = orph,
    
    1429
    -                          ru_auto = auto,
    
    1430
    -                          ru_local = False }) } -- An imported RULE is never for a local Id
    
    1431
    -                                                -- or, even if it is (module loop, perhaps)
    
    1432
    -                                                -- we'll just leave it in the non-local set
    
    1424
    +        ; return (Rule { ru_name   = name
    
    1425
    +                       , ru_fn     = fn
    
    1426
    +                       , ru_act    = act
    
    1427
    +                       , ru_bndrs  = bndrs_occ
    
    1428
    +                       , ru_args   = args'
    
    1429
    +                       , ru_rhs    = rhs_occ
    
    1430
    +                       , ru_rough  = mb_tcs
    
    1431
    +                       , ru_origin = this_mod
    
    1432
    +                       , ru_orphan = orph
    
    1433
    +                       , ru_auto   = auto
    
    1434
    +                       , ru_local  = False }) }
    
    1435
    +              -- ru_local=False: an imported RULE is never for a local Id or, even if
    
    1436
    +              -- it is (module loop, perhaps) we'll just leave it in the non-local set
    
    1433 1437
       where
    
    1434 1438
             -- This function *must* mirror exactly what Rules.roughTopNames does
    
    1435 1439
             -- We could have stored the ru_rough field in the iface file