summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2019-03-11 10:02:31 +0000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-03-12 09:13:28 -0400
commit50249a9f652ae3440e9462fdc9914edc924091f1 (patch)
tree013e20f8e82ecc722b85a28a42ae630e12d5803c /compiler
parent5165378d87602a8ce24776d220039fc05075d31f (diff)
downloadhaskell-50249a9f652ae3440e9462fdc9914edc924091f1.tar.gz
Use transSuperClasses in TcErrors
Code in TcErrors was recursively using immSuperClasses, which loops in the presence of UndecidableSuperClasses. Better to use transSuperClasses instead, which has a loop-breaker mechanism built in. Fixes issue #16414.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/typecheck/TcErrors.hs20
-rw-r--r--compiler/typecheck/TcType.hs23
2 files changed, 31 insertions, 12 deletions
diff --git a/compiler/typecheck/TcErrors.hs b/compiler/typecheck/TcErrors.hs
index d56e344454..3f0f82cb1d 100644
--- a/compiler/typecheck/TcErrors.hs
+++ b/compiler/typecheck/TcErrors.hs
@@ -2577,15 +2577,15 @@ mk_dict_err ctxt@(CEC {cec_encl = implics}) (ct, (matches, unifiers, unsafe_over
2 (sep [ text "bound by" <+> ppr skol_info
, text "at" <+>
ppr (tcl_loc (implicLclEnv implic)) ])
- where ev_vars_matching = filter ev_var_matches (map evVarPred evvars)
- ev_var_matches ty = case getClassPredTys_maybe ty of
- Just (clas', tys')
- | clas' == clas
- , Just _ <- tcMatchTys tys tys'
- -> True
- | otherwise
- -> any ev_var_matches (immSuperClasses clas' tys')
- Nothing -> False
+ where ev_vars_matching = [ pred
+ | ev_var <- evvars
+ , let pred = evVarPred ev_var
+ , any can_match (pred : transSuperClasses pred) ]
+ can_match pred
+ = case getClassPredTys_maybe pred of
+ Just (clas', tys') -> clas' == clas
+ && isJust (tcMatchTys tys tys')
+ Nothing -> False
-- Overlap error because of Safe Haskell (first
-- match should be the most specific match)
@@ -2716,7 +2716,7 @@ the alleged "provided" constraints, Show a.
So we suppress that Implication in discardProvCtxtGivens. It's
painfully ad-hoc but the truth is that adding it to the "required"
-constraints would work. Suprressing it solves two problems. First,
+constraints would work. Suppressing it solves two problems. First,
we never tell the user that we could not deduce a "provided"
constraint from the "required" context. Second, we never give a
possible fix that suggests to add a "provided" constraint to the
diff --git a/compiler/typecheck/TcType.hs b/compiler/typecheck/TcType.hs
index 155037b775..d4bac5c12b 100644
--- a/compiler/typecheck/TcType.hs
+++ b/compiler/typecheck/TcType.hs
@@ -2011,8 +2011,25 @@ isInsolubleOccursCheck eq_rel tv ty
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When we expand superclasses, we use the following algorithm:
-expand( so_far, pred ) returns the transitive superclasses of pred,
- not including pred itself
+transSuperClasses( C tys ) returns the transitive superclasses
+ of (C tys), not including C itself
+
+For example
+ class C a b => D a b
+ class D b a => C a b
+
+Then
+ transSuperClasses( Ord ty ) = [Eq ty]
+ transSuperClasses( C ta tb ) = [D tb ta, C tb ta]
+
+Notice that in the recursive-superclass case we include C again at
+the end of the chain. One could exclude C in this case, but
+the code is more awkward and there seems no good reason to do so.
+(However C.f. TcCanonical.mk_strict_superclasses, which /does/
+appear to do so.)
+
+The algorithm is expand( so_far, pred ):
+
1. If pred is not a class constraint, return empty set
Otherwise pred = C ts
2. If C is in so_far, return empty set (breaks loops)
@@ -2024,6 +2041,8 @@ Notice that
* With normal Haskell-98 classes, the loop-detector will never bite,
so we'll get all the superclasses.
+ * We need the loop-breaker in case we have UndecidableSuperClasses on
+
* Since there is only a finite number of distinct classes, expansion
must terminate.