[project @ 2000-08-01 09:08:25 by simonpj]
authorsimonpj <unknown>
Tue, 1 Aug 2000 09:08:30 +0000 (09:08 +0000)
committersimonpj <unknown>
Tue, 1 Aug 2000 09:08:30 +0000 (09:08 +0000)
Simon's Marktoberdorf Commits

1.  Tidy up the renaming story for "system binders", such as
dictionary functions, default methods, constructor workers etc.  These
are now documented in HsDecls.  The main effect of the change, apart
from tidying up, is to make the *type-checker* (instead of the
renamer) generate names for dict-funs and default-methods.  This is
good because Sergei's generic-class stuff generates new classes at
typecheck time.

2.  Fix the CSE pass so it does not require the no-shadowing invariant.
Keith discovered that the simplifier occasionally returns a result
with shadowing.  After much fiddling around (which has improved the
code in the simplifier a bit) I found that it is nearly impossible to
arrange that it really does do no-shadowing.  So I gave up and fixed
the CSE pass (which is the only one to rely on it) instead.

3. Fix a performance bug in the simplifier.  The change is in
SimplUtils.interestingArg.  It computes whether an argment should
be considered "interesting"; if a function is applied to an interesting
argument, we are more likely to inline that function.
Consider this case
let x = 3 in f x
The 'x' argument was considered "uninteresting" for a silly reason.
Since x only occurs once, it was unconditionally substituted, but
interestingArg didn't take account of that case.  Now it does.

I also made interestingArg a bit more liberal.  Let's see if we
get too much inlining now.

4.  In the occurrence analyser, we were choosing a bad loop breaker.
Here's the comment that's now in OccurAnal.reOrderRec

    score ((bndr, rhs), _, _)
| exprIsTrivial rhs     = 3 -- Practically certain to be inlined
-- Used to have also: && not (isExportedId bndr)
-- But I found this sometimes cost an extra iteration when we have
-- rec { d = (a,b); a = ...df...; b = ...df...; df = d }
-- where df is the exported dictionary. Then df makes a really
-- bad choice for loop breaker

I also increased the score for bindings with a non-functional type, so that
dictionaries have a better chance of getting inlined early

5. Add a hash code to the InScopeSet (and make it properly abstract)
This should make uniqAway a lot more robust.  Simple experiments suggest
that uniqAway no longer gets into the long iteration chains that it used
to.

6.  Fix a bug in the inliner that made the simplifier tend to get into
a loop where it would keep iterating ("4 iterations, bailing out" message).
In SimplUtils.mkRhsTyLam we float bindings out past a big lambda, thus:
x = /\ b -> let g = \x -> f x x
    in E
becomes
g* = /\a -> \x -> f x x
x = /\ b -> let g = g* b in E

It's essential that we don't simply inling g* back into the RHS of g,
else we will be back to square 1.  The inliner is meant not to do this
because there's no benefit to the inlining, but the size calculation
was a little off in CoreUnfold.

7.  In SetLevels we were bogus-ly building a Subst with an empty in-scope
set, so a WARNING popped up when compiling some modules.  (knights/ChessSetList
was the example that tickled it.)  Now in fact the warning wasn't an error,
but the Right Thing to do is to carry down a proper Subst in SetLevels, so
that is what I have now done.  It is very little more expensive.

42 files changed:
ghc/compiler/NOTES
ghc/compiler/basicTypes/Literal.lhs
ghc/compiler/basicTypes/VarEnv.lhs
ghc/compiler/basicTypes/VarSet.lhs
ghc/compiler/coreSyn/CoreUnfold.lhs
ghc/compiler/coreSyn/CoreUtils.lhs
ghc/compiler/coreSyn/Subst.lhs
ghc/compiler/deSugar/Desugar.lhs
ghc/compiler/hsSyn/HsBinds.lhs
ghc/compiler/hsSyn/HsDecls.lhs
ghc/compiler/main/Main.lhs
ghc/compiler/main/MkIface.lhs
ghc/compiler/parser/Parser.y
ghc/compiler/parser/RdrHsSyn.lhs
ghc/compiler/rename/ParseIface.y
ghc/compiler/rename/Rename.lhs
ghc/compiler/rename/RnEnv.lhs
ghc/compiler/rename/RnExpr.lhs
ghc/compiler/rename/RnIfaces.lhs
ghc/compiler/rename/RnMonad.lhs
ghc/compiler/rename/RnNames.lhs
ghc/compiler/rename/RnSource.lhs
ghc/compiler/simplCore/CSE.lhs
ghc/compiler/simplCore/OccurAnal.lhs
ghc/compiler/simplCore/SetLevels.lhs
ghc/compiler/simplCore/SimplCore.lhs
ghc/compiler/simplCore/SimplMonad.lhs
ghc/compiler/simplCore/SimplUtils.lhs
ghc/compiler/simplCore/Simplify.lhs
ghc/compiler/specialise/Rules.lhs
ghc/compiler/specialise/Specialise.lhs
ghc/compiler/typecheck/Inst.lhs
ghc/compiler/typecheck/TcBinds.lhs
ghc/compiler/typecheck/TcClassDcl.lhs
ghc/compiler/typecheck/TcDeriv.lhs
ghc/compiler/typecheck/TcEnv.lhs
ghc/compiler/typecheck/TcImprove.lhs
ghc/compiler/typecheck/TcInstDcls.lhs
ghc/compiler/typecheck/TcModule.lhs
ghc/compiler/typecheck/TcMonad.lhs
ghc/compiler/typecheck/TcTyClsDecls.lhs
ghc/compiler/types/Type.lhs

