Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

3 changed files:

Changes:

  • compiler/GHC/Tc/Solver/Dict.hs
    ... ... @@ -588,22 +588,24 @@ solving fails and we use the superclass of C:
    588 588
     The moving parts are relatively simple:
    
    589 589
     
    
    590 590
     * To attempt to solve the constraint completely, we just recursively
    
    591
    -  call the constraint solver. See the use of `tryTcS` in
    
    591
    +  call the constraint solver. See the use of `tryShortCutTcS` in
    
    592 592
       `tcShortCutSolver`.
    
    593 593
     
    
    594
    -* When this attempted recursive solving, we set a special mode
    
    595
    -  `TcSShortCut`, which signals that we are trying to solve using only
    
    596
    -  top-level instances.  We switch on `TcSShortCut` mode in
    
    597
    -  `tryShortCutSolver`.
    
    594
    +* When this attempted recursive solving, in `tryShortCutTcS`, we
    
    595
    +  - start with an empty inert set: no Givens and no Wanteds
    
    596
    +  - set a special mode  `TcSShortCut`, which signals that we are trying to solve
    
    597
    +    using only top-level instances.
    
    598 598
     
    
    599
    -* When in TcSShortCut mode, we behave specially in a few places:
    
    600
    -  - `tryInertDicts`, where we would otherwise look for a Given to solve our Wanted
    
    601
    -  - `GHC.Tc.Solver.Monad.lookupInertDict` similarly
    
    602
    -  - `noMatchableGivenDicts`, which also consults the Givens
    
    603
    -  - `matchLocalInst`, which would otherwise consult Given quantified constraints
    
    604
    -  - `GHC.Tc.Solver.Instance.Class.matchInstEnv`: when short-cut solving, don't
    
    605
    -    pick overlappable top-level instances
    
    606
    -  - `GHC.Tc.Solver.Solve.runTcPluginsWanted`: don't pass any Givens to the plugin
    
    599
    +* When in TcSShortCut mode, since there are no Givens we can short-circuit;
    
    600
    +  these are all just optimisations:
    
    601
    +      - `tryInertDicts`
    
    602
    +      - `GHC.Tc.Solver.Monad.lookupInertDict`
    
    603
    +      - `noMatchableGivenDicts`
    
    604
    +      - `matchLocalInst`
    
    605
    +      - `GHC.Tc.Solver.Solve.runTcPluginsWanted`
    
    606
    +
    
    607
    +* In `GHC.Tc.Solver.Instance.Class.matchInstEnv`: when short-cut solving,
    
    608
    +  don't pick overlappable top-level instances
    
    607 609
     
    
    608 610
     Some wrinkles:
    
    609 611
     
    
    ... ... @@ -770,14 +772,14 @@ tryInertDicts dict_ct
    770 772
     
    
    771 773
     try_inert_dicts :: TcSMode -> InertCans -> DictCt -> TcS (StopOrContinue ())
    
    772 774
     try_inert_dicts mode inerts dict_w@(DictCt { di_ev = ev_w, di_cls = cls, di_tys = tys })
    
    773
    -  | not (mode == TcSShortCut)   -- Ignore the inerts (esp Givens) in short-cut mode
    
    774
    -                                -- See Note [Shortcut solving]
    
    775
    +  | not (mode == TcSShortCut)   -- Optimisation: ignore the inerts (esp Givens) in
    
    776
    +                                -- short-cut mode. See Note [Shortcut solving]
    
    775 777
       , Just dict_i <- lookupInertDict inerts cls tys
    
    776 778
       , let ev_i  = dictCtEvidence dict_i
    
    777 779
             loc_i = ctEvLoc ev_i
    
    778 780
             loc_w = ctEvLoc ev_w
    
    779 781
       = -- There is a matching dictionary in the inert set
    
    780
    -    do { -- First to try to solve it /completely/ from top level instances
    
    782
    +    do { -- For a Wanted, first to try to solve it /completely/ from top level instances
    
    781 783
              -- See Note [Shortcut solving]
    
    782 784
            ; short_cut_worked <- tryShortCutSolver (isGiven ev_i) dict_w
    
    783 785
     
    
    ... ... @@ -833,11 +835,7 @@ tryShortCutSolver try_short_cut dict_w@(DictCt { di_ev = ev_w })
    833 835
                 , gopt Opt_SolveConstantDicts dflags
    
    834 836
                   -- Enabled by the -fsolve-constant-dicts flag
    
    835 837
     
    
    836
    -            -> tryTcS $  -- tryTcS tries to completely solve some contraints
    
    837
    -               -- Inherit the current solved_dicts, so that one invocation of
    
    838
    -               -- tryShortCutSolver can benefit from the work of earlier invocations
    
    839
    -               -- See wrinkle (SCS3) of Note [Shortcut solving]
    
    840
    -               setTcSMode TcSShortCut $
    
    838
    +            -> tryShortCutTcS $  -- tryTcS tries to completely solve some contraints
    
    841 839
                    do { residual <- solveSimpleWanteds (unitBag (CDictCan dict_w))
    
    842 840
                       ; return (isEmptyBag residual) }
    
    843 841
     
    
    ... ... @@ -977,7 +975,7 @@ matchClassInst dflags mode inerts clas tys loc
    977 975
     noMatchableGivenDicts :: TcSMode -> InertSet -> CtLoc -> Class -> [TcType] -> Bool
    
    978 976
     noMatchableGivenDicts mode inerts@(IS { inert_cans = inert_cans }) loc_w clas tys
    
    979 977
       | TcSShortCut <- mode
    
    980
    -  = True  -- In TcSShortCut mode we behave as if there were no Givens at all
    
    978
    +  = True  -- Optimisation: in TcSShortCut mode there are no Givens
    
    981 979
       | otherwise
    
    982 980
       = not $ anyBag matchable_given $
    
    983 981
         findDictsByClass (inert_dicts inert_cans) clas
    
    ... ... @@ -1153,8 +1151,7 @@ matchLocalInst :: TcPredType -> CtLoc -> TcS ClsInstResult
    1153 1151
     -- Look up the predicate in Given quantified constraints,
    
    1154 1152
     -- which are effectively just local instance declarations.
    
    1155 1153
     matchLocalInst body_pred loc
    
    1156
    -  = do { -- In TcSShortCut mode we do not look at Givens;
    
    1157
    -         -- c.f. tryInertDicts
    
    1154
    +  = do { -- Optimisation: in TcSShortCut mode there are no Givens (c.f. tryInertDicts)
    
    1158 1155
              mode <- getTcSMode
    
    1159 1156
            ; case mode of
    
    1160 1157
                { TcSShortCut -> do { traceTcS "matchLocalInst:TcSShortCut" (ppr body_pred)
    

  • compiler/GHC/Tc/Solver/Monad.hs
    ... ... @@ -19,7 +19,7 @@ module GHC.Tc.Solver.Monad (
    19 19
         runTcS, runTcSEarlyAbort, runTcSWithEvBinds, runTcSInerts,
    
    20 20
         failTcS, warnTcS, addErrTcS, wrapTcS, ctLocWarnTcS,
    
    21 21
         runTcSEqualities,
    
    22
    -    nestTcS, nestImplicTcS, tryTcS,
    
    22
    +    nestTcS, nestImplicTcS, tryShortCutTcS,
    
    23 23
         setEvBindsTcS, setTcLevelTcS,
    
    24 24
         emitFunDepWanteds,
    
    25 25
     
    
    ... ... @@ -1259,20 +1259,31 @@ nestTcS (TcS thing_inside)
    1259 1259
     
    
    1260 1260
            ; return res }
    
    1261 1261
     
    
    1262
    -tryTcS :: TcS Bool -> TcS Bool
    
    1262
    +tryShortCutTcS :: TcS Bool -> TcS Bool
    
    1263 1263
     -- Like nestTcS, but
    
    1264
    ---   (a) be a no-op if the nested computation returns Nothing
    
    1264
    +--   (a) be a no-op if the nested computation returns False
    
    1265 1265
     --   (b) if (but only if) success, propagate nested bindings to the caller
    
    1266 1266
     -- Use only by the short-cut solver;
    
    1267 1267
     --   see Note [Shortcut solving] in GHC.Tc.Solver.Dict
    
    1268
    -tryTcS (TcS thing_inside)
    
    1268
    +tryShortCutTcS (TcS thing_inside)
    
    1269 1269
       = TcS $ \ env@(TcSEnv { tcs_inerts = inerts_var
    
    1270 1270
                             , tcs_ev_binds = old_ev_binds_var }) ->
    
    1271
    -    do { old_inerts       <- TcM.readTcRef inerts_var
    
    1272
    -       ; new_inert_var    <- TcM.newTcRef old_inerts
    
    1271
    +    do { -- Initialise a fresh inert set, with no Givens and no Wanteds
    
    1272
    +         --    (i.e. empty `inert_cans`)
    
    1273
    +         -- But inherit all the InertSet cache fields; in particular
    
    1274
    +         --  * the given_eq_lvl, so we don't accidentally unify a
    
    1275
    +         --    unification variable from outside a GADT match
    
    1276
    +         --  * the `solved_dicts`; see wrinkle (SCS3) of Note [Shortcut solving]
    
    1277
    +         --  * the `famapp_cache`; similarly
    
    1278
    +         old_inerts <- TcM.readTcRef inerts_var
    
    1279
    +       ; let given_eq_lvl = inert_given_eq_lvl (inert_cans old_inerts)
    
    1280
    +             new_inerts   = old_inerts { inert_cans = emptyInertCans given_eq_lvl }
    
    1281
    +       ; new_inert_var <- TcM.newTcRef new_inerts
    
    1282
    +
    
    1273 1283
            ; new_wl_var       <- TcM.newTcRef emptyWorkList
    
    1274 1284
            ; new_ev_binds_var <- TcM.cloneEvBindsVar old_ev_binds_var
    
    1275
    -       ; let nest_env = env { tcs_ev_binds = new_ev_binds_var
    
    1285
    +       ; let nest_env = env { tcs_mode     = TcSShortCut
    
    1286
    +                            , tcs_ev_binds = new_ev_binds_var
    
    1276 1287
                                 , tcs_inerts   = new_inert_var
    
    1277 1288
                                 , tcs_worklist = new_wl_var }
    
    1278 1289
     
    

  • compiler/GHC/Tc/Solver/Solve.hs
    ... ... @@ -1681,8 +1681,9 @@ runTcPluginsWanted wanted
    1681 1681
            ; if null solvers then return (False, wanted) else
    
    1682 1682
     
    
    1683 1683
         do { -- Find the set of Givens to give to the plugin.
    
    1684
    -         -- If TcSMode = TcSShortCut, we are solving with
    
    1685
    -         -- no Givens so don't return any (#26258)!
    
    1684
    +         -- Optimisation: if TcSMode = TcSShortCut, we are solving with
    
    1685
    +         -- no Givens so don't bother to look (#26258 was a bug in an earlier
    
    1686
    +         -- version when we left the Givens in the inert set)
    
    1686 1687
              -- See Note [Shortcut solving] in GHC.Tc.Solver.Dict
    
    1687 1688
              mode <- getTcSMode
    
    1688 1689
            ; given <- case mode of