diff options
-rw-r--r-- | compiler/main/DynFlags.hs | 18 | ||||
-rw-r--r-- | compiler/main/HscMain.hs | 18 | ||||
-rw-r--r-- | compiler/main/HscTypes.hs | 6 | ||||
-rw-r--r-- | compiler/typecheck/TcRnMonad.hs | 4 | ||||
-rw-r--r-- | docs/users_guide/safe_haskell.rst | 35 | ||||
-rw-r--r-- | testsuite/tests/plugins/T16260.stdout | 2 | ||||
-rw-r--r-- | testsuite/tests/safeHaskell/check/pkg01/safePkg01.stdout | 18 | ||||
m--------- | utils/haddock | 0 |
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 |