[commit: ghc] master: Fix the superclass-cycle detection code (Trac #9739) (7c79633)
git at git.haskell.org
git at git.haskell.org
Tue Nov 4 10:39:00 UTC 2014
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/7c79633688238086ad60e1d23e0a424bb4eb325f/ghc
>---------------------------------------------------------------
commit 7c79633688238086ad60e1d23e0a424bb4eb325f
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date: Fri Oct 31 12:31:59 2014 +0000
Fix the superclass-cycle detection code (Trac #9739)
We were falling into an infinite loop when doing the ambiguity
check on a class method, even though we had previously detected
a superclass cycle. There was code to deal with this, but it
wasn't right.
>---------------------------------------------------------------
7c79633688238086ad60e1d23e0a424bb4eb325f
compiler/typecheck/TcRnMonad.lhs | 3 ++
compiler/typecheck/TcTyClsDecls.lhs | 39 +++++++++++-----------
testsuite/tests/typecheck/should_fail/T9739.hs | 9 +++--
testsuite/tests/typecheck/should_fail/T9739.stderr | 10 +++---
4 files changed, 34 insertions(+), 27 deletions(-)
diff --git a/compiler/typecheck/TcRnMonad.lhs b/compiler/typecheck/TcRnMonad.lhs
index dce4b49..cd41499 100644
--- a/compiler/typecheck/TcRnMonad.lhs
+++ b/compiler/typecheck/TcRnMonad.lhs
@@ -825,6 +825,9 @@ checkNoErrs main
Just val -> return val
}
+whenNoErrs :: TcM () -> TcM ()
+whenNoErrs thing = ifErrsM (return ()) thing
+
ifErrsM :: TcRn r -> TcRn r -> TcRn r
-- ifErrsM bale_out normal
-- does 'bale_out' if there are errors in errors collection
diff --git a/compiler/typecheck/TcTyClsDecls.lhs b/compiler/typecheck/TcTyClsDecls.lhs
index fd3c8f8..e08f269 100644
--- a/compiler/typecheck/TcTyClsDecls.lhs
+++ b/compiler/typecheck/TcTyClsDecls.lhs
@@ -1357,25 +1357,9 @@ since GADTs are not kind indexed.
Validity checking is done once the mutually-recursive knot has been
tied, so we can look at things freely.
-Note [Abort when superclass cycle is detected]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We must avoid doing the ambiguity check when there are already errors accumulated.
-This is because one of the errors may be a superclass cycle, and superclass cycles
-cause canonicalization to loop. Here is a representative example:
-
- class D a => C a where
- meth :: D a => ()
- class C a => D a
-
-This fixes Trac #9415.
-
\begin{code}
checkClassCycleErrs :: Class -> TcM ()
-checkClassCycleErrs cls
- = unless (null cls_cycles) $
- do { mapM_ recClsErr cls_cycles
- ; failM } -- See Note [Abort when superclass cycle is detected]
- where cls_cycles = calcClassCycles cls
+checkClassCycleErrs cls = mapM_ recClsErr (calcClassCycles cls)
checkValidTyCl :: TyThing -> TcM ()
checkValidTyCl thing
@@ -1628,8 +1612,11 @@ checkValidClass cls
-- If there are superclass cycles, checkClassCycleErrs bails.
; checkClassCycleErrs cls
- -- Check the class operations
- ; mapM_ (check_op constrained_class_methods) op_stuff
+ -- Check the class operations.
+ -- But only if there have been no earlier errors
+ -- See Note [Abort when superclass cycle is detected]
+ ; whenNoErrs $
+ mapM_ (check_op constrained_class_methods) op_stuff
-- Check the associated type defaults are well-formed and instantiated
; mapM_ check_at_defs at_stuff }
@@ -1695,6 +1682,20 @@ checkFamFlag tc_name
2 (ptext (sLit "Use TypeFamilies to allow indexed type families"))
\end{code}
+Note [Abort when superclass cycle is detected]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We must avoid doing the ambiguity check for the methods (in
+checkValidClass.check_op) when there are already errors accumulated.
+This is because one of the errors may be a superclass cycle, and
+superclass cycles cause canonicalization to loop. Here is a
+representative example:
+
+ class D a => C a where
+ meth :: D a => ()
+ class C a => D a
+
+This fixes Trac #9415, #9739
+
%************************************************************************
%* *
Checking role validity
diff --git a/testsuite/tests/typecheck/should_fail/T9739.hs b/testsuite/tests/typecheck/should_fail/T9739.hs
index 4b7869d..18df797 100644
--- a/testsuite/tests/typecheck/should_fail/T9739.hs
+++ b/testsuite/tests/typecheck/should_fail/T9739.hs
@@ -1,6 +1,9 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
module T9739 where
-class Class2 a => Class1 a where
- class3 :: (Class2 a) => b
+class Class3 a => Class1 a where
-class (Class1 a) => Class2 a where
+class Class2 t a where
+ class2 :: (Class3 t) => a -> m
+
+class (Class1 t, Class2 t t) => Class3 t where
diff --git a/testsuite/tests/typecheck/should_fail/T9739.stderr b/testsuite/tests/typecheck/should_fail/T9739.stderr
index 95fcf6a..34e2f11 100644
--- a/testsuite/tests/typecheck/should_fail/T9739.stderr
+++ b/testsuite/tests/typecheck/should_fail/T9739.stderr
@@ -1,10 +1,10 @@
-T9739.hs:3:1:
+T9739.hs:4:1:
Cycle in class declaration (via superclasses):
- Class1 -> Class2 -> Class1
+ Class1 -> Class3 -> Class1
In the class declaration for ‘Class1’
-T9739.hs:6:1:
+T9739.hs:9:1:
Cycle in class declaration (via superclasses):
- Class2 -> Class1 -> Class2
- In the class declaration for ‘Class2’
+ Class3 -> Class1 -> Class3
+ In the class declaration for ‘Class3’
More information about the ghc-commits
mailing list