summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2018-01-03 10:51:18 +0000
committerSimon Peyton Jones <simonpj@microsoft.com>2018-01-03 11:26:20 +0000
commit298ec78c8832b391c19d662576e59c3e16bd43b0 (patch)
treeb37bb597b4e5c313e93f391d151389d6f30aba08
parentbd438b2d67ec8f5d8ac8472f13b3175b569951b9 (diff)
downloadhaskell-298ec78c8832b391c19d662576e59c3e16bd43b0.tar.gz
No deferred type errors under a forall
As Trac #14605 showed, we can't defer a type error under a 'forall' (when unifying two forall types). The fix is simple.
-rw-r--r--compiler/typecheck/TcErrors.hs29
-rw-r--r--docs/users_guide/glasgow_exts.rst23
-rw-r--r--testsuite/tests/typecheck/should_fail/T14605.hs14
-rw-r--r--testsuite/tests/typecheck/should_fail/T14605.stderr10
-rw-r--r--testsuite/tests/typecheck/should_fail/all.T1
5 files changed, 67 insertions, 10 deletions
diff --git a/compiler/typecheck/TcErrors.hs b/compiler/typecheck/TcErrors.hs
index 6710434f29..e372c30971 100644
--- a/compiler/typecheck/TcErrors.hs
+++ b/compiler/typecheck/TcErrors.hs
@@ -378,16 +378,25 @@ reportImplic ctxt implic@(Implic { ic_skols = tvs, ic_given = given
implic' = implic { ic_skols = tvs'
, ic_given = map (tidyEvVar env1) given
, ic_info = info' }
- ctxt' = ctxt { cec_tidy = env1
- , cec_encl = implic' : cec_encl ctxt
-
- , cec_suppress = insoluble || cec_suppress ctxt
- -- Suppress inessential errors if there
- -- are insolubles anywhere in the
- -- tree rooted here, or we've come across
- -- a suppress-worthy constraint higher up (Trac #11541)
-
- , cec_binds = evb }
+ ctxt1 | termEvidenceAllowed info = ctxt
+ | otherwise = ctxt { cec_defer_type_errors = TypeError }
+ -- If we go inside an implication that has no term
+ -- evidence (i.e. unifying under a forall), we can't defer
+ -- type errors. You could imagine using the /enclosing/
+ -- bindings (in cec_binds), but that may not have enough stuff
+ -- in scope for the bindings to be well typed. So we just
+ -- switch off deferred type errors altogether. See Trac #14605.
+
+ ctxt' = ctxt1 { cec_tidy = env1
+ , cec_encl = implic' : cec_encl ctxt
+
+ , cec_suppress = insoluble || cec_suppress ctxt
+ -- Suppress inessential errors if there
+ -- are insolubles anywhere in the
+ -- tree rooted here, or we've come across
+ -- a suppress-worthy constraint higher up (Trac #11541)
+
+ , cec_binds = evb }
dead_givens = case status of
IC_Solved { ics_dead = dead } -> dead
diff --git a/docs/users_guide/glasgow_exts.rst b/docs/users_guide/glasgow_exts.rst
index 03ea986de7..6704b87250 100644
--- a/docs/users_guide/glasgow_exts.rst
+++ b/docs/users_guide/glasgow_exts.rst
@@ -11231,6 +11231,29 @@ demonstrates:
Prelude> fst x
True
+Limitations of deferred type errors
+-----------------------------------
+The errors that can be deferred are:
+
+- Out of scope term variables
+- Equality constraints; e.g. `ord True` gives rise to an insoluble equality constraint `Char ~ Bool`, which can be deferred.
+- Type-class and implicit-parameter constraints
+
+All other type errors are reported immediately, and cannot be deferred; for
+example, an ill-kinded type signature, an instance declaration that is
+non-terminating or ill-formed, a type-family instance that does not
+obey the declared injectivity constraints, etc etc.
+
+In a few cases, even equality constraints cannot be deferred. Specifically:
+
+- Kind-equalities cannot be deferred, e.g. ::
+
+ f :: Int Bool -> Char
+
+ This type signature contains a kind error which cannot be deferred.
+
+- Type equalities under a forall cannot be deferred (c.f. Trac #14605).
+
.. _template-haskell:
Template Haskell
diff --git a/testsuite/tests/typecheck/should_fail/T14605.hs b/testsuite/tests/typecheck/should_fail/T14605.hs
new file mode 100644
index 0000000000..4f75d59ebd
--- /dev/null
+++ b/testsuite/tests/typecheck/should_fail/T14605.hs
@@ -0,0 +1,14 @@
+{-# Language TypeApplications #-}
+{-# Language ImpredicativeTypes #-}
+-- This isn't a test for impredicative types; it's
+-- just that visible type application on a for-all type
+-- is an easy way to provoke the error.
+--
+-- The ticket #14605 has a much longer example that
+-- also fails; it does not use ImpredicativeTypes
+
+module T14605 where
+
+import GHC.Prim (coerce)
+
+duplicate = coerce @(forall x. ()) @(forall x. x)
diff --git a/testsuite/tests/typecheck/should_fail/T14605.stderr b/testsuite/tests/typecheck/should_fail/T14605.stderr
new file mode 100644
index 0000000000..09181c6ee8
--- /dev/null
+++ b/testsuite/tests/typecheck/should_fail/T14605.stderr
@@ -0,0 +1,10 @@
+
+T14605.hs:14:13: error:
+ • Couldn't match representation of type ‘x1’ with that of ‘()’
+ arising from a use of ‘coerce’
+ ‘x1’ is a rigid type variable bound by
+ the type ()
+ at T14605.hs:14:1-49
+ • In the expression: coerce @(forall x. ()) @(forall x. x)
+ In an equation for ‘duplicate’:
+ duplicate = coerce @(forall x. ()) @(forall x. x)
diff --git a/testsuite/tests/typecheck/should_fail/all.T b/testsuite/tests/typecheck/should_fail/all.T
index 2d8137f694..b8c3c4c1eb 100644
--- a/testsuite/tests/typecheck/should_fail/all.T
+++ b/testsuite/tests/typecheck/should_fail/all.T
@@ -464,3 +464,4 @@ test('T14390', normal, compile_fail, [''])
test('MissingExportList03', normal, compile_fail, [''])
test('T14618', normal, compile_fail, [''])
test('T14607', normal, compile, [''])
+test('T14605', normal, compile_fail, [''])