Simon Peyton Jones pushed to branch wip/T23162-part2 at Glasgow Haskell Compiler / GHC
Commits:
-
1783c632
by Simon Peyton Jones at 2025-11-14T15:43:23+00:00
3 changed files:
Changes:
| ... | ... | @@ -609,9 +609,7 @@ injectiveBranches injectivity |
| 609 | 609 | ax1@(CoAxBranch { cab_tvs = tvs1, cab_lhs = lhs1, cab_rhs = rhs1 })
|
| 610 | 610 | ax2@(CoAxBranch { cab_tvs = tvs2, cab_lhs = lhs2, cab_rhs = rhs2 })
|
| 611 | 611 | -- See Note [Verifying injectivity annotation], case 1.
|
| 612 | - = let getInjArgs = filterByList injectivity
|
|
| 613 | - in_scope = mkInScopeSetList (tvs1 ++ tvs2)
|
|
| 614 | - in case tcUnifyTysForInjectivity True in_scope [rhs1] [rhs2] of
|
|
| 612 | + = case tcUnifyTysForInjectivity True [rhs1] [rhs2] of
|
|
| 615 | 613 | -- True = two-way pre-unification
|
| 616 | 614 | Nothing -> InjectivityAccepted
|
| 617 | 615 | -- RHS are different, so equations are injective.
|
| ... | ... | @@ -633,6 +631,7 @@ injectiveBranches injectivity |
| 633 | 631 | -- Payload of InjectivityUnified used only for check 1B2, only
|
| 634 | 632 | -- for closed type families
|
| 635 | 633 | where
|
| 634 | + getInjArgs = filterByList injectivity
|
|
| 636 | 635 | lhs1Subst = Type.substTys subst (getInjArgs lhs1)
|
| 637 | 636 | lhs2Subst = Type.substTys subst (getInjArgs lhs2)
|
| 638 | 637 |
| ... | ... | @@ -818,14 +818,13 @@ 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 | - -> InScopeSet -- Should include the free tyvars of both Type args
|
|
| 822 | 821 | -> [Type] -> [Type] -- Types to unify
|
| 823 | 822 | -> Maybe Subst
|
| 824 | 823 | -- This algorithm is an implementation of the "Algorithm U" presented in
|
| 825 | 824 | -- the paper "Injective type families for Haskell", Figures 2 and 3.
|
| 826 | 825 | -- The code is incorporated with the standard unifier for convenience, but
|
| 827 | 826 | -- its operation should match the specification in the paper.
|
| 828 | -tcUnifyTysForInjectivity unif in_scope tys1 tys2
|
|
| 827 | +tcUnifyTysForInjectivity unif tys1 tys2
|
|
| 829 | 828 | = case tc_unify_tys alwaysBindFam alwaysBindTv
|
| 830 | 829 | unif -- Am I unifying?
|
| 831 | 830 | True -- Do injectivity checks
|
| ... | ... | @@ -840,6 +839,10 @@ tcUnifyTysForInjectivity unif in_scope tys1 tys2 |
| 840 | 839 | SurelyApart -> Nothing
|
| 841 | 840 | where
|
| 842 | 841 | rn_env = mkRnEnv2 in_scope
|
| 842 | + in_scope = mkInScopeSet (tyCoVarsOfTypes tys1 `unionVarSet` tyCoVarsOfTypes tys2)
|
|
| 843 | + -- The types we are unifying never contain foralls, so the
|
|
| 844 | + -- in-scope set is never looked at, so this free-var stuff
|
|
| 845 | + -- should never actually be done
|
|
| 843 | 846 | |
| 844 | 847 | maybe_fix | unif = niFixSubst in_scope
|
| 845 | 848 | | otherwise = mkTvSubst in_scope -- when matching, don't confuse
|
| ... | ... | @@ -31,14 +31,13 @@ import GHC.Core.TyCo.Subst( elemSubst ) |
| 31 | 31 | |
| 32 | 32 | import GHC.Builtin.Types.Literals( tryInteractTopFam, tryInteractInertFam )
|
| 33 | 33 | |
| 34 | -import GHC.Types.Var.Env
|
|
| 35 | 34 | import GHC.Types.Var.Set
|
| 36 | 35 | |
| 37 | 36 | import GHC.Utils.Outputable
|
| 38 | 37 | import GHC.Utils.Panic
|
| 39 | 38 | |
| 40 | 39 | import GHC.Data.Pair
|
| 41 | -import Data.Maybe( mapMaybe )
|
|
| 40 | +import Data.Maybe( isNothing, mapMaybe )
|
|
| 42 | 41 | |
| 43 | 42 | |
| 44 | 43 | {- Note [Overview of functional dependencies in type inference]
|
| ... | ... | @@ -546,34 +545,30 @@ mkTopClosedFamEqFDs ax work_args work_rhs |
| 546 | 545 | = do { let branches = fromBranches (coAxiomBranches ax)
|
| 547 | 546 | ; traceTcS "mkTopClosed" (ppr branches $$ ppr work_args $$ ppr work_rhs)
|
| 548 | 547 | ; case getRelevantBranches ax work_args work_rhs of
|
| 549 | - [CoAxBranch { cab_tvs = qtvs, cab_lhs = lhs_tys }]
|
|
| 548 | + [CoAxBranch { cab_tvs = qtvs, cab_lhs = lhs_tys, cab_rhs = rhs_ty }]
|
|
| 550 | 549 | -> return [FDEqns { fd_qtvs = qtvs
|
| 551 | - , fd_eqs = zipWith Pair lhs_tys work_args }]
|
|
| 550 | + , fd_eqs = zipWith Pair (rhs_ty:lhs_tys) (work_rhs:work_args) }]
|
|
| 552 | 551 | _ -> return [] }
|
| 553 | 552 | |
| 553 | + |
|
| 554 | +getRelevantBranches :: CoAxiom Branched -> [TcType] -> Xi -> [CoAxBranch]
|
|
| 554 | 555 | getRelevantBranches ax work_args work_rhs
|
| 555 | 556 | = go [] (fromBranches (coAxiomBranches ax))
|
| 556 | 557 | where
|
| 557 | 558 | 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 | 559 | |
| 569 | - branch_fvs = extendVarSetList work_fvs qtvs
|
|
| 560 | + go _ [] = []
|
|
| 561 | + go preceding (branch:branches)
|
|
| 562 | + | is_relevant branch = branch : go (branch:preceding) branches
|
|
| 563 | + | otherwise = go (branch:preceding) branches
|
|
| 564 | + where
|
|
| 565 | + is_relevant (CoAxBranch { cab_lhs = lhs_tys, cab_rhs = rhs_ty })
|
|
| 566 | + = case tcUnifyTysForInjectivity True work_tys (rhs_ty:lhs_tys) of
|
|
| 567 | + Nothing -> False
|
|
| 568 | + Just subst -> all (no_match (substTys subst lhs_tys)) preceding
|
|
| 570 | 569 | |
| 571 | - no_match lhs_tys [] = True
|
|
| 572 | - no_match lhs_tys (CoAxBranch { cab_qtvs = qtvs1, cab_lhs = lhs_tys1 })
|
|
| 570 | + no_match lhs_tys (CoAxBranch { cab_lhs = lhs_tys1 })
|
|
| 573 | 571 | = isNothing (tcUnifyTysForInjectivity False lhs_tys1 lhs_tys)
|
| 574 | - where
|
|
| 575 | - all_fvs = branch_fvs `extendVarSetList` qtvs1
|
|
| 576 | - |
|
| 577 | 572 | |
| 578 | 573 | mkTopOpenFamEqFDs :: TyCon -> [Bool] -> [TcType] -> Xi -> TcS [FunDepEqns]
|
| 579 | 574 | -- Implements (INJFAM:Wanted/top)
|
| ... | ... | @@ -588,8 +583,7 @@ mkTopOpenFamEqFDs fam_tc inj_flags work_args work_rhs |
| 588 | 583 | do_one branch@(CoAxBranch { cab_tvs = branch_tvs
|
| 589 | 584 | , cab_lhs = branch_lhs_tys
|
| 590 | 585 | , cab_rhs = branch_rhs })
|
| 591 | - | let in_scope1 = in_scope `extendInScopeSetList` branch_tvs
|
|
| 592 | - , Just subst <- tcUnifyTyForInjectivity False in_scope1 branch_rhs work_rhs
|
|
| 586 | + | Just subst <- tcUnifyTysForInjectivity False [branch_rhs] [work_rhs]
|
|
| 593 | 587 | -- False: matching, not unifying
|
| 594 | 588 | , let (subst', qtvs) = trim_qtvs subst branch_tvs
|
| 595 | 589 | branch_lhs_tys' = substTys subst' branch_lhs_tys
|
| ... | ... | @@ -599,8 +593,6 @@ mkTopOpenFamEqFDs fam_tc inj_flags work_args work_rhs |
| 599 | 593 | | otherwise
|
| 600 | 594 | = Nothing
|
| 601 | 595 | |
| 602 | - in_scope = mkInScopeSet (tyCoVarsOfType work_rhs)
|
|
| 603 | - |
|
| 604 | 596 | trim_qtvs :: Subst -> [TcTyVar] -> (Subst,[TcTyVar])
|
| 605 | 597 | -- Tricky stuff: see (TIF1) in
|
| 606 | 598 | -- Note [Type inference for type families with injectivity]
|