Simon Peyton Jones pushed to branch wip/T23162-spj at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC/Tc/Solver/Default.hs
    ... ... @@ -395,9 +395,9 @@ tryConstraintDefaulting wc
    395 395
       | isEmptyWC wc
    
    396 396
       = return wc
    
    397 397
       | otherwise
    
    398
    -  = do { (n_unifs, better_wc) <- reportUnifications (go_wc wc)
    
    398
    +  = do { (unif_happened, better_wc) <- reportUnifications (go_wc wc)
    
    399 399
              -- We may have done unifications; so solve again
    
    400
    -       ; solveAgainIf (n_unifs > 0) better_wc }
    
    400
    +       ; solveAgainIf unif_happened better_wc }
    
    401 401
       where
    
    402 402
         go_wc :: WantedConstraints -> TcS WantedConstraints
    
    403 403
         go_wc wc@(WC { wc_simple = simples, wc_impl = implics })
    

  • compiler/GHC/Tc/Solver/FunDeps.hs
    ... ... @@ -397,12 +397,12 @@ doDictFunDepImprovementTop dict_ct@(DictCt { di_ev = ev, di_cls = cls, di_tys =
    397 397
             new_orig  = FunDepOrigin2 dict_pred dict_origin
    
    398 398
                                       inst_pred inst_loc
    
    399 399
     
    
    400
    -
    
    401 400
     solveFunDeps :: TcS Cts -> TcS Bool
    
    402 401
     solveFunDeps generate_eqs
    
    403
    -  = nestFunDepsTcS $
    
    404
    -    do { eqs <- generate_eqs
    
    405
    -       ; solveSimpleWanteds eqs }
    
    402
    +  = do { (unif_happened, _res) <- nestFunDepsTcS $
    
    403
    +                                  do { eqs <- generate_eqs
    
    404
    +                                     ; solveSimpleWanteds eqs }
    
    405
    +       ; return unif_happened }
    
    406 406
     
    
    407 407
     {- Note [No Given/Given fundeps]
    
    408 408
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

  • compiler/GHC/Tc/Solver/Monad.hs
    ... ... @@ -451,9 +451,14 @@ kickOutRewritable ko_spec new_fr
    451 451
                              , text "Residual inerts =" <+> ppr ics' ]) } }
    
    452 452
     
    
    453 453
     kickOutAfterUnification :: [TcTyVar] -> TcS ()
    
    454
    -kickOutAfterUnification tv_list = case nonEmpty tv_list of
    
    455
    -    Nothing -> return ()
    
    456
    -    Just tvs -> do
    
    454
    +kickOutAfterUnification tv_list
    
    455
    +  = case nonEmpty tv_list of
    
    456
    +      Nothing  -> return ()
    
    457
    +      Just tvs -> setUnificationFlagTo min_tv_lvl
    
    458
    +         where
    
    459
    +           min_tv_lvl = foldr1 minTcLevel (NE.map tcTyVarLevel tvs)
    
    460
    +
    
    461
    +{-
    
    457 462
            { let tv_set = mkVarSet tv_list
    
    458 463
     
    
    459 464
            ; n_kicked <- kickOutRewritable (KOAfterUnify tv_set) (Given, NomEq)
    
    ... ... @@ -469,6 +474,7 @@ kickOutAfterUnification tv_list = case nonEmpty tv_list of
    469 474
     
    
    470 475
            ; traceTcS "kickOutAfterUnification" (ppr tvs $$ text "n_kicked =" <+> ppr n_kicked)
    
    471 476
            ; return n_kicked }
    
    477
    +-}
    
    472 478
     
    
    473 479
     kickOutAfterFillingCoercionHole :: CoercionHole -> TcS ()
    
    474 480
     -- See Wrinkle (URW2) in Note [Unify only if the rewriter set is empty]
    
    ... ... @@ -1286,43 +1292,23 @@ tryTcS (TcS thing_inside)
    1286 1292
     
    
    1287 1293
                      ; return True } }
    
    1288 1294
     
    
    1289
    -nestFunDepsTcS :: TcS a -> TcS Bool
    
    1295
    +nestFunDepsTcS :: TcS a -> TcS (Bool, a)
    
    1290 1296
     nestFunDepsTcS (TcS thing_inside)
    
    1291
    -  = TcS $ \ env@(TcSEnv { tcs_inerts = inerts_var
    
    1292
    -                        , tcs_unif_lvl = unif_lvl_var }) ->
    
    1297
    +  = reportUnifications $
    
    1298
    +    TcS $ \ env@(TcSEnv { tcs_inerts = inerts_var }) ->
    
    1299
    +    TcM.pushTcLevelM_  $
    
    1300
    +         -- pushTcLevelTcM: increase the level so that unification variables
    
    1301
    +         -- allocated by the fundep-creation itself don't count as useful unifications
    
    1293 1302
         do { inerts <- TcM.readTcRef inerts_var
    
    1294 1303
            ; new_inert_var    <- TcM.newTcRef inerts
    
    1295 1304
            ; new_wl_var       <- TcM.newTcRef emptyWorkList
    
    1296
    -       ; new_unif_lvl_var <- TcM.newTcRef Nothing
    
    1297 1305
            ; let nest_env = env { tcs_inerts   = new_inert_var
    
    1298
    -                            , tcs_worklist = new_wl_var
    
    1299
    -                            , tcs_unif_lvl = new_unif_lvl_var }
    
    1306
    +                            , tcs_worklist = new_wl_var }
    
    1300 1307
     
    
    1301 1308
            ; TcM.traceTc "nestFunDepsTcS {" empty
    
    1302
    -       ; (inner_lvl, _res) <- TcM.pushTcLevelM $
    
    1303
    -                              thing_inside nest_env
    
    1304
    -           -- Increase the level so that unification variables allocated by
    
    1305
    -           -- the fundep-creation itself don't count as useful unifications
    
    1309
    +       ; res <- thing_inside nest_env
    
    1306 1310
            ; TcM.traceTc "nestFunDepsTcS }" empty
    
    1307
    -
    
    1308
    -       -- Figure out whether the fundeps did any useful unifications,
    
    1309
    -       -- and if so update the tcs_unif_lvl
    
    1310
    -       ; mb_new_lvl <- TcM.readTcRef new_unif_lvl_var
    
    1311
    -       ; case mb_new_lvl of
    
    1312
    -           Just unif_lvl
    
    1313
    -             | inner_lvl `deeperThanOrSame` unif_lvl
    
    1314
    -             -> -- Some useful unifications took place
    
    1315
    -                do { mb_old_lvl <- TcM.readTcRef unif_lvl_var
    
    1316
    -                   ; case mb_old_lvl of
    
    1317
    -                       Just old_lvl | unif_lvl `deeperThanOrSame` old_lvl
    
    1318
    -                                    -> return ()
    
    1319
    -                       _ -> TcM.writeTcRef unif_lvl_var (Just unif_lvl)
    
    1320
    -                   ; return True }
    
    1321
    -
    
    1322
    -           _  -> return False   -- No unifications (except of vars
    
    1323
    -                                -- generated in the fundep stuff itself)
    
    1324
    -       }
    
    1325
    -
    
    1311
    +       ; return res }
    
    1326 1312
     
    
    1327 1313
     updateInertsWith :: InertSet -> InertSet -> InertSet
    
    1328 1314
     -- Update the current inert set with bits from a nested solve,
    
    ... ... @@ -1403,30 +1389,6 @@ setTcEvBindsMap :: EvBindsVar -> EvBindMap -> TcS ()
    1403 1389
     setTcEvBindsMap ev_binds_var binds
    
    1404 1390
       = wrapTcS $ TcM.setTcEvBindsMap ev_binds_var binds
    
    1405 1391
     
    
    1406
    -unifyTyVar :: TcTyVar -> TcType -> TcS ()
    
    1407
    --- Unify a meta-tyvar with a type
    
    1408
    --- We keep track of how many unifications have happened in tcs_unified,
    
    1409
    ---
    
    1410
    --- We should never unify the same variable twice!
    
    1411
    -unifyTyVar tv ty
    
    1412
    -  = assertPpr (isMetaTyVar tv) (ppr tv) $
    
    1413
    -    TcS $ \ env ->
    
    1414
    -    do { TcM.traceTc "unifyTyVar" (ppr tv <+> text ":=" <+> ppr ty)
    
    1415
    -       ; TcM.liftZonkM $ TcM.writeMetaTyVar tv ty
    
    1416
    -       ; TcM.updTcRef (tcs_unified env) (+1) }
    
    1417
    -
    
    1418
    -reportUnifications :: TcS a -> TcS (Int, a)
    
    1419
    --- Record how many unifications are done by thing_inside
    
    1420
    --- We could return a Bool instead of an Int;
    
    1421
    --- all that matters is whether it is no-zero
    
    1422
    -reportUnifications (TcS thing_inside)
    
    1423
    -  = TcS $ \ env ->
    
    1424
    -    do { inner_unified <- TcM.newTcRef 0
    
    1425
    -       ; res <- thing_inside (env { tcs_unified = inner_unified })
    
    1426
    -       ; n_unifs <- TcM.readTcRef inner_unified
    
    1427
    -       ; TcM.updTcRef (tcs_unified env) (+ n_unifs)
    
    1428
    -       ; return (n_unifs, res) }
    
    1429
    -
    
    1430 1392
     getDefaultInfo ::  TcS (DefaultEnv, Bool)
    
    1431 1393
     getDefaultInfo = wrapTcS TcM.tcGetDefaultTys
    
    1432 1394
     
    
    ... ... @@ -1844,6 +1806,43 @@ produced the same Derived constraint.)
    1844 1806
     -}
    
    1845 1807
     
    
    1846 1808
     
    
    1809
    +unifyTyVar :: TcTyVar -> TcType -> TcS ()
    
    1810
    +-- Unify a meta-tyvar with a type
    
    1811
    +-- We keep track of how many unifications have happened in tcs_unified,
    
    1812
    +--
    
    1813
    +-- We should never unify the same variable twice!
    
    1814
    +unifyTyVar tv ty
    
    1815
    +  = assertPpr (isMetaTyVar tv) (ppr tv) $
    
    1816
    +    do { liftZonkTcS (TcM.writeMetaTyVar tv ty)  -- Produces a trace message
    
    1817
    +       ; setUnificationFlagTo (tcTyVarLevel tv) }
    
    1818
    +
    
    1819
    +reportUnifications :: TcS a -> TcS (Bool, a)
    
    1820
    +-- Record whether any unifications are done by thing_inside
    
    1821
    +-- Remember to propagate the information to the enclosing context
    
    1822
    +reportUnifications (TcS thing_inside)
    
    1823
    +  = TcS $ \ env@(TcSEnv { tcs_unif_lvl = outer_ul_var }) ->
    
    1824
    +    do { inner_ul_var <- TcM.newTcRef Nothing
    
    1825
    +
    
    1826
    +       ; res <- thing_inside (env { tcs_unif_lvl = inner_ul_var })
    
    1827
    +
    
    1828
    +       ; ambient_lvl  <- TcM.getTcLevel
    
    1829
    +       ; mb_inner_lvl <- TcM.readTcRef inner_ul_var
    
    1830
    +
    
    1831
    +       ; case mb_inner_lvl of
    
    1832
    +           Just unif_lvl
    
    1833
    +             | ambient_lvl `deeperThanOrSame` unif_lvl
    
    1834
    +             -> -- Some useful unifications took place
    
    1835
    +                do { mb_outer_lvl <- TcM.readTcRef outer_ul_var
    
    1836
    +                   ; case mb_outer_lvl of
    
    1837
    +                       Just outer_unif_lvl | outer_unif_lvl `strictlyDeeperThan` unif_lvl
    
    1838
    +                         -> -- Update, because outer_unif_lv > unif_lvl
    
    1839
    +                            TcM.writeTcRef outer_ul_var (Just unif_lvl)
    
    1840
    +                       _ -> return ()
    
    1841
    +                   ; return (True, res) }
    
    1842
    +
    
    1843
    +           _  -> -- No useful unifications
    
    1844
    +                 return (False, res) }
    
    1845
    +
    
    1847 1846
     getUnificationFlag :: TcS Bool
    
    1848 1847
     -- We are at ambient level i
    
    1849 1848
     -- If the unification flag = Just i, reset it to Nothing and return True
    
    ... ... @@ -2226,7 +2225,7 @@ unifyForAllBody ev role unify_body
    2226 2225
       = do { (res, cts, unified) <- wrapUnifierX ev role unify_body
    
    2227 2226
     
    
    2228 2227
            -- Kick out any inert constraint that we have unified
    
    2229
    -       ; _ <- kickOutAfterUnification unified
    
    2228
    +       ; kickOutAfterUnification unified
    
    2230 2229
     
    
    2231 2230
            ; return (res, cts) }
    
    2232 2231
     
    
    ... ... @@ -2255,7 +2254,7 @@ wrapUnifierTcS ev role do_unifications
    2255 2254
              updWorkListTcS (extendWorkListChildEqs ev cts)
    
    2256 2255
     
    
    2257 2256
            -- And kick out any inert constraint that we have unified
    
    2258
    -       ; _ <- kickOutAfterUnification unified
    
    2257
    +       ; kickOutAfterUnification unified
    
    2259 2258
     
    
    2260 2259
            ; return (res, cts, unified) }
    
    2261 2260
     
    

  • compiler/GHC/Tc/Solver/Solve.hs
    ... ... @@ -120,13 +120,13 @@ simplify_loop n limit definitely_redo_implications
    120 120
                                 , int (lengthBag simples) <+> text "simples to solve" ])
    
    121 121
            ; traceTcS "simplify_loop: wc =" (ppr wc)
    
    122 122
     
    
    123
    -       ; (n_unifs1, simples1) <- reportUnifications $  -- See Note [Superclass iteration]
    
    124
    -                                 solveSimpleWanteds simples
    
    123
    +       ; (unif_happened, simples1) <- reportUnifications $  -- See Note [Superclass iteration]
    
    124
    +                                      solveSimpleWanteds simples
    
    125 125
                     -- Any insoluble constraints are in 'simples' and so get rewritten
    
    126 126
                     -- See Note [Rewrite insolubles] in GHC.Tc.Solver.InertSet
    
    127 127
     
    
    128
    -       ; wc2 <- if not definitely_redo_implications  -- See Note [Superclass iteration]
    
    129
    -                   && n_unifs1 == 0                  -- for this conditional
    
    128
    +       ; wc2 <- if not (definitely_redo_implications  -- See Note [Superclass iteration]
    
    129
    +                        || unif_happened)             -- for this conditional
    
    130 130
                     then return (wc { wc_simple = simples1 })  -- Short cut
    
    131 131
                     else do { implics1 <- solveNestedImplications implics
    
    132 132
                             ; return (wc { wc_simple = simples1
    
    ... ... @@ -1063,15 +1063,16 @@ solveSimpleWanteds simples
    1063 1063
                              simples limit (emptyWC { wc_simple = wc })
    
    1064 1064
           | otherwise
    
    1065 1065
           = do { -- Solve
    
    1066
    -             wc1 <- solve_simple_wanteds wc
    
    1066
    +             (unif_happened, wc1) <- reportUnifications $
    
    1067
    +                                     solve_simple_wanteds wc
    
    1067 1068
     
    
    1068 1069
                  -- Run plugins
    
    1069 1070
                  -- NB: runTcPluginsWanted has a fast path for empty wc1,
    
    1070 1071
                  --     which is the common case
    
    1071 1072
                ; (rerun_plugin, wc2) <- runTcPluginsWanted wc1
    
    1072 1073
     
    
    1073
    -           ; if rerun_plugin
    
    1074
    -             then do { traceTcS "solveSimple going round again:" (ppr rerun_plugin)
    
    1074
    +           ; if unif_happened || rerun_plugin
    
    1075
    +             then do { traceTcS "solveSimple going round again:" empty
    
    1075 1076
                          ; go (n+1) limit wc2 }   -- Loop
    
    1076 1077
                  else return (n, wc2) }           -- Done
    
    1077 1078