Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
264d1cca
by Adam Gundry at 2026-03-18T14:59:20-04:00
-
29e6623e
by sheaf at 2026-03-18T14:59:26-04:00
-
4562ceff
by Cheng Shao at 2026-03-18T14:59:28-04:00
-
607a3f73
by Sylvain Henry at 2026-03-18T14:59:35-04:00
-
c5fc7cb6
by Matthew Pickering at 2026-03-18T14:59:37-04:00
-
c257675b
by Cheng Shao at 2026-03-18T14:59:37-04:00
19 changed files:
- compiler/GHC/Core/Opt/ConstantFold.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Pmc.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Types/Origin.hs
- ghc/GHCi/UI.hs
- ghc/Main.hs
- hadrian/src/Settings/Flavours/GhcInGhci.hs
- rts/PrimOps.cmm
- + testsuite/tests/overloadedrecflds/should_compile/T26686.hs
- + testsuite/tests/overloadedrecflds/should_compile/T26686.stderr
- testsuite/tests/overloadedrecflds/should_compile/all.T
- testsuite/tests/rts/all.T
- + testsuite/tests/rts/resizeMutableByteArrayInPlace.hs
- + testsuite/tests/simplCore/should_compile/T18032.hs
- + testsuite/tests/simplCore/should_compile/T18032.stderr
- testsuite/tests/simplCore/should_compile/all.T
Changes:
| ... | ... | @@ -847,6 +847,14 @@ primOpRules nm = \case |
| 847 | 847 | |
| 848 | 848 | -- Misc
|
| 849 | 849 | |
| 850 | + -- See Note [Constant folding for Addr# equality]
|
|
| 851 | + AddrEqOp -> mkPrimOpRule nm 2 [ equalArgs >> (trueValInt <$> getPlatform)
|
|
| 852 | + , match_litAddr_eq True
|
|
| 853 | + ]
|
|
| 854 | + AddrNeOp -> mkPrimOpRule nm 2 [ equalArgs >> (falseValInt <$> getPlatform)
|
|
| 855 | + , match_litAddr_eq False
|
|
| 856 | + ]
|
|
| 857 | + |
|
| 850 | 858 | AddrAddOp -> mkPrimOpRule nm 2 [ rightIdentityPlatform zeroi ]
|
| 851 | 859 | |
| 852 | 860 | SparkOp -> mkPrimOpRule nm 4 [ sparkRule ]
|
| ... | ... | @@ -969,6 +977,39 @@ cmpOp platform cmp = go |
| 969 | 977 | |
| 970 | 978 | --------------------------
|
| 971 | 979 | |
| 980 | +-- Note [Constant folding for Addr# equality]
|
|
| 981 | +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 982 | +-- We constant-fold (eqAddr# "foo"# "bar"#) when both arguments are string
|
|
| 983 | +-- literals with *different* byte content. Because the bytes differ, the two
|
|
| 984 | +-- literals cannot reside at the same address, so the result is definitely
|
|
| 985 | +-- False (or True for neAddr#).
|
|
| 986 | +--
|
|
| 987 | +-- We use exprIsLiteral_maybe (via isLiteral) rather than binaryLit/cmpOp,
|
|
| 988 | +-- because string literals are frequently floated out to the top level as CAF
|
|
| 989 | +-- bindings. That turns them into variables, and we must look through those
|
|
| 990 | +-- variable unfoldings to recover the underlying LitString.
|
|
| 991 | +--
|
|
| 992 | +-- When both literals have the *same* byte content we do NOT fold to True.
|
|
| 993 | +-- Two distinct literal occurrences in the source may end up at different
|
|
| 994 | +-- addresses in the object file (the linker is not required to merge them),
|
|
| 995 | +-- so pointer equality is not guaranteed by equal content alone. The
|
|
| 996 | +-- equalArgs already handles the case where both arguments are the *same*
|
|
| 997 | +-- expression (provably the same pointer).
|
|
| 998 | + |
|
| 999 | +match_litAddr_eq :: Bool -- ^ True <=> eqAddr# (fold different-content to False)
|
|
| 1000 | + -- False <=> neAddr# (fold different-content to True)
|
|
| 1001 | + -> RuleM CoreExpr
|
|
| 1002 | +-- See Note [Constant folding for Addr# equality]
|
|
| 1003 | +match_litAddr_eq is_eq = do
|
|
| 1004 | + platform <- getPlatform
|
|
| 1005 | + [e1, e2] <- getArgs
|
|
| 1006 | + LitString s1 <- isLiteral e1
|
|
| 1007 | + LitString s2 <- isLiteral e2
|
|
| 1008 | + guard (s1 /= s2)
|
|
| 1009 | + return $ if is_eq then falseValInt platform else trueValInt platform
|
|
| 1010 | + |
|
| 1011 | +--------------------------
|
|
| 1012 | + |
|
| 972 | 1013 | negOp :: RuleOpts -> Literal -> Maybe CoreExpr -- Negate
|
| 973 | 1014 | negOp env = \case
|
| 974 | 1015 | (LitFloat 0.0) -> Nothing -- can't represent -0.0 as a Rational
|
| ... | ... | @@ -56,7 +56,7 @@ import GHC.Data.Graph.Directed |
| 56 | 56 | import GHC.Data.FastString
|
| 57 | 57 | import GHC.Data.Maybe ( expectJust )
|
| 58 | 58 | import qualified GHC.Data.Maybe as M
|
| 59 | -import GHC.Data.OsPath ( unsafeEncodeUtf )
|
|
| 59 | +import GHC.Data.OsPath ( OsPath, unsafeEncodeUtf )
|
|
| 60 | 60 | import GHC.Data.StringBuffer
|
| 61 | 61 | import GHC.Data.Graph.Directed.Reachability
|
| 62 | 62 | import qualified GHC.LanguageExtensions as LangExt
|
| ... | ... | @@ -216,9 +216,9 @@ downsweep hsc_env diag_wrapper msg old_summaries excl_mods allow_dup_roots = do |
| 216 | 216 | -- file was used in.
|
| 217 | 217 | -- Reuse these if we can because the most expensive part of downsweep is
|
| 218 | 218 | -- reading the headers.
|
| 219 | - old_summary_map :: M.Map (UnitId, FilePath) ModSummary
|
|
| 219 | + old_summary_map :: M.Map (UnitId, OsPath) ModSummary
|
|
| 220 | 220 | old_summary_map =
|
| 221 | - M.fromList [((ms_unitid ms, msHsFilePath ms), ms) | ms <- old_summaries]
|
|
| 221 | + M.fromList [((ms_unitid ms, msHsFileOsPath ms), ms) | ms <- old_summaries]
|
|
| 222 | 222 | |
| 223 | 223 | -- Dependencies arising on a unit (backpack and module linking deps)
|
| 224 | 224 | unitModuleNodes :: [ModuleGraphNode] -> UnitId -> HomeUnitEnv -> [Either (Messages DriverMessage) ModuleGraphNode]
|
| ... | ... | @@ -384,7 +384,7 @@ data DownsweepMode = DownsweepUseCompile | DownsweepUseFixed |
| 384 | 384 | -- This function will start at the given roots, and traverse downwards to find
|
| 385 | 385 | -- all the dependencies, all the way to the leaf units.
|
| 386 | 386 | downsweepFromRootNodes :: HscEnv
|
| 387 | - -> M.Map (UnitId, FilePath) ModSummary
|
|
| 387 | + -> M.Map (UnitId, OsPath) ModSummary
|
|
| 388 | 388 | -> [ModuleName]
|
| 389 | 389 | -> Bool
|
| 390 | 390 | -> DownsweepMode -- ^ Whether to create fixed or compile nodes for dependencies
|
| ... | ... | @@ -442,7 +442,7 @@ type DownsweepM a = ReaderT DownsweepEnv IO a |
| 442 | 442 | data DownsweepEnv = DownsweepEnv {
|
| 443 | 443 | downsweep_hsc_env :: HscEnv
|
| 444 | 444 | , _downsweep_mode :: DownsweepMode
|
| 445 | - , _downsweep_old_summaries :: M.Map (UnitId, FilePath) ModSummary
|
|
| 445 | + , _downsweep_old_summaries :: M.Map (UnitId, OsPath) ModSummary
|
|
| 446 | 446 | , _downsweep_excl_mods :: [ModuleName]
|
| 447 | 447 | }
|
| 448 | 448 | |
| ... | ... | @@ -715,7 +715,7 @@ linkNodes summaries uid hue = |
| 715 | 715 | |
| 716 | 716 | getRootSummary ::
|
| 717 | 717 | [ModuleName] ->
|
| 718 | - M.Map (UnitId, FilePath) ModSummary ->
|
|
| 718 | + M.Map (UnitId, OsPath) ModSummary ->
|
|
| 719 | 719 | HscEnv ->
|
| 720 | 720 | Target ->
|
| 721 | 721 | IO (Either DriverMessages ModSummary)
|
| ... | ... | @@ -1183,7 +1183,7 @@ mkRootMap summaries = Map.fromListWith (flip (++)) |
| 1183 | 1183 | summariseFile
|
| 1184 | 1184 | :: HscEnv
|
| 1185 | 1185 | -> HomeUnit
|
| 1186 | - -> M.Map (UnitId, FilePath) ModSummary -- old summaries
|
|
| 1186 | + -> M.Map (UnitId, OsPath) ModSummary -- old summaries
|
|
| 1187 | 1187 | -> FilePath -- source file name
|
| 1188 | 1188 | -> Maybe Phase -- start phase
|
| 1189 | 1189 | -> Maybe (StringBuffer,UTCTime)
|
| ... | ... | @@ -1192,7 +1192,7 @@ summariseFile |
| 1192 | 1192 | summariseFile hsc_env' home_unit old_summaries src_fn mb_phase maybe_buf
|
| 1193 | 1193 | -- we can use a cached summary if one is available and the
|
| 1194 | 1194 | -- source file hasn't changed,
|
| 1195 | - | Just old_summary <- M.lookup (homeUnitId home_unit, src_fn) old_summaries
|
|
| 1195 | + | Just old_summary <- M.lookup (homeUnitId home_unit, src_fn_os) old_summaries
|
|
| 1196 | 1196 | = do
|
| 1197 | 1197 | let location = ms_location $ old_summary
|
| 1198 | 1198 | |
| ... | ... | @@ -1213,6 +1213,7 @@ summariseFile hsc_env' home_unit old_summaries src_fn mb_phase maybe_buf |
| 1213 | 1213 | where
|
| 1214 | 1214 | -- change the main active unit so all operations happen relative to the given unit
|
| 1215 | 1215 | hsc_env = hscSetActiveHomeUnit home_unit hsc_env'
|
| 1216 | + src_fn_os = unsafeEncodeUtf src_fn
|
|
| 1216 | 1217 | -- src_fn does not necessarily exist on the filesystem, so we need to
|
| 1217 | 1218 | -- check what kind of target we are dealing with
|
| 1218 | 1219 | get_src_hash = case maybe_buf of
|
| ... | ... | @@ -1302,7 +1303,7 @@ data SummariseResult = |
| 1302 | 1303 | -- --make mode.
|
| 1303 | 1304 | summariseModule :: HscEnv
|
| 1304 | 1305 | -> HomeUnit
|
| 1305 | - -> M.Map (UnitId, FilePath) ModSummary
|
|
| 1306 | + -> M.Map (UnitId, OsPath) ModSummary
|
|
| 1306 | 1307 | -> IsBootInterface
|
| 1307 | 1308 | -> Located ModuleName
|
| 1308 | 1309 | -> PkgQual
|
| ... | ... | @@ -1382,7 +1383,7 @@ summariseModuleDispatch k hsc_env' home_unit is_boot (L _ wanted_mod) mb_pkg exc |
| 1382 | 1383 | -- for it and potentially compile it.
|
| 1383 | 1384 | summariseModuleWithSource
|
| 1384 | 1385 | :: HomeUnit
|
| 1385 | - -> M.Map (UnitId, FilePath) ModSummary
|
|
| 1386 | + -> M.Map (UnitId, OsPath) ModSummary
|
|
| 1386 | 1387 | -- ^ Map of old summaries
|
| 1387 | 1388 | -> IsBootInterface -- True <=> a {-# SOURCE #-} import
|
| 1388 | 1389 | -> Maybe (StringBuffer, UTCTime)
|
| ... | ... | @@ -1411,7 +1412,7 @@ summariseModuleWithSource home_unit old_summary_map is_boot maybe_buf hsc_env lo |
| 1411 | 1412 | where
|
| 1412 | 1413 | dflags = hsc_dflags hsc_env
|
| 1413 | 1414 | new_summary_cache_check loc mod src_fn h
|
| 1414 | - | Just old_summary <- Map.lookup ((toUnitId (moduleUnit mod), src_fn)) old_summary_map =
|
|
| 1415 | + | Just old_summary <- Map.lookup ((toUnitId (moduleUnit mod), src_fn_os)) old_summary_map =
|
|
| 1415 | 1416 | |
| 1416 | 1417 | -- check the hash on the source file, and
|
| 1417 | 1418 | -- return the cached summary if it hasn't changed. If the
|
| ... | ... | @@ -1422,6 +1423,8 @@ summariseModuleWithSource home_unit old_summary_map is_boot maybe_buf hsc_env lo |
| 1422 | 1423 | Nothing ->
|
| 1423 | 1424 | checkSummaryHash hsc_env (new_summary loc mod src_fn) old_summary loc h
|
| 1424 | 1425 | | otherwise = new_summary loc mod src_fn h
|
| 1426 | + where
|
|
| 1427 | + src_fn_os = unsafeEncodeUtf src_fn
|
|
| 1425 | 1428 | |
| 1426 | 1429 | new_summary :: ModLocation
|
| 1427 | 1430 | -> Module
|
| ... | ... | @@ -721,6 +721,15 @@ ds_app (XExpr (ConLikeTc con)) _hs_args core_args |
| 721 | 721 | ds_app (XExpr (HsRecSelTc (FieldOcc { foLabel = L _ sel_id }))) _hs_args core_args
|
| 722 | 722 | = ds_app_rec_sel sel_id sel_id core_args
|
| 723 | 723 | |
| 724 | +ds_app (XExpr (ExpandedThingTc _orig e)) hs_args core_args
|
|
| 725 | + = ds_app e hs_args core_args
|
|
| 726 | + -- NB: this is important for the 'getField' case of 'ds_app_var', which needs
|
|
| 727 | + -- to see all type arguments to 'getField' at once, while for record field
|
|
| 728 | + -- projections such as (.fld) we may get:
|
|
| 729 | + --
|
|
| 730 | + -- XExpr (ExpandedThingTc (.fld) (getField @Symbol @LiftedRep @LiftedRep "fld"))
|
|
| 731 | + -- `HsAppType` rec_ty `HsAppType` fld
|
|
| 732 | + |
|
| 724 | 733 | ds_app (HsVar _ lfun) hs_args core_args
|
| 725 | 734 | = ds_app_var lfun hs_args core_args
|
| 726 | 735 | |
| ... | ... | @@ -736,8 +745,10 @@ ds_app_var (L loc fun_id) hs_args core_args |
| 736 | 745 | -----------------------
|
| 737 | 746 | -- Deal with getField applications. General form:
|
| 738 | 747 | -- getField
|
| 739 | - -- @GHC.Types.Symbol {k}
|
|
| 740 | - -- @"sel" x_ty
|
|
| 748 | + -- @Symbol {k}
|
|
| 749 | + -- @LiftedRep {r_rep}
|
|
| 750 | + -- @LiftedRep {a_rep}
|
|
| 751 | + -- @"sel" fld
|
|
| 741 | 752 | -- @T r_ty
|
| 742 | 753 | -- @Int a_ty
|
| 743 | 754 | -- ($dHasField :: HasField "sel" T Int) dict
|
| ... | ... | @@ -375,6 +375,10 @@ Finally, there are two more items addressing -XOverloadedRecordDot: |
| 375 | 375 | the (IRS6) warning in the typechecker for a `HasField` constraint that
|
| 376 | 376 | arises from a record-dot HsGetField occurrence. Happily, this is easy to do
|
| 377 | 377 | by looking at its `CtOrigin`. Tested in T24891.
|
| 378 | + |
|
| 379 | + The same applies for record field projection operators such as (.fld) and
|
|
| 380 | + (.fld1.fld2), which have different 'CtOrigin's. The 'isHasFieldOrigin'
|
|
| 381 | + function catches those as well. Tested in T26686.
|
|
| 378 | 382 | -}
|
| 379 | 383 | |
| 380 | 384 | pmcRecSel :: Id -- ^ Id of the selector
|
| ... | ... | @@ -97,6 +97,7 @@ import Data.Ord ( comparing ) |
| 97 | 97 | import Data.Either ( partitionEithers )
|
| 98 | 98 | import Data.Map.Strict (Map)
|
| 99 | 99 | import qualified Data.Map.Strict as Map
|
| 100 | +import qualified Data.Semigroup as Semi
|
|
| 100 | 101 | |
| 101 | 102 | {-
|
| 102 | 103 | ************************************************************************
|
| ... | ... | @@ -2714,15 +2715,34 @@ hasFieldInfo_maybe rdr_env fam_inst_envs item |
| 2714 | 2715 | |
| 2715 | 2716 | -- (HF2e) It's a custom HasField constraint, not the one from GHC.Records.
|
| 2716 | 2717 | | Just (tc, _) <- splitTyConApp_maybe (errorItemPred item)
|
| 2717 | - , getOccString tc == "HasField"
|
|
| 2718 | - , isHasFieldOrigin (errorItemOrigin item)
|
|
| 2719 | - = return $ Just $ CustomHasField tc
|
|
| 2718 | + = do { rebindable_syntax <- xoptM LangExt.RebindableSyntax
|
|
| 2719 | + ; return $
|
|
| 2720 | + if want_custom_hasfield_msg tc rebindable_syntax
|
|
| 2721 | + then Just $ CustomHasField tc
|
|
| 2722 | + else Nothing
|
|
| 2723 | + }
|
|
| 2720 | 2724 | |
| 2721 | 2725 | | otherwise
|
| 2722 | 2726 | = return Nothing
|
| 2723 | 2727 | |
| 2724 | 2728 | where
|
| 2725 | 2729 | |
| 2730 | + orig = errorItemOrigin item
|
|
| 2731 | + |
|
| 2732 | + want_custom_hasfield_msg tc rebindable_syntax
|
|
| 2733 | + | getOccString tc == "HasField"
|
|
| 2734 | + = Semi.getAny $ foldMapCtOrigin (Semi.Any . is_has_field) orig
|
|
| 2735 | + | otherwise
|
|
| 2736 | + = False
|
|
| 2737 | + where
|
|
| 2738 | + -- Handle custom 'getField'/'setField' with RebindableSyntax.
|
|
| 2739 | + is_has_field (OccurrenceOf n)
|
|
| 2740 | + | rebindable_syntax
|
|
| 2741 | + , getOccString n `elem` ["getField", "setField"]
|
|
| 2742 | + = True
|
|
| 2743 | + is_has_field o
|
|
| 2744 | + = isHasFieldOrigin o
|
|
| 2745 | + |
|
| 2726 | 2746 | get_parent_nm :: Name -> TcM (Maybe (Either PatSyn TyCon))
|
| 2727 | 2747 | get_parent_nm nm =
|
| 2728 | 2748 | do { fld_id <- tcLookupId nm
|
| ... | ... | @@ -2762,22 +2782,6 @@ hasField_maybe pred = |
| 2762 | 2782 | -- NB: we deliberately don't handle rebound 'HasField' (with -XRebindableSyntax),
|
| 2763 | 2783 | -- as GHC only has built-in instances for the built-in 'HasField' class.
|
| 2764 | 2784 | |
| 2765 | --- | Does this constraint arise from GHC internal mechanisms that desugar to
|
|
| 2766 | --- usage of the 'HasField' typeclass (e.g. OverloadedRecordDot, etc)?
|
|
| 2767 | ---
|
|
| 2768 | --- Just used heuristically to decide whether to print an informative message to
|
|
| 2769 | --- the user (see (H2e) in Note [Error messages for unsolved HasField constraints]).
|
|
| 2770 | -isHasFieldOrigin :: CtOrigin -> Bool
|
|
| 2771 | -isHasFieldOrigin = \case
|
|
| 2772 | - OccurrenceOf n ->
|
|
| 2773 | - -- A heuristic...
|
|
| 2774 | - getOccString n `elem` ["getField", "setField"]
|
|
| 2775 | - OccurrenceOfRecSel {} -> True
|
|
| 2776 | - RecordUpdOrigin {} -> True
|
|
| 2777 | - RecordFieldProjectionOrigin {} -> True
|
|
| 2778 | - GetFieldOrigin {} -> True
|
|
| 2779 | - _ -> False
|
|
| 2780 | - |
|
| 2781 | 2785 | -----------------------
|
| 2782 | 2786 | -- relevantBindings looks at the value environment and finds values whose
|
| 2783 | 2787 | -- types mention any of the offending type variables. It has to be
|
| ... | ... | @@ -20,7 +20,7 @@ import GHC.Tc.Instance.Typeable |
| 20 | 20 | import GHC.Tc.Utils.TcMType
|
| 21 | 21 | import GHC.Tc.Types.Evidence
|
| 22 | 22 | import GHC.Tc.Types.CtLoc
|
| 23 | -import GHC.Tc.Types.Origin ( InstanceWhat (..), SafeOverlapping, CtOrigin(GetFieldOrigin) )
|
|
| 23 | +import GHC.Tc.Types.Origin ( InstanceWhat (..), SafeOverlapping, isHasFieldOrigin )
|
|
| 24 | 24 | import GHC.Tc.Instance.Family( tcGetFamInstEnvs, tcLookupDataFamInst, FamInstEnvs )
|
| 25 | 25 | |
| 26 | 26 | import GHC.Rename.Env( addUsedGRE, addUsedDataCons, DeprecationWarnings (..) )
|
| ... | ... | @@ -1275,8 +1275,8 @@ warnIncompleteRecSel :: DynFlags -> Id -> CtLoc -> TcM () |
| 1275 | 1275 | -- Warn about incomplete record selectors
|
| 1276 | 1276 | -- See (IRS6) in Note [Detecting incomplete record selectors] in GHC.HsToCore.Pmc
|
| 1277 | 1277 | warnIncompleteRecSel dflags sel_id ct_loc
|
| 1278 | - | not (isGetFieldOrigin (ctLocOrigin ct_loc))
|
|
| 1279 | - -- isGetFieldOrigin: see (IRS7) in
|
|
| 1278 | + | not $ isHasFieldOrigin (ctLocOrigin ct_loc)
|
|
| 1279 | + -- isHasFieldOrigin: see (IRS7) in
|
|
| 1280 | 1280 | -- Note [Detecting incomplete record selectors] in GHC.HsToCore.Pmc
|
| 1281 | 1281 | , RecSelId { sel_cons = RSI { rsi_undef = fallible_cons } } <- idDetails sel_id
|
| 1282 | 1282 | , not (null fallible_cons)
|
| ... | ... | @@ -1288,11 +1288,6 @@ warnIncompleteRecSel dflags sel_id ct_loc |
| 1288 | 1288 | where
|
| 1289 | 1289 | maxCons = maxUncoveredPatterns dflags
|
| 1290 | 1290 | |
| 1291 | - -- GHC.Tc.Gen.App.tcInstFun arranges that the CtOrigin of (r.x) is GetFieldOrigin,
|
|
| 1292 | - -- despite the expansion to (getField @"x" r)
|
|
| 1293 | - isGetFieldOrigin (GetFieldOrigin {}) = True
|
|
| 1294 | - isGetFieldOrigin _ = False
|
|
| 1295 | - |
|
| 1296 | 1291 | lookupHasFieldLabel
|
| 1297 | 1292 | :: FamInstEnvs -> GlobalRdrEnv -> [Type]
|
| 1298 | 1293 | -> Maybe ( Name -- Name of the record selector
|
| ... | ... | @@ -16,7 +16,8 @@ module GHC.Tc.Types.Origin ( |
| 16 | 16 | CtOrigin(..), exprCtOrigin, lexprCtOrigin, matchesCtOrigin, grhssCtOrigin,
|
| 17 | 17 | invisibleOrigin_maybe, isVisibleOrigin, toInvisibleOrigin,
|
| 18 | 18 | pprCtOrigin, pprCtOriginBriefly, isGivenOrigin,
|
| 19 | - defaultReprEqOrigins, isWantedSuperclassOrigin,
|
|
| 19 | + foldMapCtOrigin,
|
|
| 20 | + defaultReprEqOrigins, isWantedSuperclassOrigin, isHasFieldOrigin,
|
|
| 20 | 21 | ClsInstOrQC(..), NakedScFlag(..), NonLinearPatternReason(..),
|
| 21 | 22 | HsImplicitLiftSplice(..),
|
| 22 | 23 | StandaloneDeriv,
|
| ... | ... | @@ -52,6 +53,8 @@ import GHC.Tc.Utils.TcType |
| 52 | 53 | |
| 53 | 54 | import GHC.Hs
|
| 54 | 55 | |
| 56 | +import GHC.Builtin.Names (getFieldName)
|
|
| 57 | + |
|
| 55 | 58 | import GHC.Core.DataCon
|
| 56 | 59 | import GHC.Core.ConLike
|
| 57 | 60 | import GHC.Core.TyCon
|
| ... | ... | @@ -79,6 +82,8 @@ import GHC.Types.Unique.Supply |
| 79 | 82 | import qualified Data.Kind as Hs
|
| 80 | 83 | import Data.List.NonEmpty (NonEmpty (..))
|
| 81 | 84 | import Data.Maybe (isNothing)
|
| 85 | +import qualified Data.Semigroup as Semi
|
|
| 86 | +import GHC.Generics
|
|
| 82 | 87 | |
| 83 | 88 | {- *********************************************************************
|
| 84 | 89 | * *
|
| ... | ... | @@ -993,6 +998,95 @@ pprNonLinearPatternReason PatternSynonymReason = parens (text "pattern synonyms |
| 993 | 998 | pprNonLinearPatternReason ViewPatternReason = parens (text "view patterns aren't linear")
|
| 994 | 999 | pprNonLinearPatternReason OtherPatternReason = empty
|
| 995 | 1000 | |
| 1001 | + |
|
| 1002 | +{- *********************************************************************
|
|
| 1003 | +* *
|
|
| 1004 | + Recursing through CtOrigin
|
|
| 1005 | +* *
|
|
| 1006 | +********************************************************************* -}
|
|
| 1007 | + |
|
| 1008 | +-- | Fold over a 'CtOrigin', looking through all recursive
|
|
| 1009 | +-- occurrences of 'CtOrigin' within 'CtOrigin'.
|
|
| 1010 | +foldMapCtOrigin :: forall m. Semigroup m => (CtOrigin -> m) -> CtOrigin -> m
|
|
| 1011 | +foldMapCtOrigin f = go
|
|
| 1012 | + where
|
|
| 1013 | + go :: CtOrigin -> m
|
|
| 1014 | + go orig =
|
|
| 1015 | + case orig of
|
|
| 1016 | + KindEqOrigin _ _ o _ -> recur o
|
|
| 1017 | + CycleBreakerOrigin o -> recur o
|
|
| 1018 | + WantedSuperclassOrigin _ o -> recur o
|
|
| 1019 | + DefaultReprEqOrigin _ _ o -> recur o
|
|
| 1020 | + ScOrigin cls_or_qc _sc_flag ->
|
|
| 1021 | + case cls_or_qc of
|
|
| 1022 | + IsQC _ o -> recur o
|
|
| 1023 | + IsClsInst -> f orig
|
|
| 1024 | + |
|
| 1025 | + -- Explicit pattern match on remaining constructors, in order to get
|
|
| 1026 | + -- better pattern-match warnings when constructors are changed or
|
|
| 1027 | + -- added/removed. This isn't entirely fool-proof, as someone may still
|
|
| 1028 | + -- change the type of one of the fields and hide a 'CtOrigin' inside.
|
|
| 1029 | + --
|
|
| 1030 | + -- This approach was chosen instead of using 'syb'/'GHC.Generics',
|
|
| 1031 | + -- because those would require deriving 'Data.Data'/'Generic' on
|
|
| 1032 | + -- a huge number of datatypes.
|
|
| 1033 | + GivenOrigin {} -> f orig
|
|
| 1034 | + GivenSCOrigin {} -> f orig
|
|
| 1035 | + OccurrenceOf {} -> f orig
|
|
| 1036 | + OccurrenceOfRecSel {} -> f orig
|
|
| 1037 | + AppOrigin {} -> f orig
|
|
| 1038 | + SpecPragOrigin {} -> f orig
|
|
| 1039 | + TypeEqOrigin {}-> f orig
|
|
| 1040 | + IPOccOrigin {} -> f orig
|
|
| 1041 | + OverLabelOrigin {} -> f orig
|
|
| 1042 | + LiteralOrigin {} -> f orig
|
|
| 1043 | + QualLiteralOrigin {} -> f orig
|
|
| 1044 | + NegateOrigin {} -> f orig
|
|
| 1045 | + ArithSeqOrigin {} -> f orig
|
|
| 1046 | + AssocFamPatOrigin {} -> f orig
|
|
| 1047 | + SectionOrigin {} -> f orig
|
|
| 1048 | + GetFieldOrigin {} -> f orig
|
|
| 1049 | + RecordFieldProjectionOrigin {} -> f orig
|
|
| 1050 | + TupleOrigin {} -> f orig
|
|
| 1051 | + ExprSigOrigin {} -> f orig
|
|
| 1052 | + PatSigOrigin {} -> f orig
|
|
| 1053 | + PatOrigin {} -> f orig
|
|
| 1054 | + ProvCtxtOrigin {} -> f orig
|
|
| 1055 | + RecordUpdOrigin {} -> f orig
|
|
| 1056 | + ViewPatOrigin {} -> f orig
|
|
| 1057 | + DerivOrigin {} -> f orig
|
|
| 1058 | + DerivOriginDC {} -> f orig
|
|
| 1059 | + DerivOriginCoerce {} -> f orig
|
|
| 1060 | + DefaultOrigin {} -> f orig
|
|
| 1061 | + DoOrigin {} -> f orig
|
|
| 1062 | + DoPatOrigin {} -> f orig
|
|
| 1063 | + MCompOrigin {} -> f orig
|
|
| 1064 | + MCompPatOrigin {} -> f orig
|
|
| 1065 | + ProcOrigin {} -> f orig
|
|
| 1066 | + ArrowCmdOrigin {} -> f orig
|
|
| 1067 | + AnnOrigin {} -> f orig
|
|
| 1068 | + FunDepOrigin {} -> f orig
|
|
| 1069 | + ExprHoleOrigin {} -> f orig
|
|
| 1070 | + TypeHoleOrigin {} -> f orig
|
|
| 1071 | + PatCheckOrigin {} -> f orig
|
|
| 1072 | + ListOrigin {} -> f orig
|
|
| 1073 | + IfThenElseOrigin {} -> f orig
|
|
| 1074 | + BracketOrigin {} -> f orig
|
|
| 1075 | + StaticOrigin {} -> f orig
|
|
| 1076 | + ImpedanceMatching {} -> f orig
|
|
| 1077 | + Shouldn'tHappenOrigin {} -> f orig
|
|
| 1078 | + InstProvidedOrigin {} -> f orig
|
|
| 1079 | + NonLinearPatternOrigin {} -> f orig
|
|
| 1080 | + OmittedFieldOrigin {} -> f orig
|
|
| 1081 | + UsageEnvironmentOf {} -> f orig
|
|
| 1082 | + FRROrigin {} -> f orig
|
|
| 1083 | + InstanceSigOrigin {} -> f orig
|
|
| 1084 | + AmbiguityCheckOrigin {} -> f orig
|
|
| 1085 | + ImplicitLiftOrigin {} -> f orig
|
|
| 1086 | + |
|
| 1087 | + where
|
|
| 1088 | + recur o = f orig Semi.<> go o
|
|
| 1089 | + |
|
| 996 | 1090 | {- *********************************************************************
|
| 997 | 1091 | * *
|
| 998 | 1092 | Defaulting of representational equalities
|
| ... | ... | @@ -1004,21 +1098,10 @@ pprNonLinearPatternReason OtherPatternReason = empty |
| 1004 | 1098 | -- That is, this function extracts all occurrences of the 'DefaultReprEqOrigin'
|
| 1005 | 1099 | -- constructor from within a 'CtOrigin'.
|
| 1006 | 1100 | defaultReprEqOrigins :: CtOrigin -> [(CtOrigin, (TcType, TcType))]
|
| 1007 | -defaultReprEqOrigins = go
|
|
| 1101 | +defaultReprEqOrigins = foldMapCtOrigin go
|
|
| 1008 | 1102 | where
|
| 1009 | 1103 | go = \case
|
| 1010 | - DefaultReprEqOrigin l r o -> (o, (l, r)) : go o
|
|
| 1011 | - |
|
| 1012 | - -- Handle recursive occurrences of 'CtOrigin' within 'CtOrigin'.
|
|
| 1013 | - -- TODO: use syb to derive this, so that the following never goes out of date.
|
|
| 1014 | - ScOrigin cls_or_qc _ ->
|
|
| 1015 | - case cls_or_qc of
|
|
| 1016 | - IsClsInst -> []
|
|
| 1017 | - IsQC _ o -> go o
|
|
| 1018 | - KindEqOrigin _ _ o _ -> go o
|
|
| 1019 | - CycleBreakerOrigin o -> go o
|
|
| 1020 | - WantedSuperclassOrigin _ o -> go o
|
|
| 1021 | - |
|
| 1104 | + DefaultReprEqOrigin l r o -> [(o, (l, r))]
|
|
| 1022 | 1105 | _ -> []
|
| 1023 | 1106 | |
| 1024 | 1107 | {- *********************************************************************
|
| ... | ... | @@ -1046,6 +1129,37 @@ isPushCallStackOrigin_maybe orig = Just orig_fs |
| 1046 | 1129 | where
|
| 1047 | 1130 | orig_fs = mkFastString (showSDocUnsafe (pprCtOriginBriefly orig))
|
| 1048 | 1131 | |
| 1132 | +{- *********************************************************************
|
|
| 1133 | +* *
|
|
| 1134 | + HasField and CtOrigin
|
|
| 1135 | +* *
|
|
| 1136 | +********************************************************************* -}
|
|
| 1137 | + |
|
| 1138 | +-- | Does this constraint arise from GHC internal mechanisms that desugar to
|
|
| 1139 | +-- usage of the 'HasField' typeclass (e.g. OverloadedRecordDot, etc)?
|
|
| 1140 | +--
|
|
| 1141 | +-- Used in two places:
|
|
| 1142 | +--
|
|
| 1143 | +-- - When reporting an unsolved 'HasField' constraint, to decide whether to
|
|
| 1144 | +-- print an informative message to the user.
|
|
| 1145 | +-- See (H2e) in Note [Error messages for unsolved HasField constraints]
|
|
| 1146 | +-- in GHC.Tc.Errors.
|
|
| 1147 | +-- - To avoid emitting a poor "incomplete record selector" warning directly
|
|
| 1148 | +-- in typechecker, in cases when the desugarer will be able to emit a better
|
|
| 1149 | +-- error message, due to having better pattern match checking information.
|
|
| 1150 | +-- See (IRS7) in Note [Detecting incomplete record selectors]
|
|
| 1151 | +-- in GHC.HsToCore.Pmc
|
|
| 1152 | +isHasFieldOrigin :: CtOrigin -> Bool
|
|
| 1153 | +isHasFieldOrigin = Semi.getAny . foldMapCtOrigin (Semi.Any . go)
|
|
| 1154 | + where
|
|
| 1155 | + go = \case
|
|
| 1156 | + OccurrenceOf n -> n == getFieldName
|
|
| 1157 | + OccurrenceOfRecSel {} -> True
|
|
| 1158 | + RecordFieldProjectionOrigin {} -> True
|
|
| 1159 | + GetFieldOrigin {} -> True
|
|
| 1160 | + RecordUpdOrigin {} -> True
|
|
| 1161 | + _ -> False
|
|
| 1162 | + |
|
| 1049 | 1163 | {-
|
| 1050 | 1164 | ************************************************************************
|
| 1051 | 1165 | * *
|
| ... | ... | @@ -23,7 +23,8 @@ module GHCi.UI ( |
| 23 | 23 | GhciSettings(..),
|
| 24 | 24 | defaultGhciSettings,
|
| 25 | 25 | ghciCommands,
|
| 26 | - ghciWelcomeMsg
|
|
| 26 | + ghciWelcomeMsg,
|
|
| 27 | + languageEditionMsg
|
|
| 27 | 28 | ) where
|
| 28 | 29 | |
| 29 | 30 | -- GHCi
|
| ... | ... | @@ -199,6 +200,10 @@ versionString = "GHCi, version " ++ cProjectVersion |
| 199 | 200 | ghciWelcomeMsg :: String
|
| 200 | 201 | ghciWelcomeMsg = versionString ++ ": https://www.haskell.org/ghc/ :? for help"
|
| 201 | 202 | |
| 203 | +languageEditionMsg :: Maybe Language -> String
|
|
| 204 | +languageEditionMsg Nothing = "Using default language edition: " ++ show defaultLanguage
|
|
| 205 | +languageEditionMsg (Just lang) = "Using language edition: " ++ show lang
|
|
| 206 | + |
|
| 202 | 207 | ghciCommands :: [Command]
|
| 203 | 208 | ghciCommands = map mkCmd [
|
| 204 | 209 | -- Hugs users are accustomed to :e, so make sure it doesn't overlap
|
| ... | ... | @@ -37,7 +37,7 @@ import GHC.Platform |
| 37 | 37 | import GHC.Platform.Host
|
| 38 | 38 | |
| 39 | 39 | #if defined(HAVE_INTERNAL_INTERPRETER)
|
| 40 | -import GHCi.UI ( interactiveUI, ghciWelcomeMsg, defaultGhciSettings )
|
|
| 40 | +import GHCi.UI ( interactiveUI, ghciWelcomeMsg, defaultGhciSettings, languageEditionMsg )
|
|
| 41 | 41 | #endif
|
| 42 | 42 | |
| 43 | 43 | import GHC.Runtime.Loader ( loadFrontendPlugin, initializeSessionPlugins )
|
| ... | ... | @@ -334,7 +334,9 @@ showBanner _postLoadMode dflags = do |
| 334 | 334 | |
| 335 | 335 | #if defined(HAVE_INTERNAL_INTERPRETER)
|
| 336 | 336 | -- Show the GHCi banner
|
| 337 | - when (isInteractiveMode _postLoadMode && verb >= 1) $ putStrLn ghciWelcomeMsg
|
|
| 337 | + when (isInteractiveMode _postLoadMode && verb >= 1) $
|
|
| 338 | + do putStrLn ghciWelcomeMsg
|
|
| 339 | + putStrLn $ languageEditionMsg (language dflags)
|
|
| 338 | 340 | #endif
|
| 339 | 341 | |
| 340 | 342 | -- Display details of the configuration in verbose mode
|
| 1 | 1 | module Settings.Flavours.GhcInGhci (ghcInGhciFlavour) where
|
| 2 | 2 | |
| 3 | +import qualified Data.Set as Set
|
|
| 3 | 4 | import Expression
|
| 4 | 5 | import Flavour
|
| 6 | +import Oracles.Flag
|
|
| 5 | 7 | import {-# SOURCE #-} Settings.Default
|
| 6 | 8 | |
| 7 | 9 | -- Please update doc/flavours.md when changing this file.
|
| 8 | 10 | ghcInGhciFlavour :: Flavour
|
| 9 | 11 | ghcInGhciFlavour = disableProfiledLibs $ defaultFlavour
|
| 10 | 12 | { name = "ghc-in-ghci"
|
| 11 | - , extraArgs = ghciArgs
|
|
| 13 | + , extraArgs = ghciArgs
|
|
| 14 | + , libraryWays =
|
|
| 15 | + Set.fromList
|
|
| 16 | + <$> mconcat
|
|
| 17 | + [ pure [vanilla]
|
|
| 18 | + , platformSupportsSharedLibs ? pure [dynamic]
|
|
| 19 | + ]
|
|
| 12 | 20 | }
|
| 13 | 21 | |
| 14 | 22 | ghciArgs :: Args
|
| ... | ... | @@ -200,6 +200,26 @@ stg_isMutableByteArrayWeaklyPinnedzh ( gcptr mba ) |
| 200 | 200 | * used to as the LDV profiler will essentially ignore arrays anyways.
|
| 201 | 201 | */
|
| 202 | 202 | |
| 203 | +/* Note [Resizing arrays in-place]
|
|
| 204 | + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 205 | + * We try to shrink or grow bd->free when resizing a MutableByteArray in-place,
|
|
| 206 | + * to reclaim or use slop space at the end of the current block and avoid
|
|
| 207 | + * unnecessary fragmentation/allocation.
|
|
| 208 | + *
|
|
| 209 | + * But we must guarantee that:
|
|
| 210 | + *
|
|
| 211 | + * 1. mba is already at the end of current block (check bd->free).
|
|
| 212 | + * Otherwise we can't move closures that come after it anyway.
|
|
| 213 | + * 2. It's a nursery block that belongs to the current Capability,
|
|
| 214 | + * so check rCurrentAlloc (used by allocateMightFail) or
|
|
| 215 | + * pinned_object_block (used by allocatePinned). There's also no
|
|
| 216 | + * point if it's an older generation block, the mutator won't
|
|
| 217 | + * allocate into those blocks anyway.
|
|
| 218 | + *
|
|
| 219 | + * If check fails, fall back to the conservative code path: just zero the slop
|
|
| 220 | + * and return when shrinking, or allocate a new array when growing.
|
|
| 221 | + */
|
|
| 222 | + |
|
| 203 | 223 | // shrink size of MutableByteArray in-place
|
| 204 | 224 | stg_shrinkMutableByteArrayzh ( gcptr mba, W_ new_size )
|
| 205 | 225 | // MutableByteArray# s -> Int# -> State# s -> State# s
|
| ... | ... | @@ -212,20 +232,7 @@ stg_shrinkMutableByteArrayzh ( gcptr mba, W_ new_size ) |
| 212 | 232 | old_wds = BYTES_TO_WDS(SIZEOF_StgArrBytes) + ROUNDUP_BYTES_TO_WDS(old_size);
|
| 213 | 233 | new_wds = BYTES_TO_WDS(SIZEOF_StgArrBytes) + ROUNDUP_BYTES_TO_WDS(new_size);
|
| 214 | 234 | |
| 215 | - // Try to shrink bd->free as well, to reclaim slop space at the end
|
|
| 216 | - // of current block and avoid unnecessary fragmentation. But we
|
|
| 217 | - // must guarantee that:
|
|
| 218 | - //
|
|
| 219 | - // 1. mba is already at the end of current block (check bd->free).
|
|
| 220 | - // Otherwise we can't move closures that come after it anyway.
|
|
| 221 | - // 2. It's a nursery block that belongs to the current Capability,
|
|
| 222 | - // so check rCurrentAlloc (used by allocateMightFail) or
|
|
| 223 | - // pinned_object_block (used by allocatePinned). There's also no
|
|
| 224 | - // point if it's an older generation block, the mutator won't
|
|
| 225 | - // allocate into those blocks anyway.
|
|
| 226 | - //
|
|
| 227 | - // If check fails, fall back to the conservative code path: just
|
|
| 228 | - // zero the slop and return.
|
|
| 235 | + // See Note [Resizing arrays in-place]
|
|
| 229 | 236 | bd = Bdescr(mba);
|
| 230 | 237 | if (bdescr_free(bd) != mba + WDS(old_wds) ||
|
| 231 | 238 | (bd != StgRegTable_rCurrentAlloc(BaseReg) && bd != Capability_pinned_object_block(MyCapability()))) {
|
| ... | ... | @@ -258,20 +265,33 @@ stg_shrinkMutableByteArrayzh ( gcptr mba, W_ new_size ) |
| 258 | 265 | stg_resizzeMutableByteArrayzh ( gcptr mba, W_ new_size )
|
| 259 | 266 | // MutableByteArray# s -> Int# -> State# s -> (# State# s,MutableByteArray# s #)
|
| 260 | 267 | {
|
| 268 | + W_ old_size, old_wds, new_wds, new_free;
|
|
| 269 | + W_ bd;
|
|
| 270 | + |
|
| 261 | 271 | ASSERT(new_size `ge` 0);
|
| 262 | 272 | |
| 263 | - if (new_size <= StgArrBytes_bytes(mba)) {
|
|
| 273 | + old_size = StgArrBytes_bytes(mba);
|
|
| 274 | + if (new_size <= old_size) {
|
|
| 264 | 275 | call stg_shrinkMutableByteArrayzh(mba, new_size);
|
| 265 | 276 | return (mba);
|
| 277 | + }
|
|
| 278 | + |
|
| 279 | + bd = Bdescr(mba);
|
|
| 280 | + old_wds = BYTES_TO_WDS(SIZEOF_StgArrBytes) + ROUNDUP_BYTES_TO_WDS(old_size);
|
|
| 281 | + new_wds = BYTES_TO_WDS(SIZEOF_StgArrBytes) + ROUNDUP_BYTES_TO_WDS(new_size);
|
|
| 282 | + new_free = mba + WDS(new_wds);
|
|
| 283 | + |
|
| 284 | + // See Note [Resizing arrays in-place]
|
|
| 285 | + // we also need to check that we don't grow past the end of current block.
|
|
| 286 | + if (bdescr_free(bd) == mba + WDS(old_wds) &&
|
|
| 287 | + (bd == StgRegTable_rCurrentAlloc(BaseReg) || bd == Capability_pinned_object_block(MyCapability())) &&
|
|
| 288 | + new_free <= bdescr_start(bd) + (TO_W_(bdescr_blocks(bd)) * BLOCK_SIZE)) {
|
|
| 289 | + bdescr_free(bd) = new_free;
|
|
| 290 | + StgArrBytes_bytes(mba) = new_size;
|
|
| 291 | + return (mba);
|
|
| 266 | 292 | } else {
|
| 267 | 293 | (P_ new_mba) = call stg_newByteArrayzh(new_size);
|
| 268 | 294 | |
| 269 | - // maybe at some point in the future we may be able to grow the
|
|
| 270 | - // MBA in-place w/o copying if we know the space after the
|
|
| 271 | - // current MBA is still available, as often we want to grow the
|
|
| 272 | - // MBA shortly after we allocated the original MBA. So maybe no
|
|
| 273 | - // further allocations have occurred by then.
|
|
| 274 | - |
|
| 275 | 295 | // copy over old content
|
| 276 | 296 | prim %memcpy(BYTE_ARR_CTS(new_mba), BYTE_ARR_CTS(mba),
|
| 277 | 297 | StgArrBytes_bytes(mba), SIZEOF_W);
|
| 1 | +{-# LANGUAGE OverloadedRecordDot #-}
|
|
| 2 | +{-# LANGUAGE GADTs #-}
|
|
| 3 | + |
|
| 4 | +{-# OPTIONS_GHC -Wincomplete-record-selectors #-}
|
|
| 5 | + |
|
| 6 | +module T26686 where
|
|
| 7 | + |
|
| 8 | +import Data.Kind
|
|
| 9 | + |
|
| 10 | +data A
|
|
| 11 | +data B
|
|
| 12 | + |
|
| 13 | +data G = G { f2 :: Int }
|
|
| 14 | + |
|
| 15 | +data T x where
|
|
| 16 | + TA :: { ta :: G } -> T x
|
|
| 17 | + TB :: { tb :: G } -> T B
|
|
| 18 | + |
|
| 19 | +data H a = H { f1 :: T a }
|
|
| 20 | + |
|
| 21 | +test1_ok :: T A -> G
|
|
| 22 | +test1_ok = (.ta)
|
|
| 23 | +test2_ok :: T A -> Int
|
|
| 24 | +test2_ok = (.ta.f2)
|
|
| 25 | +test3_ok :: H A -> G
|
|
| 26 | +test3_ok = (.f1.ta)
|
|
| 27 | +test4_ok :: H A -> Int
|
|
| 28 | +test4_ok = (.f1.ta.f2)
|
|
| 29 | + |
|
| 30 | +test1_bad :: T x -> G
|
|
| 31 | +test1_bad = (.ta)
|
|
| 32 | +test2_bad :: T x -> Int
|
|
| 33 | +test2_bad = (.ta.f2)
|
|
| 34 | +test3_bad :: H x -> G
|
|
| 35 | +test3_bad = (.f1.ta)
|
|
| 36 | +test4_bad :: H x -> Int
|
|
| 37 | +test4_bad = (.f1.ta.f2) |
| 1 | +T26686.hs:31:13: warning: [GHC-17335] [-Wincomplete-record-selectors (in -Wall)]
|
|
| 2 | + Selecting the record field ‘ta’ may fail for the following constructors:
|
|
| 3 | + TB
|
|
| 4 | + |
|
| 5 | +T26686.hs:33:13: warning: [GHC-17335] [-Wincomplete-record-selectors (in -Wall)]
|
|
| 6 | + Selecting the record field ‘ta’ may fail for the following constructors:
|
|
| 7 | + TB
|
|
| 8 | + |
|
| 9 | +T26686.hs:35:13: warning: [GHC-17335] [-Wincomplete-record-selectors (in -Wall)]
|
|
| 10 | + Selecting the record field ‘ta’ may fail for the following constructors:
|
|
| 11 | + TB
|
|
| 12 | + |
|
| 13 | +T26686.hs:37:13: warning: [GHC-17335] [-Wincomplete-record-selectors (in -Wall)]
|
|
| 14 | + Selecting the record field ‘ta’ may fail for the following constructors:
|
|
| 15 | + TB
|
|
| 16 | + |
| ... | ... | @@ -30,6 +30,7 @@ test('T21720', req_th, compile, ['']) |
| 30 | 30 | test('T21898', normal, compile, [''])
|
| 31 | 31 | test('T22160', [extra_files(['T22160_A.hs', 'T22160_B.hs', 'T22160_C.hs'])]
|
| 32 | 32 | , multimod_compile, ['T22160_A T22160_B T22160_C T22160', '-v0'])
|
| 33 | +test('T26686', normal, compile, [''])
|
|
| 33 | 34 | test('DupFldFixity3', normal, compile, [''])
|
| 34 | 35 | test('overloadedrecflds10'
|
| 35 | 36 | , [extra_files(['OverloadedRecFlds10_A.hs', 'OverloadedRecFlds10_B.hs', 'OverloadedRecFlds10_C.hs'])]
|
| ... | ... | @@ -669,3 +669,5 @@ test('TimeoutQueue', |
| 669 | 669 | test('ClosureTable',
|
| 670 | 670 | [req_c, only_ways(['normal', 'debug']), extra_files(['ClosureTable_c.c'])], compile_and_run,
|
| 671 | 671 | ['-debug -O0 ClosureTable_c.c -I{top}/../rts -I{top}/../rts/include'])
|
| 672 | + |
|
| 673 | +test('resizeMutableByteArrayInPlace', [req_cmm, extra_ways(['optasm', 'sanity']), only_ways(['optasm', 'sanity'])], compile_and_run, ['']) |
| 1 | +{-# LANGUAGE MagicHash #-}
|
|
| 2 | +{-# LANGUAGE UnboxedTuples #-}
|
|
| 3 | + |
|
| 4 | +import Control.Monad
|
|
| 5 | +import GHC.Exts
|
|
| 6 | +import GHC.IO
|
|
| 7 | + |
|
| 8 | +-- Given newByteArray#/newPinnedByteArray#, iterate given number of
|
|
| 9 | +-- rounds: first allocate a MutableByteArray# using the first size,
|
|
| 10 | +-- then resize to the new size, then resize back
|
|
| 11 | +{-# INLINE testResize #-}
|
|
| 12 | +testResize :: (Int# -> State# RealWorld -> (# State# RealWorld, MutableByteArray# RealWorld #)) -> Int -> Int -> Int -> IO ()
|
|
| 13 | +testResize alloc# rounds (I# sz0#) (I# sz1#) =
|
|
| 14 | + replicateM_ rounds $ IO $ \s0 -> case alloc# sz0# s0 of
|
|
| 15 | + (# s1, mba0# #) -> case resizeMutableByteArray# mba0# sz1# s1 of
|
|
| 16 | + (# s2, mba1# #) -> case resizeMutableByteArray# mba1# sz0# s2 of
|
|
| 17 | + (# s3, _ #) -> (# s3, () #)
|
|
| 18 | + |
|
| 19 | +main :: IO ()
|
|
| 20 | +main = do
|
|
| 21 | + testResize newByteArray# 100000 8 64
|
|
| 22 | + testResize newByteArray# 100000 64 8
|
|
| 23 | + testResize newPinnedByteArray# 100000 8 64
|
|
| 24 | + testResize newPinnedByteArray# 100000 64 8 |
| 1 | +{-# LANGUAGE MagicHash #-}
|
|
| 2 | +module T18032 where
|
|
| 3 | + |
|
| 4 | +import GHC.Exts
|
|
| 5 | + |
|
| 6 | +-- Different byte content: eqAddr# must be False (0), neAddr# must be True (1)
|
|
| 7 | +a = I# (eqAddr# "foo"# "bar"#)
|
|
| 8 | +b = I# (neAddr# "foo"# "bar"#)
|
|
| 9 | + |
|
| 10 | +-- Same variable on both sides: eqAddr# must be True (1), neAddr# must be False (0)
|
|
| 11 | +c = let s = "baz"# in I# (eqAddr# s s)
|
|
| 12 | +d = let s = "baz"# in I# (neAddr# s s) |
| 1 | + |
|
| 2 | +==================== Tidy Core ====================
|
|
| 3 | +Result size of Tidy Core
|
|
| 4 | + = {terms: 10, types: 4, coercions: 0, joins: 0/0}
|
|
| 5 | + |
|
| 6 | +a = I# 0#
|
|
| 7 | + |
|
| 8 | +b = I# 1#
|
|
| 9 | + |
|
| 10 | +c = b
|
|
| 11 | + |
|
| 12 | +d = a
|
|
| 13 | + |
|
| 14 | + |
|
| 15 | + |
| ... | ... | @@ -593,3 +593,4 @@ test('T26722', [grep_errmsg(r'SPEC')], compile, ['-O -dno-typeable-binds']) |
| 593 | 593 | test('T26805', [grep_errmsg(r'fromInteger')], compile, ['-O -dno-typeable-binds -ddump-simpl -dsuppress-uniques'])
|
| 594 | 594 | test('T26826', normal, compile, ['-O'])
|
| 595 | 595 | test('T26903', [grep_errmsg(r'reverse')], compile, ['-O -dno-typeable-binds -ddump-simpl -dsuppress-uniques -dsuppress-all'])
|
| 596 | +test('T18032', normal, compile, ['-O -dsuppress-all -dsuppress-uniques -dno-typeable-binds -ddump-simpl']) |