Fix scoped type variables for expression type signatures
[ghc-hetmet.git] / compiler / simplCore / SimplEnv.lhs
index 00f035e..960475c 100644 (file)
@@ -7,6 +7,7 @@
 module SimplEnv (
        InId, InBind, InExpr, InAlt, InArg, InType, InBinder,
        OutId, OutTyVar, OutBind, OutExpr, OutAlt, OutArg, OutType, OutBinder,
+        InCoercion, OutCoercion,
 
        -- The simplifier mode
        setMode, getMode, 
@@ -21,7 +22,7 @@ module SimplEnv (
        SimplEnv, mkSimplEnv, extendIdSubst, extendTvSubst, 
        zapSubstEnv, setSubstEnv, 
        getInScope, setInScope, setInScopeSet, modifyInScope, addNewInScopeIds,
-       getRules, refineSimplEnv,
+       getRules, 
 
        SimplSR(..), mkContEx, substId, 
 
@@ -41,12 +42,11 @@ module SimplEnv (
 import SimplMonad      
 import Id              ( Id, idType, idOccInfo, idUnfolding, setIdUnfolding )
 import IdInfo          ( IdInfo, vanillaIdInfo, occInfo, setOccInfo, specInfo, setSpecInfo,
-                         arityInfo, setArityInfo, workerInfo, setWorkerInfo, 
+                         arityInfo, workerInfo, setWorkerInfo, 
                          unfoldingInfo, setUnfoldingInfo, isEmptySpecInfo,
-                         unknownArity, workerExists
+                         workerExists
                            )
 import CoreSyn
-import Unify           ( TypeRefinement )
 import Rules           ( RuleBase )
 import CoreUtils       ( needsCaseBinding )
 import CostCentre      ( CostCentreStack, subsumedCCS )
@@ -58,8 +58,9 @@ import OrdList
 import qualified CoreSubst     ( Subst, mkSubst, substExpr, substSpec, substWorker )
 import qualified Type          ( substTy, substTyVarBndr )
 
-import Type             ( Type, TvSubst(..), TvSubstEnv, composeTvSubst,
+import Type             ( Type, TvSubst(..), TvSubstEnv,
                          isUnLiftedType, seqType, tyVarsOfType )
+import Coercion         ( Coercion )
 import BasicTypes      ( OccInfo(..), isFragileOcc )
 import DynFlags                ( SimplifierMode(..) )
 import Util            ( mapAccumL )
@@ -73,22 +74,24 @@ import Outputable
 %************************************************************************
 
 \begin{code}
-type InBinder  = CoreBndr
-type InId      = Id                    -- Not yet cloned
-type InType    = Type                  -- Ditto
-type InBind    = CoreBind
-type InExpr    = CoreExpr
-type InAlt     = CoreAlt
-type InArg     = CoreArg
-
-type OutBinder  = CoreBndr
-type OutId     = Id                    -- Cloned
-type OutTyVar  = TyVar                 -- Cloned
-type OutType   = Type                  -- Cloned
-type OutBind   = CoreBind
-type OutExpr   = CoreExpr
-type OutAlt    = CoreAlt
-type OutArg    = CoreArg
+type InBinder   = CoreBndr
+type InId       = Id                   -- Not yet cloned
+type InType     = Type                 -- Ditto
+type InBind     = CoreBind
+type InExpr     = CoreExpr
+type InAlt      = CoreAlt
+type InArg      = CoreArg
+type InCoercion = Coercion
+
+type OutBinder   = CoreBndr
+type OutId      = Id                   -- Cloned
+type OutTyVar   = TyVar                -- Cloned
+type OutType    = Type                 -- Cloned
+type OutCoercion = Coercion
+type OutBind    = CoreBind
+type OutExpr    = CoreExpr
+type OutAlt     = CoreAlt
+type OutArg     = CoreArg
 \end{code}
 
 %************************************************************************
@@ -197,38 +200,6 @@ seIdSubst:
   That's why the "set" is actually a VarEnv Var
 
 
-Note [GADT type refinement]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-When we come to a GADT pattern match that refines the in-scope types, we
-  a) Refine the types of the Ids in the in-scope set, seInScope.  
-     For exmaple, consider
-       data T a where
-               Foo :: T (Bool -> Bool)
-
-       (\ (x::T a) (y::a) -> case x of { Foo -> y True }
-
-     Technically this is well-typed, but exprType will barf on the
-     (y True) unless we refine the type on y's occurrence.
-
-  b) Refine the range of the type substitution, seTvSubst. 
-     Very similar reason to (a).
-
-  NB: we don't refine the range of the SimplIdSubst, because it's always
-  interpreted relative to the seInScope (see substId)
-
-For (b) we need to be a little careful.  Specifically, we compose the refinement 
-with the type substitution.  Suppose 
-  The substitution was   [a->b, b->a]
-  and the refinement was  [b->Int]
-  Then we want [a->Int, b->a]
-
-But also if
-  The substitution was   [a->b]
-  and the refinement was  [b->Int]
-  Then we want [a->Int, b->Int]
-       becuase b might be both an InTyVar and OutTyVar
-
-
 \begin{code}
 mkSimplEnv :: SimplifierMode -> SwitchChecker -> RuleBase -> SimplEnv
 mkSimplEnv mode switches rules
@@ -309,31 +280,6 @@ getRules :: SimplEnv -> RuleBase
 getRules = seExtRules
 \end{code}
 
-               GADT stuff
-
-Given an idempotent substitution, generated by the unifier, use it to 
-refine the environment
-
-\begin{code}
-refineSimplEnv :: SimplEnv -> TypeRefinement -> SimplEnv
--- The TvSubstEnv is the refinement, and it refines OutTyVars into OutTypes
-refineSimplEnv env@(SimplEnv { seTvSubst = tv_subst, seInScope = in_scope })
-              (refine_tv_subst, all_bound_here)
-  = env { seTvSubst = composeTvSubst in_scope refine_tv_subst tv_subst,
-         seInScope = in_scope' }
-  where
-    in_scope' 
-       | all_bound_here = in_scope
-               -- The tvs are the tyvars bound here.  If only they 
-               -- are refined, there's no need to do anything 
-       | otherwise = mapInScopeSet refine_id in_scope
-
-    refine_id v        -- Only refine its type; any rules will get
-                       -- refined if they are used (I hope)
-       | isId v    = setIdType v (Type.substTy refine_subst (idType v))
-       | otherwise = v
-    refine_subst = TvSubst in_scope refine_tv_subst
-\end{code}
 
 %************************************************************************
 %*                                                                     *
@@ -362,8 +308,7 @@ substId (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
   where
        -- Get the most up-to-date thing from the in-scope set
        -- Even though it isn't in the substitution, it may be in
-       -- the in-scope set with a different type (we only use the
-       -- substitution if the unique changes).
+       -- the in-scope set better IdInfo
     refine v = case lookupInScope in_scope v of
                 Just v' -> v'
                 Nothing -> WARN( True, ppr v ) v       -- This is an error!
@@ -442,7 +387,7 @@ substIdBndr env@(SimplEnv { seInScope = in_scope, seIdSubst = id_subst})
 
        -- new_id has the final IdInfo
     subst  = mkCoreSubst env
-    new_id = maybeModifyIdInfo (substIdInfo subst) id2
+    new_id = maybeModifyIdInfo (substIdInfo subst (idInfo old_id)) id2
 
        -- Extend the substitution if the unique has changed
        -- See the notes with substTyVarBndr for the delSubstEnv
@@ -535,19 +480,34 @@ This is important.  Manuel found cases where he really, really
 wanted a RULE for a recursive function to apply in that function's
 own right-hand side.
 
-NB 2: We do not transfer the arity (see Subst.substIdInfo)
-The arity of an Id should not be visible
-in its own RHS, else we eta-reduce
+NB 2: ARITY.  We *do* transfer the arity.  This is important, so that
+the arity of an Id is visible in its own RHS.  For example:
+       f = \x. ....g (\y. f y)....
+We can eta-reduce the arg to g, becuase f is a value.  But that 
+needs to be visible.  
+
+This interacts with the 'state hack' too:
+       f :: Bool -> IO Int
+       f = \x. case x of 
+                 True  -> f y
+                 False -> \s -> ...
+Can we eta-expand f?  Only if we see that f has arity 1, and then we 
+take advantage of the 'state hack' on the result of
+(f y) :: State# -> (State#, Int) to expand the arity one more.
+
+There is a disadvantage though.  Making the arity visible in the RHA
+allows us to eta-reduce
        f = \x -> f x
 to
        f = f
-which isn't sound.  And it makes the arity in f's IdInfo greater than
-the manifest arity, which isn't good.
-The arity will get added later.
+which technically is not sound.   This is very much a corner case, so
+I'm not worried about it.  Another idea is to ensure that f's arity 
+never decreases; its arity started as 1, and we should never eta-reduce
+below that.
 
-NB 3: It's important that we *do* transer the loop-breaker OccInfo,
-because that's what stops the Id getting inlined infinitely, in the body
-of the letrec.
+NB 3: OccInfo.  It's important that we *do* transer the loop-breaker
+OccInfo, because that's what stops the Id getting inlined infinitely,
+in the body of the letrec.
 
 NB 4: does no harm for non-recursive bindings
 
@@ -562,7 +522,7 @@ when substituting in h's RULE.
 \begin{code}
 addLetIdInfo :: SimplEnv -> InBinder -> OutBinder -> (SimplEnv, OutBinder)
 addLetIdInfo env in_id out_id
-  = (modifyInScope env out_id out_id, final_id)
+  = (modifyInScope env out_id final_id, final_id)
   where
     final_id = out_id `setIdInfo` new_info
     subst = mkCoreSubst env
@@ -577,7 +537,7 @@ substIdInfo :: CoreSubst.Subst -> IdInfo -> Maybe IdInfo
 --     worker info
 -- Zap the unfolding 
 -- Keep only 'robust' OccInfo
--- Zap Arity
+--          arity
 -- 
 -- Seq'ing on the returned IdInfo is enough to cause all the 
 -- substitutions to happen completely
@@ -585,21 +545,18 @@ substIdInfo :: CoreSubst.Subst -> IdInfo -> Maybe IdInfo
 substIdInfo subst info
   | nothing_to_do = Nothing
   | otherwise     = Just (info `setOccInfo`              (if keep_occ then old_occ else NoOccInfo)
-                              `setArityInfo`     (if keep_arity then old_arity else unknownArity)
                               `setSpecInfo`      CoreSubst.substSpec   subst old_rules
                               `setWorkerInfo`    CoreSubst.substWorker subst old_wrkr
                               `setUnfoldingInfo` noUnfolding)
                        -- setSpecInfo does a seq
                        -- setWorkerInfo does a seq
   where
-    nothing_to_do = keep_occ && keep_arity &&
+    nothing_to_do = keep_occ && 
                    isEmptySpecInfo old_rules &&
                    not (workerExists old_wrkr) &&
                    not (hasUnfolding (unfoldingInfo info))
     
-    keep_occ   = not (isFragileOcc old_occ)
-    keep_arity = old_arity == unknownArity
-    old_arity = arityInfo info
+    keep_occ  = not (isFragileOcc old_occ)
     old_occ   = occInfo info
     old_rules = specInfo info
     old_wrkr  = workerInfo info