Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
6f9d7c71
by Markus Läll at 2026-05-21T15:25:34-04:00
-
50e999ca
by fendor at 2026-05-21T15:26:18-04:00
-
7ecc6184
by sheaf at 2026-05-21T15:27:10-04:00
-
478c6325
by Alan Zimmerman at 2026-05-23T10:17:35+01:00
-
c3dec45b
by Alan Zimmerman at 2026-05-23T11:19:31-04:00
21 changed files:
- + changelog.d/ghc-pkg-faster-closure
- compiler/GHC/CmmToLlvm/Base.hs
- compiler/GHC/Core/Opt/Monad.hs
- compiler/GHC/HsToCore/Foreign/JavaScript.hs
- compiler/GHC/Iface/Binary.hs
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Stg/Pipeline.hs
- compiler/GHC/StgToJS/Ids.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Types/Name/Cache.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Types/Unique/Supply.hs
- + testsuite/tests/ghc-api/T27273.hs
- testsuite/tests/ghc-api/all.T
- testsuite/tests/printer/Makefile
- + testsuite/tests/printer/PprQualifiedStrings.hs
- + testsuite/tests/printer/Test27291.hs
- testsuite/tests/printer/all.T
- utils/check-exact/ExactPrint.hs
- utils/ghc-pkg/Main.hs
Changes:
| 1 | +section: ghc-pkg
|
|
| 2 | +synopsis: Improve performance of `ghc-pkg list` command
|
|
| 3 | +issues: #27275
|
|
| 4 | +mrs: !16062
|
|
| 5 | + |
|
| 6 | +description: {
|
|
| 7 | +`ghc-pkg list` was quadratic in the number of packages due to an inefficient `closure` computation.
|
|
| 8 | +We cache the set of seen packages, allowing us to speed up the `closure` computation, improving run-time
|
|
| 9 | +for the commands `list`, `check`, `distrust`, `expose`, `hide`, `trust` and `unregister`.
|
|
| 10 | +} |
| ... | ... | @@ -318,7 +318,7 @@ instance DSM.MonadGetUnique LlvmM where |
| 318 | 318 | tag <- getEnv envTag
|
| 319 | 319 | liftUDSMT $! do
|
| 320 | 320 | uq <- DSM.getUniqueM
|
| 321 | - return (newTagUniqueGrimly uq tag)
|
|
| 321 | + return (newTagUniqueGrimily uq tag)
|
|
| 322 | 322 | |
| 323 | 323 | -- | Lifting of IO actions. Not exported, as we want to encapsulate IO.
|
| 324 | 324 | liftIO :: IO a -> LlvmM a
|
| ... | ... | @@ -175,11 +175,11 @@ instance MonadPlus CoreM |
| 175 | 175 | instance MonadUnique CoreM where
|
| 176 | 176 | getUniqueSupplyM = do
|
| 177 | 177 | tag <- read cr_uniq_tag
|
| 178 | - liftIO $! mkSplitUniqSupplyGrimly tag
|
|
| 178 | + liftIO $! mkSplitUniqSupplyGrimily tag
|
|
| 179 | 179 | |
| 180 | 180 | getUniqueM = do
|
| 181 | 181 | tag <- read cr_uniq_tag
|
| 182 | - liftIO $! uniqFromTagGrimly tag
|
|
| 182 | + liftIO $! uniqFromTagGrimily tag
|
|
| 183 | 183 | |
| 184 | 184 | runCoreM :: HscEnv
|
| 185 | 185 | -> RuleBase
|
| ... | ... | @@ -144,7 +144,7 @@ mkFExportJSBits platform c_nm maybe_target arg_htys res_hty is_IO_res_ty _cconv |
| 144 | 144 | | otherwise = unpackHObj res_hty
|
| 145 | 145 | |
| 146 | 146 | header_bits = maybe mempty idTag maybe_target
|
| 147 | - idTag i = let (tag, u) = unpkUniqueGrimly (getUnique i)
|
|
| 147 | + idTag i = let (tag, u) = unpkUniqueGrimily (getUnique i)
|
|
| 148 | 148 | in CHeader (char tag <> word64 u)
|
| 149 | 149 | |
| 150 | 150 | normal_args = map (\(nm,_ty,_,_) -> nm) arg_info
|
| ... | ... | @@ -707,7 +707,7 @@ putName BinSymbolTable{ |
| 707 | 707 | bin_symtab_next = symtab_next }
|
| 708 | 708 | bh name
|
| 709 | 709 | | isKnownKeyName name
|
| 710 | - , let (c, u) = unpkUniqueGrimly (nameUnique name) -- INVARIANT: (ord c) fits in 8 bits
|
|
| 710 | + , let (c, u) = unpkUniqueGrimily (nameUnique name) -- INVARIANT: (ord c) fits in 8 bits
|
|
| 711 | 711 | = -- assert (u < 2^(22 :: Int))
|
| 712 | 712 | put_ bh (0x80000000
|
| 713 | 713 | .|. (fromIntegral (ord c) `shiftL` 22)
|
| ... | ... | @@ -2274,8 +2274,9 @@ tok_quoted_label span buf len _buf2 = do |
| 2274 | 2274 | tok_qstrings :: Action -> Action
|
| 2275 | 2275 | tok_qstrings lex_str span0 buf0 len0 endBuf0 = do
|
| 2276 | 2276 | let modName = ModuleName $ lexemeToFastString buf0 modNameLen
|
| 2277 | - (src, meta, s) <- unITstring <$> lex_str strSpan strBuf strLen endBuf0
|
|
| 2278 | - pure $ L span0 $ ITstring src meta{strMetaQualified = Just modName} s
|
|
| 2277 | + (span1, src, meta, s) <- unITstring <$> lex_str strSpan strBuf strLen endBuf0
|
|
| 2278 | + let span2 = mkPsSpan (psSpanStart span0) (psSpanEnd span1)
|
|
| 2279 | + pure $ L span2 $ ITstring src meta{strMetaQualified = Just modName} s
|
|
| 2279 | 2280 | where
|
| 2280 | 2281 | -- The buffer/span starting at the string literal
|
| 2281 | 2282 | (strBuf, strSpanStart) =
|
| ... | ... | @@ -2298,7 +2299,7 @@ tok_qstrings lex_str span0 buf0 len0 endBuf0 = do |
| 2298 | 2299 | strSpan = mkPsSpan strSpanStart (psSpanEnd span0)
|
| 2299 | 2300 | |
| 2300 | 2301 | unITstring = \case
|
| 2301 | - L _ (ITstring src meta s) -> (src, meta, s)
|
|
| 2302 | + L span1 (ITstring src meta s) -> (span1, src, meta, s)
|
|
| 2302 | 2303 | tok -> panic $ "tok_qstrings got unexpected token: " ++ show tok
|
| 2303 | 2304 | |
| 2304 | 2305 | tok_char :: Action
|
| ... | ... | @@ -66,9 +66,9 @@ newtype StgM a = StgM { _unStgM :: ReaderT Char IO a } |
| 66 | 66 | |
| 67 | 67 | instance MonadUnique StgM where
|
| 68 | 68 | getUniqueSupplyM = StgM $ do { tag <- ask
|
| 69 | - ; liftIO $! mkSplitUniqSupplyGrimly tag}
|
|
| 69 | + ; liftIO $! mkSplitUniqSupplyGrimily tag}
|
|
| 70 | 70 | getUniqueM = StgM $ do { tag <- ask
|
| 71 | - ; liftIO $! uniqFromTagGrimly tag}
|
|
| 71 | + ; liftIO $! uniqFromTagGrimily tag}
|
|
| 72 | 72 | |
| 73 | 73 | runStgM :: UniqueTag -> StgM a -> IO a
|
| 74 | 74 | runStgM mask (StgM m) = runReaderT m (uniqueTag mask)
|
| ... | ... | @@ -130,7 +130,7 @@ makeIdentForId i num id_type current_module = name ident |
| 130 | 130 | -- unique suffix for non-exported Ids
|
| 131 | 131 | , if exported
|
| 132 | 132 | then mempty
|
| 133 | - else let (c,u) = unpkUniqueGrimly (getUnique i)
|
|
| 133 | + else let (c,u) = unpkUniqueGrimily (getUnique i)
|
|
| 134 | 134 | in mconcat [BSC.pack ['_',c,'_'], word64BS u]
|
| 135 | 135 | ]
|
| 136 | 136 | |
| ... | ... | @@ -235,4 +235,3 @@ declVarsForId i = case typeSize (idType i) of |
| 235 | 235 | 0 -> return mempty
|
| 236 | 236 | 1 -> decl <$> identForId i
|
| 237 | 237 | s -> mconcat <$> mapM (\n -> decl <$> identForIdN i n) [1..s] |
| 238 | - |
| ... | ... | @@ -1250,14 +1250,17 @@ emptyTcMPluginsShutdown = TcMPluginsShutdown |
| 1250 | 1250 | data TcMPluginsState
|
| 1251 | 1251 | -- | The 'TcM' plugins have not been started.
|
| 1252 | 1252 | = TcMPluginsUninitialised
|
| 1253 | - -- | The 'TcM' plugins have been initialised and not yet stopped.
|
|
| 1253 | + -- | The 'TcM' plugins have been initialised and not yet stopped,
|
|
| 1254 | + -- or there were no 'TcM' plugins to start with.
|
|
| 1254 | 1255 | --
|
| 1255 | 1256 | -- We may be in the middle of typechecker, or have finished typechecking
|
| 1256 | 1257 | -- and be in the middle of desugaring.
|
| 1257 | 1258 | | TcMPluginsRunning !RunningTcMPlugins
|
| 1258 | - -- | The 'TcM' plugins have been stopped.
|
|
| 1259 | + -- | There were 'TcM' plugins that were running, but they have been stopped.
|
|
| 1259 | 1260 | | TcMPluginsStopped
|
| 1260 | 1261 | |
| 1262 | +-- | A (possibly empty) collection of 'TcM' plugin @run@, @post-tc@ and
|
|
| 1263 | +-- @shutdown@ actions.
|
|
| 1261 | 1264 | data RunningTcMPlugins =
|
| 1262 | 1265 | RunningTcMPlugins
|
| 1263 | 1266 | { rtcmp_run :: TcMPluginsRun
|
| ... | ... | @@ -1281,11 +1284,20 @@ tcMPluginsShutdownActions = rtcmp_shutdown |
| 1281 | 1284 | |
| 1282 | 1285 | -- | Retrieve the 'TcM' plugins from a 'TcMPluginsState'.
|
| 1283 | 1286 | --
|
| 1284 | --- Assumes the plugins have been already started and not yet stopped.
|
|
| 1287 | +-- Assumes the plugins (if any) have been already started and not yet stopped.
|
|
| 1285 | 1288 | runningTcMPlugins
|
| 1286 | 1289 | :: HasDebugCallStack
|
| 1287 | 1290 | => TcMPluginsState -> RunningTcMPlugins
|
| 1288 | 1291 | runningTcMPlugins = \case
|
| 1289 | - TcMPluginsUninitialised -> panic "runningTcMPlugins: TcM plugins not started"
|
|
| 1290 | - TcMPluginsStopped -> panic "runningTcMPlugins: TcM plugins already stopped"
|
|
| 1292 | + TcMPluginsUninitialised ->
|
|
| 1293 | + pprPanic "TcM plugins have not been started" $
|
|
| 1294 | + vcat [ text "If you are a GHC API user, make sure to use an appropriate 'TcMPluginHandling'"
|
|
| 1295 | + , text "to ensure that TcM plugins (if any) are initialised before typechecking."
|
|
| 1296 | + ]
|
|
| 1297 | + TcMPluginsStopped ->
|
|
| 1298 | + pprPanic "TcM plugins already stopped" $
|
|
| 1299 | + vcat [ text "If you are a GHC API user and want to proceed to desugaring after typechecking,"
|
|
| 1300 | + , text "make sure you are not using the 'StartAndStopTcMPlugins' 'TcMPluginHandling',"
|
|
| 1301 | + , text "as that stops TcM plugins after typechecking."
|
|
| 1302 | + ]
|
|
| 1291 | 1303 | TcMPluginsRunning plugins -> plugins |
| ... | ... | @@ -790,9 +790,10 @@ withoutTcMPlugins thing_inside = do |
| 790 | 790 | tcg_env <- getGblEnv
|
| 791 | 791 | writeTcRef (tcg_plugins tcg_env) $
|
| 792 | 792 | TcMPluginsRunning emptyRunningTcMPlugins
|
| 793 | - teardown = do
|
|
| 794 | - tcg_env <- getGblEnv
|
|
| 795 | - writeTcRef (tcg_plugins tcg_env) TcMPluginsStopped
|
|
| 793 | + teardown =
|
|
| 794 | + -- Don't set 'tcg_plugins' to 'TcMPluginsStopped', as that should only
|
|
| 795 | + -- be used when there were 'TcM' plugins to start with (#27273).
|
|
| 796 | + return ()
|
|
| 796 | 797 | |
| 797 | 798 | -- | Initialise 'TcM' plugins.
|
| 798 | 799 | initTcMPlugins :: HscEnv -> TcM ()
|
| ... | ... | @@ -946,32 +947,20 @@ shutdownTcMPlugins = \case |
| 946 | 947 | runPluginShutdowns (tcs ++ defs)
|
| 947 | 948 | |
| 948 | 949 | solverTcMPlugins :: HasDebugCallStack => TcMPluginsState -> [TcPluginSolver]
|
| 949 | -solverTcMPlugins = \case
|
|
| 950 | - TcMPluginsUninitialised -> panic "solverTcMPlugins: TcM plugins not started"
|
|
| 951 | - TcMPluginsStopped -> panic "solverTcMPlugins: TcM plugins already stopped"
|
|
| 952 | - TcMPluginsRunning plugins ->
|
|
| 953 | - tcmp_solvers (tcMPluginsRunActions plugins)
|
|
| 950 | +solverTcMPlugins =
|
|
| 951 | + tcmp_solvers . tcMPluginsRunActions . runningTcMPlugins
|
|
| 954 | 952 | |
| 955 | 953 | rewriterTcMPlugins :: HasDebugCallStack => TcMPluginsState -> UniqFM TyCon [TcPluginRewriter]
|
| 956 | -rewriterTcMPlugins = \case
|
|
| 957 | - TcMPluginsUninitialised -> panic "rewriterTcMPlugins: TcM plugins not started"
|
|
| 958 | - TcMPluginsStopped -> panic "rewriterTcMPlugins: TcM plugins already stopped"
|
|
| 959 | - TcMPluginsRunning plugins ->
|
|
| 960 | - tcmp_rewriters (tcMPluginsRunActions plugins)
|
|
| 954 | +rewriterTcMPlugins =
|
|
| 955 | + tcmp_rewriters . tcMPluginsRunActions . runningTcMPlugins
|
|
| 961 | 956 | |
| 962 | 957 | defaultingTcMPlugins :: HasDebugCallStack => TcMPluginsState -> [FillDefaulting]
|
| 963 | -defaultingTcMPlugins = \case
|
|
| 964 | - TcMPluginsUninitialised -> panic "defaultingTcMPlugins: TcM plugins not started"
|
|
| 965 | - TcMPluginsStopped -> panic "defaultingTcMPlugins: TcM plugins already stopped"
|
|
| 966 | - TcMPluginsRunning plugins ->
|
|
| 967 | - tcmp_defaulters (tcMPluginsRunActions plugins)
|
|
| 958 | +defaultingTcMPlugins =
|
|
| 959 | + tcmp_defaulters . tcMPluginsRunActions . runningTcMPlugins
|
|
| 968 | 960 | |
| 969 | 961 | holeFitTcMPlugins :: HasDebugCallStack => TcMPluginsState -> [HoleFitPlugin]
|
| 970 | -holeFitTcMPlugins = \case
|
|
| 971 | - TcMPluginsUninitialised -> panic "holeFitTcMPlugins: TcM plugins not started"
|
|
| 972 | - TcMPluginsStopped -> panic "holeFitTcMPlugins: TcM plugins already stopped"
|
|
| 973 | - TcMPluginsRunning plugins ->
|
|
| 974 | - tcmp_hole_fits (tcMPluginsRunActions plugins)
|
|
| 962 | +holeFitTcMPlugins =
|
|
| 963 | + tcmp_hole_fits . tcMPluginsRunActions . runningTcMPlugins
|
|
| 975 | 964 | |
| 976 | 965 | {-
|
| 977 | 966 | ************************************************************************
|
| ... | ... | @@ -1008,13 +997,13 @@ newUnique :: TcRnIf gbl lcl Unique |
| 1008 | 997 | newUnique
|
| 1009 | 998 | = do { env <- getEnv
|
| 1010 | 999 | ; let tag = env_ut env
|
| 1011 | - ; liftIO $! uniqFromTagGrimly tag }
|
|
| 1000 | + ; liftIO $! uniqFromTagGrimily tag }
|
|
| 1012 | 1001 | |
| 1013 | 1002 | newUniqueSupply :: TcRnIf gbl lcl UniqSupply
|
| 1014 | 1003 | newUniqueSupply
|
| 1015 | 1004 | = do { env <- getEnv
|
| 1016 | 1005 | ; let tag = env_ut env
|
| 1017 | - ; liftIO $! mkSplitUniqSupplyGrimly tag }
|
|
| 1006 | + ; liftIO $! mkSplitUniqSupplyGrimily tag }
|
|
| 1018 | 1007 | |
| 1019 | 1008 | cloneLocalName :: Name -> TcM Name
|
| 1020 | 1009 | -- Make a fresh Internal name with the same OccName and SrcSpan
|
| ... | ... | @@ -122,7 +122,7 @@ data NameCache = NameCache |
| 122 | 122 | type OrigNameCache = ModuleEnv (OccEnv Name)
|
| 123 | 123 | |
| 124 | 124 | takeUniqFromNameCache :: NameCache -> IO Unique
|
| 125 | -takeUniqFromNameCache (NameCache c _) = uniqFromTagGrimly c
|
|
| 125 | +takeUniqFromNameCache (NameCache c _) = uniqFromTagGrimily c
|
|
| 126 | 126 | |
| 127 | 127 | lookupOrigNameCache :: OrigNameCache -> Module -> OccName -> Maybe Name
|
| 128 | 128 | lookupOrigNameCache nc mod occ = lookup_infinite <|> lookup_normal
|
| ... | ... | @@ -38,12 +38,12 @@ module GHC.Types.Unique ( |
| 38 | 38 | mkUniqueIntGrimily,
|
| 39 | 39 | getKey,
|
| 40 | 40 | mkUnique, unpkUnique,
|
| 41 | - unpkUniqueGrimly,
|
|
| 41 | + unpkUniqueGrimily,
|
|
| 42 | 42 | mkUniqueInt,
|
| 43 | 43 | eqUnique, ltUnique,
|
| 44 | 44 | incrUnique, stepUnique,
|
| 45 | 45 | |
| 46 | - newTagUnique, newTagUniqueGrimly,
|
|
| 46 | + newTagUnique, newTagUniqueGrimily,
|
|
| 47 | 47 | nonDetCmpUnique,
|
| 48 | 48 | isValidKnownKeyUnique,
|
| 49 | 49 | |
| ... | ... | @@ -99,7 +99,7 @@ Note [Performance implications of UniqueTag] |
| 99 | 99 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 100 | 100 | The UniqueTag ADT is meant to be ephemeral and eliminated by the simplifier,
|
| 101 | 101 | so for long term storage (i.e. in monadic environments or data structures) we
|
| 102 | -want to store the raw 'Char's. Working with the raw tags is done via the *Grimly
|
|
| 102 | +want to store the raw 'Char's. Working with the raw tags is done via the *Grimily
|
|
| 103 | 103 | class of functions
|
| 104 | 104 | |
| 105 | 105 | For instance, if we are generating a unique for a concrete tag, we should use
|
| ... | ... | @@ -116,7 +116,7 @@ newUnique |
| 116 | 116 | ; liftIO $! uniqFromTag tag }
|
| 117 | 117 | |
| 118 | 118 | Prefer `env_ut :: Char` and
|
| 119 | - ; liftIO $! uniqFromTagGrimly tag }
|
|
| 119 | + ; liftIO $! uniqFromTagGrimily tag }
|
|
| 120 | 120 | |
| 121 | 121 | -}
|
| 122 | 122 | |
| ... | ... | @@ -295,7 +295,7 @@ The stuff about unique *supplies* is handled further down this module. |
| 295 | 295 | -}
|
| 296 | 296 | |
| 297 | 297 | unpkUnique :: Unique -> (UniqueTag, Word64) -- The reverse
|
| 298 | -unpkUniqueGrimly :: Unique -> (Char, Word64) -- The reverse
|
|
| 298 | +unpkUniqueGrimily :: Unique -> (Char, Word64) -- The reverse
|
|
| 299 | 299 | |
| 300 | 300 | mkUniqueGrimily :: Word64 -> Unique -- A trap-door for UniqSupply
|
| 301 | 301 | getKey :: Unique -> Word64 -- for Var
|
| ... | ... | @@ -303,7 +303,7 @@ getKey :: Unique -> Word64 -- for Var |
| 303 | 303 | incrUnique :: Unique -> Unique
|
| 304 | 304 | stepUnique :: Unique -> Word64 -> Unique
|
| 305 | 305 | newTagUnique :: Unique -> UniqueTag -> Unique
|
| 306 | -newTagUniqueGrimly :: Unique -> Char -> Unique
|
|
| 306 | +newTagUniqueGrimily :: Unique -> Char -> Unique
|
|
| 307 | 307 | |
| 308 | 308 | mkUniqueGrimily = MkUnique
|
| 309 | 309 | |
| ... | ... | @@ -323,9 +323,9 @@ maxLocalUnique :: Unique |
| 323 | 323 | maxLocalUnique = mkLocalUnique uniqueMask
|
| 324 | 324 | |
| 325 | 325 | -- newTagUnique changes the "domain" of a unique to a different char
|
| 326 | -newTagUnique u c = newTagUniqueGrimly u (uniqueTag c)
|
|
| 326 | +newTagUnique u c = newTagUniqueGrimily u (uniqueTag c)
|
|
| 327 | 327 | |
| 328 | -newTagUniqueGrimly u c = mkUniqueGrimilyWithTag c i where (_,i) = unpkUniqueGrimly u
|
|
| 328 | +newTagUniqueGrimily u c = mkUniqueGrimilyWithTag c i where (_,i) = unpkUniqueGrimily u
|
|
| 329 | 329 | |
| 330 | 330 | -- | Bitmask that has zeros for the tag bits and ones for the rest.
|
| 331 | 331 | uniqueMask :: Word64
|
| ... | ... | @@ -368,7 +368,7 @@ mkUniqueIntGrimily = MkUnique . intToWord64 |
| 368 | 368 | |
| 369 | 369 | {-# INLINE mkUniqueIntGrimily #-}
|
| 370 | 370 | |
| 371 | -unpkUniqueGrimly (MkUnique u)
|
|
| 371 | +unpkUniqueGrimily (MkUnique u)
|
|
| 372 | 372 | = let
|
| 373 | 373 | -- The potentially truncating use of fromIntegral here is safe
|
| 374 | 374 | -- because the argument is just the tag bits after shifting.
|
| ... | ... | @@ -376,10 +376,10 @@ unpkUniqueGrimly (MkUnique u) |
| 376 | 376 | i = u .&. uniqueMask
|
| 377 | 377 | in
|
| 378 | 378 | (tag, i)
|
| 379 | -{-# INLINE unpkUniqueGrimly #-}
|
|
| 379 | +{-# INLINE unpkUniqueGrimily #-}
|
|
| 380 | 380 | |
| 381 | 381 | |
| 382 | -unpkUnique u = case unpkUniqueGrimly u of
|
|
| 382 | +unpkUnique u = case unpkUniqueGrimily u of
|
|
| 383 | 383 | (c, i) -> ( charToUniqueTag c, i)
|
| 384 | 384 | {-# INLINE unpkUnique #-}
|
| 385 | 385 | |
| ... | ... | @@ -389,7 +389,7 @@ unpkUnique u = case unpkUniqueGrimly u of |
| 389 | 389 | -- See Note [Symbol table representation of names] in "GHC.Iface.Binary" for details.
|
| 390 | 390 | isValidKnownKeyUnique :: Unique -> Bool
|
| 391 | 391 | isValidKnownKeyUnique u =
|
| 392 | - case unpkUniqueGrimly u of
|
|
| 392 | + case unpkUniqueGrimily u of
|
|
| 393 | 393 | (c, x) -> ord c < 0xff && x <= (1 `shiftL` 22)
|
| 394 | 394 | |
| 395 | 395 | {-
|
| ... | ... | @@ -512,7 +512,7 @@ showUnique :: Unique -> String |
| 512 | 512 | showUnique uniq
|
| 513 | 513 | = tagStr ++ w64ToBase62 u
|
| 514 | 514 | where
|
| 515 | - (tag, u) = unpkUniqueGrimly uniq
|
|
| 515 | + (tag, u) = unpkUniqueGrimily uniq
|
|
| 516 | 516 | -- Avoid emitting non-printable characters in pretty uniques.
|
| 517 | 517 | -- See #25989.
|
| 518 | 518 | tagStr
|
| ... | ... | @@ -16,10 +16,10 @@ module GHC.Types.Unique.Supply ( |
| 16 | 16 | -- ** Operations on supplies
|
| 17 | 17 | uniqFromSupply, uniqsFromSupply, -- basic ops
|
| 18 | 18 | takeUniqFromSupply,
|
| 19 | - uniqFromTag, uniqFromTagGrimly,
|
|
| 19 | + uniqFromTag, uniqFromTagGrimily,
|
|
| 20 | 20 | UniqueTag(..),
|
| 21 | 21 | |
| 22 | - mkSplitUniqSupply, mkSplitUniqSupplyGrimly,
|
|
| 22 | + mkSplitUniqSupply, mkSplitUniqSupplyGrimily,
|
|
| 23 | 23 | splitUniqSupply, listSplitUniqSupply,
|
| 24 | 24 | |
| 25 | 25 | -- * Unique supply monad and its abstraction
|
| ... | ... | @@ -203,10 +203,10 @@ data UniqSupply |
| 203 | 203 | -- when split => these two supplies
|
| 204 | 204 | |
| 205 | 205 | mkSplitUniqSupply :: UniqueTag -> IO UniqSupply
|
| 206 | -mkSplitUniqSupply ut = mkSplitUniqSupplyGrimly (uniqueTag ut)
|
|
| 206 | +mkSplitUniqSupply ut = mkSplitUniqSupplyGrimily (uniqueTag ut)
|
|
| 207 | 207 | {-# INLINE mkSplitUniqSupply #-}
|
| 208 | 208 | |
| 209 | -mkSplitUniqSupplyGrimly :: Char -> IO UniqSupply
|
|
| 209 | +mkSplitUniqSupplyGrimily :: Char -> IO UniqSupply
|
|
| 210 | 210 | -- ^ Create a unique supply out of thin air.
|
| 211 | 211 | -- The "tag" (Char) supplied is mostly cosmetic, making it easier
|
| 212 | 212 | -- to figure out where a Unique was born. See Note [Uniques and tags].
|
| ... | ... | @@ -219,7 +219,7 @@ mkSplitUniqSupplyGrimly :: Char -> IO UniqSupply |
| 219 | 219 | |
| 220 | 220 | -- See Note [How the unique supply works]
|
| 221 | 221 | -- See Note [Optimising the unique supply]
|
| 222 | -mkSplitUniqSupplyGrimly ut
|
|
| 222 | +mkSplitUniqSupplyGrimily ut
|
|
| 223 | 223 | = unsafeDupableInterleaveIO (IO mk_supply)
|
| 224 | 224 | |
| 225 | 225 | where
|
| ... | ... | @@ -286,15 +286,15 @@ initUniqSupply counter inc = do |
| 286 | 286 | poke ghc_unique_inc inc
|
| 287 | 287 | |
| 288 | 288 | uniqFromTag :: UniqueTag -> IO Unique
|
| 289 | -uniqFromTag !ut = uniqFromTagGrimly (uniqueTag ut)
|
|
| 289 | +uniqFromTag !ut = uniqFromTagGrimily (uniqueTag ut)
|
|
| 290 | 290 | |
| 291 | 291 | {-# INLINE uniqFromTag #-}
|
| 292 | 292 | |
| 293 | -uniqFromTagGrimly :: Char -> IO Unique
|
|
| 294 | -uniqFromTagGrimly !tag
|
|
| 293 | +uniqFromTagGrimily :: Char -> IO Unique
|
|
| 294 | +uniqFromTagGrimily !tag
|
|
| 295 | 295 | = do { uqNum <- genSym
|
| 296 | 296 | ; return $! mkUniqueGrimilyWithTag tag uqNum }
|
| 297 | -{-# NOINLINE uniqFromTagGrimly #-} -- We'll unbox everything, but we don't want to inline it
|
|
| 297 | +{-# NOINLINE uniqFromTagGrimily #-} -- We'll unbox everything, but we don't want to inline it
|
|
| 298 | 298 | |
| 299 | 299 | splitUniqSupply :: UniqSupply -> (UniqSupply, UniqSupply)
|
| 300 | 300 | -- ^ Build two 'UniqSupply' from a single one, each of which
|
| 1 | +module Main where
|
|
| 2 | + |
|
| 3 | +-- base
|
|
| 4 | +import Control.Monad
|
|
| 5 | +import Control.Monad.IO.Class (liftIO)
|
|
| 6 | +import System.Environment (getArgs)
|
|
| 7 | + |
|
| 8 | +-- time
|
|
| 9 | +import Data.Time (getCurrentTime)
|
|
| 10 | + |
|
| 11 | +-- ghc
|
|
| 12 | +import qualified GHC as GHC
|
|
| 13 | +import qualified GHC.Core as GHC
|
|
| 14 | +import qualified GHC.Data.StringBuffer as GHC
|
|
| 15 | +import qualified GHC.Unit.Module.ModGuts as GHC
|
|
| 16 | +import qualified GHC.Unit.Types as GHC
|
|
| 17 | + |
|
| 18 | +--------------------------------------------------------------------------------
|
|
| 19 | + |
|
| 20 | +main :: IO ()
|
|
| 21 | +main = do
|
|
| 22 | + let inputSource = unlines
|
|
| 23 | + [ "module NumLitDesugaring where"
|
|
| 24 | + , "f :: Num a => a" -- !!! Succeeds if type signature is f :: Int
|
|
| 25 | + , "f = 1"
|
|
| 26 | + ]
|
|
| 27 | + |
|
| 28 | + void $ compileToCore "NumLitDesugaring" inputSource
|
|
| 29 | + |
|
| 30 | +compileToCore :: String -> String -> IO [GHC.CoreBind]
|
|
| 31 | +compileToCore modName inputSource = do
|
|
| 32 | + [libdir] <- getArgs
|
|
| 33 | + GHC.runGhc (Just libdir) $ do
|
|
| 34 | + (_ms, tcMod) <- typecheckSourceCode modName inputSource
|
|
| 35 | + dsMod <- GHC.desugarModule tcMod
|
|
| 36 | + return $ GHC.mg_binds $ GHC.dm_core_module dsMod
|
|
| 37 | + |
|
| 38 | +typecheckSourceCode
|
|
| 39 | + :: GHC.GhcMonad m => String -> String -> m (GHC.ModSummary, GHC.TypecheckedModule)
|
|
| 40 | +typecheckSourceCode modName inputSource = do
|
|
| 41 | + now <- liftIO getCurrentTime
|
|
| 42 | + df1 <- GHC.getSessionDynFlags
|
|
| 43 | + GHC.setSessionDynFlags $ df1 { GHC.backend = GHC.bytecodeBackend }
|
|
| 44 | + let target = GHC.Target
|
|
| 45 | + { GHC.targetId = GHC.TargetFile (modName ++ ".hs") Nothing
|
|
| 46 | + , GHC.targetUnitId = GHC.homeUnitId_ df1
|
|
| 47 | + , GHC.targetAllowObjCode = False
|
|
| 48 | + , GHC.targetContents = Just (GHC.stringToStringBuffer inputSource, now)
|
|
| 49 | + }
|
|
| 50 | + GHC.setTargets [target]
|
|
| 51 | + void $ GHC.depanal [] False
|
|
| 52 | + |
|
| 53 | + ms <- GHC.getModSummary
|
|
| 54 | + (GHC.mkModule GHC.mainUnit (GHC.mkModuleName modName))
|
|
| 55 | + tm <- GHC.parseModule ms >>= GHC.typecheckModule GHC.NoTcMPlugins
|
|
| 56 | + return (ms, tm) |
| ... | ... | @@ -82,3 +82,6 @@ test('TypeMapStringLiteral', normal, compile_and_run, ['-package ghc']) |
| 82 | 82 | |
| 83 | 83 | test('T25121_status', normal, compile_and_run, ['-package ghc'])
|
| 84 | 84 | test('T24386', [extra_run_opts(f'"{config.libdir}"')], compile_and_run, ['-package ghc'])
|
| 85 | +test('T27273', [extra_run_opts(f'"{config.libdir}"')],
|
|
| 86 | + compile_and_run,
|
|
| 87 | + ['-package ghc']) |
| ... | ... | @@ -907,6 +907,11 @@ Test25885: |
| 907 | 907 | $(CHECK_PPR) $(LIBDIR) Test25885.hs
|
| 908 | 908 | $(CHECK_EXACT) $(LIBDIR) Test25885.hs
|
| 909 | 909 | |
| 910 | +.PHONY: Test27291
|
|
| 911 | +Test27291:
|
|
| 912 | + $(CHECK_PPR) $(LIBDIR) Test27291.hs
|
|
| 913 | + $(CHECK_EXACT) $(LIBDIR) Test27291.hs
|
|
| 914 | + |
|
| 910 | 915 | .PHONY: TestLevelImports
|
| 911 | 916 | TestLevelImports:
|
| 912 | 917 | $(CHECK_PPR) $(LIBDIR) TestLevelImports.hs
|
| ... | ... | @@ -922,3 +927,8 @@ TestNamedDefaults: |
| 922 | 927 | PprModifiers:
|
| 923 | 928 | $(CHECK_PPR) $(LIBDIR) PprModifiers.hs
|
| 924 | 929 | $(CHECK_EXACT) $(LIBDIR) PprModifiers.hs
|
| 930 | + |
|
| 931 | +.PHONY: PprQualifiedStrings
|
|
| 932 | +PprQualifiedStrings:
|
|
| 933 | + $(CHECK_PPR) $(LIBDIR) PprQualifiedStrings.hs
|
|
| 934 | + $(CHECK_EXACT) $(LIBDIR) PprQualifiedStrings.hs |
| 1 | +{-# LANGUAGE MultilineStrings #-}
|
|
| 2 | +{-# LANGUAGE QualifiedStrings #-}
|
|
| 3 | +{-# LANGUAGE TemplateHaskell #-}
|
|
| 4 | + |
|
| 5 | +-- These are harvested from ../qualified-strings
|
|
| 6 | + |
|
| 7 | +module PprQualifiedStrings where
|
|
| 8 | + |
|
| 9 | +import Data.Typeable (Typeable, typeOf)
|
|
| 10 | +import qualified Example.ByteStringAscii as Ascii
|
|
| 11 | +import qualified Example.ByteStringUtf8 as Utf8
|
|
| 12 | +import qualified Example.Text as Text
|
|
| 13 | + |
|
| 14 | +exprs :: IO ()
|
|
| 15 | +exprs = do
|
|
| 16 | + inspect "I'm a String" -- would be an ambiguous type error with OverloadedStrings
|
|
| 17 | + inspect Text."I'm a Text"
|
|
| 18 | + inspect Ascii."I'm an ASCII bytestring: 語"
|
|
| 19 | + inspect Utf8."I'm a UTF8 bytestring: 語"
|
|
| 20 | + |
|
| 21 | + inspect """
|
|
| 22 | + I'm a multiline
|
|
| 23 | + String value
|
|
| 24 | + !
|
|
| 25 | + """
|
|
| 26 | + |
|
| 27 | + inspect Text."""
|
|
| 28 | + I'm a multiline
|
|
| 29 | + Text value
|
|
| 30 | + !
|
|
| 31 | + """
|
|
| 32 | + |
|
| 33 | + inspect Text . """
|
|
| 34 | + I'm a multiline
|
|
| 35 | + Text value
|
|
| 36 | + """
|
|
| 37 | + |
|
| 38 | + inspect Text .
|
|
| 39 | + """
|
|
| 40 | + I'm a multiline
|
|
| 41 | + Text value
|
|
| 42 | + """
|
|
| 43 | + |
|
| 44 | +pats :: IO ()
|
|
| 45 | +pats = do
|
|
| 46 | + let text = Text."foo" :: Text
|
|
| 47 | + case text of
|
|
| 48 | + Text."foo" -> putStrLn "Text.\"foo\" matched"
|
|
| 49 | + _ -> putStrLn "Text.\"foo\" did not match"
|
|
| 50 | + |
|
| 51 | + let ascii = Ascii."語" :: ByteString
|
|
| 52 | + case ascii of
|
|
| 53 | + Ascii."語" -> putStrLn "Ascii.\"語\" matched"
|
|
| 54 | + _ -> putStrLn "Ascii.\"語\" did not match"
|
|
| 55 | + |
|
| 56 | + let utf = Utf8."語" :: ByteString
|
|
| 57 | + case utf of
|
|
| 58 | + Utf8."語" -> putStrLn "Utf8.\"語\" matched"
|
|
| 59 | + _ -> putStrLn "Utf8.\"語\" did not match"
|
|
| 60 | + |
|
| 61 | +th :: IO ()
|
|
| 62 | +th =
|
|
| 63 | + $(do
|
|
| 64 | + foldr (\stmt acc -> [| $stmt >> $acc |]) [| pure () |] $
|
|
| 65 | + [ [| inspect Text."I'm a Text" |]
|
|
| 66 | + , [| inspect Ascii."I'm an ASCII bytestring: 語" |]
|
|
| 67 | + , [| inspect Utf8."I'm a Utf8 bytestring: 語" |]
|
|
| 68 | + , [|
|
|
| 69 | + inspect Text."""
|
|
| 70 | + I'm a multiline
|
|
| 71 | + Text string
|
|
| 72 | + """
|
|
| 73 | + |]
|
|
| 74 | + ]
|
|
| 75 | + ) |
| 1 | +{-# LANGUAGE ExplicitNamespaces #-}
|
|
| 2 | + |
|
| 3 | +module Test27291
|
|
| 4 | + ( C(type ..) -- exports class C and data family D
|
|
| 5 | + , C(data ..) -- exports class C and method m
|
|
| 6 | + , D(type ..) -- exports data family D
|
|
| 7 | + , type T (..) -- exports type T and all its data constructors D, D2
|
|
| 8 | + , type T (type ..) -- exports type T
|
|
| 9 | + , type K (type ..) -- exports type K and its constructor K1
|
|
| 10 | + ) where
|
|
| 11 | + |
|
| 12 | +import Control.Applicative qualified as A (type Applicative (data ..))
|
|
| 13 | +import Data.Either qualified as E (type Either (data ..))
|
|
| 14 | + |
|
| 15 | +import Data.Bool (data True (..))
|
|
| 16 | +import Data.Bool (data True( data .. ) )
|
|
| 17 | +import Data.Bool (data True( type ..))
|
|
| 18 | + |
|
| 19 | +import DodgyImports03_helper (C( .. ))
|
|
| 20 | +import DodgyImports03_helper (C (data .. ))
|
|
| 21 | +import DodgyImports03_helper (C( type ..) )
|
|
| 22 | + |
|
| 23 | +import DodgyImports03_helper (T ( .. ) )
|
|
| 24 | +import DodgyImports03_helper (T(data ..))
|
|
| 25 | +import DodgyImports03_helper (T(type ..))
|
|
| 26 | + |
|
| 27 | +import Control.Applicative (type Applicative (type ..)) -- dodgy: no associated types
|
|
| 28 | +import Data.Either (type Either (type ..)) -- dodgy: not a class
|
|
| 29 | + |
|
| 30 | +import Data.Proxy (type Proxy(data ..)) -- ok
|
|
| 31 | +import Data.Proxy (type Proxy(type ..)) -- dodgy: not a class
|
|
| 32 | + |
|
| 33 | +import T25901_sub_g_helper qualified as T1 (T (data ..)) -- T and MkT
|
|
| 34 | +import T25901_sub_g_helper qualified as T2 (T (type ..)) -- T only
|
|
| 35 | +import T25901_sub_g_helper qualified as T3 (type T (..)) -- T and MkT |
| ... | ... | @@ -217,7 +217,9 @@ test('T24237', normal, compile_fail, ['']) |
| 217 | 217 | |
| 218 | 218 | test('Test25454', [ignore_stderr, req_ppr_deps], makefile_test, ['Test25454'])
|
| 219 | 219 | test('Test25885', [ignore_stderr, req_ppr_deps], makefile_test, ['Test25885'])
|
| 220 | +test('Test27291', [ignore_stderr, req_ppr_deps], makefile_test, ['Test27291'])
|
|
| 220 | 221 | |
| 221 | 222 | test('TestLevelImports', [ignore_stderr, req_ppr_deps], makefile_test, ['TestLevelImports'])
|
| 222 | 223 | test('TestNamedDefaults', [ignore_stderr, req_ppr_deps], makefile_test, ['TestNamedDefaults'])
|
| 223 | 224 | test('PprModifiers', [ignore_stderr,req_ppr_deps], makefile_test, ['PprModifiers'])
|
| 225 | +test('PprQualifiedStrings', [ignore_stderr,req_ppr_deps], makefile_test, ['PprQualifiedStrings']) |
| ... | ... | @@ -3145,6 +3145,12 @@ instance ExactPrint (HsExpr GhcPs) where |
| 3145 | 3145 | body' <- markAnnotated body
|
| 3146 | 3146 | return (HsQual noExtField ctxt' body')
|
| 3147 | 3147 | |
| 3148 | + exact (HsQualLit _ (QualLit _ modu (HsQualString src fs))) = do
|
|
| 3149 | + modu' <- markAnnotated modu
|
|
| 3150 | + printStringAdvanceA "."
|
|
| 3151 | + printSourceTextAA src (show (unpackFS fs))
|
|
| 3152 | + return (HsQualLit noExtField (QualLit noExtField modu' (HsQualString src fs)))
|
|
| 3153 | + |
|
| 3148 | 3154 | exact x = error $ "exact HsExpr for:" ++ showAst x
|
| 3149 | 3155 | |
| 3150 | 3156 | -- ---------------------------------------------------------------------
|
| ... | ... | @@ -4581,9 +4587,9 @@ instance ExactPrint (IE GhcPs) where |
| 4581 | 4587 | return (IEThingAbs depr' thing' doc')
|
| 4582 | 4588 | exact (IEThingAll x ns_spec thing doc) = do
|
| 4583 | 4589 | depr' <- markAnnotated (ieta_warning x)
|
| 4584 | - ns_spec' <- markAnnotated ns_spec
|
|
| 4585 | 4590 | thing' <- markAnnotated thing
|
| 4586 | 4591 | op' <- markEpToken (ieta_tok_lpar x)
|
| 4592 | + ns_spec' <- markAnnotated ns_spec
|
|
| 4587 | 4593 | dd' <- markEpToken (ieta_tok_wc x)
|
| 4588 | 4594 | cp' <- markEpToken (ieta_tok_rpar x)
|
| 4589 | 4595 | doc' <- markAnnotated doc
|
| ... | ... | @@ -1826,7 +1826,7 @@ checkConsistency verbosity my_flags = do |
| 1826 | 1826 | all_ps = map mungedId pkgs1
|
| 1827 | 1827 | |
| 1828 | 1828 | let not_broken_pkgs = filterOut broken_pkgs pkgs
|
| 1829 | - (_, trans_broken_pkgs) = closure [] not_broken_pkgs
|
|
| 1829 | + trans_broken_pkgs = brokenPackages not_broken_pkgs
|
|
| 1830 | 1830 | |
| 1831 | 1831 | all_broken_pkgs :: [InstalledPackageInfo]
|
| 1832 | 1832 | all_broken_pkgs = broken_pkgs ++ trans_broken_pkgs
|
| ... | ... | @@ -1845,26 +1845,26 @@ checkConsistency verbosity my_flags = do |
| 1845 | 1845 | when (not (null all_broken_pkgs)) $ exitWith (ExitFailure 1)
|
| 1846 | 1846 | |
| 1847 | 1847 | |
| 1848 | -closure :: [InstalledPackageInfo] -> [InstalledPackageInfo]
|
|
| 1849 | - -> ([InstalledPackageInfo], [InstalledPackageInfo])
|
|
| 1850 | -closure pkgs db_stack = go pkgs db_stack
|
|
| 1851 | - where
|
|
| 1852 | - go avail not_avail =
|
|
| 1853 | - case partition (depsAvailable avail) not_avail of
|
|
| 1854 | - ([], not_avail') -> (avail, not_avail')
|
|
| 1855 | - (new_avail, not_avail') -> go (new_avail ++ avail) not_avail'
|
|
| 1848 | +-- | Compute the set of transitive broken packages.
|
|
| 1849 | +--
|
|
| 1850 | +-- A package is assumed to be broken if any of its dependencies is not
|
|
| 1851 | +-- found in the 'db_stack' after a transitive reduction.
|
|
| 1852 | +brokenPackages :: [InstalledPackageInfo] -> [InstalledPackageInfo]
|
|
| 1853 | +brokenPackages db_stack = go Set.empty db_stack
|
|
| 1854 | + where
|
|
| 1855 | + go avail_ids not_avail =
|
|
| 1856 | + case partition (depsAvailable avail_ids) not_avail of
|
|
| 1857 | + ([], not_avail') -> not_avail'
|
|
| 1858 | + (new_avail, not_avail') -> go (add new_avail avail_ids) not_avail'
|
|
| 1856 | 1859 | |
| 1857 | - depsAvailable :: [InstalledPackageInfo] -> InstalledPackageInfo
|
|
| 1858 | - -> Bool
|
|
| 1859 | - depsAvailable pkgs_ok pkg = null dangling
|
|
| 1860 | - where dangling = filter (`notElem` pids) (depends pkg)
|
|
| 1861 | - pids = map installedUnitId pkgs_ok
|
|
| 1860 | + add new_avail avail_ids =
|
|
| 1861 | + foldl' (flip Set.insert) avail_ids (map installedUnitId new_avail)
|
|
| 1862 | 1862 | |
| 1863 | - -- we want mutually recursive groups of package to show up
|
|
| 1864 | - -- as broken. (#1750)
|
|
| 1863 | + depsAvailable :: Set.Set UnitId -> InstalledPackageInfo -> Bool
|
|
| 1864 | + depsAvailable pids pkg = all (`Set.member` pids) (depends pkg)
|
|
| 1865 | 1865 | |
| 1866 | -brokenPackages :: [InstalledPackageInfo] -> [InstalledPackageInfo]
|
|
| 1867 | -brokenPackages pkgs = snd (closure [] pkgs)
|
|
| 1866 | + -- we want mutually recursive groups of package to show up
|
|
| 1867 | + -- as broken. (#1750)
|
|
| 1868 | 1868 | |
| 1869 | 1869 | -----------------------------------------------------------------------------
|
| 1870 | 1870 | -- Sanity-check a new package config, and automatically build GHCi libs
|