diff options
author | Tom Schrijvers <tom.schrijvers@cs.kuleuven.be> | 2007-09-04 08:00:14 +0000 |
---|---|---|
committer | Tom Schrijvers <tom.schrijvers@cs.kuleuven.be> | 2007-09-04 08:00:14 +0000 |
commit | 66c58d1c46338135abdb76a86c7342fab005a988 (patch) | |
tree | c87d67b2c996aee77a478f5dc5190d3e5462e36a | |
parent | fe4dd43030b37772a08ed0986171d3cffcdaca6a (diff) | |
download | haskell-66c58d1c46338135abdb76a86c7342fab005a988.tar.gz |
fix of wanted equational class context
Previously failed to account for equational
class context for wanted dictionary contraints, e.g. wanted C a
in
class a ~ Int => C a
instance C Int
should give rise to wanted a ~ Int and consequently discharge a ~ Int by
unifying a with Int and then discharge C Int with the instance.
All ancestor equalities are taken into account.
-rw-r--r-- | compiler/typecheck/Inst.lhs | 8 | ||||
-rw-r--r-- | compiler/typecheck/TcSimplify.lhs | 31 |
2 files changed, 37 insertions, 2 deletions
diff --git a/compiler/typecheck/Inst.lhs b/compiler/typecheck/Inst.lhs index 8d21d1bcb1..e175951d95 100644 --- a/compiler/typecheck/Inst.lhs +++ b/compiler/typecheck/Inst.lhs @@ -48,7 +48,7 @@ module Inst ( mkWantedCo, mkGivenCo, fromWantedCo, fromGivenCo, - eitherEqInst, mkEqInst, mkEqInsts, + eitherEqInst, mkEqInst, mkEqInsts, mkWantedEqInst, finalizeEqInst, writeWantedCoercion, eqInstType, updateEqInstCoercion, eqInstCoercion, @@ -1004,6 +1004,12 @@ mkEqInst (EqPred ty1 ty2) co } where mkName uniq src_span = mkInternalName uniq (mkVarOcc "co") src_span +mkWantedEqInst :: PredType -> TcM Inst +mkWantedEqInst pred@(EqPred ty1 ty2) + = do { cotv <- newMetaTyVar TauTv (mkCoKind ty1 ty2) + ; mkEqInst pred (Left cotv) + } + -- type inference: -- We want to promote the wanted EqInst to a given EqInst -- in the signature context. diff --git a/compiler/typecheck/TcSimplify.lhs b/compiler/typecheck/TcSimplify.lhs index 007a71702b..13a85abaf6 100644 --- a/compiler/typecheck/TcSimplify.lhs +++ b/compiler/typecheck/TcSimplify.lhs @@ -1680,7 +1680,11 @@ reduceContext env wanteds ; let givens = red_givens env (given_eqs0,given_dicts0) = partitionGivenEqInsts givens - (wanted_eqs,wanted_dicts) = partitionWantedEqInsts wanteds + (wanted_eqs0,wanted_dicts) = partitionWantedEqInsts wanteds + + ; wanted_ancestor_eqs <- (mapM wantedAncestorEqualities wanted_dicts >>= \ls -> return (concat ls)) + ; traceTc (text "test wanted SCs" <+> ppr wanted_ancestor_eqs) + ; let wanted_eqs = wanted_ancestor_eqs ++ wanted_eqs0 ; -- 1. Normalise the *given* *equality* constraints (given_eqs,eliminate_skolems) <- normaliseGivens given_eqs0 @@ -2476,6 +2480,31 @@ addSCs is_loop avails dict is_given sc_dict = case findAvail avails sc_dict of Just (Given _) -> True -- Given is cheaper than superclass selection other -> False + + +wantedAncestorEqualities :: Inst -> TcM [Inst] +wantedAncestorEqualities dict + | isClassDict dict + = mapM mkWantedEqInst $ filter isEqPred $ bagToList $ wantedAncestorEqualities' (dictPred dict) emptyBag + | otherwise + = return [] + +wantedAncestorEqualities' :: PredType -> Bag PredType -> Bag PredType +wantedAncestorEqualities' pred bag + = ASSERT( isClassPred pred ) + let (clas, tys) = getClassPredTys pred + (tyvars, sc_theta, _, _) = classBigSig clas + sc_theta' = substTheta (zipTopTvSubst tyvars tys) sc_theta + add_sc bag sc_pred + | elemBag sc_pred bag = bag + | not (isEqPred sc_pred) + && not (isClassPred sc_pred) + = bag + | isEqPred sc_pred = consBag sc_pred bag + | otherwise = let bag' = consBag sc_pred bag + in wantedAncestorEqualities' sc_pred bag' + in foldl add_sc bag sc_theta' + \end{code} %************************************************************************ |