X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Ftypes%2FFunDeps.lhs;h=b8b97b11e2d3a2835c89cba9840cd995c42d4b5f;hb=c8732b3c99e93c36ad28e23d2b901b794e89542a;hp=06248b7b3cd4a79ee1ee6f534fb050be078e2b89;hpb=ab22f4e6456820c1b5169d75f5975a94e61f54ce;p=ghc-hetmet.git diff --git a/compiler/types/FunDeps.lhs b/compiler/types/FunDeps.lhs index 06248b7..b8b97b1 100644 --- a/compiler/types/FunDeps.lhs +++ b/compiler/types/FunDeps.lhs @@ -10,7 +10,7 @@ It's better to read it as: "if we know these, then we're going to know these" \begin{code} module FunDeps ( Equation, pprEquation, - oclose, grow, improve, + oclose, grow, improve, improveOne, checkInstCoverage, checkFunDeps, pprFundeps ) where @@ -21,8 +21,6 @@ import Name import Var import Class import TcGadt -import Type -import Coercion import TcType import InstEnv import VarSet @@ -125,24 +123,43 @@ oclose preds fixed_tvs ] \end{code} +Note [Growing the tau-tvs using constraints] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +(grow preds tvs) is the result of extend the set of tyvars tvs + using all conceivable links from pred + +E.g. tvs = {a}, preds = {H [a] b, K (b,Int) c, Eq e} +Then grow precs tvs = {a,b,c} + +All the type variables from an implicit parameter are added, whether or +not they are mentioned in tvs; see Note [Implicit parameters and ambiguity] +in TcSimplify. + +See also Note [Ambiguity] in TcSimplify + \begin{code} grow :: [PredType] -> TyVarSet -> TyVarSet --- See Note [Ambiguity] in TcSimplify grow preds fixed_tvs - | null preds = fixed_tvs - | otherwise = loop fixed_tvs + | null preds = real_fixed_tvs + | otherwise = loop real_fixed_tvs where + -- Add the implicit parameters; + -- see Note [Implicit parameters and ambiguity] in TcSimplify + real_fixed_tvs = foldr unionVarSet fixed_tvs ip_tvs + loop fixed_tvs | new_fixed_tvs `subVarSet` fixed_tvs = fixed_tvs | otherwise = loop new_fixed_tvs where - new_fixed_tvs = foldl extend fixed_tvs pred_sets + new_fixed_tvs = foldl extend fixed_tvs non_ip_tvs extend fixed_tvs pred_tvs | fixed_tvs `intersectsVarSet` pred_tvs = fixed_tvs `unionVarSet` pred_tvs | otherwise = fixed_tvs - pred_sets = [tyVarsOfPred pred | pred <- preds] + (ip_tvs, non_ip_tvs) = partitionWith get_ip preds + get_ip (IParam _ ty) = Left (tyVarsOfType ty) + get_ip other = Right (tyVarsOfPred other) \end{code} %************************************************************************ @@ -229,6 +246,63 @@ improve inst_env preds -- In any case, improvement *generates*, rather than -- *consumes*, equality constraints +improveOne :: (Class -> [Instance]) + -> Pred_Loc + -> [Pred_Loc] + -> [(Equation,Pred_Loc,Pred_Loc)] + +-- Just do improvement triggered by a single, distinguised predicate + +improveOne inst_env pred@(IParam ip ty, _) preds + = [ ((emptyVarSet, [(ty,ty2)]), pred, p2) + | p2@(IParam ip2 ty2, _) <- preds + , ip==ip2 + , not (ty `tcEqType` ty2)] + +improveOne inst_env pred@(ClassP cls tys, _) preds + | tys `lengthAtLeast` 2 + = instance_eqns ++ pairwise_eqns + -- NB: we put the instance equations first. This biases the + -- order so that we first improve individual constraints against the + -- instances (which are perhaps in a library and less likely to be + -- wrong; and THEN perform the pairwise checks. + -- The other way round, it's possible for the pairwise check to succeed + -- and cause a subsequent, misleading failure of one of the pair with an + -- instance declaration. See tcfail143.hs for an example + where + (cls_tvs, cls_fds) = classTvsFds cls + instances = inst_env cls + rough_tcs = roughMatchTcs tys + + -- NOTE that we iterate over the fds first; they are typically + -- empty, which aborts the rest of the loop. + pairwise_eqns :: [(Equation,Pred_Loc,Pred_Loc)] + pairwise_eqns -- This group comes from pairwise comparison + = [ (eqn, pred, p2) + | fd <- cls_fds + , p2@(ClassP cls2 tys2, _) <- preds + , cls == cls2 + , eqn <- checkClsFD emptyVarSet fd cls_tvs tys tys2 + ] + + instance_eqns :: [(Equation,Pred_Loc,Pred_Loc)] + instance_eqns -- This group comes from comparing with instance decls + = [ (eqn, p_inst, pred) + | fd <- cls_fds -- Iterate through the fundeps first, + -- because there often are none! + , let rough_fd_tcs = trimRoughMatchTcs cls_tvs fd rough_tcs + , ispec@(Instance { is_tvs = qtvs, is_tys = tys_inst, + is_tcs = mb_tcs_inst }) <- instances + , not (instanceCantMatch mb_tcs_inst rough_fd_tcs) + , eqn <- checkClsFD qtvs fd cls_tvs tys_inst tys + , let p_inst = (mkClassPred cls tys_inst, + ptext SLIT("arising from the instance declaration at") + <+> ppr (getSrcLoc ispec)) + ] + +improveOne inst_env eq_pred preds + = [] + ---------- checkGroup :: (Class -> [Instance]) -> [Pred_Loc]