Commit b260034a authored by dterei's avatar dterei

SafeHaskell: Improvements to user guide

parent 1d704e17
...@@ -62,9 +62,9 @@ ...@@ -62,9 +62,9 @@
</itemizedlist> </itemizedlist>
Put simply, these three properties guarantee that you can trust the types Put simply, these three properties guarantee that you can trust the types
in the Safe language, can trust module export lists are respected in the Safe language, can trust that module export lists are respected
in the Safe language and that code which successfully compiles in the Safe in the Safe language and can trust that code which successfully compiles
language has the same meaning as it normally would. Please see in the Safe language has the same meaning as it normally would. Please see
<xref linkend="safe-language"/> for a more detailed view of the safe <xref linkend="safe-language"/> for a more detailed view of the safe
language. language.
</sect2> </sect2>
...@@ -85,8 +85,8 @@ ...@@ -85,8 +85,8 @@
<emphasis>-XTrustworthy</emphasis>, <emphasis>-XSafeLanguage</emphasis> or <emphasis>-XTrustworthy</emphasis>, <emphasis>-XSafeLanguage</emphasis> or
<emphasis>-XSafeImports</emphasis> flags and corresponding PRAGMA's. When <emphasis>-XSafeImports</emphasis> flags and corresponding PRAGMA's. When
either the <emphasis>-XSafe</emphasis> or either the <emphasis>-XSafe</emphasis> or
<emphasis>-XSafeLanguage</emphasis> flag is used, all imports are assumed to <emphasis>-XSafeLanguage</emphasis> flag is used, the safe keyword is
be safe imports. allowed but meaningless -- all imports are safe regardless.
</sect2> </sect2>
<sect2 id="safe-trust"> <sect2 id="safe-trust">
...@@ -101,30 +101,24 @@ ...@@ -101,30 +101,24 @@
may invoke unsafe functions internally, the module's author claims that may invoke unsafe functions internally, the module's author claims that
it exports an API that can't be used in an unsafe way. This doesn't enable it exports an API that can't be used in an unsafe way. This doesn't enable
the Safe language or place any restrictions on the allowed Haskell code. the Safe language or place any restrictions on the allowed Haskell code.
The trust guarantee is provided by the module author, not GHC. Modules The trust guarantee is provided by the module author, not GHC. An import
imported with the <emphasis>safe</emphasis> import feature are required statement with the safe keyword results in a compilation error if the
to be trusted but otherwise unsafe modules can be imported as usual. imported module is not trussted. An import statement without the keyword
</listitem> behaves as usual and can import any module whether trusted or
</itemizedlist> not.</listitem>
The definition of trust for a module <emphasis>M</emphasis>, residing in
a package <emphasis>P</emphasis> for a user of GHC, a client
<emphasis>C</emphasis> (someone who is compiling a source module with GHC,
aka you!), is defined as follows:
A <emphasis>package P is trusted by client C</emphasis> if and only if one of
these conditions hold:
<itemizedlist>
<listitem>C's package database records that P is trusted (and no
command-line arguments override this).</listitem>
<listitem>C's command-line flags say to trust it regardless of the
what is recorded in the package database.</listitem>
</itemizedlist> </itemizedlist>
It is important to note that C is the only authority on package trust. It is Whether or not a module is trusted depends on a notion of trust for
up to the client to decide which packages they trust. packages, which is determined by the client C invoking GHC (i.e., you). A
package <emphasis>P</emphasis> is trusted when either C's package database
A <emphasis>module M is trusted by a client C</emphasis> if and only if: records that <emphasis>P</emphasis> is trusted (and no command-line
arguments override this), or C's command-line flags say to trust it
regardless of what is recorded in the package database. In either case, C
is the only authority on package trust. It is up to the client to decide
which packages they trust.
Now a <emphasis>module M in a package P is trusted by a client C</emphasis>
if and only if:
<itemizedlist> <itemizedlist>
<listitem>Both of these hold: <listitem>Both of these hold:
<itemizedlist> <itemizedlist>
...@@ -169,13 +163,17 @@ ...@@ -169,13 +163,17 @@
Suppose a client C decides to trust package P. Then does C trust module M? Suppose a client C decides to trust package P. Then does C trust module M?
To decide, GHC must check M's imports: M imports System.IO.Unsafe. M was To decide, GHC must check M's imports: M imports System.IO.Unsafe. M was
compiled with -XTrustworthy, so P's author takes responsibility for that compiled with -XTrustworthy, so P's author takes responsibility for that
import. C trusts P's author, so C trusts M. M has a safe import of import. C trusts P's author, so C trusts M to only use its unsafe
Buggle, so P's author takes no responsibility for the safety or otherwise imports (System.IO.Unsafe in this example)in a safe and consistent
of Buggle. So C must check whether Buggle is trusted by C. Is it? Well, manner with respect the API M exposes. M also has a safe import of
it is compiled with -XSafe, so the code in Buggle itself is Buggle, so for this import P's author takes no responsibility for the
machine-checked to be OK, but again under the assumption that Buggle's safety or otherwise. So GHC must check whether Buggle is trusted by C.
imports are trusted by C. Prelude comes from base, which C Is it? Well, it is compiled with -XSafe, so the code in Buggle itself is
trusts, and is compiled with -XTrustworthy. machine-checked to be OK, but again under the assumption that all of
Buggle's imports are trusted by C. Prelude comes from base, which C
trusts, and is compiled with -XTrustworthy (While Prelude is typically
imported implicitly, it still obeys the same rules outlined here). So
Buggle is considered trusted.
Notice that C didn't need to trust package Wuggle; the machine checking Notice that C didn't need to trust package Wuggle; the machine checking
is enough. C only needs to trust packages that have -XTrustworthy is enough. C only needs to trust packages that have -XTrustworthy
...@@ -253,7 +251,8 @@ ...@@ -253,7 +251,8 @@
module then specifies that they trust the module author by module then specifies that they trust the module author by
specifying they trust the package containing the module. specifying they trust the package containing the module.
'-XTrustworthy' has no effect on the accepted range of Haskell '-XTrustworthy' has no effect on the accepted range of Haskell
programs or their semantics.</listitem> programs or their semantics, except that they allow the safe
import keyword.</listitem>
<listitem><emphasis>Module Trusted:</emphasis> Yes but only if <listitem><emphasis>Module Trusted:</emphasis> Yes but only if
Package the module resides in is also trusted.</listitem> Package the module resides in is also trusted.</listitem>
<listitem><emphasis>Haskell Language:</emphasis> Unrestricted <listitem><emphasis>Haskell Language:</emphasis> Unrestricted
...@@ -303,15 +302,15 @@ ...@@ -303,15 +302,15 @@
at the GHC command-line to specify the trust property of packages: at the GHC command-line to specify the trust property of packages:
<itemizedlist> <itemizedlist>
<listitem><emphasis>-trust P:</emphasis> Exposes package P if it was <listitem><emphasis>-trust P</emphasis>: Exposes package P if it was
hidden and considers it a trusted package regardless of the package hidden and considers it a trusted package regardless of the package
database.</listitem> database.</listitem>
<listitem><emphasis>-distrust P: Exposes package P if it was hidden and <listitem><emphasis>-distrust P</emphasis>: Exposes package P if it was
considers it a untrusted package regardless of the package hidden and considers it an untrusted package regardless of the
database.</emphasis></listitem> package database.</listitem>
<listitem><emphasis>-distrust-all-packages: Considers all packages <listitem><emphasis>-distrust-all-packages</emphasis>: Considers all
distrusted unless they are explicitly set to be trusted by subsequent packages distrusted unless they are explicitly set to be trusted by
command-line options.</emphasis></listitem> subsequent command-line options.</listitem>
</itemizedlist> </itemizedlist>
To set a package's trust property in the package database please refer to <xref linkend="packages"/>. To set a package's trust property in the package database please refer to <xref linkend="packages"/>.
...@@ -353,13 +352,14 @@ ...@@ -353,13 +352,14 @@
instance definition) in a way that changes the behaviour of code instance definition) in a way that changes the behaviour of code
importing the untrusted module. The extension is not disabled for a importing the untrusted module. The extension is not disabled for a
module M compiled with -XSafe or -XSafeLanguage but restricted. module M compiled with -XSafe or -XSafeLanguage but restricted.
While M can defined overlapping instance declarations, they can While M can define overlapping instance declarations, they can
only be used in M. If in a module N that imports M, at a call site only overlap other instance declaration defined in M. If in a module N
that uses a type-class function there is a choice of which instance that imports M, at a call site that uses type-class function there is
to use (i.e overlapping) and the most specific choice is from M (or a choice of which instance to use (i.e. overlapping) and the most
any other Safe compiled module), then compilation will fail. It is specific instances is from M, then all the other choices must also be
irrelevant if module N is considered Safe, or Trustworthy or from M. If not, a compilation error will occur. A simple way to think
neither.</listitem> of this is a <emphasis>same origin policy</emphasis> for overlapping
instances defined in Safe compiled modules.</listitem>
</itemizedlist> </itemizedlist>
</sect2> </sect2>
...@@ -372,7 +372,7 @@ ...@@ -372,7 +372,7 @@
<title>Enforcing Good Programming Style</title> <title>Enforcing Good Programming Style</title>
Over-reliance on magic functions such as unsafePerformIO or magic symbols Over-reliance on magic functions such as unsafePerformIO or magic symbols
such as #realWorld can lead to less elegant Haskell code. The Safe dialect such as realWorld# can lead to less elegant Haskell code. The Safe dialect
formalizes this notion of magic and prohibits its use. Thus, people may formalizes this notion of magic and prohibits its use. Thus, people may
encourage their collaborators to use the Safe dialect, except when truly encourage their collaborators to use the Safe dialect, except when truly
necessary, so as to promote better programming style. It can be thought necessary, so as to promote better programming style. It can be thought
...@@ -424,12 +424,12 @@ ...@@ -424,12 +424,12 @@
rioReadFile :: FilePath -> RIO String rioReadFile :: FilePath -> RIO String
rioReadFile file = UnsafeRIO $ do rioReadFile file = UnsafeRIO $ do
ok &lt; pathOK file ok &lt;- pathOK file
if ok then readFile file else return "" if ok then readFile file else return ""
rioWriteFile :: FilePath -> String -> RIO () rioWriteFile :: FilePath -> String -> RIO ()
rioWriteFile file contents = UnsafeRIO $ do rioWriteFile file contents = UnsafeRIO $ do
ok &lt; pathOK file ok &lt;- pathOK file
if ok then writeFile file contents else return () if ok then writeFile file contents else return ()
</programlisting> </programlisting>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment