module GHC.Rename.Module (
rnSrcDecls, addTcgDUs, findSplice
) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Rename.Expr( rnLExpr )
import GHC.Rename.Splice ( rnSpliceDecl, rnTopSpliceDecls )
import GHC.Hs
import GHC.Types.FieldLabel
import GHC.Types.Name.Reader
import GHC.Rename.HsType
import GHC.Rename.Bind
import GHC.Rename.Env
import GHC.Rename.Utils ( HsDocContext(..), mapFvRn, bindLocalNames
, checkDupRdrNamesN, bindLocalNamesFV
, checkShadowedRdrNames, warnUnusedTypePatterns
, newLocalBndrsRn
, withHsDocContext, noNestedForallsContextsErr
, addNoNestedForallsContextsErr, checkInferredVars )
import GHC.Rename.Unbound ( mkUnboundName, notInScopeErr )
import GHC.Rename.Names
import GHC.Tc.Gen.Annotation ( annCtxt )
import GHC.Tc.Utils.Monad
import GHC.Types.ForeignCall ( CCallTarget(..) )
import GHC.Unit
import GHC.Unit.Module.Warnings
import GHC.Builtin.Names( applicativeClassName, pureAName, thenAName
, monadClassName, returnMName, thenMName
, semigroupClassName, sappendName
, monoidClassName, mappendName
)
import GHC.Types.Name
import GHC.Types.Name.Set
import GHC.Types.Name.Env
import GHC.Types.Avail
import GHC.Utils.Outputable
import GHC.Data.Bag
import GHC.Types.Basic ( pprRuleName, TypeOrKind(..) )
import GHC.Data.FastString
import GHC.Types.SrcLoc as SrcLoc
import GHC.Driver.Session
import GHC.Utils.Misc ( debugIsOn, lengthExceeds, partitionWith )
import GHC.Utils.Panic
import GHC.Driver.Env ( HscEnv(..), hsc_home_unit)
import GHC.Data.List.SetOps ( findDupsEq, removeDups, equivClasses )
import GHC.Data.Graph.Directed ( SCC, flattenSCC, flattenSCCs, Node(..)
, stronglyConnCompFromEdgedVerticesUniq )
import GHC.Types.Unique.Set
import GHC.Data.OrdList
import qualified GHC.LanguageExtensions as LangExt
import Control.Monad
import Control.Arrow ( first )
import Data.List ( mapAccumL )
import qualified Data.List.NonEmpty as NE
import Data.List.NonEmpty ( NonEmpty(..) )
import Data.Maybe ( isNothing, fromMaybe, mapMaybe )
import qualified Data.Set as Set ( difference, fromList, toList, null )
import Data.Function ( on )
rnSrcDecls :: HsGroup GhcPs -> RnM (TcGblEnv, HsGroup GhcRn)
rnSrcDecls group@(HsGroup { hs_valds = val_decls,
hs_splcds = splice_decls,
hs_tyclds = tycl_decls,
hs_derivds = deriv_decls,
hs_fixds = fix_decls,
hs_warnds = warn_decls,
hs_annds = ann_decls,
hs_fords = foreign_decls,
hs_defds = default_decls,
hs_ruleds = rule_decls,
hs_docs = docs })
= do {
local_fix_env <- makeMiniFixityEnv $ hsGroupTopLevelFixitySigs group ;
(tc_envs, tc_bndrs) <- getLocalNonValBinders local_fix_env group ;
setEnvs tc_envs $ do {
failIfErrsM ;
dup_fields_ok <- xopt_DuplicateRecordFields <$> getDynFlags ;
has_sel <- xopt_FieldSelectors <$> getDynFlags ;
extendPatSynEnv dup_fields_ok has_sel val_decls local_fix_env $ \pat_syn_bndrs -> do {
new_lhs <- rnTopBindsLHS local_fix_env val_decls ;
let { id_bndrs = collectHsIdBinders CollNoDictBinders new_lhs } ;
traceRn "rnSrcDecls" (ppr id_bndrs) ;
tc_envs <- extendGlobalRdrEnvRn (map avail id_bndrs) local_fix_env ;
setEnvs tc_envs $ do {
traceRn "Start rnTyClDecls" (ppr tycl_decls) ;
(rn_tycl_decls, src_fvs1) <- rnTyClDecls tycl_decls ;
traceRn "Start rnmono" empty ;
let { val_bndr_set = mkNameSet id_bndrs `unionNameSet` mkNameSet pat_syn_bndrs } ;
is_boot <- tcIsHsBootOrSig ;
(rn_val_decls, bind_dus) <- if is_boot
then rnTopBindsBoot tc_bndrs new_lhs
else rnValBindsRHS (TopSigCtxt val_bndr_set) new_lhs ;
traceRn "finish rnmono" (ppr rn_val_decls) ;
let { all_bndrs = tc_bndrs `unionNameSet` val_bndr_set } ;
rn_fix_decls <- mapM (mapM (rnSrcFixityDecl (TopSigCtxt all_bndrs)))
fix_decls ;
rn_warns <- rnSrcWarnDecls all_bndrs warn_decls ;
(rn_rule_decls, src_fvs2) <- setXOptM LangExt.ScopedTypeVariables $
rnList rnHsRuleDecls rule_decls ;
(rn_foreign_decls, src_fvs3) <- rnList rnHsForeignDecl foreign_decls ;
(rn_ann_decls, src_fvs4) <- rnList rnAnnDecl ann_decls ;
(rn_default_decls, src_fvs5) <- rnList rnDefaultDecl default_decls ;
(rn_deriv_decls, src_fvs6) <- rnList rnSrcDerivDecl deriv_decls ;
(rn_splice_decls, src_fvs7) <- rnList rnSpliceDecl splice_decls ;
last_tcg_env <- getGblEnv ;
let {rn_group = HsGroup { hs_ext = noExtField,
hs_valds = rn_val_decls,
hs_splcds = rn_splice_decls,
hs_tyclds = rn_tycl_decls,
hs_derivds = rn_deriv_decls,
hs_fixds = rn_fix_decls,
hs_warnds = [],
hs_fords = rn_foreign_decls,
hs_annds = rn_ann_decls,
hs_defds = rn_default_decls,
hs_ruleds = rn_rule_decls,
hs_docs = docs } ;
tcf_bndrs = hsTyClForeignBinders rn_tycl_decls rn_foreign_decls ;
other_def = (Just (mkNameSet tcf_bndrs), emptyNameSet) ;
other_fvs = plusFVs [src_fvs1, src_fvs2, src_fvs3, src_fvs4,
src_fvs5, src_fvs6, src_fvs7] ;
src_dus = unitOL other_def `plusDU` bind_dus `plusDU` usesOnly other_fvs ;
final_tcg_env = let tcg_env' = (last_tcg_env `addTcgDUs` src_dus)
in
tcg_env' { tcg_warns = tcg_warns tcg_env' `plusWarns` rn_warns };
} ;
traceRn "finish rnSrc" (ppr rn_group) ;
traceRn "finish Dus" (ppr src_dus ) ;
return (final_tcg_env, rn_group)
}}}}
addTcgDUs :: TcGblEnv -> DefUses -> TcGblEnv
addTcgDUs tcg_env dus = tcg_env { tcg_dus = tcg_dus tcg_env `plusDU` dus }
rnList :: (a -> RnM (b, FreeVars)) -> [LocatedA a] -> RnM ([LocatedA b], FreeVars)
rnList f xs = mapFvRn (wrapLocFstMA f) xs
rnSrcWarnDecls :: NameSet -> [LWarnDecls GhcPs] -> RnM Warnings
rnSrcWarnDecls _ []
= return NoWarnings
rnSrcWarnDecls bndr_set decls'
= do {
; mapM_ (\ dups -> let ((L loc rdr) :| (lrdr':_)) = dups
in addErrAt (locA loc) (dupWarnDecl lrdr' rdr))
warn_rdr_dups
; pairs_s <- mapM (addLocMA rn_deprec) decls
; return (WarnSome ((concat pairs_s))) }
where
decls = concatMap (wd_warnings . unLoc) decls'
sig_ctxt = TopSigCtxt bndr_set
rn_deprec (Warning _ rdr_names txt)
= do { names <- concatMapM (lookupLocalTcNames sig_ctxt what . unLoc)
rdr_names
; return [(rdrNameOcc rdr, txt) | (rdr, _) <- names] }
what = text "deprecation"
warn_rdr_dups = findDupRdrNames
$ concatMap (\(L _ (Warning _ ns _)) -> ns) decls
findDupRdrNames :: [LocatedN RdrName] -> [NonEmpty (LocatedN RdrName)]
findDupRdrNames = findDupsEq (\ x -> \ y -> rdrNameOcc (unLoc x) == rdrNameOcc (unLoc y))
dupWarnDecl :: LocatedN RdrName -> RdrName -> SDoc
dupWarnDecl d rdr_name
= vcat [text "Multiple warning declarations for" <+> quotes (ppr rdr_name),
text "also at " <+> ppr (getLocA d)]
rnAnnDecl :: AnnDecl GhcPs -> RnM (AnnDecl GhcRn, FreeVars)
rnAnnDecl ann@(HsAnnotation _ s provenance expr)
= addErrCtxt (annCtxt ann) $
do { (provenance', provenance_fvs) <- rnAnnProvenance provenance
; (expr', expr_fvs) <- setStage (Splice Untyped) $
rnLExpr expr
; return (HsAnnotation noAnn s provenance' expr',
provenance_fvs `plusFV` expr_fvs) }
rnAnnProvenance :: AnnProvenance GhcPs
-> RnM (AnnProvenance GhcRn, FreeVars)
rnAnnProvenance provenance = do
provenance' <- case provenance of
ValueAnnProvenance n -> ValueAnnProvenance <$> lookupLocatedTopBndrRnN n
TypeAnnProvenance n -> TypeAnnProvenance <$> lookupLocatedTopBndrRnN n
ModuleAnnProvenance -> return ModuleAnnProvenance
return (provenance', maybe emptyFVs unitFV (annProvenanceName_maybe provenance'))
rnDefaultDecl :: DefaultDecl GhcPs -> RnM (DefaultDecl GhcRn, FreeVars)
rnDefaultDecl (DefaultDecl _ tys)
= do { (tys', fvs) <- rnLHsTypes doc_str tys
; return (DefaultDecl noExtField tys', fvs) }
where
doc_str = DefaultDeclCtx
rnHsForeignDecl :: ForeignDecl GhcPs -> RnM (ForeignDecl GhcRn, FreeVars)
rnHsForeignDecl (ForeignImport { fd_name = name, fd_sig_ty = ty, fd_fi = spec })
= do { topEnv :: HscEnv <- getTopEnv
; name' <- lookupLocatedTopBndrRnN name
; (ty', fvs) <- rnHsSigType (ForeignDeclCtx name) TypeLevel ty
; let home_unit = hsc_home_unit topEnv
spec' = patchForeignImport (homeUnitAsUnit home_unit) spec
; return (ForeignImport { fd_i_ext = noExtField
, fd_name = name', fd_sig_ty = ty'
, fd_fi = spec' }, fvs) }
rnHsForeignDecl (ForeignExport { fd_name = name, fd_sig_ty = ty, fd_fe = spec })
= do { name' <- lookupLocatedOccRn name
; (ty', fvs) <- rnHsSigType (ForeignDeclCtx name) TypeLevel ty
; return (ForeignExport { fd_e_ext = noExtField
, fd_name = name', fd_sig_ty = ty'
, fd_fe = spec }
, fvs `addOneFV` unLoc name') }
patchForeignImport :: Unit -> ForeignImport -> ForeignImport
patchForeignImport unit (CImport cconv safety fs spec src)
= CImport cconv safety fs (patchCImportSpec unit spec) src
patchCImportSpec :: Unit -> CImportSpec -> CImportSpec
patchCImportSpec unit spec
= case spec of
CFunction callTarget -> CFunction $ patchCCallTarget unit callTarget
_ -> spec
patchCCallTarget :: Unit -> CCallTarget -> CCallTarget
patchCCallTarget unit callTarget =
case callTarget of
StaticTarget src label Nothing isFun
-> StaticTarget src label (Just unit) isFun
_ -> callTarget
rnSrcInstDecl :: InstDecl GhcPs -> RnM (InstDecl GhcRn, FreeVars)
rnSrcInstDecl (TyFamInstD { tfid_inst = tfi })
= do { (tfi', fvs) <- rnTyFamInstDecl (NonAssocTyFamEqn NotClosedTyFam) tfi
; return (TyFamInstD { tfid_ext = noExtField, tfid_inst = tfi' }, fvs) }
rnSrcInstDecl (DataFamInstD { dfid_inst = dfi })
= do { (dfi', fvs) <- rnDataFamInstDecl (NonAssocTyFamEqn NotClosedTyFam) dfi
; return (DataFamInstD { dfid_ext = noExtField, dfid_inst = dfi' }, fvs) }
rnSrcInstDecl (ClsInstD { cid_inst = cid })
= do { traceRn "rnSrcIstDecl {" (ppr cid)
; (cid', fvs) <- rnClsInstDecl cid
; traceRn "rnSrcIstDecl end }" empty
; return (ClsInstD { cid_d_ext = noExtField, cid_inst = cid' }, fvs) }
checkCanonicalInstances :: Name -> LHsSigType GhcRn -> LHsBinds GhcRn -> RnM ()
checkCanonicalInstances cls poly_ty mbinds = do
whenWOptM Opt_WarnNonCanonicalMonadInstances
$ checkCanonicalMonadInstances
"https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/monad-of-no-return"
whenWOptM Opt_WarnNonCanonicalMonoidInstances
$ checkCanonicalMonoidInstances
"https://gitlab.haskell.org/ghc/ghc/-/wikis/proposal/semigroup-monoid"
where
checkCanonicalMonadInstances refURL
| cls == applicativeClassName =
forM_ (bagToList mbinds) $ \(L loc mbind) -> setSrcSpanA loc $
case mbind of
FunBind { fun_id = L _ name
, fun_matches = mg }
| name == pureAName, isAliasMG mg == Just returnMName
-> addWarnNonCanonicalMethod1 refURL
Opt_WarnNonCanonicalMonadInstances "pure" "return"
| name == thenAName, isAliasMG mg == Just thenMName
-> addWarnNonCanonicalMethod1 refURL
Opt_WarnNonCanonicalMonadInstances "(*>)" "(>>)"
_ -> return ()
| cls == monadClassName =
forM_ (bagToList mbinds) $ \(L loc mbind) -> setSrcSpanA loc $
case mbind of
FunBind { fun_id = L _ name
, fun_matches = mg }
| name == returnMName, isAliasMG mg /= Just pureAName
-> addWarnNonCanonicalMethod2 refURL
Opt_WarnNonCanonicalMonadInstances "return" "pure"
| name == thenMName, isAliasMG mg /= Just thenAName
-> addWarnNonCanonicalMethod2 refURL
Opt_WarnNonCanonicalMonadInstances "(>>)" "(*>)"
_ -> return ()
| otherwise = return ()
checkCanonicalMonoidInstances refURL
| cls == semigroupClassName =
forM_ (bagToList mbinds) $ \(L loc mbind) -> setSrcSpanA loc $
case mbind of
FunBind { fun_id = L _ name
, fun_matches = mg }
| name == sappendName, isAliasMG mg == Just mappendName
-> addWarnNonCanonicalMethod1 refURL
Opt_WarnNonCanonicalMonoidInstances "(<>)" "mappend"
_ -> return ()
| cls == monoidClassName =
forM_ (bagToList mbinds) $ \(L loc mbind) -> setSrcSpanA loc $
case mbind of
FunBind { fun_id = L _ name
, fun_matches = mg }
| name == mappendName, isAliasMG mg /= Just sappendName
-> addWarnNonCanonicalMethod2 refURL
Opt_WarnNonCanonicalMonoidInstances
"mappend" "(<>)"
_ -> return ()
| otherwise = return ()
isAliasMG :: MatchGroup GhcRn (LHsExpr GhcRn) -> Maybe Name
isAliasMG MG {mg_alts = (L _ [L _ (Match { m_pats = []
, m_grhss = grhss })])}
| GRHSs _ [L _ (GRHS _ [] body)] lbinds <- grhss
, EmptyLocalBinds _ <- lbinds
, HsVar _ lrhsName <- unLoc body = Just (unLoc lrhsName)
isAliasMG _ = Nothing
addWarnNonCanonicalMethod1 refURL flag lhs rhs =
addWarn (Reason flag) $ vcat
[ text "Noncanonical" <+>
quotes (text (lhs ++ " = " ++ rhs)) <+>
text "definition detected"
, instDeclCtxt1 poly_ty
, text "Move definition from" <+>
quotes (text rhs) <+>
text "to" <+> quotes (text lhs)
, text "See also:" <+>
text refURL
]
addWarnNonCanonicalMethod2 refURL flag lhs rhs =
addWarn (Reason flag) $ vcat
[ text "Noncanonical" <+>
quotes (text lhs) <+>
text "definition detected"
, instDeclCtxt1 poly_ty
, quotes (text lhs) <+>
text "will eventually be removed in favour of" <+>
quotes (text rhs)
, text "Either remove definition for" <+>
quotes (text lhs) <+> text "(recommended)" <+>
text "or define as" <+>
quotes (text (lhs ++ " = " ++ rhs))
, text "See also:" <+>
text refURL
]
instDeclCtxt1 :: LHsSigType GhcRn -> SDoc
instDeclCtxt1 hs_inst_ty
= inst_decl_ctxt (ppr (getLHsInstDeclHead hs_inst_ty))
inst_decl_ctxt :: SDoc -> SDoc
inst_decl_ctxt doc = hang (text "in the instance declaration for")
2 (quotes doc <> text ".")
rnClsInstDecl :: ClsInstDecl GhcPs -> RnM (ClsInstDecl GhcRn, FreeVars)
rnClsInstDecl (ClsInstDecl { cid_poly_ty = inst_ty, cid_binds = mbinds
, cid_sigs = uprags, cid_tyfam_insts = ats
, cid_overlap_mode = oflag
, cid_datafam_insts = adts })
= do { checkInferredVars ctxt inf_err inst_ty
; (inst_ty', inst_fvs) <- rnHsSigType ctxt TypeLevel inst_ty
; let (ktv_names, _, head_ty') = splitLHsInstDeclTy inst_ty'
mb_nested_msg = noNestedForallsContextsErr
(text "Instance head") head_ty'
eith_cls = case hsTyGetAppHead_maybe head_ty' of
Just (L _ cls) -> Right cls
Nothing -> Left
( getLocA head_ty'
, hang (text "Illegal head of an instance declaration:"
<+> quotes (ppr head_ty'))
2 (vcat [ text "Instance heads must be of the form"
, nest 2 $ text "C ty_1 ... ty_n"
, text "where" <+> quotes (char 'C')
<+> text "is a class"
])
)
; cls <- case (mb_nested_msg, eith_cls) of
(Nothing, Right cls) -> pure cls
(Just err1, _) -> bail_out err1
(_, Left err2) -> bail_out err2
; (mbinds', uprags', meth_fvs) <- rnMethodBinds False cls ktv_names mbinds uprags
; checkCanonicalInstances cls inst_ty' mbinds'
; traceRn "rnSrcInstDecl" (ppr inst_ty' $$ ppr ktv_names)
; ((ats', adts'), more_fvs)
<- bindLocalNamesFV ktv_names $
do { (ats', at_fvs) <- rnATInstDecls rnTyFamInstDecl cls ktv_names ats
; (adts', adt_fvs) <- rnATInstDecls rnDataFamInstDecl cls ktv_names adts
; return ( (ats', adts'), at_fvs `plusFV` adt_fvs) }
; let all_fvs = meth_fvs `plusFV` more_fvs
`plusFV` inst_fvs
; return (ClsInstDecl { cid_ext = noExtField
, cid_poly_ty = inst_ty', cid_binds = mbinds'
, cid_sigs = uprags', cid_tyfam_insts = ats'
, cid_overlap_mode = oflag
, cid_datafam_insts = adts' },
all_fvs) }
where
ctxt = GenericCtx $ text "an instance declaration"
inf_err = Just (text "Inferred type variables are not allowed")
bail_out (l, err_msg) = do
addErrAt l $ withHsDocContext ctxt err_msg
pure $ mkUnboundName (mkTcOccFS (fsLit "<class>"))
rnFamEqn :: HsDocContext
-> AssocTyFamInfo
-> FreeKiTyVars
-> FamEqn GhcPs rhs
-> (HsDocContext -> rhs -> RnM (rhs', FreeVars))
-> RnM (FamEqn GhcRn rhs', FreeVars)
rnFamEqn doc atfi extra_kvars
(FamEqn { feqn_tycon = tycon
, feqn_bndrs = outer_bndrs
, feqn_pats = pats
, feqn_fixity = fixity
, feqn_rhs = payload }) rn_payload
= do { tycon' <- lookupFamInstName mb_cls tycon
; let all_imp_vars = pat_kity_vars ++ extra_kvars
; bindHsOuterTyVarBndrs doc mb_cls all_imp_vars outer_bndrs $ \rn_outer_bndrs ->
do { (pats', pat_fvs) <- rnLHsTypeArgs (FamPatCtx tycon) pats
; (payload', rhs_fvs) <- rn_payload doc payload
; let
rn_outer_bndrs' = mapHsOuterImplicit (map (`setNameLoc` lhs_loc))
rn_outer_bndrs
groups :: [NonEmpty (LocatedN RdrName)]
groups = equivClasses cmpLocated pat_kity_vars
; nms_dups <- mapM (lookupOccRn . unLoc) $
[ tv | (tv :| (_:_)) <- groups ]
; let nms_used = extendNameSetList rhs_fvs $
nms_dups ++ inst_head_tvs
all_nms = hsOuterTyVarNames rn_outer_bndrs'
; warnUnusedTypePatterns all_nms nms_used
; let lhs_bound_vars = extendNameSetList pat_fvs all_nms
improperly_scoped cls_tkv =
cls_tkv `elemNameSet` rhs_fvs
&& not (cls_tkv `elemNameSet` lhs_bound_vars)
bad_tvs = filter improperly_scoped inst_head_tvs
; unless (null bad_tvs) (badAssocRhs bad_tvs)
; let eqn_fvs = rhs_fvs `plusFV` pat_fvs
all_fvs = case atfi of
NonAssocTyFamEqn ClosedTyFam
-> eqn_fvs
_ -> eqn_fvs `addOneFV` unLoc tycon'
; return (FamEqn { feqn_ext = noAnn
, feqn_tycon = tycon'
, feqn_bndrs = rn_outer_bndrs'
, feqn_pats = pats'
, feqn_fixity = fixity
, feqn_rhs = payload' },
all_fvs) } }
where
mb_cls = case atfi of
NonAssocTyFamEqn _ -> Nothing
AssocTyFamDeflt cls -> Just cls
AssocTyFamInst cls _ -> Just cls
inst_head_tvs = case atfi of
NonAssocTyFamEqn _ -> []
AssocTyFamDeflt _ -> []
AssocTyFamInst _ inst_head_tvs -> inst_head_tvs
pat_kity_vars = extractHsTyArgRdrKiTyVars pats
lhs_loc = case map lhsTypeArgSrcSpan pats ++ map getLocA extra_kvars of
[] -> panic "rnFamEqn.lhs_loc"
[loc] -> loc
(loc:locs) -> loc `combineSrcSpans` last locs
badAssocRhs :: [Name] -> RnM ()
badAssocRhs ns
= addErr (hang (text "The RHS of an associated type declaration mentions"
<+> text "out-of-scope variable" <> plural ns
<+> pprWithCommas (quotes . ppr) ns)
2 (text "All such variables must be bound on the LHS"))
rnTyFamInstDecl :: AssocTyFamInfo
-> TyFamInstDecl GhcPs
-> RnM (TyFamInstDecl GhcRn, FreeVars)
rnTyFamInstDecl atfi (TyFamInstDecl { tfid_xtn = x, tfid_eqn = eqn })
= do { (eqn', fvs) <- rnTyFamInstEqn atfi eqn
; return (TyFamInstDecl { tfid_xtn = x, tfid_eqn = eqn' }, fvs) }
data AssocTyFamInfo
= NonAssocTyFamEqn
ClosedTyFamInfo
| AssocTyFamDeflt
Name
| AssocTyFamInst
Name
[Name]
data ClosedTyFamInfo
= NotClosedTyFam
| ClosedTyFam
rnTyFamInstEqn :: AssocTyFamInfo
-> TyFamInstEqn GhcPs
-> RnM (TyFamInstEqn GhcRn, FreeVars)
rnTyFamInstEqn atfi eqn@(FamEqn { feqn_tycon = tycon, feqn_rhs = rhs })
= rnFamEqn (TySynCtx tycon) atfi extra_kvs eqn rnTySyn
where
extra_kvs = extractHsTyRdrTyVarsKindVars rhs
rnTyFamDefltDecl :: Name
-> TyFamDefltDecl GhcPs
-> RnM (TyFamDefltDecl GhcRn, FreeVars)
rnTyFamDefltDecl cls = rnTyFamInstDecl (AssocTyFamDeflt cls)
rnDataFamInstDecl :: AssocTyFamInfo
-> DataFamInstDecl GhcPs
-> RnM (DataFamInstDecl GhcRn, FreeVars)
rnDataFamInstDecl atfi (DataFamInstDecl { dfid_eqn =
eqn@(FamEqn { feqn_tycon = tycon
, feqn_rhs = rhs })})
= do { let extra_kvs = extractDataDefnKindVars rhs
; (eqn', fvs) <-
rnFamEqn (TyDataCtx tycon) atfi extra_kvs eqn rnDataDefn
; return (DataFamInstDecl { dfid_eqn = eqn' }, fvs) }
rnATDecls :: Name
-> [LFamilyDecl GhcPs]
-> RnM ([LFamilyDecl GhcRn], FreeVars)
rnATDecls cls at_decls
= rnList (rnFamDecl (Just cls)) at_decls
rnATInstDecls :: (AssocTyFamInfo ->
decl GhcPs ->
RnM (decl GhcRn, FreeVars))
-> Name
-> [Name]
-> [LocatedA (decl GhcPs)]
-> RnM ([LocatedA (decl GhcRn)], FreeVars)
rnATInstDecls rnFun cls tv_ns at_insts
= rnList (rnFun (AssocTyFamInst cls tv_ns)) at_insts
rnSrcDerivDecl :: DerivDecl GhcPs -> RnM (DerivDecl GhcRn, FreeVars)
rnSrcDerivDecl (DerivDecl _ ty mds overlap)
= do { standalone_deriv_ok <- xoptM LangExt.StandaloneDeriving
; unless standalone_deriv_ok (addErr standaloneDerivErr)
; checkInferredVars ctxt inf_err nowc_ty
; (mds', ty', fvs) <- rnLDerivStrategy ctxt mds $ rnHsSigWcType ctxt ty
; addNoNestedForallsContextsErr ctxt
(text "Standalone-derived instance head")
(getLHsInstDeclHead $ dropWildCards ty')
; warnNoDerivStrat mds' loc
; return (DerivDecl noAnn ty' mds' overlap, fvs) }
where
ctxt = DerivDeclCtx
inf_err = Just (text "Inferred type variables are not allowed")
loc = getLocA nowc_ty
nowc_ty = dropWildCards ty
standaloneDerivErr :: SDoc
standaloneDerivErr
= hang (text "Illegal standalone deriving declaration")
2 (text "Use StandaloneDeriving to enable this extension")
rnHsRuleDecls :: RuleDecls GhcPs -> RnM (RuleDecls GhcRn, FreeVars)
rnHsRuleDecls (HsRules { rds_src = src
, rds_rules = rules })
= do { (rn_rules,fvs) <- rnList rnHsRuleDecl rules
; return (HsRules { rds_ext = noExtField
, rds_src = src
, rds_rules = rn_rules }, fvs) }
rnHsRuleDecl :: RuleDecl GhcPs -> RnM (RuleDecl GhcRn, FreeVars)
rnHsRuleDecl (HsRule { rd_name = rule_name
, rd_act = act
, rd_tyvs = tyvs
, rd_tmvs = tmvs
, rd_lhs = lhs
, rd_rhs = rhs })
= do { let rdr_names_w_loc = map (get_var . unLoc) tmvs
; checkDupRdrNamesN rdr_names_w_loc
; checkShadowedRdrNames rdr_names_w_loc
; names <- newLocalBndrsRn rdr_names_w_loc
; let doc = RuleCtx (snd $ unLoc rule_name)
; bindRuleTyVars doc tyvs $ \ tyvs' ->
bindRuleTmVars doc tyvs' tmvs names $ \ tmvs' ->
do { (lhs', fv_lhs') <- rnLExpr lhs
; (rhs', fv_rhs') <- rnLExpr rhs
; checkValidRule (snd $ unLoc rule_name) names lhs' fv_lhs'
; return (HsRule { rd_ext = HsRuleRn fv_lhs' fv_rhs'
, rd_name = rule_name
, rd_act = act
, rd_tyvs = tyvs'
, rd_tmvs = tmvs'
, rd_lhs = lhs'
, rd_rhs = rhs' }, fv_lhs' `plusFV` fv_rhs') } }
where
get_var :: RuleBndr GhcPs -> LocatedN RdrName
get_var (RuleBndrSig _ v _) = v
get_var (RuleBndr _ v) = v
bindRuleTmVars :: HsDocContext -> Maybe ty_bndrs
-> [LRuleBndr GhcPs] -> [Name]
-> ([LRuleBndr GhcRn] -> RnM (a, FreeVars))
-> RnM (a, FreeVars)
bindRuleTmVars doc tyvs vars names thing_inside
= go vars names $ \ vars' ->
bindLocalNamesFV names (thing_inside vars')
where
go ((L l (RuleBndr _ (L loc _))) : vars) (n : ns) thing_inside
= go vars ns $ \ vars' ->
thing_inside (L l (RuleBndr noAnn (L loc n)) : vars')
go ((L l (RuleBndrSig _ (L loc _) bsig)) : vars)
(n : ns) thing_inside
= rnHsPatSigType bind_free_tvs doc bsig $ \ bsig' ->
go vars ns $ \ vars' ->
thing_inside (L l (RuleBndrSig noAnn (L loc n) bsig') : vars')
go [] [] thing_inside = thing_inside []
go vars names _ = pprPanic "bindRuleVars" (ppr vars $$ ppr names)
bind_free_tvs = case tyvs of Nothing -> AlwaysBind
Just _ -> NeverBind
bindRuleTyVars :: HsDocContext -> Maybe [LHsTyVarBndr () GhcPs]
-> (Maybe [LHsTyVarBndr () GhcRn] -> RnM (b, FreeVars))
-> RnM (b, FreeVars)
bindRuleTyVars doc (Just bndrs) thing_inside
= bindLHsTyVarBndrs doc WarnUnusedForalls Nothing bndrs (thing_inside . Just)
bindRuleTyVars _ _ thing_inside = thing_inside Nothing
checkValidRule :: FastString -> [Name] -> LHsExpr GhcRn -> NameSet -> RnM ()
checkValidRule rule_name ids lhs' fv_lhs'
= do {
case (validRuleLhs ids lhs') of
Nothing -> return ()
Just bad -> failWithTc (badRuleLhsErr rule_name lhs' bad)
; let bad_vars = [var | var <- ids, not (var `elemNameSet` fv_lhs')]
; mapM_ (addErr . badRuleVar rule_name) bad_vars }
validRuleLhs :: [Name] -> LHsExpr GhcRn -> Maybe (HsExpr GhcRn)
validRuleLhs foralls lhs
= checkl lhs
where
checkl = check . unLoc
check (OpApp _ e1 op e2) = checkl op `mplus` checkl_e e1
`mplus` checkl_e e2
check (HsApp _ e1 e2) = checkl e1 `mplus` checkl_e e2
check (HsAppType _ e _) = checkl e
check (HsVar _ lv)
| (unLoc lv) `notElem` foralls = Nothing
check other = Just other
checkl_e _ = Nothing
badRuleVar :: FastString -> Name -> SDoc
badRuleVar name var
= sep [text "Rule" <+> doubleQuotes (ftext name) <> colon,
text "Forall'd variable" <+> quotes (ppr var) <+>
text "does not appear on left hand side"]
badRuleLhsErr :: FastString -> LHsExpr GhcRn -> HsExpr GhcRn -> SDoc
badRuleLhsErr name lhs bad_e
= sep [text "Rule" <+> pprRuleName name <> colon,
nest 2 (vcat [err,
text "in left-hand side:" <+> ppr lhs])]
$$
text "LHS must be of form (f e1 .. en) where f is not forall'd"
where
err = case bad_e of
HsUnboundVar _ uv -> notInScopeErr (mkRdrUnqual uv)
_ -> text "Illegal expression:" <+> ppr bad_e
rnTyClDecls :: [TyClGroup GhcPs]
-> RnM ([TyClGroup GhcRn], FreeVars)
rnTyClDecls tycl_ds
= do {
; tycls_w_fvs <- mapM (wrapLocFstMA rnTyClDecl) (tyClGroupTyClDecls tycl_ds)
; let tc_names = mkNameSet (map (tcdName . unLoc . fst) tycls_w_fvs)
; kisigs_w_fvs <- rnStandaloneKindSignatures tc_names (tyClGroupKindSigs tycl_ds)
; instds_w_fvs <- mapM (wrapLocFstMA rnSrcInstDecl) (tyClGroupInstDecls tycl_ds)
; role_annots <- rnRoleAnnots tc_names (tyClGroupRoleDecls tycl_ds)
; rdr_env <- getGlobalRdrEnv
; let tycl_sccs = depAnalTyClDecls rdr_env kisig_fv_env tycls_w_fvs
role_annot_env = mkRoleAnnotEnv role_annots
(kisig_env, kisig_fv_env) = mkKindSig_fv_env kisigs_w_fvs
inst_ds_map = mkInstDeclFreeVarsMap rdr_env tc_names instds_w_fvs
(init_inst_ds, rest_inst_ds) = getInsts [] inst_ds_map
first_group
| null init_inst_ds = []
| otherwise = [TyClGroup { group_ext = noExtField
, group_tyclds = []
, group_kisigs = []
, group_roles = []
, group_instds = init_inst_ds }]
(final_inst_ds, groups)
= mapAccumL (mk_group role_annot_env kisig_env) rest_inst_ds tycl_sccs
all_fvs = foldr (plusFV . snd) emptyFVs tycls_w_fvs `plusFV`
foldr (plusFV . snd) emptyFVs instds_w_fvs `plusFV`
foldr (plusFV . snd) emptyFVs kisigs_w_fvs
all_groups = first_group ++ groups
; MASSERT2( null final_inst_ds, ppr instds_w_fvs $$ ppr inst_ds_map
$$ ppr (flattenSCCs tycl_sccs) $$ ppr final_inst_ds )
; traceRn "rnTycl dependency analysis made groups" (ppr all_groups)
; return (all_groups, all_fvs) }
where
mk_group :: RoleAnnotEnv
-> KindSigEnv
-> InstDeclFreeVarsMap
-> SCC (LTyClDecl GhcRn)
-> (InstDeclFreeVarsMap, TyClGroup GhcRn)
mk_group role_env kisig_env inst_map scc
= (inst_map', group)
where
tycl_ds = flattenSCC scc
bndrs = map (tcdName . unLoc) tycl_ds
roles = getRoleAnnots bndrs role_env
kisigs = getKindSigs bndrs kisig_env
(inst_ds, inst_map') = getInsts bndrs inst_map
group = TyClGroup { group_ext = noExtField
, group_tyclds = tycl_ds
, group_kisigs = kisigs
, group_roles = roles
, group_instds = inst_ds }
newtype KindSig_FV_Env = KindSig_FV_Env (NameEnv FreeVars)
lookupKindSig_FV_Env :: KindSig_FV_Env -> Name -> FreeVars
lookupKindSig_FV_Env (KindSig_FV_Env e) name
= fromMaybe emptyFVs (lookupNameEnv e name)
type KindSigEnv = NameEnv (LStandaloneKindSig GhcRn)
mkKindSig_fv_env :: [(LStandaloneKindSig GhcRn, FreeVars)] -> (KindSigEnv, KindSig_FV_Env)
mkKindSig_fv_env kisigs_w_fvs = (kisig_env, kisig_fv_env)
where
kisig_env = mapNameEnv fst compound_env
kisig_fv_env = KindSig_FV_Env (mapNameEnv snd compound_env)
compound_env :: NameEnv (LStandaloneKindSig GhcRn, FreeVars)
= mkNameEnvWith (standaloneKindSigName . unLoc . fst) kisigs_w_fvs
getKindSigs :: [Name] -> KindSigEnv -> [LStandaloneKindSig GhcRn]
getKindSigs bndrs kisig_env = mapMaybe (lookupNameEnv kisig_env) bndrs
rnStandaloneKindSignatures
:: NameSet
-> [LStandaloneKindSig GhcPs]
-> RnM [(LStandaloneKindSig GhcRn, FreeVars)]
rnStandaloneKindSignatures tc_names kisigs
= do { let (no_dups, dup_kisigs) = removeDups (compare `on` get_name) kisigs
get_name = standaloneKindSigName . unLoc
; mapM_ dupKindSig_Err dup_kisigs
; mapM (wrapLocFstMA (rnStandaloneKindSignature tc_names)) no_dups
}
rnStandaloneKindSignature
:: NameSet
-> StandaloneKindSig GhcPs
-> RnM (StandaloneKindSig GhcRn, FreeVars)
rnStandaloneKindSignature tc_names (StandaloneKindSig _ v ki)
= do { standalone_ki_sig_ok <- xoptM LangExt.StandaloneKindSignatures
; unless standalone_ki_sig_ok $ addErr standaloneKiSigErr
; new_v <- lookupSigCtxtOccRnN (TopSigCtxt tc_names) (text "standalone kind signature") v
; let doc = StandaloneKindSigCtx (ppr v)
; (new_ki, fvs) <- rnHsSigType doc KindLevel ki
; return (StandaloneKindSig noExtField new_v new_ki, fvs)
}
where
standaloneKiSigErr :: SDoc
standaloneKiSigErr =
hang (text "Illegal standalone kind signature")
2 (text "Did you mean to enable StandaloneKindSignatures?")
depAnalTyClDecls :: GlobalRdrEnv
-> KindSig_FV_Env
-> [(LTyClDecl GhcRn, FreeVars)]
-> [SCC (LTyClDecl GhcRn)]
depAnalTyClDecls rdr_env kisig_fv_env ds_w_fvs
= stronglyConnCompFromEdgedVerticesUniq edges
where
edges :: [ Node Name (LTyClDecl GhcRn) ]
edges = [ DigraphNode d name (map (getParent rdr_env) (nonDetEltsUniqSet deps))
| (d, fvs) <- ds_w_fvs,
let { name = tcdName (unLoc d)
; kisig_fvs = lookupKindSig_FV_Env kisig_fv_env name
; deps = fvs `plusFV` kisig_fvs
}
]
toParents :: GlobalRdrEnv -> NameSet -> NameSet
toParents rdr_env ns
= nonDetStrictFoldUniqSet add emptyNameSet ns
where
add n s = extendNameSet s (getParent rdr_env n)
getParent :: GlobalRdrEnv -> Name -> Name
getParent rdr_env n
= case lookupGRE_Name rdr_env n of
Just gre -> case gre_par gre of
ParentIs { par_is = p } -> p
_ -> n
Nothing -> n
rnRoleAnnots :: NameSet
-> [LRoleAnnotDecl GhcPs]
-> RnM [LRoleAnnotDecl GhcRn]
rnRoleAnnots tc_names role_annots
= do {
let (no_dups, dup_annots) = removeDups (compare `on` get_name) role_annots
get_name = roleAnnotDeclName . unLoc
; mapM_ dupRoleAnnotErr dup_annots
; mapM (wrapLocMA rn_role_annot1) no_dups }
where
rn_role_annot1 (RoleAnnotDecl _ tycon roles)
= do {
tycon' <- lookupSigCtxtOccRnN (RoleAnnotCtxt tc_names)
(text "role annotation")
tycon
; return $ RoleAnnotDecl noExtField tycon' roles }
dupRoleAnnotErr :: NonEmpty (LRoleAnnotDecl GhcPs) -> RnM ()
dupRoleAnnotErr list
= addErrAt (locA loc) $
hang (text "Duplicate role annotations for" <+>
quotes (ppr $ roleAnnotDeclName first_decl) <> colon)
2 (vcat $ map pp_role_annot $ NE.toList sorted_list)
where
sorted_list = NE.sortBy cmp_loc list
((L loc first_decl) :| _) = sorted_list
pp_role_annot (L loc decl) = hang (ppr decl)
4 (text "-- written at" <+> ppr (locA loc))
cmp_loc = SrcLoc.leftmost_smallest `on` getLocA
dupKindSig_Err :: NonEmpty (LStandaloneKindSig GhcPs) -> RnM ()
dupKindSig_Err list
= addErrAt (locA loc) $
hang (text "Duplicate standalone kind signatures for" <+>
quotes (ppr $ standaloneKindSigName first_decl) <> colon)
2 (vcat $ map pp_kisig $ NE.toList sorted_list)
where
sorted_list = NE.sortBy cmp_loc list
((L loc first_decl) :| _) = sorted_list
pp_kisig (L loc decl) =
hang (ppr decl) 4 (text "-- written at" <+> ppr (locA loc))
cmp_loc = SrcLoc.leftmost_smallest `on` getLocA
type InstDeclFreeVarsMap = [(LInstDecl GhcRn, FreeVars)]
mkInstDeclFreeVarsMap :: GlobalRdrEnv
-> NameSet
-> [(LInstDecl GhcRn, FreeVars)]
-> InstDeclFreeVarsMap
mkInstDeclFreeVarsMap rdr_env tycl_bndrs inst_ds_fvs
= [ (inst_decl, toParents rdr_env fvs `intersectFVs` tycl_bndrs)
| (inst_decl, fvs) <- inst_ds_fvs ]
getInsts :: [Name] -> InstDeclFreeVarsMap
-> ([LInstDecl GhcRn], InstDeclFreeVarsMap)
getInsts bndrs inst_decl_map
= partitionWith pick_me inst_decl_map
where
pick_me :: (LInstDecl GhcRn, FreeVars)
-> Either (LInstDecl GhcRn) (LInstDecl GhcRn, FreeVars)
pick_me (decl, fvs)
| isEmptyNameSet depleted_fvs = Left decl
| otherwise = Right (decl, depleted_fvs)
where
depleted_fvs = delFVs bndrs fvs
rnTyClDecl :: TyClDecl GhcPs
-> RnM (TyClDecl GhcRn, FreeVars)
rnTyClDecl (FamDecl { tcdFam = fam })
= do { (fam', fvs) <- rnFamDecl Nothing fam
; return (FamDecl noExtField fam', fvs) }
rnTyClDecl (SynDecl { tcdLName = tycon, tcdTyVars = tyvars,
tcdFixity = fixity, tcdRhs = rhs })
= do { tycon' <- lookupLocatedTopBndrRnN tycon
; let kvs = extractHsTyRdrTyVarsKindVars rhs
doc = TySynCtx tycon
; traceRn "rntycl-ty" (ppr tycon <+> ppr kvs)
; bindHsQTyVars doc Nothing kvs tyvars $ \ tyvars' _ ->
do { (rhs', fvs) <- rnTySyn doc rhs
; return (SynDecl { tcdLName = tycon', tcdTyVars = tyvars'
, tcdFixity = fixity
, tcdRhs = rhs', tcdSExt = fvs }, fvs) } }
rnTyClDecl (DataDecl
{ tcdLName = tycon, tcdTyVars = tyvars,
tcdFixity = fixity,
tcdDataDefn = defn@HsDataDefn{ dd_ND = new_or_data
, dd_kindSig = kind_sig} })
= do { tycon' <- lookupLocatedTopBndrRnN tycon
; let kvs = extractDataDefnKindVars defn
doc = TyDataCtx tycon
; traceRn "rntycl-data" (ppr tycon <+> ppr kvs)
; bindHsQTyVars doc Nothing kvs tyvars $ \ tyvars' no_rhs_kvs ->
do { (defn', fvs) <- rnDataDefn doc defn
; cusk <- data_decl_has_cusk tyvars' new_or_data no_rhs_kvs kind_sig
; let rn_info = DataDeclRn { tcdDataCusk = cusk
, tcdFVs = fvs }
; traceRn "rndata" (ppr tycon <+> ppr cusk <+> ppr no_rhs_kvs)
; return (DataDecl { tcdLName = tycon'
, tcdTyVars = tyvars'
, tcdFixity = fixity
, tcdDataDefn = defn'
, tcdDExt = rn_info }, fvs) } }
rnTyClDecl (ClassDecl { tcdCtxt = context, tcdLName = lcls,
tcdTyVars = tyvars, tcdFixity = fixity,
tcdFDs = fds, tcdSigs = sigs,
tcdMeths = mbinds, tcdATs = ats, tcdATDefs = at_defs,
tcdDocs = docs})
= do { lcls' <- lookupLocatedTopBndrRnN lcls
; let cls' = unLoc lcls'
kvs = []
; ((tyvars', context', fds', ats'), stuff_fvs)
<- bindHsQTyVars cls_doc Nothing kvs tyvars $ \ tyvars' _ -> do
{ (context', cxt_fvs) <- rnContext cls_doc context
; fds' <- rnFds fds
; (ats', fv_ats) <- rnATDecls cls' ats
; let fvs = cxt_fvs `plusFV`
fv_ats
; return ((tyvars', context', fds', ats'), fvs) }
; (at_defs', fv_at_defs) <- rnList (rnTyFamDefltDecl cls') at_defs
; let sig_rdr_names_w_locs =
[op | L _ (ClassOpSig _ False ops _) <- sigs
, op <- ops]
; checkDupRdrNamesN sig_rdr_names_w_locs
; (mbinds', sigs', meth_fvs)
<- rnMethodBinds True cls' (hsAllLTyVarNames tyvars') mbinds sigs
; let all_fvs = meth_fvs `plusFV` stuff_fvs `plusFV` fv_at_defs
; return (ClassDecl { tcdCtxt = context', tcdLName = lcls',
tcdTyVars = tyvars', tcdFixity = fixity,
tcdFDs = fds', tcdSigs = sigs',
tcdMeths = mbinds', tcdATs = ats', tcdATDefs = at_defs',
tcdDocs = docs, tcdCExt = all_fvs },
all_fvs ) }
where
cls_doc = ClassDeclCtx lcls
data_decl_has_cusk :: LHsQTyVars (GhcPass p) -> NewOrData -> Bool -> Maybe (LHsKind (GhcPass p')) -> RnM Bool
data_decl_has_cusk tyvars new_or_data no_rhs_kvs kind_sig = do
{
; unlifted_newtypes <- xoptM LangExt.UnliftedNewtypes
; let non_cusk_newtype
| NewType <- new_or_data =
unlifted_newtypes && isNothing kind_sig
| otherwise = False
; return $ hsTvbAllKinded tyvars && no_rhs_kvs && not non_cusk_newtype
}
rnTySyn :: HsDocContext -> LHsType GhcPs -> RnM (LHsType GhcRn, FreeVars)
rnTySyn doc rhs = rnLHsType doc rhs
rnDataDefn :: HsDocContext -> HsDataDefn GhcPs
-> RnM (HsDataDefn GhcRn, FreeVars)
rnDataDefn doc (HsDataDefn { dd_ND = new_or_data, dd_cType = cType
, dd_ctxt = context, dd_cons = condecls
, dd_kindSig = m_sig, dd_derivs = derivs })
= do { checkTc (h98_style || null (fromMaybeContext context))
(badGadtStupidTheta doc)
; (m_sig', sig_fvs) <- case m_sig of
Just sig -> first Just <$> rnLHsKind doc sig
Nothing -> return (Nothing, emptyFVs)
; (context', fvs1) <- rnContext doc context
; (derivs', fvs3) <- rn_derivs derivs
; let { zap_lcl_env | h98_style = \ thing -> thing
| otherwise = setLocalRdrEnv emptyLocalRdrEnv }
; (condecls', con_fvs) <- zap_lcl_env $ rnConDecls condecls
; let all_fvs = fvs1 `plusFV` fvs3 `plusFV`
con_fvs `plusFV` sig_fvs
; return ( HsDataDefn { dd_ext = noAnn
, dd_ND = new_or_data, dd_cType = cType
, dd_ctxt = context', dd_kindSig = m_sig'
, dd_cons = condecls'
, dd_derivs = derivs' }
, all_fvs )
}
where
h98_style = case condecls of
(L _ (ConDeclGADT {})) : _ -> False
_ -> True
rn_derivs ds
= do { deriv_strats_ok <- xoptM LangExt.DerivingStrategies
; failIfTc (lengthExceeds ds 1 && not deriv_strats_ok)
multipleDerivClausesErr
; (ds', fvs) <- mapFvRn (rnLHsDerivingClause doc) ds
; return (ds', fvs) }
warnNoDerivStrat :: Maybe (LDerivStrategy GhcRn)
-> SrcSpan
-> RnM ()
warnNoDerivStrat mds loc
= do { dyn_flags <- getDynFlags
; when (wopt Opt_WarnMissingDerivingStrategies dyn_flags) $
case mds of
Nothing -> addWarnAt
(Reason Opt_WarnMissingDerivingStrategies)
loc
(if xopt LangExt.DerivingStrategies dyn_flags
then no_strat_warning
else no_strat_warning $+$ deriv_strat_nenabled
)
_ -> pure ()
}
where
no_strat_warning :: SDoc
no_strat_warning = text "No deriving strategy specified. Did you want stock"
<> text ", newtype, or anyclass?"
deriv_strat_nenabled :: SDoc
deriv_strat_nenabled = text "Use DerivingStrategies to specify a strategy."
rnLHsDerivingClause :: HsDocContext -> LHsDerivingClause GhcPs
-> RnM (LHsDerivingClause GhcRn, FreeVars)
rnLHsDerivingClause doc
(L loc (HsDerivingClause
{ deriv_clause_ext = noExtField
, deriv_clause_strategy = dcs
, deriv_clause_tys = dct }))
= do { (dcs', dct', fvs)
<- rnLDerivStrategy doc dcs $ rn_deriv_clause_tys dct
; warnNoDerivStrat dcs' loc
; pure ( L loc (HsDerivingClause { deriv_clause_ext = noExtField
, deriv_clause_strategy = dcs'
, deriv_clause_tys = dct' })
, fvs ) }
where
rn_deriv_clause_tys :: LDerivClauseTys GhcPs
-> RnM (LDerivClauseTys GhcRn, FreeVars)
rn_deriv_clause_tys (L l dct) = case dct of
DctSingle x ty -> do
(ty', fvs) <- rn_clause_pred ty
pure (L l (DctSingle x ty'), fvs)
DctMulti x tys -> do
(tys', fvs) <- mapFvRn rn_clause_pred tys
pure (L l (DctMulti x tys'), fvs)
rn_clause_pred :: LHsSigType GhcPs -> RnM (LHsSigType GhcRn, FreeVars)
rn_clause_pred pred_ty = do
let inf_err = Just (text "Inferred type variables are not allowed")
checkInferredVars doc inf_err pred_ty
ret@(pred_ty', _) <- rnHsSigType doc TypeLevel pred_ty
addNoNestedForallsContextsErr doc (text "Derived class type")
(getLHsInstDeclHead pred_ty')
pure ret
rnLDerivStrategy :: forall a.
HsDocContext
-> Maybe (LDerivStrategy GhcPs)
-> RnM (a, FreeVars)
-> RnM (Maybe (LDerivStrategy GhcRn), a, FreeVars)
rnLDerivStrategy doc mds thing_inside
= case mds of
Nothing -> boring_case Nothing
Just (L loc ds) ->
setSrcSpan loc $ do
(ds', thing, fvs) <- rn_deriv_strat ds
pure (Just (L loc ds'), thing, fvs)
where
rn_deriv_strat :: DerivStrategy GhcPs
-> RnM (DerivStrategy GhcRn, a, FreeVars)
rn_deriv_strat ds = do
let extNeeded :: LangExt.Extension
extNeeded
| ViaStrategy{} <- ds
= LangExt.DerivingVia
| otherwise
= LangExt.DerivingStrategies
unlessXOptM extNeeded $
failWith $ illegalDerivStrategyErr ds
case ds of
StockStrategy _ -> boring_case (StockStrategy noExtField)
AnyclassStrategy _ -> boring_case (AnyclassStrategy noExtField)
NewtypeStrategy _ -> boring_case (NewtypeStrategy noExtField)
ViaStrategy (XViaStrategyPs _ via_ty) ->
do checkInferredVars doc inf_err via_ty
(via_ty', fvs1) <- rnHsSigType doc TypeLevel via_ty
let HsSig { sig_bndrs = via_outer_bndrs
, sig_body = via_body } = unLoc via_ty'
via_tvs = hsOuterTyVarNames via_outer_bndrs
addNoNestedForallsContextsErr doc
(quotes (text "via") <+> text "type") via_body
(thing, fvs2) <- bindLocalNamesFV via_tvs thing_inside
pure (ViaStrategy via_ty', thing, fvs1 `plusFV` fvs2)
inf_err = Just (text "Inferred type variables are not allowed")
boring_case :: ds -> RnM (ds, a, FreeVars)
boring_case ds = do
(thing, fvs) <- thing_inside
pure (ds, thing, fvs)
badGadtStupidTheta :: HsDocContext -> SDoc
badGadtStupidTheta _
= vcat [text "No context is allowed on a GADT-style data declaration",
text "(You can put a context on each constructor, though.)"]
illegalDerivStrategyErr :: DerivStrategy GhcPs -> SDoc
illegalDerivStrategyErr ds
= vcat [ text "Illegal deriving strategy" <> colon <+> derivStrategyName ds
, text enableStrategy ]
where
enableStrategy :: String
enableStrategy
| ViaStrategy{} <- ds
= "Use DerivingVia to enable this extension"
| otherwise
= "Use DerivingStrategies to enable this extension"
multipleDerivClausesErr :: SDoc
multipleDerivClausesErr
= vcat [ text "Illegal use of multiple, consecutive deriving clauses"
, text "Use DerivingStrategies to allow this" ]
rnFamDecl :: Maybe Name
-> FamilyDecl GhcPs
-> RnM (FamilyDecl GhcRn, FreeVars)
rnFamDecl mb_cls (FamilyDecl { fdLName = tycon, fdTyVars = tyvars
, fdTopLevel = toplevel
, fdFixity = fixity
, fdInfo = info, fdResultSig = res_sig
, fdInjectivityAnn = injectivity })
= do { tycon' <- lookupLocatedTopBndrRnN tycon
; ((tyvars', res_sig', injectivity'), fv1) <-
bindHsQTyVars doc mb_cls kvs tyvars $ \ tyvars' _ ->
do { let rn_sig = rnFamResultSig doc
; (res_sig', fv_kind) <- wrapLocFstM rn_sig res_sig
; injectivity' <- traverse (rnInjectivityAnn tyvars' res_sig')
injectivity
; return ( (tyvars', res_sig', injectivity') , fv_kind ) }
; (info', fv2) <- rn_info info
; return (FamilyDecl { fdExt = noAnn
, fdLName = tycon', fdTyVars = tyvars'
, fdTopLevel = toplevel
, fdFixity = fixity
, fdInfo = info', fdResultSig = res_sig'
, fdInjectivityAnn = injectivity' }
, fv1 `plusFV` fv2) }
where
doc = TyFamilyCtx tycon
kvs = extractRdrKindSigVars res_sig
rn_info :: FamilyInfo GhcPs -> RnM (FamilyInfo GhcRn, FreeVars)
rn_info (ClosedTypeFamily (Just eqns))
= do { (eqns', fvs)
<- rnList (rnTyFamInstEqn (NonAssocTyFamEqn ClosedTyFam)) eqns
; return (ClosedTypeFamily (Just eqns'), fvs) }
rn_info (ClosedTypeFamily Nothing)
= return (ClosedTypeFamily Nothing, emptyFVs)
rn_info OpenTypeFamily = return (OpenTypeFamily, emptyFVs)
rn_info DataFamily = return (DataFamily, emptyFVs)
rnFamResultSig :: HsDocContext
-> FamilyResultSig GhcPs
-> RnM (FamilyResultSig GhcRn, FreeVars)
rnFamResultSig _ (NoSig _)
= return (NoSig noExtField, emptyFVs)
rnFamResultSig doc (KindSig _ kind)
= do { (rndKind, ftvs) <- rnLHsKind doc kind
; return (KindSig noExtField rndKind, ftvs) }
rnFamResultSig doc (TyVarSig _ tvbndr)
= do {
rdr_env <- getLocalRdrEnv
; let resName = hsLTyVarName tvbndr
; when (resName `elemLocalRdrEnv` rdr_env) $
addErrAt (getLocA tvbndr) $
(hsep [ text "Type variable", quotes (ppr resName) <> comma
, text "naming a type family result,"
] $$
text "shadows an already bound type variable")
; bindLHsTyVarBndr doc Nothing
tvbndr $ \ tvbndr' ->
return (TyVarSig noExtField tvbndr', unitFV (hsLTyVarName tvbndr')) }
rnInjectivityAnn :: LHsQTyVars GhcRn
-> LFamilyResultSig GhcRn
-> LInjectivityAnn GhcPs
-> RnM (LInjectivityAnn GhcRn)
rnInjectivityAnn tvBndrs (L _ (TyVarSig _ resTv))
(L srcSpan (InjectivityAnn x injFrom injTo))
= do
{ (injDecl'@(L _ (InjectivityAnn _ injFrom' injTo')), noRnErrors)
<- askNoErrs $
bindLocalNames [hsLTyVarName resTv] $
do { injFrom' <- rnLTyVar injFrom
; injTo' <- mapM rnLTyVar injTo
; return $ L srcSpan (InjectivityAnn x injFrom' injTo') }
; let tvNames = Set.fromList $ hsAllLTyVarNames tvBndrs
resName = hsLTyVarName resTv
lhsValid = EQ == (stableNameCmp resName (unLoc injFrom'))
rhsValid = Set.fromList (map unLoc injTo') `Set.difference` tvNames
; when (noRnErrors && not lhsValid) $
addErrAt (getLocA injFrom)
( vcat [ text $ "Incorrect type variable on the LHS of "
++ "injectivity condition"
, nest 5
( vcat [ text "Expected :" <+> ppr resName
, text "Actual :" <+> ppr injFrom ])])
; when (noRnErrors && not (Set.null rhsValid)) $
do { let errorVars = Set.toList rhsValid
; addErrAt srcSpan $ ( hsep
[ text "Unknown type variable" <> plural errorVars
, text "on the RHS of injectivity condition:"
, interpp'SP errorVars ] ) }
; return injDecl' }
rnInjectivityAnn _ _ (L srcSpan (InjectivityAnn x injFrom injTo)) =
setSrcSpan srcSpan $ do
(injDecl', _) <- askNoErrs $ do
injFrom' <- rnLTyVar injFrom
injTo' <- mapM rnLTyVar injTo
return $ L srcSpan (InjectivityAnn x injFrom' injTo')
return $ injDecl'
rnConDecls :: [LConDecl GhcPs] -> RnM ([LConDecl GhcRn], FreeVars)
rnConDecls = mapFvRn (wrapLocFstMA rnConDecl)
rnConDecl :: ConDecl GhcPs -> RnM (ConDecl GhcRn, FreeVars)
rnConDecl decl@(ConDeclH98 { con_name = name, con_ex_tvs = ex_tvs
, con_mb_cxt = mcxt, con_args = args
, con_doc = mb_doc, con_forall = forall })
= do { _ <- addLocMA checkConName name
; new_name <- lookupLocatedTopBndrRnN name
; let ctxt = ConDeclCtx [new_name]
; bindLHsTyVarBndrs ctxt WarnUnusedForalls
Nothing ex_tvs $ \ new_ex_tvs ->
do { (new_context, fvs1) <- rnMbContext ctxt mcxt
; (new_args, fvs2) <- rnConDeclH98Details (unLoc new_name) ctxt args
; let all_fvs = fvs1 `plusFV` fvs2
; traceRn "rnConDecl (ConDeclH98)" (ppr name <+> vcat
[ text "ex_tvs:" <+> ppr ex_tvs
, text "new_ex_dqtvs':" <+> ppr new_ex_tvs ])
; return (decl { con_ext = noAnn
, con_name = new_name, con_ex_tvs = new_ex_tvs
, con_mb_cxt = new_context, con_args = new_args
, con_doc = mb_doc
, con_forall = forall },
all_fvs) }}
rnConDecl (ConDeclGADT { con_names = names
, con_bndrs = L l outer_bndrs
, con_mb_cxt = mcxt
, con_g_args = args
, con_res_ty = res_ty
, con_doc = mb_doc })
= do { mapM_ (addLocMA checkConName) names
; new_names <- mapM lookupLocatedTopBndrRnN names
; let
implicit_bndrs =
extractHsOuterTvBndrs outer_bndrs $
extractHsTysRdrTyVars (hsConDeclTheta mcxt) $
extractConDeclGADTDetailsTyVars args $
extractHsTysRdrTyVars [res_ty] []
; let ctxt = ConDeclCtx new_names
; bindHsOuterTyVarBndrs ctxt Nothing implicit_bndrs outer_bndrs $ \outer_bndrs' ->
do { (new_cxt, fvs1) <- rnMbContext ctxt mcxt
; (new_args, fvs2) <- rnConDeclGADTDetails (unLoc (head new_names)) ctxt args
; (new_res_ty, fvs3) <- rnLHsType ctxt res_ty
; addNoNestedForallsContextsErr ctxt
(text "GADT constructor type signature") new_res_ty
; let all_fvs = fvs1 `plusFV` fvs2 `plusFV` fvs3
; traceRn "rnConDecl (ConDeclGADT)"
(ppr names $$ ppr outer_bndrs')
; return (ConDeclGADT { con_g_ext = noAnn, con_names = new_names
, con_bndrs = L l outer_bndrs', con_mb_cxt = new_cxt
, con_g_args = new_args, con_res_ty = new_res_ty
, con_doc = mb_doc },
all_fvs) } }
rnMbContext :: HsDocContext -> Maybe (LHsContext GhcPs)
-> RnM (Maybe (LHsContext GhcRn), FreeVars)
rnMbContext _ Nothing = return (Nothing, emptyFVs)
rnMbContext doc cxt = do { (ctx',fvs) <- rnContext doc cxt
; return (ctx',fvs) }
rnConDeclH98Details ::
Name
-> HsDocContext
-> HsConDeclH98Details GhcPs
-> RnM (HsConDeclH98Details GhcRn, FreeVars)
rnConDeclH98Details _ doc (PrefixCon _ tys)
= do { (new_tys, fvs) <- mapFvRn (rnScaledLHsType doc) tys
; return (PrefixCon noTypeArgs new_tys, fvs) }
rnConDeclH98Details _ doc (InfixCon ty1 ty2)
= do { (new_ty1, fvs1) <- rnScaledLHsType doc ty1
; (new_ty2, fvs2) <- rnScaledLHsType doc ty2
; return (InfixCon new_ty1 new_ty2, fvs1 `plusFV` fvs2) }
rnConDeclH98Details con doc (RecCon flds)
= do { (new_flds, fvs) <- rnRecConDeclFields con doc flds
; return (RecCon new_flds, fvs) }
rnConDeclGADTDetails ::
Name
-> HsDocContext
-> HsConDeclGADTDetails GhcPs
-> RnM (HsConDeclGADTDetails GhcRn, FreeVars)
rnConDeclGADTDetails _ doc (PrefixConGADT tys)
= do { (new_tys, fvs) <- mapFvRn (rnScaledLHsType doc) tys
; return (PrefixConGADT new_tys, fvs) }
rnConDeclGADTDetails con doc (RecConGADT flds)
= do { (new_flds, fvs) <- rnRecConDeclFields con doc flds
; return (RecConGADT new_flds, fvs) }
rnRecConDeclFields ::
Name
-> HsDocContext
-> LocatedL [LConDeclField GhcPs]
-> RnM (LocatedL [LConDeclField GhcRn], FreeVars)
rnRecConDeclFields con doc (L l fields)
= do { fls <- lookupConstructorFields con
; (new_fields, fvs) <- rnConDeclFields doc fls fields
; pure (L l new_fields, fvs) }
extendPatSynEnv :: DuplicateRecordFields -> FieldSelectors -> HsValBinds GhcPs -> MiniFixityEnv
-> ([Name] -> TcRnIf TcGblEnv TcLclEnv a) -> TcM a
extendPatSynEnv dup_fields_ok has_sel val_decls local_fix_env thing = do {
names_with_fls <- new_ps val_decls
; let pat_syn_bndrs = concat [ name: map flSelector fields
| (name, fields) <- names_with_fls ]
; let avails = map avail (map fst names_with_fls)
++ map availField (concatMap snd names_with_fls)
; (gbl_env, lcl_env) <- extendGlobalRdrEnvRn avails local_fix_env
; let field_env' = extendNameEnvList (tcg_field_env gbl_env) names_with_fls
final_gbl_env = gbl_env { tcg_field_env = field_env' }
; setEnvs (final_gbl_env, lcl_env) (thing pat_syn_bndrs) }
where
new_ps :: HsValBinds GhcPs -> TcM [(Name, [FieldLabel])]
new_ps (ValBinds _ binds _) = foldrM new_ps' [] binds
new_ps _ = panic "new_ps"
new_ps' :: LHsBindLR GhcPs GhcPs
-> [(Name, [FieldLabel])]
-> TcM [(Name, [FieldLabel])]
new_ps' bind names
| (L bind_loc (PatSynBind _ (PSB { psb_id = L _ n
, psb_args = RecCon as }))) <- bind
= do
bnd_name <- newTopSrcBinder (L (l2l bind_loc) n)
let field_occs = map ((\ f -> L (getLocA (rdrNameFieldOcc f)) f) . recordPatSynField) as
flds <- mapM (newRecordSelector dup_fields_ok has_sel [bnd_name]) field_occs
return ((bnd_name, flds): names)
| L bind_loc (PatSynBind _ (PSB { psb_id = L _ n})) <- bind
= do
bnd_name <- newTopSrcBinder (L (la2na bind_loc) n)
return ((bnd_name, []): names)
| otherwise
= return names
rnFds :: [LHsFunDep GhcPs] -> RnM [LHsFunDep GhcRn]
rnFds fds
= mapM (wrapLocMA rn_fds) fds
where
rn_fds :: FunDep GhcPs -> RnM (FunDep GhcRn)
rn_fds (FunDep x tys1 tys2)
= do { tys1' <- rnHsTyVars tys1
; tys2' <- rnHsTyVars tys2
; return (FunDep x tys1' tys2') }
rnHsTyVars :: [LocatedN RdrName] -> RnM [LocatedN Name]
rnHsTyVars tvs = mapM rnHsTyVar tvs
rnHsTyVar :: LocatedN RdrName -> RnM (LocatedN Name)
rnHsTyVar (L l tyvar) = do
tyvar' <- lookupOccRn tyvar
return (L l tyvar')
findSplice :: [LHsDecl GhcPs]
-> RnM (HsGroup GhcPs, Maybe (SpliceDecl GhcPs, [LHsDecl GhcPs]))
findSplice ds = addl emptyRdrGroup ds
addl :: HsGroup GhcPs -> [LHsDecl GhcPs]
-> RnM (HsGroup GhcPs, Maybe (SpliceDecl GhcPs, [LHsDecl GhcPs]))
addl gp [] = return (gp, Nothing)
addl gp (L l d : ds) = add gp l d ds
add :: HsGroup GhcPs -> SrcSpanAnnA -> HsDecl GhcPs -> [LHsDecl GhcPs]
-> RnM (HsGroup GhcPs, Maybe (SpliceDecl GhcPs, [LHsDecl GhcPs]))
add gp _ (SpliceD _ (SpliceDecl _ (L _ qq@HsQuasiQuote{}) _)) ds
= do { (ds', _) <- rnTopSpliceDecls qq
; addl gp (ds' ++ ds)
}
add gp loc (SpliceD _ splice@(SpliceDecl _ _ flag)) ds
= do {
case flag of
ExplicitSplice -> return ()
ImplicitSplice -> do { th_on <- xoptM LangExt.TemplateHaskell
; unless th_on $ setSrcSpan (locA loc) $
failWith badImplicitSplice }
; return (gp, Just (splice, ds)) }
where
badImplicitSplice = text "Parse error: module header, import declaration"
$$ text "or top-level declaration expected."
add gp@(HsGroup {hs_tyclds = ts}) l (TyClD _ d) ds
= addl (gp { hs_tyclds = add_tycld (L l d) ts }) ds
add gp@(HsGroup {hs_fixds = ts}) l (SigD _ (FixSig _ f)) ds
= addl (gp {hs_fixds = L l f : ts}) ds
add gp@(HsGroup {hs_tyclds = ts}) l (KindSigD _ s) ds
= addl (gp {hs_tyclds = add_kisig (L l s) ts}) ds
add gp@(HsGroup {hs_valds = ts}) l (SigD _ d) ds
= addl (gp {hs_valds = add_sig (L l d) ts}) ds
add gp@(HsGroup {hs_valds = ts}) l (ValD _ d) ds
= addl (gp { hs_valds = add_bind (L l d) ts }) ds
add gp@(HsGroup {hs_tyclds = ts}) l (RoleAnnotD _ d) ds
= addl (gp { hs_tyclds = add_role_annot (L l d) ts }) ds
add gp@(HsGroup {hs_tyclds = ts}) l (InstD _ d) ds
= addl (gp { hs_tyclds = add_instd (L l d) ts }) ds
add gp@(HsGroup {hs_derivds = ts}) l (DerivD _ d) ds
= addl (gp { hs_derivds = L l d : ts }) ds
add gp@(HsGroup {hs_defds = ts}) l (DefD _ d) ds
= addl (gp { hs_defds = L l d : ts }) ds
add gp@(HsGroup {hs_fords = ts}) l (ForD _ d) ds
= addl (gp { hs_fords = L l d : ts }) ds
add gp@(HsGroup {hs_warnds = ts}) l (WarningD _ d) ds
= addl (gp { hs_warnds = L l d : ts }) ds
add gp@(HsGroup {hs_annds = ts}) l (AnnD _ d) ds
= addl (gp { hs_annds = L l d : ts }) ds
add gp@(HsGroup {hs_ruleds = ts}) l (RuleD _ d) ds
= addl (gp { hs_ruleds = L l d : ts }) ds
add gp l (DocD _ d) ds
= addl (gp { hs_docs = (L l d) : (hs_docs gp) }) ds
add_tycld :: LTyClDecl (GhcPass p) -> [TyClGroup (GhcPass p)]
-> [TyClGroup (GhcPass p)]
add_tycld d [] = [TyClGroup { group_ext = noExtField
, group_tyclds = [d]
, group_kisigs = []
, group_roles = []
, group_instds = []
}
]
add_tycld d (ds@(TyClGroup { group_tyclds = tyclds }):dss)
= ds { group_tyclds = d : tyclds } : dss
add_instd :: LInstDecl (GhcPass p) -> [TyClGroup (GhcPass p)]
-> [TyClGroup (GhcPass p)]
add_instd d [] = [TyClGroup { group_ext = noExtField
, group_tyclds = []
, group_kisigs = []
, group_roles = []
, group_instds = [d]
}
]
add_instd d (ds@(TyClGroup { group_instds = instds }):dss)
= ds { group_instds = d : instds } : dss
add_role_annot :: LRoleAnnotDecl (GhcPass p) -> [TyClGroup (GhcPass p)]
-> [TyClGroup (GhcPass p)]
add_role_annot d [] = [TyClGroup { group_ext = noExtField
, group_tyclds = []
, group_kisigs = []
, group_roles = [d]
, group_instds = []
}
]
add_role_annot d (tycls@(TyClGroup { group_roles = roles }) : rest)
= tycls { group_roles = d : roles } : rest
add_kisig :: LStandaloneKindSig (GhcPass p)
-> [TyClGroup (GhcPass p)] -> [TyClGroup (GhcPass p)]
add_kisig d [] = [TyClGroup { group_ext = noExtField
, group_tyclds = []
, group_kisigs = [d]
, group_roles = []
, group_instds = []
}
]
add_kisig d (tycls@(TyClGroup { group_kisigs = kisigs }) : rest)
= tycls { group_kisigs = d : kisigs } : rest
add_bind :: LHsBind a -> HsValBinds a -> HsValBinds a
add_bind b (ValBinds x bs sigs) = ValBinds x (bs `snocBag` b) sigs
add_bind _ (XValBindsLR {}) = panic "GHC.Rename.Module.add_bind"
add_sig :: LSig (GhcPass a) -> HsValBinds (GhcPass a) -> HsValBinds (GhcPass a)
add_sig s (ValBinds x bs sigs) = ValBinds x bs (s:sigs)
add_sig _ (XValBindsLR {}) = panic "GHC.Rename.Module.add_sig"