summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitrios Vytiniotis <dimitris@microsoft.com>2011-11-29 19:15:17 +0000
committerDimitrios Vytiniotis <dimitris@microsoft.com>2011-11-29 19:15:17 +0000
commite4d87e140697bcb380cc51a5aee598409930281e (patch)
tree3531bd898c40742983540ab010e46abfea78b489
parent7d13e50487eb7f80be9a8b330ef65e07138b27ef (diff)
downloadhaskell-e4d87e140697bcb380cc51a5aee598409930281e.tar.gz
Insufficient rewriting during flattening. This fixes #5668.
-rw-r--r--compiler/typecheck/TcCanonical.lhs49
1 files changed, 44 insertions, 5 deletions
diff --git a/compiler/typecheck/TcCanonical.lhs b/compiler/typecheck/TcCanonical.lhs
index d8de058c2a..d13b793db6 100644
--- a/compiler/typecheck/TcCanonical.lhs
+++ b/compiler/typecheck/TcCanonical.lhs
@@ -558,18 +558,57 @@ flatten d ctxt ty
= do { (xi, co) <- flatten d ctxt ty'
; return (xi,co) }
- -- The following is tedious to do:
+ -- DV: The following is tedious to do but maybe we should return to this
-- Preserve type synonyms if possible
-- ; if no_flattening
-- then return (xi, mkReflCo xi,no_flattening) -- Importantly, not xi!
-- else return (xi,co,no_flattening)
-- }
-flatten _d ctxt v@(TyVarTy _)
+flatten d ctxt v@(TyVarTy _)
= do { ieqs <- getInertEqs
- ; let co = liftInertEqsTy ieqs ctxt v -- co :: v ~ xi
- new_ty = pSnd (liftedCoercionKind co)
- ; return (new_ty, mkSymCo co) } -- return xi ~ v
+ ; let co = liftInertEqsTy ieqs ctxt v -- co : v ~ ty
+ ty = pSnd (liftedCoercionKind co)
+ ; if v `eqType` ty then
+ return (ty,mkReflCo ty)
+ else -- NB recursive call. Why? See Note [Non-idempotent inert substitution]
+ -- Actually I believe that applying the substition only *twice* will suffice
+
+ do { (ty_final,co') <- flatten d ctxt ty -- co' : ty_final ~ ty
+ ; return (ty_final,co' `mkTransCo` mkSymCo co) } }
+
+\end{code}
+
+Note [Non-idempotent inert substitution]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The inert substitution is not idempotent in the broad sense. It is only idempotent in
+that it cannot rewrite the RHS of other inert equalities any further. An example of such
+an inert substitution is:
+
+ [Ś] g1 : ta8 ~ ta4
+ [W] g2 : ta4 ~ a5Fj
+
+Observe that the wanted cannot rewrite the solved goal, despite the fact that ta4 appears on
+an RHS of an equality. Now, imagine a constraint:
+
+ [W] g3: ta8 ~ Int
+
+coming in. If we simply apply once the inert substitution we will get:
+
+ [W] g3_1: ta4 ~ Int
+
+and because potentially ta4 is untouchable we will try to insert g3_1 in the inert set,
+getting a panic since the inert only allows ONE equation per LHS type variable (as it
+should).
+
+For this reason, when we reach to flatten a type variable, we flatten it recursively,
+so that we can make sure that the inert substitution /is/ fully applied.
+
+This insufficient rewriting was the reason for #5668.
+
+\begin{code}
+
flatten d ctxt (AppTy ty1 ty2)
= do { (xi1,co1) <- flatten d ctxt ty1