+
+-- for local binds
+-- wrapper that does both the left- and right-hand sides
+--
+-- here there are no local fixity decls passed in;
+-- the local fixity decls come from the ValBinds sigs
+rnValBindsAndThen :: HsValBinds RdrName
+ -> (HsValBinds Name -> RnM (result, FreeVars))
+ -> RnM (result, FreeVars)
+rnValBindsAndThen binds@(ValBindsIn _ sigs) thing_inside =
+ let
+ (original_bndrs, doc) = bindersAndDoc binds
+
+ in do
+ -- (A) create the local fixity environment
+ new_fixities <- makeMiniFixityEnv [L loc sig | L loc (FixSig sig) <- sigs]
+
+ -- (B) rename the LHSes
+ new_lhs <- rnValBindsLHSFromDoc_Local original_bndrs doc new_fixities binds
+ let bound_names = map unLoc $ collectHsValBinders new_lhs
+
+ -- and bring them (and their fixities) into scope
+ bindLocalNamesFV_WithFixities bound_names new_fixities $
+ warnUnusedLocalBinds bound_names $ do
+
+ -- (C) do the RHS and thing inside
+ (binds', dus) <- rnValBindsRHS bound_names new_lhs
+ (result, result_fvs) <- thing_inside binds'
+
+ let
+ -- the variables used in the val binds are:
+ -- (1) the uses of the binds
+ -- (2) the FVs of the thing-inside
+ all_uses = (duUses dus) `plusFV` result_fvs
+ -- duUses: It's important to return all the uses. Otherwise consider:
+ -- x = 3
+ -- y = let p = x in 'x' -- NB: p not used
+ -- If we don't "see" the dependency of 'y' on 'x', we may put the
+ -- bindings in the wrong order, and the type checker will complain
+ -- that x isn't in scope
+
+ return (result,
+ -- the bound names are pruned out of all_uses
+ -- by the bindLocalNamesFV call above
+ all_uses)
+
+
+-- Process the fixity declarations, making a FastString -> (Located Fixity) map
+-- (We keep the location around for reporting duplicate fixity declarations.)
+--
+-- Checks for duplicates, but not that only locally defined things are fixed.
+-- Note: for local fixity declarations, duplicates would also be checked in
+-- check_sigs below. But we also use this function at the top level.
+makeMiniFixityEnv :: [LFixitySig RdrName]
+ -> RnM (UniqFM (Located Fixity)) -- key is the FastString of the OccName
+ -- of the fixity declaration it came from
+
+makeMiniFixityEnv decls = foldlM add_one emptyUFM decls
+ where
+ add_one env (L loc (FixitySig (L name_loc name) fixity)) = do
+ { -- this fixity decl is a duplicate iff
+ -- the ReaderName's OccName's FastString is already in the env
+ -- (we only need to check the local fix_env because
+ -- definitions of non-local will be caught elsewhere)
+ let {occ = rdrNameOcc name;
+ curKey = occNameFS occ;
+ fix_item = L loc fixity};
+
+ case lookupUFM env curKey of
+ Nothing -> return $ addToUFM env curKey fix_item
+ Just (L loc' _) -> do
+ { setSrcSpan loc $
+ addLocErr (L name_loc name) (dupFixityDecl loc')
+ ; return env}
+ }
+
+pprFixEnv :: NameEnv FixItem -> SDoc
+pprFixEnv env
+ = pprWithCommas (\ (FixItem n f) -> ppr f <+> ppr n)
+ (nameEnvElts env)
+
+dupFixityDecl loc rdr_name
+ = vcat [ptext SLIT("Multiple fixity declarations for") <+> quotes (ppr rdr_name),
+ ptext SLIT("also at ") <+> ppr loc]