[commit: ghc] wip/rae-new-coercible: AppTy reflexivity check (9d4cd32)
git at git.haskell.org
git at git.haskell.org
Tue Dec 2 20:44:14 UTC 2014
Repository : ssh://git@git.haskell.org/ghc
On branch : wip/rae-new-coercible
Link : http://ghc.haskell.org/trac/ghc/changeset/9d4cd3294c09127aef6c8bcaf5475dc44a45d617/ghc
>---------------------------------------------------------------
commit 9d4cd3294c09127aef6c8bcaf5475dc44a45d617
Author: Richard Eisenberg <eir at cis.upenn.edu>
Date: Mon Dec 1 20:20:00 2014 -0500
AppTy reflexivity check
>---------------------------------------------------------------
9d4cd3294c09127aef6c8bcaf5475dc44a45d617
compiler/typecheck/TcCanonical.lhs | 50 +++++++++++++++++++++++++++++++++-----
1 file changed, 44 insertions(+), 6 deletions(-)
diff --git a/compiler/typecheck/TcCanonical.lhs b/compiler/typecheck/TcCanonical.lhs
index 856ad92..2c052a0 100644
--- a/compiler/typecheck/TcCanonical.lhs
+++ b/compiler/typecheck/TcCanonical.lhs
@@ -29,6 +29,7 @@ import RdrName
import Util
import BasicTypes
import Data.Maybe ( isJust )
+import Control.Monad ( liftM )
\end{code}
@@ -546,13 +547,25 @@ can_eq_flat_app ev eq_rel swapped s1 t1 ps_ty1 ty2 ps_ty2
| NomEq <- eq_rel
, Just (s2,t2) <- tcSplitAppTy_maybe ty2
= unSwap swapped decompose_it (s1,t1) (s2,t2)
- | mkAppTy s1 t1 `eqType` ty2 -- this check is necessary for representational
- -- equalities, where we might be unable to
- -- decompose a reflexive constraint, like
- -- Coercible (f a) (f a)
- = canEqReflexive ev eq_rel ty2
| otherwise
- = unSwap swapped (canEqFailure ev eq_rel) ps_ty1 ps_ty2
+ = do { -- See Note [AppTy reflexivity check]
+ mb <- case eq_rel of
+ NomEq -> return Nothing
+ ReprEq ->
+ do { let fmode = mkFlattenEnv ev FM_FlattenAll
+ xi1 = mkAppTy s1 t1
+ ; (xi2, co2) <- flatten fmode ps_ty2
+ ; if xi1 `eqType` xi2
+ then Just `liftM`
+ (rewriteEqEvidence ev eq_rel swapped xi1 xi2
+ (mkTcReflCo Representational xi1) co2
+ `andWhenContinue` \ new_ev ->
+ canEqReflexive new_ev eq_rel xi1)
+ else return Nothing }
+ ; case mb of
+ Just res -> return res
+ Nothing -> -- we're hosed. give up.
+ unSwap swapped (canEqFailure ev eq_rel) ps_ty1 ps_ty2 }
where
decompose_it (s1,t1) (s2,t2)
= do { let xevcomp [x,y] = EvCoercion (mkTcAppCo (evTermCoercion x) (evTermCoercion y))
@@ -580,6 +593,31 @@ we do this eager reflexivity check. This is necessary only for representational
equality because the flattener technology deals with the similar case
(recursive type families) for nominal equality.
+Note [AppTy reflexivity check]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider trying to prove (f a) ~R (f a). The AppTys in there can't
+be decomposed, because representational equality isn't congruent with respect
+to AppTy. So, when canonicalising the equality above, we get stuck and
+would normally produce a CIrredEvCan. However, we really do want to
+be able to solve (f a) ~R (f a). So, in the representational case only,
+we do a reflexivity check.
+
+(This would be sound in the nominal case, but unnecessary, and I [Richard
+E.] am worried that it would slow down the common case. Thus, the somewhat
+awkward use of Maybe (StopOrContinue CtEvidence).)
+
+We must additionally be careful to flatten the RHS of the equality before
+doing the check. Here is a real case that came from the testsuite (T9117_3):
+
+ work item: [W] c1: f a ~R g a
+ inert set: [G] c2: g ~R f
+
+In can_eq_app, we try to flatten the LHS of c1. This causes no effect,
+because `f` cannot be rewritten. So, we go to can_eq_flat_app. Without
+flattening the RHS, the reflexivity check fails, and we give up. However,
+flattening the RHS rewrites `g` to `f`, the reflexivity check succeeds,
+and we go on to glory.
+
\begin{code}
------------------------
More information about the ghc-commits
mailing list