Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
2860a9a5
by Simon Peyton Jones at 2025-08-07T20:29:18-04:00
-
2a5a3d24
by sterni at 2025-08-08T10:52:08-04:00
-
8a29fee7
by David Feuer at 2025-08-08T10:52:09-04:00
9 changed files:
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- hadrian/src/Settings/Default.hs
- hadrian/src/Settings/Packages.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Quote.hs
- libraries/template-haskell/Language/Haskell/TH/Quote.hs
- libraries/template-haskell/changelog.md
- testsuite/tests/interface-stability/template-haskell-exports.stdout
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,7 +897,9 @@ 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]
|
|
900 | +-- | The mode for the constraint solving monad.
|
|
901 | +--
|
|
902 | +-- See Note [TcSMode], where each constructor is documented
|
|
901 | 903 | data TcSMode
|
902 | 904 | = TcSVanilla -- ^ Normal constraint solving
|
903 | 905 | | TcSPMCheck -- ^ Used when doing patterm match overlap checks
|
... | ... | @@ -905,6 +907,12 @@ data TcSMode |
905 | 907 | | TcSShortCut -- ^ Fully solve all constraints, without using local Givens
|
906 | 908 | deriving (Eq)
|
907 | 909 | |
910 | +instance Outputable TcSMode where
|
|
911 | + ppr TcSVanilla = text "TcSVanilla"
|
|
912 | + ppr TcSPMCheck = text "TcSPMCheck"
|
|
913 | + ppr TcSEarlyAbort = text "TcSEarlyAbort"
|
|
914 | + ppr TcSShortCut = text "TcSShortcut"
|
|
915 | + |
|
908 | 916 | {- Note [TcSMode]
|
909 | 917 | ~~~~~~~~~~~~~~~~~
|
910 | 918 | 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,19 +1671,28 @@ 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
|
|
1672 | - |
|
1673 | - do { given <- getInertGivens
|
|
1674 | - ; wanted <- TcS.zonkSimples simples1 -- Plugin requires zonked inputs
|
|
1675 | - |
|
1676 | - ; traceTcS "Running plugins (" (vcat [ text "Given:" <+> ppr given
|
|
1677 | - , text "Wanted:" <+> ppr wanted ])
|
|
1678 | - ; p <- runTcPluginSolvers solvers (given, bagToList wanted)
|
|
1679 | + ; if null solvers then return (False, wanted) else
|
|
1680 | + |
|
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
|
|
1689 | + |
|
1690 | + -- Plugin requires zonked input wanteds
|
|
1691 | + ; zonked_wanted <- TcS.zonkSimples wanted
|
|
1692 | + |
|
1693 | + ; traceTcS "Running plugins {" (vcat [ text "Given:" <+> ppr given
|
|
1694 | + , text "Wanted:" <+> ppr zonked_wanted ])
|
|
1695 | + ; p <- runTcPluginSolvers solvers (given, bagToList zonked_wanted)
|
|
1679 | 1696 | ; let (_, solved_wanted) = pluginSolvedCts p
|
1680 | 1697 | (_, unsolved_wanted) = pluginInputCts p
|
1681 | 1698 | new_wanted = pluginNewCts 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)
|
... | ... | @@ -80,6 +80,7 @@ stageBootPackages = return |
80 | 80 | stage0Packages :: Action [Package]
|
81 | 81 | stage0Packages = do
|
82 | 82 | cross <- flag CrossCompiling
|
83 | + haveCurses <- any (/= "") <$> traverse setting [ CursesIncludeDir, CursesLibDir ]
|
|
83 | 84 | return $ [ cabalSyntax
|
84 | 85 | , cabal
|
85 | 86 | , compiler
|
... | ... | @@ -116,8 +117,8 @@ stage0Packages = do |
116 | 117 | -- that confused Hadrian, so we must make those a stage0 package as well.
|
117 | 118 | -- Once we drop `Win32`/`unix` it should be possible to drop those too.
|
118 | 119 | ]
|
119 | - ++ [ terminfo | not windowsHost, not cross ]
|
|
120 | - ++ [ timeout | windowsHost ]
|
|
120 | + ++ [ terminfo | not windowsHost, (not cross || haveCurses) ]
|
|
121 | + ++ [ timeout | windowsHost ]
|
|
121 | 122 | |
122 | 123 | -- | Packages built in 'Stage1' by default. You can change this in "UserSettings".
|
123 | 124 | stage1Packages :: Action [Package]
|
... | ... | @@ -24,6 +24,7 @@ packageArgs = do |
24 | 24 | -- immediately and may lead to cyclic dependencies.
|
25 | 25 | -- See: https://gitlab.haskell.org/ghc/ghc/issues/16809.
|
26 | 26 | cross = flag CrossCompiling
|
27 | + haveCurses = any (/= "") <$> traverse setting [ CursesIncludeDir, CursesLibDir ]
|
|
27 | 28 | |
28 | 29 | -- Check if the bootstrap compiler has the same version as the one we
|
29 | 30 | -- are building. This is used to build cross-compilers
|
... | ... | @@ -85,7 +86,7 @@ packageArgs = do |
85 | 86 | -- backends at the moment, so we might as well disable it
|
86 | 87 | -- for cross GHC.
|
87 | 88 | [ andM [expr (ghcWithInterpreter stage), notCross] `cabalFlag` "internal-interpreter"
|
88 | - , notM cross `cabalFlag` "terminfo"
|
|
89 | + , orM [ notM cross, haveCurses ] `cabalFlag` "terminfo"
|
|
89 | 90 | , arg "-build-tool-depends"
|
90 | 91 | , flag UseLibzstd `cabalFlag` "with-libzstd"
|
91 | 92 | -- ROMES: While the boot compiler is not updated wrt -this-unit-id
|
... | ... | @@ -120,7 +121,7 @@ packageArgs = do |
120 | 121 | |
121 | 122 | -------------------------------- ghcPkg --------------------------------
|
122 | 123 | , package ghcPkg ?
|
123 | - builder (Cabal Flags) ? notM cross `cabalFlag` "terminfo"
|
|
124 | + builder (Cabal Flags) ? orM [ notM cross, haveCurses ] `cabalFlag` "terminfo"
|
|
124 | 125 | |
125 | 126 | -------------------------------- ghcBoot ------------------------------
|
126 | 127 | , package ghcBoot ?
|
... | ... | @@ -202,10 +203,10 @@ packageArgs = do |
202 | 203 | , package haskeline ?
|
203 | 204 | builder (Cabal Flags) ? arg "-examples"
|
204 | 205 | -- Don't depend upon terminfo when cross-compiling to avoid unnecessary
|
205 | - -- dependencies.
|
|
206 | - -- TODO: Perhaps the user should rather be responsible for this?
|
|
206 | + -- dependencies unless the user provided ncurses explicitly.
|
|
207 | + -- TODO: Perhaps the user should be able to explicitly enable/disable this.
|
|
207 | 208 | , package haskeline ?
|
208 | - builder (Cabal Flags) ? notM cross `cabalFlag` "terminfo"
|
|
209 | + builder (Cabal Flags) ? orM [ notM cross, haveCurses ] `cabalFlag` "terminfo"
|
|
209 | 210 | |
210 | 211 | -------------------------------- terminfo ------------------------------
|
211 | 212 | , package terminfo ?
|
... | ... | @@ -26,10 +26,10 @@ import GHC.Internal.Base hiding (Type) |
26 | 26 | -- | The 'QuasiQuoter' type, a value @q@ of this type can be used
|
27 | 27 | -- in the syntax @[q| ... string to parse ...|]@. In fact, for
|
28 | 28 | -- convenience, a 'QuasiQuoter' actually defines multiple quasiquoters
|
29 | --- to be used in different splice contexts; if you are only interested
|
|
30 | --- in defining a quasiquoter to be used for expressions, you would
|
|
31 | --- define a 'QuasiQuoter' with only 'quoteExp', and leave the other
|
|
32 | --- fields stubbed out with errors.
|
|
29 | +-- to be used in different splice contexts. In the usual case of a
|
|
30 | +-- @QuasiQuoter@ that is only intended to be used in certain splice
|
|
31 | +-- contexts, the unused fields should just 'fail'. This is most easily
|
|
32 | +-- accomplished using 'namedefaultQuasiQuoter' or 'defaultQuasiQuoter'.
|
|
33 | 33 | data QuasiQuoter = QuasiQuoter {
|
34 | 34 | -- | Quasi-quoter for expressions, invoked by quotes like @lhs = $[q|...]@
|
35 | 35 | quoteExp :: String -> Q Exp,
|
... | ... | @@ -16,6 +16,8 @@ that is up to you. |
16 | 16 | module Language.Haskell.TH.Quote
|
17 | 17 | ( QuasiQuoter(..)
|
18 | 18 | , quoteFile
|
19 | + , namedDefaultQuasiQuoter
|
|
20 | + , defaultQuasiQuoter
|
|
19 | 21 | -- * For backwards compatibility
|
20 | 22 | ,dataToQa, dataToExpQ, dataToPatQ
|
21 | 23 | ) where
|
... | ... | @@ -39,3 +41,54 @@ quoteFile (QuasiQuoter { quoteExp = qe, quotePat = qp, quoteType = qt, quoteDec |
39 | 41 | get old_quoter file_name = do { file_cts <- runIO (readFile file_name)
|
40 | 42 | ; addDependentFile file_name
|
41 | 43 | ; old_quoter file_cts }
|
44 | + |
|
45 | +-- | A 'QuasiQuoter' that fails with a helpful error message in every
|
|
46 | +-- context. It is intended to be modified to create a 'QuasiQuoter' that
|
|
47 | +-- fails in all inappropriate contexts.
|
|
48 | +--
|
|
49 | +-- For example, you could write
|
|
50 | +--
|
|
51 | +-- @
|
|
52 | +-- myPatQQ = (namedDefaultQuasiQuoter "myPatQQ")
|
|
53 | +-- { quotePat = ... }
|
|
54 | +-- @
|
|
55 | +--
|
|
56 | +-- If 'myPatQQ' is used in an expression context, the compiler will report
|
|
57 | +-- that, naming 'myPatQQ'.
|
|
58 | +--
|
|
59 | +-- See also 'defaultQuasiQuoter', which does not name the 'QuasiQuoter' in
|
|
60 | +-- the error message, and might therefore be more appropriate when
|
|
61 | +-- the users of a particular 'QuasiQuoter' tend to define local \"synonyms\"
|
|
62 | +-- for it.
|
|
63 | +namedDefaultQuasiQuoter :: String -> QuasiQuoter
|
|
64 | +namedDefaultQuasiQuoter name = QuasiQuoter
|
|
65 | + { quoteExp = f "use in expression contexts."
|
|
66 | + , quotePat = f "use in pattern contexts."
|
|
67 | + , quoteType = f "use in types."
|
|
68 | + , quoteDec = f "creating declarations."
|
|
69 | + }
|
|
70 | + where
|
|
71 | + f m _ = fail $ "The " ++ name ++ " quasiquoter is not for " ++ m
|
|
72 | + |
|
73 | +-- | A 'QuasiQuoter' that fails with a helpful error message in every
|
|
74 | +-- context. It is intended to be modified to create a 'QuasiQuoter' that
|
|
75 | +-- fails in all inappropriate contexts.
|
|
76 | +--
|
|
77 | +-- For example, you could write
|
|
78 | +--
|
|
79 | +-- @
|
|
80 | +-- myExpressionQQ = defaultQuasiQuoter
|
|
81 | +-- { quoteExp = ... }
|
|
82 | +-- @
|
|
83 | +--
|
|
84 | +-- See also 'namedDefaultQuasiQuoter', which names the 'QuasiQuoter' in the
|
|
85 | +-- error messages.
|
|
86 | +defaultQuasiQuoter :: QuasiQuoter
|
|
87 | +defaultQuasiQuoter = QuasiQuoter
|
|
88 | + { quoteExp = f "use in expression contexts."
|
|
89 | + , quotePat = f "use in pattern contexts."
|
|
90 | + , quoteType = f "use in types."
|
|
91 | + , quoteDec = f "creating declarations."
|
|
92 | + }
|
|
93 | + where
|
|
94 | + f m _ = fail $ "This quasiquoter is not for " ++ m |
1 | 1 | # Changelog for [`template-haskell` package](http://hackage.haskell.org/package/template-haskell)
|
2 | 2 | |
3 | +## 2.25.0.0
|
|
4 | + * Introduce `namedDefaultQuasiQuoter` and `defaultQuasiQuoter`, which fail with a helpful error when used in an inappropriate context.
|
|
5 | + |
|
3 | 6 | ## 2.24.0.0
|
4 | 7 | |
5 | 8 | * Introduce `dataToCodeQ` and `liftDataTyped`, typed variants of `dataToExpQ` and `liftData` respectively.
|
... | ... | @@ -1370,6 +1370,8 @@ module Language.Haskell.TH.Quote where |
1370 | 1370 | dataToExpQ :: forall (m :: * -> *) a. (GHC.Internal.TH.Syntax.Quote m, GHC.Internal.Data.Data.Data a) => (forall b. GHC.Internal.Data.Data.Data b => b -> GHC.Internal.Maybe.Maybe (m GHC.Internal.TH.Syntax.Exp)) -> a -> m GHC.Internal.TH.Syntax.Exp
|
1371 | 1371 | dataToPatQ :: forall (m :: * -> *) a. (GHC.Internal.TH.Syntax.Quote m, GHC.Internal.Data.Data.Data a) => (forall b. GHC.Internal.Data.Data.Data b => b -> GHC.Internal.Maybe.Maybe (m GHC.Internal.TH.Syntax.Pat)) -> a -> m GHC.Internal.TH.Syntax.Pat
|
1372 | 1372 | dataToQa :: forall (m :: * -> *) a k q. (GHC.Internal.TH.Syntax.Quote m, GHC.Internal.Data.Data.Data a) => (GHC.Internal.TH.Syntax.Name -> k) -> (GHC.Internal.TH.Syntax.Lit -> m q) -> (k -> [m q] -> m q) -> (forall b. GHC.Internal.Data.Data.Data b => b -> GHC.Internal.Maybe.Maybe (m q)) -> a -> m q
|
1373 | + defaultQuasiQuoter :: QuasiQuoter
|
|
1374 | + namedDefaultQuasiQuoter :: GHC.Internal.Base.String -> QuasiQuoter
|
|
1373 | 1375 | quoteFile :: QuasiQuoter -> QuasiQuoter
|
1374 | 1376 | |
1375 | 1377 | module Language.Haskell.TH.Syntax where
|
... | ... | @@ -1720,8 +1722,8 @@ module Language.Haskell.TH.Syntax where |
1720 | 1722 | qAddForeignFilePath :: ForeignSrcLang -> GHC.Internal.Base.String -> m ()
|
1721 | 1723 | qAddModFinalizer :: Q () -> m ()
|
1722 | 1724 | qAddCorePlugin :: GHC.Internal.Base.String -> m ()
|
1723 | - qGetQ :: forall a. ghc-internal-9.1300.0:GHC.Internal.Data.Typeable.Internal.Typeable a => m (GHC.Internal.Maybe.Maybe a)
|
|
1724 | - qPutQ :: forall a. ghc-internal-9.1300.0:GHC.Internal.Data.Typeable.Internal.Typeable a => a -> m ()
|
|
1725 | + qGetQ :: forall a. ghc-internal-9.1500.0:GHC.Internal.Data.Typeable.Internal.Typeable a => m (GHC.Internal.Maybe.Maybe a)
|
|
1726 | + qPutQ :: forall a. ghc-internal-9.1500.0:GHC.Internal.Data.Typeable.Internal.Typeable a => a -> m ()
|
|
1725 | 1727 | qIsExtEnabled :: Extension -> m GHC.Internal.Types.Bool
|
1726 | 1728 | qExtsEnabled :: m [Extension]
|
1727 | 1729 | qPutDoc :: DocLoc -> GHC.Internal.Base.String -> m ()
|
... | ... | @@ -1802,7 +1804,7 @@ module Language.Haskell.TH.Syntax where |
1802 | 1804 | falseName :: Name
|
1803 | 1805 | getDoc :: DocLoc -> Q (GHC.Internal.Maybe.Maybe GHC.Internal.Base.String)
|
1804 | 1806 | getPackageRoot :: Q GHC.Internal.IO.FilePath
|
1805 | - getQ :: forall a. ghc-internal-9.1300.0:GHC.Internal.Data.Typeable.Internal.Typeable a => Q (GHC.Internal.Maybe.Maybe a)
|
|
1807 | + getQ :: forall a. ghc-internal-9.1500.0:GHC.Internal.Data.Typeable.Internal.Typeable a => Q (GHC.Internal.Maybe.Maybe a)
|
|
1806 | 1808 | get_cons_names :: Con -> [Name]
|
1807 | 1809 | hoistCode :: forall (m :: * -> *) (n :: * -> *) (r :: GHC.Internal.Types.RuntimeRep) (a :: TYPE r). GHC.Internal.Base.Monad m => (forall x. m x -> n x) -> Code m a -> Code n a
|
1808 | 1810 | isExtEnabled :: Extension -> Q GHC.Internal.Types.Bool
|
... | ... | @@ -1849,7 +1851,7 @@ module Language.Haskell.TH.Syntax where |
1849 | 1851 | oneName :: Name
|
1850 | 1852 | pkgString :: PkgName -> GHC.Internal.Base.String
|
1851 | 1853 | putDoc :: DocLoc -> GHC.Internal.Base.String -> Q ()
|
1852 | - putQ :: forall a. ghc-internal-9.1300.0:GHC.Internal.Data.Typeable.Internal.Typeable a => a -> Q ()
|
|
1854 | + putQ :: forall a. ghc-internal-9.1500.0:GHC.Internal.Data.Typeable.Internal.Typeable a => a -> Q ()
|
|
1853 | 1855 | recover :: forall a. Q a -> Q a -> Q a
|
1854 | 1856 | reify :: Name -> Q Info
|
1855 | 1857 | reifyAnnotations :: forall a. GHC.Internal.Data.Data.Data a => AnnLookup -> Q [a]
|