{-# LANGUAGE ScopedTypeVariables, BangPatterns #-}
{-# LANGUAGE TypeFamilies #-}
module RnBinds (
   
   rnTopBindsLHS, rnTopBindsBoot, rnValBindsRHS,
   
   rnLocalBindsAndThen, rnLocalValBindsLHS, rnLocalValBindsRHS,
   
   rnMethodBinds, renameSigs,
   rnMatchGroup, rnGRHSs, rnGRHS, rnSrcFixityDecl,
   makeMiniFixityEnv, MiniFixityEnv,
   HsSigCtxt(..)
   ) where
import GhcPrelude
import {-# SOURCE #-} RnExpr( rnLExpr, rnStmts )
import HsSyn
import TcRnMonad
import RnTypes
import RnPat
import RnNames
import RnEnv
import RnFixity
import RnUtils          ( HsDocContext(..), mapFvRn, extendTyVarEnvFVRn
                        , checkDupRdrNames, warnUnusedLocalBinds,
                        checkUnusedRecordWildcard
                        , checkDupAndShadowedNames, bindLocalNamesFV )
import DynFlags
import Module
import Name
import NameEnv
import NameSet
import RdrName          ( RdrName, rdrNameOcc )
import SrcLoc
import ListSetOps       ( findDupsEq )
import BasicTypes       ( RecFlag(..) )
import Digraph          ( SCC(..) )
import Bag
import Util
import Outputable
import UniqSet
import Maybes           ( orElse )
import qualified GHC.LanguageExtensions as LangExt
import Control.Monad
import Data.Foldable      ( toList )
import Data.List          ( partition, sort )
import Data.List.NonEmpty ( NonEmpty(..) )
rnTopBindsLHS :: MiniFixityEnv
              -> HsValBinds GhcPs
              -> RnM (HsValBindsLR GhcRn GhcPs)
rnTopBindsLHS fix_env binds
  = rnValBindsLHS (topRecNameMaker fix_env) binds
rnTopBindsBoot :: NameSet -> HsValBindsLR GhcRn GhcPs
               -> RnM (HsValBinds GhcRn, DefUses)
rnTopBindsBoot bound_names (ValBinds _ mbinds sigs)
  = do  { checkErr (isEmptyLHsBinds mbinds) (bindsInHsBootFile mbinds)
        ; (sigs', fvs) <- renameSigs (HsBootCtxt bound_names) sigs
        ; return (XValBindsLR (NValBinds [] sigs'), usesOnly fvs) }
rnTopBindsBoot _ b = pprPanic "rnTopBindsBoot" (ppr b)
rnLocalBindsAndThen :: HsLocalBinds GhcPs
                   -> (HsLocalBinds GhcRn -> FreeVars -> RnM (result, FreeVars))
                   -> RnM (result, FreeVars)
rnLocalBindsAndThen (EmptyLocalBinds x) thing_inside =
  thing_inside (EmptyLocalBinds x) emptyNameSet
rnLocalBindsAndThen (HsValBinds x val_binds) thing_inside
  = rnLocalValBindsAndThen val_binds $ \ val_binds' ->
      thing_inside (HsValBinds x val_binds')
rnLocalBindsAndThen (HsIPBinds x binds) thing_inside = do
    (binds',fv_binds) <- rnIPBinds binds
    (thing, fvs_thing) <- thing_inside (HsIPBinds x binds') fv_binds
    return (thing, fvs_thing `plusFV` fv_binds)
rnLocalBindsAndThen (XHsLocalBindsLR _) _ = panic "rnLocalBindsAndThen"
rnIPBinds :: HsIPBinds GhcPs -> RnM (HsIPBinds GhcRn, FreeVars)
rnIPBinds (IPBinds _ ip_binds ) = do
    (ip_binds', fvs_s) <- mapAndUnzipM (wrapLocFstM rnIPBind) ip_binds
    return (IPBinds noExt ip_binds', plusFVs fvs_s)
rnIPBinds (XHsIPBinds _) = panic "rnIPBinds"
rnIPBind :: IPBind GhcPs -> RnM (IPBind GhcRn, FreeVars)
rnIPBind (IPBind _ ~(Left n) expr) = do
    (expr',fvExpr) <- rnLExpr expr
    return (IPBind noExt (Left n) expr', fvExpr)
rnIPBind (XIPBind _) = panic "rnIPBind"
rnLocalValBindsLHS :: MiniFixityEnv
                   -> HsValBinds GhcPs
                   -> RnM ([Name], HsValBindsLR GhcRn GhcPs)
rnLocalValBindsLHS fix_env binds
  = do { binds' <- rnValBindsLHS (localRecNameMaker fix_env) binds
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         
       ; let bound_names = collectHsValBinders binds'
             
             
             
       ; envs <- getRdrEnvs
       ; checkDupAndShadowedNames envs bound_names
       ; return (bound_names, binds') }
rnValBindsLHS :: NameMaker
              -> HsValBinds GhcPs
              -> RnM (HsValBindsLR GhcRn GhcPs)
rnValBindsLHS topP (ValBinds x mbinds sigs)
  = do { mbinds' <- mapBagM (wrapLocM (rnBindLHS topP doc)) mbinds
       ; return $ ValBinds x mbinds' sigs }
  where
    bndrs = collectHsBindsBinders mbinds
    doc   = text "In the binding group for:" <+> pprWithCommas ppr bndrs
rnValBindsLHS _ b = pprPanic "rnValBindsLHSFromDoc" (ppr b)
rnValBindsRHS :: HsSigCtxt
              -> HsValBindsLR GhcRn GhcPs
              -> RnM (HsValBinds GhcRn, DefUses)
rnValBindsRHS ctxt (ValBinds _ mbinds sigs)
  = do { (sigs', sig_fvs) <- renameSigs ctxt sigs
       ; binds_w_dus <- mapBagM (rnLBind (mkScopedTvFn sigs')) mbinds
       ; let !(anal_binds, anal_dus) = depAnalBinds binds_w_dus
       ; let patsyn_fvs = foldr (unionNameSet . psb_ext) emptyNameSet $
                          getPatSynBinds anal_binds
                
                
                
                
                
                
             valbind'_dus = anal_dus `plusDU` usesOnly sig_fvs
                                     `plusDU` usesOnly patsyn_fvs
                            
                            
                            
        ; return (XValBindsLR (NValBinds anal_binds sigs'), valbind'_dus) }
rnValBindsRHS _ b = pprPanic "rnValBindsRHS" (ppr b)
rnLocalValBindsRHS :: NameSet  
                   -> HsValBindsLR GhcRn GhcPs
                   -> RnM (HsValBinds GhcRn, DefUses)
rnLocalValBindsRHS bound_names binds
  = rnValBindsRHS (LocalBindCtxt bound_names) binds
rnLocalValBindsAndThen
  :: HsValBinds GhcPs
  -> (HsValBinds GhcRn -> FreeVars -> RnM (result, FreeVars))
  -> RnM (result, FreeVars)
rnLocalValBindsAndThen binds@(ValBinds _ _ sigs) thing_inside
 = do   {     
          new_fixities <- makeMiniFixityEnv [ L loc sig
                                            | L loc (FixSig _ sig) <- sigs]
              
        ; (bound_names, new_lhs) <- rnLocalValBindsLHS new_fixities binds
              
        ; bindLocalNamesFV bound_names              $
          addLocalFixities new_fixities bound_names $ do
        {      
          (binds', dus) <- rnLocalValBindsRHS (mkNameSet bound_names) new_lhs
        ; (result, result_fvs) <- thing_inside binds' (allUses dus)
                
                
                
                
        ; let real_uses = findUses dus result_fvs
              
              
              rec_uses = hsValBindsImplicits binds'
              implicit_uses = mkNameSet $ concatMap snd
                                        $ rec_uses
        ; mapM_ (\(loc, ns) ->
                    checkUnusedRecordWildcard loc real_uses (Just ns))
                rec_uses
        ; warnUnusedLocalBinds bound_names
                                      (real_uses `unionNameSet` implicit_uses)
        ; let
            
            
            
            all_uses = allUses dus `plusFV` result_fvs
                
                
                
                
                
                
                
                
                
                
                
                
                
        ; return (result, all_uses) }}
                
                
rnLocalValBindsAndThen bs _ = pprPanic "rnLocalValBindsAndThen" (ppr bs)
rnBindLHS :: NameMaker
          -> SDoc
          -> HsBind GhcPs
          
          
          
          -> RnM (HsBindLR GhcRn GhcPs)
rnBindLHS name_maker _ bind@(PatBind { pat_lhs = pat })
  = do
      
      (pat',pat'_fvs) <- rnBindPat name_maker pat
      return (bind { pat_lhs = pat', pat_ext = pat'_fvs })
                
                
                
rnBindLHS name_maker _ bind@(FunBind { fun_id = rdr_name })
  = do { name <- applyNameMaker name_maker rdr_name
       ; return (bind { fun_id = name
                      , fun_ext = noExt }) }
rnBindLHS name_maker _ (PatSynBind x psb@PSB{ psb_id = rdrname })
  | isTopRecNameMaker name_maker
  = do { addLocM checkConName rdrname
       ; name <- lookupLocatedTopBndrRn rdrname   
       ; return (PatSynBind x psb{ psb_ext = noExt, psb_id = name }) }
  | otherwise  
  = do { addErr localPatternSynonymErr  
                                        
       ; name <- applyNameMaker name_maker rdrname
       ; return (PatSynBind x psb{ psb_ext = noExt, psb_id = name }) }
  where
    localPatternSynonymErr :: SDoc
    localPatternSynonymErr
      = hang (text "Illegal pattern synonym declaration for" <+> quotes (ppr rdrname))
           2 (text "Pattern synonym declarations are only valid at top level")
rnBindLHS _ _ b = pprPanic "rnBindHS" (ppr b)
rnLBind :: (Name -> [Name])      
        -> LHsBindLR GhcRn GhcPs
        -> RnM (LHsBind GhcRn, [Name], Uses)
rnLBind sig_fn (L loc bind)
  = setSrcSpan loc $
    do { (bind', bndrs, dus) <- rnBind sig_fn bind
       ; return (L loc bind', bndrs, dus) }
rnBind :: (Name -> [Name])        
       -> HsBindLR GhcRn GhcPs
       -> RnM (HsBind GhcRn, [Name], Uses)
rnBind _ bind@(PatBind { pat_lhs = pat
                       , pat_rhs = grhss
                                   
                                   
                       , pat_ext = pat_fvs })
  = do  { mod <- getModule
        ; (grhss', rhs_fvs) <- rnGRHSs PatBindRhs rnLExpr grhss
                
        ; let all_fvs = pat_fvs `plusFV` rhs_fvs
              fvs'    = filterNameSet (nameIsLocalOrFrom mod) all_fvs
                
                
                
              bndrs = collectPatBinders pat
              bind' = bind { pat_rhs  = grhss'
                           , pat_ext = fvs' }
              ok_nobind_pat
                  = 
                    case unLoc pat of
                       WildPat {}   -> True
                       BangPat {}   -> True 
                       SplicePat {} -> True
                       _            -> False
        
        
        ; whenWOptM Opt_WarnUnusedPatternBinds $
          when (null bndrs && not ok_nobind_pat) $
          addWarn (Reason Opt_WarnUnusedPatternBinds) $
          unusedPatBindWarn bind'
        ; fvs' `seq` 
          return (bind', bndrs, all_fvs) }
rnBind sig_fn bind@(FunBind { fun_id = name
                            , fun_matches = matches })
       
  = do  { let plain_name = unLoc name
        ; (matches', rhs_fvs) <- bindSigTyVarsFV (sig_fn plain_name) $
                                
                                 rnMatchGroup (mkPrefixFunRhs name)
                                              rnLExpr matches
        ; let is_infix = isInfixFunBind bind
        ; when is_infix $ checkPrecMatch plain_name matches'
        ; mod <- getModule
        ; let fvs' = filterNameSet (nameIsLocalOrFrom mod) rhs_fvs
                
                
                
        ; fvs' `seq` 
          return (bind { fun_matches = matches'
                       , fun_ext     = fvs' },
                  [plain_name], rhs_fvs)
      }
rnBind sig_fn (PatSynBind x bind)
  = do  { (bind', name, fvs) <- rnPatSynBind sig_fn bind
        ; return (PatSynBind x bind', name, fvs) }
rnBind _ b = pprPanic "rnBind" (ppr b)
depAnalBinds :: Bag (LHsBind GhcRn, [Name], Uses)
             -> ([(RecFlag, LHsBinds GhcRn)], DefUses)
depAnalBinds binds_w_dus
  = (map get_binds sccs, map get_du sccs)
  where
    sccs = depAnal (\(_, defs, _) -> defs)
                   (\(_, _, uses) -> nonDetEltsUniqSet uses)
                   
                   
                   (bagToList binds_w_dus)
    get_binds (AcyclicSCC (bind, _, _)) = (NonRecursive, unitBag bind)
    get_binds (CyclicSCC  binds_w_dus)  = (Recursive, listToBag [b | (b,_,_) <- 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 = unionNameSets [u | (_,_,u) <- binds_w_dus]
mkScopedTvFn :: [LSig GhcRn] -> (Name -> [Name])
mkScopedTvFn sigs = \n -> lookupNameEnv env n `orElse` []
  where
    env = mkHsSigEnv get_scoped_tvs sigs
    get_scoped_tvs :: LSig GhcRn -> Maybe ([Located Name], [Name])
    
    get_scoped_tvs (L _ (ClassOpSig _ _ names sig_ty))
      = Just (names, hsScopedTvs sig_ty)
    get_scoped_tvs (L _ (TypeSig _ names sig_ty))
      = Just (names, hsWcScopedTvs sig_ty)
    get_scoped_tvs (L _ (PatSynSig _ names sig_ty))
      = Just (names, hsScopedTvs sig_ty)
    get_scoped_tvs _ = Nothing
makeMiniFixityEnv :: [LFixitySig GhcPs] -> RnM MiniFixityEnv
makeMiniFixityEnv decls = foldlM add_one_sig emptyFsEnv decls
 where
   add_one_sig env (L loc (FixitySig _ names fixity)) =
     foldlM add_one env [ (loc,name_loc,name,fixity)
                        | L name_loc name <- names ]
   add_one_sig _ (L _ (XFixitySig _)) = panic "makeMiniFixityEnv"
   add_one env (loc, name_loc, name,fixity) = do
     { 
       
       
       
       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 $
             addErrAt name_loc (dupFixityDecl loc' name)
           ; return env}
     }
dupFixityDecl :: SrcSpan -> RdrName -> SDoc
dupFixityDecl loc rdr_name
  = vcat [text "Multiple fixity declarations for" <+> quotes (ppr rdr_name),
          text "also at " <+> ppr loc]
rnPatSynBind :: (Name -> [Name])           
             -> PatSynBind GhcRn GhcPs
             -> RnM (PatSynBind GhcRn GhcRn, [Name], Uses)
rnPatSynBind sig_fn bind@(PSB { psb_id = L l name
                              , psb_args = details
                              , psb_def = pat
                              , psb_dir = dir })
       
  = do  { pattern_synonym_ok <- xoptM LangExt.PatternSynonyms
        ; unless pattern_synonym_ok (addErr patternSynonymErr)
        ; let scoped_tvs = sig_fn name
        ; ((pat', details'), fvs1) <- bindSigTyVarsFV scoped_tvs $
                                      rnPat PatSyn pat $ \pat' ->
         
         
         
            case details of
               PrefixCon vars ->
                   do { checkDupRdrNames vars
                      ; names <- mapM lookupPatSynBndr vars
                      ; return ( (pat', PrefixCon names)
                               , mkFVs (map unLoc names)) }
               InfixCon var1 var2 ->
                   do { checkDupRdrNames [var1, var2]
                      ; name1 <- lookupPatSynBndr var1
                      ; name2 <- lookupPatSynBndr var2
                      
                      ; return ( (pat', InfixCon name1 name2)
                               , mkFVs (map unLoc [name1, name2])) }
               RecCon vars ->
                   do { checkDupRdrNames (map recordPatSynSelectorId vars)
                      ; let rnRecordPatSynField
                              (RecordPatSynField { recordPatSynSelectorId = visible
                                                 , recordPatSynPatVar = hidden })
                              = do { visible' <- lookupLocatedTopBndrRn visible
                                   ; hidden'  <- lookupPatSynBndr hidden
                                   ; return $ RecordPatSynField { recordPatSynSelectorId = visible'
                                                                , recordPatSynPatVar = hidden' } }
                      ; names <- mapM rnRecordPatSynField  vars
                      ; return ( (pat', RecCon names)
                               , mkFVs (map (unLoc . recordPatSynPatVar) names)) }
        ; (dir', fvs2) <- case dir of
            Unidirectional -> return (Unidirectional, emptyFVs)
            ImplicitBidirectional -> return (ImplicitBidirectional, emptyFVs)
            ExplicitBidirectional mg ->
                do { (mg', fvs) <- bindSigTyVarsFV scoped_tvs $
                                   rnMatchGroup (mkPrefixFunRhs (L l name))
                                                rnLExpr mg
                   ; return (ExplicitBidirectional mg', fvs) }
        ; mod <- getModule
        ; let fvs = fvs1 `plusFV` fvs2
              fvs' = filterNameSet (nameIsLocalOrFrom mod) fvs
                
                
                
              bind' = bind{ psb_args = details'
                          , psb_def = pat'
                          , psb_dir = dir'
                          , psb_ext = fvs' }
              selector_names = case details' of
                                 RecCon names ->
                                  map (unLoc . recordPatSynSelectorId) names
                                 _ -> []
        ; fvs' `seq` 
          return (bind', name : selector_names , fvs1)
          
      }
  where
    
    lookupPatSynBndr = wrapLocM lookupLocalOccRn
    patternSynonymErr :: SDoc
    patternSynonymErr
      = hang (text "Illegal pattern synonym declaration")
           2 (text "Use -XPatternSynonyms to enable this extension")
rnPatSynBind _ (XPatSynBind _) = panic "rnPatSynBind"
rnMethodBinds :: Bool                   
              -> Name                   
              -> [Name]                 
              -> LHsBinds GhcPs         
              -> [LSig GhcPs]           
              -> RnM (LHsBinds GhcRn, [LSig GhcRn], FreeVars)
rnMethodBinds is_cls_decl cls ktv_names binds sigs
  = do { checkDupRdrNames (collectMethodBinders binds)
             
             
             
             
             
             
             
             
             
       
       ; binds' <- foldrBagM (rnMethodBindLHS is_cls_decl cls) emptyBag binds
       
       
       
       
       
       
       ; let (spec_inst_prags, other_sigs) = partition isSpecInstLSig sigs
             bound_nms = mkNameSet (collectHsBindsBinders binds')
             sig_ctxt | is_cls_decl = ClsDeclCtxt cls
                      | otherwise   = InstDeclCtxt bound_nms
       ; (spec_inst_prags', sip_fvs) <- renameSigs sig_ctxt spec_inst_prags
       ; (other_sigs',      sig_fvs) <- extendTyVarEnvFVRn ktv_names $
                                        renameSigs sig_ctxt other_sigs
       
       
       
       ; scoped_tvs  <- xoptM LangExt.ScopedTypeVariables
       ; (binds'', bind_fvs) <- maybe_extend_tyvar_env scoped_tvs $
              do { binds_w_dus <- mapBagM (rnLBind (mkScopedTvFn other_sigs')) binds'
                 ; let bind_fvs = foldrBag (\(_,_,fv1) fv2 -> fv1 `plusFV` fv2)
                                           emptyFVs binds_w_dus
                 ; return (mapBag fstOf3 binds_w_dus, bind_fvs) }
       ; return ( binds'', spec_inst_prags' ++ other_sigs'
                , sig_fvs `plusFV` sip_fvs `plusFV` bind_fvs) }
  where
    
    
    maybe_extend_tyvar_env scoped_tvs thing_inside
       | scoped_tvs = extendTyVarEnvFVRn ktv_names thing_inside
       | otherwise  = thing_inside
rnMethodBindLHS :: Bool -> Name
                -> LHsBindLR GhcPs GhcPs
                -> LHsBindsLR GhcRn GhcPs
                -> RnM (LHsBindsLR GhcRn GhcPs)
rnMethodBindLHS _ cls (L loc bind@(FunBind { fun_id = name })) rest
  = setSrcSpan loc $ do
    do { sel_name <- wrapLocM (lookupInstDeclBndr cls (text "method")) name
                     
       ; let bind' = bind { fun_id = sel_name, fun_ext = noExt }
       ; return (L loc bind' `consBag` rest ) }
rnMethodBindLHS is_cls_decl _ (L loc bind) rest
  = do { addErrAt loc $
         vcat [ what <+> text "not allowed in" <+> decl_sort
              , nest 2 (ppr bind) ]
       ; return rest }
  where
    decl_sort | is_cls_decl = text "class declaration:"
              | otherwise   = text "instance declaration:"
    what = case bind of
              PatBind {}    -> text "Pattern bindings (except simple variables)"
              PatSynBind {} -> text "Pattern synonyms"
                               
              _ -> pprPanic "rnMethodBind" (ppr bind)
renameSigs :: HsSigCtxt
           -> [LSig GhcPs]
           -> RnM ([LSig GhcRn], FreeVars)
renameSigs ctxt sigs
  = do  { mapM_ dupSigDeclErr (findDupSigs sigs)
        ; checkDupMinimalSigs sigs
        ; (sigs', sig_fvs) <- mapFvRn (wrapLocFstM (renameSig ctxt)) sigs
        ; let (good_sigs, bad_sigs) = partition (okHsSig ctxt) sigs'
        ; mapM_ misplacedSigErr bad_sigs                 
        ; return (good_sigs, sig_fvs) }
renameSig :: HsSigCtxt -> Sig GhcPs -> RnM (Sig GhcRn, FreeVars)
renameSig _ (IdSig _ x)
  = return (IdSig noExt x, emptyFVs)    
renameSig ctxt sig@(TypeSig _ vs ty)
  = do  { new_vs <- mapM (lookupSigOccRn ctxt sig) vs
        ; let doc = TypeSigCtx (ppr_sig_bndrs vs)
        ; (new_ty, fvs) <- rnHsSigWcType BindUnlessForall doc ty
        ; return (TypeSig noExt new_vs new_ty, fvs) }
renameSig ctxt sig@(ClassOpSig _ is_deflt vs ty)
  = do  { defaultSigs_on <- xoptM LangExt.DefaultSignatures
        ; when (is_deflt && not defaultSigs_on) $
          addErr (defaultSigErr sig)
        ; new_v <- mapM (lookupSigOccRn ctxt sig) vs
        ; (new_ty, fvs) <- rnHsSigType ty_ctxt ty
        ; return (ClassOpSig noExt is_deflt new_v new_ty, fvs) }
  where
    (v1:_) = vs
    ty_ctxt = GenericCtx (text "a class method signature for"
                          <+> quotes (ppr v1))
renameSig _ (SpecInstSig _ src ty)
  = do  { (new_ty, fvs) <- rnHsSigType SpecInstSigCtx ty
        ; return (SpecInstSig noExt src new_ty,fvs) }
renameSig ctxt sig@(SpecSig _ v tys inl)
  = do  { new_v <- case ctxt of
                     TopSigCtxt {} -> lookupLocatedOccRn v
                     _             -> lookupSigOccRn ctxt sig v
        ; (new_ty, fvs) <- foldM do_one ([],emptyFVs) tys
        ; return (SpecSig noExt new_v new_ty inl, fvs) }
  where
    ty_ctxt = GenericCtx (text "a SPECIALISE signature for"
                          <+> quotes (ppr v))
    do_one (tys,fvs) ty
      = do { (new_ty, fvs_ty) <- rnHsSigType ty_ctxt ty
           ; return ( new_ty:tys, fvs_ty `plusFV` fvs) }
renameSig ctxt sig@(InlineSig _ v s)
  = do  { new_v <- lookupSigOccRn ctxt sig v
        ; return (InlineSig noExt new_v s, emptyFVs) }
renameSig ctxt (FixSig _ fsig)
  = do  { new_fsig <- rnSrcFixityDecl ctxt fsig
        ; return (FixSig noExt new_fsig, emptyFVs) }
renameSig ctxt sig@(MinimalSig _ s (L l bf))
  = do new_bf <- traverse (lookupSigOccRn ctxt sig) bf
       return (MinimalSig noExt s (L l new_bf), emptyFVs)
renameSig ctxt sig@(PatSynSig _ vs ty)
  = do  { new_vs <- mapM (lookupSigOccRn ctxt sig) vs
        ; (ty', fvs) <- rnHsSigType ty_ctxt ty
        ; return (PatSynSig noExt new_vs ty', fvs) }
  where
    ty_ctxt = GenericCtx (text "a pattern synonym signature for"
                          <+> ppr_sig_bndrs vs)
renameSig ctxt sig@(SCCFunSig _ st v s)
  = do  { new_v <- lookupSigOccRn ctxt sig v
        ; return (SCCFunSig noExt st new_v s, emptyFVs) }
renameSig _ctxt sig@(CompleteMatchSig _ s (L l bf) mty)
  = do new_bf <- traverse lookupLocatedOccRn bf
       new_mty  <- traverse lookupLocatedOccRn mty
       this_mod <- fmap tcg_mod getGblEnv
       unless (any (nameIsLocalOrFrom this_mod . unLoc) new_bf) $ do
         
         addErrCtxt (text "In" <+> ppr sig) $ failWithTc orphanError
       return (CompleteMatchSig noExt s (L l new_bf) new_mty, emptyFVs)
  where
    orphanError :: SDoc
    orphanError =
      text "Orphan COMPLETE pragmas not supported" $$
      text "A COMPLETE pragma must mention at least one data constructor" $$
      text "or pattern synonym defined in the same module."
renameSig _ (XSig _) = panic "renameSig"
ppr_sig_bndrs :: [Located RdrName] -> SDoc
ppr_sig_bndrs bs = quotes (pprWithCommas ppr bs)
okHsSig :: HsSigCtxt -> LSig a -> Bool
okHsSig ctxt (L _ sig)
  = case (sig, ctxt) of
     (ClassOpSig {}, ClsDeclCtxt {})  -> True
     (ClassOpSig {}, InstDeclCtxt {}) -> True
     (ClassOpSig {}, _)               -> False
     (TypeSig {}, ClsDeclCtxt {})  -> False
     (TypeSig {}, InstDeclCtxt {}) -> False
     (TypeSig {}, _)               -> True
     (PatSynSig {}, TopSigCtxt{}) -> True
     (PatSynSig {}, _)            -> False
     (FixSig {}, InstDeclCtxt {}) -> False
     (FixSig {}, _)               -> True
     (IdSig {}, TopSigCtxt {})   -> True
     (IdSig {}, InstDeclCtxt {}) -> True
     (IdSig {}, _)               -> False
     (InlineSig {}, HsBootCtxt {}) -> False
     (InlineSig {}, _)             -> True
     (SpecSig {}, TopSigCtxt {})    -> True
     (SpecSig {}, LocalBindCtxt {}) -> True
     (SpecSig {}, InstDeclCtxt {})  -> True
     (SpecSig {}, _)                -> False
     (SpecInstSig {}, InstDeclCtxt {}) -> True
     (SpecInstSig {}, _)               -> False
     (MinimalSig {}, ClsDeclCtxt {}) -> True
     (MinimalSig {}, _)              -> False
     (SCCFunSig {}, HsBootCtxt {}) -> False
     (SCCFunSig {}, _)             -> True
     (CompleteMatchSig {}, TopSigCtxt {} ) -> True
     (CompleteMatchSig {}, _)              -> False
     (XSig _, _) -> panic "okHsSig"
findDupSigs :: [LSig GhcPs] -> [NonEmpty (Located RdrName, Sig GhcPs)]
findDupSigs sigs
  = findDupsEq matching_sig (concatMap (expand_sig . unLoc) sigs)
  where
    expand_sig sig@(FixSig _ (FixitySig _ ns _)) = zip ns (repeat sig)
    expand_sig sig@(InlineSig _ n _)             = [(n,sig)]
    expand_sig sig@(TypeSig _ ns _)              = [(n,sig) | n <- ns]
    expand_sig sig@(ClassOpSig _ _ ns _)         = [(n,sig) | n <- ns]
    expand_sig sig@(PatSynSig _ ns  _ )          = [(n,sig) | n <- ns]
    expand_sig sig@(SCCFunSig _ _ n _)           = [(n,sig)]
    expand_sig _ = []
    matching_sig (L _ n1,sig1) (L _ n2,sig2)       = n1 == n2 && mtch sig1 sig2
    mtch (FixSig {})           (FixSig {})         = True
    mtch (InlineSig {})        (InlineSig {})      = True
    mtch (TypeSig {})          (TypeSig {})        = True
    mtch (ClassOpSig _ d1 _ _) (ClassOpSig _ d2 _ _) = d1 == d2
    mtch (PatSynSig _ _ _)     (PatSynSig _ _ _)   = True
    mtch (SCCFunSig{})         (SCCFunSig{})       = True
    mtch _ _ = False
checkDupMinimalSigs :: [LSig GhcPs] -> RnM ()
checkDupMinimalSigs sigs
  = case filter isMinimalLSig sigs of
      minSigs@(_:_:_) -> dupMinimalSigErr minSigs
      _ -> return ()
rnMatchGroup :: Outputable (body GhcPs) => HsMatchContext Name
             -> (Located (body GhcPs) -> RnM (Located (body GhcRn), FreeVars))
             -> MatchGroup GhcPs (Located (body GhcPs))
             -> RnM (MatchGroup GhcRn (Located (body GhcRn)), FreeVars)
rnMatchGroup ctxt rnBody (MG { mg_alts = L _ ms, mg_origin = origin })
  = do { empty_case_ok <- xoptM LangExt.EmptyCase
       ; when (null ms && not empty_case_ok) (addErr (emptyCaseErr ctxt))
       ; (new_ms, ms_fvs) <- mapFvRn (rnMatch ctxt rnBody) ms
       ; return (mkMatchGroup origin new_ms, ms_fvs) }
rnMatchGroup _ _ (XMatchGroup {}) = panic "rnMatchGroup"
rnMatch :: Outputable (body GhcPs) => HsMatchContext Name
        -> (Located (body GhcPs) -> RnM (Located (body GhcRn), FreeVars))
        -> LMatch GhcPs (Located (body GhcPs))
        -> RnM (LMatch GhcRn (Located (body GhcRn)), FreeVars)
rnMatch ctxt rnBody = wrapLocFstM (rnMatch' ctxt rnBody)
rnMatch' :: Outputable (body GhcPs) => HsMatchContext Name
         -> (Located (body GhcPs) -> RnM (Located (body GhcRn), FreeVars))
         -> Match GhcPs (Located (body GhcPs))
         -> RnM (Match GhcRn (Located (body GhcRn)), FreeVars)
rnMatch' ctxt rnBody (Match { m_ctxt = mf, m_pats = pats, m_grhss = grhss })
  = do  { 
        ; rnPats ctxt pats      $ \ pats' -> do
        { (grhss', grhss_fvs) <- rnGRHSs ctxt rnBody grhss
        ; let mf' = case (ctxt, mf) of
                      (FunRhs { mc_fun = L _ funid }, FunRhs { mc_fun = L lf _ })
                                            -> mf { mc_fun = L lf funid }
                      _                     -> ctxt
        ; return (Match { m_ext = noExt, m_ctxt = mf', m_pats = pats'
                        , m_grhss = grhss'}, grhss_fvs ) }}
rnMatch' _ _ (XMatch _) = panic "rnMatch'"
emptyCaseErr :: HsMatchContext Name -> SDoc
emptyCaseErr ctxt = hang (text "Empty list of alternatives in" <+> pp_ctxt)
                       2 (text "Use EmptyCase to allow this")
  where
    pp_ctxt = case ctxt of
                CaseAlt    -> text "case expression"
                LambdaExpr -> text "\\case expression"
                _ -> text "(unexpected)" <+> pprMatchContextNoun ctxt
rnGRHSs :: HsMatchContext Name
        -> (Located (body GhcPs) -> RnM (Located (body GhcRn), FreeVars))
        -> GRHSs GhcPs (Located (body GhcPs))
        -> RnM (GRHSs GhcRn (Located (body GhcRn)), FreeVars)
rnGRHSs ctxt rnBody (GRHSs _ grhss (L l binds))
  = rnLocalBindsAndThen binds   $ \ binds' _ -> do
    (grhss', fvGRHSs) <- mapFvRn (rnGRHS ctxt rnBody) grhss
    return (GRHSs noExt grhss' (L l binds'), fvGRHSs)
rnGRHSs _ _ (XGRHSs _) = panic "rnGRHSs"
rnGRHS :: HsMatchContext Name
       -> (Located (body GhcPs) -> RnM (Located (body GhcRn), FreeVars))
       -> LGRHS GhcPs (Located (body GhcPs))
       -> RnM (LGRHS GhcRn (Located (body GhcRn)), FreeVars)
rnGRHS ctxt rnBody = wrapLocFstM (rnGRHS' ctxt rnBody)
rnGRHS' :: HsMatchContext Name
        -> (Located (body GhcPs) -> RnM (Located (body GhcRn), FreeVars))
        -> GRHS GhcPs (Located (body GhcPs))
        -> RnM (GRHS GhcRn (Located (body GhcRn)), FreeVars)
rnGRHS' ctxt rnBody (GRHS _ guards rhs)
  = do  { pattern_guards_allowed <- xoptM LangExt.PatternGuards
        ; ((guards', rhs'), fvs) <- rnStmts (PatGuard ctxt) rnLExpr guards $ \ _ ->
                                    rnBody rhs
        ; unless (pattern_guards_allowed || is_standard_guard guards')
                 (addWarn NoReason (nonStdGuardErr guards'))
        ; return (GRHS noExt guards' rhs', fvs) }
  where
        
        
        
    is_standard_guard []                  = True
    is_standard_guard [L _ (BodyStmt {})] = True
    is_standard_guard _                   = False
rnGRHS' _ _ (XGRHS _) = panic "rnGRHS'"
rnSrcFixityDecl :: HsSigCtxt -> FixitySig GhcPs -> RnM (FixitySig GhcRn)
rnSrcFixityDecl sig_ctxt = rn_decl
  where
    rn_decl :: FixitySig GhcPs -> RnM (FixitySig GhcRn)
        
        
        
        
    rn_decl (FixitySig _ fnames fixity)
      = do names <- concatMapM lookup_one fnames
           return (FixitySig noExt names fixity)
    rn_decl (XFixitySig _) = panic "rnSrcFixityDecl"
    lookup_one :: Located RdrName -> RnM [Located Name]
    lookup_one (L name_loc rdr_name)
      = setSrcSpan name_loc $
                    
                    
        do names <- lookupLocalTcNames sig_ctxt what rdr_name
           return [ L name_loc name | (_, name) <- names ]
    what = text "fixity signature"
dupSigDeclErr :: NonEmpty (Located RdrName, Sig GhcPs) -> RnM ()
dupSigDeclErr pairs@((L loc name, sig) :| _)
  = addErrAt loc $
    vcat [ text "Duplicate" <+> what_it_is
           <> text "s for" <+> quotes (ppr name)
         , text "at" <+> vcat (map ppr $ sort
                                       $ map (getLoc . fst)
                                       $ toList pairs)
         ]
  where
    what_it_is = hsSigDoc sig
misplacedSigErr :: LSig GhcRn -> RnM ()
misplacedSigErr (L loc sig)
  = addErrAt loc $
    sep [text "Misplaced" <+> hsSigDoc sig <> colon, ppr sig]
defaultSigErr :: Sig GhcPs -> SDoc
defaultSigErr sig = vcat [ hang (text "Unexpected default signature:")
                              2 (ppr sig)
                         , text "Use DefaultSignatures to enable default signatures" ]
bindsInHsBootFile :: LHsBindsLR GhcRn GhcPs -> SDoc
bindsInHsBootFile mbinds
  = hang (text "Bindings in hs-boot files are not allowed")
       2 (ppr mbinds)
nonStdGuardErr :: Outputable body => [LStmtLR GhcRn GhcRn body] -> SDoc
nonStdGuardErr guards
  = hang (text "accepting non-standard pattern guards (use PatternGuards to suppress this message)")
       4 (interpp'SP guards)
unusedPatBindWarn :: HsBind GhcRn -> SDoc
unusedPatBindWarn bind
  = hang (text "This pattern-binding binds no variables:")
       2 (ppr bind)
dupMinimalSigErr :: [LSig GhcPs] -> RnM ()
dupMinimalSigErr sigs@(L loc _ : _)
  = addErrAt loc $
    vcat [ text "Multiple minimal complete definitions"
         , text "at" <+> vcat (map ppr $ sort $ map getLoc sigs)
         , text "Combine alternative minimal complete definitions with `|'" ]
dupMinimalSigErr [] = panic "dupMinimalSigErr"