summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Bolingbroke <batterseapower@hotmail.com>2011-10-25 10:28:31 +0100
committerMax Bolingbroke <batterseapower@hotmail.com>2011-10-25 10:28:49 +0100
commit95d66964bb315f1c500f179ab2da001d8f52e2ac (patch)
treec4c3d41ff8047657eada2bf9b2f3f61b474ed9e3
parentcc3c2bd9bc2d95e2a3bac70d126c9f2e33f22cf2 (diff)
downloadhaskell-95d66964bb315f1c500f179ab2da001d8f52e2ac.tar.gz
Fix infinite loop in PredTYpe size checking (#5581)
-rw-r--r--compiler/typecheck/TcMType.lhs37
1 files changed, 31 insertions, 6 deletions
diff --git a/compiler/typecheck/TcMType.lhs b/compiler/typecheck/TcMType.lhs
index f67df5a054..c362e62fe5 100644
--- a/compiler/typecheck/TcMType.lhs
+++ b/compiler/typecheck/TcMType.lhs
@@ -1480,6 +1480,9 @@ checkValidInstance hs_type tyvars theta clas inst_tys
L loc _ -> loc
\end{code}
+Note [Paterson conditions]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
Termination test: the so-called "Paterson conditions" (see Section 5 of
"Understanding functionsl dependencies via Constraint Handling Rules,
JFP Jan 2007).
@@ -1628,7 +1631,6 @@ fvTypes tys = concat (map fvType tys)
-- Size of a type: the number of variables and constructors
sizeType :: Type -> Int
sizeType ty | Just exp_ty <- tcView ty = sizeType exp_ty
-sizeType ty | isPredTy ty = sizePred ty
sizeType (TyVarTy _) = 1
sizeType (TyConApp _ tys) = sizeTypes tys + 1
sizeType (FunTy arg res) = sizeType arg + sizeType res + 1
@@ -1638,18 +1640,41 @@ sizeType (ForAllTy _ ty) = sizeType ty
sizeTypes :: [Type] -> Int
sizeTypes xs = sum (map sizeType xs)
--- Size of a predicate
+-- Size of a predicate: the number of variables and constructors
+--
+-- Note [Paterson conditions on PredTypes]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--
-- We are considering whether *class* constraints terminate
--- Once we get into an implicit parameter or equality we
--- can't get back to a class constraint, so it's safe
--- to say "size 0". See Trac #4200.
+-- (see Note [Paterson conditions]). Precisely, the Paterson conditions
+-- would have us check that "the constraint has fewer constructors and variables
+-- (taken together and counting repetitions) than the head.".
+--
+-- However, we can be a bit more refined by looking at which kind of constraint
+-- this actually is. There are two main tricks:
+--
+-- 1. It seems like it should be OK not to count the tuple type constructor
+-- for a PredType like (Show a, Eq a) :: Constraint, since we don't
+-- count the "implicit" tuple in the ThetaType itself.
+--
+-- In fact, the Paterson test just checks *each component* of the top level
+-- ThetaType against the size bound, one at a time. By analogy, it should be
+-- OK to return the size of the *largest* tuple component as the size of the
+-- whole tuple.
+--
+-- 2. Once we get into an implicit parameter or equality we
+-- can't get back to a class constraint, so it's safe
+-- to say "size 0". See Trac #4200.
+--
+-- NB: we don't want to detect PredTypes in sizeType (and then call
+-- sizePred on them), or we might get an infinite loop if that PredType
+-- is irreducible. See Trac #5581.
sizePred :: PredType -> Int
sizePred ty = go (predTypePredTree ty)
where
go (ClassPred _ tys') = sizeTypes tys'
go (IPPred {}) = 0
go (EqPred {}) = 0
- go (TuplePred ts) = sum (map go ts)
+ go (TuplePred ts) = maximum (0:map go ts)
go (IrredPred ty) = sizeType ty
\end{code}