+
+-- 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
+ = do { let (original_bndrs, doc) = bindersAndDoc binds
+
+ -- (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 $ do
+
+ { -- (C) Do the RHS and thing inside
+ (binds', dus) <- rnValBindsRHS bound_names new_lhs
+ ; (result, result_fvs) <- thing_inside binds'
+
+ -- Report unused bindings based on the (accurate)
+ -- findUses. E.g.
+ -- let x = x in 3
+ -- should report 'x' unused
+ ; let real_uses = findUses dus result_fvs
+ ; warnUnusedLocalBinds bound_names real_uses
+
+ ; let
+ -- The variables "used" in the val binds are:
+ -- (1) the uses of the binds (duUses)
+ -- (2) the FVs of the thing-inside
+ all_uses = duUses dus `plusFV` result_fvs
+ -- Note [Unused binding hack]
+ -- ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ -- Note that *in contrast* to the above reporting of
+ -- unused bindings, (1) above uses duUses to return *all*
+ -- the uses, even if the binding is unused. 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
+ --
+ -- But note that this means we won't report 'x' as unused,
+ -- whereas we would if we had { x = 3; p = x; y = 'x' }
+
+ ; return (result, all_uses) }}
+ -- The bound names are pruned out of all_uses
+ -- by the bindLocalNamesFV call above
+
+rnValBindsAndThen bs _ = pprPanic "rnValBindsAndThen" (ppr bs)
+
+
+-- 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 MiniFixityEnv
+
+makeMiniFixityEnv decls = foldlM add_one emptyFsEnv 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 { fs = occNameFS (rdrNameOcc name)
+ ; fix_item = L loc fixity };
+
+ case lookupFsEnv env fs of
+ Nothing -> return $ extendFsEnv env fs fix_item
+ Just (L loc' _) -> do
+ { setSrcSpan loc $
+ addLocErr (L name_loc name) (dupFixityDecl loc')
+ ; return env}
+ }
+
+dupFixityDecl :: SrcSpan -> RdrName -> SDoc
+dupFixityDecl loc rdr_name
+ = vcat [ptext (sLit "Multiple fixity declarations for") <+> quotes (ppr rdr_name),
+ ptext (sLit "also at ") <+> ppr loc]