Simon Peyton Jones pushed to branch wip/T23162-spj at Glasgow Haskell Compiler / GHC
Commits:
-
5cf99a78
by Simon Peyton Jones at 2025-10-14T21:28:29+01:00
12 changed files:
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
Changes:
| 1 | +{-# LANGUAGE DerivingStrategies #-}
|
|
| 1 | 2 | {-# LANGUAGE DeriveDataTypeable #-}
|
| 2 | 3 | |
| 3 | 4 | {-# OPTIONS_HADDOCK not-home #-}
|
| ... | ... | @@ -41,6 +42,11 @@ module GHC.Core.TyCo.Rep ( |
| 41 | 42 | CoercionN, CoercionR, CoercionP, KindCoercion,
|
| 42 | 43 | MCoercion(..), MCoercionR, MCoercionN, KindMCoercion,
|
| 43 | 44 | |
| 45 | + -- RewriterSet
|
|
| 46 | + -- RewriterSet(..) is exported concretely only for zonkRewriterSet
|
|
| 47 | + RewriterSet(..), emptyRewriterSet, isEmptyRewriterSet, elemRewriterSet,
|
|
| 48 | + addRewriter, unitRewriterSet, unionRewriterSet, delRewriterSet,
|
|
| 49 | + |
|
| 44 | 50 | -- * Functions over types
|
| 45 | 51 | mkNakedTyConTy, mkTyVarTy, mkTyVarTys,
|
| 46 | 52 | mkTyCoVarTy, mkTyCoVarTys,
|
| ... | ... | @@ -78,6 +84,7 @@ import {-# SOURCE #-} GHC.Core.Type( chooseFunTyFlag, typeKind, typeTypeOrConstr |
| 78 | 84 | -- friends:
|
| 79 | 85 | import GHC.Types.Var
|
| 80 | 86 | import GHC.Types.Var.Set( elemVarSet )
|
| 87 | +import GHC.Types.Unique.Set
|
|
| 81 | 88 | import GHC.Core.TyCon
|
| 82 | 89 | import GHC.Core.Coercion.Axiom
|
| 83 | 90 | |
| ... | ... | @@ -93,6 +100,7 @@ import GHC.Utils.Binary |
| 93 | 100 | |
| 94 | 101 | -- libraries
|
| 95 | 102 | import qualified Data.Data as Data hiding ( TyCon )
|
| 103 | +import Data.Coerce
|
|
| 96 | 104 | import Data.IORef ( IORef ) -- for CoercionHole
|
| 97 | 105 | import Control.DeepSeq
|
| 98 | 106 | |
| ... | ... | @@ -1672,7 +1680,7 @@ holes `HoleCo`, which get filled in later. |
| 1672 | 1680 | |
| 1673 | 1681 | {- **********************************************************************
|
| 1674 | 1682 | %* *
|
| 1675 | - Coercion holes
|
|
| 1683 | + Coercion holes and RewriterSets
|
|
| 1676 | 1684 | %* *
|
| 1677 | 1685 | %********************************************************************* -}
|
| 1678 | 1686 | |
| ... | ... | @@ -1681,7 +1689,7 @@ data CoercionHole |
| 1681 | 1689 | = CoercionHole { ch_co_var :: CoVar
|
| 1682 | 1690 | -- See Note [CoercionHoles and coercion free variables]
|
| 1683 | 1691 | |
| 1684 | - , ch_ref :: IORef (Maybe Coercion)
|
|
| 1692 | + , ch_ref :: IORef (Maybe (Coercion, RewriterSet))
|
|
| 1685 | 1693 | }
|
| 1686 | 1694 | |
| 1687 | 1695 | coHoleCoVar :: CoercionHole -> CoVar
|
| ... | ... | @@ -1702,6 +1710,33 @@ instance Outputable CoercionHole where |
| 1702 | 1710 | instance Uniquable CoercionHole where
|
| 1703 | 1711 | getUnique (CoercionHole { ch_co_var = cv }) = getUnique cv
|
| 1704 | 1712 | |
| 1713 | + |
|
| 1714 | +-- | A RewriterSet stores a set of CoercionHoles that have been used to rewrite
|
|
| 1715 | +-- a constraint. See Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint
|
|
| 1716 | +newtype RewriterSet = RewriterSet (UniqSet CoercionHole)
|
|
| 1717 | + deriving newtype (Outputable, Semigroup, Monoid)
|
|
| 1718 | + |
|
| 1719 | +emptyRewriterSet :: RewriterSet
|
|
| 1720 | +emptyRewriterSet = RewriterSet emptyUniqSet
|
|
| 1721 | + |
|
| 1722 | +unitRewriterSet :: CoercionHole -> RewriterSet
|
|
| 1723 | +unitRewriterSet = coerce (unitUniqSet @CoercionHole)
|
|
| 1724 | + |
|
| 1725 | +elemRewriterSet :: CoercionHole -> RewriterSet -> Bool
|
|
| 1726 | +elemRewriterSet = coerce (elementOfUniqSet @CoercionHole)
|
|
| 1727 | + |
|
| 1728 | +delRewriterSet :: RewriterSet -> CoercionHole -> RewriterSet
|
|
| 1729 | +delRewriterSet = coerce (delOneFromUniqSet @CoercionHole)
|
|
| 1730 | + |
|
| 1731 | +unionRewriterSet :: RewriterSet -> RewriterSet -> RewriterSet
|
|
| 1732 | +unionRewriterSet = coerce (unionUniqSets @CoercionHole)
|
|
| 1733 | + |
|
| 1734 | +isEmptyRewriterSet :: RewriterSet -> Bool
|
|
| 1735 | +isEmptyRewriterSet = coerce (isEmptyUniqSet @CoercionHole)
|
|
| 1736 | + |
|
| 1737 | +addRewriter :: RewriterSet -> CoercionHole -> RewriterSet
|
|
| 1738 | +addRewriter = coerce (addOneToUniqSet @CoercionHole)
|
|
| 1739 | + |
|
| 1705 | 1740 | {- Note [Coercion holes]
|
| 1706 | 1741 | ~~~~~~~~~~~~~~~~~~~~~~~~
|
| 1707 | 1742 | During typechecking, constraint solving for type classes works by
|
| ... | ... | @@ -1777,6 +1812,15 @@ constraint from floating] in GHC.Tc.Solver, item (4): |
| 1777 | 1812 | Here co2 is a CoercionHole. But we /must/ know that it is free in
|
| 1778 | 1813 | co1, because that's all that stops it floating outside the
|
| 1779 | 1814 | implication.
|
| 1815 | + |
|
| 1816 | +Note [CoercionHoles and RewriterSets]
|
|
| 1817 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1818 | +A constraint C carries a set of "rewriters", a set of Wanted CoercionHoles that have been
|
|
| 1819 | +used to rewrite C; see Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint.
|
|
| 1820 | + |
|
| 1821 | +If C is an equality constraint and is solved, we track its RewriterSet in the filled
|
|
| 1822 | +CoercionHole, so that it can be inherited by other constraints that have C in /their/
|
|
| 1823 | +rewriters. See zonkRewriterSet.
|
|
| 1780 | 1824 | -}
|
| 1781 | 1825 | |
| 1782 | 1826 |
| ... | ... | @@ -1327,7 +1327,7 @@ addDeferredBinding ctxt supp hints msg (EI { ei_evdest = Just dest |
| 1327 | 1327 | -> do { -- See Note [Deferred errors for coercion holes]
|
| 1328 | 1328 | let co_var = coHoleCoVar hole
|
| 1329 | 1329 | ; addTcEvBind ev_binds_var $ mkWantedEvBind co_var EvNonCanonical err_tm
|
| 1330 | - ; fillCoercionHole hole (mkCoVarCo co_var) } }
|
|
| 1330 | + ; fillCoercionHole hole (mkCoVarCo co_var, emptyRewriterSet) } }
|
|
| 1331 | 1331 | addDeferredBinding _ _ _ _ _ = return () -- Do not set any evidence for Given
|
| 1332 | 1332 | |
| 1333 | 1333 | mkSolverErrorTerm :: CtLoc -> Type -- of the error term
|
| ... | ... | @@ -1481,7 +1481,7 @@ in `getRuleQuantCts`. Why not? |
| 1481 | 1481 | do { ev_id <- newEvVar pred
|
| 1482 | 1482 | ; fillCoercionHole hole (mkCoVarCo ev_id)
|
| 1483 | 1483 | ; return ev_id }
|
| 1484 | - But that led to new complications becuase of the side effect on the coercion
|
|
| 1484 | + But that led to new complications because of the side effect on the coercion
|
|
| 1485 | 1485 | hole. Much easier just to side-step the issue entirely by not quantifying over
|
| 1486 | 1486 | equalities.
|
| 1487 | 1487 |
| ... | ... | @@ -296,7 +296,7 @@ solveImplicationUsingUnsatGiven |
| 296 | 296 | go_simple ct = case ctEvidence ct of
|
| 297 | 297 | CtWanted (WantedCt { ctev_pred = pty, ctev_dest = dest })
|
| 298 | 298 | -> do { ev_expr <- unsatisfiableEvExpr unsat_given pty
|
| 299 | - ; setWantedEvTerm dest EvNonCanonical $ EvExpr ev_expr }
|
|
| 299 | + ; setWantedDict dest EvNonCanonical $ EvExpr ev_expr }
|
|
| 300 | 300 | _ -> return ()
|
| 301 | 301 | |
| 302 | 302 | -- | Create an evidence expression for an arbitrary constraint using
|
| ... | ... | @@ -476,7 +476,7 @@ solveEqualityDict ev cls tys |
| 476 | 476 | ; co <- wrapUnifierAndEmit ev role $ \uenv ->
|
| 477 | 477 | uType uenv t1 t2
|
| 478 | 478 | -- Set d :: (t1~t2) = Eq# co
|
| 479 | - ; setWantedEvTerm dest EvCanonical $
|
|
| 479 | + ; setWantedDict dest EvCanonical $
|
|
| 480 | 480 | evDictApp cls tys [Coercion co]
|
| 481 | 481 | ; stopWith ev "Solved wanted lifted equality" }
|
| 482 | 482 |
| ... | ... | @@ -485,7 +485,7 @@ can_eq_nc_forall :: CtEvidence -> EqRel |
| 485 | 485 | -- See Note [Solving forall equalities]
|
| 486 | 486 | |
| 487 | 487 | can_eq_nc_forall ev eq_rel s1 s2
|
| 488 | - | CtWanted (WantedCt { ctev_dest = orig_dest, ctev_loc = loc }) <- ev
|
|
| 488 | + | CtWanted (WantedCt { ctev_dest = orig_dest, ctev_rewriters = rws, ctev_loc = loc }) <- ev
|
|
| 489 | 489 | = do { let (bndrs1, phi1, bndrs2, phi2) = split_foralls s1 s2
|
| 490 | 490 | flags1 = binderFlags bndrs1
|
| 491 | 491 | flags2 = binderFlags bndrs2
|
| ... | ... | @@ -567,9 +567,9 @@ can_eq_nc_forall ev eq_rel s1 s2 |
| 567 | 567 | , ic_wanted = emptyWC { wc_simple = wanteds } }
|
| 568 | 568 | |
| 569 | 569 | ; if solved
|
| 570 | - then do { zonked_all_co <- zonkCo all_co
|
|
| 571 | - -- ToDo: explain this zonk
|
|
| 572 | - ; setWantedEq orig_dest zonked_all_co
|
|
| 570 | + then do { -- all_co <- zonkCo all_co
|
|
| 571 | + -- -- ToDo: explain this zonk
|
|
| 572 | + setWantedEq orig_dest rws all_co
|
|
| 573 | 573 | ; stopWith ev "Polytype equality: solved" }
|
| 574 | 574 | else canEqSoftFailure IrredShapeReason ev s1 s2 } }
|
| 575 | 575 | |
| ... | ... | @@ -809,7 +809,7 @@ can_eq_app :: CtEvidence -- :: s1 t1 ~N s2 t2 |
| 809 | 809 | -- to an irreducible constraint; see typecheck/should_compile/T10494
|
| 810 | 810 | -- See Note [Decomposing AppTy equalities]
|
| 811 | 811 | can_eq_app ev s1 t1 s2 t2
|
| 812 | - | CtWanted (WantedCt { ctev_dest = dest }) <- ev
|
|
| 812 | + | CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rws }) <- ev
|
|
| 813 | 813 | = do { traceTcS "can_eq_app" (vcat [ text "s1:" <+> ppr s1, text "t1:" <+> ppr t1
|
| 814 | 814 | , text "s2:" <+> ppr s2, text "t2:" <+> ppr t2
|
| 815 | 815 | , text "vis:" <+> ppr (isNextArgVisible s1) ])
|
| ... | ... | @@ -824,7 +824,7 @@ can_eq_app ev s1 t1 s2 t2 |
| 824 | 824 | ; co_t <- uType arg_env t1 t2
|
| 825 | 825 | ; co_s <- uType uenv s1 s2
|
| 826 | 826 | ; return (mkAppCo co_s co_t) }
|
| 827 | - ; setWantedEq dest co
|
|
| 827 | + ; setWantedEq dest rws co
|
|
| 828 | 828 | ; stopWith ev "Decomposed [W] AppTy" }
|
| 829 | 829 | |
| 830 | 830 | -- If there is a ForAll/(->) mismatch, the use of the Left coercion
|
| ... | ... | @@ -1374,7 +1374,7 @@ canDecomposableTyConAppOK ev eq_rel tc (ty1,tys1) (ty2,tys2) |
| 1374 | 1374 | do { traceTcS "canDecomposableTyConAppOK"
|
| 1375 | 1375 | (ppr ev $$ ppr eq_rel $$ ppr tc $$ ppr tys1 $$ ppr tys2)
|
| 1376 | 1376 | ; case ev of
|
| 1377 | - CtWanted (WantedCt { ctev_dest = dest })
|
|
| 1377 | + CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rws })
|
|
| 1378 | 1378 | -- new_locs and tc_roles are both infinite, so we are
|
| 1379 | 1379 | -- guaranteed that cos has the same length as tys1 and tys2
|
| 1380 | 1380 | -- See Note [Fast path when decomposing TyConApps]
|
| ... | ... | @@ -1382,7 +1382,7 @@ canDecomposableTyConAppOK ev eq_rel tc (ty1,tys1) (ty2,tys2) |
| 1382 | 1382 | do { cos <- zipWith4M (u_arg uenv) new_locs tc_roles tys1 tys2
|
| 1383 | 1383 | -- zipWith4M: see Note [Work-list ordering]
|
| 1384 | 1384 | ; return (mkTyConAppCo role tc cos) }
|
| 1385 | - ; setWantedEq dest co }
|
|
| 1385 | + ; setWantedEq dest rws co }
|
|
| 1386 | 1386 | |
| 1387 | 1387 | CtGiven (GivenCt { ctev_evar = evar })
|
| 1388 | 1388 | | let pred_ty = mkEqPred eq_rel ty1 ty2
|
| ... | ... | @@ -1432,7 +1432,7 @@ canDecomposableFunTy ev eq_rel af f1@(ty1,m1,a1,r1) f2@(ty2,m2,a2,r2) |
| 1432 | 1432 | = do { traceTcS "canDecomposableFunTy"
|
| 1433 | 1433 | (ppr ev $$ ppr eq_rel $$ ppr f1 $$ ppr f2)
|
| 1434 | 1434 | ; case ev of
|
| 1435 | - CtWanted (WantedCt { ctev_dest = dest })
|
|
| 1435 | + CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rws })
|
|
| 1436 | 1436 | -> do { co <- wrapUnifierAndEmit ev Nominal $ \ uenv ->
|
| 1437 | 1437 | do { let mult_env = uenv `updUEnvLoc` toInvisibleLoc InvisibleMultiplicity
|
| 1438 | 1438 | `setUEnvRole` funRole role SelMult
|
| ... | ... | @@ -1443,7 +1443,7 @@ canDecomposableFunTy ev eq_rel af f1@(ty1,m1,a1,r1) f2@(ty2,m2,a2,r2) |
| 1443 | 1443 | ; arg <- uType (uenv `setUEnvRole` funRole role SelArg) a1 a2
|
| 1444 | 1444 | ; res <- uType (uenv `setUEnvRole` funRole role SelRes) r1 r2
|
| 1445 | 1445 | ; return (mkNakedFunCo role af mult arg res) }
|
| 1446 | - ; setWantedEq dest co }
|
|
| 1446 | + ; setWantedEq dest rws co }
|
|
| 1447 | 1447 | |
| 1448 | 1448 | CtGiven (GivenCt { ctev_evar = evar })
|
| 1449 | 1449 | | let pred_ty = mkEqPred eq_rel ty1 ty2
|
| ... | ... | @@ -2652,7 +2652,7 @@ rewriteEqEvidence new_rewriters old_ev swapped (Reduction lhs_co nlhs) (Reductio |
| 2652 | 2652 | ; (new_ev, hole_co) <- newWantedEq loc rewriters' (ctEvRewriteRole old_ev) nlhs nrhs
|
| 2653 | 2653 | ; let co = maybeSymCo swapped $
|
| 2654 | 2654 | lhs_co `mkTransCo` hole_co `mkTransCo` mkSymCo rhs_co
|
| 2655 | - ; setWantedEq dest co
|
|
| 2655 | + ; setWantedEq dest rewriters' co
|
|
| 2656 | 2656 | ; traceTcS "rewriteEqEvidence" (vcat [ ppr old_ev
|
| 2657 | 2657 | , ppr nlhs
|
| 2658 | 2658 | , ppr nrhs
|
| ... | ... | @@ -55,7 +55,7 @@ module GHC.Tc.Solver.Monad ( |
| 55 | 55 | newWantedNC, newWantedEvVarNC,
|
| 56 | 56 | newBoundEvVarId,
|
| 57 | 57 | unifyTyVar, reportFineGrainUnifications, reportCoarseGrainUnifications,
|
| 58 | - setEvBind, setWantedEq,
|
|
| 58 | + setEvBind, setWantedEq, setWantedDict,
|
|
| 59 | 59 | setWantedEvTerm, setEvBindIfWanted,
|
| 60 | 60 | newEvVar, newGivenEv, emitNewGivens,
|
| 61 | 61 | emitChildEqs, checkReductionDepth,
|
| ... | ... | @@ -457,16 +457,15 @@ kickOutAfterUnification tv_set |
| 457 | 457 | ; traceTcS "kickOutAfterUnification" (ppr tv_set $$ text "n_kicked =" <+> ppr n_kicked)
|
| 458 | 458 | ; return n_kicked }
|
| 459 | 459 | |
| 460 | -kickOutAfterFillingCoercionHole :: CoercionHole -> Coercion -> TcS ()
|
|
| 460 | +kickOutAfterFillingCoercionHole :: CoercionHole -> RewriterSet -> TcS ()
|
|
| 461 | 461 | -- See Wrinkle (URW2) in Note [Unify only if the rewriter set is empty]
|
| 462 | 462 | -- in GHC.Tc.Solver.Equality
|
| 463 | 463 | --
|
| 464 | 464 | -- It's possible that this could just go ahead and unify, but could there
|
| 465 | 465 | -- be occurs-check problems? Seems simpler just to kick out.
|
| 466 | -kickOutAfterFillingCoercionHole hole co
|
|
| 466 | +kickOutAfterFillingCoercionHole hole new_holes
|
|
| 467 | 467 | = do { ics <- getInertCans
|
| 468 | - ; new_holes <- liftZonkTcS $ TcM.freeHolesOfCoercion co
|
|
| 469 | - ; let (kicked_out, ics') = kick_out new_holes ics
|
|
| 468 | + ; let (kicked_out, ics') = kick_out ics
|
|
| 470 | 469 | n_kicked = length kicked_out
|
| 471 | 470 | |
| 472 | 471 | ; unless (n_kicked == 0) $
|
| ... | ... | @@ -479,14 +478,14 @@ kickOutAfterFillingCoercionHole hole co |
| 479 | 478 | |
| 480 | 479 | ; setInertCans ics' }
|
| 481 | 480 | where
|
| 482 | - kick_out :: RewriterSet -> InertCans -> ([EqCt], InertCans)
|
|
| 483 | - kick_out new_holes ics@(IC { inert_eqs = eqs })
|
|
| 481 | + kick_out :: InertCans -> ([EqCt], InertCans)
|
|
| 482 | + kick_out ics@(IC { inert_eqs = eqs })
|
|
| 484 | 483 | = (eqs_to_kick, ics { inert_eqs = eqs_to_keep })
|
| 485 | 484 | where
|
| 486 | - (eqs_to_kick, eqs_to_keep) = transformAndPartitionTyVarEqs (kick_out_eq new_holes) eqs
|
|
| 485 | + (eqs_to_kick, eqs_to_keep) = transformAndPartitionTyVarEqs kick_out_eq eqs
|
|
| 487 | 486 | |
| 488 | - kick_out_eq :: RewriterSet -> EqCt -> Either EqCt EqCt
|
|
| 489 | - kick_out_eq new_holes eq_ct@(EqCt { eq_ev = ev, eq_lhs = lhs })
|
|
| 487 | + kick_out_eq :: EqCt -> Either EqCt EqCt
|
|
| 488 | + kick_out_eq eq_ct@(EqCt { eq_ev = ev, eq_lhs = lhs })
|
|
| 490 | 489 | | CtWanted (wev@(WantedCt { ctev_rewriters = rewriters })) <- ev
|
| 491 | 490 | , TyVarLHS tv <- lhs
|
| 492 | 491 | , isMetaTyVar tv
|
| ... | ... | @@ -1951,27 +1950,32 @@ addUsedCoercion co |
| 1951 | 1950 | = do { ev_binds_var <- getTcEvBindsVar
|
| 1952 | 1951 | ; wrapTcS (TcM.updTcRef (ebv_tcvs ev_binds_var) (co :)) }
|
| 1953 | 1952 | |
| 1954 | --- | Equalities only
|
|
| 1955 | -setWantedEq :: HasDebugCallStack => TcEvDest -> TcCoercion -> TcS ()
|
|
| 1956 | -setWantedEq (HoleDest hole) co
|
|
| 1953 | +setWantedEq :: HasDebugCallStack => TcEvDest -> RewriterSet -> TcCoercion -> TcS ()
|
|
| 1954 | +-- ^ Equalities only
|
|
| 1955 | +setWantedEq (HoleDest hole) rewriters co
|
|
| 1957 | 1956 | = do { addUsedCoercion co
|
| 1958 | - ; fillCoercionHole hole co }
|
|
| 1959 | -setWantedEq (EvVarDest ev) _ = pprPanic "setWantedEq: EvVarDest" (ppr ev)
|
|
| 1957 | + ; fillCoercionHole hole rewriters co }
|
|
| 1958 | +setWantedEq (EvVarDest ev) _ _ = pprPanic "setWantedEq: EvVarDest" (ppr ev)
|
|
| 1960 | 1959 | |
| 1961 | --- | Good for both equalities and non-equalities
|
|
| 1962 | -setWantedEvTerm :: TcEvDest -> CanonicalEvidence -> EvTerm -> TcS ()
|
|
| 1963 | -setWantedEvTerm (HoleDest hole) _canonical tm
|
|
| 1960 | +setWantedDict :: TcEvDest -> CanonicalEvidence -> EvTerm -> TcS ()
|
|
| 1961 | +-- ^ Dictionaries only
|
|
| 1962 | +setWantedDict (EvVarDest ev_id) canonical tm
|
|
| 1963 | + = setEvBind (mkWantedEvBind ev_id canonical tm)
|
|
| 1964 | +setWantedDict (HoleDest h) _ _ = pprPanic "setWantedEq: HoleDest" (ppr h)
|
|
| 1965 | + |
|
| 1966 | +setWantedEvTerm :: TcEvDest -> RewriterSet -> CanonicalEvidence -> EvTerm -> TcS ()
|
|
| 1967 | +-- ^ Good for both equalities and non-equalities
|
|
| 1968 | +setWantedEvTerm (EvVarDest ev_id) _rewriters canonical tm
|
|
| 1969 | + = setEvBind (mkWantedEvBind ev_id canonical tm)
|
|
| 1970 | +setWantedEvTerm (HoleDest hole) rewriters _canonical tm
|
|
| 1964 | 1971 | | Just co <- evTermCoercion_maybe tm
|
| 1965 | 1972 | = do { addUsedCoercion co
|
| 1966 | - ; fillCoercionHole hole co }
|
|
| 1973 | + ; fillCoercionHole hole rewriters co }
|
|
| 1967 | 1974 | | otherwise
|
| 1968 | 1975 | = -- See Note [Yukky eq_sel for a HoleDest]
|
| 1969 | 1976 | do { let co_var = coHoleCoVar hole
|
| 1970 | 1977 | ; setEvBind (mkWantedEvBind co_var EvCanonical tm)
|
| 1971 | - ; fillCoercionHole hole (mkCoVarCo co_var) }
|
|
| 1972 | - |
|
| 1973 | -setWantedEvTerm (EvVarDest ev_id) canonical tm
|
|
| 1974 | - = setEvBind (mkWantedEvBind ev_id canonical tm)
|
|
| 1978 | + ; fillCoercionHole hole rewriters (mkCoVarCo co_var) }
|
|
| 1975 | 1979 | |
| 1976 | 1980 | {- Note [Yukky eq_sel for a HoleDest]
|
| 1977 | 1981 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -1992,16 +1996,17 @@ We even re-use the CoHole's Id for this binding! |
| 1992 | 1996 | Yuk!
|
| 1993 | 1997 | -}
|
| 1994 | 1998 | |
| 1995 | -fillCoercionHole :: CoercionHole -> Coercion -> TcS ()
|
|
| 1996 | -fillCoercionHole hole co
|
|
| 1997 | - = do { wrapTcS $ TcM.fillCoercionHole hole co
|
|
| 1998 | - ; kickOutAfterFillingCoercionHole hole co }
|
|
| 1999 | +fillCoercionHole :: CoercionHole -> RewriterSet -> Coercion -> TcS ()
|
|
| 2000 | +fillCoercionHole hole rewriters co
|
|
| 2001 | + = do { wrapTcS $ TcM.fillCoercionHole hole (co, rewriters)
|
|
| 2002 | + ; kickOutAfterFillingCoercionHole hole rewriters }
|
|
| 1999 | 2003 | |
| 2000 | 2004 | setEvBindIfWanted :: CtEvidence -> CanonicalEvidence -> EvTerm -> TcS ()
|
| 2001 | 2005 | setEvBindIfWanted ev canonical tm
|
| 2002 | 2006 | = case ev of
|
| 2003 | - CtWanted (WantedCt { ctev_dest = dest }) -> setWantedEvTerm dest canonical tm
|
|
| 2004 | - _ -> return ()
|
|
| 2007 | + CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rewriters })
|
|
| 2008 | + -> setWantedEvTerm dest rewriters canonical tm
|
|
| 2009 | + _ -> return ()
|
|
| 2005 | 2010 | |
| 2006 | 2011 | newTcEvBinds :: TcS EvBindsVar
|
| 2007 | 2012 | newTcEvBinds = wrapTcS TcM.newTcEvBinds
|
| ... | ... | @@ -1666,7 +1666,7 @@ solveWantedQCI mode ct@(CQuantCan (QCI { qci_ev = ev, qci_tvs = tvs |
| 1666 | 1666 | -- NB: even if it is fully solved we must return it, because it is
|
| 1667 | 1667 | -- carrying a record of which evidence variables are used
|
| 1668 | 1668 | -- See Note [Free vars of EvFun] in GHC.Tc.Types.Evidence
|
| 1669 | - do { setWantedEvTerm dest EvCanonical $
|
|
| 1669 | + do { setWantedDict dest EvCanonical $
|
|
| 1670 | 1670 | EvFun { et_tvs = skol_tvs, et_given = given_ev_vars
|
| 1671 | 1671 | , et_binds = TcEvBinds ev_binds_var
|
| 1672 | 1672 | , et_body = wantedCtEvEvId wanted_ev }
|
| ... | ... | @@ -1761,7 +1761,7 @@ finish_rewrite |
| 1761 | 1761 | ev_rw_role = ctEvRewriteRole ev
|
| 1762 | 1762 | ; mb_new_ev <- newWanted loc rewriters' new_pred
|
| 1763 | 1763 | ; massert (coercionRole co == ev_rw_role)
|
| 1764 | - ; setWantedEvTerm dest EvCanonical $
|
|
| 1764 | + ; setWantedEvTerm dest rewriters' EvCanonical $
|
|
| 1765 | 1765 | evCast (getEvExpr mb_new_ev) $
|
| 1766 | 1766 | downgradeRole Representational ev_rw_role (mkSymCo co)
|
| 1767 | 1767 | ; case mb_new_ev of
|
| ... | ... | @@ -1833,7 +1833,8 @@ runTcPluginsWanted wanted |
| 1833 | 1833 | where
|
| 1834 | 1834 | setEv :: (EvTerm,Ct) -> TcS ()
|
| 1835 | 1835 | setEv (ev,ct) = case ctEvidence ct of
|
| 1836 | - CtWanted (WantedCt { ctev_dest = dest }) -> setWantedEvTerm dest EvCanonical ev
|
|
| 1836 | + CtWanted (WantedCt { ctev_dest = dest, ctev_rewriters = rewriters })
|
|
| 1837 | + -> setWantedEvTerm dest rewriters EvCanonical ev
|
|
| 1837 | 1838 | -- TODO: plugins should be able to signal non-canonicity
|
| 1838 | 1839 | _ -> panic "runTcPluginsWanted.setEv: attempt to solve non-wanted!"
|
| 1839 | 1840 |
| ... | ... | @@ -90,8 +90,8 @@ module GHC.Tc.Types.Constraint ( |
| 90 | 90 | -- RewriterSet
|
| 91 | 91 | -- RewriterSet(..) is exported concretely only for zonkRewriterSet
|
| 92 | 92 | RewriterSet(..), emptyRewriterSet, isEmptyRewriterSet, elemRewriterSet,
|
| 93 | - addRewriter, unitRewriterSet, unionRewriterSet, rewriterSetFromCts,
|
|
| 94 | - delRewriterSet,
|
|
| 93 | + addRewriter, unitRewriterSet, unionRewriterSet, delRewriterSet,
|
|
| 94 | + rewriterSetFromCts,
|
|
| 95 | 95 | |
| 96 | 96 | wrapType,
|
| 97 | 97 | |
| ... | ... | @@ -128,7 +128,6 @@ import GHC.Tc.Types.CtLoc |
| 128 | 128 | import GHC.Builtin.Names
|
| 129 | 129 | |
| 130 | 130 | import GHC.Types.Var.Set
|
| 131 | -import GHC.Types.Unique.Set
|
|
| 132 | 131 | import GHC.Types.Name.Reader
|
| 133 | 132 | |
| 134 | 133 | import GHC.Utils.FV
|
| ... | ... | @@ -140,7 +139,6 @@ import GHC.Utils.Constants (debugIsOn) |
| 140 | 139 | import GHC.Data.Bag
|
| 141 | 140 | |
| 142 | 141 | import Control.Monad ( when )
|
| 143 | -import Data.Coerce
|
|
| 144 | 142 | import Data.List ( intersperse )
|
| 145 | 143 | import Data.Maybe ( mapMaybe, isJust )
|
| 146 | 144 | import GHC.Data.Maybe ( firstJust, firstJusts )
|
| ... | ... | @@ -2395,6 +2393,16 @@ wantedCtHasNoRewriters (WantedCt { ctev_rewriters = rws }) |
| 2395 | 2393 | setWantedCtEvRewriters :: WantedCtEvidence -> RewriterSet -> WantedCtEvidence
|
| 2396 | 2394 | setWantedCtEvRewriters ev rs = ev { ctev_rewriters = rs }
|
| 2397 | 2395 | |
| 2396 | +rewriterSetFromCts :: Bag Ct -> RewriterSet
|
|
| 2397 | +-- Take a bag of Wanted equalities, and collect them as a RewriterSet
|
|
| 2398 | +rewriterSetFromCts cts
|
|
| 2399 | + = foldr add emptyRewriterSet cts
|
|
| 2400 | + where
|
|
| 2401 | + add ct rw_set =
|
|
| 2402 | + case ctEvidence ct of
|
|
| 2403 | + CtWanted (WantedCt { ctev_dest = HoleDest hole }) -> rw_set `addRewriter` hole
|
|
| 2404 | + _ -> rw_set
|
|
| 2405 | + |
|
| 2398 | 2406 | ctEvExpr :: HasDebugCallStack => CtEvidence -> EvExpr
|
| 2399 | 2407 | ctEvExpr (CtWanted ev@(WantedCt { ctev_dest = HoleDest _ }))
|
| 2400 | 2408 | = Coercion $ ctEvCoercion (CtWanted ev)
|
| ... | ... | @@ -2488,50 +2496,6 @@ isGiven :: CtEvidence -> Bool |
| 2488 | 2496 | isGiven (CtGiven {}) = True
|
| 2489 | 2497 | isGiven _ = False
|
| 2490 | 2498 | |
| 2491 | -{-
|
|
| 2492 | -************************************************************************
|
|
| 2493 | -* *
|
|
| 2494 | - RewriterSet
|
|
| 2495 | -* *
|
|
| 2496 | -************************************************************************
|
|
| 2497 | --}
|
|
| 2498 | - |
|
| 2499 | --- | Stores a set of CoercionHoles that have been used to rewrite a constraint.
|
|
| 2500 | --- See Note [Wanteds rewrite Wanteds].
|
|
| 2501 | -newtype RewriterSet = RewriterSet (UniqSet CoercionHole)
|
|
| 2502 | - deriving newtype (Outputable, Semigroup, Monoid)
|
|
| 2503 | - |
|
| 2504 | -emptyRewriterSet :: RewriterSet
|
|
| 2505 | -emptyRewriterSet = RewriterSet emptyUniqSet
|
|
| 2506 | - |
|
| 2507 | -unitRewriterSet :: CoercionHole -> RewriterSet
|
|
| 2508 | -unitRewriterSet = coerce (unitUniqSet @CoercionHole)
|
|
| 2509 | - |
|
| 2510 | -elemRewriterSet :: CoercionHole -> RewriterSet -> Bool
|
|
| 2511 | -elemRewriterSet = coerce (elementOfUniqSet @CoercionHole)
|
|
| 2512 | - |
|
| 2513 | -delRewriterSet :: RewriterSet -> CoercionHole -> RewriterSet
|
|
| 2514 | -delRewriterSet = coerce (delOneFromUniqSet @CoercionHole)
|
|
| 2515 | - |
|
| 2516 | -unionRewriterSet :: RewriterSet -> RewriterSet -> RewriterSet
|
|
| 2517 | -unionRewriterSet = coerce (unionUniqSets @CoercionHole)
|
|
| 2518 | - |
|
| 2519 | -isEmptyRewriterSet :: RewriterSet -> Bool
|
|
| 2520 | -isEmptyRewriterSet = coerce (isEmptyUniqSet @CoercionHole)
|
|
| 2521 | - |
|
| 2522 | -addRewriter :: RewriterSet -> CoercionHole -> RewriterSet
|
|
| 2523 | -addRewriter = coerce (addOneToUniqSet @CoercionHole)
|
|
| 2524 | - |
|
| 2525 | -rewriterSetFromCts :: Bag Ct -> RewriterSet
|
|
| 2526 | --- Take a bag of Wanted equalities, and collect them as a RewriterSet
|
|
| 2527 | -rewriterSetFromCts cts
|
|
| 2528 | - = foldr add emptyRewriterSet cts
|
|
| 2529 | - where
|
|
| 2530 | - add ct rw_set =
|
|
| 2531 | - case ctEvidence ct of
|
|
| 2532 | - CtWanted (WantedCt { ctev_dest = HoleDest hole }) -> rw_set `addRewriter` hole
|
|
| 2533 | - _ -> rw_set
|
|
| 2534 | - |
|
| 2535 | 2499 | {-
|
| 2536 | 2500 | ************************************************************************
|
| 2537 | 2501 | * *
|
| ... | ... | @@ -360,15 +360,14 @@ newCoercionHole pred_ty |
| 360 | 360 | ; return $ CoercionHole { ch_co_var = co_var, ch_ref = ref } }
|
| 361 | 361 | |
| 362 | 362 | -- | Put a value in a coercion hole
|
| 363 | -fillCoercionHole :: CoercionHole -> Coercion -> TcM ()
|
|
| 364 | -fillCoercionHole (CoercionHole { ch_ref = ref, ch_co_var = cv }) co = do
|
|
| 365 | - when debugIsOn $ do
|
|
| 366 | - cts <- readTcRef ref
|
|
| 367 | - whenIsJust cts $ \old_co ->
|
|
| 368 | - pprPanic "Filling a filled coercion hole" (ppr cv $$ ppr co $$ ppr old_co)
|
|
| 369 | - traceTc "Filling coercion hole" (ppr cv <+> text ":=" <+> ppr co)
|
|
| 370 | - writeTcRef ref (Just co)
|
|
| 371 | - |
|
| 363 | +fillCoercionHole :: CoercionHole -> (Coercion, RewriterSet) -> TcM ()
|
|
| 364 | +fillCoercionHole (CoercionHole { ch_ref = ref, ch_co_var = cv }) co
|
|
| 365 | + = do { when debugIsOn $
|
|
| 366 | + do { cts <- readTcRef ref
|
|
| 367 | + ; whenIsJust cts $ \old_co ->
|
|
| 368 | + pprPanic "Filling a filled coercion hole" (ppr cv $$ ppr co $$ ppr old_co) }
|
|
| 369 | + ; traceTc "Filling coercion hole" (ppr cv <+> text ":=" <+> ppr co)
|
|
| 370 | + ; writeTcRef ref (Just co) }
|
|
| 372 | 371 | |
| 373 | 372 | {- **********************************************************************
|
| 374 | 373 | *
|
| ... | ... | @@ -1546,8 +1545,8 @@ collect_cand_qtvs_co orig_ty cur_lvl bound = go_co |
| 1546 | 1545 | go_co dv (HoleCo hole)
|
| 1547 | 1546 | = do m_co <- liftZonkM (unpackCoercionHole_maybe hole)
|
| 1548 | 1547 | case m_co of
|
| 1549 | - Just co -> go_co dv co
|
|
| 1550 | - Nothing -> go_cv dv (coHoleCoVar hole)
|
|
| 1548 | + Just (co,_) -> go_co dv co
|
|
| 1549 | + Nothing -> go_cv dv (coHoleCoVar hole)
|
|
| 1551 | 1550 | |
| 1552 | 1551 | go_co dv (CoVarCo cv) = go_cv dv cv
|
| 1553 | 1552 |
| ... | ... | @@ -43,8 +43,6 @@ module GHC.Tc.Zonk.TcType |
| 43 | 43 | |
| 44 | 44 | -- * Coercion holes
|
| 45 | 45 | , isFilledCoercionHole, unpackCoercionHole, unpackCoercionHole_maybe
|
| 46 | - , freeHolesOfCoercion
|
|
| 47 | - |
|
| 48 | 46 | |
| 49 | 47 | -- * Tidying
|
| 50 | 48 | , tcInitTidyEnv, tcInitOpenTidyEnv
|
| ... | ... | @@ -241,8 +239,8 @@ zonkCo :: Coercion -> ZonkM Coercion |
| 241 | 239 | hole _ hole@(CoercionHole { ch_ref = ref, ch_co_var = cv })
|
| 242 | 240 | = do { contents <- readTcRef ref
|
| 243 | 241 | ; case contents of
|
| 244 | - Just co -> do { co' <- zonkCo co
|
|
| 245 | - ; checkCoercionHole cv co' }
|
|
| 242 | + Just (co,_) -> do { co' <- zonkCo co
|
|
| 243 | + ; checkCoercionHole cv co' }
|
|
| 246 | 244 | Nothing -> do { cv' <- zonkCoVar cv
|
| 247 | 245 | ; return $ HoleCo (hole { ch_co_var = cv' }) } }
|
| 248 | 246 | |
| ... | ... | @@ -592,26 +590,12 @@ zonkRewriterSet (RewriterSet set) |
| 592 | 590 | go :: CoercionHole -> UnfilledCoercionHoleMonoid -> UnfilledCoercionHoleMonoid
|
| 593 | 591 | go hole m_acc = freeHolesOfHole hole `mappend` m_acc
|
| 594 | 592 | |
| 595 | -freeHolesOfCoercion :: Coercion -> ZonkM RewriterSet
|
|
| 596 | -freeHolesOfCoercion co = unUCHM (freeHolesOfCo co)
|
|
| 597 | - |
|
| 598 | 593 | freeHolesOfHole :: CoercionHole -> UnfilledCoercionHoleMonoid
|
| 599 | 594 | freeHolesOfHole hole
|
| 600 | 595 | = UCHM $ do { m_co <- unpackCoercionHole_maybe hole
|
| 601 | 596 | ; case m_co of
|
| 602 | 597 | Nothing -> return (unitRewriterSet hole) -- Not filled
|
| 603 | - Just co -> unUCHM (freeHolesOfCo co) } -- Filled: look inside
|
|
| 604 | - |
|
| 605 | -freeHolesOfTy :: Type -> UnfilledCoercionHoleMonoid
|
|
| 606 | -freeHolesOfCo :: Coercion -> UnfilledCoercionHoleMonoid
|
|
| 607 | -(freeHolesOfTy, _, freeHolesOfCo, _) = foldTyCo freeHolesFolder ()
|
|
| 608 | - |
|
| 609 | -freeHolesFolder :: TyCoFolder () UnfilledCoercionHoleMonoid
|
|
| 610 | -freeHolesFolder = TyCoFolder { tcf_view = noView
|
|
| 611 | - , tcf_tyvar = \ _ tv -> freeHolesOfTy (tyVarKind tv)
|
|
| 612 | - , tcf_covar = \ _ cv -> freeHolesOfTy (varType cv)
|
|
| 613 | - , tcf_hole = \ _ h -> freeHolesOfHole h
|
|
| 614 | - , tcf_tycobinder = \ _ _ _ -> () }
|
|
| 598 | + Just (_co,holes) -> zonkRewriterSet holes }
|
|
| 615 | 599 | |
| 616 | 600 | newtype UnfilledCoercionHoleMonoid = UCHM { unUCHM :: ZonkM RewriterSet }
|
| 617 | 601 | |
| ... | ... | @@ -641,11 +625,11 @@ unpackCoercionHole :: CoercionHole -> ZonkM Coercion |
| 641 | 625 | unpackCoercionHole hole
|
| 642 | 626 | = do { contents <- unpackCoercionHole_maybe hole
|
| 643 | 627 | ; case contents of
|
| 644 | - Just co -> return co
|
|
| 628 | + Just (co,_) -> return co
|
|
| 645 | 629 | Nothing -> pprPanic "Unfilled coercion hole" (ppr hole) }
|
| 646 | 630 | |
| 647 | 631 | -- | Retrieve the contents of a coercion hole, if it is filled
|
| 648 | -unpackCoercionHole_maybe :: CoercionHole -> ZonkM (Maybe Coercion)
|
|
| 632 | +unpackCoercionHole_maybe :: CoercionHole -> ZonkM (Maybe (Coercion,RewriterSet))
|
|
| 649 | 633 | unpackCoercionHole_maybe (CoercionHole { ch_ref = ref }) = readTcRef ref
|
| 650 | 634 | |
| 651 | 635 |
| ... | ... | @@ -488,8 +488,8 @@ zonkCoHole :: CoercionHole -> ZonkTcM Coercion |
| 488 | 488 | zonkCoHole hole@(CoercionHole { ch_ref = ref, ch_co_var = cv })
|
| 489 | 489 | = do { contents <- readTcRef ref
|
| 490 | 490 | ; case contents of
|
| 491 | - Just co -> do { co' <- zonkCoToCo co
|
|
| 492 | - ; lift $ liftZonkM $ checkCoercionHole cv co' }
|
|
| 491 | + Just (co,_) -> do { co' <- zonkCoToCo co
|
|
| 492 | + ; lift $ liftZonkM $ checkCoercionHole cv co' }
|
|
| 493 | 493 | |
| 494 | 494 | -- This next case should happen only in the presence of
|
| 495 | 495 | -- (undeferred) type errors. Originally, I put in a panic
|