[project @ 1996-03-19 08:58:34 by partain]
[ghc-hetmet.git] / ghc / compiler / rename / RnBinds4.lhs
diff --git a/ghc/compiler/rename/RnBinds4.lhs b/ghc/compiler/rename/RnBinds4.lhs
new file mode 100644 (file)
index 0000000..418c626
--- /dev/null
@@ -0,0 +1,711 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
+%
+\section[RnBinds4]{Renaming and dependency analysis of bindings}
+
+This module does renaming and dependency analysis on value bindings in
+the abstract syntax.  It does {\em not} do cycle-checks on class or
+type-synonym declarations; those cannot be done at this stage because
+they may be affected by renaming (which isn't fully worked out yet).
+
+\begin{code}
+#include "HsVersions.h"
+
+module RnBinds4 (
+       rnTopBinds, rnMethodBinds,
+       rnBinds,
+       FreeVars(..), DefinedVars(..)
+
+       -- and to make the interface self-sufficient...
+   ) where
+
+import Ubiq{-uitous-}
+import RnLoop  -- break the RnPass4/RnExpr4/RnBinds4 loops
+
+import HsSyn
+import RdrHsSyn
+import RnHsSyn
+import HsPragmas       ( noGenPragmas )
+import RnMonad4
+
+-- others:
+import CmdLineOpts     ( opt_SigsRequired )
+import Digraph         ( stronglyConnComp )
+import ErrUtils                ( addErrLoc, addShortErrLocLine )
+import Maybes          ( catMaybes )
+import Name            ( isUnboundName, Name{-instances-} )
+import Pretty
+import ProtoName       ( elemByLocalNames, eqByLocalName, ProtoName{-instances-} )
+import RnExpr4         -- OK to look here; but not the other way 'round
+import UniqSet         ( emptyUniqSet, singletonUniqSet, mkUniqSet,
+                         unionUniqSets, unionManyUniqSets,
+                         elementOfUniqSet,
+                         uniqSetToList,
+                         UniqSet(..)
+                       )
+import Util            ( isIn, removeDups, panic, panic# )
+\end{code}
+
+-- ToDo: Put the annotations into the monad, so that they arrive in the proper
+-- place and can be used when complaining.
+
+The code tree received by the function @rnBinds@ contains definitions
+in where-clauses which are all apparently mutually recursive, but which may
+not really depend upon each other. For example, in the top level program
+\begin{verbatim}
+f x = y where a = x
+             y = x
+\end{verbatim}
+the definitions of @a@ and @y@ do not depend on each other at all.
+Unfortunately, the typechecker cannot always check such definitions.
+\footnote{Mycroft, A. 1984. Polymorphic type schemes and recursive
+definitions. In Proceedings of the International Symposium on Programming,
+Toulouse, pp. 217-39. LNCS 167. Springer Verlag.}
+However, the typechecker usually can check definitions in which only the
+strongly connected components have been collected into recursive bindings.
+This is precisely what the function @rnBinds@ does.
+
+ToDo: deal with case where a single monobinds binds the same variable
+twice.
+
+Sets of variable names are represented as sets explicitly, rather than lists.
+
+\begin{code}
+type DefinedVars = UniqSet Name
+type FreeVars    = UniqSet Name
+\end{code}
+
+i.e., binders.
+
+The vertag tag is a unique @Int@; the tags only need to be unique
+within one @MonoBinds@, so that unique-Int plumbing is done explicitly
+(heavy monad machinery not needed).
+
+\begin{code}
+type VertexTag = Int
+type Cycle     = [VertexTag]
+type Edge      = (VertexTag, VertexTag)
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+%* naming conventions                                                  *
+%*                                                                     *
+%************************************************************************
+\subsection[name-conventions]{Name conventions}
+
+The basic algorithm involves walking over the tree and returning a tuple
+containing the new tree plus its free variables. Some functions, such
+as those walking polymorphic bindings (HsBinds) and qualifier lists in
+list comprehensions (@Quals@), return the variables bound in local
+environments. These are then used to calculate the free variables of the
+expression evaluated in these environments.
+
+Conventions for variable names are as follows:
+\begin{itemize}
+\item
+new code is given a prime to distinguish it from the old.
+
+\item
+a set of variables defined in @Exp@ is written @dvExp@
+
+\item
+a set of variables free in @Exp@ is written @fvExp@
+\end{itemize}
+
+%************************************************************************
+%*                                                                     *
+%* analysing polymorphic bindings (HsBinds, Bind, MonoBinds)           *
+%*                                                                     *
+%************************************************************************
+\subsubsection[dep-HsBinds]{Polymorphic bindings}
+
+Non-recursive expressions are reconstructed without any changes at top
+level, although their component expressions may have to be altered.
+However, non-recursive expressions are currently not expected as
+\Haskell{} programs, and this code should not be executed.
+
+Monomorphic bindings contain information that is returned in a tuple
+(a @FlatMonoBindsInfo@) containing:
+
+\begin{enumerate}
+\item
+a unique @Int@ that serves as the ``vertex tag'' for this binding.
+
+\item
+the name of a function or the names in a pattern. These are a set
+referred to as @dvLhs@, the defined variables of the left hand side.
+
+\item
+the free variables of the body. These are referred to as @fvBody@.
+
+\item
+the definition's actual code. This is referred to as just @code@.
+\end{enumerate}
+
+The function @nonRecDvFv@ returns two sets of variables. The first is
+the set of variables defined in the set of monomorphic bindings, while the
+second is the set of free variables in those bindings.
+
+The set of variables defined in a non-recursive binding is just the
+union of all of them, as @union@ removes duplicates. However, the
+free variables in each successive set of cumulative bindings is the
+union of those in the previous set plus those of the newest binding after
+the defined variables of the previous set have been removed.
+
+@rnMethodBinds@ deals only with the declarations in class and
+instance declarations. It expects only to see @FunMonoBind@s, and
+it expects the global environment to contain bindings for the binders
+(which are all class operations).
+
+\begin{code}
+rnTopBinds     :: ProtoNameHsBinds -> Rn4M RenamedHsBinds
+rnMethodBinds  :: Name{-class-} -> ProtoNameMonoBinds -> Rn4M RenamedMonoBinds
+rnBinds        :: ProtoNameHsBinds -> Rn4M (RenamedHsBinds, FreeVars, [Name])
+
+rnTopBinds EmptyBinds                     = returnRn4 EmptyBinds
+rnTopBinds (SingleBind (RecBind bind))    = rnTopMonoBinds bind []
+rnTopBinds (BindWith (RecBind bind) sigs) = rnTopMonoBinds bind sigs
+  -- the parser doesn't produce other forms
+
+-- ********************************************************************
+
+rnMethodBinds class_name EmptyMonoBinds = returnRn4 EmptyMonoBinds
+
+rnMethodBinds class_name (AndMonoBinds mb1 mb2)
+  = andRn4 AndMonoBinds (rnMethodBinds class_name mb1)
+                       (rnMethodBinds class_name mb2)
+
+rnMethodBinds class_name (FunMonoBind pname matches locn)
+  = pushSrcLocRn4 locn                           (
+    lookupClassOp class_name pname     `thenRn4` \ op_name ->
+    mapAndUnzipRn4 rnMatch matches     `thenRn4` \ (new_matches, _) ->
+    returnRn4 (FunMonoBind op_name new_matches locn)
+    )
+
+rnMethodBinds class_name (PatMonoBind (VarPatIn pname) grhss_and_binds locn)
+  = pushSrcLocRn4 locn                           (
+    lookupClassOp class_name pname     `thenRn4` \ op_name ->
+    rnGRHSsAndBinds grhss_and_binds    `thenRn4` \ (grhss_and_binds', _) ->
+    returnRn4 (PatMonoBind (VarPatIn op_name) grhss_and_binds' locn)
+    )
+
+-- Can't handle method pattern-bindings which bind multiple methods.
+rnMethodBinds _ mbind@(PatMonoBind other_pat _ locn)
+  = failButContinueRn4 EmptyMonoBinds (methodBindErr mbind locn)
+
+-- ********************************************************************
+
+rnBinds EmptyBinds                     = returnRn4 (EmptyBinds,emptyUniqSet,[])
+rnBinds (SingleBind (RecBind bind))    = rnNestedMonoBinds bind []
+rnBinds (BindWith (RecBind bind) sigs) = rnNestedMonoBinds bind sigs
+  -- the parser doesn't produce other forms
+\end{code}
+
+@rnNestedMonoBinds@
+       - collects up the binders for this declaration group,
+       - checkes that they form a set
+       - extends the environment to bind them to new local names
+       - calls @rnMonoBinds@ to do the real work
+
+In contrast, @rnTopMonoBinds@ doesn't extend the environment, because that's
+already done in pass3. All it does is call @rnMonoBinds@ and discards
+the free var info.
+
+\begin{code}
+rnTopMonoBinds :: ProtoNameMonoBinds -> [ProtoNameSig] -> Rn4M RenamedHsBinds
+
+rnTopMonoBinds EmptyMonoBinds sigs = returnRn4 EmptyBinds
+
+rnTopMonoBinds mbs sigs
+ = rnBindSigs True{-top-level-} (collectMonoBinders mbs) sigs `thenRn4` \ siglist ->
+   rnMonoBinds mbs siglist `thenRn4` \ (new_binds, fv_set) ->
+   returnRn4 new_binds
+
+
+rnNestedMonoBinds :: ProtoNameMonoBinds -> [ProtoNameSig]
+                     -> Rn4M (RenamedHsBinds, FreeVars, [Name])
+
+rnNestedMonoBinds EmptyMonoBinds sigs
+  = returnRn4 (EmptyBinds, emptyUniqSet, [])
+
+rnNestedMonoBinds mbinds sigs  -- Non-empty monobinds
+  =
+       -- Extract all the binders in this group,
+       -- and extend current scope, inventing new names for the new binders
+       -- This also checks that the names form a set
+    let
+       mbinders_w_srclocs = collectMonoBindersAndLocs mbinds
+       mbinders           = map fst mbinders_w_srclocs
+    in
+    namesFromProtoNames
+       "variable" -- in binding group
+       mbinders_w_srclocs              `thenRn4` \ new_mbinders ->
+
+    extendSS2 new_mbinders (
+        rnBindSigs False{-not top- level-} mbinders sigs `thenRn4` \ siglist ->
+        rnMonoBinds mbinds  siglist
+    )                                  `thenRn4` \ (new_binds, fv_set) ->
+    returnRn4 (new_binds, fv_set, new_mbinders)
+\end{code}
+
+@rnMonoBinds@ is used by *both* top-level and nested bindings.  It
+assumes that all variables bound in this group are already in scope.
+This is done *either* by pass 3 (for the top-level bindings),
+*or* by @rnNestedMonoBinds@ (for the nested ones).
+
+\begin{code}
+rnMonoBinds :: ProtoNameMonoBinds
+            -> [RenamedSig]    -- Signatures attached to this group
+            -> Rn4M (RenamedHsBinds, FreeVars)
+
+rnMonoBinds mbinds siglist
+  =
+        -- Rename the bindings, returning a MonoBindsInfo
+        -- which is a list of indivisible vertices so far as
+        -- the strongly-connected-components (SCC) analysis is concerned
+    flattenMonoBinds 0 siglist mbinds  `thenRn4` \ (_, mbinds_info) ->
+
+        -- Do the SCC analysis
+    let vertices = mkVertices mbinds_info
+       edges   = mkEdges vertices mbinds_info
+
+       scc_result = stronglyConnComp (==) edges vertices
+
+        -- Deal with bound and free-var calculation
+       rhs_free_vars = foldr f emptyUniqSet mbinds_info
+
+       final_binds = reconstructRec scc_result edges mbinds_info
+
+       happy_answer = returnRn4 (final_binds, rhs_free_vars)
+    in
+    case (inline_sigs_in_recursive_binds final_binds) of
+      Nothing -> happy_answer
+      Just names_n_locns ->
+-- SLPJ: sometimes want recursive INLINE for worker wrapper style stuff
+--     addErrRn4 (inlineInRecursiveBindsErr names_n_locns) `thenRn4_`
+       {-not so-}happy_answer
+  where
+    f :: (a,b, FreeVars, c,d) -> FreeVars -> FreeVars
+
+    f (_, _, fvs_body, _, _) fvs_sofar = fvs_sofar `unionUniqSets` fvs_body
+
+    inline_sigs_in_recursive_binds (BindWith (RecBind _) sigs)
+      = case [(n, locn) | (InlineSig n locn) <- sigs ] of
+         []   -> Nothing
+         sigh ->
+#if OMIT_DEFORESTER
+               Just sigh
+#else
+               -- Allow INLINEd recursive functions if they are
+               -- designated DEFORESTable too.
+               case [(n, locn) | (DeforestSig n locn) <- sigs ] of
+                       []   -> Just sigh
+                       sigh -> Nothing
+#endif
+
+    inline_sigs_in_recursive_binds (ThenBinds b1 b2)
+      = case (inline_sigs_in_recursive_binds b1) of
+         Nothing -> inline_sigs_in_recursive_binds b2
+         Just  x -> Just x -- NB: won't report error(s) in b2
+
+    inline_sigs_in_recursive_binds anything_else = Nothing
+\end{code}
+
+@flattenMonoBinds@ is ever-so-slightly magical in that it sticks
+unique ``vertex tags'' on its output; minor plumbing required.
+
+\begin{code}
+flattenMonoBinds :: Int                                -- Next free vertex tag
+                -> [RenamedSig]                -- Signatures
+                -> ProtoNameMonoBinds
+                -> Rn4M (Int, FlatMonoBindsInfo)
+
+flattenMonoBinds uniq sigs EmptyMonoBinds = returnRn4 (uniq, [])
+
+flattenMonoBinds uniq sigs (AndMonoBinds mB1 mB2)
+  = flattenMonoBinds uniq sigs mB1     `thenRn4` \ (uniq1, flat1) ->
+    flattenMonoBinds uniq1 sigs mB2    `thenRn4` \ (uniq2, flat2) ->
+    returnRn4 (uniq2, flat1 ++ flat2)
+
+flattenMonoBinds uniq sigs (PatMonoBind pat grhss_and_binds locn)
+  = pushSrcLocRn4 locn                           (
+    rnPat pat                          `thenRn4` \ pat' ->
+    rnGRHSsAndBinds grhss_and_binds    `thenRn4` \ (grhss_and_binds', fvs) ->
+
+        -- Find which things are bound in this group
+    let
+       names_bound_here = collectPatBinders pat'
+
+       sigs_etc_for_here = foldl (sig_for_here (\ n -> n `is_elem` names_bound_here))
+                                 [] sigs
+
+       sigs_fvs = foldr sig_fv emptyUniqSet sigs_etc_for_here
+
+       is_elem = isIn "flattenMonoBinds"
+    in
+    returnRn4 (
+       uniq + 1,
+       [(uniq,
+         mkUniqSet names_bound_here,
+          fvs `unionUniqSets` sigs_fvs,
+          PatMonoBind pat' grhss_and_binds' locn,
+          sigs_etc_for_here
+        )]
+    ))
+
+flattenMonoBinds uniq sigs (FunMonoBind name matches locn)
+  = pushSrcLocRn4 locn                           (
+    lookupValue name                   `thenRn4` \ name' ->
+    mapAndUnzipRn4 rnMatch matches     `thenRn4` \ (new_matches, fv_lists) ->
+    let
+       fvs = unionManyUniqSets fv_lists
+
+       sigs_for_me = foldl (sig_for_here (\ n -> n == name')) [] sigs
+
+       sigs_fvs = foldr sig_fv emptyUniqSet sigs_for_me
+    in
+    returnRn4 (
+      uniq + 1,
+      [(uniq,
+       singletonUniqSet name',
+       fvs `unionUniqSets` sigs_fvs,
+       FunMonoBind name' new_matches locn,
+       sigs_for_me
+       )]
+    ))
+\end{code}
+
+Grab type-signatures/user-pragmas of interest:
+\begin{code}
+sig_for_here want_me acc s@(Sig n _ _ _)     | want_me n = s:acc
+sig_for_here want_me acc s@(InlineSig n _)   | want_me n = s:acc
+sig_for_here want_me acc s@(DeforestSig n _) | want_me n = s:acc
+sig_for_here want_me acc s@(SpecSig n _ _ _) | want_me n = s:acc
+sig_for_here want_me acc s@(MagicUnfoldingSig n _ _)
+                                            | want_me n = s:acc
+sig_for_here want_me acc other_wise                     = acc
+
+-- If a SPECIALIZE pragma is of the "... = blah" form,
+-- then we'd better make sure "blah" is taken into
+-- acct in the dependency analysis (or we get an
+-- unexpected out-of-scope error)! WDP 95/07
+
+sig_fv (SpecSig _ _ (Just blah) _) acc = acc `unionUniqSets` singletonUniqSet blah
+sig_fv _                          acc = acc
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection[reconstruct-deps]{Reconstructing dependencies}
+%*                                                                     *
+%************************************************************************
+
+This @MonoBinds@- and @ClassDecls@-specific code is segregated here,
+as the two cases are similar.
+
+\begin{code}
+reconstructRec :: [Cycle]      -- Result of SCC analysis; at least one
+               -> [Edge]       -- Original edges
+               -> FlatMonoBindsInfo
+               -> RenamedHsBinds
+
+reconstructRec cycles edges mbi
+  = foldr1 ThenBinds (map (reconstructCycle mbi) cycles)
+  where
+    reconstructCycle :: FlatMonoBindsInfo -> Cycle -> RenamedHsBinds
+
+    reconstructCycle mbi2 cycle
+      = BIND [(binds,sigs) | (vertex, _, _, binds, sigs) <- mbi2, vertex `is_elem` cycle]
+                 _TO_ relevant_binds_and_sigs ->
+
+       BIND (unzip relevant_binds_and_sigs) _TO_ (binds, sig_lists) ->
+
+       BIND (foldr AndMonoBinds EmptyMonoBinds binds) _TO_ this_gp_binds ->
+       let
+           this_gp_sigs        = foldr1 (++) sig_lists
+           have_sigs           = not (null sig_lists)
+               -- ToDo: this might not be the right
+               -- thing to call this predicate;
+               -- e.g. "have_sigs [[], [], []]" ???????????
+       in
+       mk_binds this_gp_binds this_gp_sigs (isCyclic edges cycle) have_sigs
+       BEND BEND BEND
+      where
+       is_elem = isIn "reconstructRec"
+
+       mk_binds :: RenamedMonoBinds -> [RenamedSig]
+                -> Bool -> Bool -> RenamedHsBinds
+
+       mk_binds bs ss True  False              = SingleBind (RecBind    bs)
+       mk_binds bs ss True  True{-have sigs-}  = BindWith   (RecBind    bs) ss
+       mk_binds bs ss False False              = SingleBind (NonRecBind bs)
+       mk_binds bs ss False True{-have sigs-}  = BindWith   (NonRecBind bs) ss
+
+       -- moved from Digraph, as this is the only use here
+       -- (avoid overloading cost).  We have to use elem
+       -- (not FiniteMaps or whatever), because there may be
+       -- many edges out of one vertex.  We give it its own
+       -- "elem" just for speed.
+
+       isCyclic es []  = panic "isCyclic: empty component"
+       isCyclic es [v] = (v,v) `elem` es
+       isCyclic es vs  = True
+
+       elem _ []       = False
+       elem x (y:ys)   = x==y || elem x ys
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+%*     Manipulating FlatMonoBindInfo                                   *
+%*                                                                     *
+%************************************************************************
+
+During analysis a @MonoBinds@ is flattened to a @FlatMonoBindsInfo@.
+The @RenamedMonoBinds@ is always an empty bind, a pattern binding or
+a function binding, and has itself been dependency-analysed and
+renamed.
+
+\begin{code}
+type FlatMonoBindsInfo
+  = [(VertexTag,               -- Identifies the vertex
+      UniqSet Name,            -- Set of names defined in this vertex
+      UniqSet Name,            -- Set of names used in this vertex
+      RenamedMonoBinds,                -- Binding for this vertex (always just one binding, either fun or pat)
+      [RenamedSig])            -- Signatures, if any, for this vertex
+    ]
+
+mkVertices :: FlatMonoBindsInfo -> [VertexTag]
+mkVertices info = [ vertex | (vertex,_,_,_,_) <- info]
+
+mkEdges :: [VertexTag] -> FlatMonoBindsInfo -> [Edge]
+
+mkEdges vertices flat_info
+ -- An edge (v,v') indicates that v depends on v'
+ = [ (source_vertex, target_vertex)
+   | (source_vertex, _, used_names, _, _) <- flat_info,
+     target_name   <- uniqSetToList used_names,
+     target_vertex <- vertices_defining target_name flat_info
+   ]
+   where
+   -- If each name only has one binding in this group, then
+   -- vertices_defining will always return the empty list, or a
+   -- singleton.  The case when there is more than one binding (an
+   -- error) needs more thought.
+
+   vertices_defining name flat_info2
+    = [ vertex |  (vertex, names_defined, _, _, _) <- flat_info2,
+               name `elementOfUniqSet` names_defined
+      ]
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+\subsubsection[dep-Sigs]{Signatures (and user-pragmas for values)}
+%*                                                                     *
+%************************************************************************
+
+@rnBindSigs@ checks for: (a)~more than one sig for one thing;
+(b)~signatures given for things not bound here; (c)~with suitably
+flaggery, that all top-level things have type signatures.
+
+\begin{code}
+rnBindSigs :: Bool                 -- True <=> top-level binders
+           -> [ProtoName]          -- Binders for this decl group
+           -> [ProtoNameSig]
+           -> Rn4M [RenamedSig]    -- List of Sig constructors
+
+rnBindSigs is_toplev binder_pnames sigs
+  =
+        -- Rename the signatures
+        -- Will complain about sigs for variables not in this group
+    mapRn4 rename_sig sigs   `thenRn4` \ sigs_maybe ->
+    let
+       sigs' = catMaybes sigs_maybe
+
+        -- Discard unbound ones we've already complained about, so we
+        -- complain about duplicate ones.
+
+       (goodies, dups) = removeDups compare (filter not_unbound sigs')
+    in
+    mapRn4 (addErrRn4 . dupSigDeclErr) dups `thenRn4_`
+
+    getSrcLocRn4               `thenRn4` \ locn ->
+
+    (if (is_toplev && opt_SigsRequired) then
+       let
+           sig_frees = catMaybes (map (sig_free sigs) binder_pnames)
+       in
+       mapRn4 (addErrRn4 . missingSigErr locn) sig_frees
+     else
+       returnRn4 []
+    )                                      `thenRn4_`
+
+    returnRn4 sigs' -- bad ones and all:
+                   -- we need bindings of *some* sort for every name
+  where
+    rename_sig (Sig v ty pragma src_loc)
+      = pushSrcLocRn4 src_loc  (
+
+       if not (v `elemByLocalNames` binder_pnames) then
+          addErrRn4 (unknownSigDeclErr "type signature" v src_loc) `thenRn4_`
+          returnRn4 Nothing
+       else
+          lookupValue v                                `thenRn4` \ new_v ->
+          rnPolyType False nullTyVarNamesEnv ty        `thenRn4` \ new_ty ->
+          recoverQuietlyRn4 noGenPragmas (
+               rnGenPragmas pragma
+          )                                        `thenRn4` \ new_pragma ->
+          returnRn4 (Just (Sig new_v new_ty new_pragma src_loc))
+       )
+
+    -- and now, the various flavours of value-modifying user-pragmas:
+
+    rename_sig (SpecSig v ty using src_loc)
+      = pushSrcLocRn4 src_loc  (
+
+       if not (v `elemByLocalNames` binder_pnames) then
+          addErrRn4 (unknownSigDeclErr "SPECIALIZE pragma" v src_loc) `thenRn4_`
+          returnRn4 Nothing
+       else
+          lookupValue v                                `thenRn4` \ new_v ->
+          rnPolyType False nullTyVarNamesEnv ty        `thenRn4` \ new_ty ->
+          rn_using using                               `thenRn4` \ new_using ->
+          returnRn4 (Just (SpecSig new_v new_ty new_using src_loc))
+       )
+      where
+       rn_using Nothing  = returnRn4 Nothing
+       rn_using (Just x) = lookupValue x `thenRn4` \ new_x ->
+                           returnRn4 (Just new_x)
+
+    rename_sig (InlineSig v src_loc)
+      = pushSrcLocRn4 src_loc  (
+
+       if not (v `elemByLocalNames` binder_pnames) then
+          addErrRn4 (unknownSigDeclErr "INLINE pragma" v src_loc) `thenRn4_`
+          returnRn4 Nothing
+       else
+          lookupValue v        `thenRn4` \ new_v ->
+          returnRn4 (Just (InlineSig new_v src_loc))
+       )
+
+    rename_sig (DeforestSig v src_loc)
+      = pushSrcLocRn4 src_loc   (
+
+       if not (v `elemByLocalNames` binder_pnames) then
+          addErrRn4 (unknownSigDeclErr "DEFOREST pragma" v src_loc) `thenRn4_`
+          returnRn4 Nothing
+       else
+          lookupValue v        `thenRn4` \ new_v ->
+          returnRn4 (Just (DeforestSig new_v src_loc))
+       )
+
+    rename_sig (MagicUnfoldingSig v str src_loc)
+      = pushSrcLocRn4 src_loc  (
+
+       if not (v `elemByLocalNames` binder_pnames) then
+          addErrRn4 (unknownSigDeclErr "MAGIC_UNFOLDING pragma" v src_loc) `thenRn4_`
+          returnRn4 Nothing
+       else
+          lookupValue v        `thenRn4` \ new_v ->
+          returnRn4 (Just (MagicUnfoldingSig new_v str src_loc))
+       )
+
+    not_unbound :: RenamedSig -> Bool
+
+    not_unbound (Sig n _ _ _)            = not (isUnboundName n)
+    not_unbound (SpecSig n _ _ _)        = not (isUnboundName n)
+    not_unbound (InlineSig n _)                  = not (isUnboundName n)
+    not_unbound (DeforestSig n _)        = not (isUnboundName n)
+    not_unbound (MagicUnfoldingSig n _ _) = not (isUnboundName n)
+
+    -------------------------------------
+    sig_free :: [ProtoNameSig] -> ProtoName -> Maybe ProtoName
+       -- Return "Just x" if "x" has no type signature in
+       -- sigs.  Nothing, otherwise.
+
+    sig_free [] ny = Just ny
+    sig_free (Sig nx _ _ _ : rest) ny
+      = if (nx `eqByLocalName` ny) then Nothing else sig_free rest ny
+    sig_free (_ : rest) ny = sig_free rest ny
+
+    -------------------------------------
+    compare :: RenamedSig -> RenamedSig -> TAG_
+    compare x y = c x y
+
+    c (Sig n1 _ _ _)            (Sig n2 _ _ _)             = n1 `cmp` n2
+    c (InlineSig n1 _)          (InlineSig n2 _)           = n1 `cmp` n2
+    c (MagicUnfoldingSig n1 _ _) (MagicUnfoldingSig n2 _ _) = n1 `cmp` n2
+    c (SpecSig n1 ty1 _ _)      (SpecSig n2 ty2 _ _)
+      = -- may have many specialisations for one value;
+       -- but not ones that are exactly the same...
+       case (n1 `cmp` n2) of
+         EQ_   -> cmpPolyType cmp ty1 ty2
+         other -> other
+
+    c other_1 other_2  -- tags *must* be different
+      = let tag1 = tag other_1
+           tag2 = tag other_2
+       in
+       if tag1 _LT_ tag2 then LT_ else GT_
+
+    tag (Sig n1 _ _ _)            = (ILIT(1) :: FAST_INT)
+    tag (SpecSig n1 _ _ _)        = ILIT(2)
+    tag (InlineSig n1 _)          = ILIT(3)
+    tag (MagicUnfoldingSig n1 _ _) = ILIT(4)
+    tag (DeforestSig n1 _)         = ILIT(5)
+    tag _ = panic# "tag(RnBinds4)"
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection{Error messages}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+dupSigDeclErr sigs
+  = let
+       undup_sigs = fst (removeDups cmp_sig sigs)
+    in
+    addErrLoc locn1
+       ("more than one "++what_it_is++"\n\thas been given for these variables") ( \ sty ->
+    ppAboves (map (ppr sty) undup_sigs) )
+  where
+    (what_it_is, locn1)
+      = case (head sigs) of
+         Sig        _ _ _ loc -> ("type signature",loc)
+         ClassOpSig _ _ _ loc -> ("class-method type signature", loc)
+         SpecSig    _ _ _ loc -> ("SPECIALIZE pragma",loc)
+         InlineSig  _     loc -> ("INLINE pragma",loc)
+         MagicUnfoldingSig _ _ loc -> ("MAGIC_UNFOLDING pragma",loc)
+
+    cmp_sig a b = get_name a `cmp` get_name b
+
+    get_name (Sig        n _ _ _) = n
+    get_name (ClassOpSig n _ _ _) = n
+    get_name (SpecSig    n _ _ _) = n
+    get_name (InlineSig  n     _) = n
+    get_name (MagicUnfoldingSig n _ _) = n
+
+------------------------
+methodBindErr mbind locn
+ = addErrLoc locn "Can't handle multiple methods defined by one pattern binding"
+       (\ sty -> ppr sty mbind)
+
+--------------------------
+missingSigErr locn var
+  = addShortErrLocLine locn ( \ sty ->
+    ppBesides [ppStr "a definition but no type signature for `",
+              ppr sty var,
+              ppStr "'."])
+
+--------------------------------
+unknownSigDeclErr flavor var locn
+  = addShortErrLocLine locn ( \ sty ->
+    ppBesides [ppStr flavor, ppStr " but no definition for `",
+              ppr sty var,
+              ppStr "'."])
+\end{code}