{-# LANGUAGE CPP #-}
{-# LANGUAGE TypeFamilies #-}
module TcForeign
( tcForeignImports
, tcForeignExports
, isForeignImport, isForeignExport
, tcFImport, tcFExport
, tcForeignImports'
, tcCheckFIType, checkCTarget, checkForeignArgs, checkForeignRes
, normaliseFfiType
, nonIOok, mustBeIO
, checkSafe, noCheckSafe
, tcForeignExports'
, tcCheckFEType
) where
#include "HsVersions.h"
import GhcPrelude
import HsSyn
import TcRnMonad
import TcHsType
import TcExpr
import TcEnv
import FamInst
import FamInstEnv
import Coercion
import Type
import ForeignCall
import ErrUtils
import Id
import Name
import RdrName
import DataCon
import TyCon
import TcType
import PrelNames
import DynFlags
import Outputable
import Platform
import SrcLoc
import Bag
import Hooks
import qualified GHC.LanguageExtensions as LangExt
import Control.Monad
import Data.Maybe
isForeignImport :: LForeignDecl name -> Bool
isForeignImport :: LForeignDecl name -> Bool
isForeignImport (L _ (ForeignImport {})) = Bool
True
isForeignImport _ = Bool
False
isForeignExport :: LForeignDecl name -> Bool
isForeignExport :: LForeignDecl name -> Bool
isForeignExport (L _ (ForeignExport {})) = Bool
True
isForeignExport _ = Bool
False
normaliseFfiType :: Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
normaliseFfiType :: Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
normaliseFfiType ty :: Type
ty
= do FamInstEnvs
fam_envs <- TcM FamInstEnvs
tcGetFamInstEnvs
FamInstEnvs -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
normaliseFfiType' FamInstEnvs
fam_envs Type
ty
normaliseFfiType' :: FamInstEnvs -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
normaliseFfiType' :: FamInstEnvs -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
normaliseFfiType' env :: FamInstEnvs
env ty0 :: Type
ty0 = RecTcChecker -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
go RecTcChecker
initRecTc Type
ty0
where
go :: RecTcChecker -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
go :: RecTcChecker -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
go rec_nts :: RecTcChecker
rec_nts ty :: Type
ty
| Just ty' :: Type
ty' <- Type -> Maybe Type
tcView Type
ty
= RecTcChecker -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
go RecTcChecker
rec_nts Type
ty'
| Just (tc :: TyCon
tc, tys :: [Type]
tys) <- HasDebugCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
splitTyConApp_maybe Type
ty
= RecTcChecker
-> TyCon -> [Type] -> TcM (Coercion, Type, Bag GlobalRdrElt)
go_tc_app RecTcChecker
rec_nts TyCon
tc [Type]
tys
| (bndrs :: [TyCoVarBinder]
bndrs, inner_ty :: Type
inner_ty) <- Type -> ([TyCoVarBinder], Type)
splitForAllVarBndrs Type
ty
, Bool -> Bool
not ([TyCoVarBinder] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [TyCoVarBinder]
bndrs)
= do (coi :: Coercion
coi, nty1 :: Type
nty1, gres1 :: Bag GlobalRdrElt
gres1) <- RecTcChecker -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
go RecTcChecker
rec_nts Type
inner_ty
(Coercion, Type, Bag GlobalRdrElt)
-> TcM (Coercion, Type, Bag GlobalRdrElt)
forall (m :: * -> *) a. Monad m => a -> m a
return ( [TyCoVar] -> Coercion -> Coercion
mkHomoForAllCos ([TyCoVarBinder] -> [TyCoVar]
forall tv argf. [VarBndr tv argf] -> [tv]
binderVars [TyCoVarBinder]
bndrs) Coercion
coi
, [TyCoVarBinder] -> Type -> Type
mkForAllTys [TyCoVarBinder]
bndrs Type
nty1, Bag GlobalRdrElt
gres1 )
| Bool
otherwise
= (Coercion, Type, Bag GlobalRdrElt)
-> TcM (Coercion, Type, Bag GlobalRdrElt)
forall (m :: * -> *) a. Monad m => a -> m a
return (Type -> Coercion
mkRepReflCo Type
ty, Type
ty, Bag GlobalRdrElt
forall a. Bag a
emptyBag)
go_tc_app :: RecTcChecker -> TyCon -> [Type]
-> TcM (Coercion, Type, Bag GlobalRdrElt)
go_tc_app :: RecTcChecker
-> TyCon -> [Type] -> TcM (Coercion, Type, Bag GlobalRdrElt)
go_tc_app rec_nts :: RecTcChecker
rec_nts tc :: TyCon
tc tys :: [Type]
tys
| Unique
tc_key Unique -> [Unique] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Unique
ioTyConKey, Unique
funPtrTyConKey, Unique
funTyConKey]
= TcM (Coercion, Type, Bag GlobalRdrElt)
children_only
| TyCon -> Bool
isNewTyCon TyCon
tc
, Just rec_nts' :: RecTcChecker
rec_nts' <- RecTcChecker -> TyCon -> Maybe RecTcChecker
checkRecTc RecTcChecker
rec_nts TyCon
tc
= do { GlobalRdrEnv
rdr_env <- TcRn GlobalRdrEnv
getGlobalRdrEnv
; case GlobalRdrEnv -> TyCon -> Maybe GlobalRdrElt
checkNewtypeFFI GlobalRdrEnv
rdr_env TyCon
tc of
Nothing -> TcM (Coercion, Type, Bag GlobalRdrElt)
nothing
Just gre :: GlobalRdrElt
gre -> do { (co' :: Coercion
co', ty' :: Type
ty', gres :: Bag GlobalRdrElt
gres) <- RecTcChecker -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
go RecTcChecker
rec_nts' Type
nt_rhs
; (Coercion, Type, Bag GlobalRdrElt)
-> TcM (Coercion, Type, Bag GlobalRdrElt)
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion -> Coercion -> Coercion
mkTransCo Coercion
nt_co Coercion
co', Type
ty', GlobalRdrElt
gre GlobalRdrElt -> Bag GlobalRdrElt -> Bag GlobalRdrElt
forall a. a -> Bag a -> Bag a
`consBag` Bag GlobalRdrElt
gres) } }
| TyCon -> Bool
isFamilyTyCon TyCon
tc
, (co :: Coercion
co, ty :: Type
ty) <- FamInstEnvs -> Role -> TyCon -> [Type] -> (Coercion, Type)
normaliseTcApp FamInstEnvs
env Role
Representational TyCon
tc [Type]
tys
, Bool -> Bool
not (Coercion -> Bool
isReflexiveCo Coercion
co)
= do (co' :: Coercion
co', ty' :: Type
ty', gres :: Bag GlobalRdrElt
gres) <- RecTcChecker -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
go RecTcChecker
rec_nts Type
ty
(Coercion, Type, Bag GlobalRdrElt)
-> TcM (Coercion, Type, Bag GlobalRdrElt)
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion -> Coercion -> Coercion
mkTransCo Coercion
co Coercion
co', Type
ty', Bag GlobalRdrElt
gres)
| Bool
otherwise
= TcM (Coercion, Type, Bag GlobalRdrElt)
nothing
where
tc_key :: Unique
tc_key = TyCon -> Unique
forall a. Uniquable a => a -> Unique
getUnique TyCon
tc
children_only :: TcM (Coercion, Type, Bag GlobalRdrElt)
children_only
= do [(Coercion, Type, Bag GlobalRdrElt)]
xs <- (Type -> TcM (Coercion, Type, Bag GlobalRdrElt))
-> [Type]
-> IOEnv
(Env TcGblEnv TcLclEnv) [(Coercion, Type, Bag GlobalRdrElt)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (RecTcChecker -> Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
go RecTcChecker
rec_nts) [Type]
tys
let (cos :: [Coercion]
cos, tys' :: [Type]
tys', gres :: [Bag GlobalRdrElt]
gres) = [(Coercion, Type, Bag GlobalRdrElt)]
-> ([Coercion], [Type], [Bag GlobalRdrElt])
forall a b c. [(a, b, c)] -> ([a], [b], [c])
unzip3 [(Coercion, Type, Bag GlobalRdrElt)]
xs
cos' :: [Coercion]
cos' = (Role -> Role -> Coercion -> Coercion)
-> [Role] -> [Role] -> [Coercion] -> [Coercion]
forall a b c d. (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3 Role -> Role -> Coercion -> Coercion
downgradeRole (TyCon -> [Role]
tyConRoles TyCon
tc)
(Role -> [Role]
forall a. a -> [a]
repeat Role
Representational) [Coercion]
cos
(Coercion, Type, Bag GlobalRdrElt)
-> TcM (Coercion, Type, Bag GlobalRdrElt)
forall (m :: * -> *) a. Monad m => a -> m a
return ( HasDebugCallStack => Role -> TyCon -> [Coercion] -> Coercion
Role -> TyCon -> [Coercion] -> Coercion
mkTyConAppCo Role
Representational TyCon
tc [Coercion]
cos'
, TyCon -> [Type] -> Type
mkTyConApp TyCon
tc [Type]
tys', [Bag GlobalRdrElt] -> Bag GlobalRdrElt
forall a. [Bag a] -> Bag a
unionManyBags [Bag GlobalRdrElt]
gres)
nt_co :: Coercion
nt_co = Role -> CoAxiom Unbranched -> [Type] -> [Coercion] -> Coercion
mkUnbranchedAxInstCo Role
Representational (TyCon -> CoAxiom Unbranched
newTyConCo TyCon
tc) [Type]
tys []
nt_rhs :: Type
nt_rhs = TyCon -> [Type] -> Type
newTyConInstRhs TyCon
tc [Type]
tys
ty :: Type
ty = TyCon -> [Type] -> Type
mkTyConApp TyCon
tc [Type]
tys
nothing :: TcM (Coercion, Type, Bag GlobalRdrElt)
nothing = (Coercion, Type, Bag GlobalRdrElt)
-> TcM (Coercion, Type, Bag GlobalRdrElt)
forall (m :: * -> *) a. Monad m => a -> m a
return (Type -> Coercion
mkRepReflCo Type
ty, Type
ty, Bag GlobalRdrElt
forall a. Bag a
emptyBag)
checkNewtypeFFI :: GlobalRdrEnv -> TyCon -> Maybe GlobalRdrElt
checkNewtypeFFI :: GlobalRdrEnv -> TyCon -> Maybe GlobalRdrElt
checkNewtypeFFI rdr_env :: GlobalRdrEnv
rdr_env tc :: TyCon
tc
| Just con :: DataCon
con <- TyCon -> Maybe DataCon
tyConSingleDataCon_maybe TyCon
tc
, Just gre :: GlobalRdrElt
gre <- GlobalRdrEnv -> Name -> Maybe GlobalRdrElt
lookupGRE_Name GlobalRdrEnv
rdr_env (DataCon -> Name
dataConName DataCon
con)
= GlobalRdrElt -> Maybe GlobalRdrElt
forall a. a -> Maybe a
Just GlobalRdrElt
gre
| Bool
otherwise
= Maybe GlobalRdrElt
forall a. Maybe a
Nothing
tcForeignImports :: [LForeignDecl GhcRn]
-> TcM ([Id], [LForeignDecl GhcTc], Bag GlobalRdrElt)
tcForeignImports :: [LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt)
tcForeignImports decls :: [LForeignDecl GhcRn]
decls
= (Hooks
-> Maybe
([LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt)))
-> ([LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> IOEnv
(Env TcGblEnv TcLclEnv)
([LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt))
forall (f :: * -> *) a.
(Functor f, HasDynFlags f) =>
(Hooks -> Maybe a) -> a -> f a
getHooked Hooks
-> Maybe
([LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt))
tcForeignImportsHook [LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt)
tcForeignImports' IOEnv
(Env TcGblEnv TcLclEnv)
([LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> (([LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (([LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> [LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt)
forall a b. (a -> b) -> a -> b
$ [LForeignDecl GhcRn]
decls)
tcForeignImports' :: [LForeignDecl GhcRn]
-> TcM ([Id], [LForeignDecl GhcTc], Bag GlobalRdrElt)
tcForeignImports' :: [LForeignDecl GhcRn]
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt)
tcForeignImports' decls :: [LForeignDecl GhcRn]
decls
= do { (ids :: [TyCoVar]
ids, decls :: [LForeignDecl GhcTc]
decls, gres :: [Bag GlobalRdrElt]
gres) <- (LForeignDecl GhcRn
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt))
-> [LForeignDecl GhcRn]
-> IOEnv
(Env TcGblEnv TcLclEnv)
([TyCoVar], [LForeignDecl GhcTc], [Bag GlobalRdrElt])
forall (m :: * -> *) a b c d.
Monad m =>
(a -> m (b, c, d)) -> [a] -> m ([b], [c], [d])
mapAndUnzip3M LForeignDecl GhcRn
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
tcFImport ([LForeignDecl GhcRn]
-> IOEnv
(Env TcGblEnv TcLclEnv)
([TyCoVar], [LForeignDecl GhcTc], [Bag GlobalRdrElt]))
-> [LForeignDecl GhcRn]
-> IOEnv
(Env TcGblEnv TcLclEnv)
([TyCoVar], [LForeignDecl GhcTc], [Bag GlobalRdrElt])
forall a b. (a -> b) -> a -> b
$
(LForeignDecl GhcRn -> Bool)
-> [LForeignDecl GhcRn] -> [LForeignDecl GhcRn]
forall a. (a -> Bool) -> [a] -> [a]
filter LForeignDecl GhcRn -> Bool
forall name. LForeignDecl name -> Bool
isForeignImport [LForeignDecl GhcRn]
decls
; ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt)
-> TcM ([TyCoVar], [LForeignDecl GhcTc], Bag GlobalRdrElt)
forall (m :: * -> *) a. Monad m => a -> m a
return ([TyCoVar]
ids, [LForeignDecl GhcTc]
decls, [Bag GlobalRdrElt] -> Bag GlobalRdrElt
forall a. [Bag a] -> Bag a
unionManyBags [Bag GlobalRdrElt]
gres) }
tcFImport :: LForeignDecl GhcRn
-> TcM (Id, LForeignDecl GhcTc, Bag GlobalRdrElt)
tcFImport :: LForeignDecl GhcRn
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
tcFImport (L dloc :: SrcSpan
dloc fo :: ForeignDecl GhcRn
fo@(ForeignImport { fd_name :: forall pass. ForeignDecl pass -> Located (IdP pass)
fd_name = L nloc :: SrcSpan
nloc nm :: IdP GhcRn
nm, fd_sig_ty :: forall pass. ForeignDecl pass -> LHsSigType pass
fd_sig_ty = LHsSigType GhcRn
hs_ty
, fd_fi :: forall pass. ForeignDecl pass -> ForeignImport
fd_fi = ForeignImport
imp_decl }))
= SrcSpan
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
forall a. SrcSpan -> TcRn a -> TcRn a
setSrcSpan SrcSpan
dloc (IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt))
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
forall a b. (a -> b) -> a -> b
$ MsgDoc
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
forall a. MsgDoc -> TcM a -> TcM a
addErrCtxt (ForeignDecl GhcRn -> MsgDoc
foreignDeclCtxt ForeignDecl GhcRn
fo) (IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt))
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
forall a b. (a -> b) -> a -> b
$
do { Type
sig_ty <- UserTypeCtxt -> LHsSigType GhcRn -> TcM Type
tcHsSigType (Name -> UserTypeCtxt
ForSigCtxt Name
IdP GhcRn
nm) LHsSigType GhcRn
hs_ty
; (norm_co :: Coercion
norm_co, norm_sig_ty :: Type
norm_sig_ty, gres :: Bag GlobalRdrElt
gres) <- Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
normaliseFfiType Type
sig_ty
; let
(bndrs :: [TyBinder]
bndrs, res_ty :: Type
res_ty) = Type -> ([TyBinder], Type)
tcSplitPiTys Type
norm_sig_ty
arg_tys :: [Type]
arg_tys = (TyBinder -> Maybe Type) -> [TyBinder] -> [Type]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe TyBinder -> Maybe Type
binderRelevantType_maybe [TyBinder]
bndrs
id :: TyCoVar
id = Name -> Type -> TyCoVar
mkLocalId Name
IdP GhcRn
nm Type
sig_ty
; ForeignImport
imp_decl' <- [Type] -> Type -> ForeignImport -> TcM ForeignImport
tcCheckFIType [Type]
arg_tys Type
res_ty ForeignImport
imp_decl
; let fi_decl :: ForeignDecl GhcTc
fi_decl = ForeignImport :: forall pass.
XForeignImport pass
-> Located (IdP pass)
-> LHsSigType pass
-> ForeignImport
-> ForeignDecl pass
ForeignImport { fd_name :: Located (IdP GhcTc)
fd_name = SrcSpan -> TyCoVar -> GenLocated SrcSpan TyCoVar
forall l e. l -> e -> GenLocated l e
L SrcSpan
nloc TyCoVar
id
, fd_sig_ty :: LHsSigType GhcTc
fd_sig_ty = LHsSigType GhcTc
forall a. HasCallStack => a
undefined
, fd_i_ext :: XForeignImport GhcTc
fd_i_ext = Coercion -> Coercion
mkSymCo Coercion
norm_co
, fd_fi :: ForeignImport
fd_fi = ForeignImport
imp_decl' }
; (TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
forall (m :: * -> *) a. Monad m => a -> m a
return (TyCoVar
id, SrcSpan -> ForeignDecl GhcTc -> LForeignDecl GhcTc
forall l e. l -> e -> GenLocated l e
L SrcSpan
dloc ForeignDecl GhcTc
fi_decl, Bag GlobalRdrElt
gres) }
tcFImport d :: LForeignDecl GhcRn
d = String
-> MsgDoc
-> IOEnv
(Env TcGblEnv TcLclEnv)
(TyCoVar, LForeignDecl GhcTc, Bag GlobalRdrElt)
forall a. HasCallStack => String -> MsgDoc -> a
pprPanic "tcFImport" (LForeignDecl GhcRn -> MsgDoc
forall a. Outputable a => a -> MsgDoc
ppr LForeignDecl GhcRn
d)
tcCheckFIType :: [Type] -> Type -> ForeignImport -> TcM ForeignImport
tcCheckFIType :: [Type] -> Type -> ForeignImport -> TcM ForeignImport
tcCheckFIType arg_tys :: [Type]
arg_tys res_ty :: Type
res_ty (CImport (L lc :: SrcSpan
lc cconv :: CCallConv
cconv) safety :: Located Safety
safety mh :: Maybe Header
mh l :: CImportSpec
l@(CLabel _) src :: Located SourceText
src)
= do (HscTarget -> Validity) -> TcM ()
checkCg HscTarget -> Validity
checkCOrAsmOrLlvmOrInterp
Validity -> (MsgDoc -> MsgDoc) -> TcM ()
check (Type -> Validity
isFFILabelTy ([Type] -> Type -> Type
mkFunTys [Type]
arg_tys Type
res_ty)) (MsgDoc -> MsgDoc -> MsgDoc
illegalForeignTyErr MsgDoc
Outputable.empty)
CCallConv
cconv' <- CCallConv -> TcM CCallConv
checkCConv CCallConv
cconv
ForeignImport -> TcM ForeignImport
forall (m :: * -> *) a. Monad m => a -> m a
return (GenLocated SrcSpan CCallConv
-> Located Safety
-> Maybe Header
-> CImportSpec
-> Located SourceText
-> ForeignImport
CImport (SrcSpan -> CCallConv -> GenLocated SrcSpan CCallConv
forall l e. l -> e -> GenLocated l e
L SrcSpan
lc CCallConv
cconv') Located Safety
safety Maybe Header
mh CImportSpec
l Located SourceText
src)
tcCheckFIType arg_tys :: [Type]
arg_tys res_ty :: Type
res_ty (CImport (L lc :: SrcSpan
lc cconv :: CCallConv
cconv) safety :: Located Safety
safety mh :: Maybe Header
mh CWrapper src :: Located SourceText
src) = do
(HscTarget -> Validity) -> TcM ()
checkCg HscTarget -> Validity
checkCOrAsmOrLlvmOrInterp
CCallConv
cconv' <- CCallConv -> TcM CCallConv
checkCConv CCallConv
cconv
case [Type]
arg_tys of
[arg1_ty :: Type
arg1_ty] -> do (Type -> Validity) -> [Type] -> TcM ()
checkForeignArgs Type -> Validity
isFFIExternalTy [Type]
arg1_tys
Bool -> Bool -> (Type -> Validity) -> Type -> TcM ()
checkForeignRes Bool
nonIOok Bool
checkSafe Type -> Validity
isFFIExportResultTy Type
res1_ty
Bool -> Bool -> (Type -> Validity) -> Type -> TcM ()
checkForeignRes Bool
mustBeIO Bool
checkSafe (Type -> Type -> Validity
isFFIDynTy Type
arg1_ty) Type
res_ty
where
(arg1_tys :: [Type]
arg1_tys, res1_ty :: Type
res1_ty) = Type -> ([Type], Type)
tcSplitFunTys Type
arg1_ty
_ -> MsgDoc -> TcM ()
addErrTc (MsgDoc -> MsgDoc -> MsgDoc
illegalForeignTyErr MsgDoc
Outputable.empty (String -> MsgDoc
text "One argument expected"))
ForeignImport -> TcM ForeignImport
forall (m :: * -> *) a. Monad m => a -> m a
return (GenLocated SrcSpan CCallConv
-> Located Safety
-> Maybe Header
-> CImportSpec
-> Located SourceText
-> ForeignImport
CImport (SrcSpan -> CCallConv -> GenLocated SrcSpan CCallConv
forall l e. l -> e -> GenLocated l e
L SrcSpan
lc CCallConv
cconv') Located Safety
safety Maybe Header
mh CImportSpec
CWrapper Located SourceText
src)
tcCheckFIType arg_tys :: [Type]
arg_tys res_ty :: Type
res_ty idecl :: ForeignImport
idecl@(CImport (L lc :: SrcSpan
lc cconv :: CCallConv
cconv) (L ls :: SrcSpan
ls safety :: Safety
safety) mh :: Maybe Header
mh
(CFunction target :: CCallTarget
target) src :: Located SourceText
src)
| CCallTarget -> Bool
isDynamicTarget CCallTarget
target = do
(HscTarget -> Validity) -> TcM ()
checkCg HscTarget -> Validity
checkCOrAsmOrLlvmOrInterp
CCallConv
cconv' <- CCallConv -> TcM CCallConv
checkCConv CCallConv
cconv
case [Type]
arg_tys of
[] ->
MsgDoc -> TcM ()
addErrTc (MsgDoc -> MsgDoc -> MsgDoc
illegalForeignTyErr MsgDoc
Outputable.empty (String -> MsgDoc
text "At least one argument expected"))
(arg1_ty :: Type
arg1_ty:arg_tys :: [Type]
arg_tys) -> do
DynFlags
dflags <- IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let curried_res_ty :: Type
curried_res_ty = [Type] -> Type -> Type
mkFunTys [Type]
arg_tys Type
res_ty
Validity -> (MsgDoc -> MsgDoc) -> TcM ()
check (Type -> Type -> Validity
isFFIDynTy Type
curried_res_ty Type
arg1_ty)
(MsgDoc -> MsgDoc -> MsgDoc
illegalForeignTyErr MsgDoc
argument)
(Type -> Validity) -> [Type] -> TcM ()
checkForeignArgs (DynFlags -> Safety -> Type -> Validity
isFFIArgumentTy DynFlags
dflags Safety
safety) [Type]
arg_tys
Bool -> Bool -> (Type -> Validity) -> Type -> TcM ()
checkForeignRes Bool
nonIOok Bool
checkSafe (DynFlags -> Type -> Validity
isFFIImportResultTy DynFlags
dflags) Type
res_ty
ForeignImport -> TcM ForeignImport
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignImport -> TcM ForeignImport)
-> ForeignImport -> TcM ForeignImport
forall a b. (a -> b) -> a -> b
$ GenLocated SrcSpan CCallConv
-> Located Safety
-> Maybe Header
-> CImportSpec
-> Located SourceText
-> ForeignImport
CImport (SrcSpan -> CCallConv -> GenLocated SrcSpan CCallConv
forall l e. l -> e -> GenLocated l e
L SrcSpan
lc CCallConv
cconv') (SrcSpan -> Safety -> Located Safety
forall l e. l -> e -> GenLocated l e
L SrcSpan
ls Safety
safety) Maybe Header
mh (CCallTarget -> CImportSpec
CFunction CCallTarget
target) Located SourceText
src
| CCallConv
cconv CCallConv -> CCallConv -> Bool
forall a. Eq a => a -> a -> Bool
== CCallConv
PrimCallConv = do
DynFlags
dflags <- IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
Bool -> MsgDoc -> TcM ()
checkTc (Extension -> DynFlags -> Bool
xopt Extension
LangExt.GHCForeignImportPrim DynFlags
dflags)
(String -> MsgDoc
text "Use GHCForeignImportPrim to allow `foreign import prim'.")
(HscTarget -> Validity) -> TcM ()
checkCg HscTarget -> Validity
checkCOrAsmOrLlvmOrInterp
CCallTarget -> TcM ()
checkCTarget CCallTarget
target
Bool -> MsgDoc -> TcM ()
checkTc (Safety -> Bool
playSafe Safety
safety)
(String -> MsgDoc
text "The safe/unsafe annotation should not be used with `foreign import prim'.")
(Type -> Validity) -> [Type] -> TcM ()
checkForeignArgs (DynFlags -> Type -> Validity
isFFIPrimArgumentTy DynFlags
dflags) [Type]
arg_tys
Bool -> Bool -> (Type -> Validity) -> Type -> TcM ()
checkForeignRes Bool
nonIOok Bool
checkSafe (DynFlags -> Type -> Validity
isFFIPrimResultTy DynFlags
dflags) Type
res_ty
ForeignImport -> TcM ForeignImport
forall (m :: * -> *) a. Monad m => a -> m a
return ForeignImport
idecl
| Bool
otherwise = do
(HscTarget -> Validity) -> TcM ()
checkCg HscTarget -> Validity
checkCOrAsmOrLlvmOrInterp
CCallConv
cconv' <- CCallConv -> TcM CCallConv
checkCConv CCallConv
cconv
CCallTarget -> TcM ()
checkCTarget CCallTarget
target
DynFlags
dflags <- IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
(Type -> Validity) -> [Type] -> TcM ()
checkForeignArgs (DynFlags -> Safety -> Type -> Validity
isFFIArgumentTy DynFlags
dflags Safety
safety) [Type]
arg_tys
Bool -> Bool -> (Type -> Validity) -> Type -> TcM ()
checkForeignRes Bool
nonIOok Bool
checkSafe (DynFlags -> Type -> Validity
isFFIImportResultTy DynFlags
dflags) Type
res_ty
DynFlags -> [Type] -> Type -> TcM ()
checkMissingAmpersand DynFlags
dflags [Type]
arg_tys Type
res_ty
case CCallTarget
target of
StaticTarget _ _ _ False
| Bool -> Bool
not ([Type] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Type]
arg_tys) ->
MsgDoc -> TcM ()
addErrTc (String -> MsgDoc
text "`value' imports cannot have function types")
_ -> () -> TcM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
ForeignImport -> TcM ForeignImport
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignImport -> TcM ForeignImport)
-> ForeignImport -> TcM ForeignImport
forall a b. (a -> b) -> a -> b
$ GenLocated SrcSpan CCallConv
-> Located Safety
-> Maybe Header
-> CImportSpec
-> Located SourceText
-> ForeignImport
CImport (SrcSpan -> CCallConv -> GenLocated SrcSpan CCallConv
forall l e. l -> e -> GenLocated l e
L SrcSpan
lc CCallConv
cconv') (SrcSpan -> Safety -> Located Safety
forall l e. l -> e -> GenLocated l e
L SrcSpan
ls Safety
safety) Maybe Header
mh (CCallTarget -> CImportSpec
CFunction CCallTarget
target) Located SourceText
src
checkCTarget :: CCallTarget -> TcM ()
checkCTarget :: CCallTarget -> TcM ()
checkCTarget (StaticTarget _ str :: CLabelString
str _ _) = do
(HscTarget -> Validity) -> TcM ()
checkCg HscTarget -> Validity
checkCOrAsmOrLlvmOrInterp
Bool -> MsgDoc -> TcM ()
checkTc (CLabelString -> Bool
isCLabelString CLabelString
str) (CLabelString -> MsgDoc
badCName CLabelString
str)
checkCTarget DynamicTarget = String -> TcM ()
forall a. String -> a
panic "checkCTarget DynamicTarget"
checkMissingAmpersand :: DynFlags -> [Type] -> Type -> TcM ()
checkMissingAmpersand :: DynFlags -> [Type] -> Type -> TcM ()
checkMissingAmpersand dflags :: DynFlags
dflags arg_tys :: [Type]
arg_tys res_ty :: Type
res_ty
| [Type] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Type]
arg_tys Bool -> Bool -> Bool
&& Type -> Bool
isFunPtrTy Type
res_ty Bool -> Bool -> Bool
&&
WarningFlag -> DynFlags -> Bool
wopt WarningFlag
Opt_WarnDodgyForeignImports DynFlags
dflags
= WarnReason -> MsgDoc -> TcM ()
addWarn (WarningFlag -> WarnReason
Reason WarningFlag
Opt_WarnDodgyForeignImports)
(String -> MsgDoc
text "possible missing & in foreign import of FunPtr")
| Bool
otherwise
= () -> TcM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
tcForeignExports :: [LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTcId, [LForeignDecl GhcTcId], Bag GlobalRdrElt)
tcForeignExports :: [LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
tcForeignExports decls :: [LForeignDecl GhcRn]
decls =
(Hooks
-> Maybe
([LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)))
-> ([LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> IOEnv
(Env TcGblEnv TcLclEnv)
([LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt))
forall (f :: * -> *) a.
(Functor f, HasDynFlags f) =>
(Hooks -> Maybe a) -> a -> f a
getHooked Hooks
-> Maybe
([LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt))
tcForeignExportsHook [LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
tcForeignExports' IOEnv
(Env TcGblEnv TcLclEnv)
([LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> (([LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (([LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> [LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
forall a b. (a -> b) -> a -> b
$ [LForeignDecl GhcRn]
decls)
tcForeignExports' :: [LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTcId, [LForeignDecl GhcTcId], Bag GlobalRdrElt)
tcForeignExports' :: [LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
tcForeignExports' decls :: [LForeignDecl GhcRn]
decls
= ((LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
-> LForeignDecl GhcRn
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt))
-> (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
-> [LForeignDecl GhcRn]
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> m a) -> a -> [b] -> m a
foldlM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
-> LForeignDecl GhcRn
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
combine (LHsBinds GhcTc
forall idL idR. LHsBindsLR idL idR
emptyLHsBinds, [], Bag GlobalRdrElt
forall a. Bag a
emptyBag) ((LForeignDecl GhcRn -> Bool)
-> [LForeignDecl GhcRn] -> [LForeignDecl GhcRn]
forall a. (a -> Bool) -> [a] -> [a]
filter LForeignDecl GhcRn -> Bool
forall name. LForeignDecl name -> Bool
isForeignExport [LForeignDecl GhcRn]
decls)
where
combine :: (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
-> LForeignDecl GhcRn
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
combine (binds :: LHsBinds GhcTc
binds, fs :: [LForeignDecl GhcTc]
fs, gres1 :: Bag GlobalRdrElt
gres1) (L loc :: SrcSpan
loc fe :: ForeignDecl GhcRn
fe) = do
(b :: LHsBind GhcTc
b, f :: ForeignDecl GhcTc
f, gres2 :: Bag GlobalRdrElt
gres2) <- SrcSpan
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
forall a. SrcSpan -> TcRn a -> TcRn a
setSrcSpan SrcSpan
loc (ForeignDecl GhcRn
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
tcFExport ForeignDecl GhcRn
fe)
(LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
-> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)
forall (m :: * -> *) a. Monad m => a -> m a
return (LHsBind GhcTc
b LHsBind GhcTc -> LHsBinds GhcTc -> LHsBinds GhcTc
forall a. a -> Bag a -> Bag a
`consBag` LHsBinds GhcTc
binds, SrcSpan -> ForeignDecl GhcTc -> LForeignDecl GhcTc
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc ForeignDecl GhcTc
f LForeignDecl GhcTc -> [LForeignDecl GhcTc] -> [LForeignDecl GhcTc]
forall a. a -> [a] -> [a]
: [LForeignDecl GhcTc]
fs, Bag GlobalRdrElt
gres1 Bag GlobalRdrElt -> Bag GlobalRdrElt -> Bag GlobalRdrElt
forall a. Bag a -> Bag a -> Bag a
`unionBags` Bag GlobalRdrElt
gres2)
tcFExport :: ForeignDecl GhcRn
-> TcM (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
tcFExport :: ForeignDecl GhcRn
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
tcFExport fo :: ForeignDecl GhcRn
fo@(ForeignExport { fd_name :: forall pass. ForeignDecl pass -> Located (IdP pass)
fd_name = L loc :: SrcSpan
loc nm :: IdP GhcRn
nm, fd_sig_ty :: forall pass. ForeignDecl pass -> LHsSigType pass
fd_sig_ty = LHsSigType GhcRn
hs_ty, fd_fe :: forall pass. ForeignDecl pass -> ForeignExport
fd_fe = ForeignExport
spec })
= MsgDoc
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
forall a. MsgDoc -> TcM a -> TcM a
addErrCtxt (ForeignDecl GhcRn -> MsgDoc
foreignDeclCtxt ForeignDecl GhcRn
fo) (TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt))
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
forall a b. (a -> b) -> a -> b
$ do
Type
sig_ty <- UserTypeCtxt -> LHsSigType GhcRn -> TcM Type
tcHsSigType (Name -> UserTypeCtxt
ForSigCtxt Name
IdP GhcRn
nm) LHsSigType GhcRn
hs_ty
LHsExpr GhcTc
rhs <- LHsExpr GhcRn -> Type -> TcM (LHsExpr GhcTc)
tcPolyExpr (IdP GhcRn -> LHsExpr GhcRn
forall (id :: Pass). IdP (GhcPass id) -> LHsExpr (GhcPass id)
nlHsVar IdP GhcRn
nm) Type
sig_ty
(norm_co :: Coercion
norm_co, norm_sig_ty :: Type
norm_sig_ty, gres :: Bag GlobalRdrElt
gres) <- Type -> TcM (Coercion, Type, Bag GlobalRdrElt)
normaliseFfiType Type
sig_ty
ForeignExport
spec' <- Type -> ForeignExport -> TcM ForeignExport
tcCheckFEType Type
norm_sig_ty ForeignExport
spec
TyCoVar
id <- Name -> Type -> SrcSpan -> (OccName -> OccName) -> TcM TyCoVar
mkStableIdFromName Name
IdP GhcRn
nm Type
sig_ty SrcSpan
loc OccName -> OccName
mkForeignExportOcc
(LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
forall (m :: * -> *) a. Monad m => a -> m a
return ( IdP GhcTc -> LHsExpr GhcTc -> LHsBind GhcTc
forall (p :: Pass).
IdP (GhcPass p) -> LHsExpr (GhcPass p) -> LHsBind (GhcPass p)
mkVarBind TyCoVar
IdP GhcTc
id LHsExpr GhcTc
rhs
, ForeignExport :: forall pass.
XForeignExport pass
-> Located (IdP pass)
-> LHsSigType pass
-> ForeignExport
-> ForeignDecl pass
ForeignExport { fd_name :: Located (IdP GhcTc)
fd_name = SrcSpan -> TyCoVar -> GenLocated SrcSpan TyCoVar
forall l e. l -> e -> GenLocated l e
L SrcSpan
loc TyCoVar
id
, fd_sig_ty :: LHsSigType GhcTc
fd_sig_ty = LHsSigType GhcTc
forall a. HasCallStack => a
undefined
, fd_e_ext :: XForeignExport GhcTc
fd_e_ext = Coercion
XForeignExport GhcTc
norm_co, fd_fe :: ForeignExport
fd_fe = ForeignExport
spec' }
, Bag GlobalRdrElt
gres)
tcFExport d :: ForeignDecl GhcRn
d = String
-> MsgDoc
-> TcRn (LHsBind GhcTc, ForeignDecl GhcTc, Bag GlobalRdrElt)
forall a. HasCallStack => String -> MsgDoc -> a
pprPanic "tcFExport" (ForeignDecl GhcRn -> MsgDoc
forall a. Outputable a => a -> MsgDoc
ppr ForeignDecl GhcRn
d)
tcCheckFEType :: Type -> ForeignExport -> TcM ForeignExport
tcCheckFEType :: Type -> ForeignExport -> TcM ForeignExport
tcCheckFEType sig_ty :: Type
sig_ty (CExport (L l :: SrcSpan
l (CExportStatic esrc :: SourceText
esrc str :: CLabelString
str cconv :: CCallConv
cconv)) src :: Located SourceText
src) = do
(HscTarget -> Validity) -> TcM ()
checkCg HscTarget -> Validity
checkCOrAsmOrLlvm
Bool -> MsgDoc -> TcM ()
checkTc (CLabelString -> Bool
isCLabelString CLabelString
str) (CLabelString -> MsgDoc
badCName CLabelString
str)
CCallConv
cconv' <- CCallConv -> TcM CCallConv
checkCConv CCallConv
cconv
(Type -> Validity) -> [Type] -> TcM ()
checkForeignArgs Type -> Validity
isFFIExternalTy [Type]
arg_tys
Bool -> Bool -> (Type -> Validity) -> Type -> TcM ()
checkForeignRes Bool
nonIOok Bool
noCheckSafe Type -> Validity
isFFIExportResultTy Type
res_ty
ForeignExport -> TcM ForeignExport
forall (m :: * -> *) a. Monad m => a -> m a
return (GenLocated SrcSpan CExportSpec
-> Located SourceText -> ForeignExport
CExport (SrcSpan -> CExportSpec -> GenLocated SrcSpan CExportSpec
forall l e. l -> e -> GenLocated l e
L SrcSpan
l (SourceText -> CLabelString -> CCallConv -> CExportSpec
CExportStatic SourceText
esrc CLabelString
str CCallConv
cconv')) Located SourceText
src)
where
(bndrs :: [TyBinder]
bndrs, res_ty :: Type
res_ty) = Type -> ([TyBinder], Type)
tcSplitPiTys Type
sig_ty
arg_tys :: [Type]
arg_tys = (TyBinder -> Maybe Type) -> [TyBinder] -> [Type]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe TyBinder -> Maybe Type
binderRelevantType_maybe [TyBinder]
bndrs
checkForeignArgs :: (Type -> Validity) -> [Type] -> TcM ()
checkForeignArgs :: (Type -> Validity) -> [Type] -> TcM ()
checkForeignArgs pred :: Type -> Validity
pred tys :: [Type]
tys = (Type -> TcM ()) -> [Type] -> TcM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Type -> TcM ()
go [Type]
tys
where
go :: Type -> TcM ()
go ty :: Type
ty = Validity -> (MsgDoc -> MsgDoc) -> TcM ()
check (Type -> Validity
pred Type
ty) (MsgDoc -> MsgDoc -> MsgDoc
illegalForeignTyErr MsgDoc
argument)
checkForeignRes :: Bool -> Bool -> (Type -> Validity) -> Type -> TcM ()
checkForeignRes :: Bool -> Bool -> (Type -> Validity) -> Type -> TcM ()
checkForeignRes non_io_result_ok :: Bool
non_io_result_ok check_safe :: Bool
check_safe pred_res_ty :: Type -> Validity
pred_res_ty ty :: Type
ty
| Just (_, res_ty :: Type
res_ty) <- Type -> Maybe (TyCon, Type)
tcSplitIOType_maybe Type
ty
=
Validity -> (MsgDoc -> MsgDoc) -> TcM ()
check (Type -> Validity
pred_res_ty Type
res_ty) (MsgDoc -> MsgDoc -> MsgDoc
illegalForeignTyErr MsgDoc
result)
| Bool -> Bool
not Bool
non_io_result_ok
= MsgDoc -> TcM ()
addErrTc (MsgDoc -> TcM ()) -> MsgDoc -> TcM ()
forall a b. (a -> b) -> a -> b
$ MsgDoc -> MsgDoc -> MsgDoc
illegalForeignTyErr MsgDoc
result (String -> MsgDoc
text "IO result type expected")
| Bool
otherwise
= do { DynFlags
dflags <- IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; case Type -> Validity
pred_res_ty Type
ty of
NotValid msg :: MsgDoc
msg -> MsgDoc -> TcM ()
addErrTc (MsgDoc -> TcM ()) -> MsgDoc -> TcM ()
forall a b. (a -> b) -> a -> b
$ MsgDoc -> MsgDoc -> MsgDoc
illegalForeignTyErr MsgDoc
result MsgDoc
msg
_ | Bool
check_safe Bool -> Bool -> Bool
&& DynFlags -> Bool
safeInferOn DynFlags
dflags
-> WarningMessages -> TcM ()
recordUnsafeInfer WarningMessages
forall a. Bag a
emptyBag
_ | Bool
check_safe Bool -> Bool -> Bool
&& DynFlags -> Bool
safeLanguageOn DynFlags
dflags
-> MsgDoc -> TcM ()
addErrTc (MsgDoc -> MsgDoc -> MsgDoc
illegalForeignTyErr MsgDoc
result MsgDoc
safeHsErr)
_ -> () -> TcM ()
forall (m :: * -> *) a. Monad m => a -> m a
return () }
where
safeHsErr :: MsgDoc
safeHsErr =
String -> MsgDoc
text "Safe Haskell is on, all FFI imports must be in the IO monad"
nonIOok, mustBeIO :: Bool
nonIOok :: Bool
nonIOok = Bool
True
mustBeIO :: Bool
mustBeIO = Bool
False
checkSafe, noCheckSafe :: Bool
checkSafe :: Bool
checkSafe = Bool
True
noCheckSafe :: Bool
noCheckSafe = Bool
False
checkCOrAsmOrLlvm :: HscTarget -> Validity
checkCOrAsmOrLlvm :: HscTarget -> Validity
checkCOrAsmOrLlvm HscC = Validity
IsValid
checkCOrAsmOrLlvm HscAsm = Validity
IsValid
checkCOrAsmOrLlvm HscLlvm = Validity
IsValid
checkCOrAsmOrLlvm _
= MsgDoc -> Validity
NotValid (String -> MsgDoc
text "requires unregisterised, llvm (-fllvm) or native code generation (-fasm)")
checkCOrAsmOrLlvmOrInterp :: HscTarget -> Validity
checkCOrAsmOrLlvmOrInterp :: HscTarget -> Validity
checkCOrAsmOrLlvmOrInterp HscC = Validity
IsValid
checkCOrAsmOrLlvmOrInterp HscAsm = Validity
IsValid
checkCOrAsmOrLlvmOrInterp HscLlvm = Validity
IsValid
checkCOrAsmOrLlvmOrInterp HscInterpreted = Validity
IsValid
checkCOrAsmOrLlvmOrInterp _
= MsgDoc -> Validity
NotValid (String -> MsgDoc
text "requires interpreted, unregisterised, llvm or native code generation")
checkCg :: (HscTarget -> Validity) -> TcM ()
checkCg :: (HscTarget -> Validity) -> TcM ()
checkCg check :: HscTarget -> Validity
check = do
DynFlags
dflags <- IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let target :: HscTarget
target = DynFlags -> HscTarget
hscTarget DynFlags
dflags
case HscTarget
target of
HscNothing -> () -> TcM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
_ ->
case HscTarget -> Validity
check HscTarget
target of
IsValid -> () -> TcM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
NotValid err :: MsgDoc
err -> MsgDoc -> TcM ()
addErrTc (String -> MsgDoc
text "Illegal foreign declaration:" MsgDoc -> MsgDoc -> MsgDoc
<+> MsgDoc
err)
checkCConv :: CCallConv -> TcM CCallConv
checkCConv :: CCallConv -> TcM CCallConv
checkCConv CCallConv = CCallConv -> TcM CCallConv
forall (m :: * -> *) a. Monad m => a -> m a
return CCallConv
CCallConv
checkCConv CApiConv = CCallConv -> TcM CCallConv
forall (m :: * -> *) a. Monad m => a -> m a
return CCallConv
CApiConv
checkCConv StdCallConv = do DynFlags
dflags <- IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
let platform :: Platform
platform = DynFlags -> Platform
targetPlatform DynFlags
dflags
if Platform -> Arch
platformArch Platform
platform Arch -> Arch -> Bool
forall a. Eq a => a -> a -> Bool
== Arch
ArchX86
then CCallConv -> TcM CCallConv
forall (m :: * -> *) a. Monad m => a -> m a
return CCallConv
StdCallConv
else do
Bool -> TcM () -> TcM ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (WarningFlag -> DynFlags -> Bool
wopt WarningFlag
Opt_WarnUnsupportedCallingConventions DynFlags
dflags) (TcM () -> TcM ()) -> TcM () -> TcM ()
forall a b. (a -> b) -> a -> b
$
WarnReason -> MsgDoc -> TcM ()
addWarnTc (WarningFlag -> WarnReason
Reason WarningFlag
Opt_WarnUnsupportedCallingConventions)
(String -> MsgDoc
text "the 'stdcall' calling convention is unsupported on this platform," MsgDoc -> MsgDoc -> MsgDoc
$$ String -> MsgDoc
text "treating as ccall")
CCallConv -> TcM CCallConv
forall (m :: * -> *) a. Monad m => a -> m a
return CCallConv
CCallConv
checkCConv PrimCallConv = do MsgDoc -> TcM ()
addErrTc (String -> MsgDoc
text "The `prim' calling convention can only be used with `foreign import'")
CCallConv -> TcM CCallConv
forall (m :: * -> *) a. Monad m => a -> m a
return CCallConv
PrimCallConv
checkCConv JavaScriptCallConv = do DynFlags
dflags <- IOEnv (Env TcGblEnv TcLclEnv) DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
if Platform -> Arch
platformArch (DynFlags -> Platform
targetPlatform DynFlags
dflags) Arch -> Arch -> Bool
forall a. Eq a => a -> a -> Bool
== Arch
ArchJavaScript
then CCallConv -> TcM CCallConv
forall (m :: * -> *) a. Monad m => a -> m a
return CCallConv
JavaScriptCallConv
else do MsgDoc -> TcM ()
addErrTc (String -> MsgDoc
text "The `javascript' calling convention is unsupported on this platform")
CCallConv -> TcM CCallConv
forall (m :: * -> *) a. Monad m => a -> m a
return CCallConv
JavaScriptCallConv
check :: Validity -> (MsgDoc -> MsgDoc) -> TcM ()
check :: Validity -> (MsgDoc -> MsgDoc) -> TcM ()
check IsValid _ = () -> TcM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
check (NotValid doc :: MsgDoc
doc) err_fn :: MsgDoc -> MsgDoc
err_fn = MsgDoc -> TcM ()
addErrTc (MsgDoc -> MsgDoc
err_fn MsgDoc
doc)
illegalForeignTyErr :: SDoc -> SDoc -> SDoc
illegalForeignTyErr :: MsgDoc -> MsgDoc -> MsgDoc
illegalForeignTyErr arg_or_res :: MsgDoc
arg_or_res extra :: MsgDoc
extra
= MsgDoc -> Int -> MsgDoc -> MsgDoc
hang MsgDoc
msg 2 MsgDoc
extra
where
msg :: MsgDoc
msg = [MsgDoc] -> MsgDoc
hsep [ String -> MsgDoc
text "Unacceptable", MsgDoc
arg_or_res
, String -> MsgDoc
text "type in foreign declaration:"]
argument, result :: SDoc
argument :: MsgDoc
argument = String -> MsgDoc
text "argument"
result :: MsgDoc
result = String -> MsgDoc
text "result"
badCName :: CLabelString -> MsgDoc
badCName :: CLabelString -> MsgDoc
badCName target :: CLabelString
target
= [MsgDoc] -> MsgDoc
sep [MsgDoc -> MsgDoc
quotes (CLabelString -> MsgDoc
forall a. Outputable a => a -> MsgDoc
ppr CLabelString
target) MsgDoc -> MsgDoc -> MsgDoc
<+> String -> MsgDoc
text "is not a valid C identifier"]
foreignDeclCtxt :: ForeignDecl GhcRn -> SDoc
foreignDeclCtxt :: ForeignDecl GhcRn -> MsgDoc
foreignDeclCtxt fo :: ForeignDecl GhcRn
fo
= MsgDoc -> Int -> MsgDoc -> MsgDoc
hang (String -> MsgDoc
text "When checking declaration:")
2 (ForeignDecl GhcRn -> MsgDoc
forall a. Outputable a => a -> MsgDoc
ppr ForeignDecl GhcRn
fo)