[commit: ghc] master: Use tyCoVarsOfType for CTyEqCan in shouldSplitWD (afa409f)
git at git.haskell.org
git at git.haskell.org
Fri Feb 3 17:47:22 UTC 2017
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/afa409faffba6c340db9ee20f7fa2634ac4f8cd0/ghc
>---------------------------------------------------------------
commit afa409faffba6c340db9ee20f7fa2634ac4f8cd0
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date: Fri Feb 3 16:15:56 2017 +0000
Use tyCoVarsOfType for CTyEqCan in shouldSplitWD
An ASSERT failure in rewritableTyVars made me realise
that there was an outright bug in shouldSplitWD. See
the long Note [Splitting WD constraints].
>---------------------------------------------------------------
afa409faffba6c340db9ee20f7fa2634ac4f8cd0
compiler/typecheck/TcSMonad.hs | 52 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 47 insertions(+), 5 deletions(-)
diff --git a/compiler/typecheck/TcSMonad.hs b/compiler/typecheck/TcSMonad.hs
index 7e19ea9..caa20e0 100644
--- a/compiler/typecheck/TcSMonad.hs
+++ b/compiler/typecheck/TcSMonad.hs
@@ -1043,7 +1043,8 @@ can rewrite it. Then:
[WD] fmv ~ Maybe e -- (C)
[WD] Foo ee ~ fmv
-Now the work item is rewritten by (C) and we soon get ee := e.
+See Note [Splitting WD constraints]. Now the work item is rewritten
+by (C) and we soon get ee := e.
Additional notes:
@@ -1066,6 +1067,41 @@ Additional notes:
* inert_funeqs, inert_dicts is a finite map keyed by
the type; it's inconvenient for it to map to TWO constraints
+Note [Splitting WD constraints]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We are about to add a [WD] constraint to the inert set; and we
+know that the inert set has fully rewritten it. Should we split
+it into [W] and [D], and put the [D] in the work list for further
+work?
+
+* CDictCan (C tys) or CFunEqCan (F tys ~ fsk):
+ Yes if the inert set couuld rerite tys to make the class constraint,
+ or type family, fire. That is, yes if the inert_eqs interects
+ with the free vars of tys. For this test we use rewriteableTyVars
+ which ignores casts and coercions in tys, because rewriting the
+ casts or coercions won't make the thing fire more often.
+
+* CTyEqCan (a ~ ty): Yes if the inert set could rewrite 'a' or 'ty'.
+ We need to check both 'a' and 'ty' against the inert set:
+ - Inert set contains [D] a ~ ty2
+ Then we want to put [D] a ~ ty in the worklist, so we'll
+ get [D] ty ~ ty2 with consequent good things
+
+ - Inert set constains [D] b ~ a, where b is in ty.
+ We can't just add [WD] a ~ ty[b] to the inert set, because
+ that breaks the inert-set invariants. If we tried to
+ canonicalise another [D] constraint mentioning 'a', we'd
+ get an infinite loop
+
+ Moreover we must use the full-blown (tyVarsOfType ty) for the
+ RHS, for two reasons:
+ 1. even tyvars in the casts and coercions could give
+ an infinite loop
+ 2. rewritableTyVarsOfType doesn't handle foralls (just
+ because it doesn't need to)
+
+* Others: nothing is gained by splitting.
+
Note [Examples of how Derived shadows helps completeness]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Trac #10009, a very nasty example:
@@ -1211,14 +1247,20 @@ shouldSplitWD :: InertEqs -> Ct -> Bool
-- Precondition: 'ct' is [WD], and is inert
-- True <=> we should split ct ito [W] and [D] because
-- the inert_eqs can make progress on the [D]
-
+-- See Note [Splitting WD constraints]
shouldSplitWD inert_eqs (CFunEqCan { cc_tyargs = tys })
= inert_eqs `intersects_with` rewritableTyVarsOfTypes tys
-- We don't need to split if the tv is the RHS fsk
-shouldSplitWD inert_eqs ct
- = inert_eqs `intersects_with` rewritableTyVarsOfType (ctPred ct)
- -- Otherwise split if the tv is mentioned at all
+shouldSplitWD inert_eqs (CDictCan { cc_tyargs = tys })
+ = inert_eqs `intersects_with` rewritableTyVarsOfTypes tys
+
+shouldSplitWD inert_eqs (CTyEqCan { cc_tyvar = tv, cc_rhs = ty })
+ = tv `elemDVarEnv` inert_eqs
+ || inert_eqs `intersects_with` tyCoVarsOfType ty
+ -- See Note [Splitting WD constraints]
+
+shouldSplitWD _ _ = False -- No point in splitting otherwise
intersects_with :: InertEqs -> TcTyVarSet -> Bool
intersects_with inert_eqs free_vars
More information about the ghc-commits
mailing list