Simon Peyton Jones pushed to branch wip/T23162-part2 at Glasgow Haskell Compiler / GHC
Commits:
-
827aaf71
by Simon Peyton Jones at 2025-11-13T17:32:23+00:00
3 changed files:
Changes:
| ... | ... | @@ -611,7 +611,7 @@ injectiveBranches injectivity |
| 611 | 611 | -- See Note [Verifying injectivity annotation], case 1.
|
| 612 | 612 | = let getInjArgs = filterByList injectivity
|
| 613 | 613 | in_scope = mkInScopeSetList (tvs1 ++ tvs2)
|
| 614 | - in case tcUnifyTyForInjectivity True in_scope rhs1 rhs2 of
|
|
| 614 | + in case tcUnifyTysForInjectivity True in_scope [rhs1] [rhs2] of
|
|
| 615 | 615 | -- True = two-way pre-unification
|
| 616 | 616 | Nothing -> InjectivityAccepted
|
| 617 | 617 | -- RHS are different, so equations are injective.
|
| ... | ... | @@ -12,7 +12,7 @@ module GHC.Core.Unify ( |
| 12 | 12 | |
| 13 | 13 | -- Side-effect free unification
|
| 14 | 14 | tcUnifyTy, tcUnifyTys, tcUnifyFunDeps, tcUnifyDebugger,
|
| 15 | - tcUnifyTysFG, tcUnifyTyForInjectivity,
|
|
| 15 | + tcUnifyTysFG, tcUnifyTysForInjectivity,
|
|
| 16 | 16 | BindTvFun, BindFamFun, BindFlag(..),
|
| 17 | 17 | matchBindTv, alwaysBindTv, alwaysBindFam, dontCareBindFam,
|
| 18 | 18 | UnifyResult, UnifyResultM(..), MaybeApartReason(..),
|
| ... | ... | @@ -381,7 +381,7 @@ Wrinkles |
| 381 | 381 | |
| 382 | 382 | (ATF7) There is one other, very special case of matching where we /do/ want to
|
| 383 | 383 | bind type families in `um_fam_env`, namely in GHC.Tc.Solver.Equality, the call
|
| 384 | - to `tcUnifyTyForInjectivity False` in `improve_injective_wanted_top`.
|
|
| 384 | + to `tcUnifyTysForInjectivity False` in `improve_injective_wanted_top`.
|
|
| 385 | 385 | Consider
|
| 386 | 386 | of a match. Consider
|
| 387 | 387 | type family G6 a = r | r -> a
|
| ... | ... | @@ -814,25 +814,25 @@ tcUnifyFunDeps qtvs tys1 tys2 |
| 814 | 814 | |
| 815 | 815 | -- | Unify or match a type-family RHS with a type (possibly another type-family RHS)
|
| 816 | 816 | -- Precondition: kinds are the same
|
| 817 | -tcUnifyTyForInjectivity
|
|
| 817 | +tcUnifyTysForInjectivity
|
|
| 818 | 818 | :: AmIUnifying -- ^ True <=> do two-way unification;
|
| 819 | 819 | -- False <=> do one-way matching.
|
| 820 | 820 | -- See end of sec 5.2 from the paper
|
| 821 | 821 | -> InScopeSet -- Should include the free tyvars of both Type args
|
| 822 | - -> Type -> Type -- Types to unify
|
|
| 822 | + -> [Type] -> [Type] -- Types to unify
|
|
| 823 | 823 | -> Maybe Subst
|
| 824 | 824 | -- This algorithm is an implementation of the "Algorithm U" presented in
|
| 825 | 825 | -- the paper "Injective type families for Haskell", Figures 2 and 3.
|
| 826 | 826 | -- The code is incorporated with the standard unifier for convenience, but
|
| 827 | 827 | -- its operation should match the specification in the paper.
|
| 828 | -tcUnifyTyForInjectivity unif in_scope t1 t2
|
|
| 828 | +tcUnifyTysForInjectivity unif in_scope tys1 tys2
|
|
| 829 | 829 | = case tc_unify_tys alwaysBindFam alwaysBindTv
|
| 830 | 830 | unif -- Am I unifying?
|
| 831 | 831 | True -- Do injectivity checks
|
| 832 | 832 | False -- Don't check outermost kinds
|
| 833 | 833 | RespectMultiplicities
|
| 834 | 834 | rn_env emptyTvSubstEnv emptyCvSubstEnv
|
| 835 | - [t1] [t2] of
|
|
| 835 | + tys1 tys2 of
|
|
| 836 | 836 | Unifiable (tv_subst, _cv_subst) -> Just $ maybe_fix tv_subst
|
| 837 | 837 | MaybeApart _reason (tv_subst, _cv_subst) -> Just $ maybe_fix tv_subst
|
| 838 | 838 | -- We want to *succeed* in questionable cases.
|
| ... | ... | @@ -25,7 +25,7 @@ import GHC.Core.FamInstEnv |
| 25 | 25 | import GHC.Core.Coercion
|
| 26 | 26 | import GHC.Core.Predicate( EqRel(..) )
|
| 27 | 27 | import GHC.Core.TyCon
|
| 28 | -import GHC.Core.Unify( tcUnifyTyForInjectivity, typeListsAreApart )
|
|
| 28 | +import GHC.Core.Unify( tcUnifyTysForInjectivity, typeListsAreApart )
|
|
| 29 | 29 | import GHC.Core.Coercion.Axiom
|
| 30 | 30 | import GHC.Core.TyCo.Subst( elemSubst )
|
| 31 | 31 | |
| ... | ... | @@ -545,14 +545,35 @@ mkTopClosedFamEqFDs :: CoAxiom Branched -> [TcType] -> Xi -> TcS [FunDepEqns] |
| 545 | 545 | mkTopClosedFamEqFDs ax work_args work_rhs
|
| 546 | 546 | = do { let branches = fromBranches (coAxiomBranches ax)
|
| 547 | 547 | ; traceTcS "mkTopClosed" (ppr branches $$ ppr work_args $$ ppr work_rhs)
|
| 548 | - ; case filter relevant_branch branches of
|
|
| 549 | - [CoAxBranch { cab_tvs = qtvs, cab_lhs = lhs_tys }]
|
|
| 548 | + ; case getRelevantBranches ax work_args work_rhs of
|
|
| 549 | + [CoAxBranch { cab_tvs = qtvs, cab_lhs = lhs_tys }]
|
|
| 550 | 550 | -> return [FDEqns { fd_qtvs = qtvs
|
| 551 | 551 | , fd_eqs = zipWith Pair lhs_tys work_args }]
|
| 552 | 552 | _ -> return [] }
|
| 553 | + |
|
| 554 | +getRelevantBranches ax work_args work_rhs
|
|
| 555 | + = go [] (fromBranches (coAxiomBranches ax))
|
|
| 553 | 556 | where
|
| 554 | - relevant_branch (CoAxBranch { cab_lhs = lhs_tys, cab_rhs = rhs_ty })
|
|
| 555 | - = eqnIsRelevant lhs_tys rhs_ty work_args work_rhs
|
|
| 557 | + work_tys = work_rhs : work_args
|
|
| 558 | + work_fvs = tyCoVarsOfTypes work_tys
|
|
| 559 | + |
|
| 560 | + go preceding [] = []
|
|
| 561 | + go preceding (CoAxBranch { cab_qtvs = qtvs, cab_lhs = lhs_tys, cab_rhs = rhs_ty } : rest)
|
|
| 562 | + | is_relevant = br : go (br:preceding) rest
|
|
| 563 | + | otherwise = go (br:preceding) rest
|
|
| 564 | + where
|
|
| 565 | + is_relevant = case tcUnifyTysForInjectivity True branch_fvs work_tys (rhs_ty:lhs_tys) of
|
|
| 566 | + Nothing -> False
|
|
| 567 | + Just subst -> no_match (substTy subst lhs_tys) preceding
|
|
| 568 | + |
|
| 569 | + branch_fvs = extendVarSetList work_fvs qtvs
|
|
| 570 | + |
|
| 571 | + no_match lhs_tys [] = True
|
|
| 572 | + no_match lhs_tys (CoAxBranch { cab_qtvs = qtvs1, cab_lhs = lhs_tys1 })
|
|
| 573 | + = isNothing (tcUnifyTysForInjectivity False lhs_tys1 lhs_tys)
|
|
| 574 | + where
|
|
| 575 | + all_fvs = branch_fvs `extendVarSetList` qtvs1
|
|
| 576 | + |
|
| 556 | 577 | |
| 557 | 578 | mkTopOpenFamEqFDs :: TyCon -> [Bool] -> [TcType] -> Xi -> TcS [FunDepEqns]
|
| 558 | 579 | -- Implements (INJFAM:Wanted/top)
|