diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2015-01-28 14:31:52 +0000 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2015-01-28 14:32:31 +0000 |
commit | 276da7929c187f007c198a38e88bdad91866e500 (patch) | |
tree | 11fdde58d4566f05f525a487e31c44301f93f04d | |
parent | cf3e3406a0b66f1831decd88f8deda5e297f4395 (diff) | |
download | haskell-276da7929c187f007c198a38e88bdad91866e500.tar.gz |
Improve error message on typed holes, and user manual (Tradc #10040)
-rw-r--r-- | compiler/typecheck/TcErrors.hs | 12 | ||||
-rw-r--r-- | docs/users_guide/glasgow_exts.xml | 73 | ||||
-rw-r--r-- | testsuite/tests/typecheck/should_compile/T9497a.stderr | 1 | ||||
-rw-r--r-- | testsuite/tests/typecheck/should_compile/holes3.stderr | 3 | ||||
-rw-r--r-- | testsuite/tests/typecheck/should_fail/T9497d.stderr | 1 |
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 |