Simon Peyton Jones pushed to branch wip/T23162-spj at Glasgow Haskell Compiler / GHC
Commits:
-
58d6142b
by Simon Peyton Jones at 2025-08-14T12:15:10+01:00
5 changed files:
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Tc/Solver/FunDeps.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Utils/Outputable.hs
Changes:
| ... | ... | @@ -253,7 +253,7 @@ pprTermM y p t = pprDeeper `liftM` ppr_termM y p t |
| 253 | 253 | ppr_termM y p Term{dc=Left dc_tag, subTerms=tt} = do
|
| 254 | 254 | tt_docs <- mapM (y app_prec) tt
|
| 255 | 255 | return $ cparen (not (null tt) && p >= app_prec)
|
| 256 | - (text dc_tag <+> pprDeeperList fsep tt_docs)
|
|
| 256 | + (text dc_tag <+> pprDeeper (fsep tt_docs))
|
|
| 257 | 257 | |
| 258 | 258 | ppr_termM y p Term{dc=Right dc, subTerms=tt}
|
| 259 | 259 | {- | dataConIsInfix dc, (t1:t2:tt') <- tt --TODO fixity
|
| ... | ... | @@ -270,7 +270,7 @@ ppr_termM y p Term{dc=Right dc, subTerms=tt} |
| 270 | 270 | show_tm tt_docs
|
| 271 | 271 | | null tt_docs = ppr dc
|
| 272 | 272 | | otherwise = cparen (p >= app_prec) $
|
| 273 | - sep [ppr dc, nest 2 (pprDeeperList fsep tt_docs)]
|
|
| 273 | + sep [ppr dc, nest 2 (pprDeeper (fsep tt_docs))]
|
|
| 274 | 274 | |
| 275 | 275 | ppr_termM y p t@NewtypeWrap{} = pprNewtypeWrap y p t
|
| 276 | 276 | ppr_termM y p RefWrap{wrapped_term=t} = do
|
| ... | ... | @@ -929,6 +929,11 @@ solving. |
| 929 | 929 | solveFunDeps :: CtEvidence -- The work item
|
| 930 | 930 | -> [FunDepEqn (CtLoc, RewriterSet)]
|
| 931 | 931 | -> TcS Bool
|
| 932 | +-- Solve a bunch of type-equality equations, generated by functional dependencies
|
|
| 933 | +-- By "solve" we mean: (only) do unifications. We do not generate evidence, and
|
|
| 934 | +-- other than unifications there should be no effects whatsoever
|
|
| 935 | +--
|
|
| 936 | +-- Return True if some unifications happened
|
|
| 932 | 937 | -- See Note [FunDep and implicit parameter reactions]
|
| 933 | 938 | solveFunDeps work_ev fd_eqns
|
| 934 | 939 | | null fd_eqns
|
| ... | ... | @@ -16,7 +16,7 @@ module GHC.Tc.Solver.InertSet ( |
| 16 | 16 | -- * The inert set
|
| 17 | 17 | InertSet(..),
|
| 18 | 18 | InertCans(..),
|
| 19 | - emptyInertSet, emptyInertCans,
|
|
| 19 | + emptyInertSet, emptyInertCans, resetInertCans,
|
|
| 20 | 20 | |
| 21 | 21 | noGivenNewtypeReprEqs, updGivenEqs,
|
| 22 | 22 | prohibitedSuperClassSolve,
|
| ... | ... | @@ -76,7 +76,7 @@ import GHC.Utils.Panic |
| 76 | 76 | import GHC.Data.Bag
|
| 77 | 77 | |
| 78 | 78 | import Control.Monad ( forM_ )
|
| 79 | -import Data.List.NonEmpty ( NonEmpty(..), (<|) )
|
|
| 79 | +import qualified Data.List.NonEmpty as NE
|
|
| 80 | 80 | import Data.Function ( on )
|
| 81 | 81 | |
| 82 | 82 | {-
|
| ... | ... | @@ -305,7 +305,7 @@ instance Outputable WorkList where |
| 305 | 305 | * *
|
| 306 | 306 | ********************************************************************* -}
|
| 307 | 307 | |
| 308 | -type CycleBreakerVarStack = NonEmpty (Bag (TcTyVar, TcType))
|
|
| 308 | +type CycleBreakerVarStack = NE.NonEmpty (Bag (TcTyVar, TcType))
|
|
| 309 | 309 | -- ^ a stack of (CycleBreakerTv, original family applications) lists
|
| 310 | 310 | -- first element in the stack corresponds to current implication;
|
| 311 | 311 | -- later elements correspond to outer implications
|
| ... | ... | @@ -323,6 +323,7 @@ data InertSet |
| 323 | 323 | , inert_givens :: InertCans
|
| 324 | 324 | -- A subset of inert_cans, containing only Givens
|
| 325 | 325 | -- Used to initialise inert_cans when recursing inside implications
|
| 326 | + -- See `resetInertCans`
|
|
| 326 | 327 | |
| 327 | 328 | , inert_cycle_breakers :: CycleBreakerVarStack
|
| 328 | 329 | |
| ... | ... | @@ -378,13 +379,21 @@ emptyInertSet :: TcLevel -> InertSet |
| 378 | 379 | emptyInertSet given_eq_lvl
|
| 379 | 380 | = IS { inert_cans = empty_cans
|
| 380 | 381 | , inert_givens = empty_cans
|
| 381 | - , inert_cycle_breakers = emptyBag :| []
|
|
| 382 | + , inert_cycle_breakers = emptyBag NE.:| []
|
|
| 382 | 383 | , inert_famapp_cache = emptyFunEqs
|
| 383 | 384 | , inert_solved_dicts = emptyDictMap
|
| 384 | 385 | , inert_safehask = emptyDictMap }
|
| 385 | 386 | where
|
| 386 | 387 | empty_cans = emptyInertCans given_eq_lvl
|
| 387 | 388 | |
| 389 | + |
|
| 390 | +resetInertCans :: InertSet -> InertSet
|
|
| 391 | +-- Reset the `inert_cans` to the saved `inert_givens :: InertCans`
|
|
| 392 | +-- In effect, this just purges all Wanteds from the InertSet
|
|
| 393 | +resetInertCans inerts@(IS { inert_givens = saved_givens })
|
|
| 394 | + = inerts { inert_cans = saved_givens }
|
|
| 395 | + |
|
| 396 | + |
|
| 388 | 397 | {- Note [Solved dictionaries]
|
| 389 | 398 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 390 | 399 | When we apply a top-level instance declaration, we add the "solved"
|
| ... | ... | @@ -1913,8 +1922,9 @@ prohibitedSuperClassSolve given_loc wanted_loc |
| 1913 | 1922 | |
| 1914 | 1923 | -- | Push a fresh environment onto the cycle-breaker var stack. Useful
|
| 1915 | 1924 | -- when entering a nested implication.
|
| 1916 | -pushCycleBreakerVarStack :: CycleBreakerVarStack -> CycleBreakerVarStack
|
|
| 1917 | -pushCycleBreakerVarStack = (emptyBag <|)
|
|
| 1925 | +pushCycleBreakerVarStack :: InertSet -> InertSet
|
|
| 1926 | +pushCycleBreakerVarStack inerts@(IS { inert_cycle_breakers = cbs })
|
|
| 1927 | + = inerts { inert_cycle_breakers = emptyBag NE.<| cbs }
|
|
| 1918 | 1928 | |
| 1919 | 1929 | -- | Add a new cycle-breaker binding to the top environment on the stack.
|
| 1920 | 1930 | addCycleBreakerBindings :: Bag (TcTyVar, Type) -- ^ (cbv,expansion) pairs
|
| ... | ... | @@ -1923,14 +1933,14 @@ addCycleBreakerBindings prs ics |
| 1923 | 1933 | = assertPpr (all (isCycleBreakerTyVar . fst) prs) (ppr prs) $
|
| 1924 | 1934 | ics { inert_cycle_breakers = add_to (inert_cycle_breakers ics) }
|
| 1925 | 1935 | where
|
| 1926 | - add_to (top_env :| rest_envs) = (prs `unionBags` top_env) :| rest_envs
|
|
| 1936 | + add_to (top_env NE.:| rest_envs) = (prs `unionBags` top_env) NE.:| rest_envs
|
|
| 1927 | 1937 | |
| 1928 | 1938 | -- | Perform a monadic operation on all pairs in the top environment
|
| 1929 | 1939 | -- in the stack.
|
| 1930 | 1940 | forAllCycleBreakerBindings_ :: Monad m
|
| 1931 | 1941 | => CycleBreakerVarStack
|
| 1932 | 1942 | -> (TcTyVar -> TcType -> m ()) -> m ()
|
| 1933 | -forAllCycleBreakerBindings_ (top_env :| _rest_envs) action
|
|
| 1943 | +forAllCycleBreakerBindings_ (top_env NE.:| _rest_envs) action
|
|
| 1934 | 1944 | = forM_ top_env (uncurry action)
|
| 1935 | 1945 | {-# INLINABLE forAllCycleBreakerBindings_ #-} -- to allow SPECIALISE later
|
| 1936 | 1946 |
| ... | ... | @@ -1177,14 +1177,13 @@ nestImplicTcS ev_binds_var inner_tclvl (TcS thing_inside) |
| 1177 | 1177 | = TcS $ \ env@(TcSEnv { tcs_inerts = old_inert_var }) ->
|
| 1178 | 1178 | do { inerts <- TcM.readTcRef old_inert_var
|
| 1179 | 1179 | |
| 1180 | - -- Initialise the inert_cans from the inert_givens of the parent
|
|
| 1181 | - -- so that the child is not polluted with the parent's inert Wanteds
|
|
| 1180 | + -- resetInertcans: initialise the inert_cans from the inert_givens of the
|
|
| 1181 | + -- parent so that the child is not polluted with the parent's inert Wanteds
|
|
| 1182 | 1182 | -- See Note [trySolveImplication] in GHC.Tc.Solver.Solve
|
| 1183 | 1183 | -- All other InertSet fields are inherited
|
| 1184 | - ; let nest_inert = inerts { inert_cycle_breakers = pushCycleBreakerVarStack
|
|
| 1185 | - (inert_cycle_breakers inerts)
|
|
| 1186 | - , inert_cans = (inert_givens inerts)
|
|
| 1187 | - { inert_given_eqs = False } }
|
|
| 1184 | + ; let nest_inert = pushCycleBreakerVarStack $
|
|
| 1185 | + resetInertCans $
|
|
| 1186 | + inerts
|
|
| 1188 | 1187 | ; new_inert_var <- TcM.newTcRef nest_inert
|
| 1189 | 1188 | ; new_wl_var <- TcM.newTcRef emptyWorkList
|
| 1190 | 1189 | ; let nest_env = env { tcs_ev_binds = ev_binds_var
|
| ... | ... | @@ -1203,6 +1202,26 @@ nestImplicTcS ev_binds_var inner_tclvl (TcS thing_inside) |
| 1203 | 1202 | #endif
|
| 1204 | 1203 | ; return res }
|
| 1205 | 1204 | |
| 1205 | +nestFunDepsTcS :: TcS a -> TcS (Bool, a)
|
|
| 1206 | +nestFunDepsTcS (TcS thing_inside)
|
|
| 1207 | + = reportUnifications $
|
|
| 1208 | + TcS $ \ env@(TcSEnv { tcs_inerts = inerts_var }) ->
|
|
| 1209 | + TcM.pushTcLevelM_ $
|
|
| 1210 | + -- pushTcLevelTcM: increase the level so that unification variables
|
|
| 1211 | + -- allocated by the fundep-creation itself don't count as useful unifications
|
|
| 1212 | + do { inerts <- TcM.readTcRef inerts_var
|
|
| 1213 | + ; let nest_inerts = resetInertCans inerts
|
|
| 1214 | + -- resetInertCasns: like nestImplicTcS
|
|
| 1215 | + ; new_inert_var <- TcM.newTcRef nest_inerts
|
|
| 1216 | + ; new_wl_var <- TcM.newTcRef emptyWorkList
|
|
| 1217 | + ; let nest_env = env { tcs_inerts = new_inert_var
|
|
| 1218 | + , tcs_worklist = new_wl_var }
|
|
| 1219 | + |
|
| 1220 | + ; TcM.traceTc "nestFunDepsTcS {" empty
|
|
| 1221 | + ; res <- thing_inside nest_env
|
|
| 1222 | + ; TcM.traceTc "nestFunDepsTcS }" empty
|
|
| 1223 | + ; return res }
|
|
| 1224 | + |
|
| 1206 | 1225 | nestTcS :: TcS a -> TcS a
|
| 1207 | 1226 | -- Use the current untouchables, augmenting the current
|
| 1208 | 1227 | -- evidence bindings, and solved dictionaries
|
| ... | ... | @@ -1262,24 +1281,6 @@ tryTcS (TcS thing_inside) |
| 1262 | 1281 | |
| 1263 | 1282 | ; return True } }
|
| 1264 | 1283 | |
| 1265 | -nestFunDepsTcS :: TcS a -> TcS (Bool, a)
|
|
| 1266 | -nestFunDepsTcS (TcS thing_inside)
|
|
| 1267 | - = reportUnifications $
|
|
| 1268 | - TcS $ \ env@(TcSEnv { tcs_inerts = inerts_var }) ->
|
|
| 1269 | - TcM.pushTcLevelM_ $
|
|
| 1270 | - -- pushTcLevelTcM: increase the level so that unification variables
|
|
| 1271 | - -- allocated by the fundep-creation itself don't count as useful unifications
|
|
| 1272 | - do { inerts <- TcM.readTcRef inerts_var
|
|
| 1273 | - ; new_inert_var <- TcM.newTcRef inerts
|
|
| 1274 | - ; new_wl_var <- TcM.newTcRef emptyWorkList
|
|
| 1275 | - ; let nest_env = env { tcs_inerts = new_inert_var
|
|
| 1276 | - , tcs_worklist = new_wl_var }
|
|
| 1277 | - |
|
| 1278 | - ; TcM.traceTc "nestFunDepsTcS {" empty
|
|
| 1279 | - ; res <- thing_inside nest_env
|
|
| 1280 | - ; TcM.traceTc "nestFunDepsTcS }" empty
|
|
| 1281 | - ; return res }
|
|
| 1282 | - |
|
| 1283 | 1284 | updateInertsWith :: InertSet -> InertSet -> InertSet
|
| 1284 | 1285 | -- Update the current inert set with bits from a nested solve,
|
| 1285 | 1286 | -- that finished with a new inert set
|
| ... | ... | @@ -528,8 +528,10 @@ pprDeeperList f ds |
| 528 | 528 | | null ds = f []
|
| 529 | 529 | | otherwise = SDoc work
|
| 530 | 530 | where
|
| 531 | - work ctx@SDC{ sdocStyle=PprUser {} }
|
|
| 531 | + work ctx@SDC{ sdocStyle=PprUser _ (PartWay {}) _ }
|
|
| 532 | 532 | = let -- Only do this depth-limitation in User style
|
| 533 | + -- when PartWay is on. Why not for DefaultDepth?
|
|
| 534 | + -- I have no idea; seems like a bug to me.
|
|
| 533 | 535 | go _ [] = []
|
| 534 | 536 | go i (d:ds) | i >= default_depth = [text "...."]
|
| 535 | 537 | | otherwise = d : go (i+1) ds
|