+ sccs = stronglyConnComp edges
+
+ keyd_nodes = bagToList binds_w_dus `zip` [0::Int ..]
+
+ edges = [ (node, key, [fromJust mb_key | n <- nameSetToList uses,
+ let mb_key = lookupNameEnv key_map n,
+ isJust mb_key ])
+ | (node@(_,_,uses), key) <- keyd_nodes ]
+
+ key_map :: NameEnv Int -- Which binding it comes from
+ key_map = mkNameEnv [(bndr, key) | ((_, bndrs, _), key) <- keyd_nodes
+ , bndr <- bndrs ]
+
+ get_binds (AcyclicSCC (bind, _, _)) = (NonRecursive, unitBag bind)
+ get_binds (CyclicSCC binds_w_dus) = (Recursive, listToBag [b | (b,d,u) <- binds_w_dus])
+
+ get_du (AcyclicSCC (_, bndrs, uses)) = (Just (mkNameSet bndrs), uses)
+ get_du (CyclicSCC binds_w_dus) = (Just defs, uses)
+ where
+ defs = mkNameSet [b | (_,bs,_) <- binds_w_dus, b <- bs]
+ uses = unionManyNameSets [u | (_,_,u) <- binds_w_dus]
+
+
+---------------------
+-- Bind the top-level forall'd type variables in the sigs.
+-- E.g f :: a -> a
+-- f = rhs
+-- The 'a' scopes over the rhs
+--
+-- NB: there'll usually be just one (for a function binding)
+-- but if there are many, one may shadow the rest; too bad!
+-- e.g x :: [a] -> [a]
+-- y :: [(a,a)] -> a
+-- (x,y) = e
+-- In e, 'a' will be in scope, and it'll be the one from 'y'!
+
+mkSigTvFn :: [LSig Name] -> (Name -> [Name])
+-- Return a lookup function that maps an Id Name to the names
+-- of the type variables that should scope over its body..
+mkSigTvFn sigs
+ = \n -> lookupNameEnv env n `orElse` []
+ where
+ env :: NameEnv [Name]
+ env = mkNameEnv [ (name, map hsLTyVarName ltvs)
+ | L _ (Sig (L _ name)
+ (L _ (HsForAllTy Explicit ltvs _ _))) <- sigs]
+ -- Note the pattern-match on "Explicit"; we only bind
+ -- type variables from signatures with an explicit top-level for-all
+
+-- The trimming function trims the free vars we attach to a
+-- binding so that it stays reasonably small
+noTrim :: FreeVars -> FreeVars
+noTrim fvs = fvs -- Used at top level
+
+trimWith :: [Name] -> FreeVars -> FreeVars
+-- Nested bindings; trim by intersection with the names bound here
+trimWith bndrs = intersectNameSet (mkNameSet bndrs)
+
+---------------------
+rnBind :: (Name -> [Name]) -- Signature tyvar function
+ -> (FreeVars -> FreeVars) -- Trimming function for rhs free vars
+ -> LHsBind RdrName
+ -> RnM (LHsBind Name, [Name], Uses)
+rnBind sig_fn trim (L loc (PatBind pat grhss ty _))
+ = setSrcSpan loc $
+ do { (pat', pat_fvs) <- rnLPat pat
+
+ ; let bndrs = collectPatBinders pat'
+
+ ; (grhss', fvs) <- bindSigTyVarsFV (concatMap sig_fn bndrs) $
+ rnGRHSs PatBindRhs grhss
+
+ ; return (L loc (PatBind pat' grhss' ty (trim fvs)), bndrs, pat_fvs `plusFV` fvs) }
+
+rnBind sig_fn trim (L loc (FunBind name inf matches _))
+ = setSrcSpan loc $
+ do { new_name <- lookupLocatedBndrRn name
+ ; let plain_name = unLoc new_name
+
+ ; (matches', fvs) <- bindSigTyVarsFV (sig_fn plain_name) $
+ rnMatchGroup (FunRhs plain_name) matches
+
+ ; checkPrecMatch inf plain_name matches'
+
+ ; return (L loc (FunBind new_name inf matches' (trim fvs)), [plain_name], fvs)
+ }