index d0332b1..2809640 100644 (file)
@@ -1,3 +1,23 @@
+Notes July 00
+~~~~~~~~~~~~~~
+Time.lhs: fails with too many arguments to C function
+works with native code gen
+
+CTypes.lhs: fails with
+    /tmp/ghc2840.hc:42413: fixed or forbidden register 3 (bx) was spilled for class GENERAL_REGS.
+    This may be due to a compiler bug or to impossible asm statements or clauses.
+works without -O
+
+posix/* fails with
+      ghc1653.c:4: `#include' expects "FILENAME" or <FILENAME>
+      ghc1653.c:6: `#include' expects "FILENAME" or <FILENAME>
+works when one fixes the makefile
+
+make depend needs the -osuf o removed.
+
+CTypes also has a Subst-worker WARNING.
+
+
 Notes June 99
 ~~~~~~~~~~~~~
 * In nofib/spectral/mandel2/Main.check_radius, there's a call to (fromIntegral m), where
index b3037d1..3d53165 100644 (file)
@@ -8,7 +8,7 @@ module Literal
        ( Literal(..)           -- Exported to ParseIface
        , mkMachInt, mkMachWord
        , mkMachInt64, mkMachWord64
-       , isLitLitLit, maybeLitLit
+       , isLitLitLit, maybeLitLit, litIsDupable,
        , literalType, literalPrimRep
        , hashLiteral
 
@@ -183,6 +183,12 @@ isLitLitLit _                   = False
 
 maybeLitLit (MachLitLit s t) = Just (s,t)
 maybeLitLit _               = Nothing
+
+litIsDupable :: Literal -> Bool
+       -- True if code space does not go bad if we duplicate this literal
+       -- False principally of strings
+litIsDupable (MachStr _) = False
+litIsDupable other      = True
 \end{code}
 
        Types
index f8783f4..fcf64f1 100644 (file)
@@ -23,7 +23,7 @@ module VarEnv (
        SubstEnv, TyVarSubstEnv, SubstResult(..),
        emptySubstEnv, 
        mkSubstEnv, lookupSubstEnv, extendSubstEnv, extendSubstEnvList,
-       delSubstEnv, noTypeSubst, isEmptySubstEnv
+       delSubstEnv, delSubstEnvList, noTypeSubst, isEmptySubstEnv
     ) where
 
 #include "HsVersions.h"
@@ -102,6 +102,9 @@ extendSubstEnvList (SE env nt) (b:bs) (r:rs) = extendSubstEnvList (SE (extendVar
 
 delSubstEnv :: SubstEnv -> Var -> SubstEnv
 delSubstEnv (SE s nt) v = SE (delVarEnv s v) nt
+
+delSubstEnvList :: SubstEnv -> [Var] -> SubstEnv
+delSubstEnvList (SE s nt) vs = SE (delVarEnvList s vs) nt
 \end{code}
 
 
index faf1db1..261426e 100644 (file)
@@ -13,16 +13,14 @@ module VarSet (
        intersectVarSet, intersectsVarSet,
        isEmptyVarSet, delVarSet, delVarSetByKey,
        minusVarSet, foldVarSet, filterVarSet,
-       lookupVarSet, mapVarSet, sizeVarSet, seqVarSet,
-
-       uniqAway
+       lookupVarSet, mapVarSet, sizeVarSet, seqVarSet
     ) where
 
 #include "HsVersions.h"
 
 import CmdLineOpts     ( opt_PprStyle_Debug )
 import Var             ( Var, Id, TyVar, UVar, setVarUnique )
-import Unique          ( Unique, Uniquable(..), incrUnique, deriveUnique )
+import Unique          ( Unique, Uniquable(..) )
 import UniqSet
 import UniqFM          ( delFromUFM_Directly )
 import Outputable
@@ -91,20 +89,3 @@ seqVarSet :: VarSet -> ()
 seqVarSet s = sizeVarSet s `seq` ()
 \end{code}
 
-\begin{code}
-uniqAway :: VarSet -> Var -> Var
--- Give the Var a new unique, different to any in the VarSet
-uniqAway set var
-  | not (var `elemVarSet` set) = var   -- Nothing to do
-
-  | otherwise
-  = try 1 (deriveUnique (getUnique var) (hashUniqSet set))
-  where
-    try n uniq | uniq `elemUniqSet_Directly` set = try ((n+1)::Int) (incrUnique uniq)
-#ifdef DEBUG
-              | opt_PprStyle_Debug && n > 3
-              = pprTrace "uniqAway:" (ppr n <+> text "tries" <+> ppr var) 
-                setVarUnique var uniq
-#endif                     
-              | otherwise = setVarUnique var uniq
-\end{code}
index 239cd1d..c170c47 100644 (file)
@@ -50,7 +50,7 @@ import Id             ( Id, idType, idFlavour, isId, idWorkerInfo,
                          isPrimOpId_maybe
                        )
 import VarSet
-import Literal         ( isLitLitLit )
+import Literal         ( isLitLitLit, litIsDupable )
 import PrimOp          ( PrimOp(..), primOpIsDupable, primOpOutOfLine, ccallIsCasm )
 import IdInfo          ( ArityInfo(..), InlinePragInfo(..), OccInfo(..), IdFlavour(..), CprInfo(..), 
                          insideLam, workerExists, isNeverInlinePrag
@@ -192,7 +192,8 @@ sizeExpr (I# bOMB_OUT_SIZE) top_args expr
     size_up (App fun (Type t))  = size_up fun
     size_up (App fun arg)     = size_up_app fun [arg]
 
-    size_up (Lit lit) = sizeOne
+    size_up (Lit lit) | litIsDupable lit = sizeOne
+                     | otherwise        = sizeN opt_UF_DearOp  -- For lack of anything better
 
     size_up (Lam b e) | isId b    = lamScrutDiscount (size_up e `addSizeN` 1)
                      | otherwise = size_up e
@@ -211,40 +212,39 @@ sizeExpr (I# bOMB_OUT_SIZE) top_args expr
       where
        rhs_size = foldr (addSize . size_up . snd) sizeZero pairs
 
-       -- We want to make wrapper-style evaluation look cheap, so that
-       -- when we inline a wrapper it doesn't make call site (much) bigger
-       -- Otherwise we get nasty phase ordering stuff: 
-       --      f x = g x x
-       --      h y = ...(f e)...
-       -- If we inline g's wrapper, f looks big, and doesn't get inlined
-       -- into h; if we inline f first, while it looks small, then g's 
-       -- wrapper will get inlined later anyway.  To avoid this nasty
-       -- ordering difference, we make (case a of (x,y) -> ...) look free.
-    size_up (Case (Var v) _ [alt]) 
-       | v `elem` top_args
-       = size_up_alt alt `addSize` SizeIs 0# (unitBag (v, 1)) 0#
+    size_up (Case (Var v) _ alts) 
+       | v `elem` top_args             -- We are scrutinising an argument variable
+       = case alts of
+               [alt] -> size_up_alt alt `addSize` SizeIs 0# (unitBag (v, 1)) 0#
+               -- We want to make wrapper-style evaluation look cheap, so that
+               -- when we inline a wrapper it doesn't make call site (much) bigger
+               -- Otherwise we get nasty phase ordering stuff: 
+               --      f x = g x x
+               --      h y = ...(f e)...
+               -- If we inline g's wrapper, f looks big, and doesn't get inlined
+               -- into h; if we inline f first, while it looks small, then g's 
+               -- wrapper will get inlined later anyway.  To avoid this nasty
+               -- ordering difference, we make (case a of (x,y) -> ...), 
+               -- *where a is one of the arguments* look free.
+
+               other -> alts_size (foldr addSize sizeOne alt_sizes)    -- The 1 is for the scrutinee
+                                  (foldr1 maxSize alt_sizes)
+
                -- Good to inline if an arg is scrutinised, because
                -- that may eliminate allocation in the caller
                -- And it eliminates the case itself
-       | otherwise     
-       = size_up_alt alt
-
-       -- Scrutinising one of the argument variables,
-       -- with more than one alternative
-    size_up (Case (Var v) _ alts)
-       | v `elem` top_args
-       = alts_size (foldr addSize sizeOne alt_sizes)   -- The 1 is for the scrutinee
-                   (foldr1 maxSize alt_sizes)
+
        where
          alt_sizes = map size_up_alt alts
 
+               -- alts_size tries to compute a good discount for
+               -- the case when we are scrutinising an argument variable
          alts_size (SizeIs tot tot_disc tot_scrut)             -- Size of all alternatives
                    (SizeIs max max_disc max_scrut)             -- Size of biggest alternative
                = SizeIs tot (unitBag (v, I# (1# +# tot -# max)) `unionBags` max_disc) max_scrut
                        -- If the variable is known, we produce a discount that
                        -- will take us back to 'max', the size of rh largest alternative
                        -- The 1+ is a little discount for reduced allocation in the caller
-
          alts_size tot_size _ = tot_size
 
 
@@ -306,7 +306,7 @@ sizeExpr (I# bOMB_OUT_SIZE) top_args expr
     ------------
        -- We want to record if we're case'ing, or applying, an argument
     fun_discount v | v `elem` top_args = SizeIs 0# (unitBag (v, opt_UF_FunAppDiscount)) 0#
-    fun_discount other                   = sizeZero
+    fun_discount other                = sizeZero
 
     ------------
        -- These addSize things have to be here because
index 5147bfd..0c01569 100644 (file)
@@ -42,7 +42,7 @@ import Var            ( Var, isId, isTyVar )
 import VarSet
 import VarEnv
 import Name            ( isLocallyDefined, hashName )
-import Literal         ( Literal, hashLiteral, literalType )
+import Literal         ( Literal, hashLiteral, literalType, litIsDupable )
 import DataCon         ( DataCon, dataConRepArity )
 import PrimOp          ( primOpOkForSpeculation, primOpIsCheap, 
                          primOpIsDupable )
@@ -271,7 +271,7 @@ exprIsTrivial other                = False
 \begin{code}
 exprIsDupable (Type _)      = True
 exprIsDupable (Var v)       = True
-exprIsDupable (Lit lit)      = True
+exprIsDupable (Lit lit)      = litIsDupable lit
 exprIsDupable (Note _ e)     = exprIsDupable e
 exprIsDupable expr          
   = go expr 0
index 22128ef..1f0f928 100644 (file)
@@ -6,14 +6,19 @@
 \begin{code}
 module Subst (
        -- In-scope set
-       InScopeSet, emptyInScopeSet,
-       lookupInScope, setInScope, extendInScope, extendInScopes, isInScope, modifyInScope,
+       InScopeSet, emptyInScopeSet, mkInScopeSet,
+       extendInScopeSet, extendInScopeSetList,
+       lookupInScope, elemInScopeSet, uniqAway,
+
 
        -- Substitution stuff
        Subst, TyVarSubst, IdSubst,
        emptySubst, mkSubst, substEnv, substInScope,
        lookupSubst, lookupIdSubst, isEmptySubst, extendSubst, extendSubstList,
        zapSubstEnv, setSubstEnv, 
+       setInScope, 
+       extendInScope, extendInScopeList, extendNewInScope, extendNewInScopeList, 
+       isInScope, modifyInScope,
 
        bindSubst, unBindSubst, bindSubstList, unBindSubstList,
 
@@ -31,6 +36,7 @@ module Subst (
 
 #include "HsVersions.h"
 
+import CmdLineOpts     ( opt_PprStyle_Debug )
 import CoreSyn         ( Expr(..), Bind(..), Note(..), CoreExpr, CoreBndr,
                          CoreRules(..), CoreRule(..), 
                          emptyCoreRules, isEmptyCoreRules, seqRules
@@ -49,6 +55,8 @@ import IdInfo         ( IdInfo, isFragileOccInfo,
                          specInfo, setSpecInfo, 
                          WorkerInfo(..), workerExists, workerInfo, setWorkerInfo, WorkerInfo
                        )
+import Unique          ( Uniquable(..), deriveUnique )
+import UniqSet         ( elemUniqSet_Directly )
 import UniqSupply      ( UniqSupply, uniqFromSupply, splitUniqSupply )
 import Var             ( Var, Id, TyVar, isTyVar )
 import Outputable
@@ -56,15 +64,88 @@ import PprCore              ()      -- Instances
 import Util            ( mapAccumL, foldl2, seqList, ($!) )
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
-\subsection{Substitutions}
+\subsection{The in-scope set}
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-type InScopeSet = VarEnv Var
+data InScopeSet = InScope (VarEnv Var) Int#
+       -- The Int# is a kind of hash-value used by uniqAway
+       -- For example, it might be the size of the set
+
+emptyInScopeSet :: InScopeSet
+emptyInScopeSet = InScope emptyVarSet 0#
+
+mkInScopeSet :: VarEnv Var -> InScopeSet
+mkInScopeSet in_scope = InScope in_scope 0#
+
+extendInScopeSet :: InScopeSet -> Var -> InScopeSet
+extendInScopeSet (InScope in_scope n) v = InScope (extendVarEnv in_scope v v) (n +# 1#)
+
+extendInScopeSetList :: InScopeSet -> [Var] -> InScopeSet
+extendInScopeSetList (InScope in_scope n) vs = InScope (foldl (\s v -> extendVarEnv s v v) in_scope vs)
+                                                      (case length vs of { I# l -> n +# l })
+
+modifyInScopeSet :: InScopeSet -> Var -> Var -> InScopeSet
+-- Exploit the fact that the in-scope "set" is really a map
+--     Make old_v map to new_v
+modifyInScopeSet (InScope in_scope n) old_v new_v = InScope (extendVarEnv in_scope old_v new_v) (n +# 1#)
+
+delInScopeSet :: InScopeSet -> Var -> InScopeSet
+delInScopeSet (InScope in_scope n) v = InScope (in_scope `delVarEnv` v) n
+
+elemInScopeSet :: Var -> InScopeSet -> Bool
+elemInScopeSet v (InScope in_scope n) = v `elemVarEnv` in_scope
+
+lookupInScope :: InScopeSet -> Var -> Var
+-- It's important to look for a fixed point
+-- When we see (case x of y { I# v -> ... })
+-- we add  [x -> y] to the in-scope set (Simplify.simplCaseBinder).
+-- When we lookup up an occurrence of x, we map to y, but then
+-- we want to look up y in case it has acquired more evaluation information by now.
+lookupInScope (InScope in_scope n) v 
+  = go v
+  where
+    go v = case lookupVarEnv in_scope v of
+               Just v' | v == v'   -> v'       -- Reached a fixed point
+                       | otherwise -> go v'
+               Nothing             -> WARN( mustHaveLocalBinding v, ppr v )
+                                      v
+\end{code}
+
+\begin{code}
+uniqAway :: InScopeSet -> Var -> Var
+-- (uniqAway in_scope v) finds a unique that is not used in the
+-- in-scope set, and gives that to v.  It starts with v's current unique, of course,
+-- in the hope that it won't have to change it, nad thereafter uses a combination
+-- of that and the hash-code found in the in-scope set
+uniqAway (InScope set n) var
+  | not (var `elemVarSet` set) = var   -- Nothing to do
+  | otherwise                 = try 1#
+  where
+    orig_unique = getUnique var
+    try k | uniq `elemUniqSet_Directly` set = try (k +# 1#)
+#ifdef DEBUG
+         | opt_PprStyle_Debug && k ># 3#
+         = pprTrace "uniqAway:" (ppr (I# k) <+> text "tries" <+> ppr var <+> int (I# n)) 
+           setVarUnique var uniq
+#endif                     
+         | otherwise = setVarUnique var uniq
+         where
+           uniq = deriveUnique orig_unique (I# (n *# k))
+\end{code}
+
 
+%************************************************************************
+%*                                                                     *
+\subsection{Substitutions}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
 data Subst = Subst InScopeSet          -- In scope
                   SubstEnv             -- Substitution itself
        -- INVARIANT 1: The (domain of the) in-scope set is a superset
@@ -124,15 +205,6 @@ The general plan about the substitution and in-scope set for Ids is as follows
        case y of x { ... }
   That's why the "set" is actually a VarEnv Var
 
-\begin{code}
-emptyInScopeSet :: InScopeSet
-emptyInScopeSet = emptyVarSet
-
-add_in_scope :: InScopeSet -> Var -> InScopeSet
-add_in_scope in_scope v = extendVarEnv in_scope v v
-\end{code}
-
-
 
 \begin{code}
 isEmptySubst :: Subst -> Bool
@@ -177,38 +249,38 @@ lookupIdSubst (Subst in_scope env) v
                             where
                                    v' = lookupInScope in_scope v
 
-lookupInScope :: InScopeSet -> Var -> Var
--- It's important to look for a fixed point
--- When we see (case x of y { I# v -> ... })
--- we add  [x -> y] to the in-scope set (Simplify.simplCaseBinder).
--- When we lookup up an occurrence of x, we map to y, but then
--- we want to look up y in case it has acquired more evaluation information by now.
-lookupInScope in_scope v 
-  = case lookupVarEnv in_scope v of
-       Just v' | v == v'   -> v'       -- Reached a fixed point
-               | otherwise -> lookupInScope in_scope v'
-       Nothing             -> WARN( mustHaveLocalBinding v, ppr v )
-                              v
-
 isInScope :: Var -> Subst -> Bool
-isInScope v (Subst in_scope _) = v `elemVarEnv` in_scope
-
-extendInScope :: Subst -> Var -> Subst
-extendInScope (Subst in_scope env) v = Subst (in_scope `add_in_scope` v) env
+isInScope v (Subst in_scope _) = v `elemInScopeSet` in_scope
 
 modifyInScope :: Subst -> Var -> Var -> Subst
-modifyInScope (Subst in_scope env) old_v new_v = Subst (extendVarEnv in_scope old_v new_v) env
+modifyInScope (Subst in_scope env) old_v new_v = Subst (modifyInScopeSet in_scope old_v new_v) env
        -- make old_v map to new_v
 
-extendInScopes :: Subst -> [Var] -> Subst
-extendInScopes (Subst in_scope env) vs = Subst (foldl add_in_scope in_scope vs) env
+extendInScope :: Subst -> Var -> Subst
+       -- Add a new variable as in-scope
+       -- Remember to delete any existing binding in the substitution!
+extendInScope (Subst in_scope env) v = Subst (in_scope `extendInScopeSet` v)
+                                            (env `delSubstEnv` v)
+
+extendInScopeList :: Subst -> [Var] -> Subst
+extendInScopeList (Subst in_scope env) vs = Subst (extendInScopeSetList in_scope vs)
+                                                 (delSubstEnvList env vs)
+
+-- The "New" variants are guaranteed to be adding freshly-allocated variables
+-- It's not clear that the gain (not needing to delete it from the substitution)
+-- is worth the extra proof obligation
+extendNewInScope :: Subst -> Var -> Subst
+extendNewInScope (Subst in_scope env) v = Subst (in_scope `extendInScopeSet` v) env
+
+extendNewInScopeList :: Subst -> [Var] -> Subst
+extendNewInScopeList (Subst in_scope env) vs = Subst (in_scope `extendInScopeSetList` vs) env
 
 -------------------------------
 bindSubst :: Subst -> Var -> Var -> Subst
 -- Extend with a substitution, v1 -> Var v2
 -- and extend the in-scopes with v2
 bindSubst (Subst in_scope env) old_bndr new_bndr
-  = Subst (in_scope `add_in_scope` new_bndr)
+  = Subst (in_scope `extendInScopeSet` new_bndr)
          (extendSubstEnv env old_bndr subst_result)
   where
     subst_result | isId old_bndr = DoneEx (Var new_bndr)
@@ -218,7 +290,7 @@ unBindSubst :: Subst -> Var -> Var -> Subst
 -- Reverse the effect of bindSubst
 -- If old_bndr was already in the substitution, this doesn't quite work
 unBindSubst (Subst in_scope env) old_bndr new_bndr
-  = Subst (in_scope `delVarEnv` new_bndr) (delSubstEnv env old_bndr)
+  = Subst (in_scope `delInScopeSet` new_bndr) (delSubstEnv env old_bndr)
 
 -- And the "List" forms
 bindSubstList :: Subst -> [Var] -> [Var] -> Subst
@@ -251,14 +323,14 @@ setSubstEnv (Subst in_scope1 _) env2 = Subst in_scope1 env2
 %************************************************************************
 
 \begin{code}
-type TyVarSubst    = Subst     -- TyVarSubst are expected to have range elements
+type TyVarSubst = Subst        -- TyVarSubst are expected to have range elements
        -- (We could have a variant of Subst, but it doesn't seem worth it.)
 
 -- mkTyVarSubst generates the in-scope set from
 -- the types given; but it's just a thunk so with a bit of luck
 -- it'll never be evaluated
 mkTyVarSubst :: [TyVar] -> [Type] -> Subst
-mkTyVarSubst tyvars tys = Subst (tyVarsOfTypes tys) (zip_ty_env tyvars tys emptySubstEnv)
+mkTyVarSubst tyvars tys = Subst (mkInScopeSet (tyVarsOfTypes tys)) (zip_ty_env tyvars tys emptySubstEnv)
 
 -- mkTopTyVarSubst is called when doing top-level substitutions.
 -- Here we expect that the free vars of the range of the
@@ -325,7 +397,7 @@ substTyVar subst@(Subst in_scope env) old_var
                        --
                        -- The new_id isn't cloned, but it may have a different type
                        -- etc, so we must return it, not the old id
-  = (Subst (in_scope `add_in_scope` new_var)
+  = (Subst (in_scope `extendInScopeSet` new_var)
           (delSubstEnv env old_var),
      new_var)
 
@@ -334,7 +406,7 @@ substTyVar subst@(Subst in_scope env) old_var
                -- Extending the substitution to do this renaming also
                -- has the (correct) effect of discarding any existing
                -- substitution for that variable
-  = (Subst (in_scope `add_in_scope` new_var) 
+  = (Subst (in_scope `extendInScopeSet` new_var) 
           (extendSubstEnv env old_var (DoneTy (TyVarTy new_var))),
      new_var)
   where
@@ -437,7 +509,7 @@ substId :: Subst -> Id -> (Subst, Id)
        -- top of this module
 
 substId subst@(Subst in_scope env) old_id
-  = (Subst (in_scope `add_in_scope` new_id) new_env, new_id)
+  = (Subst (in_scope `extendInScopeSet` new_id) new_env, new_id)
   where
     id_ty    = idType old_id
     occ_info = idOccInfo old_id
@@ -476,7 +548,7 @@ substAndCloneIds subst us (b:bs) = case substAndCloneId  subst  us  b  of { (sub
                                        
 substAndCloneId :: Subst -> UniqSupply -> Id -> (Subst, UniqSupply, Id)
 substAndCloneId subst@(Subst in_scope env) us old_id
-  = (Subst (in_scope `add_in_scope` new_id) 
+  = (Subst (in_scope `extendInScopeSet` new_id) 
           (extendSubstEnv env old_id (DoneEx (Var new_id))),
      new_us,
      new_id)
index c42d127..557ac73 100644 (file)
@@ -14,7 +14,7 @@ import TcHsSyn                ( TypecheckedRuleDecl )
 import TcModule                ( TcResults(..) )
 import CoreSyn
 import Rules           ( ProtoCoreRule(..), pprProtoCoreRule )
-import Subst           ( substExpr, mkSubst )
+import Subst           ( substExpr, mkSubst, mkInScopeSet )
 import DsMonad
 import DsExpr          ( dsExpr )
 import DsBinds         ( dsMonoBinds, AutoScc(..) )
@@ -110,7 +110,7 @@ dsRule in_scope (HsRule name sig_tvs vars lhs rhs loc)
                            (Rule name tpl_vars args core_rhs))
   where
     tpl_vars = sig_tvs ++ [var | RuleBndr var <- vars]
-    all_vars = in_scope `unionVarSet` mkVarSet tpl_vars
+    all_vars = mkInScopeSet (in_scope `unionVarSet` mkVarSet tpl_vars)
 
 ds_lhs all_vars lhs
   = let
index db83e15..2d72e03 100644 (file)
@@ -236,9 +236,10 @@ data Sig name
                SrcLoc
 
   | ClassOpSig name            -- Selector name
-               name            -- Default-method name (if any)
-               Bool            -- True <=> there is an explicit, programmer-supplied
-                               -- default declaration in the class decl
+               (Maybe          -- Nothing for source-file class signatures
+                     (name,            -- Default-method name (if any)
+                      Bool))           -- True <=> there is an explicit, programmer-supplied
+                                       --          default declaration in the class decl
                (HsType name)
                SrcLoc
 
@@ -269,7 +270,7 @@ instance Eq name => Eq (FixitySig name) where
 
 \begin{code}
 okBindSig :: NameSet -> Sig Name -> Bool
-okBindSig ns (ClassOpSig _ _ _ _ _)                            = False
+okBindSig ns (ClassOpSig _ _ _ _)                              = False
 okBindSig ns sig = sigForThisGroup ns sig
 
 okClsDclSig :: NameSet -> Sig Name -> Bool
@@ -290,7 +291,7 @@ sigForThisGroup ns sig
 
 sigName :: Sig name -> Maybe name
 sigName (Sig         n _ _)             = Just n
-sigName (ClassOpSig  n _ _ _ _)         = Just n
+sigName (ClassOpSig  n _ _ _)           = Just n
 sigName (SpecSig     n _ _)             = Just n
 sigName (InlineSig   n _   _)           = Just n
 sigName (NoInlineSig n _   _)           = Just n
@@ -302,8 +303,8 @@ isFixitySig (FixSig _) = True
 isFixitySig _         = False
 
 isClassOpSig :: Sig name -> Bool
-isClassOpSig (ClassOpSig _ _ _ _ _) = True
-isClassOpSig _                     = False
+isClassOpSig (ClassOpSig _ _ _ _) = True
+isClassOpSig _                   = False
 
 isPragSig :: Sig name -> Bool
        -- Identifies pragmas 
@@ -316,7 +317,7 @@ isPragSig other                   = False
 
 \begin{code}
 hsSigDoc (Sig        _ _ loc)        = (SLIT("type signature"),loc)
-hsSigDoc (ClassOpSig _ _ _ _ loc)     = (SLIT("class-method type signature"), loc)
+hsSigDoc (ClassOpSig _ _ _ loc)       = (SLIT("class-method type signature"), loc)
 hsSigDoc (SpecSig    _ _ loc)        = (SLIT("SPECIALISE pragma"),loc)
 hsSigDoc (InlineSig  _ _    loc)      = (SLIT("INLINE pragma"),loc)
 hsSigDoc (NoInlineSig  _ _  loc)      = (SLIT("NOINLINE pragma"),loc)
@@ -332,10 +333,12 @@ ppr_sig :: Outputable name => Sig name -> SDoc
 ppr_sig (Sig var ty _)
       = sep [ppr var <+> dcolon, nest 4 (ppr ty)]
 
-ppr_sig (ClassOpSig var _ dm ty _)
+ppr_sig (ClassOpSig var dm ty _)
       = sep [ppr var <+> pp_dm <+> dcolon, nest 4 (ppr ty)]
       where
-       pp_dm = if dm then equals else empty    -- Default-method indicator
+       pp_dm = case dm of 
+                 Just (_, True) -> equals      -- Default-method indicator
+                 other          -> empty
 
 ppr_sig (SpecSig var ty _)
       = sep [ hsep [text "{-# SPECIALIZE", ppr var, dcolon],
index 092ee68..fd1212a 100644 (file)
@@ -15,7 +15,7 @@ module HsDecls (
        BangType(..), getBangType,
        IfaceSig(..),  SpecDataSig(..), 
        DeprecDecl(..), DeprecTxt,
-       hsDeclName, tyClDeclName, isClassDecl, isSynDecl, isDataDecl, countTyClDecls, toHsRule
+       hsDeclName, instDeclName, tyClDeclName, isClassDecl, isSynDecl, isDataDecl, countTyClDecls, toHsRule
     ) where
 
 #include "HsVersions.h"
@@ -79,20 +79,24 @@ data HsDecl name pat
 hsDeclName :: (Outputable name, Outputable pat)
           => HsDecl name pat -> name
 #endif
-hsDeclName (TyClD decl)                                  = tyClDeclName decl
-hsDeclName (SigD    (IfaceSig name _ _ _))       = name
-hsDeclName (InstD   (InstDecl _ _ _ name _))      = name
-hsDeclName (ForD    (ForeignDecl name _ _ _ _ _)) = name
-hsDeclName (FixD    (FixitySig name _ _))        = name
+hsDeclName (TyClD decl)                                    = tyClDeclName decl
+hsDeclName (InstD   decl)                          = instDeclName decl
+hsDeclName (SigD    (IfaceSig name _ _ _))         = name
+hsDeclName (ForD    (ForeignDecl name _ _ _ _ _))   = name
+hsDeclName (FixD    (FixitySig name _ _))          = name
 -- Others don't make sense
 #ifdef DEBUG
 hsDeclName x                                 = pprPanic "HsDecls.hsDeclName" (ppr x)
 #endif
 
+
 tyClDeclName :: TyClDecl name pat -> name
 tyClDeclName (TyData _ _ name _ _ _ _ _ _)          = name
 tyClDeclName (TySynonym name _ _ _)                 = name
 tyClDeclName (ClassDecl _ name _ _ _ _ _ _ _ _ _ _) = name
+
+instDeclName :: InstDecl name pat -> name
+instDeclName (InstDecl _ _ _ (Just name) _) = name
 \end{code}
 
 \begin{code}
@@ -126,6 +130,48 @@ instance Ord name => Eq (HsDecl name pat) where
 %*                                                                     *
 %************************************************************************
 
+Type and class declarations carry 'implicit names'.  In particular:
+
+Type A.  
+~~~~~~~
+  Each data type decl defines 
+       a worker name for each constructor
+       to-T and from-T convertors
+  Each class decl defines
+       a tycon for the class
+       a data constructor for that tycon
+       the worker for that constructor
+       a selector for each superclass
+
+All have occurrence names that are derived uniquely from their parent declaration.
+
+None of these get separate definitions in an interface file; they are
+fully defined by the data or class decl.  But they may *occur* in
+interface files, of course.  Any such occurrence must haul in the
+relevant type or class decl.
+
+Plan of attack:
+ - Make up their occurrence names immediately
+
+ - Ensure they "point to" the parent data/class decl 
+   when loading that decl from an interface file
+
+ - When renaming the decl look them up in the name cache,
+   ensure correct module and provenance is set
+
+Type B: Default methods and dictionary functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Have their own binding in an interface file.
+
+Default methods : occurrence name is derived uniquely from the class decl.
+Dict functions  : occurrence name is derived from the instance decl, plus a unique number.
+
+Plan of attack: 
+  - Do *not* make them point to the parent class decl
+  - Interface-file decls: treat just like Type A
+  - Source-file decls:    the names aren't in the decl at all; 
+                         instead the typechecker makes them up
+
 \begin{code}
 data TyClDecl name pat
   = TyData     NewOrData
@@ -189,8 +235,16 @@ instance Ord name => Eq (TyClDecl name pat) where
 eq_hsFD env (ns1,ms1) (ns2,ms2)
   = eqListBy (eq_hsVar env) ns1 ns2 && eqListBy (eq_hsVar env) ms1 ms2
 
-eq_cls_sig env (ClassOpSig n1 _ b1 ty1 _) (ClassOpSig n2 _ b2 ty2 _)
-  = n1==n2 && b1==b2 && eq_hsType env ty1 ty2
+eq_cls_sig env (ClassOpSig n1 dm1 ty1 _) (ClassOpSig n2 dm2 ty2 _)
+  = n1==n2 && dm1 `eq_dm` dm2 && eq_hsType env ty1 ty2
+  where
+       -- Ignore the name of the default method.
+       -- This is used for comparing declarations before putting
+       -- them into interface files, and the name of the default 
+       -- method isn't relevant
+    (Just (_,explicit_dm1)) `eq_dm` (Just (_,explicit_dm2)) = explicit_dm1 == explicit_dm2
+    Nothing                `eq_dm` Nothing                 = True
+    dm1                            `eq_dm` dm2                     = False
 \end{code}
 
 \begin{code}
@@ -400,7 +454,8 @@ data InstDecl name pat
 
                [Sig name]              -- User-supplied pragmatic info
 
-               name                    -- Name for the dictionary function
+               (Maybe name)            -- Name for the dictionary function
+                                       -- Nothing for source-file instance decls
 
                SrcLoc
 \end{code}
@@ -409,14 +464,18 @@ data InstDecl name pat
 instance (Outputable name, Outputable pat)
              => Outputable (InstDecl name pat) where
 
-    ppr (InstDecl inst_ty binds uprags dfun_name src_loc)
+    ppr (InstDecl inst_ty binds uprags maybe_dfun_name src_loc)
       = getPprStyle $ \ sty ->
         if ifaceStyle sty then
-           hsep [ptext SLIT("instance"), ppr inst_ty, equals, ppr dfun_name]
+           hsep [ptext SLIT("instance"), ppr inst_ty, equals, pp_dfun]
        else
           vcat [hsep [ptext SLIT("instance"), ppr inst_ty, ptext SLIT("where")],
                 nest 4 (ppr uprags),
                 nest 4 (ppr binds) ]
+      where
+       pp_dfun = case maybe_dfun_name of
+                   Just df -> ppr df
+                   Nothing -> empty
 \end{code}
 
 \begin{code}
index ab31840..f19b445 100644 (file)
@@ -309,7 +309,7 @@ ppSourceStats short (HsModule name version exports imports decls _ src_loc)
     count_sigs sigs = foldr add4 (0,0,0,0) (map sig_info sigs)
 
     sig_info (Sig _ _ _)            = (1,0,0,0)
-    sig_info (ClassOpSig _ _ _ _ _) = (0,1,0,0)
+    sig_info (ClassOpSig _ _ _ _)   = (0,1,0,0)
     sig_info (SpecSig _ _ _)        = (0,0,1,0)
     sig_info (InlineSig _ _ _)      = (0,0,0,1)
     sig_info (NoInlineSig _ _ _)    = (0,0,0,1)
index 354b7da..3321130 100644 (file)
@@ -333,13 +333,9 @@ completeIface new_iface local_tycons local_classes
      orphan_rule_ids = unionVarSets [ ruleSomeFreeVars interestingId rule 
                                    | ProtoCoreRule _ _ rule <- tidy_orphan_rules]
 
-lt_inst_decl (InstDecl _ _ _ dfun_id1 _) (InstDecl _ _ _ dfun_id2 _)
-   = dfun_id1 < dfun_id2
-       -- The dfuns are assigned names df1, df2, etc, 
-       -- in order of original textual
-       -- occurrence, and this makes as good a sort order as any
-
-lt_decl d1 d2 = hsDeclName d1 < hsDeclName d2
+lt_decl      d1 d2 = hsDeclName   d1 < hsDeclName d2
+lt_inst_decl d1 d2 = instDeclName d1 < instDeclName d2
+       -- Even instance decls have names, namely the dfun name
 \end{code}
 
 
@@ -396,7 +392,7 @@ ifaceInstances inst_infos
                                      (deNoteType (mkDictTy clas tys))
            tidy_ty = tidyTopType forall_ty
        in                       
-       InstDecl (toHsType tidy_ty) EmptyMonoBinds [] (toRdrName dfun_id) noSrcLoc 
+       InstDecl (toHsType tidy_ty) EmptyMonoBinds [] (Just (toRdrName dfun_id)) noSrcLoc 
 \end{code}
 
 \begin{code}
@@ -464,7 +460,7 @@ ifaceClass clas
 
      toClassOpSig (sel_id, dm_id, explicit_dm)
        = ASSERT( sel_tyvars == clas_tyvars)
-         ClassOpSig (toRdrName sel_id) bogus explicit_dm (toHsType op_ty) noSrcLoc
+         ClassOpSig (toRdrName sel_id) (Just (bogus, explicit_dm)) (toHsType op_ty) noSrcLoc
        where
          (sel_tyvars, _, op_ty) = splitSigmaTy (idType sel_id)
 \end{code}
index d8aef16..095f828 100644 (file)
@@ -1,6 +1,6 @@
 {-
 -----------------------------------------------------------------------------
-$Id: Parser.y,v 1.33 2000/07/06 14:08:31 simonmar Exp $
+$Id: Parser.y,v 1.34 2000/08/01 09:08:27 simonpj Exp $
 
 Haskell grammar.
 
@@ -229,8 +229,8 @@ body        :: { ([RdrNameImportDecl], [RdrNameHsDecl]) }
        |      layout_on  top close             { $2 }
 
 top    :: { ([RdrNameImportDecl], [RdrNameHsDecl]) }
-       : importdecls ';' cvtopdecls            { (reverse $1,$3) }
-       | importdecls                           { (reverse $1,[]) }
+       : importdecls                           { (reverse $1,[]) }
+       | importdecls ';' cvtopdecls            { (reverse $1,$3) }
        | cvtopdecls                            { ([],$1) }
 
 cvtopdecls :: { [RdrNameHsDecl] }
@@ -345,9 +345,8 @@ topdecl :: { RdrBinding }
 
        | srcloc 'class' ctype fds where
                {% checkDataHeader $3 `thenP` \(cs,c,ts) ->
-                  let (binds,sigs) 
-                          = cvMonoBindsAndSigs cvClassOpSig 
-                               (groupBindings $5) 
+                  let 
+                       (binds,sigs) = cvMonoBindsAndSigs cvClassOpSig (groupBindings $5) 
                   in
                   returnP (RdrHsDecl (TyClD
                      (mkClassDecl cs c ts $4 sigs binds 
@@ -357,8 +356,7 @@ topdecl :: { RdrBinding }
                { let (binds,sigs) 
                        = cvMonoBindsAndSigs cvInstDeclSig 
                                (groupBindings $4)
-                 in RdrHsDecl (InstD
-                               (InstDecl $3 binds sigs dummyRdrVarName $1)) }
+                 in RdrHsDecl (InstD (InstDecl $3 binds sigs Nothing $1)) }
 
        | srcloc 'default' '(' types0 ')'
                { RdrHsDecl (DefD (DefaultDecl $4 $1)) }
@@ -527,13 +525,6 @@ atype :: { RdrNameHsType }
        | '[' type ']'                  { HsListTy $2 }
        | '(' ctype ')'                 { $2 }
 
-gtycon         :: { RdrName }
-       : qtycon                        { $1 }
-       | '(' ')'                       { unitTyCon_RDR }
-       | '(' '->' ')'                  { funTyCon_RDR }
-       | '[' ']'                       { listTyCon_RDR }
-       | '(' commas ')'                { tupleTyCon_RDR $2 }
-
 -- An inst_type is what occurs in the head of an instance decl
 --     e.g.  (Foo a, Gaz b) => Wibble a b
 -- It's kept as a single type, with a MonoDictTy at the right
@@ -750,10 +741,6 @@ aexp1      :: { RdrNameHsExpr }
        | '_'                           { EWildPat }
        | '~' aexp1                     { ELazyPat $2 }
 
-commas :: { Int }
-       : commas ','                    { $1 + 1 }
-       | ','                           { 2 }
-
 texps :: { [RdrNameHsExpr] }
        : texps ',' exp                 { $3 : $1 }
        | exp                           { [$1] }
@@ -881,6 +868,13 @@ dbind      : ipvar '=' exp                 { ($1, $3) }
 -----------------------------------------------------------------------------
 -- Variables, Constructors and Operators.
 
+gtycon         :: { RdrName }
+       : qtycon                        { $1 }
+       | '(' ')'                       { unitTyCon_RDR }
+       | '(' '->' ')'                  { funTyCon_RDR }
+       | '[' ']'                       { listTyCon_RDR }
+       | '(' commas ')'                { tupleTyCon_RDR $2 }
+
 gcon   :: { RdrName }
        : '(' ')'               { unitCon_RDR }
        | '[' ']'               { nilCon_RDR }
@@ -1081,6 +1075,10 @@ tyvar    :: { RdrName }
        | 'ccall'               { ccall_tyvar_RDR }
        -- NOTE: no 'forall'
 
+commas :: { Int }
+       : commas ','                    { $1 + 1 }
+       | ','                           { 2 }
+
 -----------------------------------------------------------------------------
 
 {
index a4cbc80..d1b0e0e 100644 (file)
@@ -217,7 +217,7 @@ mkClassDecl cxt cname tyvars fds sigs mbinds prags loc
       --  superclasses both called C!)
 
 mkClassOpSig has_default_method op ty loc
-  = ClassOpSig op dm_rn has_default_method ty loc
+  = ClassOpSig op (Just (dm_rn, has_default_method)) ty loc
   where
     dm_rn = mkRdrUnqual (mkDefaultMethodOcc (rdrNameOcc op))
 
@@ -285,9 +285,7 @@ cvValSig      sig = sig
 
 cvInstDeclSig sig = sig
 
-cvClassOpSig (Sig var poly_ty src_loc) = ClassOpSig var (panic "cvClassOpSig:dm_name")
-                                                       False
-                                                       poly_ty src_loc
+cvClassOpSig (Sig var poly_ty src_loc) = ClassOpSig var Nothing poly_ty src_loc
 cvClassOpSig sig                      = sig
 \end{code}
 
index 674af45..c854f14 100644 (file)
@@ -353,7 +353,7 @@ inst_decl   :  src_loc 'instance' type '=' var_name ';'
                        { InstDecl $3
                                   EmptyMonoBinds       {- No bindings -}
                                   []                   {- No user pragmas -}
-                                  $5                   {- Dfun id -}
+                                  (Just $5)            {- Dfun id -}
                                   $1
                        }
 
index f2f8614..c601856 100644 (file)
@@ -29,7 +29,7 @@ import RnIfaces               ( getImportedInstDecls, importDecl, mkImportExportInfo, getInte
 import RnEnv           ( availName, availsToNameSet, 
                          emptyAvailEnv, unitAvailEnv, availEnvElts, plusAvailEnv, 
                          warnUnusedImports, warnUnusedLocalBinds, warnUnusedModules,
-                         lookupImplicitOccsRn, unknownNameErr,
+                         lookupOrigNames, unknownNameErr,
                          FreeVars, plusFVs, plusFV, unitFV, emptyFVs, isEmptyFVs, addOneFV
                        )
 import Module           ( Module, ModuleName, WhereFrom(..),
@@ -83,7 +83,9 @@ renameModule us this_mod@(HsModule mod_name vers exports imports local_decls _ l
   =    -- Initialise the renamer monad
     do {
        ((maybe_rn_stuff, dump_action), rn_errs_bag, rn_warns_bag) 
-          <- initRn mod_name us (mkSearchPath opt_HiMap) loc (rename this_mod) ;
+          <- initRn (mkThisModule mod_name) us 
+                    (mkSearchPath opt_HiMap) loc
+                    (rename this_mod) ;
 
        -- Check for warnings
        printErrorsAndWarnings rn_errs_bag rn_warns_bag ;
@@ -210,7 +212,7 @@ mentioned explicitly, but which might be needed by the type checker.
 
 \begin{code}
 implicitFVs mod_name decls
-  = lookupImplicitOccsRn implicit_occs         `thenRn` \ implicit_names ->
+  = lookupOrigNames implicit_occs                      `thenRn` \ implicit_names ->
     returnRn (mkNameSet (map getName default_tycons)   `plusFV`
              implicit_names)
   where
@@ -494,7 +496,7 @@ getGates source_fvs (TyClD (ClassDecl ctxt cls tvs _ sigs _ _ _ _ _ _ _))
      `addOneToNameSet` cls)
     `plusFV` maybe_double
   where
-    get (ClassOpSig n _ _ ty _) 
+    get (ClassOpSig n _ ty _) 
        | n `elemNameSet` source_fvs = extractHsTyNames ty
        | otherwise                  = emptyFVs
 
@@ -724,7 +726,7 @@ reportUnusedNames mod_name direct_import_mods
        --       import This.  Sigh. 
        --       There's really no good way to detect this, so the error message 
        --       in RnEnv.warnUnusedModules is weakened instead
-       inst_mods = [m | InstD (InstDecl _ _ _ dfun _) <- imported_decls,
+       inst_mods = [m | InstD (InstDecl _ _ _ (Just dfun) _) <- imported_decls,
                         let m = moduleName (nameModule dfun),
                         m `elem` direct_import_mods
                    ]
index 80b6174..7bd630c 100644 (file)
@@ -60,9 +60,9 @@ newTopBinder mod occ
   =    -- First check the cache
     traceRn (text "newTopBinder" <+> ppr mod <+> ppr occ) `thenRn_`
 
-    getNameSupplyRn            `thenRn` \ (us, inst_ns, cache, ipcache) ->
+    getNameSupplyRn            `thenRn` \ (us, cache, ipcache) ->
     let 
-       key          = (moduleName mod, occ)
+       key = (moduleName mod, occ)
     in
     case lookupFM cache key of
 
@@ -89,7 +89,7 @@ newTopBinder mod occ
                        new_name  = setNameModule name mod
                        new_cache = addToFM cache key new_name
                     in
-                    setNameSupplyRn (us, inst_ns, new_cache, ipcache)  `thenRn_`
+                    setNameSupplyRn (us, new_cache, ipcache)   `thenRn_`
                     traceRn (text "newTopBinder: overwrite" <+> ppr new_name) `thenRn_`
                     returnRn new_name
                     
@@ -103,17 +103,20 @@ newTopBinder mod occ
                        new_name   = mkGlobalName uniq mod occ implicitImportProvenance
                        new_cache  = addToFM cache key new_name
                   in
-                  setNameSupplyRn (us', inst_ns, new_cache, ipcache)   `thenRn_`
+                  setNameSupplyRn (us', new_cache, ipcache)    `thenRn_`
                   traceRn (text "newTopBinder: new" <+> ppr new_name) `thenRn_`
                   returnRn new_name
 
 
-mkImportedGlobalName :: ModuleName -> OccName -> RnM d Name
+newGlobalName :: ModuleName -> OccName -> RnM d Name
   -- Used for *occurrences*.  We make a place-holder Name, really just
   -- to agree on its unique, which gets overwritten when we read in
   -- the binding occurence later (newImportedBinder)
   -- The place-holder Name doesn't have the right Provenance, and its
-  -- Module won't have the right Package either
+  -- Module won't have the right Package either.
+  --
+  -- (We have to pass a ModuleName, not a Module, because we may be
+  -- simply looking at an occurrence M.x in an interface file.)
   --
   -- This means that a renamed program may have incorrect info
   -- on implicitly-imported occurrences, but the correct info on the 
@@ -123,16 +126,17 @@ mkImportedGlobalName :: ModuleName -> OccName -> RnM d Name
   -- it doesn't matter that we get the correct info in place till later,
   -- (but since it affects DLL-ery it does matter that we get it right
   --  in the end).
-mkImportedGlobalName mod_name occ
-  = getNameSupplyRn            `thenRn` \ (us, inst_ns, cache, ipcache) ->
+newGlobalName mod_name occ
+  = getNameSupplyRn            `thenRn` \ (us, cache, ipcache) ->
     let
        key = (mod_name, occ)
     in
     case lookupFM cache key of
-       Just name -> traceRn (text "mkImportedGlobalName: hit" <+> ppr name) `thenRn_`
+       Just name -> traceRn (text "newGlobalName: hit" <+> ppr name) `thenRn_`
                     returnRn name
-       Nothing   -> setNameSupplyRn (us', inst_ns, new_cache, ipcache)         `thenRn_`
-                    traceRn (text "mkImportedGlobalName: new" <+> ppr name)    `thenRn_`
+
+       Nothing   -> setNameSupplyRn (us', new_cache, ipcache)          `thenRn_`
+                    traceRn (text "newGlobalName: new" <+> ppr name)   `thenRn_`
                     returnRn name
                  where
                     (us', us1) = splitUniqSupply us
@@ -141,6 +145,20 @@ mkImportedGlobalName mod_name occ
                     name       = mkGlobalName uniq mod occ implicitImportProvenance
                     new_cache  = addToFM cache key name
 
+
+newIPName rdr_name
+  = getNameSupplyRn            `thenRn` \ (us, cache, ipcache) ->
+    case lookupFM ipcache key of
+       Just name -> returnRn name
+       Nothing   -> setNameSupplyRn (us', cache, new_ipcache)  `thenRn_`
+                    returnRn name
+                 where
+                    (us', us1)  = splitUniqSupply us
+                    uniq        = uniqFromSupply us1
+                    name        = mkIPName uniq key
+                    new_ipcache = addToFM ipcache key name
+    where key = (rdrNameOcc rdr_name)
+
 updateProvenances :: [Name] -> RnM d ()
 -- Update the provenances of everything that is in scope.
 -- We must be careful not to disturb the Module package info
@@ -159,8 +177,8 @@ updateProvenances :: [Name] -> RnM d ()
 -- Step 3 must not destroy package info recorded in Step 2.
 
 updateProvenances names
-  = getNameSupplyRn            `thenRn` \ (us, inst_ns, cache, ipcache) ->
-    setNameSupplyRn (us, inst_ns, foldr update cache names, ipcache)
+  = getNameSupplyRn            `thenRn` \ (us, cache, ipcache) ->
+    setNameSupplyRn (us, foldr update cache names, ipcache)
   where
     update name cache = addToFM_C update_prov cache key name
                      where
@@ -168,76 +186,161 @@ updateProvenances names
 
     update_prov name_in_cache name_with_prov
        = setNameProvenance name_in_cache (getNameProvenance name_with_prov)
-                       
+\end{code}
+
+%*********************************************************
+%*                                                     *
+\subsection{Looking up names}
+%*                                                     *
+%*********************************************************
+
+Looking up a name in the RnEnv.
+
+\begin{code}
+lookupBndrRn rdr_name
+  = getLocalNameEnv            `thenRn` \ local_env ->
+    case lookupRdrEnv local_env rdr_name of 
+         Just name -> returnRn name
+         Nothing   -> lookupTopBndrRn rdr_name
+
+lookupTopBndrRn rdr_name
+  = getModeRn  `thenRn` \ mode ->
+    case mode of 
+       InterfaceMode ->        -- Look in the global name cache
+                           lookupOrigName rdr_name     
+
+       SourceMode    -> -- Source mode, so look up a *qualified* version
+                        -- of the name, so that we get the right one even
+                        -- if there are many with the same occ name
+                        -- There must *be* a binding
+               getModuleRn             `thenRn` \ mod ->
+               getGlobalNameEnv        `thenRn` \ global_env ->
+               case lookupRdrEnv global_env (qualifyRdrName (moduleName mod) rdr_name) of
+                 Just (name:rest) -> ASSERT( null rest )
+                                     returnRn name 
+                 Nothing          ->   -- Almost always this case is a compiler bug.
+                                       -- But consider a type signature that doesn't have 
+                                       -- a corresponding binder: 
+                                       --      module M where { f :: Int->Int }
+                                       -- We use lookupSigOccRn, which uses lookupBndrRn (for good reasons)
+                                       -- and we don't want to panic.  So we report an out-of-scope error
+                                       failWithRn (mkUnboundName rdr_name)
+                                                  (unknownNameErr rdr_name)
+
+-- lookupSigOccRn is used for type signatures and pragmas
+-- Is this valid?
+--   module A
+--     import M( f )
+--     f :: Int -> Int
+--     f x = x
+-- It's clear that the 'f' in the signature must refer to A.f
+-- The Haskell98 report does not stipulate this, but it will!
+-- So we must treat the 'f' in the signature in the same way
+-- as the binding occurrence of 'f', using lookupBndrRn
+lookupSigOccRn :: RdrName -> RnMS Name
+lookupSigOccRn = lookupBndrRn
+
+-- lookupOccRn looks up an occurrence of a RdrName
+lookupOccRn :: RdrName -> RnMS Name
+lookupOccRn rdr_name
+  = getLocalNameEnv                    `thenRn` \ local_env ->
+    case lookupRdrEnv local_env rdr_name of
+         Just name -> returnRn name
+         Nothing   -> lookupGlobalOccRn rdr_name
+
+-- lookupGlobalOccRn is like lookupOccRn, except that it looks in the global 
+-- environment.  It's used only for
+--     record field names
+--     class op names in class and instance decls
+lookupGlobalOccRn rdr_name
+  = getModeRn  `thenRn` \ mode ->
+    case mode of {
+               -- When processing interface files, the global env 
+               -- is always empty, so go straight to the name cache
+       InterfaceMode -> lookupOrigName rdr_name ;
+
+       SourceMode ->
+
+    getGlobalNameEnv   `thenRn` \ global_env ->
+    case lookupRdrEnv global_env rdr_name of
+       Just [name]         -> returnRn name
+       Just stuff@(name:_) -> addNameClashErrRn rdr_name stuff `thenRn_`
+                              returnRn name
+       Nothing ->      -- Not found when processing source code; so fail
+                       failWithRn (mkUnboundName rdr_name)
+                                  (unknownNameErr rdr_name)
+    }
+\end{code}
+%
+
+@lookupOrigName@ takes an RdrName representing an {\em original}
+name, and adds it to the occurrence pool so that it'll be loaded
+later.  This is used when language constructs (such as monad
+comprehensions, overloaded literals, or deriving clauses) require some
+stuff to be loaded that isn't explicitly mentioned in the code.
+
+This doesn't apply in interface mode, where everything is explicit,
+but we don't check for this case: it does no harm to record an
+``extra'' occurrence and @lookupOrigNames@ isn't used much in
+interface mode (it's only the @Nothing@ clause of @rnDerivs@ that
+calls it at all I think).
 
-mkImportedGlobalFromRdrName :: RdrName -> RnM d Name 
-mkImportedGlobalFromRdrName rdr_name
+  \fbox{{\em Jan 98: this comment is wrong: @rnHsType@ uses it quite a bit.}}
+
+For List and Tuple types it's important to get the correct
+@isLocallyDefined@ flag, which is used in turn when deciding
+whether there are any instance decls in this module are ``special''.
+The name cache should have the correct provenance, though.
+
+\begin{code}
+lookupOrigName :: RdrName -> RnM d Name 
+lookupOrigName rdr_name
   | isQual rdr_name
-  = mkImportedGlobalName (rdrNameModule rdr_name) (rdrNameOcc rdr_name)
+  = newGlobalName (rdrNameModule rdr_name) (rdrNameOcc rdr_name)
 
   | otherwise
   =    -- An Unqual is allowed; interface files contain 
        -- unqualified names for locally-defined things, such as
        -- constructors of a data type.
-    getModuleRn                        `thenRn ` \ mod_name ->
-    mkImportedGlobalName mod_name (rdrNameOcc rdr_name)
-
+    getModuleRn                        `thenRn ` \ mod ->
+    newGlobalName (moduleName mod) (rdrNameOcc rdr_name)
 
-getIPName rdr_name
-  = getNameSupplyRn            `thenRn` \ (us, inst_ns, cache, ipcache) ->
-    case lookupFM ipcache key of
-       Just name -> returnRn name
-       Nothing   -> setNameSupplyRn (us', inst_ns, cache, new_ipcache) `thenRn_`
-                    returnRn name
-                 where
-                    (us', us1)  = splitUniqSupply us
-                    uniq        = uniqFromSupply us1
-                    name        = mkIPName uniq key
-                    new_ipcache = addToFM ipcache key name
-    where key = (rdrNameOcc rdr_name)
+lookupOrigNames :: [RdrName] -> RnM d NameSet
+lookupOrigNames rdr_names
+  = mapRn lookupOrigName rdr_names     `thenRn` \ names ->
+    returnRn (mkNameSet names)
 \end{code}
 
-%*********************************************************
-%*                                                     *
-\subsection{Dfuns and default methods}
-%*                                                     *
-%*********************************************************
-
-@newImplicitBinder@ is used for
-       (a) dfuns               (RnSource.rnDecl on InstDecls)
-       (b) default methods     (RnSource.rnDecl on ClassDecls)
-when these dfuns/default methods are defined in the module being compiled
+lookupSysBinder is used for the "system binders" of a type, class, or instance decl.
+It ensures that the module is set correctly in the name cache, and sets the provenance
+on the returned name too.  The returned name will end up actually in the type, class,
+or instance.
 
 \begin{code}
-newImplicitBinder occ src_loc
-  = getModuleRn                                `thenRn` \ mod_name ->
-    newTopBinder (mkThisModule mod_name) occ   `thenRn` \ name ->
-    returnRn (setNameProvenance name (LocalDef src_loc Exported))
+lookupSysBinder rdr_name
+  = ASSERT( isUnqual rdr_name )
+    getModuleRn                                        `thenRn` \ mod ->
+    newTopBinder mod (rdrNameOcc rdr_name)     `thenRn` \ name ->
+    getModeRn                                  `thenRn` \ mode ->
+    case mode of
+       SourceMode    -> getSrcLocRn            `thenRn` \ loc ->
+                        returnRn (setNameProvenance name (LocalDef loc Exported))
+       InterfaceMode -> returnRn name
 \end{code}
 
-Make a name for the dict fun for an instance decl
+@unQualInScope@ returns a function that takes a @Name@ and tells whether
+its unqualified name is in scope.  This is put as a boolean flag in
+the @Name@'s provenance to guide whether or not to print the name qualified
+in error messages.
 
 \begin{code}
-newDFunName :: (OccName, OccName) -> SrcLoc -> RnMS Name
-newDFunName key@(cl_occ, tycon_occ) loc
-  = newInstUniq string `thenRn` \ inst_uniq ->
-    newImplicitBinder (mkDFunOcc string inst_uniq) loc
+unQualInScope :: GlobalRdrEnv -> Name -> Bool
+unQualInScope env
+  = lookup
   where
-       -- Any string that is somewhat unique will do
-    string = occNameString cl_occ ++ occNameString tycon_occ
-\end{code}
-
-\begin{code}
-getDFunKey :: RenamedHsType -> (OccName, OccName)      -- Used to manufacture DFun names
-getDFunKey (HsForAllTy _ _ ty)              = getDFunKey ty
-getDFunKey (HsFunTy _ ty)                   = getDFunKey ty
-getDFunKey (HsPredTy (HsPClass cls (ty:_))) = (nameOccName cls, get_tycon_key ty)
-
-get_tycon_key (HsTyVar tv)                  = getOccName tv
-get_tycon_key (HsAppTy ty _)                = get_tycon_key ty
-get_tycon_key (HsTupleTy (HsTupCon n _) tys) = getOccName n
-get_tycon_key (HsListTy _)                  = getOccName listTyCon
-get_tycon_key (HsFunTy _ _)                 = getOccName funTyCon
+    lookup name = case lookupRdrEnv env (mkRdrUnqual (nameOccName name)) of
+                          Just [name'] -> name == name'
+                          other        -> False
 \end{code}
 
 
@@ -248,7 +351,6 @@ get_tycon_key (HsFunTy _ _)              = getOccName funTyCon
 %*********************************************************
 
 \begin{code}
--------------------------------------
 bindLocatedLocalsRn :: SDoc    -- Documentation string for error message
                    -> [(RdrName,SrcLoc)]
                    -> ([Name] -> RnMS a)
@@ -265,7 +367,7 @@ bindLocatedLocalsRn doc_str rdr_names_w_loc enclosed_scope
        other                              -> returnRn ()
     )                                  `thenRn_`
        
-    getNameSupplyRn            `thenRn` \ (us, inst_ns, cache, ipcache) ->
+    getNameSupplyRn            `thenRn` \ (us, cache, ipcache) ->
     let
        n          = length rdr_names_w_loc
        (us', us1) = splitUniqSupply us
@@ -279,7 +381,7 @@ bindLocatedLocalsRn doc_str rdr_names_w_loc enclosed_scope
                     -- Keep track of whether the name originally came from 
                     -- an interface file.
     in
-    setNameSupplyRn (us', inst_ns, cache, ipcache)     `thenRn_`
+    setNameSupplyRn (us', cache, ipcache)      `thenRn_`
 
     let
        new_name_env = addListToRdrEnv name_env (map fst rdr_names_w_loc `zip` names)
@@ -304,13 +406,13 @@ bindCoreLocalFVRn :: RdrName -> (Name -> RnMS (a, FreeVars))
 bindCoreLocalFVRn rdr_name enclosed_scope
   = getSrcLocRn                `thenRn` \ loc ->
     getLocalNameEnv            `thenRn` \ name_env ->
-    getNameSupplyRn            `thenRn` \ (us, inst_ns, cache, ipcache) ->
+    getNameSupplyRn            `thenRn` \ (us, cache, ipcache) ->
     let
        (us', us1) = splitUniqSupply us
        uniq       = uniqFromSupply us1
        name       = mkImportedLocalName uniq (rdrNameOcc rdr_name) loc
     in
-    setNameSupplyRn (us', inst_ns, cache, ipcache)     `thenRn_`
+    setNameSupplyRn (us', cache, ipcache)      `thenRn_`
     let
        new_name_env = extendRdrEnv name_env rdr_name name
     in
@@ -419,145 +521,6 @@ checkDupNames doc_str rdr_names_w_loc
 \end{code}
 
 
-%*********************************************************
-%*                                                     *
-\subsection{Looking up names}
-%*                                                     *
-%*********************************************************
-
-Looking up a name in the RnEnv.
-
-\begin{code}
-lookupBndrRn rdr_name
-  = traceRn (text "lookupBndrRn" <+> ppr rdr_name)     `thenRn_`
-    getNameEnvs                `thenRn` \ (global_env, local_env) ->
-
-       -- Try local env
-    case lookupRdrEnv local_env rdr_name of {
-         Just name -> returnRn name ;
-         Nothing   ->
-
-    getModeRn  `thenRn` \ mode ->
-    case mode of 
-       InterfaceMode ->        -- Look in the global name cache
-                           mkImportedGlobalFromRdrName rdr_name                `thenRn` \ n ->
-                           traceRn (text "lookupBndrRn result:" <+> ppr n)     `thenRn_` 
-                           returnRn n
-
-       SourceMode    -> -- Source mode, so look up a *qualified* version
-                        -- of the name, so that we get the right one even
-                        -- if there are many with the same occ name
-                        -- There must *be* a binding
-               getModuleRn             `thenRn` \ mod ->
-               case lookupRdrEnv global_env (qualifyRdrName mod rdr_name) of
-                 Just (name:rest) -> ASSERT( null rest )
-                                     returnRn name 
-                 Nothing          ->   -- Almost always this case is a compiler bug.
-                                       -- But consider a type signature that doesn't have 
-                                       -- a corresponding binder: 
-                                       --      module M where { f :: Int->Int }
-                                       -- We use lookupSigOccRn, which uses lookupBndrRn (for good reasons)
-                                       -- and we don't want to panic.  So we report an out-of-scope error
-                                       failWithRn (mkUnboundName rdr_name)
-                                                  (unknownNameErr rdr_name)
-    }
-
--- lookupOccRn looks up an occurrence of a RdrName
-lookupOccRn :: RdrName -> RnMS Name
-lookupOccRn rdr_name
-  = getNameEnvs                                `thenRn` \ (global_env, local_env) ->
-    lookup_occ global_env local_env rdr_name
-
--- lookupGlobalOccRn is like lookupOccRn, except that it looks in the global 
--- environment.  It's used only for
---     record field names
---     class op names in class and instance decls
-lookupGlobalOccRn :: RdrName -> RnMS Name
-lookupGlobalOccRn rdr_name
-  = getNameEnvs                                `thenRn` \ (global_env, local_env) ->
-    lookup_global_occ global_env rdr_name
-
--- lookupSigOccRn is used for type signatures and pragmas
--- Is this valid?
---   module A
---     import M( f )
---     f :: Int -> Int
---     f x = x
--- It's clear that the 'f' in the signature must refer to A.f
--- The Haskell98 report does not stipulate this, but it will!
--- So we must treat the 'f' in the signature in the same way
--- as the binding occurrence of 'f', using lookupBndrRn
-lookupSigOccRn :: RdrName -> RnMS Name
-lookupSigOccRn = lookupBndrRn
-
-
--- Look in both local and global env
-lookup_occ global_env local_env rdr_name
-  = case lookupRdrEnv local_env rdr_name of
-         Just name -> returnRn name
-         Nothing   -> lookup_global_occ global_env rdr_name
-
--- Look in global env only
-lookup_global_occ global_env rdr_name
-  = case lookupRdrEnv global_env rdr_name of
-       Just [name]         -> returnRn name
-       Just stuff@(name:_) -> addNameClashErrRn rdr_name stuff `thenRn_`
-                              returnRn name
-       Nothing -> getModeRn    `thenRn` \ mode ->
-                  case mode of 
-                       -- Not found when processing source code; so fail
-                       SourceMode    -> failWithRn (mkUnboundName rdr_name)
-                                                   (unknownNameErr rdr_name)
-               
-                       -- Not found when processing an imported declaration,
-                       -- so we create a new name for the purpose
-                       InterfaceMode -> mkImportedGlobalFromRdrName rdr_name
-\end{code}
-%
-@lookupImplicitOccRn@ takes an RdrName representing an {\em original} name,
-and adds it to the occurrence pool so that it'll be loaded later.
-This is used when language constructs
-(such as monad comprehensions, overloaded literals, or deriving clauses)
-require some stuff to be loaded that isn't explicitly mentioned in the code.
-
-This doesn't apply in interface mode, where everything is explicit,
-but we don't check for this case:
-it does no harm to record an ``extra'' occurrence
-and @lookupImplicitOccRn@ isn't used much in interface mode
-(it's only the @Nothing@ clause of @rnDerivs@ that calls it at all I think).
-
-  \fbox{{\em Jan 98: this comment is wrong: @rnHsType@ uses it quite a bit.}}
-
-For List and Tuple types it's important to get the correct
-@isLocallyDefined@ flag, which is used in turn when deciding
-whether there are any instance decls in this module are ``special''.
-The name cache should have the correct provenance, though.
-
-\begin{code}
-lookupImplicitOccRn :: RdrName -> RnM d Name 
-lookupImplicitOccRn rdr_name = mkImportedGlobalFromRdrName rdr_name
-
-lookupImplicitOccsRn :: [RdrName] -> RnM d NameSet
-lookupImplicitOccsRn rdr_names
-  = mapRn lookupImplicitOccRn rdr_names        `thenRn` \ names ->
-    returnRn (mkNameSet names)
-\end{code}
-
-@unQualInScope@ returns a function that takes a @Name@ and tells whether
-its unqualified name is in scope.  This is put as a boolean flag in
-the @Name@'s provenance to guide whether or not to print the name qualified
-in error messages.
-
-\begin{code}
-unQualInScope :: GlobalRdrEnv -> Name -> Bool
-unQualInScope env
-  = lookup
-  where
-    lookup name = case lookupRdrEnv env (mkRdrUnqual (nameOccName name)) of
-                          Just [name'] -> name == name'
-                          other        -> False
-\end{code}
-
 %************************************************************************
 %*                                                                     *
 \subsection{Envt utility functions}
@@ -593,6 +556,7 @@ is_duplicate :: Name -> Name -> Bool
 is_duplicate n1 n2 | isLocallyDefined n1 && isLocallyDefined n2 = False
                   | otherwise                                  = n1 == n2
 \end{code}
+
 We treat two bindings of a locally-defined name as a duplicate,
 because they might be two separate, local defns and we want to report
 and error for that, {\em not} eliminate a duplicate.
index e1125a9..b5b5036 100644 (file)
@@ -85,7 +85,7 @@ rnPat (SigPatIn pat ty)
     
 rnPat (LitPatIn lit) 
   = litOccurrence lit                  `thenRn` \ fvs1 ->
-    lookupImplicitOccRn eqClass_RDR    `thenRn` \ eq   ->      -- Needed to find equality on pattern
+    lookupOrigName eqClass_RDR `thenRn` \ eq   ->      -- Needed to find equality on pattern
     returnRn (LitPatIn lit, fvs1 `addOneFV` eq)
 
 rnPat (LazyPatIn pat)
@@ -139,7 +139,7 @@ rnPat (ParPatIn pat)
 
 rnPat (NPlusKPatIn name lit)
   = litOccurrence lit                  `thenRn` \ fvs ->
-    lookupImplicitOccRn ordClass_RDR   `thenRn` \ ord ->
+    lookupOrigName ordClass_RDR        `thenRn` \ ord ->
     lookupBndrRn name                  `thenRn` \ name' ->
     returnRn (NPlusKPatIn name' lit, fvs `addOneFV` ord)
 
@@ -288,7 +288,7 @@ rnExpr (HsVar v)
        returnRn (HsVar name, unitFV name)
 
 rnExpr (HsIPVar v)
-  = getIPName v                        `thenRn` \ name ->
+  = newIPName v                        `thenRn` \ name ->
     returnRn (HsIPVar name, emptyFVs)
 
 -- Special case for integral literals with a large magnitude:
@@ -338,7 +338,7 @@ rnExpr (NegApp (HsLit (HsDoublePrim i)) _) = rnExpr (HsLit (HsDoublePrim (-i)))
 
 rnExpr (NegApp e n)
   = rnExpr e                           `thenRn` \ (e', fv_e) ->
-    lookupImplicitOccRn negate_RDR     `thenRn` \ neg ->
+    lookupOrigName negate_RDR  `thenRn` \ neg ->
     mkNegAppRn e' (HsVar neg)          `thenRn` \ final_e ->
     returnRn (final_e, fv_e `addOneFV` neg)
 
@@ -360,7 +360,7 @@ rnExpr section@(SectionR op expr)
 
 rnExpr (HsCCall fun args may_gc is_casm fake_result_ty)
        -- Check out the comment on RnIfaces.getNonWiredDataDecl about ccalls
-  = lookupImplicitOccsRn [ccallableClass_RDR, 
+  = lookupOrigNames [ccallableClass_RDR, 
                          creturnableClass_RDR, 
                          ioDataCon_RDR]        `thenRn` \ implicit_fvs ->
     rnExprs args                               `thenRn` \ (args', fvs_args) ->
@@ -389,7 +389,7 @@ rnExpr (HsWith expr binds)
 
 rnExpr e@(HsDo do_or_lc stmts src_loc)
   = pushSrcLocRn src_loc $
-    lookupImplicitOccsRn implicit_rdr_names    `thenRn` \ implicit_fvs ->
+    lookupOrigNames implicit_rdr_names `thenRn` \ implicit_fvs ->
     rnStmts rnExpr stmts                       `thenRn` \ (stmts', fvs) ->
        -- check the statement list ends in an expression
     case last stmts' of {
@@ -438,7 +438,7 @@ rnExpr (HsIf p b1 b2 src_loc)
     returnRn (HsIf p' b1' b2' src_loc, plusFVs [fvP, fvB1, fvB2])
 
 rnExpr (ArithSeqIn seq)
-  = lookupImplicitOccRn enumClass_RDR  `thenRn` \ enum ->
+  = lookupOrigName enumClass_RDR       `thenRn` \ enum ->
     rn_seq seq                         `thenRn` \ (new_seq, fvs) ->
     returnRn (ArithSeqIn new_seq, fvs `addOneFV` enum)
   where
@@ -535,7 +535,7 @@ rnRpats rpats
 \begin{code}
 rnIPBinds [] = returnRn ([], emptyFVs)
 rnIPBinds ((n, expr) : binds)
-  = getIPName n                        `thenRn` \ name ->
+  = newIPName n                        `thenRn` \ name ->
     rnExpr expr                        `thenRn` \ (expr',fvExpr) ->
     rnIPBinds binds            `thenRn` \ (binds',fvBinds) ->
     returnRn ((name, expr') : binds', fvExpr `plusFV` fvBinds)
@@ -835,11 +835,11 @@ litOccurrence (HsStringPrim _)
   = returnRn (unitFV (getName addrPrimTyCon))
 
 litOccurrence (HsInt _)
-  = lookupImplicitOccsRn [numClass_RDR, addr2Integer_RDR]
+  = lookupOrigNames [numClass_RDR, addr2Integer_RDR]
     -- Int and Integer are forced in by Num
 
 litOccurrence (HsFrac _)
-  = lookupImplicitOccsRn [fractionalClass_RDR,ratioDataCon_RDR,addr2Integer_RDR]
+  = lookupOrigNames [fractionalClass_RDR,ratioDataCon_RDR,addr2Integer_RDR]
        -- We have to make sure that the Ratio type is imported with
        -- its constructor, because literals of type Ratio t are
        -- built with that constructor.
@@ -856,7 +856,7 @@ litOccurrence (HsDoublePrim _)
   = returnRn (unitFV (getName doublePrimTyCon))
 
 litOccurrence (HsLitLit _)
-  = lookupImplicitOccRn ccallableClass_RDR     `thenRn` \ cc ->
+  = lookupOrigName ccallableClass_RDR  `thenRn` \ cc ->
     returnRn (unitFV cc)
 \end{code}
 
@@ -869,8 +869,8 @@ litOccurrence (HsLitLit _)
 \begin{code}
 mkAssertExpr :: RnMS (RenamedHsExpr, FreeVars)
 mkAssertExpr =
-  mkImportedGlobalFromRdrName assertErr_RDR            `thenRn` \ name ->
-  getSrcLocRn                                          `thenRn` \ sloc ->
+  lookupOrigName assertErr_RDR         `thenRn` \ name ->
+  getSrcLocRn                          `thenRn` \ sloc ->
 
     -- if we're ignoring asserts, return (\ _ e -> e)
     -- if not, return (assertError "src-loc")
index dbb90e5..a9e9d3e 100644 (file)
@@ -163,9 +163,9 @@ tryLoadInterface doc_str mod_name from
        --     If we do loadExport first the wrong info gets into the cache (unless we
        --      explicitly tag each export which seems a bit of a bore)
 
-    getModuleRn                `thenRn` \ this_mod_nm ->
+    getModuleRn                `thenRn` \ this_mod ->
     let
-       mod = pi_mod   iface
+       mod = pi_mod iface
     in
        -- Sanity check.  If we're system-importing a module we know nothing at all
        -- about, it should be from a different package to this one
@@ -173,12 +173,12 @@ tryLoadInterface doc_str mod_name from
          case from of { ImportBySystem -> True; other -> False } &&
          isLocalModule mod,
          ppr mod )
-    foldlRn (loadDecl mod)        (iDecls ifaces)   (pi_decls iface)   `thenRn` \ new_decls ->
-    foldlRn (loadInstDecl mod)    (iInsts ifaces)   (pi_insts iface)   `thenRn` \ new_insts ->
-    loadRules mod                 (iRules ifaces)   (pi_rules iface)   `thenRn` \ new_rules ->
-    loadFixDecls mod_name         (iFixes ifaces)   (pi_fixity iface)  `thenRn` \ new_fixities ->
-    foldlRn (loadDeprec mod)      (iDeprecs ifaces) (pi_deprecs iface) `thenRn` \ new_deprecs ->
-    mapRn (loadExport this_mod_nm) (pi_exports iface)                  `thenRn` \ avails_s ->
+    foldlRn (loadDecl mod)     (iDecls ifaces)   (pi_decls iface)      `thenRn` \ new_decls ->
+    foldlRn (loadInstDecl mod) (iInsts ifaces)   (pi_insts iface)      `thenRn` \ new_insts ->
+    loadRules mod              (iRules ifaces)   (pi_rules iface)      `thenRn` \ new_rules ->
+    loadFixDecls mod_name      (iFixes ifaces)   (pi_fixity iface)     `thenRn` \ new_fixities ->
+    foldlRn (loadDeprec mod)   (iDeprecs ifaces) (pi_deprecs iface)    `thenRn` \ new_deprecs ->
+    mapRn (loadExport this_mod) (pi_exports iface)                     `thenRn` \ avails_s ->
     let
        -- For an explicit user import, add to mod_map info about
        -- the things the imported module depends on, extracted
@@ -240,9 +240,9 @@ addModDeps mod new_deps mod_deps
 --     Loading the export list
 -----------------------------------------------------
 
-loadExport :: ModuleName -> ExportItem -> RnM d [AvailInfo]
+loadExport :: Module -> ExportItem -> RnM d [AvailInfo]
 loadExport this_mod (mod, entities)
-  | mod == this_mod = returnRn []
+  | mod == moduleName this_mod = returnRn []
        -- If the module exports anything defined in this module, just ignore it.
        -- Reason: otherwise it looks as if there are two local definition sites
        -- for the thing, and an error gets reported.  Easiest thing is just to
@@ -262,7 +262,7 @@ loadExport this_mod (mod, entities)
   | otherwise
   = mapRn (load_entity mod) entities
   where
-    new_name mod occ = mkImportedGlobalName mod occ
+    new_name mod occ = newGlobalName mod occ
 
     load_entity mod (Avail occ)
       =        new_name mod occ        `thenRn` \ name ->
@@ -347,7 +347,7 @@ loadFixDecls mod_name fixity_env (version, decls)
     returnRn (extendNameEnvList fixity_env to_add)
 
 loadFixDecl mod_name sig@(FixitySig rdr_name fixity loc)
-  = mkImportedGlobalName mod_name (rdrNameOcc rdr_name)        `thenRn` \ name ->
+  = newGlobalName mod_name (rdrNameOcc rdr_name)       `thenRn` \ name ->
     returnRn (name, FixitySig name fixity loc)
 
 
@@ -374,8 +374,8 @@ loadInstDecl mod insts decl@(InstDecl inst_ty binds uprags dfun_name src_loc)
        munged_inst_ty = removeContext inst_ty
        free_names     = extractHsTyRdrNames munged_inst_ty
     in
-    setModuleRn (moduleName mod) $
-    mapRn mkImportedGlobalFromRdrName free_names       `thenRn` \ gate_names ->
+    setModuleRn mod $
+    mapRn lookupOrigName free_names    `thenRn` \ gate_names ->
     returnRn ((mkNameSet gate_names, (mod, InstD decl)) `consBag` insts)
 
 
@@ -401,17 +401,15 @@ loadRules mod rule_bag (version, rules)
   | null rules || opt_IgnoreIfacePragmas 
   = returnRn rule_bag
   | otherwise
-  = setModuleRn mod_name               $
+  = setModuleRn mod                    $
     mapRn (loadRule mod) rules         `thenRn` \ new_rules ->
     returnRn (rule_bag `unionBags` listToBag new_rules)
-  where
-    mod_name = moduleName mod
 
 loadRule :: Module -> RdrNameRuleDecl -> RnM d GatedDecl
 -- "Gate" the rule simply by whether the rule variable is
 -- needed.  We can refine this later.
 loadRule mod decl@(IfaceRule _ _ var _ _ src_loc)
-  = mkImportedGlobalFromRdrName var            `thenRn` \ var_name ->
+  = lookupOrigName var         `thenRn` \ var_name ->
     returnRn (unitNameSet var_name, (mod, RuleD decl))
 
 loadBuiltinRules :: [(RdrName, CoreRule)] -> RnMG ()
@@ -421,7 +419,7 @@ loadBuiltinRules builtin_rules
     setIfacesRn (ifaces { iRules = iRules ifaces `unionBags` listToBag rule_decls })
 
 loadBuiltinRule (var, rule)
-  = mkImportedGlobalFromRdrName var            `thenRn` \ var_name ->
+  = lookupOrigName var         `thenRn` \ var_name ->
     returnRn (unitNameSet var_name, (nameModule var_name, RuleD (IfaceRuleOut var rule)))
 
 
@@ -436,8 +434,8 @@ loadDeprec mod deprec_env (Deprecation (IEModuleContents _) txt _)
     returnRn deprec_env
 
 loadDeprec mod deprec_env (Deprecation ie txt _)
-  = setModuleRn (moduleName mod) $
-    mapRn mkImportedGlobalFromRdrName (ieNames ie) `thenRn` \ names ->
+  = setModuleRn mod                                    $
+    mapRn lookupOrigName (ieNames ie)          `thenRn` \ names ->
     traceRn (text "loaded deprecation(s) for" <+> hcat (punctuate comma (map ppr names)) <> colon <+> ppr txt) `thenRn_`
     returnRn (extendNameEnvList deprec_env (zip names (repeat txt)))
 \end{code}
@@ -529,7 +527,7 @@ checkEntityUsage mod decls []
   = returnRn upToDate  -- Yes!  All up to date!
 
 checkEntityUsage mod decls ((occ_name,old_vers) : rest)
-  = mkImportedGlobalName mod occ_name  `thenRn` \ name ->
+  = newGlobalName mod occ_name         `thenRn` \ name ->
     case lookupNameEnv decls name of
 
        Nothing       ->        -- We used it before, but it ain't there now
@@ -1051,8 +1049,8 @@ getDeclBinders new_name (ForD (ForeignDecl nm kind _ dyn _ loc))
   = new_name nm loc                `thenRn` \ name ->
     returnRn (Just (Avail name))
 
-  | otherwise -- a foreign export
-  = lookupImplicitOccRn nm `thenRn_` 
+  | otherwise          -- a foreign export
+  = lookupOrigName nm `thenRn_` 
     returnRn Nothing
 
 getDeclBinders new_name (DefD _)  = returnRn Nothing
@@ -1083,7 +1081,7 @@ getConFieldNames new_name (ConDecl con _ _ _ condecl src_loc : rest)
 
 getConFieldNames new_name [] = returnRn []
 
-getClassOpNames new_name (ClassOpSig op _ _ _ src_loc) = new_name op src_loc
+getClassOpNames new_name (ClassOpSig op _ _ src_loc) = new_name op src_loc
 \end{code}
 
 @getDeclSysBinders@ gets the implicit binders introduced by a decl.
index 457f2c1..609f423 100644 (file)
@@ -107,7 +107,7 @@ type RnMG r  = RnM ()    r          -- Getting global names etc
 
        -- Common part
 data RnDown = RnDown {
-                 rn_mod     :: ModuleName,
+                 rn_mod     :: Module,
                  rn_loc     :: SrcLoc,
                  rn_ns      :: IORef RnNameSupply,
                  rn_errs    :: IORef (Bag WarnMsg, Bag ErrMsg),
@@ -175,19 +175,6 @@ type DeprecationEnv = NameEnv DeprecTxt
 type RnNameSupply
  = ( UniqSupply
 
-   , FiniteMap String Int
-       -- This is used as a name supply for dictionary functions
-       -- From the inst decl we derive a string, usually by glomming together
-       -- the class and tycon name -- but it doesn't matter exactly how;
-       -- this map then gives a unique int for each inst decl with that
-       -- string.  (In Haskell 98 there can only be one,
-       -- but not so in more extended versions; also class CC type T
-       -- and class C type TT might both give the string CCT
-       --      
-       -- We could just use one Int for all the instance decls, but this
-       -- way the uniques change less when you add an instance decl,   
-       -- hence less recompilation
-
    , FiniteMap (ModuleName, OccName) Name
        -- Ensures that one (module,occname) pair gets one unique
    , FiniteMap OccName Name
@@ -363,13 +350,13 @@ type DeclsMap = NameEnv (Version, AvailInfo, Bool, (Module, RdrNameHsDecl))
 %************************************************************************
 
 \begin{code}
-initRn :: ModuleName -> UniqSupply -> SearchPath -> SrcLoc
+initRn :: Module -> UniqSupply -> SearchPath -> SrcLoc
        -> RnMG r
        -> IO (r, Bag ErrMsg, Bag WarnMsg)
 
 initRn mod us dirs loc do_rn = do
   himaps    <- mkModuleHiMaps dirs
-  names_var <- newIORef (us, emptyFM, builtins, emptyFM)
+  names_var <- newIORef (us, builtins, emptyFM)
   errs_var  <- newIORef (emptyBag,emptyBag)
   iface_var <- newIORef emptyIfaces 
   let
@@ -399,7 +386,7 @@ initRnMS rn_env fixity_env mode thing_inside rn_down g_down
 initIfaceRnMS :: Module -> RnMS r -> RnM d r
 initIfaceRnMS mod thing_inside 
   = initRnMS emptyRdrEnv emptyNameEnv InterfaceMode $
-    setModuleRn (moduleName mod) thing_inside
+    setModuleRn mod thing_inside
 
 emptyIfaces :: Ifaces
 emptyIfaces = Ifaces { iImpModInfo = emptyFM,
@@ -432,12 +419,12 @@ The @RnNameSupply@ includes a @UniqueSupply@, so if you call it more than
 once you must either split it, or install a fresh unique supply.
 
 \begin{code}
-renameSourceCode :: ModuleName
+renameSourceCode :: Module
                 -> RnNameSupply
                 -> RnMS r
                 -> r
 
-renameSourceCode mod_name name_supply m
+renameSourceCode mod name_supply m
   = unsafePerformIO (
        -- It's not really unsafe!  When renaming source code we
        -- only do any I/O if we need to read in a fixity declaration;
@@ -449,7 +436,7 @@ renameSourceCode mod_name name_supply m
        let
            rn_down = RnDown { rn_loc = mkGeneratedSrcLoc, rn_ns = names_var,
                               rn_errs = errs_var, rn_hi_maps = himaps,
-                              rn_mod = mod_name, 
+                              rn_mod = mod, 
                               rn_ifaces = panic "rnameSourceCode: rn_ifaces"  -- Not required
                             }
            s_down = SDown { rn_mode = InterfaceMode,
@@ -625,26 +612,13 @@ setNameSupplyRn :: RnNameSupply -> RnM d ()
 setNameSupplyRn names' (RnDown {rn_ns = names_var}) l_down
   = writeIORef names_var names'
 
--- See comments with RnNameSupply above.
-newInstUniq :: String -> RnM d Int
-newInstUniq key (RnDown {rn_ns = names_var}) l_down
-  = readIORef names_var                                >>= \ (us, mapInst, cache, ipcache) ->
-    let
-       uniq = case lookupFM mapInst key of
-                  Just x  -> x+1
-                  Nothing -> 0
-       mapInst' = addToFM mapInst key uniq
-    in
-    writeIORef names_var (us, mapInst', cache, ipcache) >>
-    return uniq
-
 getUniqRn :: RnM d Unique
 getUniqRn (RnDown {rn_ns = names_var}) l_down
- = readIORef names_var >>= \ (us, mapInst, cache, ipcache) ->
+ = readIORef names_var >>= \ (us, cache, ipcache) ->
    let
      (us1,us') = splitUniqSupply us
    in
-   writeIORef names_var (us', mapInst, cache, ipcache)  >>
+   writeIORef names_var (us', cache, ipcache)  >>
    return (uniqFromSupply us1)
 \end{code}
 
@@ -653,11 +627,11 @@ getUniqRn (RnDown {rn_ns = names_var}) l_down
 %=====================
 
 \begin{code}
-getModuleRn :: RnM d ModuleName
-getModuleRn (RnDown {rn_mod = mod_name}) l_down
-  = return mod_name
+getModuleRn :: RnM d Module
+getModuleRn (RnDown {rn_mod = mod}) l_down
+  = return mod
 
-setModuleRn :: ModuleName -> RnM d a -> RnM d a
+setModuleRn :: Module -> RnM d a -> RnM d a
 setModuleRn new_mod enclosed_thing rn_down l_down
   = enclosed_thing (rn_down {rn_mod = new_mod}) l_down
 \end{code}
@@ -682,6 +656,10 @@ getLocalNameEnv :: RnMS LocalRdrEnv
 getLocalNameEnv rn_down (SDown {rn_lenv = local_env})
   = return local_env
 
+getGlobalNameEnv :: RnMS GlobalRdrEnv
+getGlobalNameEnv rn_down (SDown {rn_genv = global_env})
+  = return global_env
+
 setLocalNameEnv :: LocalRdrEnv -> RnMS a -> RnMS a
 setLocalNameEnv local_env' m rn_down l_down
   = m rn_down (l_down {rn_lenv = local_env'})
index 7bcd565..0af917b 100644 (file)
@@ -82,7 +82,6 @@ getGlobalNames (HsModule this_mod _ exports imports decls _ mod_loc)
           rec_exp_fn :: Name -> ExportFlag
           rec_exp_fn = mk_export_fn (availsToNameSet rec_export_avails)
        in
-       setModuleRn this_mod                    $
 
                -- PROCESS LOCAL DECLS
                -- Do these *first* so that the correct provenance gets
@@ -255,7 +254,7 @@ improveAvails imp_mod iloc explicits is_unqual avails
 
 \begin{code}
 importsFromLocalDecls mod_name rec_exp_fn decls
-  = mapRn (getLocalDeclBinders newLocalName) decls     `thenRn` \ avails_s ->
+  = mapRn (getLocalDeclBinders mod rec_exp_fn) decls   `thenRn` \ avails_s ->
 
     let
        avails = concat avails_s
@@ -282,39 +281,34 @@ importsFromLocalDecls mod_name rec_exp_fn decls
   where
     mod = mkThisModule mod_name
 
-    newLocalName rdr_name loc 
-       = check_unqual rdr_name loc                     `thenRn_`
-         newTopBinder mod (rdrNameOcc rdr_name)        `thenRn` \ name ->
-         returnRn (setNameProvenance name (LocalDef loc (rec_exp_fn name)))
-
-       -- There should never be a qualified name in a binding position (except in instance decls)
-       -- The parser doesn't check this because the same parser parses instance decls
-    check_unqual rdr_name loc
-       | isUnqual rdr_name = returnRn ()
-       | otherwise         = qualNameErr (text "the binding for" <+> quotes (ppr rdr_name)) 
-                                         (rdr_name,loc)
-
-getLocalDeclBinders :: (RdrName -> SrcLoc -> RnMG Name)        -- New-name function
-                   -> RdrNameHsDecl
-                   -> RnMG Avails
-getLocalDeclBinders new_name (ValD binds)
+getLocalDeclBinders :: Module -> (Name -> ExportFlag)
+                   -> RdrNameHsDecl -> RnMG Avails
+getLocalDeclBinders mod rec_exp_fn (ValD binds)
   = mapRn do_one (bagToList (collectTopBinders binds))
   where
-    do_one (rdr_name, loc) = new_name rdr_name loc     `thenRn` \ name ->
+    do_one (rdr_name, loc) = newLocalName mod rec_exp_fn rdr_name loc  `thenRn` \ name ->
                             returnRn (Avail name)
 
-getLocalDeclBinders new_name decl
-  = getDeclBinders new_name decl       `thenRn` \ maybe_avail ->
+getLocalDeclBinders mod rec_exp_fn decl
+  = getDeclBinders (newLocalName mod rec_exp_fn) decl  `thenRn` \ maybe_avail ->
     case maybe_avail of
        Nothing    -> returnRn []               -- Instance decls and suchlike
-       Just avail -> getDeclSysBinders new_sys_name decl               `thenRn_`  
-                     returnRn [avail]
+       Just avail -> returnRn [avail]
+
+newLocalName mod rec_exp_fn rdr_name loc 
+  = check_unqual rdr_name loc                  `thenRn_`
+    newTopBinder mod (rdrNameOcc rdr_name)     `thenRn` \ name ->
+    returnRn (setNameProvenance name (LocalDef loc (rec_exp_fn name)))
   where
-       -- The getDeclSysBinders is just to get the names of superclass selectors
-       -- etc, into the cache
-    new_sys_name rdr_name loc = newImplicitBinder (rdrNameOcc rdr_name) loc
+       -- There should never be a qualified name in a binding position (except in instance decls)
+       -- The parser doesn't check this because the same parser parses instance decls
+    check_unqual rdr_name loc
+       | isUnqual rdr_name = returnRn ()
+       | otherwise         = qualNameErr (text "the binding for" <+> quotes (ppr rdr_name)) 
+                                         (rdr_name,loc)
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
 \subsection{Filtering imports}
index b458ed8..360ebd4 100644 (file)
@@ -21,14 +21,12 @@ import RnHsSyn
 import HsCore
 
 import RnBinds         ( rnTopBinds, rnMethodBinds, renameSigs, unknownSigErr )
-import RnEnv           ( bindTyVarsRn, lookupBndrRn, lookupOccRn, getIPName,
-                         lookupImplicitOccRn, lookupImplicitOccsRn,
+import RnEnv           ( bindTyVarsRn, lookupTopBndrRn, lookupOccRn, newIPName,
+                         lookupOrigName, lookupOrigNames, lookupSysBinder,
                          bindLocalsRn, bindLocalRn, bindLocalsFVRn, bindUVarRn,
                          bindTyVarsFVRn, bindTyVarsFV2Rn, extendTyVarEnvFVRn,
                          bindCoreLocalFVRn, bindCoreLocalsFVRn, bindLocalNames,
                          checkDupOrQualNames, checkDupNames,
-                         mkImportedGlobalName, mkImportedGlobalFromRdrName,
-                         newDFunName, getDFunKey, newImplicitBinder,
                          FreeVars, emptyFVs, plusFV, plusFVs, unitFV, 
                          addOneFV, mapFvRn
                        )
@@ -114,7 +112,7 @@ rnDecl (ValD binds) = rnTopBinds binds      `thenRn` \ (new_binds, fvs) ->
 
 rnDecl (SigD (IfaceSig name ty id_infos loc))
   = pushSrcLocRn loc $
-    mkImportedGlobalFromRdrName name   `thenRn` \ name' ->
+    lookupTopBndrRn name               `thenRn` \ name' ->
     rnHsType doc_str ty                        `thenRn` \ (ty',fvs1) ->
     mapFvRn rnIdInfo id_infos          `thenRn` \ (id_infos', fvs2) -> 
     returnRn (SigD (IfaceSig name' ty' id_infos' loc), fvs1 `plusFV` fvs2)
@@ -144,7 +142,7 @@ However, we can also do some scoping checks at the same time.
 \begin{code}
 rnDecl (TyClD (TyData new_or_data context tycon tyvars condecls nconstrs derivings pragmas src_loc))
   = pushSrcLocRn src_loc $
-    lookupBndrRn tycon                         `thenRn` \ tycon' ->
+    lookupTopBndrRn tycon                      `thenRn` \ tycon' ->
     bindTyVarsFVRn data_doc tyvars             $ \ tyvars' ->
     rnContext data_doc context                         `thenRn` \ (context', cxt_fvs) ->
     checkDupOrQualNames data_doc con_names     `thenRn_`
@@ -160,7 +158,7 @@ rnDecl (TyClD (TyData new_or_data context tycon tyvars condecls nconstrs derivin
 
 rnDecl (TyClD (TySynonym name tyvars ty src_loc))
   = pushSrcLocRn src_loc $
-    lookupBndrRn name                          `thenRn` \ name' ->
+    lookupTopBndrRn name                       `thenRn` \ name' ->
     bindTyVarsFVRn syn_doc tyvars              $ \ tyvars' ->
     rnHsType syn_doc (unquantify ty)           `thenRn` \ (ty', ty_fvs) ->
     returnRn (TyClD (TySynonym name' tyvars' ty' src_loc), ty_fvs)
@@ -176,7 +174,7 @@ rnDecl (TyClD (ClassDecl context cname tyvars fds sigs mbinds pragmas
                tname dname dwname snames src_loc))
   = pushSrcLocRn src_loc $
 
-    lookupBndrRn cname                                 `thenRn` \ cname' ->
+    lookupTopBndrRn cname                      `thenRn` \ cname' ->
 
        -- Deal with the implicit tycon and datacon name
        -- They aren't in scope (because they aren't visible to the user)
@@ -185,10 +183,10 @@ rnDecl (TyClD (ClassDecl context cname tyvars fds sigs mbinds pragmas
        -- So the 'Imported' part of this call is not relevant. 
        -- Unclean; but since these two are the only place this happens
        -- I can't work up the energy to do it more beautifully
-    mkImportedGlobalFromRdrName tname                  `thenRn` \ tname' ->
-    mkImportedGlobalFromRdrName dname                  `thenRn` \ dname' ->
-    mkImportedGlobalFromRdrName dwname                 `thenRn` \ dwname' ->
-    mapRn mkImportedGlobalFromRdrName snames           `thenRn` \ snames' ->
+    lookupSysBinder tname                      `thenRn` \ tname' ->
+    lookupSysBinder dname                      `thenRn` \ dname' ->
+    lookupSysBinder dwname                     `thenRn` \ dwname' ->
+    mapRn lookupSysBinder snames               `thenRn` \ snames' ->
 
        -- Tyvars scope over bindings and context
     bindTyVarsFV2Rn cls_doc tyvars             ( \ clas_tyvar_names tyvars' ->
@@ -207,14 +205,13 @@ rnDecl (TyClD (ClassDecl context cname tyvars fds sigs mbinds pragmas
     checkDupOrQualNames sig_doc sig_rdr_names_w_locs     `thenRn_` 
     mapFvRn (rn_op cname' clas_tyvar_names fds') op_sigs  `thenRn` \ (sigs', sig_fvs) ->
     let
-     binders = mkNameSet [ nm | (ClassOpSig nm _ _ _ _) <- sigs' ]
+     binders = mkNameSet [ nm | (ClassOpSig nm _ _ _) <- sigs' ]
     in
     renameSigs (okClsDclSig binders) non_op_sigs         `thenRn` \ (non_ops', fix_fvs) ->
 
        -- Check the methods
     checkDupOrQualNames meth_doc meth_rdr_names_w_locs `thenRn_`
-    rnMethodBinds mbinds
-    `thenRn` \ (mbinds', meth_fvs) ->
+    rnMethodBinds mbinds                               `thenRn` \ (mbinds', meth_fvs) ->
 
        -- Typechecker is responsible for checking that we only
        -- give default-method bindings for things in this class.
@@ -236,13 +233,12 @@ rnDecl (TyClD (ClassDecl context cname tyvars fds sigs mbinds pragmas
     sig_doc  = text "the signatures for class"         <+> ppr cname
     meth_doc = text "the default-methods for class"    <+> ppr cname
 
-    sig_rdr_names_w_locs  = [(op,locn) | ClassOpSig op _ _ _ locn <- sigs]
+    sig_rdr_names_w_locs  = [(op,locn) | ClassOpSig op _ _ locn <- sigs]
     meth_rdr_names_w_locs = bagToList (collectMonoBinders mbinds)
-    meth_rdr_names       = map fst meth_rdr_names_w_locs
 
-    rn_op clas clas_tyvars clas_fds sig@(ClassOpSig op dm_rdr_name explicit_dm ty locn)
+    rn_op clas clas_tyvars clas_fds sig@(ClassOpSig op maybe_dm_stuff ty locn)
       = pushSrcLocRn locn $
-       lookupBndrRn op                         `thenRn` \ op_name ->
+       lookupTopBndrRn op                      `thenRn` \ op_name ->
 
                -- Check the signature
        rnHsSigType (quotes (ppr op)) ty        `thenRn` \ (new_ty, op_ty_fvs)  ->
@@ -254,23 +250,21 @@ rnDecl (TyClD (ClassDecl context cname tyvars fds sigs mbinds pragmas
         mapRn_ check_in_op_ty clas_tyvars               `thenRn_`
 
                -- Make the default-method name
-       getModeRn                                       `thenRn` \ mode ->
-       (case mode of 
-           SourceMode -> -- Source class decl
-                  newImplicitBinder (mkDefaultMethodOcc (rdrNameOcc op)) locn     `thenRn` \ dm_name ->
-                  returnRn (dm_name, op `elem` meth_rdr_names, emptyFVs)
+       (case maybe_dm_stuff of 
+           Nothing -> returnRn (Nothing, emptyFVs)             -- Source-file class decl
 
-           InterfaceMode
+           Just (dm_rdr_name, explicit_dm)
                ->      -- Imported class that has a default method decl
                        -- See comments with tname, snames, above
-                   lookupImplicitOccRn dm_rdr_name     `thenRn` \ dm_name ->
-                   returnRn (dm_name, explicit_dm, if explicit_dm then unitFV dm_name else emptyFVs)
+                   lookupSysBinder dm_rdr_name         `thenRn` \ dm_name ->
+                   returnRn (Just (dm_name, explicit_dm), 
+                             if explicit_dm then unitFV dm_name else emptyFVs)
                        -- An imported class decl for a class decl that had an explicit default
                        -- method, mentions, rather than defines,
                        -- the default method, so we must arrange to pull it in
-       )                                               `thenRn` \ (dm_name, final_explicit_dm, dm_fvs) ->
+       )                                               `thenRn` \ (maybe_dm_stuff', dm_fvs) ->
 
-       returnRn (ClassOpSig op_name dm_name final_explicit_dm new_ty locn, op_ty_fvs `plusFV` dm_fvs)
+       returnRn (ClassOpSig op_name maybe_dm_stuff' new_ty locn, op_ty_fvs `plusFV` dm_fvs)
 \end{code}
 
 
@@ -281,7 +275,7 @@ rnDecl (TyClD (ClassDecl context cname tyvars fds sigs mbinds pragmas
 %*********************************************************
 
 \begin{code}
-rnDecl (InstD (InstDecl inst_ty mbinds uprags dfun_rdr_name src_loc))
+rnDecl (InstD (InstDecl inst_ty mbinds uprags maybe_dfun_rdr_name src_loc))
   = pushSrcLocRn src_loc $
     rnHsSigType (text "an instance decl") inst_ty `thenRn` \ (inst_ty', inst_fvs) ->
     let
@@ -313,18 +307,15 @@ rnDecl (InstD (InstDecl inst_ty mbinds uprags dfun_rdr_name src_loc))
        renameSigs (okInstDclSig binder_set) uprags
     )                                                  `thenRn` \ (new_uprags, prag_fvs) ->
 
-    getModeRn          `thenRn` \ mode ->
-    (case mode of
-       InterfaceMode -> lookupImplicitOccRn dfun_rdr_name      `thenRn` \ dfun_name ->
-                        returnRn (dfun_name, unitFV dfun_name)
-       SourceMode    -> newDFunName (getDFunKey inst_ty') src_loc
-                         `thenRn` \ dfun_name ->
-                        returnRn (dfun_name, emptyFVs)
-    )
-    `thenRn` \ (dfun_name, dfun_fv) ->
+    (case maybe_dfun_rdr_name of
+       Nothing            -> returnRn (Nothing, emptyFVs)
+
+       Just dfun_rdr_name -> lookupSysBinder dfun_rdr_name     `thenRn` \ dfun_name ->
+                             returnRn (Just dfun_name, unitFV dfun_name)
+    )                                                  `thenRn` \ (maybe_dfun_name, dfun_fv) ->
 
     -- The typechecker checks that all the bindings are for the right class.
-    returnRn (InstD (InstDecl inst_ty' mbinds' new_uprags dfun_name src_loc),
+    returnRn (InstD (InstDecl inst_ty' mbinds' new_uprags maybe_dfun_name src_loc),
              inst_fvs `plusFV` meth_fvs `plusFV` prag_fvs `plusFV` dfun_fv)
   where
     meth_doc = text "the bindings in an instance declaration"
@@ -358,11 +349,10 @@ rnDecl (ForD (ForeignDecl name imp_exp ty ext_nm cconv src_loc))
     lookupOccRn name                   `thenRn` \ name' ->
     let 
        extra_fvs FoExport 
-         | isDyn = 
-               lookupImplicitOccsRn [makeStablePtr_RDR, deRefStablePtr_RDR,
-                                     bindIO_RDR, returnIO_RDR]
-         | otherwise = 
-               lookupImplicitOccsRn [bindIO_RDR, returnIO_RDR] `thenRn` \ fvs ->
+         | isDyn = lookupOrigNames [makeStablePtr_RDR, deRefStablePtr_RDR,
+                                    bindIO_RDR, returnIO_RDR]
+         | otherwise =
+               lookupOrigNames [bindIO_RDR, returnIO_RDR] `thenRn` \ fvs ->
                returnRn (addOneFV fvs name')
        extra_fvs other = returnRn emptyFVs
     in
@@ -465,10 +455,10 @@ conDeclName (ConDecl n _ _ _ _ l) = (n,l)
 rnConDecl :: RdrNameConDecl -> RnMS (RenamedConDecl, FreeVars)
 rnConDecl (ConDecl name wkr tvs cxt details locn)
   = pushSrcLocRn locn $
-    checkConName name                  `thenRn_` 
-    lookupBndrRn name                  `thenRn` \ new_name ->
+    checkConName name          `thenRn_` 
+    lookupTopBndrRn name       `thenRn` \ new_name ->
 
-    mkImportedGlobalFromRdrName wkr    `thenRn` \ new_wkr ->
+    lookupSysBinder wkr                `thenRn` \ new_wkr ->
        -- See comments with ClassDecl
 
     bindTyVarsFVRn doc tvs             $ \ new_tyvars ->
@@ -495,7 +485,7 @@ rnConDetails doc locn (NewCon ty mb_field)
   where
     rn_field Nothing  = returnRn Nothing
     rn_field (Just f) =
-       lookupBndrRn f      `thenRn` \ new_f ->
+       lookupTopBndrRn f           `thenRn` \ new_f ->
        returnRn (Just new_f)
 
 rnConDetails doc locn (RecCon fields)
@@ -506,7 +496,7 @@ rnConDetails doc locn (RecCon fields)
     field_names = [(fld, locn) | (flds, _) <- fields, fld <- flds]
 
 rnField doc (names, ty)
-  = mapRn lookupBndrRn names   `thenRn` \ new_names ->
+  = mapRn lookupTopBndrRn names        `thenRn` \ new_names ->
     rnBangTy doc ty            `thenRn` \ (new_ty, fvs) ->
     returnRn ((new_names, new_ty), fvs) 
 
@@ -697,7 +687,7 @@ rnPred doc (HsPClass clas tys)
     returnRn (HsPClass clas_name tys', fvs `addOneFV` clas_name)
 
 rnPred doc (HsPIParam n ty)
-  = getIPName n                        `thenRn` \ name ->
+  = newIPName n                        `thenRn` \ name ->
     rnHsType doc ty            `thenRn` \ (ty', fvs) ->
     returnRn (HsPIParam name ty', fvs)
 \end{code}
index 91cb81c..b2821ad 100644 (file)
@@ -15,6 +15,7 @@ import Id             ( Id, idType )
 import CoreUtils       ( hashExpr, cheapEqExpr, exprIsBig, mkAltExpr )
 import DataCon         ( isUnboxedTupleCon )
 import Type            ( splitTyConApp_maybe )
+import Subst           ( InScopeSet, uniqAway, emptyInScopeSet, extendInScopeSet, elemInScopeSet )
 import CoreSyn
 import VarEnv  
 import CoreLint                ( beginPass, endPass )
@@ -42,21 +43,26 @@ so that a subsequent binding
        y2 = C y1 b
 will get transformed to C x1 b, and then to x2.  
 
-So we carry an extra var->var mapping which we apply *before* looking up in the
+So we carry an extra var->var substitution which we apply *before* looking up in the
 reverse mapping.
 
 
 IMPORTANT NOTE
 ~~~~~~~~~~~~~~
-This pass relies on the no-shadowing invariant, so it must run
-immediately after the simplifier.
-
+We have to be careful about shadowing.
 For example, consider
        f = \x -> let y = x+x in
                      h = \x -> x+x
                  in ...
 
-Here we must *not* do CSE on the inner x+x!
+Here we must *not* do CSE on the inner x+x!  The simplifier used to guarantee no
+shadowing, but it doesn't any more (it proved too hard), so we clone as we go.
+We can simply add clones to the substitution already described.
+
+However, we do NOT clone type variables.  It's just too hard, because then we need
+to run the substitution over types and IdInfo.  No no no.  Instead, we just throw
+away the entire reverse mapping if this unusual situation ever shows up.   
+(In fact, I think the simplifier does guarantee no-shadowing for type variables.)
 
 
 Another important wrinkle
@@ -72,7 +78,8 @@ But that's not quite obvious.  In general we want to keep it as (wild1:as),
 but for CSE purpose that's a bad idea.
 
 So we add the binding (wild1 -> a) to the extra var->var mapping.
-
+Notice this is exactly backwards to what the simplifier does, which is
+to try to replaces uses of a with uses of wild1
 
 Yet another wrinkle
 ~~~~~~~~~~~~~~~~~~~
@@ -82,7 +89,10 @@ Consider
 We'd like to replace (h x) in the alternative, by y.  But because of
 the preceding "Another important wrinkle", we only want to add the mapping
        scrutinee -> case binder
-to the CSE mapping if the scrutinee is a non-trivial expression.
+to the reverse CSE mapping if the scrutinee is a non-trivial expression.
+(If the scrutinee is a simple variable we want to add the mapping
+       case binder -> scrutinee 
+to the substitution
 
 
 %************************************************************************
@@ -118,11 +128,11 @@ cseBind env (Rec pairs)  = let (env', pairs') = mapAccumL do_one env pairs
                         
 
 do_one env (id, rhs) = case lookupCSEnv env rhs' of
-                         Just other_id -> (extendSubst env id other_id, (id, Var other_id))
-                         Nothing       -> (addCSEnvItem env id rhs',    (id, rhs'))
+                         Just other_id -> (extendSubst env' id other_id, (id', Var other_id))
+                         Nothing       -> (addCSEnvItem env' id' rhs',   (id', rhs'))
                     where
-                       rhs' = cseExpr env rhs
-
+                       (env', id') = addBinder env id
+                       rhs'        = cseExpr env' rhs
 
 tryForCSE :: CSEnv -> CoreExpr -> CoreExpr
 tryForCSE env (Type t) = Type t
@@ -138,24 +148,26 @@ cseExpr env (Lit lit)                = Lit lit
 cseExpr env (Var v)               = Var (lookupSubst env v)
 cseExpr env (App f a)             = App (cseExpr env f) (tryForCSE env a)
 cseExpr env (Note n e)            = Note n (cseExpr env e)
-cseExpr env (Lam b e)             = Lam b (cseExpr env e)
-cseExpr env (Let bind e)          = let (env1, bind') = cseBind env bind
-                                    in Let bind' (cseExpr env1 e)
-cseExpr env (Case scrut bndr alts) = Case scrut' bndr (cseAlts env scrut' bndr alts)
+cseExpr env (Lam b e)             = let (env', b') = addBinder env b
+                                    in Lam b' (cseExpr env' e)
+cseExpr env (Let bind e)          = let (env', bind') = cseBind env bind
+                                    in Let bind' (cseExpr env' e)
+cseExpr env (Case scrut bndr alts) = Case scrut' bndr' (cseAlts env' scrut' bndr bndr' alts)
                                   where
                                     scrut' = tryForCSE env scrut
+                                    (env', bndr') = addBinder env bndr
 
 
-cseAlts env new_scrut bndr alts
+cseAlts env scrut' bndr bndr' alts
   = map cse_alt alts
   where
     (con_target, alt_env)
-       = case new_scrut of
-               Var v -> (v,    extendSubst env bndr v)         -- See "another important wrinkle"
-                                                               -- map: bndr -> v
+       = case scrut' of
+               Var v' -> (v',    extendSubst env bndr v')      -- See "another important wrinkle"
+                                                               -- map: bndr -> v'
 
-               other -> (bndr, extendCSEnv env bndr new_scrut) -- See "yet another wrinkle"
-                                                               -- map: new_scrut -> bndr
+               other ->  (bndr', extendCSEnv env bndr' scrut') -- See "yet another wrinkle"
+                                                               -- map: scrut' -> bndr'
 
     arg_tys = case splitTyConApp_maybe (idType bndr) of
                Just (_, arg_tys) -> arg_tys
@@ -169,12 +181,15 @@ cseAlts env new_scrut bndr alts
                -- Don't replace True by x!  
                -- Hence the 'null args', which also deal with literals and DEFAULT
                -- And we can't CSE on unboxed tuples
-       = (DataAlt con, args, tryForCSE new_env rhs)
+       = (DataAlt con, args', tryForCSE new_env rhs)
        where
-         new_env = extendCSEnv alt_env con_target (mkAltExpr (DataAlt con) args arg_tys)
+         (env', args') = addBinders alt_env args
+         new_env       = extendCSEnv env' con_target (mkAltExpr (DataAlt con) args' arg_tys)
 
     cse_alt (con, args, rhs)
-       = (con, args, tryForCSE alt_env rhs)
+       = (con, args', tryForCSE env' rhs)
+       where
+         (env', args') = addBinders alt_env args
 \end{code}
 
 
@@ -185,13 +200,18 @@ cseAlts env new_scrut bndr alts
 %************************************************************************
 
 \begin{code}
-data CSEnv = CS (UniqFM [(Id, CoreExpr)])      -- The expr in the range has already been CSE'd
-               (IdEnv Id)                      -- Simple substitution
+data CSEnv = CS CSEMap InScopeSet (IdEnv Id)
+                       -- Simple substitution
+
+type CSEMap = UniqFM [(Id, CoreExpr)]  -- This is the reverse mapping
+       -- It maps the hash-code of an expression to list of (x,e) pairs
+       -- This means that it's good to replace e by x
+       -- INVARIANT: The expr in the range has already been CSE'd
 
-emptyCSEnv = CS emptyUFM emptyVarEnv
+emptyCSEnv = CS emptyUFM emptyInScopeSet emptyVarEnv
 
 lookupCSEnv :: CSEnv -> CoreExpr -> Maybe Id
-lookupCSEnv (CS cs _) expr
+lookupCSEnv (CS cs _ _) expr
   = case lookupUFM cs (hashExpr expr) of
        Nothing -> Nothing
        Just pairs -> lookup_list pairs expr
@@ -204,8 +224,8 @@ lookup_list ((x,e):es) expr | cheapEqExpr e expr = Just x
 addCSEnvItem env id expr | exprIsBig expr = env
                         | otherwise      = extendCSEnv env id expr
 
-extendCSEnv (CS cs sub) id expr
-  = CS (addToUFM_C combine cs hash [(id, expr)]) sub
+extendCSEnv (CS cs in_scope sub) id expr
+  = CS (addToUFM_C combine cs hash [(id, expr)]) in_scope sub
   where
     hash   = hashExpr expr
     combine old new = WARN( length result > 4, text "extendCSEnv: long list:" <+> ppr result )
@@ -213,9 +233,24 @@ extendCSEnv (CS cs sub) id expr
                    where
                      result = new ++ old
 
-lookupSubst (CS _ sub) x = case lookupVarEnv sub x of
-                            Just y  -> y
-                            Nothing -> x
+lookupSubst (CS _ _ sub) x = case lookupVarEnv sub x of
+                              Just y  -> y
+                              Nothing -> x
+
+extendSubst (CS cs in_scope sub) x y = CS cs in_scope (extendVarEnv sub x y)
+
+addBinder :: CSEnv -> Id -> (CSEnv, Id)
+addBinder env@(CS cs in_scope sub) v
+  | not (v `elemInScopeSet` in_scope) = (CS cs (extendInScopeSet in_scope v)  sub,                    v)
+  | isId v                           = (CS cs (extendInScopeSet in_scope v') (extendVarEnv sub v v'), v')
+  | not (isId v)                     = WARN( True, ppr v )
+                                       (CS emptyUFM in_scope                 sub,                     v)
+       -- This last case is the unusual situation where we have shadowing of
+       -- a type variable; we have to discard the CSE mapping
+       -- See "IMPORTANT NOTE" at the top 
+  where
+    v' = uniqAway in_scope v
 
-extendSubst (CS cs sub) x y = CS cs (extendVarEnv sub x y)
+addBinders :: CSEnv -> [Id] -> (CSEnv, [Id])
+addBinders env vs = mapAccumL addBinder env vs
 \end{code}
index 4d856f7..b7d7c22 100644 (file)
@@ -97,12 +97,10 @@ where exp is exported, and loc is not, then we replace it with this:
        exp = <expression>
        ...
 
-Without this we never get rid of the exp = loc thing.
-This save a gratuitous jump
-(from \tr{x_exported} to \tr{x_local}), and makes strictness
-information propagate better.
-This used to happen in the final phase, but it's tidier to do it here.
-
+Without this we never get rid of the exp = loc thing.  This save a
+gratuitous jump (from \tr{x_exported} to \tr{x_local}), and makes
+strictness information propagate better.  This used to happen in the
+final phase, but it's tidier to do it here.
 
 If more than one exported thing is equal to a local thing (i.e., the
 local thing really is shared), then we do one only:
@@ -144,7 +142,10 @@ occurAnalyseBinds binds
     go :: OccEnv -> [CoreBind]
        -> (UsageDetails,       -- Occurrence info
           IdEnv Id,            -- Indirection elimination info
-          [CoreBind])
+                               --   Maps local-id -> exported-id, but it embodies
+                               --   bindings of the form exported-id = local-id in
+                               --   the argument to go
+          [CoreBind])          -- Occ-analysed bindings, less the exported-id=local-id ones
 
     go env [] = (emptyDetails, emptyVarEnv, [])
 
@@ -449,13 +450,24 @@ reOrderRec env (CyclicSCC (bind : binds))
          
     score :: Node Details2 -> Int      -- Higher score => less likely to be picked as loop breaker
     score ((bndr, rhs), _, _)
-       | exprIsTrivial rhs && 
-         not (isExportedId bndr)  = 3          -- Practically certain to be inlined
-       | inlineCandidate bndr rhs = 3          -- Likely to be inlined
-       | not_fun_ty (idType bndr) = 2          -- Data types help with cases
+       | exprIsTrivial rhs        = 4  -- Practically certain to be inlined
+               -- Used to have also: && not (isExportedId bndr)
+               -- But I found this sometimes cost an extra iteration when we have
+               --      rec { d = (a,b); a = ...df...; b = ...df...; df = d }
+               -- where df is the exported dictionary. Then df makes a really
+               -- bad choice for loop breaker
+         
+       | not_fun_ty (idType bndr) = 3  -- Data types help with cases
+               -- This used to have a lower score than inlineCandidate, but
+               -- it's *really* helpful if dictionaries get inlined fast,
+               -- so I'm experimenting with giving higher priority to data-typed things
+
+       | inlineCandidate bndr rhs = 2  -- Likely to be inlined
+
        | not (isEmptyCoreRules (idSpecialisation bndr)) = 1
                -- Avoid things with specialisations; we'd like
                -- to take advantage of them in the subsequent bindings
+
        | otherwise = 0
 
     inlineCandidate :: Id -> CoreExpr -> Bool
index 51a4676..517d2d9 100644 (file)
 
 3. We clone the binders of any floatable let-binding, so that when it is
    floated out it will be unique.  (This used to be done by the simplifier
-   but the latter now only ensures that there's no shadowing.)
+   but the latter now only ensures that there's no shadowing; indeed, even 
+   that may not be true.)
+
+   NOTE: this can't be done using the uniqAway idea, because the variable
+        must be unique in the whole program, not just its current scope,
+        because two variables in different scopes may float out to the
+        same top level place
+
    NOTE: Very tiresomely, we must apply this substitution to
         the rules stored inside a variable too.
 
@@ -441,6 +448,8 @@ lvlFloatRhs abs_vars dest_lvl env rhs
 \begin{code}
 lvlLamBndrs :: Level -> [CoreBndr] -> (Level, [(CoreBndr, Level)])
 -- Compute the levels for the binders of a lambda group
+-- The binders returned are exactly the same as the ones passed,
+-- but they are now paired with a level
 lvlLamBndrs lvl [] 
   = (lvl, [])
 
@@ -527,7 +536,8 @@ isFunction other                   = False
 \begin{code}
 type LevelEnv = (Bool,                                 -- True <=> Float lambdas too
                 VarEnv Level,                  -- Domain is *post-cloned* TyVars and Ids
-                SubstEnv,                      -- Domain is pre-cloned Ids
+                Subst,                         -- Domain is pre-cloned Ids; tracks the in-scope set
+                                               --      so that subtitution is capture-avoiding
                 IdEnv ([Var], LevelledExpr))   -- Domain is pre-cloned Ids
        -- We clone let-bound variables so that they are still
        -- distinct when floated out; hence the SubstEnv/IdEnv.
@@ -535,7 +545,7 @@ type LevelEnv = (Bool,                              -- True <=> Float lambdas too
        -- We also use these envs when making a variable polymorphic
        -- because we want to float it out past a big lambda.
        --
-       -- The two Envs always implement the same mapping, but the
+       -- The SubstEnv and IdEnv always implement the same mapping, but the
        -- SubstEnv maps to CoreExpr and the IdEnv to LevelledExpr
        -- Since the range is always a variable or type application,
        -- there is never any difference between the two, but sadly
@@ -551,25 +561,25 @@ type LevelEnv = (Bool,                            -- True <=> Float lambdas too
        -- The domain of the VarEnv Level is the *post-cloned* Ids
 
 initialEnv :: Bool -> LevelEnv
-initialEnv float_lams = (float_lams, emptyVarEnv, emptySubstEnv, emptyVarEnv)
+initialEnv float_lams = (float_lams, emptyVarEnv, emptySubst, emptyVarEnv)
 
 floatLams :: LevelEnv -> Bool
 floatLams (float_lams, _, _, _) = float_lams
 
 extendLvlEnv :: LevelEnv -> [(Var,Level)] -> LevelEnv
 -- Used when *not* cloning
-extendLvlEnv (float_lams, lvl_env, subst_env, id_env) prs
+extendLvlEnv (float_lams, lvl_env, subst, id_env) prs
   = (float_lams,
      foldl add_lvl lvl_env prs,
-     foldl del_subst subst_env prs,
+     foldl del_subst subst prs,
      foldl del_id id_env prs)
   where
     add_lvl   env (v,l) = extendVarEnv env v l
-    del_subst env (v,_) = delSubstEnv env v
+    del_subst env (v,_) = extendInScope env v
     del_id    env (v,_) = delVarEnv env v
   -- We must remove any clone for this variable name in case of
-  -- shadowing.  This bit me in the following case (in
-  -- nofib/real/gg/Spark.hs):
+  -- shadowing.  This bit me in the following case
+  -- (in nofib/real/gg/Spark.hs):
   -- 
   --   case ds of wild {
   --     ... -> case e of wild {
@@ -588,25 +598,25 @@ extendCaseBndrLvlEnv env scrut case_bndr lvl
        Var v -> extendCloneLvlEnv lvl env [(case_bndr, v)]
        other -> extendLvlEnv          env [(case_bndr,lvl)]
 
-extendPolyLvlEnv dest_lvl (float_lams, lvl_env, subst_env, id_env) abs_vars bndr_pairs
+extendPolyLvlEnv dest_lvl (float_lams, lvl_env, subst, id_env) abs_vars bndr_pairs
   = (float_lams,
-     foldl add_lvl   lvl_env   bndr_pairs,
-     foldl add_subst subst_env bndr_pairs,
-     foldl add_id    id_env    bndr_pairs)
+     foldl add_lvl   lvl_env bndr_pairs,
+     foldl add_subst subst   bndr_pairs,
+     foldl add_id    id_env  bndr_pairs)
   where
-     add_lvl   env (v,v') = extendVarEnv   env v' dest_lvl
-     add_subst env (v,v') = extendSubstEnv env v (DoneEx (mkVarApps (Var v') abs_vars))
-     add_id    env (v,v') = extendVarEnv   env v ((v':abs_vars), mkVarApps (Var v') abs_vars)
+     add_lvl   env (v,v') = extendVarEnv env v' dest_lvl
+     add_subst env (v,v') = extendSubst  env v (DoneEx (mkVarApps (Var v') abs_vars))
+     add_id    env (v,v') = extendVarEnv env v ((v':abs_vars), mkVarApps (Var v') abs_vars)
 
-extendCloneLvlEnv lvl (float_lams, lvl_env, subst_env, id_env) bndr_pairs
+extendCloneLvlEnv lvl (float_lams, lvl_env, subst, id_env) bndr_pairs
   = (float_lams,
-     foldl add_lvl lvl_env bndr_pairs,
-     foldl add_subst subst_env bndr_pairs,
-     foldl add_id    id_env    bndr_pairs)
+     foldl add_lvl   lvl_env bndr_pairs,
+     foldl add_subst subst   bndr_pairs,
+     foldl add_id    id_env  bndr_pairs)
   where
-     add_lvl   env (v,v') = extendVarEnv   env v' lvl
-     add_subst env (v,v') = extendSubstEnv env v (DoneEx (Var v'))
-     add_id    env (v,v') = extendVarEnv   env v ([v'], Var v')
+     add_lvl   env (v,v') = extendVarEnv env v' lvl
+     add_subst env (v,v') = extendSubst  env v (DoneEx (Var v'))
+     add_id    env (v,v') = extendVarEnv env v ([v'], Var v')
 
 
 maxIdLevel :: LevelEnv -> VarSet -> Level
@@ -718,11 +728,9 @@ cloneVars NotTopLevel env vs ctxt_lvl dest_lvl
     in
     returnUs (env', vs'')
 
-subst_id_info (_, _, subst_env, _) ctxt_lvl dest_lvl v
+subst_id_info (_, _, subst, _) ctxt_lvl dest_lvl v
     = modifyIdInfo (\info -> substIdInfo subst info (zap_dmd info)) v
   where
-    subst = mkSubst emptyVarSet subst_env
-
        -- VERY IMPORTANT: we must zap the demand info 
        -- if the thing is going to float out past a lambda
     zap_dmd info
index 0321bf7..ddca237 100644 (file)
@@ -16,7 +16,7 @@ import CmdLineOpts    ( CoreToDo(..), SimplifierSwitch(..),
                          opt_D_dump_rules,
                          opt_D_verbose_core2core,
                          opt_D_dump_occur_anal,
-                          opt_UsageSPOn,
+                          opt_UsageSPOn
                        )
 import CoreLint                ( beginPass, endPass )
 import CoreSyn
index 697fb71..e7dd9c7 100644 (file)
@@ -15,7 +15,7 @@ module SimplMonad (
        mapSmpl, mapAndUnzipSmpl, mapAccumLSmpl,
 
        -- The inlining black-list
-       getBlackList,
+       setBlackList, getBlackList, noInlineBlackList,
 
         -- Unique supply
         getUniqueSmpl, getUniquesSmpl,
@@ -37,10 +37,9 @@ module SimplMonad (
        getEnv, setAllExceptInScope,
        getSubst, setSubst,
        getSubstEnv, extendSubst, extendSubstList,
-       getInScope, setInScope, extendInScope, extendInScopes, modifyInScope,
+       getInScope, setInScope, modifyInScope, addNewInScopeIds,
        setSubstEnv, zapSubstEnv,
-       getSimplBinderStuff, setSimplBinderStuff,
-       switchOffInlining
+       getSimplBinderStuff, setSimplBinderStuff
     ) where
 
 #include "HsVersions.h"
@@ -56,7 +55,7 @@ import VarEnv
 import VarSet
 import qualified Subst
 import Subst           ( Subst, mkSubst, substEnv, 
-                         InScopeSet, substInScope, isInScope
+                         InScopeSet, mkInScopeSet, substInScope, isInScope
                        )
 import Type             ( Type )
 import UniqSupply      ( uniqsFromSupply, uniqFromSupply, splitUniqSupply,
@@ -124,11 +123,13 @@ type SimplM result                -- We thread the unique supply because
   -> SimplCount 
   -> (result, UniqSupply, SimplCount)
 
+type BlackList = Id -> Bool    -- True =>  don't inline this Id
+
 data SimplEnv
   = SimplEnv {
        seChkr      :: SwitchChecker,
        seCC        :: CostCentreStack, -- The enclosing CCS (when profiling)
-       seBlackList :: Id -> Bool,      -- True =>  don't inline this Id
+       seBlackList :: BlackList,
        seSubst     :: Subst            -- The current substitution
     }
        -- The range of the substitution is OutType and OutExpr resp
@@ -153,7 +154,7 @@ data SimplEnv
 initSmpl :: SwitchChecker
         -> UniqSupply          -- No init count; set to 0
         -> VarSet              -- In scope (usually empty, but useful for nested calls)
-        -> (Id -> Bool)        -- Black-list function
+        -> BlackList           -- Black-list function
         -> SimplM a
         -> (a, SimplCount)
 
@@ -494,7 +495,7 @@ getSimplIntSwitch chkr switch
 \end{code}
 
 
-@switchOffInlining@ is used to prepare the environment for simplifying
+@setBlackList@ is used to prepare the environment for simplifying
 the RHS of an Id that's marked with an INLINE pragma.  It is going to
 be inlined wherever they are used, and then all the inlining will take
 effect.  Meanwhile, there isn't much point in doing anything to the
@@ -521,10 +522,7 @@ and        (b) Consider the following example
        then we won't get deforestation at all.
        We havn't solved this problem yet!
 
-We prepare the envt by simply modifying the in_scope_env, which has all the
-unfolding info. At one point we did it by modifying the chkr so that
-it said "EssentialUnfoldingsOnly", but that prevented legitmate, and
-important, simplifications happening in the body of the RHS.
+We prepare the envt by simply modifying the black list.
 
 6/98 update: 
 
@@ -544,31 +542,27 @@ must-inlineable. We don't generate any code for a superclass
 selector, so failing to inline it in the RHS of `f' will
 leave a reference to a non-existent id, with bad consequences.
 
-ALSO NOTE that we do all this by modifing the inline-pragma,
+ALSO NOTE that we do all this by modifing the black list
 not by zapping the unfolding.  The latter may still be useful for
 knowing when something is evaluated.
 
-June 98 update: I've gone back to dealing with this by adding
-the EssentialUnfoldingsOnly switch.  That doesn't stop essential
-unfoldings, nor inlineUnconditionally stuff; and the thing's going
-to be inlined at every call site anyway.  Running over the whole
-environment seems like wild overkill.
-
 \begin{code}
-switchOffInlining :: SimplM a -> SimplM a
-switchOffInlining m env us sc
-  = m (env { seBlackList = \v -> not (isCompulsoryUnfolding (idUnfolding v)) &&
-                                not (isDataConWrapId v) &&
-                                ((v `isInScope` subst) || not (isLocallyDefined v))
-          }) us sc
-       
+setBlackList :: BlackList -> SimplM a -> SimplM a
+setBlackList black_list m env us sc = m (env { seBlackList = black_list }) us sc
+
+getBlackList :: SimplM BlackList
+getBlackList env us sc = (seBlackList env, us, sc)
+
+noInlineBlackList :: BlackList
        -- Inside inlinings, black list anything that is in scope or imported.
        -- except for things that must be unfolded (Compulsory)
        -- and data con wrappers.  The latter is a hack, like the one in
-       -- SimplCore.simplRules, to make wrappers inline in rule LHSs.  We
-       -- may as well do the same here.
-  where
-    subst         = seSubst env
+       -- SimplCore.simplRules, to make wrappers inline in rule LHSs.
+       -- We may as well do the same here.
+noInlineBlackList v = not (isCompulsoryUnfolding (idUnfolding v)) &&
+                     not (isDataConWrapId v)
+       --                              ((v `isInScope` subst) || not (isLocallyDefined v))
+       -- I don't see why we have these conditions
 \end{code}
 
 
@@ -595,12 +589,12 @@ setEnclosingCC cc m env us sc = m (env { seCC = cc }) us sc
 
 
 \begin{code}
-emptySimplEnv :: SwitchChecker -> InScopeSet -> (Id -> Bool) -> SimplEnv
+emptySimplEnv :: SwitchChecker -> VarSet -> (Id -> Bool) -> SimplEnv
 
 emptySimplEnv sw_chkr in_scope black_list
   = SimplEnv { seChkr = sw_chkr, seCC = subsumedCCS,
               seBlackList = black_list,
-              seSubst = mkSubst in_scope emptySubstEnv }
+              seSubst = mkSubst (mkInScopeSet in_scope) emptySubstEnv }
        -- The top level "enclosing CC" is "SUBSUMED".
 
 getEnv :: SimplM SimplEnv
@@ -614,22 +608,16 @@ setAllExceptInScope new_env@(SimplEnv {seSubst = new_subst}) m
 getSubst :: SimplM Subst
 getSubst env us sc = (seSubst env, us, sc)
 
-getBlackList :: SimplM (Id -> Bool)
-getBlackList env us sc = (seBlackList env, us, sc)
-
 setSubst :: Subst -> SimplM a -> SimplM a
 setSubst subst m env us sc = m (env {seSubst = subst}) us sc
 
 getSubstEnv :: SimplM SubstEnv
 getSubstEnv env us sc = (substEnv (seSubst env), us, sc)
 
-extendInScope :: CoreBndr -> SimplM a -> SimplM a
-extendInScope v m env@(SimplEnv {seSubst = subst}) us sc
-  = m (env {seSubst = Subst.extendInScope subst v}) us sc
-
-extendInScopes :: [CoreBndr] -> SimplM a -> SimplM a
-extendInScopes vs m env@(SimplEnv {seSubst = subst}) us sc
-  = m (env {seSubst = Subst.extendInScopes subst vs}) us sc
+addNewInScopeIds :: [CoreBndr] -> SimplM a -> SimplM a
+       -- The new Ids are guaranteed to be freshly allocated
+addNewInScopeIds  vs m env@(SimplEnv {seSubst = subst}) us sc
+  = m (env {seSubst = Subst.extendNewInScopeList subst vs}) us sc
 
 getInScope :: SimplM InScopeSet
 getInScope env us sc = (substInScope (seSubst env), us, sc)
@@ -673,14 +661,14 @@ newId :: UserFS -> Type -> (Id -> SimplM a) -> SimplM a
        -- Extends the in-scope-env too
 newId fs ty m env@(SimplEnv {seSubst = subst}) us sc
   =  case splitUniqSupply us of
-       (us1, us2) -> m v (env {seSubst = Subst.extendInScope subst v}) us2 sc
+       (us1, us2) -> m v (env {seSubst = Subst.extendNewInScope subst v}) us2 sc
                   where
                      v = mkSysLocal fs (uniqFromSupply us1) ty
 
 newIds :: UserFS -> [Type] -> ([Id] -> SimplM a) -> SimplM a
 newIds fs tys m env@(SimplEnv {seSubst = subst}) us sc
   =  case splitUniqSupply us of
-       (us1, us2) -> m vs (env {seSubst = Subst.extendInScopes subst vs}) us2 sc
+       (us1, us2) -> m vs (env {seSubst = Subst.extendNewInScopeList subst vs}) us2 sc
                   where
                      vs = zipWithEqual "newIds" (mkSysLocal fs) 
                                        (uniqsFromSupply (length tys) us1) tys
index 544a791..90a759d 100644 (file)
@@ -11,33 +11,39 @@ module SimplUtils (
 
        -- The continuation type
        SimplCont(..), DupFlag(..), contIsDupable, contResultType,
-       pushArgs, discardCont, countValArgs, countArgs,
-       analyseCont, discardInline
+       countValArgs, countArgs,
+       getContArgs, interestingCallContext, interestingArg, isStrictType, discardInline
 
     ) where
 
 #include "HsVersions.h"
 
-import CmdLineOpts     ( opt_SimplDoLambdaEtaExpansion, opt_SimplCaseMerge )
+import CmdLineOpts     ( switchIsOn, SimplifierSwitch(..),
+                         opt_SimplDoLambdaEtaExpansion, opt_SimplCaseMerge, opt_DictsStrict
+                       )
 import CoreSyn
 import CoreUnfold      ( isValueUnfolding )
 import CoreUtils       ( exprIsTrivial, cheapEqExpr, exprType, exprIsCheap, exprEtaExpandArity, bindNonRec )
 import Subst           ( InScopeSet, mkSubst, substBndrs, substBndr, substIds, lookupIdSubst )
 import Id              ( Id, idType, isId, idName, 
-                         idOccInfo, idUnfolding,
+                         idOccInfo, idUnfolding, idStrictness,
                          mkId, idInfo
                        )
-import IdInfo          ( arityLowerBound, setOccInfo, vanillaIdInfo )
+import IdInfo          ( StrictnessInfo(..), arityLowerBound, setOccInfo, vanillaIdInfo )
 import Maybes          ( maybeToBool, catMaybes )
 import Name            ( isLocalName, setNameUnique )
+import Demand          ( Demand, isStrict, wwLazy, wwLazy )
 import SimplMonad
 import Type            ( Type, tyVarsOfType, tyVarsOfTypes, mkForAllTys, seqType, repType,
-                         splitTyConApp_maybe, mkTyVarTys, applyTys, splitFunTys, mkFunTys
+                         splitTyConApp_maybe, mkTyVarTys, applyTys, splitFunTys, mkFunTys,
+                         isDictTy, isDataType, applyTy, splitFunTy, isUnLiftedType,
+                         splitRepFunTys
                        )
 import TyCon           ( tyConDataConsIfAvailable )
 import DataCon         ( dataConRepArity )
 import VarSet
 import VarEnv          ( SubstEnv, SubstResult(..) )
+import Util            ( lengthExceeds )
 import Outputable
 \end{code}
 
@@ -69,11 +75,12 @@ data SimplCont              -- Strict contexts
   | ArgOf    DupFlag           -- An arbitrary strict context: the argument 
                                --      of a strict function, or a primitive-arg fn
                                --      or a PrimOp
-            OutType            -- The type of the expression being sought by the context
+            OutType            -- cont_ty: the type of the expression being sought by the context
                                --      f (error "foo") ==> coerce t (error "foo")
                                -- when f is strict
                                -- We need to know the type t, to which to coerce.
             (OutExpr -> SimplM OutExprStuff)   -- What to do with the result
+                               -- The result expression in the OutExprStuff has type cont_ty
 
 instance Outputable SimplCont where
   ppr (Stop _)                      = ptext SLIT("Stop")
@@ -90,6 +97,7 @@ instance Outputable DupFlag where
   ppr OkToDup = ptext SLIT("ok")
   ppr NoDup   = ptext SLIT("nodup")
 
+-------------------
 contIsDupable :: SimplCont -> Bool
 contIsDupable (Stop _)                  = True
 contIsDupable (ApplyTo  OkToDup _ _ _)   = True
@@ -99,9 +107,18 @@ contIsDupable (CoerceIt _ cont)          = contIsDupable cont
 contIsDupable (InlinePlease cont)       = contIsDupable cont
 contIsDupable other                     = False
 
-pushArgs :: SubstEnv -> [InExpr] -> SimplCont -> SimplCont
-pushArgs se []         cont = cont
-pushArgs se (arg:args) cont = ApplyTo NoDup arg se (pushArgs se args cont)
+-------------------
+discardInline :: SimplCont -> SimplCont
+discardInline (InlinePlease cont)  = cont
+discardInline (ApplyTo d e s cont) = ApplyTo d e s (discardInline cont)
+discardInline cont                = cont
+
+-------------------
+discardableCont :: SimplCont -> Bool
+discardableCont (Stop _)           = False
+discardableCont (CoerceIt _ cont)   = discardableCont cont
+discardableCont (InlinePlease cont) = discardableCont cont
+discardableCont other              = True
 
 discardCont :: SimplCont       -- A continuation, expecting
            -> SimplCont        -- Replace the continuation with a suitable coerce
@@ -110,6 +127,7 @@ discardCont cont     = CoerceIt to_ty (Stop to_ty)
                         where
                           to_ty = contResultType cont
 
+-------------------
 contResultType :: SimplCont -> OutType
 contResultType (Stop to_ty)         = to_ty
 contResultType (ArgOf _ to_ty _)     = to_ty
@@ -118,6 +136,7 @@ contResultType (CoerceIt _ cont)     = contResultType cont
 contResultType (InlinePlease cont)   = contResultType cont
 contResultType (Select _ _ _ _ cont) = contResultType cont
 
+-------------------
 countValArgs :: SimplCont -> Int
 countValArgs (ApplyTo _ (Type ty) se cont) = countValArgs cont
 countValArgs (ApplyTo _ val_arg   se cont) = 1 + countValArgs cont
@@ -129,8 +148,132 @@ countArgs other                     = 0
 \end{code}
 
 
-Comment about analyseCont
-~~~~~~~~~~~~~~~~~~~~~~~~~
+\begin{code}
+getContArgs :: OutId -> SimplCont 
+           -> SimplM ([(InExpr, SubstEnv, Bool)],      -- Arguments; the Bool is true for strict args
+                       SimplCont,                      -- Remaining continuation
+                       Bool)                           -- Whether we came across an InlineCall
+-- getContArgs id k = (args, k', inl)
+--     args are the leading ApplyTo items in k
+--     (i.e. outermost comes first)
+--     augmented with demand info from the functionn
+getContArgs fun orig_cont
+  = getSwitchChecker   `thenSmpl` \ chkr ->
+    let
+               -- Ignore strictness info if the no-case-of-case
+               -- flag is on.  Strictness changes evaluation order
+               -- and that can change full laziness
+       stricts | switchIsOn chkr NoCaseOfCase = vanilla_stricts
+               | otherwise                    = computed_stricts
+    in
+    go [] stricts False orig_cont
+  where
+    ----------------------------
+
+       -- Type argument
+    go acc ss inl (ApplyTo _ arg@(Type _) se cont)
+       = go ((arg,se,False) : acc) ss inl cont
+               -- NB: don't bother to instantiate the function type
+
+       -- Value argument
+    go acc (s:ss) inl (ApplyTo _ arg se cont)
+       = go ((arg,se,s) : acc) ss inl cont
+
+       -- An Inline continuation
+    go acc ss inl (InlinePlease cont)
+       = go acc ss True cont
+
+       -- We're run out of arguments, or else we've run out of demands
+       -- The latter only happens if the result is guaranteed bottom
+       -- This is the case for
+       --      * case (error "hello") of { ... }
+       --      * (error "Hello") arg
+       --      * f (error "Hello") where f is strict
+       --      etc
+    go acc ss inl cont 
+       | null ss && discardableCont cont = tick BottomFound    `thenSmpl_`
+                                           returnSmpl (reverse acc, discardCont cont, inl)
+       | otherwise                       = returnSmpl (reverse acc, cont,             inl)
+
+    ----------------------------
+    vanilla_stricts, computed_stricts :: [Bool]
+    vanilla_stricts  = repeat False
+    computed_stricts = zipWith (||) fun_stricts arg_stricts
+
+    ----------------------------
+    (val_arg_tys, _) = splitRepFunTys (idType fun)
+    arg_stricts      = map isStrictType val_arg_tys ++ repeat False
+       -- These argument types are used as a cheap and cheerful way to find
+       -- unboxed arguments, which must be strict.  But it's an InType
+       -- and so there might be a type variable where we expect a function
+       -- type (the substitution hasn't happened yet).  And we don't bother
+       -- doing the type applications for a polymorphic function.
+       -- Hence the split*Rep*FunTys
+
+    ----------------------------
+       -- If fun_stricts is finite, it means the function returns bottom
+       -- after that number of value args have been consumed
+       -- Otherwise it's infinite, extended with False
+    fun_stricts
+      = case idStrictness fun of
+         StrictnessInfo demands result_bot 
+               | not (demands `lengthExceeds` countValArgs orig_cont)
+               ->      -- Enough args, use the strictness given.
+                       -- For bottoming functions we used to pretend that the arg
+                       -- is lazy, so that we don't treat the arg as an
+                       -- interesting context.  This avoids substituting
+                       -- top-level bindings for (say) strings into 
+                       -- calls to error.  But now we are more careful about
+                       -- inlining lone variables, so its ok (see SimplUtils.analyseCont)
+                  if result_bot then
+                       map isStrict demands            -- Finite => result is bottom
+                  else
+                       map isStrict demands ++ vanilla_stricts
+
+         other -> vanilla_stricts      -- Not enough args, or no strictness
+
+
+-------------------
+isStrictType :: Type -> Bool
+       -- isStrictType computes whether an argument (or let RHS) should
+       -- be computed strictly or lazily, based only on its type
+isStrictType ty
+  | isUnLiftedType ty                              = True
+  | opt_DictsStrict && isDictTy ty && isDataType ty = True
+  | otherwise                                      = False 
+       -- Return true only for dictionary types where the dictionary
+       -- has more than one component (else we risk poking on the component
+       -- of a newtype dictionary)
+
+-------------------
+interestingArg :: InScopeSet -> InExpr -> SubstEnv -> Bool
+       -- An argument is interesting if it has *some* structure
+       -- We are here trying to avoid unfolding a function that
+       -- is applied only to variables that have no unfolding
+       -- (i.e. they are probably lambda bound): f x y z
+       -- There is little point in inlining f here.
+interestingArg in_scope arg subst
+  = analyse arg
+  where
+    analyse (Var v)
+       = case lookupIdSubst (mkSubst in_scope subst) v of
+           DoneId v' _ -> hasSomeUnfolding (idUnfolding v')
+                                       -- was: isValueUnfolding (idUnfolding v')
+                                       -- But that seems over-pessimistic
+
+           other       -> True         -- was: False
+                                       -- But that is *definitely* too pessimistic.
+                                       -- E.g.         let x = 3 in f 
+                                       -- Here, x will be unconditionally substituted, via
+                                       -- the substitution!
+    analyse (Type _)         = False
+    analyse (App fn (Type _)) = analyse fn
+    analyse (Note _ a)       = analyse a
+    analyse other            = True
+\end{code}
+
+Comment about interestingCallContext
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 We want to avoid inlining an expression where there can't possibly be
 any gain, such as in an argument position.  Hence, if the continuation
 is interesting (eg. a case scrutinee, application etc.) then we
@@ -163,13 +306,9 @@ contIsInteresting looks for case expressions with just a single
 default case.
 
 \begin{code}
-analyseCont :: InScopeSet -> SimplCont
-           -> ([Bool],         -- Arg-info flags; one for each value argument
-               Bool,           -- Context of the result of the call is interesting
-               Bool)           -- There was an InlinePlease 
-
-analyseCont in_scope cont 
-  = case cont of
+interestingCallContext :: Bool                 -- False <=> no args at all
+                      -> Bool          -- False <=> no value args
+                      -> SimplCont -> Bool
        -- The "lone-variable" case is important.  I spent ages
        -- messing about with unsatisfactory varaints, but this is nice.
        -- The idea is that if a variable appear all alone
@@ -197,59 +336,23 @@ analyseCont in_scope cont
        -- However, even a type application isn't a lone variable.  Consider
        --      case $fMonadST @ RealWorld of { :DMonad a b c -> c }
        -- We had better inline that sucker!  The case won't see through it.
-
-      (Stop _)                   -> boring_result              -- Don't inline a lone variable
-      (Select _ _ _ _ _)         -> boring_result              -- Ditto
-      (ArgOf _ _ _)              -> boring_result              -- Ditto
-      (ApplyTo _ (Type _) _ cont) -> analyse_ty_app cont
-      other                      -> analyse_app cont
+       --
+       -- For now, I'm treating treating a variable applied to types as
+       -- "lone". The motivating example was
+       --      f = /\a. \x. BIG
+       --      g = /\a. \y.  h (f a)
+       -- There's no advantage in inlining f here, and perhaps
+       -- a significant disadvantage.  Hence some_val_args in the Stop case
+
+interestingCallContext some_args some_val_args cont
+  = interesting cont
   where
-    boring_result = ([], False, False)
-
-               -- For now, I'm treating not treating a variable applied to types as
-               -- "lone". The motivating example was
-               --      f = /\a. \x. BIG
-               --      g = /\a. \y.  h (f a)
-               -- There's no advantage in inlining f here, and perhaps
-               -- a significant disadvantage.
-    analyse_ty_app (Stop _)                    = boring_result
-    analyse_ty_app (ArgOf _ _ _)               = boring_result
-    analyse_ty_app (Select _ _ _ _ _)          = ([], True, False)     -- See the $fMonadST example above
-    analyse_ty_app (ApplyTo _ (Type _) _ cont) = analyse_ty_app cont
-    analyse_ty_app cont                                = analyse_app cont
-
-    analyse_app (InlinePlease cont)  
-       = case analyse_app cont of
-                (infos, icont, inline) -> (infos, icont, True)
-
-    analyse_app (ApplyTo _ arg subst cont) 
-       | isValArg arg = case analyse_app cont of
-                          (infos, icont, inline) -> (analyse_arg subst arg : infos, icont, inline)
-       | otherwise    = analyse_app cont
-
-    analyse_app cont = ([], interesting_call_context cont, False)
-
-       -- An argument is interesting if it has *some* structure
-       -- We are here trying to avoid unfolding a function that
-       -- is applied only to variables that have no unfolding
-       -- (i.e. they are probably lambda bound): f x y z
-       -- There is little point in inlining f here.
-    analyse_arg :: SubstEnv -> InExpr -> Bool
-    analyse_arg subst (Var v)          = case lookupIdSubst (mkSubst in_scope subst) v of
-                                               DoneId v' _ -> isValueUnfolding (idUnfolding v')
-                                               other       -> False
-    analyse_arg subst (Type _)         = False
-    analyse_arg subst (App fn (Type _)) = analyse_arg subst fn
-    analyse_arg subst (Note _ a)       = analyse_arg subst a
-    analyse_arg subst other            = True
-
-    interesting_call_context (Stop ty)                  = canUpdateInPlace ty
-    interesting_call_context (InlinePlease _)           = True
-    interesting_call_context (Select _ _ _ _ _)          = True
-    interesting_call_context (CoerceIt _ cont)           = interesting_call_context cont
-    interesting_call_context (ApplyTo _ (Type _) _ cont) = interesting_call_context cont
-    interesting_call_context (ApplyTo _ _       _ _)    = True
-    interesting_call_context (ArgOf _ _ _)              = True
+    interesting (InlinePlease _)   = True
+    interesting (ApplyTo _ _ _ _)  = some_args -- Can happen if we have (coerce t (f x)) y
+    interesting (Select _ _ _ _ _) = some_args
+    interesting (ArgOf _ _ _)     = some_val_args
+    interesting (Stop ty)         = some_val_args && canUpdateInPlace ty
+    interesting (CoerceIt _ cont)  = interesting cont
        -- If this call is the arg of a strict function, the context
        -- is a bit interesting.  If we inline here, we may get useful
        -- evaluation information to avoid repeated evals: e.g.
@@ -266,11 +369,8 @@ analyseCont in_scope cont
        -- the context for (f x) is not totally uninteresting.
 
 
-discardInline :: SimplCont -> SimplCont
-discardInline (InlinePlease cont)  = cont
-discardInline (ApplyTo d e s cont) = ApplyTo d e s (discardInline cont)
-discardInline cont                = cont
-
+-------------------
+canUpdateInPlace :: Type -> Bool
 -- Consider   let x = <wurble> in ...
 -- If <wurble> returns an explicit constructor, we might be able
 -- to do update in place.  So we treat even a thunk RHS context
@@ -502,10 +602,10 @@ mkRhsTyLam tyvars body                    -- Only does something if there's a let
                -- 
                -- It's even right to retain single-occurrence or dead-var info:
                -- Suppose we started with  /\a -> let x = E in B
-               -- where x occurs once in E. Then we transform to:
+               -- where x occurs once in B. Then we transform to:
                --      let x' = /\a -> E in /\a -> let x* = x' a in B
                -- where x* has an INLINE prag on it.  Now, once x* is inlined,
-               -- the occurrences of x' will be just the occurrences originaly
+               -- the occurrences of x' will be just the occurrences originally
                -- pinned on x.
            poly_info = vanillaIdInfo `setOccInfo` idOccInfo var
 
@@ -514,8 +614,7 @@ mkRhsTyLam tyvars body                      -- Only does something if there's a let
        returnSmpl (poly_id, mkTyApps (Var poly_id) (mkTyVarTys tyvars_here))
 
     mk_silly_bind var rhs = NonRec var rhs
-               -- The Inline note is really important!  If we don't say 
-               -- INLINE on these silly little bindings then look what happens!
+               -- We need to be careful about inlining.
                -- Suppose we start with:
                --
                --      x = let g = /\a -> \x -> f x x
@@ -523,11 +622,13 @@ mkRhsTyLam tyvars body                    -- Only does something if there's a let
                --          /\ b -> let g* = g b in E
                --
                -- Then:        * the binding for g gets floated out
-               --              * but then it gets inlined into the rhs of g*
+               --              * but then it MIGHT get inlined into the rhs of g*
                --              * then the binding for g* is floated out of the /\b
                --              * so we're back to square one
-               -- The silly binding for g* must be INLINEd, so that
-               -- we simply substitute for g* throughout.
+               -- We rely on the simplifier not to inline g into the RHS of g*,
+               -- because it's a "lone" occurrence, and there is no benefit in
+               -- inlining.  But it's a slightly delicate property, and there's
+               -- a danger of making the simplifier loop here.
 \end{code}
 
 
index ae04f14..68f8c22 100644 (file)
@@ -9,14 +9,15 @@ module Simplify ( simplTopBinds, simplExpr ) where
 #include "HsVersions.h"
 
 import CmdLineOpts     ( switchIsOn, opt_SimplDoEtaReduction,
-                         opt_SimplNoPreInlining, opt_DictsStrict,
+                         opt_SimplNoPreInlining, 
                          SimplifierSwitch(..)
                        )
 import SimplMonad
-import SimplUtils      ( mkCase, transformRhs, findAlt,
+import SimplUtils      ( mkCase, transformRhs, findAlt, 
                          simplBinder, simplBinders, simplIds, findDefault,
-                         SimplCont(..), DupFlag(..), contResultType, analyseCont, 
-                         discardInline, countArgs, countValArgs, discardCont, contIsDupable
+                         SimplCont(..), DupFlag(..), 
+                         contResultType, discardInline, countArgs, contIsDupable,
+                         getContArgs, interestingCallContext, interestingArg, isStrictType
                        )
 import Var             ( mkSysTyVar, tyVarKind )
 import VarEnv
@@ -24,13 +25,13 @@ import Id           ( Id, idType, idInfo, isDataConId,
                          idUnfolding, setIdUnfolding, isExportedId, isDeadBinder,
                          idDemandInfo, setIdInfo,
                          idOccInfo, setIdOccInfo,
-                         zapLamIdInfo, idStrictness, setOneShotLambda, 
+                         zapLamIdInfo, setOneShotLambda, 
                        )
-import IdInfo          ( OccInfo(..), StrictnessInfo(..), ArityInfo(..),
+import IdInfo          ( OccInfo(..), ArityInfo(..),
                          setArityInfo, setUnfoldingInfo,
                          occInfo
                        )
-import Demand          ( Demand, isStrict, wwLazy )
+import Demand          ( Demand, isStrict )
 import DataCon         ( dataConNumInstArgs, dataConRepStrictness,
                          dataConSig, dataConArgTys
                        )
@@ -48,19 +49,17 @@ import Rules                ( lookupRule )
 import CostCentre      ( currentCCS )
 import Type            ( mkTyVarTys, isUnLiftedType, seqType,
                          mkFunTy, splitFunTy, splitTyConApp_maybe, 
-                         funResultTy, isDictTy, isDataType, applyTy 
+                         funResultTy
                        )
 import Subst           ( mkSubst, substTy, substExpr,
                          isInScope, lookupIdSubst, substIdInfo
                        )
-import TyCon           ( isDataTyCon, tyConDataConsIfAvailable, 
-                         isDataTyCon
-                       )
+import TyCon           ( isDataTyCon, tyConDataConsIfAvailable )
 import TysPrim         ( realWorldStatePrimTy )
 import PrelInfo                ( realWorldPrimId )
 import BasicTypes      ( isLoopBreaker )
 import Maybes          ( maybeToBool )
-import Util            ( zipWithEqual, lengthExceeds )
+import Util            ( zipWithEqual )
 import Outputable
 \end{code}
 
@@ -69,6 +68,16 @@ The guts of the simplifier is in this module, but the driver
 loop for the simplifier is in SimplCore.lhs.
 
 
+-----------------------------------------
+       *** IMPORTANT NOTE ***
+-----------------------------------------
+The simplifier used to guarantee that the output had no shadowing, but
+it does not do so any more.   (Actually, it never did!)  The reason is
+documented with simplifyArgs.
+
+
+
+
 %************************************************************************
 %*                                                                     *
 \subsection{Bindings}
@@ -295,7 +304,7 @@ simplExprF (Note InlineMe e) cont
   = case cont of
        Stop _ ->       -- Totally boring continuation
                        -- Don't inline inside an INLINE expression
-                 switchOffInlining (simplExpr e)       `thenSmpl` \ e' ->
+                 setBlackList noInlineBlackList (simplExpr e)  `thenSmpl` \ e' ->
                  rebuild (mkInlineMe e') cont
 
        other  ->       -- Dissolve the InlineMe note if there's
@@ -421,11 +430,14 @@ simplBeta bndr rhs rhs_se cont_ty thing_inside
   | otherwise
   =    -- Simplify the RHS
     simplBinder bndr                                   $ \ bndr' ->
-    simplValArg (idType bndr') (idDemandInfo bndr)
-               rhs rhs_se cont_ty                      $ \ rhs' ->
+    let
+       bndr_ty'  = idType bndr'
+       is_strict = isStrict (idDemandInfo bndr) || isStrictType bndr_ty'
+    in
+    simplValArg bndr_ty' is_strict rhs rhs_se cont_ty  $ \ rhs' ->
 
        -- Now complete the binding and simplify the body
-    if needsCaseBinding (idType bndr') rhs' then
+    if needsCaseBinding bndr_ty' rhs' then
        addCaseBind bndr' rhs' thing_inside
     else
        completeBinding bndr bndr' False False rhs' thing_inside
@@ -442,26 +454,23 @@ simplTyArg ty_arg se
     seqType ty_arg'    `seq`
     returnSmpl ty_arg'
 
-simplValArg :: OutType         -- Type of arg
-           -> Demand           -- Demand on the argument
+simplValArg :: OutType         -- rhs_ty: Type of arg; used only occasionally
+           -> Bool             -- True <=> evaluate eagerly
            -> InExpr -> SubstEnv
-           -> OutType          -- Type of thing computed by the context
-           -> (OutExpr -> SimplM OutExprStuff)
-           -> SimplM OutExprStuff
-
-simplValArg arg_ty demand arg arg_se cont_ty thing_inside
-  | isStrict demand || 
-    isUnLiftedType arg_ty || 
-    (opt_DictsStrict && isDictTy arg_ty && isDataType arg_ty)
-       -- Return true only for dictionary types where the dictionary
-       -- has more than one component (else we risk poking on the component
-       -- of a newtype dictionary)
+           -> OutType          -- cont_ty: Type of thing computed by the context
+           -> (OutExpr -> SimplM OutExprStuff) 
+                               -- Takes an expression of type rhs_ty, 
+                               -- returns an expression of type cont_ty
+           -> SimplM OutExprStuff      -- An expression of type cont_ty
+
+simplValArg arg_ty is_strict arg arg_se cont_ty thing_inside
+  | is_strict
   = transformRhs arg                   `thenSmpl` \ t_arg ->
     getEnv                             `thenSmpl` \ env ->
     setSubstEnv arg_se                                 $
     simplExprF t_arg (ArgOf NoDup cont_ty      $ \ rhs' ->
     setAllExceptInScope env                    $
-    etaFirst thing_inside rhs')
+    thing_inside (etaFirst rhs'))
 
   | otherwise
   = simplRhs False {- Not top level -} 
@@ -470,17 +479,14 @@ simplValArg arg_ty demand arg arg_se cont_ty thing_inside
             thing_inside
    
 -- Do eta-reduction on the simplified RHS, if eta reduction is on
--- NB: etaFirst only eta-reduces if that results in something trivial
-etaFirst | opt_SimplDoEtaReduction = \ thing_inside rhs -> thing_inside (etaCoreExprToTrivial rhs)
-        | otherwise               = \ thing_inside rhs -> thing_inside rhs
-
--- Try for eta reduction, but *only* if we get all
--- the way to an exprIsTrivial expression.    We don't want to remove
--- extra lambdas unless we are going to avoid allocating this thing altogether
-etaCoreExprToTrivial rhs | exprIsTrivial rhs' = rhs'
-                        | otherwise          = rhs
-                        where
-                          rhs' = etaReduceExpr rhs
+-- But *only* if we get all the way to an exprIsTrivial expression.    
+-- We don't want to remove extra lambdas unless we are going 
+-- to avoid allocating this thing altogether
+etaFirst rhs 
+  | opt_SimplDoEtaReduction && exprIsTrivial rhs' = rhs'
+  | otherwise                                    = rhs
+ where
+   rhs' = etaReduceExpr rhs
 \end{code}
 
 
@@ -546,7 +552,7 @@ completeBinding old_bndr new_bndr top_lvl black_listed new_rhs thing_inside
        -- Making loop breakers not have an unfolding at all 
        -- means that we can avoid tests in exprIsConApp, for example.
        -- This is important: if exprIsConApp says 'yes' for a recursive
-       -- thing we can get into an infinite loop
+       -- thing, then we can get into an infinite loop
        info_w_unf | isLoopBreaker (occInfo old_info) = new_bndr_info
                   | otherwise = new_bndr_info `setUnfoldingInfo` mkUnfolding top_lvl new_rhs
 
@@ -602,7 +608,7 @@ simplLazyBind top_lvl bndr bndr' rhs thing_inside
 
        -- Simplify the RHS
     getSubstEnv                                        `thenSmpl` \ rhs_se ->
-    simplRhs top_lvl False {- Not ok to float unboxed -}
+    simplRhs top_lvl False {- Not ok to float unboxed (conservative) -}
             (idType bndr')
             rhs rhs_se                                 $ \ rhs' ->
 
@@ -615,7 +621,8 @@ simplLazyBind top_lvl bndr bndr' rhs thing_inside
 \begin{code}
 simplRhs :: Bool               -- True <=> Top level
         -> Bool                -- True <=> OK to float unboxed (speculative) bindings
-        -> OutType -> InExpr -> SubstEnv
+        -> OutType             -- Type of RHS; used only occasionally
+        -> InExpr -> SubstEnv
         -> (OutExpr -> SimplM (OutStuff a))
         -> SimplM (OutStuff a)
 simplRhs top_lvl float_ubx rhs_ty rhs rhs_se thing_inside
@@ -628,8 +635,7 @@ simplRhs top_lvl float_ubx rhs_ty rhs rhs_se thing_inside
 
        -- Float lets out of RHS
     let
-       (floats_out, rhs'') | float_ubx = (floats, rhs')
-                           | otherwise = splitFloats floats rhs' 
+       (floats_out, rhs'') = splitFloats float_ubx floats rhs'
     in
     if (top_lvl || wantToExpose 0 rhs') &&     -- Float lets if (a) we're at the top level
         not (null floats_out)                  -- or            (b) the resulting RHS is one we'd like to expose
@@ -646,12 +652,12 @@ simplRhs top_lvl float_ubx rhs_ty rhs rhs_se thing_inside
        WARN( any demanded_float floats_out, ppr floats_out )
        addLetBinds floats_out  $
        setInScope in_scope'    $
-       etaFirst thing_inside rhs''
+       thing_inside (etaFirst rhs'')
                -- in_scope' may be excessive, but that's OK;
                -- it's a superset of what's in scope
     else       
                -- Don't do the float
-       etaFirst thing_inside (mkLets floats rhs')
+       thing_inside (etaFirst (mkLets floats rhs'))
 
 -- In a let-from-let float, we just tick once, arbitrarily
 -- choosing the first floated binder to identify it
@@ -662,11 +668,17 @@ demanded_float (NonRec b r) = isStrict (idDemandInfo b) && not (isUnLiftedType (
                -- Unlifted-type (cheap-eagerness) lets may well have a demanded flag on them
 demanded_float (Rec _)     = False
 
--- Don't float any unlifted bindings out, because the context
+-- If float_ubx is true we float all the bindings, otherwise
+-- we just float until we come across an unlifted one.
+-- Remember that the unlifted bindings in the floats are all for
+-- guaranteed-terminating non-exception-raising unlifted things,
+-- which we are happy to do speculatively.  However, we may still
+-- not be able to float them out, because the context
 -- is either a Rec group, or the top level, neither of which
 -- can tolerate them.
-splitFloats floats rhs
-  = go floats
+splitFloats float_ubx floats rhs
+  | float_ubx = (floats, rhs)          -- Float them all
+  | otherwise = go floats
   where
     go []                  = ([], rhs)
     go (f:fs) | must_stay f = ([], mkLets (f:fs) rhs)
@@ -738,31 +750,36 @@ simplVar var cont
 --     Dealing with a call
 
 completeCall var occ cont
-  = getBlackList       `thenSmpl` \ black_list_fn ->
-    getInScope         `thenSmpl` \ in_scope ->
-    getSwitchChecker   `thenSmpl` \ chkr ->
+  = getBlackList               `thenSmpl` \ black_list_fn ->
+    getInScope                 `thenSmpl` \ in_scope ->
+    getContArgs var cont       `thenSmpl` \ (args, call_cont, inline_call) ->
     let
-       dont_use_rules     = switchIsOn chkr DontApplyRules
-       no_case_of_case    = switchIsOn chkr NoCaseOfCase
        black_listed       = black_list_fn var
+       arg_infos          = [ interestingArg in_scope arg subst 
+                            | (arg, subst, _) <- args, isValArg arg]
+
+       interesting_cont = interestingCallContext (not (null args)) 
+                                                 (not (null arg_infos))
+                                                 call_cont
 
-       (arg_infos, interesting_cont, inline_call) = analyseCont in_scope cont
-       discard_inline_cont | inline_call = discardInline cont
-                           | otherwise   = cont
+       inline_cont | inline_call = discardInline cont
+                   | otherwise   = cont
 
        maybe_inline = callSiteInline black_listed inline_call occ
                                      var arg_infos interesting_cont
     in
        -- First, look for an inlining
-
     case maybe_inline of {
        Just unfolding          -- There is an inlining!
          ->  tick (UnfoldingDone var)          `thenSmpl_`
-             simplExprF unfolding discard_inline_cont
+             simplExprF unfolding inline_cont
 
        ;
        Nothing ->              -- No inlining!
 
+
+    simplifyArgs (isDataConId var) args (contResultType call_cont)  $ \ args' ->
+
        -- Next, look for rules or specialisations that match
        --
        -- It's important to simplify the args first, because the rule-matcher
@@ -777,133 +794,110 @@ completeCall var occ cont
        -- won't occur for things that have specialisations till a later phase, so
        -- it's ok to try for inlining first.
 
-    prepareArgs no_case_of_case var cont       $ \ args' cont' ->
+    getSwitchChecker   `thenSmpl` \ chkr ->
     let
-       maybe_rule | dont_use_rules = Nothing
-                  | otherwise      = lookupRule in_scope var args' 
+       maybe_rule | switchIsOn chkr DontApplyRules = Nothing
+                  | otherwise                      = lookupRule in_scope var args' 
     in
     case maybe_rule of {
        Just (rule_name, rule_rhs) -> 
                tick (RuleFired rule_name)                      `thenSmpl_`
-               simplExprF rule_rhs cont' ;
+               simplExprF rule_rhs call_cont ;
        
        Nothing ->              -- No rules
 
        -- Done
-    rebuild (mkApps (Var var) args') cont'
+    rebuild (mkApps (Var var) args') call_cont
     }}
-\end{code}                
 
 
-\begin{code}
 ---------------------------------------------------------
---     Preparing arguments for a call
-
-prepareArgs :: Bool    -- True if the no-case-of-case switch is on
-           -> OutId -> SimplCont
-           -> ([OutExpr] -> SimplCont -> SimplM OutExprStuff)
-           -> SimplM OutExprStuff
-prepareArgs no_case_of_case fun orig_cont thing_inside
-  = go [] demands orig_fun_ty orig_cont
-  where
-    orig_fun_ty = idType fun
-    is_data_con = isDataConId fun
-
-    (demands, result_bot)
-      | no_case_of_case = ([], False)  -- Ignore strictness info if the no-case-of-case
-                                       -- flag is on.  Strictness changes evaluation order
-                                       -- and that can change full laziness
-      | otherwise
-      = case idStrictness fun of
-         StrictnessInfo demands result_bot 
-               | not (demands `lengthExceeds` countValArgs orig_cont)
-               ->      -- Enough args, use the strictness given.
-                       -- For bottoming functions we used to pretend that the arg
-                       -- is lazy, so that we don't treat the arg as an
-                       -- interesting context.  This avoids substituting
-                       -- top-level bindings for (say) strings into 
-                       -- calls to error.  But now we are more careful about
-                       -- inlining lone variables, so its ok (see SimplUtils.analyseCont)
-                  (demands, result_bot)
-
-         other -> ([], False)  -- Not enough args, or no strictness
-
-       -- Main game plan: loop through the arguments, simplifying
-       -- each of them in turn.  We carry with us a list of demands,
-       -- and the type of the function-applied-to-earlier-args
-
-       -- We've run out of demands, and the result is now bottom
-       -- This deals with
-       --      * case (error "hello") of { ... }
-       --      * (error "Hello") arg
-       --      * f (error "Hello") where f is strict
-       --      etc
-    go acc [] fun_ty cont 
-       | result_bot
-       = tick_case_of_error cont               `thenSmpl_`
-         thing_inside (reverse acc) (discardCont cont)
-
-       -- Type argument
-    go acc ds fun_ty (ApplyTo _ arg@(Type ty_arg) se cont)
-       = simplTyArg ty_arg se  `thenSmpl` \ new_ty_arg ->
-         go (Type new_ty_arg : acc) ds (applyTy fun_ty new_ty_arg) cont
-
-       -- Value argument
-    go acc ds fun_ty (ApplyTo _ val_arg se cont)
-       | not is_data_con       -- Function isn't a data constructor
-       = simplValArg arg_ty dem val_arg se (contResultType cont)       $ \ new_arg ->
-         go (new_arg : acc) ds' res_ty cont
-
-       | exprIsTrivial val_arg -- Function is a data contstructor, arg is trivial
-       = getInScope            `thenSmpl` \ in_scope ->
-         let
-               new_arg = substExpr (mkSubst in_scope se) val_arg
-               -- Simplify the RHS with inlining switched off, so that
-               -- only absolutely essential things will happen.
+--     Simplifying the arguments of a call
+
+simplifyArgs :: Bool                           -- It's a data constructor
+            -> [(InExpr, SubstEnv, Bool)]      -- Details of the arguments
+            -> OutType                         -- Type of the continuation
+            -> ([OutExpr] -> SimplM OutExprStuff)
+            -> SimplM OutExprStuff
+
+-- Simplify the arguments to a call.
+-- This part of the simplifier may break the no-shadowing invariant
+-- Consider
+--     f (...(\a -> e)...) (case y of (a,b) -> e')
+-- where f is strict in its second arg
+-- If we simplify the innermost one first we get (...(\a -> e)...)
+-- Simplifying the second arg makes us float the case out, so we end up with
+--     case y of (a,b) -> f (...(\a -> e)...) e'
+-- So the output does not have the no-shadowing invariant.  However, there is
+-- no danger of getting name-capture, because when the first arg was simplified
+-- we used an in-scope set that at least mentioned all the variables free in its
+-- static environment, and that is enough.
+--
+-- We can't just do innermost first, or we'd end up with a dual problem:
+--     case x of (a,b) -> f e (...(\a -> e')...)
+--
+-- I spent hours trying to recover the no-shadowing invariant, but I just could
+-- not think of an elegant way to do it.  The simplifier is already knee-deep in
+-- continuations.  We have to keep the right in-scope set around; AND we have
+-- to get the effect that finding (error "foo") in a strict arg position will
+-- discard the entire application and replace it with (error "foo").  Getting
+-- all this at once is TOO HARD!
+
+simplifyArgs is_data_con args cont_ty thing_inside
+  | not is_data_con
+  = go args thing_inside
+
+  | otherwise  -- It's a data constructor, so we want 
+               -- to switch off inlining in the arguments
                -- If we don't do this, consider:
                --      let x = +# p q in C {x}
                -- Even though x get's an occurrence of 'many', its RHS looks cheap,
                -- and there's a good chance it'll get inlined back into C's RHS. Urgh!
-               --
-               -- It's important that the substitution *does* deal with case-binder synonyms:
-               --      case x of y { True -> (x,1) }
-               -- Here we must be sure to substitute y for x when simplifying the args of the pair,
-               -- to increase the chances of being able to inline x.  The substituter will do
-               -- that because the x->y mapping is held in the in-scope set.
-         in
-               -- It's not always the case that the new arg will be trivial
-               -- Consider             f x
-               -- where, in one pass, f gets substituted by a constructor,
-               -- but x gets substituted by an expression (assume this is the
-               -- unique occurrence of x).  It doesn't really matter -- it'll get
-               -- fixed up next pass.  And it happens for dictionary construction,
-               -- which mentions the wrapper constructor to start with.
-
-         go (new_arg : acc) ds' res_ty cont
-
-       | otherwise
-       = simplValArg arg_ty dem val_arg se (contResultType cont)       $ \ new_arg ->
-                   -- A data constructor whose argument is now non-trivial;
-                   -- so let/case bind it.
-         newId SLIT("a") arg_ty                                $ \ arg_id ->
-         addNonRecBind arg_id new_arg                          $
-         go (Var arg_id : acc) ds' res_ty cont
+  = getBlackList                               `thenSmpl` \ old_bl ->
+    setBlackList noInlineBlackList             $
+    go args                                    $ \ args' ->
+    setBlackList old_bl                                $
+    thing_inside args'
 
-       where
-         (arg_ty, res_ty) = splitFunTy fun_ty
-         (dem, ds') = case ds of 
-                       []     -> (wwLazy, [])
-                       (d:ds) -> (d,ds)
-
-       -- We're run out of arguments and the result ain't bottom
-    go acc ds fun_ty cont = thing_inside (reverse acc) cont
-
--- Boring: we must only record a tick if there was an interesting
---        continuation to discard.  If not, we tick forever.
-tick_case_of_error (Stop _)             = returnSmpl ()
-tick_case_of_error (CoerceIt _ (Stop _)) = returnSmpl ()
-tick_case_of_error other                = tick BottomFound
-\end{code}
+  where
+    go []        thing_inside = thing_inside []
+    go (arg:args) thing_inside = simplifyArg is_data_con arg cont_ty   $ \ arg' ->
+                                go args                                $ \ args' ->
+                                thing_inside (arg':args')
+
+simplifyArg is_data_con (Type ty_arg, se, _) cont_ty thing_inside
+  = simplTyArg ty_arg se       `thenSmpl` \ new_ty_arg ->
+    thing_inside (Type new_ty_arg)
+
+simplifyArg is_data_con (val_arg, se, is_strict) cont_ty thing_inside
+  = getInScope         `thenSmpl` \ in_scope ->
+    let
+       arg_ty = substTy (mkSubst in_scope se) (exprType val_arg)
+    in
+    if not is_data_con then
+       -- An ordinary function
+       simplValArg arg_ty is_strict val_arg se cont_ty thing_inside
+    else
+       -- A data constructor
+       -- simplifyArgs has already switched off inlining, so 
+       -- all we have to do here is to let-bind any non-trivial argument
+
+       -- It's not always the case that new_arg will be trivial
+       -- Consider             f x
+       -- where, in one pass, f gets substituted by a constructor,
+       -- but x gets substituted by an expression (assume this is the
+       -- unique occurrence of x).  It doesn't really matter -- it'll get
+       -- fixed up next pass.  And it happens for dictionary construction,
+       -- which mentions the wrapper constructor to start with.
+       simplValArg arg_ty is_strict val_arg se cont_ty         $ \ arg' ->
+       
+       if exprIsTrivial arg' then
+            thing_inside arg'
+       else
+       newId SLIT("a") (exprType arg')         $ \ arg_id ->
+       addNonRecBind arg_id arg'               $
+       thing_inside (Var arg_id)
+\end{code}                
 
 
 %************************************************************************
@@ -1448,7 +1442,8 @@ mkDupableCont join_arg_ty (ArgOf _ cont_ty cont_fn) thing_inside
        -- Build the join Id and continuation
        -- We give it a "$j" name just so that for later amusement
        -- we can identify any join points that don't end up as let-no-escapes
-    newId SLIT("$j") (exprType join_rhs)               $ \ join_id ->
+       -- [NOTE: the type used to be exprType join_rhs, but this seems more elegant.]
+    newId SLIT("$j") (mkFunTy join_arg_ty cont_ty)     $ \ join_id ->
     let
        new_cont = ArgOf OkToDup cont_ty
                         (\arg' -> rebuild_done (App (Var join_id) arg'))
@@ -1491,7 +1486,7 @@ mkDupableCont ty (Select _ case_bndr alts se cont) thing_inside
        returnSmpl (concat alt_binds_s, alts')
     )                                  `thenSmpl` \ (alt_binds, alts') ->
 
-    extendInScopes [b | NonRec b _ <- alt_binds]               $
+    addNewInScopeIds [b | NonRec b _ <- alt_binds]             $
 
        -- NB that the new alternatives, alts', are still InAlts, using the original
        -- binders.  That means we can keep the case_bndr intact. This is important
index b5c7002..aa47275 100644 (file)
@@ -19,9 +19,9 @@ import CoreFVs                ( exprFreeVars, idRuleVars, ruleRhsFreeVars, ruleSomeLhsFreeVars
 import CoreUnfold      ( isCheapUnfolding, unfoldingTemplate )
 import CoreUtils       ( eqExpr )
 import PprCore         ( pprCoreRule )
-import Subst           ( Subst, InScopeSet, lookupSubst, extendSubst,
+import Subst           ( Subst, InScopeSet, mkInScopeSet, lookupSubst, extendSubst,
                          substEnv, setSubstEnv, emptySubst, isInScope,
-                         bindSubstList, unBindSubstList, substInScope
+                         bindSubstList, unBindSubstList, substInScope, uniqAway
                        )
 import Id              ( Id, idUnfolding, zapLamIdInfo, 
                          idSpecialisation, setIdSpecialisation,
@@ -416,7 +416,7 @@ addRule id (Rules rules rhs_fvs) rule
 insertRule rules new_rule@(Rule _ tpl_vars tpl_args _)
   = go rules
   where
-    tpl_var_set = mkVarSet tpl_vars
+    tpl_var_set = mkInScopeSet (mkVarSet tpl_vars)
        -- Actually we should probably include the free vars of tpl_args,
        -- but I can't be bothered
 
index 884d70b..5f865c2 100644 (file)
@@ -21,7 +21,7 @@ import Type           ( Type, mkTyVarTy, splitSigmaTy, splitFunTysN,
                          tyVarsOfType, tyVarsOfTypes, tyVarsOfTheta, applyTys,
                          mkForAllTys, boxedTypeKind
                        )
-import Subst           ( Subst, mkSubst, substTy, mkSubst, substBndrs, extendSubstList,
+import Subst           ( Subst, mkSubst, substTy, mkSubst, substBndrs, extendSubstList, mkInScopeSet,
                          substId, substAndCloneId, substAndCloneIds, lookupIdSubst, substInScope
                        ) 
 import Var             ( TyVar, mkSysTyVar, setVarUnique )
@@ -599,7 +599,7 @@ specProgram us binds
        -- accidentally re-use a unique that's already in use
        -- Easiest thing is to do it all at once, as if all the top-level
        -- decls were mutually recursive
-    top_subst      = mkSubst (mkVarSet (bindersOfBinds binds)) emptySubstEnv
+    top_subst      = mkSubst (mkInScopeSet (mkVarSet (bindersOfBinds binds))) emptySubstEnv
 
     go []          = returnSM ([], emptyUDs)
     go (bind:binds) = go binds                                 `thenSM` \ (binds', uds) ->
index 2311800..416f0bf 100644 (file)
@@ -64,7 +64,7 @@ import Type   ( Type, PredType(..), ThetaType,
                  splitRhoTy, tyVarsOfType, tyVarsOfTypes, tyVarsOfPred,
                  mkSynTy, tidyOpenType, tidyOpenTypes
                )
-import Subst   ( emptyInScopeSet, mkSubst,
+import Subst   ( emptyInScopeSet, mkSubst, mkInScopeSet,
                  substTy, substClasses, mkTyVarSubst, mkTopTyVarSubst
                )
 import Literal ( inIntRange )
@@ -640,7 +640,7 @@ lookupInst dict@(Dict _ (Class clas tys) loc)
 
       FoundInst tenv dfun_id
        -> let
-               subst         = mkSubst (tyVarsOfTypes tys) tenv
+               subst         = mkSubst (mkInScopeSet (tyVarsOfTypes tys)) tenv
                (tyvars, rho) = splitForAllTys (idType dfun_id)
                ty_args       = map subst_tv tyvars
                dfun_rho      = substTy subst rho
index 775a36d..1ebd734 100644 (file)
@@ -612,7 +612,6 @@ tcMonoBinds :: RenamedMonoBinds
 tcMonoBinds mbinds tc_ty_sigs is_rec
   = tc_mb_pats mbinds          `thenTc` \ (complete_it, lie_req_pat, tvs, ids, lie_avail) ->
     let
-       tv_list           = bagToList tvs
        id_list           = bagToList ids
        (names, mono_ids) = unzip id_list
 
index 3bcb58a..d0e5379 100644 (file)
@@ -27,7 +27,7 @@ import TcHsSyn                ( TcMonoBinds, idsToMonoBinds )
 import Inst            ( Inst, InstOrigin(..), LIE, emptyLIE, plusLIE, plusLIEs, newDicts, newMethod )
 import TcEnv           ( TcId, ValueEnv, TyThing(..), TyThingDetails(..), tcAddImportedIdInfo,
                          tcLookupTy, tcExtendTyVarEnvForMeths, tcExtendGlobalTyVars,
-                         tcExtendLocalValEnv, tcExtendTyVarEnv
+                         tcExtendLocalValEnv, tcExtendTyVarEnv, newDefaultMethodName
                        )
 import TcBinds         ( tcBindWithSigs, tcSpecSigs )
 import TcTyDecls       ( mkNewTyConRep )
@@ -44,7 +44,7 @@ import MkId           ( mkDictSelId, mkDataConId, mkDataConWrapId, mkDefaultMethodId )
 import DataCon         ( mkDataCon, dataConId, dataConWrapId, notMarkedStrict )
 import Id              ( Id, setInlinePragma, idUnfolding, idType, idName )
 import Name            ( Name, nameOccName, isLocallyDefined, NamedThing(..) )
-import NameSet         ( emptyNameSet )
+import NameSet         ( NameSet, mkNameSet, elemNameSet, emptyNameSet )
 import Outputable
 import Type            ( Type, ThetaType, ClassContext,
                          mkFunTy, mkTyVarTy, mkTyVarTys, mkDictTy, mkDictTys,
@@ -55,6 +55,7 @@ import Var            ( tyVarKind, TyVar )
 import VarSet          ( mkVarSet, emptyVarSet )
 import TyCon           ( AlgTyConFlavour(..), mkClassTyCon )
 import Maybes          ( seqMaybe )
+import SrcLoc          ( SrcLoc )
 import FiniteMap        ( lookupWithDefaultFM )
 \end{code}
 
@@ -113,6 +114,8 @@ tcClassDecl1 rec_env
     tcLookupTy class_name                              `thenTc` \ (AClass clas) ->
     let
        tyvars = classTyVars clas
+       dm_bndrs_w_locs = bagToList (collectMonoBinders def_methods)
+       dm_bndr_set     = mkNameSet (map fst dm_bndrs_w_locs)
     in
     tcExtendTyVarEnv tyvars                    $ 
        
@@ -121,7 +124,7 @@ tcClassDecl1 rec_env
                   context sc_sel_names         `thenTc` \ (sc_theta, sc_sel_ids) ->
 
        -- CHECK THE CLASS SIGNATURES,
-    mapTc (tcClassSig rec_env clas tyvars) 
+    mapTc (tcClassSig rec_env dm_bndr_set clas tyvars) 
          (filter isClassOpSig class_sigs)              `thenTc` \ sig_stuff ->
 
        -- MAKE THE CLASS DETAILS
@@ -182,6 +185,7 @@ tcSuperClasses class_name clas context sc_sel_names
 
 
 tcClassSig :: ValueEnv         -- Knot tying only!
+          -> NameSet           -- Names bound in the default-method bindings
           -> Class                     -- ...ditto...
           -> [TyVar]                   -- The class type variable, used for error check only
           -> RenamedClassOpSig
@@ -189,8 +193,8 @@ tcClassSig :: ValueEnv              -- Knot tying only!
                     ClassOpItem)       -- Selector Id, default-method Id, True if explicit default binding
 
 
-tcClassSig rec_env clas clas_tyvars
-          (ClassOpSig op_name dm_name explicit_dm op_ty src_loc)
+tcClassSig rec_env dm_bind_names clas clas_tyvars
+          (ClassOpSig op_name maybe_dm_stuff op_ty src_loc)
   = tcAddSrcLoc src_loc $
 
        -- Check the type signature.  NB that the envt *already has*
@@ -206,10 +210,20 @@ tcClassSig rec_env clas clas_tyvars
 
        -- Build the selector id and default method id
        sel_id      = mkDictSelId op_name clas
-       dm_id       = mkDefaultMethodId dm_name clas global_ty
-       final_dm_id = tcAddImportedIdInfo rec_env dm_id
     in
-    returnTc (local_ty, (sel_id, final_dm_id, explicit_dm))
+    (case maybe_dm_stuff of
+       Nothing ->      -- Source-file class declaration
+           newDefaultMethodName op_name src_loc        `thenNF_Tc` \ dm_name ->
+           returnNF_Tc (mkDefaultMethodId dm_name clas global_ty, op_name `elemNameSet` dm_bind_names)
+
+       Just (dm_name, explicit_dm) ->  -- Interface-file class decl
+           let
+               dm_id = mkDefaultMethodId dm_name clas global_ty
+           in
+           returnNF_Tc (tcAddImportedIdInfo rec_env dm_id, explicit_dm)
+    )                          `thenNF_Tc` \ (dm_id, explicit_dm) ->
+
+    returnTc (local_ty, (sel_id, dm_id, explicit_dm))
 \end{code}
 
 
@@ -274,17 +288,15 @@ mkImplicitClassBinds :: [Class] -> NF_TcM s ([Id], TcMonoBinds)
 mkImplicitClassBinds classes
   = returnNF_Tc (concat cls_ids_s, andMonoBindList binds_s)
        -- The selector binds are already in the selector Id's unfoldings
+       -- We don't return the data constructor etc from the class,
+       -- because that's done via the class's TyCon
   where
     (cls_ids_s, binds_s) = unzip (map mk_implicit classes)
 
-    mk_implicit clas = (all_cls_ids, binds)
+    mk_implicit clas = (sel_ids, binds)
                     where
-                       dict_con    = classDataCon clas
-                       all_cls_ids = dataConId dict_con : cls_ids
-                       cls_ids     = dataConWrapId dict_con : classSelIds clas
-
-                       -- The wrapper and selectors get bindings, the worker does not
-                       binds | isLocallyDefined clas = idsToMonoBinds cls_ids
+                       sel_ids = classSelIds clas
+                       binds | isLocallyDefined clas = idsToMonoBinds sel_ids
                              | otherwise             = EmptyMonoBinds
 \end{code}
 
@@ -358,7 +370,7 @@ tcDefaultMethodBinds
 
 tcDefaultMethodBinds clas default_binds sigs
   =    -- Check that the default bindings come from this class
-    checkFromThisClass clas op_items default_binds     `thenNF_Tc_`
+    checkFromThisClass clas default_binds      `thenNF_Tc_`
 
        -- Do each default method separately
        -- For Hugs compatibility we make a default-method for every
@@ -426,17 +438,17 @@ tcDefaultMethodBinds clas default_binds sigs
 \end{code}
 
 \begin{code}
-checkFromThisClass :: Class -> [ClassOpItem] -> RenamedMonoBinds -> NF_TcM s ()
-checkFromThisClass clas op_items mono_binds
-  = mapNF_Tc check_from_this_class bndrs       `thenNF_Tc_`
+checkFromThisClass :: Class -> RenamedMonoBinds -> NF_TcM s ()
+checkFromThisClass clas mbinds
+  = mapNF_Tc check_from_this_class bndrs_w_locs        `thenNF_Tc_`
     returnNF_Tc ()
   where
     check_from_this_class (bndr, loc)
          | nameOccName bndr `elem` sel_names = returnNF_Tc ()
          | otherwise                         = tcAddSrcLoc loc $
                                                addErrTc (badMethodErr bndr clas)
-    sel_names = [getOccName sel_id | (sel_id,_,_) <- op_items]
-    bndrs = bagToList (collectMonoBinders mono_binds)
+    sel_names    = map getOccName (classSelIds clas)
+    bndrs_w_locs = bagToList (collectMonoBinders mbinds)
 \end{code}
     
 
index 44a0c5e..6c45d81 100644 (file)
@@ -16,13 +16,13 @@ import RnHsSyn              ( RenamedHsBinds, RenamedMonoBinds )
 import CmdLineOpts     ( opt_D_dump_deriv )
 
 import TcMonad
-import TcEnv           ( InstEnv, getEnvTyCons, tcSetInstEnv )
+import TcEnv           ( InstEnv, getEnvTyCons, tcSetInstEnv, newDFunName )
 import TcGenDeriv      -- Deriv stuff
 import TcInstUtil      ( InstInfo(..), buildInstanceEnv )
 import TcSimplify      ( tcSimplifyThetas )
 
 import RnBinds         ( rnMethodBinds, rnTopMonoBinds )
-import RnEnv           ( newDFunName, bindLocatedLocalsRn )
+import RnEnv           ( bindLocatedLocalsRn )
 import RnMonad         ( RnNameSupply, 
                          renameSourceCode, thenRn, mapRn, returnRn )
 
@@ -34,7 +34,7 @@ import Id             ( mkVanillaId )
 import DataCon         ( dataConArgTys, isNullaryDataCon, isExistentialDataCon )
 import PrelInfo                ( needsDataDeclCtxtClassKeys )
 import Maybes          ( maybeToBool, catMaybes )
-import Module          ( ModuleName )
+import Module          ( Module )
 import Name            ( isLocallyDefined, getSrcLoc,
                          Name, NamedThing(..),
                          OccName, nameOccName
@@ -185,14 +185,14 @@ context to the instance decl.  The "offending classes" are
 %************************************************************************
 
 \begin{code}
-tcDeriving  :: ModuleName              -- name of module under scrutiny
+tcDeriving  :: Module                  -- name of module under scrutiny
            -> FixityEnv                -- for the deriving code (Show/Read.)
            -> RnNameSupply             -- for "renaming" bits of generated code
            -> Bag InstInfo             -- What we already know about instances
            -> TcM s (Bag InstInfo,     -- The generated "instance decls".
                      RenamedHsBinds)   -- Extra generated bindings
 
-tcDeriving modname fixs rn_name_supply inst_decl_infos_in
+tcDeriving mod fixs rn_name_supply inst_decl_infos_in
   = recoverTc (returnTc (emptyBag, EmptyBinds)) $
 
        -- Fish the "deriving"-related information out of the TcEnv
@@ -225,26 +225,18 @@ tcDeriving modname fixs rn_name_supply inst_decl_infos_in
        -- Rename to get RenamedBinds.
        -- The only tricky bit is that the extra_binds must scope over the
        -- method bindings for the instances.
-       (dfun_names_w_method_binds, rn_extra_binds)
-               = renameSourceCode modname rn_name_supply (
+       (rn_method_binds_s, rn_extra_binds)
+               = renameSourceCode mod rn_name_supply (
                        bindLocatedLocalsRn (ptext (SLIT("deriving"))) mbinders $ \ _ ->
                        rnTopMonoBinds extra_mbinds []          `thenRn` \ (rn_extra_binds, _) ->
-                       mapRn rn_one method_binds_s             `thenRn` \ dfun_names_w_method_binds ->
-                       returnRn (dfun_names_w_method_binds, rn_extra_binds)
+                       mapRn rn_meths method_binds_s           `thenRn` \ rn_method_binds_s ->
+                       returnRn (rn_method_binds_s, rn_extra_binds)
                  )
-       rn_one (cl_nm, tycon_nm, meth_binds) 
-               = newDFunName (cl_nm, tycon_nm)
-                             mkGeneratedSrcLoc         `thenRn` \ dfun_name ->
-                 rnMethodBinds meth_binds              `thenRn` \ (rn_meth_binds, _) ->
-                 returnRn (dfun_name, rn_meth_binds)
-
-       really_new_inst_infos = zipWith gen_inst_info
-                                       new_inst_infos
-                                       dfun_names_w_method_binds
-
-       ddump_deriv = ddump_deriving really_new_inst_infos rn_extra_binds
     in
-    ioToTc (dumpIfSet opt_D_dump_deriv "Derived instances" ddump_deriv)        `thenTc_`
+    mapNF_Tc gen_inst_info (new_inst_infos `zip` rn_method_binds_s)    `thenNF_Tc` \ really_new_inst_infos ->
+
+    ioToTc (dumpIfSet opt_D_dump_deriv "Derived instances" 
+                     (ddump_deriving really_new_inst_infos rn_extra_binds))    `thenTc_`
 
     returnTc (listToBag really_new_inst_infos, rn_extra_binds)
   where
@@ -257,6 +249,18 @@ tcDeriving modname fixs rn_name_supply inst_decl_infos_in
            $$
            ppr mbinds
            where inst_decl_theta' = classesToPreds inst_decl_theta
+
+       -- Paste the dfun id and method binds into the InstInfo
+    gen_inst_info (InstInfo clas tyvars tys@(ty:_) inst_decl_theta _ _ locn _, meth_binds)
+      = newDFunName mod clas tys locn  `thenNF_Tc` \ dfun_name ->
+       let
+           dfun_id = mkDictFunId dfun_name clas tyvars tys inst_decl_theta
+       in
+       returnNF_Tc (InstInfo clas tyvars tys inst_decl_theta
+                             dfun_id meth_binds locn [])
+
+    rn_meths meths = rnMethodBinds meths `thenRn` \ (meths', _) -> returnRn meths'
+       -- Ignore the free vars returned
 \end{code}
 
 
@@ -292,7 +296,6 @@ makeDerivEqns
 
        think_about_deriving = need_deriving local_data_tycons
        (derive_these, _)    = removeDups cmp_deriv think_about_deriving
-       eqns                 = map mk_eqn derive_these
     in
     if null local_data_tycons then
        returnTc []     -- Bale out now
@@ -551,17 +554,13 @@ the renamer.  What a great hack!
 -- Generate the method bindings for the required instance
 -- (paired with class name, as we need that when generating dict
 --  names.)
-gen_bind :: FixityEnv -> InstInfo -> ({-class-}OccName, {-tyCon-}OccName, RdrNameMonoBinds)
+gen_bind :: FixityEnv -> InstInfo -> RdrNameMonoBinds
 gen_bind fixities (InstInfo clas _ [ty] _ _ _ _ _)
-  | not from_here 
-  = (clas_nm, tycon_nm, EmptyMonoBinds)
-  |  clas `hasKey` showClassKey 
-  = (clas_nm, tycon_nm, gen_Show_binds fixities tycon)
-  |  clas `hasKey` readClassKey 
-  = (clas_nm, tycon_nm, gen_Read_binds fixities tycon)
+  | not from_here              = EmptyMonoBinds
+  | clas `hasKey` showClassKey  = gen_Show_binds fixities tycon
+  | clas `hasKey` readClassKey  = gen_Read_binds fixities tycon
   | otherwise
-  = (clas_nm, tycon_nm,
-     assoc "gen_bind:bad derived class"
+  = assoc "gen_bind:bad derived class"
           [(eqClassKey,      gen_Eq_binds)
           ,(ordClassKey,     gen_Ord_binds)
           ,(enumClassKey,    gen_Enum_binds)
@@ -569,30 +568,10 @@ gen_bind fixities (InstInfo clas _ [ty] _ _ _ _ _)
           ,(ixClassKey,      gen_Ix_binds)
           ]
           (classKey clas)
-          tycon)
+          tycon
   where
-      clas_nm     = nameOccName (getName clas)
-      tycon_nm    = nameOccName (getName tycon)
       from_here   = isLocallyDefined tycon
       (tycon,_,_) = splitAlgTyConApp ty        
-
-gen_inst_info :: InstInfo
-             -> (Name, RenamedMonoBinds)
-             -> InstInfo                               -- the gen'd (filled-in) "instance decl"
-
-gen_inst_info (InstInfo clas tyvars tys@(ty:_) inst_decl_theta _ _ locn _) 
-             (dfun_name, meth_binds)
-  =
-       -- Generate the various instance-related Ids
-    InstInfo clas tyvars tys inst_decl_theta
-              dfun_id
-              meth_binds
-              locn []
-  where
-   dfun_id = mkDictFunId dfun_name clas tyvars tys inst_decl_theta
-
-   from_here = isLocallyDefined tycon
-   (tycon,_,_) = splitAlgTyConApp ty
 \end{code}
 
 
index ab30217..cdfc6f3 100644 (file)
@@ -26,6 +26,7 @@ module TcEnv(
        valueEnvIds,
 
        newLocalId, newSpecPragmaId,
+       newDefaultMethodName, newDFunName,
        tcGetGlobalTyVars, tcExtendGlobalTyVars,
 
        InstEnv, emptyInstEnv, addToInstEnv, 
@@ -50,7 +51,7 @@ import VarSet
 import Type    ( Kind, Type, superKind,
                  tyVarsOfType, tyVarsOfTypes,
                  splitForAllTys, splitRhoTy, splitFunTys,
-                 splitAlgTyConApp_maybe, getTyVar
+                 splitAlgTyConApp_maybe, getTyVar, getDFunTyKey
                )
 import Subst   ( substTy )
 import UsageSPUtils ( unannotTy )
@@ -62,12 +63,14 @@ import TcMonad
 
 import BasicTypes      ( Arity )
 import IdInfo          ( vanillaIdInfo )
-import Name            ( Name, OccName, nameOccName, getSrcLoc,
+import Name            ( Name, OccName, Provenance(..), ExportFlag(..), NamedThing(..), 
+                         nameOccName, nameModule, getSrcLoc, mkGlobalName,
                          maybeWiredInTyConName, maybeWiredInIdName, isLocallyDefined,
-                         NamedThing(..), 
                          NameEnv, emptyNameEnv, lookupNameEnv, nameEnvElts, 
                                   extendNameEnv, extendNameEnvList
                        )
+import OccName         ( mkDFunOcc, mkDefaultMethodOcc, occNameString )
+import Module          ( Module )
 import Unify           ( unifyTyListsX, matchTys )
 import Unique          ( pprUnique10, Unique, Uniquable(..) )
 import UniqFM
@@ -736,6 +739,27 @@ addToInstEnv overlap_ok inst_env clas ins_tvs ins_tys value
        identical = ins_item_more_specific && cur_item_more_specific
 \end{code}
 
+Make a name for the dict fun for an instance decl
+
+\begin{code}
+newDFunName :: Module -> Class -> [Type] -> SrcLoc -> NF_TcM s Name
+newDFunName mod clas (ty:_) loc
+  = tcGetDFunUniq dfun_string  `thenNF_Tc` \ inst_uniq ->
+    tcGetUnique                        `thenNF_Tc` \ uniq ->
+    returnNF_Tc (mkGlobalName uniq mod
+                             (mkDFunOcc dfun_string inst_uniq) 
+                             (LocalDef loc Exported))
+  where
+       -- Any string that is somewhat unique will do
+    dfun_string = occNameString (getOccName clas) ++ occNameString (getDFunTyKey ty)
+
+newDefaultMethodName :: Name -> SrcLoc -> NF_TcM s Name
+newDefaultMethodName op_name loc
+  = tcGetUnique                        `thenNF_Tc` \ uniq ->
+    returnNF_Tc (mkGlobalName uniq (nameModule op_name)
+                             (mkDefaultMethodOcc (getOccName op_name))
+                             (LocalDef loc Exported))
+\end{code}
 
 
 %************************************************************************
index 7ba6d21..9093ccb 100644 (file)
@@ -6,7 +6,7 @@ module TcImprove ( tcImprove ) where
 import Name            ( Name )
 import Class           ( Class, FunDep, className, classExtraBigSig )
 import Unify           ( unifyTyListsX, matchTys )
-import Subst           ( mkSubst, substTy )
+import Subst           ( mkSubst, emptyInScopeSet, substTy )
 import TcEnv           ( tcGetInstEnv, classInstEnv )
 import TcMonad
 import TcType          ( TcType, TcTyVar, TcTyVarSet, zonkTcType, zonkTcTypes )
@@ -104,8 +104,9 @@ checkFd free (t_x, t_y) (s_x, s_y)
   = zonkUnifyTys free t_x s_x `thenTc` \ msubst ->
     case msubst of
       Just subst ->
-       let t_y' = map (substTy (mkSubst emptyVarEnv subst)) t_y
-           s_y' = map (substTy (mkSubst emptyVarEnv subst)) s_y
+       let full_subst = mkSubst emptyInScopeSet subst
+           t_y' = map (substTy full_subst) t_y
+           s_y' = map (substTy full_subst) s_y
        in
            zonkEqTys t_y' s_y' `thenTc` \ eq ->
            if eq then
index fd2b5dd..38a4f3f 100644 (file)
@@ -25,7 +25,7 @@ import Inst           ( Inst, InstOrigin(..),
                          LIE, emptyLIE, plusLIE, plusLIEs )
 import TcDeriv         ( tcDeriving )
 import TcEnv           ( ValueEnv, tcExtendGlobalValEnv, tcExtendTyVarEnvForMeths,
-                         tcAddImportedIdInfo, tcInstId
+                         tcAddImportedIdInfo, tcInstId, newDFunName
                        )
 import TcInstUtil      ( InstInfo(..), classDataCon )
 import TcMonoType      ( tcHsSigType )
@@ -40,7 +40,7 @@ import Class          ( classBigSig, Class )
 import Var             ( idName, idType, Id, TyVar )
 import Maybes          ( maybeToBool, catMaybes, expectJust )
 import MkId            ( mkDictFunId )
-import Module          ( ModuleName )
+import Module          ( Module )
 import Name            ( isLocallyDefined, NamedThing(..)      )
 import NameSet         ( emptyNameSet )
 import PrelInfo                ( eRROR_ID )
@@ -136,15 +136,15 @@ and $dbinds_super$ bind the superclass dictionaries sd1 \ldots sdm.
 \begin{code}
 tcInstDecls1 :: ValueEnv               -- Contains IdInfo for dfun ids
             -> [RenamedHsDecl]
-            -> ModuleName                      -- module name for deriving
-            -> FixityEnv
-            -> RnNameSupply                    -- for renaming derivings
+            -> Module                  -- Module for deriving
+            -> FixityEnv               -- For derivings
+            -> RnNameSupply            -- For renaming derivings
             -> TcM s (Bag InstInfo,
                       RenamedHsBinds)
 
-tcInstDecls1 unf_env decls mod_name fixs rn_name_supply
+tcInstDecls1 unf_env decls mod fixs rn_name_supply
   =    -- Do the ordinary instance declarations
-    mapNF_Tc (tcInstDecl1 unf_env) 
+    mapNF_Tc (tcInstDecl1 mod unf_env) 
             [inst_decl | InstD inst_decl <- decls]     `thenNF_Tc` \ inst_info_bags ->
     let
        decl_inst_info = unionManyBags inst_info_bags
@@ -152,7 +152,7 @@ tcInstDecls1 unf_env decls mod_name fixs rn_name_supply
        -- Handle "derived" instances; note that we only do derivings
        -- for things in this module; we ignore deriving decls from
        -- interfaces!
-    tcDeriving mod_name fixs rn_name_supply decl_inst_info
+    tcDeriving mod fixs rn_name_supply decl_inst_info
                        `thenTc` \ (deriv_inst_info, deriv_binds) ->
 
     let
@@ -161,9 +161,9 @@ tcInstDecls1 unf_env decls mod_name fixs rn_name_supply
     returnTc (full_inst_info, deriv_binds)
 
 
-tcInstDecl1 :: ValueEnv -> RenamedInstDecl -> NF_TcM s (Bag InstInfo)
+tcInstDecl1 :: Module -> ValueEnv -> RenamedInstDecl -> NF_TcM s (Bag InstInfo)
 
-tcInstDecl1 unf_env (InstDecl poly_ty binds uprags dfun_name src_loc)
+tcInstDecl1 mod unf_env (InstDecl poly_ty binds uprags maybe_dfun_name src_loc)
   =    -- Prime error recovery, set source location
     recoverNF_Tc (returnNF_Tc emptyBag)        $
     tcAddSrcLoc src_loc                        $
@@ -178,28 +178,30 @@ tcInstDecl1 unf_env (InstDecl poly_ty binds uprags dfun_name src_loc)
                                     Nothing -> pprPanic "tcInstDecl1" (ppr poly_ty)
     in
 
-       -- Check for respectable instance type, and context
-       -- but only do this for non-imported instance decls.
-       -- Imported ones should have been checked already, and may indeed
-       -- contain something illegal in normal Haskell, notably
-       --      instance CCallable [Char] 
-    (if isLocallyDefined dfun_name then
-       scrutiniseInstanceHead clas inst_tys    `thenNF_Tc_`
-       mapNF_Tc scrutiniseInstanceConstraint constr
-     else
-       returnNF_Tc []
-     )                                         `thenNF_Tc_`
-
-       -- Make the dfun id
-    let
-       dfun_id = mkDictFunId dfun_name clas tyvars inst_tys constr
-
-       -- Add info from interface file
-       final_dfun_id = tcAddImportedIdInfo unf_env dfun_id
-    in
-    returnTc (unitBag (InstInfo clas tyvars inst_tys constr
-                               final_dfun_id
-                               binds src_loc uprags))
+    (case maybe_dfun_name of
+       Nothing ->      -- A source-file instance declaration
+
+               -- Check for respectable instance type, and context
+               -- but only do this for non-imported instance decls.
+               -- Imported ones should have been checked already, and may indeed
+               -- contain something illegal in normal Haskell, notably
+               --      instance CCallable [Char] 
+           scrutiniseInstanceHead clas inst_tys                `thenNF_Tc_`
+           mapNF_Tc scrutiniseInstanceConstraint constr        `thenNF_Tc_`
+
+               -- Make the dfun id and return it
+           newDFunName mod clas inst_tys src_loc               `thenNF_Tc` \ dfun_name ->
+           returnNF_Tc (mkDictFunId dfun_name clas tyvars inst_tys constr)
+
+       Just dfun_name ->       -- An interface-file instance declaration
+               -- Make the dfun id and add info from interface file
+           let
+               dfun_id = mkDictFunId dfun_name clas tyvars inst_tys constr
+           in
+           returnNF_Tc (tcAddImportedIdInfo unf_env dfun_id)
+    )                                          `thenNF_Tc` \ dfun_id ->
+
+    returnTc (unitBag (InstInfo clas tyvars inst_tys constr dfun_id binds src_loc uprags))
 \end{code}
 
 
@@ -299,22 +301,14 @@ tcInstDecl2 (InstInfo clas inst_tyvars inst_tys
   | not (isLocallyDefined dfun_id)
   = returnNF_Tc (emptyLIE, EmptyMonoBinds)
 
-{-
-  -- I deleted this "optimisation" because when importing these
-  -- instance decls the renamer would look for the dfun bindings and they weren't there.
-  -- This would be fixable, but it seems simpler just to produce a tiny void binding instead,
-  -- even though it's never used.
-
-       -- This case deals with CCallable etc, which don't need any bindings
-  | isNoDictClass clas                 
-  = returnNF_Tc (emptyLIE, EmptyBinds)
--}
-
   | otherwise
   =     -- Prime error recovery
     recoverNF_Tc (returnNF_Tc (emptyLIE, EmptyMonoBinds))  $
     tcAddSrcLoc locn                                      $
 
+        -- Check that all the method bindings come from this class
+    checkFromThisClass clas monobinds                  `thenNF_Tc_`
+
        -- Instantiate the instance decl with tc-style type variables
     tcInstId dfun_id           `thenNF_Tc` \ (inst_tyvars', dfun_theta', dict_ty') ->
     let
@@ -339,9 +333,6 @@ tcInstDecl2 (InstInfo clas inst_tyvars inst_tys
     newClassDicts origin inst_decl_theta' `thenNF_Tc` \ (inst_decl_dicts, _) ->
     newClassDicts origin [(clas,inst_tys')] `thenNF_Tc` \ (this_dict,       [this_dict_id]) ->
 
-        -- Check that all the method bindings come from this class
-    checkFromThisClass clas op_items monobinds         `thenNF_Tc_`
-
     tcExtendTyVarEnvForMeths inst_tyvars inst_tyvars' (
        tcExtendGlobalValEnv dm_ids (
                -- Default-method Ids may be mentioned in synthesised RHSs 
index 86f20ca..34a82d1 100644 (file)
@@ -45,12 +45,12 @@ import RnMonad              ( RnNameSupply, FixityEnv )
 import Bag             ( isEmptyBag )
 import ErrUtils                ( Message, printErrorsAndWarnings, dumpIfSet )
 import Id              ( Id, idType, idName )
-import Module           ( pprModuleName )
+import Module           ( pprModuleName, mkThisModule )
 import OccName         ( isSysOcc )
 import Name            ( Name, nameUnique, nameOccName, isLocallyDefined, 
                          toRdrName, nameEnvElts, NamedThing(..)
                        )
-import TyCon           ( TyCon, tyConKind )
+import TyCon           ( TyCon, tyConKind, tyConClass_maybe )
 import Class           ( Class, classSelIds, classTyCon )
 import PrelInfo                ( mAIN_Name )
 import Unique          ( Unique, mainKey )
@@ -151,17 +151,22 @@ tcModule rn_name_supply fixities
        tcSetEnv env $
 
        tcInstDecls1 unf_env decls 
-                    mod_name fixities 
-                    rn_name_supply     `thenTc` \ (inst_info, deriv_binds) ->
+                    (mkThisModule mod_name)
+                    fixities rn_name_supply    `thenTc` \ (inst_info, deriv_binds) ->
     
        buildInstanceEnv inst_info      `thenNF_Tc` \ inst_env ->
 
        tcSetInstEnv inst_env $
        let
-           tycons       = getEnvTyCons env
            classes      = getEnvClasses env
-           local_tycons  = filter isLocallyDefined tycons
+           tycons       = getEnvTyCons env     -- INCLUDES tycons derived from classes
            local_classes = filter isLocallyDefined classes
+           local_tycons  = [ tc | tc <- tycons,
+                                  isLocallyDefined tc,
+                                  Nothing <- [tyConClass_maybe tc]
+                           ]
+                               -- For local_tycons, filter out the ones derived from classes
+                               -- Otherwise the latter show up in interface files
        in
        
            -- Default declarations
index 0f86e07..5b3e11f 100644 (file)
@@ -26,7 +26,7 @@ module TcMonad(
 
        tcGetEnv, tcSetEnv,
        tcGetDefaultTys, tcSetDefaultTys,
-       tcGetUnique, tcGetUniques,
+       tcGetUnique, tcGetUniques, tcGetDFunUniq,
 
        tcAddSrcLoc, tcGetSrcLoc, tcGetInstLoc,
        tcAddErrCtxtM, tcSetErrCtxtM,
@@ -62,6 +62,7 @@ import VarSet         ( TyVarSet )
 import UniqSupply      ( UniqSupply, uniqFromSupply, uniqsFromSupply, splitUniqSupply,
                          UniqSM, initUs_ )
 import SrcLoc          ( SrcLoc, noSrcLoc )
+import FiniteMap       ( FiniteMap, lookupFM, addToFM, emptyFM )
 import UniqFM          ( UniqFM, emptyUFM )
 import Unique          ( Unique )
 import BasicTypes      ( Unused )
@@ -126,11 +127,12 @@ initTc :: UniqSupply
 initTc us initenv do_this
   = do {
       us_var   <- newIORef us ;
+      dfun_var <- newIORef emptyFM ;
       errs_var <- newIORef (emptyBag,emptyBag) ;
       tvs_var  <- newIORef emptyUFM ;
 
       let
-          init_down = TcDown [] us_var
+          init_down = TcDown [] us_var dfun_var
                             noSrcLoc
                             [] errs_var
          init_env  = initenv tvs_var
@@ -246,7 +248,7 @@ We throw away any error messages!
 
 \begin{code}
 forkNF_Tc :: NF_TcM s r -> NF_TcM s r
-forkNF_Tc m (TcDown deflts u_var src_loc err_cxt err_var) env
+forkNF_Tc m (TcDown deflts u_var df_var src_loc err_cxt err_var) env
   = do
        -- Get a fresh unique supply
        us <- readIORef u_var
@@ -257,7 +259,7 @@ forkNF_Tc m (TcDown deflts u_var src_loc err_cxt err_var) env
                us_var'  <- newIORef us2 ;
                err_var' <- newIORef (emptyBag,emptyBag) ;
                tv_var'  <- newIORef emptyUFM ;
-               let { down' = TcDown deflts us_var' src_loc err_cxt err_var' } ;
+               let { down' = TcDown deflts us_var' df_var src_loc err_cxt err_var' } ;
                m down' env
                        -- ToDo: optionally dump any error messages
                })
@@ -532,6 +534,23 @@ uniqSMToTcM m down env
 \end{code}
 
 
+\section{Dictionary function name supply
+%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+\begin{code}
+tcGetDFunUniq :: String -> NF_TcM s Int
+tcGetDFunUniq key down env
+  = do dfun_supply <- readIORef d_var
+       let uniq = case lookupFM dfun_supply key of
+                     Just x  -> x+1
+                     Nothing -> 0
+       let dfun_supply' = addToFM dfun_supply key uniq
+       writeIORef d_var dfun_supply'
+       return uniq
+  where
+    d_var = getDFunSupplyVar down
+\end{code}
+
+
 \section{TcDown}
 %~~~~~~~~~~~~~~~
 
@@ -541,35 +560,49 @@ data TcDown
        [Type]                  -- Types used for defaulting
 
        (TcRef UniqSupply)      -- Unique supply
+       (TcRef DFunNameSupply)  -- Name supply for dictionary function names
 
        SrcLoc                  -- Source location
        ErrCtxt                 -- Error context
-       (TcRef (Bag WarnMsg, 
-                 Bag ErrMsg))
+       (TcRef (Bag WarnMsg, Bag ErrMsg))
 
 type ErrCtxt = [TidyEnv -> NF_TcM Unused (TidyEnv, Message)]   
                        -- Innermost first.  Monadic so that we have a chance
                        -- to deal with bound type variables just before error
                        -- message construction
+
+type DFunNameSupply = FiniteMap String Int
+       -- This is used as a name supply for dictionary functions
+       -- From the inst decl we derive a string, usually by glomming together
+       -- the class and tycon name -- but it doesn't matter exactly how;
+       -- this map then gives a unique int for each inst decl with that
+       -- string.  (In Haskell 98 there can only be one,
+       -- but not so in more extended versions; also class CC type T
+       -- and class C type TT might both give the string CCT
+       --      
+       -- We could just use one Int for all the instance decls, but this
+       -- way the uniques change less when you add an instance decl,   
+       -- hence less recompilation
 \end{code}
 
 -- These selectors are *local* to TcMonad.lhs
 
 \begin{code}
-getTcErrs (TcDown def us loc ctxt errs)      = errs
-setTcErrs (TcDown def us loc ctxt _   ) errs = TcDown def us loc ctxt errs
+getTcErrs (TcDown def us ds loc ctxt errs)      = errs
+setTcErrs (TcDown def us ds loc ctxt _   ) errs = TcDown def us ds loc ctxt errs
 
-getDefaultTys (TcDown def us loc ctxt errs)     = def
-setDefaultTys (TcDown _   us loc ctxt errs) def = TcDown def us loc ctxt errs
+getDefaultTys (TcDown def us ds loc ctxt errs)     = def
+setDefaultTys (TcDown _   us ds loc ctxt errs) def = TcDown def us ds loc ctxt errs
 
-getLoc (TcDown def us loc ctxt errs)     = loc
-setLoc (TcDown def us _   ctxt errs) loc = TcDown def us loc ctxt errs
+getLoc (TcDown def us ds loc ctxt errs)     = loc
+setLoc (TcDown def us ds _   ctxt errs) loc = TcDown def us ds loc ctxt errs
 
-getUniqSupplyVar (TcDown def us loc ctxt errs) = us
+getUniqSupplyVar (TcDown def us ds loc ctxt errs) = us
+getDFunSupplyVar (TcDown def us ds loc ctxt errs) = ds
 
-setErrCtxt (TcDown def us loc ctxt errs) msg = TcDown def us loc [msg]      errs
-addErrCtxt (TcDown def us loc ctxt errs) msg = TcDown def us loc (msg:ctxt) errs
-getErrCtxt (TcDown def us loc ctxt errs)     = ctxt
+setErrCtxt (TcDown def us ds loc ctxt errs) msg = TcDown def us ds loc [msg]      errs
+addErrCtxt (TcDown def us ds loc ctxt errs) msg = TcDown def us ds loc (msg:ctxt) errs
+getErrCtxt (TcDown def us ds loc ctxt errs)     = ctxt
 \end{code}
 
 
index a194ed3..8d803fd 100644 (file)
@@ -240,7 +240,7 @@ kcTyClDecl decl@(ClassDecl context class_name
     kcHsContext context                        `thenTc_`
     mapTc_ kc_sig (filter isClassOpSig class_sigs)
   where
-    kc_sig (ClassOpSig _ _ _ op_ty loc) = tcAddSrcLoc loc (kcHsBoxedSigType op_ty)
+    kc_sig (ClassOpSig _ _ op_ty loc) = tcAddSrcLoc loc (kcHsBoxedSigType op_ty)
 
 kcTyClDeclBody :: Name -> [HsTyVarBndr Name]   -- Kind of the tycon/cls and its tyvars
               -> (Kind -> TcM s a)             -- Thing inside
@@ -452,8 +452,8 @@ get_tys tys = unionManyUniqSets (map get_ty tys)
 get_sigs sigs
   = unionManyUniqSets (map get_sig sigs)
   where 
-    get_sig (ClassOpSig _ _ _ ty _) = get_ty ty
-    get_sig (FixSig _)             = emptyUniqSet
+    get_sig (ClassOpSig _ _ ty _) = get_ty ty
+    get_sig (FixSig _)           = emptyUniqSet
     get_sig other = panic "TcTyClsDecls:get_sig"
 
 ----------------------------------------------------
index f20ef3d..e57e125 100644 (file)
@@ -47,6 +47,7 @@ module Type (
        getClassTys_maybe, ipName_maybe, classesToPreds, classesOfPreds,
        isTauTy, mkRhoTy, splitRhoTy,
        mkSigmaTy, isSigmaTy, splitSigmaTy,
+       getDFunTyKey,
 
        -- Lifting and boxity
        isUnLiftedType, isUnboxedType, isUnboxedTupleType, isAlgType, isDataType, isNewType,
@@ -86,8 +87,7 @@ import Var    ( TyVar, Var, UVar,
 import VarEnv
 import VarSet
 
-import Name    ( Name, NamedThing(..), mkLocalName, tidyOccName
-               )
+import Name    ( Name, NamedThing(..), OccName, mkLocalName, tidyOccName )
 import NameSet
 import Class   ( classTyCon, Class, ClassPred, ClassContext )
 import TyCon   ( TyCon,
@@ -762,6 +762,17 @@ splitSigmaTy ty =
   (theta,tau)  = splitRhoTy rho
 \end{code}
 
+\begin{code}
+getDFunTyKey :: Type -> OccName        -- Get some string from a type, to be used to 
+                               -- construct a dictionary function name
+getDFunTyKey (TyVarTy tv)    = getOccName tv
+getDFunTyKey (TyConApp tc _) = getOccName tc
+getDFunTyKey (AppTy fun _)   = getDFunTyKey fun
+getDFunTyKey (NoteTy _ t)    = getDFunTyKey t
+getDFunTyKey (FunTy arg _)   = getOccName funTyCon
+getDFunTyKey (ForAllTy _ t)  = getDFunTyKey t
+\end{code}
+
 
 %************************************************************************
 %*                                                                     *