Simon Peyton Jones pushed to branch wip/T23162-spj at Glasgow Haskell Compiler / GHC
Commits:
-
d6fac0a4
by Simon Peyton Jones at 2025-08-08T11:37:43+01:00
4 changed files:
- compiler/GHC/Tc/Solver/FunDeps.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Utils/Unify.hs
Changes:
... | ... | @@ -323,9 +323,11 @@ doDictFunDepImprovementLocal dict_ct@(DictCt { di_cls = cls, di_ev = work_ev }) |
323 | 323 | = Stage $
|
324 | 324 | do { inerts <- getInertCans
|
325 | 325 | |
326 | + ; traceTcS "doDictFunDepImprovementLocal {" (ppr dict_ct)
|
|
326 | 327 | ; imp <- solveFunDeps $
|
327 | 328 | foldM do_interaction emptyCts $
|
328 | 329 | findDictsByClass (inert_dicts inerts) cls
|
330 | + ; traceTcS "doDictFunDepImprovementLocal }" (text "imp =" <+> ppr imp)
|
|
329 | 331 | |
330 | 332 | ; if imp then startAgainWith (CDictCan dict_ct)
|
331 | 333 | else continueWith () }
|
... | ... | @@ -344,15 +346,13 @@ doDictFunDepImprovementLocal dict_ct@(DictCt { di_cls = cls, di_ev = work_ev }) |
344 | 346 | = return new_eqs1
|
345 | 347 | |
346 | 348 | | otherwise
|
347 | - = do { traceTcS "doLocalFunDepImprovement" $
|
|
348 | - vcat [ ppr work_ev
|
|
349 | - , pprCtLoc work_loc, ppr (isGivenLoc work_loc)
|
|
350 | - , pprCtLoc inert_loc, ppr (isGivenLoc inert_loc)
|
|
351 | - , pprCtLoc deriv_loc, ppr (isGivenLoc deriv_loc) ]
|
|
352 | - |
|
353 | - ; new_eqs2 <- unifyFunDepWanteds_new work_ev $
|
|
349 | + = do { new_eqs2 <- unifyFunDepWanteds_new work_ev $
|
|
354 | 350 | improveFromAnother (deriv_loc, inert_rewriters)
|
355 | 351 | inert_pred work_pred
|
352 | + |
|
353 | + ; traceTcS "doDictFunDepImprovementLocal item" $
|
|
354 | + vcat [ ppr work_ev, ppr new_eqs2 ]
|
|
355 | + |
|
356 | 356 | ; return (new_eqs1 `unionBags` new_eqs2) }
|
357 | 357 | where
|
358 | 358 | inert_pred = ctEvPred inert_ev
|
... | ... | @@ -374,10 +374,12 @@ doDictFunDepImprovementTop dict_ct@(DictCt { di_ev = ev, di_cls = cls, di_tys = |
374 | 374 | = Stage $
|
375 | 375 | do { inst_envs <- getInstEnvs
|
376 | 376 | |
377 | + ; traceTcS "doDictFunDepImprovementTop {" (ppr dict_ct)
|
|
377 | 378 | ; let eqns :: [FunDepEqn (CtLoc, RewriterSet)]
|
378 | 379 | eqns = improveFromInstEnv inst_envs mk_ct_loc cls xis
|
379 | 380 | ; imp <- solveFunDeps $
|
380 | 381 | unifyFunDepWanteds_new ev eqns
|
382 | + ; traceTcS "doDictFunDepImprovementTop }" (text "imp =" <+> ppr imp)
|
|
381 | 383 | |
382 | 384 | ; if imp then startAgainWith (CDictCan dict_ct)
|
383 | 385 | else continueWith () }
|
... | ... | @@ -44,7 +44,7 @@ module GHC.Tc.Solver.Monad ( |
44 | 44 | panicTcS, traceTcS, tryEarlyAbortTcS,
|
45 | 45 | traceFireTcS, bumpStepCountTcS, csTraceTcS,
|
46 | 46 | wrapErrTcS, wrapWarnTcS,
|
47 | - getUnificationFlag,
|
|
47 | + getUnificationFlag, traceUnificationFlag,
|
|
48 | 48 | |
49 | 49 | -- Evidence creation and transformation
|
50 | 50 | MaybeNew(..), freshGoals, isFresh, getEvExpr,
|
... | ... | @@ -454,7 +454,8 @@ kickOutAfterUnification :: [TcTyVar] -> TcS () |
454 | 454 | kickOutAfterUnification tv_list
|
455 | 455 | = case nonEmpty tv_list of
|
456 | 456 | Nothing -> return ()
|
457 | - Just tvs -> setUnificationFlagTo min_tv_lvl
|
|
457 | + Just tvs -> do { traceTcS "kickOutAfterUnification" (ppr min_tv_lvl $$ ppr tv_list)
|
|
458 | + ; setUnificationFlagTo min_tv_lvl }
|
|
458 | 459 | where
|
459 | 460 | min_tv_lvl = foldr1 minTcLevel (NE.map tcTyVarLevel tvs)
|
460 | 461 | |
... | ... | @@ -1833,16 +1834,31 @@ reportUnifications (TcS thing_inside) |
1833 | 1834 | | ambient_lvl `deeperThanOrSame` unif_lvl
|
1834 | 1835 | -> -- Some useful unifications took place
|
1835 | 1836 | do { mb_outer_lvl <- TcM.readTcRef outer_ul_var
|
1837 | + ; TcM.traceTc "reportUnifications" $
|
|
1838 | + vcat [ text "ambient =" <+> ppr ambient_lvl
|
|
1839 | + , text "unif_lvl =" <+> ppr unif_lvl
|
|
1840 | + , text "mb_outer =" <+> ppr mb_outer_lvl ]
|
|
1836 | 1841 | ; case mb_outer_lvl of
|
1837 | - Just outer_unif_lvl | outer_unif_lvl `strictlyDeeperThan` unif_lvl
|
|
1838 | - -> -- Update, because outer_unif_lv > unif_lvl
|
|
1842 | + Just outer_unif_lvl | unif_lvl `deeperThanOrSame` outer_unif_lvl
|
|
1843 | + -> -- No need to update: outer_unif_lvl is already shallower
|
|
1844 | + return ()
|
|
1845 | + _ -> -- Update the outer level
|
|
1839 | 1846 | TcM.writeTcRef outer_ul_var (Just unif_lvl)
|
1840 | - _ -> return ()
|
|
1841 | 1847 | ; return (True, res) }
|
1842 | 1848 | |
1843 | 1849 | _ -> -- No useful unifications
|
1844 | 1850 | return (False, res) }
|
1845 | 1851 | |
1852 | +traceUnificationFlag :: String -> TcS ()
|
|
1853 | +traceUnificationFlag str
|
|
1854 | + = TcS $ \env ->
|
|
1855 | + do { ambient_lvl <- TcM.getTcLevel
|
|
1856 | + ; mb_lvl <- TcM.readTcRef (tcs_unif_lvl env)
|
|
1857 | + ; TcM.traceTc ("trace-uni-flag: " ++ str) $
|
|
1858 | + vcat [ text "ambient =" <+> ppr ambient_lvl
|
|
1859 | + , text "mb_lvl =" <+> ppr mb_lvl ]
|
|
1860 | + ; return () }
|
|
1861 | + |
|
1846 | 1862 | getUnificationFlag :: TcS Bool
|
1847 | 1863 | -- We are at ambient level i
|
1848 | 1864 | -- If the unification flag = Just i, reset it to Nothing and return True
|
... | ... | @@ -1872,8 +1888,11 @@ setUnificationFlagTo lvl |
1872 | 1888 | ; mb_lvl <- TcM.readTcRef ref
|
1873 | 1889 | ; case mb_lvl of
|
1874 | 1890 | Just unif_lvl | lvl `deeperThanOrSame` unif_lvl
|
1875 | - -> return ()
|
|
1876 | - _ -> TcM.writeTcRef ref (Just lvl) }
|
|
1891 | + -> do { TcM.traceTc "set-uni-flag skip" $
|
|
1892 | + vcat [ text "lvl" <+> ppr lvl, text "unif_lvl" <+> ppr unif_lvl ]
|
|
1893 | + ; return () }
|
|
1894 | + _ -> do { TcM.traceTc "set-uni-flag" (ppr lvl)
|
|
1895 | + ; TcM.writeTcRef ref (Just lvl) } }
|
|
1877 | 1896 | |
1878 | 1897 | |
1879 | 1898 | {- *********************************************************************
|
... | ... | @@ -2263,14 +2282,16 @@ wrapUnifierX :: CtEvidence -> Role |
2263 | 2282 | -> TcS (a, Bag Ct, [TcTyVar])
|
2264 | 2283 | wrapUnifierX ev role do_unifications
|
2265 | 2284 | = do { unif_count_ref <- getUnifiedRef
|
2285 | + ; given_eq_lvl <- getInnermostGivenEqLevel
|
|
2266 | 2286 | ; wrapTcS $
|
2267 | 2287 | do { defer_ref <- TcM.newTcRef emptyBag
|
2268 | 2288 | ; unified_ref <- TcM.newTcRef []
|
2269 | - ; let env = UE { u_role = role
|
|
2270 | - , u_rewriters = ctEvRewriters ev
|
|
2271 | - , u_loc = ctEvLoc ev
|
|
2272 | - , u_defer = defer_ref
|
|
2273 | - , u_unified = Just unified_ref}
|
|
2289 | + ; let env = UE { u_role = role
|
|
2290 | + , u_given_eq_lvl = given_eq_lvl
|
|
2291 | + , u_rewriters = ctEvRewriters ev
|
|
2292 | + , u_loc = ctEvLoc ev
|
|
2293 | + , u_defer = defer_ref
|
|
2294 | + , u_unified = Just unified_ref}
|
|
2274 | 2295 | -- u_rewriters: the rewriter set and location from
|
2275 | 2296 | -- the parent constraint `ev` are inherited in any
|
2276 | 2297 | -- new constraints spat out by the unifier
|
... | ... | @@ -1063,8 +1063,10 @@ solveSimpleWanteds simples |
1063 | 1063 | simples limit (emptyWC { wc_simple = wc })
|
1064 | 1064 | | otherwise
|
1065 | 1065 | = do { -- Solve
|
1066 | - (unif_happened, wc1) <- reportUnifications $
|
|
1066 | + traceUnificationFlag "solveSimpleWanteds1"
|
|
1067 | + ; (unif_happened, wc1) <- reportUnifications $
|
|
1067 | 1068 | solve_simple_wanteds wc
|
1069 | + ; traceUnificationFlag "solveSimpleWanteds2"
|
|
1068 | 1070 | |
1069 | 1071 | -- Run plugins
|
1070 | 1072 | -- NB: runTcPluginsWanted has a fast path for empty wc1,
|
... | ... | @@ -2063,7 +2063,12 @@ unifyTypeAndEmit :: TypeOrKind -> CtOrigin -> TcType -> TcType -> TcM CoercionN |
2063 | 2063 | unifyTypeAndEmit t_or_k orig ty1 ty2
|
2064 | 2064 | = do { ref <- newTcRef emptyBag
|
2065 | 2065 | ; loc <- getCtLocM orig (Just t_or_k)
|
2066 | + ; cur_lvl <- getTcLevel
|
|
2067 | + -- See Note [Unification preconditions], (UNTOUCHABLE) wrinkles
|
|
2068 | + -- Here we don't know about given equalities; so we treat
|
|
2069 | + -- /any/ level outside this one as untouchable. Hence cur_lvl.
|
|
2066 | 2070 | ; let env = UE { u_loc = loc, u_role = Nominal
|
2071 | + , u_given_eq_lvl = cur_lvl
|
|
2067 | 2072 | , u_rewriters = emptyRewriterSet -- ToDo: check this
|
2068 | 2073 | , u_defer = ref, u_unified = Nothing }
|
2069 | 2074 | |
... | ... | @@ -2112,11 +2117,14 @@ A job for the future. |
2112 | 2117 | -}
|
2113 | 2118 | |
2114 | 2119 | data UnifyEnv
|
2115 | - = UE { u_role :: Role
|
|
2116 | - , u_loc :: CtLoc
|
|
2117 | - , u_rewriters :: RewriterSet
|
|
2118 | - |
|
2119 | - -- Deferred constraints
|
|
2120 | + = UE { u_role :: Role
|
|
2121 | + , u_loc :: CtLoc
|
|
2122 | + , u_rewriters :: RewriterSet
|
|
2123 | + , u_given_eq_lvl :: TcLevel -- Just like the inert_given_eq_lvl field
|
|
2124 | + -- of GHC.Tc.Solver.InertSet.InertCans
|
|
2125 | + |
|
2126 | + -- Deferred constraints; ones that could not be
|
|
2127 | + -- solved by "on the fly" unification
|
|
2120 | 2128 | , u_defer :: TcRef (Bag Ct)
|
2121 | 2129 | |
2122 | 2130 | -- Which variables are unified;
|
... | ... | @@ -2483,15 +2491,22 @@ uUnfilledVar2 :: UnifyEnv -- Precondition: u_role==Nominal |
2483 | 2491 | -- definitely not a /filled/ meta-tyvar
|
2484 | 2492 | -> TcTauType -- Type 2, zonked
|
2485 | 2493 | -> TcM CoercionN
|
2486 | -uUnfilledVar2 env@(UE { u_defer = def_eq_ref }) swapped tv1 ty2
|
|
2487 | - = do { cur_lvl <- getTcLevel
|
|
2488 | - -- See Note [Unification preconditions], (UNTOUCHABLE) wrinkles
|
|
2489 | - -- Here we don't know about given equalities; so we treat
|
|
2490 | - -- /any/ level outside this one as untouchable. Hence cur_lvl.
|
|
2491 | - ; if simpleUnifyCheck UC_OnTheFly cur_lvl tv1 ty2 /= SUC_CanUnify
|
|
2492 | - then not_ok_so_defer cur_lvl
|
|
2493 | - else
|
|
2494 | - do { def_eqs <- readTcRef def_eq_ref -- Capture current state of def_eqs
|
|
2494 | +uUnfilledVar2 env@(UE { u_defer = def_eq_ref, u_given_eq_lvl = given_eq_lvl })
|
|
2495 | + swapped tv1 ty2
|
|
2496 | + | simpleUnifyCheck UC_OnTheFly given_eq_lvl tv1 ty2 /= SUC_CanUnify
|
|
2497 | + = -- Simple unification check fails, so defer
|
|
2498 | + do { traceTc "uUnfilledVar2 not ok" $
|
|
2499 | + vcat [ text "tv1:" <+> ppr tv1
|
|
2500 | + , text "ty2:" <+> ppr ty2
|
|
2501 | + , text "simple-unify-chk:" <+> ppr (simpleUnifyCheck UC_OnTheFly given_eq_lvl tv1 ty2)
|
|
2502 | + ]
|
|
2503 | + -- Occurs check or an untouchable: just defer
|
|
2504 | + -- NB: occurs check isn't necessarily fatal:
|
|
2505 | + -- eg tv1 occurred in type family parameter
|
|
2506 | + ; defer }
|
|
2507 | + |
|
2508 | + | otherwise
|
|
2509 | + = do { def_eqs <- readTcRef def_eq_ref -- Capture current state of def_eqs
|
|
2495 | 2510 | |
2496 | 2511 | -- Attempt to unify kinds
|
2497 | 2512 | -- When doing so, be careful to preserve orientation;
|
... | ... | @@ -2524,22 +2539,11 @@ uUnfilledVar2 env@(UE { u_defer = def_eq_ref }) swapped tv1 ty2 |
2524 | 2539 | -- Do this dicarding by simply restoring the previous state
|
2525 | 2540 | -- of def_eqs; a bit imperative/yukky but works fine.
|
2526 | 2541 | ; defer }
|
2527 | - }}
|
|
2542 | + }
|
|
2528 | 2543 | where
|
2529 | 2544 | ty1 = mkTyVarTy tv1
|
2530 | 2545 | defer = unSwap swapped (uType_defer env) ty1 ty2
|
2531 | 2546 | |
2532 | - not_ok_so_defer cur_lvl =
|
|
2533 | - do { traceTc "uUnfilledVar2 not ok" $
|
|
2534 | - vcat [ text "tv1:" <+> ppr tv1
|
|
2535 | - , text "ty2:" <+> ppr ty2
|
|
2536 | - , text "simple-unify-chk:" <+> ppr (simpleUnifyCheck UC_OnTheFly cur_lvl tv1 ty2)
|
|
2537 | - ]
|
|
2538 | - -- Occurs check or an untouchable: just defer
|
|
2539 | - -- NB: occurs check isn't necessarily fatal:
|
|
2540 | - -- eg tv1 occurred in type family parameter
|
|
2541 | - ; defer }
|
|
2542 | - |
|
2543 | 2547 | swapOverTyVars :: Bool -> TcTyVar -> TcTyVar -> Bool
|
2544 | 2548 | swapOverTyVars is_given tv1 tv2
|
2545 | 2549 | -- See Note [Unification variables on the left]
|