Cheng Shao pushed to branch wip/ghci-messages-no-string at Glasgow Haskell Compiler / GHC

Commits:

22 changed files:

Changes:

  • compiler/GHC/ByteCode/Breakpoints.hs
    ... ... @@ -37,6 +37,7 @@ import GHC.Prelude
    37 37
     import GHC.Types.SrcLoc
    
    38 38
     import GHC.Types.Name.Occurrence
    
    39 39
     import Control.DeepSeq
    
    40
    +import qualified Data.ByteString.Short as SBS
    
    40 41
     import Data.IntMap.Strict (IntMap)
    
    41 42
     import qualified Data.IntMap.Strict as IM
    
    42 43
     
    
    ... ... @@ -235,8 +236,8 @@ getBreakVars = getBreakXXX modBreaks_vars
    235 236
     getBreakDecls :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO [String]
    
    236 237
     getBreakDecls = getBreakXXX modBreaks_decls
    
    237 238
     
    
    238
    --- | Get the decls for this breakpoint
    
    239
    -getBreakCCS :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO ((String, String))
    
    239
    +-- | Get the cost centre info for this breakpoint
    
    240
    +getBreakCCS :: (Module -> IO ModBreaks) -> InternalBreakpointId -> InternalModBreaks -> IO (SBS.ShortByteString, SBS.ShortByteString)
    
    240 241
     getBreakCCS = getBreakXXX modBreaks_ccs
    
    241 242
     
    
    242 243
     -- | Internal utility to access a ModBreaks field at a particular breakpoint index
    

  • compiler/GHC/Driver/Plugins.hs
    ... ... @@ -405,7 +405,7 @@ loadExternalPlugins ps = do
    405 405
             symbol
    
    406 406
               | null unit = ztmp
    
    407 407
               | otherwise = zEncodeString unit ++ "_" ++ ztmp
    
    408
    -    plugin <- lookupSymbol symbol >>= \case
    
    408
    +    plugin <- lookupSymbol (utf8EncodeShortByteString symbol) >>= \case
    
    409 409
           Nothing -> pprPanic "loadExternalPlugins"
    
    410 410
                       (vcat [ text "Symbol not found"
    
    411 411
                             , text "  Library path: " <> text path
    

  • compiler/GHC/HsToCore/Breakpoints.hs
    ... ... @@ -23,6 +23,7 @@ module GHC.HsToCore.Breakpoints
    23 23
     
    
    24 24
     import GHC.Prelude
    
    25 25
     import Data.Array
    
    26
    +import qualified Data.ByteString.Short as SBS
    
    26 27
     
    
    27 28
     import GHC.HsToCore.Ticks (Tick (..))
    
    28 29
     import GHC.Data.SizedSeq
    
    ... ... @@ -31,6 +32,7 @@ import GHC.Types.Name (OccName)
    31 32
     import GHC.Types.Tickish (BreakTickIndex, BreakpointId(..))
    
    32 33
     import GHC.Unit.Module (Module)
    
    33 34
     import GHC.Utils.Binary
    
    35
    +import GHC.Utils.Encoding (utf8EncodeShortByteString)
    
    34 36
     import GHC.Utils.Outputable
    
    35 37
     import Data.List (intersperse)
    
    36 38
     import Data.Coerce
    
    ... ... @@ -59,7 +61,7 @@ data ModBreaks
    59 61
        , modBreaks_decls  :: !(Array BreakTickIndex [String])
    
    60 62
             -- ^ An array giving the names of the declarations enclosing each breakpoint.
    
    61 63
             -- See Note [Field modBreaks_decls]
    
    62
    -   , modBreaks_ccs    :: !(Array BreakTickIndex (String, String))
    
    64
    +   , modBreaks_ccs    :: !(Array BreakTickIndex (SBS.ShortByteString, SBS.ShortByteString))
    
    63 65
             -- ^ Array pointing to cost centre info for each breakpoint;
    
    64 66
             -- actual 'CostCentre' allocation is done at link-time.
    
    65 67
        , modBreaks_module :: !Module
    
    ... ... @@ -89,8 +91,8 @@ mkModBreaks interpreterProfiled modl extendedMixEntries
    89 91
               | interpreterProfiled =
    
    90 92
                   listArray
    
    91 93
                     (0, count - 1)
    
    92
    -                [ ( concat $ intersperse "." $ tick_path t,
    
    93
    -                    renderWithContext defaultSDocContext $ ppr $ tick_loc t
    
    94
    +                [ ( utf8EncodeShortByteString $ concat $ intersperse "." $ tick_path t,
    
    95
    +                    utf8EncodeShortByteString $ renderWithContext defaultSDocContext $ ppr $ tick_loc t
    
    94 96
                       )
    
    95 97
                     | t <- entries
    
    96 98
                     ]
    

  • compiler/GHC/Linker/Loader.hs
    ... ... @@ -1846,7 +1846,7 @@ allocateCCS interp ce mbss
    1846 1846
                 ccs <- {- one ccs ptr per tick index -}
    
    1847 1847
                   mkCostCentres
    
    1848 1848
                     interp
    
    1849
    -                (moduleNameString $ moduleName modBreaks_module)
    
    1849
    +                (moduleNameFS $ moduleName modBreaks_module)
    
    1850 1850
                     (elems modBreaks_ccs)
    
    1851 1851
                 return $ M.fromList $
    
    1852 1852
                   zipWith (\el ix -> (BreakpointId modBreaks_module ix, el)) ccs [0..]
    

  • compiler/GHC/Runtime/Interpreter.hs
    ... ... @@ -107,6 +107,7 @@ import Control.Monad.IO.Class
    107 107
     import Control.Monad.Catch as MC (mask)
    
    108 108
     import Data.Binary
    
    109 109
     import Data.ByteString (ByteString)
    
    110
    +import qualified Data.ByteString.Short as SBS
    
    110 111
     import Foreign hiding (void)
    
    111 112
     import qualified GHC.Exts.Heap as Heap
    
    112 113
     import GHC.Stack.CCS (CostCentre,CostCentreStack)
    
    ... ... @@ -352,9 +353,15 @@ evalStringToIOString interp fhv str =
    352 353
     mallocData :: Interp -> ByteString -> IO (RemotePtr ())
    
    353 354
     mallocData interp bs = interpCmd interp (MallocData bs)
    
    354 355
     
    
    355
    -mkCostCentres :: Interp -> String -> [(String,String)] -> IO [RemotePtr CostCentre]
    
    356
    -mkCostCentres interp mod ccs =
    
    357
    -  interpCmd interp (MkCostCentres mod ccs)
    
    356
    +mkCostCentres :: Interp -> FastString -> [(SBS.ShortByteString, SBS.ShortByteString)] -> IO [RemotePtr CostCentre]
    
    357
    +mkCostCentres interp mod ccs = do
    
    358
    +  rp <- modifyMVar (interpStringCache interp) $ \fs_env ->
    
    359
    +    case lookupFsEnv fs_env mod of
    
    360
    +      Just rp -> pure (fs_env, rp)
    
    361
    +      Nothing -> do
    
    362
    +        rp <- fmap head $ interpCmd interp $ MallocStrings [bytesFS mod]
    
    363
    +        pure (extendFsEnv fs_env mod rp, rp)
    
    364
    +  interpCmd interp $ MkCostCentres rp ccs
    
    358 365
     
    
    359 366
     -- | Create a set of BCOs that may be mutually recursive.
    
    360 367
     createBCOs :: Interp -> [ResolvedBCO] -> IO [HValueRef]
    
    ... ... @@ -413,7 +420,7 @@ evalBreakpointToId :: EvalBreakpoint -> InternalBreakpointId
    413 420
     evalBreakpointToId eval_break =
    
    414 421
       let
    
    415 422
         mkUnitId u = fsToUnit $ mkFastStringShortByteString u
    
    416
    -    toModule u n = mkModule (mkUnitId u) (mkModuleName n)
    
    423
    +    toModule u n = mkModule (mkUnitId u) (mkModuleNameFS (mkFastStringShortByteString n))
    
    417 424
       in
    
    418 425
         InternalBreakpointId
    
    419 426
           { ibi_info_mod   = toModule (eb_info_mod_unit eval_break) (eb_info_mod eval_break)
    
    ... ... @@ -465,27 +472,27 @@ lookupSymbol :: Interp -> InterpSymbol s -> IO (Maybe (Ptr ()))
    465 472
     lookupSymbol interp str = withSymbolCache interp str $
    
    466 473
       case interpInstance interp of
    
    467 474
     #if defined(HAVE_INTERNAL_INTERPRETER)
    
    468
    -    InternalInterp -> fmap fromRemotePtr <$> run (LookupSymbol (unpackFS (interpSymbolToCLabel str)))
    
    475
    +    InternalInterp -> fmap fromRemotePtr <$> run (LookupSymbol (fastStringToShortByteString (interpSymbolToCLabel str)))
    
    469 476
     #endif
    
    470 477
         ExternalInterp ext -> case ext of
    
    471 478
           ExtIServ i -> withIServ i $ \inst -> fmap fromRemotePtr <$> do
    
    472 479
             uninterruptibleMask_ $
    
    473
    -          sendMessage inst (LookupSymbol (unpackFS (interpSymbolToCLabel str)))
    
    480
    +          sendMessage inst (LookupSymbol (fastStringToShortByteString (interpSymbolToCLabel str)))
    
    474 481
           ExtJS {} -> pprPanic "lookupSymbol not supported by the JS interpreter" (ppr str)
    
    475 482
           ExtWasm i -> withWasmInterp i $ \inst -> fmap fromRemotePtr <$> do
    
    476 483
             uninterruptibleMask_ $
    
    477
    -          sendMessage inst (LookupSymbol (unpackFS (interpSymbolToCLabel str)))
    
    484
    +          sendMessage inst (LookupSymbol (fastStringToShortByteString (interpSymbolToCLabel str)))
    
    478 485
     
    
    479 486
     lookupSymbolInDLL :: Interp -> RemotePtr LoadedDLL -> InterpSymbol s -> IO (Maybe (Ptr ()))
    
    480 487
     lookupSymbolInDLL interp dll str = withSymbolCache interp str $
    
    481 488
       case interpInstance interp of
    
    482 489
     #if defined(HAVE_INTERNAL_INTERPRETER)
    
    483
    -    InternalInterp -> fmap fromRemotePtr <$> run (LookupSymbolInDLL dll (unpackFS (interpSymbolToCLabel str)))
    
    490
    +    InternalInterp -> fmap fromRemotePtr <$> run (LookupSymbolInDLL dll (fastStringToShortByteString (interpSymbolToCLabel str)))
    
    484 491
     #endif
    
    485 492
         ExternalInterp ext -> case ext of
    
    486 493
           ExtIServ i -> withIServ i $ \inst -> fmap fromRemotePtr <$> do
    
    487 494
             uninterruptibleMask_ $
    
    488
    -          sendMessage inst (LookupSymbolInDLL dll (unpackFS (interpSymbolToCLabel str)))
    
    495
    +          sendMessage inst (LookupSymbolInDLL dll (fastStringToShortByteString (interpSymbolToCLabel str)))
    
    489 496
           ExtJS {} -> pprPanic "lookupSymbol not supported by the JS interpreter" (ppr str)
    
    490 497
           -- wasm dyld doesn't track which symbol comes from which .so
    
    491 498
           ExtWasm {} -> lookupSymbol interp str
    
    ... ... @@ -519,7 +526,7 @@ interpSymbolToCLabel s = eliminateInterpSymbol s interpretedInterpSymbol $ \is -
    519 526
     
    
    520 527
     lookupClosure :: Interp -> InterpSymbol s -> IO (Maybe HValueRef)
    
    521 528
     lookupClosure interp str =
    
    522
    -  interpCmd interp (LookupClosure (unpackFS (interpSymbolToCLabel str)))
    
    529
    +  interpCmd interp (LookupClosure (fastStringToShortByteString (interpSymbolToCLabel str)))
    
    523 530
     
    
    524 531
     -- | 'withSymbolCache' tries to find a symbol in the 'interpLookupSymbolCache'
    
    525 532
     -- which maps symbols to the address where they are loaded.
    

  • compiler/GHC/Tc/Errors/Ppr.hs
    ... ... @@ -7710,12 +7710,8 @@ pprHsCtxt = \case
    7710 7710
       PatSigErrCtxt sig_ty res_ty ->
    
    7711 7711
         vcat [ hang (text "When checking that the pattern signature:")
    
    7712 7712
                   4 (ppr sig_ty)
    
    7713
    -         , nest 2 (hang (text "fits the type of its context:") 2 pp_res_ty) ]
    
    7714
    -    where
    
    7715
    -      -- Zonking will have turned Infer into Check
    
    7716
    -      pp_res_ty = case res_ty of
    
    7717
    -                    Check ty -> ppr ty
    
    7718
    -                    Infer ir -> text "OOPS" <+> ppr ir
    
    7713
    +         , nest 2 (hang (text "fits the type of its context:")
    
    7714
    +                      2 (ppr (getCheckExpType res_ty))) ]
    
    7719 7715
     
    
    7720 7716
       PatCtxt pat ->
    
    7721 7717
         hang (text "In the pattern:") 2 (ppr pat)
    
    ... ... @@ -7777,7 +7773,7 @@ pprHsCtxt = \case
    7777 7773
           full_herald = pprExpectedFunTyHerald herald
    
    7778 7774
                     <+> speakNOf n_vis_args_in_call (text "visible argument")
    
    7779 7775
                      -- What are "visible" arguments? See Note [Visibility and arity] in GHC.Types.Basic
    
    7780
    -  FunResCtxt fun n_val_args res_fun res_env n_fun n_env
    
    7776
    +  FunResCtxt fun n_val_args fun_res_ty env_ty
    
    7781 7777
         | -- Check for too few args
    
    7782 7778
           --  fun_tau = a -> b, res_tau = Int
    
    7783 7779
           n_fun > n_env
    
    ... ... @@ -7801,6 +7797,18 @@ pprHsCtxt = \case
    7801 7797
         -> empty
    
    7802 7798
           -- text "Debug" <+> vcat [ppr fun, ppr n_val_args, ppr res_fun, ppr res_env, ppr n_fun, ppr n_env]
    
    7803 7799
         where
    
    7800
    +      -- See Note [Splitting nested sigma types in mismatched
    
    7801
    +      --           function types]
    
    7802
    +      -- env_ty is an ExpRhoTy, but with simple subsumption it
    
    7803
    +      -- is not /deeply/ skolemised, so still use tcSplitNestedSigmaTys
    
    7804
    +
    
    7805
    +      (_,_,fun_tau)   = tcSplitNestedSigmaTys fun_res_ty
    
    7806
    +      (_, _, env_tau) = tcSplitNestedSigmaTys (getCheckExpType env_ty)
    
    7807
    +      (args_fun, res_fun) = tcSplitFunTys fun_tau
    
    7808
    +      (args_env, res_env) = tcSplitFunTys env_tau
    
    7809
    +      n_fun = length args_fun
    
    7810
    +      n_env = length args_env
    
    7811
    +
    
    7804 7812
           not_fun ty   -- ty is definitely not an arrow type,
    
    7805 7813
                        -- and cannot conceivably become one
    
    7806 7814
             = case tcSplitTyConApp_maybe ty of
    

  • compiler/GHC/Tc/Gen/Head.hs
    ... ... @@ -68,7 +68,6 @@ import GHC.Builtin.Names
    68 68
     import GHC.Driver.DynFlags
    
    69 69
     import GHC.Utils.Misc
    
    70 70
     import GHC.Utils.Outputable as Outputable
    
    71
    -import GHC.Utils.Panic
    
    72 71
     
    
    73 72
     import GHC.Data.Maybe
    
    74 73
     
    
    ... ... @@ -961,7 +960,8 @@ See Note [-fno-code mode].
    961 960
     *                                                                      *
    
    962 961
     ********************************************************************* -}
    
    963 962
     
    
    964
    -addFunResCtxt :: HsExpr GhcTc -> [HsExprArg p]
    
    963
    +addFunResCtxt :: HasDebugCallStack
    
    964
    +              => HsExpr GhcTc -> [HsExprArg p]
    
    965 965
                   -> TcType -> ExpRhoType
    
    966 966
                   -> TcM a -> TcM a
    
    967 967
     -- When we have a mis-match in the return type of a function
    
    ... ... @@ -969,33 +969,10 @@ addFunResCtxt :: HsExpr GhcTc -> [HsExprArg p]
    969 969
     -- But not in generated code, where we don't want
    
    970 970
     -- to mention internal (rebindable syntax) function names
    
    971 971
     addFunResCtxt fun args fun_res_ty env_ty thing_inside
    
    972
    -  = do { env_tv  <- newFlexiTyVarTy liftedTypeKind
    
    973
    -       ; dumping <- doptM Opt_D_dump_tc_trace
    
    974
    -       ; msg <- mk_msg dumping env_tv
    
    975
    -       ; addErrCtxt msg thing_inside }
    
    972
    +  = addErrCtxt (FunResCtxt fun (count isValArg args) fun_res_ty env_ty) $
    
    973
    +    thing_inside
    
    976 974
           -- NB: use a landmark error context, so that an empty context
    
    977 975
           -- doesn't suppress some more useful context
    
    978
    -  where
    
    979
    -    mk_msg dumping env_tv
    
    980
    -      = do { mb_env_ty <- readExpType_maybe env_ty
    
    981
    -                     -- by the time the message is rendered, the ExpType
    
    982
    -                     -- will be filled in (except if we're debugging)
    
    983
    -           ; env'     <- case mb_env_ty of
    
    984
    -                           Just env_ty -> return env_ty
    
    985
    -                           Nothing     -> do { massert dumping; return env_tv }
    
    986
    -           ; let -- See Note [Splitting nested sigma types in mismatched
    
    987
    -                 --           function types]
    
    988
    -                 (_, _, fun_tau) = tcSplitNestedSigmaTys fun_res_ty
    
    989
    -                 (_, _, env_tau) = tcSplitNestedSigmaTys env'
    
    990
    -                     -- env_ty is an ExpRhoTy, but with simple subsumption it
    
    991
    -                     -- is not deeply skolemised, so still use tcSplitNestedSigmaTys
    
    992
    -                 (args_fun, res_fun) = tcSplitFunTys fun_tau
    
    993
    -                 (args_env, res_env) = tcSplitFunTys env_tau
    
    994
    -                 info =
    
    995
    -                  FunResCtxt fun (count isValArg args) res_fun res_env
    
    996
    -                    (length args_fun) (length args_env)
    
    997
    -           ; return info }
    
    998
    -
    
    999 976
     
    
    1000 977
     {-
    
    1001 978
     Note [Splitting nested sigma types in mismatched function types]
    

  • compiler/GHC/Tc/Types/ErrCtxt.hs
    ... ... @@ -251,7 +251,10 @@ data HsCtxt
    251 251
       -- | In the instance type signature of a class method.
    
    252 252
       | MethSigCtxt !Name !TcType !TcType
    
    253 253
       -- | In a pattern type signature.
    
    254
    +
    
    254 255
       | PatSigErrCtxt !TcType !ExpType
    
    256
    +     -- ExpType: see Note [ExpType in HsCtxt]
    
    257
    +
    
    255 258
       -- | In a pattern.
    
    256 259
       | PatCtxt !(Pat GhcRn)
    
    257 260
       -- | In a pattern synonym declaration.
    
    ... ... @@ -268,7 +271,10 @@ data HsCtxt
    268 271
       -- | In a function call.
    
    269 272
       | FunTysCtxt !ExpectedFunTyCtxt !Type !Int !Int
    
    270 273
       -- | In the result of a function call.
    
    271
    -  | FunResCtxt !(HsExpr GhcTc) !Int !Type !Type !Int !Int
    
    274
    +
    
    275
    +  | FunResCtxt !(HsExpr GhcTc) !Int !TcType !ExpType
    
    276
    +     -- ExpType: see Note [ExpType in HsCtxt]
    
    277
    +
    
    272 278
       -- | In the declaration of a type constructor.
    
    273 279
       | TyConDeclCtxt !Name !(TyConFlavour TyCon)
    
    274 280
       -- | In a type or data family instance (or default instance).
    
    ... ... @@ -377,3 +383,14 @@ isHsCtxtLandmark (DerivBindCtxt{}) = True
    377 383
     isHsCtxtLandmark (FunResCtxt{}) = True
    
    378 384
     isHsCtxtLandmark (VDQWarningCtxt{}) = True
    
    379 385
     isHsCtxtLandmark _ = False
    
    386
    +
    
    387
    +{- Note [ExpType in HsCtxt]
    
    388
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    389
    +A couple of HsCtxt constructors have ExpTypes in them.  When zonking the
    
    390
    +Infer{} case we read the hole, which should be filled in by now, and zonk
    
    391
    +that type.  Now we want to put it back: we use (Check ty') for this, so that
    
    392
    +clients of a zonked HsCtxt don't need to be monadic.
    
    393
    +
    
    394
    +Result: after zonking, these ExpTypes are always (Check ty).  It woudl be nice
    
    395
    +to guarantee this statically, but it's hard to do so.
    
    396
    +-}

  • compiler/GHC/Tc/Utils/TcType.hs
    ... ... @@ -28,7 +28,7 @@ module GHC.Tc.Utils.TcType (
    28 28
       ExpType(..), ExpKind, InferResult(..), InferInstFlag(..), InferFRRFlag(..),
    
    29 29
       ExpTypeFRR, ExpSigmaType, ExpSigmaTypeFRR,
    
    30 30
       ExpRhoType, ExpRhoTypeFRR,
    
    31
    -  mkCheckExpType,
    
    31
    +  mkCheckExpType, getCheckExpType,
    
    32 32
       checkingExpType_maybe, checkingExpType,
    
    33 33
     
    
    34 34
       ExpPatType(..), mkCheckExpFunPatTy, mkInvisExpPatType,
    
    ... ... @@ -440,11 +440,12 @@ data InferInstFlag -- Specifies whether the inference should return an uninstan
    440 440
     
    
    441 441
       | IIF_ShallowRho  -- Trying to infer a shallow RhoType (no foralls or => at the top)
    
    442 442
                         -- Top-instantiate (only, regardless of DeepSubsumption) before filling the hole
    
    443
    -                    -- Typically used when inferring the type of an expression
    
    443
    +                    -- Used only for view patterns; see Note [View patterns and polymorphism]
    
    444 444
     
    
    445 445
       | IIF_DeepRho     -- Trying to infer a possibly-deep RhoType (depending on DeepSubsumption)
    
    446 446
                         -- If DeepSubsumption is off, same as IIF_ShallowRho
    
    447 447
                         -- If DeepSubsumption is on, instantiate deeply before filling the hole
    
    448
    +                    -- Typically used when inferring the type of an expression
    
    448 449
     
    
    449 450
     type ExpSigmaType = ExpType
    
    450 451
     type ExpRhoType   = ExpType
    
    ... ... @@ -490,6 +491,12 @@ instance Outputable InferResult where
    490 491
     mkCheckExpType :: TcType -> ExpType
    
    491 492
     mkCheckExpType = Check
    
    492 493
     
    
    494
    +getCheckExpType :: HasDebugCallStack => ExpType -> TcType
    
    495
    +-- Expect a (Check ty).
    
    496
    +-- See Note [ExpType in HsCtxt] in GHC.Tc.Types.ErrCtxt
    
    497
    +getCheckExpType (Check ty) = ty
    
    498
    +getCheckExpType (Infer ir) = pprPanic "getCheckExpType" (ppr ir)
    
    499
    +
    
    493 500
     -- | Returns the expected type when in checking mode.
    
    494 501
     checkingExpType_maybe :: ExpType -> Maybe TcType
    
    495 502
     checkingExpType_maybe (Check ty) = Just ty
    

  • compiler/GHC/Tc/Zonk/TcType.hs
    ... ... @@ -818,19 +818,26 @@ zonkTidyHsCtxt env e@(FunAppCtxt{}) = return (env, e)
    818 818
     zonkTidyHsCtxt env (FunTysCtxt ctxt ty i1 i2) = do
    
    819 819
       (env', ty') <- zonkTidyTcType env ty
    
    820 820
       return $ (env', FunTysCtxt ctxt ty' i1 i2)
    
    821
    -zonkTidyHsCtxt env (FunResCtxt e i1 ty1 ty2 i2 i3) = do
    
    822
    -  (env', ty1') <- zonkTidyTcType env ty1
    
    823
    -  (env', ty2') <- zonkTidyTcType env' ty2
    
    824
    -  return $ (env', FunResCtxt e i1 ty1' ty2' i2 i3)
    
    821
    +zonkTidyHsCtxt env (FunResCtxt e n ty1 env_ty) = do
    
    822
    +  (env', ty1')    <- zonkTidyTcType env ty1
    
    823
    +  (env', env_ty') <- zonkExpType env' env_ty
    
    824
    +  return $ (env', FunResCtxt e n ty1' env_ty')
    
    825 825
     zonkTidyHsCtxt env (PatSigErrCtxt sig_ty res_ty) = do
    
    826 826
       (env', sig_ty') <- zonkTidyTcType env sig_ty
    
    827
    -  (env', res_ty') <-
    
    828
    -    case res_ty of
    
    829
    -      Check ty -> zonkTidyTcType env' ty
    
    830
    -      Infer (IR {ir_ref = ref}) -> do -- inlining readExpTyp_maybe to avoid module dep loops
    
    831
    -        mb_ty <- liftIO $ readIORef ref
    
    832
    -        case mb_ty of
    
    833
    -          Nothing -> error "zonkTidyHsCtxt PatSigErrCtxt"
    
    834
    -          Just ty -> zonkTidyTcType env' ty
    
    835
    -  return (env', PatSigErrCtxt sig_ty' (Check res_ty'))
    
    827
    +  (env', res_ty') <- zonkExpType env' res_ty
    
    828
    +  return (env', PatSigErrCtxt sig_ty' res_ty')
    
    836 829
     zonkTidyHsCtxt env p = return (env, p)
    
    830
    +
    
    831
    +zonkExpType :: TidyEnv -> ExpType -> ZonkM (TidyEnv, ExpType)
    
    832
    +-- Zonk Infer{} to Check.  The hole should have been filled in by now
    
    833
    +zonkExpType env (Check ty)
    
    834
    +  = do { (env', ty') <- zonkTidyTcType env ty
    
    835
    +       ; return (env', Check ty') }
    
    836
    +zonkExpType env (Infer ir@(IR { ir_ref = ref }))
    
    837
    +  = do { -- inlining readExpTyp_maybe to avoid module dep loops
    
    838
    +       ; mb_ty <- liftIO $ readIORef ref
    
    839
    +       ; case mb_ty of
    
    840
    +            Nothing -> pprPanic "zonkTidyHsCtxt PatSigErrCtxt" (ppr ir)
    
    841
    +            Just ty -> do { (env', ty') <- zonkTidyTcType env ty
    
    842
    +                          ; return (env', Check ty') } }
    
    843
    +

  • libraries/base/changelog.md
    ... ... @@ -28,6 +28,7 @@
    28 28
       * Hide implementation details when throwing exceptions in throw and throwSTM. ([CLC proposal #387](https://github.com/haskell/core-libraries-committee/issues/387))
    
    29 29
       * Change `hIsReadable` and `hIsWritable` such that they always throw a respective exception when encountering a closed or semi-closed handle, not just in the case of a file handle. ([CLC proposal #371](github.com/haskell/core-libraries-committee/issues/371))
    
    30 30
       * Annotate `onException` continuation with `WhileHandling`. ([CLC Proposal #397](https://github.com/haskell/core-libraries-committee/issues/397))
    
    31
    +  * Improve error message for `Data.Char.chr`. ([CLC Proposal #384](https://github.com/haskell/core-libraries-committee/issues/384))
    
    31 32
     
    
    32 33
     ## 4.22.0.0 *TBA*
    
    33 34
       * Shipped with GHC 9.14.1
    

  • libraries/base/tests/enum01.stdout
    ... ... @@ -81,7 +81,7 @@ Testing Enum Char:
    81 81
         pred (maxBound::Char) = '\1114110'
    
    82 82
         pred (minBound::Char) = error "Prelude.Enum.Char.pred: bad argument"
    
    83 83
         (map (toEnum::Int->Char) [123,ord (minBound::Char), ord(maxBound::Char)]) = "{\NUL\1114111"
    
    84
    -    (toEnum::Int->Char) (minBound::Int) = error "Prelude.chr: bad argument: (-2147483648)"
    
    84
    +    (toEnum::Int->Char) (minBound::Int) = error "Data.Char.chr: argument outside Unicode range: 0..1114111: (-2147483648)"
    
    85 85
         (map fromEnum ['X',minBound,maxBound]) = [88,0,1114111]
    
    86 86
         (take 7 ['\NUL' .. ]) = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK"
    
    87 87
         (take 7 ['\250' .. ]) = "\250\251\252\253\254\255\256"
    

  • libraries/base/tests/enum01.stdout-alpha-dec-osf3
    ... ... @@ -65,7 +65,7 @@ Testing Enum Char:
    65 65
         pred (maxBound::Char) = '\1114110'
    
    66 66
         pred (minBound::Char) = error "Prelude.Enum.Char.pred: bad argument"
    
    67 67
         (map (toEnum::Int->Char) [123,ord (minBound::Char), ord(maxBound::Char)]) = "{\NUL\1114111"
    
    68
    -    (toEnum::Int->Char) (minBound::Int) = error "Prelude.chr: bad argument"
    
    68
    +    (toEnum::Int->Char) (minBound::Int) = error "Data.Char.chr: argument outside Unicode range: 0..1114111:"
    
    69 69
         (map fromEnum ['X',minBound,maxBound]) = [88,0,1114111]
    
    70 70
         (take 7 ['\NUL' .. ]) = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK"
    
    71 71
         (take 7 ['\250' .. ]) = "\250\251\252\253\254\255\256"
    

  • libraries/base/tests/enum01.stdout-ws-64
    ... ... @@ -81,7 +81,7 @@ Testing Enum Char:
    81 81
         pred (maxBound::Char) = '\1114110'
    
    82 82
         pred (minBound::Char) = error "Prelude.Enum.Char.pred: bad argument"
    
    83 83
         (map (toEnum::Int->Char) [123,ord (minBound::Char), ord(maxBound::Char)]) = "{\NUL\1114111"
    
    84
    -    (toEnum::Int->Char) (minBound::Int) = error "Prelude.chr: bad argument: (-9223372036854775808)"
    
    84
    +    (toEnum::Int->Char) (minBound::Int) = error "Data.Char.chr: argument outside Unicode range: 0..1114111: (-9223372036854775808)"
    
    85 85
         (map fromEnum ['X',minBound,maxBound]) = [88,0,1114111]
    
    86 86
         (take 7 ['\NUL' .. ]) = "\NUL\SOH\STX\ETX\EOT\ENQ\ACK"
    
    87 87
         (take 7 ['\250' .. ]) = "\250\251\252\253\254\255\256"
    

  • libraries/ghc-internal/src/GHC/Internal/Char.hs
    ... ... @@ -12,7 +12,7 @@ module GHC.Internal.Char
    12 12
     
    
    13 13
     import GHC.Internal.Classes (eqChar, neChar)
    
    14 14
     import GHC.Internal.Base (otherwise, (++))
    
    15
    -import GHC.Internal.Err (errorWithoutStackTrace)
    
    15
    +import GHC.Internal.Err (error)
    
    16 16
     import GHC.Internal.Show
    
    17 17
     import GHC.Internal.Prim (chr#, int2Word#, leWord#, Int#, Char#)
    
    18 18
     import GHC.Internal.Types (Char(..), Int(..), isTrue#)
    
    ... ... @@ -29,4 +29,7 @@ safe_chr# i#
    29 29
     
    
    30 30
     {-# NOINLINE chr_error #-}
    
    31 31
     chr_error :: Int# -> Char#
    
    32
    -chr_error i# = errorWithoutStackTrace ("Prelude.chr: bad argument: " ++ showSignedInt (I# 9#) (I# i#) "")
    32
    +chr_error i# = error ("Data.Char.chr: argument outside Unicode range: 0..1114111: " ++ showSignedInt (I# 9#) (I# i#) "")
    
    33
    +-- It's not really "Data.Char", but we assume that
    
    34
    +-- the majority of users will import it from "base:Data.Char"
    
    35
    +-- and not from "ghc-internal:GHC.Internal.Char".

  • libraries/ghci/GHCi/Message.hs
    ... ... @@ -86,9 +86,9 @@ data Message a where
    86 86
     
    
    87 87
       -- These all invoke the corresponding functions in the RTS Linker API.
    
    88 88
       InitLinker :: Message ()
    
    89
    -  LookupSymbol :: String -> Message (Maybe (RemotePtr ()))
    
    90
    -  LookupSymbolInDLL :: RemotePtr LoadedDLL -> String -> Message (Maybe (RemotePtr ()))
    
    91
    -  LookupClosure :: String -> Message (Maybe HValueRef)
    
    89
    +  LookupSymbol :: !BS.ShortByteString -> Message (Maybe (RemotePtr ()))
    
    90
    +  LookupSymbolInDLL :: !(RemotePtr LoadedDLL) -> !BS.ShortByteString -> Message (Maybe (RemotePtr ()))
    
    91
    +  LookupClosure :: !BS.ShortByteString -> Message (Maybe HValueRef)
    
    92 92
       LoadDLLs :: [String] -> Message (Either String [RemotePtr LoadedDLL])
    
    93 93
       LoadArchive :: String -> Message () -- error?
    
    94 94
       LoadObj :: String -> Message () -- error?
    
    ... ... @@ -162,8 +162,8 @@ data Message a where
    162 162
     
    
    163 163
       -- | Create a set of CostCentres with the same module name
    
    164 164
       MkCostCentres
    
    165
    -   :: String     -- module, RemotePtr so it can be shared
    
    166
    -   -> [(String,String)] -- (name, SrcSpan)
    
    165
    +   :: !(RemotePtr ())                             -- ModuleName
    
    166
    +   -> ![(BS.ShortByteString, BS.ShortByteString)] -- (name, SrcSpan)
    
    167 167
        -> Message [RemotePtr CostCentre]
    
    168 168
     
    
    169 169
       -- | Show a 'CostCentreStack' as a @[String]@
    
    ... ... @@ -430,7 +430,7 @@ data EvalStatus_ a b
    430 430
     instance Binary a => Binary (EvalStatus_ a b)
    
    431 431
     
    
    432 432
     data EvalBreakpoint = EvalBreakpoint
    
    433
    -  { eb_info_mod      :: String -- ^ Breakpoint info module
    
    433
    +  { eb_info_mod      :: !BS.ShortByteString -- ^ Breakpoint info module
    
    434 434
       , eb_info_mod_unit :: BS.ShortByteString -- ^ Breakpoint tick module unit id
    
    435 435
       , eb_info_index    :: Int    -- ^ Breakpoint info index
    
    436 436
       }
    

  • libraries/ghci/GHCi/ObjLink.hs
    ... ... @@ -31,6 +31,8 @@ import GHCi.RemoteTypes
    31 31
     import GHCi.Message (LoadedDLL)
    
    32 32
     import Control.Exception (throwIO, ErrorCall(..))
    
    33 33
     import Control.Monad    ( when )
    
    34
    +import qualified Data.ByteString.Short as BS
    
    35
    +import Data.Char (ord)
    
    34 36
     import Data.Foldable
    
    35 37
     import Foreign.C
    
    36 38
     import Foreign.Marshal.Alloc ( alloca, free )
    
    ... ... @@ -104,15 +106,15 @@ unloadObj f = throwIO $ ErrorCall $ "unloadObj: unsupported on wasm for " <> f
    104 106
     purgeObj :: String -> IO ()
    
    105 107
     purgeObj f = throwIO $ ErrorCall $ "purgeObj: unsupported on wasm for " <> f
    
    106 108
     
    
    107
    -lookupSymbol :: String -> IO (Maybe (Ptr a))
    
    108
    -lookupSymbol sym = do
    
    109
    -  r <- js_lookupSymbol $ toJSString sym
    
    109
    +lookupSymbol :: BS.ShortByteString -> IO (Maybe (Ptr a))
    
    110
    +lookupSymbol sym@(BS.SBS ba#) = do
    
    111
    +  r <- js_lookupSymbolPtr ba# (BS.length sym)
    
    110 112
       evaluate $ if r == nullPtr then Nothing else Just r
    
    111 113
     
    
    112
    -foreign import javascript unsafe "__ghc_wasm_jsffi_dyld.lookupSymbol($1)"
    
    113
    -  js_lookupSymbol :: JSString -> IO (Ptr a)
    
    114
    +foreign import javascript unsafe "__ghc_wasm_jsffi_dyld.lookupSymbolPtr($1,$2)"
    
    115
    +  js_lookupSymbolPtr :: ByteArray# -> Int -> IO (Ptr a)
    
    114 116
     
    
    115
    -lookupSymbolInDLL :: Ptr LoadedDLL -> String -> IO (Maybe (Ptr a))
    
    117
    +lookupSymbolInDLL :: Ptr LoadedDLL -> BS.ShortByteString -> IO (Maybe (Ptr a))
    
    116 118
     lookupSymbolInDLL _ _ = pure Nothing
    
    117 119
     
    
    118 120
     resolveObjs :: IO Bool
    
    ... ... @@ -149,27 +151,27 @@ initObjLinker :: ShouldRetainCAFs -> IO ()
    149 151
     initObjLinker RetainCAFs = c_initLinker_ 1
    
    150 152
     initObjLinker _ = c_initLinker_ 0
    
    151 153
     
    
    152
    -lookupSymbol :: String -> IO (Maybe (Ptr a))
    
    154
    +lookupSymbol :: BS.ShortByteString -> IO (Maybe (Ptr a))
    
    153 155
     lookupSymbol str_in = do
    
    154 156
        let str = prefixUnderscore str_in
    
    155
    -   withCAString str $ \c_str -> do
    
    157
    +   BS.useAsCString str $ \c_str -> do
    
    156 158
          addr <- c_lookupSymbol c_str
    
    157 159
          if addr == nullPtr
    
    158 160
             then return Nothing
    
    159 161
             else return (Just addr)
    
    160 162
     
    
    161
    -lookupSymbolInDLL :: Ptr LoadedDLL -> String -> IO (Maybe (Ptr a))
    
    163
    +lookupSymbolInDLL :: Ptr LoadedDLL -> BS.ShortByteString -> IO (Maybe (Ptr a))
    
    162 164
     lookupSymbolInDLL dll str_in = do
    
    163 165
        let str = prefixUnderscore str_in
    
    164
    -   withCAString str $ \c_str -> do
    
    166
    +   BS.useAsCString str $ \c_str -> do
    
    165 167
          addr <- c_lookupSymbolInNativeObj dll c_str
    
    166 168
          if addr == nullPtr
    
    167 169
            then return Nothing
    
    168 170
            else return (Just addr)
    
    169 171
     
    
    170
    -prefixUnderscore :: String -> String
    
    172
    +prefixUnderscore :: BS.ShortByteString -> BS.ShortByteString
    
    171 173
     prefixUnderscore
    
    172
    - | cLeadingUnderscore = ('_':)
    
    174
    + | cLeadingUnderscore = BS.cons (fromIntegral (ord '_'))
    
    173 175
      | otherwise          = id
    
    174 176
     
    
    175 177
     -- | loadDLL loads a dynamic library using the OS's native linker
    
    ... ... @@ -298,7 +300,7 @@ isWindowsHost = False
    298 300
     
    
    299 301
     #endif
    
    300 302
     
    
    301
    -lookupClosure :: String -> IO (Maybe HValueRef)
    
    303
    +lookupClosure :: BS.ShortByteString -> IO (Maybe HValueRef)
    
    302 304
     lookupClosure str = do
    
    303 305
       m <- lookupSymbol str
    
    304 306
       case m of
    

  • libraries/ghci/GHCi/Run.hs
    ... ... @@ -34,7 +34,7 @@ import Control.DeepSeq
    34 34
     import Control.Exception
    
    35 35
     import Control.Monad
    
    36 36
     import Data.ByteString (ByteString)
    
    37
    -import qualified Data.ByteString.Short as BS
    
    37
    +import qualified Data.ByteString.Short.Internal as BS
    
    38 38
     import qualified Data.ByteString.Unsafe as B
    
    39 39
     import GHC.Exts
    
    40 40
     import qualified GHC.Exts.Heap as Heap
    
    ... ... @@ -135,12 +135,12 @@ foreign import javascript "((ptr,off) => globalThis.h$loadJS(h$decodeUtf8z(ptr,o
    135 135
     
    
    136 136
     foreign import javascript "((ptr,off) => globalThis.h$lookupClosure(h$decodeUtf8z(ptr,off)))" lookupJSClosure# :: CString -> State# RealWorld -> (# State# RealWorld, Int# #)
    
    137 137
     
    
    138
    -lookupJSClosure' :: String -> IO Int
    
    139
    -lookupJSClosure' str = withCString str $ \cstr -> IO (\s ->
    
    138
    +lookupJSClosure' :: BS.ShortByteString -> IO Int
    
    139
    +lookupJSClosure' str = BS.useAsCString str $ \cstr -> IO (\s ->
    
    140 140
       case lookupJSClosure# cstr s of
    
    141 141
         (# s', r #) -> (# s', I# r #))
    
    142 142
     
    
    143
    -lookupJSClosure :: String -> IO (Maybe HValueRef)
    
    143
    +lookupJSClosure :: BS.ShortByteString -> IO (Maybe HValueRef)
    
    144 144
     lookupJSClosure str = lookupJSClosure' str >>= \case
    
    145 145
       0 -> pure Nothing
    
    146 146
       r -> pure (Just (RemoteRef (RemotePtr (fromIntegral r))))
    
    ... ... @@ -359,7 +359,7 @@ withBreakAction opts breakMVar statusMVar mtid act
    359 359
            if is_exception
    
    360 360
            then pure Nothing
    
    361 361
            else do
    
    362
    -         info_mod <- peekCString (Ptr info_mod#)
    
    362
    +         info_mod <- BS.packCString (Ptr info_mod#)
    
    363 363
              info_mod_uid <- BS.packCString (Ptr info_mod_uid#)
    
    364 364
              pure (Just (EvalBreakpoint info_mod info_mod_uid (I# infox#)))
    
    365 365
          putMVar statusMVar $ EvalBreak apStack_r breakpoint resume_r ccs
    
    ... ... @@ -434,17 +434,24 @@ mkString0 bs = B.unsafeUseAsCStringLen bs $ \(cstr,len) -> do
    434 434
       pokeElemOff (ptr :: Ptr CChar) len 0
    
    435 435
       return (castRemotePtr (toRemotePtr ptr))
    
    436 436
     
    
    437
    -mkCostCentres :: String -> [(String,String)] -> IO [RemotePtr CostCentre]
    
    437
    +mkCostCentres :: RemotePtr () -> [(BS.ShortByteString, BS.ShortByteString)] -> IO [RemotePtr CostCentre]
    
    438 438
     #if defined(PROFILING)
    
    439 439
     mkCostCentres mod ccs = do
    
    440
    -  c_module <- newCString mod
    
    440
    +  let c_module = fromRemotePtr $ castRemotePtr mod
    
    441 441
       mapM (mk_one c_module) ccs
    
    442 442
      where
    
    443 443
       mk_one c_module (decl_path,srcspan) = do
    
    444
    -    c_name <- newCString decl_path
    
    445
    -    c_srcspan <- newCString srcspan
    
    444
    +    c_name <- newCStringFromSBS decl_path
    
    445
    +    c_srcspan <- newCStringFromSBS srcspan
    
    446 446
         toRemotePtr <$> c_mkCostCentre c_name c_module c_srcspan
    
    447 447
     
    
    448
    +  newCStringFromSBS sbs = do
    
    449
    +    let len = BS.length sbs
    
    450
    +    buf <- mallocBytes $ len + 1
    
    451
    +    BS.copyToPtr sbs 0 buf (fromIntegral len)
    
    452
    +    pokeByteOff buf len (0 :: Word8)
    
    453
    +    pure buf
    
    454
    +
    
    448 455
     foreign import ccall unsafe "mkCostCentre"
    
    449 456
       c_mkCostCentre :: Ptr CChar -> Ptr CChar -> Ptr CChar -> IO (Ptr CostCentre)
    
    450 457
     #else
    

  • testsuite/tests/driver/linkwhole/Main.hs
    1
    +{-# LANGUAGE OverloadedStrings #-}
    
    1 2
     {-# LANGUAGE RecordWildCards #-}
    
    2 3
     
    
    3 4
     module Main (main) where
    
    4 5
     
    
    5 6
     import Control.Exception
    
    6 7
     import Control.Monad
    
    8
    +import Data.ByteString.Short (ShortByteString)
    
    7 9
     
    
    8 10
     import Foreign
    
    9 11
     
    
    ... ... @@ -15,7 +17,7 @@ import GHCi.ObjLink
    15 17
     
    
    16 18
     rotateSO
    
    17 19
       :: (FunPtr (IO (StablePtr a)) -> (IO (StablePtr a)))
    
    18
    -  -> String
    
    20
    +  -> ShortByteString
    
    19 21
       -> (Maybe FilePath, FilePath)
    
    20 22
       -> IO a
    
    21 23
     rotateSO dynamicCall symName (old, newDLL) = do
    

  • testsuite/tests/ghci/should_run/T18064.script
    1
    +:set -XOverloadedStrings
    
    1 2
     import GHCi.ObjLink
    
    2 3
     lookupClosure "blah"

  • testsuite/tests/rts/KeepCafsMain.hs
    1
    +{-# LANGUAGE OverloadedStrings #-}
    
    2
    +
    
    1 3
     module Main (main) where
    
    2 4
     
    
    3 5
     import Foreign
    

  • utils/jsffi/dyld.mjs
    ... ... @@ -1334,6 +1334,13 @@ class DyLD {
    1334 1334
         }
    
    1335 1335
         return 0;
    
    1336 1336
       }
    
    1337
    +
    
    1338
    +  lookupSymbolPtr(symPtr, symLen) {
    
    1339
    +    const sym = new TextDecoder("utf-8", { fatal: true }).decode(
    
    1340
    +      new Uint8Array(this.#memory.buffer, symPtr, symLen)
    
    1341
    +    );
    
    1342
    +    return this.lookupSymbol(sym);
    
    1343
    +  }
    
    1337 1344
     }
    
    1338 1345
     
    
    1339 1346
     // The main entry point of dyld that may be run on node/browser, and