summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Terei <davidterei@gmail.com>2011-10-31 14:27:25 -0700
committerDavid Terei <davidterei@gmail.com>2011-11-01 01:11:50 -0700
commit794078170b8e0f57319ee030069b4020a4847181 (patch)
tree12f981584e9236790a65317e872474cd73fca707
parent9241aa0bb24e983c371205b1e4cc636cfdb4237a (diff)
downloadhaskell-794078170b8e0f57319ee030069b4020a4847181.tar.gz
safe haskell wip
-rw-r--r--compiler/main/DynFlags.hs6
-rw-r--r--compiler/main/HscMain.lhs76
-rw-r--r--compiler/main/HscTypes.lhs16
3 files changed, 54 insertions, 44 deletions
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs
index 1c047b7cfe..537e2b4dfe 100644
--- a/compiler/main/DynFlags.hs
+++ b/compiler/main/DynFlags.hs
@@ -1037,12 +1037,6 @@ safeLanguageOn dflags = safeHaskell dflags == Sf_Safe
safeInferOn :: DynFlags -> Bool
safeInferOn dflags = safeHaskell dflags == Sf_SafeInfered
--- | Turn off Safe Haskell inference mode (set module to unsafe)
-setSafeInferOff :: DynFlags -> DynFlags
-setSafeInferOff dflags
- | safeHaskell dflags == Sf_SafeInfered = dflags { safeHaskell = Sf_None }
- | otherwise = dflags
-
-- | Test if Safe Imports are on in some form
safeImportsOn :: DynFlags -> Bool
safeImportsOn dflags = safeHaskell dflags == Sf_Unsafe ||
diff --git a/compiler/main/HscMain.lhs b/compiler/main/HscMain.lhs
index 08ae763107..54c8267365 100644
--- a/compiler/main/HscMain.lhs
+++ b/compiler/main/HscMain.lhs
@@ -161,12 +161,13 @@ import Data.IORef
\begin{code}
newHscEnv :: DynFlags -> IO HscEnv
newHscEnv dflags = do
- { eps_var <- newIORef initExternalPackageState
- ; us <- mkSplitUniqSupply 'r'
- ; nc_var <- newIORef (initNameCache us knownKeyNames)
- ; fc_var <- newIORef emptyUFM
- ; mlc_var <- newIORef emptyModuleEnv
- ; optFuel <- initOptFuelState
+ { eps_var <- newIORef initExternalPackageState
+ ; us <- mkSplitUniqSupply 'r'
+ ; nc_var <- newIORef (initNameCache us knownKeyNames)
+ ; fc_var <- newIORef emptyUFM
+ ; mlc_var <- newIORef emptyModuleEnv
+ ; optFuel <- initOptFuelState
+ ; safe_var <- newIORef True
; return (HscEnv { hsc_dflags = dflags,
hsc_targets = [],
hsc_mod_graph = [],
@@ -177,7 +178,8 @@ newHscEnv dflags = do
hsc_FC = fc_var,
hsc_MLC = mlc_var,
hsc_OptFuel = optFuel,
- hsc_type_env_var = Nothing } ) }
+ hsc_type_env_var = Nothing,
+ hsc_safeInf = safe_var } ) }
knownKeyNames :: [Name] -- Put here to avoid loops involving DsMeta,
@@ -191,40 +193,37 @@ knownKeyNames = -- where templateHaskellNames are defined
-- -----------------------------------------------------------------------------
-- The Hsc monad: Passing an enviornment and warning state
-newtype Hsc a = Hsc (HscEnv -> WarningMessages -> IO (a, WarningMessages, HscEnv))
+newtype Hsc a = Hsc (HscEnv -> WarningMessages -> IO (a, WarningMessages))
instance Monad Hsc where
- return a = Hsc $ \e w -> return (a, w, e)
- Hsc m >>= k = Hsc $ \e w -> do (a, w1, e1) <- m e w
+ return a = Hsc $ \_ w -> return (a, w)
+ Hsc m >>= k = Hsc $ \e w -> do (a, w1) <- m e w
case k a of
- Hsc k' -> k' e1 w1
+ Hsc k' -> k' e w1
instance MonadIO Hsc where
- liftIO io = Hsc $ \e w -> do a <- io; return (a, w, e)
+ liftIO io = Hsc $ \_ w -> do a <- io; return (a, w)
runHsc :: HscEnv -> Hsc a -> IO a
runHsc hsc_env (Hsc hsc) = do
- (a, w, e) <- hsc hsc_env emptyBag
- printOrThrowWarnings (hsc_dflags e) w
+ (a, w) <- hsc hsc_env emptyBag
+ printOrThrowWarnings (hsc_dflags hsc_env) w
return a
getWarnings :: Hsc WarningMessages
-getWarnings = Hsc $ \e w -> return (w, w, e)
+getWarnings = Hsc $ \_ w -> return (w, w)
clearWarnings :: Hsc ()
-clearWarnings = Hsc $ \e _w -> return ((), emptyBag, e)
+clearWarnings = Hsc $ \_ _ -> return ((), emptyBag)
logWarnings :: WarningMessages -> Hsc ()
-logWarnings w = Hsc $ \e w0 -> return ((), w0 `unionBags` w, e)
+logWarnings w = Hsc $ \_ w0 -> return ((), w0 `unionBags` w)
getHscEnv :: Hsc HscEnv
-getHscEnv = Hsc $ \e w -> return (e, w, e)
+getHscEnv = Hsc $ \e w -> return (e, w)
getDynFlags :: Hsc DynFlags
-getDynFlags = Hsc $ \e w -> return (hsc_dflags e, w, e)
-
-setDynFlags :: DynFlags -> Hsc ()
-setDynFlags dflags = Hsc $ \e w -> return ((), w, e { hsc_dflags = dflags })
+getDynFlags = Hsc $ \e w -> return (hsc_dflags e, w)
handleWarnings :: Hsc ()
handleWarnings = do
@@ -607,7 +606,7 @@ hscOneShotCompiler =
, hscRecompile = genericHscRecompile hscOneShotCompiler
- , hscBackend = \ tc_result mod_summary mb_old_hash -> do
+ , hscBackend = \tc_result mod_summary mb_old_hash -> do
dflags <- getDynFlags
case hscTarget dflags of
HscNothing -> return (HscRecomp Nothing ())
@@ -902,18 +901,21 @@ checkSafeImports dflags hsc_env tcg_env
logWarnings oldErrs
-- See the Note [ Safe Haskell Inference]
- when (not $ isEmptyBag errs) (
- -- did we fail safe inference or fail -XSafe?
- case safeInferOn dflags of
- True -> setDynFlags (dflags { safeHaskell = Sf_None } )
- False -> liftIO . throwIO . mkSrcErr $ errs
- )
-
- when (packageTrustOn dflags) $ checkPkgTrust pkg_reqs
-
- -- add in trusted package requirements for this module
- let new_trust = emptyImportAvails { imp_trust_pkgs = catMaybes pkgs }
- return tcg_env { tcg_imports = imp_info `plusImportAvails` new_trust }
+ case (not $ isEmptyBag errs) of
+
+ -- We have errors!
+ True ->
+ -- did we fail safe inference or fail -XSafe?
+ case safeInferOn dflags of
+ True -> wipeTrust tcg_env
+ False -> liftIO . throwIO . mkSrcErr $ errs
+
+ -- All good matey!
+ False -> do
+ when (packageTrustOn dflags) $ checkPkgTrust pkg_reqs
+ -- add in trusted package requirements for this module
+ let new_trust = emptyImportAvails { imp_trust_pkgs = catMaybes pkgs }
+ return tcg_env { tcg_imports = imp_info `plusImportAvails` new_trust }
where
imp_info = tcg_imports tcg_env -- ImportAvails
@@ -1029,8 +1031,8 @@ checkSafeImports dflags hsc_env tcg_env
-- | Set module to unsafe and wipe trust information.
wipeTrust :: TcGblEnv -> Hsc TcGblEnv
wipeTrust tcg_env = do
- dflags <- getDynFlags
- setDynFlags (dflags { safeHaskell = Sf_None })
+ env <- getHscEnv
+ liftIO $ hscSetSafeInf env False
let imps = (tcg_imports tcg_env) { imp_trust_pkgs = [] }
return $ tcg_env { tcg_imports = imps }
diff --git a/compiler/main/HscTypes.lhs b/compiler/main/HscTypes.lhs
index 5ad122de00..814e7f0a40 100644
--- a/compiler/main/HscTypes.lhs
+++ b/compiler/main/HscTypes.lhs
@@ -95,6 +95,7 @@ module HscTypes (
noIfaceVectInfo,
-- * Safe Haskell information
+ hscGetSafeInf, hscSetSafeInf,
IfaceTrustInfo, getSafeMode, setSafeMode, noIfaceTrustInfo,
trustInfoToNum, numToTrustInfo, IsSafeImport,
@@ -315,12 +316,25 @@ data HscEnv
-- by limiting the number of transformations,
-- we can use binary search to help find compiler bugs.
- hsc_type_env_var :: Maybe (Module, IORef TypeEnv)
+ hsc_type_env_var :: Maybe (Module, IORef TypeEnv),
-- ^ Used for one-shot compilation only, to initialise
-- the 'IfGblEnv'. See 'TcRnTypes.tcg_type_env_var' for
-- 'TcRunTypes.TcGblEnv'
+
+ hsc_safeInf :: {-# UNPACK #-} !(IORef Bool)
+ -- ^ Have we infered the module being compiled as
+ -- being safe?
}
+-- | Get if the current module is considered safe or not by inference.
+hscGetSafeInf :: HscEnv -> IO Bool
+hscGetSafeInf hsc_env = readIORef (hsc_safeInf hsc_env)
+
+-- | Set if the current module is considered safe or not by inference.
+hscSetSafeInf :: HscEnv -> Bool -> IO ()
+hscSetSafeInf hsc_env b = writeIORef (hsc_safeInf hsc_env) b
+
+-- | Retrieve the ExternalPackageState cache.
hscEPS :: HscEnv -> IO ExternalPackageState
hscEPS hsc_env = readIORef (hsc_EPS hsc_env)