summaryrefslogtreecommitdiff
path: root/compiler/GHC/Tc/TyCl/Utils.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Tc/TyCl/Utils.hs')
-rw-r--r--compiler/GHC/Tc/TyCl/Utils.hs32
1 files changed, 12 insertions, 20 deletions
diff --git a/compiler/GHC/Tc/TyCl/Utils.hs b/compiler/GHC/Tc/TyCl/Utils.hs
index b37977bb47..e052cb7633 100644
--- a/compiler/GHC/Tc/TyCl/Utils.hs
+++ b/compiler/GHC/Tc/TyCl/Utils.hs
@@ -305,19 +305,14 @@ Each step expands superclasses one layer, and clearly does not terminate.
type ClassSet = UniqSet Class
-checkClassCycles :: Class -> Maybe SDoc
+checkClassCycles :: Class -> Maybe SuperclassCycle
-- Nothing <=> ok
-- Just err <=> possible cycle error
checkClassCycles cls
- = do { (definite_cycle, err) <- go (unitUniqSet cls)
+ = do { (definite_cycle, details) <- go (unitUniqSet cls)
cls (mkTyVarTys (classTyVars cls))
- ; let herald | definite_cycle = text "Superclass cycle for"
- | otherwise = text "Potential superclass cycle for"
- ; return (vcat [ herald <+> quotes (ppr cls)
- , nest 2 err, hint]) }
+ ; return (MkSuperclassCycle cls definite_cycle details) }
where
- hint = text "Use UndecidableSuperClasses to accept this"
-
-- Expand superclasses starting with (C a b), complaining
-- if you find the same class a second time, or a type function
-- or predicate headed by a type variable
@@ -325,12 +320,12 @@ checkClassCycles cls
-- NB: this code duplicates TcType.transSuperClasses, but
-- with more error message generation clobber
-- Make sure the two stay in sync.
- go :: ClassSet -> Class -> [Type] -> Maybe (Bool, SDoc)
+ go :: ClassSet -> Class -> [Type] -> Maybe (Bool, [SuperclassCycleDetail])
go so_far cls tys = firstJusts $
map (go_pred so_far) $
immSuperClasses cls tys
- go_pred :: ClassSet -> PredType -> Maybe (Bool, SDoc)
+ go_pred :: ClassSet -> PredType -> Maybe (Bool, [SuperclassCycleDetail])
-- Nothing <=> ok
-- Just (True, err) <=> definite cycle
-- Just (False, err) <=> possible cycle
@@ -338,31 +333,28 @@ checkClassCycles cls
| Just (tc, tys) <- tcSplitTyConApp_maybe pred
= go_tc so_far pred tc tys
| hasTyVarHead pred
- = Just (False, hang (text "one of whose superclass constraints is headed by a type variable:")
- 2 (quotes (ppr pred)))
+ = Just (False, [SCD_HeadTyVar pred])
| otherwise
= Nothing
- go_tc :: ClassSet -> PredType -> TyCon -> [Type] -> Maybe (Bool, SDoc)
+ go_tc :: ClassSet -> PredType -> TyCon -> [Type] -> Maybe (Bool, [SuperclassCycleDetail])
go_tc so_far pred tc tys
| isFamilyTyCon tc
- = Just (False, hang (text "one of whose superclass constraints is headed by a type family:")
- 2 (quotes (ppr pred)))
+ = Just (False, [SCD_HeadTyFam pred])
| Just cls <- tyConClass_maybe tc
= go_cls so_far cls tys
| otherwise -- Equality predicate, for example
= Nothing
- go_cls :: ClassSet -> Class -> [Type] -> Maybe (Bool, SDoc)
+ go_cls :: ClassSet -> Class -> [Type] -> Maybe (Bool, [SuperclassCycleDetail])
go_cls so_far cls tys
| cls `elementOfUniqSet` so_far
- = Just (True, text "one of whose superclasses is" <+> quotes (ppr cls))
+ = Just (True, [SCD_Superclass cls])
| isCTupleClass cls
= go so_far cls tys
| otherwise
- = do { (b,err) <- go (so_far `addOneToUniqSet` cls) cls tys
- ; return (b, text "one of whose superclasses is" <+> quotes (ppr cls)
- $$ err) }
+ = do { (b, details) <- go (so_far `addOneToUniqSet` cls) cls tys
+ ; return (b, SCD_Superclass cls : details) }
{-
************************************************************************