diff options
author | David Terei <davidterei@gmail.com> | 2011-04-25 17:27:33 -0700 |
---|---|---|
committer | David Terei <davidterei@gmail.com> | 2011-06-17 18:39:28 -0700 |
commit | d19f2a372759356ea10223f8d29fa45568d5c0e6 (patch) | |
tree | 912d8c73ecb9f051d5f458984027b000bafd8877 /compiler | |
parent | 45c64c1da96dc26ebc89b080dc12cfcc52a4cd68 (diff) | |
download | haskell-d19f2a372759356ea10223f8d29fa45568d5c0e6.tar.gz |
SafeHaskell: Force all FFI imports to be in IO
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/iface/MkIface.lhs | 2 | ||||
-rw-r--r-- | compiler/typecheck/TcForeign.lhs | 28 |
2 files changed, 20 insertions, 10 deletions
diff --git a/compiler/iface/MkIface.lhs b/compiler/iface/MkIface.lhs index e9e921f0a5..ccfa710b0a 100644 --- a/compiler/iface/MkIface.lhs +++ b/compiler/iface/MkIface.lhs @@ -232,7 +232,7 @@ mkIface_ hsc_env maybe_old_fingerprint ; iface_insts = map instanceToIfaceInst insts ; iface_fam_insts = map famInstToIfaceFamInst fam_insts ; iface_vect_info = flattenVectInfo vect_info - ; trust_info = (setSafeMode . safeHaskell . hsc_dflags) hsc_env + ; trust_info = (setSafeMode . safeHaskell) dflags ; intermediate_iface = ModIface { mi_module = this_mod, diff --git a/compiler/typecheck/TcForeign.lhs b/compiler/typecheck/TcForeign.lhs index 8f53d6e7b8..a24eb47b9d 100644 --- a/compiler/typecheck/TcForeign.lhs +++ b/compiler/typecheck/TcForeign.lhs @@ -107,8 +107,8 @@ tcCheckFIType sig_ty arg_tys res_ty idecl@(CImport cconv safety _ CWrapper) = do checkSafety safety case arg_tys of [arg1_ty] -> do checkForeignArgs isFFIExternalTy arg1_tys - checkForeignRes nonIOok isFFIExportResultTy res1_ty - checkForeignRes mustBeIO isFFIDynResultTy res_ty + checkForeignRes nonIOok False isFFIExportResultTy res1_ty + checkForeignRes mustBeIO False isFFIDynResultTy res_ty where (arg1_tys, res1_ty) = tcSplitFunTys arg1_ty _ -> addErrTc (illegalForeignTyErr empty sig_ty) @@ -128,7 +128,9 @@ tcCheckFIType sig_ty arg_tys res_ty idecl@(CImport cconv safety _ (CFunction tar check (isFFIDynArgumentTy arg1_ty) (illegalForeignTyErr argument arg1_ty) checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys - checkForeignRes nonIOok (isFFIImportResultTy dflags) res_ty + let safe_on = safeLanguageOn dflags + ioOK = if safe_on then mustBeIO else nonIOok + checkForeignRes ioOK safe_on (isFFIImportResultTy dflags) res_ty return idecl | cconv == PrimCallConv = do dflags <- getDOpts @@ -140,7 +142,9 @@ tcCheckFIType sig_ty arg_tys res_ty idecl@(CImport cconv safety _ (CFunction tar (text "The safe/unsafe annotation should not be used with `foreign import prim'.") checkForeignArgs (isFFIPrimArgumentTy dflags) arg_tys -- prim import result is more liberal, allows (#,,#) - checkForeignRes nonIOok (isFFIPrimResultTy dflags) res_ty + let safe_on = safeLanguageOn dflags + ioOK = if safe_on then mustBeIO else nonIOok + checkForeignRes ioOK safe_on (isFFIPrimResultTy dflags) res_ty return idecl | otherwise = do -- Normal foreign import checkCg (checkCOrAsmOrLlvmOrDotNetOrInterp) @@ -149,7 +153,9 @@ tcCheckFIType sig_ty arg_tys res_ty idecl@(CImport cconv safety _ (CFunction tar checkCTarget target dflags <- getDOpts checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys - checkForeignRes nonIOok (isFFIImportResultTy dflags) res_ty + let safe_on = safeLanguageOn dflags + ioOK = if safe_on then mustBeIO else nonIOok + checkForeignRes ioOK safe_on (isFFIImportResultTy dflags) res_ty checkMissingAmpersand dflags arg_tys res_ty return idecl @@ -221,7 +227,7 @@ tcCheckFEType sig_ty (CExport (CExportStatic str cconv)) = do check (isCLabelString str) (badCName str) checkCConv cconv checkForeignArgs isFFIExternalTy arg_tys - checkForeignRes nonIOok isFFIExportResultTy res_ty + checkForeignRes nonIOok False isFFIExportResultTy res_ty where -- Drop the foralls before inspecting n -- the structure of the foreign type. @@ -249,13 +255,13 @@ checkForeignArgs pred tys -- Check that the type has the form -- (IO t) or (t) , and that t satisfies the given predicate. -- -checkForeignRes :: Bool -> (Type -> Bool) -> Type -> TcM () +checkForeignRes :: Bool -> Bool -> (Type -> Bool) -> Type -> TcM () nonIOok, mustBeIO :: Bool nonIOok = True mustBeIO = False -checkForeignRes non_io_result_ok pred_res_ty ty +checkForeignRes non_io_result_ok safehs_check pred_res_ty ty -- (IO t) is ok, and so is any newtype wrapping thereof | Just (_, res_ty, _) <- tcSplitIOType_maybe ty, pred_res_ty res_ty @@ -263,7 +269,7 @@ checkForeignRes non_io_result_ok pred_res_ty ty | otherwise = check (non_io_result_ok && pred_res_ty ty) - (illegalForeignTyErr result ty) + (illegalForeignTyErr result ty $+$ safeHsErr safehs_check) \end{code} \begin{code} @@ -338,6 +344,10 @@ illegalForeignTyErr arg_or_res ty ptext (sLit "type in foreign declaration:")]) 2 (hsep [ppr ty]) +safeHsErr :: Bool -> SDoc +safeHsErr False = empty +safeHsErr True = ptext $ sLit "Safe Haskell is on, all FFI imports must be in the IO monad" + -- Used for 'arg_or_res' argument to illegalForeignTyErr argument, result :: SDoc argument = text "argument" |