summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2015-01-28 14:31:52 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2015-01-28 14:32:31 +0000
commit276da7929c187f007c198a38e88bdad91866e500 (patch)
tree11fdde58d4566f05f525a487e31c44301f93f04d
parentcf3e3406a0b66f1831decd88f8deda5e297f4395 (diff)
downloadhaskell-276da7929c187f007c198a38e88bdad91866e500.tar.gz
Improve error message on typed holes, and user manual (Tradc #10040)
-rw-r--r--compiler/typecheck/TcErrors.hs12
-rw-r--r--docs/users_guide/glasgow_exts.xml73
-rw-r--r--testsuite/tests/typecheck/should_compile/T9497a.stderr1
-rw-r--r--testsuite/tests/typecheck/should_compile/holes3.stderr3
-rw-r--r--testsuite/tests/typecheck/should_fail/T9497d.stderr1
5 files changed, 51 insertions, 39 deletions
diff --git a/compiler/typecheck/TcErrors.hs b/compiler/typecheck/TcErrors.hs
index 31772a229c..6b9be0112f 100644
--- a/compiler/typecheck/TcErrors.hs
+++ b/compiler/typecheck/TcErrors.hs
@@ -636,16 +636,22 @@ mkHoleError ctxt ct@(CHoleCan { cc_occ = occ, cc_hole = hole_sort })
tyvars_msg = map loc_msg tyvars
msg = vcat [ hang (ptext (sLit "Found hole") <+> quotes (ppr occ))
2 (ptext (sLit "with type:") <+> pprType (ctEvPred (ctEvidence ct)))
- , ppUnless (null tyvars_msg) (ptext (sLit "Where:") <+> vcat tyvars_msg)
- , pts_hint ]
+ , ppUnless (null tyvars) (ptext (sLit "Where:") <+> vcat tyvars_msg)
+ , hint ]
; (ctxt, binds_doc, _) <- relevantBindings False ctxt ct
-- The 'False' means "don't filter the bindings"; see Trac #8191
; mkErrorMsgFromCt ctxt ct (msg $$ binds_doc) }
where
- pts_hint
+ hint
| TypeHole <- hole_sort
, HoleError <- cec_type_holes ctxt
= ptext (sLit "To use the inferred type, enable PartialTypeSignatures")
+
+ | ExprHole <- hole_sort -- Give hint for, say, f x = _x
+ , lengthFS (occNameFS occ) > 1 -- Don't give this hint for plain "_", which isn't legal Haskell
+ = ptext (sLit "Or perhaps") <+> quotes (ppr occ)
+ <+> ptext (sLit "is mis-spelled, or not in scope")
+
| otherwise
= empty
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index 190af38d67..279c59c9c4 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -8595,19 +8595,6 @@ check the type of the term they are about to write.
</para>
<para>
-To run and test a piece of code containing holes, use the
-<literal>-fdefer-typed-holes</literal> flag. This flag defers errors
-produced by typed holes and converts them into warnings. The result is that
-typed hole errors are converted into warnings (controlled by
-<literal>-fwarn-typed-holes</literal>). The result is that a hole will behave
-like <literal>undefined</literal>, but with the added benefits that it shows a
-warning at compile time and will show another warning message if it gets
-evaluated. This behaviour follows that of the
-<literal>-fdefer-type-errors</literal> option, which implies
-<literal>-fdefer-typed-holes</literal>. See <xref linkend="defer-type-errors"/>.
-</para>
-
-<para>
For example, compiling the following module with GHC:
<programlisting>
f :: a -> a
@@ -8628,29 +8615,31 @@ hole.hs:2:7:
</para>
<para>
-Multiple typed holes can be used to find common type variables between expressions. For example:
-<programlisting>
-sum :: [Int] -> Int
-sum xs = foldr _f _z xs
-</programlisting>
-Shows:
-<programlisting>
-holes.hs:2:15:
- Found hole `_f' with type: Int -> Int -> Int
- In the first argument of `foldr', namely `_'
- In the expression: foldr _a _b _c
- In an equation for `sum': sum x = foldr _a _b _c
-
-holes.hs:2:17:
- Found hole `_z' with type: Int
- In the second argument of `foldr', namely `_'
- In the expression: foldr _a _b _c
- In an equation for `sum': sum x = foldr _a _b _c
-</programlisting>
+Here are some more details:
+<itemizedlist>
+<listitem>
+<para>
+A "<literal>Found hole</literal>" error usually terminates compilation, like
+any other type error. After all, you have omitted some code from your program.
+Nevertheless, you can run and test a piece of code containing holes, by using the flag
+<option>-fdefer-typed-holes</option> flag. This flag defers errors
+produced by typed holes until runtime, and converts them into compile-time warnings.
+These warnings can in turn
+be suppressed entirely by <option>-fnowarn-typed-holes</option>).
</para>
-
<para>
-Unbound identifiers with the same name are never unified, even within the same function, but always printed individually.
+The result is that a hole will behave
+like <literal>undefined</literal>, but with the added benefits that it shows a
+warning at compile time and will show another warning message if it gets
+evaluated at runtime.. This behaviour follows that of the
+<literal>-fdefer-type-errors</literal> option, which implies
+<literal>-fdefer-typed-holes</literal>. See <xref linkend="defer-type-errors"/>.
+</para>
+</listitem>
+
+<listitem><para>
+Unbound identifiers with the same name are never unified, even within the
+same function, but shown individually.
For example:
<programlisting>
cons = _x : _x
@@ -8676,8 +8665,20 @@ unbound.hs:1:13:
In the expression: _x : _x
In an equation for `cons': cons = _x : _x
</programlisting>
-This ensures that an unbound identifier is never reported with a too polymorphic type, like
-<literal>forall a. a</literal>, when used multiple times for types that can not be unified.
+Notice the two different types reported for the two different occurrences of <literal>_x</literal>.
+</para></listitem>
+
+<listitem><para>
+No language extension is required to use typed holes. The lexeme "<literal>_</literal>" was previously
+illegal in Haskell, but now has a more informative error message. The lexeme "<literal>_x</literal>"
+is a perfectly legal varaible, and its behaviour is unchanged when it is in scope. For example
+<programlisting>
+f _x = _x + 1
+</programlisting>
+does not elict any errors. Only a variable starting with an underscore <emphasis>that is not in scope</emphasis>
+is treated as an error (which it always was), albeit now with a more informative error message
+</para></listitem>
+</itemizedlist>
</para>
</sect1>
diff --git a/testsuite/tests/typecheck/should_compile/T9497a.stderr b/testsuite/tests/typecheck/should_compile/T9497a.stderr
index 763fbaea33..2c39875668 100644
--- a/testsuite/tests/typecheck/should_compile/T9497a.stderr
+++ b/testsuite/tests/typecheck/should_compile/T9497a.stderr
@@ -1,6 +1,7 @@
T9497a.hs:2:8: Warning:
Found hole ‘_main’ with type: IO ()
+ Or perhaps ‘_main’ is mis-spelled, or not in scope
Relevant bindings include main :: IO () (bound at T9497a.hs:2:1)
In the expression: _main
In an equation for ‘main’: main = _main
diff --git a/testsuite/tests/typecheck/should_compile/holes3.stderr b/testsuite/tests/typecheck/should_compile/holes3.stderr
index e203acaa74..17b786c7bd 100644
--- a/testsuite/tests/typecheck/should_compile/holes3.stderr
+++ b/testsuite/tests/typecheck/should_compile/holes3.stderr
@@ -9,6 +9,7 @@ holes3.hs:3:5:
holes3.hs:6:7:
Found hole ‘_gr’ with type: Char
+ Or perhaps ‘_gr’ is mis-spelled, or not in scope
Relevant bindings include
x :: Int (bound at holes3.hs:6:3)
g :: Int -> Char (bound at holes3.hs:6:1)
@@ -17,6 +18,7 @@ holes3.hs:6:7:
holes3.hs:8:5:
Found hole ‘_aa’ with type: [Char]
+ Or perhaps ‘_aa’ is mis-spelled, or not in scope
Relevant bindings include h :: [Char] (bound at holes3.hs:8:1)
In the first argument of ‘(++)’, namely ‘_aa’
In the expression: _aa ++ "a"
@@ -25,6 +27,7 @@ holes3.hs:8:5:
holes3.hs:11:15:
Found hole ‘_x’ with type: b0
Where: ‘b0’ is an ambiguous type variable
+ Or perhaps ‘_x’ is mis-spelled, or not in scope
Relevant bindings include
y :: [a] (bound at holes3.hs:11:3)
z :: [a] -> [a] (bound at holes3.hs:11:1)
diff --git a/testsuite/tests/typecheck/should_fail/T9497d.stderr b/testsuite/tests/typecheck/should_fail/T9497d.stderr
index 4f18ce9497..ee23278e53 100644
--- a/testsuite/tests/typecheck/should_fail/T9497d.stderr
+++ b/testsuite/tests/typecheck/should_fail/T9497d.stderr
@@ -1,6 +1,7 @@
T9497d.hs:2:8:
Found hole ‘_main’ with type: IO ()
+ Or perhaps ‘_main’ is mis-spelled, or not in scope
Relevant bindings include main :: IO () (bound at T9497d.hs:2:1)
In the expression: _main
In an equation for ‘main’: main = _main