Add new VarEnv functions minusVarEnv, intersectsVarEnv, unionInScope
[ghc-hetmet.git] / compiler / basicTypes / Id.lhs
index fbf6b4a..3640693 100644 (file)
@@ -30,7 +30,7 @@ module Id (
        mkLocalId, mkLocalIdWithInfo, mkExportedLocalId,
        mkSysLocal, mkSysLocalM, mkUserLocal, mkUserLocalM,
        mkTemplateLocals, mkTemplateLocalsNum, mkTemplateLocal,
-       mkWorkerId, 
+       mkWorkerId, mkWiredInIdName,
 
        -- ** Taking an Id apart
        idName, idType, idUnique, idInfo, idDetails,
@@ -258,6 +258,9 @@ mkUserLocal occ uniq ty loc = mkLocalId (mkInternalName uniq occ loc) ty
 mkUserLocalM :: MonadUnique m => OccName -> Type -> SrcSpan -> m Id
 mkUserLocalM occ ty loc = getUniqueM >>= (\uniq -> return (mkUserLocal occ uniq ty loc))
 
+mkWiredInIdName :: Module -> FastString -> Unique -> Id -> Name
+mkWiredInIdName mod fs uniq id
+ = mkWiredInName mod (mkOccNameFS varName fs) uniq (AnId id) UserSyntax
 \end{code}
 
 Make some local @Ids@ for a template @CoreExpr@.  These have bogus
@@ -651,29 +654,44 @@ zapFragileIdInfo = zapInfo zapFragileInfo
 
 Note [transferPolyIdInfo]
 ~~~~~~~~~~~~~~~~~~~~~~~~~
-Suppose we have
+This transfer is used in two places: 
+       FloatOut (long-distance let-floating)
+       SimplUtils.abstractFloats (short-distance let-floating)
+
+Consider the short-distance let-floating:
 
    f = /\a. let g = rhs in ...
 
-where g has interesting strictness information.  Then if we float thus
+Then if we float thus
 
    g' = /\a. rhs
-   f = /\a. ...[g' a/g]
+   f = /\a. ...[g' a/g]....
 
 we *do not* want to lose g's
   * strictness information
   * arity 
   * inline pragma (though that is bit more debatable)
+  * occurrence info
+
+Mostly this is just an optimisation, but it's *vital* to
+transfer the occurrence info.  Consider
+   
+   NonRec { f = /\a. let Rec { g* = ..g.. } in ... }
+
+where the '*' means 'LoopBreaker'.  Then if we float we must get
 
-It's simple to retain strictness and arity, but not so simple to retain
+   Rec { g'* = /\a. ...(g' a)... }
+   NonRec { f = /\a. ...[g' a/g]....}
+
+where g' is also marked as LoopBreaker.  If not, terrible things
+can happen if we re-simplify the binding (and the Simplifier does
+sometimes simplify a term twice); see Trac #4345.
+
+It's not so simple to retain
   * worker info
   * rules
 so we simply discard those.  Sooner or later this may bite us.
 
-This transfer is used in two places: 
-       FloatOut (long-distance let-floating)
-       SimplUtils.abstractFloats (short-distance let-floating)
-
 If we abstract wrt one or more *value* binders, we must modify the 
 arity and strictness info before transferring it.  E.g. 
       f = \x. e
@@ -696,6 +714,7 @@ transferPolyIdInfo old_id abstract_wrt new_id
     old_info       = idInfo old_id
     old_arity       = arityInfo old_info
     old_inline_prag = inlinePragInfo old_info
+    old_occ_info    = occInfo old_info
     new_arity       = old_arity + arity_increase
     old_strictness  = strictnessInfo old_info
     new_strictness  = fmap (increaseStrictSigArity arity_increase) old_strictness
@@ -703,4 +722,5 @@ transferPolyIdInfo old_id abstract_wrt new_id
     transfer new_info = new_info `setStrictnessInfo` new_strictness
                                 `setArityInfo` new_arity
                                 `setInlinePragInfo` old_inline_prag
+                                `setOccInfo` old_occ_info
 \end{code}