summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleg Grenrus <oleg.grenrus@iki.fi>2019-05-06 23:14:52 +0300
committerBen Gamari <ben@smart-cactus.org>2019-06-25 23:25:08 -0400
commita863c44f35720b760054e949de1b2f431f32774e (patch)
treedac3585b3b42570dd2afd2b2a2297f67ef52d580
parent5c3f20801c4149d6a950cfb36c7a841dd32d17e0 (diff)
downloadhaskell-a863c44f35720b760054e949de1b2f431f32774e.tar.gz
Add -Winferred-safe-imports warning
This commit partly reverts e69619e923e84ae61a6bb4357f06862264daa94b commit by reintroducing Sf_SafeInferred SafeHaskellMode. We preserve whether module was declared or inferred Safe. When declared-Safe module imports inferred-Safe, we warn. This inferred status is volatile, often enough it's a happy coincidence, something which cannot be relied upon. However, explicitly Safe or Trustworthy packages won't accidentally become Unsafe. Updates haddock submodule.
-rw-r--r--compiler/main/DynFlags.hs18
-rw-r--r--compiler/main/HscMain.hs18
-rw-r--r--compiler/main/HscTypes.hs6
-rw-r--r--compiler/typecheck/TcRnMonad.hs4
-rw-r--r--docs/users_guide/safe_haskell.rst35
-rw-r--r--testsuite/tests/plugins/T16260.stdout2
-rw-r--r--testsuite/tests/safeHaskell/check/pkg01/safePkg01.stdout18
m---------utils/haddock0
8 files changed, 79 insertions, 22 deletions
diff --git a/compiler/main/DynFlags.hs b/compiler/main/DynFlags.hs
index 7a6bca6277..54fb684649 100644
--- a/compiler/main/DynFlags.hs
+++ b/compiler/main/DynFlags.hs
@@ -912,6 +912,8 @@ data WarningFlag =
| Opt_WarnMissingDerivingStrategies -- Since 8.8
| Opt_WarnPrepositiveQualifiedModule -- Since TBD
| Opt_WarnUnusedPackages -- Since 8.10
+ | Opt_WarnInferredSafeImports -- Since 8.10
+ | Opt_WarnMissingSafeHaskellMode -- Since 8.10
deriving (Eq, Show, Enum)
data Language = Haskell98 | Haskell2010
@@ -922,11 +924,12 @@ instance Outputable Language where
-- | The various Safe Haskell modes
data SafeHaskellMode
- = Sf_None
- | Sf_Unsafe
- | Sf_Trustworthy
- | Sf_Safe
- | Sf_Ignore
+ = Sf_None -- ^ inferred unsafe
+ | Sf_Unsafe -- ^ declared and checked
+ | Sf_Trustworthy -- ^ declared and checked
+ | Sf_Safe -- ^ declared and checked
+ | Sf_SafeInferred -- ^ inferred as safe
+ | Sf_Ignore -- ^ @-fno-safe-haskell@ state
deriving (Eq)
instance Show SafeHaskellMode where
@@ -934,6 +937,7 @@ instance Show SafeHaskellMode where
show Sf_Unsafe = "Unsafe"
show Sf_Trustworthy = "Trustworthy"
show Sf_Safe = "Safe"
+ show Sf_SafeInferred = "Safe-Inferred"
show Sf_Ignore = "Ignore"
instance Outputable SafeHaskellMode where
@@ -3758,6 +3762,8 @@ dynamic_flags_deps = [
, make_ord_flag defFlag "fno-safe-infer" (noArg (\d ->
d { safeInfer = False }))
, make_ord_flag defFlag "fno-safe-haskell" (NoArg (setSafeHaskell Sf_Ignore))
+
+ ------ position independent flags ----------------------------------
, make_ord_flag defGhcFlag "fPIC" (NoArg (setGeneralFlag Opt_PIC))
, make_ord_flag defGhcFlag "fno-PIC" (NoArg (unSetGeneralFlag Opt_PIC))
, make_ord_flag defGhcFlag "fPIE" (NoArg (setGeneralFlag Opt_PIC))
@@ -4076,6 +4082,8 @@ wWarningFlagsDeps = [
flagSpec "all-missed-specializations" Opt_WarnAllMissedSpecs,
flagSpec' "safe" Opt_WarnSafe setWarnSafe,
flagSpec "trustworthy-safe" Opt_WarnTrustworthySafe,
+ flagSpec "inferred-safe-imports" Opt_WarnInferredSafeImports,
+ flagSpec "missing-safe-haskell-mode" Opt_WarnMissingSafeHaskellMode,
flagSpec "tabs" Opt_WarnTabs,
flagSpec "type-defaults" Opt_WarnTypeDefaults,
flagSpec "typed-holes" Opt_WarnTypedHoles,
diff --git a/compiler/main/HscMain.hs b/compiler/main/HscMain.hs
index d7658ad2aa..91a1f1d1e6 100644
--- a/compiler/main/HscMain.hs
+++ b/compiler/main/HscMain.hs
@@ -1109,21 +1109,36 @@ hscCheckSafe' m l = do
let trust = getSafeMode $ mi_trust iface'
trust_own_pkg = mi_trust_pkg iface'
-- check module is trusted
- safeM = trust `elem` [Sf_Safe, Sf_Trustworthy]
+ safeM = trust `elem` [Sf_Safe, Sf_SafeInferred, Sf_Trustworthy]
-- check package is trusted
safeP = packageTrusted dflags trust trust_own_pkg m
-- pkg trust reqs
pkgRs = S.fromList . map fst $ filter snd $ dep_pkgs $ mi_deps iface'
+ -- warn if Safe module imports Safe-Inferred module.
+ warns = if wopt Opt_WarnInferredSafeImports dflags
+ && safeLanguageOn dflags
+ && trust == Sf_SafeInferred
+ then inferredImportWarn
+ else emptyBag
-- General errors we throw but Safe errors we log
errs = case (safeM, safeP) of
(True, True ) -> emptyBag
(True, False) -> pkgTrustErr
(False, _ ) -> modTrustErr
in do
+ logWarnings warns
logWarnings errs
return (trust == Sf_Trustworthy, pkgRs)
where
+ inferredImportWarn = unitBag
+ $ makeIntoWarning (Reason Opt_WarnInferredSafeImports)
+ $ mkErrMsg dflags l (pkgQual dflags)
+ $ sep
+ [ text "Importing Safe-Inferred module "
+ <> ppr (moduleName m)
+ <> text " from explicitly Safe module"
+ ]
pkgTrustErr = unitBag $ mkErrMsg dflags l (pkgQual dflags) $
sep [ ppr (moduleName m)
<> text ": Can't be safely imported!"
@@ -1146,6 +1161,7 @@ hscCheckSafe' m l = do
packageTrusted dflags _ _ _
| not (packageTrustOn dflags) = True
packageTrusted _ Sf_Safe False _ = True
+ packageTrusted _ Sf_SafeInferred False _ = True
packageTrusted dflags _ _ m
| isHomePkg dflags m = True
| otherwise = trusted $ getPackageDetails dflags (moduleUnitId m)
diff --git a/compiler/main/HscTypes.hs b/compiler/main/HscTypes.hs
index 0fa9ffa664..e2dbcb0ecf 100644
--- a/compiler/main/HscTypes.hs
+++ b/compiler/main/HscTypes.hs
@@ -2948,6 +2948,7 @@ trustInfoToNum it
Sf_Unsafe -> 1
Sf_Trustworthy -> 2
Sf_Safe -> 3
+ Sf_SafeInferred -> 4
Sf_Ignore -> 0
numToTrustInfo :: Word8 -> IfaceTrustInfo
@@ -2955,9 +2956,7 @@ numToTrustInfo 0 = setSafeMode Sf_None
numToTrustInfo 1 = setSafeMode Sf_Unsafe
numToTrustInfo 2 = setSafeMode Sf_Trustworthy
numToTrustInfo 3 = setSafeMode Sf_Safe
-numToTrustInfo 4 = setSafeMode Sf_Safe -- retained for backwards compat, used
- -- to be Sf_SafeInfered but we no longer
- -- differentiate.
+numToTrustInfo 4 = setSafeMode Sf_SafeInferred
numToTrustInfo n = error $ "numToTrustInfo: bad input number! (" ++ show n ++ ")"
instance Outputable IfaceTrustInfo where
@@ -2966,6 +2965,7 @@ instance Outputable IfaceTrustInfo where
ppr (TrustInfo Sf_Unsafe) = text "unsafe"
ppr (TrustInfo Sf_Trustworthy) = text "trustworthy"
ppr (TrustInfo Sf_Safe) = text "safe"
+ ppr (TrustInfo Sf_SafeInferred) = text "safe-inferred"
instance Binary IfaceTrustInfo where
put_ bh iftrust = putByte bh $ trustInfoToNum iftrust
diff --git a/compiler/typecheck/TcRnMonad.hs b/compiler/typecheck/TcRnMonad.hs
index e297301b6b..48d8cae841 100644
--- a/compiler/typecheck/TcRnMonad.hs
+++ b/compiler/typecheck/TcRnMonad.hs
@@ -1835,13 +1835,13 @@ finalSafeMode :: DynFlags -> TcGblEnv -> IO SafeHaskellMode
finalSafeMode dflags tcg_env = do
safeInf <- fst <$> readIORef (tcg_safeInfer tcg_env)
return $ case safeHaskell dflags of
- Sf_None | safeInferOn dflags && safeInf -> Sf_Safe
+ Sf_None | safeInferOn dflags && safeInf -> Sf_SafeInferred
| otherwise -> Sf_None
s -> s
-- | Switch instances to safe instances if we're in Safe mode.
fixSafeInstances :: SafeHaskellMode -> [ClsInst] -> [ClsInst]
-fixSafeInstances sfMode | sfMode /= Sf_Safe = id
+fixSafeInstances sfMode | sfMode /= Sf_Safe && sfMode /= Sf_SafeInferred = id
fixSafeInstances _ = map fixSafe
where fixSafe inst = let new_flag = (is_flag inst) { isSafeOverlap = True }
in inst { is_flag = new_flag }
diff --git a/docs/users_guide/safe_haskell.rst b/docs/users_guide/safe_haskell.rst
index bf7f1fb5d0..af016194bf 100644
--- a/docs/users_guide/safe_haskell.rst
+++ b/docs/users_guide/safe_haskell.rst
@@ -740,7 +740,7 @@ And one general flag:
requiring the package that ``M`` resides in be considered trusted, for ``M``
to be considered trusted.
-And three warning flags:
+And four warning flags:
.. ghc-flag:: -Wunsafe
:shortdesc: warn if the module being compiled is regarded to be unsafe.
@@ -777,6 +777,39 @@ And three warning flags:
-XSafe , a more informative bound. Can be used to detect once a Safe Haskell
bound can be improved as dependencies are updated.
+.. ghc-flag:: -Winferred-safe-imports
+ :shortdesc: warn when an explicitly Safe Haskell module imports a Safe-Inferred one
+ :type: dynamic
+ :reverse: -Wno-inferred-safe-imports
+ :category:
+
+ :since: 8.10.1
+
+ .. index::
+ single: safe haskell imports, warning
+
+ The module ``A`` below is annotated to be explictly ``Safe``, but it imports
+ ``Safe-Inferred`` module.
+
+ {-# LANGUAGE Safe #-}
+ module A where
+
+ import B (double)
+
+ quad :: Int -> Int
+ quad = double . double
+
+
+ module B where
+
+ double :: Int -> Int
+ double n = n + n
+
+ The inferred status is volatile: if an unsafe import is added to the module
+ ``B``, it will cause compilation error of ``A``. When
+ :ghc-flag:`-Winferred-safe-imports` is enabled, the compiler will emit a
+ warning about this.
+
.. _safe-compilation:
Safe Compilation
diff --git a/testsuite/tests/plugins/T16260.stdout b/testsuite/tests/plugins/T16260.stdout
index ae9d3fb430..dd1db9a46b 100644
--- a/testsuite/tests/plugins/T16260.stdout
+++ b/testsuite/tests/plugins/T16260.stdout
@@ -1,4 +1,4 @@
False
None
True
-Safe
+Safe-Inferred
diff --git a/testsuite/tests/safeHaskell/check/pkg01/safePkg01.stdout b/testsuite/tests/safeHaskell/check/pkg01/safePkg01.stdout
index 31b2278577..53e219ddd5 100644
--- a/testsuite/tests/safeHaskell/check/pkg01/safePkg01.stdout
+++ b/testsuite/tests/safeHaskell/check/pkg01/safePkg01.stdout
@@ -4,42 +4,42 @@ pdb.safePkg01/local.db
trusted: False
M_SafePkg
-package dependencies: base-4.12.0.0* ghc-prim-0.6.1 integer-gmp-1.0.2.0
+package dependencies: base-4.13.0.0* ghc-prim-0.6.1 integer-gmp-1.0.2.0
trusted: safe
require own pkg trusted: False
M_SafePkg2
-package dependencies: base-4.12.0.0 ghc-prim-0.6.1 integer-gmp-1.0.2.0
+package dependencies: base-4.13.0.0 ghc-prim-0.6.1 integer-gmp-1.0.2.0
trusted: trustworthy
require own pkg trusted: False
M_SafePkg3
-package dependencies: base-4.12.0.0* ghc-prim-0.6.1 integer-gmp-1.0.2.0
+package dependencies: base-4.13.0.0* ghc-prim-0.6.1 integer-gmp-1.0.2.0
trusted: safe
require own pkg trusted: True
M_SafePkg4
-package dependencies: base-4.12.0.0* ghc-prim-0.6.1 integer-gmp-1.0.2.0
+package dependencies: base-4.13.0.0* ghc-prim-0.6.1 integer-gmp-1.0.2.0
trusted: safe
require own pkg trusted: True
M_SafePkg5
-package dependencies: base-4.12.0.0* ghc-prim-0.6.1 integer-gmp-1.0.2.0
-trusted: safe
+package dependencies: base-4.13.0.0* ghc-prim-0.6.1 integer-gmp-1.0.2.0
+trusted: safe-inferred
require own pkg trusted: True
M_SafePkg6
-package dependencies: array-0.5.2.0 base-4.12.0.0* bytestring-0.10.8.2* deepseq-1.4.4.0 ghc-prim-0.6.1 integer-gmp-1.0.2.0
+package dependencies: array-0.5.4.0 base-4.13.0.0* bytestring-0.10.9.0* deepseq-1.4.4.0 ghc-prim-0.6.1 integer-gmp-1.0.2.0
trusted: trustworthy
require own pkg trusted: False
M_SafePkg7
-package dependencies: array-0.5.2.0 base-4.12.0.0* bytestring-0.10.8.2* deepseq-1.4.4.0 ghc-prim-0.6.1 integer-gmp-1.0.2.0
+package dependencies: array-0.5.4.0 base-4.13.0.0* bytestring-0.10.9.0* deepseq-1.4.4.0 ghc-prim-0.6.1 integer-gmp-1.0.2.0
trusted: safe
require own pkg trusted: False
M_SafePkg8
-package dependencies: array-0.5.2.0 base-4.12.0.0 bytestring-0.10.8.2* deepseq-1.4.4.0 ghc-prim-0.6.1 integer-gmp-1.0.2.0
+package dependencies: array-0.5.4.0 base-4.13.0.0 bytestring-0.10.9.0* deepseq-1.4.4.0 ghc-prim-0.6.1 integer-gmp-1.0.2.0
trusted: trustworthy
require own pkg trusted: False
diff --git a/utils/haddock b/utils/haddock
-Subproject 83bb9870a117f9426e6f6cff6fec3bb6e93a7c1
+Subproject 5e333bad752b9c048ad5400b7159e32f4d3d65b