Zubin pushed to branch ghc-9.10 at Glasgow Haskell Compiler / GHC
Commits:
-
dea3e5d6
by Teo Camarasu at 2025-08-17T22:31:50+05:30
-
97299e94
by Teo Camarasu at 2025-08-17T22:31:57+05:30
-
2e47cd55
by Reed Mullanix at 2025-08-17T22:33:53+05:30
-
1ea64785
by sheaf at 2025-08-17T22:36:18+05:30
23 changed files:
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Utils/Env.hs
- libraries/base/changelog.md
- libraries/ghc-bignum/changelog.md
- libraries/ghc-bignum/src/GHC/Num/Natural.hs
- rts/Messages.c
- rts/StgMiscClosures.cmm
- rts/Updates.h
- + testsuite/tests/numeric/should_run/T26230.hs
- + testsuite/tests/numeric/should_run/T26230.stdout
- testsuite/tests/numeric/should_run/all.T
- + testsuite/tests/rename/should_fail/T25056.hs
- + testsuite/tests/rename/should_fail/T25056.stderr
- + testsuite/tests/rename/should_fail/T25056a.hs
- + testsuite/tests/rename/should_fail/T25056b.hs
- testsuite/tests/rename/should_fail/all.T
- testsuite/tests/typecheck/should_fail/T23739b.hs
- testsuite/tests/typecheck/should_fail/T23739b.stderr
- + testsuite/tests/typecheck/should_fail/T23739c.hs
- + testsuite/tests/typecheck/should_fail/T23739c.stderr
- testsuite/tests/typecheck/should_fail/all.T
Changes:
... | ... | @@ -436,6 +436,7 @@ lookupConstructorInfo con_name |
436 | 436 | ; case info of
|
437 | 437 | IAmConLike con_info -> return con_info
|
438 | 438 | UnboundGRE -> return ConHasPositionalArgs
|
439 | + IAmTyCon {} -> failIllegalTyCon WL_Constructor con_name
|
|
439 | 440 | _ -> pprPanic "lookupConstructorInfo: not a ConLike" $
|
440 | 441 | vcat [ text "name:" <+> ppr con_name ]
|
441 | 442 | }
|
... | ... | @@ -1029,24 +1030,12 @@ lookupOccRn' which_suggest rdr_name |
1029 | 1030 | lookupOccRn :: RdrName -> RnM Name
|
1030 | 1031 | lookupOccRn = lookupOccRn' WL_Anything
|
1031 | 1032 | |
1032 | --- lookupOccRnConstr looks up an occurrence of a RdrName and displays
|
|
1033 | --- constructors and pattern synonyms as suggestions if it is not in scope
|
|
1033 | +-- | Look up an occurrence of a 'RdrName'.
|
|
1034 | 1034 | --
|
1035 | --- There is a fallback to the type level, when the first lookup fails.
|
|
1036 | --- This is required to implement a pat-to-type transformation
|
|
1037 | --- (See Note [Pattern to type (P2T) conversion] in GHC.Tc.Gen.Pat)
|
|
1038 | --- Consider this example:
|
|
1035 | +-- Displays constructors and pattern synonyms as suggestions if
|
|
1036 | +-- it is not in scope.
|
|
1039 | 1037 | --
|
1040 | --- data VisProxy a where VP :: forall a -> VisProxy a
|
|
1041 | ---
|
|
1042 | --- f :: VisProxy Int -> ()
|
|
1043 | --- f (VP Int) = ()
|
|
1044 | ---
|
|
1045 | --- Here `Int` is actually a type, but it stays on position where
|
|
1046 | --- we expect a data constructor.
|
|
1047 | ---
|
|
1048 | --- In all other cases we just use this additional lookup for better
|
|
1049 | --- error messaging (See Note [Promotion]).
|
|
1038 | +-- See Note [lookupOccRnConstr]
|
|
1050 | 1039 | lookupOccRnConstr :: RdrName -> RnM Name
|
1051 | 1040 | lookupOccRnConstr rdr_name
|
1052 | 1041 | = do { mb_gre <- lookupOccRn_maybe rdr_name
|
... | ... | @@ -1058,6 +1047,28 @@ lookupOccRnConstr rdr_name |
1058 | 1047 | Just gre -> return $ greName gre
|
1059 | 1048 | Nothing -> reportUnboundName' WL_Constructor rdr_name} }
|
1060 | 1049 | |
1050 | +{- Note [lookupOccRnConstr]
|
|
1051 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
1052 | +lookupOccRnConstr looks up a data constructor or pattern synonym. Simple.
|
|
1053 | + |
|
1054 | +However, there is a fallback to the type level when the lookup fails.
|
|
1055 | +This is required to implement a pat-to-type transformation
|
|
1056 | +(See Note [Pattern to type (P2T) conversion] in GHC.Tc.Gen.Pat)
|
|
1057 | + |
|
1058 | +Consider this example:
|
|
1059 | + |
|
1060 | + data VisProxy a where VP :: forall a -> VisProxy a
|
|
1061 | + |
|
1062 | + f :: VisProxy Int -> ()
|
|
1063 | + f (VP Int) = ()
|
|
1064 | + |
|
1065 | +Here `Int` is actually a type, but it occurs in a position in which we expect
|
|
1066 | +a data constructor.
|
|
1067 | + |
|
1068 | +In all other cases we just use this additional lookup for better
|
|
1069 | +error messaging (See Note [Promotion]).
|
|
1070 | +-}
|
|
1071 | + |
|
1061 | 1072 | -- lookupOccRnRecField looks up an occurrence of a RdrName and displays
|
1062 | 1073 | -- record fields as suggestions if it is not in scope
|
1063 | 1074 | lookupOccRnRecField :: RdrName -> RnM Name
|
... | ... | @@ -532,9 +532,9 @@ rnExpr (ExplicitSum _ alt arity expr) |
532 | 532 | = do { (expr', fvs) <- rnLExpr expr
|
533 | 533 | ; return (ExplicitSum noExtField alt arity expr', fvs) }
|
534 | 534 | |
535 | -rnExpr (RecordCon { rcon_con = con_id
|
|
535 | +rnExpr (RecordCon { rcon_con = con_rdr
|
|
536 | 536 | , rcon_flds = rec_binds@(HsRecFields { rec_dotdot = dd }) })
|
537 | - = do { con_lname@(L _ con_name) <- lookupLocatedOccRnConstr con_id
|
|
537 | + = do { con_lname@(L _ con_name) <- lookupLocatedOccRnConstr con_rdr
|
|
538 | 538 | ; (flds, fvs) <- rnHsRecFields (HsRecFieldCon con_name) mk_hs_var rec_binds
|
539 | 539 | ; (flds', fvss) <- mapAndUnzipM rn_field flds
|
540 | 540 | ; let rec_binds' = HsRecFields { rec_flds = flds', rec_dotdot = dd }
|
... | ... | @@ -1161,7 +1161,7 @@ tc_infer_id id_name |
1161 | 1161 | |
1162 | 1162 | AGlobal (AConLike (RealDataCon con)) -> tcInferDataCon con
|
1163 | 1163 | AGlobal (AConLike (PatSynCon ps)) -> tcInferPatSyn id_name ps
|
1164 | - (tcTyThingTyCon_maybe -> Just tc) -> failIllegalTyCon WL_Anything tc -- TyCon or TcTyCon
|
|
1164 | + (tcTyThingTyCon_maybe -> Just tc) -> failIllegalTyCon WL_Anything (tyConName tc)
|
|
1165 | 1165 | ATyVar name _ -> failIllegalTyVal name
|
1166 | 1166 | |
1167 | 1167 | _ -> failWithTc $ TcRnExpectedValueId thing }
|
... | ... | @@ -280,7 +280,7 @@ tcLookupConLike name = do |
280 | 280 | thing <- tcLookupGlobal name
|
281 | 281 | case thing of
|
282 | 282 | AConLike cl -> return cl
|
283 | - ATyCon tc -> failIllegalTyCon WL_Constructor tc
|
|
283 | + ATyCon {} -> failIllegalTyCon WL_Constructor name
|
|
284 | 284 | _ -> wrongThingErr WrongThingConLike (AGlobal thing) name
|
285 | 285 | |
286 | 286 | tcLookupRecSelParent :: HsRecUpdParent GhcRn -> TcM RecSelParent
|
... | ... | @@ -353,19 +353,20 @@ instance MonadThings (IOEnv (Env TcGblEnv TcLclEnv)) where |
353 | 353 | lookupThing = tcLookupGlobal
|
354 | 354 | |
355 | 355 | -- Illegal term-level use of type things
|
356 | -failIllegalTyCon :: WhatLooking -> TyCon -> TcM a
|
|
356 | +failIllegalTyCon :: WhatLooking -> Name -> TcM a
|
|
357 | 357 | failIllegalTyVal :: Name -> TcM a
|
358 | 358 | (failIllegalTyCon, failIllegalTyVal) = (fail_tycon, fail_tyvar)
|
359 | 359 | where
|
360 | - fail_tycon what_looking tc = do
|
|
360 | + fail_tycon what_looking tc_nm = do
|
|
361 | 361 | gre <- getGlobalRdrEnv
|
362 | - let nm = tyConName tc
|
|
363 | - pprov = case lookupGRE_Name gre nm of
|
|
362 | + let mb_gre = lookupGRE_Name gre tc_nm
|
|
363 | + pprov = case mb_gre of
|
|
364 | 364 | Just gre -> nest 2 (pprNameProvenance gre)
|
365 | 365 | Nothing -> empty
|
366 | - err | isClassTyCon tc = ClassTE
|
|
367 | - | otherwise = TyConTE
|
|
368 | - fail_with_msg what_looking dataName nm pprov err
|
|
366 | + err = case greInfo <$> mb_gre of
|
|
367 | + Just (IAmTyCon ClassFlavour) -> ClassTE
|
|
368 | + _ -> TyConTE
|
|
369 | + fail_with_msg what_looking dataName tc_nm pprov err
|
|
369 | 370 | |
370 | 371 | fail_tyvar nm =
|
371 | 372 | let pprov = nest 2 (text "bound at" <+> ppr (getSrcLoc nm))
|
... | ... | @@ -2,6 +2,7 @@ |
2 | 2 | |
3 | 3 | ## 4.20.2 *July 2025*
|
4 | 4 | * Fix incorrect results of `integerPowMod` when the base is 0 and the exponent is negative, and `integerRecipMod` when the modulus is zero ([#26017](https://gitlab.haskell.org/ghc/ghc/-/issues/26017)).
|
5 | + * Fix bug where `naturalAndNot` was incorrectly truncating results ([CLC proposal #350](github.com/haskell/core-libraries-committee/issues/350))
|
|
5 | 6 | |
6 | 7 | ## 4.20.1 *Jan 2025*
|
7 | 8 | * Shipped with GHC 9.10.2
|
... | ... | @@ -4,6 +4,7 @@ |
4 | 4 | |
5 | 5 | - Expose backendName
|
6 | 6 | - Add `naturalSetBit[#]` (#21173), `naturalClearBit[#]` (#21175), `naturalComplementBit[#]` (#21181)
|
7 | +- Fix bug where `naturalAndNot` was incorrectly truncating results (#26230)
|
|
7 | 8 | |
8 | 9 | ## 1.2
|
9 | 10 |
... | ... | @@ -488,7 +488,7 @@ naturalAndNot :: Natural -> Natural -> Natural |
488 | 488 | {-# NOINLINE naturalAndNot #-}
|
489 | 489 | naturalAndNot (NS n) (NS m) = NS (n `and#` not# m)
|
490 | 490 | naturalAndNot (NS n) (NB m) = NS (n `and#` not# (bigNatToWord# m))
|
491 | -naturalAndNot (NB n) (NS m) = NS (bigNatToWord# n `and#` not# m)
|
|
491 | +naturalAndNot (NB n) (NS m) = NB (bigNatAndNotWord# n m)
|
|
492 | 492 | naturalAndNot (NB n) (NB m) = naturalFromBigNat# (bigNatAndNot n m)
|
493 | 493 | |
494 | 494 | naturalOr :: Natural -> Natural -> Natural
|
... | ... | @@ -180,13 +180,22 @@ uint32_t messageBlackHole(Capability *cap, MessageBlackHole *msg) |
180 | 180 | bh_info != &stg_CAF_BLACKHOLE_info &&
|
181 | 181 | bh_info != &__stg_EAGER_BLACKHOLE_info &&
|
182 | 182 | bh_info != &stg_WHITEHOLE_info) {
|
183 | - // if it is a WHITEHOLE, then a thread is in the process of
|
|
184 | - // trying to BLACKHOLE it. But we know that it was once a
|
|
185 | - // BLACKHOLE, so there is at least a valid pointer in the
|
|
186 | - // payload, so we can carry on.
|
|
187 | 183 | return 0;
|
188 | 184 | }
|
189 | 185 | |
186 | + // If we see a WHITEHOLE then we should wait for it to turn into a BLACKHOLE.
|
|
187 | + // Otherwise we might look at the indirectee and segfault.
|
|
188 | + // See "Exception handling" in Note [Thunks, blackholes, and indirections]
|
|
189 | + // We might be looking at a *fresh* THUNK being WHITEHOLE-d so we can't
|
|
190 | + // guarantee that the indirectee is a valid pointer.
|
|
191 | +#if defined(THREADED_RTS)
|
|
192 | + if (bh_info == &stg_WHITEHOLE_info) {
|
|
193 | + while(ACQUIRE_LOAD(&bh->header.info) == &stg_WHITEHOLE_info) {
|
|
194 | + busy_wait_nop();
|
|
195 | + }
|
|
196 | + }
|
|
197 | +#endif
|
|
198 | + |
|
190 | 199 | // The blackhole must indirect to a TSO, a BLOCKING_QUEUE, an IND,
|
191 | 200 | // or a value.
|
192 | 201 | StgClosure *p;
|
... | ... | @@ -31,6 +31,7 @@ import CLOSURE ENT_VIA_NODE_ctr; |
31 | 31 | import CLOSURE RtsFlags;
|
32 | 32 | import CLOSURE stg_BLOCKING_QUEUE_CLEAN_info;
|
33 | 33 | import CLOSURE stg_BLOCKING_QUEUE_DIRTY_info;
|
34 | +import CLOSURE stg_END_TSO_QUEUE_closure;
|
|
34 | 35 | import CLOSURE stg_IND_info;
|
35 | 36 | import CLOSURE stg_MSG_BLACKHOLE_info;
|
36 | 37 | import CLOSURE stg_TSO_info;
|
... | ... | @@ -597,6 +598,9 @@ retry: |
597 | 598 | |
598 | 599 | MessageBlackHole_tso(msg) = CurrentTSO;
|
599 | 600 | MessageBlackHole_bh(msg) = node;
|
601 | + // Ensure that the link field is a valid closure,
|
|
602 | + // since we might turn this into an indirection in wakeBlockingQueue()
|
|
603 | + MessageBlackHole_link(msg) = stg_END_TSO_QUEUE_closure;
|
|
600 | 604 | SET_HDR(msg, stg_MSG_BLACKHOLE_info, CCS_SYSTEM);
|
601 | 605 | // messageBlackHole has appropriate memory barriers when this object is exposed.
|
602 | 606 | // See Note [Heap memory barriers].
|
... | ... | @@ -333,6 +333,10 @@ |
333 | 333 | * `AP_STACK` closure recording the aborted execution state.
|
334 | 334 | * See `RaiseAsync.c:raiseAsync` for details.
|
335 | 335 | *
|
336 | + * This can combine with indirection shortcutting during GC to replace a BLACKHOLE
|
|
337 | + * with a fresh THUNK. We should be very careful here since the THUNK will have an
|
|
338 | + * undefined value in the indirectee field. Looking at the indirectee field can then
|
|
339 | + * lead to a segfault such as #26205.
|
|
336 | 340 | *
|
337 | 341 | * CAFs
|
338 | 342 | * ----
|
1 | +import Data.Bits
|
|
2 | +import GHC.Num.Natural
|
|
3 | + |
|
4 | +main = do
|
|
5 | + print $ naturalAndNot ((2 ^ 4) .|. (2 ^ 3)) (2 ^ 3)
|
|
6 | + print $ naturalAndNot ((2 ^ 129) .|. (2 ^ 65)) (2 ^ 65)
|
|
7 | + print $ naturalAndNot ((2 ^ 4) .|. (2 ^ 3)) ((2 ^ 65) .|. (2 ^ 3))
|
|
8 | + print $ naturalAndNot ((2 ^ 65) .|. (2 ^ 3)) (2 ^ 3) |
1 | +16
|
|
2 | +680564733841876926926749214863536422912
|
|
3 | +16
|
|
4 | +36893488147419103232 |
... | ... | @@ -83,3 +83,4 @@ test('T22282', normal, compile_and_run, ['']) |
83 | 83 | test('T22671', js_fragile(24259), compile_and_run, [''])
|
84 | 84 | test('foundation', [when(js_arch(), run_timeout_multiplier(2)), js_fragile(24259)], compile_and_run, ['-O -package transformers'])
|
85 | 85 | test('T24066', normal, compile_and_run, [''])
|
86 | +test('T26230', normal, compile_and_run, ['']) |
1 | +{-# LANGUAGE RecordWildCards #-}
|
|
2 | +module T25056 where
|
|
3 | + |
|
4 | +import T25056b
|
|
5 | + |
|
6 | +foo :: T -> ()
|
|
7 | +foo (T { unT = x }) = x |
1 | +T25056.hs:7:10: error: [GHC-01928]
|
|
2 | + • Illegal term-level use of the type constructor ‘T’
|
|
3 | + • imported from ‘T25056b’ at T25056.hs:4:1-14
|
|
4 | + (and originally defined in ‘T25056a’ at T25056a.hs:8:1-14)
|
|
5 | + |
1 | +{-# LANGUAGE PatternSynonyms #-}
|
|
2 | +module T25056a
|
|
3 | + ( T
|
|
4 | + , T_(unT)
|
|
5 | + , pattern T
|
|
6 | + ) where
|
|
7 | + |
|
8 | +type T = T_ ()
|
|
9 | + |
|
10 | +data T_ a = PrivateT { unT_ :: a }
|
|
11 | + |
|
12 | +pattern T :: a -> T_ a
|
|
13 | +pattern T { unT } <- PrivateT { unT_ = unT } |
1 | +module T25056b (T, T_(..)) where
|
|
2 | + |
|
3 | +import T25056a (T, T_(..)) |
... | ... | @@ -222,6 +222,7 @@ test('T23740g', normal, compile_fail, ['']) |
222 | 222 | test('T23740h', normal, compile_fail, [''])
|
223 | 223 | test('T23740i', req_th, compile_fail, [''])
|
224 | 224 | test('T23740j', normal, compile_fail, [''])
|
225 | +test('T25056', [extra_files(['T25056a.hs', 'T25056b.hs'])], multimod_compile_fail, ['T25056', '-v0'])
|
|
225 | 226 | test('T23570', [extra_files(['T23570_aux.hs'])], multimod_compile_fail, ['T23570', '-v0'])
|
226 | 227 | test('T23570b', [extra_files(['T23570_aux.hs'])], multimod_compile, ['T23570b', '-v0'])
|
227 | 228 | test('T17594b', req_th, compile_fail, [''])
|
... | ... | @@ -8,7 +8,4 @@ g1 :: Int -> Unit |
8 | 8 | g1 Int = ()
|
9 | 9 | |
10 | 10 | g2 :: Int
|
11 | -g2 = Int{}
|
|
12 | - |
|
13 | -g3 :: Int
|
|
14 | -g3 = Int |
|
11 | +g2 = Int |
... | ... | @@ -6,16 +6,9 @@ T23739b.hs:8:4: error: [GHC-01928] |
6 | 6 | In an equation for ‘g1’: g1 Int = ()
|
7 | 7 | |
8 | 8 | T23739b.hs:11:6: error: [GHC-01928]
|
9 | - • Illegal term-level use of the type constructor ‘Int’
|
|
10 | - • imported from ‘Prelude’ at T23739b.hs:2:8-14
|
|
11 | - (and originally defined in ‘GHC.Types’)
|
|
12 | - • In the expression: Int {}
|
|
13 | - In an equation for ‘g2’: g2 = Int {}
|
|
14 | - |
|
15 | -T23739b.hs:14:6: error: [GHC-01928]
|
|
16 | 9 | • Illegal term-level use of the type constructor ‘Int’
|
17 | 10 | • imported from ‘Prelude’ at T23739b.hs:2:8-14
|
18 | 11 | (and originally defined in ‘GHC.Types’)
|
19 | 12 | • In the expression: Int
|
20 | - In an equation for ‘g3’: g3 = Int
|
|
13 | + In an equation for ‘g2’: g2 = Int
|
|
21 | 14 |
1 | + |
|
2 | +module T23739c where
|
|
3 | + |
|
4 | +import Data.Tuple.Experimental
|
|
5 | +import GHC.TypeLits
|
|
6 | + |
|
7 | +g :: Int
|
|
8 | +g = Int{} |
1 | +T23739c.hs:8:5: error: [GHC-01928]
|
|
2 | + • Illegal term-level use of the type constructor ‘Int’
|
|
3 | + • imported from ‘Prelude’ at T23739c.hs:2:8-14
|
|
4 | + (and originally defined in ‘GHC.Types’)
|
|
5 | + • In the expression: Int {}
|
|
6 | + In an equation for ‘g’: g = Int {}
|
|
7 | + |
... | ... | @@ -730,3 +730,4 @@ test('T23739b', normal, compile_fail, ['']) |
730 | 730 | test('T25325', normal, compile_fail, [''])
|
731 | 731 | test('T25004', normal, compile_fail, [''])
|
732 | 732 | test('T25004k', normal, compile_fail, [''])
|
733 | +test('T23739c', normal, compile_fail, ['']) |