Simon Peyton Jones pushed to branch wip/T26258 at Glasgow Haskell Compiler / GHC
Commits:
-
1f9e4f54
by Stephen Morgan at 2025-08-03T15:14:08+10:00
-
4f6bc9cf
by fendor at 2025-08-04T17:50:06-04:00
-
00ce1eb9
by Simon Peyton Jones at 2025-08-05T10:32:34+01:00
11 changed files:
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- libraries/base/changelog.md
- libraries/base/src/Control/Exception/Backtrace.hs
- libraries/base/src/Data/List/NonEmpty.hs
- libraries/ghc-internal/src/GHC/Internal/Data/OldList.hs
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
Changes:
| ... | ... | @@ -496,11 +496,15 @@ We could use the Eq [a] superclass of the Ord [a], or we could use the top-level |
| 496 | 496 | instance `Eq a => Eq [a]`. But if we did the latter we'd be stuck with an
|
| 497 | 497 | insoluble constraint (Eq a).
|
| 498 | 498 | |
| 499 | -So the ShortCutSolving rule is this:
|
|
| 499 | +-----------------------------------
|
|
| 500 | +So the ShortCutSolving plan is this:
|
|
| 500 | 501 | If we could solve a constraint from a local Given,
|
| 501 | - try first to /completely/ solve the constraint using only top-level instances.
|
|
| 502 | + try first to /completely/ solve the constraint
|
|
| 503 | + using only top-level instances,
|
|
| 504 | + /without/ using any local Givens.
|
|
| 502 | 505 | - If that succeeds, use it
|
| 503 | 506 | - If not, use the local Given
|
| 507 | +-----------------------------------
|
|
| 504 | 508 | |
| 505 | 509 | An example that succeeds:
|
| 506 | 510 | |
| ... | ... | @@ -555,7 +559,7 @@ The moving parts are relatively simple: |
| 555 | 559 | - `matchLocalInst`, which would otherwise consult Given quantified constraints
|
| 556 | 560 | - `GHC.Tc.Solver.Instance.Class.matchInstEnv`: when short-cut solving, don't
|
| 557 | 561 | pick overlappable top-level instances
|
| 558 | - |
|
| 562 | + - `GHC.Tc.Solver.Solve.runTcPluginsWanted`: don't pass any Givens to the plugin
|
|
| 559 | 563 | |
| 560 | 564 | Some wrinkles:
|
| 561 | 565 |
| ... | ... | @@ -897,14 +897,19 @@ for it, so TcS carries a mutable location where the binding can be |
| 897 | 897 | added. This is initialised from the innermost implication constraint.
|
| 898 | 898 | -}
|
| 899 | 899 | |
| 900 | --- | See Note [TcSMode]
|
|
| 901 | -data TcSMode
|
|
| 900 | +data TcSMode -- | See Note [TcSMode], where each constructor is documented
|
|
| 902 | 901 | = TcSVanilla -- ^ Normal constraint solving
|
| 903 | 902 | | TcSPMCheck -- ^ Used when doing patterm match overlap checks
|
| 904 | 903 | | TcSEarlyAbort -- ^ Abort early on insoluble constraints
|
| 905 | 904 | | TcSShortCut -- ^ Fully solve all constraints, without using local Givens
|
| 906 | 905 | deriving (Eq)
|
| 907 | 906 | |
| 907 | +instance Outputable TcSMode where
|
|
| 908 | + ppr TcSVanilla = text "TcSVanilla"
|
|
| 909 | + ppr TcSPMCheck = text "TcSPMCheck"
|
|
| 910 | + ppr TcSEarlyAbort = text "TcSEarlyAbort"
|
|
| 911 | + ppr TcSShortCut = text "TcSShortcut"
|
|
| 912 | + |
|
| 908 | 913 | {- Note [TcSMode]
|
| 909 | 914 | ~~~~~~~~~~~~~~~~~
|
| 910 | 915 | The constraint solver can operate in different modes:
|
| ... | ... | @@ -1011,9 +1011,17 @@ solveSimpleGivens givens |
| 1011 | 1011 | solveSimpleWanteds :: Cts -> TcS Cts
|
| 1012 | 1012 | -- The result is not necessarily zonked
|
| 1013 | 1013 | solveSimpleWanteds simples
|
| 1014 | - = do { traceTcS "solveSimpleWanteds {" (ppr simples)
|
|
| 1014 | + = do { mode <- getTcSMode
|
|
| 1015 | 1015 | ; dflags <- getDynFlags
|
| 1016 | + ; inerts <- getInertSet
|
|
| 1017 | + |
|
| 1018 | + ; traceTcS "solveSimpleWanteds {" $
|
|
| 1019 | + vcat [ text "Mode:" <+> ppr mode
|
|
| 1020 | + , text "Inerts:" <+> ppr inerts
|
|
| 1021 | + , text "Wanteds to solve:" <+> ppr simples ]
|
|
| 1022 | + |
|
| 1016 | 1023 | ; (n,wc) <- go 1 (solverIterations dflags) simples
|
| 1024 | + |
|
| 1017 | 1025 | ; traceTcS "solveSimpleWanteds end }" $
|
| 1018 | 1026 | vcat [ text "iterations =" <+> ppr n
|
| 1019 | 1027 | , text "residual =" <+> ppr wc ]
|
| ... | ... | @@ -1663,17 +1671,26 @@ runTcPluginsGiven |
| 1663 | 1671 | -- 'solveSimpleWanteds' should feed the updated wanteds back into the
|
| 1664 | 1672 | -- main solver.
|
| 1665 | 1673 | runTcPluginsWanted :: Cts -> TcS (Bool, Cts)
|
| 1666 | -runTcPluginsWanted simples1
|
|
| 1667 | - | isEmptyBag simples1
|
|
| 1668 | - = return (False, simples1)
|
|
| 1674 | +runTcPluginsWanted wanted
|
|
| 1675 | + | isEmptyBag wanted
|
|
| 1676 | + = return (False, wanted)
|
|
| 1669 | 1677 | | otherwise
|
| 1670 | 1678 | = do { solvers <- getTcPluginSolvers
|
| 1671 | - ; if null solvers then return (False, simples1) else
|
|
| 1679 | + ; if null solvers then return (False, wanted) else
|
|
| 1672 | 1680 | |
| 1673 | - do { given <- getInertGivens
|
|
| 1674 | - ; wanted <- TcS.zonkSimples simples1 -- Plugin requires zonked inputs
|
|
| 1681 | + do { -- Find the set of Givens to give to the plugin.
|
|
| 1682 | + -- If TcSMode = TcSShortCut, we are solving with
|
|
| 1683 | + -- no Givens so don't return any (#26258)!
|
|
| 1684 | + -- See Note [Shortcut solving] in GHC.Tc.Solver.Dict
|
|
| 1685 | + mode <- getTcSMode
|
|
| 1686 | + ; given <- case mode of
|
|
| 1687 | + TcSShortCut -> return []
|
|
| 1688 | + _ -> getInertGivens
|
|
| 1675 | 1689 | |
| 1676 | - ; traceTcS "Running plugins (" (vcat [ text "Given:" <+> ppr given
|
|
| 1690 | + -- Plugin requires zonked input wanteds
|
|
| 1691 | + ; zonked_wanted <- TcS.zonkSimples wanted
|
|
| 1692 | + |
|
| 1693 | + ; traceTcS "Running plugins {" (vcat [ text "Given:" <+> ppr given
|
|
| 1677 | 1694 | , text "Wanted:" <+> ppr wanted ])
|
| 1678 | 1695 | ; p <- runTcPluginSolvers solvers (given, bagToList wanted)
|
| 1679 | 1696 | ; let (_, solved_wanted) = pluginSolvedCts p
|
| ... | ... | @@ -1684,9 +1701,6 @@ runTcPluginsWanted simples1 |
| 1684 | 1701 | listToBag unsolved_wanted `andCts`
|
| 1685 | 1702 | listToBag insols
|
| 1686 | 1703 | |
| 1687 | --- SLPJ: I'm deeply suspicious of this
|
|
| 1688 | --- ; updInertCans (removeInertCts $ solved_givens)
|
|
| 1689 | - |
|
| 1690 | 1704 | ; mapM_ setEv solved_wanted
|
| 1691 | 1705 | |
| 1692 | 1706 | ; traceTcS "Finished plugins }" (ppr new_wanted)
|
| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | ## 4.23.0.0 *TBA*
|
| 4 | 4 | * Add `Data.List.NonEmpty.mapMaybe`. ([CLC proposal #337](https://github.com/haskell/core-libraries-committee/issues/337))
|
| 5 | 5 | * Fix issues with toRational for types capable to represent infinite and not-a-number values ([CLC proposal #338](https://github.com/haskell/core-libraries-committee/issues/338))
|
| 6 | + * Modify the implementation of `Data.List.sortOn` to use `(>)` instead of `compare`. ([CLC proposal #332](https://github.com/haskell/core-libraries-committee/issues/332))
|
|
| 6 | 7 | |
| 7 | 8 | ## 4.22.0.0 *TBA*
|
| 8 | 9 | * Shipped with GHC 9.14.1
|
| ... | ... | @@ -29,7 +30,6 @@ |
| 29 | 30 | * `GHC.TypeNats.Internal`
|
| 30 | 31 | * `GHC.ExecutionStack.Internal`.
|
| 31 | 32 | * Deprecate `GHC.JS.Prim.Internal.Build`, as per [CLC #329](https://github.com/haskell/core-libraries-committee/issues/329)
|
| 32 | - * Expose constructor and field of `Backtraces` from `Control.Exception.Backtrace`, as per [CLC #199](https://github.com/haskell/core-libraries-committee/issues/199#issuecomment-1954662391)
|
|
| 33 | 33 | |
| 34 | 34 | * Fix incorrect results of `integerPowMod` when the base is 0 and the exponent is negative, and `integerRecipMod` when the modulus is zero ([#26017](https://gitlab.haskell.org/ghc/ghc/-/issues/26017)).
|
| 35 | 35 | * Fix the rewrite rule for `scanl'` not being strict in the first element of the output list ([#26143](https://gitlab.haskell.org/ghc/ghc/-/issues/26143)).
|
| ... | ... | @@ -51,7 +51,7 @@ module Control.Exception.Backtrace |
| 51 | 51 | , getBacktraceMechanismState
|
| 52 | 52 | , setBacktraceMechanismState
|
| 53 | 53 | -- * Collecting backtraces
|
| 54 | - , Backtraces(..)
|
|
| 54 | + , Backtraces
|
|
| 55 | 55 | , displayBacktraces
|
| 56 | 56 | , collectBacktraces
|
| 57 | 57 | ) where
|
| ... | ... | @@ -268,6 +268,9 @@ sort = lift List.sort |
| 268 | 268 | -- >>> (sortBy . comparing) fst $ (3, 1) :| [(2, 2), (1, 3)]
|
| 269 | 269 | -- (1,3) :| [(2,2),(3,1)]
|
| 270 | 270 | --
|
| 271 | +-- However, 'sortOn' may still be faster for instances with a more efficient
|
|
| 272 | +-- implementation of '(>)' than 'compare'.
|
|
| 273 | +--
|
|
| 271 | 274 | -- 'sortWith' is an alias for `sortBy . comparing`.
|
| 272 | 275 | --
|
| 273 | 276 | -- @since 4.20.0.0
|
| ... | ... | @@ -216,7 +216,6 @@ module GHC.Internal.Data.OldList |
| 216 | 216 | import GHC.Internal.Data.Maybe
|
| 217 | 217 | import GHC.Internal.Data.Bits ( (.&.) )
|
| 218 | 218 | import GHC.Internal.Unicode ( isSpace )
|
| 219 | -import GHC.Internal.Data.Ord ( comparing )
|
|
| 220 | 219 | import GHC.Internal.Data.Tuple ( fst, snd )
|
| 221 | 220 | |
| 222 | 221 | import GHC.Internal.Num
|
| ... | ... | @@ -1862,10 +1861,13 @@ rqpart cmp x (y:ys) rle rgt r = |
| 1862 | 1861 | -- >>> (sortBy . comparing) fst [(3, 1), (2, 2), (1, 3)]
|
| 1863 | 1862 | -- [(1,3),(2,2),(3,1)]
|
| 1864 | 1863 | --
|
| 1864 | +-- However, 'sortOn' may still be faster for instances with a more efficient
|
|
| 1865 | +-- implementation of '(>)' than 'compare'.
|
|
| 1866 | +--
|
|
| 1865 | 1867 | -- @since base-4.8.0.0
|
| 1866 | 1868 | sortOn :: Ord b => (a -> b) -> [a] -> [a]
|
| 1867 | 1869 | sortOn f =
|
| 1868 | - map snd . sortBy (comparing fst) . map (\x -> let y = f x in y `seq` (y, x))
|
|
| 1870 | + map snd . actualSort (\x y -> fst x > fst y) . map (\x -> let y = f x in y `seq` (y, x))
|
|
| 1869 | 1871 | |
| 1870 | 1872 | -- | Construct a list from a single element.
|
| 1871 | 1873 | --
|
| ... | ... | @@ -323,7 +323,7 @@ module Control.Exception.Backtrace where |
| 323 | 323 | type BacktraceMechanism :: *
|
| 324 | 324 | data BacktraceMechanism = CostCentreBacktrace | HasCallStackBacktrace | ExecutionBacktrace | IPEBacktrace
|
| 325 | 325 | type Backtraces :: *
|
| 326 | - data Backtraces = Backtraces {btrCostCentre :: GHC.Internal.Maybe.Maybe (GHC.Internal.Ptr.Ptr GHC.Internal.Stack.CCS.CostCentreStack), btrHasCallStack :: GHC.Internal.Maybe.Maybe GHC.Internal.Stack.Types.CallStack, btrExecutionStack :: GHC.Internal.Maybe.Maybe [GHC.Internal.ExecutionStack.Internal.Location], btrIpe :: GHC.Internal.Maybe.Maybe [GHC.Internal.Stack.CloneStack.StackEntry]}
|
|
| 326 | + data Backtraces = ...
|
|
| 327 | 327 | collectBacktraces :: (?callStack::GHC.Internal.Stack.Types.CallStack) => GHC.Internal.Types.IO Backtraces
|
| 328 | 328 | displayBacktraces :: Backtraces -> GHC.Internal.Base.String
|
| 329 | 329 | getBacktraceMechanismState :: BacktraceMechanism -> GHC.Internal.Types.IO GHC.Internal.Types.Bool
|
| ... | ... | @@ -323,7 +323,7 @@ module Control.Exception.Backtrace where |
| 323 | 323 | type BacktraceMechanism :: *
|
| 324 | 324 | data BacktraceMechanism = CostCentreBacktrace | HasCallStackBacktrace | ExecutionBacktrace | IPEBacktrace
|
| 325 | 325 | type Backtraces :: *
|
| 326 | - data Backtraces = Backtraces {btrCostCentre :: GHC.Internal.Maybe.Maybe (GHC.Internal.Ptr.Ptr GHC.Internal.Stack.CCS.CostCentreStack), btrHasCallStack :: GHC.Internal.Maybe.Maybe GHC.Internal.Stack.Types.CallStack, btrExecutionStack :: GHC.Internal.Maybe.Maybe [GHC.Internal.ExecutionStack.Internal.Location], btrIpe :: GHC.Internal.Maybe.Maybe [GHC.Internal.Stack.CloneStack.StackEntry]}
|
|
| 326 | + data Backtraces = ...
|
|
| 327 | 327 | collectBacktraces :: (?callStack::GHC.Internal.Stack.Types.CallStack) => GHC.Internal.Types.IO Backtraces
|
| 328 | 328 | displayBacktraces :: Backtraces -> GHC.Internal.Base.String
|
| 329 | 329 | getBacktraceMechanismState :: BacktraceMechanism -> GHC.Internal.Types.IO GHC.Internal.Types.Bool
|
| ... | ... | @@ -323,7 +323,7 @@ module Control.Exception.Backtrace where |
| 323 | 323 | type BacktraceMechanism :: *
|
| 324 | 324 | data BacktraceMechanism = CostCentreBacktrace | HasCallStackBacktrace | ExecutionBacktrace | IPEBacktrace
|
| 325 | 325 | type Backtraces :: *
|
| 326 | - data Backtraces = Backtraces {btrCostCentre :: GHC.Internal.Maybe.Maybe (GHC.Internal.Ptr.Ptr GHC.Internal.Stack.CCS.CostCentreStack), btrHasCallStack :: GHC.Internal.Maybe.Maybe GHC.Internal.Stack.Types.CallStack, btrExecutionStack :: GHC.Internal.Maybe.Maybe [GHC.Internal.ExecutionStack.Internal.Location], btrIpe :: GHC.Internal.Maybe.Maybe [GHC.Internal.Stack.CloneStack.StackEntry]}
|
|
| 326 | + data Backtraces = ...
|
|
| 327 | 327 | collectBacktraces :: (?callStack::GHC.Internal.Stack.Types.CallStack) => GHC.Internal.Types.IO Backtraces
|
| 328 | 328 | displayBacktraces :: Backtraces -> GHC.Internal.Base.String
|
| 329 | 329 | getBacktraceMechanismState :: BacktraceMechanism -> GHC.Internal.Types.IO GHC.Internal.Types.Bool
|
| ... | ... | @@ -323,7 +323,7 @@ module Control.Exception.Backtrace where |
| 323 | 323 | type BacktraceMechanism :: *
|
| 324 | 324 | data BacktraceMechanism = CostCentreBacktrace | HasCallStackBacktrace | ExecutionBacktrace | IPEBacktrace
|
| 325 | 325 | type Backtraces :: *
|
| 326 | - data Backtraces = Backtraces {btrCostCentre :: GHC.Internal.Maybe.Maybe (GHC.Internal.Ptr.Ptr GHC.Internal.Stack.CCS.CostCentreStack), btrHasCallStack :: GHC.Internal.Maybe.Maybe GHC.Internal.Stack.Types.CallStack, btrExecutionStack :: GHC.Internal.Maybe.Maybe [GHC.Internal.ExecutionStack.Internal.Location], btrIpe :: GHC.Internal.Maybe.Maybe [GHC.Internal.Stack.CloneStack.StackEntry]}
|
|
| 326 | + data Backtraces = ...
|
|
| 327 | 327 | collectBacktraces :: (?callStack::GHC.Internal.Stack.Types.CallStack) => GHC.Internal.Types.IO Backtraces
|
| 328 | 328 | displayBacktraces :: Backtraces -> GHC.Internal.Base.String
|
| 329 | 329 | getBacktraceMechanismState :: BacktraceMechanism -> GHC.Internal.Types.IO GHC.Internal.Types.Bool
|