[commit: ghc] master: Fix #10493. (ace8d4f)
git at git.haskell.org
git at git.haskell.org
Tue Jun 16 18:22:44 UTC 2015
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/ace8d4fcfd798b70c34e325c562878b0a8f5e2cb/ghc
>---------------------------------------------------------------
commit ace8d4fcfd798b70c34e325c562878b0a8f5e2cb
Author: Richard Eisenberg <eir at cis.upenn.edu>
Date: Mon Jun 8 16:46:46 2015 -0400
Fix #10493.
Now, a Coercible (T1 ...) (T2 ...) constraint is insoluble only
when both T1 and T2 say "yes" to isDistinctTyCon. Several comments
also updated in this patch.
>---------------------------------------------------------------
ace8d4fcfd798b70c34e325c562878b0a8f5e2cb
compiler/typecheck/TcCanonical.hs | 11 +++++++++--
compiler/types/TyCon.hs | 2 +-
compiler/types/Unify.hs | 11 +++++++++--
testsuite/tests/typecheck/should_compile/T10493.hs | 9 +++++++++
testsuite/tests/typecheck/should_compile/all.T | 1 +
5 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/compiler/typecheck/TcCanonical.hs b/compiler/typecheck/TcCanonical.hs
index ab9d2c2..e69f12d 100644
--- a/compiler/typecheck/TcCanonical.hs
+++ b/compiler/typecheck/TcCanonical.hs
@@ -665,7 +665,7 @@ canDecomposableTyConApp ev eq_rel tc1 tys1 tc2 tys2
-- Fail straight away for better error messages
-- See Note [Use canEqFailure in canDecomposableTyConApp]
- | isDataFamilyTyCon tc1 || isDataFamilyTyCon tc2
+ | eq_rel == ReprEq && not (isDistinctTyCon tc1 && isDistinctTyCon tc2)
= canEqFailure ev eq_rel ty1 ty2
| otherwise
= canEqHardFailure ev eq_rel ty1 ty2
@@ -678,7 +678,7 @@ Note [Use canEqFailure in canDecomposableTyConApp]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We must use canEqFailure, not canEqHardFailure here, because there is
the possibility of success if working with a representational equality.
-Here is the case:
+Here is one case:
type family TF a where TF Char = Bool
data family DF a
@@ -688,6 +688,13 @@ Suppose we are canonicalising (Int ~R DF (T a)), where we don't yet
know `a`. This is *not* a hard failure, because we might soon learn
that `a` is, in fact, Char, and then the equality succeeds.
+Here is another case:
+
+ [G] Coercible Age Int
+
+where Age's constructor is not in scope. We don't want to report
+an "inaccessible code" error in the context of this Given!
+
Note [Decomposing newtypes]
~~~~~~~~~~~~~~~~~~~~~~~~~~~
As explained in Note [NthCo and newtypes] in Coercion, we can't use
diff --git a/compiler/types/TyCon.hs b/compiler/types/TyCon.hs
index 94fba28..71111c0 100644
--- a/compiler/types/TyCon.hs
+++ b/compiler/types/TyCon.hs
@@ -1211,7 +1211,7 @@ isDataTyCon (AlgTyCon {algTcRhs = rhs})
isDataTyCon _ = False
-- | 'isDistinctTyCon' is true of 'TyCon's that are equal only to
--- themselves, even via coercions (except for unsafeCoerce).
+-- themselves, even via representational coercions (except for unsafeCoerce).
-- This excludes newtypes, type functions, type synonyms.
-- It relates directly to the FC consistency story:
-- If the axioms are consistent,
diff --git a/compiler/types/Unify.hs b/compiler/types/Unify.hs
index 0bfcfab..218dc99 100644
--- a/compiler/types/Unify.hs
+++ b/compiler/types/Unify.hs
@@ -280,8 +280,8 @@ to 'Bool', in which case x::T Int, so
Suppose x::T X. Then *in Haskell* it's impossible to construct a (non-bottom)
value of type (T X) using T1. But *in FC* it's quite possible. The newtype
gives a coercion
- CoX :: X ~ Int
-So (T CoX) :: T X ~ T Int; hence (T1 `cast` sym (T CoX)) is a non-bottom value
+ CoX :: X ~R Int
+So (T CoX)_R :: T X ~R T Int; hence (T1 `cast` sym (T CoX)) is a non-bottom value
of type (T X) constructed with T1. Hence
ANSWER = NO we can't prune the T1 branch (surprisingly)
@@ -317,6 +317,13 @@ drop more and more dead code.
For now we implement a very simple test: type variables match
anything, type functions (incl newtypes) match anything, and only
distinct data types fail to match. We can elaborate later.
+
+NB: typesCantMatch is subtly different than the apartness checks
+elsewhere in this module. It reasons over *representational* equality
+(saying that a newtype is not distinct from its representation) whereas
+the checks in, say, tcUnifyTysFG are about *nominal* equality. tcUnifyTysFG
+also assumes that its inputs are type-family-free, whereas no such assumption
+is in play here.
-}
typesCantMatch :: [(Type,Type)] -> Bool
diff --git a/testsuite/tests/typecheck/should_compile/T10493.hs b/testsuite/tests/typecheck/should_compile/T10493.hs
new file mode 100644
index 0000000..3e3caae
--- /dev/null
+++ b/testsuite/tests/typecheck/should_compile/T10493.hs
@@ -0,0 +1,9 @@
+{-# LANGUAGE FlexibleContexts #-}
+
+module T10493 where
+
+import Data.Coerce
+import Data.Ord (Down) -- no constructor
+
+foo :: Coercible (Down Int) Int => Down Int -> Int
+foo = coerce
diff --git a/testsuite/tests/typecheck/should_compile/all.T b/testsuite/tests/typecheck/should_compile/all.T
index 1f5623d..e26d27a 100644
--- a/testsuite/tests/typecheck/should_compile/all.T
+++ b/testsuite/tests/typecheck/should_compile/all.T
@@ -460,3 +460,4 @@ test('T10423', normal, compile, [''])
test('T10489', normal, compile, [''])
test('T10348', normal, compile, [''])
test('T10494', normal, compile, [''])
+test('T10493', normal, compile, [''])
More information about the ghc-commits
mailing list