summaryrefslogtreecommitdiff
path: root/compiler/GHC/Tc/Gen/Foreign.hs
diff options
context:
space:
mode:
authorKrzysztof Gogolewski <krzysztof.gogolewski@tweag.io>2020-09-24 23:13:10 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-09-26 13:19:00 -0400
commit160fba4aa306c0649c72a6dcd7c98d9782a0e74b (patch)
tree1d4d70dfa3463a079f9eda797e4932b90dfb6812 /compiler/GHC/Tc/Gen/Foreign.hs
parentbda55fa0444310079ab89f2d28ddb8982975b646 (diff)
downloadhaskell-160fba4aa306c0649c72a6dcd7c98d9782a0e74b.tar.gz
Disallow linear types in FFI (#18472)
Diffstat (limited to 'compiler/GHC/Tc/Gen/Foreign.hs')
-rw-r--r--compiler/GHC/Tc/Gen/Foreign.hs29
1 files changed, 19 insertions, 10 deletions
diff --git a/compiler/GHC/Tc/Gen/Foreign.hs b/compiler/GHC/Tc/Gen/Foreign.hs
index 040a246091..5f392e6028 100644
--- a/compiler/GHC/Tc/Gen/Foreign.hs
+++ b/compiler/GHC/Tc/Gen/Foreign.hs
@@ -243,7 +243,7 @@ tcFImport (L dloc fo@(ForeignImport { fd_name = L nloc nm, fd_sig_ty = hs_ty
-- things are LocalIds. However, it does not need zonking,
-- (so GHC.Tc.Utils.Zonk.zonkForeignExports ignores it).
- ; imp_decl' <- tcCheckFIType (map scaledThing arg_tys) res_ty imp_decl
+ ; imp_decl' <- tcCheckFIType arg_tys res_ty imp_decl
-- Can't use sig_ty here because sig_ty :: Type and
-- we need HsType Id hence the undefined
; let fi_decl = ForeignImport { fd_name = L nloc id
@@ -255,14 +255,14 @@ tcFImport d = pprPanic "tcFImport" (ppr d)
-- ------------ Checking types for foreign import ----------------------
-tcCheckFIType :: [Type] -> Type -> ForeignImport -> TcM ForeignImport
+tcCheckFIType :: [Scaled Type] -> Type -> ForeignImport -> TcM ForeignImport
tcCheckFIType arg_tys res_ty (CImport (L lc cconv) safety mh l@(CLabel _) src)
-- Foreign import label
= do checkCg checkCOrAsmOrLlvmOrInterp
-- NB check res_ty not sig_ty!
-- In case sig_ty is (forall a. ForeignPtr a)
- check (isFFILabelTy (mkVisFunTysMany arg_tys res_ty)) (illegalForeignTyErr Outputable.empty)
+ check (isFFILabelTy (mkVisFunTys arg_tys res_ty)) (illegalForeignTyErr Outputable.empty)
cconv' <- checkCConv cconv
return (CImport (L lc cconv') safety mh l src)
@@ -274,7 +274,9 @@ tcCheckFIType arg_tys res_ty (CImport (L lc cconv) safety mh CWrapper src) = do
checkCg checkCOrAsmOrLlvmOrInterp
cconv' <- checkCConv cconv
case arg_tys of
- [arg1_ty] -> do checkForeignArgs isFFIExternalTy (map scaledThing arg1_tys)
+ [Scaled arg1_mult arg1_ty] -> do
+ checkNoLinearFFI arg1_mult
+ checkForeignArgs isFFIExternalTy arg1_tys
checkForeignRes nonIOok checkSafe isFFIExportResultTy res1_ty
checkForeignRes mustBeIO checkSafe (isFFIDynTy arg1_ty) res_ty
where
@@ -290,9 +292,10 @@ tcCheckFIType arg_tys res_ty idecl@(CImport (L lc cconv) (L ls safety) mh
case arg_tys of -- The first arg must be Ptr or FunPtr
[] ->
addErrTc (illegalForeignTyErr Outputable.empty (text "At least one argument expected"))
- (arg1_ty:arg_tys) -> do
+ (Scaled arg1_mult arg1_ty:arg_tys) -> do
dflags <- getDynFlags
- let curried_res_ty = mkVisFunTysMany arg_tys res_ty
+ let curried_res_ty = mkVisFunTys arg_tys res_ty
+ checkNoLinearFFI arg1_mult
check (isFFIDynTy curried_res_ty arg1_ty)
(illegalForeignTyErr argument)
checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys
@@ -317,7 +320,7 @@ tcCheckFIType arg_tys res_ty idecl@(CImport (L lc cconv) (L ls safety) mh
dflags <- getDynFlags
checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys
checkForeignRes nonIOok checkSafe (isFFIImportResultTy dflags) res_ty
- checkMissingAmpersand dflags arg_tys res_ty
+ checkMissingAmpersand dflags (map scaledThing arg_tys) res_ty
case target of
StaticTarget _ _ _ False
| not (null arg_tys) ->
@@ -405,7 +408,7 @@ tcCheckFEType sig_ty (CExport (L l (CExportStatic esrc str cconv)) src) = do
checkCg checkCOrAsmOrLlvm
checkTc (isCLabelString str) (badCName str)
cconv' <- checkCConv cconv
- checkForeignArgs isFFIExternalTy (map scaledThing arg_tys)
+ checkForeignArgs isFFIExternalTy arg_tys
checkForeignRes nonIOok noCheckSafe isFFIExportResultTy res_ty
return (CExport (L l (CExportStatic esrc str cconv')) src)
where
@@ -422,10 +425,16 @@ tcCheckFEType sig_ty (CExport (L l (CExportStatic esrc str cconv)) src) = do
-}
------------ Checking argument types for foreign import ----------------------
-checkForeignArgs :: (Type -> Validity) -> [Type] -> TcM ()
+checkForeignArgs :: (Type -> Validity) -> [Scaled Type] -> TcM ()
checkForeignArgs pred tys = mapM_ go tys
where
- go ty = check (pred ty) (illegalForeignTyErr argument)
+ go (Scaled mult ty) = checkNoLinearFFI mult >>
+ check (pred ty) (illegalForeignTyErr argument)
+
+checkNoLinearFFI :: Mult -> TcM () -- No linear types in FFI (#18472)
+checkNoLinearFFI Many = return ()
+checkNoLinearFFI _ = addErrTc $ illegalForeignTyErr argument
+ (text "Linear types are not supported in FFI declarations, see #18472")
------------ Checking result types for foreign calls ----------------------
-- | Check that the type has the form