summaryrefslogtreecommitdiff
path: root/testsuite
diff options
context:
space:
mode:
authorRyan Scott <ryan.gl.scott@gmail.com>2020-03-24 18:44:08 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-03-29 17:33:20 -0400
commita0d8e92e9c9b67426aa139d6bc46363d8940f992 (patch)
tree9fdca21dbaae8f20633d3673a3750be866b851f5 /testsuite
parent64bf7f51064dad9c63728ac8bccdb9cf00bdb420 (diff)
downloadhaskell-a0d8e92e9c9b67426aa139d6bc46363d8940f992.tar.gz
Run checkNewDataCon before constraint-solving newtype constructors
Within `checkValidDataCon`, we used to run `checkValidType` on the argument types of a newtype constructor before running `checkNewDataCon`, which ensures that the user does not attempt non-sensical things such as newtypes with multiple arguments or constraints. This works out in most situations, but this falls over on a corner case revealed in #17955: ```hs newtype T = Coercible () T => T () ``` `checkValidType`, among other things, peforms an ambiguity check on the context of a data constructor, and that it turn invokes the constraint solver. It turns out that there is a special case in the constraint solver for representational equalities (read: `Coercible` constraints) that causes newtypes to be unwrapped (see `Note [Unwrap newtypes first]` in `TcCanonical`). This special case does not know how to cope with an ill formed newtype like `T`, so it ends up panicking. The solution is surprisingly simple: just invoke `checkNewDataCon` before `checkValidType` to ensure that the illicit newtype constructor context is detected before the constraint solver can run amok with it. Fixes #17955.
Diffstat (limited to 'testsuite')
-rw-r--r--testsuite/tests/typecheck/should_fail/T17955.hs6
-rw-r--r--testsuite/tests/typecheck/should_fail/T17955.stderr6
-rw-r--r--testsuite/tests/typecheck/should_fail/all.T1
3 files changed, 13 insertions, 0 deletions
diff --git a/testsuite/tests/typecheck/should_fail/T17955.hs b/testsuite/tests/typecheck/should_fail/T17955.hs
new file mode 100644
index 0000000000..1bcb9a6d90
--- /dev/null
+++ b/testsuite/tests/typecheck/should_fail/T17955.hs
@@ -0,0 +1,6 @@
+{-# LANGUAGE FlexibleContexts #-}
+module T17955 where
+
+import Data.Coerce
+
+newtype T = Coercible () T => T ()
diff --git a/testsuite/tests/typecheck/should_fail/T17955.stderr b/testsuite/tests/typecheck/should_fail/T17955.stderr
new file mode 100644
index 0000000000..0762facf45
--- /dev/null
+++ b/testsuite/tests/typecheck/should_fail/T17955.stderr
@@ -0,0 +1,6 @@
+
+T17955.hs:6:13: error:
+ • A newtype constructor cannot have a context in its type
+ T :: Coercible () T => () -> T
+ • In the definition of data constructor ‘T’
+ In the newtype declaration for ‘T’
diff --git a/testsuite/tests/typecheck/should_fail/all.T b/testsuite/tests/typecheck/should_fail/all.T
index 4f8f08ed85..14728794ce 100644
--- a/testsuite/tests/typecheck/should_fail/all.T
+++ b/testsuite/tests/typecheck/should_fail/all.T
@@ -561,3 +561,4 @@ test('T17566c', normal, compile_fail, [''])
test('T17773', normal, compile_fail, [''])
test('T17021', normal, compile_fail, [''])
test('T17021b', normal, compile_fail, [''])
+test('T17955', normal, compile_fail, [''])